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.
502// orphan in tx_mempool, template creation fails503hash = tx.GetHash();504TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).FromTx(tx));505BOOST_CHECK_EXCEPTION(mining->createNewBlock(options, /*cooldown=*/false), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));506}508{509CTxMemPool& tx_mempool{MakeMempool()};510LOCK(tx_mempool.cs);512// child with higher feerate than parent513tx.vin[0].scriptSig = CScript() << OP_1;514tx.vin[0].prevout.hash = txFirst[1]->GetHash();515tx.vout[0].nValue = BLOCKSUBSIDY - HIGHFEE;516hash = tx.GetHash();517TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));518tx.vin[0].prevout.hash = hash;519tx.vin.resize(2);520tx.vin[1].scriptSig = CScript() << OP_1;521tx.vin[1].prevout.hash = txFirst[0]->GetHash();522tx.vin[1].prevout.n = 0;523tx.vout[0].nValue = tx.vout[0].nValue + BLOCKSUBSIDY - HIGHERFEE; // First txn output + fresh coinbase - new txn fee524hash = tx.GetHash();525TryAddToMempool(tx_mempool, entry.Fee(HIGHERFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));526BOOST_REQUIRE(mining->createNewBlock(options, /*cooldown=*/false));527}529{530CTxMemPool& tx_mempool{MakeMempool()};531LOCK(tx_mempool.cs);533// coinbase in tx_mempool, template creation fails534tx.vin.resize(1);535tx.vin[0].prevout.SetNull();536tx.vin[0].scriptSig = CScript() << OP_0 << OP_1;537tx.vout[0].nValue = 0;538hash = tx.GetHash();539// give it a fee so it'll get mined540TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));541// Should throw bad-cb-multiple542BOOST_CHECK_EXCEPTION(mining->createNewBlock(options, /*cooldown=*/false), std::runtime_error, HasReason("bad-cb-multiple"));543}545{546CTxMemPool& tx_mempool{MakeMempool()};547LOCK(tx_mempool.cs);549// double spend txn pair in tx_mempool, template creation fails550tx.vin[0].prevout.hash = txFirst[0]->GetHash();551tx.vin[0].scriptSig = CScript() << OP_1;552tx.vout[0].nValue = BLOCKSUBSIDY - HIGHFEE;553tx.vout[0].scriptPubKey = CScript() << OP_1;554hash = tx.GetHash();555TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));556tx.vout[0].scriptPubKey = CScript() << OP_2;557hash = tx.GetHash();558TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));559BOOST_CHECK_EXCEPTION(mining->createNewBlock(options, /*cooldown=*/false), std::runtime_error, HasReason("bad-txns-inputs-missingorspent"));560}562{563CTxMemPool& tx_mempool{MakeMempool()};564LOCK(tx_mempool.cs);566// subsidy changing567int nHeight = m_node.chainman->ActiveChain().Height();568// Create an actual 209999-long block chain (without valid blocks).569while (m_node.chainman->ActiveChain().Tip()->nHeight < 209999) {570CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();571CBlockIndex* next = new CBlockIndex();572next->phashBlock = new uint256(m_rng.rand256());573m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(next->GetBlockHash());574next->pprev = prev;575next->nHeight = prev->nHeight + 1;576next->BuildSkip();577m_node.chainman->ActiveChain().SetTip(*next);578}579BOOST_REQUIRE(mining->createNewBlock(options, /*cooldown=*/false));580// Extend to a 210000-long block chain.581while (m_node.chainman->ActiveChain().Tip()->nHeight < 210000) {582CBlockIndex* prev = m_node.chainman->ActiveChain().Tip();583CBlockIndex* next = new CBlockIndex();584next->phashBlock = new uint256(m_rng.rand256());585m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(next->GetBlockHash());586next->pprev = prev;587next->nHeight = prev->nHeight + 1;588next->BuildSkip();589m_node.chainman->ActiveChain().SetTip(*next);590}591BOOST_REQUIRE(mining->createNewBlock(options, /*cooldown=*/false));593// invalid p2sh txn in tx_mempool, template creation fails594tx.vin[0].prevout.hash = txFirst[0]->GetHash();595tx.vin[0].prevout.n = 0;596tx.vin[0].scriptSig = CScript() << OP_1;597tx.vout[0].nValue = BLOCKSUBSIDY - LOWFEE;598CScript script = CScript() << OP_0;599tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script));600hash = tx.GetHash();601TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));602tx.vin[0].prevout.hash = hash;603tx.vin[0].scriptSig = CScript() << std::vector<unsigned char>(script.begin(), script.end());604tx.vout[0].nValue -= LOWFEE;605hash = tx.GetHash();606TryAddToMempool(tx_mempool, entry.Fee(LOWFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(false).FromTx(tx));607BOOST_CHECK_EXCEPTION(mining->createNewBlock(options, /*cooldown=*/false), std::runtime_error, HasReason("block-script-verify-flag-failed"));609// Delete the dummy blocks again.610while (m_node.chainman->ActiveChain().Tip()->nHeight > nHeight) {611CBlockIndex* del = m_node.chainman->ActiveChain().Tip();612m_node.chainman->ActiveChain().SetTip(*Assert(del->pprev));613m_node.chainman->ActiveChainstate().CoinsTip().SetBestBlock(del->pprev->GetBlockHash());614delete del->phashBlock;615delete del;616}617}619CTxMemPool& tx_mempool{MakeMempool()};620LOCK(tx_mempool.cs);622// non-final txs in mempool623clock.set(std::chrono::seconds{m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1});624const int flags{LOCKTIME_VERIFY_SEQUENCE};625// height map626std::vector<int> prevheights;628// relative height locked629tx.version = 2;630tx.vin.resize(1);631prevheights.resize(1);632tx.vin[0].prevout.hash = txFirst[0]->GetHash(); // only 1 transaction633tx.vin[0].prevout.n = 0;634tx.vin[0].scriptSig = CScript() << OP_1;635tx.vin[0].nSequence = m_node.chainman->ActiveChain().Tip()->nHeight + 1; // txFirst[0] is the 2nd block636prevheights[0] = baseheight + 1;637tx.vout.resize(1);638tx.vout[0].nValue = BLOCKSUBSIDY-HIGHFEE;639tx.vout[0].scriptPubKey = CScript() << OP_1;640tx.nLockTime = 0;641hash = tx.GetHash();642TryAddToMempool(tx_mempool, entry.Fee(HIGHFEE).Time(Now<NodeSeconds>()).SpendsCoinbase(true).FromTx(tx));643BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes644BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail646{647CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();648BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, *CreateBlockIndex(active_chain_tip->nHeight + 2, active_chain_tip))); // Sequence locks pass on 2nd block649}651// relative time locked652tx.vin[0].prevout.hash = txFirst[1]->GetHash();653tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | (((m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()+1-m_node.chainman->ActiveChain()[1]->GetMedianTimePast()) >> CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) + 1); // txFirst[1] is the 3rd block654prevheights[0] = baseheight + 2;655hash = tx.GetHash();656TryAddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));657BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes658BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail660const int SEQUENCE_LOCK_TIME = 512; // Sequence locks pass 512 seconds later661for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i)662m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i)->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast663{664CBlockIndex* active_chain_tip = m_node.chainman->ActiveChain().Tip();665BOOST_CHECK(SequenceLocks(CTransaction(tx), flags, prevheights, *CreateBlockIndex(active_chain_tip->nHeight + 1, active_chain_tip)));666}668for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {669CBlockIndex* ancestor{Assert(m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i))};670ancestor->nTime -= SEQUENCE_LOCK_TIME; // undo tricked MTP671}673// absolute height locked674tx.vin[0].prevout.hash = txFirst[2]->GetHash();675tx.vin[0].nSequence = CTxIn::MAX_SEQUENCE_NONFINAL;676prevheights[0] = baseheight + 3;677tx.nLockTime = m_node.chainman->ActiveChain().Tip()->nHeight + 1;678hash = tx.GetHash();679TryAddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));680BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails681BOOST_CHECK(TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks pass682BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast())); // Locktime passes on 2nd block684// ensure tx is final for a specific case where there is no locktime and block height is zero685tx.nLockTime = 0;686BOOST_CHECK(IsFinalTx(CTransaction(tx), /*nBlockHeight=*/0, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast()));688// absolute time locked689tx.vin[0].prevout.hash = txFirst[3]->GetHash();690tx.nLockTime = m_node.chainman->ActiveChain().Tip()->GetMedianTimePast();691prevheights.resize(1);692prevheights[0] = baseheight + 4;693hash = tx.GetHash();694TryAddToMempool(tx_mempool, entry.Time(Now<NodeSeconds>()).FromTx(tx));695BOOST_CHECK(!CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime fails696BOOST_CHECK(TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks pass697BOOST_CHECK(IsFinalTx(CTransaction(tx), m_node.chainman->ActiveChain().Tip()->nHeight + 2, m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1)); // Locktime passes 1 second later699// mempool-dependent transactions (not added)700tx.vin[0].prevout.hash = hash;701prevheights[0] = m_node.chainman->ActiveChain().Tip()->nHeight + 1;702tx.nLockTime = 0;703tx.vin[0].nSequence = 0;704BOOST_CHECK(CheckFinalTxAtTip(*Assert(m_node.chainman->ActiveChain().Tip()), CTransaction{tx})); // Locktime passes705BOOST_CHECK(TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks pass706tx.vin[0].nSequence = 1;707BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail708tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG;709BOOST_CHECK(TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks pass710tx.vin[0].nSequence = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | 1;711BOOST_CHECK(!TestSequenceLocks(CTransaction{tx}, tx_mempool)); // Sequence locks fail713auto block_template = mining->createNewBlock(options, /*cooldown=*/false);714BOOST_REQUIRE(block_template);716// None of the of the absolute height/time locked tx should have made717// it into the template because we still check IsFinalTx in CreateNewBlock,718// but relative locked txs will if inconsistently added to mempool.719// For now these will still generate a valid template until BIP68 soft fork720CBlock block{block_template->getBlock()};721BOOST_CHECK_EQUAL(block.vtx.size(), 3U);722// However if we advance height by 1 and time by SEQUENCE_LOCK_TIME, all of them should be mined723for (int i = 0; i < CBlockIndex::nMedianTimeSpan; ++i) {724CBlockIndex* ancestor{Assert(m_node.chainman->ActiveChain().Tip()->GetAncestor(m_node.chainman->ActiveChain().Tip()->nHeight - i))};725ancestor->nTime += SEQUENCE_LOCK_TIME; // Trick the MedianTimePast726}727m_node.chainman->ActiveChain().Tip()->nHeight++;728clock.set(std::chrono::seconds{m_node.chainman->ActiveChain().Tip()->GetMedianTimePast() + 1});730block_template = mining->createNewBlock(options, /*cooldown=*/false);731BOOST_REQUIRE(block_template);732block = block_template->getBlock();733BOOST_CHECK_EQUAL(block.vtx.size(), 5U);734}736void MinerTestingSetup::TestPrioritisedMining(const CScript& scriptPubKey, const std::vector<CTransactionRef>& txFirst)737{738auto mining{MakeMining()};739BOOST_REQUIRE(mining);741BlockCreateOptions options{742.coinbase_output_script = scriptPubKey,743};745CTxMemPool& tx_mempool{MakeMempool()};746LOCK(tx_mempool.cs);748TestMemPoolEntryHelper entry;750// Test that a tx below min fee but prioritised is included
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.