fix: keep submitting full epoch proofs once the proven tip passes the epoch - #25277
Open
spalladino wants to merge 3 commits into
Open
fix: keep submitting full epoch proofs once the proven tip passes the epoch#25277spalladino wants to merge 3 commits into
spalladino wants to merge 3 commits into
Conversation
… epoch The publisher refused to submit any proof whose range ended below the global proven checkpoint tip. That is only a valid "publishing this earns nothing" test while the tip sits inside our own epoch. Since partial proofs let a prover advance the tip into epoch N+1 mid-epoch, a full proof for epoch N was dropped while its submission window was still open, costing the node the epoch's rewards: the rollup pays only provers holding shares in the epoch's longest proven length, and shares are registered on submission. Scope the check to partial candidates, which genuinely cannot reach that longest length, and let full-epoch proofs through. Since that removes what was incidentally stopping a repeat submission from reaching L1, also skip a proof this prover has already submitted for the same epoch and length, which the rollup reverts.
Two prover nodes on one sequencer. The slow one is held at its top-tree gate while the fast one proves the same epoch and then partially proves the next, taking the proven tip past the gated epoch's last checkpoint. Releasing the gate must produce a published proof and an on-chain submission record for the slow prover; before the publisher fix its session settled as failed.
alexghr
reviewed
Aug 21, 2026
| attestations: ViemCommitteeAttestation[]; | ||
| headers: CheckpointHeader[]; | ||
| /** Whether the range covers the whole epoch. Governs whether an already-overtaken proof is still worth sending. */ | ||
| kind: 'full' | 'partial'; |
Contributor
There was a problem hiding this comment.
I don't see where this is passed from the prover node. Was it already an field that was being sent?
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.
Context
A prover node proving epoch N never submits its proof if another prover posts a partial epoch proof for epoch N+1 while epoch N's submission window is still open, so it earns nothing for an epoch it fully proved.
validateEpochProofSubmissionrefused any proof whose range ended below the global proven checkpoint tip. That is only a valid "publishing this earns nothing" test while the tip sits inside our own epoch. Partial proofs need only an epoch's first checkpoints, so another prover can advance the tip into epoch N+1 mid-epoch — and epoch N's proof is dropped even though L1 still accepts it (assertAcceptablerequires only_start - 1 <= proven, andhandleRewardsAndFeesruns whether or not the tip moves).The cost is real:
claimProverRewardspays only provers holding shares in the epoch's longest proven length, and shares are registered on submission. Not submitting means zero for the epoch. The publishing service already encodes the right policy — full candidates are never auto-superseded by the proven tip — and the publisher was contradicting it.Approach
Thread the candidate's
kindfromPublishCandidateinto the publisher and apply the tip check only to partial candidates, which genuinely cannot reach the epoch's longest proven length. Full-epoch proofs always match that length, so they stay worth sending until the window closes.That removes what was incidentally stopping a repeat submission from reaching L1, so the publisher now also skips a proof this prover has already submitted for the same epoch and length, which the rollup reverts (
Rollup__ProverHaveAlreadySubmitted).Covered by
single-node/proving/proof_after_tip_advances: two prover nodes, one held at its top-tree gate while the other proves the same epoch and then partially proves the next, taking the tip past the gated epoch. Releasing the gate must yield a published proof and an on-chain submission record; before the fix the session settled asfailed.Same bug is present on
next; this targets the v5 line first.Note for reviewers: the tests were not run locally — this checkout cannot build (
node_modules/@aztec/bb.jspoints at thenext-line layout), so type-checking and the suite are unverified beyond CI.Fixes A-1795