LCOV - code coverage report
Current view: top level - src/test - validation_chainstatemanager_tests.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 234 234 100.0 %
Date: 2022-04-21 14:51:19 Functions: 5 5 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 27 28 96.4 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2019-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 <node/utxo_snapshot.h>
#       8                 :            : #include <random.h>
#       9                 :            : #include <rpc/blockchain.h>
#      10                 :            : #include <sync.h>
#      11                 :            : #include <test/util/chainstate.h>
#      12                 :            : #include <test/util/setup_common.h>
#      13                 :            : #include <uint256.h>
#      14                 :            : #include <validation.h>
#      15                 :            : #include <validationinterface.h>
#      16                 :            : 
#      17                 :            : #include <tinyformat.h>
#      18                 :            : 
#      19                 :            : #include <vector>
#      20                 :            : 
#      21                 :            : #include <boost/test/unit_test.hpp>
#      22                 :            : 
#      23                 :            : using node::SnapshotMetadata;
#      24                 :            : 
#      25                 :            : BOOST_FIXTURE_TEST_SUITE(validation_chainstatemanager_tests, ChainTestingSetup)
#      26                 :            : 
#      27                 :            : //! Basic tests for ChainstateManager.
#      28                 :            : //!
#      29                 :            : //! First create a legacy (IBD) chainstate, then create a snapshot chainstate.
#      30                 :            : BOOST_AUTO_TEST_CASE(chainstatemanager)
#      31                 :          1 : {
#      32                 :          1 :     ChainstateManager& manager = *m_node.chainman;
#      33                 :          1 :     CTxMemPool& mempool = *m_node.mempool;
#      34                 :            : 
#      35                 :          1 :     std::vector<CChainState*> chainstates;
#      36                 :            : 
#      37                 :          1 :     BOOST_CHECK(!manager.SnapshotBlockhash().has_value());
#      38                 :            : 
#      39                 :            :     // Create a legacy (IBD) chainstate.
#      40                 :            :     //
#      41                 :          1 :     CChainState& c1 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(&mempool));
#      42                 :          1 :     chainstates.push_back(&c1);
#      43                 :          1 :     c1.InitCoinsDB(
#      44                 :          1 :         /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
#      45                 :          1 :     WITH_LOCK(::cs_main, c1.InitCoinsCache(1 << 23));
#      46                 :            : 
#      47                 :          1 :     BOOST_CHECK(!manager.IsSnapshotActive());
#      48                 :          1 :     BOOST_CHECK(!manager.IsSnapshotValidated());
#      49                 :          1 :     auto all = manager.GetAll();
#      50                 :          1 :     BOOST_CHECK_EQUAL_COLLECTIONS(all.begin(), all.end(), chainstates.begin(), chainstates.end());
#      51                 :            : 
#      52                 :          1 :     auto& active_chain = manager.ActiveChain();
#      53                 :          1 :     BOOST_CHECK_EQUAL(&active_chain, &c1.m_chain);
#      54                 :            : 
#      55                 :          1 :     BOOST_CHECK_EQUAL(manager.ActiveHeight(), -1);
#      56                 :            : 
#      57                 :          1 :     auto active_tip = manager.ActiveTip();
#      58                 :          1 :     auto exp_tip = c1.m_chain.Tip();
#      59                 :          1 :     BOOST_CHECK_EQUAL(active_tip, exp_tip);
#      60                 :            : 
#      61                 :          1 :     BOOST_CHECK(!manager.SnapshotBlockhash().has_value());
#      62                 :            : 
#      63                 :            :     // Create a snapshot-based chainstate.
#      64                 :            :     //
#      65                 :          1 :     const uint256 snapshot_blockhash = GetRandHash();
#      66                 :          1 :     CChainState& c2 = WITH_LOCK(::cs_main, return manager.InitializeChainstate(
#      67                 :          1 :         &mempool, snapshot_blockhash));
#      68                 :          1 :     chainstates.push_back(&c2);
#      69                 :            : 
#      70                 :          1 :     BOOST_CHECK_EQUAL(manager.SnapshotBlockhash().value(), snapshot_blockhash);
#      71                 :            : 
#      72                 :          1 :     c2.InitCoinsDB(
#      73                 :          1 :         /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
#      74                 :          1 :     WITH_LOCK(::cs_main, c2.InitCoinsCache(1 << 23));
#      75                 :            :     // Unlike c1, which doesn't have any blocks. Gets us different tip, height.
#      76                 :          1 :     c2.LoadGenesisBlock();
#      77                 :          1 :     BlockValidationState _;
#      78                 :          1 :     BOOST_CHECK(c2.ActivateBestChain(_, nullptr));
#      79                 :            : 
#      80                 :          1 :     BOOST_CHECK(manager.IsSnapshotActive());
#      81                 :          1 :     BOOST_CHECK(!manager.IsSnapshotValidated());
#      82                 :          1 :     BOOST_CHECK_EQUAL(&c2, &manager.ActiveChainstate());
#      83                 :          1 :     BOOST_CHECK(&c1 != &manager.ActiveChainstate());
#      84                 :          1 :     auto all2 = manager.GetAll();
#      85                 :          1 :     BOOST_CHECK_EQUAL_COLLECTIONS(all2.begin(), all2.end(), chainstates.begin(), chainstates.end());
#      86                 :            : 
#      87                 :          1 :     auto& active_chain2 = manager.ActiveChain();
#      88                 :          1 :     BOOST_CHECK_EQUAL(&active_chain2, &c2.m_chain);
#      89                 :            : 
#      90                 :          1 :     BOOST_CHECK_EQUAL(manager.ActiveHeight(), 0);
#      91                 :            : 
#      92                 :          1 :     auto active_tip2 = manager.ActiveTip();
#      93                 :          1 :     auto exp_tip2 = c2.m_chain.Tip();
#      94                 :          1 :     BOOST_CHECK_EQUAL(active_tip2, exp_tip2);
#      95                 :            : 
#      96                 :            :     // Ensure that these pointers actually correspond to different
#      97                 :            :     // CCoinsViewCache instances.
#      98                 :          1 :     BOOST_CHECK(exp_tip != exp_tip2);
#      99                 :            : 
#     100                 :            :     // Let scheduler events finish running to avoid accessing memory that is going to be unloaded
#     101                 :          1 :     SyncWithValidationInterfaceQueue();
#     102                 :          1 : }
#     103                 :            : 
#     104                 :            : //! Test rebalancing the caches associated with each chainstate.
#     105                 :            : BOOST_AUTO_TEST_CASE(chainstatemanager_rebalance_caches)
#     106                 :          1 : {
#     107                 :          1 :     ChainstateManager& manager = *m_node.chainman;
#     108                 :          1 :     CTxMemPool& mempool = *m_node.mempool;
#     109                 :            : 
#     110                 :          1 :     size_t max_cache = 10000;
#     111                 :          1 :     manager.m_total_coinsdb_cache = max_cache;
#     112                 :          1 :     manager.m_total_coinstip_cache = max_cache;
#     113                 :            : 
#     114                 :          1 :     std::vector<CChainState*> chainstates;
#     115                 :            : 
#     116                 :            :     // Create a legacy (IBD) chainstate.
#     117                 :            :     //
#     118                 :          1 :     CChainState& c1 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool));
#     119                 :          1 :     chainstates.push_back(&c1);
#     120                 :          1 :     c1.InitCoinsDB(
#     121                 :          1 :         /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
#     122                 :            : 
#     123                 :          1 :     {
#     124                 :          1 :         LOCK(::cs_main);
#     125                 :          1 :         c1.InitCoinsCache(1 << 23);
#     126                 :          1 :         BOOST_REQUIRE(c1.LoadGenesisBlock());
#     127                 :          1 :         c1.CoinsTip().SetBestBlock(InsecureRand256());
#     128                 :          1 :         manager.MaybeRebalanceCaches();
#     129                 :          1 :     }
#     130                 :            : 
#     131                 :          1 :     BOOST_CHECK_EQUAL(c1.m_coinstip_cache_size_bytes, max_cache);
#     132                 :          1 :     BOOST_CHECK_EQUAL(c1.m_coinsdb_cache_size_bytes, max_cache);
#     133                 :            : 
#     134                 :            :     // Create a snapshot-based chainstate.
#     135                 :            :     //
#     136                 :          1 :     CChainState& c2 = WITH_LOCK(cs_main, return manager.InitializeChainstate(&mempool, GetRandHash()));
#     137                 :          1 :     chainstates.push_back(&c2);
#     138                 :          1 :     c2.InitCoinsDB(
#     139                 :          1 :         /*cache_size_bytes=*/1 << 23, /*in_memory=*/true, /*should_wipe=*/false);
#     140                 :            : 
#     141                 :          1 :     {
#     142                 :          1 :         LOCK(::cs_main);
#     143                 :          1 :         c2.InitCoinsCache(1 << 23);
#     144                 :          1 :         BOOST_REQUIRE(c2.LoadGenesisBlock());
#     145                 :          1 :         c2.CoinsTip().SetBestBlock(InsecureRand256());
#     146                 :          1 :         manager.MaybeRebalanceCaches();
#     147                 :          1 :     }
#     148                 :            : 
#     149                 :            :     // Since both chainstates are considered to be in initial block download,
#     150                 :            :     // the snapshot chainstate should take priority.
#     151                 :          1 :     BOOST_CHECK_CLOSE(c1.m_coinstip_cache_size_bytes, max_cache * 0.05, 1);
#     152                 :          1 :     BOOST_CHECK_CLOSE(c1.m_coinsdb_cache_size_bytes, max_cache * 0.05, 1);
#     153                 :          1 :     BOOST_CHECK_CLOSE(c2.m_coinstip_cache_size_bytes, max_cache * 0.95, 1);
#     154                 :          1 :     BOOST_CHECK_CLOSE(c2.m_coinsdb_cache_size_bytes, max_cache * 0.95, 1);
#     155                 :          1 : }
#     156                 :            : 
#     157                 :            : //! Test basic snapshot activation.
#     158                 :            : BOOST_FIXTURE_TEST_CASE(chainstatemanager_activate_snapshot, TestChain100Setup)
#     159                 :          1 : {
#     160                 :          1 :     ChainstateManager& chainman = *Assert(m_node.chainman);
#     161                 :            : 
#     162                 :          1 :     size_t initial_size;
#     163                 :          1 :     size_t initial_total_coins{100};
#     164                 :            : 
#     165                 :            :     // Make some initial assertions about the contents of the chainstate.
#     166                 :          1 :     {
#     167                 :          1 :         LOCK(::cs_main);
#     168                 :          1 :         CCoinsViewCache& ibd_coinscache = chainman.ActiveChainstate().CoinsTip();
#     169                 :          1 :         initial_size = ibd_coinscache.GetCacheSize();
#     170                 :          1 :         size_t total_coins{0};
#     171                 :            : 
#     172         [ +  + ]:        100 :         for (CTransactionRef& txn : m_coinbase_txns) {
#     173                 :        100 :             COutPoint op{txn->GetHash(), 0};
#     174                 :        100 :             BOOST_CHECK(ibd_coinscache.HaveCoin(op));
#     175                 :        100 :             total_coins++;
#     176                 :        100 :         }
#     177                 :            : 
#     178                 :          1 :         BOOST_CHECK_EQUAL(total_coins, initial_total_coins);
#     179                 :          1 :         BOOST_CHECK_EQUAL(initial_size, initial_total_coins);
#     180                 :          1 :     }
#     181                 :            : 
#     182                 :            :     // Snapshot should refuse to load at this height.
#     183                 :          1 :     BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(m_node, m_path_root));
#     184                 :          1 :     BOOST_CHECK(!chainman.ActiveChainstate().m_from_snapshot_blockhash);
#     185                 :          1 :     BOOST_CHECK(!chainman.SnapshotBlockhash());
#     186                 :            : 
#     187                 :            :     // Mine 10 more blocks, putting at us height 110 where a valid assumeutxo value can
#     188                 :            :     // be found.
#     189                 :          1 :     constexpr int snapshot_height = 110;
#     190                 :          1 :     mineBlocks(10);
#     191                 :          1 :     initial_size += 10;
#     192                 :          1 :     initial_total_coins += 10;
#     193                 :            : 
#     194                 :            :     // Should not load malleated snapshots
#     195                 :          1 :     BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
#     196                 :          1 :         m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
#     197                 :            :             // A UTXO is missing but count is correct
#     198                 :          1 :             metadata.m_coins_count -= 1;
#     199                 :            : 
#     200                 :          1 :             COutPoint outpoint;
#     201                 :          1 :             Coin coin;
#     202                 :            : 
#     203                 :          1 :             auto_infile >> outpoint;
#     204                 :          1 :             auto_infile >> coin;
#     205                 :          1 :     }));
#     206                 :          1 :     BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
#     207                 :          1 :         m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
#     208                 :            :             // Coins count is larger than coins in file
#     209                 :          1 :             metadata.m_coins_count += 1;
#     210                 :          1 :     }));
#     211                 :          1 :     BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
#     212                 :          1 :         m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
#     213                 :            :             // Coins count is smaller than coins in file
#     214                 :          1 :             metadata.m_coins_count -= 1;
#     215                 :          1 :     }));
#     216                 :          1 :     BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
#     217                 :          1 :         m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
#     218                 :            :             // Wrong hash
#     219                 :          1 :             metadata.m_base_blockhash = uint256::ZERO;
#     220                 :          1 :     }));
#     221                 :          1 :     BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(
#     222                 :          1 :         m_node, m_path_root, [](CAutoFile& auto_infile, SnapshotMetadata& metadata) {
#     223                 :            :             // Wrong hash
#     224                 :          1 :             metadata.m_base_blockhash = uint256::ONE;
#     225                 :          1 :     }));
#     226                 :            : 
#     227                 :          1 :     BOOST_REQUIRE(CreateAndActivateUTXOSnapshot(m_node, m_path_root));
#     228                 :            : 
#     229                 :            :     // Ensure our active chain is the snapshot chainstate.
#     230                 :          1 :     BOOST_CHECK(!chainman.ActiveChainstate().m_from_snapshot_blockhash->IsNull());
#     231                 :          1 :     BOOST_CHECK_EQUAL(
#     232                 :          1 :         *chainman.ActiveChainstate().m_from_snapshot_blockhash,
#     233                 :          1 :         *chainman.SnapshotBlockhash());
#     234                 :            : 
#     235                 :            :     // Ensure that the genesis block was not marked assumed-valid.
#     236                 :          1 :     BOOST_CHECK(WITH_LOCK(::cs_main, return !chainman.ActiveChain().Genesis()->IsAssumedValid()));
#     237                 :            : 
#     238                 :          1 :     const AssumeutxoData& au_data = *ExpectedAssumeutxo(snapshot_height, ::Params());
#     239                 :          1 :     const CBlockIndex* tip = chainman.ActiveTip();
#     240                 :            : 
#     241                 :          1 :     BOOST_CHECK_EQUAL(tip->nChainTx, au_data.nChainTx);
#     242                 :            : 
#     243                 :            :     // To be checked against later when we try loading a subsequent snapshot.
#     244                 :          1 :     uint256 loaded_snapshot_blockhash{*chainman.SnapshotBlockhash()};
#     245                 :            : 
#     246                 :            :     // Make some assertions about the both chainstates. These checks ensure the
#     247                 :            :     // legacy chainstate hasn't changed and that the newly created chainstate
#     248                 :            :     // reflects the expected content.
#     249                 :          1 :     {
#     250                 :          1 :         LOCK(::cs_main);
#     251                 :          1 :         int chains_tested{0};
#     252                 :            : 
#     253         [ +  + ]:          2 :         for (CChainState* chainstate : chainman.GetAll()) {
#     254                 :          2 :             BOOST_TEST_MESSAGE("Checking coins in " << chainstate->ToString());
#     255                 :          2 :             CCoinsViewCache& coinscache = chainstate->CoinsTip();
#     256                 :            : 
#     257                 :            :             // Both caches will be empty initially.
#     258                 :          2 :             BOOST_CHECK_EQUAL((unsigned int)0, coinscache.GetCacheSize());
#     259                 :            : 
#     260                 :          2 :             size_t total_coins{0};
#     261                 :            : 
#     262         [ +  + ]:        220 :             for (CTransactionRef& txn : m_coinbase_txns) {
#     263                 :        220 :                 COutPoint op{txn->GetHash(), 0};
#     264                 :        220 :                 BOOST_CHECK(coinscache.HaveCoin(op));
#     265                 :        220 :                 total_coins++;
#     266                 :        220 :             }
#     267                 :            : 
#     268                 :          2 :             BOOST_CHECK_EQUAL(initial_size , coinscache.GetCacheSize());
#     269                 :          2 :             BOOST_CHECK_EQUAL(total_coins, initial_total_coins);
#     270                 :          2 :             chains_tested++;
#     271                 :          2 :         }
#     272                 :            : 
#     273                 :          1 :         BOOST_CHECK_EQUAL(chains_tested, 2);
#     274                 :          1 :     }
#     275                 :            : 
#     276                 :            :     // Mine some new blocks on top of the activated snapshot chainstate.
#     277                 :          1 :     constexpr size_t new_coins{100};
#     278                 :          1 :     mineBlocks(new_coins);  // Defined in TestChain100Setup.
#     279                 :            : 
#     280                 :          1 :     {
#     281                 :          1 :         LOCK(::cs_main);
#     282                 :          1 :         size_t coins_in_active{0};
#     283                 :          1 :         size_t coins_in_background{0};
#     284                 :          1 :         size_t coins_missing_from_background{0};
#     285                 :            : 
#     286         [ +  + ]:          2 :         for (CChainState* chainstate : chainman.GetAll()) {
#     287                 :          2 :             BOOST_TEST_MESSAGE("Checking coins in " << chainstate->ToString());
#     288                 :          2 :             CCoinsViewCache& coinscache = chainstate->CoinsTip();
#     289                 :          2 :             bool is_background = chainstate != &chainman.ActiveChainstate();
#     290                 :            : 
#     291         [ +  + ]:        420 :             for (CTransactionRef& txn : m_coinbase_txns) {
#     292                 :        420 :                 COutPoint op{txn->GetHash(), 0};
#     293         [ +  + ]:        420 :                 if (coinscache.HaveCoin(op)) {
#     294         [ +  + ]:        320 :                     (is_background ? coins_in_background : coins_in_active)++;
#     295         [ +  - ]:        320 :                 } else if (is_background) {
#     296                 :        100 :                     coins_missing_from_background++;
#     297                 :        100 :                 }
#     298                 :        420 :             }
#     299                 :          2 :         }
#     300                 :            : 
#     301                 :          1 :         BOOST_CHECK_EQUAL(coins_in_active, initial_total_coins + new_coins);
#     302                 :          1 :         BOOST_CHECK_EQUAL(coins_in_background, initial_total_coins);
#     303                 :          1 :         BOOST_CHECK_EQUAL(coins_missing_from_background, new_coins);
#     304                 :          1 :     }
#     305                 :            : 
#     306                 :            :     // Snapshot should refuse to load after one has already loaded.
#     307                 :          1 :     BOOST_REQUIRE(!CreateAndActivateUTXOSnapshot(m_node, m_path_root));
#     308                 :            : 
#     309                 :            :     // Snapshot blockhash should be unchanged.
#     310                 :          1 :     BOOST_CHECK_EQUAL(
#     311                 :          1 :         *chainman.ActiveChainstate().m_from_snapshot_blockhash,
#     312                 :          1 :         loaded_snapshot_blockhash);
#     313                 :          1 : }
#     314                 :            : 
#     315                 :            : //! Test LoadBlockIndex behavior when multiple chainstates are in use.
#     316                 :            : //!
#     317                 :            : //! - First, verfiy that setBlockIndexCandidates is as expected when using a single,
#     318                 :            : //!   fully-validating chainstate.
#     319                 :            : //!
#     320                 :            : //! - Then mark a region of the chain BLOCK_ASSUMED_VALID and introduce a second chainstate
#     321                 :            : //!   that will tolerate assumed-valid blocks. Run LoadBlockIndex() and ensure that the first
#     322                 :            : //!   chainstate only contains fully validated blocks and the other chainstate contains all blocks,
#     323                 :            : //!   even those assumed-valid.
#     324                 :            : //!
#     325                 :            : BOOST_FIXTURE_TEST_CASE(chainstatemanager_loadblockindex, TestChain100Setup)
#     326                 :          1 : {
#     327                 :          1 :     ChainstateManager& chainman = *Assert(m_node.chainman);
#     328                 :          1 :     CTxMemPool& mempool = *m_node.mempool;
#     329                 :          1 :     CChainState& cs1 = chainman.ActiveChainstate();
#     330                 :            : 
#     331                 :          1 :     int num_indexes{0};
#     332                 :          1 :     int num_assumed_valid{0};
#     333                 :          1 :     const int expected_assumed_valid{20};
#     334                 :          1 :     const int last_assumed_valid_idx{40};
#     335                 :          1 :     const int assumed_valid_start_idx = last_assumed_valid_idx - expected_assumed_valid;
#     336                 :            : 
#     337                 :          1 :     CBlockIndex* validated_tip{nullptr};
#     338                 :          1 :     CBlockIndex* assumed_tip{chainman.ActiveChain().Tip()};
#     339                 :            : 
#     340                 :          2 :     auto reload_all_block_indexes = [&]() {
#     341         [ +  + ]:          3 :         for (CChainState* cs : chainman.GetAll()) {
#     342                 :          3 :             LOCK(::cs_main);
#     343                 :          3 :             cs->UnloadBlockIndex();
#     344                 :          3 :             BOOST_CHECK(cs->setBlockIndexCandidates.empty());
#     345                 :          3 :         }
#     346                 :            : 
#     347                 :          2 :         WITH_LOCK(::cs_main, chainman.LoadBlockIndex());
#     348                 :          2 :     };
#     349                 :            : 
#     350                 :            :     // Ensure that without any assumed-valid BlockIndex entries, all entries are considered
#     351                 :            :     // tip candidates.
#     352                 :          1 :     reload_all_block_indexes();
#     353                 :          1 :     BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.size(), cs1.m_chain.Height() + 1);
#     354                 :            : 
#     355                 :            :     // Mark some region of the chain assumed-valid.
#     356         [ +  + ]:        102 :     for (int i = 0; i <= cs1.m_chain.Height(); ++i) {
#     357                 :        101 :         LOCK(::cs_main);
#     358                 :        101 :         auto index = cs1.m_chain[i];
#     359                 :            : 
#     360 [ +  + ][ +  + ]:        101 :         if (i < last_assumed_valid_idx && i >= assumed_valid_start_idx) {
#     361                 :         20 :             index->nStatus = BlockStatus::BLOCK_VALID_TREE | BlockStatus::BLOCK_ASSUMED_VALID;
#     362                 :         20 :         }
#     363                 :            : 
#     364                 :        101 :         ++num_indexes;
#     365         [ +  + ]:        101 :         if (index->IsAssumedValid()) ++num_assumed_valid;
#     366                 :            : 
#     367                 :            :         // Note the last fully-validated block as the expected validated tip.
#     368         [ +  + ]:        101 :         if (i == (assumed_valid_start_idx - 1)) {
#     369                 :          1 :             validated_tip = index;
#     370                 :          1 :             BOOST_CHECK(!index->IsAssumedValid());
#     371                 :          1 :         }
#     372                 :        101 :     }
#     373                 :            : 
#     374                 :          1 :     BOOST_CHECK_EQUAL(expected_assumed_valid, num_assumed_valid);
#     375                 :            : 
#     376                 :          1 :     CChainState& cs2 = WITH_LOCK(::cs_main,
#     377                 :          1 :         return chainman.InitializeChainstate(&mempool, GetRandHash()));
#     378                 :            : 
#     379                 :          1 :     reload_all_block_indexes();
#     380                 :            : 
#     381                 :            :     // The fully validated chain only has candidates up to the start of the assumed-valid
#     382                 :            :     // blocks.
#     383                 :          1 :     BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(validated_tip), 1);
#     384                 :          1 :     BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.count(assumed_tip), 0);
#     385                 :          1 :     BOOST_CHECK_EQUAL(cs1.setBlockIndexCandidates.size(), assumed_valid_start_idx);
#     386                 :            : 
#     387                 :            :     // The assumed-valid tolerant chain has all blocks as candidates.
#     388                 :          1 :     BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(validated_tip), 1);
#     389                 :          1 :     BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.count(assumed_tip), 1);
#     390                 :          1 :     BOOST_CHECK_EQUAL(cs2.setBlockIndexCandidates.size(), num_indexes);
#     391                 :          1 : }
#     392                 :            : 
#     393                 :            : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a