|
@ -0,0 +1,128 @@ |
|
|
|
|
|
# RFC 009 : Consensus Parameter Upgrade Considerations |
|
|
|
|
|
|
|
|
|
|
|
## Changelog |
|
|
|
|
|
|
|
|
|
|
|
- 06-Jan-2011: Initial draft (@williambanfield). |
|
|
|
|
|
|
|
|
|
|
|
## Abstract |
|
|
|
|
|
|
|
|
|
|
|
This document discusses the challenges of adding additional consensus parameters |
|
|
|
|
|
to Tendermint and proposes a few solutions that can enable addition of consensus |
|
|
|
|
|
parameters in a backwards-compatible way. |
|
|
|
|
|
|
|
|
|
|
|
## Background |
|
|
|
|
|
|
|
|
|
|
|
This section provides an overview of the issues of adding consensus parameters |
|
|
|
|
|
to Tendermint. |
|
|
|
|
|
|
|
|
|
|
|
### Hash Compatibility |
|
|
|
|
|
|
|
|
|
|
|
Tendermint produces a hash of a subset of the consensus parameters. The values |
|
|
|
|
|
that are hashed currently are the `BlockMaxGas` and the `BlockMaxSize`. These |
|
|
|
|
|
are currently in the [HashedParams struct][hashed-params]. This hash is included |
|
|
|
|
|
in the block and validators use it to validate that their local view of the consensus |
|
|
|
|
|
parameters matches what the rest of the network is configured with. |
|
|
|
|
|
|
|
|
|
|
|
Any new consensus parameters added to Tendermint should be included in this |
|
|
|
|
|
hash. This presents a challenge for verification of historical blocks when consensus |
|
|
|
|
|
parameters are added. If a network produced blocks with a version of Tendermint that |
|
|
|
|
|
did not yet have the new consensus parameters, the parameter hash it produced will |
|
|
|
|
|
not reference the new parameters. Any nodes joining the network with the newer |
|
|
|
|
|
version of Tendermint will have the new consensus parameters. Tendermint will need |
|
|
|
|
|
to handle this case so that new versions of Tendermint with new consensus parameters |
|
|
|
|
|
can still validate old blocks correctly without having to do anything overly complex |
|
|
|
|
|
or hacky. |
|
|
|
|
|
|
|
|
|
|
|
### Allowing Developer-Defined Values and the `EndBlock` Problem |
|
|
|
|
|
|
|
|
|
|
|
When new consensus parameters are added, application developers may wish to set |
|
|
|
|
|
values for them so that the developer-defined values may be used as soon as the |
|
|
|
|
|
software upgrades. We do not currently have a clean mechanism for handling this. |
|
|
|
|
|
|
|
|
|
|
|
Consensus parameter updates are communicated from the application to Tendermint |
|
|
|
|
|
within `EndBlock` of some height `H` and take effect at the next height, `H+1`. |
|
|
|
|
|
This means that for updates that add a consensus parameter, there is a single |
|
|
|
|
|
height where the new parameters cannot take effect. The parameters did not exist |
|
|
|
|
|
in the version of the software that emitted the `EndBlock` response for height `H-1`, |
|
|
|
|
|
so they cannot take effect at height `H`. The first height that the updated params |
|
|
|
|
|
can take effect is height `H+1`. As of now, height `H` must run with the defaults. |
|
|
|
|
|
|
|
|
|
|
|
## Discussion |
|
|
|
|
|
|
|
|
|
|
|
### Hash Compatibility |
|
|
|
|
|
|
|
|
|
|
|
This section discusses possible solutions to the problem of maintaining backwards-compatibility |
|
|
|
|
|
of hashed parameters while adding new parameters. |
|
|
|
|
|
|
|
|
|
|
|
#### Never Hash Defaults |
|
|
|
|
|
|
|
|
|
|
|
One solution to the problem of backwards-compatibility is to never include parameters |
|
|
|
|
|
in the hash if the are using the default value. This means that blocks produced |
|
|
|
|
|
before the parameters existed will have implicitly been created with the defaults. |
|
|
|
|
|
This works because any software with newer versions of Tendermint must be using the |
|
|
|
|
|
defaults for new parameters when validating old blocks since the defaults can not |
|
|
|
|
|
have been updated until a height at which the parameters existed. |
|
|
|
|
|
|
|
|
|
|
|
#### Only Update HashedParams on Hash-Breaking Releases |
|
|
|
|
|
|
|
|
|
|
|
An alternate solution to never hashing defaults is to not update the hashed |
|
|
|
|
|
parameters on non-hash-breaking releases. This means that when new consensus |
|
|
|
|
|
parameters are added to Tendermint, there may be a release that makes use of the |
|
|
|
|
|
parameters but does not verify that they are the same across all validators by |
|
|
|
|
|
referencing them in the hash. This seems reasonably safe given the fact that |
|
|
|
|
|
only a very far subset of the consensus parameters are currently verified at all. |
|
|
|
|
|
|
|
|
|
|
|
#### Version The Consensus Parameter Hash Scheme |
|
|
|
|
|
|
|
|
|
|
|
The upcoming work on [soft upgrades](https://github.com/tendermint/spec/pull/222) |
|
|
|
|
|
proposes applying different hashing rules depending on the active block version. |
|
|
|
|
|
The consensus parameter hash could be versioned in the same way. When different |
|
|
|
|
|
block versions are used, a different set of consensus parameters will be included |
|
|
|
|
|
in the hash. |
|
|
|
|
|
|
|
|
|
|
|
### Developer Defined Values |
|
|
|
|
|
|
|
|
|
|
|
This section discusses possible solutions to the problem of allowing application |
|
|
|
|
|
developers to define values for the new parameters during the upgrade that adds |
|
|
|
|
|
the parameters. |
|
|
|
|
|
|
|
|
|
|
|
#### Using `InitChain` for New Values |
|
|
|
|
|
|
|
|
|
|
|
One solution to the problem of allowing application developers to define values |
|
|
|
|
|
for new consensus parameters is to call the `InitChain` ABCI method on application |
|
|
|
|
|
startup and fetch the value for any new consensus parameters. The [response object][init-chain-response] |
|
|
|
|
|
contains a field for `ConsensusParameter` updates so this may serve as a natural place |
|
|
|
|
|
to put this logic. |
|
|
|
|
|
|
|
|
|
|
|
This poses a few difficulties. Nodes replaying old blocks while running new |
|
|
|
|
|
software do not ever call `InitChain` after the initial time. They will therefore |
|
|
|
|
|
not have a way to determine that the parameters changed at some height by using a |
|
|
|
|
|
call to `InitChain`. The `EndBlock` response is how parameter changes at a height |
|
|
|
|
|
are currently communicated to Tendermint and conflating these cases seems risky. |
|
|
|
|
|
|
|
|
|
|
|
#### Force Defaults For Single Height |
|
|
|
|
|
|
|
|
|
|
|
An alternate option is to not use `InitChain` and instead require chains to use the |
|
|
|
|
|
default values of the new parameters for a single height. |
|
|
|
|
|
|
|
|
|
|
|
As documented in the upcoming [ADR-74][adr-74], popular chains often simply use the default |
|
|
|
|
|
values. Additionally, great care is being taken to ensure that logic governed by upcoming |
|
|
|
|
|
consensus parameters is not liveness-breaking. This means that, at worst-case, |
|
|
|
|
|
chains will experience a single slow height while waiting for the new values to |
|
|
|
|
|
by applied. |
|
|
|
|
|
|
|
|
|
|
|
#### Add a new `UpgradeChain` method |
|
|
|
|
|
|
|
|
|
|
|
An additional method for allowing chains to update the consensus parameters that |
|
|
|
|
|
do not yet exist is to add a new `UpgradeChain` method to `ABCI`. The upgrade chain |
|
|
|
|
|
method would be called when the chain detects that the version of block that it |
|
|
|
|
|
is about to produce does not match the previous block. This method would be called |
|
|
|
|
|
after `EndBlock` and would return the set of consensus parameters to use at the |
|
|
|
|
|
next height. It would therefore give an application the chance to set the new |
|
|
|
|
|
consensus parameters before running a height with these new parameter. |
|
|
|
|
|
|
|
|
|
|
|
### References |
|
|
|
|
|
|
|
|
|
|
|
[hashed-params]: https://github.com/tendermint/tendermint/blob/0ae974e63911804d4a2007bd8a9b3ad81d6d2a90/types/params.go#L49 |
|
|
|
|
|
[init-chain-response]: https://github.com/tendermint/tendermint/blob/0ae974e63911804d4a2007bd8a9b3ad81d6d2a90/abci/types/types.pb.go#L1616 |
|
|
|
|
|
[adr-74]: https://github.com/tendermint/tendermint/pull/7503 |