Skip to content

Commit 91186e5

Browse files
author
MarcoFalke
committed
Merge #13083: Add compile time checking for cs_main runtime locking assertions
9e0a514 Add compile time checking for all cs_main runtime locking assertions (practicalswift) Pull request description: Add compile time checking for `cs_main` runtime locking assertions. This PR is a subset of #12665. The PR was broken up to make reviewing easier. The intention is that literally all `EXCLUSIVE_LOCKS_REQUIRED`/`LOCKS_EXCLUDED`:s added in this PR should follow either directly or indirectly from `AssertLockHeld(…)`/`AssertLockNotHeld(…)`:s already existing in the repo. Consider the case where function `A(…)` contains `AssertLockHeld(cs_foo)` (without first locking `cs_foo` in `A`), and that `B(…)` calls `A(…)` (without first locking `cs_main`): * It _directly_ follows that: `A(…)` should have an `EXCLUSIVE_LOCKS_REQUIRED(cs_foo)` annotation. * It _indirectly_ follows that: `B(…)` should have an `EXCLUSIVE_LOCKS_REQUIRED(cs_foo)` annotation. Tree-SHA512: 120e7410c4c223dbc7d42030b1a19e328d01a55f041bb6fb5eaac10ac35cb0c5d469b9b3bda6444731164c73b88ac6495a00890672b107d9305e891571f64dd6
2 parents 6516b36 + 9e0a514 commit 91186e5

13 files changed

+54
-52
lines changed

src/interfaces/wallet.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class PendingWalletTxImpl : public PendingWalletTx
5757
};
5858

5959
//! Construct wallet tx struct.
60-
WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
60+
static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
6161
{
6262
WalletTx result;
6363
result.tx = wtx.tx;
@@ -85,7 +85,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
8585
}
8686

8787
//! Construct wallet tx status struct.
88-
WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
88+
static WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
8989
{
9090
WalletTxStatus result;
9191
auto mi = ::mapBlockIndex.find(wtx.hashBlock);
@@ -104,7 +104,7 @@ WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
104104
}
105105

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

src/net_processing.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,7 @@ static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIV
442442
* lNodesAnnouncingHeaderAndIDs, and keeping that list under a certain size by
443443
* removing the first element if necessary.
444444
*/
445-
static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman)
445+
static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
446446
{
447447
AssertLockHeld(cs_main);
448448
CNodeState* nodestate = State(nodeid);
@@ -831,7 +831,7 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIV
831831
// active chain if they are no more than a month older (both in time, and in
832832
// best equivalent proof of work) than the best header chain we know about and
833833
// we fully-validated them at some point.
834-
static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams)
834+
static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
835835
{
836836
AssertLockHeld(cs_main);
837837
if (chainActive.Contains(pindex)) return true;
@@ -1260,7 +1260,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
12601260
}
12611261
}
12621262

1263-
void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
1263+
void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
12641264
{
12651265
AssertLockNotHeld(cs_main);
12661266

@@ -2925,7 +2925,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
29252925
return true;
29262926
}
29272927

2928-
static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool enable_bip61)
2928+
static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
29292929
{
29302930
AssertLockHeld(cs_main);
29312931
CNodeState &state = *State(pnode->GetId());

src/net_processing.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class PeerLogicValidation final : public CValidationInterface, public NetEventsI
6161
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
6262

6363
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
64-
void ConsiderEviction(CNode *pto, int64_t time_in_seconds);
64+
void ConsiderEviction(CNode *pto, int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
6565
/** Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound */
6666
void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams);
6767
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */

src/test/miner_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static CBlockIndex CreateBlockIndex(int nHeight)
9090
return index;
9191
}
9292

93-
static bool TestSequenceLocks(const CTransaction &tx, int flags)
93+
static bool TestSequenceLocks(const CTransaction &tx, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
9494
{
9595
LOCK(mempool.cs);
9696
return CheckSequenceLocks(tx, flags);

src/txmempool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ void CTxMemPool::removeRecursive(const CTransaction &origTx, MemPoolRemovalReaso
497497
}
498498
}
499499

500-
void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags)
500+
void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
501501
{
502502
// Remove transactions spending a coinbase which are now immature and no-longer-final transactions
503503
LOCK(cs);

src/validation.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class CChainState {
170170
// Block (dis)connection on a given view:
171171
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
172172
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
173-
CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false);
173+
CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
174174

175175
// Block disconnection on our pcoinsTip:
176176
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions *disconnectpool);
@@ -189,8 +189,8 @@ class CChainState {
189189
void UnloadBlockIndex();
190190

191191
private:
192-
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace);
193-
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool);
192+
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
193+
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions &disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
194194

