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)
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);
// 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 (wtx.isBlockConflicted()) return false;
// using wtx's cached debit
if (!wallet.m_spend_zero_conf_change || !CachedTxIsFromMe(wallet, wtx, ISMINE_ALL)) return false;
if (std::holds_alternative<TxStateConfirmed>(state)) return true;
if (std::holds_alternative<TxStateBlockConflicted>(state)) return false;
// 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:
for (const CTxIn& txin : wtx.tx->vin)
for (const CTxIn& txin : wtx->tx->vin)
{
// Transactions not sent by us: not trusted
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 (trusted_parents.count(parent->GetHash())) continue;
// 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());
}
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)
{
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()) {
Assert(MoneyRange(txo.GetTxOut().nValue));
const bool is_trusted{CachedTxIsTrusted(wallet, txo.GetWalletTx())};
const int tx_depth{wallet.GetTxDepthInMainChain(txo.GetWalletTx())};
const bool is_trusted{CachedTxIsTrusted(wallet, txo.GetState(), outpoint.hash)};
const int tx_depth{wallet.GetTxStateDepthInMainChain(txo.GetState())};
if (!wallet.IsSpent(outpoint) && (allow_used_addresses || !wallet.IsSpentKey(txo.GetTxOut().scriptPubKey))) {
// 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
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_watchonly_immature += credit_watchonly;
} else if (is_trusted && tx_depth >= min_depth) {
ret.m_mine_trusted += credit_mine;
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_watchonly_untrusted_pending += credit_watchonly;
}
@ -298,10 +313,10 @@ std::map<CTxDestination, CAmount> GetAddressBalances(const CWallet& wallet)
{
LOCK(wallet.cs_wallet);
for (const auto& [outpoint, txo] : wallet.GetTXOs()) {
if (!CachedTxIsTrusted(wallet, txo.GetWalletTx())) continue;
if (wallet.IsTxImmatureCoinBase(txo.GetWalletTx())) continue;
if (!CachedTxIsTrusted(wallet, txo.GetState(), outpoint.hash)) 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;
CTxDestination addr;

View file

@ -41,6 +41,8 @@ void CachedTxGetAmounts(const CWallet& wallet, const CWalletTx& wtx,
CAmount& nFee, const isminefilter& filter,
bool include_change);
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);