/** * Calculate the balance for a coinbase, to-address, or p2sh address. * * @param address The address to calculate the balance of * @return The balance of the address supplied. If the address has not been seen, or there are no * outputs open for this address, the return value is 0 * @throws BlockStoreException */ public BigInteger calculateBalanceForAddress(Address address) throws BlockStoreException { maybeConnect(); PreparedStatement s = null; try { s = conn.get() .prepareStatement( "select sum(('x'||lpad(substr(value::text, 3, 50),16,'0'))::bit(64)::bigint) " + "from openoutputs where toaddress = ?"); s.setString(1, address.toString()); ResultSet rs = s.executeQuery(); if (rs.next()) { return BigInteger.valueOf(rs.getLong(1)); } else { throw new BlockStoreException("Failed to execute balance lookup"); } } catch (SQLException ex) { throw new BlockStoreException(ex); } finally { if (s != null) try { s.close(); } catch (SQLException e) { throw new BlockStoreException("Could not close statement"); } } }
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); } } }