From 4279da47855ec776f8d57c6579fe89afc9cbe8c1 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Mon, 25 Jun 2018 14:39:36 -0400 Subject: [wallet] GetBalance can take an isminefilter filter. GetBalance() can now take an ismine filter, which is passed down to GetAvailableCredit. This allows GetBalance to be used to get watch-only balances. --- src/wallet/wallet.cpp | 30 +++++++++++++++++++++--------- src/wallet/wallet.h | 4 ++-- 2 files changed, 23 insertions(+), 11 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 842516bb0e..4f3a443201 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1968,7 +1968,7 @@ CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const return 0; } -CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const +CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter) const { if (pwallet == nullptr) return 0; @@ -1977,8 +1977,17 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const if (IsCoinBase() && GetBlocksToMaturity() > 0) return 0; - if (fUseCache && fAvailableCreditCached) - return nAvailableCreditCached; + CAmount* cache = nullptr; + bool* cache_used = nullptr; + + if (filter == ISMINE_SPENDABLE) { + cache = &nAvailableCreditCached; + cache_used = &fAvailableCreditCached; + } + + if (fUseCache && cache_used && *cache_used) { + return *cache; + } CAmount nCredit = 0; uint256 hashTx = GetHash(); @@ -1987,14 +1996,16 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const if (!pwallet->IsSpent(hashTx, i)) { const CTxOut &txout = tx->vout[i]; - nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE); + nCredit += pwallet->GetCredit(txout, filter); if (!MoneyRange(nCredit)) throw std::runtime_error(std::string(__func__) + " : value out of range"); } } - nAvailableCreditCached = nCredit; - fAvailableCreditCached = true; + if (cache) { + *cache = nCredit; + *cache_used = true; + } return nCredit; } @@ -2154,7 +2165,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman */ -CAmount CWallet::GetBalance() const +CAmount CWallet::GetBalance(const isminefilter& filter) const { CAmount nTotal = 0; { @@ -2162,8 +2173,9 @@ CAmount CWallet::GetBalance() const for (const auto& entry : mapWallet) { const CWalletTx* pcoin = &entry.second; - if (pcoin->IsTrusted()) - nTotal += pcoin->GetAvailableCredit(); + if (pcoin->IsTrusted()) { + nTotal += pcoin->GetAvailableCredit(true, filter); + } } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index b829394847..004c0935eb 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -460,7 +460,7 @@ public: CAmount GetDebit(const isminefilter& filter) const; CAmount GetCredit(const isminefilter& filter) const; CAmount GetImmatureCredit(bool fUseCache=true) const; - CAmount GetAvailableCredit(bool fUseCache=true) const; + CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const; CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const; CAmount GetAvailableWatchOnlyCredit(const bool fUseCache=true) const; CAmount GetChange() const; @@ -944,7 +944,7 @@ public: void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override; // ResendWalletTransactionsBefore may only be called if fBroadcastTransactions! std::vector ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman); - CAmount GetBalance() const; + CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE) const; CAmount GetUnconfirmedBalance() const; CAmount GetImmatureBalance() const; CAmount GetWatchOnlyBalance() const; -- cgit v1.2.3 From ef7bc8893c7a953953aa457736d79c28a4f45792 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 27 Jun 2018 13:43:25 -0400 Subject: [wallet] Factor out GetWatchOnlyBalance() --- src/wallet/wallet.cpp | 16 ---------------- src/wallet/wallet.h | 1 - 2 files changed, 17 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4f3a443201..f999394062 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2211,22 +2211,6 @@ CAmount CWallet::GetImmatureBalance() const return nTotal; } -CAmount CWallet::GetWatchOnlyBalance() const -{ - CAmount nTotal = 0; - { - LOCK2(cs_main, cs_wallet); - for (const auto& entry : mapWallet) - { - const CWalletTx* pcoin = &entry.second; - if (pcoin->IsTrusted()) - nTotal += pcoin->GetAvailableWatchOnlyCredit(); - } - } - - return nTotal; -} - CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const { CAmount nTotal = 0; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 004c0935eb..4cb881bc48 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -947,7 +947,6 @@ public: CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE) const; CAmount GetUnconfirmedBalance() const; CAmount GetImmatureBalance() const; - CAmount GetWatchOnlyBalance() const; CAmount GetUnconfirmedWatchOnlyBalance() const; CAmount GetImmatureWatchOnlyBalance() const; CAmount GetLegacyBalance(const isminefilter& filter, int minDepth, const std::string* account) const; -- cgit v1.2.3 From 7110c830f8c5de3570178bf4e5d28fe3e4f109e1 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 27 Jun 2018 11:46:27 -0400 Subject: [wallet] deduplicate GetAvailableCredit logic --- src/wallet/wallet.cpp | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f999394062..4d3263671c 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1983,6 +1983,9 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache, const isminefilter& filter if (filter == ISMINE_SPENDABLE) { cache = &nAvailableCreditCached; cache_used = &fAvailableCreditCached; + } else if (filter == ISMINE_WATCH_ONLY) { + cache = &nAvailableWatchCreditCached; + cache_used = &fAvailableWatchCreditCached; } if (fUseCache && cache_used && *cache_used) { @@ -2025,31 +2028,7 @@ CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool fUseCache) const { - if (pwallet == nullptr) - return 0; - - // Must wait until coinbase is safely deep enough in the chain before valuing it - if (IsCoinBase() && GetBlocksToMaturity() > 0) - return 0; - - if (fUseCache && fAvailableWatchCreditCached) - return nAvailableWatchCreditCached; - - CAmount nCredit = 0; - for (unsigned int i = 0; i < tx->vout.size(); i++) - { - if (!pwallet->IsSpent(GetHash(), i)) - { - const CTxOut &txout = tx->vout[i]; - nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY); - if (!MoneyRange(nCredit)) - throw std::runtime_error(std::string(__func__) + ": value out of range"); - } - } - - nAvailableWatchCreditCached = nCredit; - fAvailableWatchCreditCached = true; - return nCredit; + return GetAvailableCredit(fUseCache, ISMINE_WATCH_ONLY); } CAmount CWalletTx::GetChange() const -- cgit v1.2.3 From 0f3d6e9ab75837ead3acfda342aa3ea404efb81d Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 27 Jun 2018 11:53:08 -0400 Subject: [wallet] factor out GetAvailableWatchOnlyBalance() --- src/wallet/wallet.cpp | 7 +------ src/wallet/wallet.h | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4d3263671c..1038416fe4 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2026,11 +2026,6 @@ CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool fUseCache) const return 0; } -CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool fUseCache) const -{ - return GetAvailableCredit(fUseCache, ISMINE_WATCH_ONLY); -} - CAmount CWalletTx::GetChange() const { if (fChangeCached) @@ -2199,7 +2194,7 @@ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const { const CWalletTx* pcoin = &entry.second; if (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0 && pcoin->InMempool()) - nTotal += pcoin->GetAvailableWatchOnlyCredit(); + nTotal += pcoin->GetAvailableCredit(true, ISMINE_WATCH_ONLY); } } return nTotal; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 4cb881bc48..bc70ffc595 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -462,7 +462,6 @@ public: CAmount GetImmatureCredit(bool fUseCache=true) const; CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const; CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const; - CAmount GetAvailableWatchOnlyCredit(const bool fUseCache=true) const; CAmount GetChange() const; // Get the marginal bytes if spending the specified output from this transaction -- cgit v1.2.3 From cf15761f6d4526d205126fbf5f088ac8edebeb57 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 27 Jun 2018 14:11:21 -0400 Subject: [wallet] GetBalance can take a min_depth argument. --- src/wallet/wallet.cpp | 4 ++-- src/wallet/wallet.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 1038416fe4..25a832e813 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2139,7 +2139,7 @@ void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman */ -CAmount CWallet::GetBalance(const isminefilter& filter) const +CAmount CWallet::GetBalance(const isminefilter& filter, const int min_depth) const { CAmount nTotal = 0; { @@ -2147,7 +2147,7 @@ CAmount CWallet::GetBalance(const isminefilter& filter) const for (const auto& entry : mapWallet) { const CWalletTx* pcoin = &entry.second; - if (pcoin->IsTrusted()) { + if (pcoin->IsTrusted() && pcoin->GetDepthInMainChain() >= min_depth) { nTotal += pcoin->GetAvailableCredit(true, filter); } } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index bc70ffc595..ed766556fd 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -943,7 +943,7 @@ public: void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) override; // ResendWalletTransactionsBefore may only be called if fBroadcastTransactions! std::vector ResendWalletTransactionsBefore(int64_t nTime, CConnman* connman); - CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE) const; + CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE, const int min_depth=0) const; CAmount GetUnconfirmedBalance() const; CAmount GetImmatureBalance() const; CAmount GetUnconfirmedWatchOnlyBalance() const; -- cgit v1.2.3 From 702ae1e21a09d8c31406839c4ea507c5fa276898 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 26 Jun 2018 17:21:30 -0400 Subject: [RPC] [wallet] allow getbalance to use min_conf and watch_only without accounts. --- src/wallet/rpcwallet.cpp | 65 +++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 29 deletions(-) (limited to 'src/wallet') diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index bc381d3cda..32d707663c 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"} }, -- cgit v1.2.3