@aztec/sequencer-client 3.0.0-nightly.20251221 → 3.0.0-nightly.20251223
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/client/sequencer-client.d.ts +9 -8
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +28 -24
- package/dest/config.d.ts +7 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +63 -26
- package/dest/global_variable_builder/global_builder.d.ts +16 -8
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +35 -26
- package/dest/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/publisher/config.d.ts +3 -3
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +2 -2
- package/dest/publisher/sequencer-publisher-factory.d.ts +3 -3
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +1 -1
- package/dest/publisher/sequencer-publisher-metrics.d.ts +3 -3
- package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.d.ts +11 -24
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +50 -62
- package/dest/sequencer/block_builder.d.ts +1 -3
- package/dest/sequencer/block_builder.d.ts.map +1 -1
- package/dest/sequencer/block_builder.js +4 -2
- package/dest/sequencer/checkpoint_builder.d.ts +63 -0
- package/dest/sequencer/checkpoint_builder.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_builder.js +131 -0
- package/dest/sequencer/checkpoint_proposal_job.d.ts +73 -0
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_proposal_job.js +638 -0
- package/dest/sequencer/checkpoint_voter.d.ts +34 -0
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_voter.js +85 -0
- package/dest/sequencer/events.d.ts +46 -0
- package/dest/sequencer/events.d.ts.map +1 -0
- package/dest/sequencer/events.js +1 -0
- package/dest/sequencer/index.d.ts +5 -1
- package/dest/sequencer/index.d.ts.map +1 -1
- package/dest/sequencer/index.js +4 -0
- package/dest/sequencer/metrics.d.ts +3 -1
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +9 -0
- package/dest/sequencer/sequencer.d.ts +87 -127
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +179 -596
- package/dest/sequencer/timetable.d.ts +33 -13
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +73 -39
- package/dest/sequencer/types.d.ts +3 -0
- package/dest/sequencer/types.d.ts.map +1 -0
- package/dest/sequencer/types.js +1 -0
- package/dest/sequencer/utils.d.ts +14 -8
- package/dest/sequencer/utils.d.ts.map +1 -1
- package/dest/sequencer/utils.js +7 -4
- package/dest/test/index.d.ts +3 -1
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +27 -27
- package/src/client/sequencer-client.ts +24 -31
- package/src/config.ts +68 -25
- package/src/global_variable_builder/global_builder.ts +45 -39
- package/src/index.ts +2 -0
- package/src/publisher/config.ts +3 -3
- package/src/publisher/sequencer-publisher-factory.ts +3 -3
- package/src/publisher/sequencer-publisher-metrics.ts +2 -2
- package/src/publisher/sequencer-publisher.ts +71 -74
- package/src/sequencer/block_builder.ts +4 -1
- package/src/sequencer/checkpoint_builder.ts +217 -0
- package/src/sequencer/checkpoint_proposal_job.ts +701 -0
- package/src/sequencer/checkpoint_voter.ts +105 -0
- package/src/sequencer/events.ts +27 -0
- package/src/sequencer/index.ts +4 -0
- package/src/sequencer/metrics.ts +11 -0
- package/src/sequencer/sequencer.ts +275 -804
- package/src/sequencer/timetable.ts +84 -49
- package/src/sequencer/types.ts +6 -0
- package/src/sequencer/utils.ts +18 -9
- package/src/test/index.ts +2 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/aztec.js/log';
|
|
2
2
|
|
|
3
|
-
import { DEFAULT_ATTESTATION_PROPAGATION_TIME } from '../config.js';
|
|
3
|
+
import { DEFAULT_ATTESTATION_PROPAGATION_TIME as DEFAULT_P2P_PROPAGATION_TIME } from '../config.js';
|
|
4
4
|
import { SequencerTooSlowError } from './errors.js';
|
|
5
5
|
import type { SequencerMetrics } from './metrics.js';
|
|
6
6
|
import { SequencerState } from './utils.js';
|
|
7
7
|
|
|
8
|
-
const MIN_EXECUTION_TIME = 1;
|
|
9
|
-
const
|
|
10
|
-
const
|
|
8
|
+
export const MIN_EXECUTION_TIME = 1;
|
|
9
|
+
export const CHECKPOINT_INITIALIZATION_TIME = 1;
|
|
10
|
+
export const CHECKPOINT_FINALIZATION_TIME = 1;
|
|
11
11
|
|
|
12
12
|
export class SequencerTimetable {
|
|
13
13
|
/**
|
|
@@ -22,19 +22,22 @@ export class SequencerTimetable {
|
|
|
22
22
|
* but we'll timeout sooner to give it more time to propagate (remember we also have blobs!). Still, when working in anvil,
|
|
23
23
|
* we can just post in the very last second of the L1 slot and still expect the tx to be accepted.
|
|
24
24
|
*/
|
|
25
|
-
public readonly l1PublishingTime;
|
|
25
|
+
public readonly l1PublishingTime: number;
|
|
26
26
|
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* What's the minimum time we want to leave available for execution and reexecution (used to derive init deadline)
|
|
29
|
+
* Defaults to half of the block duration if set, otherwise a constant.
|
|
30
|
+
*/
|
|
28
31
|
public readonly minExecutionTime: number = MIN_EXECUTION_TIME;
|
|
29
32
|
|
|
30
33
|
/** How long it takes to get ready to start building */
|
|
31
|
-
public readonly
|
|
34
|
+
public readonly checkpointInitializationTime: number = CHECKPOINT_INITIALIZATION_TIME;
|
|
32
35
|
|
|
33
36
|
/** How long it takes to for proposals and attestations to travel across the p2p layer (one-way) */
|
|
34
|
-
public readonly
|
|
37
|
+
public readonly p2pPropagationTime: number;
|
|
35
38
|
|
|
36
|
-
/** How much time we spend validating and processing a
|
|
37
|
-
public readonly
|
|
39
|
+
/** How much time we spend validating and processing a checkpoint after building it */
|
|
40
|
+
public readonly checkpointFinalizationTime: number = CHECKPOINT_FINALIZATION_TIME;
|
|
38
41
|
|
|
39
42
|
/** Ethereum slot duration in seconds */
|
|
40
43
|
public readonly ethereumSlotDuration: number;
|
|
@@ -42,18 +45,19 @@ export class SequencerTimetable {
|
|
|
42
45
|
/** Aztec slot duration in seconds (must be multiple of ethereum slot duration) */
|
|
43
46
|
public readonly aztecSlotDuration: number;
|
|
44
47
|
|
|
45
|
-
/** How late into an L1 slot we can send a tx to make sure it gets included in the immediate next block. Complement of l1PublishingTime. */
|
|
46
|
-
public readonly maxL1TxInclusionTimeIntoSlot: number;
|
|
47
|
-
|
|
48
48
|
/** Whether assertTimeLeft will throw if not enough time. */
|
|
49
49
|
public readonly enforce: boolean;
|
|
50
50
|
|
|
51
|
+
/** Duration per block when building multiple blocks per slot (undefined = single block per slot) */
|
|
52
|
+
public readonly blockDuration: number | undefined;
|
|
53
|
+
|
|
51
54
|
constructor(
|
|
52
55
|
opts: {
|
|
53
56
|
ethereumSlotDuration: number;
|
|
54
57
|
aztecSlotDuration: number;
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
l1PublishingTime: number;
|
|
59
|
+
p2pPropagationTime?: number;
|
|
60
|
+
blockDurationMs?: number;
|
|
57
61
|
enforce: boolean;
|
|
58
62
|
},
|
|
59
63
|
private readonly metrics?: SequencerMetrics,
|
|
@@ -61,57 +65,57 @@ export class SequencerTimetable {
|
|
|
61
65
|
) {
|
|
62
66
|
this.ethereumSlotDuration = opts.ethereumSlotDuration;
|
|
63
67
|
this.aztecSlotDuration = opts.aztecSlotDuration;
|
|
64
|
-
this.
|
|
65
|
-
this.
|
|
66
|
-
this.
|
|
68
|
+
this.l1PublishingTime = opts.l1PublishingTime;
|
|
69
|
+
this.p2pPropagationTime = opts.p2pPropagationTime ?? DEFAULT_P2P_PROPAGATION_TIME;
|
|
70
|
+
this.blockDuration = opts.blockDurationMs ? opts.blockDurationMs / 1000 : undefined;
|
|
71
|
+
this.minExecutionTime = MIN_EXECUTION_TIME;
|
|
67
72
|
this.enforce = opts.enforce;
|
|
68
73
|
|
|
69
74
|
// Assume zero-cost propagation time and faster runs in test environments where L1 slot duration is shortened
|
|
70
75
|
if (this.ethereumSlotDuration < 8) {
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
76
|
+
this.p2pPropagationTime = 0;
|
|
77
|
+
this.checkpointFinalizationTime = 0.5;
|
|
78
|
+
this.checkpointInitializationTime = 0.5;
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
81
|
+
// Minimum work to do within a slot for building a block with the minimum time for execution and publishing its checkpoint
|
|
82
|
+
const minWorkToDo =
|
|
83
|
+
this.checkpointInitializationTime +
|
|
84
|
+
this.minExecutionTime * 2 + // Execution and reexecution
|
|
85
|
+
this.checkpointFinalizationTime +
|
|
86
|
+
this.p2pPropagationTime * 2 + // Send proposal and receive attestations
|
|
87
|
+
this.l1PublishingTime; // Submit to L1
|
|
82
88
|
|
|
83
|
-
const initializeDeadline = this.aztecSlotDuration -
|
|
89
|
+
const initializeDeadline = this.aztecSlotDuration - minWorkToDo;
|
|
84
90
|
this.initializeDeadline = initializeDeadline;
|
|
85
91
|
|
|
86
92
|
this.log.verbose(`Sequencer timetable initialized (${this.enforce ? 'enforced' : 'not enforced'})`, {
|
|
87
93
|
ethereumSlotDuration: this.ethereumSlotDuration,
|
|
88
94
|
aztecSlotDuration: this.aztecSlotDuration,
|
|
89
|
-
maxL1TxInclusionTimeIntoSlot: this.maxL1TxInclusionTimeIntoSlot,
|
|
90
95
|
l1PublishingTime: this.l1PublishingTime,
|
|
91
96
|
minExecutionTime: this.minExecutionTime,
|
|
92
|
-
blockPrepareTime: this.
|
|
93
|
-
|
|
94
|
-
blockValidationTime: this.
|
|
97
|
+
blockPrepareTime: this.checkpointInitializationTime,
|
|
98
|
+
p2pPropagationTime: this.p2pPropagationTime,
|
|
99
|
+
blockValidationTime: this.checkpointFinalizationTime,
|
|
95
100
|
initializeDeadline: this.initializeDeadline,
|
|
96
101
|
enforce: this.enforce,
|
|
97
|
-
allWorkToDo,
|
|
102
|
+
allWorkToDo: minWorkToDo,
|
|
98
103
|
});
|
|
99
104
|
|
|
100
105
|
if (initializeDeadline <= 0) {
|
|
101
106
|
throw new Error(
|
|
102
|
-
`Block proposal initialize deadline cannot be negative (got ${initializeDeadline} from total time needed ${
|
|
107
|
+
`Block proposal initialize deadline cannot be negative (got ${initializeDeadline} from total time needed ${minWorkToDo} and a slot duration of ${this.aztecSlotDuration}).`,
|
|
103
108
|
);
|
|
104
109
|
}
|
|
105
110
|
}
|
|
106
111
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
public getBlockProposalExecTimeEnd(secondsIntoSlot: number): number {
|
|
112
|
+
/** Deadline for a block proposal execution. Ensures we have enough time left for reexecution and publishing. */
|
|
113
|
+
public getProposerExecTimeEnd(secondsIntoSlot: number): number {
|
|
112
114
|
// We are N seconds into the slot. We need to account for `afterBlockBuildingTimeNeededWithoutReexec` seconds,
|
|
113
115
|
// send then split the remaining time between the re-execution and the block building.
|
|
114
|
-
const
|
|
116
|
+
const afterBlockBuildingTimeNeededWithoutReexec =
|
|
117
|
+
this.checkpointFinalizationTime + this.p2pPropagationTime * 2 + this.l1PublishingTime;
|
|
118
|
+
const maxAllowed = this.aztecSlotDuration - afterBlockBuildingTimeNeededWithoutReexec;
|
|
115
119
|
const available = maxAllowed - secondsIntoSlot;
|
|
116
120
|
const executionTimeEnd = secondsIntoSlot + available / 2;
|
|
117
121
|
this.log.debug(`Block proposal execution time deadline is ${executionTimeEnd}`, {
|
|
@@ -123,13 +127,11 @@ export class SequencerTimetable {
|
|
|
123
127
|
return executionTimeEnd;
|
|
124
128
|
}
|
|
125
129
|
|
|
126
|
-
|
|
127
|
-
return this.attestationPropagationTime + this.l1PublishingTime;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
+
/** Deadline for block proposal reexecution. Ensures the proposer has enough time for publishing. */
|
|
130
131
|
public getValidatorReexecTimeEnd(secondsIntoSlot?: number): number {
|
|
131
132
|
// We need to leave for `afterBlockReexecTimeNeeded` seconds available.
|
|
132
|
-
const
|
|
133
|
+
const afterBlockReexecTimeNeeded = this.p2pPropagationTime + this.l1PublishingTime;
|
|
134
|
+
const validationTimeEnd = this.aztecSlotDuration - afterBlockReexecTimeNeeded;
|
|
133
135
|
this.log.debug(`Validator re-execution time deadline is ${validationTimeEnd}`, {
|
|
134
136
|
secondsIntoSlot,
|
|
135
137
|
validationTimeEnd,
|
|
@@ -152,13 +154,16 @@ export class SequencerTimetable {
|
|
|
152
154
|
case SequencerState.SYNCHRONIZING:
|
|
153
155
|
return; // We don't really care about times for this states
|
|
154
156
|
case SequencerState.PROPOSER_CHECK:
|
|
155
|
-
case SequencerState.
|
|
157
|
+
case SequencerState.INITIALIZING_CHECKPOINT:
|
|
156
158
|
return this.initializeDeadline;
|
|
159
|
+
case SequencerState.WAITING_FOR_TXS:
|
|
157
160
|
case SequencerState.CREATING_BLOCK:
|
|
158
|
-
|
|
161
|
+
case SequencerState.WAITING_UNTIL_NEXT_BLOCK:
|
|
162
|
+
return this.initializeDeadline + this.checkpointInitializationTime;
|
|
163
|
+
case SequencerState.FINALIZING_CHECKPOINT:
|
|
159
164
|
case SequencerState.COLLECTING_ATTESTATIONS:
|
|
160
|
-
return this.aztecSlotDuration - this.l1PublishingTime - 2 * this.
|
|
161
|
-
case SequencerState.
|
|
165
|
+
return this.aztecSlotDuration - this.l1PublishingTime - 2 * this.p2pPropagationTime;
|
|
166
|
+
case SequencerState.PUBLISHING_CHECKPOINT:
|
|
162
167
|
return this.aztecSlotDuration - this.l1PublishingTime;
|
|
163
168
|
default: {
|
|
164
169
|
const _exhaustiveCheck: never = state;
|
|
@@ -185,4 +190,34 @@ export class SequencerTimetable {
|
|
|
185
190
|
this.metrics?.recordStateTransitionBufferMs(Math.floor(bufferSeconds * 1000), newState);
|
|
186
191
|
this.log.trace(`Enough time to transition to ${newState}`, { maxAllowedTime, secondsIntoSlot });
|
|
187
192
|
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Get timing information for building blocks within a slot.
|
|
196
|
+
* @param secondsIntoSlot - Current seconds into the slot
|
|
197
|
+
* @returns Object containing:
|
|
198
|
+
* - canStart: boolean - Whether there's time to start a block now
|
|
199
|
+
* - deadline: number - Deadline (seconds into slot) for building the block
|
|
200
|
+
* - isLastBlock: boolean - Whether the next block would be the last one in the checkpoint
|
|
201
|
+
*/
|
|
202
|
+
public canStartNextBlock(secondsIntoSlot: number): {
|
|
203
|
+
canStart: boolean;
|
|
204
|
+
deadline: number | undefined;
|
|
205
|
+
isLastBlock: boolean;
|
|
206
|
+
} {
|
|
207
|
+
const minExecutionTime = this.minExecutionTime;
|
|
208
|
+
const deadline = this.enforce ? this.getProposerExecTimeEnd(secondsIntoSlot) : undefined;
|
|
209
|
+
|
|
210
|
+
// Always allow to start if we don't enforce the timetable
|
|
211
|
+
const canStart = !this.enforce || deadline === undefined || deadline - secondsIntoSlot >= minExecutionTime;
|
|
212
|
+
|
|
213
|
+
// Single block per slot
|
|
214
|
+
if (this.blockDuration === undefined) {
|
|
215
|
+
this.log.debug(`${canStart ? 'Can' : 'Cannot'} start single-block checkpoint at ${secondsIntoSlot}s into slot`);
|
|
216
|
+
return { deadline, canStart, isLastBlock: true };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Multiple blocks per slot
|
|
220
|
+
// TODO(palla/mbps) Implement me
|
|
221
|
+
return { deadline, canStart, isLastBlock: true };
|
|
222
|
+
}
|
|
188
223
|
}
|
package/src/sequencer/utils.ts
CHANGED
|
@@ -9,22 +9,31 @@ export enum SequencerState {
|
|
|
9
9
|
SYNCHRONIZING = 'SYNCHRONIZING',
|
|
10
10
|
/** Checking if we are the proposer for the current slot. */
|
|
11
11
|
PROPOSER_CHECK = 'PROPOSER_CHECK',
|
|
12
|
-
/** Initializing the
|
|
13
|
-
|
|
14
|
-
/**
|
|
12
|
+
/** Initializing the checkpoint proposal. */
|
|
13
|
+
INITIALIZING_CHECKPOINT = 'INITIALIZING_CHECKPOINT',
|
|
14
|
+
/** Waiting for transactions to arrive in the pool. */
|
|
15
|
+
WAITING_FOR_TXS = 'WAITING_FOR_TXS',
|
|
16
|
+
/** Creating a new L2 block. Includes processing public function calls. */
|
|
15
17
|
CREATING_BLOCK = 'CREATING_BLOCK',
|
|
16
|
-
/**
|
|
18
|
+
/** Waiting until the next block can be created. */
|
|
19
|
+
WAITING_UNTIL_NEXT_BLOCK = 'WAITING_UNTIL_NEXT_BLOCK',
|
|
20
|
+
/** Finalizing and broadcasting the checkpoint. */
|
|
21
|
+
FINALIZING_CHECKPOINT = 'FINALIZING_CHECKPOINT',
|
|
22
|
+
/** Collecting attestations from its peers. */
|
|
17
23
|
COLLECTING_ATTESTATIONS = 'COLLECTING_ATTESTATIONS',
|
|
18
|
-
/** Sending the tx to L1 with the L2
|
|
19
|
-
|
|
24
|
+
/** Sending the tx to L1 with the L2 checkpoint data and awaiting it to be mined.. */
|
|
25
|
+
PUBLISHING_CHECKPOINT = 'PUBLISHING_CHECKPOINT',
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
export type SequencerStateWithSlot =
|
|
23
|
-
| SequencerState.
|
|
29
|
+
| SequencerState.INITIALIZING_CHECKPOINT
|
|
30
|
+
| SequencerState.WAITING_FOR_TXS
|
|
24
31
|
| SequencerState.CREATING_BLOCK
|
|
32
|
+
| SequencerState.WAITING_UNTIL_NEXT_BLOCK
|
|
25
33
|
| SequencerState.COLLECTING_ATTESTATIONS
|
|
26
|
-
| SequencerState.
|
|
27
|
-
| SequencerState.PROPOSER_CHECK
|
|
34
|
+
| SequencerState.PUBLISHING_CHECKPOINT
|
|
35
|
+
| SequencerState.PROPOSER_CHECK
|
|
36
|
+
| SequencerState.FINALIZING_CHECKPOINT;
|
|
28
37
|
|
|
29
38
|
export type SequencerStateCallback = () => SequencerState;
|
|
30
39
|
|
package/src/test/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { ValidatorClient } from '@aztec/validator-client';
|
|
|
6
6
|
import { SequencerClient } from '../client/sequencer-client.js';
|
|
7
7
|
import type { SequencerPublisherFactory } from '../publisher/sequencer-publisher-factory.js';
|
|
8
8
|
import type { SequencerPublisher } from '../publisher/sequencer-publisher.js';
|
|
9
|
+
import type { FullNodeCheckpointsBuilder } from '../sequencer/checkpoint_builder.js';
|
|
9
10
|
import { Sequencer } from '../sequencer/sequencer.js';
|
|
10
11
|
import type { SequencerTimetable } from '../sequencer/timetable.js';
|
|
11
12
|
|
|
@@ -15,6 +16,7 @@ class TestSequencer_ extends Sequencer {
|
|
|
15
16
|
declare public publisher: SequencerPublisher;
|
|
16
17
|
declare public publisherFactory: SequencerPublisherFactory;
|
|
17
18
|
declare public validatorClient: ValidatorClient;
|
|
19
|
+
declare public checkpointsBuilder: FullNodeCheckpointsBuilder;
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export type TestSequencer = TestSequencer_;
|