Merge #15747: wallet: Remove plethora of Get*Balance

fa57411fc wallet: Get all balances in one call (MarcoFalke)

Pull request description:

  The wallet provides a getter for each "type" of balance. However, a single iteration over `mapWallet` is sufficient to calculate all types of balances.

ACKs for commit fa5741:
  Empact:
    utACK fa57411fcb
  promag:
    utACK fa57411.
  MeshCollider:
    utACK fa57411fcb

Tree-SHA512: 38b7f346ec95d2604a4d32f4caef2841b8fe59511d2d23890ba3dc497bb2f45eb6be87d12eb004005cad16e9fea83ae6e3000f2197c7a677a07debdb457064a2
This commit is contained in:
MeshCollider 2019-04-10 00:21:35 +12:00
commit db2985651d
No known key found for this signature in database
GPG key ID: D300116E1C875A3D
5 changed files with 48 additions and 92 deletions

View file

@ -358,15 +358,16 @@ public:
} }
WalletBalances getBalances() override WalletBalances getBalances() override
{ {
const auto bal = m_wallet->GetBalance();
WalletBalances result; WalletBalances result;
result.balance = m_wallet->GetBalance(); result.balance = bal.m_mine_trusted;
result.unconfirmed_balance = m_wallet->GetUnconfirmedBalance(); result.unconfirmed_balance = bal.m_mine_untrusted_pending;
result.immature_balance = m_wallet->GetImmatureBalance(); result.immature_balance = bal.m_mine_immature;
result.have_watch_only = m_wallet->HaveWatchOnly(); result.have_watch_only = m_wallet->HaveWatchOnly();
if (result.have_watch_only) { if (result.have_watch_only) {
result.watch_only_balance = m_wallet->GetBalance(ISMINE_WATCH_ONLY); result.watch_only_balance = bal.m_watchonly_trusted;
result.unconfirmed_watch_only_balance = m_wallet->GetUnconfirmedWatchOnlyBalance(); result.unconfirmed_watch_only_balance = bal.m_watchonly_untrusted_pending;
result.immature_watch_only_balance = m_wallet->GetImmatureWatchOnlyBalance(); result.immature_watch_only_balance = bal.m_watchonly_immature;
} }
return result; return result;
} }
@ -382,7 +383,7 @@ public:
num_blocks = locked_chain->getHeight().get_value_or(-1); num_blocks = locked_chain->getHeight().get_value_or(-1);
return true; return true;
} }
CAmount getBalance() override { return m_wallet->GetBalance(); } CAmount getBalance() override { return m_wallet->GetBalance().m_mine_trusted; }
CAmount getAvailableBalance(const CCoinControl& coin_control) override CAmount getAvailableBalance(const CCoinControl& coin_control) override
{ {
return m_wallet->GetAvailableBalance(&coin_control); return m_wallet->GetAvailableBalance(&coin_control);

View file

@ -308,7 +308,7 @@ static UniValue setlabel(const JSONRPCRequest& request)
static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue) static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet * const pwallet, const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, const CCoinControl& coin_control, mapValue_t mapValue)
{ {
CAmount curBalance = pwallet->GetBalance(); CAmount curBalance = pwallet->GetBalance().m_mine_trusted;
// Check amount // Check amount
if (nValue <= 0) if (nValue <= 0)
@ -761,12 +761,14 @@ static UniValue getbalance(const JSONRPCRequest& request)
min_depth = request.params[1].get_int(); min_depth = request.params[1].get_int();
} }
isminefilter filter = ISMINE_SPENDABLE; bool include_watchonly = false;
if (!request.params[2].isNull() && request.params[2].get_bool()) { if (!request.params[2].isNull() && request.params[2].get_bool()) {
filter = filter | ISMINE_WATCH_ONLY; include_watchonly = true;
} }
return ValueFromAmount(pwallet->GetBalance(filter, min_depth)); const auto bal = pwallet->GetBalance(min_depth);
return ValueFromAmount(bal.m_mine_trusted + (include_watchonly ? bal.m_watchonly_trusted : 0));
} }
static UniValue getunconfirmedbalance(const JSONRPCRequest &request) static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
@ -794,7 +796,7 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
auto locked_chain = pwallet->chain().lock(); auto locked_chain = pwallet->chain().lock();
LOCK(pwallet->cs_wallet); LOCK(pwallet->cs_wallet);
return ValueFromAmount(pwallet->GetUnconfirmedBalance()); return ValueFromAmount(pwallet->GetBalance().m_mine_untrusted_pending);
} }
@ -2416,11 +2418,12 @@ static UniValue getwalletinfo(const JSONRPCRequest& request)
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
size_t kpExternalSize = pwallet->KeypoolCountExternalKeys(); size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
const auto bal = pwallet->GetBalance();
obj.pushKV("walletname", pwallet->GetName()); obj.pushKV("walletname", pwallet->GetName());
obj.pushKV("walletversion", pwallet->GetVersion()); obj.pushKV("walletversion", pwallet->GetVersion());
obj.pushKV("balance", ValueFromAmount(pwallet->GetBalance())); obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
obj.pushKV("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance())); obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
obj.pushKV("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance())); obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
obj.pushKV("txcount", (int)pwallet->mapWallet.size()); obj.pushKV("txcount", (int)pwallet->mapWallet.size());
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime()); obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
obj.pushKV("keypoolsize", (int64_t)kpExternalSize); obj.pushKV("keypoolsize", (int64_t)kpExternalSize);

View file

@ -58,7 +58,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_CHECK(result.last_failed_block.IsNull()); BOOST_CHECK(result.last_failed_block.IsNull());
BOOST_CHECK(result.last_scanned_block.IsNull()); BOOST_CHECK(result.last_scanned_block.IsNull());
BOOST_CHECK(!result.last_scanned_height); BOOST_CHECK(!result.last_scanned_height);
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 0); BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 0);
} }
// Verify ScanForWalletTransactions picks up transactions in both the old // Verify ScanForWalletTransactions picks up transactions in both the old
@ -73,7 +73,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_CHECK(result.last_failed_block.IsNull()); BOOST_CHECK(result.last_failed_block.IsNull());
BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash()); BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight); BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight);
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 100 * COIN); BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 100 * COIN);
} }
// Prune the older block file. // Prune the older block file.
@ -92,7 +92,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_CHECK_EQUAL(result.last_failed_block, oldTip->GetBlockHash()); BOOST_CHECK_EQUAL(result.last_failed_block, oldTip->GetBlockHash());
BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash()); BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight); BOOST_CHECK_EQUAL(*result.last_scanned_height, newTip->nHeight);
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 50 * COIN); BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 50 * COIN);
} }
// Prune the remaining block file. // Prune the remaining block file.
@ -110,7 +110,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_CHECK_EQUAL(result.last_failed_block, newTip->GetBlockHash()); BOOST_CHECK_EQUAL(result.last_failed_block, newTip->GetBlockHash());
BOOST_CHECK(result.last_scanned_block.IsNull()); BOOST_CHECK(result.last_scanned_block.IsNull());
BOOST_CHECK(!result.last_scanned_height); BOOST_CHECK(!result.last_scanned_height);
BOOST_CHECK_EQUAL(wallet.GetImmatureBalance(), 0); BOOST_CHECK_EQUAL(wallet.GetBalance().m_mine_immature, 0);
} }
} }

