syntax = "proto2";

/**
 * Messages for SafeWISE communication
 */

// Sugar for easier handling in Java
option java_package = "io.coinwise.safewise.lib.protobuf";
option java_outer_classname = "SafeWISEMessage";

import "types.proto";

/**
 * Mapping between SafeWISE 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_LiskSignMessage = 118 [(wire_in) = true];
	MessageType_LiskMessageSignature = 119 [(wire_out) = true];
	MessageType_LiskVerifyMessage = 120 [(wire_in) = 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_StellarGetAddress = 207 [(wire_in) = true];
	MessageType_StellarAddress = 208 [(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. "safewise.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 expiry = 6;				// only for Decred and Zcash
	optional bool overwintered = 7;				// only for Zcash
}

/**
 * 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
	optional uint32 expiry = 7;				// only for Decred and Zcash
	optional bool overwintered = 8;				// only for Zcash
}

/**
 * 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'
	optional bool show_display = 2;			// optionally show on display before sending the result
}

/**
 * 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: Address at the specified index
 * @next StellarAddress
 */
message StellarGetAddress {
	repeated uint32 address_n = 1;			// BIP-32 path. For compatibility with other wallets, must be m/44'/148'/index'
	optional bool show_display = 2;			// optionally show on display before sending the result
}

/**
 * Response: Address for the given index
 * @prev StellarGetAddress
 */
message StellarAddress {
	optional string address = 1;	// Address in Stellar format (base32 of a pubkey with 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;
}

/**
* Request: Ask device to sign message
* @next LiskMessageSignature
* @next Failure
*/
message LiskSignMessage {
	repeated uint32 address_n = 1;
	optional bytes message = 2;
}

/**
* Response: Signed message
* @prev LiskSignMessage
*/
message LiskMessageSignature {
	optional bytes public_key = 1;
	optional bytes signature = 2;
}

/**
* Request: Ask device to verify message
* @next Success
* @next Failure
*/
message LiskVerifyMessage {
	optional bytes public_key = 1;
	optional bytes signature = 2;
	optional bytes message = 3;
}

/////////////////////////////////////////////////////////////
// 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;
}
