From bd5235a5a8603ad1a0d2d1ee3b6847ff98352209 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Tue, 18 Jan 2022 12:51:03 +0100 Subject: [PATCH] Require IsBlockPruned() to hold mutex cs_main Summary: Co-authored-by: Vasil Dimov This is a partial backport of [[https://github.com/bitcoin/bitcoin/pull/22932 | core#22932]] https://github.com/bitcoin/bitcoin/pull/22932/commits/eaeeb88768db529b5241ccd42f1e87579908b4df Depends on D13036 Test Plan: With clang and DEBUG: `ninja all check-all` Reviewers: #bitcoin_abc, Fabien Reviewed By: #bitcoin_abc, Fabien Subscribers: Fabien Differential Revision: https://reviews.bitcoinabc.org/D13037 --- src/node/blockstorage.cpp | 1 + src/node/blockstorage.h | 3 ++- src/rpc/blockchain.cpp | 13 +++++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index df52066e4f..f9e7a27295 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -398,6 +398,7 @@ BlockManager::GetLastCheckpoint(const CCheckpointData &data) { } bool IsBlockPruned(const CBlockIndex *pblockindex) { + AssertLockHeld(::cs_main); return (fHavePruned && !pblockindex->nStatus.hasData() && pblockindex->nTx > 0); } diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 2a813119c9..55d77dbd6b 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -197,7 +197,8 @@ class BlockManager { }; //! Check whether the block associated with this index entry is pruned or not. -bool IsBlockPruned(const CBlockIndex *pblockindex); +bool IsBlockPruned(const CBlockIndex *pblockindex) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main); void CleanupBlockRevFiles(); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 348987f261..9363c6eed4 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -172,8 +172,9 @@ UniValue blockToJSON(const CBlock &block, const CBlockIndex *tip, UniValue txs(UniValue::VARR); if (txDetails) { CBlockUndo blockUndo; - const bool have_undo = !IsBlockPruned(blockindex) && - UndoReadFromDisk(blockUndo, blockindex); + const bool have_undo{WITH_LOCK( + ::cs_main, return !IsBlockPruned(blockindex) && + UndoReadFromDisk(blockUndo, blockindex))}; for (size_t i = 0; i < block.vtx.size(); ++i) { const CTransactionRef &tx = block.vtx.at(i); // coinbase transaction (i == 0) doesn't have undo data @@ -1065,7 +1066,9 @@ static RPCHelpMan getblockheader() { } static CBlock GetBlockChecked(const Config &config, - const CBlockIndex *pblockindex) { + const CBlockIndex *pblockindex) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); CBlock block; if (IsBlockPruned(pblockindex)) { throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)"); @@ -1082,7 +1085,9 @@ static CBlock GetBlockChecked(const Config &config, return block; } -static CBlockUndo GetUndoChecked(const CBlockIndex *pblockindex) { +static CBlockUndo GetUndoChecked(const CBlockIndex *pblockindex) + EXCLUSIVE_LOCKS_REQUIRED(cs_main) { + AssertLockHeld(::cs_main); CBlockUndo blockUndo; if (IsBlockPruned(pblockindex)) { throw JSONRPCError(RPC_MISC_ERROR,