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) 2022-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or https://opensource.org/license/mit.5#include <arith_uint256.h>6#include <chain.h>7#include <chainparams.h>8#include <headerssync.h>9#include <test/fuzz/fuzz.h>10#include <test/fuzz/util.h>11#include <test/util/setup_common.h>12#include <test/util/time.h>13#include <uint256.h>14#include <util/chaintype.h>15#include <util/time.h>16#include <validation.h>18#include <iterator>19#include <vector>21static void initialize_headers_sync_state_fuzz()22{23static const auto testing_setup = MakeNoLogFileContext<>(24/*chain_type=*/ChainType::MAIN);25}27void MakeHeadersContinuous(28const CBlockHeader& genesis_header,29const std::vector<CBlockHeader>& all_headers,30std::vector<CBlockHeader>& new_headers)31{32Assume(!new_headers.empty());34const CBlockHeader* prev_header{35all_headers.empty() ? &genesis_header : &all_headers.back()};37for (auto& header : new_headers) {38header.hashPrevBlock = prev_header->GetHash();40prev_header = &header;41}42}44class FuzzedHeadersSyncState : public HeadersSyncState45{46public:47FuzzedHeadersSyncState(const HeadersSyncParams& sync_params, const size_t commit_offset,48const CBlockIndex& chain_start, const arith_uint256& minimum_required_work)49: HeadersSyncState(/*id=*/0, Params().GetConsensus(), sync_params, chain_start, minimum_required_work)50{51const_cast<size_t&>(m_commit_offset) = commit_offset;52}53};55FUZZ_TARGET(headers_sync_state, .init = initialize_headers_sync_state_fuzz)56{57SeedRandomStateForTest(SeedRand::ZEROS);58FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());60CBlockHeader genesis_header{Params().GenesisBlock()};61CBlockIndex start_index(genesis_header);63FakeNodeClock clock{ConsumeTime(fuzzed_data_provider, /*min=*/start_index.GetMedianTimePast())};65const uint256 genesis_hash = genesis_header.GetHash();66start_index.phashBlock = &genesis_hash;68const HeadersSyncParams params{69.commitment_period = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, Params().HeadersSync().commitment_period * 2),70.redownload_buffer_size = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, Params().HeadersSync().redownload_buffer_size * 2),71};72arith_uint256 min_work{UintToArith256(ConsumeUInt256(fuzzed_data_provider))};73FuzzedHeadersSyncState headers_sync(74params,75/*commit_offset=*/fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, params.commitment_period - 1),76/*chain_start=*/start_index,77/*minimum_required_work=*/min_work);79// Store headers for potential redownload phase.80std::vector<CBlockHeader> all_headers;81std::vector<CBlockHeader>::const_iterator redownloaded_it;82bool presync{true};83bool requested_more{true};85while (requested_more) {86std::vector<CBlockHeader> headers;88// Consume headers from fuzzer or maybe replay headers if we got to the89// redownload phase.90if (presync || fuzzed_data_provider.ConsumeBool()) {91auto deser_headers = ConsumeDeserializable<std::vector<CBlockHeader>>(fuzzed_data_provider);92if (!deser_headers || deser_headers->empty()) return;94if (fuzzed_data_provider.ConsumeBool()) {95MakeHeadersContinuous(genesis_header, all_headers, *deser_headers);96}98headers.swap(*deser_headers);99} else if (auto num_headers_left{std::distance(redownloaded_it, all_headers.cend())}; num_headers_left > 0) {100// Consume some headers from the redownload buffer (At least one101// header is consumed).102auto begin_it{redownloaded_it};103std::advance(redownloaded_it, fuzzed_data_provider.ConsumeIntegralInRange<int>(1, num_headers_left));104headers.insert(headers.cend(), begin_it, redownloaded_it);105}107if (headers.empty()) return;108auto result = headers_sync.ProcessNextHeaders(headers, fuzzed_data_provider.ConsumeBool());109requested_more = result.request_more;111if (result.request_more) {112if (presync) {113all_headers.insert(all_headers.cend(), headers.cbegin(), headers.cend());115if (headers_sync.GetState() == HeadersSyncState::State::REDOWNLOAD) {116presync = false;117redownloaded_it = all_headers.cbegin();119// If we get to redownloading, the presynced headers need120// to have the min amount of work on them.121assert(CalculateClaimedHeadersWork(all_headers) >= min_work);122}123}125(void)headers_sync.NextHeadersRequestLocator();126}127}128}
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.