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};253// Process all mined blocks254BOOST_REQUIRE(ProcessBlock(std::make_shared<CBlock>(Params().GenesisBlock())));255auto last_mined = GoodBlock(Params().GenesisBlock().GetHash());256BOOST_REQUIRE(ProcessBlock(last_mined));258// Run the test multiple times259for (int test_runs = 3; test_runs > 0; --test_runs) {260BOOST_CHECK_EQUAL(last_mined->GetHash(), WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockHash()));262// Later on split from here263const uint256 split_hash{last_mined->hashPrevBlock};265// Create a bunch of transactions to spend the miner rewards of the266// most recent blocks267std::vector<CTransactionRef> txs;268for (int num_txs = 22; num_txs > 0; --num_txs) {269CMutableTransaction mtx;270mtx.vin.emplace_back(COutPoint{last_mined->vtx[0]->GetHash(), 1}, CScript{});271mtx.vin[0].scriptWitness.stack.push_back(WITNESS_STACK_ELEM_OP_TRUE);272mtx.vout.push_back(last_mined->vtx[0]->vout[1]);273mtx.vout[0].nValue -= 1000;274txs.push_back(MakeTransactionRef(mtx));276last_mined = GoodBlock(last_mined->GetHash());277BOOST_REQUIRE(ProcessBlock(last_mined));278}280// Mature the inputs of the txs281for (int j = COINBASE_MATURITY; j > 0; --j) {282last_mined = GoodBlock(last_mined->GetHash());283BOOST_REQUIRE(ProcessBlock(last_mined));284}286// Mine a reorg (and hold it back) before adding the txs to the mempool287const uint256 tip_init{last_mined->GetHash()};289std::vector<std::shared_ptr<const CBlock>> reorg;290last_mined = GoodBlock(split_hash);291reorg.push_back(last_mined);292for (size_t j = COINBASE_MATURITY + txs.size() + 1; j > 0; --j) {293last_mined = GoodBlock(last_mined->GetHash());294reorg.push_back(last_mined);295}297// Add the txs to the tx pool298{299LOCK(cs_main);300for (const auto& tx : txs) {301const MempoolAcceptResult result = m_node.chainman->ProcessTransaction(tx);302BOOST_REQUIRE(result.m_result_type == MempoolAcceptResult::ResultType::VALID);303}304}306// Check that all txs are in the pool307{308BOOST_CHECK_EQUAL(m_node.mempool->size(), txs.size());309}311// Run a thread that simulates an RPC caller that is polling while312// validation is doing a reorg313std::thread rpc_thread{[&]() {314// This thread is checking that the mempool either contains all of315// the transactions invalidated by the reorg, or none of them, and316// not some intermediate amount.317while (true) {318LOCK(m_node.mempool->cs);319if (m_node.mempool->size() == 0) {320// We are done with the reorg321break;322}323// Internally, we might be in the middle of the reorg, but324// externally the reorg to the most-proof-of-work chain should325// be atomic. So the caller assumes that the returned mempool326// is consistent. That is, it has all txs that were there327// before the reorg.328assert(m_node.mempool->size() == txs.size());329continue;330}331LOCK(cs_main);332// We are done with the reorg, so the tip must have changed333assert(tip_init != m_node.chainman->ActiveChain().Tip()->GetBlockHash());334}};336// Submit the reorg in this thread to invalidate and remove the txs from the tx pool337for (const auto& b : reorg) {338ProcessBlock(b);339}340// Check that the reorg was eventually successful341BOOST_CHECK_EQUAL(last_mined->GetHash(), WITH_LOCK(Assert(m_node.chainman)->GetMutex(), return m_node.chainman->ActiveChain().Tip()->GetBlockHash()));343// We can join the other thread, which returns when the reorg was successful344rpc_thread.join();345}346}348BOOST_AUTO_TEST_CASE(witness_commitment_index)349{350LOCK(Assert(m_node.chainman)->GetMutex());351CScript pubKey;352pubKey << 1 << OP_TRUE;353auto mining{interfaces::MakeMining(m_node)};354auto block_template{mining->createNewBlock({355.coinbase_output_script = pubKey,356}, /*cooldown=*/false)};357BOOST_REQUIRE(block_template);358CBlock pblock{block_template->getBlock()};360CTxOut witness;361witness.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT);362witness.scriptPubKey[0] = OP_RETURN;363witness.scriptPubKey[1] = 0x24;364witness.scriptPubKey[2] = 0xaa;365witness.scriptPubKey[3] = 0x21;366witness.scriptPubKey[4] = 0xa9;367witness.scriptPubKey[5] = 0xed;369// A witness larger than the minimum size is still valid370CTxOut min_plus_one = witness;371min_plus_one.scriptPubKey.resize(MINIMUM_WITNESS_COMMITMENT + 1);373CTxOut invalid = witness;374invalid.scriptPubKey[0] = OP_VERIFY;376CMutableTransaction txCoinbase(*pblock.vtx[0]);377txCoinbase.vout.resize(4);378txCoinbase.vout[0] = witness;379txCoinbase.vout[1] = witness;380txCoinbase.vout[2] = min_plus_one;381txCoinbase.vout[3] = invalid;382pblock.vtx[0] = MakeTransactionRef(std::move(txCoinbase));384BOOST_CHECK_EQUAL(GetWitnessCommitmentIndex(pblock), 2);385}386BOOST_AUTO_TEST_SUITE_END()
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.