diff --git a/src/config.h b/src/config.h --- a/src/config.h +++ b/src/config.h @@ -48,7 +48,6 @@ public: DummyConfig(); explicit DummyConfig(std::string net); - explicit DummyConfig(std::unique_ptr chainParamsIn); bool SetMaxBlockSize(uint64_t maxBlockSize) override { return false; } uint64_t GetMaxBlockSize() const override { return 32'000'000; } diff --git a/src/config.cpp b/src/config.cpp --- a/src/config.cpp +++ b/src/config.cpp @@ -47,6 +47,3 @@ DummyConfig::DummyConfig(std::string net) : chainParams(CreateChainParams(net)) {} - -DummyConfig::DummyConfig(std::unique_ptr chainParamsIn) - : chainParams(std::move(chainParamsIn)) {} diff --git a/src/test/checkpoints_tests.cpp b/src/test/checkpoints_tests.cpp --- a/src/test/checkpoints_tests.cpp +++ b/src/test/checkpoints_tests.cpp @@ -24,9 +24,9 @@ #include -BOOST_AUTO_TEST_SUITE(checkpoints_tests) +BOOST_FIXTURE_TEST_SUITE(checkpoints_tests, TestingSetup) -BOOST_FIXTURE_TEST_CASE(sanity, TestingSetup) { +BOOST_AUTO_TEST_CASE(sanity) { const auto params = CreateChainParams(CBaseChainParams::MAIN); const CCheckpointData &checkpoints = params->Checkpoints(); BlockHash p11111 = BlockHash::fromHex( @@ -45,40 +45,6 @@ BOOST_CHECK(Checkpoints::CheckBlock(checkpoints, 134444 + 1, p11111)); } -class ChainParamsWithCheckpoints : public CChainParams { -public: - ChainParamsWithCheckpoints(const CChainParams &chainParams, - CCheckpointData &checkpoints) - : CChainParams(chainParams) { - checkpointData = checkpoints; - } -}; - -class MainnetConfigWithTestCheckpoints : public DummyConfig { -public: - MainnetConfigWithTestCheckpoints() : DummyConfig(createChainParams()) {} - - static std::unique_ptr createChainParams() { - CCheckpointData checkpoints = { - .mapCheckpoints = { - {2, BlockHash::fromHex("000000006a625f06636b8bb6ac7b960a8d03705" - "d1ace08b1a19da3fdcc99ddbd")}, - }}; - const auto mainParams = CreateChainParams(CBaseChainParams::MAIN); - return std::make_unique(*mainParams, - checkpoints); - } -}; - -static const MainnetConfigWithTestCheckpoints g_config{}; - -struct CheckpointsTestingSetup : public TestingSetup { - CheckpointsTestingSetup() - : TestingSetup{CBaseChainParams::MAIN, /*extra_args=*/{}, - /*coins_db_in_memory=*/true, - /*block_tree_db_in_memory=*/true, g_config} {} -}; - /** * This test has 4 precomputed blocks mined ontop of the genesis block: * G ---> A ---> AA (checkpointed) @@ -88,24 +54,24 @@ * * B should be rejected for forking prior to an accepted checkpoint * * AB should be rejected for forking at an accepted checkpoint */ -BOOST_FIXTURE_TEST_CASE(ban_fork_prior_to_and_at_checkpoints, - CheckpointsTestingSetup) { - const Config &config = m_node.chainman->GetConfig(); - assert(std::addressof(config) == std::addressof(g_config)); - +BOOST_AUTO_TEST_CASE(ban_fork_prior_to_and_at_checkpoints) { + const CCheckpointData test_checkpoints = { + .mapCheckpoints = {{2, BlockHash::fromHex( + "000000006a625f06636b8bb6ac7b960a8d03705" + "d1ace08b1a19da3fdcc99ddbd")}}, + }; const CBlockIndex *pindex = nullptr; // Start with mainnet genesis block - CBlockHeader headerG = config.GetChainParams().GenesisBlock(); + CBlockHeader headerG = Assert(m_node.chainman)->GetParams().GenesisBlock(); BOOST_CHECK(headerG.GetHash() == uint256S("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f" "1b60a8ce26f")); { BlockValidationState state; - BOOST_CHECK( - Assert(m_node.chainman) - ->ProcessNewBlockHeaders({headerG}, true, state, &pindex)); + BOOST_CHECK(m_node.chainman->ProcessNewBlockHeaders( + {headerG}, true, state, &pindex, test_checkpoints)); pindex = nullptr; } @@ -169,9 +135,8 @@ // Headers A and AA should be accepted { BlockValidationState state; - BOOST_CHECK( - Assert(m_node.chainman) - ->ProcessNewBlockHeaders({headerA}, true, state, &pindex)); + BOOST_CHECK(m_node.chainman->ProcessNewBlockHeaders( + {headerA}, true, state, &pindex, test_checkpoints)); BOOST_CHECK(state.IsValid()); BOOST_CHECK(pindex != nullptr); pindex = nullptr; @@ -179,9 +144,8 @@ { BlockValidationState state; - BOOST_CHECK( - Assert(m_node.chainman) - ->ProcessNewBlockHeaders({headerAA}, true, state, &pindex)); + BOOST_CHECK(m_node.chainman->ProcessNewBlockHeaders( + {headerAA}, true, state, &pindex, test_checkpoints)); BOOST_CHECK(state.IsValid()); BOOST_CHECK(pindex != nullptr); pindex = nullptr; @@ -190,9 +154,8 @@ // Header B should be rejected { BlockValidationState state; - BOOST_CHECK( - !Assert(m_node.chainman) - ->ProcessNewBlockHeaders({headerB}, true, state, &pindex)); + BOOST_CHECK(!m_node.chainman->ProcessNewBlockHeaders( + {headerB}, true, state, &pindex, test_checkpoints)); BOOST_CHECK(state.IsInvalid()); BOOST_CHECK(state.GetRejectReason() == "bad-fork-prior-to-checkpoint"); BOOST_CHECK(pindex == nullptr); @@ -208,9 +171,8 @@ // Header AB should be rejected { BlockValidationState state; - BOOST_CHECK( - !Assert(m_node.chainman) - ->ProcessNewBlockHeaders({headerAB}, true, state, &pindex)); + BOOST_CHECK(!m_node.chainman->ProcessNewBlockHeaders( + {headerAB}, true, state, &pindex, test_checkpoints)); BOOST_CHECK(state.IsInvalid()); BOOST_CHECK(state.GetRejectReason() == "checkpoint mismatch"); BOOST_CHECK(pindex == nullptr); diff --git a/src/test/util/setup_common.h b/src/test/util/setup_common.h --- a/src/test/util/setup_common.h +++ b/src/test/util/setup_common.h @@ -121,8 +121,7 @@ explicit ChainTestingSetup( const std::string &chainName = CBaseChainParams::MAIN, - const std::vector &extra_args = {}, - const Config &config = ::GetConfig()); + const std::vector &extra_args = {}); ~ChainTestingSetup(); }; @@ -138,8 +137,7 @@ explicit TestingSetup(const std::string &chainName = CBaseChainParams::MAIN, const std::vector &extra_args = {}, const bool coins_db_in_memory = true, - const bool block_tree_db_in_memory = true, - const Config &config = ::GetConfig()); + const bool block_tree_db_in_memory = true); }; /** Identical to TestingSetup, but chain set to regtest */ diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -194,9 +194,10 @@ } ChainTestingSetup::ChainTestingSetup( - const std::string &chainName, const std::vector &extra_args, - const Config &config) + const std::string &chainName, const std::vector &extra_args) : BasicTestingSetup(chainName, extra_args) { + const Config &config = GetConfig(); + // We have to run a scheduler thread to prevent ActivateBestChain // from blocking due to queue overrun. m_node.scheduler = std::make_unique(); @@ -274,11 +275,12 @@ TestingSetup::TestingSetup(const std::string &chainName, const std::vector &extra_args, const bool coins_db_in_memory, - const bool block_tree_db_in_memory, - const Config &config) - : ChainTestingSetup(chainName, extra_args, config), + const bool block_tree_db_in_memory) + : ChainTestingSetup(chainName, extra_args), m_coins_db_in_memory(coins_db_in_memory), m_block_tree_db_in_memory(block_tree_db_in_memory) { + const Config &config = GetConfig(); + // Ideally we'd move all the RPC tests to the functional testing framework // instead of unit tests, but for now we need these here. RPCServer rpcServer; diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -1196,9 +1196,10 @@ * block index (permanent memory storage), indicating that the header is * known to be part of a sufficiently high-work chain (anti-dos check). */ - bool AcceptBlockHeader(const CBlockHeader &block, - BlockValidationState &state, CBlockIndex **ppindex, - bool min_pow_checked) + bool AcceptBlockHeader( + const CBlockHeader &block, BlockValidationState &state, + CBlockIndex **ppindex, bool min_pow_checked, + const std::optional &test_checkpoints = std::nullopt) EXCLUSIVE_LOCKS_REQUIRED(cs_main); friend Chainstate; @@ -1417,10 +1418,10 @@ * headers. * @return True if block headers were accepted as valid. */ - bool ProcessNewBlockHeaders(const std::vector &block, - bool min_pow_checked, - BlockValidationState &state, - const CBlockIndex **ppindex = nullptr) + bool ProcessNewBlockHeaders( + const std::vector &block, bool min_pow_checked, + BlockValidationState &state, const CBlockIndex **ppindex = nullptr, + const std::optional &test_checkpoints = std::nullopt) LOCKS_EXCLUDED(cs_main); /** diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3881,12 +3881,11 @@ * in ConnectBlock(). * Note that -reindex-chainstate skips the validation that happens here! */ -static bool ContextualCheckBlockHeader(const CBlockHeader &block, - BlockValidationState &state, - BlockManager &blockman, - ChainstateManager &chainman, - const CBlockIndex *pindexPrev, - NodeClock::time_point now) +static bool ContextualCheckBlockHeader( + const CBlockHeader &block, BlockValidationState &state, + BlockManager &blockman, ChainstateManager &chainman, + const CBlockIndex *pindexPrev, NodeClock::time_point now, + const std::optional &test_checkpoints = std::nullopt) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { AssertLockHeld(::cs_main); assert(pindexPrev != nullptr); @@ -3903,7 +3902,8 @@ // Check against checkpoints if (chainman.m_options.checkpoints_enabled) { - const CCheckpointData &checkpoints = params.Checkpoints(); + const CCheckpointData &checkpoints = + test_checkpoints ? test_checkpoints.value() : params.Checkpoints(); // Check that the block chain matches the known block chain up to a // checkpoint. @@ -4081,10 +4081,10 @@ * * Returns true if the block is successfully added to the block index. */ -bool ChainstateManager::AcceptBlockHeader(const CBlockHeader &block, - BlockValidationState &state, - CBlockIndex **ppindex, - bool min_pow_checked) { +bool ChainstateManager::AcceptBlockHeader( + const CBlockHeader &block, BlockValidationState &state, + CBlockIndex **ppindex, bool min_pow_checked, + const std::optional &test_checkpoints) { AssertLockHeld(cs_main); const Config &config = this->GetConfig(); const CChainParams &chainparams = config.GetChainParams(); @@ -4139,9 +4139,9 @@ "bad-prevblk"); } - if (!ContextualCheckBlockHeader(block, state, m_blockman, *this, - pindexPrev, - m_options.adjusted_time_callback())) { + if (!ContextualCheckBlockHeader( + block, state, m_blockman, *this, pindexPrev, + m_options.adjusted_time_callback(), test_checkpoints)) { LogPrint(BCLog::VALIDATION, "%s: Consensus::ContextualCheckBlockHeader: %s, %s\n", __func__, hash.ToString(), state.ToString()); @@ -4213,15 +4213,16 @@ // Exposed wrapper for AcceptBlockHeader bool ChainstateManager::ProcessNewBlockHeaders( const std::vector &headers, bool min_pow_checked, - BlockValidationState &state, const CBlockIndex **ppindex) { + BlockValidationState &state, const CBlockIndex **ppindex, + const std::optional &test_checkpoints) { AssertLockNotHeld(cs_main); { LOCK(cs_main); for (const CBlockHeader &header : headers) { // Use a temp pindex instead of ppindex to avoid a const_cast CBlockIndex *pindex = nullptr; - bool accepted = - AcceptBlockHeader(header, state, &pindex, min_pow_checked); + bool accepted = AcceptBlockHeader( + header, state, &pindex, min_pow_checked, test_checkpoints); ActiveChainstate().CheckBlockIndex(); if (!accepted) {