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) 2026 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 <addrman.h>6#include <blockencodings.h>7#include <chain.h>8#include <chainparams.h>9#include <coins.h>10#include <consensus/amount.h>11#include <consensus/consensus.h>12#include <consensus/merkle.h>13#include <net.h>14#include <net_processing.h>15#include <netmessagemaker.h>16#include <node/blockstorage.h>17#include <policy/truc_policy.h>18#include <primitives/block.h>19#include <primitives/transaction.h>20#include <protocol.h>21#include <script/script.h>22#include <serialize.h>23#include <sync.h>24#include <test/fuzz/FuzzedDataProvider.h>25#include <test/fuzz/fuzz.h>26#include <test/fuzz/util.h>27#include <test/fuzz/util/net.h>28#include <test/util/net.h>29#include <test/util/random.h>30#include <test/util/script.h>31#include <test/util/setup_common.h>32#include <test/util/time.h>33#include <test/util/validation.h>34#include <txmempool.h>35#include <uint256.h>36#include <util/check.h>37#include <util/time.h>38#include <validation.h>39#include <validationinterface.h>41#include <boost/multi_index/detail/hash_index_iterator.hpp>43#include <cstddef>44#include <cstdint>45#include <functional>46#include <iterator>47#include <memory>48#include <optional>49#include <string>50#include <utility>51#include <vector>53namespace {55TestingSetup* g_setup;57//! Fee each created tx will pay.58const CAmount AMOUNT_FEE{1000};59//! Cached coinbases that each iteration can copy and use.60std::vector<std::pair<COutPoint, CAmount>> g_mature_coinbase;61//! Constant value used to create valid headers.62uint32_t g_nBits;63//! One for each block the fuzzer generates.64struct BlockInfo {65std::shared_ptr<CBlock> block;66uint256 hash;67uint32_t height;68};69//! Used to access prefilledtxn and shorttxids.70class FuzzedCBlockHeaderAndShortTxIDs : public CBlockHeaderAndShortTxIDs71{72using CBlockHeaderAndShortTxIDs::CBlockHeaderAndShortTxIDs;74public:75void AddPrefilledTx(PrefilledTransaction&& prefilledtx)76{77prefilledtxn.push_back(std::move(prefilledtx));78}80void RemoveCoinbasePrefill()81{82prefilledtxn.erase(prefilledtxn.begin());83}85void InsertCoinbaseShortTxID(uint64_t shorttxid)86{87shorttxids.insert(shorttxids.begin(), shorttxid);88}90void EraseShortTxIDs(size_t index)91{92shorttxids.erase(shorttxids.begin() + index);93}95size_t PrefilledTxCount() {96return prefilledtxn.size();97}99size_t ShortTxIDCount() {100return shorttxids.size();101}102};105} // namespace107extern void MakeRandDeterministicDANGEROUS(const uint256& seed) noexcept;109void initialize_cmpctblock()110{111FakeNodeClock init_clock{}; // Uses the existing mock time112static const auto testing_setup = MakeNoLogFileContext<TestingSetup>();113g_setup = testing_setup.get();114g_nBits = Params().GenesisBlock().nBits;115// Replace validation_signals before creating chainman and mempool so they use it.116testing_setup->m_node.validation_signals = std::make_unique<ValidationSignals>(std::make_unique<ImmediateBackgroundTaskRunner>());117g_mature_coinbase = ResetChainmanAndMempool(*g_setup, init_clock);118}120FUZZ_TARGET(cmpctblock, .init = initialize_cmpctblock)121{122SeedRandomStateForTest(SeedRand::ZEROS);123FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());125FakeNodeClock node_clock{1610000000s}; // 2021-01-07, arbitrary126FakeSteadyClock steady_clock;128auto setup = g_setup;129auto& connman = *static_cast<ConnmanTestMsg*>(setup->m_node.connman.get());130connman.Reset();131auto& mempool = *setup->m_node.mempool;132auto& chainman = static_cast<TestChainstateManager&>(*setup->m_node.chainman);133chainman.ResetIbd();134chainman.DisableNextWrite();135const size_t initial_index_size{WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())};137AddrMan addrman{*setup->m_node.netgroupman, /*deterministic=*/true, /*consistency_check_ratio=*/0};138auto peerman = PeerManager::make(connman, addrman,139/*banman=*/nullptr, chainman,140mempool, *setup->m_node.warnings,141PeerManager::Options{142.deterministic_rng = true,143});144connman.SetMsgProc(peerman.get());146setup->m_node.validation_signals->RegisterValidationInterface(peerman.get());147setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();149LOCK(NetEventsInterface::g_msgproc_mutex);151std::vector<CNode*> peers;152for (int i = 0; i < 4; ++i) {153peers.push_back(ConsumeNodeAsUniquePtr(fuzzed_data_provider, steady_clock, i).release());154CNode& p2p_node = *peers.back();155FillNode(fuzzed_data_provider, connman, p2p_node);156connman.AddTestNode(p2p_node);157}159// Stores blocks generated this iteration.160std::vector<BlockInfo> info;162// Coinbase UTXOs for this iteration.163std::vector<std::pair<COutPoint, CAmount>> mature_coinbase = g_mature_coinbase;165const uint64_t initial_sequence{WITH_LOCK(mempool.cs, return mempool.GetSequence())};167auto create_tx = [&]() -> CTransactionRef {168CMutableTransaction tx_mut;169tx_mut.version = fuzzed_data_provider.ConsumeBool() ? CTransaction::CURRENT_VERSION : TRUC_VERSION;170tx_mut.nLockTime = fuzzed_data_provider.ConsumeBool() ? 0 : fuzzed_data_provider.ConsumeIntegral<uint32_t>();172// Choose an outpoint from the mempool, created blocks, or coinbases.173CAmount amount_in;174COutPoint outpoint;175unsigned long mempool_size = mempool.size();176if (mempool_size != 0 && fuzzed_data_provider.ConsumeBool()) {177size_t random_idx = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, mempool_size - 1);178CTransactionRef tx = WITH_LOCK(mempool.cs, return mempool.txns_randomized[random_idx].second->GetSharedTx(););179outpoint = COutPoint(tx->GetHash(), 0);180amount_in = tx->vout[0].nValue;181} else if (info.size() != 0 && fuzzed_data_provider.ConsumeBool()) {182// These blocks (and txs) may be invalid, use a spent output, or not be in the main chain.183auto info_it = info.begin();184std::advance(info_it, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, info.size() - 1));185auto tx_it = info_it->block->vtx.begin();186std::advance(tx_it, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, info_it->block->vtx.size() - 1));187outpoint = COutPoint(tx_it->get()->GetHash(), 0);188amount_in = tx_it->get()->vout[0].nValue;189} else {190auto coinbase_it = mature_coinbase.begin();191std::advance(coinbase_it, fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, mature_coinbase.size() - 1));192outpoint = coinbase_it->first;193amount_in = coinbase_it->second;194}196const auto sequence = ConsumeSequence(fuzzed_data_provider);197const auto script_sig = CScript{};198const auto script_wit_stack = std::vector<std::vector<uint8_t>>{WITNESS_STACK_ELEM_OP_TRUE};200CTxIn in;201in.prevout = outpoint;202in.nSequence = sequence;203in.scriptSig = script_sig;204in.scriptWitness.stack = script_wit_stack;205tx_mut.vin.push_back(in);207const CAmount amount_out = amount_in - AMOUNT_FEE;208tx_mut.vout.emplace_back(amount_out, P2WSH_OP_TRUE);210auto tx = MakeTransactionRef(tx_mut);211return tx;212};214auto create_block = [&]() {215uint256 prev;216uint32_t height;218if (info.size() == 0 || fuzzed_data_provider.ConsumeBool()) {219LOCK(cs_main);220prev = chainman.ActiveChain().Tip()->GetBlockHash();221height = chainman.ActiveChain().Height() + 1;222} else {223size_t index = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, info.size() - 1);224prev = info[index].hash;225height = info[index].height + 1;226}228const auto new_time = WITH_LOCK(::cs_main, return chainman.ActiveChain().Tip()->GetMedianTimePast() + 1);230CBlockHeader header;231header.nNonce = 0;232header.hashPrevBlock = prev;233header.nBits = g_nBits;234header.nTime = new_time;235header.nVersion = fuzzed_data_provider.ConsumeIntegral<int32_t>();237std::shared_ptr<CBlock> block = std::make_shared<CBlock>();238*block = header;240CMutableTransaction coinbase_tx;241coinbase_tx.vin.resize(1);242coinbase_tx.vin[0].prevout.SetNull();243coinbase_tx.vin[0].scriptSig = CScript() << height << OP_0;244coinbase_tx.vout.resize(1);245coinbase_tx.vout[0].scriptPubKey = CScript() << OP_TRUE;246coinbase_tx.vout[0].nValue = COIN;247block->vtx.push_back(MakeTransactionRef(coinbase_tx));249const auto mempool_size = mempool.size();250if (fuzzed_data_provider.ConsumeBool() && mempool_size != 0) {
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.