diff options
author | MacroFake <falke.marco@gmail.com> | 2022-05-18 16:23:37 +0200 |
---|---|---|
committer | MacroFake <falke.marco@gmail.com> | 2022-05-18 16:23:43 +0200 |
commit | 629e250cbdee84c20d362da845d7aacfb84ddabe (patch) | |
tree | 47f8fecbe4cb08a93ad674249caf28f95873e307 | |
parent | 139f789d7a9fbb64176d3897239f93f60019c521 (diff) | |
parent | a55db4ea1cf10e0ab4a6eb5cd1dd3bd95626fba0 (diff) |
Merge bitcoin/bitcoin#25148: refactor: Remove `NO_THREAD_SAFETY_ANALYSIS` from non-test/benchmarking code
a55db4ea1cf10e0ab4a6eb5cd1dd3bd95626fba0 Add more proper thread safety annotations (Hennadii Stepanov)
8cfe93e3fcf263bf059f738d5e7d9c94901a7c5a Add proper thread safety annotation to `CWallet::GetTxConflicts()` (Hennadii Stepanov)
ca446f2c59720c1575aeeab9c9d636d98ce8528c Add proper thread safety annotation to `CachedTxGetAvailableCredit()` (Hennadii Stepanov)
Pull request description:
In non-test/benchmarking code, there are three cases of the `NO_THREAD_SAFETY_ANALYSIS` annotation which are accompanied with `TODO` comments.
This PR adds proper thread safety annotations instead of `NO_THREAD_SAFETY_ANALYSIS`.
ACKs for top commit:
laanwj:
Code review ACK a55db4ea1cf10e0ab4a6eb5cd1dd3bd95626fba0
Tree-SHA512: 806d72eebc1edf088bfa435c8cd11465be0de6789798dd92abd008425516768acb864a73d834a49d412bb10f7fccfb47473f998cb72739dab6caeef6bcfaf191
-rw-r--r-- | src/wallet/interfaces.cpp | 3 | ||||
-rw-r--r-- | src/wallet/receive.cpp | 8 | ||||
-rw-r--r-- | src/wallet/receive.h | 16 | ||||
-rw-r--r-- | src/wallet/rpc/transactions.cpp | 1 | ||||
-rw-r--r-- | src/wallet/wallet.cpp | 20 | ||||
-rw-r--r-- | src/wallet/wallet.h | 29 |
6 files changed, 44 insertions, 33 deletions
diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index b269137254..e1203817e0 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -80,7 +80,10 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) //! Construct wallet tx status struct. WalletTxStatus MakeWalletTxStatus(const CWallet& wallet, const CWalletTx& wtx) + EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) { + AssertLockHeld(wallet.cs_wallet); + WalletTxStatus result; result.block_height = wtx.state<TxStateConfirmed>() ? wtx.state<TxStateConfirmed>()->confirmed_block_height : diff --git a/src/wallet/receive.cpp b/src/wallet/receive.cpp index cddf94aab2..8cce07b921 100644 --- a/src/wallet/receive.cpp +++ b/src/wallet/receive.cpp @@ -123,6 +123,8 @@ static CAmount GetCachableAmount(const CWallet& wallet, const CWalletTx& wtx, CW CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter) { + AssertLockHeld(wallet.cs_wallet); + // Must wait until coinbase is safely deep enough in the chain before valuing it if (wallet.IsTxImmatureCoinBase(wtx)) return 0; @@ -164,6 +166,8 @@ CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx) CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache) { + AssertLockHeld(wallet.cs_wallet); + if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) { return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, ISMINE_SPENDABLE, !fUseCache); } @@ -173,6 +177,8 @@ CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, b CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletTx& wtx, const bool fUseCache) { + AssertLockHeld(wallet.cs_wallet); + if (wallet.IsTxImmatureCoinBase(wtx) && wallet.IsTxInMainChain(wtx)) { return GetCachableAmount(wallet, wtx, CWalletTx::IMMATURE_CREDIT, ISMINE_WATCH_ONLY, !fUseCache); } @@ -182,6 +188,8 @@ CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletT CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache, const isminefilter& filter) { + AssertLockHeld(wallet.cs_wallet); + // Avoid caching ismine for NO or ALL cases (could remove this check and simplify in the future). bool allow_cache = (filter & ISMINE_ALL) && (filter & ISMINE_ALL) != ISMINE_ALL; diff --git a/src/wallet/receive.h b/src/wallet/receive.h index d7705b5262..1caef293f2 100644 --- a/src/wallet/receive.h +++ b/src/wallet/receive.h @@ -24,17 +24,17 @@ bool OutputIsChange(const CWallet& wallet, const CTxOut& txout) EXCLUSIVE_LOCKS_ CAmount OutputGetChange(const CWallet& wallet, const CTxOut& txout) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx); -CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter); +CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter) + EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); //! filter decides which addresses will count towards the debit CAmount CachedTxGetDebit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter); CAmount CachedTxGetChange(const CWallet& wallet, const CWalletTx& wtx); -CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache = true); -CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletTx& wtx, const bool fUseCache = true); -// TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct -// annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The -// annotation "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid -// having to resolve the issue of member access into incomplete type CWallet. -CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache = true, const isminefilter& filter = ISMINE_SPENDABLE) NO_THREAD_SAFETY_ANALYSIS; +CAmount CachedTxGetImmatureCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache = true) + EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); +CAmount CachedTxGetImmatureWatchOnlyCredit(const CWallet& wallet, const CWalletTx& wtx, const bool fUseCache = true) + EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); +CAmount CachedTxGetAvailableCredit(const CWallet& wallet, const CWalletTx& wtx, bool fUseCache = true, const isminefilter& filter = ISMINE_SPENDABLE) + EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); struct COutputEntry { CTxDestination destination; diff --git a/src/wallet/rpc/transactions.cpp b/src/wallet/rpc/transactions.cpp index c87af2ea30..1b06973f78 100644 --- a/src/wallet/rpc/transactions.cpp +++ b/src/wallet/rpc/transactions.cpp @@ -15,6 +15,7 @@ using interfaces::FoundBlock; namespace wallet { static void WalletTxToJSON(const CWallet& wallet, const CWalletTx& wtx, UniValue& entry) + EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet) { interfaces::Chain& chain = wallet.chain(); int confirms = wallet.GetTxDepthInMainChain(wtx); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b59e7bf2ff..6c333c709b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1841,6 +1841,8 @@ void CWallet::ReacceptWalletTransactions() bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const { + AssertLockHeld(cs_wallet); + // Can't relay if wallet is not broadcasting if (!GetBroadcastTransactions()) return false; // Don't relay abandoned transactions @@ -1869,12 +1871,11 @@ bool CWallet::SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string std::set<uint256> CWallet::GetTxConflicts(const CWalletTx& wtx) const { - std::set<uint256> result; - { - uint256 myHash = wtx.GetHash(); - result = GetConflicts(myHash); - result.erase(myHash); - } + AssertLockHeld(cs_wallet); + + const uint256 myHash{wtx.GetHash()}; + std::set<uint256> result{GetConflicts(myHash)}; + result.erase(myHash); return result; } @@ -3128,8 +3129,11 @@ int CWallet::GetTxDepthInMainChain(const CWalletTx& wtx) const int CWallet::GetTxBlocksToMaturity(const CWalletTx& wtx) const { - if (!wtx.IsCoinBase()) + AssertLockHeld(cs_wallet); + + if (!wtx.IsCoinBase()) { return 0; + } int chain_depth = GetTxDepthInMainChain(wtx); assert(chain_depth >= 0); // coinbase tx should not be conflicted return std::max(0, (COINBASE_MATURITY+1) - chain_depth); @@ -3137,6 +3141,8 @@ int CWallet::GetTxBlocksToMaturity(const CWalletTx& wtx) const bool CWallet::IsTxImmatureCoinBase(const CWalletTx& wtx) const { + AssertLockHeld(cs_wallet); + // note GetBlocksToMaturity is 0 for non-coinbase tx return GetTxBlocksToMaturity(wtx) > 0; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 4e81a2b957..7da601c3b7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -415,13 +415,7 @@ public: const CWalletTx* GetWalletTx(const uint256& hash) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); - // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct - // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation - // "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to - // resolve the issue of member access into incomplete type CWallet. Note - // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)" - // in place. - std::set<uint256> GetTxConflicts(const CWalletTx& wtx) const NO_THREAD_SAFETY_ANALYSIS; + std::set<uint256> GetTxConflicts(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); /** * Return depth of transaction in blockchain: @@ -429,22 +423,20 @@ public: * 0 : in memory pool, waiting to be included in a block * >=1 : this many blocks deep in the main chain */ - // TODO: Remove "NO_THREAD_SAFETY_ANALYSIS" and replace it with the correct - // annotation "EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)". The annotation - // "NO_THREAD_SAFETY_ANALYSIS" was temporarily added to avoid having to - // resolve the issue of member access into incomplete type CWallet. Note - // that we still have the runtime check "AssertLockHeld(pwallet->cs_wallet)" - // in place. - int GetTxDepthInMainChain(const CWalletTx& wtx) const NO_THREAD_SAFETY_ANALYSIS; - bool IsTxInMainChain(const CWalletTx& wtx) const { return GetTxDepthInMainChain(wtx) > 0; } + int GetTxDepthInMainChain(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + bool IsTxInMainChain(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) + { + AssertLockHeld(cs_wallet); + return GetTxDepthInMainChain(wtx) > 0; + } /** * @return number of blocks to maturity for this transaction: * 0 : is not a coinbase transaction, or is a mature coinbase transaction * >0 : is a coinbase transaction which matures in this many blocks */ - int GetTxBlocksToMaturity(const CWalletTx& wtx) const; - bool IsTxImmatureCoinBase(const CWalletTx& wtx) const; + int GetTxBlocksToMaturity(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); + bool IsTxImmatureCoinBase(const CWalletTx& wtx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); //! check whether we support the named feature bool CanSupportFeature(enum WalletFeature wf) const override EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) { AssertLockHeld(cs_wallet); return IsFeatureSupported(nWalletVersion, wf); } @@ -584,7 +576,8 @@ public: void CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::vector<std::pair<std::string, std::string>> orderForm); /** Pass this transaction to node for mempool insertion and relay to peers if flag set to true */ - bool SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const; + bool SubmitTxMemoryPoolAndRelay(CWalletTx& wtx, std::string& err_string, bool relay) const + EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool DummySignTx(CMutableTransaction &txNew, const std::set<CTxOut> &txouts, const CCoinControl* coin_control = nullptr) const { |