Skip to content

Commit dee4292

Browse files
wallet: Add Clang thread safety analysis annotations
1 parent 1c7e25d commit dee4292

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

src/interfaces/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ static WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx) EXCLUSIVE_LOCKS_R
103103
}
104104

105105
//! Construct wallet TxOut struct.
106-
static WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
106+
static WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth) EXCLUSIVE_LOCKS_REQUIRED(cs_main, wallet.cs_wallet)
107107
{
108108
WalletTxOut result;
109109
result.txout = wtx.tx->vout[n];

src/wallet/rpcwallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,7 @@ struct tallyitem
11211121
}
11221122
};
11231123

1124-
static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
1124+
static UniValue ListReceived(CWallet * const pwallet, const UniValue& params, bool by_label) EXCLUSIVE_LOCKS_REQUIRED(cs_main, pwallet->cs_wallet)
11251125
{
11261126
// Minimum confirmations
11271127
int nMinDepth = 1;

src/wallet/wallet.h

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,11 @@ class CWalletTx : public CMerkleTx
460460
CAmount GetDebit(const isminefilter& filter) const;
461461
CAmount GetCredit(const isminefilter& filter) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
462462
CAmount GetImmatureCredit(bool fUseCache=true) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
463-
CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
463+
// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
464+
// annotation "EXCLUSIVE_LOCKS_REQUIRED(cs_main, pwallet->cs_wallet)". The
465+
// annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid
466+
// having to resolve the issue of member access into incomplete type CWallet.
467+
CAmount GetAvailableCredit(bool fUseCache=true, const isminefilter& filter=ISMINE_SPENDABLE) const NO_THREAD_SAFETY_ANALYSIS;
464468
CAmount GetImmatureWatchOnlyCredit(const bool fUseCache=true) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
465469
CAmount GetChange() const;
466470

@@ -492,7 +496,13 @@ class CWalletTx : public CMerkleTx
492496
/** Pass this transaction to the mempool. Fails if absolute fee exceeds absurd fee. */
493497
bool AcceptToMemoryPool(const CAmount& nAbsurdFee, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
494498

495-
std::set<uint256> GetConflicts() const;
499+
// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct
500+
// annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation
501+
// "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to
502+
// resolve the issue of member access into incomplete type CWallet. Note
503+
// that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)"
504+
// in place.
505+
std::set<uint256> GetConflicts() const NO_THREAD_SAFETY_ANALYSIS;
496506
};
497507

498508
class COutput
@@ -609,9 +619,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
609619
* mutated transactions where the mutant gets mined).
610620
*/
611621
typedef std::multimap<COutPoint, uint256> TxSpends;
612-
TxSpends mapTxSpends;
613-
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
614-
void AddToSpends(const uint256& wtxid);
622+
TxSpends mapTxSpends GUARDED_BY(cs_wallet);
623+
void AddToSpends(const COutPoint& outpoint, const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
624+
void AddToSpends(const uint256& wtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
615625

616626
/**
617627
* Add a transaction to the wallet, or update it. pIndex and posInBlock should
@@ -632,9 +642,9 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
632642
void MarkConflicted(const uint256& hashBlock, const uint256& hashTx);
633643

634644
/* Mark a transaction's inputs dirty, thus forcing the outputs to be recomputed */
635-
void MarkInputsDirty(const CTransactionRef& tx);
645+
void MarkInputsDirty(const CTransactionRef& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
636646

637-
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
647+
void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
638648

639649
/* Used by TransactionAddedToMemorypool/BlockConnected/Disconnected/ScanForWalletTransactions.
640650
* Should be called with pindexBlock and posInBlock if this is for a transaction that is included in a block. */
@@ -653,7 +663,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
653663
std::map<CKeyID, int64_t> m_pool_key_to_index;
654664
std::atomic<uint64_t> m_wallet_flags{0};
655665

656-
int64_t nTimeFirstKey = 0;
666+
int64_t nTimeFirstKey GUARDED_BY(cs_wallet) = 0;
657667

658668
/**
659669
* Private version of AddWatchOnly method which does not accept a
@@ -709,7 +719,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
709719
* if they are not ours
710720
*/
711721
bool SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAmount& nTargetValue, std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet,
712-
const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const;
722+
const CCoinControl& coin_control, CoinSelectionParams& coin_selection_params, bool& bnb_used) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
713723

714724
/** Get a name for this wallet for logging/debugging purposes.
715725
*/
@@ -739,7 +749,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
739749
encrypted_batch = nullptr;
740750
}
741751

742-
std::map<uint256, CWalletTx> mapWallet;
752+
std::map<uint256, CWalletTx> mapWallet GUARDED_BY(cs_wallet);
743753

744754
typedef std::multimap<int64_t, CWalletTx*> TxItems;
745755
TxItems wtxOrdered;
@@ -769,7 +779,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
769779
/**
770780
* Find non-change parent output.
771781
*/
772-
const CTxOut& FindNonChangeParentOutput(const CTransaction& tx, int output) const;
782+
const CTxOut& FindNonChangeParentOutput(const CTransaction& tx, int output) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
773783

774784
/**
775785
* Shuffle and select coins until nTargetValue is reached while avoiding
@@ -780,7 +790,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
780790
bool SelectCoinsMinConf(const CAmount& nTargetValue, const CoinEligibilityFilter& eligibility_filter, std::vector<OutputGroup> groups,
781791
std::set<CInputCoin>& setCoinsRet, CAmount& nValueRet, const CoinSelectionParams& coin_selection_params, bool& bnb_used) const;
782792

783-
bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
793+
bool IsSpent(const uint256& hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_main, cs_wallet);
784794
std::vector<OutputGroup> GroupOutputs(const std::vector<COutput>& outputs, bool single_coin) const;
785795

786796
bool IsLockedCoin(uint256 hash, unsigned int n) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -856,7 +866,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
856866

857867
void MarkDirty();
858868
bool AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose=true);
859-
void LoadToWallet(const CWalletTx& wtxIn);
869+
void LoadToWallet(const CWalletTx& wtxIn) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
860870
void TransactionAddedToMempool(const CTransactionRef& tx) override;
861871
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex *pindex, const std::vector<CTransactionRef>& vtxConflicted) override;
862872
void BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) override;
@@ -1000,7 +1010,7 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
10001010
int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
10011011

10021012
//! Get wallet transactions that conflict with given transaction (spend same outputs)
1003-
std::set<uint256> GetConflicts(const uint256& txid) const;
1013+
std::set<uint256> GetConflicts(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
10041014

10051015
//! Check if a given transaction has any of its outputs spent by another transaction in the wallet
10061016
bool HasWalletSpend(const uint256& txid) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@@ -1198,6 +1208,6 @@ class WalletRescanReserver
11981208
// Use DummySignatureCreator, which inserts 71 byte signatures everywhere.
11991209
// NOTE: this requires that all inputs must be in mapWallet (eg the tx should
12001210
// be IsAllFromMe).
1201-
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false);
1211+
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
12021212
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig = false);
12031213
#endif // BITCOIN_WALLET_WALLET_H

0 commit comments

Comments
 (0)