diff --git a/qa/rpc-tests/addressindex.py b/qa/rpc-tests/addressindex.py index 2e15348d6b..8f123eaa07 100755 --- a/qa/rpc-tests/addressindex.py +++ b/qa/rpc-tests/addressindex.py @@ -44,6 +44,10 @@ class AddressIndexTest(BitcoinTestFramework): assert_equal(self.nodes[1].getbalance(), 0) assert_equal(self.nodes[2].getbalance(), 0) + # Check that balances are correct + balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(balance0['balance'], 0); + # Check p2pkh and p2sh address indexes print "Testing p2pkh and p2sh address index..." @@ -89,6 +93,10 @@ class AddressIndexTest(BitcoinTestFramework): assert_equal(multitxids[4], txid2); assert_equal(multitxids[5], txidb2); + # Check that balances are correct + balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(balance0['balance'], 45 * 100000000); + # Check that outputs with the same address will only return one txid print "Testing for txid uniqueness..." addressHash = "6349a418fc4578d10a372b54b45c280cc8c4382f".decode("hex") @@ -109,6 +117,10 @@ class AddressIndexTest(BitcoinTestFramework): assert_equal(len(txidsmany), 4); assert_equal(txidsmany[3], sent_txid); + # Check that balances are correct + balance0 = self.nodes[1].getaddressbalance("2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br") + assert_equal(balance0['balance'], 45 * 100000000 + 21); + print "Passed\n" diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 1a86353e27..d4ad29e655 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -397,23 +397,9 @@ UniValue setmocktime(const UniValue& params, bool fHelp) return NullUniValue; } -UniValue getaddresstxids(const UniValue& params, bool fHelp) +bool getAddressesFromParams(const UniValue& params, std::vector > &addresses) { - if (fHelp || params.size() != 1) - throw runtime_error( - "getaddresstxids\n" - "\nReturns the txids for an address (requires addressindex to be enabled).\n" - "\nResult\n" - "[\n" - " \"transactionid\" (string) The transaction id\n" - " ,...\n" - "]\n" - ); - - std::vector > addresses; - if (params[0].isStr()) { - CBitcoinAddress address(params[0].get_str()); uint160 hashBytes; int type = 0; @@ -421,7 +407,6 @@ UniValue getaddresstxids(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); } addresses.push_back(std::make_pair(hashBytes, type)); - } else if (params[0].isObject()) { UniValue addressValues = find_value(params[0].get_obj(), "addresses"); @@ -445,9 +430,73 @@ UniValue getaddresstxids(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); } + return true; + + +} + +UniValue getaddressbalance(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddressbalance\n" + "\nReturns the balance for an address (requires addressindex to be enabled).\n" + "\nResult\n" + "{\n" + " \"balance\" (string) The current balance\n" + " ,...\n" + "}\n" + ); + + std::vector > addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + std::vector > addressIndex; - for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); ++it) { + for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { + if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); + } + } + + CAmount balance = 0; + + for (std::vector >::const_iterator it=addressIndex.begin(); it!=addressIndex.end(); it++) { + balance += it->second; + } + + UniValue result(UniValue::VOBJ); + result.push_back(Pair("balance", balance)); + + return result; + +} + +UniValue getaddresstxids(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "getaddresstxids\n" + "\nReturns the txids for an address (requires addressindex to be enabled).\n" + "\nResult\n" + "[\n" + " \"transactionid\" (string) The transaction id\n" + " ,...\n" + "]\n" + ); + + std::vector > addresses; + + if (!getAddressesFromParams(params, addresses)) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); + } + + std::vector > addressIndex; + + for (std::vector >::iterator it = addresses.begin(); it != addresses.end(); it++) { if (!GetAddressIndex((*it).first, (*it).second, addressIndex)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available for address"); } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index 67da51ceb7..da66b1c0a1 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -315,6 +315,7 @@ static const CRPCCommand vRPCCommands[] = /* Address index */ { "addressindex", "getaddresstxids", &getaddresstxids, false }, + { "addressindex", "getaddressbalance", &getaddressbalance, false }, /* Utility functions */ { "util", "createmultisig", &createmultisig, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 11f7600511..8a80fc5ee2 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -167,6 +167,7 @@ extern void EnsureWalletIsUnlocked(); extern UniValue getconnectioncount(const UniValue& params, bool fHelp); // in rpcnet.cpp extern UniValue getaddresstxids(const UniValue& params, bool fHelp); +extern UniValue getaddressbalance(const UniValue& params, bool fHelp); extern UniValue getpeerinfo(const UniValue& params, bool fHelp); extern UniValue ping(const UniValue& params, bool fHelp);