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 <bench/bench.h>6#include <kernel/disconnected_transactions.h>7#include <primitives/block.h>8#include <primitives/transaction.h>9#include <script/script.h>10#include <test/util/setup_common.h>11#include <util/check.h>13#include <algorithm>14#include <cstddef>15#include <cstdint>16#include <iterator>17#include <vector>19constexpr size_t BLOCK_VTX_COUNT{4000};20constexpr size_t BLOCK_VTX_COUNT_10PERCENT{400};22using BlockTxns = decltype(CBlock::vtx);24/** Reorg where 1 block is disconnected and 2 blocks are connected. */25struct ReorgTxns {26/** Disconnected block. */27BlockTxns disconnected_txns;28/** First connected block. */29BlockTxns connected_txns_1;30/** Second connected block, new chain tip. Has no overlap with disconnected_txns. */31BlockTxns connected_txns_2;32/** Transactions shared between disconnected_txns and connected_txns_1. */33size_t num_shared;34};36static BlockTxns CreateRandomTransactions(size_t num_txns)37{38// Ensure every transaction has a different txid by having each one spend the previous one.39static Txid prevout_hash{};41BlockTxns txns;42txns.reserve(num_txns);43// Simplest spk for every tx44CScript spk = CScript() << OP_TRUE;45for (uint32_t i = 0; i < num_txns; ++i) {46CMutableTransaction tx;47tx.vin.emplace_back(COutPoint{prevout_hash, 0});48tx.vout.emplace_back(CENT, spk);49auto ptx{MakeTransactionRef(tx)};50txns.emplace_back(ptx);51prevout_hash = ptx->GetHash();52}53return txns;54}56/** Creates blocks for a Reorg, each with BLOCK_VTX_COUNT transactions. Between the disconnected57* block and the first connected block, there will be num_not_shared transactions that are58* different, and all other transactions the exact same. The second connected block has all unique59* transactions. This is to simulate a reorg in which all but num_not_shared transactions are60* confirmed in the new chain. */61static ReorgTxns CreateBlocks(size_t num_not_shared)62{63auto num_shared{BLOCK_VTX_COUNT - num_not_shared};64const auto shared_txns{CreateRandomTransactions(/*num_txns=*/num_shared)};66// Create different sets of transactions...67auto disconnected_block_txns{CreateRandomTransactions(/*num_txns=*/num_not_shared)};68std::copy(shared_txns.begin(), shared_txns.end(), std::back_inserter(disconnected_block_txns));70auto connected_block_txns{CreateRandomTransactions(/*num_txns=*/num_not_shared)};71std::copy(shared_txns.begin(), shared_txns.end(), std::back_inserter(connected_block_txns));73assert(disconnected_block_txns.size() == BLOCK_VTX_COUNT);74assert(connected_block_txns.size() == BLOCK_VTX_COUNT);76return ReorgTxns{/*disconnected_txns=*/disconnected_block_txns,77/*connected_txns_1=*/connected_block_txns,78/*connected_txns_2=*/CreateRandomTransactions(BLOCK_VTX_COUNT),79/*num_shared=*/num_shared};80}82static void Reorg(const ReorgTxns& reorg)83{84DisconnectedBlockTransactions disconnectpool{MAX_DISCONNECTED_TX_POOL_BYTES};85// Disconnect block86const auto evicted = disconnectpool.AddTransactionsFromBlock(reorg.disconnected_txns);87assert(evicted.empty());89// Connect first block90disconnectpool.removeForBlock(reorg.connected_txns_1);91// Connect new tip92disconnectpool.removeForBlock(reorg.connected_txns_2);94// Sanity Check95assert(disconnectpool.size() == BLOCK_VTX_COUNT - reorg.num_shared);97disconnectpool.clear();98}100/** Add transactions from DisconnectedBlockTransactions, remove all but one (the disconnected101* block's coinbase transaction) of them, and then pop from the front until empty. This is a reorg102* in which all of the non-coinbase transactions in the disconnected chain also exist in the new103* chain. */104static void AddAndRemoveDisconnectedBlockTransactionsAll(benchmark::Bench& bench)105{106const auto chains{CreateBlocks(/*num_not_shared=*/1)};107assert(chains.num_shared == BLOCK_VTX_COUNT - 1);109bench.minEpochIterations(10).run([&]() {110Reorg(chains);111});112}114/** Add transactions from DisconnectedBlockTransactions, remove 90% of them, and then pop from the front until empty. */115static void AddAndRemoveDisconnectedBlockTransactions90(benchmark::Bench& bench)116{117const auto chains{CreateBlocks(/*num_not_shared=*/BLOCK_VTX_COUNT_10PERCENT)};118assert(chains.num_shared == BLOCK_VTX_COUNT - BLOCK_VTX_COUNT_10PERCENT);120bench.minEpochIterations(10).run([&]() {121Reorg(chains);122});123}125/** Add transactions from DisconnectedBlockTransactions, remove 10% of them, and then pop from the front until empty. */126static void AddAndRemoveDisconnectedBlockTransactions10(benchmark::Bench& bench)127{128const auto chains{CreateBlocks(/*num_not_shared=*/BLOCK_VTX_COUNT - BLOCK_VTX_COUNT_10PERCENT)};129assert(chains.num_shared == BLOCK_VTX_COUNT_10PERCENT);131bench.minEpochIterations(10).run([&]() {132Reorg(chains);133});134}136BENCHMARK(AddAndRemoveDisconnectedBlockTransactionsAll);137BENCHMARK(AddAndRemoveDisconnectedBlockTransactions90);138BENCHMARK(AddAndRemoveDisconnectedBlockTransactions10);
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.