From 07ea998555b469d27b148ef1d566fdc62b9e8f05 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:10:47 +0530 Subject: [PATCH 01/46] partial bitcoin#24595: move g_versionbitscache global to ChainstateManager includes: - 69675ea4e73dcf5e9dd0f94802bd3463e4262081 - 38860f93b680f152fc6fc3d9ae574a4c0659e775 - 5c67e84d37d452e9186a6357e5405fabeff241c7 - deffe0df6c36225bada18603b5a840139f030f2c - 78adef17536edef833a0bfca06b61ce28120e486 --- src/init.cpp | 2 +- src/net_processing.cpp | 6 +- src/rpc/blockchain.cpp | 38 +++++----- src/rpc/mining.cpp | 6 +- src/test/blockfilter_index_tests.cpp | 8 +-- src/test/evo_deterministicmns_tests.cpp | 18 ++--- src/test/fuzz/utxo_snapshot.cpp | 2 +- src/test/miner_tests.cpp | 2 +- src/test/util/mining.cpp | 2 +- src/test/util/setup_common.cpp | 8 +-- src/test/validation_block_tests.cpp | 10 +-- src/validation.cpp | 93 ++++++++++++------------- src/validation.h | 38 ++++++++-- 13 files changed, 130 insertions(+), 103 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index dcd0923bdd5d..07f3d165e981 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1981,7 +1981,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) for (bool fLoaded = false; !fLoaded && !ShutdownRequested();) { node.mempool = std::make_unique(node.fee_estimator.get(), mempool_check_ratio); - node.chainman = std::make_unique(); + node.chainman = std::make_unique(chainparams); ChainstateManager& chainman = *node.chainman; /** diff --git a/src/net_processing.cpp b/src/net_processing.cpp index d69a44eeb4cb..7fe1201dda63 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -3276,7 +3276,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer, bool received_new_header{WITH_LOCK(::cs_main, return m_chainman.m_blockman.LookupBlockIndex(headers.back().GetHash()) == nullptr)}; BlockValidationState state; - if (!m_chainman.ProcessNewBlockHeaders(headers, state, m_chainparams, &pindexLast)) { + if (!m_chainman.ProcessNewBlockHeaders(headers, state, &pindexLast)) { if (state.IsInvalid()) { MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received"); return; @@ -3581,7 +3581,7 @@ std::pair static ValidateDSTX(CDeterministicMN void PeerManagerImpl::ProcessBlock(CNode& node, const std::shared_ptr& block, bool force_processing) { bool new_block{false}; - m_chainman.ProcessNewBlock(m_chainparams, block, force_processing, &new_block); + m_chainman.ProcessNewBlock(block, force_processing, &new_block); if (new_block) { node.m_last_block_time = GetTime(); } else { @@ -4798,7 +4798,7 @@ void PeerManagerImpl::ProcessMessage( const CBlockIndex *pindex = nullptr; BlockValidationState state; - if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, m_chainparams, &pindex)) { + if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, &pindex)) { if (state.IsInvalid()) { MaybePunishNodeForBlock(pfrom.GetId(), state, /*via_compact_block=*/true, "invalid header via cmpctblock"); return; diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index a2c4aa399072..193b32f11f9e 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1406,29 +1406,29 @@ static RPCHelpMan verifychain() }; } -static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const Consensus::Params& params, Consensus::BuriedDeployment dep) +static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, UniValue& softforks, const ChainstateManager& chainman, Consensus::BuriedDeployment dep) { // For buried deployments. - if (!DeploymentEnabled(params, dep)) return; + if (!DeploymentEnabled(chainman, dep)) return; UniValue rv(UniValue::VOBJ); rv.pushKV("type", "buried"); // getblockchaininfo reports the softfork as active from when the chain height is // one below the activation height - rv.pushKV("active", DeploymentActiveAfter(active_chain_tip, params, dep)); - rv.pushKV("height", params.DeploymentHeight(dep)); + rv.pushKV("active", DeploymentActiveAfter(active_chain_tip, chainman, dep)); + rv.pushKV("height", chainman.GetConsensus().DeploymentHeight(dep)); softforks.pushKV(DeploymentName(dep), rv); } -static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, const std::unordered_map& signals, UniValue& softforks, const Consensus::Params& consensusParams, Consensus::DeploymentPos id) +static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, const std::unordered_map& signals, UniValue& softforks, const ChainstateManager& chainman, Consensus::DeploymentPos id) { // For BIP9 deployments. - if (!DeploymentEnabled(consensusParams, id)) return; + if (!DeploymentEnabled(chainman, id)) return; UniValue bip9(UniValue::VOBJ); - const ThresholdState thresholdState = g_versionbitscache.State(active_chain_tip, consensusParams, id); + const ThresholdState thresholdState = g_versionbitscache.State(active_chain_tip, chainman.GetConsensus(), id); switch (thresholdState) { case ThresholdState::DEFINED: bip9.pushKV("status", "defined"); break; case ThresholdState::STARTED: bip9.pushKV("status", "started"); break; @@ -1438,19 +1438,20 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, const std: } const bool has_signal = (ThresholdState::STARTED == thresholdState || ThresholdState::LOCKED_IN == thresholdState); if (has_signal) { - bip9.pushKV("bit", consensusParams.vDeployments[id].bit); + bip9.pushKV("bit", chainman.GetConsensus().vDeployments[id].bit); } - bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime); - bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout); - bip9.pushKV("ehf", consensusParams.vDeployments[id].useEHF); - if (auto it = signals.find(consensusParams.vDeployments[id].bit); it != signals.end()) { + bip9.pushKV("start_time", chainman.GetConsensus().vDeployments[id].nStartTime); + bip9.pushKV("timeout", chainman.GetConsensus().vDeployments[id].nTimeout); + bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height); + bip9.pushKV("ehf", chainman.GetConsensus().vDeployments[id].useEHF); + if (auto it = signals.find(chainman.GetConsensus().vDeployments[id].bit); it != signals.end()) { bip9.pushKV("ehf_height", it->second); } - int64_t since_height = g_versionbitscache.StateSinceHeight(active_chain_tip, consensusParams, id); + int64_t since_height = g_versionbitscache.StateSinceHeight(active_chain_tip, chainman.GetConsensus(), id); bip9.pushKV("since", since_height); if (has_signal) { UniValue statsUV(UniValue::VOBJ); - BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, consensusParams, id); + BIP9Stats statsStruct = g_versionbitscache.Statistics(active_chain_tip, chainman.GetConsensus(), id); statsUV.pushKV("period", statsStruct.period); statsUV.pushKV("elapsed", statsStruct.elapsed); statsUV.pushKV("count", statsStruct.count); @@ -1461,9 +1462,9 @@ static void SoftForkDescPushBack(const CBlockIndex* active_chain_tip, const std: bip9.pushKV("statistics", statsUV); } if (ThresholdState::LOCKED_IN == thresholdState) { - bip9.pushKV("activation_height", since_height + static_cast(consensusParams.vDeployments[id].nWindowSize)); + bip9.pushKV("activation_height", since_height + static_cast(chainman.GetConsensus().vDeployments[id].nWindowSize)); } - bip9.pushKV("min_activation_height", consensusParams.vDeployments[id].min_activation_height); + bip9.pushKV("min_activation_height", chainman.GetConsensus().vDeployments[id].min_activation_height); UniValue rv(UniValue::VOBJ); rv.pushKV("type", "bip9"); @@ -1578,7 +1579,6 @@ RPCHelpMan getblockchaininfo() } } - const Consensus::Params& consensusParams = Params().GetConsensus(); UniValue softforks(UniValue::VOBJ); for (auto deploy : { /* sorted by activation block */ Consensus::DEPLOYMENT_HEIGHTINCB, @@ -1597,12 +1597,12 @@ RPCHelpMan getblockchaininfo() Consensus::DEPLOYMENT_MN_RR, Consensus::DEPLOYMENT_WITHDRAWALS, }) { - SoftForkDescPushBack(&tip, softforks, consensusParams, deploy); + SoftForkDescPushBack(&tip, softforks, chainman, deploy); } for (auto ehf_deploy : { /* sorted by activation block */ Consensus::DEPLOYMENT_V24, Consensus::DEPLOYMENT_TESTDUMMY }) { - SoftForkDescPushBack(&tip, ehfSignals, softforks, consensusParams, ehf_deploy); + SoftForkDescPushBack(&tip, ehfSignals, softforks, chainman, ehf_deploy); } obj.pushKV("softforks", softforks); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index bf23b3b260f3..ae973491d111 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -145,7 +145,7 @@ static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& } std::shared_ptr shared_pblock = std::make_shared(block); - if (!chainman.ProcessNewBlock(chainparams, shared_pblock, true, nullptr)) { + if (!chainman.ProcessNewBlock(shared_pblock, true, nullptr)) { throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); } @@ -1041,7 +1041,7 @@ static RPCHelpMan submitblock() bool new_block; auto sc = std::make_shared(block.GetHash()); RegisterSharedValidationInterface(sc); - bool accepted = chainman.ProcessNewBlock(Params(), blockptr, /*force_processing=*/true, /*new_block=*/&new_block); + bool accepted = chainman.ProcessNewBlock(blockptr, /*force_processing=*/true, /*new_block=*/&new_block); UnregisterSharedValidationInterface(sc); if (!new_block && accepted) { return "duplicate"; @@ -1083,7 +1083,7 @@ static RPCHelpMan submitheader() } BlockValidationState state; - chainman.ProcessNewBlockHeaders({h}, state, Params()); + chainman.ProcessNewBlockHeaders({h}, state); if (state.IsValid()) return UniValue::VNULL; if (state.IsError()) { throw JSONRPCError(RPC_VERIFY_ERROR, state.ToString()); diff --git a/src/test/blockfilter_index_tests.cpp b/src/test/blockfilter_index_tests.cpp index a94bb2fe74e5..eb7c114f6a63 100644 --- a/src/test/blockfilter_index_tests.cpp +++ b/src/test/blockfilter_index_tests.cpp @@ -102,7 +102,7 @@ bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex, CBlockHeader header = block->GetBlockHeader(); BlockValidationState state; - if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, Params(), &pindex)) { + if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, &pindex)) { return false; } } @@ -174,7 +174,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) uint256 chainA_last_header = last_header; for (size_t i = 0; i < 2; i++) { const auto& block = chainA[i]; - BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr)); } for (size_t i = 0; i < 2; i++) { const auto& block = chainA[i]; @@ -192,7 +192,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) uint256 chainB_last_header = last_header; for (size_t i = 0; i < 3; i++) { const auto& block = chainB[i]; - BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr)); } for (size_t i = 0; i < 3; i++) { const auto& block = chainB[i]; @@ -223,7 +223,7 @@ BOOST_FIXTURE_TEST_CASE(blockfilter_index_initial_sync, BuildChainTestingSetup) // Reorg back to chain A. for (size_t i = 2; i < 4; i++) { const auto& block = chainA[i]; - BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(Assert(m_node.chainman)->ProcessNewBlock(block, true, nullptr)); } // Check that chain A and B blocks can be retrieved. diff --git a/src/test/evo_deterministicmns_tests.cpp b/src/test/evo_deterministicmns_tests.cpp index f741811d0e74..b21ec98fa23e 100644 --- a/src/test/evo_deterministicmns_tests.cpp +++ b/src/test/evo_deterministicmns_tests.cpp @@ -264,7 +264,7 @@ void FuncDIP3Activation(TestChainSetup& setup) // We start one block before DIP3 activation, so mining a block with a DIP3 transaction should fail auto block = std::make_shared(setup.CreateBlock(txns, coinbase_pk, chainman.ActiveChainstate())); - chainman.ProcessNewBlock(Params(), block, true, nullptr); + chainman.ProcessNewBlock(block, true, nullptr); BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight); BOOST_REQUIRE(block->GetHash() != chainman.ActiveChain().Tip()->GetBlockHash()); BOOST_REQUIRE(!dmnman.GetListAtChainTip().HasMN(tx.GetHash())); @@ -274,7 +274,7 @@ void FuncDIP3Activation(TestChainSetup& setup) BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight + 1); // Mining a block with a DIP3 transaction should succeed now block = std::make_shared(setup.CreateBlock(txns, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip()); BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight + 2); BOOST_CHECK_EQUAL(block->GetHash(), chainman.ActiveChain().Tip()->GetBlockHash()); @@ -302,7 +302,7 @@ void FuncV19Activation(TestChainSetup& setup) int nHeight = chainman.ActiveChain().Height(); auto block = std::make_shared(setup.CreateBlock({tx_reg}, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); BOOST_REQUIRE(!DeploymentActiveAfter(chainman.ActiveChain().Tip(), Params().GetConsensus(), Consensus::DEPLOYMENT_V19)); ++nHeight; BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight); @@ -320,7 +320,7 @@ void FuncV19Activation(TestChainSetup& setup) auto tx_upreg = CreateProUpRegTx(chainman.ActiveChain(), *(setup.m_node.mempool), utxos, tx_reg_hash, owner_key, operator_key_new.GetPublicKey(), owner_key.GetPubKey().GetID(), collateralScript, setup.coinbaseKey); block = std::make_shared(setup.CreateBlock({tx_upreg}, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); BOOST_REQUIRE(!DeploymentActiveAfter(chainman.ActiveChain().Tip(), Params().GetConsensus(), Consensus::DEPLOYMENT_V19)); ++nHeight; BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight); @@ -340,7 +340,7 @@ void FuncV19Activation(TestChainSetup& setup) signing_provider.AddKeyPubKey(collateral_key, collateral_key.GetPubKey()); BOOST_REQUIRE(SignSignature(signing_provider, CTransaction(tx_reg), tx_spend, 0, SIGHASH_ALL)); block = std::make_shared(setup.CreateBlock({tx_spend}, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); BOOST_REQUIRE(!DeploymentActiveAfter(chainman.ActiveChain().Tip(), Params().GetConsensus(), Consensus::DEPLOYMENT_V19)); ++nHeight; BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight); @@ -640,7 +640,7 @@ void FuncTestMempoolReorg(TestChainSetup& setup) SignTransaction(*(setup.m_node.mempool), tx_collateral, setup.coinbaseKey); auto block = std::make_shared(setup.CreateBlock({tx_collateral}, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); setup.m_node.dmnman->UpdatedBlockTip(chainman.ActiveChain().Tip()); BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight + 1); BOOST_CHECK_EQUAL(block->GetHash(), chainman.ActiveChain().Tip()->GetBlockHash()); @@ -786,7 +786,7 @@ void FuncVerifyDB(TestChainSetup& setup) SignTransaction(*(setup.m_node.mempool), tx_collateral, setup.coinbaseKey); auto block = std::make_shared(setup.CreateBlock({tx_collateral}, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip()); BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight + 1); BOOST_CHECK_EQUAL(block->GetHash(), chainman.ActiveChain().Tip()->GetBlockHash()); @@ -819,7 +819,7 @@ void FuncVerifyDB(TestChainSetup& setup) auto tx_reg_hash = tx_reg.GetHash(); block = std::make_shared(setup.CreateBlock({tx_reg}, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip()); BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight + 2); BOOST_CHECK_EQUAL(block->GetHash(), chainman.ActiveChain().Tip()->GetBlockHash()); @@ -831,7 +831,7 @@ void FuncVerifyDB(TestChainSetup& setup) auto proUpRevTx = CreateProUpRevTx(chainman.ActiveChain(), *(setup.m_node.mempool), collateral_utxos, tx_reg_hash, operatorKey, collateralKey); block = std::make_shared(setup.CreateBlock({proUpRevTx}, coinbase_pk, chainman.ActiveChainstate())); - BOOST_REQUIRE(chainman.ProcessNewBlock(Params(), block, true, nullptr)); + BOOST_REQUIRE(chainman.ProcessNewBlock(block, true, nullptr)); dmnman.UpdatedBlockTip(chainman.ActiveChain().Tip()); BOOST_CHECK_EQUAL(chainman.ActiveChain().Height(), nHeight + 3); BOOST_CHECK_EQUAL(block->GetHash(), chainman.ActiveChain().Tip()->GetBlockHash()); diff --git a/src/test/fuzz/utxo_snapshot.cpp b/src/test/fuzz/utxo_snapshot.cpp index b1025023ca81..b4a5de6371b1 100644 --- a/src/test/fuzz/utxo_snapshot.cpp +++ b/src/test/fuzz/utxo_snapshot.cpp @@ -57,7 +57,7 @@ FUZZ_TARGET(utxo_snapshot, .init = initialize_chain) if (fuzzed_data_provider.ConsumeBool()) { for (const auto& block : *g_chain) { BlockValidationState dummy; - bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy, ::Params())}; + bool processed{chainman.ProcessNewBlockHeaders({*block}, dummy)}; Assert(processed); const auto* index{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(block->GetHash()))}; Assert(index); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 057421dc3151..49d553aaee31 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -600,7 +600,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) } } std::shared_ptr shared_pblock = std::make_shared(*pblock); - BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(chainparams, shared_pblock, true, nullptr)); + BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, nullptr)); pblock->hashPrevBlock = pblock->GetHash(); }; diff --git a/src/test/util/mining.cpp b/src/test/util/mining.cpp index e98eed3f8fd9..491951c37727 100644 --- a/src/test/util/mining.cpp +++ b/src/test/util/mining.cpp @@ -70,7 +70,7 @@ CTxIn MineBlock(const NodeContext& node, const CScript& coinbase_scriptPubKey) assert(block->nNonce); } - bool processed{Assert(node.chainman)->ProcessNewBlock(Params(), block, true, nullptr)}; + bool processed{Assert(node.chainman)->ProcessNewBlock(block, true, nullptr)}; assert(processed); return CTxIn{block->vtx[0]->GetHash(), 0}; diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 821fb4a9cb48..c352458754a0 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -260,6 +260,8 @@ BasicTestingSetup::~BasicTestingSetup() ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::vector& extra_args) : BasicTestingSetup(chainName, extra_args) { + const CChainParams& chainparams = Params(); + // We have to run a scheduler thread to prevent ActivateBestChain // from blocking due to queue overrun. m_node.scheduler = std::make_unique(); @@ -271,7 +273,7 @@ ChainTestingSetup::ChainTestingSetup(const std::string& chainName, const std::ve m_cache_sizes = CalculateCacheSizes(m_args); - m_node.chainman = std::make_unique(); + m_node.chainman = std::make_unique(chainparams); m_node.chainman->m_blockman.m_block_tree_db = std::make_unique(m_cache_sizes.block_tree_db, true); m_node.mn_sync = std::make_unique(std::make_unique(*m_node.connman, *m_node.netfulfilledman)); @@ -485,11 +487,9 @@ CBlock TestChainSetup::CreateAndProcessBlock( chainstate = &Assert(m_node.chainman)->ActiveChainstate(); } - const CChainParams& chainparams = Params(); auto block = this->CreateBlock(txns, scriptPubKey, *chainstate); - std::shared_ptr shared_pblock = std::make_shared(block); - Assert(m_node.chainman)->ProcessNewBlock(chainparams, shared_pblock, true, nullptr); + Assert(m_node.chainman)->ProcessNewBlock(shared_pblock, true, nullptr); return block; } diff --git a/src/test/validation_block_tests.cpp b/src/test/validation_block_tests.cpp index 280908c8d558..84daeb098541 100644 --- a/src/test/validation_block_tests.cpp +++ b/src/test/validation_block_tests.cpp @@ -99,7 +99,7 @@ std::shared_ptr MinerTestingSetup::FinalizeBlock(std::shared_ptr // submit block header, so that miner can get the block height from the // global state and the node has the topology of the chain BlockValidationState ignored; - BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({pblock->GetBlockHeader()}, ignored, Params())); + BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlockHeaders({pblock->GetBlockHeader()}, ignored)); return pblock; } @@ -156,7 +156,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) bool ignored; // Connect the genesis block and drain any outstanding events - BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(Params(), std::make_shared(Params().GenesisBlock()), true, &ignored)); + BOOST_CHECK(Assert(m_node.chainman)->ProcessNewBlock(std::make_shared(Params().GenesisBlock()), true, &ignored)); SyncWithValidationInterfaceQueue(); // subscribe to events (this subscriber will validate event ordering) @@ -178,13 +178,13 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering) FastRandomContext insecure; for (int i = 0; i < 1000; i++) { const auto& block = blocks[insecure.randrange(blocks.size() - 1)]; - Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, &ignored); + Assert(m_node.chainman)->ProcessNewBlock(block, true, &ignored); } // to make sure that eventually we process the full chain - do it here for (const auto& block : blocks) { if (block->vtx.size() == 1) { - bool processed = Assert(m_node.chainman)->ProcessNewBlock(Params(), block, true, &ignored); + bool processed = Assert(m_node.chainman)->ProcessNewBlock(block, true, &ignored); assert(processed); } } @@ -223,7 +223,7 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg) { bool ignored; auto ProcessBlock = [&](std::shared_ptr block) -> bool { - return Assert(m_node.chainman)->ProcessNewBlock(Params(), block, /*force_processing=*/true, /*new_block=*/&ignored); + return Assert(m_node.chainman)->ProcessNewBlock(block, /*force_processing=*/true, /*new_block=*/&ignored); }; // Process all mined blocks diff --git a/src/validation.cpp b/src/validation.cpp index 7686968416c2..ff331e2dc1e4 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -317,9 +316,8 @@ int GetUTXOConfirmations(CChainState& active_chainstate, const COutPoint& outpoi static bool ContextualCheckTransaction(const CTransaction& tx, TxValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { - int nHeight = pindexPrev == nullptr ? 0 : pindexPrev->nHeight + 1; - bool fDIP0001Active_context = nHeight >= consensusParams.DIP0001Height; - bool fDIP0003Active_context = nHeight >= consensusParams.DIP0003Height; + bool fDIP0001Active_context = DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DIP0001); + bool fDIP0003Active_context = DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DIP0003); if (fDIP0003Active_context) { // check version 3 transaction types @@ -351,7 +349,7 @@ static bool ContextualCheckTransaction(const CTransaction& tx, TxValidationState } // Returns the script flags which should be checked for a given block -static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams); +static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const ChainstateManager& chainman); static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache, size_t limit, std::chrono::seconds age) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs) @@ -1004,7 +1002,6 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws) const CTransaction& tx = *ws.m_ptx; const uint256& hash = ws.m_hash; TxValidationState& state = ws.m_state; - const CChainParams& chainparams = args.m_chainparams; // Check again against the current block tip's script verification // flags to cache our script execution flags. This is, of course, @@ -1021,7 +1018,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws) // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks (using TestBlockValidity), however allowing such // transactions into the mempool can be exploited as a DoS attack. - unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(m_active_chainstate.m_chain.Tip(), chainparams.GetConsensus()); + unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)}; if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags, ws.m_precomputed_txdata, m_active_chainstate.CoinsTip())) { LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString()); @@ -1431,7 +1428,7 @@ PackageMempoolAcceptResult ProcessNewPackage(CChainState& active_chainstate, CTx assert(std::all_of(package.cbegin(), package.cend(), [](const auto& tx){return tx != nullptr;})); std::vector coins_to_uncache; - const CChainParams& chainparams = Params(); + const CChainParams& chainparams = active_chainstate.m_params; const auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); if (test_accept) { @@ -1655,7 +1652,7 @@ CChainState::CChainState(CTxMemPool* mempool, m_chain_helper(chain_helper), m_evoDb(evoDb), m_blockman(blockman), - m_params(::Params()), + m_params(chainman.GetParams()), m_chainman(chainman), m_from_snapshot_blockhash(from_snapshot_blockhash) {} @@ -1998,7 +1995,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI AssertLockHeld(cs_main); assert(m_chain_helper); - bool fDIP0003Active = pindex->nHeight >= Params().GetConsensus().DIP0003Height; + bool fDIP0003Active = DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_DIP0003); if (fDIP0003Active && !m_evoDb.VerifyBestBlock(pindex->GetBlockHash())) { // Nodes that upgraded after DIP3 activation will have to reindex to ensure evodb consistency AbortNode("Found EvoDB inconsistency, you must reindex to continue"); @@ -2219,7 +2216,7 @@ class WarningBitsConditionChecker : public AbstractThresholdConditionChecker static std::array warningcache GUARDED_BY(cs_main); -static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) +static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const ChainstateManager& chainman) { unsigned int flags = SCRIPT_VERIFY_NONE; @@ -2228,22 +2225,22 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens flags |= SCRIPT_VERIFY_P2SH; // Enforce the DERSIG (BIP66) rule - if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_DERSIG)) { + if (DeploymentActiveAt(*pindex, chainman.GetConsensus(), Consensus::DEPLOYMENT_DERSIG)) { flags |= SCRIPT_VERIFY_DERSIG; } // Enforce CHECKLOCKTIMEVERIFY (BIP65) - if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CLTV)) { + if (DeploymentActiveAt(*pindex, chainman.GetConsensus(), Consensus::DEPLOYMENT_CLTV)) { flags |= SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY; } // Enforce CHECKSEQUENCEVERIFY (BIP112) - if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_CSV)) { + if (DeploymentActiveAt(*pindex, chainman.GetConsensus(), Consensus::DEPLOYMENT_CSV)) { flags |= SCRIPT_VERIFY_CHECKSEQUENCEVERIFY; } // Enforce BIP147 NULLDUMMY - if (DeploymentActiveAt(*pindex, consensusparams, Consensus::DEPLOYMENT_BIP147)) { + if (DeploymentActiveAt(*pindex, chainman.GetConsensus(), Consensus::DEPLOYMENT_BIP147)) { flags |= SCRIPT_VERIFY_NULLDUMMY; } @@ -2317,7 +2314,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, assert(hashPrevBlock == view.GetBestBlock()); if (pindex->pprev) { - bool fDIP0003Active = pindex->nHeight >= m_params.GetConsensus().DIP0003Height; + bool fDIP0003Active = DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_DIP0003); if (fDIP0003Active && !m_evoDb.VerifyBestBlock(pindex->pprev->GetBlockHash())) { // Nodes that upgraded after DIP3 activation will have to reindex to ensure evodb consistency return AbortNode(state, "Found EvoDB inconsistency, you must reindex to continue"); @@ -2419,7 +2416,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, } // Get the script flags for this block - unsigned int flags = GetBlockScriptFlags(pindex, m_params.GetConsensus()); + unsigned int flags{GetBlockScriptFlags(pindex, m_chainman)}; int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint(BCLog::BENCHMARK, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime2 - nTime1), nTimeForks * MICRO, nTimeForks * MILLI / nBlocksTotal); @@ -2443,7 +2440,7 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state, std::vector addressUnspentIndex; std::vector spentIndex; - bool fDIP0001Active_context = pindex->nHeight >= Params().GetConsensus().DIP0001Height; + bool fDIP0001Active_context = DeploymentActiveAt(*pindex, m_params.GetConsensus(), Consensus::DEPLOYMENT_DIP0001); // MUST process special txes before updating UTXO to ensure consistency between mempool and block processing std::optional mnlist_updates_opt{std::nullopt}; @@ -4055,17 +4052,16 @@ bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensu * in ConnectBlock(). * Note that -reindex-chainstate skips the validation that happens here! */ -static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const CChainParams& params, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) +static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidationState& state, BlockManager& blockman, const ChainstateManager& chainman, const CBlockIndex* pindexPrev, int64_t nAdjustedTime) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { AssertLockHeld(::cs_main); assert(pindexPrev != nullptr); const int nHeight = pindexPrev->nHeight + 1; // Check proof of work - const Consensus::Params& consensusParams = params.GetConsensus(); - if(Params().NetworkIDString() == CBaseChainParams::MAIN && nHeight <= 68589){ + if (chainman.GetParams().NetworkIDString() == CBaseChainParams::MAIN && nHeight <= 68589){ // architecture issues with DGW v1 and v2) - unsigned int nBitsNext = GetNextWorkRequired(pindexPrev, &block, consensusParams); + unsigned int nBitsNext = GetNextWorkRequired(pindexPrev, &block, chainman.GetConsensus()); double n1 = ConvertBitsToDouble(block.nBits); double n2 = ConvertBitsToDouble(nBitsNext); @@ -4074,8 +4070,9 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "bad-diffbits"); } } else { - if (block.nBits != GetNextWorkRequired(pindexPrev, &block, consensusParams)) + if (block.nBits != GetNextWorkRequired(pindexPrev, &block, chainman.GetConsensus())) { return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, "bad-diffbits", strprintf("incorrect proof of work at %d", nHeight)); + } } // Check against checkpoints @@ -4083,7 +4080,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio // Don't accept any forks from the main chain prior to last checkpoint. // GetLastCheckpoint finds the last checkpoint in MapCheckpoints that's in our // BlockIndex(). - const CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(params.Checkpoints()); + const CBlockIndex* pcheckpoint = blockman.GetLastCheckpoint(chainman.GetParams().Checkpoints()); if (pcheckpoint && nHeight < pcheckpoint->nHeight) { LogPrintf("ERROR: %s: forked chain older than last checkpoint (height %d)\n", __func__, nHeight); return state.Invalid(BlockValidationResult::BLOCK_CHECKPOINT, "bad-fork-prior-to-checkpoint"); @@ -4099,9 +4096,9 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio return state.Invalid(BlockValidationResult::BLOCK_TIME_FUTURE, "time-too-new", strprintf("block timestamp too far in the future %d %d", block.GetBlockTime(), nAdjustedTime + 2 * 60 * 60)); // Reject blocks with outdated version - if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB)) || - (block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DERSIG)) || - (block.nVersion < 4 && DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CLTV))) { + if ((block.nVersion < 2 && DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), Consensus::DEPLOYMENT_HEIGHTINCB)) || + (block.nVersion < 3 && DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), Consensus::DEPLOYMENT_DERSIG)) || + (block.nVersion < 4 && DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), Consensus::DEPLOYMENT_CLTV))) { return state.Invalid(BlockValidationResult::BLOCK_INVALID_HEADER, strprintf("bad-version(0x%08x)", block.nVersion), strprintf("rejected nVersion=0x%08x block", block.nVersion)); } @@ -4115,7 +4112,7 @@ static bool ContextualCheckBlockHeader(const CBlockHeader& block, BlockValidatio * in ConnectBlock(). * Note that -reindex-chainstate skips the validation that happens here! */ -static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) +static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& state, const ChainstateManager& chainman, const CBlockIndex* pindexPrev) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { // TODO: validate - why do we need this cs_main ? AssertLockHeld(::cs_main); @@ -4123,7 +4120,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat // Enforce BIP113 (Median Time Past). bool enforce_locktime_median_time_past{false}; - if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_CSV)) { + if (DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), Consensus::DEPLOYMENT_CSV)) { assert(pindexPrev != nullptr); enforce_locktime_median_time_past = true; } @@ -4132,8 +4129,8 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat pindexPrev->GetMedianTimePast() : block.GetBlockTime()}; - bool fDIP0001Active_context = nHeight >= consensusParams.DIP0001Height; - bool fDIP0003Active_context = nHeight >= consensusParams.DIP0003Height; + bool fDIP0001Active_context = DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), Consensus::DEPLOYMENT_DIP0001); + bool fDIP0003Active_context = DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), Consensus::DEPLOYMENT_DIP0003); // Size limits unsigned int nMaxBlockSize = MaxBlockSize(fDIP0001Active_context); @@ -4148,7 +4145,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-txns-nonfinal", "non-final transaction"); } TxValidationState tx_state; - if (!ContextualCheckTransaction(*tx, tx_state, consensusParams, pindexPrev)) { + if (!ContextualCheckTransaction(*tx, tx_state, chainman.GetConsensus(), pindexPrev)) { // ContextCheckTransaction() does validation checks than only should // fails as consensus failures. assert(tx_state.GetResult() == TxValidationResult::TX_CONSENSUS); @@ -4165,7 +4162,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat // Enforce rule that the coinbase starts with serialized block height // After DIP3/DIP4 activation, we don't enforce the height in the input script anymore. // The CbTx special transaction payload will then contain the height, which is checked in CheckCbTx - if (DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_HEIGHTINCB) && !fDIP0003Active_context) + if (DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), Consensus::DEPLOYMENT_HEIGHTINCB) && !fDIP0003Active_context) { CScript expect = CScript() << nHeight; if (block.vtx[0]->vin[0].scriptSig.size() < expect.size() || @@ -4183,7 +4180,7 @@ static bool ContextualCheckBlock(const CBlock& block, BlockValidationState& stat return true; } -bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex) +bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValidationState& state, CBlockIndex** ppindex) { AssertLockHeld(cs_main); // Check for duplicate @@ -4191,7 +4188,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida // TODO : ENABLE BLOCK CACHE IN SPECIFIC CASES BlockMap::iterator miSelf{m_blockman.m_block_index.find(hash)}; - if (hash != chainparams.GetConsensus().hashGenesisBlock) { + if (hash != GetConsensus().hashGenesisBlock) { if (miSelf != m_blockman.m_block_index.end()) { // Block header is already known. CBlockIndex* pindex = &(miSelf->second); @@ -4208,7 +4205,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida return true; } - if (!CheckBlockHeader(block, hash, state, chainparams.GetConsensus())) { + if (!CheckBlockHeader(block, hash, state, GetConsensus())) { LogPrint(BCLog::VALIDATION, "%s: Consensus::CheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString()); return false; } @@ -4234,7 +4231,7 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida return state.Invalid(BlockValidationResult::BLOCK_CHAINLOCK, "bad-prevblk-chainlock"); } - if (!ContextualCheckBlockHeader(block, state, m_blockman, chainparams, pindexPrev, GetAdjustedTime())) { + if (!ContextualCheckBlockHeader(block, state, m_blockman, *this, pindexPrev, GetAdjustedTime())) { LogPrint(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString()); return false; } @@ -4314,14 +4311,14 @@ bool ChainstateManager::AcceptBlockHeader(const CBlockHeader& block, BlockValida } // Exposed wrapper for AcceptBlockHeader -bool ChainstateManager::ProcessNewBlockHeaders(const std::vector& headers, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex) +bool ChainstateManager::ProcessNewBlockHeaders(const std::vector& headers, BlockValidationState& state, const CBlockIndex** ppindex) { AssertLockNotHeld(cs_main); { LOCK(cs_main); for (const CBlockHeader& header : headers) { CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast - bool accepted{AcceptBlockHeader(header, state, chainparams, &pindex)}; + bool accepted{AcceptBlockHeader(header, state, &pindex)}; ActiveChainstate().CheckBlockIndex(); if (!accepted) { @@ -4335,7 +4332,7 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector& if (NotifyHeaderTip(ActiveChainstate())) { if (ActiveChainstate().IsInitialBlockDownload() && ppindex && *ppindex) { const CBlockIndex& last_accepted{**ppindex}; - const int64_t blocks_left{(GetTime() - last_accepted.GetBlockTime()) / chainparams.GetConsensus().nPowTargetSpacing}; + const int64_t blocks_left{(GetTime() - last_accepted.GetBlockTime()) / GetConsensus().nPowTargetSpacing}; const double progress{100.0 * last_accepted.nHeight / (last_accepted.nHeight + blocks_left)}; LogPrintf("Synchronizing blockheaders, height: %d (~%.2f%%)\n", last_accepted.nHeight, progress); } @@ -4356,7 +4353,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, Block CBlockIndex *pindexDummy = nullptr; CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy; - bool accepted_header{m_chainman.AcceptBlockHeader(block, state, m_params, &pindex)}; + bool accepted_header{m_chainman.AcceptBlockHeader(block, state, &pindex)}; CheckBlockIndex(); if (!accepted_header) @@ -4396,7 +4393,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, Block } if (!CheckBlock(block, state, m_params.GetConsensus()) || - !ContextualCheckBlock(block, state, m_params.GetConsensus(), pindex->pprev)) { + !ContextualCheckBlock(block, state, m_chainman, pindex->pprev)) { if (state.IsInvalid() && state.GetResult() != BlockValidationResult::BLOCK_MUTATED) { pindex->nStatus |= BLOCK_FAILED_VALID; m_blockman.m_dirty_blockindex.insert(pindex); @@ -4435,7 +4432,7 @@ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, Block return true; } -bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr& block, bool force_processing, bool* new_block) +bool ChainstateManager::ProcessNewBlock(const std::shared_ptr& block, bool force_processing, bool* new_block) { AssertLockNotHeld(cs_main); @@ -4453,7 +4450,7 @@ bool ChainstateManager::ProcessNewBlock(const CChainParams& chainparams, const s // malleability that cause CheckBlock() to fail; see e.g. CVE-2012-2459 and // https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-February/016697.html. Because CheckBlock() is // not very expensive, the anti-DoS benefits of caching failure (of a definitely-invalid block) are not substantial. - bool ret = CheckBlock(*block, state, chainparams.GetConsensus()); + bool ret = CheckBlock(*block, state, GetConsensus()); if (ret) { // Store to disk ret = ActiveChainstate().AcceptBlock(block, state, &pindex, force_processing, nullptr, new_block); @@ -4522,11 +4519,11 @@ bool TestBlockValidity(BlockValidationState& state, auto dbTx = evoDb.BeginTransaction(); // NOTE: CheckBlockHeader is called by CheckBlock - if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainparams, pindexPrev, GetAdjustedTime())) + if (!ContextualCheckBlockHeader(block, state, chainstate.m_blockman, chainstate.m_chainman, pindexPrev, GetAdjustedTime())) return error("%s: Consensus::ContextualCheckBlockHeader: %s", __func__, state.ToString()); if (!CheckBlock(block, state, chainparams.GetConsensus(), fCheckPOW, fCheckMerkleRoot)) return error("%s: Consensus::CheckBlock: %s", __func__, state.ToString()); - if (!ContextualCheckBlock(block, state, chainparams.GetConsensus(), pindexPrev)) + if (!ContextualCheckBlock(block, state, chainstate.m_chainman, pindexPrev)) return error("%s: Consensus::ContextualCheckBlock: %s", __func__, state.ToString()); if (!chainstate.ConnectBlock(block, state, &indexDummy, viewNew, true)) return false; @@ -4861,7 +4858,7 @@ bool CChainState::ReplayBlocks() pindexOld = &(m_blockman.m_block_index[hashHeads[1]]); pindexFork = LastCommonAncestor(pindexOld, pindexNew); assert(pindexFork != nullptr); - const bool fDIP0003Active = pindexOld->nHeight >= m_params.GetConsensus().DIP0003Height; + const bool fDIP0003Active = DeploymentActiveAt(*pindexOld, m_params.GetConsensus(), Consensus::DEPLOYMENT_DIP0003); if (fDIP0003Active && !m_evoDb.VerifyBestBlock(pindexOld->GetBlockHash())) { return error("ReplayBlocks(DASH): Found EvoDB inconsistency"); } @@ -5836,7 +5833,7 @@ bool ChainstateManager::PopulateAndValidateSnapshot( } int base_height = snapshot_start_block->nHeight; - auto maybe_au_data = ExpectedAssumeutxo(base_height, ::Params()); + auto maybe_au_data = ExpectedAssumeutxo(base_height, GetParams()); if (!maybe_au_data) { LogPrintf("[snapshot] assumeutxo height in snapshot metadata not recognized " /* Continued */ diff --git a/src/validation.h b/src/validation.h index 6d78bedc6207..810dfd9c8575 100644 --- a/src/validation.h +++ b/src/validation.h @@ -14,7 +14,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -57,6 +59,9 @@ struct ChainTxData; struct DisconnectedBlockTransactions; struct LockPoints; struct AssumeutxoData; +namespace Consensus { +struct Params; +} // namespace Consensus namespace node { class SnapshotMetadata; } // namespace node @@ -514,6 +519,7 @@ class CChainState node::BlockManager& m_blockman; /** Chain parameters for this chainstate */ + /* TODO: replace with m_chainman.GetParams() */ const CChainParams& m_params; //! The chainstate manager that owns this chainstate. The reference is @@ -895,6 +901,8 @@ class ChainstateManager CBlockIndex* m_best_invalid GUARDED_BY(::cs_main){nullptr}; + const CChainParams& m_chainparams; + //! Internal helper for ActivateSnapshot(). [[nodiscard]] bool PopulateAndValidateSnapshot( CChainState& snapshot_chainstate, @@ -908,11 +916,15 @@ class ChainstateManager bool AcceptBlockHeader( const CBlockHeader& block, BlockValidationState& state, - const CChainParams& chainparams, CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); friend CChainState; public: + explicit ChainstateManager(const CChainParams& chainparams) : m_chainparams{chainparams} { } + + const CChainParams& GetParams() const { return m_chainparams; } + const Consensus::Params& GetConsensus() const { return m_chainparams.GetConsensus(); } + std::thread m_load_block; //! A single BlockManager instance is shared across each constructed //! chainstate to avoid duplicating block metadata. @@ -1027,7 +1039,7 @@ class ChainstateManager * @param[out] new_block A boolean which is set to indicate if the block was first received via this call * @returns If the block was processed, independently of block validity */ - bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main); + bool ProcessNewBlock(const std::shared_ptr& block, bool force_processing, bool* new_block) LOCKS_EXCLUDED(cs_main); /** * Process incoming block headers. @@ -1037,10 +1049,9 @@ class ChainstateManager * * @param[in] block The block headers themselves * @param[out] state This may be set to an Error state if any error occurred processing them - * @param[in] chainparams The params for the chain we want to connect to * @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers */ - bool ProcessNewBlockHeaders(const std::vector& block, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main); + bool ProcessNewBlockHeaders(const std::vector& block, BlockValidationState& state, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main); /** * Try to add a transaction to the memory pool. @@ -1064,6 +1075,25 @@ class ChainstateManager ~ChainstateManager(); }; +/** Deployment* info via ChainstateManager */ +template +bool DeploymentActiveAfter(const CBlockIndex* pindexPrev, const ChainstateManager& chainman, DEP dep) +{ + return DeploymentActiveAfter(pindexPrev, chainman.GetConsensus(), dep); +} + +template +bool DeploymentActiveAt(const CBlockIndex& index, const ChainstateManager& chainman, DEP dep) +{ + return DeploymentActiveAt(index, chainman.GetConsensus(), dep); +} + +template +bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep) +{ + return DeploymentEnabled(chainman.GetConsensus(), dep); +} + /** * Return true if hash can be found in active_chain at nBlockHeight height. * Fills hashRet with found hash, if no nBlockHeight is specified - active_chain.Height() is used. From b25e4fd3445978b5d866c6729309db13d9263f18 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kwvg@users.noreply.github.com> Date: Fri, 19 Dec 2025 14:52:33 +0530 Subject: [PATCH 02/46] refactor: adapt ProTx logic to `DeploymentActive{At,After}` --- src/evo/deterministicmns.cpp | 57 +++++++++++++++---------- src/evo/deterministicmns.h | 15 +++++-- src/evo/providertx.cpp | 52 +++++++++++++--------- src/evo/providertx.h | 15 ++++--- src/evo/smldiff.cpp | 4 +- src/evo/specialtxman.cpp | 8 ++-- src/rpc/evo.cpp | 14 +++--- src/test/evo_deterministicmns_tests.cpp | 16 +++---- src/test/evo_trivialvalidation.cpp | 25 +++++------ 9 files changed, 122 insertions(+), 84 deletions(-) diff --git a/src/evo/deterministicmns.cpp b/src/evo/deterministicmns.cpp index 805c4c8f46f1..39a6a6c0206e 100644 --- a/src/evo/deterministicmns.cpp +++ b/src/evo/deterministicmns.cpp @@ -3,32 +3,35 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include + #include #include #include #include #include #include +#include +#include +#include +#include +#include #include #include #include #include #include -#include -#include #include #include