Skip to content

Commit f1d0a58

Browse files
committed
1 parent 1c3d844 commit f1d0a58

14 files changed

+433
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Messages to Events
2+
3+
The consensus state-machine operates on complex `Event`s that reflect the
4+
reception of one or multiple `Message`s, combined with state elements and the
5+
interaction with other modules.
6+
7+
This document overviews how messages should be handled at different stages of
8+
the protocol.
9+
10+
It is assume that a process is at round `r` of height `h` of consensus, or in
11+
short, at round `(h, r)`.
12+
13+
## Pending
14+
15+
- [ ] How to handle messages from [different heights](#different-heights) in general
16+
- [ ] Definitions and details regarding the [round skipping](#round-skipping) mechanism
17+
- [ ] How to limit the amount of messages from [future rounds](#future-rounds) stored
18+
- [ ] Full mapping between messages of the [current round](#current-round) and the produced events
19+
20+
## Different heights
21+
22+
Messages with heights `h'` with either `h' < h` (past) or `h' > h` (future).
23+
24+
The pseudo-code description of the algorithm ignores messages from different
25+
heights.
26+
If we take the same approach in this specification, we have to specify
27+
separately modules responsible to handle those messages.
28+
29+
30+
- Past heights (`h' < h`): the consensus state machine is not affected by such
31+
messages. However, their reception might indicate that a peer is lagging
32+
behind in the protocol, and need to be synchronized.
33+
- In CometBFT's implementation we handle message from the previous height
34+
(`h' = h - 1`) for the `LastCommit` vote set. This only happens during the
35+
first step of the first round (`r = 0`) of a height.
36+
- Future heights (`h' > h`): the consensus state machine is not able to process
37+
message from future heights in a proper way, as the validator set for them is
38+
not known. However, once the process reaches this height `h'`, those messages
39+
are _required_ for proper operation. There are two options here:
40+
1. Buffer a limited amount of such messages
41+
2. Assume that the communication subsystem (p2p) is able to retrieve (ask for
42+
retransmission) of them when the process reaches height `h'`.
43+
Notice that this option implies that processes keep a minimal set of
44+
consensus messages that enables peers lagging behind to decide a past height.
45+
46+
## Previous rounds
47+
48+
Messages from rounds `(h, r')` with `r' < r`: same height `h` but previous round `r'`.
49+
50+
The consensus state machine requires receiving and processing messages from
51+
previous rounds:
52+
53+
- `PREVOTE` messages can produce a Proof of Lock (POL) `2f + 1 ⟨PREVOTE, h, vr, id(v)⟩`
54+
needed for accepting `PROPOSAL(h, r, v, vr)` message from the current round,
55+
where `vr == r' < r` (L28).
56+
- `PRECOMMIT` messages can produce a Precommit quorum `2f + 1 ⟨PRECOMMIT, h, r', id(v)⟩`
57+
that leads to the decision of `v` at round `r'` (L49).
58+
- `PROPOSAL` messages can be required to match a produced Precommit quorum (L49).
59+
- Associated full value messages are required to produce the `⟨PROPOSAL, h, r', v, *⟩` event
60+
61+
The production of the enumerated events from previous rounds should be
62+
identical to the production of events from messages from the [current round](#current-round).
63+
64+
## Future rounds
65+
66+
Messages from rounds `(h, r')` with `r' > r`: same height `h` but future round `r'`.
67+
68+
### Round skipping
69+
70+
The consensus state machine requires receiving and processing messages from
71+
future rounds for enabling the _round skipping_ mechanism, defined as follows
72+
in the pseudo-code:
73+
74+
```
75+
55: upon f + 1 ⟨∗, hp, round, ∗, ∗⟩ with round > roundp do
76+
56: StartRound(round)
77+
```
78+
79+
The current interpretation of this rule is that messages from a round `r' > r`
80+
are received from `f + 1` voting-power equivalent distinct senders.
81+
This means, that at least `1` correct process is at round `r'`.
82+
83+
While this threshold does not need to be adopted (it can be configurable),
84+
messages from a future round should initially have their unique senders counted.
85+
Once the round skip threshold of processes is reached, the corresponding event
86+
should be produced.
87+
88+
### Limits
89+
90+
The same reasoning applied for messages from [future heights](#different-heights)
91+
applies for messages from future rounds.
92+
93+
Messages from future rounds are _required_ for the proper operation of the
94+
consensus state machine once the process reaches their round `r'`.
95+
There are two options, which can in particular be combined:
96+
97+
1. Buffer a limited amount of such messages, or messages from a limited amount
98+
of future rounds `r'`
99+
- In CometBFT's implementation, only messages from round `r' = r + 1` are tracked.
100+
2. Assume that the communication subsystem (p2p) is able to retrieve (ask for
101+
retransmission) of messages from future rounds when the process reaches round `r'`.
102+
Since messages from [previous rounds](#previous-rounds) are stored by
103+
default, peers that have reached the future round `r'` should be able to
104+
retransmit them.
105+
106+
## Current round
107+
108+
Messages matching the current round `(h, r)` of a process produce most of the
109+
relevant events for the consensus state machine.
110+
111+
TODO:
112+
113+
## Counting votes
114+
115+
Messages `⟨PREVOTE, h, r, *⟩` and `⟨PRECOMMIT, h, r, *⟩` are generically called votes.
116+
They refer to a round step `(h, r, s)` of consensus, where `s` is defined by
117+
the vote type, either `PREVOTE` or `PRECOMMIT`.
118+
119+
The processing of _individual_ vote messages don't produce events relevant for
120+
the consensus state machine.
121+
But when the number of unique vote messages referring to a given round step
122+
`(h, r, s)` reaches a given _threshold_, relevant events are produced;
123+
the produced event depends on the value carried by such votes.
124+
125+
General assumptions regarding vote messages:
126+
127+
- Vote messages are produced, signed and broadcast by a validator, which is its
128+
*sender*
129+
- To define whether a vote message for round step `(h, r, s)` is valid, the
130+
validator set for height `h` must to be known.
131+
The validator set can change over heights, but it is the same within a height.
132+
- To each validator in the validator set of a height `h` is associated a *voting power*
133+
- Thresholds are computed from the voting power associated to the
134+
sender of each vote message
135+
- A vote message carries a value: either a reference to a proposed value
136+
`id(v)`, or the special `nil` value
137+
- For practical effects, it should be considered that the size of vote
138+
messages is constant
139+
- Correct validators produce at most one vote message per round step: either
140+
for a `id(v)` or for `nil`
141+
- Byzantine validators may equivocate and produce multiple distinct vote
142+
messages for the same round step. Equivocating vote messages differ on the
143+
value they carry: for `nil`, `id(v)`, `id(v')`, etc.
144+
- This possibility constitutes an attack vector. A process must thus restrict
145+
the number of distinct vote messages from the same sender and referring to
146+
the same round step that can be stored.
147+
148+
### `f + 1` threshold
149+
150+
This threshold represents that vote messages referring to a round step were
151+
received from a enough number of unique senders, so that it is guaranteed that
152+
_at least one_ of the senders is a _correct_ validator.
153+
154+
The rationale here is that the cumulative voting power of Byzantine validators
155+
cannot exceed `f`, so that at least one of the considered vote messages must
156+
have been produced by a correct validator.
157+
158+
### `2f + 1` threshold
159+
160+
This threshold represents that vote messages referring to a round step were
161+
received from a enough number of unique senders, so that it is guaranteed that
162+
_the majority_ of the senders are _correct_ validators.
163+
164+
The rationale here is that the cumulative voting power of Byzantine validators
165+
cannot exceed `f`, so that the subset of considered vote messages that must
166+
have been produced by correct validators have a cumulative voting power of at
167+
least `f + 1`, which is strictly greater than `f`.
168+
169+
> TODO: this also means that the majority of the voting power hold by correct
170+
> validators is represented in the considered set of vote messages.

0 commit comments

Comments
 (0)