From 0ae3b40c274a37a870f91a27ed6b2e70dda4ea29 Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Tue, 8 Sep 2026 21:05:59 -0400 Subject: [PATCH 1/2] test: characterize startup with newly added prune and index --- test/functional/feature_pruning.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index 0a8f8e44029..e786ae781aa 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -20,6 +20,7 @@ from test_framework.script import ( OP_RETURN, ) from test_framework.test_framework import BitcoinTestFramework +from test_framework.test_node import ErrorMatch from test_framework.util import ( assert_equal, assert_greater_than, @@ -470,6 +471,17 @@ class PruneTest(BitcoinTestFramework): self.connect_nodes(0, 5) self.sync_blocks([self.nodes[0], self.nodes[5]], wait=5, timeout=300) + self.log.info("Test prune with a new index") + self.stop_node(0) + node = self.nodes[0] + # TODO: Starting prune with a new index must sync the index before pruning. + node.assert_start_raises_init_error( + extra_args=["-prune=550", "-blockfilterindex=1"], + expected_msg="basic block filter index best block of the index goes beyond pruned data", + match=ErrorMatch.PARTIAL_REGEX, + ) + self.start_node(0, extra_args=["-prune=550"]) + if self.is_wallet_compiled(): self.log.info("Test wallet re-scan") self.test_wallet_rescan() From 9b2299514028f5055d4314e402776cbb45c5f538 Mon Sep 17 00:00:00 2001 From: Andrew Toth Date: Wed, 2 Sep 2026 12:43:01 -0400 Subject: [PATCH 2/2] indexes: set prune lock to genesis before first block When setting both a new index and prune size and restarting an unpruned node, the node will prune the block store first and then the index will fail to start syncing. Fix this by setting the prune lock to 0 if the index does not yet have a best block. --- src/index/base.cpp | 4 ++-- test/functional/feature_pruning.py | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/index/base.cpp b/src/index/base.cpp index 5820448bb7f..160c5fa8cd6 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -504,9 +504,9 @@ void BaseIndex::SetBestBlockIndex(const CBlockIndex* block) { assert(!m_chainstate->m_blockman.IsPruneMode() || AllowPrune()); - if (AllowPrune() && block) { + if (AllowPrune()) { node::PruneLockInfo prune_lock; - prune_lock.height_first = block->nHeight; + prune_lock.height_first = block ? block->nHeight : 0; WITH_LOCK(::cs_main, m_chainstate->m_blockman.UpdatePruneLock(GetName(), prune_lock)); } diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py index e786ae781aa..db06f24d929 100755 --- a/test/functional/feature_pruning.py +++ b/test/functional/feature_pruning.py @@ -20,7 +20,6 @@ from test_framework.script import ( OP_RETURN, ) from test_framework.test_framework import BitcoinTestFramework -from test_framework.test_node import ErrorMatch from test_framework.util import ( assert_equal, assert_greater_than, @@ -472,15 +471,9 @@ class PruneTest(BitcoinTestFramework): self.sync_blocks([self.nodes[0], self.nodes[5]], wait=5, timeout=300) self.log.info("Test prune with a new index") - self.stop_node(0) + self.restart_node(0, extra_args=["-prune=550", "-blockfilterindex=1"]) node = self.nodes[0] - # TODO: Starting prune with a new index must sync the index before pruning. - node.assert_start_raises_init_error( - extra_args=["-prune=550", "-blockfilterindex=1"], - expected_msg="basic block filter index best block of the index goes beyond pruned data", - match=ErrorMatch.PARTIAL_REGEX, - ) - self.start_node(0, extra_args=["-prune=550"]) + self.wait_until(lambda: node.getindexinfo()["basic block filter index"]["best_block_height"] >= 10, timeout=300) if self.is_wallet_compiled(): self.log.info("Test wallet re-scan")