LCOV - code coverage report
Current view: top level - src/test - validation_chainstate_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 96.5 % 57 55
Test Date: 2024-11-04 05:10:19 Functions: 100.0 % 9 9
Branches: 50.0 % 284 142

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2020-2022 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 <node/kernel_notifications.h>
       8                 :             : #include <random.h>
       9                 :             : #include <rpc/blockchain.h>
      10                 :             : #include <sync.h>
      11                 :             : #include <test/util/chainstate.h>
      12                 :             : #include <test/util/coins.h>
      13                 :             : #include <test/util/random.h>
      14                 :             : #include <test/util/setup_common.h>
      15                 :             : #include <uint256.h>
      16                 :             : #include <util/check.h>
      17                 :             : #include <validation.h>
      18                 :             : 
      19                 :             : #include <vector>
      20                 :             : 
      21                 :             : #include <boost/test/unit_test.hpp>
      22                 :             : 
      23                 :             : BOOST_FIXTURE_TEST_SUITE(validation_chainstate_tests, ChainTestingSetup)
      24                 :             : 
      25                 :             : //! Test resizing coins-related Chainstate caches during runtime.
      26                 :             : //!
      27   [ +  -  +  -  :           7 : 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   [ +  -  +  - ]:           3 :     Chainstate& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
      32         [ +  - ]:           1 :     c1.InitCoinsDB(
      33                 :             :         /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
      34         [ +  - ]:           3 :     WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
      35   [ +  -  +  - ]:           2 :     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                 :           1 :     {
      39                 :           1 :         LOCK(::cs_main);
      40   [ +  -  +  - ]:           1 :         const auto outpoint = AddTestCoin(m_rng, 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(m_rng.rand256());
      45                 :             : 
      46   [ +  -  +  -  :           2 :         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   [ +  -  +  -  :           2 :         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   [ +  -  +  -  :           2 :         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   [ +  -  +  -  :           7 : BOOST_FIXTURE_TEST_CASE(chainstate_update_tip, TestChain100Setup)
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                      - ]
      71                 :             : {
      72                 :           1 :     ChainstateManager& chainman = *Assert(m_node.chainman);
      73                 :           7 :     const auto get_notify_tip{[&]() {
      74                 :           6 :         LOCK(m_node.notifications->m_tip_block_mutex);
      75         [ +  - ]:           6 :         return m_node.notifications->m_tip_block;
      76                 :           7 :     }};
      77                 :           1 :     uint256 curr_tip = get_notify_tip();
      78                 :             : 
      79                 :             :     // Mine 10 more blocks, putting at us height 110 where a valid assumeutxo value can
      80                 :             :     // be found.
      81                 :           1 :     mineBlocks(10);
      82                 :             : 
      83                 :             :     // After adding some blocks to the tip, best block should have changed.
      84   [ +  -  +  - ]:           2 :     BOOST_CHECK(get_notify_tip() != curr_tip);
      85                 :             : 
      86                 :             :     // Grab block 1 from disk; we'll add it to the background chain later.
      87                 :           1 :     std::shared_ptr<CBlock> pblockone = std::make_shared<CBlock>();
      88                 :           1 :     {
      89         [ +  - ]:           1 :         LOCK(::cs_main);
      90   [ +  -  +  -  :           2 :         chainman.m_blockman.ReadBlockFromDisk(*pblockone, *chainman.ActiveChain()[1]);
                   +  - ]
      91                 :           0 :     }
      92                 :             : 
      93   [ +  -  +  -  :           2 :     BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(
             +  -  +  - ]
      94                 :             :         this, NoMalleation, /*reset_chainstate=*/ true));
      95                 :             : 
      96                 :             :     // Ensure our active chain is the snapshot chainstate.
      97   [ +  -  +  -  :           4 :     BOOST_CHECK(WITH_LOCK(::cs_main, return chainman.IsSnapshotActive()));
             +  -  +  - ]
      98                 :             : 
      99         [ +  - ]:           1 :     curr_tip = get_notify_tip();
     100                 :             : 
     101                 :             :     // Mine a new block on top of the activated snapshot chainstate.
     102         [ +  - ]:           1 :     mineBlocks(1);  // Defined in TestChain100Setup.
     103                 :             : 
     104                 :             :     // After adding some blocks to the snapshot tip, best block should have changed.
     105   [ +  -  +  -  :           2 :     BOOST_CHECK(get_notify_tip() != curr_tip);
             +  -  +  - ]
     106                 :             : 
     107         [ +  - ]:           1 :     curr_tip = get_notify_tip();
     108                 :             : 
     109   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(chainman.GetAll().size(), 2);
                   +  - ]
     110                 :             : 
     111   [ +  -  +  -  :           2 :     Chainstate& background_cs{*Assert([&]() -> Chainstate* {
                   +  - ]
     112                 :             :         for (Chainstate* cs : chainman.GetAll()) {
     113                 :             :             if (cs != &chainman.ActiveChainstate()) {
     114                 :             :                 return cs;
     115                 :             :             }
     116                 :             :         }
     117                 :             :         return nullptr;
     118                 :           1 :     }())};
     119                 :             : 
     120                 :             :     // Append the first block to the background chain.
     121         [ +  - ]:           1 :     BlockValidationState state;
     122                 :           1 :     CBlockIndex* pindex = nullptr;
     123         [ +  - ]:           1 :     const CChainParams& chainparams = Params();
     124                 :           1 :     bool newblock = false;
     125                 :             : 
     126                 :             :     // TODO: much of this is inlined from ProcessNewBlock(); just reuse PNB()
     127                 :             :     // once it is changed to support multiple chainstates.
     128                 :           1 :     {
     129         [ +  - ]:           1 :         LOCK(::cs_main);
     130         [ +  - ]:           1 :         bool checked = CheckBlock(*pblockone, state, chainparams.GetConsensus());
     131   [ +  -  +  -  :           2 :         BOOST_CHECK(checked);
                   +  - ]
     132   [ +  -  +  -  :           2 :         bool accepted = chainman.AcceptBlock(
                   +  - ]
     133                 :             :             pblockone, state, &pindex, true, nullptr, &newblock, true);
     134   [ +  -  +  -  :           2 :         BOOST_CHECK(accepted);
                   +  - ]
     135                 :           0 :     }
     136                 :             : 
     137                 :             :     // UpdateTip is called here
     138   [ +  -  +  -  :           2 :     bool block_added = background_cs.ActivateBestChain(state, pblockone);
                   +  - ]
     139                 :             : 
     140                 :             :     // Ensure tip is as expected
     141   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(background_cs.m_chain.Tip()->GetBlockHash(), pblockone->GetHash());
             +  -  +  - ]
     142                 :             : 
     143                 :             :     // get_notify_tip() should be unchanged after adding a block to the background
     144                 :             :     // validation chain.
     145   [ +  -  +  -  :           2 :     BOOST_CHECK(block_added);
                   +  - ]
     146   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(curr_tip, get_notify_tip());
                   +  - ]
     147         [ +  - ]:           2 : }
     148                 :             : 
     149                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1