Skip to content

feat(pipeline): minimize deadzone w cross slot attesting#21435

Merged
Maddiaa0 merged 1 commit intomerge-train/spartanfrom
md/pipeline-overlap
Apr 9, 2026
Merged

feat(pipeline): minimize deadzone w cross slot attesting#21435
Maddiaa0 merged 1 commit intomerge-train/spartanfrom
md/pipeline-overlap

Conversation

@Maddiaa0
Copy link
Copy Markdown
Member

@Maddiaa0 Maddiaa0 commented Mar 12, 2026

Overview

Allow validators to attest to old proposals slightly into the next slot, this allows validators from the slot before to send their checkpoint proposals
later in their own slot.

Key points

  • Allows timetable to extend past the current slot
  • Decouples attestation gathering from the hot path for sequencers - it can move async
  • Refactor of the timetable model into stdlib so it can be consumed elsewhere

@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from 730df54 to 67be055 Compare March 16, 2026 12:13
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-spartan-config branch from 26acaf0 to f18cc20 Compare March 16, 2026 12:13
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-spartan-config branch from f18cc20 to b7b0c11 Compare March 16, 2026 18:08
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from 67be055 to 72312e1 Compare March 16, 2026 18:08
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from 72312e1 to 9f24073 Compare March 18, 2026 11:33
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-spartan-config branch 2 times, most recently from 0944eb7 to de53468 Compare March 18, 2026 11:59
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from 9f24073 to c2d1bb4 Compare March 18, 2026 11:59
@Maddiaa0 Maddiaa0 marked this pull request as ready for review March 19, 2026 22:02
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from c2d1bb4 to ef383be Compare March 19, 2026 22:03
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-spartan-config branch from de53468 to 82f2dbd Compare March 19, 2026 22:03
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch 2 times, most recently from a399cd5 to c1e72e3 Compare March 20, 2026 13:21
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-spartan-config branch from 82f2dbd to 4f49f4a Compare March 20, 2026 13:21
@Maddiaa0
Copy link
Copy Markdown
Member Author

fix here

initialValidators: validators,
enableProposerPipelining: true, // <- yehaw
mockGossipSubNetwork: true,
mockGossipSubNetworkLatency: 500, // 200 ms delay in message prop - adverse network conditions
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's amazing how fast comments become outdated

disableAnvilTestWatcher: true,
startProverNode: true,
perBlockAllocationMultiplier: 1,
perBlockAllocationMultiplier: 8,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This will lead to very big blocks at the beginning of the checkpoint, we sure about it?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

i had the value so high as it essentially disables it. ceil(remainingBudget / remainingBlocks * multiplier)

Comment on lines +81 to +86
ethereumSlotDuration: 12,
aztecSlotDuration: 72,
blockDurationMs: 8000,
l1PublishingTime: 2,
attestationPropagationTime: 0.5,
// maxDABlockGas: 786432, // Set max DA block gas to be the same as the checkpoint
// l1PublishingTime: 2,
// attestationPropagationTime: 1,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why these changes?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

legacy and ill have to make sure if still true - l1PublishingTime + attestationPropagationTime removal was to use the network defaults in this test.

maxDaBlockGas was due dividing the defaults across blocks at one point in time was not enough to get a tx into a block

