From 6fd4341c10b319399c58d71c4ddeae4417e337d7 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Thu, 9 Sep 2021 17:17:39 +0200 Subject: Require CBlockIndex::GetBlockPos() to hold mutex cs_main --- src/chain.h | 6 +++++- src/index/txindex.cpp | 4 +++- src/test/fuzz/chain.cpp | 21 ++++++++++++--------- src/test/util/blockfilter.cpp | 2 ++ src/wallet/test/wallet_tests.cpp | 17 +++++++++++------ 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/chain.h b/src/chain.h index 55bdf4cd56..534f226f28 100644 --- a/src/chain.h +++ b/src/chain.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,8 @@ static constexpr int64_t TIMESTAMP_WINDOW = MAX_FUTURE_BLOCK_TIME; */ static constexpr int64_t MAX_BLOCK_TIME_GAP = 90 * 60; +extern RecursiveMutex cs_main; + class CBlockFileInfo { public: @@ -223,8 +226,9 @@ public: { } - FlatFilePos GetBlockPos() const + FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); FlatFilePos ret; if (nStatus & BLOCK_HAVE_DATA) { ret.nFile = nFile; diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index e9aeb58194..e1d807f39a 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -59,7 +59,9 @@ bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex) // Exclude genesis block transaction because outputs are not spendable. if (pindex->nHeight == 0) return true; - CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size())); + CDiskTxPos pos{ + WITH_LOCK(::cs_main, return pindex->GetBlockPos()), + GetSizeOfCompactSize(block.vtx.size())}; std::vector> vPos; vPos.reserve(block.vtx.size()); for (const auto& tx : block.vtx) { diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp index 326904a811..4f97e1ebb1 100644 --- a/src/test/fuzz/chain.cpp +++ b/src/test/fuzz/chain.cpp @@ -21,15 +21,18 @@ FUZZ_TARGET(chain) const uint256 zero{}; disk_block_index->phashBlock = &zero; - (void)disk_block_index->GetBlockHash(); - (void)disk_block_index->GetBlockPos(); - (void)disk_block_index->GetBlockTime(); - (void)disk_block_index->GetBlockTimeMax(); - (void)disk_block_index->GetMedianTimePast(); - (void)disk_block_index->GetUndoPos(); - (void)disk_block_index->HaveTxsDownloaded(); - (void)disk_block_index->IsValid(); - (void)disk_block_index->ToString(); + { + LOCK(::cs_main); + (void)disk_block_index->GetBlockHash(); + (void)disk_block_index->GetBlockPos(); + (void)disk_block_index->GetBlockTime(); + (void)disk_block_index->GetBlockTimeMax(); + (void)disk_block_index->GetMedianTimePast(); + (void)disk_block_index->GetUndoPos(); + (void)disk_block_index->HaveTxsDownloaded(); + (void)disk_block_index->IsValid(); + (void)disk_block_index->ToString(); + } const CBlockHeader block_header = disk_block_index->GetBlockHeader(); (void)CDiskBlockIndex{*disk_block_index}; diff --git a/src/test/util/blockfilter.cpp b/src/test/util/blockfilter.cpp index 538981ce36..3ae22921b9 100644 --- a/src/test/util/blockfilter.cpp +++ b/src/test/util/blockfilter.cpp @@ -13,6 +13,8 @@ using node::UndoReadFromDisk; bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter) { + LOCK(::cs_main); + CBlock block; if (!ReadBlockFromDisk(block, block_index->GetBlockPos(), Params().GetConsensus())) { return false; diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index bb6021b857..9a74545fb5 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -140,11 +140,13 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) } // Prune the older block file. + int file_number; { LOCK(cs_main); - Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(oldTip->GetBlockPos().nFile); + file_number = oldTip->GetBlockPos().nFile; + Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number); } - UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); + UnlinkPrunedFiles({file_number}); // Verify ScanForWalletTransactions only picks transactions in the new block // file. @@ -169,9 +171,10 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) // Prune the remaining block file. { LOCK(cs_main); - Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(newTip->GetBlockPos().nFile); + file_number = newTip->GetBlockPos().nFile; + Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number); } - UnlinkPrunedFiles({newTip->GetBlockPos().nFile}); + UnlinkPrunedFiles({file_number}); // Verify ScanForWalletTransactions scans no blocks. { @@ -202,11 +205,13 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup) CBlockIndex* newTip = m_node.chainman->ActiveChain().Tip(); // Prune the older block file. + int file_number; { LOCK(cs_main); - Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(oldTip->GetBlockPos().nFile); + file_number = oldTip->GetBlockPos().nFile; + Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number); } - UnlinkPrunedFiles({oldTip->GetBlockPos().nFile}); + UnlinkPrunedFiles({file_number}); // Verify importmulti RPC returns failure for a key whose creation time is // before the missing block, and success for a key whose creation time is -- cgit v1.2.3 From 2e557ced2830fc54476e598d52225f1679205e7d Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Thu, 21 Oct 2021 16:56:34 +0200 Subject: Require WriteUndoDataForBlock() to hold mutex cs_main Mutex cs_main is already held by the caller of WriteUndoDataForBlock(). This change is needed to require CBlockIndex::GetUndoPos() to hold cs_main and CBlockIndex::nStatus to be guarded by cs_main in the following commits without adding 2 unnecessary cs_main locks to WriteUndoDataForBlock(). --- src/node/blockstorage.cpp | 1 + src/node/blockstorage.h | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index cbfdcb6f11..526100f1b2 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -712,6 +712,7 @@ static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessa bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams) { + AssertLockHeld(::cs_main); // Write undo information to disk if (pindex->GetUndoPos().IsNull()) { FlatFilePos _pos; diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 78c9210892..69c97f5d56 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -7,12 +7,15 @@ #include #include // For CMessageHeader::MessageStartChars +#include #include #include #include #include +extern RecursiveMutex cs_main; + class ArgsManager; class BlockValidationState; class CBlock; @@ -146,7 +149,8 @@ public: /** Get block file info entry for one block file */ CBlockFileInfo* GetBlockFileInfo(size_t n); - bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams); + bool WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams) + EXCLUSIVE_LOCKS_REQUIRED(::cs_main); FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp); -- cgit v1.2.3 From 572393448b4d32f91b92edc84b4200ab52d62422 Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Thu, 9 Sep 2021 18:48:22 +0200 Subject: Require CBlockIndex::GetUndoPos() to hold mutex cs_main --- src/chain.h | 3 ++- src/node/blockstorage.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/chain.h b/src/chain.h index 534f226f28..fc89599bd1 100644 --- a/src/chain.h +++ b/src/chain.h @@ -237,8 +237,9 @@ public: return ret; } - FlatFilePos GetUndoPos() const + FlatFilePos GetUndoPos() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); FlatFilePos ret; if (nStatus & BLOCK_HAVE_UNDO) { ret.nFile = nFile; diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 526100f1b2..2c18ee0c7d 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -513,7 +513,8 @@ static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex) { - FlatFilePos pos = pindex->GetUndoPos(); + const FlatFilePos pos{WITH_LOCK(::cs_main, return pindex->GetUndoPos())}; + if (pos.IsNull()) { return error("%s: no undo data available", __func__); } -- cgit v1.2.3 From 8ef457cb83fac796f8b6a56977b1016193fc1185 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Wed, 19 Jan 2022 14:03:23 +0100 Subject: Require CBlockIndex::IsAssumedValid() to hold cs_main --- src/chain.h | 6 +++++- src/test/validation_chainstatemanager_tests.cpp | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/chain.h b/src/chain.h index fc89599bd1..2eb780d499 100644 --- a/src/chain.h +++ b/src/chain.h @@ -320,7 +320,11 @@ public: //! @returns true if the block is assumed-valid; this means it is queued to be //! validated by a background chainstate. - bool IsAssumedValid() const { return nStatus & BLOCK_ASSUMED_VALID; } + bool IsAssumedValid() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) + { + AssertLockHeld(::cs_main); + return nStatus & BLOCK_ASSUMED_VALID; + } //! Raise the validity level of this block index entry. //! Returns true if the validity was changed. diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index f5742b65a1..26392e690d 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -235,7 +235,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup) *chainman.SnapshotBlockhash()); // Ensure that the genesis block was not marked assumed-valid. - BOOST_CHECK(!chainman.ActiveChain().Genesis()->IsAssumedValid()); + BOOST_CHECK(WITH_LOCK(::cs_main, return !chainman.ActiveChain().Genesis()->IsAssumedValid())); const AssumeutxoData& au_data = *ExpectedAssumeutxo(snapshot_height, ::Params()); const CBlockIndex* tip = chainman.ActiveTip(); @@ -356,6 +356,7 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup) // Mark some region of the chain assumed-valid. for (int i = 0; i <= cs1.m_chain.Height(); ++i) { + LOCK(::cs_main); auto index = cs1.m_chain[i]; if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) { -- cgit v1.2.3 From e9f3aa5f6a7b39e8d5f2069617e5e382798d8d60 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Wed, 19 Jan 2022 14:03:37 +0100 Subject: Require CBlockIndex::RaiseValidity() to hold cs_main --- src/chain.h | 3 ++- src/test/fuzz/chain.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/chain.h b/src/chain.h index 2eb780d499..c2a9cba1e6 100644 --- a/src/chain.h +++ b/src/chain.h @@ -328,8 +328,9 @@ public: //! Raise the validity level of this block index entry. //! Returns true if the validity was changed. - bool RaiseValidity(enum BlockStatus nUpTo) + bool RaiseValidity(enum BlockStatus nUpTo) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. if (nStatus & BLOCK_FAILED_MASK) return false; diff --git a/src/test/fuzz/chain.cpp b/src/test/fuzz/chain.cpp index 4f97e1ebb1..8c0ed32d51 100644 --- a/src/test/fuzz/chain.cpp +++ b/src/test/fuzz/chain.cpp @@ -58,7 +58,7 @@ FUZZ_TARGET(chain) if (block_status & ~BLOCK_VALID_MASK) { continue; } - (void)disk_block_index->RaiseValidity(block_status); + WITH_LOCK(::cs_main, (void)disk_block_index->RaiseValidity(block_status)); } CBlockIndex block_index{block_header}; -- cgit v1.2.3 From ca47b005770f71aa229ecc1f7b8146a96ff02151 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Wed, 19 Jan 2022 14:03:46 +0100 Subject: Require CBlockIndex::IsValid() to hold cs_main --- src/chain.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chain.h b/src/chain.h index c2a9cba1e6..fbc033281f 100644 --- a/src/chain.h +++ b/src/chain.h @@ -311,7 +311,9 @@ public: //! Check whether this block index entry is valid up to the passed validity level. bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const + EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + AssertLockHeld(::cs_main); assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. if (nStatus & BLOCK_FAILED_MASK) return false; -- cgit v1.2.3 From eaeeb88768db529b5241ccd42f1e87579908b4df Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Tue, 18 Jan 2022 12:51:03 +0100 Subject: Require IsBlockPruned() to hold mutex cs_main Co-authored-by: Vasil Dimov --- src/node/blockstorage.cpp | 1 + src/node/blockstorage.h | 2 +- src/rpc/blockchain.cpp | 8 +++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 2c18ee0c7d..5f6bf535b3 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -429,6 +429,7 @@ CBlockIndex* BlockManager::GetLastCheckpoint(const CCheckpointData& data) bool IsBlockPruned(const CBlockIndex* pblockindex) { + AssertLockHeld(::cs_main); return (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0); } diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 69c97f5d56..d7c980af85 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -167,7 +167,7 @@ public: }; //! 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 b07221c9bb..8df0aac203 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -185,7 +185,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* tip, const CBlockIn case TxVerbosity::SHOW_DETAILS: case TxVerbosity::SHOW_DETAILS_AND_PREVOUT: 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); @@ -929,8 +929,9 @@ static RPCHelpMan getblockheader() }; } -static CBlock GetBlockChecked(const CBlockIndex* pblockindex) +static CBlock GetBlockChecked(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)"); @@ -946,8 +947,9 @@ static CBlock GetBlockChecked(const CBlockIndex* pblockindex) 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, "Undo data not available (pruned data)"); -- cgit v1.2.3 From 5d59ae0ba88849b1eb0d7350871bc19fcd5ef601 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 21 Dec 2021 17:42:28 +0100 Subject: Remove/inline ReadRawBlockFromDisk(block_data, pindex, message_start) --- src/net_processing.cpp | 2 +- src/node/blockstorage.cpp | 11 ----------- src/node/blockstorage.h | 1 - 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index bd51b0f785..3cebca1a77 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1880,7 +1880,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& // Fast-path: in this case it is possible to serve the block directly from disk, // as the network format matches the format on disk std::vector block_data; - if (!ReadRawBlockFromDisk(block_data, pindex, m_chainparams.MessageStart())) { + if (!ReadRawBlockFromDisk(block_data, pindex->GetBlockPos(), m_chainparams.MessageStart())) { assert(!"cannot load block from disk"); } m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::BLOCK, Span{block_data})); diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index 5f6bf535b3..62be9f9aac 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -821,17 +821,6 @@ bool ReadRawBlockFromDisk(std::vector& block, const FlatFilePos& pos, c return true; } -bool ReadRawBlockFromDisk(std::vector& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start) -{ - FlatFilePos block_pos; - { - LOCK(cs_main); - block_pos = pindex->GetBlockPos(); - } - - return ReadRawBlockFromDisk(block, block_pos, message_start); -} - /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp) { diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index d7c980af85..42e46797d2 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -185,7 +185,6 @@ void UnlinkPrunedFiles(const std::set& setFilesToPrune); bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams); bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams); bool ReadRawBlockFromDisk(std::vector& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start); -bool ReadRawBlockFromDisk(std::vector& block, const CBlockIndex* pindex, const CMessageHeader::MessageStartChars& message_start); bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex); -- cgit v1.2.3 From 6ea56827842b9b2bd730edc38f3a7b1f46f6247b Mon Sep 17 00:00:00 2001 From: Jon Atack Date: Wed, 19 Jan 2022 13:42:32 +0100 Subject: Guard CBlockIndex::nStatus/nFile/nDataPos/nUndoPos by cs_main Co-authored-by: Vasil Dimov --- src/chain.h | 9 +++++---- src/rpc/blockchain.cpp | 3 ++- src/rpc/rawtransaction.cpp | 3 ++- src/test/interfaces_tests.cpp | 1 + src/txdb.cpp | 14 +++++++++----- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/chain.h b/src/chain.h index fbc033281f..8b03e66a96 100644 --- a/src/chain.h +++ b/src/chain.h @@ -164,13 +164,13 @@ public: int nHeight{0}; //! Which # file this block is stored in (blk?????.dat) - int nFile{0}; + int nFile GUARDED_BY(::cs_main){0}; //! Byte offset within blk?????.dat where this block's data is stored - unsigned int nDataPos{0}; + unsigned int nDataPos GUARDED_BY(::cs_main){0}; //! Byte offset within rev?????.dat where this block's undo data is stored - unsigned int nUndoPos{0}; + unsigned int nUndoPos GUARDED_BY(::cs_main){0}; //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block arith_uint256 nChainWork{}; @@ -198,7 +198,7 @@ public: //! load to avoid the block index being spuriously rewound. //! @sa NeedsRedownload //! @sa ActivateSnapshot - uint32_t nStatus{0}; + uint32_t nStatus GUARDED_BY(::cs_main){0}; //! block header int32_t nVersion{0}; @@ -382,6 +382,7 @@ public: SERIALIZE_METHODS(CDiskBlockIndex, obj) { + LOCK(::cs_main); int _nVersion = s.GetVersion(); if (!(s.GetType() & SER_GETHASH)) READWRITE(VARINT_MODE(_nVersion, VarIntMode::NONNEGATIVE_SIGNED)); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8df0aac203..c5697983d5 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -818,7 +818,8 @@ static RPCHelpMan getblockfrompeer() throw JSONRPCError(RPC_MISC_ERROR, "Block header missing"); } - if (index->nStatus & BLOCK_HAVE_DATA) { + const bool block_has_data = WITH_LOCK(::cs_main, return index->nStatus & BLOCK_HAVE_DATA); + if (block_has_data) { throw JSONRPCError(RPC_MISC_ERROR, "Block already downloaded"); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index f227fde0f7..e7d9f434f4 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -240,7 +240,8 @@ static RPCHelpMan getrawtransaction() if (!tx) { std::string errmsg; if (blockindex) { - if (!(blockindex->nStatus & BLOCK_HAVE_DATA)) { + const bool block_has_data = WITH_LOCK(::cs_main, return blockindex->nStatus & BLOCK_HAVE_DATA); + if (!block_has_data) { throw JSONRPCError(RPC_MISC_ERROR, "Block not available"); } errmsg = "No such transaction found in the provided block"; diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp index f4bf6ff8c9..49b7d2003b 100644 --- a/src/test/interfaces_tests.cpp +++ b/src/test/interfaces_tests.cpp @@ -123,6 +123,7 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor) BOOST_AUTO_TEST_CASE(hasBlocks) { + LOCK(::cs_main); auto& chain = m_node.chain; const CChain& active = Assert(m_node.chainman)->ActiveChain(); diff --git a/src/txdb.cpp b/src/txdb.cpp index 85eea888cc..e2aed1da7c 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -311,19 +311,23 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash()); pindexNew->pprev = insertBlockIndex(diskindex.hashPrev); pindexNew->nHeight = diskindex.nHeight; - pindexNew->nFile = diskindex.nFile; - pindexNew->nDataPos = diskindex.nDataPos; - pindexNew->nUndoPos = diskindex.nUndoPos; pindexNew->nVersion = diskindex.nVersion; pindexNew->hashMerkleRoot = diskindex.hashMerkleRoot; pindexNew->nTime = diskindex.nTime; pindexNew->nBits = diskindex.nBits; pindexNew->nNonce = diskindex.nNonce; - pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; + { + LOCK(::cs_main); + pindexNew->nFile = diskindex.nFile; + pindexNew->nDataPos = diskindex.nDataPos; + pindexNew->nUndoPos = diskindex.nUndoPos; + pindexNew->nStatus = diskindex.nStatus; + } - if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) + if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, consensusParams)) { return error("%s: CheckProofOfWork failed: %s", __func__, pindexNew->ToString()); + } pcursor->Next(); } else { -- cgit v1.2.3