LCOV - code coverage report
Current view: top level - src/test/fuzz - block_index.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 100.0 % 75 75
Test Date: 2026-04-29 06:25:28 Functions: 100.0 % 6 6
Branches: 53.8 % 104 56

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2023-present 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 <chain.h>
       6                 :             : #include <chainparams.h>
       7                 :             : #include <node/blockstorage.h>
       8                 :             : #include <test/fuzz/FuzzedDataProvider.h>
       9                 :             : #include <test/fuzz/fuzz.h>
      10                 :             : #include <test/fuzz/util.h>
      11                 :             : #include <test/util/setup_common.h>
      12                 :             : #include <txdb.h>
      13                 :             : #include <util/byte_units.h>
      14                 :             : #include <validation.h>
      15                 :             : 
      16                 :             : using kernel::CBlockFileInfo;
      17                 :             : 
      18                 :             : namespace {
      19                 :             : 
      20                 :             : const BasicTestingSetup* g_setup;
      21                 :             : 
      22                 :             : // Hardcoded block hash and nBits to make sure the blocks we store pass the pow check.
      23                 :             : uint256 g_block_hash;
      24                 :             : 
      25                 :       16768 : bool operator==(const CBlockFileInfo& a, const CBlockFileInfo& b)
      26                 :             : {
      27                 :       33536 :     return a.nBlocks == b.nBlocks &&
      28         [ +  - ]:       16768 :         a.nSize == b.nSize &&
      29         [ +  - ]:       16768 :         a.nUndoSize == b.nUndoSize &&
      30         [ +  - ]:       16768 :         a.nHeightFirst == b.nHeightFirst &&
      31         [ +  - ]:       16768 :         a.nHeightLast == b.nHeightLast &&
      32   [ +  -  +  - ]:       33536 :         a.nTimeFirst == b.nTimeFirst &&
      33         [ -  + ]:       16768 :         a.nTimeLast == b.nTimeLast;
      34                 :             : }
      35                 :             : 
      36                 :     1369608 : CBlockHeader ConsumeBlockHeader(FuzzedDataProvider& provider)
      37                 :             : {
      38                 :     1369608 :     CBlockHeader header;
      39                 :     1369608 :     header.nVersion = provider.ConsumeIntegral<decltype(header.nVersion)>();
      40                 :     1369608 :     header.hashPrevBlock = g_block_hash;
      41                 :     1369608 :     header.hashMerkleRoot = g_block_hash;
      42                 :     1369608 :     header.nTime = provider.ConsumeIntegral<decltype(header.nTime)>();
      43                 :     1369608 :     header.nBits = Params().GenesisBlock().nBits;
      44                 :     1369608 :     header.nNonce = provider.ConsumeIntegral<decltype(header.nNonce)>();
      45                 :     1369608 :     return header;
      46                 :             : }
      47                 :             : 
      48                 :             : } // namespace
      49                 :             : 
      50                 :           1 : void init_block_index()
      51                 :             : {
      52   [ +  -  +  -  :           1 :     static const auto testing_setup = MakeNoLogFileContext<>(ChainType::MAIN);
                   +  - ]
      53                 :           1 :     g_setup = testing_setup.get();
      54                 :           1 :     g_block_hash = Params().GenesisBlock().GetHash();
      55                 :           1 : }
      56                 :             : 
      57         [ +  - ]:         925 : FUZZ_TARGET(block_index, .init = init_block_index)
      58                 :             : {
      59                 :         467 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
      60         [ +  - ]:         467 :     auto block_index = kernel::BlockTreeDB(DBParams{
      61                 :             :         .path = "", // Memory only.
      62                 :             :         .cache_bytes = 1_MiB,
      63                 :             :         .memory_only = true,
      64                 :         467 :     });
      65                 :             : 
      66                 :             :     // Generate a number of block files to be stored in the index.
      67                 :         467 :     int files_count = fuzzed_data_provider.ConsumeIntegralInRange(1, 100);
      68                 :         467 :     std::vector<std::unique_ptr<CBlockFileInfo>> files;
      69         [ +  - ]:         467 :     files.reserve(files_count);
      70                 :         467 :     std::vector<std::pair<int, const CBlockFileInfo*>> files_info;
      71         [ +  - ]:         467 :     files_info.reserve(files_count);
      72         [ +  + ]:       17267 :     for (int i = 0; i < files_count; i++) {
      73         [ +  + ]:       16828 :         if (auto file_info = ConsumeDeserializable<CBlockFileInfo>(fuzzed_data_provider)) {
      74         [ +  - ]:       33600 :             files.push_back(std::make_unique<CBlockFileInfo>(std::move(*file_info)));
      75         [ +  - ]:       16800 :             files_info.emplace_back(i, files.back().get());
      76                 :             :         } else {
      77                 :          28 :             return;
      78                 :             :         }
      79                 :             :     }
      80                 :             : 
      81                 :             :     // Generate a number of block headers to be stored in the index.
      82                 :         439 :     int blocks_count = fuzzed_data_provider.ConsumeIntegralInRange(files_count * 10, files_count * 100);
      83                 :         439 :     std::vector<std::unique_ptr<CBlockIndex>> blocks;
      84         [ +  - ]:         439 :     blocks.reserve(blocks_count);
      85                 :         439 :     std::vector<const CBlockIndex*> blocks_info;
      86         [ +  - ]:         439 :     blocks_info.reserve(blocks_count);
      87         [ +  + ]:     1370047 :     for (int i = 0; i < blocks_count; i++) {
      88         [ +  - ]:     1369608 :         CBlockHeader header{ConsumeBlockHeader(fuzzed_data_provider)};
      89         [ +  - ]:     2739216 :         blocks.push_back(std::make_unique<CBlockIndex>(std::move(header)));
      90         [ +  - ]:     1369608 :         blocks.back()->phashBlock = &g_block_hash;
      91         [ +  - ]:     1369608 :         blocks_info.push_back(blocks.back().get());
      92                 :             :     }
      93                 :             : 
      94                 :             :     // Store these files and blocks in the block index. It should not fail.
      95         [ +  - ]:         439 :     block_index.WriteBatchSync(files_info, files_count - 1, blocks_info);
      96                 :             : 
      97                 :             :     // We should be able to read every block file info we stored. Its value should correspond to
      98                 :             :     // what we stored above.
      99                 :         439 :     CBlockFileInfo info;
     100   [ +  -  +  + ]:       17207 :     for (const auto& [n, file_info]: files_info) {
     101   [ +  -  -  + ]:       16768 :         assert(block_index.ReadBlockFileInfo(n, info));
     102         [ -  + ]:       16768 :         assert(info == *file_info);
     103                 :             :     }
     104                 :             : 
     105                 :             :     // We should be able to read the last block file number. Its value should be consistent.
     106                 :         439 :     int last_block_file;
     107   [ +  -  -  + ]:         439 :     assert(block_index.ReadLastBlockFile(last_block_file));
     108         [ -  + ]:         439 :     assert(last_block_file == files_count - 1);
     109                 :             : 
     110                 :             :     // We should be able to flip and read the reindexing flag.
     111                 :         439 :     bool reindexing;
     112         [ +  - ]:         439 :     block_index.WriteReindexing(true);
     113         [ +  - ]:         439 :     block_index.ReadReindexing(reindexing);
     114         [ -  + ]:         439 :     assert(reindexing);
     115         [ +  - ]:         439 :     block_index.WriteReindexing(false);
     116         [ +  - ]:         439 :     block_index.ReadReindexing(reindexing);
     117         [ -  + ]:         439 :     assert(!reindexing);
     118                 :             : 
     119                 :             :     // We should be able to set and read the value of any random flag.
     120         [ +  - ]:         439 :     const std::string flag_name = fuzzed_data_provider.ConsumeRandomLengthString(100);
     121                 :         439 :     bool flag_value;
     122         [ +  - ]:         439 :     block_index.WriteFlag(flag_name, true);
     123         [ +  - ]:         439 :     block_index.ReadFlag(flag_name, flag_value);
     124         [ -  + ]:         439 :     assert(flag_value);
     125         [ +  - ]:         439 :     block_index.WriteFlag(flag_name, false);
     126         [ +  - ]:         439 :     block_index.ReadFlag(flag_name, flag_value);
     127         [ -  + ]:         439 :     assert(!flag_value);
     128                 :             : 
     129                 :             :     // We should be able to load everything we've previously stored. Note to assert on the
     130                 :             :     // return value we need to make sure all blocks pass the pow check.
     131   [ +  -  +  - ]:         439 :     const auto params{Params().GetConsensus()};
     132                 :        1317 :     const auto inserter = [&](const uint256&) {
     133                 :         878 :         return blocks.back().get();
     134                 :         439 :     };
     135   [ +  -  -  +  :        1756 :     WITH_LOCK(::cs_main, assert(block_index.LoadBlockIndexGuts(params, inserter, g_setup->m_interrupt)));
                   +  - ]
     136                 :         467 : }
        

Generated by: LCOV version 2.0-1