Skip to content

Commit 0264836

Browse files
author
MarcoFalke
committed
Merge #11689: mempool: Fix missing locking in CTxMemPool::check(…) and CTxMemPool::setSanityCheck(…)
47782b4 Add Clang thread safety analysis annotations (practicalswift) 0e2dfa8 Fix missing locking in CTxMemPool::setSanityCheck(double dFrequency) (practicalswift) 6bc5b71 Fix missing locking in CTxMemPool::check(const CCoinsViewCache *pcoins) (practicalswift) Pull request description: Fix missing locking in `CTxMemPool::check(const CCoinsViewCache *pcoins)`: * reading variable `mapTx` requires holding mutex `cs` * reading variable `mapNextTx` requires holding mutex `cs` * reading variable `nCheckFrequency` requires holding mutex `cs` Fix missing locking in `CTxMemPool::setSanityCheck(double dFrequency)`: * writing variable `nCheckFrequency` requires holding mutex `cs` Tree-SHA512: ce7c365ac89225223fb06e6f469451b121acaa499f35b21ad8a6d2a266c91194639b3703c5428871be033d4f5f7be790cc297bd8c25b2e0c59345ef09c3693d0
2 parents 19a3a9e + 47782b4 commit 0264836

File tree

5 files changed

+20
-20
lines changed

5 files changed

+20
-20
lines changed

src/miner.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <consensus/merkle.h>
1515
#include <consensus/validation.h>
1616
#include <hash.h>
17-
#include <validation.h>
1817
#include <net.h>
1918
#include <policy/feerate.h>
2019
#include <policy/policy.h>

src/miner.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <primitives/block.h>
1010
#include <txmempool.h>
11+
#include <validation.h>
1112

1213
#include <stdint.h>
1314
#include <memory>
@@ -169,7 +170,7 @@ class BlockAssembler
169170
/** Add transactions based on feerate including unconfirmed ancestors
170171
* Increments nPackagesSelected / nDescendantsUpdated with corresponding
171172
* statistics from the package selection (for logging statistics). */
172-
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated);
173+
void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
173174

174175
// helper functions for addPackageTxs()
175176
/** Remove confirmed (inBlock) entries from given set */
@@ -183,13 +184,13 @@ class BlockAssembler
183184
bool TestPackageTransactions(const CTxMemPool::setEntries& package);
184185
/** Return true if given transaction from mapTx has already been evaluated,
185186
* or if the transaction's cached data in mapTx is incorrect. */
186-
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx);
187+
bool SkipMapTxEntry(CTxMemPool::txiter it, indexed_modified_transaction_set &mapModifiedTx, CTxMemPool::setEntries &failedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
187188
/** Sort the package in an order that is valid to appear in a block */
188189
void SortForBlock(const CTxMemPool::setEntries& package, std::vector<CTxMemPool::txiter>& sortedEntries);
189190
/** Add descendants of given transactions to mapModifiedTx with ancestor
190191
* state updated assuming given transactions are inBlock. Returns number
191192
* of updated descendants. */
192-
int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx);
193+
int UpdatePackagesForAdded(const CTxMemPool::setEntries& alreadyAdded, indexed_modified_transaction_set &mapModifiedTx) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs);
193194
};
194195

195196
/** Modify the extranonce in a block */

src/test/mempool_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(MempoolRemoveTest)
106106
}
107107

