# ADR 009: ABCI UX Improvements

## Changelog

23-06-2018: Some minor fixes from review
07-06-2018: Some updates based on discussion with Jae
07-06-2018: Initial draft to match what was released in ABCI v0.11

## 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 (proto3) 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 [references](#references) for more.

### Imports

The native proto library in Go generates inflexible and verbose code.
Many in the Go community have adopted a fork called
[gogoproto](https://github.com/gogo/protobuf) that provides a
variety of features aimed to improve the developer experience.
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 proto4.

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 proto4. In the meantime,
we want it to be easy to use.

### PubKey

PubKeys are encoded using Amino (and before that, go-wire).
Ideally, PubKeys are an interface type where we don't know all the
implementation types, so its unfitting to use `oneof` or `enum`.

### Addresses

The address for ED25519 pubkey is the RIPEMD160 of the Amino
encoded pubkey. This introduces an Amino dependency in the address generation,
a functionality that is widely required and should be easy to compute as
possible.

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

### Header

ABCI provides the Header in RequestBeginBlock so the application can have
important information about the latest state of the blockchain.

## 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 proto4.
To facilitate adoption and cross-language compatibility in the near-term, Amino
v1 will:

- be fully compatible with the subset of proto3 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>`


As we want to retain flexibility here, and since ideally, PubKey would be an
interface type, we do not use `enum` or `oneof`.

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

Add a `bytes address` field:

```
message Validator {
    bytes address
    PubKey pub_key
    int64 power
}
```

### RequestBeginBlock and AbsentValidators

To simplify this, RequestBeginBlock will include the complete validator set,
including the address, and voting power of each validator, along
with a boolean for whether or not they voted:

```
message RequestBeginBlock {
  bytes hash
  Header header
  LastCommitInfo last_commit_info
  repeated Evidence byzantine_validators
}

message LastCommitInfo {
  int32 CommitRound
  repeated SigningValidator validators
}

message SigningValidator {
    Validator validator
    bool signed_last_block
}
```

Note that in Validators in RequestBeginBlock, we DO NOT include public keys. Public keys are
larger than addresses and in the future, with quantum computers, will be much
larger. The overhead of passing them, especially during fast-sync, is
significant.

Additional, addresses are changing to be simpler to compute, further removing
the need to include pubkeys here.

In short, ABCI developers must be aware of both addresses and public keys.

### ResponseEndBlock

Since ResponseEndBlock includes Validator, it must now include their address.

### InitChain

Change RequestInitChain to give the app all the information from the genesis file:

```
message RequestInitChain {
    int64 time
    string chain_id
    ConsensusParams consensus_params
    repeated Validator validators
    bytes app_state_bytes
}
```

Change ResponseInitChain to allow the app to specify the initial validator set
and consensus parameters.

```
message ResponseInitChain {
    ConsensusParams consensus_params
    repeated Validator validators
}
```

### Header

Now that Tendermint Amino will be compatible with proto3, the Header in ABCI
should exactly match the Tendermint header - they will then be encoded
identically in ABCI and in Tendermint Core.

## Status

Accepted.

## Consequences

### Positive

- Easier for developers to build on the ABCI
- ABCI and Tendermint headers are identically serialized

### Negative

- Maintenance overhead of alternative type encoding scheme
- Performance overhead of passing all validator info every block (at least its
  only addresses, and not also pubkeys)
- Maintenance overhead of duplicate types

### Neutral

- ABCI developers must know about validator addresses

## References

- [ABCI v0.10.3 Specification (before this
  proposal)](https://github.com/tendermint/abci/blob/v0.10.3/specification.rst)
- [ABCI v0.11.0 Specification (implementing first draft of this
  proposal)](https://github.com/tendermint/abci/blob/v0.11.0/specification.md)
- [Ed25519 addresses](https://github.com/tendermint/go-crypto/issues/103)
- [InitChain contains the
  Genesis](https://github.com/tendermint/abci/issues/216)
- [PubKeys](https://github.com/tendermint/tendermint/issues/1524)
- [Notes on
  Header](https://github.com/tendermint/tendermint/issues/1605)
- [Gogoproto issues](https://github.com/tendermint/abci/issues/256)
- [Absent Validators](https://github.com/tendermint/abci/issues/231)
