From df44afdc983e36ba1c2718597e3833bf21a771b8 Mon Sep 17 00:00:00 2001 From: Peter Zafonte Date: Fri, 20 Mar 2026 15:14:33 -0400 Subject: [PATCH] kernel: expose btck_block_tree_entry_get_ancestor Allows callers to jump to any ancestor of a block tree entry by height using the skiplist-backed GetAncestor, which runs in O(log N) rather than walking back one entry at a time with btck_block_tree_entry_get_previous. Includes a C++ convenience wrapper and tests in btck_block_tree_entry_tests. --- src/kernel/bitcoinkernel.cpp | 7 +++++++ src/kernel/bitcoinkernel.h | 11 +++++++++++ src/kernel/bitcoinkernel_wrapper.h | 6 ++++++ src/test/kernel/test_kernel.cpp | 5 +++++ 4 files changed, 29 insertions(+) diff --git a/src/kernel/bitcoinkernel.cpp b/src/kernel/bitcoinkernel.cpp index 09b4853fa91..c951100e142 100644 --- a/src/kernel/bitcoinkernel.cpp +++ b/src/kernel/bitcoinkernel.cpp @@ -885,6 +885,13 @@ const btck_BlockTreeEntry* btck_block_tree_entry_get_previous(const btck_BlockTr return btck_BlockTreeEntry::ref(btck_BlockTreeEntry::get(entry).pprev); } +const btck_BlockTreeEntry* btck_block_tree_entry_get_ancestor(const btck_BlockTreeEntry* block_tree_entry, int32_t height) +{ + const auto* ancestor{btck_BlockTreeEntry::get(block_tree_entry).GetAncestor(height)}; + assert(ancestor); + return btck_BlockTreeEntry::ref(ancestor); +} + btck_BlockValidationState* btck_block_validation_state_create() { return btck_BlockValidationState::create(); diff --git a/src/kernel/bitcoinkernel.h b/src/kernel/bitcoinkernel.h index 57c88c1279c..2b4ab48f549 100644 --- a/src/kernel/bitcoinkernel.h +++ b/src/kernel/bitcoinkernel.h @@ -1008,6 +1008,17 @@ BITCOINKERNEL_API const btck_BlockHash* BITCOINKERNEL_WARN_UNUSED_RESULT btck_bl BITCOINKERNEL_API int BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_tree_entry_equals( const btck_BlockTreeEntry* entry1, const btck_BlockTreeEntry* entry2) BITCOINKERNEL_ARG_NONNULL(1, 2); +/** + * @brief Return the ancestor of a btck_BlockTreeEntry at the given height. + * + * @param[in] block_tree_entry Non-null. + * @param[in] height The height of the requested ancestor. + * @return The ancestor at the given height. + */ +BITCOINKERNEL_API const btck_BlockTreeEntry* BITCOINKERNEL_WARN_UNUSED_RESULT btck_block_tree_entry_get_ancestor( + const btck_BlockTreeEntry* block_tree_entry, + int32_t height) BITCOINKERNEL_ARG_NONNULL(1); + ///@} /** @name ChainstateManagerOptions diff --git a/src/kernel/bitcoinkernel_wrapper.h b/src/kernel/bitcoinkernel_wrapper.h index 064d0dd14b9..0caa2d33f95 100644 --- a/src/kernel/bitcoinkernel_wrapper.h +++ b/src/kernel/bitcoinkernel_wrapper.h @@ -882,6 +882,12 @@ public: { return BlockHeader{btck_block_tree_entry_get_block_header(get())}; } + + BlockTreeEntry GetAncestor(int32_t height) const + { + return BlockTreeEntry{btck_block_tree_entry_get_ancestor(get(), height)}; + } + }; class KernelNotifications diff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp index 4a97f5ba467..8eb15ec3d03 100644 --- a/src/test/kernel/test_kernel.cpp +++ b/src/test/kernel/test_kernel.cpp @@ -973,6 +973,11 @@ BOOST_AUTO_TEST_CASE(btck_block_tree_entry_tests) auto prev{entry_1.GetPrevious()}; BOOST_CHECK(prev.has_value()); BOOST_CHECK(prev.value() == entry_0); + + // Test GetAncestor + BOOST_CHECK(entry_2.GetAncestor(2) == entry_2); + BOOST_CHECK(entry_2.GetAncestor(1) == entry_1); + BOOST_CHECK(entry_2.GetAncestor(0) == entry_0); } BOOST_AUTO_TEST_CASE(btck_chainman_in_memory_tests)