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.
251// Add txns from the mempool. Since we do not include parents, it may be an invalid block.252size_t num_txns = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, mempool_size);253size_t random_idx = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, mempool_size - 1);255LOCK(mempool.cs);256for (size_t i = random_idx; i < random_idx + num_txns; ++i) {257CTransactionRef mempool_tx = mempool.txns_randomized[i % mempool_size].second->GetSharedTx();258block->vtx.push_back(mempool_tx);259}260}262// Create and add (possibly invalid) txns that are not in the mempool.263if (fuzzed_data_provider.ConsumeBool()) {264size_t new_txns = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 10);265for (size_t i = 0; i < new_txns; ++i) {266CTransactionRef non_mempool_tx = create_tx();267block->vtx.push_back(non_mempool_tx);268}269}271CBlockIndex* pindexPrev{WITH_LOCK(::cs_main, return chainman.m_blockman.LookupBlockIndex(prev))};272chainman.GenerateCoinbaseCommitment(*block, pindexPrev);274bool mutated;275block->hashMerkleRoot = BlockMerkleRoot(*block, &mutated);276FinalizeHeader(*block, chainman);278BlockInfo block_info;279block_info.block = block;280block_info.hash = block->GetHash();281block_info.height = height;283return block_info;284};286LIMITED_WHILE (fuzzed_data_provider.ConsumeBool(), 1000) {287CSerializedNetMsg net_msg;288bool sent_net_msg = true;289bool requested_hb = false;290bool sent_sendcmpct = false;291bool valid_sendcmpct = false;293CallOneOf(294fuzzed_data_provider,295[&]() {296// Send a compact block.297std::shared_ptr<CBlock> cblock;299// Pick an existing block or create a new block.300if (fuzzed_data_provider.ConsumeBool() && info.size() != 0) {301size_t index = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, info.size() - 1);302cblock = info[index].block;303} else {304BlockInfo block_info = create_block();305cblock = block_info.block;306info.push_back(block_info);307}309uint64_t nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();310FuzzedCBlockHeaderAndShortTxIDs cmpctblock(*cblock, nonce);312if (fuzzed_data_provider.ConsumeBool()) {313CBlockHeaderAndShortTxIDs base_cmpctblock = cmpctblock;314net_msg = NetMsg::Make(NetMsgType::CMPCTBLOCK, base_cmpctblock);315return;316}318int prev_idx = 0;319size_t num_erased = 1;320size_t num_txs = cblock->vtx.size();322for (size_t i = 0; i < num_txs; ++i) {323if (i == 0) {324// Handle the coinbase specially. We either keep it prefilled or remove it.325if (fuzzed_data_provider.ConsumeBool()) continue;327// Remove the prefilled coinbase.328num_erased = 0;329uint64_t coinbase_shortid = cmpctblock.GetShortID(cblock->vtx[0]->GetWitnessHash());330cmpctblock.RemoveCoinbasePrefill();331cmpctblock.InsertCoinbaseShortTxID(coinbase_shortid);332continue;333}335if (fuzzed_data_provider.ConsumeBool()) continue;337uint16_t prefill_idx = num_erased == 0 ? i : i - prev_idx - 1;338prev_idx = i;339CTransactionRef txref = cblock->vtx[i];340PrefilledTransaction prefilledtx = {/*index=*/prefill_idx, txref};341cmpctblock.AddPrefilledTx(std::move(prefilledtx));343// Remove from shorttxids since we've prefilled. Subtract however many txs have been prefilled.344cmpctblock.EraseShortTxIDs(i - num_erased);345++num_erased;346}348assert(cmpctblock.PrefilledTxCount() + cmpctblock.ShortTxIDCount() == num_txs);350CBlockHeaderAndShortTxIDs base_cmpctblock = cmpctblock;351net_msg = NetMsg::Make(NetMsgType::CMPCTBLOCK, base_cmpctblock);352},353[&]() {354// Send a blocktxn message for an existing block (if one exists).355size_t num_blocks = info.size();356if (num_blocks == 0) {357sent_net_msg = false;358return;359}361// Fetch an existing block and randomly choose transactions to send over.362size_t index = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, num_blocks - 1);363const BlockInfo& block_info = info[index];364BlockTransactions block_txn;365block_txn.blockhash = block_info.hash;366std::shared_ptr<CBlock> cblock = block_info.block;368for (size_t i = 0; i < cblock->vtx.size(); i++) {369if (fuzzed_data_provider.ConsumeBool()) continue;371block_txn.txn.push_back(cblock->vtx[i]);372}374net_msg = NetMsg::Make(NetMsgType::BLOCKTXN, block_txn);375},376[&]() {377// Send a headers message for an existing block (if one exists).378size_t num_blocks = info.size();379if (num_blocks == 0) {380sent_net_msg = false;381return;382}384// Choose an existing block and send a HEADERS message for it.385size_t index = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(0, num_blocks - 1);386CBlock block = *info[index].block;387block.vtx.clear(); // No tx in HEADERS.388std::vector<CBlock> headers;389headers.emplace_back(block);391net_msg = NetMsg::Make(NetMsgType::HEADERS, TX_WITH_WITNESS(headers));392},393[&]() {394// Send a sendcmpct message, optionally setting hb mode.395bool hb = fuzzed_data_provider.ConsumeBool();396uint64_t version{fuzzed_data_provider.ConsumeBool() ? CMPCTBLOCKS_VERSION : fuzzed_data_provider.ConsumeIntegral<uint64_t>()};397net_msg = NetMsg::Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/hb, /*version=*/version);398requested_hb = hb;399sent_sendcmpct = true;400valid_sendcmpct = version == CMPCTBLOCKS_VERSION;401},402[&]() {403// Mine a block, but don't send it.404BlockInfo block_info = create_block();405info.push_back(block_info);406sent_net_msg = false;407},408[&]() {409// Send a transaction.410CTransactionRef tx = create_tx();411net_msg = NetMsg::Make(NetMsgType::TX, TX_WITH_WITNESS(*tx));412},413[&]() {414// Set mock time randomly or to tip's time.415if (fuzzed_data_provider.ConsumeBool()) {416node_clock.set(ConsumeTime(fuzzed_data_provider));417} else {418const NodeSeconds tip_time = WITH_LOCK(::cs_main, return chainman.ActiveChain().Tip()->Time());419node_clock.set(tip_time);420}422sent_net_msg = false;423});425if (!sent_net_msg) {426continue;427}429CNode& random_node = *PickValue(fuzzed_data_provider, peers);430connman.FlushSendBuffer(random_node);431(void)connman.ReceiveMsgFrom(random_node, std::move(net_msg));433bool more_work{true};434while (more_work) {435random_node.fPauseSend = false;437more_work = connman.ProcessMessagesOnce(random_node);438peerman->SendMessages(random_node);439}441std::vector<CNodeStats> stats;442connman.GetNodeStats(stats);444// We should have at maximum 3 HB peers.445int num_hb = 0;446for (const CNodeStats& stat : stats) {447if (stat.m_bip152_highbandwidth_to) {448// HB peers cannot be feelers or other "special" connections (besides addr-fetch).449CNode* hb_peer = peers[stat.nodeid];450if (!hb_peer->fDisconnect) num_hb += 1;451assert(hb_peer->IsInboundConn() || hb_peer->IsOutboundOrBlockRelayConn() || hb_peer->IsManualConn() || hb_peer->IsAddrFetchConn());452}453}454assert(num_hb <= 3);456if (sent_sendcmpct && !random_node.fDisconnect) {457// If the fuzzer sent SENDCMPCT with proper version, check the node's state matches what it sent.458const CNodeStats& random_node_stats = stats[random_node.GetId()];459if (valid_sendcmpct) assert(random_node_stats.m_bip152_highbandwidth_from == requested_hb);460}461}463setup->m_node.validation_signals->SyncWithValidationInterfaceQueue();464setup->m_node.validation_signals->UnregisterAllValidationInterfaces();465connman.StopNodes();467const size_t end_index_size{WITH_LOCK(chainman.GetMutex(), return chainman.BlockIndex().size())};468const uint64_t end_sequence{WITH_LOCK(mempool.cs, return mempool.GetSequence())};470if (initial_index_size != end_index_size || initial_sequence != end_sequence) {471MakeRandDeterministicDANGEROUS(uint256::ZERO);472g_mature_coinbase = ResetChainmanAndMempool(*g_setup, node_clock);473}474}
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.