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