193 lines
5.8 KiB
Markdown
Raw Normal View History

2017-12-26 15:30:34 -05:00
# Tendermint Encoding
2018-04-26 09:09:56 -04:00
## Amino
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
Tendermint uses the Protobuf3 derrivative [Amino]() for all data structures.
Thik of Amino as an object-oriented Protobuf3 with native JSON support.
The goal of the Amino encoding protocol is to bring parity between application
logic objects and persistence objects.
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
Please see the [Amino
specification](https://github.com/tendermint/go-amino#amino-encoding-for-go) for
more details.
2018-01-19 17:51:09 -05:00
2018-04-26 09:09:56 -04:00
Notably, every object that satisfies an interface (eg. a particular kind of p2p message,
or a particular kind of pubkey) is registered with a global name, the hash of
which is included in the object's encoding as the so-called "prefix bytes".
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
## Public Key Cryptography
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
Tendermint uses Amino to distinguish between different types of private keys,
public keys, and signatures. Additionally, for each public key, Tendermint
defines an Address function that can be used as a more compact identifier in
place of the public key. Here we list the concrete types, their names,
and prefix bytes for public keys and signatures. Note for brevity we don't
include details of the private keys beyond their type and name, as they can be
derrived the same way as the others using Amino.
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
All registered objects are encoded by Amino using a 4-byte PrefixBytes that
uniquely identifies the object and includes information about its underlying
type. For details on how PrefixBytes are computed, see the [Amino
spec](https://github.com/tendermint/go-amino#computing-the-prefix-and-disambiguation-bytes).
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
In what follows, we provide the type names and prefix bytes directly.
Notice that when encoding byte-arrays, the length of the byte-array is appended
to the PrefixBytes. Thus the encoding of a byte array becomes `<PrefixBytes>
<Length> <ByteArray>`
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
### PubKeyEd25519
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
```
// Name: tendermint/PubKeyEd25519
// PrefixBytes: 0x1624DE62
// Length: 0x20
// Notes: raw 32-byte Ed25519 pubkey
type PubKeyEd25519 [32]byte
```
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
For example, the 32-byte Ed25519 pubkey
`76852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85` would be
encoded as
`1624DE622076852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85`
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
### SignatureEd25519
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
```
// Name: tendermint/SignatureKeyEd25519
// PrefixBytes: 0x3DA1DB2A
// Length: 0x40
// Notes: raw 64-byte Ed25519 signature
type SignatureEd25519 [64]byte
```
2017-12-26 16:33:42 -05:00
2018-04-26 09:09:56 -04:00
For example, the 64-byte Ed25519 signature
`005E76B3B0D790959B03F862A9EF8F6236457032B5F522C4CAB5AAD7C44A00A12669E1A2761798E70A0A923DA0CF981839558123CF6466553BCBFF25DADD630F`
would be encoded as
`3DA1DB2A40005E76B3B0D790959B03F862A9EF8F6236457032B5F522C4CAB5AAD7C44A00A12669E1A2761798E70A0A923DA0CF981839558123CF6466553BCBFF25DADD630F`
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
### PrivKeyEd25519
2017-12-26 15:30:34 -05:00
```
2018-04-26 09:09:56 -04:00
// Name: tendermint/PrivKeyEd25519
// Notes: raw 32-byte priv key concatenated to raw 32-byte pub key
type PrivKeyEd25519 [64]byte
```
### PubKeySecp256k1
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
```
// Name: tendermint/PubKeySecp256k1
// PrefixBytes: 0xEB5AE982
// Length: 0x21
// Notes: OpenSSL compressed pubkey prefixed with 0x02 or 0x03
type PubKeySecp256k1 [33]byte
```
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
For example, the 33-byte Secp256k1 pubkey
`03573E0EC1F989DECC3913AC7D44D0509C1A992ECE700845594A1078DAF19A3380` would be
encoded as
`EB5AE9822103573E0EC1F989DECC3913AC7D44D0509C1A992ECE700845594A1078DAF19A3380`
2017-12-26 16:33:42 -05:00
2018-04-26 09:09:56 -04:00
### SignatureSecp256k1
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
```
// Name: tendermint/SignatureKeySecp256k1
// PrefixBytes: 0x16E1FEEA
// Length: Variable
// Encoding prefix: Variable
// Notes: raw bytes of the Secp256k1 signature
type SignatureSecp256k1 []byte
2017-12-26 15:30:34 -05:00
```
2018-04-26 09:09:56 -04:00
For example, the Secp256k1 signature
`304402207447640A5C12A72BAA052D110B666FB6DF717A7B863361C092E751D016C6C08802205C20F9DEBF8915DED310B98BFA890105F43925FDB2B67B78510FE18EDA2B30DA` would
be encoded as
`16E1FEEA46304402202C10C874E413AF538D97EBEF2B01024719F8B7CC559CEEBDC7C380F9DCC4A6E002200EDE9B62F8531933F88DB2A62E73BA3D43ACEB1CBD23070C2F792AAA18717A4A`
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
### PrivKeySecp256k1
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
```
// Name: tendermint/PrivKeySecp256k1
// Notes: raw 32-byte priv key
type PrivKeySecp256k1 [32]byte
2017-12-26 15:30:34 -05:00
```
2017-12-26 16:33:42 -05:00
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
## Other Common Types
2017-12-26 15:30:34 -05:00
### BitArray
2018-01-03 10:46:43 +01:00
2018-01-19 17:51:09 -05:00
BitArray is encoded as an `int` of the number of bits, and with an array of `uint64` to encode
value of each array element.
2018-01-03 10:46:43 +01:00
```go
type BitArray struct {
2018-01-19 17:51:09 -05:00
Bits int
Elems []uint64
}
```
2018-04-26 09:09:56 -04:00
### Part
2017-12-26 15:30:34 -05:00
2018-01-03 10:46:43 +01:00
```go
2018-04-26 09:09:56 -04:00
type Part struct {
Index int
Bytes byte[]
Proof byte[]
}
2017-12-26 15:30:34 -05:00
```
2018-04-26 09:09:56 -04:00
### MakeParts
2017-12-26 15:30:34 -05:00
2018-04-26 09:09:56 -04:00
Encode an object using Amino and slice it into parts.
2017-12-26 15:30:34 -05:00
2018-01-03 10:46:43 +01:00
```go
2018-04-26 09:09:56 -04:00
MakeParts(object, partSize)
2017-12-26 15:30:34 -05:00
```
## Merkle Trees
2017-12-26 18:43:03 -05:00
Simple Merkle trees are used in numerous places in Tendermint to compute a cryptographic digest of a data structure.
2017-12-26 15:30:34 -05:00
2017-12-26 15:48:17 -05:00
RIPEMD160 is always used as the hashing function.
The function `SimpleMerkleRoot` is a simple recursive function defined as follows:
2018-01-03 10:46:43 +01:00
```go
2017-12-26 15:48:17 -05:00
func SimpleMerkleRoot(hashes [][]byte) []byte{
2018-01-03 10:46:43 +01:00
switch len(hashes) {
case 0:
return nil
case 1:
return hashes[0]
default:
left := SimpleMerkleRoot(hashes[:(len(hashes)+1)/2])
right := SimpleMerkleRoot(hashes[(len(hashes)+1)/2:])
return RIPEMD160(append(left, right))
}
2017-12-26 15:48:17 -05:00
}
```
2018-01-25 02:11:07 +00:00
Note: we abuse notion and call `SimpleMerkleRoot` with arguments of type `struct` or type `[]struct`.
2018-01-03 10:46:43 +01:00
For `struct` arguments, we compute a `[][]byte` by sorting elements of the `struct` according to
field name and then hashing them.
2017-12-26 15:48:17 -05:00
For `[]struct` arguments, we compute a `[][]byte` by hashing the individual `struct` elements.
2017-12-26 18:43:03 -05:00
2018-04-26 09:09:56 -04:00
## AminoJSON
2017-12-26 18:43:03 -05:00
2018-04-26 09:09:56 -04:00
Signed messages (eg. votes, proposals) in the consensus are encoded in AminoJSON, rather than binary Amino.
2017-12-26 18:43:03 -05:00
2018-01-03 10:46:43 +01:00
When signing, the elements of a message are sorted by key and the sorted message is embedded in an
outer JSON that includes a `chain_id` field.
We call this encoding the CanonicalSignBytes. For instance, CanonicalSignBytes for a vote would look
like:
2017-12-26 18:43:03 -05:00
2018-01-03 10:46:43 +01:00
```json
2017-12-26 18:43:03 -05:00
{"chain_id":"my-chain-id","vote":{"block_id":{"hash":DEADBEEF,"parts":{"hash":BEEFDEAD,"total":3}},"height":3,"round":2,"timestamp":1234567890, "type":2}
```
Note how the fields within each level are sorted.