Skip to content

Commit f56be42

Browse files
committed
docs: do an improvement pass
1 parent ba5431c commit f56be42

1 file changed

Lines changed: 91 additions & 20 deletions

File tree

docs/slots_and_intervals.md

Lines changed: 91 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,110 @@
11
# Slots and Intervals
22

3-
A Lean Chain slot has a duration of 4 seconds and is divided in 5 intervals:
3+
A Lean Chain slot has a duration of 4 seconds and is divided in 5 intervals of 800 ms.
4+
Every duty a validator owes the chain is due in one of them:
45

5-
1. Block proposal
6-
2. Vote propagation
7-
3. Vote aggregation
8-
4. Safe target computation
9-
5. Head update
6+
| Interval | Offset | Duty | Who acts | What it publishes |
7+
| --- | --- | --- | --- | --- |
8+
| 0 | t+0 ms | [Block proposal](#interval-0-block-proposal) | the slot's proposer | the block, on the `block` topic |
9+
| 1 | t+800 ms | [Vote propagation](#interval-1-vote-propagation) | every validator | a signed attestation, on its subnet topic |
10+
| 2 | t+1600 ms | [Vote aggregation](#interval-2-vote-aggregation) | aggregators | an aggregated attestation, on the `aggregation` topic |
11+
| 3 | t+2400 ms | [Safe target computation](#interval-3-safe-target-computation) | every validator | nothing: local bookkeeping |
12+
| 4 | t+3200 ms | [Head update](#interval-4-head-update) | every validator | nothing: local bookkeeping |
1013

1114
```text
1215
ONE SLOT (4000 ms)
1316
┌────────────┬────────────┬────────────┬────────────┬────────────┐
1417
│ Interval 0 │ Interval 1 │ Interval 2 │ Interval 3 │ Interval 4 │
1518
│ t+0 ms │ t+800 ms │ t+1600 ms │ t+2400 ms │ t+3200 ms │
1619
├────────────┼────────────┼────────────┼────────────┼────────────┤
17-
│ block │ vote │ vote │ safe target│ head │
20+
│ block │ vote │ vote │safe target │ head │
1821
│ proposal │propagation │aggregation │computation │ update │
1922
└────────────┴────────────┴────────────┴────────────┴────────────┘
23+
◄───────────── gossiped ─────────────▶ ◄───── local only ───────▶
2024
```
2125

22-
Block proposal is the first interval of a slot. During this interval, a block proposer, selected in a round-robin fashion, proposes a new block and gossips it to the network. Right before building the block, the proposer merges their "new attestations buffer" into their fork-choice view. They then include attestations that the proposer has recently seen into their block. Other validators verify the block and its contents, and merge the votes it includes into their fork-choice view. After importing a block, all validators recompute their [head](./lmd_ghost.md), and update the latest [finalized and justified checkpoints](./3sf_mini.md) according to the block's post-state.
26+
The grid comes from a genesis timestamp every node shares, so the schedule needs no
27+
coordination messages: a node reads its clock, works out which interval it is in, and
28+
knows which duty is due. The order is a dependency chain, since each interval consumes
29+
what the previous one produced. A duty that overruns its interval is not rescheduled: it
30+
lands late, and the slot moves on without it.
2331

24-
Vote propagation is the second interval of a slot. During this interval, validators gossip their votes for the block they consider to be the head of the chain, and append to it a `(source, target)` [finality vote](./3sf_mini.md). These votes are in aggregation subnets and are imported by aggregators. Aggregators verify the votes in their subnet and store them for later aggregation.
32+
> **In ethlambda:** the intervals are the `SlotInterval` variants in
33+
> `crates/blockchain/src/lib.rs`, and their length comes from
34+
> `MILLISECONDS_PER_INTERVAL` and `INTERVALS_PER_SLOT` in
35+
> `crates/common/types/src/constants.rs`.
2536
26-
Vote aggregation is the third interval of a slot. During this interval, aggregators aggregate the votes they have received and gossip the resulting aggregated attestations to the network. These aggregated attestations are imported by all validators, who verify and store them in a "new attestations buffer".
37+
## Interval 0: Block proposal
2738

28-
Safe target computation is the fourth interval of a slot. During this interval, validators compute the [safe target](./lmd_ghost.md#safe-target-selection) they'll use when deciding which finality vote to cast on the next slot. The safe target is computed based on the votes received in the current slot.
39+
A block proposer, selected in a round-robin fashion (`slot % num_validators`), proposes a
40+
new block and gossips it to the network. Right before building the block, the proposer
41+
merges their "new attestations buffer" into their fork-choice view. They then include
42+
attestations that the proposer has recently seen into their block. Other validators verify
43+
the block and its contents, and merge the votes it includes into their fork-choice view.
44+
After importing a block, all validators [recompute their head](./lmd_ghost.md), and update
45+
the latest [finalized and justified checkpoints](./3sf_mini.md) according to the block's
46+
post-state.
2947

30-
Head update is the fifth and final interval of a slot. During this interval, validators merge the aggregated attestations they have in their "new attestations buffer" into their fork-choice view, and recompute their head.
48+
A block body carries at most
49+
`MAX_ATTESTATIONS_DATA` aggregated attestations: distinct `(slot, head, target, source)` tuples, each paired with a
50+
bitfield naming the validators bound to it.
51+
Genesis occupies slot 0, so proposals start at slot 1, and nothing forces a slot to be
52+
filled: a proposer that is offline or too slow leaves an empty slot, and the next block
53+
simply points its parent root at an older block.
3154

32-
> **In ethlambda:** the intervals are the `SlotInterval` variants in
33-
> `crates/blockchain/src/lib.rs`, and their length comes from
34-
> `MILLISECONDS_PER_INTERVAL` and `INTERVALS_PER_SLOT` in
35-
> `crates/common/types/src/constants.rs`. Block proposal is merged into the
36-
> previous slot's head-update interval: the proposer advances its store to the
37-
> next slot, builds the block there, and holds publication until the slot
38-
> boundary. That buys the build one extra interval of headroom and leaves no
39-
> actor work at the block-proposal tick itself.
55+
> **In ethlambda:** block proposal is merged into the previous slot's head-update
56+
> interval: the proposer advances its store to the next slot, builds the block there,
57+
> and holds publication until the slot boundary. That buys the build one extra interval
58+
> of headroom and leaves no actor work at the block-proposal tick itself.
59+
60+
## Interval 1: Vote propagation
61+
62+
Validators gossip their votes for the block they consider to be the head of the chain, and
63+
append to it a `(source, target)` [finality vote](./3sf_mini.md#recap-attestation-anatomy).
64+
These votes are in aggregation subnets and are imported by aggregators. Aggregators verify
65+
the votes in their subnet and store them for later aggregation.
66+
67+
> **In ethlambda:** a validator's subnet is `validator_index % attestation_committee_count`,
68+
> and a node only aggregates for subnets it subscribed to at startup. Aggregation is also
69+
> gated on the aggregator role, seeded by `--is-aggregator` and flippable at runtime
70+
> through the admin API. A chain whose validators all decline the role still gossips votes
71+
> and logs them as processed, but no aggregate is ever produced, so every block is empty
72+
> and the chain never justifies.
73+
74+
## Interval 2: Vote aggregation
75+
76+
Aggregators aggregate the votes they have received and gossip the resulting aggregated
77+
attestations to the network. These aggregated attestations are imported by all validators,
78+
who verify and store them in a "new attestations buffer".
79+
80+
Aggregation earns its own interval because it is the heaviest recurring computation in the
81+
client: collapsing a subnet's worth of them
82+
into one proof is heavy CPU work. It is also what makes a block affordable, since a block
83+
carrying raw votes would need one full XMSS signature per voter, quickly going over the network bandwidth limit.
84+
85+
> **In ethlambda:** the proofs run on an off-thread worker so the blockchain actor's
86+
> message loop stays responsive, and a session may start up to `EARLY_AGGREGATION_WINDOW`
87+
> before the interval boundary once two thirds of the signatures are in. At the session's
88+
> soft deadline the actor stops handing out new jobs, but a proof already in flight
89+
> finishes and publishes late rather than being discarded.
90+
91+
## Interval 3: Safe target computation
92+
93+
Validators compute the [safe target](./lmd_ghost.md#safe-target-selection) they'll use when
94+
deciding which finality vote to cast on the next slot. The safe target is computed based on
95+
the votes received in the current slot.
96+
97+
It is LMD-GHOST run with a two-thirds weight threshold instead of a plain majority, so it
98+
sits at or behind the head and advances only once a branch is backed by a supermajority.
99+
Deriving targets from it is what stops [3SF-mini](./3sf_mini.md) from justifying a branch
100+
the network has not visibly converged on.
101+
102+
## Interval 4: Head update
103+
104+
Validators merge the aggregated attestations they have in their "new attestations buffer"
105+
into their fork-choice view, and recompute their head.
106+
107+
This is the slot's second and last promotion point; the first is the proposer's, just
108+
before it builds. Between promotions a vote sits in the buffer without weight, which is
109+
what keeps a validator's fork-choice view from shifting under it mid-slot. See
110+
[why staged promotion](./lmd_ghost.md#why-staged-promotion) for the reasoning.

0 commit comments

Comments
 (0)