Repository navigation
Conversation
…at startup Parallel IBD before the undo fix stored empty BlockUndoLogs. A reorg over those blocks restored nothing and left the UTXO set wrong, with no message. Check the last 100 blocks at startup and log what happened and how to recover; refuse a reorg whose disconnected blocks have missing or empty undo data.
This was referenced Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Before the parallel-IBD undo fix (now on blvm-consensus
mainas 59357b7, the change BTCDecoded/blvm-consensus#22 proposed), parallel IBD stored an emptyBlockUndoLogfor every block it connected. Upgrading the binary doesn't repair data that's already on disk. On such a node, a reorg over those blocks:and logs nothing about it.
A correct undo log is never empty: the coinbase always creates at least one output, and every created output is recorded (
apply.rs). So "missing or empty" pins down exactly this damage.Fix (Malmi lens: tell the operator, no silent failure)
New
node::undo_checkmodule:Startup:
check_recent_undo_at_startupchecks the undo logs of the last 100 blocks (coinbase-maturity depth, never genesis). It only reads undo logs, not blocks.error!with:-reindexyet)info!line.Reorg: before
reorganize_chain_with_witnesses,try_activate_heavier_forkchecks every block it would disconnect (everything above the common ancestor). If any has missing or empty undo data, it refuses with an error that names:This happens before the UTXO set is touched, so the node stays on its chain with its UTXO set intact.
Wired in
start_componentsandreorg_executor.rs. Everything isproduction-gated, like the undo storage it reads.Tests
tests/fork_reorg_regtest.rs(end to end throughSyncCoordinator::process_block):build_fork()/import_fork(); its behaviour is unchanged.heavier_fork_over_empty_undo_logs_is_refused: mine main chain 1..=12, overwrite undo for heights 5..=12 with an empty log (the old-IBD state), then import a heavier fork that diverges at 5. The tip must stay on main and the stored UTXO set must be unchanged.left: [31,109,…]fork tip vsright: [67,183,…]main tip).tests/undo_startup_check.rs(6 tests, all pass on the branch). This file doesn't compile on main, because the check doesn't exist there.Refusing reorg of depth 3 … height 28 … resync) and on missing undoAlso green:
fork_reorg_equal_work,fork_reorg_events,cargo test --lib reorg,cargo clippy --lib --test undo_startup_check,cargo fmt.Reviewer notes
verifychainlevel 4 already reports missing undo, but it doesn't flag empty logs. I left it alone.Merge order
main(59357b7), which supersedes fix(consensus): build the undo log on the parallel IBD connect path blvm-consensus#22. Ship this in the same node release that picks up that consensus version, so upgraded nodes get the warning.blockchain_rpc_tests.rs), so any order works.