Skip to content

Commit 37af8a2

Browse files
jonatackshaavan
andcommitted
Add missing thread safety lock assertions in validation.cpp
Co-authored-by: Shashwat <[email protected]>
1 parent 280a777 commit 37af8a2

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

src/validation.cpp

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,10 @@ bool CheckSequenceLocks(CBlockIndex* tip,
286286
static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams);
287287

288288
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age)
289-
EXCLUSIVE_LOCKS_REQUIRED(pool.cs, ::cs_main)
289+
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
290290
{
291+
AssertLockHeld(::cs_main);
292+
AssertLockHeld(pool.cs);
291293
int expired = pool.Expire(GetTime<std::chrono::seconds>() - age);
292294
if (expired != 0) {
293295
LogPrint(BCLog::MEMPOOL, "Expired %i transactions from the memory pool\n", expired);
@@ -628,8 +630,10 @@ class MemPoolAccept
628630
EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
629631

630632
// Compare a package's feerate against minimum allowed.
631-
bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs)
633+
bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_pool.cs)
632634
{
635+
AssertLockHeld(::cs_main);
636+
AssertLockHeld(m_pool.cs);
633637
CAmount mempoolRejectFee = m_pool.GetMinFee(gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(package_size);
634638
if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
635639
return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
@@ -663,6 +667,8 @@ class MemPoolAccept
663667

664668
bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
665669
{
670+
AssertLockHeld(cs_main);
671+
AssertLockHeld(m_pool.cs);
666672
const CTransactionRef& ptx = ws.m_ptx;
667673
const CTransaction& tx = *ws.m_ptx;
668674
const uint256& hash = ws.m_hash;
@@ -963,6 +969,8 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
963969

964970
bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
965971
{
972+
AssertLockHeld(cs_main);
973+
AssertLockHeld(m_pool.cs);
966974
const CTransaction& tx = *ws.m_ptx;
967975
TxValidationState& state = ws.m_state;
968976

@@ -989,6 +997,8 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
989997

990998
bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
991999
{
1000+
AssertLockHeld(cs_main);
1001+
AssertLockHeld(m_pool.cs);
9921002
const CTransaction& tx = *ws.m_ptx;
9931003
const uint256& hash = ws.m_hash;
9941004
TxValidationState& state = ws.m_state;
@@ -1021,6 +1031,8 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
10211031

10221032
bool MemPoolAccept::Finalize(const ATMPArgs& args, Workspace& ws)
10231033
{
1034+
AssertLockHeld(cs_main);
1035+
AssertLockHeld(m_pool.cs);
10241036
const CTransaction& tx = *ws.m_ptx;
10251037
const uint256& hash = ws.m_hash;
10261038
TxValidationState& state = ws.m_state;
@@ -1342,8 +1354,9 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
13421354

13431355
MempoolAcceptResult AcceptToMemoryPool(CChainState& active_chainstate, const CTransactionRef& tx,
13441356
int64_t accept_time, bool bypass_limits, bool test_accept)
1345-
EXCLUSIVE_LOCKS_REQUIRED(cs_main)
1357+
EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
13461358
{
1359+
AssertLockHeld(::cs_main);
13471360
const CChainParams& chainparams{active_chainstate.m_params};
13481361
assert(active_chainstate.GetMempool() != nullptr);
13491362
CTxMemPool& pool{*active_chainstate.GetMempool()};
@@ -1421,6 +1434,7 @@ CoinsViews::CoinsViews(
14211434

14221435
void CoinsViews::InitCache()
14231436
{
1437+
AssertLockHeld(::cs_main);
14241438
m_cacheview = std::make_unique<CCoinsViewCache>(&m_catcherview);
14251439
}
14261440

@@ -1451,6 +1465,7 @@ void CChainState::InitCoinsDB(
14511465

14521466
void CChainState::InitCoinsCache(size_t cache_size_bytes)
14531467
{
1468+
AssertLockHeld(::cs_main);
14541469
assert(m_coins_views != nullptr);
14551470
m_coinstip_cache_size_bytes = cache_size_bytes;
14561471
m_coins_views->InitCache();
@@ -1524,6 +1539,7 @@ void CChainState::CheckForkWarningConditions()
15241539
// Called both upon regular invalid block discovery *and* InvalidateBlock
15251540
void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
15261541
{
1542+
AssertLockHeld(cs_main);
15271543
if (!m_chainman.m_best_invalid || pindexNew->nChainWork > m_chainman.m_best_invalid->nChainWork) {
15281544
m_chainman.m_best_invalid = pindexNew;
15291545
}
@@ -1546,6 +1562,7 @@ void CChainState::InvalidChainFound(CBlockIndex* pindexNew)
15461562
// which does its own setBlockIndexCandidates management.
15471563
void CChainState::InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state)
15481564
{
1565+
AssertLockHeld(cs_main);
15491566
if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) {
15501567
pindex->nStatus |= BLOCK_FAILED_VALID;
15511568
m_chainman.m_failed_blocks.insert(pindex);
@@ -2209,6 +2226,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
22092226

22102227
CoinsCacheSizeState CChainState::GetCoinsCacheSizeState()
22112228
{
2229+
AssertLockHeld(::cs_main);
22122230
return this->GetCoinsCacheSizeState(
22132231
m_coinstip_cache_size_bytes,
22142232
gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000);
@@ -2218,6 +2236,7 @@ CoinsCacheSizeState CChainState::GetCoinsCacheSizeState(
22182236
size_t max_coins_cache_size_bytes,
22192237
size_t max_mempool_size_bytes)
22202238
{
2239+
AssertLockHeld(::cs_main);
22212240
const int64_t nMempoolUsage = m_mempool ? m_mempool->DynamicMemoryUsage() : 0;
22222241
int64_t cacheSize = CoinsTip().DynamicMemoryUsage();
22232242
int64_t nTotalSpace =
@@ -2426,6 +2445,7 @@ static void UpdateTipLog(
24262445

24272446
void CChainState::UpdateTip(const CBlockIndex* pindexNew)
24282447
{
2448+
AssertLockHeld(::cs_main);
24292449
const auto& coins_tip = this->CoinsTip();
24302450

24312451
// The remainder of the function isn't relevant if we are not acting on
@@ -2649,7 +2669,9 @@ bool CChainState::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew
26492669
* Return the tip of the chain with the most work in it, that isn't
26502670
* known to be invalid (it's however far from certain to be valid).
26512671
*/
2652-
CBlockIndex* CChainState::FindMostWorkChain() {
2672+
CBlockIndex* CChainState::FindMostWorkChain()
2673+
{
2674+
AssertLockHeld(::cs_main);
26532675
do {
26542676
CBlockIndex *pindexNew = nullptr;
26552677

@@ -2853,7 +2875,7 @@ bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr
28532875
// far from a guarantee. Things in the P2P/RPC will often end up calling
28542876
// us in the middle of ProcessNewBlock - do not assume pblock is set
28552877
// sanely for performance or correctness!
2856-
AssertLockNotHeld(cs_main);
2878+
AssertLockNotHeld(::cs_main);
28572879

28582880
// ABC maintains a fair degree of expensive-to-calculate internal state
28592881
// because this function periodically releases cs_main so that it does not lock up other threads for too long
@@ -2949,6 +2971,8 @@ bool CChainState::ActivateBestChain(BlockValidationState& state, std::shared_ptr
29492971

29502972
bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex)
29512973
{
2974+
AssertLockNotHeld(m_chainstate_mutex);
2975+
AssertLockNotHeld(::cs_main);
29522976
{
29532977
LOCK(cs_main);
29542978
if (pindex->nChainWork < m_chain.Tip()->nChainWork) {
@@ -2979,6 +3003,7 @@ bool CChainState::PreciousBlock(BlockValidationState& state, CBlockIndex* pindex
29793003
bool CChainState::InvalidateBlock(BlockValidationState& state, CBlockIndex* pindex)
29803004
{
29813005
AssertLockNotHeld(m_chainstate_mutex);
3006+
AssertLockNotHeld(::cs_main);
29823007

29833008
// Genesis block can't be invalidated
29843009
assert(pindex);
@@ -3157,6 +3182,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
31573182
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
31583183
void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos)
31593184
{
3185+
AssertLockHeld(cs_main);
31603186
pindexNew->nTx = block.vtx.size();
31613187
pindexNew->nChainTx = 0;
31623188
pindexNew->nFile = pos.nFile;
@@ -3329,8 +3355,9 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
33293355
* in ConnectBlock().
33303356
* Note that -reindex-chainstate skips the validation that happens here!
33313357
*/
3332-
static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
3358+
static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
33333359
{
3360+
AssertLockHeld(::cs_main);
33343361
assert(pindexPrev != nullptr);
33353362
const int nHeight = pindexPrev->nHeight + 1;
33363363

@@ -3701,6 +3728,7 @@ bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const s
37013728

37023729
MempoolAcceptResult ChainstateManager::ProcessTransaction(const CTransactionRef& tx, bool test_accept)
37033730
{
3731+
AssertLockHeld(cs_main);
37043732
CChainState& active_chainstate = ActiveChainstate();
37053733
if (!active_chainstate.GetMempool()) {
37063734
TxValidationState state;
@@ -3914,6 +3942,7 @@ bool CVerifyDB::VerifyDB(
39143942
/** Apply the effects of a block on the utxo cache, ignoring that it may already have been applied. */
39153943
bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs)
39163944
{
3945+
AssertLockHeld(cs_main);
39173946
// TODO: merge with ConnectBlock
39183947
CBlock block;
39193948
if (!ReadBlockFromDisk(block, pindex, m_params.GetConsensus())) {
@@ -4017,7 +4046,9 @@ bool CChainState::NeedsRedownload() const
40174046
return false;
40184047
}
40194048

4020-
void CChainState::UnloadBlockIndex() {
4049+
void CChainState::UnloadBlockIndex()
4050+
{
4051+
AssertLockHeld(::cs_main);
40214052
nBlockSequenceId = 1;
40224053
setBlockIndexCandidates.clear();
40234054
}
@@ -4089,6 +4120,7 @@ bool CChainState::LoadGenesisBlock()
40894120

40904121
void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
40914122
{
4123+
AssertLockNotHeld(m_chainstate_mutex);
40924124
// Map of disk positions for blocks with unknown parent (only used for reindex)
40934125
static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
40944126
int64_t nStart = GetTimeMillis();
@@ -4429,6 +4461,7 @@ void CChainState::CheckBlockIndex()
44294461

44304462
std::string CChainState::ToString()
44314463
{
4464+
AssertLockHeld(::cs_main);
44324465
CBlockIndex* tip = m_chain.Tip();
44334466
return strprintf("Chainstate [%s] @ height %d (%s)",
44344467
m_from_snapshot_blockhash ? "snapshot" : "ibd",
@@ -4437,6 +4470,7 @@ std::string CChainState::ToString()
44374470

44384471
bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
44394472
{
4473+
AssertLockHeld(::cs_main);
44404474
if (coinstip_size == m_coinstip_cache_size_bytes &&
44414475
coinsdb_size == m_coinsdb_cache_size_bytes) {
44424476
// Cache sizes are unchanged, no need to continue.
@@ -4661,6 +4695,7 @@ std::vector<CChainState*> ChainstateManager::GetAll()
46614695
CChainState& ChainstateManager::InitializeChainstate(
46624696
CTxMemPool* mempool, const std::optional<uint256>& snapshot_blockhash)
46634697
{
4698+
AssertLockHeld(::cs_main);
46644699
bool is_snapshot = snapshot_blockhash.has_value();
46654700
std::unique_ptr<CChainState>& to_modify =
46664701
is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate;
@@ -4998,6 +5033,7 @@ bool ChainstateManager::IsSnapshotActive() const
49985033

49995034
void ChainstateManager::Unload()
50005035
{
5036+
AssertLockHeld(::cs_main);
50015037
for (CChainState* chainstate : this->GetAll()) {
50025038
chainstate->m_chain.SetTip(nullptr);
50035039
chainstate->UnloadBlockIndex();
@@ -5019,6 +5055,7 @@ void ChainstateManager::Reset()
50195055

50205056
void ChainstateManager::MaybeRebalanceCaches()
50215057
{
5058+
AssertLockHeld(::cs_main);
50225059
if (m_ibd_chainstate && !m_snapshot_chainstate) {
50235060
LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n");
50245061
// Allocate everything to the IBD chainstate.

0 commit comments

Comments
 (0)