#36452 validation: fix false corruption errors after pruning or AssumeUTXO

ReviewabilityReviewsAgreementSize
#36452 l0rinc validation: fix false corruption errors after pruning or AssumeUTXOReady0Crickets11 + 20 tests
  • Prevent false database corruption errors and failed restarts on pruned nodes and AssumeUTXO snapshots
  • Treat missing block undo records as unavailable history rather than corruption during chain verification
  • Reviewable now; no open blockers or rebases invalidate review
  • No review verdicts recorded
  • No formal approvals or objections recorded yet
  • Verified through extensive testing on Linux aarch64 (cyb3ralbert)
  • Questions open on AssumeUTXO scope and interaction with #35307 on verifychain behavior (cyb3ralbert)
  • Clarified how this can trigger under default checks with AssumeUTXO (andrewtoth)
  • 11 lines added or modified outside tests
  • 20 lines added or modified in tests
  • 5 lines removed in total
  • 3 files, 3 commits
Validation#7 of 53
P2 · bug fix
  • P2 because it fixes false corruption reports that abort startup when refetched blocks lack undo data
  • Prevents spurious node restart failures and unblocks pending pruneassumevalid and pruned txindex work
  • Ranking pass: Moved up: concrete startup-blocking false-corruption bug on pruned/assumeutxo nodes, and it unblocks pruneassumevalid and pruned-txindex work
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Stops chain verification in CVerifyDB::VerifyDB early when deep verification checks encounter missing block undo data on pruned nodes or AssumeUTXO snapshot chainstates. Missing undo data is treated as unavailable history rather than a database corruption failure, returning an incomplete verification status. This allows nodes to restart cleanly and run verifychain even if pruned blocks have been refetched without undo records.

Problem: Refetching a pruned block via getblockfrompeer restores the block body but not its undo data. When startup checks or the verifychain RPC run at check level 3 or higher, the node attempts to disconnect blocks to verify UTXO manipulation, encounters missing undo records, falsely reports database corruption, and aborts startup.

Evidence of importance:

  • PR description: 'getblockfrompeer restores a pruned block\'s body without recreating its undo record. If startup verification reaches that block at level >2, it attempts to disconnect it and reports database corruption, preventing the node from restarting.'
  • PR description notes it arose during pruned txindex review (#36002) and is required for pending pruneassumevalid work.

Risk of a mistake: medium (validation). A mistake in CVerifyDB could prematurely stop verification of actually corrupted chainstates during node startup or verifychain calls.

Changed since the previous assessment: The previous description was generated without a patch; this version confirms the implementation in CVerifyDB::VerifyDB and the addition of functional regression tests for AssumeUTXO snapshots and getblockfrompeer.

Reviewability

Ready

Nothing known that would invalidate a review now.

Waiting on (from the thread read):

  • author: answer cyb3ralbert's questions about AssumeUTXO scope and interaction with #35307 2026-10-28

Agreement

Crickets

no substantive comment either way

Thread notes: cyb3ralbert tested extensively on Linux aarch64 and asked two questions about AssumeUTXO startup scope and the conflict/interaction with #35307 regarding verifychain()'s return value.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
andrewtoth (member)question, correctnessCan this bug realistically be triggered with default checkblocks=6?answered · author confirmed for ordinary pruning, but explained it can trigger under AssumeUTXO with default checksansweredyes2026-10-07: 'IIUC this bug can't realistically be triggered with default `checkblocks=6` config.'
Status from: 2026-10-08: l0rinc: 'that’s right for ordinary pruning, but this can also happen with default checks under AssumeUTXO'
cyb3ralbert (contributor)question, scopeIs the AssumeUTXO part of this PR meant to make startup verification stop erroring on a snapshot base block missing undo data, leaving the subsequent startup abort to #35307?openansweredno2026-10-28: 'Is the AssumeUTXO part of this PR meant to make startup verification stop erroring on such a node, with the restart itself left to #35307?'
cyb3ralbert (contributor)question, interfaceWhich verifychain() return value is intended at the snapshot base once both this PR and #35307 land, since the ordering of their checks determines the result?openansweredno2026-10-28: 'Which value is intended once both land?'

Participants:

  • andrewtoth (member, question, 1 statements 2026-10-07 to 2026-10-07): asked whether the bug can realistically trigger under default checkblocks
  • cyb3ralbert (contributor, question, 1 statements 2026-10-28 to 2026-10-28): tested on aarch64; asked about AssumeUTXO scope and interaction with #35307

Dependencies

Enables:

  • pruneassumevalid
  • pruned txindex (#36002)

Files

20 lines under test/bench/ci.

  • src/validation.cpp +11/-5
  • test/functional/rpc_getblockfrompeer.py +15/-0
  • test/functional/feature_assumeutxo.py +5/-0

Card

The short text the ranking pass compares across PRs.

Stops chain verification from falsely reporting database corruption when startup checks or verifychain encounter missing undo data on refetched pruned blocks or AssumeUTXO snapshot chainstates. Using getblockfrompeer downloads a pruned block body without undo data, causing verification at level 3 or 4 to treat missing undo records as database corruption and prevent the node from starting. The fix treats missing undo data as unavailable history, returning incomplete verification status rather than aborting. This bug was found during review of pruned txindex (#36002) and unblocks pending pruneassumevalid changes.

Data

dossier JSON · extract JSON · model ledger, generated 2026-10-29T01:23, confidence high, input hash 1fa1807d1f078439
thread read through 2026-10-28 (3 statements), head e262a1fbf7
labels: Validation

Categories

Validation

P2 · bug fix (ranking pass: Moved up: concrete startup-blocking false-corruption bug on pruned/assumeutxo nodes, and it unblocks pruneassumevalid and pruned-txindex work)

Fixes false database corruption errors and prevented node restarts when startup checks encounter missing block undo data on pruned nodes or AssumeUTXO chainstates. When blocks are refetched without undo data, verification at check level >2 'reports database corruption, preventing the node from restarting', which directly impacts chainstate integrity reporting and node reliability.

Membership: Labeled 'Validation' and alters chainstate verification logic in src/validation.cpp (CVerifyDB::VerifyDB).

Factors: security/stability 2, bug 2, performance 0, user value 1, leverage 1