Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2023-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.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>16using kernel::CBlockFileInfo;18namespace {20const BasicTestingSetup* g_setup;22// Hardcoded block hash and nBits to make sure the blocks we store pass the pow check.23uint256 g_block_hash;25bool operator==(const CBlockFileInfo& a, const CBlockFileInfo& b)26{27return a.nBlocks == b.nBlocks &&28a.nSize == b.nSize &&29a.nUndoSize == b.nUndoSize &&30a.nHeightFirst == b.nHeightFirst &&31a.nHeightLast == b.nHeightLast &&32a.nTimeFirst == b.nTimeFirst &&33a.nTimeLast == b.nTimeLast;34}36CBlockHeader ConsumeBlockHeader(FuzzedDataProvider& provider)37{38CBlockHeader header;39header.nVersion = provider.ConsumeIntegral<decltype(header.nVersion)>();40header.hashPrevBlock = g_block_hash;41header.hashMerkleRoot = g_block_hash;42header.nTime = provider.ConsumeIntegral<decltype(header.nTime)>();43header.nBits = Params().GenesisBlock().nBits;44header.nNonce = provider.ConsumeIntegral<decltype(header.nNonce)>();45return header;46}48} // namespace50void init_block_index()51{52static const auto testing_setup = MakeNoLogFileContext<>(ChainType::MAIN);53g_setup = testing_setup.get();54g_block_hash = Params().GenesisBlock().GetHash();55}57FUZZ_TARGET(block_index, .init = init_block_index)58{59FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};60auto block_index = kernel::BlockTreeDB(DBParams{61.path = "", // Memory only.62.cache_bytes = 1_MiB,63.memory_only = true,64});66// Generate a number of block files to be stored in the index.67int files_count = fuzzed_data_provider.ConsumeIntegralInRange(1, 100);68std::vector<std::unique_ptr<CBlockFileInfo>> files;69files.reserve(files_count);70std::vector<std::pair<int, const CBlockFileInfo*>> files_info;71files_info.reserve(files_count);72for (int i = 0; i < files_count; i++) {73if (auto file_info = ConsumeDeserializable<CBlockFileInfo>(fuzzed_data_provider)) {74files.push_back(std::make_unique<CBlockFileInfo>(std::move(*file_info)));75files_info.emplace_back(i, files.back().get());76} else {77return;78}79}81// Generate a number of block headers to be stored in the index.82int blocks_count = fuzzed_data_provider.ConsumeIntegralInRange(files_count * 10, files_count * 100);83std::vector<std::unique_ptr<CBlockIndex>> blocks;84blocks.reserve(blocks_count);85std::vector<const CBlockIndex*> blocks_info;86blocks_info.reserve(blocks_count);87for (int i = 0; i < blocks_count; i++) {88CBlockHeader header{ConsumeBlockHeader(fuzzed_data_provider)};89blocks.push_back(std::make_unique<CBlockIndex>(std::move(header)));90blocks.back()->phashBlock = &g_block_hash;91blocks_info.push_back(blocks.back().get());92}94// Store these files and blocks in the block index. It should not fail.95block_index.WriteBatchSync(files_info, files_count - 1, blocks_info);97// We should be able to read every block file info we stored. Its value should correspond to98// what we stored above.99CBlockFileInfo info;100for (const auto& [n, file_info]: files_info) {101assert(block_index.ReadBlockFileInfo(n, info));102assert(info == *file_info);103}105// We should be able to read the last block file number. Its value should be consistent.106int last_block_file;107assert(block_index.ReadLastBlockFile(last_block_file));108assert(last_block_file == files_count - 1);110// We should be able to flip and read the reindexing flag.111bool reindexing;112block_index.WriteReindexing(true);113block_index.ReadReindexing(reindexing);114assert(reindexing);115block_index.WriteReindexing(false);116block_index.ReadReindexing(reindexing);117assert(!reindexing);119// We should be able to set and read the value of any random flag.120const std::string flag_name = fuzzed_data_provider.ConsumeRandomLengthString(100);121bool flag_value;122block_index.WriteFlag(flag_name, true);123block_index.ReadFlag(flag_name, flag_value);124assert(flag_value);125block_index.WriteFlag(flag_name, false);126block_index.ReadFlag(flag_name, flag_value);127assert(!flag_value);129// We should be able to load everything we've previously stored. Note to assert on the130// return value we need to make sure all blocks pass the pow check.131const auto params{Params().GetConsensus()};132const auto inserter = [&](const uint256&) {133return blocks.back().get();134};135WITH_LOCK(::cs_main, assert(block_index.LoadBlockIndexGuts(params, inserter, g_setup->m_interrupt)));136}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.