|
|
@ -0,0 +1,205 @@ |
|
|
|
# ADR 009: ABCI UX Improvements |
|
|
|
|
|
|
|
## Context |
|
|
|
|
|
|
|
The ABCI was first introduced in late 2015. It's purpose is to be: |
|
|
|
|
|
|
|
- a generic interface between state machines and their replication engines |
|
|
|
- agnostic to the language the state machine is written in |
|
|
|
- agnostic to the replication engine that drives it |
|
|
|
|
|
|
|
This means ABCI should provide an interface for both pluggable applications and |
|
|
|
pluggable consensus engines. |
|
|
|
|
|
|
|
To achieve this, it uses Protocol Buffers for message types. The dominant |
|
|
|
implementation is in Go. |
|
|
|
|
|
|
|
After some recent discussions with the community on github, the following were |
|
|
|
identified as pain points: |
|
|
|
|
|
|
|
- Amino encoded types |
|
|
|
- Managing validator sets |
|
|
|
- Imports in the protobuf file |
|
|
|
|
|
|
|
See the following relevent github issues: |
|
|
|
- TODO |
|
|
|
|
|
|
|
### Imports |
|
|
|
|
|
|
|
The native Protobuf library in Go generates code that is inellegant and difficult to work with. |
|
|
|
The solution in the Go community is to use a fork of it called `gogoproto`. |
|
|
|
While `gogoproto` is nice, it creates an additional dependency, and compiling |
|
|
|
the protobuf types for other languages has been reported to fail when `gogoproto` is used. |
|
|
|
|
|
|
|
### Amino |
|
|
|
|
|
|
|
Amino is an encoding protocol designed to improve over insufficiencies of protobuf. |
|
|
|
It's goal is to be Protobuf4. |
|
|
|
|
|
|
|
Many people are frustrated by incompatibility with protobuf, |
|
|
|
and with the requirement for Amino to be used at all within ABCI. |
|
|
|
|
|
|
|
We intend to make Amino successful enough that we can eventually use it for ABCI |
|
|
|
message types directly. By then it should be called Protobuf4. In the meantime, |
|
|
|
we want it to be easy to use. |
|
|
|
|
|
|
|
### PubKey |
|
|
|
|
|
|
|
PubKeys were previously encoded using Amino (and before that, go-wire). |
|
|
|
|
|
|
|
### Addresses |
|
|
|
|
|
|
|
The address for an ED25519 pubkey is currently the RIPEMD160 of the Amino |
|
|
|
encoded pubkey. |
|
|
|
|
|
|
|
### Validators |
|
|
|
|
|
|
|
To change the validator set, applications can return a list of validator updates |
|
|
|
with ResponseEndBlock. In these updates, the public key *must* be included, |
|
|
|
because Tendermint requires the public key to verify validator signatures. This |
|
|
|
means ABCI developers have to work with PubKeys. That said, it would also be |
|
|
|
convenient to work with address information, and for it to be simple to do so. |
|
|
|
|
|
|
|
### AbsentValidators |
|
|
|
|
|
|
|
Tendermint also provides a list of validators in BeginBlock who did not sign the |
|
|
|
last block. This allows applications to reflect availability behaviour in the |
|
|
|
application, for instance by punishing validators for not having votes included |
|
|
|
in commits. |
|
|
|
|
|
|
|
### InitChain |
|
|
|
|
|
|
|
Tendermint passes in a list of validators here, and nothing else. It would |
|
|
|
benefit the application to be able to control the initial validator set. For |
|
|
|
instance the genesis file could include application-based information about the |
|
|
|
initial validator set that the application could process to determine the |
|
|
|
initial validator set. Additionally, InitChain would benefit from getting all |
|
|
|
the genesis information. |
|
|
|
|
|
|
|
|
|
|
|
## Decision |
|
|
|
|
|
|
|
### Imports |
|
|
|
|
|
|
|
Move away from gogoproto. In the short term, we will just maintain a second |
|
|
|
protobuf file without the gogoproto annotations. In the medium term, we will |
|
|
|
make copies of all the structs in Golang and shuttle back and forth. In the long |
|
|
|
term, we will use Amino. |
|
|
|
|
|
|
|
### Amino |
|
|
|
|
|
|
|
To simplify ABCI application development in the short term, |
|
|
|
Amino will be completely removed from the ABCI: |
|
|
|
|
|
|
|
- It will not be required for PubKey encoding |
|
|
|
- It will not be required for computing PubKey addresses |
|
|
|
|
|
|
|
That said, we are working to make Amino a huge success, and to become Protobuf4. |
|
|
|
To facilitate adoption and cross-language compatibility in the near-term, Amino |
|
|
|
v1 will: |
|
|
|
|
|
|
|
- be fully compatible with the subset of Protobuf3 that excludes `oneof` |
|
|
|
- use the Amino prefix system to provide interface types, as opposed to `oneof` |
|
|
|
style union types. |
|
|
|
|
|
|
|
That said, an Amino v2 will be worked on to improve the performance of the |
|
|
|
format and its useability in cryptographic applications. |
|
|
|
|
|
|
|
|
|
|
|
### PubKey |
|
|
|
|
|
|
|
Encoding schemes infect software. As a generic middleware, ABCI aims to have |
|
|
|
some cross scheme compatibility. For this it has no choice but to include opaque |
|
|
|
bytes from time to time. While we will not enforce Amino encoding for these |
|
|
|
bytes yet, we need to provide a type system. The simplest way to do this is to |
|
|
|
use a type string. |
|
|
|
|
|
|
|
PubKey will now look like: |
|
|
|
|
|
|
|
``` |
|
|
|
message PubKey { |
|
|
|
string type |
|
|
|
bytes data |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
where `type` can be: |
|
|
|
|
|
|
|
- "ed225519", with `data = <raw 32-byte pubkey>` |
|
|
|
- "secp256k1", with `data = <33-byte OpenSSL compressed pubkey>` |
|
|
|
|
|
|
|
and generated types. At the least we should use a reflection-based protobuf so |
|
|
|
we can just encode our own types, rather than using protobuf generated ones. |
|
|
|
|
|
|
|
### Addresses |
|
|
|
|
|
|
|
To simplify and improve computing addresses, we change it to the first 20-bytes of the SHA256 |
|
|
|
of the raw 32-byte public key. |
|
|
|
|
|
|
|
We continue to use the Bitcoin address scheme for secp256k1 keys. |
|
|
|
|
|
|
|
### Validators |
|
|
|
|
|
|
|
Change the following: |
|
|
|
|
|
|
|
- Validator includes an optional `bytes address` field |
|
|
|
- If the field is provided, it *MUST* correspond to the `pubkey.Address()` |
|
|
|
|
|
|
|
|
|
|
|
``` |
|
|
|
message Validator { |
|
|
|
bytes address |
|
|
|
PubKey pub_key |
|
|
|
int64 power |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
### AbsentValidators |
|
|
|
|
|
|
|
To simplify this, RequestBeginBlock will include the complete validator set, |
|
|
|
including the address, public key, and voting power of each validator, along |
|
|
|
with a boolean for whether or not they voted: |
|
|
|
|
|
|
|
``` |
|
|
|
message SigningValidator { |
|
|
|
Validator validator |
|
|
|
bool signed_last_block |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
### InitChain |
|
|
|
|
|
|
|
Change RequestInitChain and ResponseInitChain to |
|
|
|
|
|
|
|
``` |
|
|
|
message RequestInitChain { |
|
|
|
int64 time |
|
|
|
string chain_id |
|
|
|
ConsensusParams consensus_params |
|
|
|
repeated Validator validators |
|
|
|
bytes app_state_bytes |
|
|
|
} |
|
|
|
|
|
|
|
message ResponseInitChain { |
|
|
|
ConsensusParams consensus_params |
|
|
|
repeated Validator validators |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
## Status |
|
|
|
|
|
|
|
Accepted. |
|
|
|
|
|
|
|
## Consequences |
|
|
|
|
|
|
|
### Positive |
|
|
|
|
|
|
|
- Easier for developers to build on the ABCI |
|
|
|
|
|
|
|
### Negative |
|
|
|
|
|
|
|
- Maintenance overhead of alternative type encoding scheme |
|
|
|
- Performance overhead of passing all the validator info every block |
|
|
|
- Maintenance overhead of duplicate types |
|
|
|
|
|
|
|
### Neutral |