// Check if message is for previous slot and within clock tolerance
if (!isWithinClockTolerance(slotNumber, targetSlot, this.epochCache)) {
// When pipelining, accept attestations for the current slot (built in the previous slot)
// if we're within the first ethereumSlotDuration/2 seconds of the slot.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment is wrong? The implementation accepts up until the p2p propagation time.

* @param epochCache - EpochCache to get timing and pipelining state
* @returns true if pipelining is enabled, the message is for the current slot, and we're within the grace period
*/
export function isWithinPipeliningGracePeriod(messageSlot: SlotNumber, epochCache: EpochCacheInterface): boolean {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shouldn't this function also consider the clock disparity time?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actually, can't we just merge this function with the one above? They are all used in all the same places after all.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

ive done a little refactor here

Comment on lines +211 to +214
if (this.pipelining) {
// L1 submission happens in target slot, after attestations
return this.aztecSlotDuration + this.pipeliningAttestationGracePeriod;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This limit feels too tight. We're saying here that we're only willing to collect attestations until this time, after that, we just give up. I'd update this to this.aztecSlotDuration * 2 - this.l1PublishingTime.

stateDiff: [
{ slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true), value: toPaddedHex(0n, true) },
...forcePendingArchiveStateDiff,
...forcePendingCheckpointNumberStateDiff,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm surprised we need the archive override tbh, given the checkpoint number override works for simulating. Maybe we can merge them and keep a single override for "current state of the network"?

Copy link
Copy Markdown
Member Author

@Maddiaa0 Maddiaa0 Apr 8, 2026

Choose a reason for hiding this comment

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

I dont think we do either, theres got to be a good reason i didnt migrate it in to the earlier PR. This appears to just be stale

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right, its required if supporting a pipeline depth > 1. When building ontop of a proposed checkpoint that is not confirmed, then this is required else the value of the archive for the checkpoint being built on is 0

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

merging them is a good idea

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

done

Comment thread yarn-project/sequencer-client/src/sequencer/checkpoint_proposal_job.ts Outdated

if (checkpoint) {
this.metrics.recordCheckpointProposalSuccess();
if (!broadcast) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe it's in a later PR, but if we failed to broadcast (or if there was any error broadcasting) we should clean up our proposed blocks from our archiver, so we can attest in the next slot.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is true, right now the wider rollback covers this - but we will need to tighten it up

Comment on lines +190 to +191
// Background the attestation → signing → L1 pipeline so the work loop is unblocked
this.pendingL1Submission = this.waitForAttestationsAndEnqueueSubmissionAsync(broadcast, votesPromises);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm trying to figure out if there's an issue with this getting overwritten before completion if we are the proposer for two slots in a row. But I don't think so - this is just used for awaiting completion, right?

@Maddiaa0 Maddiaa0 changed the base branch from md/pipeline-spartan-config to graphite-base/21435 April 8, 2026 11:46
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from c1e72e3 to bfadfa1 Compare April 8, 2026 16:38
@Maddiaa0 Maddiaa0 requested review from a team and jeanmon as code owners April 8, 2026 16:38
@Maddiaa0 Maddiaa0 changed the base branch from graphite-base/21435 to md/pipeline-spartan-config April 8, 2026 16:39
@Maddiaa0 Maddiaa0 added the ci-full Run all master checks. label Apr 8, 2026
@Maddiaa0 Maddiaa0 changed the base branch from md/pipeline-spartan-config to graphite-base/21435 April 8, 2026 19:51
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from 59aca30 to 8fd3bbe Compare April 8, 2026 19:52
@Maddiaa0 Maddiaa0 force-pushed the graphite-base/21435 branch from 7c93544 to 0f459dd Compare April 8, 2026 19:52
@Maddiaa0 Maddiaa0 changed the base branch from graphite-base/21435 to md/pipeline-spartan-config April 8, 2026 19:52
@Maddiaa0 Maddiaa0 changed the base branch from md/pipeline-spartan-config to graphite-base/21435 April 8, 2026 20:03
@Maddiaa0 Maddiaa0 force-pushed the graphite-base/21435 branch from 0f459dd to 95557a0 Compare April 8, 2026 20:08
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from 8fd3bbe to 0c09382 Compare April 8, 2026 20:08
@Maddiaa0 Maddiaa0 changed the base branch from graphite-base/21435 to md/pipeline-spartan-config April 8, 2026 20:08
const elapsedMs = Number(nowMs - slotStartMs);
const windowMs = windowSeconds * 1000;

return elapsedMs < windowMs;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should still account for clock disparity here

};

/**
* Shared checkpoint timing model used by the sequencer timetable and P2P validators.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good refactor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

WDYT about having different impls for pipelining and not pipelining, to avoid all the conditionals in the getters? No need to implement now, for sure.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

yeah good idea

}

const timeAvailableForBlocks = this.aztecSlotDuration - this.checkpointInitializationTime - this.timeReservedAtEnd;
return Math.max(1, Math.floor(timeAvailableForBlocks / this.blockDuration));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can this mask errors where we have an invalid config altogether? Should we instead throw if the resulting blocks per slot is below 1?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah good point

Comment on lines +71 to +73
public get pipeliningAttestationGracePeriod(): number {
return (this.blockDuration ?? 0) + this.p2pPropagationTime;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you remind me why this value?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Aside from that, it'd be good to keep comments on what each value represents, and the rationale for it.

Base automatically changed from md/pipeline-spartan-config to merge-train/spartan April 9, 2026 11:15
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch 2 times, most recently from 2c391ba to de83910 Compare April 9, 2026 12:24
@Maddiaa0 Maddiaa0 force-pushed the md/pipeline-overlap branch from de83910 to da950b2 Compare April 9, 2026 14:43
@Maddiaa0 Maddiaa0 merged commit 3548b45 into merge-train/spartan Apr 9, 2026
13 checks passed
@Maddiaa0 Maddiaa0 deleted the md/pipeline-overlap branch April 9, 2026 15:19
github-merge-queue Bot pushed a commit that referenced this pull request Apr 10, 2026
BEGIN_COMMIT_OVERRIDE
fix(stdlib): use bigint arithmetic in GasFees.mul() for non-integer
scalars (#22383)
fix(node-lib): reuse existing fileStore in snapshot sync instead of
recreating (#22375)
fix: gate req/resp data protocols for unauthenticated peers (#22406)
fix(p2p): use per-batch ops array in AztecDatastore.batch() (#22357)
chore(pipeline): spartan config (#21285)
chore: add claude skill to send txs (#22439)
feat(pipeline): minimize deadzone w cross slot attesting (#21435)
fix(p2p): avoid 32-bit overflow in attestation pool block position key
(#22412)
fix(prover-client): increment retry count on timeout re-enqueue to
prevent infinite loop (#22355)
fix: remove redundant p2pClient.start() call (#22438)
chore: add kubectl binary to spartan .gitignore (#22454)
END_COMMIT_OVERRIDE
critesjosh pushed a commit that referenced this pull request Apr 14, 2026
## Overview

Allow validators to attest to old proposals slightly into the next slot,
this allows validators from the slot before to send their checkpoint
proposals
later in their own slot.

## Key points
- Allows timetable to extend past the current slot 
- Decouples attestation gathering from the hot path for sequencers - it
can move async
- Refactor of the timetable model into stdlib so it can be consumed
elsewhere
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-full Run all master checks.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants