tests: add unit tests for CBlockIndex::GetAncestor and LastCommonAncestor
What changed, and why it matters
This commit only adds new automated unit tests for existing chain-history helper functions in Bitcoin Core. It does not change any production code, fix a bug, or introduce a security-relevant behavior change. There is no indication this is a security patch.
No security action needed. Treat as routine test-coverage improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit adds src/test/chain_tests.cpp and registers it in src/test/CMakeLists.txt. The new tests exercise CBlockIndex::GetAncestor and LastCommonAncestor by building randomized 10,001-block chain trees, then comparing optimized results against naive reference implementations across 10,000 queries per function per iteration. No production source files are modified.
Changed components
src/test/chain_tests.cpp (new test file)src/test/CMakeLists.txt (test build registration)Inspect captured patch +86 / −0
diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt
index aacefb3f..b4c1ec69 100644
--- a/src/test/CMakeLists.txt
+++ b/src/test/CMakeLists.txt
@@ -26,6 +26,7 @@ add_executable(test_bitcoin
bloom_tests.cpp
bswap_tests.cpp
caches_tests.cpp
+ chain_tests.cpp
chainstate_write_tests.cpp
checkqueue_tests.cpp
cluster_linearize_tests.cpp
diff --git a/src/test/chain_tests.cpp b/src/test/chain_tests.cpp
new file mode 100644
index 00000000..a782e880
--- /dev/null
+++ b/src/test/chain_tests.cpp
@@ -0,0 +1,85 @@
+// Copyright (c) The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <boost/test/unit_test.hpp>
+
+#include <chain.h>
+#include <test/util/setup_common.h>
+
+#include <memory>
+
+BOOST_FIXTURE_TEST_SUITE(chain_tests, BasicTestingSetup)
+
+namespace {
+
+const CBlockIndex* NaiveGetAncestor(const CBlockIndex* a, int height)
+{
+ while (a->nHeight > height) {
+ a = a->pprev;
+ }
+ BOOST_REQUIRE_EQUAL(a->nHeight, height);
+ return a;
+}
+
+const CBlockIndex* NaiveLastCommonAncestor(const CBlockIndex* a, const CBlockIndex* b)
+{
+ while (a->nHeight > b->nHeight) {
+ a = a->pprev;
+ }
+ while (b->nHeight > a->nHeight) {
+ b = b->pprev;
+ }
+ while (a != b) {
+ BOOST_REQUIRE_EQUAL(a->nHeight, b->nHeight);
+ a = a->pprev;
+ b = b->pprev;
+ }
+ BOOST_REQUIRE_EQUAL(a, b);
+ return a;
+}
+
+} // namespace
+
+BOOST_AUTO_TEST_CASE(chain_test)
+{
+ FastRandomContext ctx;
+ std::vector<std::unique_ptr<CBlockIndex>> block_index;
+ // Run 10 iterations of the whole test.
+ for (int i = 0; i < 10; ++i) {
+ block_index.clear();
+ // Create genesis block.
+ auto genesis = std::make_unique<CBlockIndex>();
+ genesis->nHeight = 0;
+ block_index.push_back(std::move(genesis));
+ // Create 10000 more blocks.
+ for (int b = 0; b < 10000; ++b) {
+ auto new_index = std::make_unique<CBlockIndex>();
+ // 95% of blocks build on top of the last block; the others fork off randomly.
+ if (ctx.randrange(20) != 0) {
+ new_index->pprev = block_index.back().get();
+ } else {
+ new_index->pprev = block_index[ctx.randrange(block_index.size())].get();
+ }
+ new_index->nHeight = new_index->pprev->nHeight + 1;
+ new_index->BuildSkip();
+ block_index.push_back(std::move(new_index));
+ }
+ // Run 10000 random GetAncestor queries.
+ for (int q = 0; q < 10000; ++q) {
+ const CBlockIndex* block = block_index[ctx.randrange(block_index.size())].get();
+ unsigned height = ctx.randrange<unsigned>(block->nHeight + 1);
+ const CBlockIndex* result = block->GetAncestor(height);
+ BOOST_CHECK(result == NaiveGetAncestor(block, height));
+ }
+ // Run 10000 random LastCommonAncestor queries.
+ for (int q = 0; q < 10000; ++q) {
+ const CBlockIndex* block1 = block_index[ctx.randrange(block_index.size())].get();
+ const CBlockIndex* block2 = block_index[ctx.randrange(block_index.size())].get();
+ const CBlockIndex* result = LastCommonAncestor(block1, block2);
+ BOOST_CHECK(result == NaiveLastCommonAncestor(block1, block2));
+ }
+ }
+}
+
+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.