Skip to content

fix(sequencer): enforce build-frame deadlines and align attestation/publish windows#23776

Merged
spalladino merged 3 commits into
merge-train/spartanfrom
spl/timetable-frame-fixes
Jun 3, 2026
Merged

fix(sequencer): enforce build-frame deadlines and align attestation/publish windows#23776
spalladino merged 3 commits into
merge-train/spartanfrom
spl/timetable-frame-fixes

Conversation

@spalladino

@spalladino spalladino commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes timing bugs in block building and validation, now that proposer pipelining is the only production mode. Found via an audit of the sequencer timetable, checkpoint proposal job, validator client, proposal handler, and p2p proposal/attestation validators.

The frame bug (main fix)

Under pipelining the proposer job runs with slotNow = N-1 (build slot) and targetSlot = N. The job passed targetSlot to setState for build-frame states, so Sequencer.setState measured the assertTimeLeft deadlines against getSlotStartBuildTimestamp(targetSlot) — one full Aztec slot (72s) later than the build frame. The build-frame deadlines (INITIALIZING_CHECKPOINT, CREATING_BLOCK, ASSEMBLING_CHECKPOINT, COLLECTING_ATTESTATIONS, PUBLISHING_CHECKPOINT, …) were therefore checked ~72s too late and never fired. Now these states are measured against slotNow. targetSlot is still used for headers, signing, and sendRequestsAt.

Aligning the attestation / publish windows around L1 geometry

  • The checkpoint attestation/publish deadline and the p2p attestation acceptance window are now derived from ethereumSlotDurationone Ethereum slot (12s) before the last L1 block of the target slot, the latest a checkpoint can be submitted and still land on L1 in its slot. Previously the deadline used the configurable l1PublishingTime and the p2p window was only 2 * p2pPropagationTime (~4.5s into the target slot). This also unifies the deadline with the publisher's send lead (sendRequestsAt already targets one Ethereum slot before the target slot start).
  • Validators (in validateCheckpointProposal) keep validating/attesting checkpoint proposals until that L1 publish deadline instead of the target-slot start, so attestations stay useful right up to the proposer's real publish cutoff. Block-proposal re-execution deadlines are intentionally left at the target-slot start.

Why no test caught the frame bug

The job timing test built the job with slotNow === targetSlot (so the two frames coincided) and stubbed setStateFn with a no-op, mocking away the very assertTimeLeft enforcement where the frame matters. This PR adds:

  • A contract test asserting every build-frame state is set against the build slot (slotNow), not the target slot.
  • A behavioral test with a real enforcing setStateFn: a checkpoint whose assembly crosses the build-frame deadline is now correctly abandoned. Both fail on the pre-fix code and pass after the fix.
  • Updated stdlib/timetable, clock-tolerance, attestation-validator, proposal-handler, and validator tests for the realigned windows (including an l1PublishingTime != ethereumSlotDuration case proving the deadline is now Ethereum-slot-based).

No constants were removed and no broader cleanup was done; that is deferred.

Test plan

  • yarn build green; touched packages lint/format clean.
  • @aztec/stdlib timetable, @aztec/sequencer-client (incl. timetable, checkpoint_proposal_job.timing, sequencer-publisher), @aztec/validator-client (incl. proposal_handler, validator), and @aztec/p2p msg_validators suites pass.

@spalladino spalladino force-pushed the spl/timetable-frame-fixes branch from f282249 to 0308462 Compare June 2, 2026 12:03
…ublish windows

Under proposer pipelining the checkpoint proposal job passed `targetSlot` to
`setState` for build-frame states, which made `Sequencer.setState` measure the
state deadlines a full Aztec slot too late (frame B), so they never fired.
Measure build-frame deadlines against `slotNow` (the build slot).

Also align the timing windows around L1 geometry:
- Base the checkpoint attestation/publish deadlines and the p2p attestation
  acceptance window on `ethereumSlotDuration` (12s before the last L1 block of
  the target slot) rather than the configurable `l1PublishingTime`. This unifies
  the deadline with the publisher's send lead, which already targets one Ethereum
  slot before the target slot start.
- Validators keep validating/attesting checkpoint proposals until the L1 publish
  deadline instead of the target-slot start.

Adds regression coverage for the frame bug (build-frame states must be measured
against the build slot) and for the realigned attestation/publish windows.
@spalladino spalladino force-pushed the spl/timetable-frame-fixes branch from 0308462 to 3929940 Compare June 2, 2026 20:31
@spalladino spalladino enabled auto-merge (squash) June 2, 2026 20:31
@AztecBot

