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.
751auto ptx = MakeTransactionSpending({}, det_rand);752const auto& wtxid = ptx->GetWitnessHash();753BOOST_CHECK(orphanage->AddTx(ptx, node0));754BOOST_CHECK(orphanage->HaveTx(wtxid));755expected_total_count += 1;756BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);758// Adding again should do nothing.759BOOST_CHECK(!orphanage->AddTx(ptx, node0));760BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);762// We can add another tx with the same txid but different witness.763auto ptx_mutated{MakeMutation(ptx)};764BOOST_CHECK(orphanage->AddTx(ptx_mutated, node0));765BOOST_CHECK(orphanage->HaveTx(ptx_mutated->GetWitnessHash()));766expected_total_count += 1;768BOOST_CHECK(!orphanage->AddTx(ptx, node0));770// Adding a new announcer should not change overall accounting.771BOOST_CHECK(orphanage->AddAnnouncer(ptx->GetWitnessHash(), node2));772BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);774// If we already have this announcer, AddAnnouncer returns false.775BOOST_CHECK(orphanage->HaveTxFromPeer(ptx->GetWitnessHash(), node2));776BOOST_CHECK(!orphanage->AddAnnouncer(ptx->GetWitnessHash(), node2));778// Same with using AddTx for an existing tx, which is equivalent to using AddAnnouncer779BOOST_CHECK(!orphanage->AddTx(ptx, node1));780BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);782// if EraseForPeer is called for an orphan with multiple announcers, the orphanage should only783// erase that peer from the announcers set.784orphanage->EraseForPeer(node0);785BOOST_CHECK(orphanage->HaveTx(ptx->GetWitnessHash()));786BOOST_CHECK(!orphanage->HaveTxFromPeer(ptx->GetWitnessHash(), node0));787// node0 is the only one that announced ptx_mutated788BOOST_CHECK(!orphanage->HaveTx(ptx_mutated->GetWitnessHash()));789expected_total_count -= 1;790BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);792// EraseForPeer should delete the orphan if it's the only announcer left.793orphanage->EraseForPeer(node1);794BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);795BOOST_CHECK(orphanage->HaveTx(ptx->GetWitnessHash()));796orphanage->EraseForPeer(node2);797expected_total_count -= 1;798BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);799BOOST_CHECK(!orphanage->HaveTx(ptx->GetWitnessHash()));800}802// Check that erasure for blocks removes for all peers.803{804CBlock block;805auto tx_block = MakeTransactionSpending({}, det_rand);806block.vtx.emplace_back(tx_block);807BOOST_CHECK(orphanage->AddTx(tx_block, node0));808BOOST_CHECK(!orphanage->AddTx(tx_block, node1));810expected_total_count += 1;812BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);814orphanage->EraseForBlock(block);816expected_total_count -= 1;818BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), expected_total_count);819}820}821BOOST_AUTO_TEST_CASE(peer_worksets)822{823const NodeId node0{0};824const NodeId node1{1};825const NodeId node2{2};826FastRandomContext det_rand{true};827std::unique_ptr<node::TxOrphanage> orphanage{node::MakeTxOrphanage()};828// AddChildrenToWorkSet should pick an announcer randomly829{830auto tx_missing_parent = MakeTransactionSpending({}, det_rand);831auto tx_orphan = MakeTransactionSpending({COutPoint{tx_missing_parent->GetHash(), 0}}, det_rand);832const auto& orphan_wtxid = tx_orphan->GetWitnessHash();834// All 3 peers are announcers.835BOOST_CHECK(orphanage->AddTx(tx_orphan, node0));836BOOST_CHECK(!orphanage->AddTx(tx_orphan, node1));837BOOST_CHECK(orphanage->AddAnnouncer(orphan_wtxid, node2));838for (NodeId node = node0; node <= node2; ++node) {839BOOST_CHECK(orphanage->HaveTxFromPeer(orphan_wtxid, node));840}842// Parent accepted: child is added to 1 of 3 worksets.843auto newly_reconsiderable = orphanage->AddChildrenToWorkSet(*tx_missing_parent, det_rand);844BOOST_CHECK_EQUAL(newly_reconsiderable.size(), 1);845int node0_reconsider = orphanage->HaveTxToReconsider(node0);846int node1_reconsider = orphanage->HaveTxToReconsider(node1);847int node2_reconsider = orphanage->HaveTxToReconsider(node2);848BOOST_CHECK_EQUAL(node0_reconsider + node1_reconsider + node2_reconsider, 1);850NodeId assigned_peer;851if (node0_reconsider) {852assigned_peer = node0;853} else if (node1_reconsider) {854assigned_peer = node1;855} else {856BOOST_CHECK(node2_reconsider);857assigned_peer = node2;858}860// EraseForPeer also removes that tx from the workset.861orphanage->EraseForPeer(assigned_peer);862BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(node0), nullptr);864// Delete this tx, clearing the orphanage.865BOOST_CHECK_EQUAL(orphanage->EraseTx(orphan_wtxid), 1);866BOOST_CHECK_EQUAL(orphanage->CountUniqueOrphans(), 0);867for (NodeId node = node0; node <= node2; ++node) {868BOOST_CHECK_EQUAL(orphanage->GetTxToReconsider(node), nullptr);869BOOST_CHECK(!orphanage->HaveTxFromPeer(orphan_wtxid, node));870}871}872}873BOOST_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.