Skip to content

Commit 3b0823e

Browse files
spalladinoaztec-bot
authored andcommitted
perf(e2e): shrink e2e slot times (#24570)
## What PR 5 of the round-4 e2e speedup effort: shrink e2e slot times, the highest-leverage remaining lever now that the warp lever is exhausted (PR 4) and the fees setup costs are pure inclusion latency at CI cadence (PR 6). Every cadence-bound cost — setup txs, inclusion waits, epoch walks — scales linearly with what these commits cut. Config-only. Three commits, in **ascending risk order** so the CI-survey/fix phase can revert from the top. A fourth candidate (WIDE_SLOT 72s → 48s) was investigated and **dropped** — see below. All guard math is recomputed from `stdlib/src/timetable/budgets.ts` + `stdlib/src/timetable/proposer_timetable.ts`: maxBlocksPerCheckpoint = floor((S - init - D - 2P - prepCp) / D) must be >= 1 where `S` = aztecSlotDuration, `init` = checkpointProposalInitTime (1s, never clamped), `D` = blockDurationMs/1000, `P` = p2pPropagationTime, `prepCp` = checkpointProposalPrepareTime. Fast-profile clamping (`P -> 0.5`, `prepCp -> 0.5`, `minBlock -> 1`) applies only when `ethereumSlotDuration < 8` (`FAST_PROFILE_ETHEREUM_SLOT_DURATION`). At or above 8s the production budgets apply verbatim. ## Commit 1 (lowest risk) — `perf(e2e): cut default CI L1 block time to 8s` `DEFAULT_L1_BLOCK_TIME`: `process.env.CI ? 12 : 8` → `8`. Local dev already ran at 8, so this only removes a CI-vs-local cadence asymmetry. Default single-node L2 slot goes 24s → 16s. Guard (default single-node: D = DEFAULT_BLOCK_DURATION_MS/1000 = 3, production budgets P=2, prepCp=1, init=1): - before (eth 12): S = 2x12 = 24 → floor((24 - 1 - 3 - 4 - 1)/3) = floor(15/3) = **5** blocks/cp - after (eth 8): S = 2x8 = 16 → floor((16 - 1 - 3 - 4 - 1)/3) = floor(7/3) = **2** blocks/cp Both >= 1. eth=8 is AT the fast-profile boundary, so budgets stay at production values (no clamping). **Blast radius is much smaller than the round-4 plan assumed.** The plan expected this to cut the fees / cross-chain / bot families, but the base has drifted: those suites now run on `PIPELINING_SETUP_OPTS` / `AUTOMINE_E2E_OPTS` (both set `ethereumSlotDuration: 4` explicitly) and no longer read `DEFAULT_L1_BLOCK_TIME`. The genuine default-cadence consumers (eth from `SingleNodeTestContext.getSlotDurations`, no explicit eth) are four single-node proving/recovery suites: `proving/default_node`, `proving/cross_chain_public_message`, `recovery/sync_after_reorg`, `partial-proofs/multi_root`. The only other `process.env.CI` timing coupling (`multi-node/slashing/inactivity_setup.ts`, `process.env.CI ? 8 : 4`) sets its own eth slot and does not read `DEFAULT_L1_BLOCK_TIME`, so it is untouched. ## Commit 2 (medium risk) — `perf(e2e): cut reorg cadence to 24s slots` `REORG_TIMING_BASE`: aztecSlotDuration 36 → 24, blockDurationMs 8000 → 5000 (epoch stays 4 slots). Shared by both reorg profiles, both below the fast-profile boundary: - `FAST_REORG_TIMING` (eth 4): proving/optimistic reorg describes, l1-reorgs/ - `MULTI_VALIDATOR_REORG_TIMING` (eth 6, attestationPropagationTime 0.5): recovery/proposal_failure_recovery, recovery/equivocation_recovery, high-availability/ha_sync, high-availability/ha_checkpoint_handoff Both run fast-profile: P = 0.5, prepCp = 0.5, init = 1. Guard, FAST_REORG_TIMING and MULTI_VALIDATOR_REORG_TIMING (identical budgets): - before: S = 36, D = 8 → floor((36 - 1 - 8 - 1 - 0.5)/8) = floor(25.5/8) = **3** blocks/cp - after: S = 24, D = 5 → floor((24 - 1 - 5 - 1 - 0.5)/5) = floor(16.5/5) = **3** blocks/cp blockDurationMs drops 8000 → 5000 specifically to preserve 3 blocks/checkpoint. Leaving it at 8000 would give floor(13.5/8) = **1**, which would break the l1-reorgs suites' `assertMultipleBlocksPerSlot(2)` (they push TX_COUNT=8 with maxTxsPerBlock=1 to force multi-block checkpoints). All other timing scales off `test.constants.slotDuration` (waits, warps). equivocation_recovery's manual fit calc still holds (3 x 5s = 15 + 0.5 init + 5 final block + 2.5 finalization = 23s <= 24s); its comment is updated. ## Commit 3 (higher risk) — `perf(e2e): cut multi-validator block-production cadence to 24s slots` `MULTI_VALIDATOR_BLOCK_PRODUCTION_TIMING`: aztecSlotDurationInL1Slots 3 → 2 (36s → 24s at eth 12), blockDurationMs 6000 → 4000. eth stays 12 (production budgets). Consumers: block-production/simple, first_slot, proof_boundary. Guard (eth 12, production budgets prepCp=1, init=1; P = per-test attestationPropagationTime), S=24, D=4: - simple (P=default 2): floor((24 - 1 - 4 - 4 - 1)/4) = floor(14/4) = **3** (was 4 at 36/6) - proof_boundary (P=default 2): floor((24 - 1 - 4 - 4 - 1)/4) = **3** (was 4) - first_slot (P=0.5): floor((24 - 1 - 4 - 1 - 1)/4) = floor(17/4) = **4** (was 4) All >= 1. simple asserts no block-count (only no-sequencer-failures); proof_boundary asserts proof-vs-boundary timing that scales off `test.constants`; first_slot keeps 4 blocks/checkpoint (its comment stays accurate). So the drop 4 → 3 is harmless for those three. `high_tps` is **pinned to the old 36s/6s cadence at its call site** (`aztecSlotDurationInL1Slots: 3`, `blockDurationMs: 6000` in its setupOpts, overriding the shared profile). Its checkpoint packing is 2 txs x 2.5s = 5s per block, which needs a 6s block sub-slot; a 4s block cannot hold it, and the suite hard-asserts `max-checkpoint-length == 4` and `max-txs-per-block == 2`. Pinning keeps high_tps at its tuned cadence rather than rewriting its whole timing model. The other three suites still take the cut. ## Dropped candidate — WIDE_SLOT 72s → 48s Investigated per the plan's stretch item and **dropped**. `blob_promotion` hard-asserts a checkpoint with >= `PIPELINE_EXPECTED_BLOCKS_PER_CHECKPOINT = 8` blocks. At the profile's D = 5.5s: - current 72/12: floor((72 - 1 - 5.5 - 4 - 1)/5.5) = floor(60.5/5.5) = **11** blocks/cp (fits 8) - 48/12: floor((48 - 1 - 5.5 - 4 - 1)/5.5) = floor(36.5/5.5) = **6** blocks/cp (cannot fit 8) Forcing 8 blocks would require shrinking D to ~4.5s, which lands the guard at exactly 8 with zero margin — under the deliberate `mockGossipSubNetworkLatency: 500ms` the suite runs with, and on top of the profile's documented A-914 constraint (pipelined multiple-blocks-per-slot starves non-proposer nodes with `CheckpointNumberNotSequentialError` when the L2 slot is tightened, worsened by a shorter slot). This is the "provably can't fit" case, and it cannot be verified locally (heavy multi-node pipelining), so it is not shipped. proposed_chain / cross_chain_messages (only need 2 blocks/cp) would survive the guard but share the A-914 risk; not worth the exposure for one profile. ## Local verification - **Commit 1: verified.** Ran `single-node/proving/default_node.test.ts -t 'returns initial block data'` locally (eth=8 = the new CI cadence, which local already uses). The node came up at `ethereumSlotDuration: 8, aztecSlotDuration: 16, blockDurationMs: 3000` and logged `Sequencer timetable initialized with 2 blocks per slot {"maxNumberOfBlocks":2}` — exactly the guard value above. No "Invalid timing configuration", no missed-slot warnings, test passed. Budgets stayed at production values (`attestationPropagationTime: 2, minBlockDuration: 2`), confirming eth=8 does not trip fast-profile clamping. - **Commits 2 and 3: guard math + CI only.** The reorg and multi-validator block-production suites are too heavy for the dev machine (multi-node + real-time waits + proving). The guard math above is the verification; CI validates end-to-end. The formula was confirmed exact against commit 1's live run. ## Revert protocol for the fix phase Commits are ordered by ascending risk; revert individual commits from the top on flake rather than fighting them: 1. **Any block-production suite flake** (simple / first_slot / proof_boundary) → revert commit 3 first. proof_boundary is the most real-time-sensitive (it warps to N-3 then runs the boundary in real time at the tighter 24s cadence); watch it first. 2. **Any reorg / prune / HA flake** (l1-reorgs, proving/optimistic reorg cases, recovery/proposal_failure_recovery, recovery/equivocation_recovery, high-availability/*) → revert commit 2. Watch the l1-reorgs `assertMultipleBlocksPerSlot(2)` assertions and equivocation_recovery's slashing-round timing. 3. **Any of the four default-cadence single-node proving/recovery suites** → revert commit 1 (lowest probability; the cadence is what local already runs). ## Notes for PR 7 (bot suite cadence) The bot suite (`single-node/bot/bot.test.ts`) uses `setup(0, { ...PIPELINING_SETUP_OPTS, ... })`, which sets `ethereumSlotDuration: 4` explicitly. It does not read `DEFAULT_L1_BLOCK_TIME`, so **commit 1 does not affect the bot suite** — its cadence lever remains its own PIPELINING preset, unchanged here. ## Measured impact The cadence cuts land a run-wide −6.4%: −1,600s summed across shards over the 135 suites present in both runs (−2,046s of improvements against +446s of regressions). The wall-clock benefit is smaller, since shards run in parallel across workers. Controls confirm the deltas are real cadence effects, not run-type artifacts. `high_tps` (deliberately pinned at the old cadence) is unchanged (+0.1s), and the WIDE_SLOT / explicit-preset proving suites are flat — pipeline_prune −1.2s, blob_promotion −0.1s, long_proving_time −1.1s, prune_when_cannot_build −0.1s. Only the default-cadence and reorg/block-production timings moved. Largest per-suite wall cuts (default-cadence proving/recovery from commit 1; reorg from commit 2): - optimistic.parallel −399.9s (−23.5%, ×8 shards) - proof_boundary.parallel −346.0s (−25.6%, ×5 shards) - full −202.7s; blocks.parallel −196.3s (−28.8%, ×5 shards) - invalidate_block.parallel −118.5s (×11 shards); sync_after_reorg −108.3s - data_withholding_slash −72.0s; proposal_failure_recovery.parallel −60.1s; cross_chain_public_message −48.2s; equivocation_recovery −46.9s; late_prover_tx_collection −43.3s Regressions, all on high-variance multi-node suites that are not cadence-cut here (run-to-run noise, not attributable to this change): multi_root +74.1s, inactivity_slash +64.4s, attested_invalid_proposal.parallel +32.1s, proposed_chain.parallel +26.1s, bot +22.3s. The metric is whole-suite wall time (sum of test durations + hooks); a cadence change carries no new span to attribute against, so these are run-vs-run wall deltas — the flat pinned/preset controls above are what make the cadence attribution defensible. Baseline CI run 1783417125211175 (merge-base 13a53f1, full). PR CI run 1783426164237985 (x-fast). Fixes A-1184 (cherry picked from commit eedf4eb)
1 parent d108109 commit 3b0823e

9 files changed

Lines changed: 48 additions & 30 deletions

File tree

yarn-project/end-to-end/src/multi-node/block-production/high_tps.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ describe('multi-node/block-production/high_tps', () => {
7676
({ test, context, logger, validators, nodes, from } = await setupSimpleBlockProduction({
7777
nodeCount: NODE_COUNT,
7878
setupOpts: {
79+
// Pin the old 36s/6s cadence (overriding MULTI_VALIDATOR_BLOCK_PRODUCTION_TIMING's 24s/4s): this
80+
// suite's per-block budget is 2 txs x 2.5s = 5s, which needs a 6s block sub-slot (the full T=0..36s
81+
// budget in this file's header is built around it) and does not fit the profile's 4s block.
82+
aztecSlotDurationInL1Slots: 3,
83+
blockDurationMs: 6000,
7984
fakeProcessingDelayPerTxMs: TX_DURATION_MS,
8085
attestationPropagationTime: 1,
8186
minTxsPerBlock: 1,

yarn-project/end-to-end/src/multi-node/block-production/proof_boundary.parallel.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ type PublishedEvent = Parameters<SequencerEvents['checkpoint-published']>[0];
2828

2929
// Suite: 5 parallel scenarios testing the interaction between the proof submission deadline and
3030
// the pipelining boundary slot. MultiNodeTestContext: 3 validator nodes + 1 prover node,
31-
// mockGossipSubNetwork, skipInitialSequencer. Timing: ethSlot=12s, aztecSlot=3×12=36s,
32-
// epoch=default 6, proofSubmissionEpochs=1 (overridden per test via setupTest), blockDurationMs=6s,
31+
// mockGossipSubNetwork, skipInitialSequencer. Timing: ethSlot=12s, aztecSlot=2×12=24s,
32+
// epoch=default 6, proofSubmissionEpochs=1 (overridden per test via setupTest), blockDurationMs=4s,
3333
// inboxLag=2 (v5 always enforces the timetable, so the former enforceTimeTable/disableAnvilTestWatcher
3434
// overrides are gone). The Delayer is used to steer proof tx timing.
3535
describe('multi-node/block-production/proof_boundary', () => {

yarn-project/end-to-end/src/multi-node/block-production/simple.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const TX_COUNT_SIMPLE = 8;
1616

1717
// Verifies that 3 validator nodes can build blocks without sequencer errors. Lightweight RPC-only
1818
// initial node (skipInitialSequencer), mockGossipSubNetwork, no prover. Timing: ethSlot=12s,
19-
// aztecSlot=36s, epoch=default 6, proofSubmissionEpochs=1024, blockDurationMs=6s. Pre-proved txs sent
19+
// aztecSlot=24s, epoch=default 6, proofSubmissionEpochs=1024, blockDurationMs=4s. Pre-proved txs sent
2020
// from the hardcoded genesis-funded account (no on-chain account deploy needed).
2121
describe('multi-node/block-production/simple', () => {
2222
let context: EndToEndContext;

yarn-project/end-to-end/src/multi-node/high-availability/ha_checkpoint_handoff.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ const VALIDATOR_COUNT = 4;
5757
* `mockGossipSubNetwork` bus, then 4 validator nodes created via `test.createValidatorNode` in 2 HA pairs. Each pair
5858
* shares its two validator keys plus an in-memory `createSharedSlashingProtectionDb` (so only one peer signs per duty)
5959
* — explicitly NOT the Postgres-backed docker-compose HA suite, so this is an in-proc `multi-node` test, not infra.
60-
* Production `Sequencer`, no prover node. Timing: ethSlot=6s, aztecSlot=36s, epoch=4, proofSubEpochs=1024,
61-
* blockDurationMs=8s, committeeSize=4, attestationPropagationTime=0.5, inboxLag=2; anvil on interval mining. Nodes build
60+
* Production `Sequencer`, no prover node. Timing: ethSlot=6s, aztecSlot=24s, epoch=4, proofSubEpochs=1024,
61+
* blockDurationMs=5s, committeeSize=4, attestationPropagationTime=0.5, inboxLag=2; anvil on interval mining. Nodes build
6262
* empty checkpoints (`buildCheckpointIfEmpty` + `minTxsPerBlock: 0`) so no txs are needed, and each node uses a distinct
6363
* coinbase so the secondary assertion can prove which peer produced S2. Time is warped with `cheatCodes.eth.warp`:
6464
* `findConsecutiveSamePairSlots` recovers from `ValidatorSelection__EpochNotStable` by warping forward one epoch, and

yarn-project/end-to-end/src/multi-node/recovery/equivocation_recovery.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ describe('multi-node/recovery/equivocation_recovery', () => {
5757
// Build 4 validators (V1..V4) using the shared deterministic builder (keys from index 3).
5858
const validators = buildMockGossipValidators(NODE_COUNT);
5959

60-
// Timing calculation for 3 blocks per checkpoint with 8s sub-slots:
60+
// Timing calculation for 3 blocks per checkpoint with 5s sub-slots:
6161
// - initializationOffset = 0.5s (test mode, ethereumSlotDuration < 8)
62-
// - 3 blocks x 8s = 24s
62+
// - 3 blocks x 5s = 15s
6363
// - checkpointFinalization = 0.5s (assemble) + 0 (p2p in test) + 2s (L1 publish) = 2.5s
64-
// - finalBlockDuration = 8s (re-execution)
65-
// - Total: 0.5 + 24 + 8 + 2.5 = 35s => use 36s
64+
// - finalBlockDuration = 5s (re-execution)
65+
// - Total: 0.5 + 15 + 5 + 2.5 = 23s => use 24s
6666
const slashingUnit = BigInt(1e14);
6767
test = await MultiNodeTestContext.setup({
6868
...MOCK_GOSSIP_MULTI_VALIDATOR_OPTS,

yarn-project/end-to-end/src/multi-node/recovery/proposal_failure_recovery.parallel.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const NODE_COUNT = 4;
2929
* blocks, and the next proposer rebuilds a fresh checkpoint that lands on L1.
3030
*
3131
* Both scenarios share the same 4-validator mock-gossip cluster (one key per node, no prover) on the
32-
* multi-validator reorg cadence (ethSlot=6s, aztecSlot=36s, epoch=4, proofSubmissionEpochs=1024, blockDurationMs=8000,
32+
* multi-validator reorg cadence (ethSlot=6s, aztecSlot=24s, epoch=4, proofSubmissionEpochs=1024, blockDurationMs=5000,
3333
* inboxLag=2 — v5 always enforces the timetable). Each test warps L1 to align with its target build slot.
3434
*/
3535
describe('multi-node/recovery/proposal_failure_recovery', () => {

yarn-project/end-to-end/src/single-node/l1-reorgs/setup.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const TX_COUNT = 8;
2424
/**
2525
* The single-node + prover-node fixture shared by the L1-reorg suites (`blocks`, `messages`). Stands
2626
* up a {@link SingleNodeTestContext} on the {@link FAST_REORG_TIMING} cadence (ethSlot=4s,
27-
* aztecSlot=36s, block=8s, epoch=4, 32 slots/epoch) with L1 speed-ups disabled so prover/sequencer txs
27+
* aztecSlot=24s, block=5s, epoch=4, 32 slots/epoch) with L1 speed-ups disabled so prover/sequencer txs
2828
* can be held back and reorged, registers a {@link TestContract}, and exposes the per-test handles plus
2929
* a `sendTransactions` helper that pre-proves and fires `count` lightweight txs to drive multi-block
3030
* checkpoints. Reorgs themselves are driven by `EthCheatCodes.reorg`/`reorgWithReplacement` at the call
@@ -47,14 +47,14 @@ export class L1ReorgsTest {
4747

4848
public async setup(): Promise<void> {
4949
this.test = await setupWithProver({
50-
...FAST_REORG_TIMING, // ethSlot=4s, aztecSlot=36s, block=8s, epoch=4, 32 slots/epoch (mainnet)
50+
...FAST_REORG_TIMING, // ethSlot=4s, aztecSlot=24s, block=5s, epoch=4, 32 slots/epoch (mainnet)
5151
numberOfAccounts: 1,
5252
maxSpeedUpAttempts: 0, // Do not speed up l1 txs, we dont want them to land
5353
cancelTxOnTimeout: false,
5454
minTxsPerBlock: 0,
5555
maxTxsPerBlock: 1,
5656
aztecProofSubmissionEpochs: 1,
57-
// Pipelining + multi-blocks-per-slot: 8s blocks fit ~4 blocks per 36s slot, and TX_COUNT=8
57+
// Pipelining + multi-blocks-per-slot: 5s blocks fit ~3 blocks per 24s slot, and TX_COUNT=8
5858
// ensures multiple checkpoints have multiple blocks
5959
});
6060
({

yarn-project/end-to-end/src/single-node/proving/optimistic.parallel.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ jest.setTimeout(1000 * 60 * 20);
2424
* Setup: a single sequencer/validator node from `setupWithProver` plus the context's fake prover-node (no
2525
* `mockGossipSubNetwork`, so no gossip bus), making this a `single-node` test on the production `Sequencer`. Each of the
2626
* six `describe` blocks builds a fresh context in its own `beforeEach` and tears it down in the shared `afterEach`. The
27-
* happy-path pair uses defaults (`numberOfAccounts: 1`; ethSlot=8s local/12s CI, aztecSlot=16s/24s, epoch=6,
28-
* proofSubEpochs=1); the five reorg describes use a faster cadence (ethSlot=4s, aztecSlot=36s, epoch=4 — or 8 for the
29-
* with-replacement case so the replacement lands in-epoch — proofSubEpochs=NO_REORG_SUBMISSION_EPOCHS, blockDurationMs=8s, minTxsPerBlock=0,
27+
* happy-path pair uses defaults (`numberOfAccounts: 1`; ethSlot=8s, aztecSlot=16s, epoch=6,
28+
* proofSubEpochs=1); the five reorg describes use a faster cadence (ethSlot=4s, aztecSlot=24s, epoch=4 — or 8 for the
29+
* with-replacement case so the replacement lands in-epoch — proofSubEpochs=NO_REORG_SUBMISSION_EPOCHS, blockDurationMs=5s, minTxsPerBlock=0,
3030
* anvilSlotsInAnEpoch=32, maxSpeedUpAttempts=0, cancelTxOnTimeout=false). The `prover-node starts mid-epoch` describe
3131
* sets `startProverNode: false` and spins up the prover via `test.createProverNode()` partway through the epoch.
3232
*

yarn-project/end-to-end/src/single-node/single_node_test_context.ts

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,14 @@ import type { TestWallet } from '../test-wallet/test_wallet.js';
6060
export const WORLD_STATE_CHECKPOINT_HISTORY = 2;
6161
export const WORLD_STATE_BLOCK_CHECK_INTERVAL = 50;
6262
export const ARCHIVER_POLL_INTERVAL = 50;
63-
export const DEFAULT_L1_BLOCK_TIME = process.env.CI ? 12 : 8;
63+
/**
64+
* Default L1 (ethereum) slot duration in seconds for single-node e2e tests. Kept at 8s, the fast-profile
65+
* boundary (`FAST_PROFILE_ETHEREUM_SLOT_DURATION`): at 8s the proposer still uses the production operational
66+
* budgets (fast-profile clamping only kicks in strictly below 8s), so the default single-node L2 slot is
67+
* `2 x 8 = 16s`. CI previously ran at 12s (24s L2 slots); unifying it with the local value removes a
68+
* CI-vs-local cadence asymmetry and cuts every default-cadence single-node suite by a third.
69+
*/
70+
export const DEFAULT_L1_BLOCK_TIME = 8;
6471

6572
export type SingleNodeTestOpts = Partial<SetupOptions> & {
6673
numberOfAccounts?: number;
@@ -87,15 +94,18 @@ export type TrackedSequencerEvent = {
8794
export type BlockProposedEvent = { blockNumber: BlockNumber; slot: SlotNumber; buildSlot: SlotNumber };
8895

8996
/**
90-
* The 36s-slot reorg cadence shared by every reorg/prune/HA test, regardless of single-node vs
91-
* multi-validator topology: a 36s L2 slot, 8s blocks, and a 4-slot epoch. The two concrete reorg
97+
* The 24s-slot reorg cadence shared by every reorg/prune/HA test, regardless of single-node vs
98+
* multi-validator topology: a 24s L2 slot, 5s blocks, and a 4-slot epoch. The 5s block duration is chosen
99+
* so the fast-profile budgets both reorg profiles run under (eth < 8s: p2p 0.5s, prepare 0.5s, init 1s)
100+
* still fit ~3 full block sub-slots per checkpoint — `floor((24 - 1 - 5 - 2*0.5 - 0.5) / 5) = 3` — which
101+
* the l1-reorgs suites' `assertMultipleBlocksPerSlot(2)` assertions require. The two concrete reorg
92102
* profiles ({@link FAST_REORG_TIMING}, {@link MULTI_VALIDATOR_REORG_TIMING}) extend this with their topology's L1
93103
* slot duration and any extra knobs. Kept timing-only — `maxSpeedUpAttempts`, `cancelTxOnTimeout`, and
94104
* `aztecProofSubmissionEpochs` encode per-test scenario intent and stay explicit at the call site.
95105
*/
96106
export const REORG_TIMING_BASE = {
97-
aztecSlotDuration: 36,
98-
blockDurationMs: 8000,
107+
aztecSlotDuration: 24,
108+
blockDurationMs: 5000,
99109
aztecEpochDuration: 4,
100110
} as const;
101111

@@ -115,7 +125,7 @@ export const FAST_REORG_TIMING = {
115125
} as const;
116126

117127
/**
118-
* Timing-only profile naming the 36s/6s reorg-and-prune cadence copied verbatim across the
128+
* Timing-only profile naming the 24s/6s reorg-and-prune cadence copied verbatim across the
119129
* multi-validator recovery and high-availability tests (`recovery/proposal_failure_recovery`,
120130
* `recovery/equivocation_recovery`, `high-availability/ha_sync`,
121131
* `high-availability/ha_checkpoint_handoff`). The multi-validator analogue of
@@ -130,17 +140,20 @@ export const MULTI_VALIDATOR_REORG_TIMING = {
130140
} as const;
131141

132142
/**
133-
* Timing-only profile naming the 36s/12s multi-validator block-production cadence copied across
134-
* `block-production/` (`simple`, `high_tps`, `first_slot`, and `proof_boundary`). Uses
135-
* `aztecSlotDurationInL1Slots: 3` rather than an explicit `aztecSlotDuration: 36` so the L2 slot stays
136-
* coupled to `ethereumSlotDuration` if a test overrides eth. Deliberately omits
137-
* `attestationPropagationTime` (per-scenario: default 2, 0.5, or 1) — set it per test. Spread BEFORE
138-
* per-test overrides.
143+
* Timing-only profile naming the 24s/12s multi-validator block-production cadence copied across
144+
* `block-production/` (`simple`, `first_slot`, and `proof_boundary`). Uses `aztecSlotDurationInL1Slots: 2`
145+
* rather than an explicit `aztecSlotDuration: 24` so the L2 slot stays coupled to `ethereumSlotDuration`
146+
* if a test overrides eth. The 4s block duration keeps enough full block sub-slots per checkpoint under
147+
* the production budgets these eth=12 tests run with (init 1s, prepare 1s, min-block 2s, p2p =
148+
* attestationPropagationTime): `floor((24 - 1 - 4 - 2P - 1) / 4)` = 4 blocks at P<=1, 3 blocks at P=2
149+
* (the default). Deliberately omits `attestationPropagationTime` (per-scenario: default 2, 0.5, or 1) —
150+
* set it per test. `high_tps` pins the old 36s/6s cadence at its own call site because its 2-txs-x-2.5s
151+
* per-block budget does not fit a 4s block. Spread BEFORE per-test overrides.
139152
*/
140153
export const MULTI_VALIDATOR_BLOCK_PRODUCTION_TIMING = {
141154
ethereumSlotDuration: 12,
142-
aztecSlotDurationInL1Slots: 3,
143-
blockDurationMs: 6000,
155+
aztecSlotDurationInL1Slots: 2,
156+
blockDurationMs: 4000,
144157
} as const;
145158

146159
/**

0 commit comments

Comments
 (0)