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 % 74 74
Test Date: 2024-12-04 04:00:22 Functions: 100.0 % 6 6
Branches: 53.9 % 102 55

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

Generated by: LCOV version 2.0-1