* `tendermint.ivy`, a specification of Tendermint algorithm as described in *The latest gossip on BFT consensus* by E. Buchman, J. Kwon, Z. Milosevic.
* `tendermint.ivy`, a specification of Tendermint algorithm as described in *The latest gossip on BFT consensus* by E. Buchman, J. Kwon, Z. Milosevic.
* `abstract_tendermint.ivy`, a more abstract specification of Tendermint that is more verification-friendly.
* `abstract_tendermint.ivy`, a more abstract specification of Tendermint that is more verification-friendly.
* `classic_safety.ivy`, a proof that Tendermint satisfies the classic safety property of BFT consensus: if every two quorums have a well-behaved node in common, then no two well-behaved nodes ever disagree.
* `classic_safety.ivy`, a proof that Tendermint satisfies the classic safety property of BFT consensus: if every two quorums have a well-behaved node in common, then no two well-behaved nodes ever disagree.
@ -17,7 +22,8 @@ All specifications and proofs are written in [Ivy](https://github.com/kenmcmil/i
The license above applies to all files in this folder.
The license above applies to all files in this folder.
# Building and running
## Building and running
The easiest way to check the proofs is to use [Docker](https://www.docker.com/).
The easiest way to check the proofs is to use [Docker](https://www.docker.com/).
1. Install [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/).
1. Install [Docker](https://docs.docker.com/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/).
@ -42,6 +42,7 @@ This phase aims to allow applications to require their validators do more than j
Example usecases of this include validator determined price oracles, validator guaranteed IBC connection attempts, and validator based threshold crypto.
Example usecases of this include validator determined price oracles, validator guaranteed IBC connection attempts, and validator based threshold crypto.
This adds an app-determined data field that every validator must include with their vote, and these will thus appear in the header.
This adds an app-determined data field that every validator must include with their vote, and these will thus appear in the header.
#### Rename {BeginBlock, [DeliverTx], EndBlock} to FinalizeBlock
#### Rename {BeginBlock, [DeliverTx], EndBlock} to FinalizeBlock
The prior phases gives the application more flexibility in their execution model for a block, and they obsolete the current methods for how the consensus engine relates the block data to the state machine. Thus we refactor the existing methods to better reflect what is happening in the new ABCI model.
The prior phases gives the application more flexibility in their execution model for a block, and they obsolete the current methods for how the consensus engine relates the block data to the state machine. Thus we refactor the existing methods to better reflect what is happening in the new ABCI model.
@ -185,7 +186,7 @@ We go through this phase by phase.
##### Prepare proposal IPC overhead
##### Prepare proposal IPC overhead
This requires a round of IPC communication, where both directions are quite large. Namely the proposer communicating an entire block to the application.
This requires a round of IPC communication, where both directions are quite large. Namely the proposer communicating an entire block to the application.
However, this can be mitigated by splitting up `PrepareProposal` into two distinct, async methods, one for the block IPC communication, and one for the Header IPC communication.
However, this can be mitigated by splitting up `PrepareProposal` into two distinct, async methods, one for the block IPC communication, and one for the Header IPC communication.
Then for chains where the block data does not depend on the header data, the block data IPC communication can proceed in parallel to the prior block's voting phase. (As a node can know whether or not its the leader in the next round)
Then for chains where the block data does not depend on the header data, the block data IPC communication can proceed in parallel to the prior block's voting phase. (As a node can know whether or not its the leader in the next round)
The algorithm in the [arXiv paper][arXiv] evaluates rules of the received messages without making explicit how these messages are received. In our solution, we will make some message filtering explicit. We will assume that there are message reception steps (where messages are received and possibly stored locally for later evaluation of rules) and processing steps (the latter roughly as described in a way similar to the pseudo code of the arXiv paper).
The algorithm in the [arXiv paper][arXiv] evaluates rules of the received messages without making explicit how these messages are received. In our solution, we will make some message filtering explicit. We will assume that there are message reception steps (where messages are received and possibly stored locally for later evaluation of rules) and processing steps (the latter roughly as described in a way similar to the pseudo code of the arXiv paper).
In contrast to the original algorithm the field `proposal` in the `PROPOSE` message is a pair `(v, time)`, of the proposed consensus value `v` and the proposed time `time`.
In contrast to the original algorithm the field `proposal` in the `PROPOSE` message is a pair `(v, time)`, of the proposed consensus value `v` and the proposed time `time`.
#### **[PBTS-RECEPTION-STEP.0]**
#### **[PBTS-RECEPTION-STEP.0]**
In the reception step at process `p` at local time `now_p`, upon receiving a message `m`:
In the reception step at process `p` at local time `now_p`, upon receiving a message `m`:
- if the message `m` is of type `PROPOSE` and satisfies `now_p - PRECISION < m.time < now_p + PRECISION + MSGDELAY`, then mark the message as `timely`
- if the message `m` is of type `PROPOSE` and satisfies `now_p - PRECISION < m.time < now_p + PRECISION + MSGDELAY`, then mark the message as `timely`
> if `m` does not satisfy the constraint consider it `untimely`
> if `m` does not satisfy the constraint consider it `untimely`
#### **[PBTS-PROCESSING-STEP.0]**
#### **[PBTS-PROCESSING-STEP.0]**
In the processing step, based on the messages stored, the rules of the algorithms are
In the processing step, based on the messages stored, the rules of the algorithms are
executed. Note that the processing step only operates on messages
executed. Note that the processing step only operates on messages
for the current height. The consensus algorithm rules are defined by the following updates to arXiv paper.
for the current height. The consensus algorithm rules are defined by the following updates to arXiv paper.
@ -23,6 +26,7 @@ for the current height. The consensus algorithm rules are defined by the followi
#### New `StartRound`
#### New `StartRound`
There are two additions
There are two additions
- in case the proposer's local time is smaller than the time of the previous block, the proposer waits until this is not the case anymore (to ensure the block time is monotonically increasing)
- in case the proposer's local time is smaller than the time of the previous block, the proposer waits until this is not the case anymore (to ensure the block time is monotonically increasing)
- the proposer sends its time `now_p` as part of its proposal
- the proposer sends its time `now_p` as part of its proposal
@ -35,11 +39,12 @@ We update the timeout for the `PROPOSE` step according to the following reasonin
So we should set the timeout to `max(timeoutPropose(round_p), waitingTime)`.
So we should set the timeout to `max(timeoutPropose(round_p), waitingTime)`.
> If, in the future, a block delay parameter `BLOCKDELAY` is introduced, this means
that the proposer should wait for `now_p > blockTime + BLOCKDELAY` before sending a `PROPOSE` message.
> If, in the future, a block delay parameter `BLOCKDELAY` is introduced, this means
that the proposer should wait for `now_p > blockTime + BLOCKDELAY` before sending a `PROPOSE` message.
Also, `BLOCKDELAY` needs to be added to `waitingTime`.
Also, `BLOCKDELAY` needs to be added to `waitingTime`.
#### **[PBTS-ALG-STARTROUND.0]**
#### **[PBTS-ALG-STARTROUND.0]**
```go
```go
function StartRound(round) {
function StartRound(round) {
blockTime ← block time of block h_p - 1
blockTime ← block time of block h_p - 1
@ -68,6 +73,7 @@ function StartRound(round) {
- the code changes as the `PROPOSAL` message carries time (while `lockedValue` does not)
- the code changes as the `PROPOSAL` message carries time (while `lockedValue` does not)
#### **[PBTS-ALG-UPON-PROP.0]**
#### **[PBTS-ALG-UPON-PROP.0]**
```go
```go
upon timely(⟨PROPOSAL, h_p, round_p, (v,t), −1⟩) from proposer(h_p, round_p) while step_p = propose do {
upon timely(⟨PROPOSAL, h_p, round_p, (v,t), −1⟩) from proposer(h_p, round_p) while step_p = propose do {
@ -107,6 +114,7 @@ while step_p = propose ∧ (vr ≥ 0 ∧ vr < round_p) do {
- the stored values (i.e., `lockedValue`, `validValue`) do not contain the time
- the stored values (i.e., `lockedValue`, `validValue`) do not contain the time
#### **[PBTS-ALG-NEW-PREVOTE.0]**
#### **[PBTS-ALG-NEW-PREVOTE.0]**
```go
```go
upon timely(⟨PROPOSAL, h_p, round_p, (v,t), ∗⟩) from proposer(h_p, round_p) AND 2f + 1 ⟨PREVOTE, h_p, round_p, id(v,t)⟩ while valid(v) ∧ step_p ≥ prevote for the first time do {
upon timely(⟨PROPOSAL, h_p, round_p, (v,t), ∗⟩) from proposer(h_p, round_p) AND 2f + 1 ⟨PREVOTE, h_p, round_p, id(v,t)⟩ while valid(v) ∧ step_p ≥ prevote for the first time do {
if step_p = prevote {
if step_p = prevote {
@ -121,11 +129,14 @@ upon timely(⟨PROPOSAL, h_p, round_p, (v,t), ∗⟩) from proposer(h_p, round_p
```
```
#### New Rule Replacing Lines 49 - 54
#### New Rule Replacing Lines 49 - 54
- we decide on `v` as well as on the time from the proposal message
- we decide on `v` as well as on the time from the proposal message
- here we do not care whether the proposal was received timely.
- here we do not care whether the proposal was received timely.
> In particular we need to take care of the case where the proposer is untimely to one correct validator only. We need to ensure that this validator decides if all decide.
> In particular we need to take care of the case where the proposer is untimely to one correct validator only. We need to ensure that this validator decides if all decide.
#### **[PBTS-ALG-DECIDE.0]**
#### **[PBTS-ALG-DECIDE.0]**
```go
```go
upon ⟨PROPOSAL, h_p, r, (v,t), ∗⟩ from proposer(h_p, r) AND 2f + 1 ⟨PRECOMMIT, h_p, r, id(v,t)⟩ while decisionp[h_p] = nil do {
upon ⟨PROPOSAL, h_p, r, (v,t), ∗⟩ from proposer(h_p, r) AND 2f + 1 ⟨PRECOMMIT, h_p, r, id(v,t)⟩ while decisionp[h_p] = nil do {
There is a reference Newtonian real-time `t` (UTC).
There is a reference Newtonian real-time `t` (UTC).
Every correct validator `V` maintains a synchronized clock `C_V` that ensures:
Every correct validator `V` maintains a synchronized clock `C_V` that ensures:
#### **[PBTS-CLOCK-PRECISION.0]**
#### **[PBTS-CLOCK-PRECISION.0]**
There exists a system parameter `PRECISION` such that for any two correct validators `V` and `W`, and at any real-time `t`,
There exists a system parameter `PRECISION` such that for any two correct validators `V` and `W`, and at any real-time `t`,
`|C_V(t) - C_W(t)| < PRECISION`
`|C_V(t) - C_W(t)| < PRECISION`
@ -22,6 +24,7 @@ In general the local clock may drift from the global time. (It may progress fast
#### **[PBTS-MSG-D.0]**
#### **[PBTS-MSG-D.0]**
There exists a system parameter `MSGDELAY` for message end-to-end delays **counted in clock-time**.
There exists a system parameter `MSGDELAY` for message end-to-end delays **counted in clock-time**.
> Observe that [PBTS-MSG-D.0] imposes constraints on message delays as well as on the clock.
> Observe that [PBTS-MSG-D.0] imposes constraints on message delays as well as on the clock.
@ -36,32 +39,37 @@ The message end-to-end delay between a correct proposer and a correct validator
In this section we define the properties of Tendermint consensus (cf. the [arXiv paper][arXiv]) in this new system model.
In this section we define the properties of Tendermint consensus (cf. the [arXiv paper][arXiv]) in this new system model.
#### **[PBTS-PROPOSE.0]**
#### **[PBTS-PROPOSE.0]**
A proposer proposes a pair `(v,t)` of consensus value `v` and time `t`.
A proposer proposes a pair `(v,t)` of consensus value `v` and time `t`.
> We then restrict the allowed decisions along the following lines:
> We then restrict the allowed decisions along the following lines:
#### **[PBTS-INV-AGREEMENT.0]**
#### **[PBTS-INV-AGREEMENT.0]**
[Agreement] No two correct validators decide on different values `v`.
[Agreement] No two correct validators decide on different values `v`.
#### **[PBTS-INV-TIME-VAL.0]**
#### **[PBTS-INV-TIME-VAL.0]**
[Time-Validity] If a correct validator decides on `t` then `t` is "OK" (we will formalize this below), even if up to `2f` validators are faulty.
[Time-Validity] If a correct validator decides on `t` then `t` is "OK" (we will formalize this below), even if up to `2f` validators are faulty.
However, the properties of Tendermint consensus are of more interest with respect to the blocks, that is, what is written into a block and when. We therefore, in the following, will give the safety and liveness properties from this block-centric viewpoint.
However, the properties of Tendermint consensus are of more interest with respect to the blocks, that is, what is written into a block and when. We therefore, in the following, will give the safety and liveness properties from this block-centric viewpoint.
For this, observe that the time `t` decided at consensus height `k` will be written in the block of height `k+1`, and will be supported by `2f + 1``PRECOMMIT` messages of the same consensus round `r`. The time written in the block, we will denote by `b.time` (to distinguish it from the term `bfttime` used for median-based time). For this, it is important to have the following consensus algorithm property:
For this, observe that the time `t` decided at consensus height `k` will be written in the block of height `k+1`, and will be supported by `2f + 1``PRECOMMIT` messages of the same consensus round `r`. The time written in the block, we will denote by `b.time` (to distinguish it from the term `bfttime` used for median-based time). For this, it is important to have the following consensus algorithm property:
#### **[PBTS-INV-TIME-AGR.0]**
#### **[PBTS-INV-TIME-AGR.0]**
[Time-Agreement] If two correct validators decide in the same round, then they decide on the same `t`.
[Time-Agreement] If two correct validators decide in the same round, then they decide on the same `t`.
#### **[PBTS-DECISION-ROUND.0]**
#### **[PBTS-DECISION-ROUND.0]**
Note that the relation between consensus decisions, on the one hand, and blocks, on the other hand, is not immediate; in particular if we consider time: In the proposed solution,
Note that the relation between consensus decisions, on the one hand, and blocks, on the other hand, is not immediate; in particular if we consider time: In the proposed solution,
as validators may decide in different rounds, they may decide on different times.
as validators may decide in different rounds, they may decide on different times.
The proposer of the next block, may pick a commit (at least `2f + 1``PRECOMMIT` messages from one round), and thus it picks a decision round that is going to become "canonic".
As a result, the proposer implicitly has a choice of one of the times that belong to rounds in which validators decided. Observe that this choice was implicitly the case already in the median-based `bfttime`.
The proposer of the next block, may pick a commit (at least `2f + 1``PRECOMMIT` messages from one round), and thus it picks a decision round that is going to become "canonic".
As a result, the proposer implicitly has a choice of one of the times that belong to rounds in which validators decided. Observe that this choice was implicitly the case already in the median-based `bfttime`.
However, as most consensus instances terminate within one round on the Cosmos hub, this is hardly ever observed in practice.
However, as most consensus instances terminate within one round on the Cosmos hub, this is hardly ever observed in practice.
Finally, observe that the agreement ([Agreement] and [Time-Agreement]) properties are based on the Tendermint security model [TMBC-FM-2THIRDS.0] of more than 2/3 correct validators, while [Time-Validity] is based on more than 1/3 correct validators.
Finally, observe that the agreement ([Agreement] and [Time-Agreement]) properties are based on the Tendermint security model [TMBC-FM-2THIRDS.0] of more than 2/3 correct validators, while [Time-Validity] is based on more than 1/3 correct validators.
### SAFETY
### SAFETY
@ -69,10 +77,11 @@ Here we will provide specifications that relate local time to block time. Howeve
For a correct validator `V`, let `beginConsensus(V,k)` be the local time when it sets its height to `k`, and let `endConsensus(V,k)` be the time when it sets its height to `k + 1`.
For a correct validator `V`, let `beginConsensus(V,k)` be the local time when it sets its height to `k`, and let `endConsensus(V,k)` be the time when it sets its height to `k + 1`.
Let
- `beginConsensus(k)` be the minimum over `beginConsensus(V,k)`, and
- `last-beginConsensus(k)` be the maximum over `beginConsensus(V,k)`, and
- `endConsensus(k)` the maximum over `endConsensus(V,k)`
Let
- `beginConsensus(k)` be the minimum over `beginConsensus(V,k)`, and
- `last-beginConsensus(k)` be the maximum over `beginConsensus(V,k)`, and
- `endConsensus(k)` the maximum over `endConsensus(V,k)`
for all correct validators `V`.
for all correct validators `V`.
@ -84,27 +93,34 @@ We assume that during one consensus instance, local clocks are not set back, in
#### **[PBTS-CONSENSUS-TIME-VALID.0]**
#### **[PBTS-CONSENSUS-TIME-VALID.0]**
If
If
- there is a valid commit `c` for height `k`, and
- there is a valid commit `c` for height `k`, and
- `c` contains a `PRECOMMIT` message by at least one correct validator,
- `c` contains a `PRECOMMIT` message by at least one correct validator,
then the time `b.time` in the block `b` that is signed by `c` satisfies
then the time `b.time` in the block `b` that is signed by `c` satisfies
> [PBTS-CONSENSUS-TIME-VALID.0] is based on an analysis where the proposer is faulty (and does does not count towards `beginConsensus(k)` and `endConsensus(k)`), and we estimate the times at which correct validators receive and `accept` the `propose` message. If the proposer is correct we obtain
> [PBTS-CONSENSUS-TIME-VALID.0] is based on an analysis where the proposer is faulty (and does does not count towards `beginConsensus(k)` and `endConsensus(k)`), and we estimate the times at which correct validators receive and `accept` the `propose` message. If the proposer is correct we obtain
#### **[PBTS-CONSENSUS-LIVE-VALID-CORR-PROP.0]**
#### **[PBTS-CONSENSUS-LIVE-VALID-CORR-PROP.0]**
If the proposer of round 1 is correct, and
If the proposer of round 1 is correct, and
- [TMBC-FM-2THIRDS.0] holds for a block of height `k - 1`, and
- [TMBC-FM-2THIRDS.0] holds for a block of height `k - 1`, and
- [PBTS-MSG-FAIR.0], and
- [PBTS-MSG-FAIR.0], and
- [PBTS-CLOCK-PRECISION.0], and
- [PBTS-CLOCK-PRECISION.0], and
- [PBTS-CLOCK-GROW.0] (**TODO:** is that enough?)
- [PBTS-CLOCK-GROW.0] (**TODO:** is that enough?)
then eventually (within bounded time) every correct validator decides in round 1.
then eventually (within bounded time) every correct validator decides in round 1.
#### **[PBTS-CONSENSUS-SAFE-VALID-CORR-PROP.0]**
#### **[PBTS-CONSENSUS-SAFE-VALID-CORR-PROP.0]**
If the proposer of round 1 is correct, and
If the proposer of round 1 is correct, and
- [TMBC-FM-2THIRDS.0] holds for a block of height `k - 1`, and
- [TMBC-FM-2THIRDS.0] holds for a block of height `k - 1`, and
- [PBTS-MSG-FAIR.0], and
- [PBTS-MSG-FAIR.0], and
- [PBTS-CLOCK-PRECISION.0], and
- [PBTS-CLOCK-PRECISION.0], and
@ -117,7 +133,8 @@ then `beginConsensus_k <= b.time <= last-beginConsensus_k`.
### LIVENESS
### LIVENESS
If
If
- [TMBC-FM-2THIRDS.0] holds for a block of height `k - 1`, and
- [TMBC-FM-2THIRDS.0] holds for a block of height `k - 1`, and
- [PBTS-MSG-FAIR.0],
- [PBTS-MSG-FAIR.0],
- [PBTS-CLOCK.0], and
- [PBTS-CLOCK.0], and
@ -132,7 +149,8 @@ then eventually there is a valid commit `c` for height `k`.
#### **[PBTS-CLOCKSYNC-EXTERNAL.0]**
#### **[PBTS-CLOCKSYNC-EXTERNAL.0]**
There is a system parameter `ACCURACY`, such that for all real-times `t` and all correct validators `V`,
There is a system parameter `ACCURACY`, such that for all real-times `t` and all correct validators `V`,
- `| C_V(t) - t | < ACCURACY`.
- `| C_V(t) - t | < ACCURACY`.
> `ACCURACY` is not necessarily visible at the code level. The properties below just show that the smaller
> `ACCURACY` is not necessarily visible at the code level. The properties below just show that the smaller
@ -141,6 +159,7 @@ its value, the closer the block time will be to real-time
#### **[PBTS-CONSENSUS-PTIME.0]**
#### **[PBTS-CONSENSUS-PTIME.0]**
LET `m` be a propose message. We consider the following two real-times `proposalTime(m)` and `propRecvTime(m)`:
LET `m` be a propose message. We consider the following two real-times `proposalTime(m)` and `propRecvTime(m)`:
- if the proposer is correct and sends `m` at time `t`, we write `proposalTime(m)` for real-time `t`.
- if the proposer is correct and sends `m` at time `t`, we write `proposalTime(m)` for real-time `t`.
- if first correct validator receives `m` at time `t`, we write `propRecvTime(m)` for real-time `t`.
- if first correct validator receives `m` at time `t`, we write `propRecvTime(m)` for real-time `t`.
@ -158,7 +177,7 @@ Let `b` be a block with a valid commit that contains at least one `precommit` me
In Tendermint consensus, the first version of how time is computed and stored in a block works as follows:
In Tendermint consensus, the first version of how time is computed and stored in a block works as follows:
- validators send their current local time as part of `precommit` messages
- validators send their current local time as part of `precommit` messages
- upon collecting the `precommit` messages that the proposer uses to build a commit to be put in the next block, the proposer computes the `time` of the next block as the median (weighted over voting power) of the times in the `precommit` messages.
- upon collecting the `precommit` messages that the proposer uses to build a commit to be put in the next block, the proposer computes the `time` of the next block as the median (weighted over voting power) of the times in the `precommit` messages.
### Analysis
### Analysis
1. **Fault tolerance.** The computed median time is called [`bfttime`][bfttime] as it is indeed fault-tolerant: if **less than a third** of the validators is faulty (counted in voting power), it is guaranteed that the computed time lies between the minimum and the maximum times sent by correct validators.
1. **Fault tolerance.** The computed median time is called [`bfttime`][bfttime] as it is indeed fault-tolerant: if **less than a third** of the validators is faulty (counted in voting power), it is guaranteed that the computed time lies between the minimum and the maximum times sent by correct validators.
2. **Effect of faulty validators.** If more than `1/2` of the voting power (which is in fact more than one third and less than two thirds of the voting power) is held by faulty validators, then the time is under total control of the faulty validators. (This is particularly challenging in the context of [lightclient][lcspec] security.)
3. **Proposer influence on block time.** The proposer of the next block has a degree of freedom in choosing the `bfttime`, since it computes the median time based on the timestamps from `precommit` messages sent by
`2f + 1` correct validators.
1. If there are `n` different timestamps in the `precommit` messages, the proposer can use any subset of timestamps that add up to `2f + 1`
of the voting power in order to compute the median.
1. If the validators decide in different rounds, the proposer can decide on which round the median computation is based.
1. **Effect of faulty validators.** If more than `1/2` of the voting power (which is in fact more than one third and less than two thirds of the voting power) is held by faulty validators, then the time is under total control of the faulty validators. (This is particularly challenging in the context of [lightclient][lcspec] security.)
1. **Proposer influence on block time.** The proposer of the next block has a degree of freedom in choosing the `bfttime`, since it computes the median time based on the timestamps from `precommit` messages sent by
`2f + 1` correct validators.
1. If there are `n` different timestamps in the `precommit` messages, the proposer can use any subset of timestamps that add up to `2f + 1`
of the voting power in order to compute the median.
1. If the validators decide in different rounds, the proposer can decide on which round the median computation is based.
1. **Liveness.** The liveness of the protocol:
1. **Liveness.** The liveness of the protocol:
1. does not depend on clock synchronization,
1. does not depend on clock synchronization,
1. depends on bounded message delays.
1. depends on bounded message delays.
@ -27,18 +28,18 @@ In Tendermint consensus, the first version of how time is computed and stored in
### Outline
### Outline
An alternative approach to time has been discussed: Rather than having the validators send the time in the `precommit` messages, the proposer in the consensus algorithm sends its time in the `propose` message, and the validators locally check whether the time is OK (by comparing to their local clock).
An alternative approach to time has been discussed: Rather than having the validators send the time in the `precommit` messages, the proposer in the consensus algorithm sends its time in the `propose` message, and the validators locally check whether the time is OK (by comparing to their local clock).
This proposed solution adds the requirement of having synchronized clocks, and other implicit assumptions.
This proposed solution adds the requirement of having synchronized clocks, and other implicit assumptions.
### Comparison of the Suggested Method to the Old One
### Comparison of the Suggested Method to the Old One
1. **Fault tolerance.** Maintained in the suggested protocol.
2. **Effect of faulty validators.** Eliminated in the suggested protocol,
that is, the block `time` can be corrupted only in the extreme case when
`>2/3` of the validators are faulty.
1. **Fault tolerance.** Maintained in the suggested protocol.
1. **Effect of faulty validators.** Eliminated in the suggested protocol,
that is, the block `time` can be corrupted only in the extreme case when
`>2/3` of the validators are faulty.
1. **Proposer influence on block time.** The proposer of the next block
1. **Proposer influence on block time.** The proposer of the next block
has less freedom when choosing the block time.
has less freedom when choosing the block time.
1. This scenario is eliminated in the suggested protocol, provided that there are `<1/3` faulty validators.
1. This scenario is eliminated in the suggested protocol, provided that there are `<1/3` faulty validators.
1. This scenario is still there.
1. This scenario is still there.
1. **Liveness.** The liveness of the suggested protocol:
1. **Liveness.** The liveness of the suggested protocol:
@ -50,17 +51,21 @@ has less freedom when choosing the block time.
### Protocol Overview
### Protocol Overview
#### Proposed Time
#### Proposed Time
We assume that the field `proposal` in the `PROPOSE` message is a pair `(v, time)`, of the proposed consensus value `v` and the proposed time `time`.
We assume that the field `proposal` in the `PROPOSE` message is a pair `(v, time)`, of the proposed consensus value `v` and the proposed time `time`.
#### Reception Step
#### Reception Step
In the reception step at node `p` at local time `now_p`, upon receiving a message `m`:
In the reception step at node `p` at local time `now_p`, upon receiving a message `m`:
- **if** the message `m` is of type `PROPOSE` and satisfies `now_p - PRECISION < m.time < now_p + PRECISION + MSGDELAY`, then mark the message as `timely`.
- **if** the message `m` is of type `PROPOSE` and satisfies `now_p - PRECISION < m.time < now_p + PRECISION + MSGDELAY`, then mark the message as `timely`.
(`PRECISION` and `MSGDELAY` being system parameters, see [below](#safety-and-liveness))
(`PRECISION` and `MSGDELAY` being system parameters, see [below](#safety-and-liveness))
> after the presentation in the dev session, we realized that different semantics for the reception step is closer aligned to the implementation. Instead of dropping propose messages, we keep all of them, and mark timely ones.
> after the presentation in the dev session, we realized that different semantics for the reception step is closer aligned to the implementation. Instead of dropping propose messages, we keep all of them, and mark timely ones.
#### Processing Step
#### Processing Step
- Start round
- Start round
<table>
<table>
<tr>
<tr>
@ -228,7 +233,7 @@ upon ⟨PROPOSAL, h_p, r, (v,t), ∗⟩ from proposer(h_p, r)
For safety (Point 1, Point 2, Point 3i) and liveness (Point 4) we need
For safety (Point 1, Point 2, Point 3i) and liveness (Point 4) we need
the following assumptions:
the following assumptions:
- There exists a system parameter `PRECISION` such that for any two correct validators `V` and `W`, and at any real-time `t`, their local times `C_V(t)` and `C_W(t)` differ by less than `PRECISION` time units,
- There exists a system parameter `PRECISION` such that for any two correct validators `V` and `W`, and at any real-time `t`, their local times `C_V(t)` and `C_W(t)` differ by less than `PRECISION` time units,
i.e., `|C_V(t) - C_W(t)| < PRECISION`
i.e., `|C_V(t) - C_W(t)| < PRECISION`
- The message end-to-end delay between a correct proposer and a correct validator (for `PROPOSE` messages) is less than `MSGDELAY`.
- The message end-to-end delay between a correct proposer and a correct validator (for `PROPOSE` messages) is less than `MSGDELAY`.
For analyzing real-time safety (Point 5), we use a system parameter `ACCURACY`, such that for all real-times `t` and all correct validators `V`, we have `| C_V(t) - t | < ACCURACY`.
For analyzing real-time safety (Point 5), we use a system parameter `ACCURACY`, such that for all real-times `t` and all correct validators `V`, we have `| C_V(t) - t | < ACCURACY`.
> `ACCURACY` is not necessarily visible at the code level. We might even view `ACCURACY` as variable over time. The smaller it is during a consensus instance, the closer the block time will be to real-time.
> `ACCURACY` is not necessarily visible at the code level. We might even view `ACCURACY` as variable over time. The smaller it is during a consensus instance, the closer the block time will be to real-time.
> Note that `PRECISION` and `MSGDELAY` show up in the code.
>
> Note that `PRECISION` and `MSGDELAY` show up in the code.
### Detailed Specification
### Detailed Specification
@ -248,9 +253,6 @@ This specification describes the changes needed to be done to the Tendermint con