View file

@ -2154,84 +2154,32 @@ void CWallet::ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, in
*/ */
CAmount CWallet::GetBalance(const isminefilter& filter, const int min_depth) const CWallet::Balance CWallet::GetBalance(const int min_depth) const
{ {
CAmount nTotal = 0; Balance ret;
{ {
auto locked_chain = chain().lock(); auto locked_chain = chain().lock();
LOCK(cs_wallet); LOCK(cs_wallet);
for (const auto& entry : mapWallet) for (const auto& entry : mapWallet)
{ {
const CWalletTx& wtx = entry.second; const CWalletTx& wtx = entry.second;
if (wtx.IsTrusted(*locked_chain) && wtx.GetDepthInMainChain(*locked_chain) >= min_depth) { const bool is_trusted{wtx.IsTrusted(*locked_chain)};
nTotal += wtx.GetAvailableCredit(*locked_chain, true, filter); const int tx_depth{wtx.GetDepthInMainChain(*locked_chain)};
const CAmount tx_credit_mine{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_SPENDABLE)};
const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(*locked_chain, /* fUseCache */ true, ISMINE_WATCH_ONLY)};
if (is_trusted && tx_depth >= min_depth) {
ret.m_mine_trusted += tx_credit_mine;
ret.m_watchonly_trusted += tx_credit_watchonly;
}
if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
ret.m_mine_untrusted_pending += tx_credit_mine;
ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
}
ret.m_mine_immature += wtx.GetImmatureCredit(*locked_chain);
ret.m_watchonly_immature += wtx.GetImmatureWatchOnlyCredit(*locked_chain);
} }
} }
} return ret;
return nTotal;
}
CAmount CWallet::GetUnconfirmedBalance() const
{
CAmount nTotal = 0;
{
auto locked_chain = chain().lock();
LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx& wtx = entry.second;
if (!wtx.IsTrusted(*locked_chain) && wtx.GetDepthInMainChain(*locked_chain) == 0 && wtx.InMempool())
nTotal += wtx.GetAvailableCredit(*locked_chain);
}
}
return nTotal;
}
CAmount CWallet::GetImmatureBalance() const
{
CAmount nTotal = 0;
{
auto locked_chain = chain().lock();
LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx& wtx = entry.second;
nTotal += wtx.GetImmatureCredit(*locked_chain);
}
}
return nTotal;
}
CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
{
CAmount nTotal = 0;
{
auto locked_chain = chain().lock();
LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx& wtx = entry.second;
if (!wtx.IsTrusted(*locked_chain) && wtx.GetDepthInMainChain(*locked_chain) == 0 && wtx.InMempool())
nTotal += wtx.GetAvailableCredit(*locked_chain, true, ISMINE_WATCH_ONLY);
}
}
return nTotal;
}
CAmount CWallet::GetImmatureWatchOnlyBalance() const
{
CAmount nTotal = 0;
{
auto locked_chain = chain().lock();
LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx& wtx = entry.second;
nTotal += wtx.GetImmatureWatchOnlyCredit(*locked_chain);
}
}
return nTotal;
} }
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const

