Skip to content

Commit d3be5a7

Browse files
authored
feat: Multiple blocks per checkpoint (#18825)
## Summary This PR refactors the sequencer to propose checkpoints instead of individual blocks, enabling multi-block checkpoint proposals. The sequencer now builds multiple blocks within a slot and packages them into a single checkpoint for L1 publication. _Yes, this text was written by Claude_ ## Environment Variables ### New - **`SEQ_BLOCK_DURATION_MS`**: Duration per block in milliseconds when building multiple blocks per slot. If undefined (default), builds a single block per slot using the full slot duration. - **`SEQ_BUILD_CHECKPOINT_IF_EMPTY`**: Whether to build and publish an empty checkpoint when there are no txs (defaults to `true`). ### Changed - **`SEQ_MAX_L1_TX_INCLUSION_TIME_INTO_SLOT`** changed to **`SEQ_L1_PUBLISHING_TIME_ALLOWANCE_IN_SLOT`**: Aka "the dead zone". Renamed to better reflect its purpose of how much time (in seconds) we allow in the slot for publishing the L1 tx (defaults to 1 L1 slot). - **`SEQ_TX_POLLING_INTERVAL_MS`** changed to **`SEQ_POLLING_INTERVAL_MS`**: This is the polling for the sequencer loop, unrelated to polling for txs. ## Architecture Changes ### Main `Sequencer` Sequencer now focuses on orchestration and state management by delegating checkpoint proposal logic to a job-like class. It now manages lifecycle of checkpoint proposal jobs and handles checkpoint invalidation. ### `CheckpointProposalJob` (new) Extracted checkpoint proposal logic into a dedicated, self-contained job that manages the full lifecycle of building and proposing a checkpoint. Handles block building loop, attestation collection, L1 publishing, and P2P broadcasting. ### `CheckpointVoter` (new) Handles voting for slashing and governance proposals, called from both the main sequencer and the proposal job. ### `SequencerPublisher` Updated the publisher to work with Checkpoints as opposed to Blocks. ### `CheckpointsBuilder` (new) Emulates the old `BlockBuilder` but for checkpoints, managing checkpoint-level state, and orchestrating building multiple blocks within a checkpoint. Builds on top of the `LightweightCheckpointBuilder`. ## Miscellaneous Changes ### Disposable Interface `MerkleTreeWriteOperations`, `GuardedMerkleTree`, and `HintingDbSource` now implement a `Disposable` interface for proper resource cleanup. ### Global Variables Introduced a `CheckpointGlobalVariables` for checkpoint-level constants, separating block-level and checkpoint-level variables. ### Sequencer Config All sequencer config defaults are now in a single `DefaultSequencerConfig` object, and the `Sequencer` works with a config type with most entries defined. ## Placeholders ### Validator Client Block proposals currently create dummy checkpoint proposals, and checkpoint proposal creation needs to be distinguished from block proposals. ### Archiver & World State Sync Provisional blocks are not yet sent to archiver and world state, actual sync mechanism to be wired once available. ### P2P Broadcasting Checkpoint proposals and provisional blocks use placeholder P2P API, needs wiring to new P2P protocol once available. ## Pending Work 1. **Timetable fixes**: Review timing for new states and fix timing calculations. 2. **Checkpoint invalidation**: Implement proper checkpoint invalidation (currently invalidates blocks) 3. **Checkpoint number computation**: Derive proper checkpoint numbers (currently assumes checkpoint number is the same as block number) 4. **Block builder cleanup**: Remove old block builder in favor of CheckpointsBuilder 5. **Metrics review**: Audit all metrics for checkpoint-level tracking 6. **Re-enable disabled tests**: Fix and restore checkpoint proposal failure tests and multi-block checkpoint tests
2 parents 100e1d8 + 4ed9f7e commit d3be5a7

File tree

86 files changed

+3192
-1390
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+3192
-1390
lines changed

yarn-project/archiver/tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
},
88
"references": [
99
{
10-
"path": "../blob-lib"
10+
"path": "../blob-client"
1111
},
1212
{
13-
"path": "../blob-client"
13+
"path": "../blob-lib"
1414
},
1515
{
1616
"path": "../constants"

yarn-project/aztec-node/src/aztec-node/server.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
type SequencerPublisher,
4444
createValidatorForAcceptingTxs,
4545
} from '@aztec/sequencer-client';
46+
import { CheckpointsBuilder } from '@aztec/sequencer-client';
4647
import { PublicProcessorFactory } from '@aztec/simulator/server';
4748
import {
4849
AttestationsBlockWatcher,
@@ -427,7 +428,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
427428
// Validator enabled, create/start relevant service
428429
let sequencer: SequencerClient | undefined;
429430
let slasherClient: SlasherClientInterface | undefined;
430-
if (!config.disableValidator) {
431+
if (!config.disableValidator && validatorClient) {
431432
// We create a slasher only if we have a sequencer, since all slashing actions go through the sequencer publisher
432433
// as they are executed when the node is selected as proposer.
433434
const validatorAddresses = keyStoreManager
@@ -462,6 +463,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
462463
);
463464

464465
// Create and start the sequencer client
466+
const checkpointsBuilder = new CheckpointsBuilder(
467+
{ ...config, l1GenesisTime, slotDuration: Number(slotDuration) },
468+
archiver,
469+
dateProvider,
470+
telemetry,
471+
);
472+
465473
sequencer = await SequencerClient.new(config, {
466474
...deps,
467475
epochCache,
@@ -470,7 +478,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
470478
p2pClient,
471479
worldStateSynchronizer,
472480
slasherClient,
473-
blockBuilder,
481+
checkpointsBuilder,
474482
l2BlockSource: archiver,
475483
l1ToL2MessageSource: archiver,
476484
telemetry,
@@ -487,6 +495,13 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
487495
log.warn(`Sequencer created but not started`);
488496
}
489497

498+
const globalVariableBuilder = new GlobalVariableBuilder({
499+
...config,
500+
rollupVersion: BigInt(config.rollupVersion),
501+
l1GenesisTime,
502+
slotDuration: Number(slotDuration),
503+
});
504+
490505
return new AztecNodeService(
491506
config,
492507
p2pClient,
@@ -501,7 +516,7 @@ export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
501516
epochPruneWatcher,
502517
ethereumChain.chainInfo.id,
503518
config.rollupVersion,
504-
new GlobalVariableBuilder(config),
519+
globalVariableBuilder,
505520
epochCache,
506521
packageVersion,
507522
proofVerifier,

yarn-project/aztec/src/cli/aztec_start_options.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ export const aztecStartOptions: { [key: string]: AztecStartOption[] } = {
202202
'sequencer',
203203
omitConfigMappings(sequencerClientConfigMappings, [
204204
'fakeProcessingDelayPerTxMs',
205+
'fakeThrowAfterProcessingTxCount',
205206
'skipCollectingAttestations',
206207
'skipInvalidateBlockAsProposer',
207208
'blobSinkMapSizeKb',

yarn-project/cli/src/config/chain_l2_config.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ describe('enrichEnvironmentWithChainConfig', () => {
2626
publicMetricsCollectFrom: ['bar'],
2727
skipArchiverInitialSync: true,
2828
blobAllowEmptySources: true,
29+
blockDurationMs: 12000,
30+
buildCheckpointIfEmpty: true,
2931
};
3032

3133
// Enrich env with those

yarn-project/cli/src/config/chain_l2_config.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const tbMapSizeKb = 1_024 * 1_024 * 1_024; // 1 TB
1919
export type L2ChainConfig = Omit<L1ContractsConfig, keyof L1TxUtilsConfig> &
2020
Omit<SlasherConfig, 'slashValidatorsNever' | 'slashValidatorsAlways' | 'slashOverridePayload' | 'slashSelfAllowed'> &
2121
Pick<P2PConfig, 'bootstrapNodes' | 'p2pEnabled' | 'txPoolDeleteTxsAfterReorg'> &
22-
Pick<SequencerConfig, 'minTxsPerBlock' | 'maxTxsPerBlock'> & {
22+
Pick<SequencerConfig, 'buildCheckpointIfEmpty' | 'minTxsPerBlock' | 'maxTxsPerBlock' | 'blockDurationMs'> & {
2323
l1ChainId: number;
2424
testAccounts: boolean;
2525
sponsoredFPC: boolean;
@@ -104,6 +104,7 @@ export const stagingIgnitionL2ChainConfig: L2ChainConfig = {
104104
bootstrapNodes: [],
105105
minTxsPerBlock: 0,
106106
maxTxsPerBlock: 0,
107+
buildCheckpointIfEmpty: true,
107108
realProofs: true,
108109
snapshotsUrls: [`${SNAPSHOTS_URL}/staging-ignition/`],
109110
autoUpdate: 'config-and-version',
@@ -189,6 +190,7 @@ export const stagingPublicL2ChainConfig: L2ChainConfig = {
189190
bootstrapNodes: [],
190191
minTxsPerBlock: 0,
191192
maxTxsPerBlock: 20,
193+
buildCheckpointIfEmpty: true,
192194
realProofs: true,
193195
snapshotsUrls: [`${SNAPSHOTS_URL}/staging-public/`],
194196
autoUpdate: 'config-and-version',
@@ -246,6 +248,7 @@ export const nextNetL2ChainConfig: L2ChainConfig = {
246248
bootstrapNodes: [],
247249
minTxsPerBlock: 0,
248250
maxTxsPerBlock: 8,
251+
buildCheckpointIfEmpty: true,
249252
realProofs: true,
250253
snapshotsUrls: [],
251254
autoUpdate: 'config-and-version',
@@ -303,6 +306,7 @@ export const testnetL2ChainConfig: L2ChainConfig = {
303306
bootstrapNodes: [],
304307
minTxsPerBlock: 0,
305308
maxTxsPerBlock: 20,
309+
buildCheckpointIfEmpty: true,
306310
realProofs: true,
307311
snapshotsUrls: [`${SNAPSHOTS_URL}/testnet/`],
308312
autoUpdate: 'config-and-version',
@@ -396,6 +400,7 @@ export const mainnetL2ChainConfig: L2ChainConfig = {
396400
bootstrapNodes: [],
397401
minTxsPerBlock: 0,
398402
maxTxsPerBlock: 0,
403+
buildCheckpointIfEmpty: true,
399404
realProofs: true,
400405
snapshotsUrls: [`${SNAPSHOTS_URL}/mainnet/`],
401406
autoUpdate: 'notify',
@@ -484,6 +489,7 @@ export const devnetL2ChainConfig: L2ChainConfig = {
484489
bootstrapNodes: [],
485490
minTxsPerBlock: 0,
486491
maxTxsPerBlock: 8,
492+
buildCheckpointIfEmpty: true,
487493
realProofs: false,
488494
snapshotsUrls: [],
489495
autoUpdate: 'config-and-version',
@@ -577,6 +583,12 @@ export function enrichEnvironmentWithChainConfig(config: L2ChainConfig) {
577583
enrichVar('L1_CHAIN_ID', config.l1ChainId.toString());
578584
enrichVar('SEQ_MIN_TX_PER_BLOCK', config.minTxsPerBlock.toString());
579585
enrichVar('SEQ_MAX_TX_PER_BLOCK', config.maxTxsPerBlock.toString());
586+
if (config.blockDurationMs !== undefined) {
587+
enrichVar('SEQ_BLOCK_DURATION_MS', config.blockDurationMs.toString());
588+
}
589+
if (config.buildCheckpointIfEmpty !== undefined) {
590+
enrichVar('SEQ_BUILD_CHECKPOINT_IF_EMPTY', config.buildCheckpointIfEmpty.toString());
591+
}
580592
enrichVar('PROVER_REAL_PROOFS', config.realProofs.toString());
581593
enrichVar('PXE_PROVER_ENABLED', config.realProofs.toString());
582594
enrichVar('SYNC_SNAPSHOTS_URLS', config.snapshotsUrls.join(','));

yarn-project/cli/src/config/network_config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,7 @@ export async function enrichEnvironmentWithNetworkConfig(networkName: NetworkNam
141141
if (networkConfig.blobFileStoreUrls?.length) {
142142
enrichVar('BLOB_FILE_STORE_URLS', networkConfig.blobFileStoreUrls.join(','));
143143
}
144+
if (networkConfig.blockDurationMs !== undefined) {
145+
enrichVar('SEQ_BLOCK_DURATION_MS', String(networkConfig.blockDurationMs));
146+
}
144147
}

yarn-project/end-to-end/scripts/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ services:
2323
FORCE_COLOR: ${FORCE_COLOR:-1}
2424
ARCHIVER_POLLING_INTERVAL_MS: 500
2525
P2P_BLOCK_CHECK_INTERVAL_MS: 500
26-
SEQ_TX_POLLING_INTERVAL_MS: 500
26+
SEQ_POLLING_INTERVAL_MS: 500
2727
WS_BLOCK_CHECK_INTERVAL_MS: 500
2828
ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500
2929
HARDWARE_CONCURRENCY: ${HARDWARE_CONCURRENCY:-}

yarn-project/end-to-end/src/composed/web3signer/e2e_multi_validator_node_key_store.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ describe('e2e_multi_validator_node', () => {
290290
minTxsPerBlock: 1,
291291
maxTxsPerBlock: 1,
292292
archiverPollingIntervalMS: 200,
293-
transactionPollingIntervalMS: 200,
293+
sequencerPollingIntervalMS: 200,
294294
worldStateBlockCheckIntervalMS: 200,
295295
blockCheckIntervalMS: 200,
296296
startProverNode: true,

0 commit comments

Comments
 (0)