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
{
const auto bal = m_wallet->GetBalance();
WalletBalances result;
result.balance = m_wallet->GetBalance();
result.unconfirmed_balance = m_wallet->GetUnconfirmedBalance();
result.immature_balance = m_wallet->GetImmatureBalance();
result.balance = bal.m_mine_trusted;
result.unconfirmed_balance = bal.m_mine_untrusted_pending;
result.immature_balance = bal.m_mine_immature;
result.have_watch_only = m_wallet->HaveWatchOnly();
if (result.have_watch_only) {
result.watch_only_balance = m_wallet->GetBalance(ISMINE_WATCH_ONLY);
result.unconfirmed_watch_only_balance = m_wallet->GetUnconfirmedWatchOnlyBalance();
result.immature_watch_only_balance = m_wallet->GetImmatureWatchOnlyBalance();
result.watch_only_balance = bal.m_watchonly_trusted;
result.unconfirmed_watch_only_balance = bal.m_watchonly_untrusted_pending;
result.immature_watch_only_balance = bal.m_watchonly_immature;
}
return result;
}
@ -382,7 +383,7 @@ public:
num_blocks = locked_chain->getHeight().get_value_or(-1);
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
{
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)
{
CAmount curBalance = pwallet->GetBalance();
CAmount curBalance = pwallet->GetBalance().m_mine_trusted;
// Check amount
if (nValue <= 0)
@ -761,12 +761,14 @@ static UniValue getbalance(const JSONRPCRequest& request)
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()) {
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)
@ -794,7 +796,7 @@ static UniValue getunconfirmedbalance(const JSONRPCRequest &request)
auto locked_chain = pwallet->chain().lock();
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);
size_t kpExternalSize = pwallet->KeypoolCountExternalKeys();
const auto bal = pwallet->GetBalance();
obj.pushKV("walletname", pwallet->GetName());
obj.pushKV("walletversion", pwallet->GetVersion());
obj.pushKV("balance", ValueFromAmount(pwallet->GetBalance()));
obj.pushKV("unconfirmed_balance", ValueFromAmount(pwallet->GetUnconfirmedBalance()));
obj.pushKV("immature_balance", ValueFromAmount(pwallet->GetImmatureBalance()));
obj.pushKV("balance", ValueFromAmount(bal.m_mine_trusted));
obj.pushKV("unconfirmed_balance", ValueFromAmount(bal.m_mine_untrusted_pending));
obj.pushKV("immature_balance", ValueFromAmount(bal.m_mine_immature));
obj.pushKV("txcount", (int)pwallet->mapWallet.size());
obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime());
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_scanned_block.IsNull());
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
@ -73,7 +73,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_CHECK(result.last_failed_block.IsNull());
BOOST_CHECK_EQUAL(result.last_scanned_block, newTip->GetBlockHash());
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.
@ -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_scanned_block, newTip->GetBlockHash());
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.
@ -110,7 +110,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
BOOST_CHECK_EQUAL(result.last_failed_block, newTip->GetBlockHash());
BOOST_CHECK(result.last_scanned_block.IsNull());
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();
LOCK(cs_wallet);
for (const auto& entry : mapWallet)
{
const CWalletTx& wtx = entry.second;
if (wtx.IsTrusted(*locked_chain) && wtx.GetDepthInMainChain(*locked_chain) >= min_depth) {
nTotal += wtx.GetAvailableCredit(*locked_chain, true, filter);
const bool is_trusted{wtx.IsTrusted(*locked_chain)};
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 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;
return ret;
}
CAmount CWallet::GetAvailableBalance(const CCoinControl* coinControl) const

View file

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