Skip to content

execution: preserve parent-chain blockhash transitions - #4720

Draft
exocognosis wants to merge 1 commit into
OffchainLabs:masterfrom
exocognosis:agent/prevent-stale-l1-blockhashes
Draft

execution: preserve parent-chain blockhash transitions#4720
exocognosis wants to merge 1 commit into
OffchainLabs:masterfrom
exocognosis:agent/prevent-stale-l1-blockhashes

Conversation

@exocognosis

Copy link
Copy Markdown

Summary

Prevent the sequencer from skipping parent-chain blockhash transitions when its header reader observes a jump in the L1 block number.

This change:

  • reads the parent-chain block number serialized in the previous L2 header
  • limits each newly sequenced L2 block to one parent-chain block of advancement
  • lets subsequent L2 blocks catch up in order when the reader has missed multiple L1 headers
  • adds table-driven coverage for normal progression, skipped observations, legacy headers, lower observations, and the maximum block number boundary
  • adds a release-note fragment for the fix

Problem

If the previous L2 header records parent-chain block N and the header reader next observes N+2, the sequencer currently places N+2 directly in the next incoming message. ArbOS then associates the previous L2 block hash with parent-chain block N+1. The ring-buffer entry for block N is never updated, so an older value can remain in that slot and reappear after the 256-entry ring wraps.

Lowering the header reader polling interval reduces how often this happens, but it does not guarantee that every intermediate header will be observed. Network delays and temporary reader stalls can still produce jumps.

Solution

Before constructing the sequencer message header, compare the latest observed parent-chain block number with the number stored in the previous L2 header. When the observation is more than one block ahead, use previous + 1 for the new message. If the observation remains ahead, each following L2 block advances one more step until the sequencer catches up.

For example, an observation jump from N to N+2 now produces transitions through N+1 and then N+2. ArbOS receives the previous L2 block hash for each transition and updates the corresponding ring-buffer slots in order.

Normal one-block progress, unchanged observations, and lower observations keep their existing behavior. Headers without ArbOS metadata also keep the existing behavior for compatibility.

Consensus considerations

Changing ApplyInternalTxUpdate directly would alter the ArbOS state transition for historical input and would require an ArbOS version gate plus coordinated activation. This change avoids that consensus risk by correcting the sequencer-produced input before it enters deterministic execution. Validators continue to replay the exact incoming message chosen by the sequencer.

After a missed observation, the parent-chain number exposed by newly produced L2 blocks can temporarily trail the reader's latest observation. It catches up by one parent-chain block per produced L2 block. Existing stale ring-buffer entries are not rewritten, but they age out as the ring advances. The change prevents new gaps on the sequencer path described in the issue.

Validation

  • go test ./execution/gethexec -run '^TestNextSequencerParentChainBlockNumber' -count=1
  • go run ./linters ./execution/gethexec
  • go vet ./execution/gethexec
  • git diff --check

Fixes #4718

@CLAassistant

CLAassistant commented Aug 4, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inaccurate L1 tip in L2 block construction leads to stale L2 blockhashes being included in the blockhash ring buffer

2 participants