Merge bitcoin/bitcoin#27570: refactor: Remove need to pass chainparams to BlockManager methods

fa5d7c39eb Remove unused chainparams from BlockManager methods (MarcoFalke)
fa3f74a40e Replace pindex pointer with block reference (MarcoFalke)
facdb8b331 Add BlockManagerOpts::chainparams reference (MarcoFalke)

Pull request description:

  Seems confusing to pass chainparams to each method individually, when the params can't change anyway for the whole lifetime of the block manager, and also must be equal to the ones used by the chainstate manager.

  Fix this issue by removing them from the methods and instead storing a reference once in a member field.

ACKs for top commit:
  dergoegge:
    Code review ACK fa5d7c39eb
  TheCharlatan:
    ACK fa5d7c39eb

Tree-SHA512: b44e2466b70a2a39a46625d618ce3173897ef30418db4efb9ff73d0eb2c082633204a5586c34b95f227e6711e64f19f12d5ac0f9f34692d40cb372e98389324b
This commit is contained in:
fanquake 2023-05-05 17:28:08 +01:00
commit ccd4db7d62
No known key found for this signature in database
GPG key ID: 2EEB9F5CC09526C1
9 changed files with 53 additions and 31 deletions

View file

@ -86,7 +86,10 @@ int main(int argc, char* argv[])
.datadir = gArgs.GetDataDirNet(), .datadir = gArgs.GetDataDirNet(),
.adjusted_time_callback = NodeClock::now, .adjusted_time_callback = NodeClock::now,
}; };
ChainstateManager chainman{chainman_opts, {}}; const node::BlockManager::Options blockman_opts{
.chainparams = chainman_opts.chainparams,
};
ChainstateManager chainman{chainman_opts, blockman_opts};
node::CacheSizes cache_sizes; node::CacheSizes cache_sizes;
cache_sizes.block_tree_db = 2 << 20; cache_sizes.block_tree_db = 2 << 20;

View file

