Skip to content

Commit c00ebe4

Browse files
fix: make a missing snapshot base header nonfatal at startup
With loadtxoutset a snapshot chainstate legitimately exists before its base header arrives, so the M3-era LoadBlockIndex hard error (and its test) is superseded: candidate admission and CheckBlockIndex already tolerate a null snapshot base, and snapshot_startup_missing_base_header_is_nonfatal covers the replacement behavior. This matches the reviewed pre-decomposition M5 disposition; fold into the load-integration commit when the M5 PR is cut. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 678aaa6 commit c00ebe4

2 files changed

Lines changed: 4 additions & 36 deletions

File tree

‎src/test/validation_chainstatemanager_tests.cpp‎

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,31 +1298,6 @@ BOOST_FIXTURE_TEST_CASE(chainstatemanager_snapshot_base_is_cached, SnapshotTestS
12981298
}
12991299
}
13001300

1301-
//! A snapshot chainstate whose base block is missing from the on-disk block
1302-
//! index must fail startup with a recoverable error (reindex discards the
1303-
//! snapshot), not abort in candidate admission.
1304-
BOOST_FIXTURE_TEST_CASE(chainstatemanager_snapshot_missing_base_fails_load, SnapshotTestSetup)
1305-
{
1306-
this->SetupSnapshot();
1307-
this->SimulateNodeRestart();
1308-
1309-
// Simulate a block-tree database that has lost the snapshot's history
1310-
// (wiped or swapped blocks/index) while the snapshot chainstate directory
1311-
// and its EvoDB marker survive.
1312-
fs::remove_all(gArgs.GetDataDirNet() / "blocks" / "index");
1313-
1314-
ChainstateManager& chainman = *Assert(m_node.chainman);
1315-
node::ChainstateLoadStatus status;
1316-
bilingual_str error;
1317-
{
1318-
ASSERT_DEBUG_LOG("missing from the block index");
1319-
std::tie(status, error) = node::LoadChainstate(chainman, m_cache_sizes, ChainstateLoadOptionsForTest(),
1320-
*m_node.evodb, *m_node.dmnman, m_node.llmq_ctx,
1321-
m_node.chain_helper);
1322-
}
1323-
BOOST_CHECK(status == node::ChainstateLoadStatus::FAILURE);
1324-
}
1325-
13261301
BOOST_FIXTURE_TEST_CASE(chainstatemanager_snapshot_completion_without_base_list_marker, SnapshotTestSetup)
13271302
{
13281303
this->SetupSnapshot();

‎src/validation.cpp‎

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5117,17 +5117,10 @@ bool ChainstateManager::LoadBlockIndex()
51175117

51185118
m_blockman.ScanAndUnlinkAlreadyPrunedFiles();
51195119

5120-
// Candidate admission below Asserts the snapshot base for the
5121-
// background chainstate, so a base missing from the on-disk block
5122-
// index must be reported here, as a recoverable startup error, before
5123-
// any admission runs. -reindex discards the snapshot chainstate and
5124-
// its EvoDB markers, so the standard rebuild advice recovers.
5125-
if (const auto base_hash{SnapshotBlockhash()}) {
5126-
if (!m_blockman.LookupBlockIndex(*base_hash)) {
5127-
return error("[snapshot] base block %s of the active snapshot chainstate is missing from the block index",
5128-
base_hash->ToString());
5129-
}
5130-
}
5120+
// A snapshot chainstate may legitimately exist before its base header
5121+
// has arrived (a loadtxoutset node restarted before header sync), so a
5122+
// base missing from the block index is not a startup error: candidate
5123+
// admission and CheckBlockIndex tolerate a null snapshot base.
51315124

51325125
std::vector<CBlockIndex*> vSortedByHeight{m_blockman.GetAllBlockIndices()};
51335126
std::sort(vSortedByHeight.begin(), vSortedByHeight.end(),

0 commit comments

Comments
 (0)