fix: clamp finalized block to oldest available in world-state#21643
Merged
PhilWindle merged 2 commits intomerge-train/spartanfrom Mar 17, 2026
Merged
fix: clamp finalized block to oldest available in world-state#21643PhilWindle merged 2 commits intomerge-train/spartanfrom
PhilWindle merged 2 commits intomerge-train/spartanfrom
Conversation
PR #21597 increased the finalized block lookback from epochDuration*2 to epochDuration*2*4. This caused the finalized block number to jump backwards past blocks that had already been pruned from world-state, causing advance_finalized_block to fail with 'Failed to read block data'. Two fixes: 1. TypeScript: clamp blockNumber to oldestHistoricalBlock before calling setFinalized, so we never request a pruned block. 2. C++: reorder checks in advance_finalized_block to check the no-op condition (already finalized past this block) before attempting to read block data. This makes the native layer resilient to receiving a stale finalized block number.
…uned blocks Tests that handleBlockStreamEvent with chain-finalized for a block older than the oldest available block does not throw, validating the clamping fix in handleChainFinalized.
spalladino
approved these changes
Mar 17, 2026
PhilWindle
approved these changes
Mar 17, 2026
This was referenced Mar 17, 2026
AztecBot
pushed a commit
that referenced
this pull request
Mar 17, 2026
## Summary PR #21597 increased the finalized block lookback from `epochDuration*2` to `epochDuration*2*4`, which caused the finalized block number to jump backwards past blocks already pruned from world-state. The native `advance_finalized_block` then failed trying to read pruned block data, crashing the block stream with: ``` Error: Unable to advance finalized block: 15370. Failed to read block data. Tree name: NullifierTree ``` Two fixes: - **TypeScript** (`server_world_state_synchronizer.ts`): Clamp the finalized block number to `oldestHistoricalBlock` before calling `setFinalized`, so we never request a pruned block. - **C++** (`cached_content_addressed_tree_store.hpp`): Reorder checks in `advance_finalized_block` to check the no-op condition (`finalizedBlockHeight >= blockNumber`) before attempting `read_block_data`. This makes the native layer resilient to stale finalized block numbers. Full analysis: https://gist.github.com/AztecBot/6221fb074ed7bbd8a753ec3602133b42 ClaudeBox log: https://claudebox.work/s/8e97449f22ba9343?run=1
Collaborator
Author
|
✅ Successfully backported to backport-to-v4-staging #21651. |
PhilWindle
added a commit
that referenced
this pull request
Mar 17, 2026
…21656) ## Summary Follow-up to #21643. The clamping fix avoided the `setFinalized` error, but the method continued into the pruning logic where `removeHistoricalBlocks` failed with: ``` Unable to remove historical blocks to block number 15812, blocks not found. Current oldest block: 15812 ``` Two changes: - When the finalized block is older than `oldestHistoricalBlock`, return early instead of clamping and continuing. There's nothing useful to do — world-state is already finalized past this point. - Guard `removeHistoricalBlocks` against being called with a block `<= oldestHistoricalBlock`, which the C++ layer rejects. The C++ reorder fix from #21643 is preserved. ClaudeBox log: https://claudebox.work/s/8e97449f22ba9343?run=4
AztecBot
pushed a commit
that referenced
this pull request
Mar 17, 2026
…21656) ## Summary Follow-up to #21643. The clamping fix avoided the `setFinalized` error, but the method continued into the pruning logic where `removeHistoricalBlocks` failed with: ``` Unable to remove historical blocks to block number 15812, blocks not found. Current oldest block: 15812 ``` Two changes: - When the finalized block is older than `oldestHistoricalBlock`, return early instead of clamping and continuing. There's nothing useful to do — world-state is already finalized past this point. - Guard `removeHistoricalBlocks` against being called with a block `<= oldestHistoricalBlock`, which the C++ layer rejects. The C++ reorder fix from #21643 is preserved. ClaudeBox log: https://claudebox.work/s/8e97449f22ba9343?run=4
alexghr
added a commit
that referenced
this pull request
Mar 17, 2026
BEGIN_COMMIT_OVERRIDE fix(aztec-nr): return Option from decode functions and fix event commitment capacity (backport #21264) (#21360) fix: backport #21271 — handle bad note lengths on compute_note_hash_and_nullifier (#21364) fix: not reusing tags of partially reverted txs (#20817) chore: revert accidental backport of #20817 (#21583) feat: Implement commit all and revert all for world state checkpoints (#21532) cherry-pick: fix: dependabot alerts (#21531) fix: dependabot alerts (backport #21531 to v4) (#21592) fix: backport #21443 — Don't update state if we failed to execute sufficient transactions (v4) (#21610) chore: Fix msgpack serialisation (#21612) fix(p2p): fall back to maxTxsPerCheckpoint for per-block tx validation (#21605) chore: merge v4 into backport-to-v4-staging (#21618) fix(revert): avm sim uses event loop again (#21138) (#21630) fix(e2e): remove historic/finalized block checks from epochs_multiple test (#21642) fix: clamp finalized block to oldest available in world-state (#21643) fix: skip handleChainFinalized when block is behind oldest available (#21656) chore: demote finalized block skip log to trace (#21661) fix: off-by-1 in getBlockHashMembershipWitness archive snapshot (backport #21648) (#21663) fix: capture txs not available error reason in proposal handler (#21670) chore: add L1 inclusion time to stg public (#21665) END_COMMIT_OVERRIDE --------- Co-authored-by: Jan Beneš <janbenes1234@gmail.com> Co-authored-by: PhilWindle <60546371+PhilWindle@users.noreply.github.com> Co-authored-by: Phil Windle <philip.windle@gmail.com> Co-authored-by: Santiago Palladino <santiago@aztecprotocol.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: ludamad <adam.domurad@gmail.com> Co-authored-by: Alex Gherghisan <alexghr@users.noreply.github.com>
github-merge-queue bot
pushed a commit
that referenced
this pull request
Mar 18, 2026
BEGIN_COMMIT_OVERRIDE fix(p2p): fall back to maxTxsPerCheckpoint for per-block tx validation (#21605) chore: fixing M3 devcontainer builds (#21611) fix: clamp finalized block to oldest available in world-state (#21643) chore: fix proving logs script (#21335) fix: (A-649) tx collector bench test (#21619) fix(validator): process block proposals from own validator keys in HA setups (#21603) fix: add bounds when allocating arrays in deserialization (#21622) fix: skip handleChainFinalized when block is behind oldest available (#21656) chore: demote finalized block skip log to trace (#21661) fix: skip -march auto-detection for cross-compilation presets (#21356) chore: revert "add bounds when allocating arrays in deserialization" (#21622) (#21666) fix: capture txs not available error reason in proposal handler (#21670) fix: estimate gas in bot and make BatchCall.simulate() return SimulationResult (#21676) fix: prevent HA peer proposals from blocking equivocation in duplicate proposal test (#21673) fix(p2p): penalize peers for errors during response reading (#21680) feat(sequencer): add build-ahead config and metrics (#20779) chore: fixing build on mac (#21685) fix: HA deadlock for last block edge case (#21690) fix: process all contract classes in storeBroadcastedIndividualFunctions (A-683) (#21686) chore: add slack success post on nightly scenario (#21701) fix(builder): persist contractsDB across blocks within a checkpoint (#21520) fix: only delete logs from rolled-back blocks, not entire tag (A-686) (#21687) chore(p2p): lower attestation pool per-slot caps to 2 (#21709) chore(p2p): remove unused method (#21678) fix(p2p): penalize peer on tx rejected by pool (#21677) fix(test): workaround slow mock creation (#21708) fix(sequencer): fix checkpoint budget redistribution for multi-block slots (#21692) fix: batch checkpoint unwinding in handleEpochPrune (A-690) (#21668) fix(sequencer): add missing opts arg to checkpoint_builder tests (#21733) fix: race condition in fast tx collection (#21496) fix: increase default postgres disk size from 1Gi to 10Gi (#21741) fix: update batch_tx_requester tests to use RequestTracker (#21734) chore: replace dead BOOTSTRAP_TO env var with bootstrap.sh build arg (#21744) fix(sequencer): extract gas and blob configs from valid requests only (A-677) (#21747) fix: deflake attempt for l1_tx_utils (#21743) fix(test): fix flaky keystore reload test (#21749) fix(test): fix flaky duplicate_attestation_slash test (#21753) feat(pipeline): introduce pipeline views for building (#21026) END_COMMIT_OVERRIDE
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
PR #21597 increased the finalized block lookback from
epochDuration*2toepochDuration*2*4, which caused the finalized block number to jump backwards past blocks already pruned from world-state. The nativeadvance_finalized_blockthen failed trying to read pruned block data, crashing the block stream with:Two fixes:
server_world_state_synchronizer.ts): Clamp the finalized block number tooldestHistoricalBlockbefore callingsetFinalized, so we never request a pruned block.cached_content_addressed_tree_store.hpp): Reorder checks inadvance_finalized_blockto check the no-op condition (finalizedBlockHeight >= blockNumber) before attemptingread_block_data. This makes the native layer resilient to stale finalized block numbers.Full analysis: https://gist.github.com/AztecBot/6221fb074ed7bbd8a753ec3602133b42
ClaudeBox log: https://claudebox.work/s/8e97449f22ba9343?run=1