Skip to content

Commit dde7cbe

Browse files
committed
wallet: Change balance calculation to use m_txos
Since we track the outputs owned by the wallet with m_txos, we can now calculate the balance of the wallet by iterating m_txos and summing up the amounts of the unspent txos. As ISMINE_USED is not an actual isminetype that we attach to outputs and was just passed into `CachedTxGetAvailableCredit` for convenience, we pull the same determining logic from that function into `GetBalances` in order to preserve existing behavior.
1 parent 96e7a89 commit dde7cbe

File tree

2 files changed

+42
-35
lines changed

2 files changed

+42
-35
lines changed

src/wallet/receive.cpp

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <consensus/amount.h>
66
#include <consensus/consensus.h>
7+
#include <util/check.h>
78
#include <wallet/receive.h>
89
#include <wallet/transaction.h>
910
#include <wallet/wallet.h>
@@ -297,27 +298,41 @@ bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx)
297298
Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
298299
{
299300
Balance ret;
300-
isminefilter reuse_filter = avoid_reuse ? ISMINE_NO : ISMINE_USED;
301+
bool allow_used_addresses = !avoid_reuse || !wallet.IsWalletFlagSet(WALLET_FLAG_AVOID_REUSE);
301302
{
302303
LOCK(wallet.cs_wallet);
303304
std::set<Txid> trusted_parents;
304-
for (const auto& entry : wallet.mapWallet)
305-
{
306-
const CWalletTx& wtx = entry.second;
305+
for (const auto& [outpoint, txo] : wallet.GetTXOs()) {
306+
const CWalletTx& wtx = txo.GetWalletTx();
307+
307308
const bool is_trusted{CachedTxIsTrusted(wallet, wtx, trusted_parents)};
308309
const int tx_depth{wallet.GetTxDepthInMainChain(wtx)};
309-
const CAmount tx_credit_mine{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_SPENDABLE | reuse_filter)};
310-
const CAmount tx_credit_watchonly{CachedTxGetAvailableCredit(wallet, wtx, ISMINE_WATCH_ONLY | reuse_filter)};
311-
if (is_trusted && tx_depth >= min_depth) {
312-
ret.m_mine_trusted += tx_credit_mine;
313-
ret.m_watchonly_trusted += tx_credit_watchonly;
314-
}
315-
if (!is_trusted && tx_depth == 0 && wtx.InMempool()) {
316-
ret.m_mine_untrusted_pending += tx_credit_mine;
317-
ret.m_watchonly_untrusted_pending += tx_credit_watchonly;
310+
311+
if (!wallet.IsSpent(outpoint) && (allow_used_addresses || !wallet.IsSpentKey(txo.GetTxOut().scriptPubKey))) {
312+
// Get the amounts for mine and watchonly
313+
CAmount credit_mine = 0;
314+
CAmount credit_watchonly = 0;
315+
if (txo.GetIsMine() == ISMINE_SPENDABLE) {
316+
credit_mine = txo.GetTxOut().nValue;
317+
} else if (txo.GetIsMine() == ISMINE_WATCH_ONLY) {
318+
credit_watchonly = txo.GetTxOut().nValue;
319+
} else {
320+
// We shouldn't see any other isminetypes
321+
Assume(false);
322+
}
323+
324+
// Set the amounts in the return object
325+
if (wallet.IsTxImmatureCoinBase(wtx) && wtx.isConfirmed()) {
326+
ret.m_mine_immature += credit_mine;
327+
ret.m_watchonly_immature += credit_watchonly;
328+
} else if (is_trusted && tx_depth >= min_depth) {
329+
ret.m_mine_trusted += credit_mine;
330+
ret.m_watchonly_trusted += credit_watchonly;
331+
} else if (!is_trusted && wtx.InMempool()) {
332+
ret.m_mine_untrusted_pending += credit_mine;
333+
ret.m_watchonly_untrusted_pending += credit_watchonly;
334+
}
318335
}
319-
ret.m_mine_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_SPENDABLE);
320-
ret.m_watchonly_immature += CachedTxGetImmatureCredit(wallet, wtx, ISMINE_WATCH_ONLY);
321336
}
322337
}
323338
return ret;
@@ -330,31 +345,21 @@ std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
330345
{
331346
LOCK(wallet.cs_wallet);
332347
std::set<Txid> trusted_parents;
333-
for (const auto& walletEntry : wallet.mapWallet)
334-
{
335-
const CWalletTx& wtx = walletEntry.second;
336-
337-
if (!CachedTxIsTrusted(wallet, wtx, trusted_parents))
338-
continue;
348+
for (const auto& [outpoint, txo] : wallet.GetTXOs()) {
349+
const CWalletTx& wtx = txo.GetWalletTx();
339350

340-
if (wallet.IsTxImmatureCoinBase(wtx))
341-
continue;
351+
if (!CachedTxIsTrusted(wallet, wtx, trusted_parents)) continue;
352+
if (wallet.IsTxImmatureCoinBase(wtx)) continue;
342353

343354
int nDepth = wallet.GetTxDepthInMainChain(wtx);
344-
if (nDepth < (CachedTxIsFromMe(wallet, wtx, ISMINE_ALL) ? 0 : 1))
345-
continue;
355+
if (nDepth < (CachedTxIsFromMe(wallet, wtx, ISMINE_ALL) ? 0 : 1)) continue;
346356

347-
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
348-
const auto& output = wtx.tx->vout[i];
349-
CTxDestination addr;
350-
if (!wallet.IsMine(output))
351-
continue;
352-
if(!ExtractDestination(output.scriptPubKey, addr))
353-
continue;
357+
CTxDestination addr;
358+
Assume(wallet.IsMine(txo.GetTxOut()));
359+
if(!ExtractDestination(txo.GetTxOut().scriptPubKey, addr)) continue;
354360

355-
CAmount n = wallet.IsSpent(COutPoint(walletEntry.first, i)) ? 0 : output.nValue;
356-
balances[addr] += n;
357-
}
361+
CAmount n = wallet.IsSpent(outpoint) ? 0 : txo.GetTxOut().nValue;
362+
balances[addr] += n;
358363
}
359364
}
360365

src/wallet/wallet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,8 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
523523

524524
std::set<Txid> GetTxConflicts(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
525525

526+
const std::unordered_map<COutPoint, WalletTXO, SaltedOutpointHasher>& GetTXOs() const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return m_txos; };
527+
526528
/** Cache outputs that belong to the wallet from a single transaction */
527529
void RefreshTXOsFromTx(const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
528530
/** Cache outputs that belong to the wallet for all transactions in the wallet */

0 commit comments

Comments
 (0)