mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-22 01:52:35 +02:00
wallet: Avoid recursive lock in IsTrusted
This commit is contained in:
parent
819f10f671
commit
772ea4844c
@ -1970,37 +1970,38 @@ bool CWalletTx::InMempool() const
|
|||||||
|
|
||||||
bool CWalletTx::IsTrusted() const
|
bool CWalletTx::IsTrusted() const
|
||||||
{
|
{
|
||||||
std::set<uint256> s;
|
std::set<uint256> trusted_parents;
|
||||||
return IsTrusted(s);
|
LOCK(pwallet->cs_wallet);
|
||||||
|
return pwallet->IsTrusted(*this, trusted_parents);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWalletTx::IsTrusted(std::set<uint256>& trusted_parents) const
|
bool CWallet::IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs_wallet);
|
||||||
// Quick answer in most cases
|
// Quick answer in most cases
|
||||||
if (!pwallet->chain().checkFinalTx(*tx)) return false;
|
if (!chain().checkFinalTx(*wtx.tx)) return false;
|
||||||
int nDepth = GetDepthInMainChain();
|
int nDepth = wtx.GetDepthInMainChain();
|
||||||
if (nDepth >= 1) return true;
|
if (nDepth >= 1) return true;
|
||||||
if (nDepth < 0) return false;
|
if (nDepth < 0) return false;
|
||||||
// using wtx's cached debit
|
// using wtx's cached debit
|
||||||
if (!pwallet->m_spend_zero_conf_change || !IsFromMe(ISMINE_ALL)) return false;
|
if (!m_spend_zero_conf_change || !wtx.IsFromMe(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 (!InMempool()) return false;
|
if (!wtx.InMempool()) 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:
|
||||||
LOCK(pwallet->cs_wallet);
|
for (const CTxIn& txin : wtx.tx->vin)
|
||||||
for (const CTxIn& txin : tx->vin)
|
|
||||||
{
|
{
|
||||||
// Transactions not sent by us: not trusted
|
// Transactions not sent by us: not trusted
|
||||||
const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
|
const CWalletTx* parent = GetWalletTx(txin.prevout.hash);
|
||||||
if (parent == nullptr) return false;
|
if (parent == nullptr) return false;
|
||||||
const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
|
const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
|
||||||
// Check that this specific input being spent is trusted
|
// Check that this specific input being spent is trusted
|
||||||
if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false;
|
if (IsMine(parentOut) != ISMINE_SPENDABLE) return false;
|
||||||
// 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 (!parent->IsTrusted(trusted_parents)) return false;
|
if (!IsTrusted(*parent, trusted_parents)) return false;
|
||||||
trusted_parents.insert(parent->GetHash());
|
trusted_parents.insert(parent->GetHash());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -2086,7 +2087,7 @@ CWallet::Balance CWallet::GetBalance(const int min_depth, bool avoid_reuse) cons
|
|||||||
for (const auto& entry : mapWallet)
|
for (const auto& entry : mapWallet)
|
||||||
{
|
{
|
||||||
const CWalletTx& wtx = entry.second;
|
const CWalletTx& wtx = entry.second;
|
||||||
const bool is_trusted{wtx.IsTrusted(trusted_parents)};
|
const bool is_trusted{IsTrusted(wtx, trusted_parents)};
|
||||||
const int tx_depth{wtx.GetDepthInMainChain()};
|
const int tx_depth{wtx.GetDepthInMainChain()};
|
||||||
const CAmount tx_credit_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)};
|
const CAmount tx_credit_mine{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_SPENDABLE | reuse_filter)};
|
||||||
const CAmount tx_credit_watchonly{wtx.GetAvailableCredit(/* fUseCache */ true, ISMINE_WATCH_ONLY | reuse_filter)};
|
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
|
|||||||
if (nDepth == 0 && !wtx.InMempool())
|
if (nDepth == 0 && !wtx.InMempool())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool safeTx = wtx.IsTrusted(trusted_parents);
|
bool safeTx = IsTrusted(wtx, trusted_parents);
|
||||||
|
|
||||||
// We should not consider coins from transactions that are replacing
|
// We should not consider coins from transactions that are replacing
|
||||||
// other transactions.
|
// other transactions.
|
||||||
@ -3353,7 +3354,7 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances() const
|
|||||||
{
|
{
|
||||||
const CWalletTx& wtx = walletEntry.second;
|
const CWalletTx& wtx = walletEntry.second;
|
||||||
|
|
||||||
if (!wtx.IsTrusted(trusted_parents))
|
if (!IsTrusted(wtx, trusted_parents))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (wtx.IsImmatureCoinBase())
|
if (wtx.IsImmatureCoinBase())
|
||||||
|
@ -502,7 +502,6 @@ public:
|
|||||||
|
|
||||||
bool InMempool() const;
|
bool InMempool() const;
|
||||||
bool IsTrusted() const;
|
bool IsTrusted() const;
|
||||||
bool IsTrusted(std::set<uint256>& trusted_parents) const;
|
|
||||||
|
|
||||||
int64_t GetTxTime() const;
|
int64_t GetTxTime() const;
|
||||||
|
|
||||||
@ -806,6 +805,7 @@ public:
|
|||||||
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
|
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
|
||||||
|
|
||||||
const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
bool IsTrusted(const CWalletTx& wtx, std::set<uint256>& trusted_parents) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
|
||||||
//! check whether we are allowed to upgrade (or already support) to the named feature
|
//! check whether we are allowed to upgrade (or already support) to the named feature
|
||||||
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
|
bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
|
||||||
|
Loading…
Reference in New Issue
Block a user