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.
251const auto total_tx_count = graph->GetTransactionCount(TxGraph::Level::TOP);252BOOST_CHECK(total_tx_count == top_refs.size() + bottom_refs.size());253BOOST_CHECK(total_tx_count == NUM_TOTAL_TX);255// Call Trim() to remove transactions and bring the cluster back within limits.256auto removed_refs = graph->Trim();257BOOST_CHECK(!graph->IsOversized(TxGraph::Level::TOP));258BOOST_CHECK(removed_refs.size() == total_tx_count - graph->GetTransactionCount(TxGraph::Level::TOP));259graph->SanityCheck();261// At least 99% of chains must survive.262BOOST_CHECK(graph->GetTransactionCount(TxGraph::Level::TOP) >= (NUM_TOP_CHAINS * NUM_TX_PER_TOP_CHAIN * 99) / 100);263}265BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons)266{267// Mempool consists of 100 singleton clusters; there are no dependencies. Some are oversized. Trim() should remove all of the oversized ones.268static constexpr int MAX_CLUSTER_COUNT = 64;269static constexpr int32_t MAX_CLUSTER_SIZE = 100'000;270static constexpr int NUM_TOTAL_TX = 100;272// Create a new graph for the test.273auto graph = MakeTxGraph(MAX_CLUSTER_COUNT, MAX_CLUSTER_SIZE, HIGH_ACCEPTABLE_COST, PointerComparator);275// Add all transactions and store their Refs.276std::vector<TxGraph::Ref> refs;277refs.reserve(NUM_TOTAL_TX);279// Add all transactions. They are in individual clusters.280for (unsigned int i = 0; i < NUM_TOTAL_TX; ++i) {281// The 88th transaction is oversized.282// Every 20th transaction is oversized.283const FeePerWeight feerate{500 + i, (i == 88 || i % 20 == 0) ? MAX_CLUSTER_SIZE + 1 : 100};284graph->AddTransaction(refs.emplace_back(), feerate);285}286graph->SanityCheck();288// Check that the graph is now oversized. This also forces the graph to289// group clusters and compute the oversized status.290BOOST_CHECK(graph->IsOversized(TxGraph::Level::TOP));292// Call Trim() to remove transactions and bring the cluster back within limits.293graph->Trim();294graph->SanityCheck();295BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), NUM_TOTAL_TX - 6);296BOOST_CHECK(!graph->IsOversized(TxGraph::Level::TOP));298// Check that all the oversized transactions were removed.299for (unsigned int i = 0; i < refs.size(); ++i) {300BOOST_CHECK_EQUAL(graph->Exists(refs[i], TxGraph::Level::TOP), i != 88 && i % 20 != 0);301}302}304BOOST_AUTO_TEST_CASE(txgraph_chunk_chain)305{306// Create a new graph for the test.307auto graph = MakeTxGraph(50, 1000, HIGH_ACCEPTABLE_COST, PointerComparator);309auto block_builder_checker = [&graph](std::vector<std::vector<TxGraph::Ref*>> expected_chunks) {310std::vector<std::vector<TxGraph::Ref*>> chunks;311auto builder = graph->GetBlockBuilder();312FeePerWeight last_chunk_feerate;313while (auto chunk = builder->GetCurrentChunk()) {314FeePerWeight sum;315for (TxGraph::Ref* ref : chunk->first) {316// The reported chunk feerate must match the chunk feerate obtained by asking317// it for each of the chunk's transactions individually.318BOOST_CHECK(graph->GetMainChunkFeerate(*ref) == chunk->second);319// Verify the chunk feerate matches the sum of the reported individual feerates.320sum += graph->GetIndividualFeerate(*ref);321}322BOOST_CHECK(sum == chunk->second);323chunks.push_back(std::move(chunk->first));324last_chunk_feerate = chunk->second;325builder->Include();326}328BOOST_CHECK(chunks == expected_chunks);329auto& last_chunk = chunks.back();330// The last chunk returned by the BlockBuilder must match GetWorstMainChunk, in reverse.331std::reverse(last_chunk.begin(), last_chunk.end());332auto [worst_chunk, worst_chunk_feerate] = graph->GetWorstMainChunk();333BOOST_CHECK(last_chunk == worst_chunk);334BOOST_CHECK(last_chunk_feerate == worst_chunk_feerate);335};337std::vector<TxGraph::Ref> refs;338refs.reserve(4);340FeePerWeight feerateA{2, 10};341FeePerWeight feerateB{1, 10};342FeePerWeight feerateC{2, 10};343FeePerWeight feerateD{4, 10};345// everytime adding a transaction, test the chunk status346// [A]347graph->AddTransaction(refs.emplace_back(), feerateA);348BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);349block_builder_checker({{&refs[0]}});350// [A, B]351graph->AddTransaction(refs.emplace_back(), feerateB);352graph->AddDependency(/*parent=*/refs[0], /*child=*/refs[1]);353BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2);354block_builder_checker({{&refs[0]}, {&refs[1]}});356// [A, BC]357graph->AddTransaction(refs.emplace_back(), feerateC);358graph->AddDependency(/*parent=*/refs[1], /*child=*/refs[2]);359BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 3);360block_builder_checker({{&refs[0]}, {&refs[1], &refs[2]}});362// [ABCD]363graph->AddTransaction(refs.emplace_back(), feerateD);364graph->AddDependency(/*parent=*/refs[2], /*child=*/refs[3]);365BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 4);366block_builder_checker({{&refs[0], &refs[1], &refs[2], &refs[3]}});368graph->SanityCheck();370// D->C->A371graph->RemoveTransaction(refs[1]);372// txgraph is not responsible for removing the descendants or ancestors373BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 3);374// only A remains there375graph->RemoveTransaction(refs[2]);376graph->RemoveTransaction(refs[3]);377BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);378block_builder_checker({{&refs[0]}});379}381BOOST_AUTO_TEST_CASE(txgraph_staging)382{383/* Create a new graph for the test.384* The parameters are max_cluster_count, max_cluster_size, acceptable_iters385*/386auto graph = MakeTxGraph(10, 1000, HIGH_ACCEPTABLE_COST, PointerComparator);388std::vector<TxGraph::Ref> refs;389refs.reserve(2);391FeePerWeight feerateA{2, 10};392FeePerWeight feerateB{1, 10};394// everytime adding a transaction, test the chunk status395// [A]396graph->AddTransaction(refs.emplace_back(), feerateA);397BOOST_CHECK_EQUAL(graph->HaveStaging(), false);398BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);400graph->StartStaging();401BOOST_CHECK_EQUAL(graph->HaveStaging(), true);402BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);404// [A, B]405graph->AddTransaction(refs.emplace_back(), feerateB);406BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 1);407BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2);408BOOST_CHECK_EQUAL(graph->Exists(refs[0], TxGraph::Level::TOP), true);409BOOST_CHECK_EQUAL(graph->Exists(refs[1], TxGraph::Level::TOP), true);411graph->AddDependency(/*parent=*/refs[0], /*child=*/refs[1]);412BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 1);413BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2);415graph->CommitStaging();416BOOST_CHECK_EQUAL(graph->HaveStaging(), false);418BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 2);420graph->StartStaging();422// [A]423graph->RemoveTransaction(refs[1]);424BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 2);425BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);427graph->CommitStaging();429BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::MAIN), 1);431graph->SanityCheck();432}434BOOST_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.