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 https://opensource.org/license/mit.5#include <blockencodings.h>6#include <consensus/merkle.h>7#include <consensus/validation.h>8#include <primitives/block.h>9#include <primitives/transaction.h>10#include <test/fuzz/FuzzedDataProvider.h>11#include <test/fuzz/fuzz.h>12#include <test/fuzz/util.h>13#include <test/fuzz/util/mempool.h>14#include <test/util/setup_common.h>15#include <test/util/time.h>16#include <test/util/txmempool.h>17#include <txmempool.h>18#include <util/check.h>19#include <util/time.h>20#include <util/translation.h>22#include <cstddef>23#include <cstdint>24#include <limits>25#include <memory>26#include <optional>27#include <set>28#include <vector>30namespace {31const TestingSetup* g_setup;32} // namespace34void initialize_pdb()35{36static const auto testing_setup = MakeNoLogFileContext<const TestingSetup>();37g_setup = testing_setup.get();38}40PartiallyDownloadedBlock::IsBlockMutatedFn FuzzedIsBlockMutated(bool result)41{42return [result](const CBlock& block, bool) {43return result;44};45}47FUZZ_TARGET(partially_downloaded_block, .init = initialize_pdb)48{49SeedRandomStateForTest(SeedRand::ZEROS);50FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};51FakeNodeClock clock{ConsumeTime(fuzzed_data_provider)};53auto block{ConsumeDeserializable<CBlock>(fuzzed_data_provider, TX_WITH_WITNESS)};54if (!block || block->vtx.size() == 0 ||55block->vtx.size() >= std::numeric_limits<uint16_t>::max()) {56return;57}59CBlockHeaderAndShortTxIDs cmpctblock{*block, fuzzed_data_provider.ConsumeIntegral<uint64_t>()};61bilingual_str error;62CTxMemPool pool{MemPoolOptionsForTest(g_setup->m_node), error};63Assert(error.empty());64PartiallyDownloadedBlock pdb{&pool};66// Set of available transactions (mempool or extra_txn)67std::set<uint16_t> available;68// The coinbase is always available69available.insert(0);71std::vector<std::pair<Wtxid, CTransactionRef>> extra_txn;72for (size_t i = 1; i < block->vtx.size(); ++i) {73auto tx{block->vtx[i]};75bool add_to_extra_txn{fuzzed_data_provider.ConsumeBool()};76bool add_to_mempool{fuzzed_data_provider.ConsumeBool()};78if (add_to_extra_txn) {79extra_txn.emplace_back(tx->GetWitnessHash(), tx);80available.insert(i);81}83if (add_to_mempool && !pool.exists(tx->GetHash())) {84LOCK2(cs_main, pool.cs);85TryAddToMempool(pool, ConsumeTxMemPoolEntry(fuzzed_data_provider, *tx));86available.insert(i);87}88}90auto init_status{pdb.InitData(cmpctblock, extra_txn)};92std::vector<CTransactionRef> missing;93// Whether we skipped a transaction that should be included in `missing`.94// FillBlock should never return READ_STATUS_OK if that is the case.95bool skipped_missing{false};96for (size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {97// If init_status == READ_STATUS_OK then a available transaction in the98// compact block (i.e. IsTxAvailable(i) == true) implies that we marked99// that transaction as available above (i.e. available.contains(i)).100// The reverse is not true, due to possible compact block short id101// collisions (i.e. available.contains(i) does not imply102// IsTxAvailable(i) == true).103if (init_status == READ_STATUS_OK) {104assert(!pdb.IsTxAvailable(i) || available.contains(i));105}107bool skip{fuzzed_data_provider.ConsumeBool()};108if (!pdb.IsTxAvailable(i) && !skip) {109missing.push_back(block->vtx[i]);110}112skipped_missing |= (!pdb.IsTxAvailable(i) && skip);113}115bool segwit_active{fuzzed_data_provider.ConsumeBool()};117// Mock IsBlockMutated118bool fail_block_mutated{fuzzed_data_provider.ConsumeBool()};119pdb.m_check_block_mutated_mock = FuzzedIsBlockMutated(fail_block_mutated);121CBlock reconstructed_block;122auto fill_status{pdb.FillBlock(reconstructed_block, missing, segwit_active)};123switch (fill_status) {124case READ_STATUS_OK:125assert(!skipped_missing);126assert(!fail_block_mutated);127assert(block->GetHash() == reconstructed_block.GetHash());128break;129case READ_STATUS_FAILED:130assert(fail_block_mutated);131break;132case READ_STATUS_INVALID:133break;134}135}
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.