@ -1036,7 +1036,9 @@ bool AppInitParameterInteraction(const ArgsManager& args, bool use_syscall_sandb
if (const auto error{ApplyArgsManOptions(args, chainman_opts_dummy)}) { if (const auto error{ApplyArgsManOptions(args, chainman_opts_dummy)}) {
return InitError(*error); return InitError(*error);
} }
node::BlockManager::Options blockman_opts_dummy{}; node::BlockManager::Options blockman_opts_dummy{
.chainparams = chainman_opts_dummy.chainparams,
};
if (const auto error{ApplyArgsManOptions(args, blockman_opts_dummy)}) { if (const auto error{ApplyArgsManOptions(args, blockman_opts_dummy)}) {
return InitError(*error); return InitError(*error);
} }
@ -1439,7 +1441,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}; };
Assert(!ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction Assert(!ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction
node::BlockManager::Options blockman_opts{}; node::BlockManager::Options blockman_opts{
.chainparams = chainman_opts.chainparams,
};
Assert(!ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction Assert(!ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction
// cache size calculations // cache size calculations

View file

@ -5,6 +5,8 @@
#ifndef BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H #ifndef BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H
#define BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H #define BITCOIN_KERNEL_BLOCKMANAGER_OPTS_H
class CChainParams;
namespace kernel { namespace kernel {
/** /**
@ -12,6 +14,7 @@ namespace kernel {
* `BlockManager::Options` due to the using-declaration in `BlockManager`. * `BlockManager::Options` due to the using-declaration in `BlockManager`.
*/ */
struct BlockManagerOpts { struct BlockManagerOpts {
const CChainParams& chainparams;
uint64_t prune_target{0}; uint64_t prune_target{0};
}; };

View file

@ -253,9 +253,9 @@ CBlockIndex* BlockManager::InsertBlockIndex(const uint256& hash)
return pindex; return pindex;
} }
bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params) bool BlockManager::LoadBlockIndex()
{ {
if (!m_block_tree_db->LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) { if (!m_block_tree_db->LoadBlockIndexGuts(GetConsensus(), [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); })) {
return false; return false;
} }
@ -318,9 +318,9 @@ bool BlockManager::WriteBlockIndexDB()
return true; return true;
} }
bool BlockManager::LoadBlockIndexDB(const Consensus::Params& consensus_params) bool BlockManager::LoadBlockIndexDB()
{ {
if (!LoadBlockIndex(consensus_params)) { if (!LoadBlockIndex()) {
return false; return false;
} }
@ -720,16 +720,16 @@ static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessa
return true; return true;
} }
bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex* pindex, const CChainParams& chainparams) bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValidationState& state, CBlockIndex& block)
{ {
AssertLockHeld(::cs_main); AssertLockHeld(::cs_main);
// Write undo information to disk // Write undo information to disk
if (pindex->GetUndoPos().IsNull()) { if (block.GetUndoPos().IsNull()) {
FlatFilePos _pos; FlatFilePos _pos;
if (!FindUndoPos(state, pindex->nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40)) { if (!FindUndoPos(state, block.nFile, _pos, ::GetSerializeSize(blockundo, CLIENT_VERSION) + 40)) {
return error("ConnectBlock(): FindUndoPos failed"); return error("ConnectBlock(): FindUndoPos failed");
} }
if (!UndoWriteToDisk(blockundo, _pos, pindex->pprev->GetBlockHash(), chainparams.MessageStart())) { if (!UndoWriteToDisk(blockundo, _pos, block.pprev->GetBlockHash(), GetParams().MessageStart())) {
return AbortNode(state, "Failed to write undo data"); return AbortNode(state, "Failed to write undo data");
} }
// rev files are written in block height order, whereas blk files are written as blocks come in (often out of order) // rev files are written in block height order, whereas blk files are written as blocks come in (often out of order)
@ -737,14 +737,14 @@ bool BlockManager::WriteUndoDataForBlock(const CBlockUndo& blockundo, BlockValid
// in the block file info as below; note that this does not catch the case where the undo writes are keeping up // in the block file info as below; note that this does not catch the case where the undo writes are keeping up
// with the block writes (usually when a synced up node is getting newly mined blocks) -- this case is caught in // with the block writes (usually when a synced up node is getting newly mined blocks) -- this case is caught in
// the FindBlockPos function // the FindBlockPos function
if (_pos.nFile < m_last_blockfile && static_cast<uint32_t>(pindex->nHeight) == m_blockfile_info[_pos.nFile].nHeightLast) { if (_pos.nFile < m_last_blockfile && static_cast<uint32_t>(block.nHeight) == m_blockfile_info[_pos.nFile].nHeightLast) {
FlushUndoFile(_pos.nFile, true); FlushUndoFile(_pos.nFile, true);
} }
// update nUndoPos in block index // update nUndoPos in block index
pindex->nUndoPos = _pos.nPos; block.nUndoPos = _pos.nPos;
pindex->nStatus |= BLOCK_HAVE_UNDO; block.nStatus |= BLOCK_HAVE_UNDO;
m_dirty_blockindex.insert(pindex); m_dirty_blockindex.insert(&block);
} }
return true; return true;
@ -829,7 +829,7 @@ bool ReadRawBlockFromDisk(std::vector<uint8_t>& block, const FlatFilePos& pos, c
return true; return true;
} }
FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp) FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const FlatFilePos* dbp)
{ {
unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION); unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION);
FlatFilePos blockPos; FlatFilePos blockPos;
@ -847,7 +847,7 @@ FlatFilePos BlockManager::SaveBlockToDisk(const CBlock& block, int nHeight, CCha
return FlatFilePos(); return FlatFilePos();
} }
if (!position_known) { if (!position_known) {
if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) { if (!WriteBlockToDisk(block, blockPos, GetParams().MessageStart())) {
AbortNode("Failed to write block"); AbortNode("Failed to write block");
return FlatFilePos(); return FlatFilePos();
} }

View file

@ -8,6 +8,7 @@
#include <attributes.h> #include <attributes.h>
#include <chain.h> #include <chain.h>
#include <kernel/blockmanager_opts.h> #include <kernel/blockmanager_opts.h>
#include <kernel/chainparams.h>
#include <kernel/cs_main.h> #include <kernel/cs_main.h>
#include <protocol.h> #include <protocol.h>
#include <sync.h> #include <sync.h>
@ -81,12 +82,14 @@ class BlockManager
friend ChainstateManager; friend ChainstateManager;
private: private:
const CChainParams& GetParams() const { return m_opts.chainparams; }
const Consensus::Params& GetConsensus() const { return m_opts.chainparams.GetConsensus(); }
/** /**
* Load the blocktree off disk and into memory. Populate certain metadata * Load the blocktree off disk and into memory. Populate certain metadata
* per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral * per index entry (nStatus, nChainWork, nTimeMax, etc.) as well as peripheral
* collections like m_dirty_blockindex. * collections like m_dirty_blockindex.
*/ */
bool LoadBlockIndex(const Consensus::Params& consensus_params) bool LoadBlockIndex()
EXCLUSIVE_LOCKS_REQUIRED(cs_main); EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false); void FlushBlockFile(bool fFinalize = false, bool finalize_undo = false);
void FlushUndoFile(int block_file, bool finalize = false); void FlushUndoFile(int block_file, bool finalize = false);
@ -162,7 +165,7 @@ public:
std::unique_ptr<CBlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main); std::unique_ptr<CBlockTreeDB> m_block_tree_db GUARDED_BY(::cs_main);
bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); bool WriteBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
bool LoadBlockIndexDB(const Consensus::Params& consensus_params) EXCLUSIVE_LOCKS_REQUIRED(::cs_main); bool LoadBlockIndexDB() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** /**
* Remove any pruned block & undo files that are still on disk. * Remove any pruned block & undo files that are still on disk.
@ -184,11 +187,11 @@ public:
/** Get block file info entry for one block file */ /** Get block file info entry for one block file */
CBlockFileInfo* GetBlockFileInfo(size_t n); 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& block)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main); EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
/** Store block on disk. If dbp is not nullptr, then it provides the known position of the block within a block file on disk. */ /** Store block on disk. If dbp is not nullptr, then it provides the known position of the block within a block file on disk. */
FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp); FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const FlatFilePos* dbp);
/** Whether running in -prune mode. */ /** Whether running in -prune mode. */
[[nodiscard]] bool IsPruneMode() const { return m_prune_mode; } [[nodiscard]] bool IsPruneMode() const { return m_prune_mode; }

