syntax = "proto2"; /** * Messages for TREZOR communication */ // Sugar for easier handling in Java option java_package = "com.satoshilabs.trezor.lib.protobuf"; option java_outer_classname = "TrezorMessage"; import "types.proto"; /** * Mapping between Trezor wire identifier (uint) and a protobuf message */ enum MessageType { MessageType_Initialize = 0 [(wire_in) = true]; MessageType_Ping = 1 [(wire_in) = true]; MessageType_Success = 2 [(wire_out) = true]; MessageType_Failure = 3 [(wire_out) = true]; MessageType_ChangePin = 4 [(wire_in) = true]; MessageType_WipeDevice = 5 [(wire_in) = true]; MessageType_FirmwareErase = 6 [(wire_in) = true, (wire_bootloader) = true]; MessageType_FirmwareUpload = 7 [(wire_in) = true, (wire_bootloader) = true]; MessageType_FirmwareRequest = 8 [(wire_out) = true, (wire_bootloader) = true]; MessageType_GetEntropy = 9 [(wire_in) = true]; MessageType_Entropy = 10 [(wire_out) = true]; MessageType_GetPublicKey = 11 [(wire_in) = true]; MessageType_PublicKey = 12 [(wire_out) = true]; MessageType_LoadDevice = 13 [(wire_in) = true]; MessageType_ResetDevice = 14 [(wire_in) = true]; MessageType_SignTx = 15 [(wire_in) = true]; MessageType_SimpleSignTx = 16 [(wire_in) = true, deprecated = true]; MessageType_Features = 17 [(wire_out) = true]; MessageType_PinMatrixRequest = 18 [(wire_out) = true]; MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true]; MessageType_Cancel = 20 [(wire_in) = true]; MessageType_TxRequest = 21 [(wire_out) = true]; MessageType_TxAck = 22 [(wire_in) = true]; MessageType_CipherKeyValue = 23 [(wire_in) = true]; MessageType_ClearSession = 24 [(wire_in) = true]; MessageType_ApplySettings = 25 [(wire_in) = true]; MessageType_ButtonRequest = 26 [(wire_out) = true]; MessageType_ButtonAck = 27 [(wire_in) = true, (wire_tiny) = true]; MessageType_ApplyFlags = 28 [(wire_in) = true]; MessageType_GetAddress = 29 [(wire_in) = true]; MessageType_Address = 30 [(wire_out) = true]; MessageType_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true]; MessageType_BackupDevice = 34 [(wire_in) = true]; MessageType_EntropyRequest = 35 [(wire_out) = true]; MessageType_EntropyAck = 36 [(wire_in) = true]; MessageType_SignMessage = 38 [(wire_in) = true]; MessageType_VerifyMessage = 39 [(wire_in) = true]; MessageType_MessageSignature = 40 [(wire_out) = true]; MessageType_PassphraseRequest = 41 [(wire_out) = true]; MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true]; MessageType_PassphraseStateRequest = 77 [(wire_out) = true]; MessageType_PassphraseStateAck = 78 [(wire_in) = true, (wire_tiny) = true]; MessageType_EstimateTxSize = 43 [(wire_in) = true, deprecated = true]; MessageType_TxSize = 44 [(wire_out) = true, deprecated = true]; MessageType_RecoveryDevice = 45 [(wire_in) = true]; MessageType_WordRequest = 46 [(wire_out) = true]; MessageType_WordAck = 47 [(wire_in) = true]; MessageType_CipheredKeyValue = 48 [(wire_out) = true]; MessageType_EncryptMessage = 49 [(wire_in) = true, deprecated = true]; MessageType_EncryptedMessage = 50 [(wire_out) = true, deprecated = true]; MessageType_DecryptMessage = 51 [(wire_in) = true, deprecated = true]; MessageType_DecryptedMessage = 52 [(wire_out) = true, deprecated = true]; MessageType_SignIdentity = 53 [(wire_in) = true]; MessageType_SignedIdentity = 54 [(wire_out) = true]; MessageType_GetFeatures = 55 [(wire_in) = true]; MessageType_EthereumGetAddress = 56 [(wire_in) = true]; MessageType_EthereumAddress = 57 [(wire_out) = true]; MessageType_EthereumSignTx = 58 [(wire_in) = true]; MessageType_EthereumTxRequest = 59 [(wire_out) = true]; MessageType_EthereumTxAck = 60 [(wire_in) = true]; MessageType_GetECDHSessionKey = 61 [(wire_in) = true]; MessageType_ECDHSessionKey = 62 [(wire_out) = true]; MessageType_SetU2FCounter = 63 [(wire_in) = true]; MessageType_EthereumSignMessage = 64 [(wire_in) = true]; MessageType_EthereumVerifyMessage = 65 [(wire_in) = true]; MessageType_EthereumMessageSignature = 66 [(wire_out) = true]; MessageType_NEMGetAddress = 67 [(wire_in) = true]; MessageType_NEMAddress = 68 [(wire_out) = true]; MessageType_NEMSignTx = 69 [(wire_in) = true]; MessageType_NEMSignedTx = 70 [(wire_out) = true]; MessageType_CosiCommit = 71 [(wire_in) = true]; MessageType_CosiCommitment = 72 [(wire_out) = true]; MessageType_CosiSign = 73 [(wire_in) = true]; MessageType_CosiSignature = 74 [(wire_out) = true]; MessageType_NEMDecryptMessage = 75 [(wire_in) = true]; MessageType_NEMDecryptedMessage = 76 [(wire_out) = true]; MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true]; MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true]; MessageType_DebugLinkState = 102 [(wire_debug_out) = true]; MessageType_DebugLinkStop = 103 [(wire_debug_in) = true]; MessageType_DebugLinkLog = 104 [(wire_debug_out) = true]; MessageType_DebugLinkMemoryRead = 110 [(wire_debug_in) = true]; MessageType_DebugLinkMemory = 111 [(wire_debug_out) = true]; MessageType_DebugLinkMemoryWrite = 112 [(wire_debug_in) = true]; MessageType_DebugLinkFlashErase = 113 [(wire_debug_in) = true]; // Lisk MessageType_LiskGetAddress = 114 [(wire_in) = true]; MessageType_LiskAddress = 115 [(wire_out) = true]; MessageType_LiskSignTx = 116 [(wire_in) = true]; MessageType_LiskSignedTx = 117 [(wire_out) = true]; MessageType_LiskGetPublicKey = 121 [(wire_in) = true]; MessageType_LiskPublicKey = 122 [(wire_out) = true]; // Stellar MessageType_StellarGetPublicKey = 200 [(wire_in) = true]; MessageType_StellarPublicKey = 201 [(wire_out) = true]; MessageType_StellarSignTx = 202 [(wire_in) = true]; MessageType_StellarTxOpRequest = 203 [(wire_out) = true]; MessageType_StellarCreateAccountOp = 210 [(wire_in) = true]; MessageType_StellarPaymentOp = 211 [(wire_in) = true]; MessageType_StellarPathPaymentOp = 212 [(wire_in) = true]; MessageType_StellarManageOfferOp = 213 [(wire_in) = true]; MessageType_StellarCreatePassiveOfferOp = 214 [(wire_in) = true]; MessageType_StellarSetOptionsOp = 215 [(wire_in) = true]; MessageType_StellarChangeTrustOp = 216 [(wire_in) = true]; MessageType_StellarAllowTrustOp = 217 [(wire_in) = true]; MessageType_StellarAccountMergeOp = 218 [(wire_in) = true]; // Omitted: inflation is not a supported operation, would be 219 MessageType_StellarManageDataOp = 220 [(wire_in) = true]; MessageType_StellarBumpSequenceOp = 221 [(wire_in) = true]; MessageType_StellarSignedTx = 230 [(wire_out) = true]; } //////////////////// // Basic messages // //////////////////// /** * Request: Reset device to default state and ask for device details * @next Features */ message Initialize { optional bytes state = 1; // assumed device state, clear session if set and different optional bool skip_passphrase = 2; // this session should always assume empty passphrase } /** * Request: Ask for device details (no device reset) * @next Features */ message GetFeatures { } /** * Response: Reports various information about the device * @prev Initialize * @prev GetFeatures */ message Features { optional string vendor = 1; // name of the manufacturer, e.g. "trezor.io" optional uint32 major_version = 2; // major version of the firmware/bootloader, e.g. 1 optional uint32 minor_version = 3; // minor version of the firmware/bootloader, e.g. 0 optional uint32 patch_version = 4; // patch version of the firmware/bootloader, e.g. 0 optional bool bootloader_mode = 5; // is device in bootloader mode? optional string device_id = 6; // device's unique identifier optional bool pin_protection = 7; // is device protected by PIN? optional bool passphrase_protection = 8; // is node/mnemonic encrypted using passphrase? optional string language = 9; // device language optional string label = 10; // device description label optional bool initialized = 12; // does device contain seed? optional bytes revision = 13; // SCM revision of firmware optional bytes bootloader_hash = 14; // hash of the bootloader optional bool imported = 15; // was storage imported from an external source? optional bool pin_cached = 16; // is PIN already cached in session? optional bool passphrase_cached = 17; // is passphrase already cached in session? optional bool firmware_present = 18; // is valid firmware loaded? optional bool needs_backup = 19; // does storage need backup? (equals to Storage.needs_backup) optional uint32 flags = 20; // device flags (equals to Storage.flags) optional string model = 21; // device hardware model optional uint32 fw_major = 22; // reported firmware version if in bootloader mode optional uint32 fw_minor = 23; // reported firmware version if in bootloader mode optional uint32 fw_patch = 24; // reported firmware version if in bootloader mode optional string fw_vendor = 25; // reported firmware vendor if in bootloader mode optional bytes fw_vendor_keys = 26; // reported firmware vendor keys (their hash) optional bool unfinished_backup = 27; // report unfinished backup (equals to Storage.unfinished_backup) } /** * Request: clear session (removes cached PIN, passphrase, etc). * @next Success */ message ClearSession { } /** * Request: change language and/or label of the device * @next Success * @next Failure * @next ButtonRequest * @next PinMatrixRequest */ message ApplySettings { optional string language = 1; optional string label = 2; optional bool use_passphrase = 3; optional bytes homescreen = 4; optional PassphraseSourceType passphrase_source = 5; optional uint32 auto_lock_delay_ms = 6; } /** * Request: set flags of the device * @next Success * @next Failure */ message ApplyFlags { optional uint32 flags = 1; // bitmask, can only set bits, not unset } /** * Request: Starts workflow for setting/changing/removing the PIN * @next ButtonRequest * @next PinMatrixRequest */ message ChangePin { optional bool remove = 1; // is PIN removal requested? } /** * Request: Test if the device is alive, device sends back the message in Success response * @next Success */ message Ping { optional string message = 1; // message to send back in Success message optional bool button_protection = 2; // ask for button press optional bool pin_protection = 3; // ask for PIN if set in device optional bool passphrase_protection = 4; // ask for passphrase if set in device } /** * Response: Success of the previous request */ message Success { optional string message = 1; // human readable description of action or request-specific payload } /** * Response: Failure of the previous request */ message Failure { optional FailureType code = 1; // computer-readable definition of the error state optional string message = 2; // human-readable message of the error state } /** * Response: Device is waiting for HW button press. * @next ButtonAck * @next Cancel */ message ButtonRequest { optional ButtonRequestType code = 1; optional string data = 2; } /** * Request: Computer agrees to wait for HW button press * @prev ButtonRequest */ message ButtonAck { } /** * Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme * @next PinMatrixAck * @next Cancel */ message PinMatrixRequest { optional PinMatrixRequestType type = 1; } /** * Request: Computer responds with encoded PIN * @prev PinMatrixRequest */ message PinMatrixAck { required string pin = 1; // matrix encoded PIN entered by user } /** * Request: Abort last operation that required user interaction * @prev ButtonRequest * @prev PinMatrixRequest * @prev PassphraseRequest */ message Cancel { } /** * Response: Device awaits encryption passphrase * @next PassphraseAck * @next Cancel */ message PassphraseRequest { optional bool on_device = 1; // passphrase is being entered on the device } /** * Request: Send passphrase back * @prev PassphraseRequest * @next PassphraseStateRequest */ message PassphraseAck { optional string passphrase = 1; optional bytes state = 2; // expected device state } /** * @prev PassphraseAck * @next PassphraseStateAck */ message PassphraseStateRequest { optional bytes state = 1; // actual device state } /** * @prev PassphraseStateRequest */ message PassphraseStateAck { } /** * Request: Request a sample of random data generated by hardware RNG. May be used for testing. * @next ButtonRequest * @next Entropy * @next Failure */ message GetEntropy { required uint32 size = 1; // size of requested entropy } /** * Response: Reply with random data generated by internal RNG * @prev GetEntropy */ message Entropy { required bytes entropy = 1; // stream of random generated bytes } /** * Request: Ask device for public key corresponding to address_n path * @next PassphraseRequest * @next PublicKey * @next Failure */ message GetPublicKey { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional string ecdsa_curve_name = 2; // ECDSA curve name to use optional bool show_display = 3; // optionally show on display before sending the result optional string coin_name = 4 [default='Bitcoin']; } /** * Response: Contains public key derived from device private seed * @prev GetPublicKey */ message PublicKey { required HDNodeType node = 1; // BIP32 public node optional string xpub = 2; // serialized form of public node } /** * Request: Ask device for address corresponding to address_n path * @next PassphraseRequest * @next Address * @next Failure */ message GetAddress { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional string coin_name = 2 [default='Bitcoin']; optional bool show_display = 3 ; // optionally show on display before sending the result optional MultisigRedeemScriptType multisig = 4; // filled if we are showing a multisig address optional InputScriptType script_type = 5 [default=SPENDADDRESS]; // used to distinguish between various address formats (non-segwit, segwit, etc.) } /** * Request: Ask device for Ethereum address corresponding to address_n path * @next PassphraseRequest * @next EthereumAddress * @next Failure */ message EthereumGetAddress { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional bool show_display = 2; // optionally show on display before sending the result } /** * Response: Contains address derived from device private seed * @prev GetAddress */ message Address { required string address = 1; // Coin address in Base58 encoding } /** * Response: Contains an Ethereum address derived from device private seed * @prev EthereumGetAddress */ message EthereumAddress { required bytes address = 1; // Coin address as an Ethereum 160 bit hash } /** * Request: Request device to wipe all sensitive data and settings * @next ButtonRequest */ message WipeDevice { } /** * Request: Load seed and related internal settings from the computer * @next ButtonRequest * @next Success * @next Failure */ message LoadDevice { optional string mnemonic = 1; // seed encoded as BIP-39 mnemonic (12, 18 or 24 words) optional HDNodeType node = 2; // BIP-32 node optional string pin = 3; // set PIN protection optional bool passphrase_protection = 4; // enable master node encryption using passphrase optional string language = 5 [default='english']; // device language optional string label = 6; // device label optional bool skip_checksum = 7; // do not test mnemonic for valid BIP-39 checksum optional uint32 u2f_counter = 8; // U2F counter } /** * Request: Ask device to do initialization involving user interaction * @next EntropyRequest * @next Failure */ message ResetDevice { optional bool display_random = 1; // display entropy generated by the device before asking for additional entropy optional uint32 strength = 2 [default=256]; // strength of seed in bits optional bool passphrase_protection = 3; // enable master node encryption using passphrase optional bool pin_protection = 4; // enable PIN protection optional string language = 5 [default='english']; // device language optional string label = 6; // device label optional uint32 u2f_counter = 7; // U2F counter optional bool skip_backup = 8; // postpone seed backup to BackupDevice workflow } /** * Request: Perform backup of the device seed if not backed up using ResetDevice * @next ButtonRequest */ message BackupDevice { } /** * Response: Ask for additional entropy from host computer * @prev ResetDevice * @next EntropyAck */ message EntropyRequest { } /** * Request: Provide additional entropy for seed generation function * @prev EntropyRequest * @next ButtonRequest */ message EntropyAck { optional bytes entropy = 1; // 256 bits (32 bytes) of random data } /** * Request: Start recovery workflow asking user for specific words of mnemonic * Used to recovery device safely even on untrusted computer. * @next WordRequest */ message RecoveryDevice { optional uint32 word_count = 1; // number of words in BIP-39 mnemonic optional bool passphrase_protection = 2; // enable master node encryption using passphrase optional bool pin_protection = 3; // enable PIN protection optional string language = 4 [default='english']; // device language optional string label = 5; // device label optional bool enforce_wordlist = 6; // enforce BIP-39 wordlist during the process // 7 reserved for unused recovery method optional uint32 type = 8; // supported recovery type (see RecoveryType) optional uint32 u2f_counter = 9; // U2F counter optional bool dry_run = 10; // perform dry-run recovery workflow (for safe mnemonic validation) } /** * Response: Device is waiting for user to enter word of the mnemonic * Its position is shown only on device's internal display. * @prev RecoveryDevice * @prev WordAck */ message WordRequest { optional WordRequestType type = 1; } /** * Request: Computer replies with word from the mnemonic * @prev WordRequest * @next WordRequest * @next Success * @next Failure */ message WordAck { required string word = 1; // one word of mnemonic on asked position } ////////////////////////////// // Message signing messages // ////////////////////////////// /** * Request: Ask device to sign message * @next MessageSignature * @next Failure */ message SignMessage { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node required bytes message = 2; // message to be signed optional string coin_name = 3 [default='Bitcoin']; // coin to use for signing optional InputScriptType script_type = 4 [default=SPENDADDRESS]; // used to distinguish between various address formats (non-segwit, segwit, etc.) } /** * Request: Ask device to verify message * @next Success * @next Failure */ message VerifyMessage { optional string address = 1; // address to verify optional bytes signature = 2; // signature to verify optional bytes message = 3; // message to verify optional string coin_name = 4 [default='Bitcoin']; // coin to use for verifying } /** * Response: Signed message * @prev SignMessage */ message MessageSignature { optional string address = 1; // address used to sign the message optional bytes signature = 2; // signature of the message } /////////////////////////// // Encryption/decryption // /////////////////////////// /** * Request: Ask device to encrypt message * @next EncryptedMessage * @next Failure */ message EncryptMessage { optional bytes pubkey = 1; // public key optional bytes message = 2; // message to encrypt optional bool display_only = 3; // show just on display? (don't send back via wire) repeated uint32 address_n = 4; // BIP-32 path to derive the signing key from master node optional string coin_name = 5 [default='Bitcoin']; // coin to use for signing } /** * Response: Encrypted message * @prev EncryptMessage */ message EncryptedMessage { optional bytes nonce = 1; // nonce used during encryption optional bytes message = 2; // encrypted message optional bytes hmac = 3; // message hmac } /** * Request: Ask device to decrypt message * @next Success * @next Failure */ message DecryptMessage { repeated uint32 address_n = 1; // BIP-32 path to derive the decryption key from master node optional bytes nonce = 2; // nonce used during encryption optional bytes message = 3; // message to decrypt optional bytes hmac = 4; // message hmac } /** * Response: Decrypted message * @prev DecryptedMessage */ message DecryptedMessage { optional bytes message = 1; // decrypted message optional string address = 2; // address used to sign the message (if used) } /** * Request: Ask device to encrypt or decrypt value of given key * @next CipheredKeyValue * @next Failure */ message CipherKeyValue { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional string key = 2; // key component of key:value optional bytes value = 3; // value component of key:value optional bool encrypt = 4; // are we encrypting (True) or decrypting (False)? optional bool ask_on_encrypt = 5; // should we ask on encrypt operation? optional bool ask_on_decrypt = 6; // should we ask on decrypt operation? optional bytes iv = 7; // initialization vector (will be computed if not set) } /** * Response: Return ciphered/deciphered value * @prev CipherKeyValue */ message CipheredKeyValue { optional bytes value = 1; // ciphered/deciphered value } ////////////////////////////////// // Transaction signing messages // ////////////////////////////////// /** * Request: Estimated size of the transaction * This behaves exactly like SignTx, which means that it can ask using TxRequest * This call is non-blocking (except possible PassphraseRequest to unlock the seed) * @next TxSize * @next Failure */ message EstimateTxSize { required uint32 outputs_count = 1; // number of transaction outputs required uint32 inputs_count = 2; // number of transaction inputs optional string coin_name = 3 [default='Bitcoin']; // coin to use } /** * Response: Estimated size of the transaction * @prev EstimateTxSize */ message TxSize { optional uint32 tx_size = 1; // estimated size of transaction in bytes } /** * Request: Ask device to sign transaction * @next PassphraseRequest * @next PinMatrixRequest * @next TxRequest * @next Failure */ message SignTx { required uint32 outputs_count = 1; // number of transaction outputs required uint32 inputs_count = 2; // number of transaction inputs optional string coin_name = 3 [default='Bitcoin']; // coin to use optional uint32 version = 4 [default=1]; // transaction version optional uint32 lock_time = 5 [default=0]; // transaction lock_time optional uint32 decred_expiry = 6; } /** * Request: Simplified transaction signing * This method doesn't support streaming, so there are hardware limits in number of inputs and outputs. * In case of success, the result is returned using TxRequest message. * @next PassphraseRequest * @next PinMatrixRequest * @next TxRequest * @next Failure */ message SimpleSignTx { repeated TxInputType inputs = 1; // transaction inputs repeated TxOutputType outputs = 2; // transaction outputs repeated TransactionType transactions = 3; // transactions whose outputs are used to build current inputs optional string coin_name = 4 [default='Bitcoin']; // coin to use optional uint32 version = 5 [default=1]; // transaction version optional uint32 lock_time = 6 [default=0]; // transaction lock_time } /** * Response: Device asks for information for signing transaction or returns the last result * If request_index is set, device awaits TxAck message (with fields filled in according to request_type) * If signature_index is set, 'signature' contains signed input of signature_index's input * @prev SignTx * @prev SimpleSignTx * @prev TxAck */ message TxRequest { optional RequestType request_type = 1; // what should be filled in TxAck message? optional TxRequestDetailsType details = 2; // request for tx details optional TxRequestSerializedType serialized = 3; // serialized data and request for next } /** * Request: Reported transaction data * @prev TxRequest * @next TxRequest */ message TxAck { optional TransactionType tx = 1; } /** * Request: Ask device to sign transaction * All fields are optional from the protocol's point of view. Each field defaults to value `0` if missing. * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. * @next PassphraseRequest * @next PinMatrixRequest * @next EthereumTxRequest * @next Failure */ message EthereumSignTx { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional bytes nonce = 2; // <=256 bit unsigned big endian optional bytes gas_price = 3; // <=256 bit unsigned big endian (in wei) optional bytes gas_limit = 4; // <=256 bit unsigned big endian optional bytes to = 5; // 160 bit address hash optional bytes value = 6; // <=256 bit unsigned big endian (in wei) optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes) optional uint32 data_length = 8; // Length of transaction payload optional uint32 chain_id = 9; // Chain Id for EIP 155 optional uint32 tx_type = 10; // (only for Wanchain) } /** * Response: Device asks for more data from transaction payload, or returns the signature. * If data_length is set, device awaits that many more bytes of payload. * Otherwise, the signature_* fields contain the computed transaction signature. All three fields will be present. * @prev EthereumSignTx * @next EthereumTxAck */ message EthereumTxRequest { optional uint32 data_length = 1; // Number of bytes being requested (<= 1024) optional uint32 signature_v = 2; // Computed signature (recovery parameter, limited to 27 or 28) optional bytes signature_r = 3; // Computed signature R component (256 bit) optional bytes signature_s = 4; // Computed signature S component (256 bit) } /** * Request: Transaction payload data. * @prev EthereumTxRequest * @next EthereumTxRequest */ message EthereumTxAck { optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes) } //////////////////////////////////////// // Ethereum: Message signing messages // //////////////////////////////////////// /** * Request: Ask device to sign message * @next EthereumMessageSignature * @next Failure */ message EthereumSignMessage { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node required bytes message = 2; // message to be signed } /** * Request: Ask device to verify message * @next Success * @next Failure */ message EthereumVerifyMessage { optional bytes address = 1; // address to verify optional bytes signature = 2; // signature to verify optional bytes message = 3; // message to verify } /** * Response: Signed message * @prev EthereumSignMessage */ message EthereumMessageSignature { optional bytes address = 1; // address used to sign the message optional bytes signature = 2; // signature of the message } /////////////////////// // Identity messages // /////////////////////// /** * Request: Ask device to sign identity * @next SignedIdentity * @next Failure */ message SignIdentity { optional IdentityType identity = 1; // identity optional bytes challenge_hidden = 2; // non-visible challenge optional string challenge_visual = 3; // challenge shown on display (e.g. date+time) optional string ecdsa_curve_name = 4; // ECDSA curve name to use } /** * Response: Device provides signed identity * @prev SignIdentity */ message SignedIdentity { optional string address = 1; // identity address optional bytes public_key = 2; // identity public key optional bytes signature = 3; // signature of the identity data } /////////////////// // ECDH messages // /////////////////// /** * Request: Ask device to generate ECDH session key * @next ECDHSessionKey * @next Failure */ message GetECDHSessionKey { optional IdentityType identity = 1; // identity optional bytes peer_public_key = 2; // peer's public key optional string ecdsa_curve_name = 3; // ECDSA curve name to use } /** * Response: Device provides ECDH session key * @prev GetECDHSessionKey */ message ECDHSessionKey { optional bytes session_key = 1; // ECDH session key } /////////////////// // U2F messages // /////////////////// /** * Request: Set U2F counter * @next Success */ message SetU2FCounter { optional uint32 u2f_counter = 1; // counter } ///////////////////////// // Bootloader messages // ///////////////////////// /** * Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload) * @next Success * @next FirmwareRequest * @next Failure */ message FirmwareErase { optional uint32 length = 1; // length of new firmware } /** * Response: Ask for firmware chunk * @next FirmwareUpload */ message FirmwareRequest { optional uint32 offset = 1; // offset of requested firmware chunk optional uint32 length = 2; // length of requested firmware chunk } /** * Request: Send firmware in binary form to the device * @next Success * @next Failure */ message FirmwareUpload { required bytes payload = 1; // firmware to be loaded into device optional bytes hash = 2; // hash of the payload } /** * Request: Perform a device self-test * @next Success * @next Failure */ message SelfTest { optional bytes payload = 1; // payload to be used in self-test } ////////////////// // NEM messages // ////////////////// /** * Request: Ask device for NEM address corresponding to address_n path * @next PassphraseRequest * @next NEMAddress * @next Failure */ message NEMGetAddress { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional uint32 network = 2; // Network ID (0x68 = Mainnet, 0x98 = Testnet, 0x60 = Mijin) optional bool show_display = 3; // Optionally show on display before sending the result } /** * Response: Contains NEM address derived from device private seed * @prev NEMGetAddress */ message NEMAddress { required string address = 1; // NEM address in Base32 encoding } /** * Request: Ask device to sign transaction * @next NEMSignedTx * @next Failure */ message NEMSignTx { optional NEMTransactionCommon transaction = 1; // Common part of transaction optional NEMTransactionCommon multisig = 2; // Common part of inner transaction for multisig transactions optional NEMTransfer transfer = 3; // Transfer transaction part optional bool cosigning = 4; // Whether cosigning or initiating the multisig transaction optional NEMProvisionNamespace provision_namespace = 5; // Provision namespace part optional NEMMosaicCreation mosaic_creation = 6; // Mosaic definition creation part optional NEMMosaicSupplyChange supply_change = 7; // Mosaic supply change part optional NEMAggregateModification aggregate_modification = 8; // Aggregate modification part optional NEMImportanceTransfer importance_transfer = 9; // Importance transfer part } /** * Response: Contains NEM transaction data and signature * @prev NEMSignTx */ message NEMSignedTx { optional bytes data = 1; // Transaction data optional bytes signature = 2; // Signature for the transaction } /** * Request: Ask device to decrypt NEM transaction payload * @next NEMDecryptedMessage * @next Failure */ message NEMDecryptMessage { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional uint32 network = 2; // Network ID (0x68 = Mainnet, 0x98 = Testnet, 0x60 = Mijin) optional bytes public_key = 3; // Public key of the other party optional bytes payload = 4; // Actual message data (encrypted) } /** * Response: Contains decrypted NEM transaction payload * @prev NEMDecryptMessage */ message NEMDecryptedMessage { optional bytes payload = 1; // Actual message data (unencrypted) } /////////////////// // CoSi messages // /////////////////// /** * Request: Ask device to commit to CoSi signing * @next CosiCommitment * @next Failure */ message CosiCommit { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional bytes data = 2; // Data to be signed } /** * Response: Contains a CoSi commitment * @prev CosiCommit */ message CosiCommitment { optional bytes commitment = 1; // Commitment optional bytes pubkey = 2; // Public key } /** * Request: Ask device to sign using CoSi * @next CosiSignature * @next Failure */ message CosiSign { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional bytes data = 2; // Data to be signed optional bytes global_commitment = 3; // Aggregated commitment optional bytes global_pubkey = 4; // Aggregated public key } /** * Response: Contains a CoSi signature * @prev CosiSign */ message CosiSignature { optional bytes signature = 1; // Signature } ////////////////////// // Stellar messages // ////////////////////// /** * Request: Public key at the specified index * @next StellarPublicKey */ message StellarGetPublicKey { repeated uint32 address_n = 1; // BIP-32 path. For compatibility with other wallets, must be m/44'/148'/index' } /** * Response: Public key for the given index * @prev StellarGetPublicKey */ message StellarPublicKey { optional bytes public_key = 1; // Raw bytes of the public key (no version or checksum) } /** * Request: ask device to sign Stellar transaction * @next StellarTxOpRequest */ message StellarSignTx { optional uint32 protocol_version = 1; // version of the protofbuf messaging protocol the client is using repeated uint32 address_n = 2; // BIP-32 path. For compatibility with other wallets, must be m/44'/148'/index' optional string network_passphrase = 3; // passphrase for signing messages on the destination network optional bytes source_account = 4; // 32-byte source optional uint32 fee = 5; // Fee (in stroops) for the transaction optional uint64 sequence_number = 6; // transaction sequence number optional uint32 timebounds_start = 8; // unix timestamp (client must truncate this to 32 bytes) optional uint32 timebounds_end = 9; // unix timestamp (client must truncate this to 32 bytes) optional uint32 memo_type = 10; // 0 = none, 1 = text, 2 = id, 3 = hash, 4 = return optional string memo_text = 11; // up to 28 characters (4 bytes are for length) optional uint64 memo_id = 12; // 8-byte uint64 optional bytes memo_hash = 13; // 32 bytes representing a hash optional uint32 num_operations = 14; // number of operations in this transaction } /** * Response: device is ready for client to send the next operation * @prev StellarSignTx * @next StellarPaymentOp * @next StellarCreateAccountOp * @next StellarPathPaymentOp * @next StellarManageOfferOp * @next StellarCreatePassiveOfferOp * @next StellarSetOptionsOp * @next StellarChangeTrustOp * @next StellarAllowTrustOp * @next StellarAccountMergeOp * @next StellarManageDataOp * @next StellarBumpSequenceOp */ message StellarTxOpRequest { } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarPaymentOp { optional bytes source_account = 1; // (optional) 32-byte source account optional bytes destination_account = 2; // 32-byte destination account optional StellarAssetType asset = 3; // asset involved in the operation optional sint64 amount = 4; // amount of the given asset to pay } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarCreateAccountOp { optional bytes source_account = 1; // (optional) 32-byte source account optional bytes new_account = 2; // 32-byte account ID to create optional sint64 starting_balance = 3; // initial starting balance for the new account } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarPathPaymentOp { optional bytes source_account = 1; // (optional) 32-byte source account optional StellarAssetType send_asset = 2; optional sint64 send_max = 3; optional bytes destination_account = 4; optional StellarAssetType destination_asset = 5; optional sint64 destination_amount = 6; repeated StellarAssetType paths = 7; } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarManageOfferOp { optional bytes source_account = 1; // (optional) 32-byte source account optional StellarAssetType selling_asset = 2; optional StellarAssetType buying_asset = 3; optional sint64 amount = 4; optional uint32 price_n = 5; // Price numerator optional uint32 price_d = 6; // Price denominator optional uint64 offer_id = 7; // Offer ID for updating an existing offer } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarCreatePassiveOfferOp { optional bytes source_account = 1; // (optional) 32-byte source account optional StellarAssetType selling_asset = 2; optional StellarAssetType buying_asset = 3; optional sint64 amount = 4; optional uint32 price_n = 5; // Price numerator optional uint32 price_d = 6; // Price denominator } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarSetOptionsOp { optional bytes source_account = 1; // (optional) 32-byte source account optional bytes inflation_destination_account = 2; // (optional) 32-byte inflation destination optional uint32 clear_flags = 3; optional uint32 set_flags = 4; optional uint32 master_weight = 5; optional uint32 low_threshold = 6; optional uint32 medium_threshold = 7; optional uint32 high_threshold = 8; optional string home_domain = 9; optional uint32 signer_type = 10; optional bytes signer_key = 11; optional uint32 signer_weight = 12; } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarChangeTrustOp { optional bytes source_account = 1; // (optional) 32-byte source account optional StellarAssetType asset = 2; optional uint64 limit = 3; } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarAllowTrustOp { optional bytes source_account = 1; // (optional) 32-byte source account optional bytes trusted_account = 2; // The account being allowed to hold the asset optional uint32 asset_type = 3; // 1 = 4-character, 2 = 12-character optional string asset_code = 4; // human-readable asset code optional uint32 is_authorized = 5; } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarAccountMergeOp { optional bytes source_account = 1; // (optional) 32-byte source account optional bytes destination_account = 2; // 32-byte destination account } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarManageDataOp { optional bytes source_account = 1; // (optional) 32-byte source account optional string key = 2; optional bytes value = 3; // 64 bytes of arbitrary data } /** * Request: ask device to confirm this operation type * @prev StellarTxOpRequest * @next StellarTxOpRequest * @next StellarSignedTx */ message StellarBumpSequenceOp { optional bytes source_account = 1; // (optional) 32-byte source account optional uint64 bump_to = 2; // new sequence number } /** * Response: signature for transaction * @prev StellarPaymentOp * @prev StellarCreateAccountOp * @prev StellarPathPaymentOp * @prev StellarManageOfferOp * @prev StellarCreatePassiveOfferOp * @prev StellarSetOptionsOp * @prev StellarChangeTrustOp * @prev StellarAllowTrustOp * @prev StellarAccountMergeOp * @prev StellarManageDataOp * @prev StellarBumpSequenceOp */ message StellarSignedTx { optional bytes public_key = 1; // public key for the private key used to sign data optional bytes signature = 2; // signature suitable for sending to the Stellar network } //////////////////// // Lisk messages // ////////////////// /** * Request: Ask device for Lisk public key corresponding to address_n path * @next LiskPublicKey */ message LiskGetPublicKey { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional bool show_display = 2; // Optionally show on display before sending the result } /** * Response: Contains Lisk public key derived from device private seed * @prev LiskGetPublicKey */ message LiskPublicKey { optional bytes public_key = 1; // Lisk public key } /** * Request: Ask device for Lisk address corresponding to address_n path * @next PassphraseRequest * @next LiskAddress * @next Failure */ message LiskGetAddress { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional bool show_display = 2; // Optionally show on display before sending the result } /** * Response: Contains Lisk address derived from device private seed * @prev LiskGetAddress */ message LiskAddress { optional string address = 1; // Lisk address } /** * Request: Ask device to sign Lisk transaction * @next LiskSignedTx */ message LiskSignTx { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node optional LiskTransactionCommon transaction = 2; // Lisk transaction structure } /** * Response: Contains Lisk transaction signature * @prev LiskSignTx */ message LiskSignedTx { optional bytes signature = 1; } ///////////////////////////////////////////////////////////// // Debug messages (only available if DebugLink is enabled) // ///////////////////////////////////////////////////////////// /** * Request: "Press" the button on the device * @next Success */ message DebugLinkDecision { optional bool yes_no = 1; // true for "Confirm", false for "Cancel" optional bool up_down = 2; // true for scroll up, false for scroll down optional string input = 3; // keyboard input } /** * Request: Computer asks for device state * @next DebugLinkState */ message DebugLinkGetState { } /** * Response: Device current state * @prev DebugLinkGetState */ message DebugLinkState { optional bytes layout = 1; // raw buffer of display optional string pin = 2; // current PIN, blank if PIN is not set/enabled optional string matrix = 3; // current PIN matrix optional string mnemonic = 4; // current BIP-39 mnemonic optional HDNodeType node = 5; // current BIP-32 node optional bool passphrase_protection = 6; // is node/mnemonic encrypted using passphrase? optional string reset_word = 7; // word on device display during ResetDevice workflow optional bytes reset_entropy = 8; // current entropy during ResetDevice workflow optional string recovery_fake_word = 9; // (fake) word on display during RecoveryDevice workflow optional uint32 recovery_word_pos = 10; // index of mnemonic word the device is expecting during RecoveryDevice workflow optional uint32 reset_word_pos = 11; // index of mnemonic word the device is expecting during ResetDevice workflow } /** * Request: Ask device to restart */ message DebugLinkStop { } /** * Response: Device wants host to log event */ message DebugLinkLog { optional uint32 level = 1; optional string bucket = 2; optional string text = 3; } /** * Request: Read memory from device * @next DebugLinkMemory */ message DebugLinkMemoryRead { optional uint32 address = 1; optional uint32 length = 2; } /** * Response: Device sends memory back * @prev DebugLinkMemoryRead */ message DebugLinkMemory { optional bytes memory = 1; } /** * Request: Write memory to device. * WARNING: Writing to the wrong location can irreparably break the device. */ message DebugLinkMemoryWrite { optional uint32 address = 1; optional bytes memory = 2; optional bool flash = 3; } /** * Request: Erase block of flash on device * WARNING: Writing to the wrong location can irreparably break the device. */ message DebugLinkFlashErase { optional uint32 sector = 1; }