#36543 validation: check the most recent AssumeUTXO commitment during IBD

ReviewabilityReviewsAgreementSize
#36543 l0rinc validation: check the most recent AssumeUTXO commitment during IBDWaiting on author0Blocked110 + 106 tests
  • Audit hardcoded AssumeUTXO snapshot commitments during standard IBD
  • Crowdsource verification of baked-in snapshot hashes against chain history
  • Ready to review
  • Concept approval for crowdsourced verification during IBD (optout21, Sjors)
  • Concept approval without stated reasons (fametrano)
  • Unaddressed objection: shutdown on mismatch acts as an unsafe checkpoint (Sjors)
  • Unaddressed objection: assertion crash leaves state inconsistent and restart bypasses check (fametrano)
  • Unaddressed objection: crashing IBD penalizes verified nodes without protecting snapshot users (ajtowns)
  • 110 lines added or modified outside tests
  • 106 lines added or modified in tests
  • 220 lines removed in total
  • 17 files, 7 commits
Validation#25 of 53
P2 · new feature
  • P2 because it crowdsources verification of hardcoded AssumeUTXO snapshot commitments
  • Closes a trust gap by having every full node validate baked-in hashes against history during IBD
  • Ranking pass: Moved up: closes a real trust gap in hardcoded snapshot commitments, comparable to other assumeutxo correctness 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

Verifies the hardcoded AssumeUTXO commitment during normal Initial Block Download when block connection reaches the snapshot height and block hash. Pending UTXO modifications are synchronously flushed to disk, the serialized UTXO set is hashed, and a mismatch or failure causes the node to shut down with a fatal error. To prevent repeated multi-minute hashing passes during IBD, chainparams is simplified to store only the single most recent AssumeUTXO commitment per network, deprecating older snapshot activations.