View file

@ -947,11 +947,15 @@ public:
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override; void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
void ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); void ReacceptWalletTransactions(interfaces::Chain::Lock& locked_chain) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
void ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime) override; void ResendWalletTransactions(interfaces::Chain::Lock& locked_chain, int64_t nBestBlockTime) override;
CAmount GetBalance(const isminefilter& filter=ISMINE_SPENDABLE, const int min_depth=0) const; struct Balance {
CAmount GetUnconfirmedBalance() const; CAmount m_mine_trusted{0}; //!< Trusted, at depth=GetBalance.min_depth or more
CAmount GetImmatureBalance() const; CAmount m_mine_untrusted_pending{0}; //!< Untrusted, but in mempool (pending)
CAmount GetUnconfirmedWatchOnlyBalance() const; CAmount m_mine_immature{0}; //!< Immature coinbases in the main chain
CAmount GetImmatureWatchOnlyBalance() const; CAmount m_watchonly_trusted{0};
CAmount m_watchonly_untrusted_pending{0};
CAmount m_watchonly_immature{0};
};
Balance GetBalance(int min_depth = 0) const;
CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const; CAmount GetAvailableBalance(const CCoinControl* coinControl = nullptr) const;
OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend); OutputType TransactionChangeType(OutputType change_type, const std::vector<CRecipient>& vecSend);