public void removeUnspentTransactionOutput(StoredTransactionOutput out)
     throws BlockStoreException {
   maybeConnect();
   // TODO: This should only need one query (maybe a stored procedure)
   if (getTransactionOutput(out.getHash(), out.getIndex()) == null)
     throw new BlockStoreException(
         "Tried to remove a StoredTransactionOutput from PostgresFullPrunedBlockStore that it didn't have!");
   try {
     PreparedStatement s =
         conn.get().prepareStatement("DELETE FROM openOutputs WHERE hash = ? AND index = ?");
     s.setBytes(1, out.getHash().getBytes());
     // index is actually an unsigned int
     s.setInt(2, (int) out.getIndex());
     s.executeUpdate();
     s.close();
   } catch (SQLException e) {
     throw new BlockStoreException(e);
   }
 }
  public void addUnspentTransactionOutput(StoredTransactionOutput out) throws BlockStoreException {
    maybeConnect();
    PreparedStatement s = null;

    // Calculate the toAddress (if any)
    String dbAddress = "";
    int type = 0;
    Script outputScript = null;
    try {
      outputScript = new Script(out.getScriptBytes());
    } catch (ScriptException e) {
      // Unparseable, but this isn't an error - it's an output not containing an address
      log.info("Could not parse script for output: " + out.getHash().toString());
    }
    if (outputScript != null
        && (outputScript.isSentToAddress()
            || outputScript.isSentToRawPubKey()
            || outputScript.isPayToScriptHash())) {
      if (outputScript.isSentToAddress()) {
        Address targetAddr = new Address(params, outputScript.getPubKeyHash());
        dbAddress = targetAddr.toString();
        type = 1;
      } else if (outputScript.isSentToRawPubKey()) {
        /*
         *   Note we use the deprecated getFromAddress here.  Coinbase outputs seem to have the target address
         *   in the pubkey of the script - perhaps we can rename this function?
         */

        dbAddress = outputScript.getFromAddress(params).toString();
        type = 2;
      } else if (outputScript.isPayToScriptHash()) {
        dbAddress = Address.fromP2SHHash(params, outputScript.getPubKeyHash()).toString();
        type = 3;
      }
    }

    try {
      s =
          conn.get()
              .prepareStatement(
                  "INSERT INTO openOutputs (hash, index, height, value, scriptBytes, toAddress, addressTargetable) "
                      + "VALUES (?, ?, ?, ?, ?, ?, ?)");
      s.setBytes(1, out.getHash().getBytes());
      // index is actually an unsigned int
      s.setInt(2, (int) out.getIndex());
      s.setInt(3, out.getHeight());
      s.setBytes(4, out.getValue().toByteArray());
      s.setBytes(5, out.getScriptBytes());
      s.setString(6, dbAddress);
      s.setInt(7, type);
      s.executeUpdate();
      s.close();
    } catch (SQLException e) {
      if (!(e.getSQLState().equals(POSTGRES_DUPLICATE_KEY_ERROR_CODE)))
        throw new BlockStoreException(e);
    } finally {
      if (s != null)
        try {
          s.close();
        } catch (SQLException e) {
          throw new BlockStoreException(e);
        }
    }
  }