mirror of
https://github.com/fluencelabs/tendermint
synced 2025-07-31 04:01:55 +00:00
Revert "delete everything" (includes everything non-go-crypto)
This reverts commit 96a3502
This commit is contained in:
172
docs/specification/wire-protocol.rst
Normal file
172
docs/specification/wire-protocol.rst
Normal file
@@ -0,0 +1,172 @@
|
||||
Wire Protocol
|
||||
=============
|
||||
|
||||
The `Tendermint wire protocol <https://github.com/tendermint/go-wire>`__
|
||||
encodes data in `c-style binary <#binary>`__ and `JSON <#json>`__ form.
|
||||
|
||||
Supported types
|
||||
---------------
|
||||
|
||||
- Primitive types
|
||||
- ``uint8`` (aka ``byte``), ``uint16``, ``uint32``, ``uint64``
|
||||
- ``int8``, ``int16``, ``int32``, ``int64``
|
||||
- ``uint``, ``int``: variable length (un)signed integers
|
||||
- ``string``, ``[]byte``
|
||||
- ``time``
|
||||
- Derived types
|
||||
- structs
|
||||
- var-length arrays of a particular type
|
||||
- fixed-length arrays of a particular type
|
||||
- interfaces: registered union types preceded by a ``type byte``
|
||||
- pointers
|
||||
|
||||
Binary
|
||||
------
|
||||
|
||||
**Fixed-length primitive types** are encoded with 1,2,3, or 4 big-endian
|
||||
bytes. - ``uint8`` (aka ``byte``), ``uint16``, ``uint32``, ``uint64``:
|
||||
takes 1,2,3, and 4 bytes respectively - ``int8``, ``int16``, ``int32``,
|
||||
``int64``: takes 1,2,3, and 4 bytes respectively - ``time``: ``int64``
|
||||
representation of nanoseconds since epoch
|
||||
|
||||
**Variable-length integers** are encoded with a single leading byte
|
||||
representing the length of the following big-endian bytes. For signed
|
||||
negative integers, the most significant bit of the leading byte is a 1.
|
||||
|
||||
- ``uint``: 1-byte length prefixed variable-size (0 ~ 255 bytes)
|
||||
unsigned integers
|
||||
- ``int``: 1-byte length prefixed variable-size (0 ~ 127 bytes) signed
|
||||
integers
|
||||
|
||||
NOTE: While the number 0 (zero) is encoded with a single byte ``x00``,
|
||||
the number 1 (one) takes two bytes to represent: ``x0101``. This isn't
|
||||
the most efficient representation, but the rules are easier to remember.
|
||||
|
||||
+---------------+----------------+----------------+
|
||||
| number | binary | binary ``int`` |
|
||||
| | ``uint`` | |
|
||||
+===============+================+================+
|
||||
| 0 | ``x00`` | ``x00`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 1 | ``x0101`` | ``x0101`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 2 | ``x0102`` | ``x0102`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 256 | ``x020100`` | ``x020100`` |
|
||||
+---------------+----------------+----------------+
|
||||
| 2^(127\ *8)-1 | ``x800100...`` | overflow |
|
||||
| \| | | |
|
||||
| ``x7FFFFF...` | | |
|
||||
| ` | | |
|
||||
| \| | | |
|
||||
| ``x7FFFFF...` | | |
|
||||
| ` | | |
|
||||
| \| \| | | |
|
||||
| 2^(127*\ 8) | | |
|
||||
+---------------+----------------+----------------+
|
||||
| 2^(255\*8)-1 |
|
||||
| \| |
|
||||
| ``xFFFFFF...` |
|
||||
| ` |
|
||||
| \| overflow |
|
||||
| \| \| -1 \| |
|
||||
| n/a \| |
|
||||
| ``x8101`` \| |
|
||||
| \| -2 \| n/a |
|
||||
| \| ``x8102`` |
|
||||
| \| \| -256 \| |
|
||||
| n/a \| |
|
||||
| ``x820100`` |
|
||||
| \| |
|
||||
+---------------+----------------+----------------+
|
||||
|
||||
**Structures** are encoded by encoding the field values in order of
|
||||
declaration.
|
||||
|
||||
.. code:: go
|
||||
|
||||
type Foo struct {
|
||||
MyString string
|
||||
MyUint32 uint32
|
||||
}
|
||||
var foo = Foo{"626172", math.MaxUint32}
|
||||
|
||||
/* The binary representation of foo:
|
||||
0103626172FFFFFFFF
|
||||
0103: `int` encoded length of string, here 3
|
||||
626172: 3 bytes of string "bar"
|
||||
FFFFFFFF: 4 bytes of uint32 MaxUint32
|
||||
*/
|
||||
|
||||
**Variable-length arrays** are encoded with a leading ``int`` denoting
|
||||
the length of the array followed by the binary representation of the
|
||||
items. **Fixed-length arrays** are similar but aren't preceded by the
|
||||
leading ``int``.
|
||||
|
||||
.. code:: go
|
||||
|
||||
foos := []Foo{foo, foo}
|
||||
|
||||
/* The binary representation of foos:
|
||||
01020103626172FFFFFFFF0103626172FFFFFFFF
|
||||
0102: `int` encoded length of array, here 2
|
||||
0103626172FFFFFFFF: the first `foo`
|
||||
0103626172FFFFFFFF: the second `foo`
|
||||
*/
|
||||
|
||||
foos := [2]Foo{foo, foo} // fixed-length array
|
||||
|
||||
/* The binary representation of foos:
|
||||
0103626172FFFFFFFF0103626172FFFFFFFF
|
||||
0103626172FFFFFFFF: the first `foo`
|
||||
0103626172FFFFFFFF: the second `foo`
|
||||
*/
|
||||
|
||||
**Interfaces** can represent one of any number of concrete types. The
|
||||
concrete types of an interface must first be declared with their
|
||||
corresponding ``type byte``. An interface is then encoded with the
|
||||
leading ``type byte``, then the binary encoding of the underlying
|
||||
concrete type.
|
||||
|
||||
NOTE: The byte ``x00`` is reserved for the ``nil`` interface value and
|
||||
``nil`` pointer values.
|
||||
|
||||
.. code:: go
|
||||
|
||||
type Animal interface{}
|
||||
type Dog uint32
|
||||
type Cat string
|
||||
|
||||
RegisterInterface(
|
||||
struct{ Animal }{}, // Convenience for referencing the 'Animal' interface
|
||||
ConcreteType{Dog(0), 0x01}, // Register the byte 0x01 to denote a Dog
|
||||
ConcreteType{Cat(""), 0x02}, // Register the byte 0x02 to denote a Cat
|
||||
)
|
||||
|
||||
var animal Animal = Dog(02)
|
||||
|
||||
/* The binary representation of animal:
|
||||
010102
|
||||
01: the type byte for a `Dog`
|
||||
0102: the bytes of Dog(02)
|
||||
*/
|
||||
|
||||
**Pointers** are encoded with a single leading byte ``x00`` for ``nil``
|
||||
pointers, otherwise encoded with a leading byte ``x01`` followed by the
|
||||
binary encoding of the value pointed to.
|
||||
|
||||
NOTE: It's easy to convert pointer types into interface types, since the
|
||||
``type byte`` ``x00`` is always ``nil``.
|
||||
|
||||
JSON
|
||||
----
|
||||
|
||||
The JSON codec is compatible with the ```binary`` <#binary>`__ codec,
|
||||
and is fairly intuitive if you're already familiar with golang's JSON
|
||||
encoding. Some quirks are noted below:
|
||||
|
||||
- variable-length and fixed-length bytes are encoded as uppercase
|
||||
hexadecimal strings
|
||||
- interface values are encoded as an array of two items:
|
||||
``[type_byte, concrete_value]``
|
||||
- times are encoded as rfc2822 strings
|
Reference in New Issue
Block a user