195195
CBlockIndex* AddToBlockIndex(const CBlockHeader& block) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
196196
/** Create a new block index entry for a given block hash */
@@ -202,7 +202,7 @@ class CChainState {
202202
*/
203203
void CheckBlockIndex(const Consensus::Params& consensusParams);
204204

205-
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state);
205+
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
206206
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
207207
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const CDiskBlockPos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
208208

@@ -457,7 +457,7 @@ std::string FormatStateMessage(const CValidationState &state)
457457
state.GetRejectCode());
458458
}
459459

460-
static bool IsCurrentForFeeEstimation()
460+
static bool IsCurrentForFeeEstimation() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
461461
{
462462
AssertLockHeld(cs_main);
463463
if (IsInitialBlockDownload())
@@ -482,7 +482,7 @@ static bool IsCurrentForFeeEstimation()
482482
* and instead just erase from the mempool as needed.
483483
*/
484484

485-
static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool)
485+
static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool, bool fAddToMempool) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
486486
{
487487
AssertLockHeld(cs_main);
488488
std::vector<uint256> vHashUpdate;
@@ -524,7 +524,7 @@ static void UpdateMempoolForReorg(DisconnectedBlockTransactions &disconnectpool,
524524
// Used to avoid mempool polluting consensus critical paths if CCoinsViewMempool
525525
// were somehow broken and returning the wrong scriptPubKeys
526526
static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& view, const CTxMemPool& pool,
527-
unsigned int flags, bool cacheSigStore, PrecomputedTransactionData& txdata) {
527+
unsigned int flags, bool cacheSigStore, PrecomputedTransactionData& txdata) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
528528
AssertLockHeld(cs_main);
529529

530530
// pool.cs should be locked already, but go ahead and re-take the lock here
@@ -559,7 +559,7 @@ static bool CheckInputsFromMempoolAndCache(const CTransaction& tx, CValidationSt
559559

560560
static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool& pool, CValidationState& state, const CTransactionRef& ptx,
561561
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
562-
bool bypass_limits, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache, bool test_accept)
562+
bool bypass_limits, const CAmount& nAbsurdFee, std::vector<COutPoint>& coins_to_uncache, bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
563563
{
564564
const CTransaction& tx = *ptx;
565565
const uint256 hash = tx.GetHash();
@@ -977,7 +977,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
977977
/** (try to) add transaction to memory pool with a specified acceptance time **/
978978
static bool AcceptToMemoryPoolWithTime(const CChainParams& chainparams, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
979979
bool* pfMissingInputs, int64_t nAcceptTime, std::list<CTransactionRef>* plTxnReplaced,
980-
bool bypass_limits, const CAmount nAbsurdFee, bool test_accept)
980+
bool bypass_limits, const CAmount nAbsurdFee, bool test_accept) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
981981
{
982982
std::vector<COutPoint> coins_to_uncache;
983983
bool res = AcceptToMemoryPoolWorker(chainparams, pool, state, tx, pfMissingInputs, nAcceptTime, plTxnReplaced, bypass_limits, nAbsurdFee, coins_to_uncache, test_accept);
@@ -1216,7 +1216,7 @@ static void AlertNotify(const std::string& strMessage)
12161216
t.detach(); // thread runs free
12171217
}
12181218

1219-
static void CheckForkWarningConditions()
1219+
static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main)
12201220
{
12211221
AssertLockHeld(cs_main);
12221222
// Before we get past initial download, we cannot reliably alert about forks
@@ -1257,7 +1257,7 @@ static void CheckForkWarningConditions()
12571257
}
12581258
}
12591259

1260-
static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
1260+
static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
12611261
{
12621262
AssertLockHeld(cs_main);
12631263
// If we are on a fork that is sufficiently large, set a warning flag
@@ -1290,7 +1290,7 @@ static void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
12901290
CheckForkWarningConditions();
12911291
}
12921292