Problem: AssumeUTXO relies on hardcoded snapshot hashes compiled into the node binary. Even though nodes running standard IBD independently reconstruct the exact UTXO set from genesis, they never compare it against the hardcoded commitment, passing up crowd-sourced verification of baked-in snapshot commitments against history (#32377).

Evidence of importance:

  • Linked issue #32377 ('AssumeUTXO: crowdsource trust through independent snapshot verification') notes that every syncing full node could automatically audit hardcoded snapshot hashes during standard IBD.
  • Commit 36a2a70452 explains: 'This checks the developer-provided commitment against the UTXO set that every node reconstructs during IBD (see #32377).'

Scope: Retaining only the single latest snapshot commitment is a breaking change for loading older AssumeUTXO snapshots or restarting snapshot chainstates built against retired commitments.

Risk of a mistake: medium (validation). It inserts a synchronous disk flush, multi-minute UTXO hashing pass, and potential fatal error exit into ConnectTip during normal block validation.

Changed since the previous assessment: Propagates snapshot verification errors out of ConnectTip as runtime errors instead of reporting success, and refines interruption handling so interrupted hashing during shutdown is not recorded as a validation failure.

Reviewability

Paused · Waiting on author

Open objections from Sjors, ajtowns, fametrano with no author reply for 7 days; review would repeat what has been asked.

Waiting on (from the thread read):

  • author: addressing objections and suggestions from Sjors, optout21, ajtowns, and fametrano's assert bug report 2026-10-25

Agreement

Blocked

objection that needs a change, nobody has replied (Sjors, fametrano)

Thread notes: fametrano gave a Concept ACK but reported a concrete correctness objection: an assertion failure occurs when the check fails because coins update before the chain tip, which also allows a restart to skip the check.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
Sjors (member)objection, safetyStopping the node on a mismatch risks introducing an effective checkpoint that prevents normal sync if the snapshot commitment is maliciousopenchangedno2026-10-17: 'I think this risks introducing a new effective checkpoint. If the snapshot were malicious, normal users couldn't sync'
Sjors (member)suggestion, scopeLimit the scope of the PR by checking the latest hash without deleting the older commitments yetopenansweredno2026-10-17: 'Maybe limit the scope of this PR by only _checking_ the latest hash, but not (yet) deleting the other hashes.'
Sjors (member)suggestion, maintenanceProvide benchmark numbers in the PR description showing minimal performance impactopenansweredno2026-10-17: 'It would be good to provide some numbers in the PR description.'
Sjors (member)question, correctnessHow does flushing chainstate to disk before hashing interact with current IBD flush frequency?openansweredno2026-10-17: 'I'm not up to speed on how often and when we flush the chainstate to disk during IBD nowadays. How does this interact with that?'
optout21 (contributor)suggestion, interfaceAdd a configuration option to bypass or ignore the AssumeUTXO hash checkopenansweredno2026-10-17: 'Introduce an option to skip the new AssumeUTXO hash check (may be a hidden option)'
optout21 (contributor)suggestion, scopeKeep non-latest AssumeUTXO commitments in source for visibility instead of dropping themopenansweredno2026-10-17: 'So not checking the non-latest hashes is fine, but it's useful to keep them for visibility.'
ajtowns (member)question, maintenanceWhat is the performance impact when hitting an AssumeUTXO commitment block during validation?openansweredno2026-10-24: 'What's the performance impact when hitting such a block?'
ajtowns (member)objection, safetyCrashing an IBD node on snapshot mismatch penalizes nodes with fully verified valid data while failing to protect snapshot users from following an incorrect chainopenansweredno2026-10-24: 'Doesn't this make the result of a release including bad snaphot data worse for everyone -- Alice who does IBD has her node crash despite having good data that she fully verified, and Bob who uses the '
ajtowns (member)suggestion, approachConsider predictable snapshot points (e.g. BIP 452) or including the block's muhash in the AssumeUTXO commitment to make verification easier and less disruptiveopenansweredno2026-10-24: 'Having predictable snapshot points (every 14112 blocks [per bip452]) would allow every node to calculate the appropriate hash... Including the block's muhash in the assumeutxo set would also probably '
fametrano (contributor)objection, correctnessA node failing the check aborts on an assertion due to inconsistent chainstate/coins tip, and a plain restart syncs past the commitment without checking it againopenchangedno2026-10-25: 'a node that fails the new check aborts on an assertion, and a plain restart then syncs past the commitment without checking it again'

Support:

  • Sjors (member) (Concept ACK, 2026-10-17): see #32377, with two caveats
  • optout21 (contributor) (Concept ACK, 2026-10-17): As there is a hash provided that requires trust, the more checks the better. It makes sense to use all nodes performing IBD to also perform this check, as it's relatively cheap to do.
  • fametrano (contributor) (Concept ACK, 2026-10-25) [both: ConnectTip, ConnectBlock, CheckBlockIndex, feature_assumeutxo.py]: (no reason given) [not substantive]

Participants:

  • Sjors (member, objection, 1 statements 2026-10-17 to 2026-10-17): Concept ACK with caveats; objects to stopping on mismatch as an effective checkpoint, suggests keeping older commitments, and asks about flushing
  • optout21 (contributor, support, 1 statements 2026-10-17 to 2026-10-17): Concept ACK; suggests an option to skip the check and keeping older commitments for visibility
  • ajtowns (member, objection, 1 statements 2026-10-24 to 2026-10-24): objects that crashing IBD on mismatch makes bad snapshot releases worse for everyone, asks about performance impact, and suggests alternative approaches
  • fametrano (contributor, objection, 1 statements 2026-10-25 to 2026-10-25): Concept ACK, but objects to assertion failure on mismatch leaving coins cache and chain tip out of sync, allowing restarts to bypass the check

Files

145 lines under test/bench/ci.

  • src/kernel/chainparams.cpp +21/-116
  • src/validation.cpp +48/-31
  • src/test/validation_chainstatemanager_tests.cpp +55/-9
  • src/test/validation_tests.cpp +5/-17
  • src/test/fuzz/utxo_snapshot.cpp +14/-6
  • src/test/util/setup_common.cpp +18/-2
  • doc/assumeutxo.md +15/-1
  • src/kernel/chainparams.h +3/-11
  • src/util/vector.h +0/-12
  • test/functional/feature_assumeutxo.py +7/-5
  • doc/release-notes-assumeutxo-latest-snapshot.md +11/-0
  • src/rpc/blockchain.cpp +2/-5
  • src/test/util/setup_common.h +7/-0
  • src/validation.h +6/-0
  • src/node/blockstorage.cpp +2/-3
  • doc/release-process.md +1/-1
  • src/external_signer.cpp +1/-1

Card

The short text the ranking pass compares across PRs.

This PR verifies the hardcoded AssumeUTXO snapshot hash during standard Initial Block Download when block connection reaches the commitment height, triggering a fatal error and node shutdown on a mismatch. Full nodes independently rebuild the UTXO set from genesis during IBD, but previously never checked whether their reconstructed UTXO set matched the baked-in commitments (#32377). To avoid multiple expensive UTXO hashing passes during IBD, chainparams is changed to retain only the single latest AssumeUTXO commitment per network, retiring support for loading older snapshots.

Data

dossier JSON · extract JSON · model ledger, generated 2026-10-26T01:22, confidence high, input hash e23d1c518a967867
thread read through 2026-10-25 (4 statements), head 97b2138e39
labels: Validation

Categories

Validation

P2 · new feature (ranking pass: Moved up: closes a real trust gap in hardcoded snapshot commitments, comparable to other assumeutxo correctness work)

Crowdsources verification of baked-in snapshot commitments against history during standard IBD. As noted in #32377, full nodes currently reconstruct the full UTXO set without auditing hardcoded AssumeUTXO commitments, leaving a trust gap in snapshot validation.

Membership: Has the Validation label and modifies block connection and chainstate flushing logic in src/validation.cpp to audit AssumeUTXO commitments during IBD.

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