refactor(archiver)!: unify L2BlockSource checkpoint lookups via query objects#22933
Merged
PhilWindle merged 1 commit intomerge-train/spartanfrom May 6, 2026
Merged
Conversation
b8c6577 to
928510b
Compare
Base automatically changed from
spl/internal-archiver-api-review
to
merge-train/spartan
May 5, 2026 09:04
… objects Apply the same simplification PR #22809 made to the block-side API to the checkpoint-side API: collapse 9 narrow methods over 4 return shapes into 4 query-shaped methods over 2 return shapes, plus a polymorphic proposed-checkpoint lookup. Tightens the public RPC: removes the 'latest' / 'proposed' alias foot-gun, adds a confirmed->proposed fallback for by-number/by-slot lookups, and rejects incompatible include flags up-front. BREAKING CHANGE: `getCheckpointsDataForEpoch` removed; `'latest'` removed from `CheckpointParameter`; `'proposed'` semantics tightened (was alias for latest confirmed, now strictly the proposed map / proposed-tip with confirmed fallback); `getCheckpoint('proposed', { includeAttestations | includeL1PublishInfo })` and proposed-fallback equivalents now throw `BadRequestError`.
928510b to
069d262
Compare
PhilWindle
approved these changes
May 6, 2026
This was referenced May 6, 2026
PhilWindle
added a commit
that referenced
this pull request
May 6, 2026
PR #22933 (and earlier #22809) reshaped L2BlockSource: getBlockHeader, getCheckpointsForEpoch, and the positional getCheckpoints(from, limit) were removed. L2TipsMemoryStore also gained a required initialBlockHash constructor argument. - getBlockHeader(n) -> (await getBlockData({ number: n }))?.header - getCheckpointsForEpoch(epoch) -> getCheckpoints({ epoch }), with field access moving from .number/.blocks to .checkpoint.number/.blocks - startProof folds the two-call pattern (checkpoints + separate attestations fetch) into one getCheckpoints({ epoch }) call since PublishedCheckpoint already carries attestations per entry - L2TipsMemoryStore initialised in the constructor body with l2BlockSource.getGenesisBlockHash() Test updates mirror the production migration; also restores the beforeEach getBlockData mock to return a header for any block number (the merge resolution had narrowed it to a single block, breaking the checkpoint-driven flow tests).
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
Clean up the checkpoint side of
L2BlockSource. PR #22809 already collapsed the block-side API into 4 query-shaped methods over 2 return types; the checkpoint surface was left with the pre-refactor sprawl (9 narrow methods over 4 return shapes, parallel by-number / by-range / by-epoch entrypoints, and a wire-level alias that conflated proposed and confirmed checkpoints). This change applies the same simplification.Fixes A-979
Approach
L2BlockSourcecheckpoint methods reduce to 4 query-shaped readers (getCheckpoint,getCheckpoints,getCheckpointData,getCheckpointsData) over 2 return shapes (PublishedCheckpoint,CheckpointData), plus a polymorphicgetProposedCheckpointData(query?)for the proposed-only path. Three new query types live next toBlockQuery/BlocksQuery. On-disk format andBlockStoreprimitives are unchanged — the simplification is at the API boundary. The public RPC'sgetCheckpointkeeps the same wire signature but gains a confirmed→proposed fallback (for{number}/{slot}/'proposed'lookups) andBadRequestErrorguards for incompatibleinclude*flags.API surface change
Methods removed from
L2BlockSourcegetCheckpoints(from, limit),getCheckpointData(n),getCheckpointDataRange(from, limit),getCheckpointsForEpoch(epoch),getCheckpointsDataForEpoch(epoch),getCheckpointNumberBySlot(slot),getLastCheckpoint(),getLastProposedCheckpoint(). Dead methods ondata_source_basealso removed:getCheckpointHeader,getLastBlockNumberInCheckpoint,getSynchedCheckpointNumber.Methods added to
L2BlockSourcePublic RPC (
AztecNode) wire-level changesgetCheckpointsDataForEpoch(epoch)removed;getCheckpointsData(query: CheckpointsQuery)added (range or epoch).'latest'removed fromCheckpointParameter.'proposed'semantics changed: previously aliased to "latest L1-confirmed checkpoint" (a documented foot-gun); nowgetCheckpoint('proposed')strictly targets the proposed-checkpoint store, andgetCheckpointNumber('proposed')returns the proposed-tip number with confirmed fallback.getCheckpoint({ number }) / ({ slot })now check confirmed first then fall back to proposed; tag-based lookups ('checkpointed'/'proven'/'finalized') do not fall back.getCheckpoint('proposed', { includeL1PublishInfo: true | includeAttestations: true })and the same flags on a by-number/by-slot lookup that resolves to a proposed entry now throwBadRequestError(proposed checkpoints have no L1 publish info or attestations).Types kept
CheckpointData,CommonCheckpointData(structural base ofCheckpointData/ProposedCheckpointInput),ProposedCheckpointData,ProposedCheckpointInput,PublishedCheckpoint,Checkpoint. No structural-type deletions.Migration guidance for wallet/SDK consumers is in
docs/docs-developers/docs/resources/migration_notes.md.Changes
CheckpointQuery,CheckpointsQuery,ProposedCheckpointQuery) + Zod schemas inblock/l2_block_source.ts.'latest'literal removed frominterfaces/checkpoint_parameter.ts.NormalizedCheckpointDispatchtype for the server's parameter normalizer.ArchiverApiSchemaandAztecNodeschema updated.computeL2ToL1MembershipWitnessswitched to the new query shape.data_source_baseaddsresolveCheckpointQuery/resolveCheckpointsQuerymirroring the block-side helpers, implements the 4 confirmed methods plus the polymorphic proposed lookup.BlockStoreaddsgetProposedCheckpointBySlot(slot).MockArchiverandmock_l2_block_sourceupdated to match the new interface.server.tsadds the confirmed→proposed fallback flow with the twoBadRequestErrorguards ingetCheckpoint, sources all tips from a singlegetL2Tips()call ingetCheckpointNumber, and routes the public RPC through the new internal methods. New pure-projection helperprojectProposedToCheckpointResponseinblock_response_helpers.ts.getCheckpoints({ epoch })), world-state, slasher, sequencer (checkpoint_proposal_job,sequencer), validator (proposal_handler),L2BlockStream, pxeblock_stream_source, telemetry wrapper, and 10 e2e files updated to the new query shapes.it()blocks covering each query discriminant, the throw guards, the confirmed→proposed fallback, the polymorphicgetProposedCheckpointDatadispatch, andBlockStore.getProposedCheckpointBySlot.migration_notes.mdupdated with the breaking changes for downstream wallet/SDK consumers.