From 702ae1e21a09d8c31406839c4ea507c5fa276898 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 26 Jun 2018 17:21:30 -0400 Subject: [PATCH] [RPC] [wallet] allow getbalance to use min_conf and watch_only without accounts. --- src/wallet/rpcwallet.cpp | 65 ++++++++++++++++++--------------- test/functional/wallet_basic.py | 9 +++++ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index bc381d3cd..32d707663 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -853,8 +853,9 @@ static UniValue getbalance(const JSONRPCRequest& request) return NullUniValue; } - if (request.fHelp || (request.params.size() > 3 && IsDeprecatedRPCEnabled("accounts")) || (request.params.size() != 0 && !IsDeprecatedRPCEnabled("accounts"))) + if (request.fHelp || (request.params.size() > 3 )) throw std::runtime_error( + (IsDeprecatedRPCEnabled("accounts") ? std::string( "getbalance ( \"account\" minconf include_watchonly )\n" "\nIf account is not specified, returns the server's total available balance.\n" "The available balance is what the wallet considers currently spendable, and is\n" @@ -876,8 +877,17 @@ static UniValue getbalance(const JSONRPCRequest& request) " balances. In general, account balance calculation is not considered\n" " reliable and has resulted in confusing outcomes, so it is recommended to\n" " avoid passing this argument.\n" - "2. minconf (numeric, optional, default=1) DEPRECATED. Only valid when an account is specified. This argument will be removed in V0.18. To use this deprecated argument, start bitcoind with -deprecatedrpc=accounts. Only include transactions confirmed at least this many times.\n" - "3. include_watchonly (bool, optional, default=false) DEPRECATED. Only valid when an account is specified. This argument will be removed in V0.18. To use this deprecated argument, start bitcoind with -deprecatedrpc=accounts. Also include balance in watch-only addresses (see 'importaddress')\n" + "2. minconf (numeric, optional) Only include transactions confirmed at least this many times. \n" + " The default is 1 if an account is provided or 0 if no account is provided\n") + : std::string( + "getbalance ( \"(dummy)\" minconf include_watchonly )\n" + "\nReturns the total available balance.\n" + "The available balance is what the wallet considers currently spendable, and is\n" + "thus affected by options which limit spendability such as -spendzeroconfchange.\n" + "\nArguments:\n" + "1. (dummy) (string, optional) Remains for backward compatibility. Must be excluded or set to \"*\".\n" + "2. minconf (numeric, optional, default=0) Only include transactions confirmed at least this many times.\n")) + + "3. include_watchonly (bool, optional, default=false) Also include balance in watch-only addresses (see 'importaddress')\n" "\nResult:\n" "amount (numeric) The total amount in " + CURRENCY_UNIT + " received for this account.\n" "\nExamples:\n" @@ -895,38 +905,35 @@ static UniValue getbalance(const JSONRPCRequest& request) LOCK2(cs_main, pwallet->cs_wallet); - if (IsDeprecatedRPCEnabled("accounts")) { - const UniValue& account_value = request.params[0]; - const UniValue& minconf = request.params[1]; - const UniValue& include_watchonly = request.params[2]; + const UniValue& account_value = request.params[0]; - if (account_value.isNull()) { - if (!minconf.isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, - "getbalance minconf option is only currently supported if an account is specified"); - } - if (!include_watchonly.isNull()) { - throw JSONRPCError(RPC_INVALID_PARAMETER, - "getbalance include_watchonly option is only currently supported if an account is specified"); - } - return ValueFromAmount(pwallet->GetBalance()); - } + int min_depth = 0; + if (IsDeprecatedRPCEnabled("accounts") && !account_value.isNull()) { + // Default min_depth to 1 when an account is provided. + min_depth = 1; + } + if (!request.params[1].isNull()) { + min_depth = request.params[1].get_int(); + } + + isminefilter filter = ISMINE_SPENDABLE; + if (!request.params[2].isNull() && request.params[2].get_bool()) { + filter = filter | ISMINE_WATCH_ONLY; + } + + if (!account_value.isNull()) { const std::string& account_param = account_value.get_str(); const std::string* account = account_param != "*" ? &account_param : nullptr; - int nMinDepth = 1; - if (!minconf.isNull()) - nMinDepth = minconf.get_int(); - isminefilter filter = ISMINE_SPENDABLE; - if(!include_watchonly.isNull()) - if(include_watchonly.get_bool()) - filter = filter | ISMINE_WATCH_ONLY; - - return ValueFromAmount(pwallet->GetLegacyBalance(filter, nMinDepth, account)); + if (!IsDeprecatedRPCEnabled("accounts") && account_param != "*") { + throw JSONRPCError(RPC_METHOD_DEPRECATED, "dummy first argument must be excluded or set to \"*\"."); + } else if (IsDeprecatedRPCEnabled("accounts")) { + return ValueFromAmount(pwallet->GetLegacyBalance(filter, min_depth, account)); + } } - return ValueFromAmount(pwallet->GetBalance()); + return ValueFromAmount(pwallet->GetBalance(filter, min_depth)); } static UniValue getunconfirmedbalance(const JSONRPCRequest &request) @@ -4416,7 +4423,7 @@ static const CRPCCommand commands[] = { "wallet", "dumpwallet", &dumpwallet, {"filename"} }, { "wallet", "encryptwallet", &encryptwallet, {"passphrase"} }, { "wallet", "getaddressinfo", &getaddressinfo, {"address"} }, - { "wallet", "getbalance", &getbalance, {"account","minconf","include_watchonly"} }, + { "wallet", "getbalance", &getbalance, {"account|dummy","minconf","include_watchonly"} }, { "wallet", "getnewaddress", &getnewaddress, {"label|account","address_type"} }, { "wallet", "getrawchangeaddress", &getrawchangeaddress, {"address_type"} }, { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, {"address","minconf"} }, diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index d6a64eaef..92aec200c 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -64,6 +64,15 @@ class WalletTest(BitcoinTestFramework): assert_equal(self.nodes[1].getbalance(), 50) assert_equal(self.nodes[2].getbalance(), 0) + # Check getbalance with different arguments + assert_equal(self.nodes[0].getbalance("*"), 50) + assert_equal(self.nodes[0].getbalance("*", 1), 50) + assert_equal(self.nodes[0].getbalance("*", 1, True), 50) + assert_equal(self.nodes[0].getbalance(minconf=1), 50) + + # first argument of getbalance must be excluded or set to "*" + assert_raises_rpc_error(-32, "dummy first argument must be excluded or set to \"*\"", self.nodes[0].getbalance, "") + # Check that only first and second nodes have UTXOs utxos = self.nodes[0].listunspent() assert_equal(len(utxos), 1)