Skip to content

Commit 772ea48

Browse files
committed
wallet: Avoid recursive lock in IsTrusted
1 parent 819f10f commit 772ea48

File tree

2 files changed

+17
-16
lines changed

2 files changed

+17
-16
lines changed

src/wallet/wallet.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,37 +1970,38 @@ bool CWalletTx::InMempool() const
19701970

19711971
bool CWalletTx::IsTrusted() const
19721972
{
1973-
std::set<uint256> s;
1974-
return IsTrusted(s);
1973+
std::set<uint256> trusted_parents;
1974+
LOCK(pwallet->cs_wallet);
1975+
return pwallet->IsTrusted(*this, trusted_parents);
19751976
}
19761977

1977-
bool CWalletTx::IsTrusted(std::set<uint256>& trusted_parents) const
1978+
bool CWallet::IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const
19781979
{
1980+
AssertLockHeld(cs_wallet);
19791981
// Quick answer in most cases
1980-
if (!pwallet->chain().checkFinalTx(*tx)) return false;
1981-
int nDepth = GetDepthInMainChain();
1982+
if (!chain().checkFinalTx(*wtx.tx)) return false;
1983+
int nDepth = wtx.GetDepthInMainChain();
19821984
if (nDepth >= 1) return true;
19831985
if (nDepth < 0) return false;
19841986
// using wtx's cached debit
1985-
if (!pwallet->m_spend_zero_conf_change || !IsFromMe(ISMINE_ALL)) return false;
1987+
if (!m_spend_zero_conf_change || !wtx.IsFromMe(ISMINE_ALL)) return false;
19861988

19871989
// Don't trust unconfirmed transactions from us unless they are in the mempool.
1988-
if (!InMempool()) return false;
1990+
if (!wtx.InMempool()) return false;
19891991

19901992
// Trusted if all inputs are from us and are in the mempool:
1991-
LOCK(pwallet->cs_wallet);
1992-
for (const CTxIn& txin : tx->vin)
1993+
for (const CTxIn& txin : wtx.tx->vin)
19931994
{
19941995
// Transactions not sent by us: not trusted
1995-
const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
1996+
const CWalletTx* parent = GetWalletTx(txin.prevout.hash);
19961997
if (parent == nullptr) return false;
19971998
const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
19981999
// Check that this specific input being spent is trusted
1999-
if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false;
2000+
if (IsMine(parentOut) != ISMINE_SPENDABLE) return false;
20002001
// If we've already trusted this parent, continue
20012002
if (trusted_parents.count(parent->GetHash())) continue;
20022003
// Recurse to check that the parent is also trusted
2003-
if (!parent->IsTrusted(trusted_parents)) return false;
2004+
if (!IsTrusted(*parent, trusted_parents)) return false;
20042005
trusted_parents.insert(parent->GetHash());
20052006
}
20062007
return true;
@@ -2086,7 +2087,7 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
20862087
for (const auto& entry : mapWallet)
20872088
{
20882089
const CWalletTx& wtx = entry.second;
2089-
const bool is_trusted{wtx.IsTrusted(trusted_parents)};
2090+
const bool is_trusted{IsTrusted(wtx, trusted_parents)};
20902091
const int tx_depth{wtx.GetDepthInMainChain()};
20912092
const CAmount tx_credit_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)};
20922093
const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)};
@@ -2154,7 +2155,7 @@ void CWallet::AvailableCoins(std::vector<COutput>& vCoins, bool fOnlySafe, const
21542155
if (nDepth == 0 && !wtx.InMempool())
21552156
continue;
21562157

2157-
bool safeTx = wtx.IsTrusted(trusted_parents);
2158+
bool safeTx = IsTrusted(wtx, trusted_parents);
21582159

21592160
// We should not consider coins from transactions that are replacing
21602161
// other transactions.
@@ -3353,7 +3354,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances() const
33533354
{
33543355
const CWalletTx& wtx = walletEntry.second;
33553356

3356-
if (!wtx.IsTrusted(trusted_parents))
3357+
if (!IsTrusted(wtx, trusted_parents))
33573358
continue;
33583359

33593360
if (wtx.IsImmatureCoinBase())

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,6 @@ class CWalletTx
502502

503503
bool InMempool() const;
504504
bool IsTrusted() const;
505-
bool IsTrusted(std::set<uint256>& trusted_parents) const;
506505

507506
int64_t GetTxTime() const;
508507

@@ -806,6 +805,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
806805
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
807806

808807
const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
808+
bool IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
809809

810810
//! check whether we are allowed to upgrade (or already support) to the named feature
811811
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }

0 commit comments

Comments
 (0)