cl/persistence: fix caplin historical state reconstruction loop at bellatrix transition#22345
Merged
domiwei merged 4 commits intoJul 10, 2026
Conversation
domiwei
approved these changes
Jul 9, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes Caplin historical state reconstruction getting stuck at the Bellatrix fork boundary by skipping Execution Layer (EL) transaction/withdrawal lookups when the execution payload header indicates execution is not enabled (zero BlockHash).
Changes:
- Add an early-return in
ReadBlockFromSnapshotfor post-Altair blocks with a zero executionBlockHash, avoiding EL lookups for pre-Merge Bellatrix blocks. - Add a regression test ensuring EL lookups are skipped for a pre-Merge Bellatrix block (prevents the infinite retry loop reported in #22337).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
cl/persistence/format/snapshot_format/blocks.go |
Skips EL transaction/withdrawal fetch when the blinded block’s execution BlockHash is zero (pre-Merge Bellatrix payload header). |
cl/persistence/format/snapshot_format/blocks_test.go |
Adds regression test that fails if ReadBlockFromSnapshot attempts an EL lookup for a zero-hash Bellatrix execution payload. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
domiwei
approved these changes
Jul 10, 2026
2 tasks
yperbasis
pushed a commit
that referenced
this pull request
Jul 10, 2026
…p at bellatrix transition (#22370) ## Summary Cherry-pick of #22345 to `release/3.5`. - Pre-Merge Bellatrix blocks carry a default (all-zero) execution payload header — `ReadBlockFromSnapshot` now detects the zero `BlockHash` and skips the EL transaction lookup, preventing an infinite retry loop during historical state reconstruction at the Bellatrix transition. ## Test plan - [x] `TestPreMergeBellatrixBlockSkipsExecutionLookup` passes - [x] `make lint` clean Co-authored-by: Sahil Sojitra <sahilsojitra4555@gmail.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.
What was the issue?
The first Bellatrix-era slot is
4,636,672. Since the Merge did not happen yet at this point, this block has an empty execution payload header withBlockHash = 0x000...000andBlockNumber = 0.Previously, if the block version was post-Altair, we were unconditionally trying to fetch EL transactions. This means we queried
executionReader.Transactions(0, 0x00...).Because of a recent change (commit
04d330df0bwhich routes block0queries to the database instead of snapshots), this lookup went to the DB. Since the database requires a matching hash and the zero hash doesn't match our real genesis block hash, it returnednil, throwing the error:transactions not found for block 0. This caused the antiquary loop to crash and rollback to the previous checkpoint, looping forever.What is the fix?
We added a simple check to check if the execution payload
blockHashis the zero hash. If it is, this is a pre-Merge block where execution is not yet active under consensus rules, so we skip the EL transaction/withdrawal lookup completely.Checking the block hash instead of the block number also keeps custom networks safe where execution block
0can have a valid non-zero block hash.closes #22337