diff options
author | fanquake <fanquake@gmail.com> | 2023-05-11 10:14:30 +0100 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2023-05-11 10:28:51 +0100 |
commit | c2f2abd0a4f4bd18bfca41b632d21d803479f3f4 (patch) | |
tree | 8cb500f47f2582a4029eab75c95003bb4e1e0d74 /src | |
parent | 3ff67f77831474e342502e6a24be8a2ce5688e04 (diff) | |
parent | 5ff63a09a9edd1204b2cc56cf6f48a44adab7bb3 (diff) |
Merge bitcoin/bitcoin#27125: refactor, kernel: Decouple ArgsManager from blockstorage
5ff63a09a9edd1204b2cc56cf6f48a44adab7bb3 refactor, blockstorage: Replace stopafterblockimport arg (TheCharlatan)
18e5ba7c8002bcd473ee29ce4b5bfc56df6142a4 refactor, blockstorage: Replace blocksdir arg (TheCharlatan)
02a0899527ba3d31329e56c791c9dbf36075bb84 refactor, BlockManager: Replace fastprune from arg with options (TheCharlatan)
a498d699e3fdac5bfdb33020a1fd6c4a79989752 refactor/iwyu: Complete includes for blockmanager_args (TheCharlatan)
f0bb1021f0d60f5f19176e67a66fcf7c325f88d1 refactor: Move functions to BlockManager methods (TheCharlatan)
cfbb2124939822e95265a39242ffca3d86bac6e8 zmq: Pass lambda to zmq's ZMQPublishRawBlockNotifier (TheCharlatan)
8ed4ff8e05d61a8e954d72cebdc2e1d1ab24fb84 refactor: Declare g_zmq_notification_interface as unique_ptr (TheCharlatan)
Pull request description:
The libbitcoin_kernel library should not rely on the `ArgsManager`, but rather use option structs that can be passed to the various classes it uses. This PR removes reliance on the `ArgsManager` from the `blockstorage.*` files. Like similar prior work, it uses the options struct in the `BlockManager` that can be populated with `ArgsManager` values.
Some related prior work: https://github.com/bitcoin/bitcoin/pull/26889 https://github.com/bitcoin/bitcoin/pull/25862 https://github.com/bitcoin/bitcoin/pull/25527 https://github.com/bitcoin/bitcoin/pull/25487
Related PR removing blockstorage globals: https://github.com/bitcoin/bitcoin/pull/25781
ACKs for top commit:
ryanofsky:
Code review ACK 5ff63a09a9edd1204b2cc56cf6f48a44adab7bb3. Since last ACK just added std::move and fixed commit title. Sorry for the noise!
mzumsande:
Code Review ACK 5ff63a09a9edd1204b2cc56cf6f48a44adab7bb3
Tree-SHA512: 4bde8fd140a40b97eca923e9016d85dcea6fad6fd199731f158376294af59c3e8b163a0725aa47b4be3519b61828044e0a042deea005e0c28de21d8b6c3e1ea7
Diffstat (limited to 'src')
32 files changed, 188 insertions, 169 deletions
diff --git a/src/bitcoin-chainstate.cpp b/src/bitcoin-chainstate.cpp index 52e697a78d..16c3bfb708 100644 --- a/src/bitcoin-chainstate.cpp +++ b/src/bitcoin-chainstate.cpp @@ -89,6 +89,7 @@ int main(int argc, char* argv[]) }; const node::BlockManager::Options blockman_opts{ .chainparams = chainman_opts.chainparams, + .blocks_dir = gArgs.GetBlocksDirPath(), }; ChainstateManager chainman{chainman_opts, blockman_opts}; diff --git a/src/index/base.cpp b/src/index/base.cpp index 237c8e8be0..3e05c9b965 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -23,8 +23,6 @@ #include <string> #include <utility> -using node::ReadBlockFromDisk; - constexpr uint8_t DB_BEST_BLOCK{'B'}; constexpr auto SYNC_LOG_INTERVAL{30s}; @@ -159,8 +157,6 @@ void BaseIndex::ThreadSync() SetSyscallSandboxPolicy(SyscallSandboxPolicy::TX_INDEX); const CBlockIndex* pindex = m_best_block_index.load(); if (!m_synced) { - auto& consensus_params = Params().GetConsensus(); - std::chrono::steady_clock::time_point last_log_time{0s}; std::chrono::steady_clock::time_point last_locator_write_time{0s}; while (true) { @@ -207,7 +203,7 @@ void BaseIndex::ThreadSync() CBlock block; interfaces::BlockInfo block_info = kernel::MakeBlockInfo(pindex); - if (!ReadBlockFromDisk(block, pindex, consensus_params)) { + if (!m_chainstate->m_blockman.ReadBlockFromDisk(block, *pindex)) { FatalError("%s: Failed to read block %s from disk", __func__, pindex->GetBlockHash().ToString()); return; diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp index e6300ce3dd..a860b3a94d 100644 --- a/src/index/blockfilterindex.cpp +++ b/src/index/blockfilterindex.cpp @@ -12,8 +12,6 @@ #include <util/fs_helpers.h> #include <validation.h> -using node::UndoReadFromDisk; - /* The index database stores three items for each block: the disk location of the encoded filter, * its dSHA256 hash, and the header. Those belonging to blocks on the active chain are indexed by * height, and those belonging to blocks that have been reorganized out of the active chain are @@ -223,7 +221,7 @@ bool BlockFilterIndex::CustomAppend(const interfaces::BlockInfo& block) // pindex variable gives indexing code access to node internals. It // will be removed in upcoming commit const CBlockIndex* pindex = WITH_LOCK(cs_main, return m_chainstate->m_blockman.LookupBlockIndex(block.hash)); - if (!UndoReadFromDisk(block_undo, pindex)) { + if (!m_chainstate->m_blockman.UndoReadFromDisk(block_undo, *pindex)) { return false; } diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp index 5bc6ad3d31..d80885f842 100644 --- a/src/index/coinstatsindex.cpp +++ b/src/index/coinstatsindex.cpp @@ -19,9 +19,6 @@ using kernel::CCoinsStats; using kernel::GetBogoSize; using kernel::TxOutSer; -using node::ReadBlockFromDisk; -using node::UndoReadFromDisk; - static constexpr uint8_t DB_BLOCK_HASH{'s'}; static constexpr uint8_t DB_BLOCK_HEIGHT{'t'}; static constexpr uint8_t DB_MUHASH{'M'}; @@ -125,7 +122,7 @@ bool CoinStatsIndex::CustomAppend(const interfaces::BlockInfo& block) // pindex variable gives indexing code access to node internals. It // will be removed in upcoming commit const CBlockIndex* pindex = WITH_LOCK(cs_main, return m_chainstate->m_blockman.LookupBlockIndex(block.hash)); - if (!UndoReadFromDisk(block_undo, pindex)) { + if (!m_chainstate->m_blockman.UndoReadFromDisk(block_undo, *pindex)) { return false; } @@ -282,12 +279,11 @@ bool CoinStatsIndex::CustomRewind(const interfaces::BlockKey& current_tip, const LOCK(cs_main); const CBlockIndex* iter_tip{m_chainstate->m_blockman.LookupBlockIndex(current_tip.hash)}; const CBlockIndex* new_tip_index{m_chainstate->m_blockman.LookupBlockIndex(new_tip.hash)}; - const auto& consensus_params{Params().GetConsensus()}; do { CBlock block; - if (!ReadBlockFromDisk(block, iter_tip, consensus_params)) { + if (!m_chainstate->m_blockman.ReadBlockFromDisk(block, *iter_tip)) { return error("%s: Failed to read block %s from disk", __func__, iter_tip->GetBlockHash().ToString()); } @@ -409,7 +405,7 @@ bool CoinStatsIndex::ReverseBlock(const CBlock& block, const CBlockIndex* pindex // Ignore genesis block if (pindex->nHeight > 0) { - if (!UndoReadFromDisk(block_undo, pindex)) { + if (!m_chainstate->m_blockman.UndoReadFromDisk(block_undo, *pindex)) { return false; } diff --git a/src/index/txindex.cpp b/src/index/txindex.cpp index 49bddf2d4d..2e07a35d0d 100644 --- a/src/index/txindex.cpp +++ b/src/index/txindex.cpp @@ -10,8 +10,6 @@ #include <node/blockstorage.h> #include <validation.h> -using node::OpenBlockFile; - constexpr uint8_t DB_TXINDEX{'t'}; std::unique_ptr<TxIndex> g_txindex; @@ -80,7 +78,7 @@ bool TxIndex::FindTx(const uint256& tx_hash, uint256& block_hash, CTransactionRe return false; } - CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); + CAutoFile file(m_chainstate->m_blockman.OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION); if (file.IsNull()) { return error("%s: OpenBlockFile failed", __func__); } diff --git a/src/init.cpp b/src/init.cpp index 802397b3cf..52c5780ed4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -112,22 +112,23 @@ #include <zmq/zmqrpc.h> #endif +using kernel::DEFAULT_STOPAFTERBLOCKIMPORT; using kernel::DumpMempool; using kernel::ValidationCacheSizes; using node::ApplyArgsManOptions; +using node::BlockManager; using node::CacheSizes; using node::CalculateCacheSizes; using node::DEFAULT_PERSIST_MEMPOOL; using node::DEFAULT_PRINTPRIORITY; -using node::DEFAULT_STOPAFTERBLOCKIMPORT; +using node::fReindex; using node::LoadChainstate; using node::MempoolPath; -using node::ShouldPersistMempool; using node::NodeContext; +using node::ShouldPersistMempool; using node::ThreadImport; using node::VerifyLoadedChainstate; -using node::fReindex; static constexpr bool DEFAULT_PROXYRANDOMIZE{true}; static constexpr bool DEFAULT_REST_ENABLE{false}; @@ -328,9 +329,8 @@ void Shutdown(NodeContext& node) #if ENABLE_ZMQ if (g_zmq_notification_interface) { - UnregisterValidationInterface(g_zmq_notification_interface); - delete g_zmq_notification_interface; - g_zmq_notification_interface = nullptr; + UnregisterValidationInterface(g_zmq_notification_interface.get()); + g_zmq_notification_interface.reset(); } #endif @@ -1038,8 +1038,9 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb if (const auto error{ApplyArgsManOptions(args, chainman_opts_dummy)}) { return InitError(*error); } - node::BlockManager::Options blockman_opts_dummy{ + BlockManager::Options blockman_opts_dummy{ .chainparams = chainman_opts_dummy.chainparams, + .blocks_dir = args.GetBlocksDirPath(), }; if (const auto error{ApplyArgsManOptions(args, blockman_opts_dummy)}) { return InitError(*error); @@ -1425,10 +1426,14 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } #if ENABLE_ZMQ - g_zmq_notification_interface = CZMQNotificationInterface::Create(); + g_zmq_notification_interface = CZMQNotificationInterface::Create( + [&chainman = node.chainman](CBlock& block, const CBlockIndex& index) { + assert(chainman); + return chainman->m_blockman.ReadBlockFromDisk(block, index); + }); if (g_zmq_notification_interface) { - RegisterValidationInterface(g_zmq_notification_interface); + RegisterValidationInterface(g_zmq_notification_interface.get()); } #endif @@ -1443,8 +1448,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) }; Assert(!ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction - node::BlockManager::Options blockman_opts{ + BlockManager::Options blockman_opts{ .chainparams = chainman_opts.chainparams, + .blocks_dir = args.GetBlocksDirPath(), }; Assert(!ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction @@ -1674,7 +1680,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } chainman.m_load_block = std::thread(&util::TraceThread, "loadblk", [=, &chainman, &args] { - ThreadImport(chainman, vImportFiles, args, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{}); + ThreadImport(chainman, vImportFiles, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{}); }); // Wait for genesis block to be processed diff --git a/src/kernel/blockmanager_opts.h b/src/kernel/blockmanager_opts.h index 5584a66e02..8f26422f72 100644 --- a/src/kernel/blockmanager_opts.h +++ b/src/kernel/blockmanager_opts.h @@ -5,10 +5,16 @@ #ifndef BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H #define BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H +#include <util/fs.h> + +#include <cstdint> + class CChainParams; namespace kernel { +static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false}; + /** * An options struct for `BlockManager`, more ergonomically referred to as * `BlockManager::Options` due to the using-declaration in `BlockManager`. @@ -16,6 +22,9 @@ namespace kernel { struct BlockManagerOpts { const CChainParams& chainparams; uint64_t prune_target{0}; + bool fast_prune{false}; + bool stop_after_block_import{DEFAULT_STOPAFTERBLOCKIMPORT}; + const fs::path blocks_dir; }; } // namespace kernel diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 0f1fa0499c..e9d317fe99 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -51,9 +51,6 @@ #include <optional> #include <typeinfo> -using node::ReadBlockFromDisk; -using node::ReadRawBlockFromDisk; - /** How long to cache transactions in mapRelay for normal relay */ static constexpr auto RELAY_TX_CACHE_TIME = 15min; /** How long a transaction has to be in the mempool before it can unconditionally be relayed (even when not in mapRelay). */ @@ -2189,7 +2186,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<uint8_t> block_data; - if (!ReadRawBlockFromDisk(block_data, pindex->GetBlockPos(), m_chainparams.MessageStart())) { + if (!m_chainman.m_blockman.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})); @@ -2197,7 +2194,7 @@ void PeerManagerImpl::ProcessGetBlockData(CNode& pfrom, Peer& peer, const CInv& } else { // Send block from disk std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>(); - if (!ReadBlockFromDisk(*pblockRead, pindex, m_chainparams.GetConsensus())) { + if (!m_chainman.m_blockman.ReadBlockFromDisk(*pblockRead, *pindex)) { assert(!"cannot load block from disk"); } pblock = pblockRead; @@ -3889,7 +3886,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type, if (pindex->nHeight >= m_chainman.ActiveChain().Height() - MAX_BLOCKTXN_DEPTH) { CBlock block; - bool ret = ReadBlockFromDisk(block, pindex, m_chainparams.GetConsensus()); + const bool ret{m_chainman.m_blockman.ReadBlockFromDisk(block, *pindex)}; assert(ret); SendBlockTransactions(pfrom, *peer, block, req); @@ -5546,7 +5543,7 @@ bool PeerManagerImpl::SendMessages(CNode* pto) m_connman.PushMessage(pto, std::move(cached_cmpctblock_msg.value())); } else { CBlock block; - bool ret = ReadBlockFromDisk(block, pBestIndex, consensusParams); + const bool ret{m_chainman.m_blockman.ReadBlockFromDisk(block, *pBestIndex)}; assert(ret); CBlockHeaderAndShortTxIDs cmpctblock{block}; m_connman.PushMessage(pto, msgMaker.Make(NetMsgType::CMPCTBLOCK, cmpctblock)); diff --git a/src/node/blockmanager_args.cpp b/src/node/blockmanager_args.cpp index 06a1934947..23b0bd37ab 100644 --- a/src/node/blockmanager_args.cpp +++ b/src/node/blockmanager_args.cpp @@ -5,8 +5,14 @@ #include <node/blockmanager_args.h> #include <common/args.h> +#include <node/blockstorage.h> +#include <tinyformat.h> +#include <util/translation.h> #include <validation.h> +#include <cstdint> +#include <optional> + namespace node { std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& args, BlockManager::Options& opts) { @@ -25,6 +31,9 @@ std::optional<bilingual_str> ApplyArgsManOptions(const ArgsManager& args, BlockM } opts.prune_target = nPruneTarget; + if (auto value{args.GetBoolArg("-fastprune")}) opts.fast_prune = *value; + if (auto value{args.GetBoolArg("-stopafterblockimport")}) opts.stop_after_block_import = *value; + return std::nullopt; } } // namespace node diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp index bafee4e237..65dac459c5 100644 --- a/src/node/blockstorage.cpp +++ b/src/node/blockstorage.cpp @@ -6,7 +6,6 @@ #include <chain.h> #include <clientversion.h> -#include <common/args.h> #include <consensus/validation.h> #include <flatfile.h> #include <hash.h> @@ -53,10 +52,6 @@ bool CBlockIndexHeightOnlyComparator::operator()(const CBlockIndex* pa, const CB return pa->nHeight < pb->nHeight; } -static FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false); -static FlatFileSeq BlockFileSeq(); -static FlatFileSeq UndoFileSeq(); - std::vector<CBlockIndex*> BlockManager::GetAllBlockIndices() { AssertLockHeld(cs_main); @@ -423,7 +418,7 @@ const CBlockIndex* BlockManager::GetFirstStoredBlock(const CBlockIndex& start_bl // rev files since they'll be rewritten by the reindex anyway. This ensures that m_blockfile_info // is in sync with what's actually on disk by the time we start downloading, so that pruning // works correctly. -void CleanupBlockRevFiles() +void BlockManager::CleanupBlockRevFiles() const { std::map<std::string, fs::path> mapBlockFiles; @@ -431,8 +426,7 @@ void CleanupBlockRevFiles() // Remove the rev files immediately and insert the blk file paths into an // ordered map keyed by block file index. LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for -reindex with -prune\n"); - const fs::path& blocksdir = gArgs.GetBlocksDirPath(); - for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); it++) { + for (fs::directory_iterator it(m_opts.blocks_dir); it != fs::directory_iterator(); it++) { const std::string path = fs::PathToString(it->path().filename()); if (fs::is_regular_file(*it) && path.length() == 12 && @@ -467,7 +461,7 @@ CBlockFileInfo* BlockManager::GetBlockFileInfo(size_t n) return &m_blockfile_info.at(n); } -static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) +bool BlockManager::UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) const { // Open history file to append AutoFile fileout{OpenUndoFile(pos)}; @@ -496,9 +490,9 @@ static bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const return true; } -bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex) +bool BlockManager::UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex& index) const { - const FlatFilePos pos{WITH_LOCK(::cs_main, return pindex->GetUndoPos())}; + const FlatFilePos pos{WITH_LOCK(::cs_main, return index.GetUndoPos())}; if (pos.IsNull()) { return error("%s: no undo data available", __func__); @@ -514,7 +508,7 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex) uint256 hashChecksum; HashVerifier verifier{filein}; // Use HashVerifier as reserializing may lose data, c.f. commit d342424301013ec47dc146a4beb49d5c9319d80a try { - verifier << pindex->pprev->GetBlockHash(); + verifier << index.pprev->GetBlockHash(); verifier >> blockundo; filein >> hashChecksum; } catch (const std::exception& e) { @@ -570,7 +564,7 @@ uint64_t BlockManager::CalculateCurrentUsage() return retval; } -void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) +void BlockManager::UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const { std::error_code ec; for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) { @@ -583,28 +577,28 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) } } -static FlatFileSeq BlockFileSeq() +FlatFileSeq BlockManager::BlockFileSeq() const { - return FlatFileSeq(gArgs.GetBlocksDirPath(), "blk", gArgs.GetBoolArg("-fastprune", false) ? 0x4000 /* 16kb */ : BLOCKFILE_CHUNK_SIZE); + return FlatFileSeq(m_opts.blocks_dir, "blk", m_opts.fast_prune ? 0x4000 /* 16kb */ : BLOCKFILE_CHUNK_SIZE); } -static FlatFileSeq UndoFileSeq() +FlatFileSeq BlockManager::UndoFileSeq() const { - return FlatFileSeq(gArgs.GetBlocksDirPath(), "rev", UNDOFILE_CHUNK_SIZE); + return FlatFileSeq(m_opts.blocks_dir, "rev", UNDOFILE_CHUNK_SIZE); } -FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly) +FILE* BlockManager::OpenBlockFile(const FlatFilePos& pos, bool fReadOnly) const { return BlockFileSeq().Open(pos, fReadOnly); } /** Open an undo file (rev?????.dat) */ -static FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly) +FILE* BlockManager::OpenUndoFile(const FlatFilePos& pos, bool fReadOnly) const { return UndoFileSeq().Open(pos, fReadOnly); } -fs::path GetBlockPosFilename(const FlatFilePos& pos) +fs::path BlockManager::GetBlockPosFilename(const FlatFilePos& pos) const { return BlockFileSeq().FileName(pos); } @@ -623,7 +617,7 @@ bool BlockManager::FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigne unsigned int max_blockfile_size{MAX_BLOCKFILE_SIZE}; // Use smaller blockfiles in test-only -fastprune mode - but avoid // the possibility of having a block not fit into the block file. - if (gArgs.GetBoolArg("-fastprune", false)) { + if (m_opts.fast_prune) { max_blockfile_size = 0x10000; // 64kiB if (nAddSize >= max_blockfile_size) { // dynamically adjust the blockfile size to be larger than the added size @@ -697,7 +691,7 @@ bool BlockManager::FindUndoPos(BlockValidationState& state, int nFile, FlatFileP return true; } -static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) +bool BlockManager::WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) const { // Open history file to append CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); @@ -750,7 +744,7 @@ bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValid return true; } -bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams) +bool BlockManager::ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) const { block.SetNull(); @@ -768,33 +762,33 @@ bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::P } // Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) { + if (!CheckProofOfWork(block.GetHash(), block.nBits, GetConsensus())) { return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); } // Signet only: check block solution - if (consensusParams.signet_blocks && !CheckSignetBlockSolution(block, consensusParams)) { + if (GetConsensus().signet_blocks && !CheckSignetBlockSolution(block, GetConsensus())) { return error("ReadBlockFromDisk: Errors in block solution at %s", pos.ToString()); } return true; } -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) +bool BlockManager::ReadBlockFromDisk(CBlock& block, const CBlockIndex& index) const { - const FlatFilePos block_pos{WITH_LOCK(cs_main, return pindex->GetBlockPos())}; + const FlatFilePos block_pos{WITH_LOCK(cs_main, return index.GetBlockPos())}; - if (!ReadBlockFromDisk(block, block_pos, consensusParams)) { + if (!ReadBlockFromDisk(block, block_pos)) { return false; } - if (block.GetHash() != pindex->GetBlockHash()) { + if (block.GetHash() != index.GetBlockHash()) { return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", - pindex->ToString(), block_pos.ToString()); + index.ToString(), block_pos.ToString()); } return true; } -bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start) +bool BlockManager::ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start) const { FlatFilePos hpos = pos; hpos.nPos -= 8; // Seek back 8 bytes for meta header @@ -872,7 +866,7 @@ public: } }; -void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args, const fs::path& mempool_path) +void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const fs::path& mempool_path) { SetSyscallSandboxPolicy(SyscallSandboxPolicy::INITIALIZATION_LOAD_BLOCKS); ScheduleBatchPriority(); @@ -888,10 +882,10 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent; while (true) { FlatFilePos pos(nFile, 0); - if (!fs::exists(GetBlockPosFilename(pos))) { + if (!fs::exists(chainman.m_blockman.GetBlockPosFilename(pos))) { break; // No block files left to reindex } - FILE* file = OpenBlockFile(pos, true); + FILE* file = chainman.m_blockman.OpenBlockFile(pos, true); if (!file) { break; // This error is logged in OpenBlockFile } @@ -939,7 +933,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile } } - if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { + if (chainman.m_blockman.StopAfterBlockImport()) { LogPrintf("Stopping after block import\n"); StartShutdown(); return; diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h index 8f699f8e68..bce071c7df 100644 --- a/src/node/blockstorage.h +++ b/src/node/blockstorage.h @@ -20,7 +20,6 @@ #include <unordered_map> #include <vector> -class ArgsManager; class BlockValidationState; class CBlock; class CBlockFileInfo; @@ -36,7 +35,6 @@ struct Params; } namespace node { -static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false}; /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */ static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB @@ -96,6 +94,14 @@ private: bool FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown); bool FindUndoPos(BlockValidationState& state, int nFile, FlatFilePos& pos, unsigned int nAddSize); + FlatFileSeq BlockFileSeq() const; + FlatFileSeq UndoFileSeq() const; + + FILE* OpenUndoFile(const FlatFilePos& pos, bool fReadOnly = false) const; + + bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) const; + bool UndoWriteToDisk(const CBlockUndo& blockundo, FlatFilePos& pos, const uint256& hashBlock, const CMessageHeader::MessageStartChars& messageStart) const; + /* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */ void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight, int chain_tip_height); @@ -202,6 +208,8 @@ public: [[nodiscard]] bool LoadingBlocks() const { return m_importing || fReindex; } + [[nodiscard]] bool StopAfterBlockImport() const { return m_opts.stop_after_block_import; } + /** Calculate the amount of disk space the block & undo files currently use */ uint64_t CalculateCurrentUsage(); @@ -219,28 +227,29 @@ public: //! Create or update a prune lock identified by its name void UpdatePruneLock(const std::string& name, const PruneLockInfo& lock_info) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); -}; -void CleanupBlockRevFiles(); + /** Open a block file (blk?????.dat) */ + FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false) const; -/** Open a block file (blk?????.dat) */ -FILE* OpenBlockFile(const FlatFilePos& pos, bool fReadOnly = false); -/** Translation to a filesystem path */ -fs::path GetBlockPosFilename(const FlatFilePos& pos); + /** Translation to a filesystem path */ + fs::path GetBlockPosFilename(const FlatFilePos& pos) const; -/** - * Actually unlink the specified files - */ -void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune); + /** + * Actually unlink the specified files + */ + void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) const; -/** Functions for disk access for blocks */ -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<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start); + /** Functions for disk access for blocks */ + bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos) const; + bool ReadBlockFromDisk(CBlock& block, const CBlockIndex& index) const; + bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, const CMessageHeader::MessageStartChars& message_start) const; -bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex); + bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex& index) const; + + void CleanupBlockRevFiles() const; +}; -void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const ArgsManager& args, const fs::path& mempool_path); +void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFiles, const fs::path& mempool_path); } // namespace node #endif // BITCOIN_NODE_BLOCKSTORAGE_H diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index f60ff83a0d..40b609d069 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -51,7 +51,7 @@ static ChainstateLoadResult CompleteChainstateInitialization( pblocktree->WriteReindexing(true); //If we're reindexing in prune mode, wipe away unusable block files and all undo data files if (options.prune) { - CleanupBlockRevFiles(); + chainman.m_blockman.CleanupBlockRevFiles(); } } diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 49b88c3596..6e39ccf34e 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -394,7 +394,7 @@ public: NodeContext* m_context{nullptr}; }; -bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active) +bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active, const BlockManager& blockman) { if (!index) return false; if (block.m_hash) *block.m_hash = index->GetBlockHash(); @@ -404,10 +404,10 @@ bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<Rec if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast(); if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index; if (block.m_locator) { *block.m_locator = GetLocator(index); } - if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active); + if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active, blockman); if (block.m_data) { REVERSE_LOCK(lock); - if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull(); + if (!blockman.ReadBlockFromDisk(*block.m_data, *index)) block.m_data->SetNull(); } block.found = true; return true; @@ -557,13 +557,13 @@ public: bool findBlock(const uint256& hash, const FoundBlock& block) override { WAIT_LOCK(cs_main, lock); - return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, chainman().ActiveChain()); + return FillBlock(chainman().m_blockman.LookupBlockIndex(hash), block, lock, chainman().ActiveChain(), chainman().m_blockman); } bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override { WAIT_LOCK(cs_main, lock); const CChain& active = chainman().ActiveChain(); - return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active); + return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active, chainman().m_blockman); } bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override { @@ -571,10 +571,10 @@ public: const CChain& active = chainman().ActiveChain(); if (const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash)) { if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) { - return FillBlock(ancestor, ancestor_out, lock, active); + return FillBlock(ancestor, ancestor_out, lock, active, chainman().m_blockman); } } - return FillBlock(nullptr, ancestor_out, lock, active); + return FillBlock(nullptr, ancestor_out, lock, active, chainman().m_blockman); } bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override { @@ -582,7 +582,7 @@ public: const CBlockIndex* block = chainman().m_blockman.LookupBlockIndex(block_hash); const CBlockIndex* ancestor = chainman().m_blockman.LookupBlockIndex(ancestor_hash); if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr; - return FillBlock(ancestor, ancestor_out, lock, chainman().ActiveChain()); + return FillBlock(ancestor, ancestor_out, lock, chainman().ActiveChain(), chainman().m_blockman); } bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override { @@ -594,9 +594,9 @@ public: // Using & instead of && below to avoid short circuiting and leaving // output uninitialized. Cast bool to int to avoid -Wbitwise-instead-of-logical // compiler warnings. - return int{FillBlock(ancestor, ancestor_out, lock, active)} & - int{FillBlock(block1, block1_out, lock, active)} & - int{FillBlock(block2, block2_out, lock, active)}; + return int{FillBlock(ancestor, ancestor_out, lock, active, chainman().m_blockman)} & + int{FillBlock(block1, block1_out, lock, active, chainman().m_blockman)} & + int{FillBlock(block2, block2_out, lock, active, chainman().m_blockman)}; } void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); } double guessVerificationProgress(const uint256& block_hash) override diff --git a/src/node/transaction.cpp b/src/node/transaction.cpp index c7c8493f0c..026c8084dd 100644 --- a/src/node/transaction.cpp +++ b/src/node/transaction.cpp @@ -122,7 +122,7 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t return TransactionError::OK; } -CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock) +CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, uint256& hashBlock, const BlockManager& blockman) { if (mempool && !block_index) { CTransactionRef ptx = mempool->get(hash); @@ -143,7 +143,7 @@ CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMe } if (block_index) { CBlock block; - if (ReadBlockFromDisk(block, block_index, consensusParams)) { + if (blockman.ReadBlockFromDisk(block, *block_index)) { for (const auto& tx : block.vtx) { if (tx->GetHash() == hash) { hashBlock = block_index->GetBlockHash(); diff --git a/src/node/transaction.h b/src/node/transaction.h index 45f174f13c..168273594c 100644 --- a/src/node/transaction.h +++ b/src/node/transaction.h @@ -16,6 +16,7 @@ struct Params; } namespace node { +class BlockManager; struct NodeContext; /** Maximum fee rate for sendrawtransaction and testmempoolaccept RPC calls. @@ -53,11 +54,10 @@ static const CFeeRate DEFAULT_MAX_RAW_TX_FEE_RATE{COIN / 10}; * @param[in] block_index The block to read from disk, or nullptr * @param[in] mempool If provided, check mempool for tx * @param[in] hash The txid - * @param[in] consensusParams The params * @param[out] hashBlock The block hash, if the tx was found via -txindex or block_index * @returns The tx if found, otherwise nullptr */ -CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, const Consensus::Params& consensusParams, uint256& hashBlock); +CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMemPool* const mempool, const uint256& hash, uint256& hashBlock, const BlockManager& blockman); } // namespace node #endif // BITCOIN_NODE_TRANSACTION_H diff --git a/src/rest.cpp b/src/rest.cpp index e46406f1ad..dae064f89d 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -36,7 +36,6 @@ using node::GetTransaction; using node::NodeContext; -using node::ReadBlockFromDisk; static const size_t MAX_GETUTXOS_OUTPOINTS = 15; //allow a max of 15 outpoints to be queried at once static constexpr unsigned int MAX_REST_HEADERS_RESULTS = 2000; @@ -311,7 +310,7 @@ static bool rest_block(const std::any& context, } - if (!ReadBlockFromDisk(block, pblockindex, chainman.GetParams().GetConsensus())) { + if (!chainman.m_blockman.ReadBlockFromDisk(block, *pblockindex)) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } @@ -716,7 +715,7 @@ static bool rest_tx(const std::any& context, HTTPRequest* req, const std::string const NodeContext* const node = GetNodeContext(context, req); if (!node) return false; uint256 hashBlock = uint256(); - const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, node->mempool.get(), hash, Params().GetConsensus(), hashBlock); + const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, node->mempool.get(), hash, hashBlock, node->chainman->m_blockman); if (!tx) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e7a40f812c..72866532d2 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -58,9 +58,7 @@ using kernel::CoinStatsHashType; using node::BlockManager; using node::NodeContext; -using node::ReadBlockFromDisk; using node::SnapshotMetadata; -using node::UndoReadFromDisk; struct CUpdatedBlock { @@ -183,7 +181,7 @@ UniValue blockToJSON(BlockManager& blockman, const CBlock& block, const CBlockIn case TxVerbosity::SHOW_DETAILS_AND_PREVOUT: CBlockUndo blockUndo; const bool is_not_pruned{WITH_LOCK(::cs_main, return !blockman.IsBlockPruned(blockindex))}; - const bool have_undo{is_not_pruned && UndoReadFromDisk(blockUndo, blockindex)}; + const bool have_undo{is_not_pruned && blockman.UndoReadFromDisk(blockUndo, *blockindex)}; for (size_t i = 0; i < block.vtx.size(); ++i) { const CTransactionRef& tx = block.vtx.at(i); @@ -587,7 +585,7 @@ static CBlock GetBlockChecked(BlockManager& blockman, const CBlockIndex* pblocki } } - if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus())) { + if (!blockman.ReadBlockFromDisk(block, *pblockindex)) { // Block not found on disk. This could be because we have the block // header in our index but not yet have the block or did not accept the // block. Or if the block was pruned right after we released the lock above. @@ -611,7 +609,7 @@ static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblo } } - if (!UndoReadFromDisk(blockUndo, pblockindex)) { + if (!blockman.UndoReadFromDisk(blockUndo, *pblockindex)) { throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk"); } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 4a918cbd42..464be66046 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -51,8 +51,6 @@ using node::FindCoins; using node::GetTransaction; using node::NodeContext; using node::PSBTAnalysis; -using node::ReadBlockFromDisk; -using node::UndoReadFromDisk; static void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry, Chainstate& active_chainstate, const CTxUndo* txundo = nullptr, @@ -362,7 +360,7 @@ static RPCHelpMan getrawtransaction() } uint256 hash_block; - const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), hash, chainman.GetConsensus(), hash_block); + const CTransactionRef tx = GetTransaction(blockindex, node.mempool.get(), hash, hash_block, chainman.m_blockman); if (!tx) { std::string errmsg; if (blockindex) { @@ -406,7 +404,7 @@ static RPCHelpMan getrawtransaction() if (tx->IsCoinBase() || !blockindex || is_block_pruned || - !(UndoReadFromDisk(blockUndo, blockindex) && ReadBlockFromDisk(block, blockindex, Params().GetConsensus()))) { + !(chainman.m_blockman.UndoReadFromDisk(blockUndo, *blockindex) && chainman.m_blockman.ReadBlockFromDisk(block, *blockindex))) { TxToJSON(*tx, hash_block, result, chainman.ActiveChainstate()); return result; } diff --git a/src/rpc/txoutproof.cpp b/src/rpc/txoutproof.cpp index 24b5d04115..d74959cecc 100644 --- a/src/rpc/txoutproof.cpp +++ b/src/rpc/txoutproof.cpp @@ -18,7 +18,6 @@ #include <validation.h> using node::GetTransaction; -using node::ReadBlockFromDisk; static RPCHelpMan gettxoutproof() { @@ -85,7 +84,7 @@ static RPCHelpMan gettxoutproof() } if (pblockindex == nullptr) { - const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, /*mempool=*/nullptr, *setTxids.begin(), chainman.GetConsensus(), hashBlock); + const CTransactionRef tx = GetTransaction(/*block_index=*/nullptr, /*mempool=*/nullptr, *setTxids.begin(), hashBlock, chainman.m_blockman); if (!tx || hashBlock.IsNull()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block"); } @@ -98,7 +97,7 @@ static RPCHelpMan gettxoutproof() } CBlock block; - if (!ReadBlockFromDisk(block, pblockindex, chainman.GetConsensus())) { + if (!chainman.m_blockman.ReadBlockFromDisk(block, *pblockindex)) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk"); } diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index d22dbcf671..1ff5d6cf59 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -19,6 +19,7 @@ #include <boost/test/unit_test.hpp> using node::BlockAssembler; +using node::BlockManager; using node::CBlockTemplate; BOOST_AUTO_TEST_SUITE(blockfilter_index_tests) @@ -29,10 +30,10 @@ struct BuildChainTestingSetup : public TestChain100Setup { }; static bool CheckFilterLookups(BlockFilterIndex& filter_index, const CBlockIndex* block_index, - uint256& last_header) + uint256& last_header, const BlockManager& blockman) { BlockFilter expected_filter; - if (!ComputeFilter(filter_index.GetFilterType(), block_index, expected_filter)) { + if (!ComputeFilter(filter_index.GetFilterType(), *block_index, expected_filter, blockman)) { BOOST_ERROR("ComputeFilter failed on block " << block_index->nHeight); return false; } @@ -155,7 +156,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) for (block_index = m_node.chainman->ActiveChain().Genesis(); block_index != nullptr; block_index = m_node.chainman->ActiveChain().Next(block_index)) { - CheckFilterLookups(filter_index, block_index, last_header); + CheckFilterLookups(filter_index, block_index, last_header, m_node.chainman->m_blockman); } } @@ -189,7 +190,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) } BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); - CheckFilterLookups(filter_index, block_index, chainA_last_header); + CheckFilterLookups(filter_index, block_index, chainA_last_header, m_node.chainman->m_blockman); } // Reorg to chain B. @@ -207,7 +208,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) } BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); - CheckFilterLookups(filter_index, block_index, chainB_last_header); + CheckFilterLookups(filter_index, block_index, chainB_last_header, m_node.chainman->m_blockman); } // Check that filters for stale blocks on A can be retrieved. @@ -221,7 +222,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) } BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); - CheckFilterLookups(filter_index, block_index, chainA_last_header); + CheckFilterLookups(filter_index, block_index, chainA_last_header, m_node.chainman->m_blockman); } // Reorg back to chain A. @@ -241,14 +242,14 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) block_index = m_node.chainman->m_blockman.LookupBlockIndex(chainA[i]->GetHash()); } BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); - CheckFilterLookups(filter_index, block_index, chainA_last_header); + CheckFilterLookups(filter_index, block_index, chainA_last_header, m_node.chainman->m_blockman); { LOCK(cs_main); block_index = m_node.chainman->m_blockman.LookupBlockIndex(chainB[i]->GetHash()); } BOOST_CHECK(filter_index.BlockUntilSyncedToCurrentChain()); - CheckFilterLookups(filter_index, block_index, chainB_last_header); + CheckFilterLookups(filter_index, block_index, chainB_last_header, m_node.chainman->m_blockman); } // Test lookups for a range of filters/hashes. diff --git a/src/test/blockmanager_tests.cpp b/src/test/blockmanager_tests.cpp index fd33a21147..f094766886 100644 --- a/src/test/blockmanager_tests.cpp +++ b/src/test/blockmanager_tests.cpp @@ -14,7 +14,6 @@ using node::BlockManager; using node::BLOCK_SERIALIZATION_HEADER_SIZE; using node::MAX_BLOCKFILE_SIZE; -using node::OpenBlockFile; // use BasicTestingSetup here for the data directory configuration, setup, and cleanup BOOST_FIXTURE_TEST_SUITE(blockmanager_tests, BasicTestingSetup) @@ -22,8 +21,9 @@ BOOST_FIXTURE_TEST_SUITE(blockmanager_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos) { const auto params {CreateChainParams(ArgsManager{}, ChainType::MAIN)}; - node::BlockManager::Options blockman_opts{ + const BlockManager::Options blockman_opts{ .chainparams = *params, + .blocks_dir = m_args.GetBlocksDirPath(), }; BlockManager blockman{blockman_opts}; CChain chain {}; @@ -67,13 +67,13 @@ BOOST_FIXTURE_TEST_CASE(blockmanager_scan_unlink_already_pruned_files, TestChain // Check that the file is not unlinked after ScanAndUnlinkAlreadyPrunedFiles // if m_have_pruned is not yet set WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles()); - BOOST_CHECK(!AutoFile(OpenBlockFile(pos, true)).IsNull()); + BOOST_CHECK(!AutoFile(blockman.OpenBlockFile(pos, true)).IsNull()); // Check that the file is unlinked after ScanAndUnlinkAlreadyPrunedFiles // once m_have_pruned is set blockman.m_have_pruned = true; WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles()); - BOOST_CHECK(AutoFile(OpenBlockFile(pos, true)).IsNull()); + BOOST_CHECK(AutoFile(blockman.OpenBlockFile(pos, true)).IsNull()); // Check that calling with already pruned files doesn't cause an error WITH_LOCK(chainman->GetMutex(), blockman.ScanAndUnlinkAlreadyPrunedFiles()); @@ -83,7 +83,7 @@ BOOST_FIXTURE_TEST_CASE(blockmanager_scan_unlink_already_pruned_files, TestChain BOOST_CHECK_NE(old_tip, new_tip); const int new_file_number{WITH_LOCK(chainman->GetMutex(), return new_tip->GetBlockPos().nFile)}; const FlatFilePos new_pos(new_file_number, 0); - BOOST_CHECK(!AutoFile(OpenBlockFile(new_pos, true)).IsNull()); + BOOST_CHECK(!AutoFile(blockman.OpenBlockFile(new_pos, true)).IsNull()); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/util/blockfilter.cpp b/src/test/util/blockfilter.cpp index ec703c6a7b..a806844e34 100644 --- a/src/test/util/blockfilter.cpp +++ b/src/test/util/blockfilter.cpp @@ -8,20 +8,19 @@ #include <node/blockstorage.h> #include <validation.h> -using node::ReadBlockFromDisk; -using node::UndoReadFromDisk; +using node::BlockManager; -bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter) +bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex& block_index, BlockFilter& filter, const BlockManager& blockman) { LOCK(::cs_main); CBlock block; - if (!ReadBlockFromDisk(block, block_index->GetBlockPos(), Params().GetConsensus())) { + if (!blockman.ReadBlockFromDisk(block, block_index.GetBlockPos())) { return false; } CBlockUndo block_undo; - if (block_index->nHeight > 0 && !UndoReadFromDisk(block_undo, block_index)) { + if (block_index.nHeight > 0 && !blockman.UndoReadFromDisk(block_undo, block_index)) { return false; } diff --git a/src/test/util/blockfilter.h b/src/test/util/blockfilter.h index 79d11dcad8..789ce5d3aa 100644 --- a/src/test/util/blockfilter.h +++ b/src/test/util/blockfilter.h @@ -6,8 +6,12 @@ #define BITCOIN_TEST_UTIL_BLOCKFILTER_H #include <blockfilter.h> + class CBlockIndex; +namespace node { +class BlockManager; +} -bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter); +bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex& block_index, BlockFilter& filter, const node::BlockManager& blockman); #endif // BITCOIN_TEST_UTIL_BLOCKFILTER_H diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 642350b033..62d60d6774 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -62,6 +62,7 @@ using kernel::ValidationCacheSizes; using node::ApplyArgsManOptions; using node::BlockAssembler; +using node::BlockManager; using node::CalculateCacheSizes; using node::LoadChainstate; using node::RegenerateCommitments; @@ -186,8 +187,9 @@ ChainTestingSetup::ChainTestingSetup(const ChainType chainType, const std::vecto .adjusted_time_callback = GetAdjustedTime, .check_block_index = true, }; - node::BlockManager::Options blockman_opts{ + const BlockManager::Options blockman_opts{ .chainparams = chainman_opts.chainparams, + .blocks_dir = m_args.GetBlocksDirPath(), }; m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, blockman_opts); m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(DBParams{ diff --git a/src/test/validation_chainstatemanager_tests.cpp b/src/test/validation_chainstatemanager_tests.cpp index 85fe065a38..05e2787075 100644 --- a/src/test/validation_chainstatemanager_tests.cpp +++ b/src/test/validation_chainstatemanager_tests.cpp @@ -22,6 +22,7 @@ #include <boost/test/unit_test.hpp> +using node::BlockManager; using node::SnapshotMetadata; BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup) @@ -381,8 +382,9 @@ struct SnapshotTestSetup : TestChain100Setup { .datadir = m_args.GetDataDirNet(), .adjusted_time_callback = GetAdjustedTime, }; - node::BlockManager::Options blockman_opts{ + const BlockManager::Options blockman_opts{ .chainparams = chainman_opts.chainparams, + .blocks_dir = m_args.GetBlocksDirPath(), }; // For robustness, ensure the old manager is destroyed before creating a // new one. diff --git a/src/validation.cpp b/src/validation.cpp index f929e77416..e536dfb4eb 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -79,10 +79,7 @@ using node::BlockMap; using node::CBlockIndexHeightOnlyComparator; using node::CBlockIndexWorkComparator; using node::fReindex; -using node::ReadBlockFromDisk; using node::SnapshotMetadata; -using node::UndoReadFromDisk; -using node::UnlinkPrunedFiles; /** Maximum kilobytes for transactions to store for processing during reorg */ static const unsigned int MAX_DISCONNECTED_TX_POOL_SIZE = 20000; @@ -1914,7 +1911,7 @@ DisconnectResult Chainstate::DisconnectBlock(const CBlock& block, const CBlockIn bool fClean = true; CBlockUndo blockUndo; - if (!UndoReadFromDisk(blockUndo, pindex)) { + if (!m_blockman.UndoReadFromDisk(blockUndo, *pindex)) { error("DisconnectBlock(): failure reading undo data"); return DISCONNECT_FAILED; } @@ -2545,7 +2542,7 @@ bool Chainstate::FlushStateToDisk( if (fFlushForPrune) { LOG_TIME_MILLIS_WITH_CATEGORY("unlink pruned files", BCLog::BENCH); - UnlinkPrunedFiles(setFilesToPrune); + m_blockman.UnlinkPrunedFiles(setFilesToPrune); } m_last_write = nNow; } @@ -2709,7 +2706,7 @@ bool Chainstate::DisconnectTip(BlockValidationState& state, DisconnectedBlockTra // Read block from disk. std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); CBlock& block = *pblock; - if (!ReadBlockFromDisk(block, pindexDelete, m_chainman.GetConsensus())) { + if (!m_blockman.ReadBlockFromDisk(block, *pindexDelete)) { return error("DisconnectTip(): Failed to read block"); } // Apply the block atomically to the chain state. @@ -2826,7 +2823,7 @@ bool Chainstate::ConnectTip(BlockValidationState& state, CBlockIndex* pindexNew, std::shared_ptr<const CBlock> pthisBlock; if (!pblock) { std::shared_ptr<CBlock> pblockNew = std::make_shared<CBlock>(); - if (!ReadBlockFromDisk(*pblockNew, pindexNew, m_chainman.GetConsensus())) { + if (!m_blockman.ReadBlockFromDisk(*pblockNew, *pindexNew)) { return AbortNode(state, "Failed to read block"); } pthisBlock = pblockNew; @@ -4208,7 +4205,7 @@ VerifyDBResult CVerifyDB::VerifyDB( } CBlock block; // check level 0: read from disk - if (!ReadBlockFromDisk(block, pindex, consensus_params)) { + if (!chainstate.m_blockman.ReadBlockFromDisk(block, *pindex)) { LogPrintf("Verification error: ReadBlockFromDisk failed at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); return VerifyDBResult::CORRUPTED_BLOCK_DB; } @@ -4222,7 +4219,7 @@ VerifyDBResult CVerifyDB::VerifyDB( if (nCheckLevel >= 2 && pindex) { CBlockUndo undo; if (!pindex->GetUndoPos().IsNull()) { - if (!UndoReadFromDisk(undo, pindex)) { + if (!chainstate.m_blockman.UndoReadFromDisk(undo, *pindex)) { LogPrintf("Verification error: found bad undo data at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); return VerifyDBResult::CORRUPTED_BLOCK_DB; } @@ -4274,7 +4271,7 @@ VerifyDBResult CVerifyDB::VerifyDB( uiInterface.ShowProgress(_("Verifying blocks…").translated, percentageDone, false); pindex = chainstate.m_chain.Next(pindex); CBlock block; - if (!ReadBlockFromDisk(block, pindex, consensus_params)) { + if (!chainstate.m_blockman.ReadBlockFromDisk(block, *pindex)) { LogPrintf("Verification error: ReadBlockFromDisk failed at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); return VerifyDBResult::CORRUPTED_BLOCK_DB; } @@ -4303,7 +4300,7 @@ bool Chainstate::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& in AssertLockHeld(cs_main); // TODO: merge with ConnectBlock CBlock block; - if (!ReadBlockFromDisk(block, pindex, m_chainman.GetConsensus())) { + if (!m_blockman.ReadBlockFromDisk(block, *pindex)) { return error("ReplayBlock(): ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); } @@ -4355,7 +4352,7 @@ bool Chainstate::ReplayBlocks() while (pindexOld != pindexFork) { if (pindexOld->nHeight > 0) { // Never disconnect the genesis block. CBlock block; - if (!ReadBlockFromDisk(block, pindexOld, m_chainman.GetConsensus())) { + if (!m_blockman.ReadBlockFromDisk(block, *pindexOld)) { return error("RollbackBlock(): ReadBlockFromDisk() failed at %d, hash=%s", pindexOld->nHeight, pindexOld->GetBlockHash().ToString()); } LogPrintf("Rolling back %s (%i)\n", pindexOld->GetBlockHash().ToString(), pindexOld->nHeight); @@ -4666,7 +4663,7 @@ void Chainstate::LoadExternalBlockFile( while (range.first != range.second) { std::multimap<uint256, FlatFilePos>::iterator it = range.first; std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>(); - if (ReadBlockFromDisk(*pblockrecursive, it->second, params.GetConsensus())) { + if (m_blockman.ReadBlockFromDisk(*pblockrecursive, it->second)) { LogPrint(BCLog::REINDEX, "%s: Processing out of order child %s of %s\n", __func__, pblockrecursive->GetHash().ToString(), head.ToString()); LOCK(cs_main); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index da4b553394..78c68fdebb 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -29,7 +29,6 @@ #include <univalue.h> using node::MAX_BLOCKFILE_SIZE; -using node::UnlinkPrunedFiles; namespace wallet { RPCHelpMan importmulti(); @@ -159,7 +158,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) file_number = oldTip->GetBlockPos().nFile; Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number); } - UnlinkPrunedFiles({file_number}); + m_node.chainman->m_blockman.UnlinkPrunedFiles({file_number}); // Verify ScanForWalletTransactions only picks transactions in the new block // file. @@ -188,7 +187,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup) file_number = newTip->GetBlockPos().nFile; Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number); } - UnlinkPrunedFiles({file_number}); + m_node.chainman->m_blockman.UnlinkPrunedFiles({file_number}); // Verify ScanForWalletTransactions scans no blocks. { @@ -226,7 +225,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup) file_number = oldTip->GetBlockPos().nFile; Assert(m_node.chainman)->m_blockman.PruneOneBlockFile(file_number); } - UnlinkPrunedFiles({file_number}); + m_node.chainman->m_blockman.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 diff --git a/src/zmq/zmqabstractnotifier.h b/src/zmq/zmqabstractnotifier.h index cf0ee48f47..17fa7bbaa9 100644 --- a/src/zmq/zmqabstractnotifier.h +++ b/src/zmq/zmqabstractnotifier.h @@ -6,6 +6,7 @@ #define BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H #include <cstdint> +#include <functional> #include <memory> #include <string> @@ -13,7 +14,7 @@ class CBlockIndex; class CTransaction; class CZMQAbstractNotifier; -using CZMQNotifierFactory = std::unique_ptr<CZMQAbstractNotifier> (*)(); +using CZMQNotifierFactory = std::function<std::unique_ptr<CZMQAbstractNotifier>()>; class CZMQAbstractNotifier { diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp index 9920d80a69..6755368249 100644 --- a/src/zmq/zmqnotificationinterface.cpp +++ b/src/zmq/zmqnotificationinterface.cpp @@ -39,12 +39,14 @@ std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotif return result; } -CZMQNotificationInterface* CZMQNotificationInterface::Create() +std::unique_ptr<CZMQNotificationInterface> CZMQNotificationInterface::Create(std::function<bool(CBlock&, const CBlockIndex&)> get_block_by_index) { std::map<std::string, CZMQNotifierFactory> factories; factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>; factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>; - factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>; + factories["pubrawblock"] = [&get_block_by_index]() -> std::unique_ptr<CZMQAbstractNotifier> { + return std::make_unique<CZMQPublishRawBlockNotifier>(get_block_by_index); + }; factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>; factories["pubsequence"] = CZMQAbstractNotifier::Create<CZMQPublishSequenceNotifier>; @@ -68,7 +70,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create() notificationInterface->notifiers = std::move(notifiers); if (notificationInterface->Initialize()) { - return notificationInterface.release(); + return notificationInterface; } } @@ -198,4 +200,4 @@ void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr<const CB }); } -CZMQNotificationInterface* g_zmq_notification_interface = nullptr; +std::unique_ptr<CZMQNotificationInterface> g_zmq_notification_interface; diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h index a43f9bfef3..ce67633b30 100644 --- a/src/zmq/zmqnotificationinterface.h +++ b/src/zmq/zmqnotificationinterface.h @@ -9,6 +9,7 @@ #include <validationinterface.h> #include <cstdint> +#include <functional> #include <list> #include <memory> @@ -23,7 +24,7 @@ public: std::list<const CZMQAbstractNotifier*> GetActiveNotifiers() const; - static CZMQNotificationInterface* Create(); + static std::unique_ptr<CZMQNotificationInterface> Create(std::function<bool(CBlock&, const CBlockIndex&)> get_block_by_index); protected: bool Initialize(); @@ -43,6 +44,6 @@ private: std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers; }; -extern CZMQNotificationInterface* g_zmq_notification_interface; +extern std::unique_ptr<CZMQNotificationInterface> g_zmq_notification_interface; #endif // BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 55f3d4e934..21aa44c309 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -39,8 +39,6 @@ namespace Consensus { struct Params; } -using node::ReadBlockFromDisk; - static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers; static const char *MSG_HASHBLOCK = "hashblock"; @@ -247,10 +245,9 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex) { LogPrint(BCLog::ZMQ, "Publish rawblock %s to %s\n", pindex->GetBlockHash().GetHex(), this->address); - const Consensus::Params& consensusParams = Params().GetConsensus(); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags()); CBlock block; - if (!ReadBlockFromDisk(block, pindex, consensusParams)) { + if (!m_get_block_by_index(block, *pindex)) { zmqError("Can't read block from disk"); return false; } diff --git a/src/zmq/zmqpublishnotifier.h b/src/zmq/zmqpublishnotifier.h index 18336a5eb0..a5cd433761 100644 --- a/src/zmq/zmqpublishnotifier.h +++ b/src/zmq/zmqpublishnotifier.h @@ -9,7 +9,9 @@ #include <cstddef> #include <cstdint> +#include <functional> +class CBlock; class CBlockIndex; class CTransaction; @@ -46,7 +48,12 @@ public: class CZMQPublishRawBlockNotifier : public CZMQAbstractPublishNotifier { +private: + const std::function<bool(CBlock&, const CBlockIndex&)> m_get_block_by_index; + public: + CZMQPublishRawBlockNotifier(std::function<bool(CBlock&, const CBlockIndex&)> get_block_by_index) + : m_get_block_by_index{std::move(get_block_by_index)} {} bool NotifyBlock(const CBlockIndex *pindex) override; }; |