108108
template<typename name>
109-
static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder)
109+
static void CheckSort(CTxMemPool &pool, std::vector<std::string> &sortedOrder) EXCLUSIVE_LOCKS_REQUIRED(pool.cs)
110110
{
111111
BOOST_CHECK_EQUAL(pool.size(), sortedOrder.size());
112112
typename CTxMemPool::indexed_transaction_set::index<name>::type::iterator it = pool.mapTx.get<name>().begin();

src/txmempool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& m
618618

619619
void CTxMemPool::check(const CCoinsViewCache *pcoins) const
620620
{
621+
LOCK(cs);
621622
if (nCheckFrequency == 0)
622623
return;
623624

@@ -632,7 +633,6 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
632633
CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
633634
const int64_t spendheight = GetSpendHeight(mempoolDuplicate);
634635

635-
LOCK(cs);
636636
std::list<const CTxMemPoolEntry*> waitingOnDependants;
637637
for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
638638
unsigned int i = 0;

src/txmempool.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ class SaltedTxidHasher
440440
class CTxMemPool
441441
{
442442
private:
443-
uint32_t nCheckFrequency; //!< Value n means that n times in 2^32 we check.
443+
uint32_t nCheckFrequency GUARDED_BY(cs); //!< Value n means that n times in 2^32 we check.
444444
unsigned int nTransactionsUpdated; //!< Used by getblocktemplate to trigger CreateNewBlock() invocation
445445
CBlockPolicyEstimator* minerPolicyEstimator;
446446

@@ -484,7 +484,7 @@ class CTxMemPool
484484
> indexed_transaction_set;
485485

486486
mutable CCriticalSection cs;
487-
indexed_transaction_set mapTx;
487+
indexed_transaction_set mapTx GUARDED_BY(cs);
488488

489489
typedef indexed_transaction_set::nth_index<0>::type::iterator txiter;
490490
std::vector<std::pair<uint256, txiter> > vTxHashes; //!< All tx witness hashes/entries in mapTx, in random order
@@ -496,8 +496,8 @@ class CTxMemPool
496496
};
497497
typedef std::set<txiter, CompareIteratorByHash> setEntries;
498498

499-
const setEntries & GetMemPoolParents(txiter entry) const;
500-
const setEntries & GetMemPoolChildren(txiter entry) const;
499+
const setEntries & GetMemPoolParents(txiter entry) const EXCLUSIVE_LOCKS_REQUIRED(cs);
500+
const setEntries & GetMemPoolChildren(txiter entry) const EXCLUSIVE_LOCKS_REQUIRED(cs);
501501
private:
502502
typedef std::map<txiter, setEntries, CompareIteratorByHash> cacheMap;
503503

@@ -515,7 +515,7 @@ class CTxMemPool
515515
std::vector<indexed_transaction_set::const_iterator> GetSortedDepthAndScore() const EXCLUSIVE_LOCKS_REQUIRED(cs);
516516

517517
public:
518-
indirectmap<COutPoint, const CTransaction*> mapNextTx;
518+
indirectmap<COutPoint, const CTransaction*> mapNextTx GUARDED_BY(cs);
519519
std::map<uint256, CAmount> mapDeltas;
520520

521521
/** Create a new CTxMemPool.
@@ -529,7 +529,7 @@ class CTxMemPool
529529
* check does nothing.
530530
*/
531531
void check(const CCoinsViewCache *pcoins) const;
532-
void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); }
532+
void setSanityCheck(double dFrequency = 1.0) { LOCK(cs); nCheckFrequency = static_cast<uint32_t>(dFrequency * 4294967295.0); }
533533

534534
// addUnchecked must updated state for all ancestors of a given transaction,
535535
// to track size/count of descendant transactions. First version of
@@ -547,7 +547,7 @@ class CTxMemPool
547547
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight);
548548

549549
void clear();
550-
void _clear(); //lock free
550+
void _clear() EXCLUSIVE_LOCKS_REQUIRED(cs); //lock free
551551
bool CompareDepthAndScore(const uint256& hasha, const uint256& hashb);
552552
void queryHashes(std::vector<uint256>& vtxid);
553553
bool isSpent(const COutPoint& outpoint) const;
@@ -600,7 +600,7 @@ class CTxMemPool
600600
/** Populate setDescendants with all in-mempool descendants of hash.
601601
* Assumes that setDescendants includes all in-mempool descendants of anything
602602
* already in it. */
603-
void CalculateDescendants(txiter it, setEntries& setDescendants) const;
603+
void CalculateDescendants(txiter it, setEntries& setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs);
604604

605605
/** The minimum fee to get into the mempool, which may itself not be enough
606606
* for larger-sized transactions.
@@ -665,17 +665,17 @@ class CTxMemPool
665665
*/
666666
void UpdateForDescendants(txiter updateIt,
667667
cacheMap &cachedDescendants,
668-
const std::set<uint256> &setExclude);
668+
const std::set<uint256> &setExclude) EXCLUSIVE_LOCKS_REQUIRED(cs);
669669
/** Update ancestors of hash to add/remove it as a descendant transaction. */
670-
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors);
670+
void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs);
671671
/** Set ancestor state for an entry */
672-
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors);
672+
void UpdateEntryForAncestors(txiter it, const setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs);
673673
/** For each transaction being removed, update ancestors and any direct children.
674674
* If updateDescendants is true, then also update in-mempool descendants'
675675
* ancestor state. */
676-
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants);
676+
void UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants) EXCLUSIVE_LOCKS_REQUIRED(cs);
677677
/** Sever link between specified transaction and direct children. */
678-
void UpdateChildrenForRemoval(txiter entry);
678+
void UpdateChildrenForRemoval(txiter entry) EXCLUSIVE_LOCKS_REQUIRED(cs);
679679

680680
/** Before calling removeUnchecked for a given transaction,
681681
* UpdateForRemoveFromMempool must be called on the entire (dependent) set
@@ -685,7 +685,7 @@ class CTxMemPool
685685
* transactions in a chain before we've updated all the state for the
686686
* removal.
687687
*/
688-
void removeUnchecked(txiter entry, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
688+
void removeUnchecked(txiter entry, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN) EXCLUSIVE_LOCKS_REQUIRED(cs);
689689
};
690690

691691
/**

0 commit comments

Comments
 (0)