|
| 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