Skip to content

fix(archiver): always advance L1-to-L2 messages syncpoint to current L1 block#22154

Merged
spalladino merged 1 commit intomerge-train/spartanfrom
palla/archiver-advance-messages-syncpoint
Mar 31, 2026
Merged

fix(archiver): always advance L1-to-L2 messages syncpoint to current L1 block#22154
spalladino merged 1 commit intomerge-train/spartanfrom
palla/archiver-advance-messages-syncpoint

Conversation

@spalladino
Copy link
Copy Markdown
Contributor

@spalladino spalladino commented Mar 30, 2026

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 currentL1BlockNumber on 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 setInboxTreeInProgress was called before messages were downloaded, allowing concurrent RPC reads to see a checkpoint as sealed before its messages were available. Also, retrieveL1ToL2Message would scan a large block range, as opposed to just using the L1 sync data already stored in the archiver.

Changes

  • archiver: Refactored handleL1ToL2Messages to always advance the syncpoint on success, with rollback-and-retry on mismatch. Merged setInboxTreeInProgress and setMessageSynchedL1Block into a single atomic setMessageSyncState. Re-throws unexpected (non-MessageStoreError) exceptions instead of swallowing them. Updated README to document the new sync logic.
  • archiver (tests): Updated store tests for setMessageSyncState. Improved fake_l1_state to correctly filter messages by block number in getState and support getMessageSentEventByHash.
  • ethereum: Updated InboxContract.getMessageSentEventByHash signature to take (msgHash, l1BlockHash) instead of (hash, fromBlock, toBlock).
  • foundation: Added retryTimes utility function (like retryUntil but with a retry count instead of a timeout).

@spalladino spalladino added ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure backport-to-v4-next labels Mar 30, 2026
@spalladino spalladino marked this pull request as draft March 30, 2026 19:35
…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>
@spalladino spalladino force-pushed the palla/archiver-advance-messages-syncpoint branch from 2d4461c to 77c7876 Compare March 30, 2026 21:52
@spalladino spalladino marked this pull request as ready for review March 30, 2026 21:55
name = '',
maxRetries: number,
retryInterval = 1,
) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised nothing else fit :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about trying to overload retryUntil, but this was cleaner

@spalladino spalladino merged commit cc3a64c into merge-train/spartan Mar 31, 2026
26 checks passed
@spalladino spalladino deleted the palla/archiver-advance-messages-syncpoint branch March 31, 2026 19:27
@AztecBot
Copy link
Copy Markdown
Collaborator

❌ Failed to cherry-pick to v4-next due to conflicts. (🤖) View backport run.

AztecBot pushed a commit that referenced this pull request Mar 31, 2026
AztecBot added a commit that referenced this pull request Mar 31, 2026
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>
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-to-v4-next ci-no-fail-fast Sets NO_FAIL_FAST in the CI so the run is not aborted on the first failure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants