1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-08 23:58:09 +00:00
trezor-firmware/common/protob/protocol.md

5.3 KiB

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
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. 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 are for management of the messages itself (wire type to message type mapping and etc.)
    • 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.
  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. 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:

/**
 * 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
    • @endmeans 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:

/**
 * Request: Ask device to sign transaction
 * @start
 * @next TxRequest
 * @next Failure
 */
/**
 * Structure representing BIP32 (hierarchical deterministic) node
 * Used for imports of private key into the device and exporting public key out of device
 * @embed
 */