AztecBot commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Flakey Tests

🤖 says: This CI run detected 2 tests that failed, but were tolerated due to a .test_patterns.yml entry.

\033FLAKED\033 (8;;http://ci.aztec-labs.com/27ae015d6090578b�27ae015d6090578b8;;�):  yarn-project/end-to-end/scripts/run_test.sh simple src/e2e_epochs/epochs_invalidate_block.parallel.test.ts "proposer invalidates multiple checkpoints" (439s) (code: 0) group:e2e-p2p-epoch-flakes
\033FLAKED\033 (8;;http://ci.aztec-labs.com/125693deaa6fb8bc�125693deaa6fb8bc8;;�): yarn-project/end-to-end/scripts/run_test.sh ha src/composed/ha/e2e_ha_full.test.ts (320s) (code: 0)

@spalladino spalladino merged commit 4d1705f into merge-train/spartan Jun 3, 2026
12 checks passed
@spalladino spalladino deleted the spl/timetable-frame-fixes branch June 3, 2026 02:21
danielntmd pushed a commit to danielntmd/aztec-packages that referenced this pull request Jun 4, 2026
BEGIN_COMMIT_OVERRIDE
chore: deploy next-net and reuse contracts (AztecProtocol#23761)
chore: turn on autoscaling (AztecProtocol#23706)
chore: rename staging-public to staging (AztecProtocol#23767)
chore(p2p): use sync hash for tx validation hashing (AztecProtocol#23768)
test(e2e): wait warmup slots in slashing tests (AztecProtocol#23719)
feat(api)!: make getTxReceipt the single tx-lookup API (AztecProtocol#23660)
fix: cap cloned n_tps fees within sponsored FPC balance (AztecProtocol#23770)
fix: protect HA validator Postgres from cluster scale-down (AztecProtocol#23772)
refactor: remove non-pipelining sequencer code path (AztecProtocol#23665)
feat(archiver): add getL2ToL1MembershipWitness node RPC (AztecProtocol#23646)
fix(p2p)!: revamp BLOCK_TXS validations (AztecProtocol#23778)
chore: name the bots (AztecProtocol#23795)
fix(e2e): ensure BBSync init (AztecProtocol#23793)
fix(p2p)!: fix BLOCK_TXS response under proposer equivocation (AztecProtocol#23786)
fix: reconnect L1 port-forward after epoch-boundary sleep in n_tps_prove
(AztecProtocol#23800)
chore: add empty vscode settings for yarn-project (AztecProtocol#23808)
fix(sequencer): only warn about missing proposed checkpoint once overdue
(AztecProtocol#23807)
fix: refresh n_tps fee quotes during sustained benchmark (AztecProtocol#23797)
fix(sequencer): enforce build-frame deadlines and align
attestation/publish windows (AztecProtocol#23776)
END_COMMIT_OVERRIDE
spalladino added a commit that referenced this pull request Jun 4, 2026
## Motivation

`v5-next` was cut from `next` at cbc99df (Jun 1), so PRs merged to
`merge-train/spartan` after the cut never flowed into it. This backports
all of them (authored by @spalladino and @fcarreiro) to keep v5-next
current with the spartan train.

## Approach

Each PR is cherry-picked from its squashed merge commit on
`merge-train/spartan`, in merge order, preserving the original commit
message and PR number — one commit per backported PR. All 11 applied
cleanly with no conflicts; patches are identical to the originals
(verified via `git patch-id`), and `bootstrap.sh build yarn-project`
passes on the result. Labeled `ci-no-squash` to preserve the per-PR
commits.

## Backported PRs

- #23768 — chore(p2p): use sync hash for tx validation hashing
- #23719 — test(e2e): wait warmup slots in slashing tests
- #23660 — feat(api)!: make getTxReceipt the single tx-lookup API
- #23665 — refactor: remove non-pipelining sequencer code path
- #23646 — feat(archiver): add getL2ToL1MembershipWitness node RPC
- #23778 — fix(p2p)!: revamp BLOCK_TXS validations
- #23786 — fix(p2p)!: fix BLOCK_TXS response under proposer equivocation
- #23808 — chore: add empty vscode settings for yarn-project
- #23807 — fix(sequencer): only warn about missing proposed checkpoint
once overdue
- #23776 — fix(sequencer): enforce build-frame deadlines and align
attestation/publish windows
- #23818 — chore(p2p): BlockTxsRequest comment

Note #23660, #23778, and #23786 are breaking changes (node RPC +
tx-effect db format, and p2p wire format respectively), as they were on
`next`.
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.

3 participants