LCOV - code coverage report
Current view: top level - src/test - validation_chainstate_tests.cpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 55 56 98.2 %
Date: 2026-06-25 07:23:51 Functions: 21 21 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2020-2021 The Bitcoin Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : //
       5             : #include <chainparams.h>
       6             : #include <consensus/validation.h>
       7             : #include <evo/evodb.h>
       8             : #include <index/txindex.h>
       9             : #include <random.h>
      10             : #include <sync.h>
      11             : #include <rpc/blockchain.h>
      12             : #include <test/util/chainstate.h>
      13             : #include <test/util/coins.h>
      14             : #include <test/util/random.h>
      15             : #include <test/util/setup_common.h>
      16             : #include <uint256.h>
      17             : #include <validation.h>
      18             : 
      19             : #include <vector>
      20             : 
      21             : #include <boost/test/unit_test.hpp>
      22             : 
      23         146 : BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, ChainTestingSetup)
      24             : 
      25             : //! Test resizing coins-related CChainState caches during runtime.
      26             : //!
      27         149 : BOOST_AUTO_TEST_CASE(validation_chainstate_resize_caches)
      28             : {
      29           1 :     ChainstateManager& manager = *Assert(m_node.chainman);
      30           1 :     CTxMemPool& mempool = *Assert(m_node.mempool);
      31           2 :     CChainState& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool, *m_node.evodb, m_node.chain_helper));
      32           1 :     c1.InitCoinsDB(
      33             :         /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
      34           2 :     WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
      35           1 :     BOOST_REQUIRE(c1.LoadGenesisBlock()); // Need at least one block loaded to be able to flush caches
      36             : 
      37             :     // Add a coin to the in-memory cache, upsize once, then downsize.
      38             :     {
      39           1 :         LOCK(::cs_main);
      40           1 :         const auto outpoint = AddTestCoin(c1.CoinsTip());
      41             : 
      42             :         // Set a meaningless bestblock value in the coinsview cache - otherwise we won't
      43             :         // flush during ResizecoinsCaches() and will subsequently hit an assertion.
      44           1 :         c1.CoinsTip().SetBestBlock(InsecureRand256());
      45             : 
      46           1 :         BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
      47             : 
      48           1 :         c1.ResizeCoinsCaches(
      49             :             1 << 24,  // upsizing the coinsview cache
      50             :             1 << 22  // downsizing the coinsdb cache
      51             :         );
      52             : 
      53             :         // View should still have the coin cached, since we haven't destructed the cache on upsize.
      54           1 :         BOOST_CHECK(c1.CoinsTip().HaveCoinInCache(outpoint));
      55             : 
      56           1 :         c1.ResizeCoinsCaches(
      57             :             1 << 22,  // downsizing the coinsview cache
      58             :             1 << 23  // upsizing the coinsdb cache
      59             :         );
      60             : 
      61             :         // The view cache should be empty since we had to destruct to downsize.
      62           1 :         BOOST_CHECK(!c1.CoinsTip().HaveCoinInCache(outpoint));
      63           1 :     }
      64           1 : }
      65             : 
      66             : //! Test UpdateTip behavior for both active and background chainstates.
      67             : //!
      68             : //! When run on the background chainstate, UpdateTip should do a subset
      69             : //! of what it does for the active chainstate.
      70         149 : BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
      71             : {
      72           1 :     ChainstateManager& chainman = *Assert(m_node.chainman);
      73           1 :     uint256 curr_tip = ::g_best_block;
      74             : 
      75             :     // Mine 10 more blocks, putting at us height 110 where a valid assumeutxo value can
      76             :     // be found.
      77           1 :     mineBlocks(10);
      78             : 
      79             :     // After adding some blocks to the tip, best block should have changed.
      80           1 :     BOOST_CHECK(::g_best_block != curr_tip);
      81             : 
      82           1 :     BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root));
      83             : 
      84             :     // Ensure our active chain is the snapshot chainstate.
      85           2 :     BOOST_CHECK(WITH_LOCK(::cs_main, return chainman.IsSnapshotActive()));
      86             : 
      87           1 :     curr_tip = ::g_best_block;
      88             : 
      89             :     // Mine a new block on top of the activated snapshot chainstate.
      90           1 :     mineBlocks(1);  // Defined in TestChain100Setup.
      91             : 
      92             :     // After adding some blocks to the snapshot tip, best block should have changed.
      93           1 :     BOOST_CHECK(::g_best_block != curr_tip);
      94             : 
      95           1 :     curr_tip = ::g_best_block;
      96             : 
      97           1 :     BOOST_CHECK_EQUAL(chainman.GetAll().size(), 2);
      98             : 
      99           2 :     CChainState& background_cs{*[&] {
     100           2 :         for (CChainState* cs : chainman.GetAll()) {
     101           1 :             if (cs != &chainman.ActiveChainstate()) {
     102           1 :                 return cs;
     103             :             }
     104             :         }
     105           0 :         assert(false);
     106           1 :     }()};
     107             : 
     108             :     // Create a block to append to the validation chain.
     109           1 :     std::vector<CMutableTransaction> noTxns;
     110           1 :     CScript scriptPubKey = CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG;
     111           1 :     CBlock validation_block = this->CreateBlock(noTxns, scriptPubKey, background_cs);
     112           1 :     auto pblock = std::make_shared<const CBlock>(validation_block);
     113           1 :     BlockValidationState state;
     114           1 :     CBlockIndex* pindex = nullptr;
     115           1 :     const CChainParams& chainparams = Params();
     116           1 :     bool newblock = false;
     117             : 
     118             :     // TODO: much of this is inlined from ProcessNewBlock(); just reuse PNB()
     119             :     // once it is changed to support multiple chainstates.
     120             :     {
     121           1 :         LOCK(::cs_main);
     122           1 :         bool checked = CheckBlock(*pblock, state, chainparams.GetConsensus());
     123           1 :         BOOST_CHECK(checked);
     124           1 :         bool accepted = background_cs.AcceptBlock(
     125             :             pblock, state, &pindex, true, nullptr, &newblock);
     126           1 :         BOOST_CHECK(accepted);
     127           1 :     }
     128             :     // UpdateTip is called here
     129           1 :     bool block_added = background_cs.ActivateBestChain(state, pblock);
     130             : 
     131             :     // Ensure tip is as expected
     132           1 :     BOOST_CHECK_EQUAL(background_cs.m_chain.Tip()->GetBlockHash(), validation_block.GetHash());
     133             : 
     134             :     // g_best_block should be unchanged after adding a block to the background
     135             :     // validation chain.
     136           1 :     BOOST_CHECK(block_added);
     137           1 :     BOOST_CHECK_EQUAL(curr_tip, ::g_best_block);
     138           1 : }
     139             : 
     140         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16