diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1193,6 +1193,8 @@ void CTxMemPool::LimitSize(CCoinsViewCache &coins_cache, size_t limit, std::chrono::seconds age) { + AssertLockHeld(::cs_main); + AssertLockHeld(cs); int expired = Expire(GetTime() - age); if (expired != 0) { LogPrint(BCLog::MEMPOOL, diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -746,7 +746,8 @@ //! @returns whether or not the CoinsViews object has been fully initialized //! and we can //! safely flush this object to disk. - bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(cs_main) { + bool CanFlushToDisk() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); return m_coins_views && m_coins_views->m_cacheview; } @@ -778,13 +779,17 @@ std::set setBlockIndexCandidates; //! @returns A reference to the in-memory cache of the UTXO set. - CCoinsViewCache &CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { + CCoinsViewCache &CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); assert(m_coins_views->m_cacheview); return *m_coins_views->m_cacheview.get(); } //! @returns A reference to the on-disk UTXO set database. - CCoinsViewDB &CoinsDB() { return m_coins_views->m_dbview; } + CCoinsViewDB &CoinsDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); + return m_coins_views->m_dbview; + } //! @returns A pointer to the mempool. CTxMemPool *GetMempool() { return m_mempool; } @@ -793,6 +798,7 @@ //! handles disk read errors gracefully. CCoinsViewErrorCatcher &CoinsErrorCatcher() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { + AssertLockHeld(::cs_main); return m_coins_views->m_catcherview; } @@ -1219,6 +1225,7 @@ CBlockIndex *ActiveTip() const { return ActiveChain().Tip(); } node::BlockMap &BlockIndex() EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); return m_blockman.m_block_index; } diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -501,6 +501,8 @@ }; bool MemPoolAccept::PreChecks(ATMPArgs &args, Workspace &ws) { + AssertLockHeld(cs_main); + AssertLockHeld(m_pool.cs); const CTransactionRef &ptx = ws.m_ptx; const CTransaction &tx = *ws.m_ptx; const TxId &txid = ws.m_ptx->GetId(); @@ -726,6 +728,8 @@ } bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs &args, Workspace &ws) { + AssertLockHeld(cs_main); + AssertLockHeld(m_pool.cs); const CTransaction &tx = *ws.m_ptx; const TxId &txid = tx.GetId(); TxValidationState &state = ws.m_state; @@ -768,6 +772,8 @@ } bool MemPoolAccept::Finalize(const ATMPArgs &args, Workspace &ws) { + AssertLockHeld(cs_main); + AssertLockHeld(m_pool.cs); const TxId &txid = ws.m_ptx->GetId(); TxValidationState &state = ws.m_state; const bool bypass_limits = args.m_bypass_limits; @@ -1098,7 +1104,7 @@ const CTransactionRef &tx, int64_t accept_time, bool bypass_limits, bool test_accept) { - AssertLockHeld(cs_main); + AssertLockHeld(::cs_main); assert(active_chainstate.GetMempool() != nullptr); CTxMemPool &pool{*active_chainstate.GetMempool()}; @@ -1183,6 +1189,7 @@ m_catcherview(&m_dbview) {} void CoinsViews::InitCache() { + AssertLockHeld(::cs_main); m_cacheview = std::make_unique(&m_catcherview); } @@ -1203,6 +1210,7 @@ } void CChainState::InitCoinsCache(size_t cache_size_bytes) { + AssertLockHeld(::cs_main); assert(m_coins_views != nullptr); m_coinstip_cache_size_bytes = cache_size_bytes; m_coins_views->InitCache(); @@ -1379,6 +1387,7 @@ // InvalidateBlock, which does its own setBlockIndexCandidates management. void CChainState::InvalidBlockFound(CBlockIndex *pindex, const BlockValidationState &state) { + AssertLockHeld(cs_main); if (state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { pindex->nStatus = pindex->nStatus.withFailed(); m_chainman.m_failed_blocks.insert(pindex); @@ -2204,6 +2213,7 @@ } CoinsCacheSizeState CChainState::GetCoinsCacheSizeState() { + AssertLockHeld(::cs_main); return this->GetCoinsCacheSizeState( m_coinstip_cache_size_bytes, gArgs.GetIntArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000); @@ -2212,6 +2222,7 @@ CoinsCacheSizeState CChainState::GetCoinsCacheSizeState(size_t max_coins_cache_size_bytes, size_t max_mempool_size_bytes) { + AssertLockHeld(::cs_main); int64_t nMempoolUsage = m_mempool ? m_mempool->DynamicMemoryUsage() : 0; int64_t cacheSize = CoinsTip().DynamicMemoryUsage(); int64_t nTotalSpace = @@ -2434,6 +2445,7 @@ } void CChainState::UpdateTip(const CBlockIndex *pindexNew) { + AssertLockHeld(::cs_main); const auto &coins_tip = CoinsTip(); // The remainder of the function isn't relevant if we are not acting on @@ -2811,7 +2823,7 @@ * invalid (it's however far from certain to be valid). */ CBlockIndex *CChainState::FindMostWorkChain() { - AssertLockHeld(cs_main); + AssertLockHeld(::cs_main); do { CBlockIndex *pindexNew = nullptr; @@ -3176,7 +3188,7 @@ // far from a guarantee. Things in the P2P/RPC will often end up calling // us in the middle of ProcessNewBlock - do not assume pblock is set // sanely for performance or correctness! - AssertLockNotHeld(cs_main); + AssertLockNotHeld(::cs_main); // ABC maintains a fair degree of expensive-to-calculate internal state // because this function periodically releases cs_main so that it does not @@ -3307,6 +3319,8 @@ bool CChainState::PreciousBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) { + AssertLockNotHeld(m_chainstate_mutex); + AssertLockNotHeld(::cs_main); { LOCK(cs_main); if (pindex->nChainWork < m_chain.Tip()->nChainWork) { @@ -3540,6 +3554,7 @@ BlockValidationState &state, CBlockIndex *pindex) { AssertLockNotHeld(m_chainstate_mutex); + AssertLockNotHeld(::cs_main); // See 'Note for backport of Core PR16849' in CChainState::UnwindBlock LOCK(m_chainstate_mutex); @@ -3549,6 +3564,7 @@ bool CChainState::ParkBlock(const Config &config, BlockValidationState &state, CBlockIndex *pindex) { AssertLockNotHeld(m_chainstate_mutex); + AssertLockNotHeld(::cs_main); // See 'Note for backport of Core PR16849' in CChainState::UnwindBlock LOCK(m_chainstate_mutex); @@ -3559,6 +3575,7 @@ BlockValidationState &state, CBlockIndex *pindex) { AssertLockNotHeld(m_chainstate_mutex); + AssertLockNotHeld(::cs_main); // See 'Note for backport of Core PR16849' in CChainState::UnwindBlock LOCK(m_chainstate_mutex); @@ -3935,7 +3952,8 @@ const CBlockHeader &block, BlockValidationState &state, BlockManager &blockman, const CBlockIndex *pindexPrev, int64_t nAdjustedTime) - EXCLUSIVE_LOCKS_REQUIRED(cs_main) { + EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); assert(pindexPrev != nullptr); const int nHeight = pindexPrev->nHeight + 1; @@ -4517,6 +4535,7 @@ MempoolAcceptResult ChainstateManager::ProcessTransaction(const CTransactionRef &tx, bool test_accept) { + AssertLockHeld(cs_main); CChainState &active_chainstate = ActiveChainstate(); if (!active_chainstate.GetMempool()) { TxValidationState state; @@ -4809,6 +4828,7 @@ */ bool CChainState::RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &view) { + AssertLockHeld(cs_main); // TODO: merge with ConnectBlock CBlock block; if (!ReadBlockFromDisk(block, pindex, m_params.GetConsensus())) { @@ -4935,6 +4955,7 @@ // May NOT be used after any connections are up as much of the peer-processing // logic assumes a consistent block index state void CChainState::UnloadBlockIndex() { + AssertLockHeld(::cs_main); nBlockSequenceId = 1; setBlockIndexCandidates.clear(); @@ -5011,6 +5032,7 @@ void CChainState::LoadExternalBlockFile(const Config &config, FILE *fileIn, FlatFilePos *dbp) { + AssertLockNotHeld(m_chainstate_mutex); // Map of disk positions for blocks with unknown parent (only used for // reindex) static std::multimap mapBlocksUnknownParent; @@ -5508,6 +5530,7 @@ } std::string CChainState::ToString() { + AssertLockHeld(::cs_main); CBlockIndex *tip = m_chain.Tip(); return strprintf("Chainstate [%s] @ height %d (%s)", m_from_snapshot_blockhash ? "snapshot" : "ibd", @@ -5516,6 +5539,7 @@ } bool CChainState::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size) { + AssertLockHeld(::cs_main); if (coinstip_size == m_coinstip_cache_size_bytes && coinsdb_size == m_coinsdb_cache_size_bytes) { // Cache sizes are unchanged, no need to continue. @@ -5763,6 +5787,7 @@ CChainState &ChainstateManager::InitializeChainstate( CTxMemPool *mempool, const std::optional &snapshot_blockhash) { + AssertLockHeld(::cs_main); bool is_snapshot = snapshot_blockhash.has_value(); std::unique_ptr &to_modify = is_snapshot ? m_snapshot_chainstate : m_ibd_chainstate; @@ -6118,6 +6143,7 @@ } void ChainstateManager::Unload() { + AssertLockHeld(::cs_main); for (CChainState *chainstate : this->GetAll()) { chainstate->m_chain.SetTip(nullptr); chainstate->UnloadBlockIndex(); @@ -6138,6 +6164,7 @@ } void ChainstateManager::MaybeRebalanceCaches() { + AssertLockHeld(::cs_main); if (m_ibd_chainstate && !m_snapshot_chainstate) { LogPrintf("[snapshot] allocating all cache to the IBD chainstate\n"); // Allocate everything to the IBD chainstate.