Repository navigation
fix(rpc): verifychain false failures on chains with spends - #21
Merged
Merged
Conversation
The verifychain RPC was incorrectly returning false/invalid on valid chains containing non-coinbase spends. The issue was that verify_chain loaded the current tip UTXO set and then tried to validate blocks that were already applied to that set. Changes: - Levels 0-3: Only perform header/merkle/linkage checks, no UTXO validation - Level 4: Properly rewind UTXO set using undo logs before reconnecting blocks - Add detailed docstring explaining Bitcoin Core checklevel semantics - Feature-gate level 4 UTXO validation under 'production' feature Test: - Add test_verify_chain_with_spends_returns_true that creates a chain with non-coinbase spends and verifies that verifychain returns true at all levels Closes #10 Co-authored-by: Secure Sovereign <secsovereign@users.noreply.github.com>
Level 4 undo log rewind: - Use correct disconnect order: remove new_utxo first, then restore previous_utxo - This matches blvm_consensus::reorganization disconnect_block semantics Level 4 MTP fix: - Use headers_before_height_for_mtp(height) for per-block MTP - Previously used tip-relative MTP which was incorrect during replay Test improvements: - Fix BIP34 height encoding (height 0 = OP_0 + padding) - Simplify level 4 test to use coinbase-only blocks (avoids 100-block maturity requirement for spending coinbase outputs) - Test verifies undo log rewind + block replay mechanics Closes #10 Co-authored-by: Secure Sovereign <secsovereign@users.noreply.github.com>
secsovereign
marked this pull request as ready for review
October 6, 2026 22:07
Co-authored-by: Secure Sovereign <secsovereign@users.noreply.github.com>
Change from two-pass (all removes then all restores) to one-pass-per-entry
matching blvm_consensus::reorganization::disconnect_block exactly:
for entry in undo_log.entries.iter() {
if entry.new_utxo.is_some() { remove }
if entry.previous_utxo.is_some() { restore }
}
This correctly handles same-block create→spend: restore wins over remove
when operating on the same outpoint.
Co-authored-by: Secure Sovereign <secsovereign@users.noreply.github.com>
Co-authored-by: Secure Sovereign <secsovereign@users.noreply.github.com>
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.
Summary
Fix
verifychainRPC returning false/invalid on valid chains containing non-coinbase spends.Root cause:
verify_chainwas loading the current tip UTXO set and then validating blocks that were already applied to that set - causing spends to fail because inputs were already consumed and outputs already existed.Changes
Levels 0-3: Header/Merkle/Linkage Only
Level 4: Full UTXO Validation with Undo Log Rewind
blvm_consensus::reorganization::disconnect_block:headers_before_height_for_mtp(height)(not tip-relative)Tests
test_verify_chain_with_spends_returns_true: Levels 1-3 pass on chain with spendstest_verify_chain_level4_with_undo_logs: Level 4 with proper undo log rewind (feature-gated with production)Closes #10