Ledger Nano Protocol

GIT: https://gitlab.com/dune-network/ledger-app-dune

General message format

Header of all message

uint8 class (always = 0)

uint8 instruction

uint8 parameter1

uint8 curve

uint8 content_length

char[content_length] content

Encodings

The curve field can take the following values:

  • 0 -> ed25519

  • 1 -> secp256k1

  • 2 -> p256 (secp256r1)

  • 3 -> any

All int32 integers are encoded in big endian.

Components of bip32 paths have the highest bit set:

v | 0x8000_0000

Contents to be signed have to carry a watermark for safe signing operations:

  • Block: 0x01 + chain_id + block_header

  • Endorsement: 0x02 + chain_id + endorsement

  • Other Operations: 0x03 + operation

    The chain_id is 0xe75d4a33 for Dune’s mainnet. If you want the chain_id for a particular chain:

    $ dune-client rpc get /chains/main/chain_id
    "NetXwhYbWGa82xo"
    $ dune-client dune decode NetXwhYbWGa82xo
    NetXwhYbWGa82xo = chain_id e75d4a33
    

The baking_mode byte is interpreted as a logical or between the following flags:

  • 1 for baking mode, 0 for wallet mode

  • 2 for always baking, i.e. the app cannot go back to wallet mode

  • 4 for volatile watermarks. In this mode, watermarks are not saved in NVRAM between signatures, but only in a clean exit. It can be used to save some lifetime for the Ledger (whose memory is supposed to only support about 500,000 erasures)

Successful reply

char[*] content

char[2] terminator = 0x90 0x00

Error reply

char[2] error = 0x69 0x85

Current messages

Query Version

  • Function: return the version of the Dune app

  • User interaction: none

  • Mode: all

  • Request:

    • instruction: 0x00

  • Reply: content_length = 4 (Tezos) or > 12 (Dune)

    uint8 baking_mode

    uint8 major

    uint8 minor

    uint8 patch

    char[8] date

    char[] commit git

Query Public Key

  • Function: query the public key at a bip32 path x curve

  • User interaction: none

  • Request:

    • instruction: 0x02

    • curve: curve to use

    • content_length: bip32 path

    uint8 path_length

    uint32[path_length] components

  • Reply: content_length variable

    uint8 key_length

    char[key_length] key

Prompt Public Key

  • Function: query the public key at a bip32 path x curve

  • User interaction: validate prompt

  • Request:

    • instruction: 0x03

    • curve: curve to use

    • content_length: bip32 path

    uint8 path_length

    uint32[path_length] components

  • Reply: content_length variable

    uint8 key_length

    char[key_length] key

Sign (with hash)

  • Function: sign the hash of an operation or a block. The operation or block is parsed. Only one transaction/origination is allowed as an internal operation (with/out a reveal operation). For baking, the ledger verifies that the level is greater than the current high watermark and increases the watermark.

  • User interaction: validate

  • Mode: all

  • Request:

    • instruction: 0xF

    • parameter1: used to send content over multiple messages

      • First message should not have flag 0x01

      • Last message should have flag 0x80

    • Curve: the curve to use (only in first message)

    • Content:

      • First message: bip32 path of key to use

      uint8 path_length

      uint32[path_length] components

      • Other messages: the block header or operation content to be signed, with signature watermarks (prefixes). See the format section above.

  • Reply:

    char[HASH_SIZE] signed_hash

    char[SIGN_SIZE] signature

Sign (unsafe)

  • Function: sign a chunk of data.

  • User interaction: validate

  • Mode: wallet only

  • Request:

    • instruction: 0x05

    • parameter1: used to send content over multiple messages

      • First message should not have flag 0x01

      • Last message should have flag 0x80

    • Curve: the curve to use (only in first message)

    • Content:

      • First message: bip32 path of key to use

        uint8 path_length

        uint32[path_length] components

      • Other messages: the block header or operation content to be signed

  • Reply:

    char[SIGN_SIZE] signature

HMAC

  • Function: Perform an HMAC of some data using a secret on the ledger

    (actually, the signature of some data by the secret key)

  • User interaction: none

  • Mode: baking only

  • Request:

    • instruction: 0x0E

    • curve: curve to use for the secret key

    • Content: the bip32 path of the secret key to use and the content to hmac

    uint8 path_length

    uint32[path_length] components

    char[] content_to_hmac

  • Reply:

    char[] hmac

Baking: Setup

  • Function: Set main_chain_id, min main level, min test level, after prompting the user.

  • User interaction: validate

  • Mode: baking only

  • Request:

    • instruction: 0x0A

    • curve to setup

    • Content: content_length variable

    uint32 main_chain_id

    uint32 main_high_watermark

    uint32 test_high_watermark

    uint8 bip32_path_length

    uint32[bip32_path_length] bip32_path

  • Reply: the public key

    uint8 key_length

    char[key_length] key

Baking: Reset Watermarks

  • Function: Reset all watermarks to a given level

  • User interaction: validate

  • Mode: baking only

  • Request:

    • instruction: 0x06

    • content: the level

    uint32 level

  • Reply: empty

Baking: Query All Watermarks

  • Function: Return all the high watermarks

  • User interaction: none

  • Mode: baking only

  • Request:

    • instruction: 0x0B

    • content: none

  • Reply:

    uint32 main_high_watermark

    uint32 test_high_watermark

    uint32 main_chain_id

Baking: Query Auth Key&Curve

  • Function: return the curve and bip32 path of the setup key

  • User interaction: none

  • Mode: baking only

  • Request:

    • instruction: 0x0D

    • Content: empty

  • Reply:

    uint8 curve

    uint8 path_length

    uint32[path_length] components

Baking: Deauthorize

  • Function: remove the setup baking key

  • User interaction: none

  • Mode: baking only

  • Request:

    • instruction: 0x0C

    • Content: none

  • Reply: none

Set Baking mode

  • Function: switch between wallet mode and baking mode

  • Mode: all

  • Request:

    • instruction: 0x10

    • Content: 1 byte

    char[1] wanted bakind_mode

    See the format of bakind_mode above.

  • Reply:

char[1] current_mode

Obsolete messages

Query GIT Commit

  • Function: return the commit version of the Dune app

  • User interaction: none

  • Mode: baking only

  • Request:

    • instruction: 0x09

    • Content: none

  • Reply:

    char[] commit

Baking: Authorize

  • Function: authorize the last displayed public key to be used to automatically sign blocks and endorsements. Obsolete: do not setup watermarks

  • User interaction: validate

  • Mode: baking only

  • Request:

    • instruction: 0x01

    • curve: curve to use

    • content_length: 0 or a bip32 path

    uint8 path_length

    uint32[path_length] components

  • Reply: content_length variable

    uint8 key_length

    char[key_length] key

Baking: Query Auth Key

  • Function: return the bip32 path of the setup key

  • User interaction: none

  • Mode: baking only

  • Request:

    • instruction: 0x07

    • Content: empty

  • Reply:

    uint8 path_length

    uint32[path_length] components

Baking: Query Main Watermark

  • Function: Return the high watermark of the setup main chain

  • User interaction: none

  • Mode: baking only

  • Request:

    • instruction: 0x08

    • Content: none

  • Reply:

    uint32 high_watermark

Sign

  • Function: sign the hash of an operation or a block. The operation or block is parsed. Only one transaction/origination is allowed as an internal operation (with/out a reveal operation). For baking, the ledger verifies that the level is greater than the current high watermark and increases the watermark.

  • User interaction: validate

  • Mode: all

  • Request:

    • instruction: 0x4

    • parameter1: used to send content over multiple messages

      • First message should not have flag 0x01

      • Last message should have flag 0x80

    • Curve: the curve to use (only in first message)

    • Content:

      • First message: bip32 path of key to use

      uint8 path_length

      uint32[path_length] components

      • Other messages: the block header or operation content to be signed

  • Reply:

    char[SIGN_SIZE] signature