@aztec/sequencer-client 0.0.1-commit.733c4a3 → 0.0.1-commit.7689c7f
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/README.md +282 -21
- package/dest/client/sequencer-client.d.ts +8 -3
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +53 -30
- package/dest/config.d.ts +28 -5
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +62 -27
- package/dest/global_variable_builder/fee_predictor.d.ts +37 -0
- package/dest/global_variable_builder/fee_predictor.d.ts.map +1 -0
- package/dest/global_variable_builder/fee_predictor.js +128 -0
- package/dest/global_variable_builder/fee_provider.d.ts +21 -0
- package/dest/global_variable_builder/fee_provider.d.ts.map +1 -0
- package/dest/global_variable_builder/fee_provider.js +58 -0
- package/dest/global_variable_builder/global_builder.d.ts +14 -14
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +16 -50
- package/dest/global_variable_builder/index.d.ts +4 -2
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/global_variable_builder/index.js +2 -0
- 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 +15 -3
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +19 -4
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +3 -4
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +1 -1
- package/dest/publisher/sequencer-bundle-simulator.d.ts +96 -0
- package/dest/publisher/sequencer-bundle-simulator.d.ts.map +1 -0
- package/dest/publisher/sequencer-bundle-simulator.js +198 -0
- package/dest/publisher/sequencer-publisher-factory.d.ts +3 -5
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +16 -3
- package/dest/publisher/sequencer-publisher.d.ts +77 -65
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +345 -512
- package/dest/sequencer/automine/automine_factory.d.ts +54 -0
- package/dest/sequencer/automine/automine_factory.d.ts.map +1 -0
- package/dest/sequencer/automine/automine_factory.js +84 -0
- package/dest/sequencer/automine/automine_sequencer.d.ts +151 -0
- package/dest/sequencer/automine/automine_sequencer.d.ts.map +1 -0
- package/dest/sequencer/automine/automine_sequencer.js +506 -0
- package/dest/sequencer/chain_state_overrides.d.ts +61 -0
- package/dest/sequencer/chain_state_overrides.d.ts.map +1 -0
- package/dest/sequencer/chain_state_overrides.js +98 -0
- package/dest/sequencer/checkpoint_proposal_job.d.ts +54 -11
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +776 -227
- package/dest/sequencer/checkpoint_proposal_job_metrics.d.ts +34 -0
- package/dest/sequencer/checkpoint_proposal_job_metrics.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_proposal_job_metrics.js +72 -0
- package/dest/sequencer/checkpoint_voter.d.ts +1 -2
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_voter.js +2 -5
- package/dest/sequencer/events.d.ts +47 -2
- package/dest/sequencer/events.d.ts.map +1 -1
- package/dest/sequencer/index.d.ts +3 -1
- package/dest/sequencer/index.d.ts.map +1 -1
- package/dest/sequencer/index.js +2 -0
- package/dest/sequencer/metrics.d.ts +13 -10
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +45 -20
- package/dest/sequencer/sequencer.d.ts +59 -16
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +333 -119
- package/dest/sequencer/timetable.d.ts +17 -3
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +51 -43
- package/dest/sequencer/types.d.ts +2 -2
- package/dest/sequencer/types.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.d.ts +7 -9
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.js +39 -30
- package/dest/test/utils.d.ts +1 -1
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +7 -6
- package/package.json +27 -28
- package/src/client/sequencer-client.ts +72 -33
- package/src/config.ts +76 -27
- package/src/global_variable_builder/README.md +44 -0
- package/src/global_variable_builder/fee_predictor.ts +172 -0
- package/src/global_variable_builder/fee_provider.ts +75 -0
- package/src/global_variable_builder/global_builder.ts +25 -62
- package/src/global_variable_builder/index.ts +3 -1
- package/src/index.ts +10 -1
- package/src/publisher/config.ts +40 -6
- package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +3 -1
- package/src/publisher/sequencer-bundle-simulator.ts +254 -0
- package/src/publisher/sequencer-publisher-factory.ts +18 -6
- package/src/publisher/sequencer-publisher.ts +426 -567
- package/src/sequencer/README.md +152 -450
- package/src/sequencer/automine/README.md +46 -0
- package/src/sequencer/automine/automine_factory.ts +145 -0
- package/src/sequencer/automine/automine_sequencer.ts +592 -0
- package/src/sequencer/chain_state_overrides.ts +162 -0
- package/src/sequencer/checkpoint_proposal_job.ts +941 -256
- package/src/sequencer/checkpoint_proposal_job_metrics.ts +128 -0
- package/src/sequencer/checkpoint_voter.ts +1 -12
- package/src/sequencer/events.ts +50 -2
- package/src/sequencer/index.ts +2 -0
- package/src/sequencer/metrics.ts +57 -24
- package/src/sequencer/sequencer.ts +414 -132
- package/src/sequencer/timetable.ts +64 -52
- package/src/sequencer/types.ts +1 -1
- package/src/test/mock_checkpoint_builder.ts +51 -48
- package/src/test/utils.ts +28 -10
package/src/sequencer/README.md
CHANGED
|
@@ -1,531 +1,233 @@
|
|
|
1
1
|
# Sequencer Timing Model
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This document covers how the sequencer schedules its work within a slot. See the [package README](../../README.md) for the high-level architecture; this one focuses on the timing math and the state-machine deadlines.
|
|
4
4
|
|
|
5
|
-
**
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
0s: Slot starts
|
|
9
|
-
0-2s: Sync + proposer check (fixed 2s offset)
|
|
10
|
-
|
|
11
|
-
Sub-slot 1: 2s-10s → Build Block 1, deadline at 10s
|
|
12
|
-
Sub-slot 2: 10s-18s → Build Block 2, deadline at 18s
|
|
13
|
-
Sub-slot 3: 18s-26s → Build Block 3, deadline at 26s
|
|
14
|
-
Sub-slot 4: 26s-34s → Build Block 4, deadline at 34s
|
|
15
|
-
Sub-slot 5: 34s-42s → Build Block 5 (last block), deadline at 42s
|
|
16
|
-
Sub-slot 6: 42s-50s → Reserved for validators to re-execute Block 5
|
|
17
|
-
|
|
18
|
-
42s: Broadcast checkpoint with Block 5
|
|
19
|
-
44s: Validators receive proposal (2s propagation)
|
|
20
|
-
44-52s: Validators re-execute Block 5 (8s)
|
|
21
|
-
52s: Validators send attestations
|
|
22
|
-
54s: Proposer receives attestations (2s propagation)
|
|
23
|
-
54-55s: Finalize checkpoint (1s)
|
|
24
|
-
55-67s: Publish to L1 (12s)
|
|
25
|
-
72s: Slot ends
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Deadlines are fixed relative to slot start, not relative to when work actually completes. If you finish initialization at 1s instead of 2s, you get bonus time for Block 1. If you finish at 3s, you have less time. If you finish at 9s, you skip the first sub-slot altogether and start building for the second one.
|
|
29
|
-
|
|
30
|
-
---
|
|
5
|
+
The model described here is for **proposer pipelining**, the standard mode in production. Non-pipelined scheduling existed historically and is in the process of being removed.
|
|
31
6
|
|
|
32
7
|
## Overview
|
|
33
8
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Key Concepts
|
|
37
|
-
|
|
38
|
-
### Slot vs Block vs Checkpoint vs Sub-Slot
|
|
9
|
+
Block production runs on three nested clocks:
|
|
39
10
|
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
42
|
-
-
|
|
43
|
-
- **Sub-slot**: A fixed-duration time window within a slot (e.g., 8 seconds) during which a block should be built
|
|
11
|
+
- A **slot** is a fixed window (e.g. 72 s) during which one elected proposer is allowed to build.
|
|
12
|
+
- A slot contains several equal-length **sub-slots** (e.g. 8 s). Each sub-slot owns the budget for one L2 block and has a deadline fixed relative to the slot start.
|
|
13
|
+
- All blocks built within one slot make up one **checkpoint**, which is what eventually goes on L1.
|
|
44
14
|
|
|
45
|
-
|
|
46
|
-
- 1 initialization period (2 seconds)
|
|
47
|
-
- 5 block-building sub-slots (8 seconds each = 40 seconds)
|
|
48
|
-
- 1 last validator re-execution sub-slot (8 seconds)
|
|
49
|
-
- 1 attestation and publishing period (17 seconds)
|
|
15
|
+
Under pipelining, the proposer for slot `N` does its building inside slot `N - 1` ("build slot"). Slot `N` ("target slot") is only used to mine the L1 transaction. This shifts work like this:
|
|
50
16
|
|
|
51
|
-
|
|
17
|
+
| Phase | When |
|
|
18
|
+
| ------------------------------ | -------------- |
|
|
19
|
+
| Initialization | slot `N - 1` |
|
|
20
|
+
| Block building | slot `N - 1` |
|
|
21
|
+
| Checkpoint proposal broadcast | slot `N - 1` |
|
|
22
|
+
| Last-block re-execution | slot `N - 1` |
|
|
23
|
+
| Attestation collection | slot `N - 1` |
|
|
24
|
+
| L1 submission | slot `N` |
|
|
52
25
|
|
|
53
|
-
|
|
26
|
+
The wall-clock slot the sequencer is reasoning about ("build slot") and the slot the checkpoint commits to ("target slot") are always `N - 1` and `N` respectively.
|
|
54
27
|
|
|
55
|
-
|
|
56
|
-
2. **Fixed deadlines**: Block N deadline = `initializationOffset + N * BLOCK_DURATION`
|
|
57
|
-
3. **Last sub-slot reserved**: The final sub-slot is reserved for validators to re-execute the last block (no block is built during this sub-slot)
|
|
58
|
-
4. **Skip if too late**: If we can't start a block with at least `MIN_EXECUTION_TIME` remaining before its deadline, we immediately start building in the next sub-slot
|
|
28
|
+
## Sub-slots
|
|
59
29
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
Understanding slot timing requires knowing these time constants:
|
|
63
|
-
|
|
64
|
-
| Component | Example Value | Purpose |
|
|
65
|
-
|-----------|---------------|---------|
|
|
66
|
-
| **Slot Duration** | 72s | Total time available for the entire checkpoint |
|
|
67
|
-
| **Block Duration** | 8s | Duration of each sub-slot (time budget for building one block) |
|
|
68
|
-
| **Initialization Offset** | 2s | Fixed estimate for sync + proposer check |
|
|
69
|
-
| **Propagation Time** | 2s | Time for messages to travel across the P2P network (one-way) |
|
|
70
|
-
| **Finalization Time** | 1s | Time to finalize checkpoint and prepare proposal message |
|
|
71
|
-
| **L1 Publishing Time** | 12s | Time reserved for L1 transaction to land in an Ethereum block |
|
|
72
|
-
| **Min Execution Time** | 3s | Minimum time needed to meaningfully build a block |
|
|
73
|
-
|
|
74
|
-
These values are configurable but must satisfy certain constraints (explained below). Example values may differ from the ones in the source code.
|
|
75
|
-
|
|
76
|
-
## Calculating Sub-Slots and Blocks
|
|
77
|
-
|
|
78
|
-
Given a slot configuration, we calculate how many blocks fit using this formula:
|
|
30
|
+
Each sub-slot has a fixed start time and a fixed deadline, both relative to the slot start:
|
|
79
31
|
|
|
80
32
|
```
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
+ propagationTime (attestations come back)
|
|
84
|
-
+ finalizationTime (checkpoint finalization)
|
|
85
|
-
+ l1PublishingTime (L1 transaction)
|
|
86
|
-
|
|
87
|
-
timeAvailableForBlocks = slotDuration - initializationOffset - timeReservedAtEnd
|
|
88
|
-
|
|
89
|
-
numberOfBlocks = floor(timeAvailableForBlocks / blockDuration)
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
**Example with typical values:**
|
|
33
|
+
subSlotStart[k] = initializationOffset + (k - 1) * blockDuration
|
|
34
|
+
subSlotDeadline[k] = initializationOffset + k * blockDuration
|
|
93
35
|
```
|
|
94
|
-
timeReservedAtEnd = 8s + 2s + 2s + 1s + 12s = 25s
|
|
95
|
-
timeAvailableForBlocks = 72s - 2s - 25s = 45s
|
|
96
|
-
numberOfBlocks = floor(45s / 8s) = 5 blocks
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
This means:
|
|
100
|
-
- Sub-slots 1-5: Build blocks 1-5
|
|
101
|
-
- Sub-slot 6: Reserved for validator re-execution of block 5
|
|
102
|
-
- After sub-slot 6: Attestation collection, finalization, and L1 publishing
|
|
103
|
-
|
|
104
|
-
## The Sequencer's Work
|
|
105
36
|
|
|
106
|
-
|
|
37
|
+
with `k = 1, 2, ..., maxNumberOfBlocks`. Deadlines do **not** shift based on when the previous block finished. If a block finishes early, the sequencer waits for the next sub-slot to begin (so validators see a regular cadence). If it finishes late, the next block has correspondingly less time.
|
|
107
38
|
|
|
108
|
-
|
|
39
|
+
`canStartNextBlock(secondsIntoSlot)` walks the sub-slot list and returns the first one with at least `minExecutionTime` left before its deadline. Sub-slots that no longer have enough headroom are skipped entirely.
|
|
109
40
|
|
|
110
|
-
|
|
111
|
-
- Verify it's the designated proposer
|
|
112
|
-
- Check all subsystems are synced
|
|
113
|
-
- Initialize checkpoint state
|
|
114
|
-
- Prepare global variables
|
|
41
|
+
### Number of sub-slots
|
|
115
42
|
|
|
116
|
-
|
|
43
|
+
The maximum number of buildable blocks per slot is:
|
|
117
44
|
|
|
118
|
-
### 2. Block Building Loop
|
|
119
|
-
|
|
120
|
-
The sequencer builds blocks in **fixed sub-slots** based on the configured block duration.
|
|
121
|
-
|
|
122
|
-
#### Sub-slot deadline calculation
|
|
123
|
-
|
|
124
|
-
Each sub-slot has a fixed start time and deadline:
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
subSlotStart[N] = initializationOffset + (N - 1) * blockDuration
|
|
128
|
-
subSlotDeadline[N] = initializationOffset + N * blockDuration
|
|
129
45
|
```
|
|
46
|
+
timeReservedAtEnd = checkpointAssembleTime
|
|
47
|
+
+ 2 * p2pPropagationTime // proposal out + attestations back
|
|
48
|
+
+ blockDuration // last-block re-execution
|
|
130
49
|
|
|
131
|
-
|
|
50
|
+
timeAvailableForBlocks = aztecSlotDuration
|
|
51
|
+
- checkpointInitializationTime
|
|
52
|
+
- timeReservedAtEnd
|
|
132
53
|
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
Sub-slot 1: starts at 2s, deadline at 10s
|
|
136
|
-
Sub-slot 2: starts at 10s, deadline at 18s
|
|
137
|
-
Sub-slot 3: starts at 18s, deadline at 26s
|
|
138
|
-
Sub-slot 4: starts at 26s, deadline at 34s
|
|
139
|
-
Sub-slot 5: starts at 34s, deadline at 42s
|
|
54
|
+
maxNumberOfBlocks = floor(timeAvailableForBlocks / blockDuration)
|
|
140
55
|
```
|
|
141
56
|
|
|
142
|
-
|
|
57
|
+
The reservation at the end of the slot is sized so that, on the happy path, attestations are in hand by the time the target slot starts. The enforced `COLLECTING_ATTESTATIONS` and `PUBLISHING_CHECKPOINT` deadlines are softer (see the deadline table below) and let a late attestation spill into the target slot. L1 publishing is **not** included in `timeReservedAtEnd` — that is paid for by the target slot.
|
|
143
58
|
|
|
144
|
-
|
|
59
|
+
### Cooldown after the last sub-slot
|
|
145
60
|
|
|
146
|
-
|
|
147
|
-
2. **Waits for transactions** (if needed): Wait up to the deadline for minimum number of transactions
|
|
148
|
-
3. **Builds block**: Execute transactions until the deadline of the sub-slot
|
|
149
|
-
4. **Signs and broadcasts**: Finalize block and broadcast proposal to validators
|
|
61
|
+
All `maxNumberOfBlocks` sub-slots build a block. The cooldown lives in the `timeReservedAtEnd` window that follows the last sub-slot:
|
|
150
62
|
|
|
151
|
-
|
|
63
|
+
- 1 × `checkpointAssembleTime` to assemble and sign the checkpoint,
|
|
64
|
+
- 1 × `p2pPropagationTime` for the `CheckpointProposal` to reach the committee,
|
|
65
|
+
- 1 × `blockDuration` for the committee to re-execute the last block,
|
|
66
|
+
- 1 × `p2pPropagationTime` for attestations to come back.
|
|
152
67
|
|
|
153
|
-
|
|
68
|
+
These four windows total `checkpointAssembleTime + blockDuration + 2 * p2pPropagationTime`, exactly the `timeReservedAtEnd` formula above. The block built in the last sub-slot is *not* broadcast as a regular `BlockProposal`; the proposer holds it as `blockPendingBroadcast` so it travels bundled inside the `CheckpointProposal`.
|
|
154
69
|
|
|
155
|
-
|
|
70
|
+
## Timing constants
|
|
156
71
|
|
|
157
|
-
|
|
72
|
+
These constants come from `@aztec/stdlib/timetable` (see `stdlib/src/timetable/index.ts`). Some are fixed across the network, some are inputs from configuration.
|
|
158
73
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
74
|
+
| Constant | Source | Typical value | Purpose |
|
|
75
|
+
| --------------------------------- | --------------------------------------- | ------------- | ---------------------------------------------------- |
|
|
76
|
+
| `aztecSlotDuration` | L1 rollup contract | 72 s | Length of one Aztec slot. |
|
|
77
|
+
| `ethereumSlotDuration` | L1 rollup contract | 12 s | Length of one Ethereum slot. |
|
|
78
|
+
| `blockDuration` | `blockDurationMs` config | 6–8 s | Sub-slot length. |
|
|
79
|
+
| `checkpointInitializationTime` | constant (`CHECKPOINT_INITIALIZATION_TIME`) | 1 s | Estimated sync + proposer check time. |
|
|
80
|
+
| `checkpointAssembleTime` | constant (`CHECKPOINT_ASSEMBLE_TIME`) | 1 s | Time to assemble and sign the checkpoint after the last block. |
|
|
81
|
+
| `p2pPropagationTime` | `attestationPropagationTime` config | 2 s | One-way p2p estimate (proposals, attestations). |
|
|
82
|
+
| `l1PublishingTime` | `l1PublishingTime` config | 12 s | Time reserved for the L1 tx to land. Used by the target slot, not the build slot. |
|
|
83
|
+
| `minExecutionTime` | constant (`MIN_EXECUTION_TIME`) | 2 s | Minimum headroom to start a block. |
|
|
84
|
+
| `initializationOffset` | `=checkpointInitializationTime` | 1 s | Where sub-slot 1 starts. |
|
|
163
85
|
|
|
164
|
-
|
|
165
|
-
1. Check current pending transaction count
|
|
166
|
-
2. If count >= `minTxsPerBlock`, proceed to build immediately
|
|
167
|
-
3. If count < `minTxsPerBlock`, poll every 500ms until either:
|
|
168
|
-
- Enough transactions arrive (proceed to build)
|
|
169
|
-
- Deadline is reached (skip building this block)
|
|
86
|
+
## Deadlines
|
|
170
87
|
|
|
171
|
-
|
|
172
|
-
- **Last block with empty checkpoint allowed**: If `buildCheckpointIfEmpty` is true and this is the last block, skip waiting and force build with 0+ transactions
|
|
173
|
-
- **Non-enforced timetable**: If enforcement is disabled, exit immediately if not enough transactions (don't wait)
|
|
88
|
+
`SequencerTimetable.getMaxAllowedTime(state)` returns the latest second-into-slot a given state is allowed to be entered. `assertTimeLeft()` throws `SequencerTooSlowError` if the slot has already advanced past that deadline. Sub-slot scheduling is measured against the build slot (`slotNow`); state assertions, however, are measured against whichever slot `setState` was called with — for the publishing path that is the target slot, which is why the publishing deadline is allowed to exceed `aztecSlotDuration`.
|
|
174
89
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
If the deadline (25s) is reached with only 2 transactions, the block is skipped and the sequencer moves to the next sub-slot.
|
|
90
|
+
| State | Max allowed time (seconds into build slot) |
|
|
91
|
+
| --------------------------- | --------------------------------------------------------------------------- |
|
|
92
|
+
| `PROPOSER_CHECK` | `initializeDeadline = aztecSlotDuration - (checkpointInitializationTime + 2*minExecutionTime)` |
|
|
93
|
+
| `INITIALIZING_CHECKPOINT` | same as `PROPOSER_CHECK` |
|
|
94
|
+
| `WAITING_FOR_TXS` | `initializeDeadline + checkpointInitializationTime` |
|
|
95
|
+
| `CREATING_BLOCK` | same as `WAITING_FOR_TXS` |
|
|
96
|
+
| `WAITING_UNTIL_NEXT_BLOCK` | same as `WAITING_FOR_TXS` |
|
|
97
|
+
| `ASSEMBLING_CHECKPOINT` | `aztecSlotDuration` (assembly completes by the build-slot boundary) |
|
|
98
|
+
| `COLLECTING_ATTESTATIONS` | same as `ASSEMBLING_CHECKPOINT` |
|
|
99
|
+
| `PUBLISHING_CHECKPOINT` | `2 * aztecSlotDuration - l1PublishingTime` (extends into the target slot) |
|
|
188
100
|
|
|
189
|
-
|
|
101
|
+
`ASSEMBLING_CHECKPOINT` and `COLLECTING_ATTESTATIONS` must be *entered* before the build-slot boundary; once entered, attestation collection itself has its own `checkpointAttestationDeadline = 2 * aztecSlotDuration - l1PublishingTime`, so a late attestation arriving after the boundary is still accepted. The publishing deadline extends into the target slot because that is when the L1 tx is actually submitted.
|
|
190
102
|
|
|
191
|
-
|
|
103
|
+
## Example: 72 s slot, 8 s sub-slots
|
|
192
104
|
|
|
193
|
-
|
|
105
|
+
With typical pipelining values:
|
|
194
106
|
|
|
195
|
-
Validators execute blocks **sequentially**. While the proposer builds Block N+1, validators are re-executing Block N (with a ~2s delay due to propagation). However, for the **last block**, there's no "Block N+1" to build while validators re-execute. We must wait for them to finish so they can attest.
|
|
196
|
-
|
|
197
|
-
**Timeline for the last block:**
|
|
198
|
-
|
|
199
|
-
```
|
|
200
|
-
T: Last block finishes building, checkpoint proposal broadcast
|
|
201
|
-
Last sub-slot begins (duration: blockDuration)
|
|
202
|
-
T+2s: Validators receive proposal (propagation delay)
|
|
203
|
-
T+2s to T+2s+blockDuration: Validators re-execute last block
|
|
204
|
-
T+2s+blockDuration: Validators finish re-execution, send attestations
|
|
205
|
-
T+4s+blockDuration: Proposer receives attestations (propagation delay)
|
|
206
107
|
```
|
|
108
|
+
checkpointInitializationTime = 1s
|
|
109
|
+
blockDuration = 8s
|
|
110
|
+
checkpointAssembleTime = 1s
|
|
111
|
+
p2pPropagationTime = 2s
|
|
112
|
+
l1PublishingTime = 12s
|
|
207
113
|
|
|
208
|
-
|
|
114
|
+
timeReservedAtEnd = 1 + 2*2 + 8 = 13s
|
|
115
|
+
timeAvailableForBlocks = 72 - 1 - 13 = 58s
|
|
116
|
+
maxNumberOfBlocks = floor(58 / 8) = 7
|
|
209
117
|
```
|
|
210
|
-
42s: Block 5 finishes, checkpoint broadcast, sub-slot 6 starts
|
|
211
|
-
44s: Validators receive checkpoint (42s + 2s)
|
|
212
|
-
44-52s: Validators re-execute Block 5 (8s)
|
|
213
|
-
52s: Validators send attestations
|
|
214
|
-
54s: Proposer receives attestations (52s + 2s)
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
Note that validators finish at `52s`, which is `2s` after the last sub-slot ends at `50s`. This is expected and accounted for in the `timeReservedAtEnd` calculation.
|
|
218
|
-
|
|
219
|
-
### 4. Attestation Collection and L1 Publishing
|
|
220
|
-
|
|
221
|
-
After the last block is built and validators have re-executed it:
|
|
222
|
-
|
|
223
|
-
1. **Collect attestations**: Wait for validators to send their signatures (arrive at T+4s+blockDuration)
|
|
224
|
-
2. **Finalize checkpoint**: Sign over attestations, assemble final checkpoint (1s)
|
|
225
|
-
3. **Publish to L1**: Submit transaction to Ethereum (needs 12s to land)
|
|
226
|
-
|
|
227
|
-
**Time reserved:** `2*propagationTime + finalizationTime + l1PublishingTime = 2s + 2s + 1s + 12s = 17s`
|
|
228
118
|
|
|
229
|
-
|
|
119
|
+
Seven sub-slots, all of which build a block:
|
|
230
120
|
|
|
231
|
-
## Handling Timing Variations
|
|
232
|
-
|
|
233
|
-
How does the sequencer timetable handle deviations from the expected times.
|
|
234
|
-
|
|
235
|
-
### Fast Initialization
|
|
236
|
-
|
|
237
|
-
**Scenario:** Initialization completes at 1s instead of 2s
|
|
238
|
-
|
|
239
|
-
```
|
|
240
|
-
0-1s: SYNCHRONIZING, PROPOSER_CHECK (1s actual, vs 2s estimate)
|
|
241
|
-
1s: Ready to build Block 1
|
|
242
|
-
1-10s: Build Block 1 (9s available vs 8s budgeted)
|
|
243
|
-
10s: Block 1 deadline
|
|
244
|
-
10-18s: Build Block 2
|
|
245
|
-
...
|
|
246
121
|
```
|
|
122
|
+
Sub-slot 1: starts 1s, deadline 9s (Block 1)
|
|
123
|
+
Sub-slot 2: starts 9s, deadline 17s (Block 2)
|
|
124
|
+
Sub-slot 3: starts 17s, deadline 25s (Block 3)
|
|
125
|
+
Sub-slot 4: starts 25s, deadline 33s (Block 4)
|
|
126
|
+
Sub-slot 5: starts 33s, deadline 41s (Block 5)
|
|
127
|
+
Sub-slot 6: starts 41s, deadline 49s (Block 6)
|
|
128
|
+
Sub-slot 7: starts 49s, deadline 57s (Block 7 — held for the checkpoint proposal)
|
|
247
129
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
This may happen if the sequencer has a slow L1 RPC endpoint and syncing the previous checkpoint from L1 takes longer than expected.
|
|
130
|
+
57s: Block 7 done, ASSEMBLING_CHECKPOINT (1s)
|
|
131
|
+
58s: CheckpointProposal broadcast
|
|
132
|
+
60s: Committee receives proposal (+2s p2p)
|
|
133
|
+
60-68s: Committee re-executes Block 7
|
|
134
|
+
68s: Committee sends attestations
|
|
135
|
+
70s: Proposer has the quorum (+2s p2p)
|
|
255
136
|
|
|
137
|
+
70-72s: Slack
|
|
138
|
+
72s: Build slot ends → L1 submission starts (target slot begins)
|
|
139
|
+
84s: L1 tx mined inside the target slot (+12s)
|
|
256
140
|
```
|
|
257
|
-
0-3s: SYNCHRONIZING, PROPOSER_CHECK (3s actual, vs 2s estimate)
|
|
258
|
-
3s: Ready to build Block 1
|
|
259
|
-
3-10s: Build Block 1 (7s available vs 8s budgeted)
|
|
260
|
-
10s: Block 1 deadline
|
|
261
|
-
10-18s: Build Block 2
|
|
262
|
-
...
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
**Result:** Block 1 has 1s less time (7s instead of 8s). Still enough time to build a block, just with fewer transactions or simpler execution.
|
|
266
141
|
|
|
267
|
-
|
|
142
|
+
## Parallel execution: proposer vs committee
|
|
268
143
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
While extremely unlikely, we still account for this scenario. We'd expect it to be related to faults to syncing blob data.
|
|
144
|
+
While the proposer builds block `k+1`, the committee is re-executing block `k`. The pipeline keeps both sides busy except for the cooldown sub-slot.
|
|
272
145
|
|
|
273
146
|
```
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
18s: Block 1 deadline (sub-slot 2)
|
|
287
|
-
18-26s: Build Block 2 using sub-slot 3
|
|
147
|
+
Time | Proposer | Committee
|
|
148
|
+
-----|------------------------------|--------------------------------------
|
|
149
|
+
1s | Start Block 1 | (idle)
|
|
150
|
+
9s | Finish Block 1, broadcast |
|
|
151
|
+
9s | Start Block 2 |
|
|
152
|
+
11s | | Receive Block 1 (9s + 2s)
|
|
153
|
+
| | Re-execute Block 1
|
|
154
|
+
17s | Finish Block 2, broadcast |
|
|
155
|
+
17s | Start Block 3 |
|
|
156
|
+
19s | | Finish Block 1 (11s + 8s)
|
|
157
|
+
| | Receive Block 2 (17s + 2s)
|
|
158
|
+
| | Re-execute Block 2
|
|
288
159
|
...
|
|
160
|
+
49s | Finish Block 6, broadcast |
|
|
161
|
+
49s | Start Block 7 (last) |
|
|
162
|
+
51s | | Receive Block 6 (49s + 2s)
|
|
163
|
+
| | Re-execute Block 6
|
|
164
|
+
57s | Finish Block 7 (held) |
|
|
165
|
+
| ASSEMBLING_CHECKPOINT (1s) |
|
|
166
|
+
58s | Broadcast CheckpointProposal |
|
|
167
|
+
59s | | Finish Block 6 (51s + 8s)
|
|
168
|
+
60s | | Receive Block 7 + Checkpoint (58s + 2s)
|
|
169
|
+
| | Re-execute Block 7
|
|
170
|
+
68s | | Send attestations (60s + 8s)
|
|
171
|
+
70s | Receive attestations |
|
|
172
|
+
70-72s| Slack |
|
|
173
|
+
72s | L1 tx submitted |
|
|
174
|
+
84s | L1 tx mined |
|
|
289
175
|
```
|
|
290
176
|
|
|
291
|
-
**
|
|
177
|
+
**Observations**:
|
|
292
178
|
|
|
293
|
-
|
|
179
|
+
- Validators always lag the proposer by ~2 s (one p2p hop).
|
|
180
|
+
- For the last block there is no `k+1` to build alongside; once the proposer broadcasts the `CheckpointProposal`, it just waits while the committee re-executes.
|
|
181
|
+
- L1 publishing happens entirely inside the next slot and does not steal time from block building.
|
|
294
182
|
|
|
295
|
-
|
|
183
|
+
## Handling timing variations
|
|
296
184
|
|
|
297
|
-
|
|
185
|
+
### Fast initialization (0.5 s instead of 1 s)
|
|
298
186
|
|
|
299
|
-
|
|
300
|
-
10s: Start building Block 2
|
|
301
|
-
19s: Block 2 finishes (1s late, deadline was 18s)
|
|
302
|
-
19s: Broadcast Block 2
|
|
303
|
-
Check: Can we start Block 3?
|
|
304
|
-
- Block 3 deadline: 26s
|
|
305
|
-
- Current time: 19s
|
|
306
|
-
- Time available: 7s
|
|
307
|
-
- MIN_EXECUTION_TIME: 3s
|
|
308
|
-
- 7s >= 3s, so CAN start Block 3
|
|
309
|
-
|
|
310
|
-
19-26s: Build Block 3 (7s available vs 8s budgeted)
|
|
311
|
-
26s: Block 3 deadline
|
|
312
|
-
```
|
|
187
|
+
Sub-slot 1's deadline is still 9 s, so Block 1 gets a 0.5 s bonus before hitting its deadline. No structural change.
|
|
313
188
|
|
|
314
|
-
|
|
189
|
+
### Slow initialization (2 s instead of 1 s)
|
|
315
190
|
|
|
316
|
-
|
|
317
|
-
```
|
|
318
|
-
24s: Block 2 finishes (6s late)
|
|
319
|
-
Check: Can we start Block 3 in sub-slot 3?
|
|
320
|
-
- Sub-slot 3 deadline: 26s
|
|
321
|
-
- Current time: 24s
|
|
322
|
-
- Time available: 2s
|
|
323
|
-
- MIN_EXECUTION_TIME: 3s
|
|
324
|
-
- 2s < 3s, so CANNOT use sub-slot 3
|
|
325
|
-
|
|
326
|
-
Use sub-slot 4 instead:
|
|
327
|
-
24-34s: Build Block 3 using sub-slot 4 (10s available vs 8s budgeted)
|
|
328
|
-
```
|
|
191
|
+
Block 1 has 7 s of build time instead of 8 s. Still well above `minExecutionTime`, so the block still gets built. No sub-slots are skipped.
|
|
329
192
|
|
|
330
|
-
|
|
193
|
+
### Very slow initialization (8 s)
|
|
331
194
|
|
|
332
|
-
|
|
195
|
+
Sub-slot 1's deadline (9 s) is closer than `minExecutionTime` (2 s), so it is skipped entirely. The first attempted block runs in sub-slot 2 with the usual budget. The checkpoint will have one fewer block.
|
|
333
196
|
|
|
334
|
-
|
|
197
|
+
### Block takes longer than its budget
|
|
335
198
|
|
|
336
|
-
|
|
199
|
+
`CheckpointBuilder` enforces the deadline by stopping public-tx execution; in practice a block can only overrun by the time it takes to finalize the block (typically < 1 s). The next sub-slot starts as scheduled but with proportionally less headroom. If that headroom drops below `minExecutionTime`, the next sub-slot is skipped.
|
|
337
200
|
|
|
338
|
-
|
|
339
|
-
10-15s: Build Block 2 (5s used vs 8s budgeted)
|
|
340
|
-
15s: Block 2 finished
|
|
341
|
-
15s: Broadcast Block 2
|
|
342
|
-
Check: Should we start Block 3 now or wait?
|
|
343
|
-
- Next sub-slot starts at 18s
|
|
344
|
-
- Wait until 18s to maintain regular intervals
|
|
345
|
-
|
|
346
|
-
15-18s: WAITING_UNTIL_NEXT_BLOCK
|
|
347
|
-
18s: Start building Block 3
|
|
348
|
-
18-26s: Build Block 3
|
|
349
|
-
```
|
|
201
|
+
### Block finishes early
|
|
350
202
|
|
|
351
|
-
|
|
203
|
+
The sequencer transitions to `WAITING_UNTIL_NEXT_BLOCK` and sleeps until the next sub-slot start. This keeps the cadence regular and gives validators predictable arrival times for re-execution.
|
|
352
204
|
|
|
353
|
-
|
|
205
|
+
### Block proposal returns insufficient txs
|
|
354
206
|
|
|
355
|
-
|
|
207
|
+
The current sub-slot is dropped without committing anything. The loop retries on the next sub-slot. If `buildCheckpointIfEmpty` is true, the last sub-slot is forced through with whatever is available, including zero txs.
|
|
356
208
|
|
|
357
|
-
###
|
|
209
|
+
### Build slot ends before attestations arrive
|
|
358
210
|
|
|
359
|
-
|
|
360
|
-
Time | Proposer | Validators
|
|
361
|
-
-----|----------------------------|---------------------------
|
|
362
|
-
2s | Start building Block 1 | (idle)
|
|
363
|
-
10s | Finish Block 1, broadcast | (idle)
|
|
364
|
-
10s | Start building Block 2 |
|
|
365
|
-
12s | | Receive Block 1 (10s + 2s)
|
|
366
|
-
| | Start re-executing Block 1
|
|
367
|
-
18s | Finish Block 2, broadcast |
|
|
368
|
-
20s | | Finish re-executing Block 1 (12s + 8s)
|
|
369
|
-
| | Receive Block 2 (18s + 2s)
|
|
370
|
-
| | Start re-executing Block 2
|
|
371
|
-
18s | Start building Block 3 |
|
|
372
|
-
26s | Finish Block 3, broadcast |
|
|
373
|
-
28s | | Finish re-executing Block 2 (20s + 8s)
|
|
374
|
-
| | Receive Block 3 (26s + 2s)
|
|
375
|
-
| | Start re-executing Block 3
|
|
376
|
-
...
|
|
377
|
-
42s | Finish Block 5, broadcast |
|
|
378
|
-
| checkpoint proposal |
|
|
379
|
-
44s | | Finish re-executing Block 4 (36s + 8s)
|
|
380
|
-
| | Receive Block 5 + checkpoint (42s + 2s)
|
|
381
|
-
| | Start re-executing Block 5
|
|
382
|
-
42-54s| COLLECTING_ATTESTATIONS |
|
|
383
|
-
52s | | Finish re-executing Block 5 (44s + 8s)
|
|
384
|
-
| | Send attestations
|
|
385
|
-
54s | Receive attestations | (done)
|
|
386
|
-
54-55s| ASSEMBLING_CHECKPOINT |
|
|
387
|
-
55s | PUBLISHING_CHECKPOINT |
|
|
388
|
-
```
|
|
211
|
+
`assertTimeLeft` will reject `PUBLISHING_CHECKPOINT` if the attestation deadline has passed; the slot is abandoned, and `checkpoint-publish-failed` is emitted. The `PUBLISHING_CHECKPOINT` deadline allows spillover into the target slot (`2 * aztecSlotDuration - l1PublishingTime`) precisely to absorb a small overrun.
|
|
389
212
|
|
|
390
|
-
|
|
391
|
-
- Validators lag by ~2s (propagation delay)
|
|
392
|
-
- While proposer builds Block N+1, validators re-execute Block N (parallel work)
|
|
393
|
-
- For the last block, proposer waits while validators re-execute
|
|
394
|
-
- The last sub-slot provides the time budget for this waiting period
|
|
213
|
+
### Pipelined parent fails on L1
|
|
395
214
|
|
|
396
|
-
|
|
215
|
+
Before submitting, the job calls `waitForValidParentCheckpointOnL1`. If the parent we built on top of did not land cleanly (wrong archive, missing attestations, etc.) the job discards its checkpoint, emits `pipelined-checkpoint-discarded`, and enqueues an invalidation for the parent so the next proposer doesn't get stuck on the same bad ancestor.
|
|
397
216
|
|
|
398
|
-
|
|
217
|
+
## Configuration constraints
|
|
399
218
|
|
|
400
|
-
|
|
219
|
+
`initializeDeadline` must be positive, so `aztecSlotDuration > checkpointInitializationTime + 2 * minExecutionTime`. With defaults that lower bound is 5 s, far below any realistic slot length.
|
|
401
220
|
|
|
402
|
-
For
|
|
403
|
-
```
|
|
404
|
-
slotDuration >= initializationOffset
|
|
405
|
-
+ blockDuration * 2 (at least 2 blocks)
|
|
406
|
-
+ blockDuration (last sub-slot)
|
|
407
|
-
+ 2 * propagationTime (round-trip)
|
|
408
|
-
+ finalizationTime (checkpoint finalization)
|
|
409
|
-
+ l1PublishingTime (L1 publishing)
|
|
410
|
-
```
|
|
221
|
+
For multi-block production to make sense, `maxNumberOfBlocks ≥ 2`:
|
|
411
222
|
|
|
412
|
-
Simplified:
|
|
413
223
|
```
|
|
414
|
-
|
|
224
|
+
aztecSlotDuration ≥ checkpointInitializationTime
|
|
225
|
+
+ 2 * blockDuration // two blocks
|
|
226
|
+
+ checkpointAssembleTime
|
|
227
|
+
+ 2 * p2pPropagationTime
|
|
228
|
+
+ blockDuration // last-block re-execution window
|
|
415
229
|
```
|
|
416
230
|
|
|
417
|
-
|
|
418
|
-
```
|
|
419
|
-
slotDuration >= 2s + 3*8s + 2*2s + 1s + 12s = 2s + 24s + 4s + 1s + 12s = 43s
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
For a 72s slot, this leaves `72s - 43s = 29s` of slack, allowing for about 3-4 additional blocks (29s / 8s ≈ 3.6).
|
|
423
|
-
|
|
424
|
-
### Block Duration Constraints
|
|
425
|
-
|
|
426
|
-
Block duration should be greater than the min execution time, and ideally a divisor of the time available for building.
|
|
427
|
-
|
|
428
|
-
```
|
|
429
|
-
blockDuration >= MIN_EXECUTION_TIME (3s practical minimum for meaningful execution)
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
### Initialization Offset
|
|
433
|
-
|
|
434
|
-
The initialization offset should be set based on empirical measurements of how long initialization typically takes, with typical values being 1-3 seconds.
|
|
435
|
-
|
|
436
|
-
**Key point:** This is an *estimate*, not a hard deadline. The sequencer will take as long as needed for initialization. If it takes longer than the offset, the first block just has less time. If it takes less, the first block has bonus time.
|
|
437
|
-
|
|
438
|
-
### Propagation Time
|
|
439
|
-
|
|
440
|
-
Should be measured empirically on the actual P2P network, accounting for:
|
|
441
|
-
- Network latency between geographically distributed validators
|
|
442
|
-
- Gossip network propagation (not direct communication)
|
|
443
|
-
- Block/checkpoint size (larger messages take longer)
|
|
444
|
-
|
|
445
|
-
Typical values: 1-3 seconds
|
|
446
|
-
|
|
447
|
-
### L1 Publishing Time
|
|
448
|
-
|
|
449
|
-
Must account for Ethereum slot duration (12s) and blob propagation time:
|
|
450
|
-
- Bare minimum: 8s (Ethereum allows txs up to 4s into the slot)
|
|
451
|
-
- Recommended minimum: 12s (full Ethereum slot)
|
|
452
|
-
- With high blob congestion: 24s (two slots)
|
|
453
|
-
|
|
454
|
-
## State Machine
|
|
455
|
-
|
|
456
|
-
The sequencer transitions through these states during a slot:
|
|
457
|
-
|
|
458
|
-
| State | Time Budget | Purpose |
|
|
459
|
-
|-------|-------------|---------|
|
|
460
|
-
| **SYNCHRONIZING** | No limit | Wait for all subsystems to sync |
|
|
461
|
-
| **PROPOSER_CHECK** | Part of init offset | Verify we're the proposer |
|
|
462
|
-
| **INITIALIZING_CHECKPOINT** | Part of init offset | Set up checkpoint state |
|
|
463
|
-
| **WAITING_FOR_TXS** | Until block deadline | Wait for enough transactions |
|
|
464
|
-
| **CREATING_BLOCK** | Until block deadline | Execute transactions and build block |
|
|
465
|
-
| **WAITING_UNTIL_NEXT_BLOCK** | Until next sub-slot start | Sleep between blocks to maintain intervals |
|
|
466
|
-
| **ASSEMBLING_CHECKPOINT** | assembleTime (1s) | Assemble final checkpoint |
|
|
467
|
-
| **COLLECTING_ATTESTATIONS** | Until L1 publish deadline | Wait for validator signatures |
|
|
468
|
-
| **PUBLISHING_CHECKPOINT** | Until slot end | Submit to L1 |
|
|
469
|
-
|
|
470
|
-
## Complete Example: 72-Second Slot with 8-Second Sub-Slots
|
|
471
|
-
|
|
472
|
-
Let's walk through a complete slot with the happy path:
|
|
473
|
-
|
|
474
|
-
```
|
|
475
|
-
T=0s Slot begins for slot N
|
|
476
|
-
|
|
477
|
-
T=0-2s SYNCHRONIZING, PROPOSER_CHECK, INITIALIZING_CHECKPOINT
|
|
478
|
-
Actual time: 1.8s (slightly faster than 2s estimate)
|
|
479
|
-
|
|
480
|
-
T=2s Sub-slot 1 deadline calculation: 2s + 1*8s = 10s
|
|
481
|
-
T=1.8s Ready to build, start Block 1 immediately
|
|
482
|
-
Available time: 10s - 1.8s = 8.2s (bonus 0.2s!)
|
|
483
|
-
T=1.8-9.5s CREATING_BLOCK 1
|
|
484
|
-
T=9.5s Block 1 complete, broadcast
|
|
485
|
-
T=9.5-10s Wait for next sub-slot
|
|
486
|
-
|
|
487
|
-
T=10s Sub-slot 2 starts, deadline: 2s + 2*8s = 18s
|
|
488
|
-
T=10-17.5s CREATING_BLOCK 2
|
|
489
|
-
T=17.5s Block 2 complete, broadcast
|
|
490
|
-
T=17.5-18s Wait for next sub-slot
|
|
491
|
-
|
|
492
|
-
T=18s Sub-slot 3 starts, deadline: 2s + 3*8s = 26s
|
|
493
|
-
T=18-25s CREATING_BLOCK 3
|
|
494
|
-
T=25s Block 3 complete, broadcast
|
|
495
|
-
T=25-26s Wait for next sub-slot
|
|
496
|
-
|
|
497
|
-
T=26s Sub-slot 4 starts, deadline: 2s + 4*8s = 34s
|
|
498
|
-
T=26-33.5s CREATING_BLOCK 4
|
|
499
|
-
T=33.5s Block 4 complete, broadcast
|
|
500
|
-
T=33.5-34s Wait for next sub-slot
|
|
501
|
-
|
|
502
|
-
T=34s Sub-slot 5 starts, deadline: 2s + 5*8s = 42s
|
|
503
|
-
T=34-41s CREATING_BLOCK 5 (last block)
|
|
504
|
-
T=41s Block 5 complete
|
|
505
|
-
|
|
506
|
-
T=41s ASSEMBLING_CHECKPOINT (1s)
|
|
507
|
-
T=42s Checkpoint proposal broadcast
|
|
508
|
-
Sub-slot 6 starts (last sub-slot, reserved for validator reexec)
|
|
509
|
-
|
|
510
|
-
T=44s Validators receive checkpoint (42s + 2s propagation)
|
|
511
|
-
Validators start re-executing Block 5
|
|
512
|
-
|
|
513
|
-
T=52s Validators finish re-executing Block 5 (44s + 8s)
|
|
514
|
-
Validators send attestations
|
|
515
|
-
|
|
516
|
-
T=54s COLLECTING_ATTESTATIONS
|
|
517
|
-
Proposer receives attestations (52s + 2s propagation)
|
|
518
|
-
|
|
519
|
-
T=55s PUBLISHING_CHECKPOINT
|
|
520
|
-
Sign over attestations, submit L1 transaction
|
|
521
|
-
|
|
522
|
-
T=67s L1 transaction lands in Ethereum block (12s)
|
|
523
|
-
|
|
524
|
-
T=72s Slot ends (5s buffer remaining)
|
|
525
|
-
```
|
|
231
|
+
Block duration should be ≥ `minExecutionTime` (otherwise no sub-slot ever has enough headroom). `p2pPropagationTime` should be measured against the deployment's actual p2p latency: it directly determines how much of each slot is spent on the cooldown.
|
|
526
232
|
|
|
527
|
-
|
|
528
|
-
- Built 5 blocks (sub-slots 1-5)
|
|
529
|
-
- Last sub-slot (6) reserved for validator re-execution
|
|
530
|
-
- Total time: 72s
|
|
531
|
-
- Buffer: 5s (72s - 67s)
|
|
233
|
+
`l1PublishingTime` should fit inside the Ethereum slot the target slot maps to. The default of 12 s lines up with one Ethereum slot; congested deployments may need to increase it (which only affects the `PUBLISHING_CHECKPOINT` deadline, not the number of blocks built).
|