fix(archiver): always advance L1-to-L2 messages syncpoint to current L1 block#22154
Merged
spalladino merged 1 commit intomerge-train/spartanfrom Mar 31, 2026
Merged
Conversation
…L1 block The messages syncpoint used to track the L1 block of the last downloaded message, causing unnecessary re-scans when no messages were sent for a long time. Now it always advances to currentL1BlockNumber, with the rolling hash check and rollback logic providing reorg protection. Also moves setInboxTreeInProgress to after message insertion to prevent concurrent reads from seeing a checkpoint as sealed before its messages are available, and fixes a pre-existing division by zero in metrics when a batch has no messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2d4461c to
77c7876
Compare
ludamad
reviewed
Mar 31, 2026
| name = '', | ||
| maxRetries: number, | ||
| retryInterval = 1, | ||
| ) { |
Collaborator
There was a problem hiding this comment.
I'm surprised nothing else fit :)
Contributor
Author
There was a problem hiding this comment.
I thought about trying to overload retryUntil, but this was cleaner
PhilWindle
approved these changes
Mar 31, 2026
Collaborator
|
❌ Failed to cherry-pick to |
AztecBot
pushed a commit
that referenced
this pull request
Mar 31, 2026
…t to current L1 block (#22154)
github-merge-queue Bot
pushed a commit
that referenced
this pull request
Apr 1, 2026
BEGIN_COMMIT_OVERRIDE chore: (A-771) remove dead code, verify keypair (#22167) fix(aes128): validate PKCS#7 padding in decryptBufferCBC (#22179) chore: (A-815) fix l1 tx utils fallback id logic (#22187) fix(archiver): always advance L1-to-L2 messages syncpoint to current L1 block (#22154) chore: (A-832) fix defaultFetch double consuming response on JSON parse failure (#22194) fix: indefinite retry for prover node and agent broker communication (#22202) fix: remove unused createDispatchFn with no method allowlist (#22219) chore: fix wallet setup to use NO_FROM instead of ZERO address (#22222) fix: update aes128 bad-key test for PKCS#7 padding validation (#22190) END_COMMIT_OVERRIDE
spalladino
added a commit
that referenced
this pull request
Apr 16, 2026
…L1 block (backport #22154) The messages syncpoint used to track the L1 block of the last downloaded message, causing unnecessary re-scans when no messages were sent for a long time. Now it always advances to currentL1BlockNumber, with the rolling hash check and rollback logic providing reorg protection. Also moves setInboxTreeInProgress to after message insertion to prevent concurrent reads from seeing a checkpoint as sealed before its messages are available, and fixes a pre-existing division by zero in metrics when a batch has no messages. NOTE: Cherry-picked with conflicts still present; resolved in following commit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
spalladino
added a commit
that referenced
this pull request
Apr 16, 2026
v4 has no setInboxTreeInProgress/treeInProgress persistence concept, so: - simplify setMessageSyncState to take only l1Block (drop treeInProgress param) - drop the tree-in-progress guard tests that don't apply to v4 - keep the improved fake_l1_state getState that computes treeInProgress from checkpoint/message visibility (InboxContractState.treeInProgress is still returned by the real inbox contract in v4) - drop getInboxTreeInProgress from message_store Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Apr 16, 2026
spalladino
added a commit
that referenced
this pull request
Apr 21, 2026
When rolling back local L1 to L2 messages, we query each message against L1 by fetching its log. Since #22154 (v5) this was done via blockHash. However, querying logs by blockhash throws an RPC error if the block no longer exists, which is likely if the local message was removed due to an L1 reorg. We never hit this during testing because of foundry-rs/foundry#14371. To fix this, we know query by an L1 block number range. This also allows to still find the locall message on L1 even if it was moved by a few blocks due to a small reorg. Additionally, this PR adds a fast-path in `rollbackL1ToL2Messages` that matches the local rolling hash against the current remote state, so we don't query by event when we don't need to.
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.
Motivation
The L1-to-L2 messages syncpoint tracked the L1 block of the last downloaded message. If no messages were sent for a long time, the syncpoint got stuck and the next non-empty sync iteration re-scanned old block ranges. The rolling hash check and rollback logic already handle L1 reorgs, making this conservative syncpoint advancement redundant.
Approach
The syncpoint now always advances to
currentL1BlockNumberon success. After downloading, local state is verified against L1; on mismatch the syncpoint rolls back and the operation retries (up to 3 times within the same L1 sync iteration).Extras
Method
setInboxTreeInProgresswas called before messages were downloaded, allowing concurrent RPC reads to see a checkpoint as sealed before its messages were available. Also,retrieveL1ToL2Messagewould scan a large block range, as opposed to just using the L1 sync data already stored in the archiver.Changes
handleL1ToL2Messagesto always advance the syncpoint on success, with rollback-and-retry on mismatch. MergedsetInboxTreeInProgressandsetMessageSynchedL1Blockinto a single atomicsetMessageSyncState. Re-throws unexpected (non-MessageStoreError) exceptions instead of swallowing them. Updated README to document the new sync logic.setMessageSyncState. Improvedfake_l1_stateto correctly filter messages by block number ingetStateand supportgetMessageSentEventByHash.InboxContract.getMessageSentEventByHashsignature to take(msgHash, l1BlockHash)instead of(hash, fromBlock, toBlock).retryTimesutility function (likeretryUntilbut with a retry count instead of a timeout).