|
|
- # ADR 71: Proposer-Based Timestamps
-
- * [Changelog](#changelog)
- * [Status](#status)
- * [Context](#context)
- * [Alternative Approaches](#alternative-approaches)
- * [Remove timestamps altogether](#remove-timestamps-altogether)
- * [Decision](#decision)
- * [Detailed Design](#detailed-design)
- * [Overview](#overview)
- * [Proposal Timestamp and Block Timestamp](#proposal-timestamp-and-block-timestamp)
- * [Saving the timestamp across heights](#saving-the-timestamp-across-heights)
- * [Changes to `CommitSig`](#changes-to-commitsig)
- * [Changes to `Commit`](#changes-to-commit)
- * [Changes to `Vote` messages](#changes-to-vote-messages)
- * [New consensus parameters](#new-consensus-parameters)
- * [Changes to `Header`](#changes-to-header)
- * [Changes to the block proposal step](#changes-to-the-block-proposal-step)
- * [Proposer selects proposal timestamp](#proposer-selects-proposal-timestamp)
- * [Proposer selects block timestamp](#proposer-selects-block-timestamp)
- * [Proposer waits](#proposer-waits)
- * [Changes to the propose step timeout](#changes-to-the-propose-step-timeout)
- * [Changes to validation rules](#changes-to-validation-rules)
- * [Proposal timestamp validation](#proposal-timestamp-validation)
- * [Block timestamp validation](#block-timestamp-validation)
- * [Changes to the prevote step](#changes-to-the-prevote-step)
- * [Changes to the precommit step](#changes-to-the-precommit-step)
- * [Changes to locking a block](#changes-to-locking-a-block)
- * [Remove voteTime Completely](#remove-votetime-completely)
- * [Future Improvements](#future-improvements)
- * [Consequences](#consequences)
- * [Positive](#positive)
- * [Neutral](#neutral)
- * [Negative](#negative)
- * [References](#references)
-
- ## Changelog
-
- - July 15 2021: Created by @williambanfield
- - Aug 4 2021: Draft completed by @williambanfield
- - Aug 5 2021: Draft updated to include data structure changes by @williambanfield
- - Aug 20 2021: Language edits completed by @williambanfield
-
- ## Status
-
- **Accepted**
-
- ## Context
-
- Tendermint currently provides a monotonically increasing source of time known as [BFTTime](https://github.com/tendermint/spec/blob/master/spec/consensus/bft-time.md).
- This mechanism for producing a source of time is reasonably simple.
- Each correct validator adds a timestamp to each `Precommit` message it sends.
- The timestamp it sends is either the validator's current known Unix time or one millisecond greater than the previous block time, depending on which value is greater.
- When a block is produced, the proposer chooses the block timestamp as the weighted median of the times in all of the `Precommit` messages the proposer received.
- The weighting is proportional to the amount of voting power, or stake, a validator has on the network.
- This mechanism for producing timestamps is both deterministic and byzantine fault tolerant.
-
- This current mechanism for producing timestamps has a few drawbacks.
- Validators do not have to agree at all on how close the selected block timestamp is to their own currently known Unix time.
- Additionally, any amount of voting power `>1/3` may directly control the block timestamp.
- As a result, it is quite possible that the timestamp is not particularly meaningful.
-
- These drawbacks present issues in the Tendermint protocol.
- Timestamps are used by light clients to verify blocks.
- Light clients rely on correspondence between their own currently known Unix time and the block timestamp to verify blocks they see;
- However, their currently known Unix time may be greatly divergent from the block timestamp as a result of the limitations of `BFTTime`.
-
- The proposer-based timestamps specification suggests an alternative approach for producing block timestamps that remedies these issues.
- Proposer-based timestamps alter the current mechanism for producing block timestamps in two main ways:
-
- 1. The block proposer is amended to offer up its currently known Unix time as the timestamp for the next block.
- 1. Correct validators only approve the proposed block timestamp if it is close enough to their own currently known Unix time.
-
- The result of these changes is a more meaningful timestamp that cannot be controlled by `<= 2/3` of the validator voting power.
- This document outlines the necessary code changes in Tendermint to implement the corresponding [proposer-based timestamps specification](https://github.com/tendermint/spec/tree/master/spec/consensus/proposer-based-timestamp).
-
- ## Alternative Approaches
-
- ### Remove timestamps altogether
-
- Computer clocks are bound to skew for a variety of reasons.
- Using timestamps in our protocol means either accepting the timestamps as not reliable or impacting the protocol’s liveness guarantees.
- This design requires impacting the protocol’s liveness in order to make the timestamps more reliable.
- An alternate approach is to remove timestamps altogether from the block protocol.
- `BFTTime` is deterministic but may be arbitrarily inaccurate.
- However, having a reliable source of time is quite useful for applications and protocols built on top of a blockchain.
-
- We therefore decided not to remove the timestamp.
- Applications often wish for some transactions to occur on a certain day, on a regular period, or after some time following a different event.
- All of these require some meaningful representation of agreed upon time.
- The following protocols and application features require a reliable source of time:
- * Tendermint Light Clients [rely on correspondence between their known time](https://github.com/tendermint/spec/blob/master/spec/light-client/verification/README.md#definitions-1) and the block time for block verification.
- * Tendermint Evidence validity is determined [either in terms of heights or in terms of time](https://github.com/tendermint/spec/blob/8029cf7a0fcc89a5004e173ec065aa48ad5ba3c8/spec/consensus/evidence.md#verification).
- * Unbonding of staked assets in the Cosmos Hub [occurs after a period of 21 days](https://github.com/cosmos/governance/blob/ce75de4019b0129f6efcbb0e752cd2cc9e6136d3/params-change/Staking.md#unbondingtime).
- * IBC packets can use either a [timestamp or a height to timeout packet delivery](https://docs.cosmos.network/v0.43/ibc/overview.html#acknowledgements).
-
- Finally, inflation distribution in the Cosmos Hub uses an approximation of time to calculate an annual percentage rate.
- This approximation of time is calculated using [block heights with an estimated number of blocks produced in a year](https://github.com/cosmos/governance/blob/master/params-change/Mint.md#blocksperyear).
- Proposer-based timestamps will allow this inflation calculation to use a more meaningful and accurate source of time.
-
-
- ## Decision
-
- Implement proposer-based timestamps and remove `BFTTime`.
-
- ## Detailed Design
-
- ### Overview
-
- Implementing proposer-based timestamps will require a few changes to Tendermint’s code.
- These changes will be to the following components:
- * The `internal/consensus/` package.
- * The `state/` package.
- * The `Vote`, `CommitSig`, `Commit` and `Header` types.
- * The consensus parameters.
-
- ### Proposal Timestamp and Block Timestamp
-
- This design discusses two timestamps: (1) The timestamp in the block and (2) the timestamp in the proposal message.
- The existence and use of both of these timestamps can get a bit confusing, so some background is given here to clarify their uses.
-
- The [proposal message currently has a timestamp](https://github.com/tendermint/tendermint/blob/e5312942e30331e7c42b75426da2c6c9c00ae476/types/proposal.go#L31).
- This timestamp is the current Unix time known to the proposer when sending the `Proposal` message.
- This timestamp is not currently used as part of consensus.
- The changes in this ADR will begin using the proposal message timestamp as part of consensus.
- We will refer to this as the **proposal timestamp** throughout this design.
-
- The block has a timestamp field [in the header](https://github.com/tendermint/tendermint/blob/dc7c212c41a360bfe6eb38a6dd8c709bbc39aae7/types/block.go#L338).
- This timestamp is set currently as part of Tendermint’s `BFTtime` algorithm.
- It is set when a block is proposed and it is checked by the validators when they are deciding to prevote the block.
- This field will continue to be used but the logic for creating and validating this timestamp will change.
- We will refer to this as the **block timestamp** throughout this design.
-
- At a high level, the proposal timestamp from height `H` is used as the block timestamp at height `H+1`.
- The following image shows this relationship.
- The rest of this document describes the code changes that will make this possible.
-
- ![](./img/pbts-message.png)
-
- ### Saving the timestamp across heights
-
- Currently, `BFTtime` uses `LastCommit` to construct the block timestamp.
- The `LastCommit` is created at height `H-1` and is saved in the state store to be included in the block at height `H`.
- `BFTtime` takes the weighted median of the timestamps in `LastCommit.CommitSig` to build the timestamp for height `H`.
-
- For proposer-based timestamps, the `LastCommit.CommitSig` timestamps will no longer be used to build the timestamps for height `H`.
- Instead, the proposal timestamp from height `H-1` will become the block timestamp for height `H`.
- To enable this, we will add a `Timestamp` field to the `Commit` struct.
- This field will be populated at each height with the proposal timestamp decided on at the previous height.
- This timestamp will also be saved with the rest of the commit in the state store [when the commit is finalized](https://github.com/tendermint/tendermint/blob/e8013281281985e3ada7819f42502b09623d24a0/internal/consensus/state.go#L1611) so that it can be recovered if Tendermint crashes.
- Changes to the `CommitSig` and `Commit` struct are detailed below.
-
- ### Changes to `CommitSig`
-
- The [CommitSig](https://github.com/tendermint/tendermint/blob/a419f4df76fe4aed668a6c74696deabb9fe73211/types/block.go#L604) struct currently contains a timestamp.
- This timestamp is the current Unix time known to the validator when it issued a `Precommit` for the block.
- This timestamp is no longer used and will be removed in this change.
-
- `CommitSig` will be updated as follows:
-
- ```diff
- type CommitSig struct {
- BlockIDFlag BlockIDFlag `json:"block_id_flag"`
- ValidatorAddress Address `json:"validator_address"`
- -- Timestamp time.Time `json:"timestamp"`
- Signature []byte `json:"signature"`
- }
- ```
-
- ### Changes to `Commit`
-
- The [Commit](https://github.com/tendermint/tendermint/blob/a419f4df76fe4aed668a6c74696deabb9fe73211/types/block.go#L746) struct does not currently contain a timestamp.
- The timestamps in the `Commit.CommitSig` entries are currently used to build the block timestamp.
- With these timestamps removed, the commit time will instead be stored in the `Commit` struct.
-
- `Commit` will be updated as follows.
-
- ```diff
- type Commit struct {
- Height int64 `json:"height"`
- Round int32 `json:"round"`
- ++ Timestamp time.Time `json:"timestamp"`
- BlockID BlockID `json:"block_id"`
- Signatures []CommitSig `json:"signatures"`
- }
- ```
-
- ### Changes to `Vote` messages
-
- `Precommit` and `Prevote` messages use a common [Vote struct](https://github.com/tendermint/tendermint/blob/a419f4df76fe4aed668a6c74696deabb9fe73211/types/vote.go#L50).
- This struct currently contains a timestamp.
- This timestamp is set using the [voteTime](https://github.com/tendermint/tendermint/blob/e8013281281985e3ada7819f42502b09623d24a0/internal/consensus/state.go#L2241) function and therefore vote times correspond to the current Unix time known to the validator.
- For precommits, this timestamp is used to construct the [CommitSig that is included in the block in the LastCommit](https://github.com/tendermint/tendermint/blob/e8013281281985e3ada7819f42502b09623d24a0/types/block.go#L754) field.
- For prevotes, this field is unused.
- Proposer-based timestamps will use the [RoundState.Proposal](https://github.com/tendermint/tendermint/blob/c3ae6f5b58e07b29c62bfdc5715b6bf8ae5ee951/internal/consensus/types/round_state.go#L76) timestamp to construct the `signedBytes` `CommitSig`.
- This timestamp is therefore no longer useful and will be dropped.
-
- `Vote` will be updated as follows:
-
- ```diff
- type Vote struct {
- Type tmproto.SignedMsgType `json:"type"`
- Height int64 `json:"height"`
- Round int32 `json:"round"`
- BlockID BlockID `json:"block_id"` // zero if vote is nil.
- -- Timestamp time.Time `json:"timestamp"`
- ValidatorAddress Address `json:"validator_address"`
- ValidatorIndex int32 `json:"validator_index"`
- Signature []byte `json:"signature"`
- }
- ```
-
- ### New consensus parameters
-
- The proposer-based timestamp specification includes multiple new parameters that must be the same among all validators.
- These parameters are `PRECISION`, `MSGDELAY`, and `ACCURACY`.
-
- The `PRECISION` and `MSGDELAY` parameters are used to determine if the proposed timestamp is acceptable.
- A validator will only Prevote a proposal if the proposal timestamp is considered `timely`.
- A proposal timestamp is considered `timely` if it is within `PRECISION` and `MSGDELAY` of the Unix time known to the validator.
- More specifically, a proposal timestamp is `timely` if `validatorLocalTime - PRECISION < proposalTime < validatorLocalTime + PRECISION + MSGDELAY`.
-
- Because the `PRECISION` and `MSGDELAY` parameters must be the same across all validators, they will be added to the [consensus parameters](https://github.com/tendermint/tendermint/blob/master/proto/tendermint/types/params.proto#L13) as [durations](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Duration).
-
- The proposer-based timestamp specification also includes a [new ACCURACY parameter](https://github.com/tendermint/spec/blob/master/spec/consensus/proposer-based-timestamp/pbts-sysmodel_001_draft.md#pbts-clocksync-external0).
- Intuitively, `ACCURACY` represents the difference between the ‘real’ time and the currently known time of correct validators.
- The currently known Unix time of any validator is always somewhat different from real time.
- `ACCURACY` is the largest such difference between each validator's time and real time taken as an absolute value.
- This is not something a computer can determine on its own and must be specified as an estimate by community running a Tendermint-based chain.
- It is used in the new algorithm to [calculate a timeout for the propose step](https://github.com/tendermint/spec/blob/master/spec/consensus/proposer-based-timestamp/pbts-algorithm_001_draft.md#pbts-alg-startround0).
- `ACCURACY` is assumed to be the same across all validators and therefore should be included as a consensus parameter.
-
- The consensus will be updated to include this `Timestamp` field as follows:
-
- ```diff
- type ConsensusParams struct {
- Block BlockParams `json:"block"`
- Evidence EvidenceParams `json:"evidence"`
- Validator ValidatorParams `json:"validator"`
- Version VersionParams `json:"version"`
- ++ Timestamp TimestampParams `json:"timestamp"`
- }
- ```
-
- ```go
- type TimestampParams struct {
- Accuracy time.Duration `json:"accuracy"`
- Precision time.Duration `json:"precision"`
- MsgDelay time.Duration `json:"msg_delay"`
- }
- ```
-
- ### Changes to `Header`
-
- The [Header](https://github.com/tendermint/tendermint/blob/a419f4df76fe4aed668a6c74696deabb9fe73211/types/block.go#L338) struct currently contains a timestamp.
- This timestamp is set as the `BFTtime` derived from the block's `LastCommit.CommitSig` timestamps.
- This timestamp will no longer be derived from the `LastCommit.CommitSig` timestamps and will instead be included directly into the block's `LastCommit`.
- This timestamp will therfore be identical in both the `Header` and the `LastCommit`.
- To clarify that the timestamp in the header corresponds to the `LastCommit`'s time, we will rename this timestamp field to `last_timestamp`.
-
- `Header` will be updated as follows:
-
- ```diff
- type Header struct {
- // basic block info
- Version version.Consensus `json:"version"`
- ChainID string `json:"chain_id"`
- Height int64 `json:"height"`
- -- Time time.Time `json:"time"`
- ++ LastTimestamp time.Time `json:"last_timestamp"`
-
- // prev block info
- LastBlockID BlockID `json:"last_block_id"`
-
- // hashes of block data
- LastCommitHash tmbytes.HexBytes `json:"last_commit_hash"`
- DataHash tmbytes.HexBytes `json:"data_hash"`
-
- // hashes from the app output from the prev block
- ValidatorsHash tmbytes.HexBytes `json:"validators_hash"`
- NextValidatorsHash tmbytes.HexBytes `json:"next_validators_hash"`
- ConsensusHash tmbytes.HexBytes `json:"consensus_hash"`
- AppHash tmbytes.HexBytes `json:"app_hash"`
-
- // root hash of all results from the txs from the previous block
- LastResultsHash tmbytes.HexBytes `json:"last_results_hash"`
-
- // consensus info
- EvidenceHash tmbytes.HexBytes `json:"evidence_hash"`
- ProposerAddress Address `json:"proposer_address"`
- }
- ```
-
- ### Changes to the block proposal step
-
- #### Proposer selects proposal timestamp
-
- The proposal logic already [sets the Unix time known to the validator](https://github.com/tendermint/tendermint/blob/2abfe20114ee3bb3adfee817589033529a804e4d/types/proposal.go#L44) into the `Proposal` message.
- This satisfies the proposer-based timestamp specification and does not need to change.
-
- #### Proposer selects block timestamp
-
- The proposal timestamp that was decided in height `H-1` will be stored in the `State` struct's in the `RoundState.LastCommit` field.
- The proposer will select this timestamp to use as the block timestamp at height `H`.
-
- #### Proposer waits
-
- Block timestamps must be monotonically increasing.
- In `BFTTime`, if a validator’s clock was behind, the [validator added 1 millisecond to the previous block’s time and used that in its vote messages](https://github.com/tendermint/tendermint/blob/e8013281281985e3ada7819f42502b09623d24a0/internal/consensus/state.go#L2246).
- A goal of adding proposer-based timestamps is to enforce some degree of clock synchronization, so having a mechanism that completely ignores the Unix time of the validator time no longer works.
-
- Validator clocks will not be perfectly in sync.
- Therefore, the proposer’s current known Unix time may be less than the `LastCommit.Timestamp`.
- If the proposer’s current known Unix time is less than the `LastCommit.Timestamp`, the proposer will sleep until its known Unix time exceeds `LastCommit.Timestamp`.
-
- This change will require amending the [defaultDecideProposal](https://github.com/tendermint/tendermint/blob/822893615564cb20b002dd5cf3b42b8d364cb7d9/internal/consensus/state.go#L1180) method.
- This method should now block until the proposer’s time is greater than `LastCommit.Timestamp`.
-
- #### Changes to the propose step timeout
-
- Currently, a validator waiting for a proposal will proceed past the propose step if the configured propose timeout is reached and no proposal is seen.
- Proposer-based timestamps requires changing this timeout logic.
-
- The proposer will now wait until its current known Unix time exceeds the `LastCommit.Timestamp` to propose a block.
- The validators must now take this and some other factors into account when deciding when to timeout the propose step.
- Specifically, the propose step timeout must also take into account potential inaccuracy in the validator’s clock and in the clock of the proposer.
- Additionally, there may be a delay communicating the proposal message from the proposer to the other validators.
-
- Therefore, validators waiting for a proposal must wait until after the `LastCommit.Timestamp` before timing out.
- To account for possible inaccuracy in its own clock, inaccuracy in the proposer’s clock, and message delay, validators waiting for a proposal will wait until `LastCommit.Timesatmp + 2*ACCURACY + MSGDELAY`.
- The spec defines this as `waitingTime`.
-
- The [propose step’s timeout is set in enterPropose](https://github.com/tendermint/tendermint/blob/822893615564cb20b002dd5cf3b42b8d364cb7d9/internal/consensus/state.go#L1108) in `state.go`.
- `enterPropose` will be changed to calculate waiting time using the new consensus parameters.
- The timeout in `enterPropose` will then be set as the maximum of `waitingTime` and the [configured proposal step timeout](https://github.com/tendermint/tendermint/blob/dc7c212c41a360bfe6eb38a6dd8c709bbc39aae7/config/config.go#L1013).
-
- ### Changes to validation rules
-
- The rules for validating that a proposal is valid will need slight modification to implement proposer-based timestamps.
- Specifically, we will change the validation logic to ensure that the proposal timestamp is `timely` and we will modify the way the block timestamp is validated as well.
-
- #### Proposal timestamp validation
-
- Adding proposal timestamp validation is a reasonably straightforward change.
- The current Unix time known to the proposer is already included in the [Proposal message](https://github.com/tendermint/tendermint/blob/dc7c212c41a360bfe6eb38a6dd8c709bbc39aae7/types/proposal.go#L31).
- Once the proposal is received, the complete message is stored in the `RoundState.Proposal` field.
- The precommit and prevote validation logic does not currently use this timestamp.
- This validation logic will be updated to check that the proposal timestamp is within `PRECISION` of the current Unix time known to the validators.
- If the timestamp is not within `PRECISION` of the current Unix time known to the validator, the proposal will not be considered it valid.
- The validator will also check that the proposal time is greater than the block timestamp from the previous height.
-
- If no valid proposal is received by the proposal timeout, the validator will prevote nil.
- This is identical to the current logic.
-
- #### Block timestamp validation
-
- The [validBlock function](https://github.com/tendermint/tendermint/blob/c3ae6f5b58e07b29c62bfdc5715b6bf8ae5ee951/state/validation.go#L14) currently [validates the proposed block timestamp in three ways](https://github.com/tendermint/tendermint/blob/c3ae6f5b58e07b29c62bfdc5715b6bf8ae5ee951/state/validation.go#L118).
- First, the validation logic checks that this timestamp is greater than the previous block’s timestamp.
- Additionally, it validates that the block timestamp is correctly calculated as the weighted median of the timestamps in the [block’s LastCommit](https://github.com/tendermint/tendermint/blob/e8013281281985e3ada7819f42502b09623d24a0/types/block.go#L48).
- Finally, the logic also authenticates the timestamps in the `LastCommit`.
- The cryptographic signature in each `CommitSig` is created by signing a hash of fields in the block with the validator’s private key.
- One of the items in this `signedBytes` hash is derived from the timestamp in the `CommitSig`.
- To authenticate the `CommitSig` timestamp, the validator builds a hash of fields that includes the timestamp and checks this hash against the provided signature.
- This takes place in the [VerifyCommit function](https://github.com/tendermint/tendermint/blob/e8013281281985e3ada7819f42502b09623d24a0/types/validation.go#L25).
-
- The logic to validate that the block timestamp is greater than the previous block’s timestamp also works for proposer-based timestamps and will not change.
-
- `BFTTime` validation is no longer applicable and will be removed.
- Validators will no longer check that the block timestamp is a weighted median of `LastCommit` timestamps.
- This will mean removing the call to [MedianTime in the validateBlock function](https://github.com/tendermint/tendermint/blob/4db71da68e82d5cb732b235eeb2fd69d62114b45/state/validation.go#L117).
- The `MedianTime` function can be completely removed.
- The `LastCommit` timestamps may also be removed.
-
- The `signedBytes` validation logic in `VerifyCommit` will be slightly altered.
- The `CommitSig`s in the block’s `LastCommit` will no longer each contain a timestamp.
- The validation logic will instead include the `LastCommit.Timestamp` in the hash of fields for generating the `signedBytes`.
- The cryptographic signatures included in the `CommitSig`s will then be checked against this `signedBytes` hash to authenticate the timestamp.
- Specifically, the `VerifyCommit` function will be updated to use this new timestamp.
-
- ### Changes to the prevote step
-
- Currently, a validator will prevote a proposal in one of three cases:
-
- * Case 1: Validator has no locked block and receives a valid proposal.
- * Case 2: Validator has a locked block and receives a valid proposal matching its locked block.
- * Case 3: Validator has a locked block, sees a valid proposal not matching its locked block but sees +⅔ prevotes for the new proposal’s block.
-
- The only change we will make to the prevote step is to what a validator considers a valid proposal as detailed above.
-
- ### Changes to the precommit step
-
- The precommit step will not require much modification.
- Its proposal validation rules will change in the same ways that validation will change in the prevote step.
-
- ### Changes to locking a block
- When a validator receives a valid proposed block and +2/3 prevotes for that block, it stores the block as its ‘locked block’ in the [RoundState.ValidBlock](https://github.com/tendermint/tendermint/blob/e8013281281985e3ada7819f42502b09623d24a0/internal/consensus/types/round_state.go#L85) field.
- In each subsequent round it will prevote that block.
- A validator will only change which block it has locked if it sees +2/3 prevotes for a different block.
-
- This mechanism will remain largely unchanged.
- The only difference is the addition of proposal timestamp validation.
- A validator will prevote nil in a round if the proposal message it received is not `timely`.
- Prevoting nil in this case will not cause a validator to ‘unlock’ its locked block.
- This difference is an incidental result of the changes to prevote validation.
- It is included in this design for completeness and to clarify that no additional changes will be made to block locking.
-
- ### Remove voteTime Completely
-
- [voteTime](https://github.com/tendermint/tendermint/blob/822893615564cb20b002dd5cf3b42b8d364cb7d9/internal/consensus/state.go#L2229) is a mechanism for calculating the next `BFTTime` given both the validator's current known Unix time and the previous block timestamp.
- If the previous block timestamp is greater than the validator's current known Unix time, then voteTime returns a value one millisecond greater than the previous block timestamp.
- This logic is used in multiple places and is no longer needed for proposer-based timestamps.
- It should therefore be removed completely.
-
- ## Future Improvements
-
- * Implement BLS signature aggregation.
- By removing fields from the `Precommit` messages, we are able to aggregate signatures.
-
- ## Consequences
-
- ### Positive
-
- * `<2/3` of validators can no longer influence block timestamps.
- * Block timestamp will have stronger correspondence to real time.
- * Improves the reliability of light client block verification.
- * Enables BLS signature aggregation.
- * Enables evidence handling to use time instead of height for evidence validity.
-
- ### Neutral
-
- * Alters Tendermint’s liveness properties.
- Liveness now requires that all correct validators have synchronized clocks within a bound.
- Liveness will now also require that validators’ clocks move forward, which was not required under `BFTTime`.
-
- ### Negative
-
- * May increase the length of the propose step if there is a large skew between the previous proposer and the current proposer’s local Unix time.
- This skew will be bound by the `PRECISION` value, so it is unlikely to be too large.
-
- * Current chains with block timestamps far in the future will either need to pause consensus until after the erroneous block timestamp or must maintain synchronized but very inaccurate clocks.
-
- ## References
-
- * [PBTS Spec](https://github.com/tendermint/spec/tree/master/spec/consensus/proposer-based-timestamp)
- * [BFTTime spec](https://github.com/tendermint/spec/blob/master/spec/consensus/bft-time.md)
|