LCOV - code coverage report
Current view: top level - src/test - coinstatsindex_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 54 54 100.0 %
Date: 2026-06-25 07:23:43 Functions: 17 17 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 <index/coinstatsindex.h>
       7             : #include <test/util/index.h>
       8             : #include <test/util/setup_common.h>
       9             : #include <test/util/validation.h>
      10             : #include <util/time.h>
      11             : #include <validation.h>
      12             : 
      13             : #include <boost/test/unit_test.hpp>
      14             : 
      15         146 : BOOST_AUTO_TEST_SUITE(coinstatsindex_tests)
      16             : 
      17         149 : BOOST_FIXTURE_TEST_CASE(coinstatsindex_initial_sync, TestChain100Setup)
      18             : {
      19           1 :     CoinStatsIndex coin_stats_index{1 << 20, true};
      20             : 
      21             :     const CBlockIndex* block_index;
      22             :     {
      23           1 :         LOCK(cs_main);
      24           1 :         block_index = m_node.chainman->ActiveChain().Tip();
      25           1 :     }
      26             : 
      27             :     // CoinStatsIndex should not be found before it is started.
      28           1 :     BOOST_CHECK(!coin_stats_index.LookUpStats(block_index));
      29             : 
      30             :     // BlockUntilSyncedToCurrentChain should return false before CoinStatsIndex
      31             :     // is started.
      32           1 :     BOOST_CHECK(!coin_stats_index.BlockUntilSyncedToCurrentChain());
      33             : 
      34           1 :     BOOST_REQUIRE(coin_stats_index.Start(m_node.chainman->ActiveChainstate()));
      35             : 
      36           1 :     IndexWaitSynced(coin_stats_index);
      37             : 
      38             :     // Check that CoinStatsIndex works for genesis block.
      39             :     const CBlockIndex* genesis_block_index;
      40             :     {
      41           1 :         LOCK(cs_main);
      42           1 :         genesis_block_index = m_node.chainman->ActiveChain().Genesis();
      43           1 :     }
      44           1 :     BOOST_CHECK(coin_stats_index.LookUpStats(genesis_block_index));
      45             : 
      46             :     // Check that CoinStatsIndex updates with new blocks.
      47           1 :     BOOST_CHECK(coin_stats_index.LookUpStats(block_index));
      48             : 
      49           1 :     const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
      50           1 :     std::vector<CMutableTransaction> noTxns;
      51           1 :     CreateAndProcessBlock(noTxns, script_pub_key);
      52             : 
      53             :     // Let the CoinStatsIndex to catch up again.
      54           1 :     BOOST_CHECK(coin_stats_index.BlockUntilSyncedToCurrentChain());
      55             : 
      56             :     const CBlockIndex* new_block_index;
      57             :     {
      58           1 :         LOCK(cs_main);
      59           1 :         new_block_index = m_node.chainman->ActiveChain().Tip();
      60           1 :     }
      61           1 :     BOOST_CHECK(coin_stats_index.LookUpStats(new_block_index));
      62             : 
      63           1 :     BOOST_CHECK(block_index != new_block_index);
      64             : 
      65             :     // It is not safe to stop and destroy the index until it finishes handling
      66             :     // the last BlockConnected notification. The BlockUntilSyncedToCurrentChain()
      67             :     // call above is sufficient to ensure this, but the
      68             :     // SyncWithValidationInterfaceQueue() call below is also needed to ensure
      69             :     // TSAN always sees the test thread waiting for the notification thread, and
      70             :     // avoid potential false positive reports.
      71           1 :     SyncWithValidationInterfaceQueue();
      72             : 
      73             :     // Shutdown sequence (c.f. Shutdown() in init.cpp)
      74           1 :     coin_stats_index.Stop();
      75           1 : }
      76             : 
      77             : // Test shutdown between BlockConnected and ChainStateFlushed notifications,
      78             : // make sure index is not corrupted and is able to reload.
      79         149 : BOOST_FIXTURE_TEST_CASE(coinstatsindex_unclean_shutdown, TestChain100Setup)
      80             : {
      81           1 :     CChainState& chainstate = Assert(m_node.chainman)->ActiveChainstate();
      82           1 :     const CChainParams& params = Params();
      83             :     {
      84           1 :         CoinStatsIndex index{1 << 20};
      85           1 :         BOOST_REQUIRE(index.Start(chainstate));
      86           1 :         IndexWaitSynced(index);
      87           1 :         std::shared_ptr<const CBlock> new_block;
      88           1 :         CBlockIndex* new_block_index = nullptr;
      89             :         {
      90           1 :             const CScript script_pub_key{CScript() << ToByteVector(coinbaseKey.GetPubKey()) << OP_CHECKSIG};
      91           1 :             const CBlock block = this->CreateBlock({}, script_pub_key, chainstate);
      92             : 
      93           1 :             new_block = std::make_shared<CBlock>(block);
      94             : 
      95           1 :             LOCK(cs_main);
      96           1 :             BlockValidationState state;
      97           1 :             BOOST_CHECK(CheckBlock(block, state, params.GetConsensus()));
      98           1 :             BOOST_CHECK(chainstate.AcceptBlock(new_block, state, &new_block_index, true, nullptr, nullptr));
      99           1 :             CCoinsViewCache view(&chainstate.CoinsTip());
     100           1 :             BOOST_CHECK(chainstate.ConnectBlock(block, state, new_block_index, view));
     101           1 :         }
     102             :         // Send block connected notification, then stop the index without
     103             :         // sending a chainstate flushed notification. Prior to #24138, this
     104             :         // would cause the index to be corrupted and fail to reload.
     105           1 :         ValidationInterfaceTest::BlockConnected(index, new_block, new_block_index);
     106           1 :         index.Stop();
     107           1 :     }
     108             : 
     109             :     {
     110           1 :         CoinStatsIndex index{1 << 20};
     111             :         // Make sure the index can be loaded.
     112           1 :         BOOST_REQUIRE(index.Start(chainstate));
     113           1 :         index.Stop();
     114           1 :     }
     115           1 : }
     116             : 
     117         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16