From 7bdc8773a21916904474830f1066ca24c20f99b1 Mon Sep 17 00:00:00 2001 From: Eric Voskuil Date: Sat, 17 Oct 2026 17:42:11 -0400 Subject: [PATCH] Prune on startup when coalesced. --- src/chasers/chaser_snapshot.cpp | 26 ++++++++++++++++++++++++++ test/chasers/chaser_estimate.cpp | 23 ++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/chasers/chaser_snapshot.cpp b/src/chasers/chaser_snapshot.cpp index cbb52992..3b8149c2 100644 --- a/src/chasers/chaser_snapshot.cpp +++ b/src/chasers/chaser_snapshot.cpp @@ -65,6 +65,32 @@ code chaser_snapshot::start() NOEXCEPT ////if (enabled_confirm_) //// confirm_ = std::max(archive().get_top_confirmed(), checkpoint()); + // Prune on startup when coalesced above genesis, before the network starts. + const auto& query = archive(); + if (!is_zero(query.get_top_confirmed()) && query.is_coalesced()) + { + LOG_ONLY(const auto begin = logger::now();) + if (const auto ec = query.prune([this](auto LOG_ONLY(event_), + auto LOG_ONLY(table)) NOEXCEPT + { + LOGN("snapshot::" << full_node::store::events.at(event_) + << "(" << full_node::store::tables.at(table) << ")"); + })) + { + LOGF("Prune deferred, " << ec.message()); + } + else + { + pruned_.store(true, std::memory_order_relaxed); + const header_t top = query.to_confirmed(query.get_top_confirmed()); + notify(error::success, chases::pruned{ top }); + LOG_ONLY(const auto time = logger::now() - begin;) + LOG_ONLY(const auto span = duration_cast(time);) + LOGN("Pruned prevout cache at height [" << query.get_top_confirmed() + << "] complete in " << span.count() << " msecs."); + } + } + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } diff --git a/test/chasers/chaser_estimate.cpp b/test/chasers/chaser_estimate.cpp index 62a6c766..1584c025 100644 --- a/test/chasers/chaser_estimate.cpp +++ b/test/chasers/chaser_estimate.cpp @@ -44,6 +44,18 @@ struct chaser_estimate_setup_fixture query.push_confirmed(query.to_header(block1.hash()), true); } + // Mainnet block 1 is a candidate, so the store is not coalesced. + static bool candidate1(node::query& query) NOEXCEPT + { + const system::settings bitcoin{ chain::selection::mainnet }; + const auto& genesis = bitcoin.genesis_block.header(); + const auto& block1 = p2p_compact_setup_fixture::block1(); + const database::context context1{ 0, 1, genesis.timestamp() }; + const auto work1 = genesis.proof() + block1.header().proof(); + return query.set(block1, context1, work1, false, true) && + query.push_candidate(query.to_header(block1.hash())); + } + inline chaser_estimate_setup_fixture(uint16_t horizon, const initializer& setup=confirm1) : p2p_setup_fixture(setup, [=](configuration& config) @@ -166,6 +178,15 @@ struct chaser_estimate_enabled_setup_fixture } }; +struct chaser_estimate_uncoalesced_setup_fixture + : chaser_estimate_setup_fixture +{ + inline chaser_estimate_uncoalesced_setup_fixture() + : chaser_estimate_setup_fixture(2, candidate1) + { + } +}; + BC_POP_WARNING() BOOST_AUTO_TEST_SUITE(chaser_estimate_tests) @@ -176,7 +197,7 @@ BOOST_FIXTURE_TEST_CASE(chaser_estimate__estimate__disabled__estimate_disabled, BOOST_REQUIRE_EQUAL(result.first, node::error::estimate_disabled); } -BOOST_FIXTURE_TEST_CASE(chaser_estimate__estimate__not_initialized__estimate_premature, chaser_estimate_enabled_setup_fixture) +BOOST_FIXTURE_TEST_CASE(chaser_estimate__estimate__not_initialized__estimate_premature, chaser_estimate_uncoalesced_setup_fixture) { const auto result = estimate(1, estimator::mode::basic); BOOST_REQUIRE_EQUAL(result.first, node::error::estimate_premature);