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) 2011-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 <addresstype.h>6#include <chain.h>7#include <coins.h>8#include <consensus/amount.h>9#include <consensus/consensus.h>10#include <consensus/merkle.h>11#include <consensus/tx_verify.h>12#include <interfaces/mining.h>13#include <interfaces/types.h>14#include <kernel/chainparams.h>15#include <node/miner.h>16#include <node/mining_args.h>17#include <node/mining_types.h>18#include <policy/feerate.h>19#include <policy/policy.h>20#include <pow.h>21#include <primitives/block.h>22#include <primitives/transaction.h>23#include <random.h>24#include <script/script.h>25#include <serialize.h>26#include <sync.h>27#include <test/util/common.h>28#include <test/util/setup_common.h>29#include <test/util/transaction_utils.h>30#include <test/util/time.h>31#include <test/util/txmempool.h>32#include <txmempool.h>33#include <uint256.h>34#include <util/check.h>35#include <util/feefrac.h>36#include <util/strencodings.h>37#include <util/translation.h>38#include <validation.h>39#include <versionbits.h>41#include <boost/test/unit_test.hpp>43#include <cstddef>44#include <cstdint>45#include <iterator>46#include <memory>47#include <optional>48#include <span>49#include <stdexcept>50#include <string>51#include <vector>53using namespace util::hex_literals;54using interfaces::BlockTemplate;55using interfaces::Mining;56using node::BlockAssembler;57using node::BlockCreateOptions;59namespace miner_tests {60struct MinerTestingSetup : public TestingSetup {61void TestPackageSelection(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);62void TestBasicMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst, int baseheight) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);63void TestPrioritisedMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);64void TestSigOpsAdjustedWeightChunkLimit(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst) EXCLUSIVE_LOCKS_REQUIRED(::cs_main);65bool TestSequenceLocks(const CTransaction& tx, CTxMemPool& tx_mempool) EXCLUSIVE_LOCKS_REQUIRED(::cs_main)66{67CCoinsViewMemPool view_mempool{&m_node.chainman->ActiveChainstate().CoinsTip(), tx_mempool};68CBlockIndex* tip{m_node.chainman->ActiveChain().Tip()};69const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip(tip, view_mempool, tx)};70return lock_points.has_value() && CheckSequenceLocksAtTip(tip, *lock_points);71}72CTxMemPool& MakeMempool()73{74// Delete the previous mempool to ensure with valgrind that the old75// pointer is not accessed, when the new one should be accessed76// instead.77m_node.mempool.reset();78bilingual_str error;79auto opts = MemPoolOptionsForTest(m_node);80// The "block size > limit" test creates a cluster of 1192590 vbytes,81// so set the cluster vbytes limit big enough so that the txgraph82// doesn't become oversized.83opts.limits.cluster_size_vbytes = 1'200'000;84m_node.mempool = std::make_unique<CTxMemPool>(opts, error);85Assert(error.empty());86return *m_node.mempool;87}88std::unique_ptr<Mining> MakeMining()89{90return interfaces::MakeMining(m_node, /*wait_loaded=*/false);91}92};93} // namespace miner_tests95BOOST_FIXTURE_TEST_SUITE(miner_tests, MinerTestingSetup)97static CFeeRate blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE);99constexpr static struct {100unsigned int extranonce;101unsigned int nonce;102} BLOCKINFO[]{{0, 3552706918}, {500, 37506755}, {1000, 948987788}, {400, 524762339}, {800, 258510074}, {300, 102309278},103{1300, 54365202}, {600, 1107740426}, {1000, 203094491}, {900, 391178848}, {800, 381177271}, {600, 87188412},104{0, 66522866}, {800, 874942736}, {1000, 89200838}, {400, 312638088}, {400, 66263693}, {500, 924648304},105{400, 369913599}, {500, 47630099}, {500, 115045364}, {100, 277026602}, {1100, 809621409}, {700, 155345322},106{800, 943579953}, {400, 28200730}, {900, 77200495}, {0, 105935488}, {400, 698721821}, {500, 111098863},107{1300, 445389594}, {500, 621849894}, {1400, 56010046}, {1100, 370669776}, {1200, 380301940}, {1200, 110654905},108{400, 213771024}, {1500, 120014726}, {1200, 835019014}, {1500, 624817237}, {900, 1404297}, {400, 189414558},109{400, 293178348}, {1100, 15393789}, {600, 396764180}, {800, 1387046371}, {800, 199368303}, {700, 111496662},110{100, 129759616}, {200, 536577982}, {500, 125881300}, {500, 101053391}, {1200, 471590548}, {900, 86957729},111{1200, 179604104}, {600, 68658642}, {1000, 203295701}, {500, 139615361}, {900, 233693412}, {300, 153225163},112{0, 27616254}, {1200, 9856191}, {100, 220392722}, {200, 66257599}, {1100, 145489641}, {1300, 37859442},113{400, 5816075}, {1200, 215752117}, {1400, 32361482}, {1400, 6529223}, {500, 143332977}, {800, 878392},114{700, 159290408}, {400, 123197595}, {700, 43988693}, {300, 304224916}, {700, 214771621}, {1100, 274148273},115{400, 285632418}, {1100, 923451065}, {600, 12818092}, {1200, 736282054}, {1000, 246683167}, {600, 92950402},116{1400, 29223405}, {1000, 841327192}, {700, 174301283}, {1400, 214009854}, {1000, 6989517}, {1200, 278226956},117{700, 540219613}, {400, 93663104}, {1100, 152345635}, {1500, 464194499}, {1300, 333850111}, {600, 258311263},118{600, 90173162}, {1000, 33590797}, {1500, 332866027}, {100, 204704427}, {1000, 463153545}, {800, 303244785},119{600, 88096214}, {0, 137477892}, {1200, 195514506}, {300, 704114595}, {900, 292087369}, {1400, 758684870},120{1300, 163493028}, {1200, 53151293}};122static std::unique_ptr<CBlockIndex> CreateBlockIndex(int nHeight, CBlockIndex* active_chain_tip) EXCLUSIVE_LOCKS_REQUIRED(cs_main)123{124auto index{std::make_unique<CBlockIndex>()};125index->nHeight = nHeight;126index->pprev = active_chain_tip;127return index;128}130// Test suite for ancestor feerate transaction selection.131// Implemented as an additional function, rather than a separate test case,132// to allow reusing the blockchain created in CreateNewBlock_validity.133void MinerTestingSetup::TestPackageSelection(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)134{135CTxMemPool& tx_mempool{MakeMempool()};136auto mining{MakeMining()};137BlockCreateOptions options{138.coinbase_output_script = scriptPubKey,139};141LOCK(tx_mempool.cs);142BOOST_CHECK(tx_mempool.size() == 0);144// Block template should only have a coinbase when there's nothing in the mempool145std::unique_ptr<BlockTemplate> block_template = mining->createNewBlock(options, /*cooldown=*/false);146BOOST_REQUIRE(block_template);147CBlock block{block_template->getBlock()};148BOOST_REQUIRE_EQUAL(block.vtx.size(), 1U);150// waitNext() on an empty mempool should return nullptr because there is no better template151auto should_be_nullptr = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 1});152BOOST_REQUIRE(should_be_nullptr == nullptr);154// Unless fee_threshold is 0155block_template = block_template->waitNext({.timeout = MillisecondsDouble{0}, .fee_threshold = 0});156BOOST_REQUIRE(block_template);158// Test the ancestor feerate transaction selection.159TestMemPoolEntryHelper entry;161// Test that a medium fee transaction will be selected after a higher fee162// rate package with a low fee rate parent.163CMutableTransaction tx;164tx.vin.resize(1);165tx.vin[0].scriptSig = CScript() << OP_1;166tx.vin[0].prevout.hash = txFirst[0]->GetHash();167tx.vin[0].prevout.n = 0;168tx.vout.resize(1);169tx.vout[0].nValue = 5000000000LL - 1000;170// This tx has a low fee: 1000 satoshis171Txid hashParentTx = tx.GetHash(); // save this txid for later use172const auto parent_tx{entry.Fee(1000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)};173TryAddToMempool(tx_mempool, parent_tx);175// This tx has a medium fee: 10000 satoshis176tx.vin[0].prevout.hash = txFirst[1]->GetHash();177tx.vout[0].nValue = 5000000000LL - 10000;178Txid hashMediumFeeTx = tx.GetHash();179const auto medium_fee_tx{entry.Fee(10000).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx)};180TryAddToMempool(tx_mempool, medium_fee_tx);182// This tx has a high fee, but depends on the first transaction183tx.vin[0].prevout.hash = hashParentTx;184tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 50k satoshi fee185Txid hashHighFeeTx = tx.GetHash();186const auto high_fee_tx{entry.Fee(50000).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx)};187TryAddToMempool(tx_mempool, high_fee_tx);189// Test getTransactionsByTxID()190const std::vector<Txid> tx_id_list{191hashParentTx,192Txid::FromUint256(uint256::ZERO) // non-existing tx193};194auto raw_txs = mining->getTransactionsByTxID(tx_id_list);195BOOST_REQUIRE_EQUAL(raw_txs.size(), tx_id_list.size());196BOOST_CHECK(raw_txs[0]);197BOOST_CHECK(raw_txs[0]->GetHash() == hashParentTx);198BOOST_CHECK(!raw_txs[1]);199// Test getTransactionsByWitnessID()200// tx has no witness, so just cast to Wtxid201const std::vector<Wtxid> wtx_id_list{202Wtxid::FromUint256(hashParentTx.ToUint256()),203Wtxid::FromUint256(uint256::ZERO)204};205raw_txs = mining->getTransactionsByWitnessID(wtx_id_list);206BOOST_REQUIRE_EQUAL(raw_txs.size(), tx_id_list.size());207BOOST_CHECK(raw_txs[0]);208BOOST_CHECK(raw_txs[0]->GetHash() == hashParentTx);209BOOST_CHECK(!raw_txs[1]);210block_template = mining->createNewBlock(options, /*cooldown=*/false);211BOOST_REQUIRE(block_template);212block = block_template->getBlock();213BOOST_REQUIRE_EQUAL(block.vtx.size(), 4U);214BOOST_CHECK(block.vtx[1]->GetHash() == hashParentTx);215BOOST_CHECK(block.vtx[2]->GetHash() == hashHighFeeTx);216BOOST_CHECK(block.vtx[3]->GetHash() == hashMediumFeeTx);218// Test the inclusion of package feerates in the block template and ensure they are sequential.219// Can't use the Mining interface because it needs access to m_package_feerates.220const auto block_package_feerates = BlockAssembler{221m_node.chainman->ActiveChainstate(),222&tx_mempool,223MergeMiningOptions(options, m_node.mining_args),224}.CreateNewBlock()->m_package_feerates;225BOOST_CHECK(block_package_feerates.size() == 2);227// parent_tx and high_fee_tx are added to the block as a package.228const auto combined_txs_fee = parent_tx.GetFee() + high_fee_tx.GetFee();229const auto combined_txs_size = parent_tx.GetTxSize() + high_fee_tx.GetTxSize();230FeeFrac package_feefrac{combined_txs_fee, combined_txs_size};231// The package should be added first.232BOOST_CHECK(block_package_feerates[0] == package_feefrac);234// The medium_fee_tx should be added next.235FeeFrac medium_tx_feefrac{medium_fee_tx.GetFee(), medium_fee_tx.GetTxSize()};236BOOST_CHECK(block_package_feerates[1] == medium_tx_feefrac);238// Test that a package below the block min tx fee doesn't get included239tx.vin[0].prevout.hash = hashHighFeeTx;240tx.vout[0].nValue = 5000000000LL - 1000 - 50000; // 0 fee241Txid hashFreeTx = tx.GetHash();242TryAddToMempool(tx_mempool, entry.Fee(0).FromTx(tx));243uint64_t freeTxSize{::GetSerializeSize(TX_WITH_WITNESS(tx))};245// Calculate a fee on child transaction that will put the package just246// below the block min tx fee (assuming 1 child tx of the same size).247CAmount feeToUse = blockMinFeeRate.GetFee(2*freeTxSize) - 1;249tx.vin[0].prevout.hash = hashFreeTx;250tx.vout[0].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
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.