View file

@ -21,23 +21,26 @@ BOOST_FIXTURE_TEST_SUITE(blockmanager_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos) BOOST_AUTO_TEST_CASE(blockmanager_find_block_pos)
{ {
const auto params {CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)}; const auto params {CreateChainParams(ArgsManager{}, CBaseChainParams::MAIN)};
BlockManager blockman{{}}; node::BlockManager::Options blockman_opts{
.chainparams = *params,
};
BlockManager blockman{blockman_opts};
CChain chain {}; CChain chain {};
// simulate adding a genesis block normally // simulate adding a genesis block normally
BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, *params, nullptr).nPos, BLOCK_SERIALIZATION_HEADER_SIZE); BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, nullptr).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
// simulate what happens during reindex // simulate what happens during reindex
// simulate a well-formed genesis block being found at offset 8 in the blk00000.dat file // simulate a well-formed genesis block being found at offset 8 in the blk00000.dat file
// the block is found at offset 8 because there is an 8 byte serialization header // the block is found at offset 8 because there is an 8 byte serialization header
// consisting of 4 magic bytes + 4 length bytes before each block in a well-formed blk file. // consisting of 4 magic bytes + 4 length bytes before each block in a well-formed blk file.
FlatFilePos pos{0, BLOCK_SERIALIZATION_HEADER_SIZE}; FlatFilePos pos{0, BLOCK_SERIALIZATION_HEADER_SIZE};
BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, *params, &pos).nPos, BLOCK_SERIALIZATION_HEADER_SIZE); BOOST_CHECK_EQUAL(blockman.SaveBlockToDisk(params->GenesisBlock(), 0, chain, &pos).nPos, BLOCK_SERIALIZATION_HEADER_SIZE);
// now simulate what happens after reindex for the first new block processed // now simulate what happens after reindex for the first new block processed
// the actual block contents don't matter, just that it's a block. // the actual block contents don't matter, just that it's a block.
// verify that the write position is at offset 0x12d. // verify that the write position is at offset 0x12d.
// this is a check to make sure that https://github.com/bitcoin/bitcoin/issues/21379 does not recur // this is a check to make sure that https://github.com/bitcoin/bitcoin/issues/21379 does not recur
// 8 bytes (for serialization header) + 285 (for serialized genesis block) = 293 // 8 bytes (for serialization header) + 285 (for serialized genesis block) = 293
// add another 8 bytes for the second block's serialization header and we get 293 + 8 = 301 // add another 8 bytes for the second block's serialization header and we get 293 + 8 = 301
FlatFilePos actual{blockman.SaveBlockToDisk(params->GenesisBlock(), 1, chain, *params, nullptr)}; FlatFilePos actual{blockman.SaveBlockToDisk(params->GenesisBlock(), 1, chain, nullptr)};
BOOST_CHECK_EQUAL(actual.nPos, BLOCK_SERIALIZATION_HEADER_SIZE + ::GetSerializeSize(params->GenesisBlock(), CLIENT_VERSION) + BLOCK_SERIALIZATION_HEADER_SIZE); BOOST_CHECK_EQUAL(actual.nPos, BLOCK_SERIALIZATION_HEADER_SIZE + ::GetSerializeSize(params->GenesisBlock(), CLIENT_VERSION) + BLOCK_SERIALIZATION_HEADER_SIZE);
} }

