LCOV - code coverage report
Current view: top level - src/test/fuzz - block_index.cpp (source / functions) Coverage Total Hit
Test: fuzz_coverage.info Lines: 87.2 % 47 41
Test Date: 2024-09-01 05:20:30 Functions: 85.7 % 7 6
Branches: 54.5 % 66 36

             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                 :       10633 : bool operator==(const CBlockFileInfo& a, const CBlockFileInfo& b)
      23                 :             : {
      24         [ +  - ]:       21266 :     return a.nBlocks == b.nBlocks &&
      25         [ +  - ]:       10633 :         a.nSize == b.nSize &&
      26         [ +  - ]:       10633 :         a.nUndoSize == b.nUndoSize &&
      27         [ +  - ]:       10633 :         a.nHeightFirst == b.nHeightFirst &&
      28         [ +  - ]:       10633 :         a.nHeightLast == b.nHeightLast &&
      29         [ -  + ]:       10633 :         a.nTimeFirst == b.nTimeFirst &&
      30                 :       10633 :         a.nTimeLast == b.nTimeLast;
      31                 :             : }
      32                 :             : 
      33                 :      787924 : CBlockHeader ConsumeBlockHeader(FuzzedDataProvider& provider)
      34                 :             : {
      35                 :      787924 :     CBlockHeader header;
      36                 :      787924 :     header.nVersion = provider.ConsumeIntegral<decltype(header.nVersion)>();
      37                 :      787924 :     header.hashPrevBlock = g_block_hash;
      38                 :      787924 :     header.hashMerkleRoot = g_block_hash;
      39                 :      787924 :     header.nTime = provider.ConsumeIntegral<decltype(header.nTime)>();
      40                 :      787924 :     header.nBits = Params().GenesisBlock().nBits;
      41                 :      787924 :     header.nNonce = provider.ConsumeIntegral<decltype(header.nNonce)>();
      42                 :      787924 :     return header;
      43                 :             : }
      44                 :             : 
      45                 :             : } // namespace
      46                 :             : 
      47                 :           0 : void init_block_index()
      48                 :             : {
      49   [ #  #  #  #  :           0 :     static const auto testing_setup = MakeNoLogFileContext<>(ChainType::MAIN);
                   #  # ]
      50                 :           0 :     g_setup = testing_setup.get();
      51                 :           0 :     g_block_hash = Params().GenesisBlock().GetHash();
      52                 :           0 : }
      53                 :             : 
      54         [ +  - ]:         578 : FUZZ_TARGET(block_index, .init = init_block_index)
      55                 :             : {
      56                 :         576 :     FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
      57   [ +  -  +  -  :        1728 :     auto block_index = kernel::BlockTreeDB(DBParams{
             +  -  +  - ]
      58                 :         576 :         .path = "", // Memory only.
      59                 :             :         .cache_bytes = 1 << 20, // 1MB.
      60                 :             :         .memory_only = true,
      61                 :             :     });
      62                 :             : 
      63                 :             :     // Generate a number of block files to be stored in the index.
      64                 :             :     int files_count = fuzzed_data_provider.ConsumeIntegralInRange(1, 100);
      65                 :             :     std::vector<std::unique_ptr<CBlockFileInfo>> files;
      66                 :             :     files.reserve(files_count);
      67                 :             :     std::vector<std::pair<int, const CBlockFileInfo*>> files_info;
      68                 :             :     files_info.reserve(files_count);
      69   [ +  +  +  + ]:       11662 :     for (int i = 0; i < files_count; i++) {
      70   [ +  +  +  + ]:       22172 :         if (auto file_info = ConsumeDeserializable<CBlockFileInfo>(fuzzed_data_provider)) {
      71   [ -  +  +  - ]:       10996 :             files.push_back(std::make_unique<CBlockFileInfo>(std::move(*file_info)));
      72         [ -  + ]:       10996 :             files_info.emplace_back(i, files.back().get());
      73                 :       10996 :         } else {
      74                 :          90 :             return;
      75                 :             :         }
      76                 :       10996 :     }
      77                 :             : 
      78                 :             :     // Generate a number of block headers to be stored in the index.
      79                 :             :     int blocks_count = fuzzed_data_provider.ConsumeIntegralInRange(files_count * 10, files_count * 100);
      80                 :             :     std::vector<std::unique_ptr<CBlockIndex>> blocks;
      81                 :             :     blocks.reserve(blocks_count);
      82                 :             :     std::vector<const CBlockIndex*> blocks_info;
      83                 :             :     blocks_info.reserve(blocks_count);
      84         [ +  + ]:      788410 :     for (int i = 0; i < blocks_count; i++) {
      85         [ -  + ]:      787924 :         CBlockHeader header{ConsumeBlockHeader(fuzzed_data_provider)};
      86   [ -  +  -  + ]:      787924 :         blocks.push_back(std::make_unique<CBlockIndex>(std::move(header)));
      87                 :      787924 :         blocks.back()->phashBlock = &g_block_hash;
      88         [ +  - ]:      787924 :         blocks_info.push_back(blocks.back().get());
      89                 :      787924 :     }
      90                 :             : 
      91                 :             :     // Store these files and blocks in the block index. It should not fail.
      92                 :             :     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                 :             :     CBlockFileInfo info;
      97         [ +  + ]:       21752 :     for (const auto& [n, file_info]: files_info) {
      98   [ +  -  -  + ]:       10633 :         assert(block_index.ReadBlockFileInfo(n, info));
      99   [ +  -  -  + ]:       10633 :         assert(info == *file_info);
     100                 :       10633 :     }
     101                 :             : 
     102                 :             :     // We should be able to read the last block file number. Its value should be consistent.
     103                 :             :     int last_block_file;
     104                 :             :     assert(block_index.ReadLastBlockFile(last_block_file));
     105                 :             :     assert(last_block_file == files_count - 1);
     106                 :             : 
     107                 :             :     // We should be able to flip and read the reindexing flag.
     108                 :             :     bool reindexing;
     109                 :             :     block_index.WriteReindexing(true);
     110                 :             :     block_index.ReadReindexing(reindexing);
     111                 :             :     assert(reindexing);
     112                 :             :     block_index.WriteReindexing(false);
     113                 :             :     block_index.ReadReindexing(reindexing);
     114                 :             :     assert(!reindexing);
     115                 :             : 
     116                 :             :     // We should be able to set and read the value of any random flag.
     117                 :             :     const std::string flag_name = fuzzed_data_provider.ConsumeRandomLengthString(100);
     118                 :             :     bool flag_value;
     119                 :             :     block_index.WriteFlag(flag_name, true);
     120                 :             :     block_index.ReadFlag(flag_name, flag_value);
     121                 :             :     assert(flag_value);
     122                 :             :     block_index.WriteFlag(flag_name, false);
     123                 :             :     block_index.ReadFlag(flag_name, flag_value);
     124                 :             :     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                 :             :     const auto params{Params().GetConsensus()};
     129                 :         972 :     const auto inserter = [&](const uint256&) {
     130                 :         972 :         return blocks.back().get();
     131                 :             :     };
     132   [ +  -  +  - ]:         486 :     WITH_LOCK(::cs_main, assert(block_index.LoadBlockIndexGuts(params, inserter, g_setup->m_interrupt)));
     133                 :           0 : }
        

Generated by: LCOV version 2.0-1