mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-09 08:08:09 +00:00
102 lines
5.3 KiB
Markdown
102 lines
5.3 KiB
Markdown
# Trezor Protocol
|
|
|
|
## version 1
|
|
|
|
Messages are sent in packets of 64 bytes.
|
|
|
|
First packet has the following structure:
|
|
|
|
| offset | length | type | contents |
|
|
|--------|--------|-------------|---------------------------------------------------------------------------------------|
|
|
| 0 | 3 | char[3] | '?##' magic constant |
|
|
| 3 | 2 | BE uint16_t | numerical [message type](messages.proto#L76) |
|
|
| 5 | 4 | BE uint32_t | message size |
|
|
| 9 | 55 | uint8_t[55] | first 55 bytes of message encoded in Protocol Buffers (padded with zeroes if shorter) |
|
|
|
|
Following packets has the following structure:
|
|
|
|
| offset | length | type | contents |
|
|
|--------|--------|-------------|----------------------------------------------------------------------------------------|
|
|
| 0 | 1 | char[1] | '?' magic constant |
|
|
| 1 | 63 | uint8_t[63] | following bytes of message encoded in Protocol Buffers (padded with zeroes if shorter) |
|
|
|
|
## Ethereum network and token definitions
|
|
Ethereum network and token definitions could be sent from host to device. External definitions are generated from time to time
|
|
and provided on publicly accessible website - `data.trezor.io` # TODO: update url. For more info look
|
|
at the [definitions README.md](../defs/README.md#eth-and-erc20).
|
|
To ensure that the definitions send to device are genuine we use Merkle tree with a combination of signed Merkle tree root hash.
|
|
Every definition is then checked and verified at FW side on receiving.
|
|
|
|
|
|
Definitions (network/token) are binary encoded and have a special format:
|
|
1. prefix:
|
|
1. format version of the definition (UTF-8 string `trzd` + version number, padded with zeroes if shorter, 8 bytes)
|
|
2. type of data (unsigned integer, 1 byte)
|
|
3. data version of the definition (unsigned integer, 4 bytes)
|
|
4. length of the encoded protobuf message - payload length in bytes (unsigned integer, 2 bytes)
|
|
2. payload: serialized form of protobuf message EthereumNetworkInfo or EthereumTokenInfo (N bytes)
|
|
3. suffix:
|
|
1. length of the Merkle tree proof - number of hashes in the proof (unsigned integer, 1 byte)
|
|
2. proof - individual hashes used to compute Merkle tree root hash (plain bits, N*32 bytes)
|
|
3. signed Merkle tree root hash (plain bits, 64 bytes)
|
|
|
|
## Adding new message
|
|
|
|
To add new message to Trezor protocol follow these steps:
|
|
1. Reconsider if there isn't already a message, that would suit your needs.
|
|
2. Choose the right place (file) to put new message:
|
|
- [`messages.proto`](messages.proto) are for management of the messages itself (wire type to message type mapping and etc.)
|
|
- [`messages-common.proto`](messages-common.proto) are for common messages
|
|
- all other files have a suffix `messages-SUFFIX.proto`, where suffix describes specific use case of messages contained within the file
|
|
3. Add new message and comment it properly following our [Messages naming and documenting conventions](#messages-naming-and-documenting-conventions).
|
|
4. If message is not embedded in another message, it has to have a wire type number assigned. This number is used to map
|
|
between Trezor wire identifier (uint) and a protobuf message. Mapping is defined in [`messages.proto`](messages.proto#L76). You have to find the lowest
|
|
free number and assign it to new message.
|
|
|
|
## Messages naming and documenting conventions
|
|
Message names must:
|
|
- be as self explanatory as possible
|
|
- have `Ack` suffix if the message is a received message (send from host to device) and serves as a response to some request made by device before
|
|
(e.g. initial messages from host to device doesn't have to have this suffix)
|
|
|
|
Documenting/commenting the messages is mandatory. Please use the following template:
|
|
```protobuf
|
|
/**
|
|
* MSG_TYPE: Description of the message
|
|
* MSG_FLOW_TAG
|
|
* MSG_FLOW_TAG
|
|
* ...
|
|
*/
|
|
```
|
|
where:
|
|
- `MSG_TYPE` is used to describe the purpose of the message and its type. Possible values are:
|
|
- `Request` for inbound messages (coming to the device (Trezor))
|
|
- `Response` for outbound messages (coming out from the device)
|
|
- in case that the message is embedded in another message we don't state the message type
|
|
- `MSG_FLOW_TAG` denotes the flow of the messages in a session (use case). Possible tags are:
|
|
- `@start` means that this message is first
|
|
- `@end`means that this message is last
|
|
- `@next` denotes messages that could follow after this message
|
|
- `@embed` denotes messages that are embedded into other message(s)
|
|
- `@auxstart` - ?? diamond start
|
|
- `@auxend` - ?? diamond end
|
|
|
|
Messages flow is checked at the compile time.
|
|
|
|
Using the template and the rules we can create for example this messages:
|
|
```protobuf
|
|
/**
|
|
* Request: Ask device to sign transaction
|
|
* @start
|
|
* @next TxRequest
|
|
* @next Failure
|
|
*/
|
|
```
|
|
```protobuf
|
|
/**
|
|
* Structure representing BIP32 (hierarchical deterministic) node
|
|
* Used for imports of private key into the device and exporting public key out of device
|
|
* @embed
|
|
*/
|
|
```
|