View file

@ -185,7 +185,10 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve
.adjusted_time_callback = GetAdjustedTime, .adjusted_time_callback = GetAdjustedTime,
.check_block_index = true, .check_block_index = true,
}; };
m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, node::BlockManager::Options{}); node::BlockManager::Options blockman_opts{
.chainparams = chainman_opts.chainparams,
};
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{ m_node.chainman->m_blockman.m_block_tree_db = std::make_unique<CBlockTreeDB>(DBParams{
.path = m_args.GetDataDirNet() / "blocks" / "index", .path = m_args.GetDataDirNet() / "blocks" / "index",
.cache_bytes = static_cast<size_t>(m_cache_sizes.block_tree_db), .cache_bytes = static_cast<size_t>(m_cache_sizes.block_tree_db),

View file

@ -381,10 +381,13 @@ struct SnapshotTestSetup : TestChain100Setup {
.datadir = m_args.GetDataDirNet(), .datadir = m_args.GetDataDirNet(),
.adjusted_time_callback = GetAdjustedTime, .adjusted_time_callback = GetAdjustedTime,
}; };
node::BlockManager::Options blockman_opts{
.chainparams = chainman_opts.chainparams,
};
// For robustness, ensure the old manager is destroyed before creating a // For robustness, ensure the old manager is destroyed before creating a
// new one. // new one.
m_node.chainman.reset(); m_node.chainman.reset();
m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, node::BlockManager::Options{}); m_node.chainman = std::make_unique<ChainstateManager>(chainman_opts, blockman_opts);
} }
return *Assert(m_node.chainman); return *Assert(m_node.chainman);
} }

View file

@ -2374,7 +2374,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state,
if (fJustCheck) if (fJustCheck)
return true; return true;
if (!m_blockman.WriteUndoDataForBlock(blockundo, state, pindex, params)) { if (!m_blockman.WriteUndoDataForBlock(blockundo, state, *pindex)) {
return false; return false;
} }
@ -4000,7 +4000,7 @@ bool Chainstate::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockV
// Write block to history file // Write block to history file
if (fNewBlock) *fNewBlock = true; if (fNewBlock) *fNewBlock = true;
try { try {
FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, pindex->nHeight, m_chain, params, dbp)}; FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, pindex->nHeight, m_chain, dbp)};
if (blockPos.IsNull()) { if (blockPos.IsNull()) {
state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__)); state.Error(strprintf("%s: Failed to find position to write new block to disk", __func__));
return false; return false;
@ -4418,7 +4418,7 @@ bool ChainstateManager::LoadBlockIndex()
// Load block index from databases // Load block index from databases
bool needs_init = fReindex; bool needs_init = fReindex;
if (!fReindex) { if (!fReindex) {
bool ret = m_blockman.LoadBlockIndexDB(GetConsensus()); bool ret{m_blockman.LoadBlockIndexDB()};
if (!ret) return false; if (!ret) return false;
m_blockman.ScanAndUnlinkAlreadyPrunedFiles(); m_blockman.ScanAndUnlinkAlreadyPrunedFiles();
@ -4522,7 +4522,7 @@ bool Chainstate::LoadGenesisBlock()
try { try {
const CBlock& block = params.GenesisBlock(); const CBlock& block = params.GenesisBlock();
FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, 0, m_chain, params, nullptr)}; FlatFilePos blockPos{m_blockman.SaveBlockToDisk(block, 0, m_chain, nullptr)};
if (blockPos.IsNull()) { if (blockPos.IsNull()) {
return error("%s: writing genesis block to disk failed", __func__); return error("%s: writing genesis block to disk failed", __func__);
} }