1293-
void static InvalidChainFound(CBlockIndex* pindexNew)
1293+
void static InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
12941294
{
12951295
if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
12961296
pindexBestInvalid = pindexNew;
@@ -1377,7 +1377,7 @@ void InitScriptExecutionCache() {
13771377
*
13781378
* Non-static (and re-declared) in src/test/txvalidationcache_tests.cpp
13791379
*/
1380-
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks)
1380+
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
13811381
{
13821382
if (!tx.IsCoinBase())
13831383
{
@@ -1743,7 +1743,7 @@ static bool IsScriptWitnessEnabled(const Consensus::Params& params)
17431743
return params.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0;
17441744
}
17451745

1746-
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) {
1746+
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
17471747
AssertLockHeld(cs_main);
17481748

17491749
unsigned int flags = SCRIPT_VERIFY_NONE;
@@ -2863,6 +2863,7 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
28632863
}
28642864
return true;
28652865
}
2866+
28662867
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) {
28672868
return g_chainstate.InvalidateBlock(state, chainparams, pindex);
28682869
}

src/validation.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ void PruneBlockFilesManual(int nManualPruneHeight);
302302
* plTxnReplaced will be appended to with all transactions replaced from mempool **/
303303
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
304304
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
305-
bool bypass_limits, const CAmount nAbsurdFee, bool test_accept=false);
305+
bool bypass_limits, const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
306306

307307
/** Convert CValidationState to a human-readable message for logging */
308308
std::string FormatStateMessage(const CValidationState &state);
@@ -329,12 +329,12 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
329329
*
330330
* See consensus/consensus.h for flag definitions.
331331
*/
332-
bool CheckFinalTx(const CTransaction &tx, int flags = -1);
332+
bool CheckFinalTx(const CTransaction &tx, int flags = -1) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
333333

334334
/**
335335
* Test whether the LockPoints height and time are still valid on the current chain
336336
*/
337-
bool TestLockPointValidity(const LockPoints* lp);
337+
bool TestLockPointValidity(const LockPoints* lp) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
338338

339339
/**
340340
* Check if transaction will be BIP 68 final in the next block to be created.
@@ -347,7 +347,7 @@ bool TestLockPointValidity(const LockPoints* lp);
347347
*
348348
* See consensus/consensus.h for flag definitions.
349349
*/
350-
bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false);
350+
bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp = nullptr, bool useExistingLockPoints = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
351351

352352
/**
353353
* Closure representing one script verification

src/validationinterface.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
#include <primitives/block.h>
99
#include <scheduler.h>
10-
#include <sync.h>
1110
#include <txmempool.h>
1211
#include <util.h>
1312
#include <validation.h>

src/validationinterface.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
#define BITCOIN_VALIDATIONINTERFACE_H
88

99
#include <primitives/transaction.h> // CTransaction(Ref)
10+
#include <sync.h>
1011

1112
#include <functional>
1213
#include <memory>
1314

15+
extern CCriticalSection cs_main;
1416
class CBlock;
1517
class CBlockIndex;
1618
struct CBlockLocator;
@@ -51,7 +53,7 @@ void CallFunctionInValidationInterfaceQueue(std::function<void ()> func);
5153
* });
5254
* promise.get_future().wait();
5355
*/
54-
void SyncWithValidationInterfaceQueue();
56+
void SyncWithValidationInterfaceQueue() LOCKS_EXCLUDED(cs_main);
5557

5658
/**
5759
* Implement this to subscribe to events generated in validation

src/wallet/feebumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
//! Check whether transaction has descendant in wallet or mempool, or has been
2020
//! mined, or conflicts with a mined transaction. Return a feebumper::Result.
21-
static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet)
21+
static feebumper::Result PreconditionChecks(const CWallet* wallet, const CWalletTx& wtx, std::vector<std::string>& errors) EXCLUSIVE_LOCKS_REQUIRED(cs_main, wallet->cs_wallet)
2222
{
2323
if (wallet->HasWalletSpend(wtx.GetHash())) {
2424
errors.push_back("Transaction has descendants in the wallet");

0 commit comments

Comments
 (0)