wallet: Use WalletTXO stored state and coinbase rather than wtx

This commit is contained in:
Ava Chow 2024-02-20 11:54:32 -05:00
parent a74ef9bfed
commit 7d2bcc7458
2 changed files with 33 additions and 16 deletions

View file

@ -209,23 +209,27 @@ bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminef
} }
// NOLINTNEXTLINE(misc-no-recursion) // NOLINTNEXTLINE(misc-no-recursion)
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents) bool CachedTxIsTrusted(const CWallet& wallet, const TxState& state, const uint256& txid, std::set<uint256>& trusted_parents)
{ {
AssertLockHeld(wallet.cs_wallet); AssertLockHeld(wallet.cs_wallet);
// This wtx is already trusted // This wtx is already trusted
if (trusted_parents.contains(wtx.GetHash())) return true; if (trusted_parents.contains(txid)) return true;
if (wtx.isConfirmed()) return true; if (std::holds_alternative<TxStateConfirmed>(state)) return true;
if (wtx.isBlockConflicted()) return false; if (std::holds_alternative<TxStateBlockConflicted>(state)) return false;
// using wtx's cached debit
if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx, ISMINE_ALL)) return false;
// Don't trust unconfirmed transactions from us unless they are in the mempool. // Don't trust unconfirmed transactions from us unless they are in the mempool.
if (!wtx.InMempool()) return false; if (!std::holds_alternative<TxStateInMempool>(state)) return false;
const CWalletTx* wtx = wallet.GetWalletTx(txid);
assert(wtx);
// using wtx's cached debit
if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, *wtx, ISMINE_ALL)) return false;
// Trusted if all inputs are from us and are in the mempool: // Trusted if all inputs are from us and are in the mempool:
for (const CTxIn& txin : wtx.tx->vin) for (const CTxIn& txin : wtx->tx->vin)
{ {
// Transactions not sent by us: not trusted // Transactions not sent by us: not trusted
const CWalletTx* parent = wallet.GetWalletTx(txin.prevout.hash); const CWalletTx* parent = wallet.GetWalletTx(txin.prevout.hash);
@ -236,12 +240,23 @@ bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uin
// If we've already trusted this parent, continue // If we've already trusted this parent, continue
if (trusted_parents.count(parent->GetHash())) continue; if (trusted_parents.count(parent->GetHash())) continue;
// Recurse to check that the parent is also trusted // Recurse to check that the parent is also trusted
if (!CachedTxIsTrusted(wallet, *parent, trusted_parents)) return false; if (!CachedTxIsTrusted(wallet, parent->GetState(), parent->GetHash(), trusted_parents)) return false;
trusted_parents.insert(parent->GetHash()); trusted_parents.insert(parent->GetHash());
} }
return true; return true;
} }
bool CachedTxIsTrusted(const CWallet& wallet, const TxState& state, const uint256& txid)
{
std::set<uint256> trusted_parents;
return CachedTxIsTrusted(wallet, state, txid, trusted_parents);
}
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents)
{
return CachedTxIsTrusted(wallet, wtx.m_state, wtx.GetHash(), trusted_parents);
}
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx) bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx)
{ {
std::set<uint256> trusted_parents; std::set<uint256> trusted_parents;
@ -258,8 +273,8 @@ Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
for (const auto& [outpoint, txo] : wallet.GetTXOs()) { for (const auto& [outpoint, txo] : wallet.GetTXOs()) {
Assert(MoneyRange(txo.GetTxOut().nValue)); Assert(MoneyRange(txo.GetTxOut().nValue));
const bool is_trusted{CachedTxIsTrusted(wallet, txo.GetWalletTx())}; const bool is_trusted{CachedTxIsTrusted(wallet, txo.GetState(), outpoint.hash)};
const int tx_depth{wallet.GetTxDepthInMainChain(txo.GetWalletTx())}; const int tx_depth{wallet.GetTxStateDepthInMainChain(txo.GetState())};
if (!wallet.IsSpent(outpoint) && (allow_used_addresses || !wallet.IsSpentKey(txo.GetTxOut().scriptPubKey))) { if (!wallet.IsSpent(outpoint) && (allow_used_addresses || !wallet.IsSpentKey(txo.GetTxOut().scriptPubKey))) {
// Get the amounts for mine and watchonly // Get the amounts for mine and watchonly
@ -275,13 +290,13 @@ Balance GetBalance(const CWallet& wallet, const int min_depth, bool avoid_reuse)
} }
// Set the amounts in the return object // Set the amounts in the return object
if (wallet.IsTxImmatureCoinBase(txo.GetWalletTx()) && txo.GetWalletTx().isConfirmed()) { if (wallet.IsTXOInImmatureCoinBase(txo) && std::holds_alternative<TxStateConfirmed>(txo.GetState())) {
ret.m_mine_immature += credit_mine; ret.m_mine_immature += credit_mine;
ret.m_watchonly_immature += credit_watchonly; ret.m_watchonly_immature += credit_watchonly;
} else if (is_trusted && tx_depth >= min_depth) { } else if (is_trusted && tx_depth >= min_depth) {
ret.m_mine_trusted += credit_mine; ret.m_mine_trusted += credit_mine;
ret.m_watchonly_trusted += credit_watchonly; ret.m_watchonly_trusted += credit_watchonly;
} else if (!is_trusted && txo.GetWalletTx().InMempool()) { } else if (!is_trusted && tx_depth == 0 && std::get_if<TxStateInMempool>(&txo.GetState())) {
ret.m_mine_untrusted_pending += credit_mine; ret.m_mine_untrusted_pending += credit_mine;
ret.m_watchonly_untrusted_pending += credit_watchonly; ret.m_watchonly_untrusted_pending += credit_watchonly;
} }
@ -298,10 +313,10 @@ std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
{ {
LOCK(wallet.cs_wallet); LOCK(wallet.cs_wallet);
for (const auto& [outpoint, txo] : wallet.GetTXOs()) { for (const auto& [outpoint, txo] : wallet.GetTXOs()) {
if (!CachedTxIsTrusted(wallet, txo.GetWalletTx())) continue; if (!CachedTxIsTrusted(wallet, txo.GetState(), outpoint.hash)) continue;
if (wallet.IsTxImmatureCoinBase(txo.GetWalletTx())) continue; if (wallet.IsTXOInImmatureCoinBase(txo)) continue;
int nDepth = wallet.GetTxDepthInMainChain(txo.GetWalletTx()); int nDepth = wallet.GetTxStateDepthInMainChain(txo.GetState());
if (nDepth < (CachedTxIsFromMe(wallet, txo.GetWalletTx(), ISMINE_ALL) ? 0 : 1)) continue; if (nDepth < (CachedTxIsFromMe(wallet, txo.GetWalletTx(), ISMINE_ALL) ? 0 : 1)) continue;
CTxDestination addr; CTxDestination addr;

View file

@ -41,6 +41,8 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
CAmount& nFee, const isminefilter& filter, CAmount& nFee, const isminefilter& filter,
bool include_change); bool include_change);
bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter); bool CachedTxIsFromMe(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter);
bool CachedTxIsTrusted(const CWallet& wallet, const TxState& state, const uint256& txid, std::set<uint256>& trusted_parents) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
bool CachedTxIsTrusted(const CWallet& wallet, const TxState& state, const uint256& txid) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx, std::set<uint256>& trusted_parents) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet);
bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx); bool CachedTxIsTrusted(const CWallet& wallet, const CWalletTx& wtx);