test: add block builder tests for txgraph
What changed, and why it matters
This commit only adds and updates unit tests for an internal transaction-graph data structure. It does not change any production code that runs on the Bitcoin network, so it cannot introduce a security vulnerability or be exploited by attackers.
No security action needed; this is a routine test-only change. Reviewers may optionally verify the new test assertions correctly exercise the intended TxGraph::BlockBuilder behavior.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies src/test/txgraph_tests.cpp, renaming the BOOST_AUTO_TEST_CASE from txgraph_get_worst_chunk_chain to txgraph_chunk_chain and replacing a helper that only checked GetWorstMainChunk with a more thorough block_builder_checker. The new checker iterates a TxGraph::GetBlockBuilder(), verifies chunk feerates, and compares the last chunk to GetWorstMainChunk(). No non-test source files are changed.
Changed components
src/test/txgraph_tests.cppInspect captured patch +31 / −13
diff --git a/src/test/txgraph_tests.cpp b/src/test/txgraph_tests.cpp
index 3472f699..e87c1c5e 100644
--- a/src/test/txgraph_tests.cpp
+++ b/src/test/txgraph_tests.cpp
@@ -291,19 +291,37 @@ BOOST_AUTO_TEST_CASE(txgraph_trim_big_singletons)
}
}
-BOOST_AUTO_TEST_CASE(txgraph_get_worst_chunk_chain)
+BOOST_AUTO_TEST_CASE(txgraph_chunk_chain)
{
// Create a new graph for the test.
auto graph = MakeTxGraph(50, 1000, NUM_ACCEPTABLE_ITERS);
- auto chunk_check_helper = [&graph](const std::vector<FeePerWeight>& expected_chunk_txs_feerates, FeePerWeight expected_chunk_feerate) {
- auto chunk = graph->GetWorstMainChunk();
- BOOST_CHECK_EQUAL(chunk.first.size(), expected_chunk_txs_feerates.size());
- for (size_t i = 0; i < expected_chunk_txs_feerates.size(); i++)
- BOOST_CHECK(graph->GetIndividualFeerate(*chunk.first[i]) == expected_chunk_txs_feerates[i]);
+ auto block_builder_checker = [&graph](std::vector<std::vector<TxGraph::Ref*>> expected_chunks) {
+ std::vector<std::vector<TxGraph::Ref*>> chunks;
+ auto builder = graph->GetBlockBuilder();
+ FeePerWeight last_chunk_feerate;
+ while (auto chunk = builder->GetCurrentChunk()) {
+ FeePerWeight sum;
+ for (TxGraph::Ref* ref : chunk->first) {
+ // The reported chunk feerate must match the chunk feerate obtained by asking
+ // it for each of the chunk's transactions individually.
+ BOOST_CHECK(graph->GetMainChunkFeerate(*ref) == chunk->second);
+ // Verify the chunk feerate matches the sum of the reported individual feerates.
+ sum += graph->GetIndividualFeerate(*ref);
+ }
+ BOOST_CHECK(sum == chunk->second);
+ chunks.push_back(std::move(chunk->first));
+ last_chunk_feerate = chunk->second;
+ builder->Include();
+ }
- BOOST_CHECK_EQUAL(chunk.second.fee, expected_chunk_feerate.fee);
- BOOST_CHECK_EQUAL(chunk.second.size, expected_chunk_feerate.size);
+ BOOST_CHECK(chunks == expected_chunks);
+ auto& last_chunk = chunks.back();
+ // The last chunk returned by the BlockBuilder must match GetWorstMainChunk, in reverse.
+ std::reverse(last_chunk.begin(), last_chunk.end());
+ auto [worst_chunk, worst_chunk_feerate] = graph->GetWorstMainChunk();
+ BOOST_CHECK(last_chunk == worst_chunk);
+ BOOST_CHECK(last_chunk_feerate == worst_chunk_feerate);
};
std::vector<TxGraph::Ref> refs;
@@ -318,24 +336,24 @@ BOOST_AUTO_TEST_CASE(txgraph_get_worst_chunk_chain)
// [A]
refs.push_back(graph->AddTransaction(feerateA));
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);
- chunk_check_helper({feerateA}, feerateA);
+ block_builder_checker({{&refs[0]}});
// [A, B]
refs.push_back(graph->AddTransaction(feerateB));
graph->AddDependency(/*parent=*/refs[0], /*child=*/refs[1]);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 2);
- chunk_check_helper({feerateB}, feerateB);
+ block_builder_checker({{&refs[0]}, {&refs[1]}});
// [A, BC]
refs.push_back(graph->AddTransaction(feerateC));
graph->AddDependency(/*parent=*/refs[1], /*child=*/refs[2]);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 3);
- chunk_check_helper({feerateC, feerateB}, FeePerWeight{3, 20});
+ block_builder_checker({{&refs[0]}, {&refs[1], &refs[2]}});
// [ABCD]
refs.push_back(graph->AddTransaction(feerateD));
graph->AddDependency(/*parent=*/refs[2], /*child=*/refs[3]);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 4);
- chunk_check_helper({feerateD, feerateC, feerateB, feerateA}, FeePerWeight{9, 40});
+ block_builder_checker({{&refs[0], &refs[1], &refs[2], &refs[3]}});
graph->SanityCheck();
@@ -347,7 +365,7 @@ BOOST_AUTO_TEST_CASE(txgraph_get_worst_chunk_chain)
graph->RemoveTransaction(refs[2]);
graph->RemoveTransaction(refs[3]);
BOOST_CHECK_EQUAL(graph->GetTransactionCount(TxGraph::Level::TOP), 1);
- chunk_check_helper({feerateA}, feerateA);
+ block_builder_checker({{&refs[0]}});
}
BOOST_AUTO_TEST_SUITE_END()
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.