aboutsummaryrefslogtreecommitdiffstats
path: root/accounts
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2017-08-01 23:45:17 +0800
committerPéter Szilágyi <peterke@gmail.com>2017-08-09 16:30:17 +0800
commitdb568a61e2a98880ab308bf2224aa34073dc7f39 (patch)
tree97da46661ad3002b6ff9f6dca07e3105da5a9c5a /accounts
parent17ce0a37de5a2712a8bf9d58df705e718b3b2cd6 (diff)
downloaddexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar.gz
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar.bz2
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar.lz
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar.xz
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.tar.zst
dexon-db568a61e2a98880ab308bf2224aa34073dc7f39.zip
accounts, console, internal: support trezor hardware wallet
Diffstat (limited to 'accounts')
-rw-r--r--accounts/accounts.go21
-rw-r--r--accounts/hd.go9
-rw-r--r--accounts/keystore/keystore.go6
-rw-r--r--accounts/keystore/keystore_test.go8
-rw-r--r--accounts/manager.go5
-rw-r--r--accounts/usbwallet/internal/trezor/messages.pb.go3081
-rw-r--r--accounts/usbwallet/internal/trezor/messages.proto903
-rw-r--r--accounts/usbwallet/internal/trezor/trezor.go46
-rw-r--r--accounts/usbwallet/internal/trezor/types.pb.go1333
-rw-r--r--accounts/usbwallet/internal/trezor/types.proto276
-rw-r--r--accounts/usbwallet/ledger_hub.go10
-rw-r--r--accounts/usbwallet/ledger_wallet.go13
-rw-r--r--accounts/usbwallet/trezor_hub.go210
-rw-r--r--accounts/usbwallet/trezor_wallet.go761
-rw-r--r--accounts/usbwallet/usbwallet.go9
15 files changed, 6662 insertions, 29 deletions
diff --git a/accounts/accounts.go b/accounts/accounts.go
index 640de5220..5872bb4a3 100644
--- a/accounts/accounts.go
+++ b/accounts/accounts.go
@@ -147,9 +147,26 @@ type Backend interface {
Subscribe(sink chan<- WalletEvent) event.Subscription
}
+// WalletEventType represents the different event types that can be fired by
+// the wallet subscription subsystem.
+type WalletEventType int
+
+const (
+ // WalletArrived is fired when a new wallet is detected either via USB or via
+ // a filesystem event in the keystore.
+ WalletArrived WalletEventType = iota
+
+ // WalletOpened is fired when a wallet is successfully opened with the purpose
+ // of starting any background processes such as automatic key derivation.
+ WalletOpened
+
+ // WalletDropped
+ WalletDropped
+)
+
// WalletEvent is an event fired by an account backend when a wallet arrival or
// departure is detected.
type WalletEvent struct {
- Wallet Wallet // Wallet instance arrived or departed
- Arrive bool // Whether the wallet was added or removed
+ Wallet Wallet // Wallet instance arrived or departed
+ Kind WalletEventType // Event type that happened in the system
}
diff --git a/accounts/hd.go b/accounts/hd.go
index e8bc191af..277f688e4 100644
--- a/accounts/hd.go
+++ b/accounts/hd.go
@@ -27,12 +27,17 @@ import (
// DefaultRootDerivationPath is the root path to which custom derivation endpoints
// are appended. As such, the first account will be at m/44'/60'/0'/0, the second
// at m/44'/60'/0'/1, etc.
-var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0}
+var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
// DefaultBaseDerivationPath is the base path from which custom derivation endpoints
// are incremented. As such, the first account will be at m/44'/60'/0'/0, the second
// at m/44'/60'/0'/1, etc.
-var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
+var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}
+
+// DefaultLedgerBaseDerivationPath is the base path from which custom derivation endpoints
+// are incremented. As such, the first account will be at m/44'/60'/0'/0, the second
+// at m/44'/60'/0'/1, etc.
+var DefaultLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
// DerivationPath represents the computer friendly version of a hierarchical
// deterministic wallet account derivaion path.
diff --git a/accounts/keystore/keystore.go b/accounts/keystore/keystore.go
index 9df7f2dd9..80ccd3741 100644
--- a/accounts/keystore/keystore.go
+++ b/accounts/keystore/keystore.go
@@ -143,14 +143,14 @@ func (ks *KeyStore) refreshWallets() {
for _, account := range accs {
// Drop wallets while they were in front of the next account
for len(ks.wallets) > 0 && ks.wallets[0].URL().Cmp(account.URL) < 0 {
- events = append(events, accounts.WalletEvent{Wallet: ks.wallets[0], Arrive: false})
+ events = append(events, accounts.WalletEvent{Wallet: ks.wallets[0], Kind: accounts.WalletDropped})
ks.wallets = ks.wallets[1:]
}
// If there are no more wallets or the account is before the next, wrap new wallet
if len(ks.wallets) == 0 || ks.wallets[0].URL().Cmp(account.URL) > 0 {
wallet := &keystoreWallet{account: account, keystore: ks}
- events = append(events, accounts.WalletEvent{Wallet: wallet, Arrive: true})
+ events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
wallets = append(wallets, wallet)
continue
}
@@ -163,7 +163,7 @@ func (ks *KeyStore) refreshWallets() {
}
// Drop any leftover wallets and set the new batch
for _, wallet := range ks.wallets {
- events = append(events, accounts.WalletEvent{Wallet: wallet, Arrive: false})
+ events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped})
}
ks.wallets = wallets
ks.mu.Unlock()
diff --git a/accounts/keystore/keystore_test.go b/accounts/keystore/keystore_test.go
index 5d89a4dbb..132b74439 100644
--- a/accounts/keystore/keystore_test.go
+++ b/accounts/keystore/keystore_test.go
@@ -296,8 +296,8 @@ func TestWalletNotifications(t *testing.T) {
}
select {
case event := <-updates:
- if !event.Arrive {
- t.Errorf("departure event on account creation")
+ if event.Kind != accounts.WalletArrived {
+ t.Errorf("non-arrival event on account creation")
}
if event.Wallet.Accounts()[0] != account {
t.Errorf("account mismatch on created wallet: have %v, want %v", event.Wallet.Accounts()[0], account)
@@ -319,8 +319,8 @@ func TestWalletNotifications(t *testing.T) {
}
select {
case event := <-updates:
- if event.Arrive {
- t.Errorf("arrival event on account deletion")
+ if event.Kind != accounts.WalletDropped {
+ t.Errorf("non-drop event on account deletion")
}
if event.Wallet.Accounts()[0] != account {
t.Errorf("account mismatch on deleted wallet: have %v, want %v", event.Wallet.Accounts()[0], account)
diff --git a/accounts/manager.go b/accounts/manager.go
index 12a5bfcd9..78ddb1368 100644
--- a/accounts/manager.go
+++ b/accounts/manager.go
@@ -96,9 +96,10 @@ func (am *Manager) update() {
case event := <-am.updates:
// Wallet event arrived, update local cache
am.lock.Lock()
- if event.Arrive {
+ switch event.Kind {
+ case WalletArrived:
am.wallets = merge(am.wallets, event.Wallet)
- } else {
+ case WalletDropped:
am.wallets = drop(am.wallets, event.Wallet)
}
am.lock.Unlock()
diff --git a/accounts/usbwallet/internal/trezor/messages.pb.go b/accounts/usbwallet/internal/trezor/messages.pb.go
new file mode 100644
index 000000000..15bb6fb73
--- /dev/null
+++ b/accounts/usbwallet/internal/trezor/messages.pb.go
@@ -0,0 +1,3081 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: messages.proto
+
+package trezor
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// *
+// Mapping between Trezor wire identifier (uint) and a protobuf message
+type MessageType int32
+
+const (
+ MessageType_MessageType_Initialize MessageType = 0
+ MessageType_MessageType_Ping MessageType = 1
+ MessageType_MessageType_Success MessageType = 2
+ MessageType_MessageType_Failure MessageType = 3
+ MessageType_MessageType_ChangePin MessageType = 4
+ MessageType_MessageType_WipeDevice MessageType = 5
+ MessageType_MessageType_FirmwareErase MessageType = 6
+ MessageType_MessageType_FirmwareUpload MessageType = 7
+ MessageType_MessageType_FirmwareRequest MessageType = 8
+ MessageType_MessageType_GetEntropy MessageType = 9
+ MessageType_MessageType_Entropy MessageType = 10
+ MessageType_MessageType_GetPublicKey MessageType = 11
+ MessageType_MessageType_PublicKey MessageType = 12
+ MessageType_MessageType_LoadDevice MessageType = 13
+ MessageType_MessageType_ResetDevice MessageType = 14
+ MessageType_MessageType_SignTx MessageType = 15
+ MessageType_MessageType_SimpleSignTx MessageType = 16
+ MessageType_MessageType_Features MessageType = 17
+ MessageType_MessageType_PinMatrixRequest MessageType = 18
+ MessageType_MessageType_PinMatrixAck MessageType = 19
+ MessageType_MessageType_Cancel MessageType = 20
+ MessageType_MessageType_TxRequest MessageType = 21
+ MessageType_MessageType_TxAck MessageType = 22
+ MessageType_MessageType_CipherKeyValue MessageType = 23
+ MessageType_MessageType_ClearSession MessageType = 24
+ MessageType_MessageType_ApplySettings MessageType = 25
+ MessageType_MessageType_ButtonRequest MessageType = 26
+ MessageType_MessageType_ButtonAck MessageType = 27
+ MessageType_MessageType_ApplyFlags MessageType = 28
+ MessageType_MessageType_GetAddress MessageType = 29
+ MessageType_MessageType_Address MessageType = 30
+ MessageType_MessageType_SelfTest MessageType = 32
+ MessageType_MessageType_BackupDevice MessageType = 34
+ MessageType_MessageType_EntropyRequest MessageType = 35
+ MessageType_MessageType_EntropyAck MessageType = 36
+ MessageType_MessageType_SignMessage MessageType = 38
+ MessageType_MessageType_VerifyMessage MessageType = 39
+ MessageType_MessageType_MessageSignature MessageType = 40
+ MessageType_MessageType_PassphraseRequest MessageType = 41
+ MessageType_MessageType_PassphraseAck MessageType = 42
+ MessageType_MessageType_EstimateTxSize MessageType = 43
+ MessageType_MessageType_TxSize MessageType = 44
+ MessageType_MessageType_RecoveryDevice MessageType = 45
+ MessageType_MessageType_WordRequest MessageType = 46
+ MessageType_MessageType_WordAck MessageType = 47
+ MessageType_MessageType_CipheredKeyValue MessageType = 48
+ MessageType_MessageType_EncryptMessage MessageType = 49
+ MessageType_MessageType_EncryptedMessage MessageType = 50
+ MessageType_MessageType_DecryptMessage MessageType = 51
+ MessageType_MessageType_DecryptedMessage MessageType = 52
+ MessageType_MessageType_SignIdentity MessageType = 53
+ MessageType_MessageType_SignedIdentity MessageType = 54
+ MessageType_MessageType_GetFeatures MessageType = 55
+ MessageType_MessageType_EthereumGetAddress MessageType = 56
+ MessageType_MessageType_EthereumAddress MessageType = 57
+ MessageType_MessageType_EthereumSignTx MessageType = 58
+ MessageType_MessageType_EthereumTxRequest MessageType = 59
+ MessageType_MessageType_EthereumTxAck MessageType = 60
+ MessageType_MessageType_GetECDHSessionKey MessageType = 61
+ MessageType_MessageType_ECDHSessionKey MessageType = 62
+ MessageType_MessageType_SetU2FCounter MessageType = 63
+ MessageType_MessageType_EthereumSignMessage MessageType = 64
+ MessageType_MessageType_EthereumVerifyMessage MessageType = 65
+ MessageType_MessageType_EthereumMessageSignature MessageType = 66
+ MessageType_MessageType_DebugLinkDecision MessageType = 100
+ MessageType_MessageType_DebugLinkGetState MessageType = 101
+ MessageType_MessageType_DebugLinkState MessageType = 102
+ MessageType_MessageType_DebugLinkStop MessageType = 103
+ MessageType_MessageType_DebugLinkLog MessageType = 104
+ MessageType_MessageType_DebugLinkMemoryRead MessageType = 110
+ MessageType_MessageType_DebugLinkMemory MessageType = 111
+ MessageType_MessageType_DebugLinkMemoryWrite MessageType = 112
+ MessageType_MessageType_DebugLinkFlashErase MessageType = 113
+)
+
+var MessageType_name = map[int32]string{
+ 0: "MessageType_Initialize",
+ 1: "MessageType_Ping",
+ 2: "MessageType_Success",
+ 3: "MessageType_Failure",
+ 4: "MessageType_ChangePin",
+ 5: "MessageType_WipeDevice",
+ 6: "MessageType_FirmwareErase",
+ 7: "MessageType_FirmwareUpload",
+ 8: "MessageType_FirmwareRequest",
+ 9: "MessageType_GetEntropy",
+ 10: "MessageType_Entropy",
+ 11: "MessageType_GetPublicKey",
+ 12: "MessageType_PublicKey",
+ 13: "MessageType_LoadDevice",
+ 14: "MessageType_ResetDevice",
+ 15: "MessageType_SignTx",
+ 16: "MessageType_SimpleSignTx",
+ 17: "MessageType_Features",
+ 18: "MessageType_PinMatrixRequest",
+ 19: "MessageType_PinMatrixAck",
+ 20: "MessageType_Cancel",
+ 21: "MessageType_TxRequest",
+ 22: "MessageType_TxAck",
+ 23: "MessageType_CipherKeyValue",
+ 24: "MessageType_ClearSession",
+ 25: "MessageType_ApplySettings",
+ 26: "MessageType_ButtonRequest",
+ 27: "MessageType_ButtonAck",
+ 28: "MessageType_ApplyFlags",
+ 29: "MessageType_GetAddress",
+ 30: "MessageType_Address",
+ 32: "MessageType_SelfTest",
+ 34: "MessageType_BackupDevice",
+ 35: "MessageType_EntropyRequest",
+ 36: "MessageType_EntropyAck",
+ 38: "MessageType_SignMessage",
+ 39: "MessageType_VerifyMessage",
+ 40: "MessageType_MessageSignature",
+ 41: "MessageType_PassphraseRequest",
+ 42: "MessageType_PassphraseAck",
+ 43: "MessageType_EstimateTxSize",
+ 44: "MessageType_TxSize",
+ 45: "MessageType_RecoveryDevice",
+ 46: "MessageType_WordRequest",
+ 47: "MessageType_WordAck",
+ 48: "MessageType_CipheredKeyValue",
+ 49: "MessageType_EncryptMessage",
+ 50: "MessageType_EncryptedMessage",
+ 51: "MessageType_DecryptMessage",
+ 52: "MessageType_DecryptedMessage",
+ 53: "MessageType_SignIdentity",
+ 54: "MessageType_SignedIdentity",
+ 55: "MessageType_GetFeatures",
+ 56: "MessageType_EthereumGetAddress",
+ 57: "MessageType_EthereumAddress",
+ 58: "MessageType_EthereumSignTx",
+ 59: "MessageType_EthereumTxRequest",
+ 60: "MessageType_EthereumTxAck",
+ 61: "MessageType_GetECDHSessionKey",
+ 62: "MessageType_ECDHSessionKey",
+ 63: "MessageType_SetU2FCounter",
+ 64: "MessageType_EthereumSignMessage",
+ 65: "MessageType_EthereumVerifyMessage",
+ 66: "MessageType_EthereumMessageSignature",
+ 100: "MessageType_DebugLinkDecision",
+ 101: "MessageType_DebugLinkGetState",
+ 102: "MessageType_DebugLinkState",
+ 103: "MessageType_DebugLinkStop",
+ 104: "MessageType_DebugLinkLog",
+ 110: "MessageType_DebugLinkMemoryRead",
+ 111: "MessageType_DebugLinkMemory",
+ 112: "MessageType_DebugLinkMemoryWrite",
+ 113: "MessageType_DebugLinkFlashErase",
+}
+var MessageType_value = map[string]int32{
+ "MessageType_Initialize": 0,
+ "MessageType_Ping": 1,
+ "MessageType_Success": 2,
+ "MessageType_Failure": 3,
+ "MessageType_ChangePin": 4,
+ "MessageType_WipeDevice": 5,
+ "MessageType_FirmwareErase": 6,
+ "MessageType_FirmwareUpload": 7,
+ "MessageType_FirmwareRequest": 8,
+ "MessageType_GetEntropy": 9,
+ "MessageType_Entropy": 10,
+ "MessageType_GetPublicKey": 11,
+ "MessageType_PublicKey": 12,
+ "MessageType_LoadDevice": 13,
+ "MessageType_ResetDevice": 14,
+ "MessageType_SignTx": 15,
+ "MessageType_SimpleSignTx": 16,
+ "MessageType_Features": 17,
+ "MessageType_PinMatrixRequest": 18,
+ "MessageType_PinMatrixAck": 19,
+ "MessageType_Cancel": 20,
+ "MessageType_TxRequest": 21,
+ "MessageType_TxAck": 22,
+ "MessageType_CipherKeyValue": 23,
+ "MessageType_ClearSession": 24,
+ "MessageType_ApplySettings": 25,
+ "MessageType_ButtonRequest": 26,
+ "MessageType_ButtonAck": 27,
+ "MessageType_ApplyFlags": 28,
+ "MessageType_GetAddress": 29,
+ "MessageType_Address": 30,
+ "MessageType_SelfTest": 32,
+ "MessageType_BackupDevice": 34,
+ "MessageType_EntropyRequest": 35,
+ "MessageType_EntropyAck": 36,
+ "MessageType_SignMessage": 38,
+ "MessageType_VerifyMessage": 39,
+ "MessageType_MessageSignature": 40,
+ "MessageType_PassphraseRequest": 41,
+ "MessageType_PassphraseAck": 42,
+ "MessageType_EstimateTxSize": 43,
+ "MessageType_TxSize": 44,
+ "MessageType_RecoveryDevice": 45,
+ "MessageType_WordRequest": 46,
+ "MessageType_WordAck": 47,
+ "MessageType_CipheredKeyValue": 48,
+ "MessageType_EncryptMessage": 49,
+ "MessageType_EncryptedMessage": 50,
+ "MessageType_DecryptMessage": 51,
+ "MessageType_DecryptedMessage": 52,
+ "MessageType_SignIdentity": 53,
+ "MessageType_SignedIdentity": 54,
+ "MessageType_GetFeatures": 55,
+ "MessageType_EthereumGetAddress": 56,
+ "MessageType_EthereumAddress": 57,
+ "MessageType_EthereumSignTx": 58,
+ "MessageType_EthereumTxRequest": 59,
+ "MessageType_EthereumTxAck": 60,
+ "MessageType_GetECDHSessionKey": 61,
+ "MessageType_ECDHSessionKey": 62,
+ "MessageType_SetU2FCounter": 63,
+ "MessageType_EthereumSignMessage": 64,
+ "MessageType_EthereumVerifyMessage": 65,
+ "MessageType_EthereumMessageSignature": 66,
+ "MessageType_DebugLinkDecision": 100,
+ "MessageType_DebugLinkGetState": 101,
+ "MessageType_DebugLinkState": 102,
+ "MessageType_DebugLinkStop": 103,
+ "MessageType_DebugLinkLog": 104,
+ "MessageType_DebugLinkMemoryRead": 110,
+ "MessageType_DebugLinkMemory": 111,
+ "MessageType_DebugLinkMemoryWrite": 112,
+ "MessageType_DebugLinkFlashErase": 113,
+}
+
+func (x MessageType) Enum() *MessageType {
+ p := new(MessageType)
+ *p = x
+ return p
+}
+func (x MessageType) String() string {
+ return proto.EnumName(MessageType_name, int32(x))
+}
+func (x *MessageType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(MessageType_value, data, "MessageType")
+ if err != nil {
+ return err
+ }
+ *x = MessageType(value)
+ return nil
+}
+func (MessageType) EnumDescriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
+
+// *
+// Request: Reset device to default state and ask for device details
+// @next Features
+type Initialize struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Initialize) Reset() { *m = Initialize{} }
+func (m *Initialize) String() string { return proto.CompactTextString(m) }
+func (*Initialize) ProtoMessage() {}
+func (*Initialize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
+
+// *
+// Request: Ask for device details (no device reset)
+// @next Features
+type GetFeatures struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GetFeatures) Reset() { *m = GetFeatures{} }
+func (m *GetFeatures) String() string { return proto.CompactTextString(m) }
+func (*GetFeatures) ProtoMessage() {}
+func (*GetFeatures) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
+
+// *
+// Response: Reports various information about the device
+// @prev Initialize
+// @prev GetFeatures
+type Features struct {
+ Vendor *string `protobuf:"bytes,1,opt,name=vendor" json:"vendor,omitempty"`
+ MajorVersion *uint32 `protobuf:"varint,2,opt,name=major_version,json=majorVersion" json:"major_version,omitempty"`
+ MinorVersion *uint32 `protobuf:"varint,3,opt,name=minor_version,json=minorVersion" json:"minor_version,omitempty"`
+ PatchVersion *uint32 `protobuf:"varint,4,opt,name=patch_version,json=patchVersion" json:"patch_version,omitempty"`
+ BootloaderMode *bool `protobuf:"varint,5,opt,name=bootloader_mode,json=bootloaderMode" json:"bootloader_mode,omitempty"`
+ DeviceId *string `protobuf:"bytes,6,opt,name=device_id,json=deviceId" json:"device_id,omitempty"`
+ PinProtection *bool `protobuf:"varint,7,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+ PassphraseProtection *bool `protobuf:"varint,8,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+ Language *string `protobuf:"bytes,9,opt,name=language" json:"language,omitempty"`
+ Label *string `protobuf:"bytes,10,opt,name=label" json:"label,omitempty"`
+ Coins []*CoinType `protobuf:"bytes,11,rep,name=coins" json:"coins,omitempty"`
+ Initialized *bool `protobuf:"varint,12,opt,name=initialized" json:"initialized,omitempty"`
+ Revision []byte `protobuf:"bytes,13,opt,name=revision" json:"revision,omitempty"`
+ BootloaderHash []byte `protobuf:"bytes,14,opt,name=bootloader_hash,json=bootloaderHash" json:"bootloader_hash,omitempty"`
+ Imported *bool `protobuf:"varint,15,opt,name=imported" json:"imported,omitempty"`
+ PinCached *bool `protobuf:"varint,16,opt,name=pin_cached,json=pinCached" json:"pin_cached,omitempty"`
+ PassphraseCached *bool `protobuf:"varint,17,opt,name=passphrase_cached,json=passphraseCached" json:"passphrase_cached,omitempty"`
+ FirmwarePresent *bool `protobuf:"varint,18,opt,name=firmware_present,json=firmwarePresent" json:"firmware_present,omitempty"`
+ NeedsBackup *bool `protobuf:"varint,19,opt,name=needs_backup,json=needsBackup" json:"needs_backup,omitempty"`
+ Flags *uint32 `protobuf:"varint,20,opt,name=flags" json:"flags,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Features) Reset() { *m = Features{} }
+func (m *Features) String() string { return proto.CompactTextString(m) }
+func (*Features) ProtoMessage() {}
+func (*Features) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
+
+func (m *Features) GetVendor() string {
+ if m != nil && m.Vendor != nil {
+ return *m.Vendor
+ }
+ return ""
+}
+
+func (m *Features) GetMajorVersion() uint32 {
+ if m != nil && m.MajorVersion != nil {
+ return *m.MajorVersion
+ }
+ return 0
+}
+
+func (m *Features) GetMinorVersion() uint32 {
+ if m != nil && m.MinorVersion != nil {
+ return *m.MinorVersion
+ }
+ return 0
+}
+
+func (m *Features) GetPatchVersion() uint32 {
+ if m != nil && m.PatchVersion != nil {
+ return *m.PatchVersion
+ }
+ return 0
+}
+
+func (m *Features) GetBootloaderMode() bool {
+ if m != nil && m.BootloaderMode != nil {
+ return *m.BootloaderMode
+ }
+ return false
+}
+
+func (m *Features) GetDeviceId() string {
+ if m != nil && m.DeviceId != nil {
+ return *m.DeviceId
+ }
+ return ""
+}
+
+func (m *Features) GetPinProtection() bool {
+ if m != nil && m.PinProtection != nil {
+ return *m.PinProtection
+ }
+ return false
+}
+
+func (m *Features) GetPassphraseProtection() bool {
+ if m != nil && m.PassphraseProtection != nil {
+ return *m.PassphraseProtection
+ }
+ return false
+}
+
+func (m *Features) GetLanguage() string {
+ if m != nil && m.Language != nil {
+ return *m.Language
+ }
+ return ""
+}
+
+func (m *Features) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+}
+
+func (m *Features) GetCoins() []*CoinType {
+ if m != nil {
+ return m.Coins
+ }
+ return nil
+}
+
+func (m *Features) GetInitialized() bool {
+ if m != nil && m.Initialized != nil {
+ return *m.Initialized
+ }
+ return false
+}
+
+func (m *Features) GetRevision() []byte {
+ if m != nil {
+ return m.Revision
+ }
+ return nil
+}
+
+func (m *Features) GetBootloaderHash() []byte {
+ if m != nil {
+ return m.BootloaderHash
+ }
+ return nil
+}
+
+func (m *Features) GetImported() bool {
+ if m != nil && m.Imported != nil {
+ return *m.Imported
+ }
+ return false
+}
+
+func (m *Features) GetPinCached() bool {
+ if m != nil && m.PinCached != nil {
+ return *m.PinCached
+ }
+ return false
+}
+
+func (m *Features) GetPassphraseCached() bool {
+ if m != nil && m.PassphraseCached != nil {
+ return *m.PassphraseCached
+ }
+ return false
+}
+
+func (m *Features) GetFirmwarePresent() bool {
+ if m != nil && m.FirmwarePresent != nil {
+ return *m.FirmwarePresent
+ }
+ return false
+}
+
+func (m *Features) GetNeedsBackup() bool {
+ if m != nil && m.NeedsBackup != nil {
+ return *m.NeedsBackup
+ }
+ return false
+}
+
+func (m *Features) GetFlags() uint32 {
+ if m != nil && m.Flags != nil {
+ return *m.Flags
+ }
+ return 0
+}
+
+// *
+// Request: clear session (removes cached PIN, passphrase, etc).
+// @next Success
+type ClearSession struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ClearSession) Reset() { *m = ClearSession{} }
+func (m *ClearSession) String() string { return proto.CompactTextString(m) }
+func (*ClearSession) ProtoMessage() {}
+func (*ClearSession) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} }
+
+// *
+// Request: change language and/or label of the device
+// @next Success
+// @next Failure
+// @next ButtonRequest
+// @next PinMatrixRequest
+type ApplySettings struct {
+ Language *string `protobuf:"bytes,1,opt,name=language" json:"language,omitempty"`
+ Label *string `protobuf:"bytes,2,opt,name=label" json:"label,omitempty"`
+ UsePassphrase *bool `protobuf:"varint,3,opt,name=use_passphrase,json=usePassphrase" json:"use_passphrase,omitempty"`
+ Homescreen []byte `protobuf:"bytes,4,opt,name=homescreen" json:"homescreen,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ApplySettings) Reset() { *m = ApplySettings{} }
+func (m *ApplySettings) String() string { return proto.CompactTextString(m) }
+func (*ApplySettings) ProtoMessage() {}
+func (*ApplySettings) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{4} }
+
+func (m *ApplySettings) GetLanguage() string {
+ if m != nil && m.Language != nil {
+ return *m.Language
+ }
+ return ""
+}
+
+func (m *ApplySettings) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+}
+
+func (m *ApplySettings) GetUsePassphrase() bool {
+ if m != nil && m.UsePassphrase != nil {
+ return *m.UsePassphrase
+ }
+ return false
+}
+
+func (m *ApplySettings) GetHomescreen() []byte {
+ if m != nil {
+ return m.Homescreen
+ }
+ return nil
+}
+
+// *
+// Request: set flags of the device
+// @next Success
+// @next Failure
+type ApplyFlags struct {
+ Flags *uint32 `protobuf:"varint,1,opt,name=flags" json:"flags,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ApplyFlags) Reset() { *m = ApplyFlags{} }
+func (m *ApplyFlags) String() string { return proto.CompactTextString(m) }
+func (*ApplyFlags) ProtoMessage() {}
+func (*ApplyFlags) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{5} }
+
+func (m *ApplyFlags) GetFlags() uint32 {
+ if m != nil && m.Flags != nil {
+ return *m.Flags
+ }
+ return 0
+}
+
+// *
+// Request: Starts workflow for setting/changing/removing the PIN
+// @next ButtonRequest
+// @next PinMatrixRequest
+type ChangePin struct {
+ Remove *bool `protobuf:"varint,1,opt,name=remove" json:"remove,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ChangePin) Reset() { *m = ChangePin{} }
+func (m *ChangePin) String() string { return proto.CompactTextString(m) }
+func (*ChangePin) ProtoMessage() {}
+func (*ChangePin) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{6} }
+
+func (m *ChangePin) GetRemove() bool {
+ if m != nil && m.Remove != nil {
+ return *m.Remove
+ }
+ return false
+}
+
+// *
+// Request: Test if the device is alive, device sends back the message in Success response
+// @next Success
+type Ping struct {
+ Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
+ ButtonProtection *bool `protobuf:"varint,2,opt,name=button_protection,json=buttonProtection" json:"button_protection,omitempty"`
+ PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+ PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Ping) Reset() { *m = Ping{} }
+func (m *Ping) String() string { return proto.CompactTextString(m) }
+func (*Ping) ProtoMessage() {}
+func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{7} }
+
+func (m *Ping) GetMessage() string {
+ if m != nil && m.Message != nil {
+ return *m.Message
+ }
+ return ""
+}
+
+func (m *Ping) GetButtonProtection() bool {
+ if m != nil && m.ButtonProtection != nil {
+ return *m.ButtonProtection
+ }
+ return false
+}
+
+func (m *Ping) GetPinProtection() bool {
+ if m != nil && m.PinProtection != nil {
+ return *m.PinProtection
+ }
+ return false
+}
+
+func (m *Ping) GetPassphraseProtection() bool {
+ if m != nil && m.PassphraseProtection != nil {
+ return *m.PassphraseProtection
+ }
+ return false
+}
+
+// *
+// Response: Success of the previous request
+type Success struct {
+ Message *string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Success) Reset() { *m = Success{} }
+func (m *Success) String() string { return proto.CompactTextString(m) }
+func (*Success) ProtoMessage() {}
+func (*Success) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} }
+
+func (m *Success) GetMessage() string {
+ if m != nil && m.Message != nil {
+ return *m.Message
+ }
+ return ""
+}
+
+// *
+// Response: Failure of the previous request
+type Failure struct {
+ Code *FailureType `protobuf:"varint,1,opt,name=code,enum=FailureType" json:"code,omitempty"`
+ Message *string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Failure) Reset() { *m = Failure{} }
+func (m *Failure) String() string { return proto.CompactTextString(m) }
+func (*Failure) ProtoMessage() {}
+func (*Failure) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} }
+
+func (m *Failure) GetCode() FailureType {
+ if m != nil && m.Code != nil {
+ return *m.Code
+ }
+ return FailureType_Failure_UnexpectedMessage
+}
+
+func (m *Failure) GetMessage() string {
+ if m != nil && m.Message != nil {
+ return *m.Message
+ }
+ return ""
+}
+
+// *
+// Response: Device is waiting for HW button press.
+// @next ButtonAck
+// @next Cancel
+type ButtonRequest struct {
+ Code *ButtonRequestType `protobuf:"varint,1,opt,name=code,enum=ButtonRequestType" json:"code,omitempty"`
+ Data *string `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ButtonRequest) Reset() { *m = ButtonRequest{} }
+func (m *ButtonRequest) String() string { return proto.CompactTextString(m) }
+func (*ButtonRequest) ProtoMessage() {}
+func (*ButtonRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} }
+
+func (m *ButtonRequest) GetCode() ButtonRequestType {
+ if m != nil && m.Code != nil {
+ return *m.Code
+ }
+ return ButtonRequestType_ButtonRequest_Other
+}
+
+func (m *ButtonRequest) GetData() string {
+ if m != nil && m.Data != nil {
+ return *m.Data
+ }
+ return ""
+}
+
+// *
+// Request: Computer agrees to wait for HW button press
+// @prev ButtonRequest
+type ButtonAck struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ButtonAck) Reset() { *m = ButtonAck{} }
+func (m *ButtonAck) String() string { return proto.CompactTextString(m) }
+func (*ButtonAck) ProtoMessage() {}
+func (*ButtonAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} }
+
+// *
+// Response: Device is asking computer to show PIN matrix and awaits PIN encoded using this matrix scheme
+// @next PinMatrixAck
+// @next Cancel
+type PinMatrixRequest struct {
+ Type *PinMatrixRequestType `protobuf:"varint,1,opt,name=type,enum=PinMatrixRequestType" json:"type,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *PinMatrixRequest) Reset() { *m = PinMatrixRequest{} }
+func (m *PinMatrixRequest) String() string { return proto.CompactTextString(m) }
+func (*PinMatrixRequest) ProtoMessage() {}
+func (*PinMatrixRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} }
+
+func (m *PinMatrixRequest) GetType() PinMatrixRequestType {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return PinMatrixRequestType_PinMatrixRequestType_Current
+}
+
+// *
+// Request: Computer responds with encoded PIN
+// @prev PinMatrixRequest
+type PinMatrixAck struct {
+ Pin *string `protobuf:"bytes,1,req,name=pin" json:"pin,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *PinMatrixAck) Reset() { *m = PinMatrixAck{} }
+func (m *PinMatrixAck) String() string { return proto.CompactTextString(m) }
+func (*PinMatrixAck) ProtoMessage() {}
+func (*PinMatrixAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} }
+
+func (m *PinMatrixAck) GetPin() string {
+ if m != nil && m.Pin != nil {
+ return *m.Pin
+ }
+ return ""
+}
+
+// *
+// Request: Abort last operation that required user interaction
+// @prev ButtonRequest
+// @prev PinMatrixRequest
+// @prev PassphraseRequest
+type Cancel struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Cancel) Reset() { *m = Cancel{} }
+func (m *Cancel) String() string { return proto.CompactTextString(m) }
+func (*Cancel) ProtoMessage() {}
+func (*Cancel) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{14} }
+
+// *
+// Response: Device awaits encryption passphrase
+// @next PassphraseAck
+// @next Cancel
+type PassphraseRequest struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *PassphraseRequest) Reset() { *m = PassphraseRequest{} }
+func (m *PassphraseRequest) String() string { return proto.CompactTextString(m) }
+func (*PassphraseRequest) ProtoMessage() {}
+func (*PassphraseRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{15} }
+
+// *
+// Request: Send passphrase back
+// @prev PassphraseRequest
+type PassphraseAck struct {
+ Passphrase *string `protobuf:"bytes,1,req,name=passphrase" json:"passphrase,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *PassphraseAck) Reset() { *m = PassphraseAck{} }
+func (m *PassphraseAck) String() string { return proto.CompactTextString(m) }
+func (*PassphraseAck) ProtoMessage() {}
+func (*PassphraseAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{16} }
+
+func (m *PassphraseAck) GetPassphrase() string {
+ if m != nil && m.Passphrase != nil {
+ return *m.Passphrase
+ }
+ return ""
+}
+
+// *
+// Request: Request a sample of random data generated by hardware RNG. May be used for testing.
+// @next ButtonRequest
+// @next Entropy
+// @next Failure
+type GetEntropy struct {
+ Size *uint32 `protobuf:"varint,1,req,name=size" json:"size,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GetEntropy) Reset() { *m = GetEntropy{} }
+func (m *GetEntropy) String() string { return proto.CompactTextString(m) }
+func (*GetEntropy) ProtoMessage() {}
+func (*GetEntropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{17} }
+
+func (m *GetEntropy) GetSize() uint32 {
+ if m != nil && m.Size != nil {
+ return *m.Size
+ }
+ return 0
+}
+
+// *
+// Response: Reply with random data generated by internal RNG
+// @prev GetEntropy
+type Entropy struct {
+ Entropy []byte `protobuf:"bytes,1,req,name=entropy" json:"entropy,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Entropy) Reset() { *m = Entropy{} }
+func (m *Entropy) String() string { return proto.CompactTextString(m) }
+func (*Entropy) ProtoMessage() {}
+func (*Entropy) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{18} }
+
+func (m *Entropy) GetEntropy() []byte {
+ if m != nil {
+ return m.Entropy
+ }
+ return nil
+}
+
+// *
+// Request: Ask device for public key corresponding to address_n path
+// @next PassphraseRequest
+// @next PublicKey
+// @next Failure
+type GetPublicKey struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ EcdsaCurveName *string `protobuf:"bytes,2,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"`
+ ShowDisplay *bool `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
+ CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GetPublicKey) Reset() { *m = GetPublicKey{} }
+func (m *GetPublicKey) String() string { return proto.CompactTextString(m) }
+func (*GetPublicKey) ProtoMessage() {}
+func (*GetPublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{19} }
+
+const Default_GetPublicKey_CoinName string = "Bitcoin"
+
+func (m *GetPublicKey) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *GetPublicKey) GetEcdsaCurveName() string {
+ if m != nil && m.EcdsaCurveName != nil {
+ return *m.EcdsaCurveName
+ }
+ return ""
+}
+
+func (m *GetPublicKey) GetShowDisplay() bool {
+ if m != nil && m.ShowDisplay != nil {
+ return *m.ShowDisplay
+ }
+ return false
+}
+
+func (m *GetPublicKey) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_GetPublicKey_CoinName
+}
+
+// *
+// Response: Contains public key derived from device private seed
+// @prev GetPublicKey
+type PublicKey struct {
+ Node *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"`
+ Xpub *string `protobuf:"bytes,2,opt,name=xpub" json:"xpub,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *PublicKey) Reset() { *m = PublicKey{} }
+func (m *PublicKey) String() string { return proto.CompactTextString(m) }
+func (*PublicKey) ProtoMessage() {}
+func (*PublicKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{20} }
+
+func (m *PublicKey) GetNode() *HDNodeType {
+ if m != nil {
+ return m.Node
+ }
+ return nil
+}
+
+func (m *PublicKey) GetXpub() string {
+ if m != nil && m.Xpub != nil {
+ return *m.Xpub
+ }
+ return ""
+}
+
+// *
+// Request: Ask device for address corresponding to address_n path
+// @next PassphraseRequest
+// @next Address
+// @next Failure
+type GetAddress struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ CoinName *string `protobuf:"bytes,2,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ ShowDisplay *bool `protobuf:"varint,3,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
+ Multisig *MultisigRedeemScriptType `protobuf:"bytes,4,opt,name=multisig" json:"multisig,omitempty"`
+ ScriptType *InputScriptType `protobuf:"varint,5,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GetAddress) Reset() { *m = GetAddress{} }
+func (m *GetAddress) String() string { return proto.CompactTextString(m) }
+func (*GetAddress) ProtoMessage() {}
+func (*GetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{21} }
+
+const Default_GetAddress_CoinName string = "Bitcoin"
+const Default_GetAddress_ScriptType InputScriptType = InputScriptType_SPENDADDRESS
+
+func (m *GetAddress) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *GetAddress) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_GetAddress_CoinName
+}
+
+func (m *GetAddress) GetShowDisplay() bool {
+ if m != nil && m.ShowDisplay != nil {
+ return *m.ShowDisplay
+ }
+ return false
+}
+
+func (m *GetAddress) GetMultisig() *MultisigRedeemScriptType {
+ if m != nil {
+ return m.Multisig
+ }
+ return nil
+}
+
+func (m *GetAddress) GetScriptType() InputScriptType {
+ if m != nil && m.ScriptType != nil {
+ return *m.ScriptType
+ }
+ return Default_GetAddress_ScriptType
+}
+
+// *
+// Request: Ask device for Ethereum address corresponding to address_n path
+// @next PassphraseRequest
+// @next EthereumAddress
+// @next Failure
+type EthereumGetAddress struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ ShowDisplay *bool `protobuf:"varint,2,opt,name=show_display,json=showDisplay" json:"show_display,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumGetAddress) Reset() { *m = EthereumGetAddress{} }
+func (m *EthereumGetAddress) String() string { return proto.CompactTextString(m) }
+func (*EthereumGetAddress) ProtoMessage() {}
+func (*EthereumGetAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{22} }
+
+func (m *EthereumGetAddress) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *EthereumGetAddress) GetShowDisplay() bool {
+ if m != nil && m.ShowDisplay != nil {
+ return *m.ShowDisplay
+ }
+ return false
+}
+
+// *
+// Response: Contains address derived from device private seed
+// @prev GetAddress
+type Address struct {
+ Address *string `protobuf:"bytes,1,req,name=address" json:"address,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *Address) Reset() { *m = Address{} }
+func (m *Address) String() string { return proto.CompactTextString(m) }
+func (*Address) ProtoMessage() {}
+func (*Address) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{23} }
+
+func (m *Address) GetAddress() string {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return ""
+}
+
+// *
+// Response: Contains an Ethereum address derived from device private seed
+// @prev EthereumGetAddress
+type EthereumAddress struct {
+ Address []byte `protobuf:"bytes,1,req,name=address" json:"address,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumAddress) Reset() { *m = EthereumAddress{} }
+func (m *EthereumAddress) String() string { return proto.CompactTextString(m) }
+func (*EthereumAddress) ProtoMessage() {}
+func (*EthereumAddress) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{24} }
+
+func (m *EthereumAddress) GetAddress() []byte {
+ if m != nil {
+ return m.Address
+ }
+ return nil
+}
+
+// *
+// Request: Request device to wipe all sensitive data and settings
+// @next ButtonRequest
+type WipeDevice struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *WipeDevice) Reset() { *m = WipeDevice{} }
+func (m *WipeDevice) String() string { return proto.CompactTextString(m) }
+func (*WipeDevice) ProtoMessage() {}
+func (*WipeDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{25} }
+
+// *
+// Request: Load seed and related internal settings from the computer
+// @next ButtonRequest
+// @next Success
+// @next Failure
+type LoadDevice struct {
+ Mnemonic *string `protobuf:"bytes,1,opt,name=mnemonic" json:"mnemonic,omitempty"`
+ Node *HDNodeType `protobuf:"bytes,2,opt,name=node" json:"node,omitempty"`
+ Pin *string `protobuf:"bytes,3,opt,name=pin" json:"pin,omitempty"`
+ PassphraseProtection *bool `protobuf:"varint,4,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+ Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"`
+ Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"`
+ SkipChecksum *bool `protobuf:"varint,7,opt,name=skip_checksum,json=skipChecksum" json:"skip_checksum,omitempty"`
+ U2FCounter *uint32 `protobuf:"varint,8,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *LoadDevice) Reset() { *m = LoadDevice{} }
+func (m *LoadDevice) String() string { return proto.CompactTextString(m) }
+func (*LoadDevice) ProtoMessage() {}
+func (*LoadDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{26} }
+
+const Default_LoadDevice_Language string = "english"
+
+func (m *LoadDevice) GetMnemonic() string {
+ if m != nil && m.Mnemonic != nil {
+ return *m.Mnemonic
+ }
+ return ""
+}
+
+func (m *LoadDevice) GetNode() *HDNodeType {
+ if m != nil {
+ return m.Node
+ }
+ return nil
+}
+
+func (m *LoadDevice) GetPin() string {
+ if m != nil && m.Pin != nil {
+ return *m.Pin
+ }
+ return ""
+}
+
+func (m *LoadDevice) GetPassphraseProtection() bool {
+ if m != nil && m.PassphraseProtection != nil {
+ return *m.PassphraseProtection
+ }
+ return false
+}
+
+func (m *LoadDevice) GetLanguage() string {
+ if m != nil && m.Language != nil {
+ return *m.Language
+ }
+ return Default_LoadDevice_Language
+}
+
+func (m *LoadDevice) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+}
+
+func (m *LoadDevice) GetSkipChecksum() bool {
+ if m != nil && m.SkipChecksum != nil {
+ return *m.SkipChecksum
+ }
+ return false
+}
+
+func (m *LoadDevice) GetU2FCounter() uint32 {
+ if m != nil && m.U2FCounter != nil {
+ return *m.U2FCounter
+ }
+ return 0
+}
+
+// *
+// Request: Ask device to do initialization involving user interaction
+// @next EntropyRequest
+// @next Failure
+type ResetDevice struct {
+ DisplayRandom *bool `protobuf:"varint,1,opt,name=display_random,json=displayRandom" json:"display_random,omitempty"`
+ Strength *uint32 `protobuf:"varint,2,opt,name=strength,def=256" json:"strength,omitempty"`
+ PassphraseProtection *bool `protobuf:"varint,3,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+ PinProtection *bool `protobuf:"varint,4,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+ Language *string `protobuf:"bytes,5,opt,name=language,def=english" json:"language,omitempty"`
+ Label *string `protobuf:"bytes,6,opt,name=label" json:"label,omitempty"`
+ U2FCounter *uint32 `protobuf:"varint,7,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+ SkipBackup *bool `protobuf:"varint,8,opt,name=skip_backup,json=skipBackup" json:"skip_backup,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ResetDevice) Reset() { *m = ResetDevice{} }
+func (m *ResetDevice) String() string { return proto.CompactTextString(m) }
+func (*ResetDevice) ProtoMessage() {}
+func (*ResetDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{27} }
+
+const Default_ResetDevice_Strength uint32 = 256
+const Default_ResetDevice_Language string = "english"
+
+func (m *ResetDevice) GetDisplayRandom() bool {
+ if m != nil && m.DisplayRandom != nil {
+ return *m.DisplayRandom
+ }
+ return false
+}
+
+func (m *ResetDevice) GetStrength() uint32 {
+ if m != nil && m.Strength != nil {
+ return *m.Strength
+ }
+ return Default_ResetDevice_Strength
+}
+
+func (m *ResetDevice) GetPassphraseProtection() bool {
+ if m != nil && m.PassphraseProtection != nil {
+ return *m.PassphraseProtection
+ }
+ return false
+}
+
+func (m *ResetDevice) GetPinProtection() bool {
+ if m != nil && m.PinProtection != nil {
+ return *m.PinProtection
+ }
+ return false
+}
+
+func (m *ResetDevice) GetLanguage() string {
+ if m != nil && m.Language != nil {
+ return *m.Language
+ }
+ return Default_ResetDevice_Language
+}
+
+func (m *ResetDevice) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+}
+
+func (m *ResetDevice) GetU2FCounter() uint32 {
+ if m != nil && m.U2FCounter != nil {
+ return *m.U2FCounter
+ }
+ return 0
+}
+
+func (m *ResetDevice) GetSkipBackup() bool {
+ if m != nil && m.SkipBackup != nil {
+ return *m.SkipBackup
+ }
+ return false
+}
+
+// *
+// Request: Perform backup of the device seed if not backed up using ResetDevice
+// @next ButtonRequest
+type BackupDevice struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *BackupDevice) Reset() { *m = BackupDevice{} }
+func (m *BackupDevice) String() string { return proto.CompactTextString(m) }
+func (*BackupDevice) ProtoMessage() {}
+func (*BackupDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{28} }
+
+// *
+// Response: Ask for additional entropy from host computer
+// @prev ResetDevice
+// @next EntropyAck
+type EntropyRequest struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EntropyRequest) Reset() { *m = EntropyRequest{} }
+func (m *EntropyRequest) String() string { return proto.CompactTextString(m) }
+func (*EntropyRequest) ProtoMessage() {}
+func (*EntropyRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{29} }
+
+// *
+// Request: Provide additional entropy for seed generation function
+// @prev EntropyRequest
+// @next ButtonRequest
+type EntropyAck struct {
+ Entropy []byte `protobuf:"bytes,1,opt,name=entropy" json:"entropy,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EntropyAck) Reset() { *m = EntropyAck{} }
+func (m *EntropyAck) String() string { return proto.CompactTextString(m) }
+func (*EntropyAck) ProtoMessage() {}
+func (*EntropyAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{30} }
+
+func (m *EntropyAck) GetEntropy() []byte {
+ if m != nil {
+ return m.Entropy
+ }
+ return nil
+}
+
+// *
+// Request: Start recovery workflow asking user for specific words of mnemonic
+// Used to recovery device safely even on untrusted computer.
+// @next WordRequest
+type RecoveryDevice struct {
+ WordCount *uint32 `protobuf:"varint,1,opt,name=word_count,json=wordCount" json:"word_count,omitempty"`
+ PassphraseProtection *bool `protobuf:"varint,2,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+ PinProtection *bool `protobuf:"varint,3,opt,name=pin_protection,json=pinProtection" json:"pin_protection,omitempty"`
+ Language *string `protobuf:"bytes,4,opt,name=language,def=english" json:"language,omitempty"`
+ Label *string `protobuf:"bytes,5,opt,name=label" json:"label,omitempty"`
+ EnforceWordlist *bool `protobuf:"varint,6,opt,name=enforce_wordlist,json=enforceWordlist" json:"enforce_wordlist,omitempty"`
+ // 7 reserved for unused recovery method
+ Type *uint32 `protobuf:"varint,8,opt,name=type" json:"type,omitempty"`
+ U2FCounter *uint32 `protobuf:"varint,9,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+ DryRun *bool `protobuf:"varint,10,opt,name=dry_run,json=dryRun" json:"dry_run,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *RecoveryDevice) Reset() { *m = RecoveryDevice{} }
+func (m *RecoveryDevice) String() string { return proto.CompactTextString(m) }
+func (*RecoveryDevice) ProtoMessage() {}
+func (*RecoveryDevice) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{31} }
+
+const Default_RecoveryDevice_Language string = "english"
+
+func (m *RecoveryDevice) GetWordCount() uint32 {
+ if m != nil && m.WordCount != nil {
+ return *m.WordCount
+ }
+ return 0
+}
+
+func (m *RecoveryDevice) GetPassphraseProtection() bool {
+ if m != nil && m.PassphraseProtection != nil {
+ return *m.PassphraseProtection
+ }
+ return false
+}
+
+func (m *RecoveryDevice) GetPinProtection() bool {
+ if m != nil && m.PinProtection != nil {
+ return *m.PinProtection
+ }
+ return false
+}
+
+func (m *RecoveryDevice) GetLanguage() string {
+ if m != nil && m.Language != nil {
+ return *m.Language
+ }
+ return Default_RecoveryDevice_Language
+}
+
+func (m *RecoveryDevice) GetLabel() string {
+ if m != nil && m.Label != nil {
+ return *m.Label
+ }
+ return ""
+}
+
+func (m *RecoveryDevice) GetEnforceWordlist() bool {
+ if m != nil && m.EnforceWordlist != nil {
+ return *m.EnforceWordlist
+ }
+ return false
+}
+
+func (m *RecoveryDevice) GetType() uint32 {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return 0
+}
+
+func (m *RecoveryDevice) GetU2FCounter() uint32 {
+ if m != nil && m.U2FCounter != nil {
+ return *m.U2FCounter
+ }
+ return 0
+}
+
+func (m *RecoveryDevice) GetDryRun() bool {
+ if m != nil && m.DryRun != nil {
+ return *m.DryRun
+ }
+ return false
+}
+
+// *
+// 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
+type WordRequest struct {
+ Type *WordRequestType `protobuf:"varint,1,opt,name=type,enum=WordRequestType" json:"type,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *WordRequest) Reset() { *m = WordRequest{} }
+func (m *WordRequest) String() string { return proto.CompactTextString(m) }
+func (*WordRequest) ProtoMessage() {}
+func (*WordRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{32} }
+
+func (m *WordRequest) GetType() WordRequestType {
+ if m != nil && m.Type != nil {
+ return *m.Type
+ }
+ return WordRequestType_WordRequestType_Plain
+}
+
+// *
+// Request: Computer replies with word from the mnemonic
+// @prev WordRequest
+// @next WordRequest
+// @next Success
+// @next Failure
+type WordAck struct {
+ Word *string `protobuf:"bytes,1,req,name=word" json:"word,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *WordAck) Reset() { *m = WordAck{} }
+func (m *WordAck) String() string { return proto.CompactTextString(m) }
+func (*WordAck) ProtoMessage() {}
+func (*WordAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{33} }
+
+func (m *WordAck) GetWord() string {
+ if m != nil && m.Word != nil {
+ return *m.Word
+ }
+ return ""
+}
+
+// *
+// Request: Ask device to sign message
+// @next MessageSignature
+// @next Failure
+type SignMessage struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ Message []byte `protobuf:"bytes,2,req,name=message" json:"message,omitempty"`
+ CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ ScriptType *InputScriptType `protobuf:"varint,4,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SignMessage) Reset() { *m = SignMessage{} }
+func (m *SignMessage) String() string { return proto.CompactTextString(m) }
+func (*SignMessage) ProtoMessage() {}
+func (*SignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{34} }
+
+const Default_SignMessage_CoinName string = "Bitcoin"
+const Default_SignMessage_ScriptType InputScriptType = InputScriptType_SPENDADDRESS
+
+func (m *SignMessage) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *SignMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+func (m *SignMessage) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_SignMessage_CoinName
+}
+
+func (m *SignMessage) GetScriptType() InputScriptType {
+ if m != nil && m.ScriptType != nil {
+ return *m.ScriptType
+ }
+ return Default_SignMessage_ScriptType
+}
+
+// *
+// Request: Ask device to verify message
+// @next Success
+// @next Failure
+type VerifyMessage struct {
+ Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
+ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
+ Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
+ CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *VerifyMessage) Reset() { *m = VerifyMessage{} }
+func (m *VerifyMessage) String() string { return proto.CompactTextString(m) }
+func (*VerifyMessage) ProtoMessage() {}
+func (*VerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{35} }
+
+const Default_VerifyMessage_CoinName string = "Bitcoin"
+
+func (m *VerifyMessage) GetAddress() string {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return ""
+}
+
+func (m *VerifyMessage) GetSignature() []byte {
+ if m != nil {
+ return m.Signature
+ }
+ return nil
+}
+
+func (m *VerifyMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+func (m *VerifyMessage) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_VerifyMessage_CoinName
+}
+
+// *
+// Response: Signed message
+// @prev SignMessage
+type MessageSignature struct {
+ Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
+ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MessageSignature) Reset() { *m = MessageSignature{} }
+func (m *MessageSignature) String() string { return proto.CompactTextString(m) }
+func (*MessageSignature) ProtoMessage() {}
+func (*MessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{36} }
+
+func (m *MessageSignature) GetAddress() string {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return ""
+}
+
+func (m *MessageSignature) GetSignature() []byte {
+ if m != nil {
+ return m.Signature
+ }
+ return nil
+}
+
+// *
+// Request: Ask device to encrypt message
+// @next EncryptedMessage
+// @next Failure
+type EncryptMessage struct {
+ Pubkey []byte `protobuf:"bytes,1,opt,name=pubkey" json:"pubkey,omitempty"`
+ Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
+ DisplayOnly *bool `protobuf:"varint,3,opt,name=display_only,json=displayOnly" json:"display_only,omitempty"`
+ AddressN []uint32 `protobuf:"varint,4,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ CoinName *string `protobuf:"bytes,5,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EncryptMessage) Reset() { *m = EncryptMessage{} }
+func (m *EncryptMessage) String() string { return proto.CompactTextString(m) }
+func (*EncryptMessage) ProtoMessage() {}
+func (*EncryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{37} }
+
+const Default_EncryptMessage_CoinName string = "Bitcoin"
+
+func (m *EncryptMessage) GetPubkey() []byte {
+ if m != nil {
+ return m.Pubkey
+ }
+ return nil
+}
+
+func (m *EncryptMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+func (m *EncryptMessage) GetDisplayOnly() bool {
+ if m != nil && m.DisplayOnly != nil {
+ return *m.DisplayOnly
+ }
+ return false
+}
+
+func (m *EncryptMessage) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *EncryptMessage) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_EncryptMessage_CoinName
+}
+
+// *
+// Response: Encrypted message
+// @prev EncryptMessage
+type EncryptedMessage struct {
+ Nonce []byte `protobuf:"bytes,1,opt,name=nonce" json:"nonce,omitempty"`
+ Message []byte `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
+ Hmac []byte `protobuf:"bytes,3,opt,name=hmac" json:"hmac,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EncryptedMessage) Reset() { *m = EncryptedMessage{} }
+func (m *EncryptedMessage) String() string { return proto.CompactTextString(m) }
+func (*EncryptedMessage) ProtoMessage() {}
+func (*EncryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{38} }
+
+func (m *EncryptedMessage) GetNonce() []byte {
+ if m != nil {
+ return m.Nonce
+ }
+ return nil
+}
+
+func (m *EncryptedMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+func (m *EncryptedMessage) GetHmac() []byte {
+ if m != nil {
+ return m.Hmac
+ }
+ return nil
+}
+
+// *
+// Request: Ask device to decrypt message
+// @next Success
+// @next Failure
+type DecryptMessage struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"`
+ Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
+ Hmac []byte `protobuf:"bytes,4,opt,name=hmac" json:"hmac,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DecryptMessage) Reset() { *m = DecryptMessage{} }
+func (m *DecryptMessage) String() string { return proto.CompactTextString(m) }
+func (*DecryptMessage) ProtoMessage() {}
+func (*DecryptMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{39} }
+
+func (m *DecryptMessage) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *DecryptMessage) GetNonce() []byte {
+ if m != nil {
+ return m.Nonce
+ }
+ return nil
+}
+
+func (m *DecryptMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+func (m *DecryptMessage) GetHmac() []byte {
+ if m != nil {
+ return m.Hmac
+ }
+ return nil
+}
+
+// *
+// Response: Decrypted message
+// @prev DecryptedMessage
+type DecryptedMessage struct {
+ Message []byte `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
+ Address *string `protobuf:"bytes,2,opt,name=address" json:"address,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DecryptedMessage) Reset() { *m = DecryptedMessage{} }
+func (m *DecryptedMessage) String() string { return proto.CompactTextString(m) }
+func (*DecryptedMessage) ProtoMessage() {}
+func (*DecryptedMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{40} }
+
+func (m *DecryptedMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+func (m *DecryptedMessage) GetAddress() string {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return ""
+}
+
+// *
+// Request: Ask device to encrypt or decrypt value of given key
+// @next CipheredKeyValue
+// @next Failure
+type CipherKeyValue struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ Key *string `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
+ Value []byte `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"`
+ Encrypt *bool `protobuf:"varint,4,opt,name=encrypt" json:"encrypt,omitempty"`
+ AskOnEncrypt *bool `protobuf:"varint,5,opt,name=ask_on_encrypt,json=askOnEncrypt" json:"ask_on_encrypt,omitempty"`
+ AskOnDecrypt *bool `protobuf:"varint,6,opt,name=ask_on_decrypt,json=askOnDecrypt" json:"ask_on_decrypt,omitempty"`
+ Iv []byte `protobuf:"bytes,7,opt,name=iv" json:"iv,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *CipherKeyValue) Reset() { *m = CipherKeyValue{} }
+func (m *CipherKeyValue) String() string { return proto.CompactTextString(m) }
+func (*CipherKeyValue) ProtoMessage() {}
+func (*CipherKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{41} }
+
+func (m *CipherKeyValue) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *CipherKeyValue) GetKey() string {
+ if m != nil && m.Key != nil {
+ return *m.Key
+ }
+ return ""
+}
+
+func (m *CipherKeyValue) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (m *CipherKeyValue) GetEncrypt() bool {
+ if m != nil && m.Encrypt != nil {
+ return *m.Encrypt
+ }
+ return false
+}
+
+func (m *CipherKeyValue) GetAskOnEncrypt() bool {
+ if m != nil && m.AskOnEncrypt != nil {
+ return *m.AskOnEncrypt
+ }
+ return false
+}
+
+func (m *CipherKeyValue) GetAskOnDecrypt() bool {
+ if m != nil && m.AskOnDecrypt != nil {
+ return *m.AskOnDecrypt
+ }
+ return false
+}
+
+func (m *CipherKeyValue) GetIv() []byte {
+ if m != nil {
+ return m.Iv
+ }
+ return nil
+}
+
+// *
+// Response: Return ciphered/deciphered value
+// @prev CipherKeyValue
+type CipheredKeyValue struct {
+ Value []byte `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *CipheredKeyValue) Reset() { *m = CipheredKeyValue{} }
+func (m *CipheredKeyValue) String() string { return proto.CompactTextString(m) }
+func (*CipheredKeyValue) ProtoMessage() {}
+func (*CipheredKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{42} }
+
+func (m *CipheredKeyValue) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+// *
+// 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
+type EstimateTxSize struct {
+ OutputsCount *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"`
+ InputsCount *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"`
+ CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EstimateTxSize) Reset() { *m = EstimateTxSize{} }
+func (m *EstimateTxSize) String() string { return proto.CompactTextString(m) }
+func (*EstimateTxSize) ProtoMessage() {}
+func (*EstimateTxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{43} }
+
+const Default_EstimateTxSize_CoinName string = "Bitcoin"
+
+func (m *EstimateTxSize) GetOutputsCount() uint32 {
+ if m != nil && m.OutputsCount != nil {
+ return *m.OutputsCount
+ }
+ return 0
+}
+
+func (m *EstimateTxSize) GetInputsCount() uint32 {
+ if m != nil && m.InputsCount != nil {
+ return *m.InputsCount
+ }
+ return 0
+}
+
+func (m *EstimateTxSize) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_EstimateTxSize_CoinName
+}
+
+// *
+// Response: Estimated size of the transaction
+// @prev EstimateTxSize
+type TxSize struct {
+ TxSize *uint32 `protobuf:"varint,1,opt,name=tx_size,json=txSize" json:"tx_size,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxSize) Reset() { *m = TxSize{} }
+func (m *TxSize) String() string { return proto.CompactTextString(m) }
+func (*TxSize) ProtoMessage() {}
+func (*TxSize) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{44} }
+
+func (m *TxSize) GetTxSize() uint32 {
+ if m != nil && m.TxSize != nil {
+ return *m.TxSize
+ }
+ return 0
+}
+
+// *
+// Request: Ask device to sign transaction
+// @next PassphraseRequest
+// @next PinMatrixRequest
+// @next TxRequest
+// @next Failure
+type SignTx struct {
+ OutputsCount *uint32 `protobuf:"varint,1,req,name=outputs_count,json=outputsCount" json:"outputs_count,omitempty"`
+ InputsCount *uint32 `protobuf:"varint,2,req,name=inputs_count,json=inputsCount" json:"inputs_count,omitempty"`
+ CoinName *string `protobuf:"bytes,3,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ Version *uint32 `protobuf:"varint,4,opt,name=version,def=1" json:"version,omitempty"`
+ LockTime *uint32 `protobuf:"varint,5,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SignTx) Reset() { *m = SignTx{} }
+func (m *SignTx) String() string { return proto.CompactTextString(m) }
+func (*SignTx) ProtoMessage() {}
+func (*SignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{45} }
+
+const Default_SignTx_CoinName string = "Bitcoin"
+const Default_SignTx_Version uint32 = 1
+const Default_SignTx_LockTime uint32 = 0
+
+func (m *SignTx) GetOutputsCount() uint32 {
+ if m != nil && m.OutputsCount != nil {
+ return *m.OutputsCount
+ }
+ return 0
+}
+
+func (m *SignTx) GetInputsCount() uint32 {
+ if m != nil && m.InputsCount != nil {
+ return *m.InputsCount
+ }
+ return 0
+}
+
+func (m *SignTx) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_SignTx_CoinName
+}
+
+func (m *SignTx) GetVersion() uint32 {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return Default_SignTx_Version
+}
+
+func (m *SignTx) GetLockTime() uint32 {
+ if m != nil && m.LockTime != nil {
+ return *m.LockTime
+ }
+ return Default_SignTx_LockTime
+}
+
+// *
+// 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
+type SimpleSignTx struct {
+ Inputs []*TxInputType `protobuf:"bytes,1,rep,name=inputs" json:"inputs,omitempty"`
+ Outputs []*TxOutputType `protobuf:"bytes,2,rep,name=outputs" json:"outputs,omitempty"`
+ Transactions []*TransactionType `protobuf:"bytes,3,rep,name=transactions" json:"transactions,omitempty"`
+ CoinName *string `protobuf:"bytes,4,opt,name=coin_name,json=coinName,def=Bitcoin" json:"coin_name,omitempty"`
+ Version *uint32 `protobuf:"varint,5,opt,name=version,def=1" json:"version,omitempty"`
+ LockTime *uint32 `protobuf:"varint,6,opt,name=lock_time,json=lockTime,def=0" json:"lock_time,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SimpleSignTx) Reset() { *m = SimpleSignTx{} }
+func (m *SimpleSignTx) String() string { return proto.CompactTextString(m) }
+func (*SimpleSignTx) ProtoMessage() {}
+func (*SimpleSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{46} }
+
+const Default_SimpleSignTx_CoinName string = "Bitcoin"
+const Default_SimpleSignTx_Version uint32 = 1
+const Default_SimpleSignTx_LockTime uint32 = 0
+
+func (m *SimpleSignTx) GetInputs() []*TxInputType {
+ if m != nil {
+ return m.Inputs
+ }
+ return nil
+}
+
+func (m *SimpleSignTx) GetOutputs() []*TxOutputType {
+ if m != nil {
+ return m.Outputs
+ }
+ return nil
+}
+
+func (m *SimpleSignTx) GetTransactions() []*TransactionType {
+ if m != nil {
+ return m.Transactions
+ }
+ return nil
+}
+
+func (m *SimpleSignTx) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return Default_SimpleSignTx_CoinName
+}
+
+func (m *SimpleSignTx) GetVersion() uint32 {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return Default_SimpleSignTx_Version
+}
+
+func (m *SimpleSignTx) GetLockTime() uint32 {
+ if m != nil && m.LockTime != nil {
+ return *m.LockTime
+ }
+ return Default_SimpleSignTx_LockTime
+}
+
+// *
+// 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
+type TxRequest struct {
+ RequestType *RequestType `protobuf:"varint,1,opt,name=request_type,json=requestType,enum=RequestType" json:"request_type,omitempty"`
+ Details *TxRequestDetailsType `protobuf:"bytes,2,opt,name=details" json:"details,omitempty"`
+ Serialized *TxRequestSerializedType `protobuf:"bytes,3,opt,name=serialized" json:"serialized,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxRequest) Reset() { *m = TxRequest{} }
+func (m *TxRequest) String() string { return proto.CompactTextString(m) }
+func (*TxRequest) ProtoMessage() {}
+func (*TxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{47} }
+
+func (m *TxRequest) GetRequestType() RequestType {
+ if m != nil && m.RequestType != nil {
+ return *m.RequestType
+ }
+ return RequestType_TXINPUT
+}
+
+func (m *TxRequest) GetDetails() *TxRequestDetailsType {
+ if m != nil {
+ return m.Details
+ }
+ return nil
+}
+
+func (m *TxRequest) GetSerialized() *TxRequestSerializedType {
+ if m != nil {
+ return m.Serialized
+ }
+ return nil
+}
+
+// *
+// Request: Reported transaction data
+// @prev TxRequest
+// @next TxRequest
+type TxAck struct {
+ Tx *TransactionType `protobuf:"bytes,1,opt,name=tx" json:"tx,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxAck) Reset() { *m = TxAck{} }
+func (m *TxAck) String() string { return proto.CompactTextString(m) }
+func (*TxAck) ProtoMessage() {}
+func (*TxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{48} }
+
+func (m *TxAck) GetTx() *TransactionType {
+ if m != nil {
+ return m.Tx
+ }
+ return nil
+}
+
+// *
+// 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
+type EthereumSignTx struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ Nonce []byte `protobuf:"bytes,2,opt,name=nonce" json:"nonce,omitempty"`
+ GasPrice []byte `protobuf:"bytes,3,opt,name=gas_price,json=gasPrice" json:"gas_price,omitempty"`
+ GasLimit []byte `protobuf:"bytes,4,opt,name=gas_limit,json=gasLimit" json:"gas_limit,omitempty"`
+ To []byte `protobuf:"bytes,5,opt,name=to" json:"to,omitempty"`
+ Value []byte `protobuf:"bytes,6,opt,name=value" json:"value,omitempty"`
+ DataInitialChunk []byte `protobuf:"bytes,7,opt,name=data_initial_chunk,json=dataInitialChunk" json:"data_initial_chunk,omitempty"`
+ DataLength *uint32 `protobuf:"varint,8,opt,name=data_length,json=dataLength" json:"data_length,omitempty"`
+ ChainId *uint32 `protobuf:"varint,9,opt,name=chain_id,json=chainId" json:"chain_id,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumSignTx) Reset() { *m = EthereumSignTx{} }
+func (m *EthereumSignTx) String() string { return proto.CompactTextString(m) }
+func (*EthereumSignTx) ProtoMessage() {}
+func (*EthereumSignTx) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{49} }
+
+func (m *EthereumSignTx) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *EthereumSignTx) GetNonce() []byte {
+ if m != nil {
+ return m.Nonce
+ }
+ return nil
+}
+
+func (m *EthereumSignTx) GetGasPrice() []byte {
+ if m != nil {
+ return m.GasPrice
+ }
+ return nil
+}
+
+func (m *EthereumSignTx) GetGasLimit() []byte {
+ if m != nil {
+ return m.GasLimit
+ }
+ return nil
+}
+
+func (m *EthereumSignTx) GetTo() []byte {
+ if m != nil {
+ return m.To
+ }
+ return nil
+}
+
+func (m *EthereumSignTx) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func (m *EthereumSignTx) GetDataInitialChunk() []byte {
+ if m != nil {
+ return m.DataInitialChunk
+ }
+ return nil
+}
+
+func (m *EthereumSignTx) GetDataLength() uint32 {
+ if m != nil && m.DataLength != nil {
+ return *m.DataLength
+ }
+ return 0
+}
+
+func (m *EthereumSignTx) GetChainId() uint32 {
+ if m != nil && m.ChainId != nil {
+ return *m.ChainId
+ }
+ return 0
+}
+
+// *
+// 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
+type EthereumTxRequest struct {
+ DataLength *uint32 `protobuf:"varint,1,opt,name=data_length,json=dataLength" json:"data_length,omitempty"`
+ SignatureV *uint32 `protobuf:"varint,2,opt,name=signature_v,json=signatureV" json:"signature_v,omitempty"`
+ SignatureR []byte `protobuf:"bytes,3,opt,name=signature_r,json=signatureR" json:"signature_r,omitempty"`
+ SignatureS []byte `protobuf:"bytes,4,opt,name=signature_s,json=signatureS" json:"signature_s,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumTxRequest) Reset() { *m = EthereumTxRequest{} }
+func (m *EthereumTxRequest) String() string { return proto.CompactTextString(m) }
+func (*EthereumTxRequest) ProtoMessage() {}
+func (*EthereumTxRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{50} }
+
+func (m *EthereumTxRequest) GetDataLength() uint32 {
+ if m != nil && m.DataLength != nil {
+ return *m.DataLength
+ }
+ return 0
+}
+
+func (m *EthereumTxRequest) GetSignatureV() uint32 {
+ if m != nil && m.SignatureV != nil {
+ return *m.SignatureV
+ }
+ return 0
+}
+
+func (m *EthereumTxRequest) GetSignatureR() []byte {
+ if m != nil {
+ return m.SignatureR
+ }
+ return nil
+}
+
+func (m *EthereumTxRequest) GetSignatureS() []byte {
+ if m != nil {
+ return m.SignatureS
+ }
+ return nil
+}
+
+// *
+// Request: Transaction payload data.
+// @prev EthereumTxRequest
+// @next EthereumTxRequest
+type EthereumTxAck struct {
+ DataChunk []byte `protobuf:"bytes,1,opt,name=data_chunk,json=dataChunk" json:"data_chunk,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumTxAck) Reset() { *m = EthereumTxAck{} }
+func (m *EthereumTxAck) String() string { return proto.CompactTextString(m) }
+func (*EthereumTxAck) ProtoMessage() {}
+func (*EthereumTxAck) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{51} }
+
+func (m *EthereumTxAck) GetDataChunk() []byte {
+ if m != nil {
+ return m.DataChunk
+ }
+ return nil
+}
+
+// *
+// Request: Ask device to sign message
+// @next EthereumMessageSignature
+// @next Failure
+type EthereumSignMessage struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ Message []byte `protobuf:"bytes,2,req,name=message" json:"message,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumSignMessage) Reset() { *m = EthereumSignMessage{} }
+func (m *EthereumSignMessage) String() string { return proto.CompactTextString(m) }
+func (*EthereumSignMessage) ProtoMessage() {}
+func (*EthereumSignMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{52} }
+
+func (m *EthereumSignMessage) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *EthereumSignMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+// *
+// Request: Ask device to verify message
+// @next Success
+// @next Failure
+type EthereumVerifyMessage struct {
+ Address []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
+ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
+ Message []byte `protobuf:"bytes,3,opt,name=message" json:"message,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumVerifyMessage) Reset() { *m = EthereumVerifyMessage{} }
+func (m *EthereumVerifyMessage) String() string { return proto.CompactTextString(m) }
+func (*EthereumVerifyMessage) ProtoMessage() {}
+func (*EthereumVerifyMessage) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{53} }
+
+func (m *EthereumVerifyMessage) GetAddress() []byte {
+ if m != nil {
+ return m.Address
+ }
+ return nil
+}
+
+func (m *EthereumVerifyMessage) GetSignature() []byte {
+ if m != nil {
+ return m.Signature
+ }
+ return nil
+}
+
+func (m *EthereumVerifyMessage) GetMessage() []byte {
+ if m != nil {
+ return m.Message
+ }
+ return nil
+}
+
+// *
+// Response: Signed message
+// @prev EthereumSignMessage
+type EthereumMessageSignature struct {
+ Address []byte `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
+ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *EthereumMessageSignature) Reset() { *m = EthereumMessageSignature{} }
+func (m *EthereumMessageSignature) String() string { return proto.CompactTextString(m) }
+func (*EthereumMessageSignature) ProtoMessage() {}
+func (*EthereumMessageSignature) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{54} }
+
+func (m *EthereumMessageSignature) GetAddress() []byte {
+ if m != nil {
+ return m.Address
+ }
+ return nil
+}
+
+func (m *EthereumMessageSignature) GetSignature() []byte {
+ if m != nil {
+ return m.Signature
+ }
+ return nil
+}
+
+// *
+// Request: Ask device to sign identity
+// @next SignedIdentity
+// @next Failure
+type SignIdentity struct {
+ Identity *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"`
+ ChallengeHidden []byte `protobuf:"bytes,2,opt,name=challenge_hidden,json=challengeHidden" json:"challenge_hidden,omitempty"`
+ ChallengeVisual *string `protobuf:"bytes,3,opt,name=challenge_visual,json=challengeVisual" json:"challenge_visual,omitempty"`
+ EcdsaCurveName *string `protobuf:"bytes,4,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SignIdentity) Reset() { *m = SignIdentity{} }
+func (m *SignIdentity) String() string { return proto.CompactTextString(m) }
+func (*SignIdentity) ProtoMessage() {}
+func (*SignIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{55} }
+
+func (m *SignIdentity) GetIdentity() *IdentityType {
+ if m != nil {
+ return m.Identity
+ }
+ return nil
+}
+
+func (m *SignIdentity) GetChallengeHidden() []byte {
+ if m != nil {
+ return m.ChallengeHidden
+ }
+ return nil
+}
+
+func (m *SignIdentity) GetChallengeVisual() string {
+ if m != nil && m.ChallengeVisual != nil {
+ return *m.ChallengeVisual
+ }
+ return ""
+}
+
+func (m *SignIdentity) GetEcdsaCurveName() string {
+ if m != nil && m.EcdsaCurveName != nil {
+ return *m.EcdsaCurveName
+ }
+ return ""
+}
+
+// *
+// Response: Device provides signed identity
+// @prev SignIdentity
+type SignedIdentity struct {
+ Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
+ PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey" json:"public_key,omitempty"`
+ Signature []byte `protobuf:"bytes,3,opt,name=signature" json:"signature,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SignedIdentity) Reset() { *m = SignedIdentity{} }
+func (m *SignedIdentity) String() string { return proto.CompactTextString(m) }
+func (*SignedIdentity) ProtoMessage() {}
+func (*SignedIdentity) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{56} }
+
+func (m *SignedIdentity) GetAddress() string {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return ""
+}
+
+func (m *SignedIdentity) GetPublicKey() []byte {
+ if m != nil {
+ return m.PublicKey
+ }
+ return nil
+}
+
+func (m *SignedIdentity) GetSignature() []byte {
+ if m != nil {
+ return m.Signature
+ }
+ return nil
+}
+
+// *
+// Request: Ask device to generate ECDH session key
+// @next ECDHSessionKey
+// @next Failure
+type GetECDHSessionKey struct {
+ Identity *IdentityType `protobuf:"bytes,1,opt,name=identity" json:"identity,omitempty"`
+ PeerPublicKey []byte `protobuf:"bytes,2,opt,name=peer_public_key,json=peerPublicKey" json:"peer_public_key,omitempty"`
+ EcdsaCurveName *string `protobuf:"bytes,3,opt,name=ecdsa_curve_name,json=ecdsaCurveName" json:"ecdsa_curve_name,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *GetECDHSessionKey) Reset() { *m = GetECDHSessionKey{} }
+func (m *GetECDHSessionKey) String() string { return proto.CompactTextString(m) }
+func (*GetECDHSessionKey) ProtoMessage() {}
+func (*GetECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{57} }
+
+func (m *GetECDHSessionKey) GetIdentity() *IdentityType {
+ if m != nil {
+ return m.Identity
+ }
+ return nil
+}
+
+func (m *GetECDHSessionKey) GetPeerPublicKey() []byte {
+ if m != nil {
+ return m.PeerPublicKey
+ }
+ return nil
+}
+
+func (m *GetECDHSessionKey) GetEcdsaCurveName() string {
+ if m != nil && m.EcdsaCurveName != nil {
+ return *m.EcdsaCurveName
+ }
+ return ""
+}
+
+// *
+// Response: Device provides ECDH session key
+// @prev GetECDHSessionKey
+type ECDHSessionKey struct {
+ SessionKey []byte `protobuf:"bytes,1,opt,name=session_key,json=sessionKey" json:"session_key,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *ECDHSessionKey) Reset() { *m = ECDHSessionKey{} }
+func (m *ECDHSessionKey) String() string { return proto.CompactTextString(m) }
+func (*ECDHSessionKey) ProtoMessage() {}
+func (*ECDHSessionKey) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{58} }
+
+func (m *ECDHSessionKey) GetSessionKey() []byte {
+ if m != nil {
+ return m.SessionKey
+ }
+ return nil
+}
+
+// *
+// Request: Set U2F counter
+// @next Success
+type SetU2FCounter struct {
+ U2FCounter *uint32 `protobuf:"varint,1,opt,name=u2f_counter,json=u2fCounter" json:"u2f_counter,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SetU2FCounter) Reset() { *m = SetU2FCounter{} }
+func (m *SetU2FCounter) String() string { return proto.CompactTextString(m) }
+func (*SetU2FCounter) ProtoMessage() {}
+func (*SetU2FCounter) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{59} }
+
+func (m *SetU2FCounter) GetU2FCounter() uint32 {
+ if m != nil && m.U2FCounter != nil {
+ return *m.U2FCounter
+ }
+ return 0
+}
+
+// *
+// Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload)
+// @next Success
+// @next FirmwareRequest
+// @next Failure
+type FirmwareErase struct {
+ Length *uint32 `protobuf:"varint,1,opt,name=length" json:"length,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FirmwareErase) Reset() { *m = FirmwareErase{} }
+func (m *FirmwareErase) String() string { return proto.CompactTextString(m) }
+func (*FirmwareErase) ProtoMessage() {}
+func (*FirmwareErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{60} }
+
+func (m *FirmwareErase) GetLength() uint32 {
+ if m != nil && m.Length != nil {
+ return *m.Length
+ }
+ return 0
+}
+
+// *
+// Response: Ask for firmware chunk
+// @next FirmwareUpload
+type FirmwareRequest struct {
+ Offset *uint32 `protobuf:"varint,1,opt,name=offset" json:"offset,omitempty"`
+ Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FirmwareRequest) Reset() { *m = FirmwareRequest{} }
+func (m *FirmwareRequest) String() string { return proto.CompactTextString(m) }
+func (*FirmwareRequest) ProtoMessage() {}
+func (*FirmwareRequest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{61} }
+
+func (m *FirmwareRequest) GetOffset() uint32 {
+ if m != nil && m.Offset != nil {
+ return *m.Offset
+ }
+ return 0
+}
+
+func (m *FirmwareRequest) GetLength() uint32 {
+ if m != nil && m.Length != nil {
+ return *m.Length
+ }
+ return 0
+}
+
+// *
+// Request: Send firmware in binary form to the device
+// @next Success
+// @next Failure
+type FirmwareUpload struct {
+ Payload []byte `protobuf:"bytes,1,req,name=payload" json:"payload,omitempty"`
+ Hash []byte `protobuf:"bytes,2,opt,name=hash" json:"hash,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *FirmwareUpload) Reset() { *m = FirmwareUpload{} }
+func (m *FirmwareUpload) String() string { return proto.CompactTextString(m) }
+func (*FirmwareUpload) ProtoMessage() {}
+func (*FirmwareUpload) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{62} }
+
+func (m *FirmwareUpload) GetPayload() []byte {
+ if m != nil {
+ return m.Payload
+ }
+ return nil
+}
+
+func (m *FirmwareUpload) GetHash() []byte {
+ if m != nil {
+ return m.Hash
+ }
+ return nil
+}
+
+// *
+// Request: Perform a device self-test
+// @next Success
+// @next Failure
+type SelfTest struct {
+ Payload []byte `protobuf:"bytes,1,opt,name=payload" json:"payload,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *SelfTest) Reset() { *m = SelfTest{} }
+func (m *SelfTest) String() string { return proto.CompactTextString(m) }
+func (*SelfTest) ProtoMessage() {}
+func (*SelfTest) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{63} }
+
+func (m *SelfTest) GetPayload() []byte {
+ if m != nil {
+ return m.Payload
+ }
+ return nil
+}
+
+// *
+// Request: "Press" the button on the device
+// @next Success
+type DebugLinkDecision struct {
+ YesNo *bool `protobuf:"varint,1,req,name=yes_no,json=yesNo" json:"yes_no,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkDecision) Reset() { *m = DebugLinkDecision{} }
+func (m *DebugLinkDecision) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkDecision) ProtoMessage() {}
+func (*DebugLinkDecision) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{64} }
+
+func (m *DebugLinkDecision) GetYesNo() bool {
+ if m != nil && m.YesNo != nil {
+ return *m.YesNo
+ }
+ return false
+}
+
+// *
+// Request: Computer asks for device state
+// @next DebugLinkState
+type DebugLinkGetState struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkGetState) Reset() { *m = DebugLinkGetState{} }
+func (m *DebugLinkGetState) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkGetState) ProtoMessage() {}
+func (*DebugLinkGetState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{65} }
+
+// *
+// Response: Device current state
+// @prev DebugLinkGetState
+type DebugLinkState struct {
+ Layout []byte `protobuf:"bytes,1,opt,name=layout" json:"layout,omitempty"`
+ Pin *string `protobuf:"bytes,2,opt,name=pin" json:"pin,omitempty"`
+ Matrix *string `protobuf:"bytes,3,opt,name=matrix" json:"matrix,omitempty"`
+ Mnemonic *string `protobuf:"bytes,4,opt,name=mnemonic" json:"mnemonic,omitempty"`
+ Node *HDNodeType `protobuf:"bytes,5,opt,name=node" json:"node,omitempty"`
+ PassphraseProtection *bool `protobuf:"varint,6,opt,name=passphrase_protection,json=passphraseProtection" json:"passphrase_protection,omitempty"`
+ ResetWord *string `protobuf:"bytes,7,opt,name=reset_word,json=resetWord" json:"reset_word,omitempty"`
+ ResetEntropy []byte `protobuf:"bytes,8,opt,name=reset_entropy,json=resetEntropy" json:"reset_entropy,omitempty"`
+ RecoveryFakeWord *string `protobuf:"bytes,9,opt,name=recovery_fake_word,json=recoveryFakeWord" json:"recovery_fake_word,omitempty"`
+ RecoveryWordPos *uint32 `protobuf:"varint,10,opt,name=recovery_word_pos,json=recoveryWordPos" json:"recovery_word_pos,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkState) Reset() { *m = DebugLinkState{} }
+func (m *DebugLinkState) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkState) ProtoMessage() {}
+func (*DebugLinkState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{66} }
+
+func (m *DebugLinkState) GetLayout() []byte {
+ if m != nil {
+ return m.Layout
+ }
+ return nil
+}
+
+func (m *DebugLinkState) GetPin() string {
+ if m != nil && m.Pin != nil {
+ return *m.Pin
+ }
+ return ""
+}
+
+func (m *DebugLinkState) GetMatrix() string {
+ if m != nil && m.Matrix != nil {
+ return *m.Matrix
+ }
+ return ""
+}
+
+func (m *DebugLinkState) GetMnemonic() string {
+ if m != nil && m.Mnemonic != nil {
+ return *m.Mnemonic
+ }
+ return ""
+}
+
+func (m *DebugLinkState) GetNode() *HDNodeType {
+ if m != nil {
+ return m.Node
+ }
+ return nil
+}
+
+func (m *DebugLinkState) GetPassphraseProtection() bool {
+ if m != nil && m.PassphraseProtection != nil {
+ return *m.PassphraseProtection
+ }
+ return false
+}
+
+func (m *DebugLinkState) GetResetWord() string {
+ if m != nil && m.ResetWord != nil {
+ return *m.ResetWord
+ }
+ return ""
+}
+
+func (m *DebugLinkState) GetResetEntropy() []byte {
+ if m != nil {
+ return m.ResetEntropy
+ }
+ return nil
+}
+
+func (m *DebugLinkState) GetRecoveryFakeWord() string {
+ if m != nil && m.RecoveryFakeWord != nil {
+ return *m.RecoveryFakeWord
+ }
+ return ""
+}
+
+func (m *DebugLinkState) GetRecoveryWordPos() uint32 {
+ if m != nil && m.RecoveryWordPos != nil {
+ return *m.RecoveryWordPos
+ }
+ return 0
+}
+
+// *
+// Request: Ask device to restart
+type DebugLinkStop struct {
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkStop) Reset() { *m = DebugLinkStop{} }
+func (m *DebugLinkStop) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkStop) ProtoMessage() {}
+func (*DebugLinkStop) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{67} }
+
+// *
+// Response: Device wants host to log event
+type DebugLinkLog struct {
+ Level *uint32 `protobuf:"varint,1,opt,name=level" json:"level,omitempty"`
+ Bucket *string `protobuf:"bytes,2,opt,name=bucket" json:"bucket,omitempty"`
+ Text *string `protobuf:"bytes,3,opt,name=text" json:"text,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkLog) Reset() { *m = DebugLinkLog{} }
+func (m *DebugLinkLog) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkLog) ProtoMessage() {}
+func (*DebugLinkLog) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{68} }
+
+func (m *DebugLinkLog) GetLevel() uint32 {
+ if m != nil && m.Level != nil {
+ return *m.Level
+ }
+ return 0
+}
+
+func (m *DebugLinkLog) GetBucket() string {
+ if m != nil && m.Bucket != nil {
+ return *m.Bucket
+ }
+ return ""
+}
+
+func (m *DebugLinkLog) GetText() string {
+ if m != nil && m.Text != nil {
+ return *m.Text
+ }
+ return ""
+}
+
+// *
+// Request: Read memory from device
+// @next DebugLinkMemory
+type DebugLinkMemoryRead struct {
+ Address *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"`
+ Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkMemoryRead) Reset() { *m = DebugLinkMemoryRead{} }
+func (m *DebugLinkMemoryRead) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkMemoryRead) ProtoMessage() {}
+func (*DebugLinkMemoryRead) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{69} }
+
+func (m *DebugLinkMemoryRead) GetAddress() uint32 {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return 0
+}
+
+func (m *DebugLinkMemoryRead) GetLength() uint32 {
+ if m != nil && m.Length != nil {
+ return *m.Length
+ }
+ return 0
+}
+
+// *
+// Response: Device sends memory back
+// @prev DebugLinkMemoryRead
+type DebugLinkMemory struct {
+ Memory []byte `protobuf:"bytes,1,opt,name=memory" json:"memory,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkMemory) Reset() { *m = DebugLinkMemory{} }
+func (m *DebugLinkMemory) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkMemory) ProtoMessage() {}
+func (*DebugLinkMemory) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{70} }
+
+func (m *DebugLinkMemory) GetMemory() []byte {
+ if m != nil {
+ return m.Memory
+ }
+ return nil
+}
+
+// *
+// Request: Write memory to device.
+// WARNING: Writing to the wrong location can irreparably break the device.
+type DebugLinkMemoryWrite struct {
+ Address *uint32 `protobuf:"varint,1,opt,name=address" json:"address,omitempty"`
+ Memory []byte `protobuf:"bytes,2,opt,name=memory" json:"memory,omitempty"`
+ Flash *bool `protobuf:"varint,3,opt,name=flash" json:"flash,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkMemoryWrite) Reset() { *m = DebugLinkMemoryWrite{} }
+func (m *DebugLinkMemoryWrite) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkMemoryWrite) ProtoMessage() {}
+func (*DebugLinkMemoryWrite) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{71} }
+
+func (m *DebugLinkMemoryWrite) GetAddress() uint32 {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return 0
+}
+
+func (m *DebugLinkMemoryWrite) GetMemory() []byte {
+ if m != nil {
+ return m.Memory
+ }
+ return nil
+}
+
+func (m *DebugLinkMemoryWrite) GetFlash() bool {
+ if m != nil && m.Flash != nil {
+ return *m.Flash
+ }
+ return false
+}
+
+// *
+// Request: Erase block of flash on device
+// WARNING: Writing to the wrong location can irreparably break the device.
+type DebugLinkFlashErase struct {
+ Sector *uint32 `protobuf:"varint,1,opt,name=sector" json:"sector,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *DebugLinkFlashErase) Reset() { *m = DebugLinkFlashErase{} }
+func (m *DebugLinkFlashErase) String() string { return proto.CompactTextString(m) }
+func (*DebugLinkFlashErase) ProtoMessage() {}
+func (*DebugLinkFlashErase) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{72} }
+
+func (m *DebugLinkFlashErase) GetSector() uint32 {
+ if m != nil && m.Sector != nil {
+ return *m.Sector
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Initialize)(nil), "Initialize")
+ proto.RegisterType((*GetFeatures)(nil), "GetFeatures")
+ proto.RegisterType((*Features)(nil), "Features")
+ proto.RegisterType((*ClearSession)(nil), "ClearSession")
+ proto.RegisterType((*ApplySettings)(nil), "ApplySettings")
+ proto.RegisterType((*ApplyFlags)(nil), "ApplyFlags")
+ proto.RegisterType((*ChangePin)(nil), "ChangePin")
+ proto.RegisterType((*Ping)(nil), "Ping")
+ proto.RegisterType((*Success)(nil), "Success")
+ proto.RegisterType((*Failure)(nil), "Failure")
+ proto.RegisterType((*ButtonRequest)(nil), "ButtonRequest")
+ proto.RegisterType((*ButtonAck)(nil), "ButtonAck")
+ proto.RegisterType((*PinMatrixRequest)(nil), "PinMatrixRequest")
+ proto.RegisterType((*PinMatrixAck)(nil), "PinMatrixAck")
+ proto.RegisterType((*Cancel)(nil), "Cancel")
+ proto.RegisterType((*PassphraseRequest)(nil), "PassphraseRequest")
+ proto.RegisterType((*PassphraseAck)(nil), "PassphraseAck")
+ proto.RegisterType((*GetEntropy)(nil), "GetEntropy")
+ proto.RegisterType((*Entropy)(nil), "Entropy")
+ proto.RegisterType((*GetPublicKey)(nil), "GetPublicKey")
+ proto.RegisterType((*PublicKey)(nil), "PublicKey")
+ proto.RegisterType((*GetAddress)(nil), "GetAddress")
+ proto.RegisterType((*EthereumGetAddress)(nil), "EthereumGetAddress")
+ proto.RegisterType((*Address)(nil), "Address")
+ proto.RegisterType((*EthereumAddress)(nil), "EthereumAddress")
+ proto.RegisterType((*WipeDevice)(nil), "WipeDevice")
+ proto.RegisterType((*LoadDevice)(nil), "LoadDevice")
+ proto.RegisterType((*ResetDevice)(nil), "ResetDevice")
+ proto.RegisterType((*BackupDevice)(nil), "BackupDevice")
+ proto.RegisterType((*EntropyRequest)(nil), "EntropyRequest")
+ proto.RegisterType((*EntropyAck)(nil), "EntropyAck")
+ proto.RegisterType((*RecoveryDevice)(nil), "RecoveryDevice")
+ proto.RegisterType((*WordRequest)(nil), "WordRequest")
+ proto.RegisterType((*WordAck)(nil), "WordAck")
+ proto.RegisterType((*SignMessage)(nil), "SignMessage")
+ proto.RegisterType((*VerifyMessage)(nil), "VerifyMessage")
+ proto.RegisterType((*MessageSignature)(nil), "MessageSignature")
+ proto.RegisterType((*EncryptMessage)(nil), "EncryptMessage")
+ proto.RegisterType((*EncryptedMessage)(nil), "EncryptedMessage")
+ proto.RegisterType((*DecryptMessage)(nil), "DecryptMessage")
+ proto.RegisterType((*DecryptedMessage)(nil), "DecryptedMessage")
+ proto.RegisterType((*CipherKeyValue)(nil), "CipherKeyValue")
+ proto.RegisterType((*CipheredKeyValue)(nil), "CipheredKeyValue")
+ proto.RegisterType((*EstimateTxSize)(nil), "EstimateTxSize")
+ proto.RegisterType((*TxSize)(nil), "TxSize")
+ proto.RegisterType((*SignTx)(nil), "SignTx")
+ proto.RegisterType((*SimpleSignTx)(nil), "SimpleSignTx")
+ proto.RegisterType((*TxRequest)(nil), "TxRequest")
+ proto.RegisterType((*TxAck)(nil), "TxAck")
+ proto.RegisterType((*EthereumSignTx)(nil), "EthereumSignTx")
+ proto.RegisterType((*EthereumTxRequest)(nil), "EthereumTxRequest")
+ proto.RegisterType((*EthereumTxAck)(nil), "EthereumTxAck")
+ proto.RegisterType((*EthereumSignMessage)(nil), "EthereumSignMessage")
+ proto.RegisterType((*EthereumVerifyMessage)(nil), "EthereumVerifyMessage")
+ proto.RegisterType((*EthereumMessageSignature)(nil), "EthereumMessageSignature")
+ proto.RegisterType((*SignIdentity)(nil), "SignIdentity")
+ proto.RegisterType((*SignedIdentity)(nil), "SignedIdentity")
+ proto.RegisterType((*GetECDHSessionKey)(nil), "GetECDHSessionKey")
+ proto.RegisterType((*ECDHSessionKey)(nil), "ECDHSessionKey")
+ proto.RegisterType((*SetU2FCounter)(nil), "SetU2FCounter")
+ proto.RegisterType((*FirmwareErase)(nil), "FirmwareErase")
+ proto.RegisterType((*FirmwareRequest)(nil), "FirmwareRequest")
+ proto.RegisterType((*FirmwareUpload)(nil), "FirmwareUpload")
+ proto.RegisterType((*SelfTest)(nil), "SelfTest")
+ proto.RegisterType((*DebugLinkDecision)(nil), "DebugLinkDecision")
+ proto.RegisterType((*DebugLinkGetState)(nil), "DebugLinkGetState")
+ proto.RegisterType((*DebugLinkState)(nil), "DebugLinkState")
+ proto.RegisterType((*DebugLinkStop)(nil), "DebugLinkStop")
+ proto.RegisterType((*DebugLinkLog)(nil), "DebugLinkLog")
+ proto.RegisterType((*DebugLinkMemoryRead)(nil), "DebugLinkMemoryRead")
+ proto.RegisterType((*DebugLinkMemory)(nil), "DebugLinkMemory")
+ proto.RegisterType((*DebugLinkMemoryWrite)(nil), "DebugLinkMemoryWrite")
+ proto.RegisterType((*DebugLinkFlashErase)(nil), "DebugLinkFlashErase")
+ proto.RegisterEnum("MessageType", MessageType_name, MessageType_value)
+}
+
+func init() { proto.RegisterFile("messages.proto", fileDescriptor1) }
+
+var fileDescriptor1 = []byte{
+ // 3424 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5a, 0xcb, 0x6f, 0xdc, 0x46,
+ 0x9a, 0x5f, 0x76, 0xb7, 0xfa, 0xf1, 0x35, 0xbb, 0x55, 0xa2, 0x2d, 0xbb, 0x2d, 0x5b, 0xb6, 0x4c,
+ 0xc9, 0xb6, 0x64, 0x27, 0xed, 0x44, 0x79, 0x6c, 0xd6, 0xbb, 0x79, 0xc8, 0x7a, 0xd8, 0xde, 0xd8,
+ 0x8e, 0xc0, 0x56, 0x9c, 0xdb, 0x12, 0x14, 0x59, 0xea, 0xae, 0x55, 0x37, 0xc9, 0xf0, 0xa1, 0xa8,
+ 0x7d, 0xd8, 0xeb, 0xee, 0x65, 0x81, 0xec, 0x69, 0x73, 0x1a, 0xe4, 0x36, 0x19, 0x04, 0x18, 0x0c,
+ 0x30, 0x18, 0x60, 0x72, 0x9a, 0x3f, 0x60, 0xfe, 0x8b, 0x39, 0xce, 0x1f, 0x30, 0xe7, 0x41, 0x3d,
+ 0x48, 0x16, 0x29, 0xb6, 0x6c, 0x27, 0xc0, 0x5c, 0x04, 0xd6, 0x57, 0xbf, 0xfe, 0xea, 0x7b, 0xd5,
+ 0x57, 0x5f, 0x7d, 0x25, 0xe8, 0x4e, 0x70, 0x18, 0x5a, 0x43, 0x1c, 0xf6, 0xfd, 0xc0, 0x8b, 0xbc,
+ 0xa5, 0x76, 0x34, 0xf5, 0x93, 0x81, 0xae, 0x02, 0x3c, 0x71, 0x49, 0x44, 0xac, 0x31, 0x79, 0x89,
+ 0xf5, 0x0e, 0xb4, 0x1f, 0xe1, 0x68, 0x0f, 0x5b, 0x51, 0x1c, 0xe0, 0x50, 0xff, 0x69, 0x0e, 0x9a,
+ 0xc9, 0x40, 0xbb, 0x04, 0xf5, 0x13, 0xec, 0x3a, 0x5e, 0xd0, 0x53, 0x56, 0x94, 0xf5, 0x96, 0x21,
+ 0x46, 0xda, 0x2a, 0x74, 0x26, 0xd6, 0x7f, 0x7a, 0x81, 0x79, 0x82, 0x83, 0x90, 0x78, 0x6e, 0xaf,
+ 0xb2, 0xa2, 0xac, 0x77, 0x0c, 0x95, 0x11, 0x5f, 0x70, 0x1a, 0x03, 0x11, 0x57, 0x02, 0x55, 0x05,
+ 0x88, 0x12, 0x25, 0x90, 0x6f, 0x45, 0xf6, 0x28, 0x05, 0xd5, 0x38, 0x88, 0x11, 0x13, 0xd0, 0x1d,
+ 0x98, 0x3f, 0xf4, 0xbc, 0x68, 0xec, 0x59, 0x0e, 0x0e, 0xcc, 0x89, 0xe7, 0xe0, 0xde, 0xdc, 0x8a,
+ 0xb2, 0xde, 0x34, 0xba, 0x19, 0xf9, 0x99, 0xe7, 0x60, 0xed, 0x2a, 0xb4, 0x1c, 0x7c, 0x42, 0x6c,
+ 0x6c, 0x12, 0xa7, 0x57, 0x67, 0x22, 0x37, 0x39, 0xe1, 0x89, 0xa3, 0xdd, 0x82, 0xae, 0x4f, 0x5c,
+ 0x93, 0xda, 0x00, 0xdb, 0x11, 0x5d, 0xab, 0xc1, 0x98, 0x74, 0x7c, 0xe2, 0xee, 0xa7, 0x44, 0xed,
+ 0x3d, 0x58, 0xf4, 0xad, 0x30, 0xf4, 0x47, 0x81, 0x15, 0x62, 0x19, 0xdd, 0x64, 0xe8, 0x8b, 0xd9,
+ 0xa4, 0xf4, 0xa3, 0x25, 0x68, 0x8e, 0x2d, 0x77, 0x18, 0x5b, 0x43, 0xdc, 0x6b, 0xf1, 0x75, 0x93,
+ 0xb1, 0x76, 0x11, 0xe6, 0xc6, 0xd6, 0x21, 0x1e, 0xf7, 0x80, 0x4d, 0xf0, 0x81, 0x76, 0x03, 0xe6,
+ 0x6c, 0x8f, 0xb8, 0x61, 0xaf, 0xbd, 0x52, 0x5d, 0x6f, 0x6f, 0xb6, 0xfa, 0xdb, 0x1e, 0x71, 0x0f,
+ 0xa6, 0x3e, 0x36, 0x38, 0x5d, 0x5b, 0x81, 0x36, 0x49, 0xbd, 0xe4, 0xf4, 0x54, 0xb6, 0xba, 0x4c,
+ 0xa2, 0x8b, 0x06, 0xf8, 0x84, 0x30, 0xb3, 0x75, 0x56, 0x94, 0x75, 0xd5, 0x48, 0xc7, 0x05, 0x93,
+ 0x8d, 0xac, 0x70, 0xd4, 0xeb, 0x32, 0x88, 0x64, 0xb2, 0xc7, 0x56, 0x38, 0xa2, 0x4c, 0xc8, 0xc4,
+ 0xf7, 0x82, 0x08, 0x3b, 0xbd, 0x79, 0xb6, 0x46, 0x3a, 0xd6, 0x96, 0x01, 0xa8, 0xc5, 0x6c, 0xcb,
+ 0x1e, 0x61, 0xa7, 0x87, 0xd8, 0x6c, 0xcb, 0x27, 0xee, 0x36, 0x23, 0x68, 0xf7, 0x60, 0x41, 0xb2,
+ 0x94, 0x40, 0x2d, 0x30, 0x14, 0xca, 0x26, 0x04, 0x78, 0x03, 0xd0, 0x11, 0x09, 0x26, 0xdf, 0x58,
+ 0x01, 0x35, 0x2a, 0x0e, 0xb1, 0x1b, 0xf5, 0x34, 0x86, 0x9d, 0x4f, 0xe8, 0xfb, 0x9c, 0xac, 0xdd,
+ 0x04, 0xd5, 0xc5, 0xd8, 0x09, 0xcd, 0x43, 0xcb, 0x3e, 0x8e, 0xfd, 0xde, 0x05, 0xae, 0x3a, 0xa3,
+ 0x3d, 0x64, 0x24, 0x6a, 0xd3, 0xa3, 0xb1, 0x35, 0x0c, 0x7b, 0x17, 0x59, 0xb8, 0xf0, 0x81, 0xde,
+ 0x05, 0x75, 0x7b, 0x8c, 0xad, 0x60, 0x80, 0x43, 0x6a, 0x04, 0xfd, 0x7f, 0x14, 0xe8, 0x6c, 0xf9,
+ 0xfe, 0x78, 0x3a, 0xc0, 0x51, 0x44, 0xdc, 0x61, 0x98, 0xf3, 0x93, 0x32, 0xcb, 0x4f, 0x15, 0xd9,
+ 0x4f, 0xb7, 0xa0, 0x1b, 0xd3, 0x38, 0x48, 0xf5, 0x61, 0x61, 0xdc, 0x34, 0x3a, 0x71, 0x88, 0xf7,
+ 0x53, 0xa2, 0x76, 0x1d, 0x60, 0xe4, 0x4d, 0x70, 0x68, 0x07, 0x18, 0xf3, 0x20, 0x56, 0x0d, 0x89,
+ 0xa2, 0xeb, 0x00, 0x4c, 0x92, 0x3d, 0x2a, 0x68, 0x26, 0xbe, 0x22, 0x8b, 0xbf, 0x0a, 0xad, 0xed,
+ 0x91, 0xe5, 0x0e, 0xf1, 0x3e, 0x71, 0xe9, 0xd6, 0x0b, 0xf0, 0xc4, 0x3b, 0xe1, 0x72, 0x36, 0x0d,
+ 0x31, 0xd2, 0x7f, 0xa3, 0x40, 0x6d, 0x9f, 0xb8, 0x43, 0xad, 0x07, 0x0d, 0xb1, 0xc9, 0x85, 0x26,
+ 0xc9, 0x90, 0xfa, 0xe5, 0x30, 0x8e, 0x22, 0x2f, 0x17, 0xeb, 0x15, 0xee, 0x17, 0x3e, 0x21, 0x45,
+ 0xee, 0xd9, 0x5d, 0x51, 0x7d, 0xa3, 0x5d, 0x51, 0x9b, 0xbd, 0x2b, 0xf4, 0x55, 0x68, 0x0c, 0x62,
+ 0xdb, 0xc6, 0x61, 0x38, 0x5b, 0x5a, 0x7d, 0x17, 0x1a, 0x7b, 0x16, 0x19, 0xc7, 0x01, 0xd6, 0x56,
+ 0xa0, 0x66, 0xd3, 0xcd, 0x4d, 0x11, 0xdd, 0x4d, 0xb5, 0x2f, 0xe8, 0x6c, 0x57, 0xb0, 0x19, 0x99,
+ 0x4d, 0x25, 0xcf, 0xe6, 0x73, 0xe8, 0x3c, 0x64, 0xba, 0x19, 0xf8, 0xeb, 0x18, 0x87, 0x91, 0x76,
+ 0x3b, 0xc7, 0x4c, 0xeb, 0xe7, 0x66, 0x25, 0x96, 0x1a, 0xd4, 0x1c, 0x2b, 0xb2, 0x04, 0x3f, 0xf6,
+ 0xad, 0xb7, 0xa1, 0xc5, 0xe1, 0x5b, 0xf6, 0xb1, 0xfe, 0x31, 0xa0, 0x7d, 0xe2, 0x3e, 0xb3, 0xa2,
+ 0x80, 0x9c, 0x26, 0xcc, 0x37, 0xa0, 0x46, 0x33, 0xaa, 0x60, 0xbe, 0xd8, 0x2f, 0x02, 0x38, 0x7f,
+ 0x0a, 0xd1, 0x57, 0x40, 0x4d, 0x67, 0xb7, 0xec, 0x63, 0x0d, 0x41, 0xd5, 0x27, 0x6e, 0x4f, 0x59,
+ 0xa9, 0xac, 0xb7, 0x0c, 0xfa, 0xa9, 0x37, 0xa1, 0xbe, 0x6d, 0xb9, 0x36, 0x1e, 0xeb, 0x17, 0x60,
+ 0x21, 0x8b, 0x29, 0xc1, 0x4a, 0xbf, 0x0f, 0x9d, 0x8c, 0x48, 0x39, 0x5c, 0x07, 0x90, 0xc2, 0x91,
+ 0x33, 0x92, 0x28, 0xfa, 0x0a, 0xc0, 0x23, 0x1c, 0xed, 0xba, 0x51, 0xe0, 0xf9, 0x53, 0xaa, 0x5f,
+ 0x48, 0x5e, 0x72, 0x5c, 0xc7, 0x60, 0xdf, 0xd4, 0x31, 0xc9, 0x74, 0x0f, 0x1a, 0x98, 0x7f, 0x32,
+ 0x84, 0x6a, 0x24, 0x43, 0xfd, 0x57, 0x0a, 0xa8, 0x8f, 0x70, 0xb4, 0x1f, 0x1f, 0x8e, 0x89, 0xfd,
+ 0x39, 0x9e, 0xd2, 0xec, 0x6a, 0x39, 0x4e, 0x80, 0xc3, 0xd0, 0xa4, 0xf2, 0x57, 0xd7, 0x3b, 0x46,
+ 0x53, 0x10, 0x9e, 0x6b, 0xeb, 0x80, 0xb0, 0xed, 0x84, 0x96, 0x69, 0xc7, 0xc1, 0x09, 0x36, 0x5d,
+ 0x6b, 0x92, 0xb8, 0xa8, 0xcb, 0xe8, 0xdb, 0x94, 0xfc, 0xdc, 0x9a, 0x60, 0xba, 0xbd, 0xc3, 0x91,
+ 0xf7, 0x8d, 0xe9, 0x90, 0xd0, 0x1f, 0x5b, 0x53, 0x11, 0x6f, 0x6d, 0x4a, 0xdb, 0xe1, 0x24, 0x6d,
+ 0x0d, 0x5a, 0x34, 0x09, 0x72, 0x2e, 0x34, 0xc2, 0x5a, 0x0f, 0x1a, 0x0f, 0x49, 0x44, 0x69, 0x46,
+ 0x93, 0xfe, 0xa5, 0x8c, 0xf4, 0xcf, 0xa0, 0x95, 0x09, 0x77, 0x03, 0x6a, 0x2e, 0x77, 0x77, 0x65,
+ 0xbd, 0xbd, 0xd9, 0xee, 0x3f, 0xde, 0x79, 0xee, 0x39, 0x22, 0x74, 0x5c, 0xe1, 0xe7, 0x53, 0x3f,
+ 0x3e, 0x4c, 0xfc, 0x4c, 0xbf, 0xf5, 0xbf, 0x2a, 0xcc, 0x54, 0x5b, 0x5c, 0x89, 0xf3, 0x15, 0xcc,
+ 0xc9, 0x54, 0x99, 0x21, 0xd3, 0xeb, 0x28, 0xf7, 0x01, 0x34, 0x27, 0xf1, 0x38, 0x22, 0x21, 0x19,
+ 0x32, 0xdd, 0xda, 0x9b, 0x57, 0xfa, 0xcf, 0x04, 0xc1, 0xc0, 0x0e, 0xc6, 0x93, 0x81, 0x1d, 0x10,
+ 0x9f, 0xc7, 0x50, 0x0a, 0xd5, 0x3e, 0x85, 0x76, 0xc8, 0xe8, 0x26, 0x8b, 0xbc, 0x39, 0x16, 0x79,
+ 0xa8, 0xff, 0xc4, 0xf5, 0xe3, 0x28, 0xfb, 0xc1, 0x03, 0x75, 0xb0, 0xbf, 0xfb, 0x7c, 0x67, 0x6b,
+ 0x67, 0xc7, 0xd8, 0x1d, 0x0c, 0x0c, 0x08, 0xd3, 0x19, 0xfd, 0x00, 0xb4, 0xdd, 0x68, 0x84, 0x03,
+ 0x1c, 0x4f, 0x5e, 0x57, 0xe7, 0xa2, 0x36, 0x95, 0x33, 0xda, 0xd0, 0x50, 0x4a, 0x58, 0xf5, 0xa0,
+ 0x21, 0x7e, 0x29, 0x82, 0x32, 0x19, 0xea, 0xf7, 0x60, 0x3e, 0x59, 0x7a, 0x06, 0x58, 0xcd, 0xc0,
+ 0x2a, 0xc0, 0x57, 0xc4, 0xc7, 0x3b, 0xec, 0xdc, 0xd6, 0xff, 0xaf, 0x02, 0xf0, 0xd4, 0xb3, 0x1c,
+ 0x3e, 0xa4, 0x09, 0x7c, 0xe2, 0xe2, 0x89, 0xe7, 0x12, 0x3b, 0x49, 0xe0, 0xc9, 0x38, 0x0d, 0x81,
+ 0x0a, 0x33, 0x6a, 0x49, 0x08, 0x88, 0xad, 0x57, 0x65, 0xbf, 0xa3, 0x9f, 0x3f, 0x2b, 0xad, 0x69,
+ 0xab, 0xd2, 0x21, 0x32, 0xc7, 0x03, 0x01, 0xbb, 0xc3, 0x31, 0x09, 0x47, 0x65, 0xa7, 0x49, 0x5d,
+ 0x3e, 0x4d, 0x56, 0xa1, 0x13, 0x1e, 0x13, 0xdf, 0xb4, 0x47, 0xd8, 0x3e, 0x0e, 0xe3, 0x89, 0x28,
+ 0x41, 0x54, 0x4a, 0xdc, 0x16, 0x34, 0xed, 0x06, 0xb4, 0xe3, 0xcd, 0x23, 0xd3, 0xf6, 0x62, 0x37,
+ 0xc2, 0x01, 0xab, 0x3b, 0x3a, 0x06, 0xc4, 0x9b, 0x47, 0xdb, 0x9c, 0xa2, 0xff, 0xb6, 0x02, 0x6d,
+ 0x03, 0x87, 0x38, 0x12, 0x46, 0xb9, 0x05, 0x5d, 0xe1, 0x21, 0x33, 0xb0, 0x5c, 0xc7, 0x9b, 0x88,
+ 0x33, 0xa3, 0x23, 0xa8, 0x06, 0x23, 0x6a, 0x37, 0xa0, 0x19, 0x46, 0x01, 0x76, 0x87, 0xd1, 0x88,
+ 0x17, 0x6c, 0x0f, 0xaa, 0x9b, 0x1f, 0x7c, 0x68, 0xa4, 0xc4, 0xd9, 0xd6, 0xa8, 0x9e, 0x63, 0x8d,
+ 0xb3, 0x07, 0x48, 0xad, 0xec, 0x00, 0xf9, 0x05, 0x46, 0x2b, 0xd8, 0xa3, 0x51, 0xb4, 0x07, 0x05,
+ 0x30, 0xab, 0x8a, 0x7a, 0x81, 0x17, 0x6a, 0x40, 0x49, 0xbc, 0x5c, 0xa0, 0x85, 0x01, 0xff, 0x12,
+ 0x41, 0x85, 0xa0, 0x2b, 0xf2, 0x5f, 0x92, 0x64, 0x6f, 0x03, 0x08, 0x0a, 0xcd, 0xb0, 0xb9, 0xa4,
+ 0xa8, 0xc8, 0x49, 0xf1, 0x4f, 0x15, 0xe8, 0x1a, 0xd8, 0xf6, 0x4e, 0x70, 0x30, 0x15, 0xd6, 0x5f,
+ 0x06, 0xf8, 0xc6, 0x0b, 0x1c, 0x2e, 0x9f, 0x38, 0xd1, 0x5b, 0x94, 0xc2, 0xc4, 0x9b, 0x6d, 0xd4,
+ 0xca, 0x1b, 0x19, 0xb5, 0xfa, 0x2a, 0xa3, 0xd6, 0x5e, 0x69, 0xd4, 0x39, 0xd9, 0xa8, 0x1b, 0x80,
+ 0xb0, 0x7b, 0xe4, 0x05, 0x36, 0x36, 0xa9, 0xac, 0x63, 0x12, 0x46, 0xcc, 0xea, 0x4d, 0x63, 0x5e,
+ 0xd0, 0xbf, 0x12, 0x64, 0x9a, 0x39, 0x59, 0xca, 0xe1, 0x81, 0xc8, 0xbe, 0x8b, 0x3e, 0x69, 0x9d,
+ 0xf1, 0xc9, 0x65, 0x68, 0x38, 0xc1, 0xd4, 0x0c, 0x62, 0x97, 0xd5, 0xbd, 0x4d, 0xa3, 0xee, 0x04,
+ 0x53, 0x23, 0x76, 0xf5, 0xf7, 0xa0, 0x4d, 0x39, 0x27, 0x27, 0xe9, 0x5a, 0xee, 0x24, 0x45, 0x7d,
+ 0x69, 0x4e, 0x3a, 0x44, 0x97, 0xa1, 0x41, 0x27, 0xa8, 0x6f, 0x34, 0xa8, 0x51, 0x81, 0x45, 0x8a,
+ 0x61, 0xdf, 0xfa, 0x8f, 0x0a, 0xb4, 0x07, 0x64, 0xe8, 0x3e, 0x13, 0x15, 0xd0, 0xb9, 0x49, 0x2d,
+ 0x57, 0x43, 0xb0, 0xcc, 0x93, 0x14, 0x4e, 0xb9, 0x14, 0x5f, 0x9d, 0x95, 0xe2, 0x0b, 0x89, 0xb8,
+ 0xf6, 0xc6, 0x89, 0xf8, 0xbf, 0x15, 0xe8, 0xbc, 0xc0, 0x01, 0x39, 0x9a, 0x26, 0xf2, 0xe6, 0x92,
+ 0xa1, 0x22, 0x65, 0x4e, 0xed, 0x1a, 0xb4, 0x42, 0x32, 0x74, 0xd9, 0x7d, 0x8c, 0x45, 0x8c, 0x6a,
+ 0x64, 0x04, 0x59, 0x95, 0x2a, 0x8f, 0xd3, 0x52, 0x55, 0x66, 0x9e, 0xa0, 0xff, 0x0e, 0x48, 0x88,
+ 0x30, 0x90, 0x79, 0xfe, 0x1c, 0x59, 0xf4, 0x1f, 0x14, 0xba, 0xa9, 0xec, 0x60, 0xea, 0x47, 0x89,
+ 0x5a, 0x97, 0xa0, 0xee, 0xc7, 0x87, 0xc7, 0x38, 0xd9, 0x45, 0x62, 0x54, 0xac, 0xe2, 0x24, 0xb1,
+ 0x6f, 0x82, 0x9a, 0x64, 0x32, 0xcf, 0x1d, 0xa7, 0xc7, 0xa7, 0xa0, 0x7d, 0xe1, 0x8e, 0x0b, 0x55,
+ 0x48, 0xed, 0xbc, 0x43, 0x7a, 0x6e, 0x96, 0xda, 0x2f, 0x00, 0x09, 0x49, 0xb1, 0x93, 0xc8, 0x7a,
+ 0x11, 0xe6, 0x5c, 0xcf, 0xb5, 0xb1, 0x10, 0x95, 0x0f, 0xce, 0x91, 0x54, 0x83, 0xda, 0x68, 0x62,
+ 0xd9, 0xc2, 0xee, 0xec, 0x5b, 0xff, 0x1a, 0xba, 0x3b, 0x38, 0x67, 0x81, 0x73, 0x03, 0x31, 0x5d,
+ 0xb2, 0x32, 0x63, 0xc9, 0x6a, 0xf9, 0x92, 0x35, 0x69, 0xc9, 0x3d, 0x40, 0x62, 0xc9, 0x4c, 0x95,
+ 0x42, 0xad, 0x2d, 0x71, 0x90, 0x7c, 0x5b, 0xc9, 0xf9, 0x56, 0xff, 0xb3, 0x02, 0xdd, 0x6d, 0xe2,
+ 0x8f, 0x70, 0xf0, 0x39, 0x9e, 0xbe, 0xb0, 0xc6, 0xf1, 0x2b, 0x64, 0x47, 0x50, 0xa5, 0x7e, 0xe5,
+ 0x5c, 0xe8, 0x27, 0xd5, 0xe6, 0x84, 0xfe, 0x4e, 0x48, 0xcd, 0x07, 0x3c, 0x93, 0x32, 0xf9, 0xc4,
+ 0xb1, 0x90, 0x0c, 0xb5, 0x35, 0xe8, 0x5a, 0xe1, 0xb1, 0xe9, 0xb9, 0x66, 0x02, 0xe0, 0x77, 0x7a,
+ 0xd5, 0x0a, 0x8f, 0xbf, 0x70, 0x77, 0xcf, 0xa0, 0x1c, 0xae, 0xa6, 0x48, 0x52, 0x1c, 0x25, 0x54,
+ 0xd7, 0xba, 0x50, 0x21, 0x27, 0xec, 0x60, 0x50, 0x8d, 0x0a, 0x39, 0xd1, 0xd7, 0x01, 0x71, 0x65,
+ 0xb0, 0x93, 0xaa, 0x93, 0xca, 0xa7, 0x48, 0xf2, 0xe9, 0xff, 0x05, 0xdd, 0xdd, 0x30, 0x22, 0x13,
+ 0x2b, 0xc2, 0x07, 0xa7, 0x03, 0xf2, 0x12, 0xd3, 0x23, 0xda, 0x8b, 0x23, 0x3f, 0x8e, 0xc2, 0x34,
+ 0xa3, 0xd3, 0xc2, 0x59, 0x15, 0x44, 0x9e, 0xd4, 0x6f, 0x82, 0x4a, 0x5c, 0x09, 0x53, 0x61, 0x98,
+ 0x36, 0xa7, 0x71, 0xc8, 0x6b, 0x25, 0x13, 0xfd, 0x26, 0xd4, 0xc5, 0xba, 0x97, 0xa1, 0x11, 0x9d,
+ 0x9a, 0xa2, 0x54, 0xa7, 0xd9, 0xb4, 0x1e, 0xb1, 0x09, 0xfd, 0xf7, 0x0a, 0xd4, 0xe9, 0xf6, 0x3c,
+ 0x38, 0xfd, 0xc7, 0xca, 0xa6, 0x5d, 0x85, 0x46, 0xae, 0x2b, 0xf3, 0x40, 0x79, 0xd7, 0x48, 0x28,
+ 0xda, 0x75, 0x68, 0x8d, 0x3d, 0xfb, 0xd8, 0x8c, 0x88, 0xd8, 0x69, 0x9d, 0x07, 0xca, 0x3b, 0x46,
+ 0x93, 0xd2, 0x0e, 0xc8, 0x04, 0xeb, 0x7f, 0x53, 0x40, 0x1d, 0x90, 0x89, 0x3f, 0xc6, 0x42, 0xf6,
+ 0x35, 0xa8, 0x73, 0x11, 0x58, 0x2c, 0xb5, 0x37, 0xd5, 0xfe, 0xc1, 0x29, 0xcb, 0x99, 0x2c, 0xcd,
+ 0x8b, 0x39, 0xed, 0x0e, 0x34, 0x84, 0x32, 0xbd, 0x0a, 0x83, 0x75, 0xfa, 0x07, 0xa7, 0x5f, 0x30,
+ 0x0a, 0xc3, 0x25, 0xb3, 0xda, 0xfb, 0xa0, 0x46, 0x81, 0xe5, 0x86, 0x16, 0x3b, 0x09, 0xc3, 0x5e,
+ 0x95, 0xa1, 0x51, 0xff, 0x20, 0x23, 0xb2, 0x1f, 0xe4, 0x50, 0xaf, 0x97, 0x16, 0x65, 0xc5, 0xe7,
+ 0xce, 0x57, 0xbc, 0x7e, 0x56, 0xf1, 0x5f, 0x2b, 0xd0, 0x3a, 0x48, 0x2f, 0x8a, 0xf7, 0x41, 0x0d,
+ 0xf8, 0xa7, 0x29, 0x1d, 0x73, 0x6a, 0x5f, 0x3e, 0xe2, 0xda, 0x41, 0x36, 0xd0, 0xee, 0x43, 0xc3,
+ 0xc1, 0x91, 0x45, 0xc6, 0xa1, 0xa8, 0x63, 0x17, 0xfb, 0x29, 0xb7, 0x1d, 0x3e, 0xc1, 0x0d, 0x21,
+ 0x50, 0xda, 0x47, 0x00, 0x21, 0x0e, 0x92, 0x36, 0x51, 0x95, 0xfd, 0xa6, 0x97, 0xfd, 0x66, 0x90,
+ 0xce, 0xb1, 0x9f, 0x49, 0x58, 0x7d, 0x03, 0xe6, 0x0e, 0xd8, 0x95, 0x74, 0x05, 0x2a, 0xd1, 0x29,
+ 0x13, 0xad, 0xcc, 0x82, 0x95, 0xe8, 0x54, 0xff, 0xdf, 0x0a, 0x74, 0x93, 0x0a, 0x5e, 0xf8, 0xf3,
+ 0x67, 0xa4, 0xb6, 0xab, 0xd0, 0x1a, 0x5a, 0xa1, 0xe9, 0x07, 0xc4, 0x4e, 0xd2, 0x44, 0x73, 0x68,
+ 0x85, 0xfb, 0x74, 0x9c, 0x4c, 0x8e, 0xc9, 0x84, 0x44, 0x22, 0xc5, 0xd1, 0xc9, 0xa7, 0x74, 0x4c,
+ 0x37, 0x78, 0xe4, 0x31, 0x67, 0xa8, 0x46, 0x25, 0xf2, 0xb2, 0xcd, 0x5c, 0x97, 0x93, 0xcd, 0x5b,
+ 0xa0, 0xd1, 0xeb, 0xbb, 0x29, 0x9a, 0x64, 0xa6, 0x3d, 0x8a, 0xdd, 0x63, 0x91, 0x16, 0x10, 0x9d,
+ 0x11, 0x6d, 0xcf, 0x6d, 0x4a, 0xa7, 0x25, 0x0c, 0x43, 0x8f, 0x79, 0x45, 0x2c, 0xca, 0x6c, 0x4a,
+ 0x7a, 0xca, 0xcb, 0xe1, 0x2b, 0xd0, 0xb4, 0x47, 0x16, 0x71, 0x4d, 0xe2, 0x88, 0x02, 0xa7, 0xc1,
+ 0xc6, 0x4f, 0x1c, 0xfd, 0xff, 0x15, 0x58, 0x48, 0xec, 0x91, 0x39, 0xbb, 0xc0, 0x51, 0x39, 0xc3,
+ 0x91, 0x16, 0xaa, 0xc9, 0x81, 0x69, 0x9e, 0x88, 0xae, 0x29, 0xa4, 0xa4, 0x17, 0x79, 0x40, 0x20,
+ 0x6c, 0x94, 0x01, 0x8c, 0x3c, 0x20, 0x4c, 0x1a, 0x4d, 0x29, 0x69, 0xa0, 0xf7, 0xa1, 0x93, 0x09,
+ 0x46, 0x9d, 0xbb, 0x0c, 0x4c, 0x02, 0x61, 0x0c, 0x9e, 0xfc, 0x5a, 0x94, 0xc2, 0xac, 0xa0, 0x3f,
+ 0x85, 0x0b, 0xb2, 0x63, 0x7f, 0x59, 0x05, 0xa5, 0x13, 0x58, 0x4c, 0xb8, 0x9d, 0x5b, 0xe1, 0xa8,
+ 0xbf, 0xb8, 0xc2, 0xd1, 0x0d, 0xe8, 0x25, 0x4b, 0xbd, 0xaa, 0x86, 0x79, 0xdd, 0xd5, 0xf4, 0x9f,
+ 0x58, 0xd2, 0x1a, 0xba, 0x4f, 0x1c, 0xec, 0x46, 0x24, 0x9a, 0x6a, 0x1b, 0xd0, 0x24, 0xe2, 0x5b,
+ 0xec, 0x8f, 0x4e, 0x3f, 0x99, 0xe4, 0xf7, 0x73, 0x92, 0x41, 0x91, 0x3d, 0xb2, 0xc6, 0xd4, 0xf7,
+ 0xd8, 0x1c, 0x11, 0xc7, 0xc1, 0xae, 0x58, 0x60, 0x3e, 0xa5, 0x3f, 0x66, 0xe4, 0x3c, 0xf4, 0x84,
+ 0x84, 0xb1, 0x35, 0x16, 0x97, 0xd2, 0x0c, 0xfa, 0x82, 0x91, 0x4b, 0xdb, 0x2a, 0xb5, 0xb2, 0xb6,
+ 0x8a, 0x3e, 0x84, 0x2e, 0x15, 0x1d, 0x3b, 0xa9, 0xf0, 0xb3, 0x2b, 0xb9, 0x65, 0x00, 0x9f, 0x75,
+ 0x4e, 0xcc, 0xe4, 0x10, 0x57, 0x8d, 0x96, 0x9f, 0xf6, 0x52, 0x72, 0x46, 0xaa, 0x16, 0x8d, 0xf4,
+ 0xad, 0x02, 0x0b, 0x8f, 0x70, 0xb4, 0xbb, 0xbd, 0xf3, 0x58, 0x34, 0x5a, 0xe9, 0x6f, 0xde, 0xc0,
+ 0x52, 0xb7, 0x61, 0xde, 0xc7, 0x38, 0x30, 0xcf, 0x88, 0xd0, 0xa1, 0xe4, 0xac, 0xa5, 0x53, 0xa6,
+ 0x7b, 0xb5, 0x54, 0xf7, 0x77, 0xa1, 0x5b, 0x10, 0x87, 0xee, 0x13, 0x3e, 0x32, 0xb3, 0xfa, 0x13,
+ 0xc2, 0x14, 0xa0, 0xbf, 0x03, 0x9d, 0x01, 0x8e, 0xbe, 0xdc, 0xdc, 0x93, 0x2e, 0x91, 0xf2, 0x8d,
+ 0x46, 0x39, 0x73, 0xeb, 0xbe, 0x03, 0x9d, 0x3d, 0xd1, 0xa9, 0xde, 0x65, 0x3d, 0xdf, 0x4b, 0x50,
+ 0xcf, 0xed, 0x74, 0x31, 0xd2, 0xb7, 0x60, 0x3e, 0x01, 0x26, 0x99, 0xe1, 0x12, 0xd4, 0xbd, 0xa3,
+ 0xa3, 0x10, 0x27, 0xf7, 0x43, 0x31, 0x92, 0x58, 0x54, 0x72, 0x2c, 0x3e, 0x81, 0x6e, 0xc2, 0xe2,
+ 0x4b, 0x7f, 0xec, 0x59, 0x0e, 0x75, 0xa6, 0x6f, 0x4d, 0xe9, 0x67, 0xd2, 0x2f, 0x11, 0x43, 0x56,
+ 0x16, 0x5a, 0xe1, 0x48, 0xd8, 0x90, 0x7d, 0xeb, 0x6b, 0xd0, 0x1c, 0xe0, 0xf1, 0xd1, 0x01, 0x5d,
+ 0x3b, 0xf7, 0x4b, 0x45, 0xfa, 0xa5, 0x7e, 0x17, 0x16, 0x76, 0xf0, 0x61, 0x3c, 0x7c, 0x4a, 0xdc,
+ 0xe3, 0x1d, 0x6c, 0xf3, 0x97, 0x83, 0x45, 0xa8, 0x4f, 0x71, 0x68, 0xba, 0x1e, 0x5b, 0xa7, 0x69,
+ 0xcc, 0x4d, 0x71, 0xf8, 0xdc, 0xd3, 0x2f, 0x48, 0xd8, 0x47, 0x38, 0x1a, 0x44, 0x56, 0x84, 0xf5,
+ 0xbf, 0x54, 0x68, 0xc5, 0x2b, 0xa8, 0x8c, 0xc4, 0x34, 0xb2, 0xa6, 0x5e, 0x1c, 0x25, 0x35, 0x3f,
+ 0x1f, 0x25, 0xbd, 0x97, 0x4a, 0xd6, 0x7b, 0xb9, 0x04, 0xf5, 0x09, 0xeb, 0x8a, 0x0a, 0xa7, 0x8a,
+ 0x51, 0xae, 0xc5, 0x53, 0x9b, 0xd1, 0xe2, 0x99, 0x9b, 0xd5, 0xe2, 0x99, 0x79, 0xdb, 0xae, 0x9f,
+ 0x73, 0xdb, 0x5e, 0x06, 0x08, 0x70, 0x88, 0x23, 0x76, 0x13, 0x66, 0xe7, 0x45, 0xcb, 0x68, 0x31,
+ 0x0a, 0xbd, 0x74, 0xd2, 0xaa, 0x8b, 0x4f, 0x27, 0x3d, 0x81, 0x26, 0xd3, 0x4c, 0x65, 0xc4, 0xa4,
+ 0x8f, 0xfa, 0x16, 0x68, 0x81, 0xe8, 0x0b, 0x98, 0x47, 0xd6, 0x31, 0xbf, 0x55, 0x8b, 0xb7, 0x20,
+ 0x94, 0xcc, 0xec, 0x59, 0xc7, 0xec, 0x5a, 0xad, 0xdd, 0x85, 0x85, 0x14, 0xcd, 0x9a, 0x07, 0xbe,
+ 0x17, 0xb2, 0x7b, 0x72, 0xc7, 0x98, 0x4f, 0x26, 0x28, 0x70, 0xdf, 0x0b, 0xf5, 0x79, 0xe8, 0x48,
+ 0x36, 0xf6, 0x7c, 0x7d, 0x1f, 0xd4, 0x94, 0xf0, 0xd4, 0x1b, 0xb2, 0x0b, 0x3e, 0x3e, 0xc1, 0xe3,
+ 0xe4, 0x35, 0x81, 0x0d, 0xa8, 0x79, 0x0f, 0x63, 0xfb, 0x18, 0x47, 0xc2, 0xe6, 0x62, 0xc4, 0x6e,
+ 0xf3, 0xf8, 0x34, 0x12, 0x46, 0x67, 0xdf, 0xfa, 0x23, 0xb8, 0x90, 0x72, 0x7c, 0x86, 0x27, 0x5e,
+ 0x30, 0x35, 0x30, 0x8f, 0x39, 0x39, 0x81, 0x74, 0xb2, 0x04, 0x32, 0x2b, 0x6e, 0x37, 0x60, 0xbe,
+ 0xc0, 0x88, 0xb9, 0x99, 0x7d, 0x25, 0x01, 0xc1, 0x47, 0xfa, 0x7f, 0xc0, 0xc5, 0x02, 0xf4, 0xab,
+ 0x80, 0x44, 0xf8, 0xfc, 0x45, 0x05, 0xa7, 0x8a, 0xcc, 0x49, 0xbc, 0xa6, 0x84, 0x23, 0x71, 0x5b,
+ 0xe4, 0x03, 0xfd, 0x6d, 0x49, 0xa7, 0x3d, 0x4a, 0x49, 0x37, 0x6d, 0x88, 0xed, 0xc8, 0x4b, 0x76,
+ 0xb8, 0x18, 0xdd, 0xfd, 0x71, 0x11, 0xda, 0xe2, 0x1c, 0x61, 0x75, 0xd8, 0x0a, 0x5c, 0x92, 0x86,
+ 0x66, 0xf6, 0x60, 0x8a, 0xfe, 0x69, 0xa9, 0xf6, 0xed, 0x1f, 0x7a, 0x8a, 0xb6, 0x94, 0x5e, 0x9e,
+ 0x19, 0x62, 0x9f, 0xb8, 0x43, 0xa4, 0x88, 0xb9, 0x65, 0xb8, 0x20, 0xcf, 0x89, 0x57, 0x10, 0x54,
+ 0x59, 0xaa, 0x7d, 0x57, 0x32, 0x2d, 0xde, 0x39, 0x50, 0x55, 0x4c, 0xdf, 0x80, 0x45, 0x79, 0x3a,
+ 0x7d, 0x14, 0x42, 0x35, 0xc1, 0xbe, 0x20, 0x5c, 0xd6, 0x2e, 0x45, 0x73, 0x02, 0x71, 0x07, 0xae,
+ 0xe4, 0x56, 0x90, 0x13, 0x17, 0xaa, 0x2f, 0x35, 0x29, 0xe8, 0x8f, 0x14, 0xb8, 0x0e, 0x4b, 0x65,
+ 0x40, 0x9e, 0x75, 0x50, 0x43, 0x42, 0x6e, 0xc0, 0xd5, 0x32, 0xa4, 0x48, 0x71, 0xa8, 0xb9, 0xd4,
+ 0xfc, 0x2e, 0x81, 0x16, 0xe4, 0xcb, 0x5e, 0x23, 0x50, 0xab, 0xdc, 0x40, 0xc9, 0x34, 0x08, 0x0b,
+ 0xe8, 0xd0, 0x2b, 0x30, 0x48, 0x8f, 0x05, 0xd4, 0x16, 0x2c, 0x0a, 0x56, 0xca, 0x00, 0xaa, 0x60,
+ 0x52, 0x90, 0x22, 0xeb, 0x22, 0xa3, 0x8e, 0x60, 0x71, 0x13, 0x2e, 0xcb, 0x08, 0xa9, 0xa7, 0x8a,
+ 0xba, 0x02, 0x72, 0x0d, 0xb4, 0x9c, 0x27, 0x59, 0xf1, 0x8b, 0xe6, 0xc5, 0xec, 0x5a, 0x5e, 0x4e,
+ 0xf9, 0xc2, 0x83, 0xd0, 0x52, 0x9d, 0x62, 0x9a, 0x8a, 0x76, 0x1d, 0x2e, 0xe6, 0x2c, 0x27, 0x9e,
+ 0xd7, 0xd1, 0x82, 0x10, 0xf4, 0x36, 0x5c, 0x2b, 0x44, 0x52, 0xee, 0x31, 0x09, 0x69, 0x29, 0xae,
+ 0x57, 0x8a, 0xdb, 0xb2, 0x8f, 0xd1, 0x05, 0xee, 0xa9, 0xdf, 0x95, 0xc8, 0xcc, 0x1f, 0x97, 0xd0,
+ 0xc5, 0x72, 0xbb, 0xa5, 0xe5, 0x2b, 0x5a, 0x14, 0xcb, 0x5c, 0x85, 0x85, 0x3c, 0x80, 0xf2, 0xbf,
+ 0x94, 0x6a, 0x9c, 0x8b, 0x97, 0x7c, 0xcf, 0x00, 0x5d, 0x16, 0xa8, 0x82, 0xff, 0xe4, 0x57, 0x59,
+ 0xd4, 0x13, 0x98, 0xd5, 0x7c, 0x88, 0xe6, 0x1e, 0x6a, 0xd1, 0x95, 0x72, 0x50, 0xee, 0x11, 0x0f,
+ 0x2d, 0x09, 0x81, 0x57, 0xf3, 0x1a, 0xa5, 0x4f, 0x77, 0xe8, 0xaa, 0x64, 0x94, 0x42, 0x34, 0x64,
+ 0xaf, 0xb1, 0xe8, 0x5a, 0xf9, 0xae, 0xca, 0x1e, 0x49, 0xd0, 0x72, 0x79, 0xd4, 0x26, 0xd3, 0xd7,
+ 0xd3, 0xa8, 0xcd, 0xf9, 0x39, 0x39, 0x81, 0xd1, 0x8a, 0xb4, 0x8b, 0x0a, 0x96, 0x91, 0xdb, 0xd2,
+ 0x48, 0x2f, 0xb7, 0x71, 0xbe, 0x55, 0x8d, 0x56, 0xcb, 0xc3, 0x3b, 0x6b, 0x5f, 0xa3, 0xb5, 0xf2,
+ 0xf0, 0x96, 0xea, 0x7b, 0x74, 0xbb, 0xdc, 0xbe, 0xb9, 0xa2, 0x1d, 0xdd, 0x11, 0xa0, 0x42, 0x7c,
+ 0x16, 0xcb, 0x6d, 0xb4, 0x2e, 0x24, 0xba, 0x03, 0xcb, 0xb9, 0xf8, 0x2c, 0x3e, 0x65, 0xa2, 0x8d,
+ 0x14, 0x78, 0xa5, 0x1c, 0x48, 0xa5, 0xbf, 0x2b, 0x39, 0xed, 0x76, 0xc1, 0x12, 0xb9, 0x56, 0x0d,
+ 0xba, 0x27, 0xed, 0x30, 0x2d, 0x1f, 0xb2, 0x6c, 0xfe, 0xad, 0xa5, 0xfa, 0x77, 0x7c, 0xbe, 0x60,
+ 0xd1, 0x7c, 0x07, 0x1f, 0xbd, 0x5d, 0x6e, 0x2f, 0xa9, 0x15, 0x8d, 0xfa, 0xe5, 0x99, 0x5b, 0x34,
+ 0xa5, 0xd1, 0xfd, 0x72, 0x4b, 0x15, 0x9b, 0x50, 0xe8, 0x9d, 0x74, 0x27, 0x17, 0x3c, 0x2c, 0x77,
+ 0x0d, 0xd1, 0xbb, 0xa9, 0x5e, 0xeb, 0x79, 0x7e, 0xc5, 0xae, 0x25, 0xda, 0x4c, 0x35, 0x2c, 0x70,
+ 0xcc, 0xf7, 0x21, 0xd1, 0x7b, 0xb3, 0x38, 0x16, 0x9b, 0x87, 0xe8, 0xfd, 0x94, 0xa3, 0x5e, 0xcc,
+ 0x6d, 0xd9, 0xbd, 0x08, 0x7d, 0x50, 0x1e, 0xa9, 0xf9, 0x0b, 0x08, 0xfa, 0x50, 0x68, 0x5b, 0xb0,
+ 0xab, 0xf4, 0xef, 0x46, 0xe8, 0x9f, 0x05, 0xa3, 0x75, 0xb8, 0x9e, 0x53, 0xf4, 0xcc, 0x43, 0x25,
+ 0xfa, 0x48, 0x20, 0x6f, 0xe5, 0x8f, 0xa1, 0xc2, 0xbb, 0x22, 0xfa, 0x17, 0xb1, 0x66, 0x71, 0x0f,
+ 0xe5, 0x9a, 0x17, 0xe8, 0x41, 0x7a, 0x4c, 0x2e, 0x97, 0xa1, 0xb2, 0x9c, 0xf8, 0xaf, 0x69, 0x8a,
+ 0xb9, 0x52, 0x0e, 0xa4, 0xde, 0xff, 0xb7, 0x72, 0x6e, 0x67, 0x2e, 0x49, 0xe8, 0xe3, 0x19, 0x1b,
+ 0x3c, 0x8f, 0xfa, 0xa4, 0x7c, 0xcd, 0xdc, 0x75, 0x05, 0x7d, 0x2a, 0x58, 0x6d, 0xc0, 0x8d, 0x59,
+ 0x7a, 0x26, 0x2e, 0xfd, 0x4c, 0x40, 0xef, 0xc1, 0xcd, 0x32, 0x68, 0x7e, 0xcf, 0x6f, 0x09, 0x70,
+ 0x1f, 0xd6, 0xca, 0xc0, 0x67, 0xf6, 0xfe, 0x43, 0x21, 0xec, 0xbd, 0xbc, 0xee, 0x67, 0xee, 0x15,
+ 0xc8, 0x59, 0x6a, 0x7e, 0x9f, 0x6c, 0xeb, 0x3b, 0x33, 0xc0, 0xc9, 0xc5, 0x02, 0xe1, 0xa5, 0xda,
+ 0xf7, 0x25, 0x86, 0xca, 0xdf, 0x35, 0xd0, 0xd1, 0x52, 0xed, 0x87, 0x12, 0x43, 0xe5, 0xaa, 0x65,
+ 0x34, 0x14, 0xac, 0x0a, 0xe1, 0x2c, 0x57, 0xd0, 0x68, 0x24, 0x18, 0x15, 0x8c, 0x59, 0x52, 0x13,
+ 0x23, 0x57, 0xb0, 0x2b, 0x84, 0x61, 0x01, 0x8a, 0x3c, 0xc1, 0xf1, 0x2e, 0xac, 0x9c, 0x03, 0x63,
+ 0x15, 0x2f, 0xf2, 0x05, 0xcb, 0x59, 0xab, 0x67, 0xd5, 0x2b, 0xfa, 0x9a, 0x43, 0x1f, 0xbe, 0x0f,
+ 0xab, 0xb6, 0x37, 0xe9, 0x87, 0x56, 0xe4, 0x85, 0x23, 0x32, 0xb6, 0x0e, 0xc3, 0x7e, 0x14, 0xe0,
+ 0x97, 0x5e, 0xd0, 0x1f, 0x93, 0x43, 0xfe, 0x6f, 0x7e, 0x87, 0xf1, 0xd1, 0xc3, 0xce, 0x01, 0x23,
+ 0x0a, 0xae, 0x7f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x2a, 0xe4, 0xc0, 0x85, 0x16, 0x28, 0x00, 0x00,
+}
diff --git a/accounts/usbwallet/internal/trezor/messages.proto b/accounts/usbwallet/internal/trezor/messages.proto
new file mode 100644
index 000000000..178956457
--- /dev/null
+++ b/accounts/usbwallet/internal/trezor/messages.proto
@@ -0,0 +1,903 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/messages.proto
+// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b.
+
+/**
+ * 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_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_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];
+}
+
+////////////////////
+// Basic messages //
+////////////////////
+
+/**
+ * Request: Reset device to default state and ask for device details
+ * @next Features
+ */
+message Initialize {
+}
+
+/**
+ * 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. "bitcointrezor.com"
+ optional uint32 major_version = 2; // major version of the device, e.g. 1
+ optional uint32 minor_version = 3; // minor version of the device, e.g. 0
+ optional uint32 patch_version = 4; // patch version of the device, 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
+ repeated CoinType coins = 11; // supported coins
+ 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)
+}
+
+/**
+ * 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;
+}
+
+/**
+ * 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 {
+}
+
+/**
+ * Request: Send passphrase back
+ * @prev PassphraseRequest
+ */
+message PassphraseAck {
+ required string passphrase = 1;
+}
+
+/**
+ * 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
+}
+
+/**
+ * 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
+}
+
+/**
+ * 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
+}
+
+/////////////////////////////////////////////////////////////
+// Debug messages (only available if DebugLink is enabled) //
+/////////////////////////////////////////////////////////////
+
+/**
+ * Request: "Press" the button on the device
+ * @next Success
+ */
+message DebugLinkDecision {
+ required bool yes_no = 1; // true for "Confirm", false for "Cancel"
+}
+
+/**
+ * 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
+}
+
+/**
+ * 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;
+}
diff --git a/accounts/usbwallet/internal/trezor/trezor.go b/accounts/usbwallet/internal/trezor/trezor.go
new file mode 100644
index 000000000..487aeb5f8
--- /dev/null
+++ b/accounts/usbwallet/internal/trezor/trezor.go
@@ -0,0 +1,46 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// This file contains the implementation for interacting with the Trezor hardware
+// wallets. The wire protocol spec can be found on the SatoshiLabs website:
+// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html
+
+//go:generate protoc --go_out=Mgoogle/protobuf/descriptor.proto=github.com/golang/protobuf/protoc-gen-go/descriptor,import_path=trezor:. types.proto messages.proto
+
+// Package trezor contains the wire protocol wrapper in Go.
+package trezor
+
+import (
+ "reflect"
+
+ "github.com/golang/protobuf/proto"
+)
+
+// Type returns the protocol buffer type number of a specific message. If the
+// message is nil, this method panics!
+func Type(msg proto.Message) uint16 {
+ return uint16(MessageType_value["MessageType_"+reflect.TypeOf(msg).Elem().Name()])
+}
+
+// Name returns the friendly message type name of a specific protocol buffer
+// type numbers.
+func Name(kind uint16) string {
+ name := MessageType_name[int32(kind)]
+ if len(name) < 12 {
+ return name
+ }
+ return name[12:]
+}
diff --git a/accounts/usbwallet/internal/trezor/types.pb.go b/accounts/usbwallet/internal/trezor/types.pb.go
new file mode 100644
index 000000000..25b7672d2
--- /dev/null
+++ b/accounts/usbwallet/internal/trezor/types.pb.go
@@ -0,0 +1,1333 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: types.proto
+
+/*
+Package trezor is a generated protocol buffer package.
+
+It is generated from these files:
+ types.proto
+ messages.proto
+
+It has these top-level messages:
+ HDNodeType
+ HDNodePathType
+ CoinType
+ MultisigRedeemScriptType
+ TxInputType
+ TxOutputType
+ TxOutputBinType
+ TransactionType
+ TxRequestDetailsType
+ TxRequestSerializedType
+ IdentityType
+ Initialize
+ GetFeatures
+ Features
+ ClearSession
+ ApplySettings
+ ApplyFlags
+ ChangePin
+ Ping
+ Success
+ Failure
+ ButtonRequest
+ ButtonAck
+ PinMatrixRequest
+ PinMatrixAck
+ Cancel
+ PassphraseRequest
+ PassphraseAck
+ GetEntropy
+ Entropy
+ GetPublicKey
+ PublicKey
+ GetAddress
+ EthereumGetAddress
+ Address
+ EthereumAddress
+ WipeDevice
+ LoadDevice
+ ResetDevice
+ BackupDevice
+ EntropyRequest
+ EntropyAck
+ RecoveryDevice
+ WordRequest
+ WordAck
+ SignMessage
+ VerifyMessage
+ MessageSignature
+ EncryptMessage
+ EncryptedMessage
+ DecryptMessage
+ DecryptedMessage
+ CipherKeyValue
+ CipheredKeyValue
+ EstimateTxSize
+ TxSize
+ SignTx
+ SimpleSignTx
+ TxRequest
+ TxAck
+ EthereumSignTx
+ EthereumTxRequest
+ EthereumTxAck
+ EthereumSignMessage
+ EthereumVerifyMessage
+ EthereumMessageSignature
+ SignIdentity
+ SignedIdentity
+ GetECDHSessionKey
+ ECDHSessionKey
+ SetU2FCounter
+ FirmwareErase
+ FirmwareRequest
+ FirmwareUpload
+ SelfTest
+ DebugLinkDecision
+ DebugLinkGetState
+ DebugLinkState
+ DebugLinkStop
+ DebugLinkLog
+ DebugLinkMemoryRead
+ DebugLinkMemory
+ DebugLinkMemoryWrite
+ DebugLinkFlashErase
+*/
+package trezor
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import google_protobuf "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// *
+// Type of failures returned by Failure message
+// @used_in Failure
+type FailureType int32
+
+const (
+ FailureType_Failure_UnexpectedMessage FailureType = 1
+ FailureType_Failure_ButtonExpected FailureType = 2
+ FailureType_Failure_DataError FailureType = 3
+ FailureType_Failure_ActionCancelled FailureType = 4
+ FailureType_Failure_PinExpected FailureType = 5
+ FailureType_Failure_PinCancelled FailureType = 6
+ FailureType_Failure_PinInvalid FailureType = 7
+ FailureType_Failure_InvalidSignature FailureType = 8
+ FailureType_Failure_ProcessError FailureType = 9
+ FailureType_Failure_NotEnoughFunds FailureType = 10
+ FailureType_Failure_NotInitialized FailureType = 11
+ FailureType_Failure_FirmwareError FailureType = 99
+)
+
+var FailureType_name = map[int32]string{
+ 1: "Failure_UnexpectedMessage",
+ 2: "Failure_ButtonExpected",
+ 3: "Failure_DataError",
+ 4: "Failure_ActionCancelled",
+ 5: "Failure_PinExpected",
+ 6: "Failure_PinCancelled",
+ 7: "Failure_PinInvalid",
+ 8: "Failure_InvalidSignature",
+ 9: "Failure_ProcessError",
+ 10: "Failure_NotEnoughFunds",
+ 11: "Failure_NotInitialized",
+ 99: "Failure_FirmwareError",
+}
+var FailureType_value = map[string]int32{
+ "Failure_UnexpectedMessage": 1,
+ "Failure_ButtonExpected": 2,
+ "Failure_DataError": 3,
+ "Failure_ActionCancelled": 4,
+ "Failure_PinExpected": 5,
+ "Failure_PinCancelled": 6,
+ "Failure_PinInvalid": 7,
+ "Failure_InvalidSignature": 8,
+ "Failure_ProcessError": 9,
+ "Failure_NotEnoughFunds": 10,
+ "Failure_NotInitialized": 11,
+ "Failure_FirmwareError": 99,
+}
+
+func (x FailureType) Enum() *FailureType {
+ p := new(FailureType)
+ *p = x
+ return p
+}
+func (x FailureType) String() string {
+ return proto.EnumName(FailureType_name, int32(x))
+}
+func (x *FailureType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(FailureType_value, data, "FailureType")
+ if err != nil {
+ return err
+ }
+ *x = FailureType(value)
+ return nil
+}
+func (FailureType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+// *
+// Type of script which will be used for transaction output
+// @used_in TxOutputType
+type OutputScriptType int32
+
+const (
+ OutputScriptType_PAYTOADDRESS OutputScriptType = 0
+ OutputScriptType_PAYTOSCRIPTHASH OutputScriptType = 1
+ OutputScriptType_PAYTOMULTISIG OutputScriptType = 2
+ OutputScriptType_PAYTOOPRETURN OutputScriptType = 3
+ OutputScriptType_PAYTOWITNESS OutputScriptType = 4
+ OutputScriptType_PAYTOP2SHWITNESS OutputScriptType = 5
+)
+
+var OutputScriptType_name = map[int32]string{
+ 0: "PAYTOADDRESS",
+ 1: "PAYTOSCRIPTHASH",
+ 2: "PAYTOMULTISIG",
+ 3: "PAYTOOPRETURN",
+ 4: "PAYTOWITNESS",
+ 5: "PAYTOP2SHWITNESS",
+}
+var OutputScriptType_value = map[string]int32{
+ "PAYTOADDRESS": 0,
+ "PAYTOSCRIPTHASH": 1,
+ "PAYTOMULTISIG": 2,
+ "PAYTOOPRETURN": 3,
+ "PAYTOWITNESS": 4,
+ "PAYTOP2SHWITNESS": 5,
+}
+
+func (x OutputScriptType) Enum() *OutputScriptType {
+ p := new(OutputScriptType)
+ *p = x
+ return p
+}
+func (x OutputScriptType) String() string {
+ return proto.EnumName(OutputScriptType_name, int32(x))
+}
+func (x *OutputScriptType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(OutputScriptType_value, data, "OutputScriptType")
+ if err != nil {
+ return err
+ }
+ *x = OutputScriptType(value)
+ return nil
+}
+func (OutputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+// *
+// Type of script which will be used for transaction output
+// @used_in TxInputType
+type InputScriptType int32
+
+const (
+ InputScriptType_SPENDADDRESS InputScriptType = 0
+ InputScriptType_SPENDMULTISIG InputScriptType = 1
+ InputScriptType_EXTERNAL InputScriptType = 2
+ InputScriptType_SPENDWITNESS InputScriptType = 3
+ InputScriptType_SPENDP2SHWITNESS InputScriptType = 4
+)
+
+var InputScriptType_name = map[int32]string{
+ 0: "SPENDADDRESS",
+ 1: "SPENDMULTISIG",
+ 2: "EXTERNAL",
+ 3: "SPENDWITNESS",
+ 4: "SPENDP2SHWITNESS",
+}
+var InputScriptType_value = map[string]int32{
+ "SPENDADDRESS": 0,
+ "SPENDMULTISIG": 1,
+ "EXTERNAL": 2,
+ "SPENDWITNESS": 3,
+ "SPENDP2SHWITNESS": 4,
+}
+
+func (x InputScriptType) Enum() *InputScriptType {
+ p := new(InputScriptType)
+ *p = x
+ return p
+}
+func (x InputScriptType) String() string {
+ return proto.EnumName(InputScriptType_name, int32(x))
+}
+func (x *InputScriptType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(InputScriptType_value, data, "InputScriptType")
+ if err != nil {
+ return err
+ }
+ *x = InputScriptType(value)
+ return nil
+}
+func (InputScriptType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+// *
+// Type of information required by transaction signing process
+// @used_in TxRequest
+type RequestType int32
+
+const (
+ RequestType_TXINPUT RequestType = 0
+ RequestType_TXOUTPUT RequestType = 1
+ RequestType_TXMETA RequestType = 2
+ RequestType_TXFINISHED RequestType = 3
+ RequestType_TXEXTRADATA RequestType = 4
+)
+
+var RequestType_name = map[int32]string{
+ 0: "TXINPUT",
+ 1: "TXOUTPUT",
+ 2: "TXMETA",
+ 3: "TXFINISHED",
+ 4: "TXEXTRADATA",
+}
+var RequestType_value = map[string]int32{
+ "TXINPUT": 0,
+ "TXOUTPUT": 1,
+ "TXMETA": 2,
+ "TXFINISHED": 3,
+ "TXEXTRADATA": 4,
+}
+
+func (x RequestType) Enum() *RequestType {
+ p := new(RequestType)
+ *p = x
+ return p
+}
+func (x RequestType) String() string {
+ return proto.EnumName(RequestType_name, int32(x))
+}
+func (x *RequestType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(RequestType_value, data, "RequestType")
+ if err != nil {
+ return err
+ }
+ *x = RequestType(value)
+ return nil
+}
+func (RequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+// *
+// Type of button request
+// @used_in ButtonRequest
+type ButtonRequestType int32
+
+const (
+ ButtonRequestType_ButtonRequest_Other ButtonRequestType = 1
+ ButtonRequestType_ButtonRequest_FeeOverThreshold ButtonRequestType = 2
+ ButtonRequestType_ButtonRequest_ConfirmOutput ButtonRequestType = 3
+ ButtonRequestType_ButtonRequest_ResetDevice ButtonRequestType = 4
+ ButtonRequestType_ButtonRequest_ConfirmWord ButtonRequestType = 5
+ ButtonRequestType_ButtonRequest_WipeDevice ButtonRequestType = 6
+ ButtonRequestType_ButtonRequest_ProtectCall ButtonRequestType = 7
+ ButtonRequestType_ButtonRequest_SignTx ButtonRequestType = 8
+ ButtonRequestType_ButtonRequest_FirmwareCheck ButtonRequestType = 9
+ ButtonRequestType_ButtonRequest_Address ButtonRequestType = 10
+ ButtonRequestType_ButtonRequest_PublicKey ButtonRequestType = 11
+)
+
+var ButtonRequestType_name = map[int32]string{
+ 1: "ButtonRequest_Other",
+ 2: "ButtonRequest_FeeOverThreshold",
+ 3: "ButtonRequest_ConfirmOutput",
+ 4: "ButtonRequest_ResetDevice",
+ 5: "ButtonRequest_ConfirmWord",
+ 6: "ButtonRequest_WipeDevice",
+ 7: "ButtonRequest_ProtectCall",
+ 8: "ButtonRequest_SignTx",
+ 9: "ButtonRequest_FirmwareCheck",
+ 10: "ButtonRequest_Address",
+ 11: "ButtonRequest_PublicKey",
+}
+var ButtonRequestType_value = map[string]int32{
+ "ButtonRequest_Other": 1,
+ "ButtonRequest_FeeOverThreshold": 2,
+ "ButtonRequest_ConfirmOutput": 3,
+ "ButtonRequest_ResetDevice": 4,
+ "ButtonRequest_ConfirmWord": 5,
+ "ButtonRequest_WipeDevice": 6,
+ "ButtonRequest_ProtectCall": 7,
+ "ButtonRequest_SignTx": 8,
+ "ButtonRequest_FirmwareCheck": 9,
+ "ButtonRequest_Address": 10,
+ "ButtonRequest_PublicKey": 11,
+}
+
+func (x ButtonRequestType) Enum() *ButtonRequestType {
+ p := new(ButtonRequestType)
+ *p = x
+ return p
+}
+func (x ButtonRequestType) String() string {
+ return proto.EnumName(ButtonRequestType_name, int32(x))
+}
+func (x *ButtonRequestType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(ButtonRequestType_value, data, "ButtonRequestType")
+ if err != nil {
+ return err
+ }
+ *x = ButtonRequestType(value)
+ return nil
+}
+func (ButtonRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+// *
+// Type of PIN request
+// @used_in PinMatrixRequest
+type PinMatrixRequestType int32
+
+const (
+ PinMatrixRequestType_PinMatrixRequestType_Current PinMatrixRequestType = 1
+ PinMatrixRequestType_PinMatrixRequestType_NewFirst PinMatrixRequestType = 2
+ PinMatrixRequestType_PinMatrixRequestType_NewSecond PinMatrixRequestType = 3
+)
+
+var PinMatrixRequestType_name = map[int32]string{
+ 1: "PinMatrixRequestType_Current",
+ 2: "PinMatrixRequestType_NewFirst",
+ 3: "PinMatrixRequestType_NewSecond",
+}
+var PinMatrixRequestType_value = map[string]int32{
+ "PinMatrixRequestType_Current": 1,
+ "PinMatrixRequestType_NewFirst": 2,
+ "PinMatrixRequestType_NewSecond": 3,
+}
+
+func (x PinMatrixRequestType) Enum() *PinMatrixRequestType {
+ p := new(PinMatrixRequestType)
+ *p = x
+ return p
+}
+func (x PinMatrixRequestType) String() string {
+ return proto.EnumName(PinMatrixRequestType_name, int32(x))
+}
+func (x *PinMatrixRequestType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(PinMatrixRequestType_value, data, "PinMatrixRequestType")
+ if err != nil {
+ return err
+ }
+ *x = PinMatrixRequestType(value)
+ return nil
+}
+func (PinMatrixRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+
+// *
+// Type of recovery procedure. These should be used as bitmask, e.g.,
+// `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
+// listing every method supported by the host computer.
+//
+// Note that ScrambledWords must be supported by every implementation
+// for backward compatibility; there is no way to not support it.
+//
+// @used_in RecoveryDevice
+type RecoveryDeviceType int32
+
+const (
+ // use powers of two when extending this field
+ RecoveryDeviceType_RecoveryDeviceType_ScrambledWords RecoveryDeviceType = 0
+ RecoveryDeviceType_RecoveryDeviceType_Matrix RecoveryDeviceType = 1
+)
+
+var RecoveryDeviceType_name = map[int32]string{
+ 0: "RecoveryDeviceType_ScrambledWords",
+ 1: "RecoveryDeviceType_Matrix",
+}
+var RecoveryDeviceType_value = map[string]int32{
+ "RecoveryDeviceType_ScrambledWords": 0,
+ "RecoveryDeviceType_Matrix": 1,
+}
+
+func (x RecoveryDeviceType) Enum() *RecoveryDeviceType {
+ p := new(RecoveryDeviceType)
+ *p = x
+ return p
+}
+func (x RecoveryDeviceType) String() string {
+ return proto.EnumName(RecoveryDeviceType_name, int32(x))
+}
+func (x *RecoveryDeviceType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(RecoveryDeviceType_value, data, "RecoveryDeviceType")
+ if err != nil {
+ return err
+ }
+ *x = RecoveryDeviceType(value)
+ return nil
+}
+func (RecoveryDeviceType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+
+// *
+// Type of Recovery Word request
+// @used_in WordRequest
+type WordRequestType int32
+
+const (
+ WordRequestType_WordRequestType_Plain WordRequestType = 0
+ WordRequestType_WordRequestType_Matrix9 WordRequestType = 1
+ WordRequestType_WordRequestType_Matrix6 WordRequestType = 2
+)
+
+var WordRequestType_name = map[int32]string{
+ 0: "WordRequestType_Plain",
+ 1: "WordRequestType_Matrix9",
+ 2: "WordRequestType_Matrix6",
+}
+var WordRequestType_value = map[string]int32{
+ "WordRequestType_Plain": 0,
+ "WordRequestType_Matrix9": 1,
+ "WordRequestType_Matrix6": 2,
+}
+
+func (x WordRequestType) Enum() *WordRequestType {
+ p := new(WordRequestType)
+ *p = x
+ return p
+}
+func (x WordRequestType) String() string {
+ return proto.EnumName(WordRequestType_name, int32(x))
+}
+func (x *WordRequestType) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(WordRequestType_value, data, "WordRequestType")
+ if err != nil {
+ return err
+ }
+ *x = WordRequestType(value)
+ return nil
+}
+func (WordRequestType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+
+// *
+// Structure representing BIP32 (hierarchical deterministic) node
+// Used for imports of private key into the device and exporting public key out of device
+// @used_in PublicKey
+// @used_in LoadDevice
+// @used_in DebugLinkState
+// @used_in Storage
+type HDNodeType struct {
+ Depth *uint32 `protobuf:"varint,1,req,name=depth" json:"depth,omitempty"`
+ Fingerprint *uint32 `protobuf:"varint,2,req,name=fingerprint" json:"fingerprint,omitempty"`
+ ChildNum *uint32 `protobuf:"varint,3,req,name=child_num,json=childNum" json:"child_num,omitempty"`
+ ChainCode []byte `protobuf:"bytes,4,req,name=chain_code,json=chainCode" json:"chain_code,omitempty"`
+ PrivateKey []byte `protobuf:"bytes,5,opt,name=private_key,json=privateKey" json:"private_key,omitempty"`
+ PublicKey []byte `protobuf:"bytes,6,opt,name=public_key,json=publicKey" json:"public_key,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *HDNodeType) Reset() { *m = HDNodeType{} }
+func (m *HDNodeType) String() string { return proto.CompactTextString(m) }
+func (*HDNodeType) ProtoMessage() {}
+func (*HDNodeType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func (m *HDNodeType) GetDepth() uint32 {
+ if m != nil && m.Depth != nil {
+ return *m.Depth
+ }
+ return 0
+}
+
+func (m *HDNodeType) GetFingerprint() uint32 {
+ if m != nil && m.Fingerprint != nil {
+ return *m.Fingerprint
+ }
+ return 0
+}
+
+func (m *HDNodeType) GetChildNum() uint32 {
+ if m != nil && m.ChildNum != nil {
+ return *m.ChildNum
+ }
+ return 0
+}
+
+func (m *HDNodeType) GetChainCode() []byte {
+ if m != nil {
+ return m.ChainCode
+ }
+ return nil
+}
+
+func (m *HDNodeType) GetPrivateKey() []byte {
+ if m != nil {
+ return m.PrivateKey
+ }
+ return nil
+}
+
+func (m *HDNodeType) GetPublicKey() []byte {
+ if m != nil {
+ return m.PublicKey
+ }
+ return nil
+}
+
+type HDNodePathType struct {
+ Node *HDNodeType `protobuf:"bytes,1,req,name=node" json:"node,omitempty"`
+ AddressN []uint32 `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *HDNodePathType) Reset() { *m = HDNodePathType{} }
+func (m *HDNodePathType) String() string { return proto.CompactTextString(m) }
+func (*HDNodePathType) ProtoMessage() {}
+func (*HDNodePathType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+func (m *HDNodePathType) GetNode() *HDNodeType {
+ if m != nil {
+ return m.Node
+ }
+ return nil
+}
+
+func (m *HDNodePathType) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+// *
+// Structure representing Coin
+// @used_in Features
+type CoinType struct {
+ CoinName *string `protobuf:"bytes,1,opt,name=coin_name,json=coinName" json:"coin_name,omitempty"`
+ CoinShortcut *string `protobuf:"bytes,2,opt,name=coin_shortcut,json=coinShortcut" json:"coin_shortcut,omitempty"`
+ AddressType *uint32 `protobuf:"varint,3,opt,name=address_type,json=addressType,def=0" json:"address_type,omitempty"`
+ MaxfeeKb *uint64 `protobuf:"varint,4,opt,name=maxfee_kb,json=maxfeeKb" json:"maxfee_kb,omitempty"`
+ AddressTypeP2Sh *uint32 `protobuf:"varint,5,opt,name=address_type_p2sh,json=addressTypeP2sh,def=5" json:"address_type_p2sh,omitempty"`
+ SignedMessageHeader *string `protobuf:"bytes,8,opt,name=signed_message_header,json=signedMessageHeader" json:"signed_message_header,omitempty"`
+ XpubMagic *uint32 `protobuf:"varint,9,opt,name=xpub_magic,json=xpubMagic,def=76067358" json:"xpub_magic,omitempty"`
+ XprvMagic *uint32 `protobuf:"varint,10,opt,name=xprv_magic,json=xprvMagic,def=76066276" json:"xprv_magic,omitempty"`
+ Segwit *bool `protobuf:"varint,11,opt,name=segwit" json:"segwit,omitempty"`
+ Forkid *uint32 `protobuf:"varint,12,opt,name=forkid" json:"forkid,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *CoinType) Reset() { *m = CoinType{} }
+func (m *CoinType) String() string { return proto.CompactTextString(m) }
+func (*CoinType) ProtoMessage() {}
+func (*CoinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+const Default_CoinType_AddressType uint32 = 0
+const Default_CoinType_AddressTypeP2Sh uint32 = 5
+const Default_CoinType_XpubMagic uint32 = 76067358
+const Default_CoinType_XprvMagic uint32 = 76066276
+
+func (m *CoinType) GetCoinName() string {
+ if m != nil && m.CoinName != nil {
+ return *m.CoinName
+ }
+ return ""
+}
+
+func (m *CoinType) GetCoinShortcut() string {
+ if m != nil && m.CoinShortcut != nil {
+ return *m.CoinShortcut
+ }
+ return ""
+}
+
+func (m *CoinType) GetAddressType() uint32 {
+ if m != nil && m.AddressType != nil {
+ return *m.AddressType
+ }
+ return Default_CoinType_AddressType
+}
+
+func (m *CoinType) GetMaxfeeKb() uint64 {
+ if m != nil && m.MaxfeeKb != nil {
+ return *m.MaxfeeKb
+ }
+ return 0
+}
+
+func (m *CoinType) GetAddressTypeP2Sh() uint32 {
+ if m != nil && m.AddressTypeP2Sh != nil {
+ return *m.AddressTypeP2Sh
+ }
+ return Default_CoinType_AddressTypeP2Sh
+}
+
+func (m *CoinType) GetSignedMessageHeader() string {
+ if m != nil && m.SignedMessageHeader != nil {
+ return *m.SignedMessageHeader
+ }
+ return ""
+}
+
+func (m *CoinType) GetXpubMagic() uint32 {
+ if m != nil && m.XpubMagic != nil {
+ return *m.XpubMagic
+ }
+ return Default_CoinType_XpubMagic
+}
+
+func (m *CoinType) GetXprvMagic() uint32 {
+ if m != nil && m.XprvMagic != nil {
+ return *m.XprvMagic
+ }
+ return Default_CoinType_XprvMagic
+}
+
+func (m *CoinType) GetSegwit() bool {
+ if m != nil && m.Segwit != nil {
+ return *m.Segwit
+ }
+ return false
+}
+
+func (m *CoinType) GetForkid() uint32 {
+ if m != nil && m.Forkid != nil {
+ return *m.Forkid
+ }
+ return 0
+}
+
+// *
+// Type of redeem script used in input
+// @used_in TxInputType
+type MultisigRedeemScriptType struct {
+ Pubkeys []*HDNodePathType `protobuf:"bytes,1,rep,name=pubkeys" json:"pubkeys,omitempty"`
+ Signatures [][]byte `protobuf:"bytes,2,rep,name=signatures" json:"signatures,omitempty"`
+ M *uint32 `protobuf:"varint,3,opt,name=m" json:"m,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *MultisigRedeemScriptType) Reset() { *m = MultisigRedeemScriptType{} }
+func (m *MultisigRedeemScriptType) String() string { return proto.CompactTextString(m) }
+func (*MultisigRedeemScriptType) ProtoMessage() {}
+func (*MultisigRedeemScriptType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+func (m *MultisigRedeemScriptType) GetPubkeys() []*HDNodePathType {
+ if m != nil {
+ return m.Pubkeys
+ }
+ return nil
+}
+
+func (m *MultisigRedeemScriptType) GetSignatures() [][]byte {
+ if m != nil {
+ return m.Signatures
+ }
+ return nil
+}
+
+func (m *MultisigRedeemScriptType) GetM() uint32 {
+ if m != nil && m.M != nil {
+ return *m.M
+ }
+ return 0
+}
+
+// *
+// Structure representing transaction input
+// @used_in SimpleSignTx
+// @used_in TransactionType
+type TxInputType struct {
+ AddressN []uint32 `protobuf:"varint,1,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ PrevHash []byte `protobuf:"bytes,2,req,name=prev_hash,json=prevHash" json:"prev_hash,omitempty"`
+ PrevIndex *uint32 `protobuf:"varint,3,req,name=prev_index,json=prevIndex" json:"prev_index,omitempty"`
+ ScriptSig []byte `protobuf:"bytes,4,opt,name=script_sig,json=scriptSig" json:"script_sig,omitempty"`
+ Sequence *uint32 `protobuf:"varint,5,opt,name=sequence,def=4294967295" json:"sequence,omitempty"`
+ ScriptType *InputScriptType `protobuf:"varint,6,opt,name=script_type,json=scriptType,enum=InputScriptType,def=0" json:"script_type,omitempty"`
+ Multisig *MultisigRedeemScriptType `protobuf:"bytes,7,opt,name=multisig" json:"multisig,omitempty"`
+ Amount *uint64 `protobuf:"varint,8,opt,name=amount" json:"amount,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxInputType) Reset() { *m = TxInputType{} }
+func (m *TxInputType) String() string { return proto.CompactTextString(m) }
+func (*TxInputType) ProtoMessage() {}
+func (*TxInputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+const Default_TxInputType_Sequence uint32 = 4294967295
+const Default_TxInputType_ScriptType InputScriptType = InputScriptType_SPENDADDRESS
+
+func (m *TxInputType) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *TxInputType) GetPrevHash() []byte {
+ if m != nil {
+ return m.PrevHash
+ }
+ return nil
+}
+
+func (m *TxInputType) GetPrevIndex() uint32 {
+ if m != nil && m.PrevIndex != nil {
+ return *m.PrevIndex
+ }
+ return 0
+}
+
+func (m *TxInputType) GetScriptSig() []byte {
+ if m != nil {
+ return m.ScriptSig
+ }
+ return nil
+}
+
+func (m *TxInputType) GetSequence() uint32 {
+ if m != nil && m.Sequence != nil {
+ return *m.Sequence
+ }
+ return Default_TxInputType_Sequence
+}
+
+func (m *TxInputType) GetScriptType() InputScriptType {
+ if m != nil && m.ScriptType != nil {
+ return *m.ScriptType
+ }
+ return Default_TxInputType_ScriptType
+}
+
+func (m *TxInputType) GetMultisig() *MultisigRedeemScriptType {
+ if m != nil {
+ return m.Multisig
+ }
+ return nil
+}
+
+func (m *TxInputType) GetAmount() uint64 {
+ if m != nil && m.Amount != nil {
+ return *m.Amount
+ }
+ return 0
+}
+
+// *
+// Structure representing transaction output
+// @used_in SimpleSignTx
+// @used_in TransactionType
+type TxOutputType struct {
+ Address *string `protobuf:"bytes,1,opt,name=address" json:"address,omitempty"`
+ AddressN []uint32 `protobuf:"varint,2,rep,name=address_n,json=addressN" json:"address_n,omitempty"`
+ Amount *uint64 `protobuf:"varint,3,req,name=amount" json:"amount,omitempty"`
+ ScriptType *OutputScriptType `protobuf:"varint,4,req,name=script_type,json=scriptType,enum=OutputScriptType" json:"script_type,omitempty"`
+ Multisig *MultisigRedeemScriptType `protobuf:"bytes,5,opt,name=multisig" json:"multisig,omitempty"`
+ OpReturnData []byte `protobuf:"bytes,6,opt,name=op_return_data,json=opReturnData" json:"op_return_data,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxOutputType) Reset() { *m = TxOutputType{} }
+func (m *TxOutputType) String() string { return proto.CompactTextString(m) }
+func (*TxOutputType) ProtoMessage() {}
+func (*TxOutputType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+
+func (m *TxOutputType) GetAddress() string {
+ if m != nil && m.Address != nil {
+ return *m.Address
+ }
+ return ""
+}
+
+func (m *TxOutputType) GetAddressN() []uint32 {
+ if m != nil {
+ return m.AddressN
+ }
+ return nil
+}
+
+func (m *TxOutputType) GetAmount() uint64 {
+ if m != nil && m.Amount != nil {
+ return *m.Amount
+ }
+ return 0
+}
+
+func (m *TxOutputType) GetScriptType() OutputScriptType {
+ if m != nil && m.ScriptType != nil {
+ return *m.ScriptType
+ }
+ return OutputScriptType_PAYTOADDRESS
+}
+
+func (m *TxOutputType) GetMultisig() *MultisigRedeemScriptType {
+ if m != nil {
+ return m.Multisig
+ }
+ return nil
+}
+
+func (m *TxOutputType) GetOpReturnData() []byte {
+ if m != nil {
+ return m.OpReturnData
+ }
+ return nil
+}
+
+// *
+// Structure representing compiled transaction output
+// @used_in TransactionType
+type TxOutputBinType struct {
+ Amount *uint64 `protobuf:"varint,1,req,name=amount" json:"amount,omitempty"`
+ ScriptPubkey []byte `protobuf:"bytes,2,req,name=script_pubkey,json=scriptPubkey" json:"script_pubkey,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxOutputBinType) Reset() { *m = TxOutputBinType{} }
+func (m *TxOutputBinType) String() string { return proto.CompactTextString(m) }
+func (*TxOutputBinType) ProtoMessage() {}
+func (*TxOutputBinType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+
+func (m *TxOutputBinType) GetAmount() uint64 {
+ if m != nil && m.Amount != nil {
+ return *m.Amount
+ }
+ return 0
+}
+
+func (m *TxOutputBinType) GetScriptPubkey() []byte {
+ if m != nil {
+ return m.ScriptPubkey
+ }
+ return nil
+}
+
+// *
+// Structure representing transaction
+// @used_in SimpleSignTx
+type TransactionType struct {
+ Version *uint32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
+ Inputs []*TxInputType `protobuf:"bytes,2,rep,name=inputs" json:"inputs,omitempty"`
+ BinOutputs []*TxOutputBinType `protobuf:"bytes,3,rep,name=bin_outputs,json=binOutputs" json:"bin_outputs,omitempty"`
+ Outputs []*TxOutputType `protobuf:"bytes,5,rep,name=outputs" json:"outputs,omitempty"`
+ LockTime *uint32 `protobuf:"varint,4,opt,name=lock_time,json=lockTime" json:"lock_time,omitempty"`
+ InputsCnt *uint32 `protobuf:"varint,6,opt,name=inputs_cnt,json=inputsCnt" json:"inputs_cnt,omitempty"`
+ OutputsCnt *uint32 `protobuf:"varint,7,opt,name=outputs_cnt,json=outputsCnt" json:"outputs_cnt,omitempty"`
+ ExtraData []byte `protobuf:"bytes,8,opt,name=extra_data,json=extraData" json:"extra_data,omitempty"`
+ ExtraDataLen *uint32 `protobuf:"varint,9,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TransactionType) Reset() { *m = TransactionType{} }
+func (m *TransactionType) String() string { return proto.CompactTextString(m) }
+func (*TransactionType) ProtoMessage() {}
+func (*TransactionType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+
+func (m *TransactionType) GetVersion() uint32 {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return 0
+}
+
+func (m *TransactionType) GetInputs() []*TxInputType {
+ if m != nil {
+ return m.Inputs
+ }
+ return nil
+}
+
+func (m *TransactionType) GetBinOutputs() []*TxOutputBinType {
+ if m != nil {
+ return m.BinOutputs
+ }
+ return nil
+}
+
+func (m *TransactionType) GetOutputs() []*TxOutputType {
+ if m != nil {
+ return m.Outputs
+ }
+ return nil
+}
+
+func (m *TransactionType) GetLockTime() uint32 {
+ if m != nil && m.LockTime != nil {
+ return *m.LockTime
+ }
+ return 0
+}
+
+func (m *TransactionType) GetInputsCnt() uint32 {
+ if m != nil && m.InputsCnt != nil {
+ return *m.InputsCnt
+ }
+ return 0
+}
+
+func (m *TransactionType) GetOutputsCnt() uint32 {
+ if m != nil && m.OutputsCnt != nil {
+ return *m.OutputsCnt
+ }
+ return 0
+}
+
+func (m *TransactionType) GetExtraData() []byte {
+ if m != nil {
+ return m.ExtraData
+ }
+ return nil
+}
+
+func (m *TransactionType) GetExtraDataLen() uint32 {
+ if m != nil && m.ExtraDataLen != nil {
+ return *m.ExtraDataLen
+ }
+ return 0
+}
+
+// *
+// Structure representing request details
+// @used_in TxRequest
+type TxRequestDetailsType struct {
+ RequestIndex *uint32 `protobuf:"varint,1,opt,name=request_index,json=requestIndex" json:"request_index,omitempty"`
+ TxHash []byte `protobuf:"bytes,2,opt,name=tx_hash,json=txHash" json:"tx_hash,omitempty"`
+ ExtraDataLen *uint32 `protobuf:"varint,3,opt,name=extra_data_len,json=extraDataLen" json:"extra_data_len,omitempty"`
+ ExtraDataOffset *uint32 `protobuf:"varint,4,opt,name=extra_data_offset,json=extraDataOffset" json:"extra_data_offset,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxRequestDetailsType) Reset() { *m = TxRequestDetailsType{} }
+func (m *TxRequestDetailsType) String() string { return proto.CompactTextString(m) }
+func (*TxRequestDetailsType) ProtoMessage() {}
+func (*TxRequestDetailsType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+
+func (m *TxRequestDetailsType) GetRequestIndex() uint32 {
+ if m != nil && m.RequestIndex != nil {
+ return *m.RequestIndex
+ }
+ return 0
+}
+
+func (m *TxRequestDetailsType) GetTxHash() []byte {
+ if m != nil {
+ return m.TxHash
+ }
+ return nil
+}
+
+func (m *TxRequestDetailsType) GetExtraDataLen() uint32 {
+ if m != nil && m.ExtraDataLen != nil {
+ return *m.ExtraDataLen
+ }
+ return 0
+}
+
+func (m *TxRequestDetailsType) GetExtraDataOffset() uint32 {
+ if m != nil && m.ExtraDataOffset != nil {
+ return *m.ExtraDataOffset
+ }
+ return 0
+}
+
+// *
+// Structure representing serialized data
+// @used_in TxRequest
+type TxRequestSerializedType struct {
+ SignatureIndex *uint32 `protobuf:"varint,1,opt,name=signature_index,json=signatureIndex" json:"signature_index,omitempty"`
+ Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
+ SerializedTx []byte `protobuf:"bytes,3,opt,name=serialized_tx,json=serializedTx" json:"serialized_tx,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *TxRequestSerializedType) Reset() { *m = TxRequestSerializedType{} }
+func (m *TxRequestSerializedType) String() string { return proto.CompactTextString(m) }
+func (*TxRequestSerializedType) ProtoMessage() {}
+func (*TxRequestSerializedType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+
+func (m *TxRequestSerializedType) GetSignatureIndex() uint32 {
+ if m != nil && m.SignatureIndex != nil {
+ return *m.SignatureIndex
+ }
+ return 0
+}
+
+func (m *TxRequestSerializedType) GetSignature() []byte {
+ if m != nil {
+ return m.Signature
+ }
+ return nil
+}
+
+func (m *TxRequestSerializedType) GetSerializedTx() []byte {
+ if m != nil {
+ return m.SerializedTx
+ }
+ return nil
+}
+
+// *
+// Structure representing identity data
+// @used_in IdentityType
+type IdentityType struct {
+ Proto *string `protobuf:"bytes,1,opt,name=proto" json:"proto,omitempty"`
+ User *string `protobuf:"bytes,2,opt,name=user" json:"user,omitempty"`
+ Host *string `protobuf:"bytes,3,opt,name=host" json:"host,omitempty"`
+ Port *string `protobuf:"bytes,4,opt,name=port" json:"port,omitempty"`
+ Path *string `protobuf:"bytes,5,opt,name=path" json:"path,omitempty"`
+ Index *uint32 `protobuf:"varint,6,opt,name=index,def=0" json:"index,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (m *IdentityType) Reset() { *m = IdentityType{} }
+func (m *IdentityType) String() string { return proto.CompactTextString(m) }
+func (*IdentityType) ProtoMessage() {}
+func (*IdentityType) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
+
+const Default_IdentityType_Index uint32 = 0
+
+func (m *IdentityType) GetProto() string {
+ if m != nil && m.Proto != nil {
+ return *m.Proto
+ }
+ return ""
+}
+
+func (m *IdentityType) GetUser() string {
+ if m != nil && m.User != nil {
+ return *m.User
+ }
+ return ""
+}
+
+func (m *IdentityType) GetHost() string {
+ if m != nil && m.Host != nil {
+ return *m.Host
+ }
+ return ""
+}
+
+func (m *IdentityType) GetPort() string {
+ if m != nil && m.Port != nil {
+ return *m.Port
+ }
+ return ""
+}
+
+func (m *IdentityType) GetPath() string {
+ if m != nil && m.Path != nil {
+ return *m.Path
+ }
+ return ""
+}
+
+func (m *IdentityType) GetIndex() uint32 {
+ if m != nil && m.Index != nil {
+ return *m.Index
+ }
+ return Default_IdentityType_Index
+}
+
+var E_WireIn = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50002,
+ Name: "wire_in",
+ Tag: "varint,50002,opt,name=wire_in,json=wireIn",
+ Filename: "types.proto",
+}
+
+var E_WireOut = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50003,
+ Name: "wire_out",
+ Tag: "varint,50003,opt,name=wire_out,json=wireOut",
+ Filename: "types.proto",
+}
+
+var E_WireDebugIn = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50004,
+ Name: "wire_debug_in",
+ Tag: "varint,50004,opt,name=wire_debug_in,json=wireDebugIn",
+ Filename: "types.proto",
+}
+
+var E_WireDebugOut = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50005,
+ Name: "wire_debug_out",
+ Tag: "varint,50005,opt,name=wire_debug_out,json=wireDebugOut",
+ Filename: "types.proto",
+}
+
+var E_WireTiny = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50006,
+ Name: "wire_tiny",
+ Tag: "varint,50006,opt,name=wire_tiny,json=wireTiny",
+ Filename: "types.proto",
+}
+
+var E_WireBootloader = &proto.ExtensionDesc{
+ ExtendedType: (*google_protobuf.EnumValueOptions)(nil),
+ ExtensionType: (*bool)(nil),
+ Field: 50007,
+ Name: "wire_bootloader",
+ Tag: "varint,50007,opt,name=wire_bootloader,json=wireBootloader",
+ Filename: "types.proto",
+}
+
+func init() {
+ proto.RegisterType((*HDNodeType)(nil), "HDNodeType")
+ proto.RegisterType((*HDNodePathType)(nil), "HDNodePathType")
+ proto.RegisterType((*CoinType)(nil), "CoinType")
+ proto.RegisterType((*MultisigRedeemScriptType)(nil), "MultisigRedeemScriptType")
+ proto.RegisterType((*TxInputType)(nil), "TxInputType")
+ proto.RegisterType((*TxOutputType)(nil), "TxOutputType")
+ proto.RegisterType((*TxOutputBinType)(nil), "TxOutputBinType")
+ proto.RegisterType((*TransactionType)(nil), "TransactionType")
+ proto.RegisterType((*TxRequestDetailsType)(nil), "TxRequestDetailsType")
+ proto.RegisterType((*TxRequestSerializedType)(nil), "TxRequestSerializedType")
+ proto.RegisterType((*IdentityType)(nil), "IdentityType")
+ proto.RegisterEnum("FailureType", FailureType_name, FailureType_value)
+ proto.RegisterEnum("OutputScriptType", OutputScriptType_name, OutputScriptType_value)
+ proto.RegisterEnum("InputScriptType", InputScriptType_name, InputScriptType_value)
+ proto.RegisterEnum("RequestType", RequestType_name, RequestType_value)
+ proto.RegisterEnum("ButtonRequestType", ButtonRequestType_name, ButtonRequestType_value)
+ proto.RegisterEnum("PinMatrixRequestType", PinMatrixRequestType_name, PinMatrixRequestType_value)
+ proto.RegisterEnum("RecoveryDeviceType", RecoveryDeviceType_name, RecoveryDeviceType_value)
+ proto.RegisterEnum("WordRequestType", WordRequestType_name, WordRequestType_value)
+ proto.RegisterExtension(E_WireIn)
+ proto.RegisterExtension(E_WireOut)
+ proto.RegisterExtension(E_WireDebugIn)
+ proto.RegisterExtension(E_WireDebugOut)
+ proto.RegisterExtension(E_WireTiny)
+ proto.RegisterExtension(E_WireBootloader)
+}
+
+func init() { proto.RegisterFile("types.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 1899 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0xdb, 0x72, 0x1a, 0xc9,
+ 0x19, 0xf6, 0x00, 0x92, 0xe0, 0x07, 0xc4, 0xa8, 0x7d, 0xd0, 0x78, 0x6d, 0xaf, 0x31, 0x76, 0x62,
+ 0x45, 0x55, 0x61, 0x77, 0xc9, 0x5a, 0x8e, 0x55, 0xa9, 0x24, 0x3a, 0xa0, 0x15, 0x65, 0x0b, 0x51,
+ 0xc3, 0x28, 0x56, 0x72, 0x33, 0x35, 0xcc, 0xb4, 0xa0, 0x4b, 0x43, 0x37, 0xe9, 0xe9, 0x91, 0xd1,
+ 0xde, 0xe4, 0x2a, 0xc9, 0x55, 0x5e, 0x23, 0x6f, 0x91, 0xaa, 0xbc, 0x41, 0xaa, 0x36, 0xa7, 0xcb,
+ 0xbc, 0x41, 0xae, 0xf2, 0x00, 0xa9, 0x3e, 0x0c, 0x02, 0xc9, 0xde, 0xd2, 0x1d, 0xfd, 0x7d, 0xff,
+ 0xf9, 0xd0, 0x3d, 0x40, 0x59, 0x5c, 0x4e, 0x70, 0xd2, 0x9c, 0x70, 0x26, 0xd8, 0x67, 0xf5, 0x21,
+ 0x63, 0xc3, 0x18, 0x7f, 0xa1, 0x4e, 0x83, 0xf4, 0xec, 0x8b, 0x08, 0x27, 0x21, 0x27, 0x13, 0xc1,
+ 0xb8, 0x96, 0x68, 0xfc, 0xd5, 0x02, 0x38, 0xdc, 0xef, 0xb2, 0x08, 0x7b, 0x97, 0x13, 0x8c, 0xee,
+ 0xc1, 0x52, 0x84, 0x27, 0x62, 0xe4, 0x58, 0xf5, 0xdc, 0x46, 0xd5, 0xd5, 0x07, 0x54, 0x87, 0xf2,
+ 0x19, 0xa1, 0x43, 0xcc, 0x27, 0x9c, 0x50, 0xe1, 0xe4, 0x14, 0x37, 0x0f, 0xa1, 0x47, 0x50, 0x0a,
+ 0x47, 0x24, 0x8e, 0x7c, 0x9a, 0x8e, 0x9d, 0xbc, 0xe2, 0x8b, 0x0a, 0xe8, 0xa6, 0x63, 0xf4, 0x04,
+ 0x20, 0x1c, 0x05, 0x84, 0xfa, 0x21, 0x8b, 0xb0, 0x53, 0xa8, 0xe7, 0x36, 0x2a, 0x6e, 0x49, 0x21,
+ 0x7b, 0x2c, 0xc2, 0xe8, 0x29, 0x94, 0x27, 0x9c, 0x5c, 0x04, 0x02, 0xfb, 0xe7, 0xf8, 0xd2, 0x59,
+ 0xaa, 0x5b, 0x1b, 0x15, 0x17, 0x0c, 0xf4, 0x16, 0x5f, 0x4a, 0xfd, 0x49, 0x3a, 0x88, 0x49, 0xa8,
+ 0xf8, 0x65, 0xc5, 0x97, 0x34, 0xf2, 0x16, 0x5f, 0x36, 0xba, 0xb0, 0xaa, 0x33, 0xe8, 0x05, 0x62,
+ 0xa4, 0xb2, 0x78, 0x0a, 0x05, 0x2a, 0x5d, 0xc9, 0x24, 0xca, 0xad, 0x72, 0xf3, 0x2a, 0x41, 0x57,
+ 0x11, 0x32, 0xdc, 0x20, 0x8a, 0x38, 0x4e, 0x12, 0x9f, 0x3a, 0xb9, 0x7a, 0x5e, 0x86, 0x6b, 0x80,
+ 0x6e, 0xe3, 0x7f, 0x39, 0x28, 0xee, 0x31, 0x42, 0x95, 0x29, 0x99, 0x18, 0x23, 0xd4, 0xa7, 0xc1,
+ 0x58, 0xda, 0xb3, 0x36, 0x4a, 0x6e, 0x51, 0x02, 0xdd, 0x60, 0x8c, 0xd1, 0x73, 0xa8, 0x2a, 0x32,
+ 0x19, 0x31, 0x2e, 0xc2, 0x54, 0x56, 0x46, 0x0a, 0x54, 0x24, 0xd8, 0x37, 0x18, 0x7a, 0x01, 0x95,
+ 0xcc, 0x97, 0x6c, 0x8d, 0x93, 0xaf, 0x5b, 0x1b, 0xd5, 0x6d, 0xeb, 0x4b, 0xb7, 0x6c, 0xe0, 0xcc,
+ 0xcf, 0x38, 0x98, 0x9e, 0x61, 0xec, 0x9f, 0x0f, 0x9c, 0x42, 0xdd, 0xda, 0x28, 0xb8, 0x45, 0x0d,
+ 0xbc, 0x1d, 0xa0, 0x1f, 0xc3, 0xda, 0xbc, 0x09, 0x7f, 0xd2, 0x4a, 0x46, 0xaa, 0x4e, 0xd5, 0x6d,
+ 0xeb, 0x95, 0x5b, 0x9b, 0xb3, 0xd3, 0x6b, 0x25, 0x23, 0xd4, 0x82, 0xfb, 0x09, 0x19, 0x52, 0x1c,
+ 0xf9, 0x63, 0x9c, 0x24, 0xc1, 0x10, 0xfb, 0x23, 0x1c, 0x44, 0x98, 0x3b, 0x45, 0x15, 0xde, 0x5d,
+ 0x4d, 0x1e, 0x69, 0xee, 0x50, 0x51, 0xe8, 0x25, 0xc0, 0x74, 0x92, 0x0e, 0xfc, 0x71, 0x30, 0x24,
+ 0xa1, 0x53, 0x52, 0xb6, 0x8b, 0xaf, 0xb7, 0xbe, 0xdc, 0x7a, 0xfd, 0x93, 0x57, 0x3f, 0x75, 0x4b,
+ 0x92, 0x3b, 0x92, 0x94, 0x16, 0xe4, 0x17, 0x46, 0x10, 0xae, 0x04, 0xb7, 0x5a, 0xaf, 0xb7, 0xa4,
+ 0x20, 0xbf, 0xd0, 0x82, 0x0f, 0x60, 0x39, 0xc1, 0xc3, 0x0f, 0x44, 0x38, 0xe5, 0xba, 0xb5, 0x51,
+ 0x74, 0xcd, 0x49, 0xe2, 0x67, 0x8c, 0x9f, 0x93, 0xc8, 0xa9, 0x48, 0x65, 0xd7, 0x9c, 0x1a, 0x09,
+ 0x38, 0x47, 0x69, 0x2c, 0x48, 0x42, 0x86, 0x2e, 0x8e, 0x30, 0x1e, 0xf7, 0xd5, 0xa4, 0xaa, 0xea,
+ 0xfc, 0x08, 0x56, 0x26, 0xe9, 0xe0, 0x1c, 0x5f, 0x26, 0x8e, 0x55, 0xcf, 0x6f, 0x94, 0x5b, 0xb5,
+ 0xe6, 0x62, 0xcb, 0xdd, 0x8c, 0x47, 0x9f, 0x03, 0xc8, 0xfc, 0x02, 0x91, 0x72, 0x9c, 0xa8, 0xde,
+ 0x56, 0xdc, 0x39, 0x04, 0x55, 0xc0, 0x1a, 0xeb, 0x1e, 0xb8, 0xd6, 0xb8, 0xf1, 0x97, 0x1c, 0x94,
+ 0xbd, 0x69, 0x87, 0x4e, 0x52, 0x91, 0xb5, 0xe1, 0x6a, 0x30, 0xac, 0xc5, 0xc1, 0x90, 0xe4, 0x84,
+ 0xe3, 0x0b, 0x7f, 0x14, 0x24, 0x23, 0xb5, 0x04, 0x15, 0xb7, 0x28, 0x81, 0xc3, 0x20, 0x19, 0xa9,
+ 0x21, 0x95, 0x24, 0xa1, 0x11, 0x9e, 0x9a, 0x15, 0x50, 0xe2, 0x1d, 0x09, 0x48, 0x5a, 0x6f, 0x9e,
+ 0x9f, 0x90, 0xa1, 0x6a, 0x70, 0xc5, 0x2d, 0x69, 0xa4, 0x4f, 0x86, 0xe8, 0x87, 0x50, 0x4c, 0xf0,
+ 0x6f, 0x53, 0x4c, 0x43, 0x6c, 0x1a, 0x0b, 0x5f, 0xb7, 0xde, 0x7c, 0xfd, 0x66, 0xeb, 0x75, 0xeb,
+ 0xcd, 0x2b, 0x77, 0xc6, 0xa1, 0x5f, 0x40, 0xd9, 0x98, 0x51, 0xb3, 0x24, 0x77, 0x61, 0xb5, 0x65,
+ 0x37, 0x55, 0x02, 0x57, 0xf5, 0xda, 0xae, 0xf4, 0x7b, 0xed, 0xee, 0xfe, 0xce, 0xfe, 0xbe, 0xdb,
+ 0xee, 0xf7, 0x5d, 0xe3, 0x59, 0x25, 0xf8, 0x0a, 0x8a, 0x63, 0x53, 0x65, 0x67, 0xa5, 0x6e, 0x6d,
+ 0x94, 0x5b, 0x0f, 0x9b, 0x9f, 0x2a, 0xbb, 0x3b, 0x13, 0x95, 0x4d, 0x0b, 0xc6, 0x2c, 0xa5, 0x42,
+ 0xcd, 0x50, 0xc1, 0x35, 0xa7, 0xc6, 0x7f, 0x2d, 0xa8, 0x78, 0xd3, 0xe3, 0x54, 0x64, 0x05, 0x74,
+ 0x60, 0xc5, 0xd4, 0xcb, 0x6c, 0x4b, 0x76, 0xfc, 0xde, 0x9d, 0x9b, 0xb3, 0x2f, 0x2b, 0x37, 0xb3,
+ 0x8f, 0x5a, 0x8b, 0xf9, 0xca, 0xbb, 0x63, 0xb5, 0xb5, 0xd6, 0xd4, 0x0e, 0xe7, 0x22, 0xfd, 0x54,
+ 0x8a, 0x4b, 0xb7, 0x4f, 0xf1, 0x05, 0xac, 0xb2, 0x89, 0xcf, 0xb1, 0x48, 0x39, 0xf5, 0xa3, 0x40,
+ 0x04, 0xe6, 0xa6, 0xa9, 0xb0, 0x89, 0xab, 0xc0, 0xfd, 0x40, 0x04, 0x8d, 0x2e, 0xd4, 0xb2, 0x7c,
+ 0x77, 0xcd, 0x15, 0x71, 0x15, 0xbb, 0xb5, 0x10, 0xfb, 0x73, 0xa8, 0x9a, 0xd8, 0xf5, 0x6c, 0x9a,
+ 0x91, 0xa9, 0x68, 0xb0, 0xa7, 0xb0, 0xc6, 0xdf, 0x72, 0x50, 0xf3, 0x78, 0x40, 0x93, 0x20, 0x14,
+ 0x84, 0xd1, 0xac, 0x86, 0x17, 0x98, 0x27, 0x84, 0x51, 0x55, 0xc3, 0xaa, 0x9b, 0x1d, 0xd1, 0x0b,
+ 0x58, 0x26, 0xb2, 0xd5, 0x7a, 0xb0, 0xcb, 0xad, 0x4a, 0x73, 0x6e, 0x78, 0x5d, 0xc3, 0xa1, 0xaf,
+ 0xa0, 0x3c, 0x20, 0xd4, 0x67, 0x2a, 0xca, 0xc4, 0xc9, 0x2b, 0x51, 0xbb, 0x79, 0x2d, 0x6e, 0x17,
+ 0x06, 0x84, 0x6a, 0x24, 0x41, 0x2f, 0x61, 0x25, 0x13, 0x5f, 0x52, 0xe2, 0xd5, 0xe6, 0x7c, 0x5b,
+ 0xdd, 0x8c, 0x95, 0x5d, 0x8c, 0x59, 0x78, 0xee, 0x0b, 0x32, 0xc6, 0x6a, 0x8c, 0xab, 0x6e, 0x51,
+ 0x02, 0x1e, 0x19, 0x63, 0x39, 0xe4, 0x3a, 0x04, 0x3f, 0xa4, 0x42, 0x95, 0xaf, 0xea, 0x96, 0x34,
+ 0xb2, 0x47, 0x85, 0xbc, 0xe8, 0x8d, 0x19, 0xc5, 0xaf, 0x28, 0x1e, 0x0c, 0x24, 0x05, 0x9e, 0x00,
+ 0xe0, 0xa9, 0xe0, 0x81, 0x2e, 0x7f, 0x51, 0x2f, 0x89, 0x42, 0x64, 0xed, 0x65, 0x87, 0xae, 0x68,
+ 0x3f, 0xc6, 0x54, 0xdf, 0x53, 0x6e, 0x65, 0x26, 0xf2, 0x0e, 0xd3, 0xc6, 0x9f, 0x2d, 0xb8, 0xe7,
+ 0x4d, 0x5d, 0xb9, 0x31, 0x89, 0xd8, 0xc7, 0x22, 0x20, 0xb1, 0xbe, 0x62, 0x9f, 0x43, 0x95, 0x6b,
+ 0xd4, 0x2c, 0xa9, 0x2e, 0x6e, 0xc5, 0x80, 0x7a, 0x4f, 0xd7, 0x61, 0x45, 0x4c, 0xb3, 0x0d, 0x97,
+ 0xfe, 0x97, 0xc5, 0x54, 0xed, 0xf7, 0x4d, 0xe7, 0xf9, 0x9b, 0xce, 0xd1, 0x26, 0xac, 0xcd, 0x49,
+ 0xb1, 0xb3, 0xb3, 0x04, 0x0b, 0x53, 0xa6, 0xda, 0x4c, 0xf0, 0x58, 0xc1, 0x8d, 0xdf, 0x5b, 0xb0,
+ 0x3e, 0x0b, 0xb4, 0x8f, 0x39, 0x09, 0x62, 0xf2, 0x2d, 0x8e, 0x54, 0xac, 0x2f, 0xa1, 0x36, 0xbb,
+ 0xb3, 0x16, 0xa2, 0x5d, 0x9d, 0xc1, 0x3a, 0xde, 0xc7, 0x50, 0x9a, 0x21, 0x26, 0xe2, 0x2b, 0x40,
+ 0x8d, 0xe0, 0xcc, 0xb0, 0x2f, 0xa6, 0x2a, 0x66, 0x39, 0x82, 0x57, 0xde, 0xa6, 0x8d, 0x3f, 0x59,
+ 0x50, 0xe9, 0x44, 0x98, 0x0a, 0x22, 0x2e, 0xb3, 0x8f, 0x00, 0xf5, 0x71, 0x60, 0x36, 0x58, 0x1f,
+ 0x10, 0x82, 0x42, 0x9a, 0x60, 0x6e, 0xde, 0x38, 0xf5, 0x5b, 0x62, 0x23, 0x96, 0x08, 0x65, 0xb6,
+ 0xe4, 0xaa, 0xdf, 0x12, 0x9b, 0x30, 0xae, 0xb3, 0x2e, 0xb9, 0xea, 0xb7, 0xc2, 0x02, 0xa1, 0xdf,
+ 0x2c, 0x89, 0x05, 0x62, 0x84, 0xd6, 0x61, 0x49, 0x27, 0xb6, 0x9c, 0x3d, 0x88, 0xfa, 0xbc, 0xf9,
+ 0x5d, 0x0e, 0xca, 0x07, 0x01, 0x89, 0x53, 0xae, 0xbf, 0x49, 0x9e, 0xc0, 0x43, 0x73, 0xf4, 0x4f,
+ 0x28, 0x9e, 0x4e, 0x70, 0x28, 0x66, 0xaf, 0x97, 0x6d, 0xa1, 0xcf, 0xe0, 0x41, 0x46, 0xef, 0xa6,
+ 0x42, 0x30, 0xda, 0x36, 0x22, 0x76, 0x0e, 0xdd, 0x87, 0xb5, 0x8c, 0x93, 0x85, 0x6f, 0x73, 0xce,
+ 0xb8, 0x9d, 0x47, 0x8f, 0x60, 0x3d, 0x83, 0x77, 0xd4, 0xda, 0xed, 0x05, 0x34, 0xc4, 0x71, 0x8c,
+ 0x23, 0xbb, 0x80, 0xd6, 0xe1, 0x6e, 0x46, 0xf6, 0xc8, 0x95, 0xb1, 0x25, 0xe4, 0xc0, 0xbd, 0x39,
+ 0xe2, 0x4a, 0x65, 0x19, 0x3d, 0x00, 0x34, 0xc7, 0x74, 0xe8, 0x45, 0x10, 0x93, 0xc8, 0x5e, 0x41,
+ 0x8f, 0xc1, 0xc9, 0x70, 0x03, 0xf6, 0xb3, 0xd6, 0xd8, 0xc5, 0x05, 0x7b, 0x9c, 0x85, 0x38, 0x49,
+ 0x74, 0x7c, 0xa5, 0xf9, 0x94, 0xba, 0x4c, 0xb4, 0x29, 0x4b, 0x87, 0xa3, 0x83, 0x94, 0x46, 0x89,
+ 0x0d, 0xd7, 0xb8, 0x0e, 0x25, 0xc2, 0x74, 0xd2, 0x2e, 0xa3, 0x87, 0x70, 0x3f, 0xe3, 0x0e, 0x08,
+ 0x1f, 0x7f, 0x08, 0x38, 0xd6, 0x26, 0xc3, 0xcd, 0x3f, 0x5a, 0x60, 0x5f, 0xbf, 0x35, 0x91, 0x0d,
+ 0x95, 0xde, 0xce, 0xaf, 0xbd, 0x63, 0xf3, 0x50, 0xd8, 0x77, 0xd0, 0x5d, 0xa8, 0x29, 0xa4, 0xbf,
+ 0xe7, 0x76, 0x7a, 0xde, 0xe1, 0x4e, 0xff, 0xd0, 0xb6, 0xd0, 0x1a, 0x54, 0x15, 0x78, 0x74, 0xf2,
+ 0xce, 0xeb, 0xf4, 0x3b, 0xdf, 0xd8, 0xb9, 0x19, 0x74, 0xdc, 0x73, 0xdb, 0xde, 0x89, 0xdb, 0xb5,
+ 0xf3, 0x33, 0x63, 0xef, 0x3b, 0x5e, 0x57, 0x1a, 0x2b, 0xa0, 0x7b, 0x60, 0x2b, 0xa4, 0xd7, 0xea,
+ 0x1f, 0x66, 0xe8, 0xd2, 0x66, 0x0c, 0xb5, 0x6b, 0xcf, 0x95, 0x54, 0x9d, 0x7f, 0xb0, 0xec, 0x3b,
+ 0xd2, 0xbe, 0x42, 0x66, 0x2e, 0x2d, 0x54, 0x81, 0x62, 0xfb, 0xd4, 0x6b, 0xbb, 0xdd, 0x9d, 0x77,
+ 0x76, 0x6e, 0xa6, 0x92, 0xd9, 0xcd, 0x4b, 0x6f, 0x0a, 0x99, 0xf7, 0x56, 0xd8, 0x3c, 0x81, 0xb2,
+ 0xd9, 0x30, 0xe5, 0xa9, 0x0c, 0x2b, 0xde, 0x69, 0xa7, 0xdb, 0x3b, 0xf1, 0xec, 0x3b, 0xd2, 0xa2,
+ 0x77, 0x7a, 0x7c, 0xe2, 0xc9, 0x93, 0x85, 0x00, 0x96, 0xbd, 0xd3, 0xa3, 0xb6, 0xb7, 0x63, 0xe7,
+ 0xd0, 0x2a, 0x80, 0x77, 0x7a, 0xd0, 0xe9, 0x76, 0xfa, 0x87, 0xed, 0x7d, 0x3b, 0x8f, 0x6a, 0x50,
+ 0xf6, 0x4e, 0xdb, 0xa7, 0x9e, 0xbb, 0xb3, 0xbf, 0xe3, 0xed, 0xd8, 0x85, 0xcd, 0xff, 0xe4, 0x60,
+ 0x4d, 0x4f, 0xdb, 0xbc, 0xf5, 0x75, 0xb8, 0xbb, 0x00, 0xfa, 0xc7, 0x62, 0x84, 0xb9, 0x6d, 0xa1,
+ 0x06, 0x7c, 0xbe, 0x48, 0x1c, 0x60, 0x7c, 0x7c, 0x81, 0xb9, 0x37, 0xe2, 0x38, 0x19, 0xb1, 0x58,
+ 0xce, 0xea, 0x53, 0x78, 0xb4, 0x28, 0xb3, 0xc7, 0xe8, 0x19, 0xe1, 0x63, 0xdd, 0x35, 0x3b, 0x2f,
+ 0xf7, 0x60, 0x51, 0xc0, 0xc5, 0x09, 0x16, 0xfb, 0xf8, 0x82, 0x84, 0xd8, 0x2e, 0xdc, 0xa4, 0x8d,
+ 0xfe, 0x7b, 0xc6, 0xe5, 0xf4, 0x3e, 0x06, 0x67, 0x91, 0x7e, 0x4f, 0x26, 0xd8, 0x28, 0x2f, 0xdf,
+ 0x54, 0xee, 0x71, 0x26, 0x70, 0x28, 0xf6, 0x82, 0x38, 0xb6, 0x57, 0xe4, 0xa8, 0x2e, 0xd2, 0x72,
+ 0x8e, 0xbd, 0xa9, 0x5d, 0xbc, 0x19, 0x75, 0x36, 0x78, 0x7b, 0x23, 0x1c, 0x9e, 0xdb, 0x25, 0x39,
+ 0x93, 0x8b, 0x02, 0x3b, 0xfa, 0xcd, 0xb7, 0x41, 0xae, 0xe1, 0x35, 0xa7, 0xd9, 0x37, 0xbd, 0x5d,
+ 0xde, 0xfc, 0x1d, 0xdc, 0xeb, 0x11, 0x7a, 0x14, 0x08, 0x4e, 0xa6, 0xf3, 0x35, 0xae, 0xc3, 0xe3,
+ 0x8f, 0xe1, 0xfe, 0x5e, 0xca, 0x39, 0xa6, 0xc2, 0xb6, 0xd0, 0x33, 0x78, 0xf2, 0x51, 0x89, 0x2e,
+ 0xfe, 0x70, 0x40, 0x78, 0x22, 0xec, 0x9c, 0xec, 0xc7, 0xa7, 0x44, 0xfa, 0x38, 0x64, 0x34, 0xb2,
+ 0xf3, 0x9b, 0xbf, 0x01, 0xe4, 0xe2, 0x90, 0x5d, 0x60, 0x7e, 0xa9, 0xcb, 0xa4, 0xdc, 0xff, 0x00,
+ 0x9e, 0xdd, 0x44, 0xfd, 0x7e, 0xc8, 0x83, 0xf1, 0x20, 0xc6, 0x91, 0x2c, 0x76, 0x62, 0xdf, 0x91,
+ 0xf5, 0xfc, 0x88, 0x98, 0x76, 0x68, 0x5b, 0x9b, 0x67, 0x50, 0x93, 0x92, 0xf3, 0x79, 0x3d, 0x84,
+ 0xfb, 0xd7, 0x20, 0xbf, 0x17, 0x07, 0x84, 0xda, 0x77, 0x64, 0x9d, 0xae, 0x53, 0xda, 0xd2, 0x1b,
+ 0xdb, 0xfa, 0x34, 0xb9, 0x65, 0xe7, 0xb6, 0x7f, 0x06, 0x2b, 0x1f, 0x88, 0x7a, 0x41, 0xd0, 0xb3,
+ 0xa6, 0xfe, 0x2f, 0xd8, 0xcc, 0xfe, 0x0b, 0x36, 0xdb, 0x34, 0x1d, 0xff, 0x2a, 0x88, 0x53, 0x7c,
+ 0x3c, 0x91, 0x77, 0x60, 0xe2, 0x7c, 0xf7, 0x87, 0xbc, 0xfe, 0x52, 0x97, 0x3a, 0x1d, 0xba, 0xfd,
+ 0x73, 0x28, 0x2a, 0x6d, 0x96, 0x8a, 0xdb, 0xa8, 0xff, 0xdd, 0xa8, 0x2b, 0x97, 0xc7, 0xa9, 0xd8,
+ 0xfe, 0x06, 0xaa, 0x4a, 0x3f, 0xc2, 0x83, 0x74, 0x78, 0xcb, 0x18, 0xfe, 0x61, 0x8c, 0x94, 0xa5,
+ 0xe6, 0xbe, 0x54, 0xec, 0xd0, 0xed, 0x0e, 0xac, 0xce, 0x19, 0xba, 0x65, 0x38, 0xff, 0x34, 0x96,
+ 0x2a, 0x33, 0x4b, 0x32, 0xa6, 0x5f, 0x42, 0x49, 0x99, 0x12, 0x84, 0x5e, 0xde, 0xc6, 0xca, 0xbf,
+ 0x8c, 0x15, 0x55, 0x09, 0x8f, 0xd0, 0xcb, 0xed, 0x77, 0x50, 0x53, 0x16, 0x06, 0x8c, 0x89, 0x98,
+ 0xa9, 0x3f, 0x4f, 0xb7, 0xb0, 0xf3, 0x6f, 0x63, 0x47, 0x25, 0xb2, 0x3b, 0x53, 0xdd, 0xfd, 0x0a,
+ 0x9e, 0x87, 0x6c, 0xdc, 0x4c, 0x02, 0xc1, 0x92, 0x11, 0x89, 0x83, 0x41, 0xd2, 0x14, 0x1c, 0x7f,
+ 0xcb, 0x78, 0x33, 0x26, 0x83, 0x99, 0xbd, 0x5d, 0xf0, 0x14, 0x28, 0xdb, 0xfb, 0xff, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0x70, 0x88, 0xcd, 0x71, 0xe2, 0x0f, 0x00, 0x00,
+}
diff --git a/accounts/usbwallet/internal/trezor/types.proto b/accounts/usbwallet/internal/trezor/types.proto
new file mode 100644
index 000000000..3a358a584
--- /dev/null
+++ b/accounts/usbwallet/internal/trezor/types.proto
@@ -0,0 +1,276 @@
+// This file originates from the SatoshiLabs Trezor `common` repository at:
+// https://github.com/trezor/trezor-common/blob/master/protob/types.proto
+// dated 28.07.2017, commit dd8ec3231fb5f7992360aff9bdfe30bb58130f4b.
+
+/**
+ * Types for TREZOR communication
+ *
+ * @author Marek Palatinus <slush@satoshilabs.com>
+ * @version 1.2
+ */
+
+// Sugar for easier handling in Java
+option java_package = "com.satoshilabs.trezor.lib.protobuf";
+option java_outer_classname = "TrezorType";
+
+import "google/protobuf/descriptor.proto";
+
+/**
+ * Options for specifying message direction and type of wire (normal/debug)
+ */
+extend google.protobuf.EnumValueOptions {
+ optional bool wire_in = 50002; // message can be transmitted via wire from PC to TREZOR
+ optional bool wire_out = 50003; // message can be transmitted via wire from TREZOR to PC
+ optional bool wire_debug_in = 50004; // message can be transmitted via debug wire from PC to TREZOR
+ optional bool wire_debug_out = 50005; // message can be transmitted via debug wire from TREZOR to PC
+ optional bool wire_tiny = 50006; // message is handled by TREZOR when the USB stack is in tiny mode
+ optional bool wire_bootloader = 50007; // message is only handled by TREZOR Bootloader
+}
+
+/**
+ * Type of failures returned by Failure message
+ * @used_in Failure
+ */
+enum FailureType {
+ Failure_UnexpectedMessage = 1;
+ Failure_ButtonExpected = 2;
+ Failure_DataError = 3;
+ Failure_ActionCancelled = 4;
+ Failure_PinExpected = 5;
+ Failure_PinCancelled = 6;
+ Failure_PinInvalid = 7;
+ Failure_InvalidSignature = 8;
+ Failure_ProcessError = 9;
+ Failure_NotEnoughFunds = 10;
+ Failure_NotInitialized = 11;
+ Failure_FirmwareError = 99;
+}
+
+/**
+ * Type of script which will be used for transaction output
+ * @used_in TxOutputType
+ */
+enum OutputScriptType {
+ PAYTOADDRESS = 0; // used for all addresses (bitcoin, p2sh, witness)
+ PAYTOSCRIPTHASH = 1; // p2sh address (deprecated; use PAYTOADDRESS)
+ PAYTOMULTISIG = 2; // only for change output
+ PAYTOOPRETURN = 3; // op_return
+ PAYTOWITNESS = 4; // only for change output
+ PAYTOP2SHWITNESS = 5; // only for change output
+}
+
+/**
+ * Type of script which will be used for transaction output
+ * @used_in TxInputType
+ */
+enum InputScriptType {
+ SPENDADDRESS = 0; // standard p2pkh address
+ SPENDMULTISIG = 1; // p2sh multisig address
+ EXTERNAL = 2; // reserved for external inputs (coinjoin)
+ SPENDWITNESS = 3; // native segwit
+ SPENDP2SHWITNESS = 4; // segwit over p2sh (backward compatible)
+}
+
+/**
+ * Type of information required by transaction signing process
+ * @used_in TxRequest
+ */
+enum RequestType {
+ TXINPUT = 0;
+ TXOUTPUT = 1;
+ TXMETA = 2;
+ TXFINISHED = 3;
+ TXEXTRADATA = 4;
+}
+
+/**
+ * Type of button request
+ * @used_in ButtonRequest
+ */
+enum ButtonRequestType {
+ ButtonRequest_Other = 1;
+ ButtonRequest_FeeOverThreshold = 2;
+ ButtonRequest_ConfirmOutput = 3;
+ ButtonRequest_ResetDevice = 4;
+ ButtonRequest_ConfirmWord = 5;
+ ButtonRequest_WipeDevice = 6;
+ ButtonRequest_ProtectCall = 7;
+ ButtonRequest_SignTx = 8;
+ ButtonRequest_FirmwareCheck = 9;
+ ButtonRequest_Address = 10;
+ ButtonRequest_PublicKey = 11;
+}
+
+/**
+ * Type of PIN request
+ * @used_in PinMatrixRequest
+ */
+enum PinMatrixRequestType {
+ PinMatrixRequestType_Current = 1;
+ PinMatrixRequestType_NewFirst = 2;
+ PinMatrixRequestType_NewSecond = 3;
+}
+
+/**
+ * Type of recovery procedure. These should be used as bitmask, e.g.,
+ * `RecoveryDeviceType_ScrambledWords | RecoveryDeviceType_Matrix`
+ * listing every method supported by the host computer.
+ *
+ * Note that ScrambledWords must be supported by every implementation
+ * for backward compatibility; there is no way to not support it.
+ *
+ * @used_in RecoveryDevice
+ */
+enum RecoveryDeviceType {
+ // use powers of two when extending this field
+ RecoveryDeviceType_ScrambledWords = 0; // words in scrambled order
+ RecoveryDeviceType_Matrix = 1; // matrix recovery type
+}
+
+/**
+ * Type of Recovery Word request
+ * @used_in WordRequest
+ */
+enum WordRequestType {
+ WordRequestType_Plain = 0;
+ WordRequestType_Matrix9 = 1;
+ WordRequestType_Matrix6 = 2;
+}
+
+/**
+ * Structure representing BIP32 (hierarchical deterministic) node
+ * Used for imports of private key into the device and exporting public key out of device
+ * @used_in PublicKey
+ * @used_in LoadDevice
+ * @used_in DebugLinkState
+ * @used_in Storage
+ */
+message HDNodeType {
+ required uint32 depth = 1;
+ required uint32 fingerprint = 2;
+ required uint32 child_num = 3;
+ required bytes chain_code = 4;
+ optional bytes private_key = 5;
+ optional bytes public_key = 6;
+}
+
+message HDNodePathType {
+ required HDNodeType node = 1; // BIP-32 node in deserialized form
+ repeated uint32 address_n = 2; // BIP-32 path to derive the key from node
+}
+
+/**
+ * Structure representing Coin
+ * @used_in Features
+ */
+message CoinType {
+ optional string coin_name = 1;
+ optional string coin_shortcut = 2;
+ optional uint32 address_type = 3 [default=0];
+ optional uint64 maxfee_kb = 4;
+ optional uint32 address_type_p2sh = 5 [default=5];
+ optional string signed_message_header = 8;
+ optional uint32 xpub_magic = 9 [default=76067358]; // default=0x0488b21e
+ optional uint32 xprv_magic = 10 [default=76066276]; // default=0x0488ade4
+ optional bool segwit = 11;
+ optional uint32 forkid = 12;
+}
+
+/**
+ * Type of redeem script used in input
+ * @used_in TxInputType
+ */
+message MultisigRedeemScriptType {
+ repeated HDNodePathType pubkeys = 1; // pubkeys from multisig address (sorted lexicographically)
+ repeated bytes signatures = 2; // existing signatures for partially signed input
+ optional uint32 m = 3; // "m" from n, how many valid signatures is necessary for spending
+}
+
+/**
+ * Structure representing transaction input
+ * @used_in SimpleSignTx
+ * @used_in TransactionType
+ */
+message TxInputType {
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ required bytes prev_hash = 2; // hash of previous transaction output to spend by this input
+ required uint32 prev_index = 3; // index of previous output to spend
+ optional bytes script_sig = 4; // script signature, unset for tx to sign
+ optional uint32 sequence = 5 [default=4294967295]; // sequence (default=0xffffffff)
+ optional InputScriptType script_type = 6 [default=SPENDADDRESS]; // defines template of input script
+ optional MultisigRedeemScriptType multisig = 7; // Filled if input is going to spend multisig tx
+ optional uint64 amount = 8; // amount of previous transaction output (for segwit only)
+}
+
+/**
+ * Structure representing transaction output
+ * @used_in SimpleSignTx
+ * @used_in TransactionType
+ */
+message TxOutputType {
+ optional string address = 1; // target coin address in Base58 encoding
+ repeated uint32 address_n = 2; // BIP-32 path to derive the key from master node; has higher priority than "address"
+ required uint64 amount = 3; // amount to spend in satoshis
+ required OutputScriptType script_type = 4; // output script type
+ optional MultisigRedeemScriptType multisig = 5; // defines multisig address; script_type must be PAYTOMULTISIG
+ optional bytes op_return_data = 6; // defines op_return data; script_type must be PAYTOOPRETURN, amount must be 0
+}
+
+/**
+ * Structure representing compiled transaction output
+ * @used_in TransactionType
+ */
+message TxOutputBinType {
+ required uint64 amount = 1;
+ required bytes script_pubkey = 2;
+}
+
+/**
+ * Structure representing transaction
+ * @used_in SimpleSignTx
+ */
+message TransactionType {
+ optional uint32 version = 1;
+ repeated TxInputType inputs = 2;
+ repeated TxOutputBinType bin_outputs = 3;
+ repeated TxOutputType outputs = 5;
+ optional uint32 lock_time = 4;
+ optional uint32 inputs_cnt = 6;
+ optional uint32 outputs_cnt = 7;
+ optional bytes extra_data = 8;
+ optional uint32 extra_data_len = 9;
+}
+
+/**
+ * Structure representing request details
+ * @used_in TxRequest
+ */
+message TxRequestDetailsType {
+ optional uint32 request_index = 1; // device expects TxAck message from the computer
+ optional bytes tx_hash = 2; // tx_hash of requested transaction
+ optional uint32 extra_data_len = 3; // length of requested extra data
+ optional uint32 extra_data_offset = 4; // offset of requested extra data
+}
+
+/**
+ * Structure representing serialized data
+ * @used_in TxRequest
+ */
+message TxRequestSerializedType {
+ optional uint32 signature_index = 1; // 'signature' field contains signed input of this index
+ optional bytes signature = 2; // signature of the signature_index input
+ optional bytes serialized_tx = 3; // part of serialized and signed transaction
+}
+
+/**
+ * Structure representing identity data
+ * @used_in IdentityType
+ */
+message IdentityType {
+ optional string proto = 1; // proto part of URI
+ optional string user = 2; // user part of URI
+ optional string host = 3; // host part of URI
+ optional string port = 4; // port part of URI
+ optional string path = 5; // path part of URI
+ optional uint32 index = 6 [default=0]; // identity index
+}
diff --git a/accounts/usbwallet/ledger_hub.go b/accounts/usbwallet/ledger_hub.go
index 2b0d56097..ffe7cffe4 100644
--- a/accounts/usbwallet/ledger_hub.go
+++ b/accounts/usbwallet/ledger_hub.go
@@ -14,10 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-// This file contains the implementation for interacting with the Ledger hardware
-// wallets. The wire protocol spec can be found in the Ledger Blue GitHub repo:
-// https://raw.githubusercontent.com/LedgerHQ/blue-app-eth/master/doc/ethapp.asc
-
package usbwallet
import (
@@ -140,14 +136,14 @@ func (hub *LedgerHub) refreshWallets() {
// Drop wallets in front of the next device or those that failed for some reason
for len(hub.wallets) > 0 && (hub.wallets[0].URL().Cmp(url) < 0 || hub.wallets[0].(*ledgerWallet).failed()) {
- events = append(events, accounts.WalletEvent{Wallet: hub.wallets[0], Arrive: false})
+ events = append(events, accounts.WalletEvent{Wallet: hub.wallets[0], Kind: accounts.WalletDropped})
hub.wallets = hub.wallets[1:]
}
// If there are no more wallets or the device is before the next, wrap new wallet
if len(hub.wallets) == 0 || hub.wallets[0].URL().Cmp(url) > 0 {
wallet := &ledgerWallet{hub: hub, url: &url, info: ledger, log: log.New("url", url)}
- events = append(events, accounts.WalletEvent{Wallet: wallet, Arrive: true})
+ events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
wallets = append(wallets, wallet)
continue
}
@@ -160,7 +156,7 @@ func (hub *LedgerHub) refreshWallets() {
}
// Drop any leftover wallets and set the new batch
for _, wallet := range hub.wallets {
- events = append(events, accounts.WalletEvent{Wallet: wallet, Arrive: false})
+ events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped})
}
hub.refreshed = time.Now()
hub.wallets = wallets
diff --git a/accounts/usbwallet/ledger_wallet.go b/accounts/usbwallet/ledger_wallet.go
index f1beebb2c..b8f04d74c 100644
--- a/accounts/usbwallet/ledger_wallet.go
+++ b/accounts/usbwallet/ledger_wallet.go
@@ -41,13 +41,6 @@ import (
"github.com/karalabe/hid"
)
-// Maximum time between wallet health checks to detect USB unplugs.
-const ledgerHeartbeatCycle = time.Second
-
-// Minimum time to wait between self derivation attempts, even it the user is
-// requesting accounts like crazy.
-const ledgerSelfDeriveThrottling = time.Second
-
// ledgerOpcode is an enumeration encoding the supported Ledger opcodes.
type ledgerOpcode byte
@@ -215,6 +208,8 @@ func (w *ledgerWallet) Open(passphrase string) error {
if w.version, err = w.ledgerVersion(); err != nil {
w.version = [3]byte{1, 0, 0} // Assume worst case, can't verify if v1.0.0 or v1.0.1
}
+ go w.hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened})
+
return nil
}
@@ -237,7 +232,7 @@ func (w *ledgerWallet) heartbeat() {
case errc = <-w.healthQuit:
// Termination requested
continue
- case <-time.After(ledgerHeartbeatCycle):
+ case <-time.After(heartbeatCycle):
// Heartbeat time
}
// Execute a tiny data exchange to see responsiveness
@@ -465,7 +460,7 @@ func (w *ledgerWallet) selfDerive() {
select {
case errc = <-w.deriveQuit:
// Termination requested, abort
- case <-time.After(ledgerSelfDeriveThrottling):
+ case <-time.After(selfDeriveThrottling):
// Waited enough, willing to self-derive again
}
}
diff --git a/accounts/usbwallet/trezor_hub.go b/accounts/usbwallet/trezor_hub.go
new file mode 100644
index 000000000..5681a55c7
--- /dev/null
+++ b/accounts/usbwallet/trezor_hub.go
@@ -0,0 +1,210 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+package usbwallet
+
+import (
+ "errors"
+ "runtime"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/karalabe/hid"
+)
+
+// TrezorScheme is the protocol scheme prefixing account and wallet URLs.
+var TrezorScheme = "trezor"
+
+// trezorVendorID is the USB vendor ID for SatoshiLabs.
+var trezorVendorID = uint16(0x534c)
+
+// trezorDeviceID is the USB device ID for the Trezor 1.
+var trezorDeviceID = uint16(0x0001)
+
+// Maximum time between wallet refreshes (if USB hotplug notifications don't work).
+const trezorRefreshCycle = time.Second
+
+// Minimum time between wallet refreshes to avoid USB trashing.
+const trezorRefreshThrottling = 500 * time.Millisecond
+
+// TrezorHub is a accounts.Backend that can find and handle Trezor hardware wallets.
+type TrezorHub struct {
+ refreshed time.Time // Time instance when the list of wallets was last refreshed
+ wallets []accounts.Wallet // List of Trezor devices currently tracking
+ updateFeed event.Feed // Event feed to notify wallet additions/removals
+ updateScope event.SubscriptionScope // Subscription scope tracking current live listeners
+ updating bool // Whether the event notification loop is running
+
+ quit chan chan error
+
+ stateLock sync.RWMutex // Protects the internals of the hub from racey access
+
+ // TODO(karalabe): remove if hotplug lands on Windows
+ commsPend int // Number of operations blocking enumeration
+ commsLock sync.Mutex // Lock protecting the pending counter and enumeration
+}
+
+// NewTrezorHub creates a new hardware wallet manager for Trezor devices.
+func NewTrezorHub() (*TrezorHub, error) {
+ if !hid.Supported() {
+ return nil, errors.New("unsupported platform")
+ }
+ hub := &TrezorHub{
+ quit: make(chan chan error),
+ }
+ hub.refreshWallets()
+ return hub, nil
+}
+
+// Wallets implements accounts.Backend, returning all the currently tracked USB
+// devices that appear to be Trezor hardware wallets.
+func (hub *TrezorHub) Wallets() []accounts.Wallet {
+ // Make sure the list of wallets is up to date
+ hub.refreshWallets()
+
+ hub.stateLock.RLock()
+ defer hub.stateLock.RUnlock()
+
+ cpy := make([]accounts.Wallet, len(hub.wallets))
+ copy(cpy, hub.wallets)
+ return cpy
+}
+
+// refreshWallets scans the USB devices attached to the machine and updates the
+// list of wallets based on the found devices.
+func (hub *TrezorHub) refreshWallets() {
+ // Don't scan the USB like crazy it the user fetches wallets in a loop
+ hub.stateLock.RLock()
+ elapsed := time.Since(hub.refreshed)
+ hub.stateLock.RUnlock()
+
+ if elapsed < trezorRefreshThrottling {
+ return
+ }
+ // Retrieve the current list of Trezor devices
+ var trezors []hid.DeviceInfo
+
+ if runtime.GOOS == "linux" {
+ // hidapi on Linux opens the device during enumeration to retrieve some infos,
+ // breaking the Trezor protocol if that is waiting for user confirmation. This
+ // is a bug acknowledged at Trezor, but it won't be fixed on old devices so we
+ // need to prevent concurrent comms ourselves. The more elegant solution would
+ // be to ditch enumeration in favor of hutplug events, but that don't work yet
+ // on Windows so if we need to hack it anyway, this is more elegant for now.
+ hub.commsLock.Lock()
+ if hub.commsPend > 0 { // A confirmation is pending, don't refresh
+ hub.commsLock.Unlock()
+ return
+ }
+ }
+ for _, info := range hid.Enumerate(trezorVendorID, trezorDeviceID) {
+ if info.Interface == 0 { // interface #1 is the debug link, skip it
+ trezors = append(trezors, info)
+ }
+ }
+ if runtime.GOOS == "linux" {
+ // See rationale before the enumeration why this is needed and only on Linux.
+ hub.commsLock.Unlock()
+ }
+ // Transform the current list of wallets into the new one
+ hub.stateLock.Lock()
+
+ wallets := make([]accounts.Wallet, 0, len(trezors))
+ events := []accounts.WalletEvent{}
+
+ for _, trezor := range trezors {
+ url := accounts.URL{Scheme: TrezorScheme, Path: trezor.Path}
+
+ // Drop wallets in front of the next device or those that failed for some reason
+ for len(hub.wallets) > 0 && (hub.wallets[0].URL().Cmp(url) < 0 || hub.wallets[0].(*trezorWallet).failed()) {
+ events = append(events, accounts.WalletEvent{Wallet: hub.wallets[0], Kind: accounts.WalletDropped})
+ hub.wallets = hub.wallets[1:]
+ }
+ // If there are no more wallets or the device is before the next, wrap new wallet
+ if len(hub.wallets) == 0 || hub.wallets[0].URL().Cmp(url) > 0 {
+ wallet := &trezorWallet{hub: hub, url: &url, info: trezor, log: log.New("url", url)}
+
+ events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletArrived})
+ wallets = append(wallets, wallet)
+ continue
+ }
+ // If the device is the same as the first wallet, keep it
+ if hub.wallets[0].URL().Cmp(url) == 0 {
+ wallets = append(wallets, hub.wallets[0])
+ hub.wallets = hub.wallets[1:]
+ continue
+ }
+ }
+ // Drop any leftover wallets and set the new batch
+ for _, wallet := range hub.wallets {
+ events = append(events, accounts.WalletEvent{Wallet: wallet, Kind: accounts.WalletDropped})
+ }
+ hub.refreshed = time.Now()
+ hub.wallets = wallets
+ hub.stateLock.Unlock()
+
+ // Fire all wallet events and return
+ for _, event := range events {
+ hub.updateFeed.Send(event)
+ }
+}
+
+// Subscribe implements accounts.Backend, creating an async subscription to
+// receive notifications on the addition or removal of Trezor wallets.
+func (hub *TrezorHub) Subscribe(sink chan<- accounts.WalletEvent) event.Subscription {
+ // We need the mutex to reliably start/stop the update loop
+ hub.stateLock.Lock()
+ defer hub.stateLock.Unlock()
+
+ // Subscribe the caller and track the subscriber count
+ sub := hub.updateScope.Track(hub.updateFeed.Subscribe(sink))
+
+ // Subscribers require an active notification loop, start it
+ if !hub.updating {
+ hub.updating = true
+ go hub.updater()
+ }
+ return sub
+}
+
+// updater is responsible for maintaining an up-to-date list of wallets stored in
+// the keystore, and for firing wallet addition/removal events. It listens for
+// account change events from the underlying account cache, and also periodically
+// forces a manual refresh (only triggers for systems where the filesystem notifier
+// is not running).
+func (hub *TrezorHub) updater() {
+ for {
+ // Wait for a USB hotplug event (not supported yet) or a refresh timeout
+ select {
+ //case <-hub.changes: // reenable on hutplug implementation
+ case <-time.After(trezorRefreshCycle):
+ }
+ // Run the wallet refresher
+ hub.refreshWallets()
+
+ // If all our subscribers left, stop the updater
+ hub.stateLock.Lock()
+ if hub.updateScope.Count() == 0 {
+ hub.updating = false
+ hub.stateLock.Unlock()
+ return
+ }
+ hub.stateLock.Unlock()
+ }
+}
diff --git a/accounts/usbwallet/trezor_wallet.go b/accounts/usbwallet/trezor_wallet.go
new file mode 100644
index 000000000..779119192
--- /dev/null
+++ b/accounts/usbwallet/trezor_wallet.go
@@ -0,0 +1,761 @@
+// Copyright 2017 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+
+// This file contains the implementation for interacting with the Trezor hardware
+// wallets. The wire protocol spec can be found on the SatoshiLabs website:
+// https://doc.satoshilabs.com/trezor-tech/api-protobuf.html
+
+package usbwallet
+
+import (
+ "context"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "math/big"
+ "sync"
+ "time"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts"
+ "github.com/ethereum/go-ethereum/accounts/usbwallet/internal/trezor"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/golang/protobuf/proto"
+ "github.com/karalabe/hid"
+)
+
+// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In
+// this case, the calling application should display a pinpad and send back the
+// encoded passphrase.
+var ErrTrezorPINNeeded = errors.New("trezor: pin needed")
+
+// trezorWallet represents a live USB Trezor hardware wallet.
+type trezorWallet struct {
+ hub *TrezorHub // USB hub the device originates from (TODO(karalabe): remove if hotplug lands on Windows)
+ url *accounts.URL // Textual URL uniquely identifying this wallet
+
+ info hid.DeviceInfo // Known USB device infos about the wallet
+ device *hid.Device // USB device advertising itself as a Trezor wallet
+ failure error // Any failure that would make the device unusable
+
+ version [3]uint32 // Current version of the Trezor formware (zero if app is offline)
+ label string // Current textual label of the Trezor device
+ pinwait bool // Flags whether the device is waiting for PIN entry
+ accounts []accounts.Account // List of derive accounts pinned on the Trezor
+ paths map[common.Address]accounts.DerivationPath // Known derivation paths for signing operations
+
+ deriveNextPath accounts.DerivationPath // Next derivation path for account auto-discovery
+ deriveNextAddr common.Address // Next derived account address for auto-discovery
+ deriveChain ethereum.ChainStateReader // Blockchain state reader to discover used account with
+ deriveReq chan chan struct{} // Channel to request a self-derivation on
+ deriveQuit chan chan error // Channel to terminate the self-deriver with
+
+ healthQuit chan chan error
+
+ // Locking a hardware wallet is a bit special. Since hardware devices are lower
+ // performing, any communication with them might take a non negligible amount of
+ // time. Worse still, waiting for user confirmation can take arbitrarily long,
+ // but exclusive communication must be upheld during. Locking the entire wallet
+ // in the mean time however would stall any parts of the system that don't want
+ // to communicate, just read some state (e.g. list the accounts).
+ //
+ // As such, a hardware wallet needs two locks to function correctly. A state
+ // lock can be used to protect the wallet's software-side internal state, which
+ // must not be held exlusively during hardware communication. A communication
+ // lock can be used to achieve exclusive access to the device itself, this one
+ // however should allow "skipping" waiting for operations that might want to
+ // use the device, but can live without too (e.g. account self-derivation).
+ //
+ // Since we have two locks, it's important to know how to properly use them:
+ // - Communication requires the `device` to not change, so obtaining the
+ // commsLock should be done after having a stateLock.
+ // - Communication must not disable read access to the wallet state, so it
+ // must only ever hold a *read* lock to stateLock.
+ commsLock chan struct{} // Mutex (buf=1) for the USB comms without keeping the state locked
+ stateLock sync.RWMutex // Protects read and write access to the wallet struct fields
+
+ log log.Logger // Contextual logger to tag the trezor with its id
+}
+
+// URL implements accounts.Wallet, returning the URL of the Trezor device.
+func (w *trezorWallet) URL() accounts.URL {
+ return *w.url // Immutable, no need for a lock
+}
+
+// Status implements accounts.Wallet, always whether the Trezor is opened, closed
+// or whether the Ethereum app was not started on it.
+func (w *trezorWallet) Status() string {
+ w.stateLock.RLock() // No device communication, state lock is enough
+ defer w.stateLock.RUnlock()
+
+ if w.failure != nil {
+ return fmt.Sprintf("Failed: %v", w.failure)
+ }
+ if w.device == nil {
+ return "Closed"
+ }
+ if w.pinwait {
+ return fmt.Sprintf("Trezor v%d.%d.%d '%s' waiting for PIN", w.version[0], w.version[1], w.version[2], w.label)
+ }
+ return fmt.Sprintf("Trezor v%d.%d.%d '%s' online", w.version[0], w.version[1], w.version[2], w.label)
+}
+
+// failed returns if the USB device wrapped by the wallet failed for some reason.
+// This is used by the device scanner to report failed wallets as departed.
+//
+// The method assumes that the state lock is *not* held!
+func (w *trezorWallet) failed() bool {
+ w.stateLock.RLock() // No device communication, state lock is enough
+ defer w.stateLock.RUnlock()
+
+ return w.failure != nil
+}
+
+// Open implements accounts.Wallet, attempting to open a USB connection to the
+// Trezor hardware wallet. Connecting to the Trezor is a two phase operation:
+// * The first phase is to establish the USB connection, initialize it and read
+// the wallet's features. This phase is invoked is the provided passphrase is
+// empty. The device will display the pinpad as a result and will return an
+// appropriate error to notify the user that a second open phase is needed.
+// * The second phase is to unlock access to the Trezor, which is done by the
+// user actually providing a passphrase mapping a keyboard keypad to the pin
+// number of the user (shuffled according to the pinpad displayed).
+func (w *trezorWallet) Open(passphrase string) error {
+ w.stateLock.Lock() // State lock is enough since there's no connection yet at this point
+ defer w.stateLock.Unlock()
+
+ // If phase 1 is requested, init the connection and wait for user callback
+ if passphrase == "" {
+ // If we're already waiting for a PIN entry, insta-return
+ if w.pinwait {
+ return ErrTrezorPINNeeded
+ }
+ // Initialize a connection to the device
+ if err := w.openInit(); err != nil {
+ return err
+ }
+ // Do a manual ping, forcing the device to ask for its PIN
+ askPin, pinRequest := true, new(trezor.PinMatrixRequest)
+ if err := w.trezorExchange(&trezor.Ping{PinProtection: &askPin}, pinRequest); err != nil {
+ return err
+ }
+ w.pinwait = true
+
+ return ErrTrezorPINNeeded
+ }
+ // Phase 2 requested with actual PIN entry
+ w.pinwait = false
+
+ success := new(trezor.Success)
+ if err := w.trezorExchange(&trezor.PinMatrixAck{Pin: &passphrase}, success); err != nil {
+ w.failure = err
+ return err
+ }
+ go w.hub.updateFeed.Send(accounts.WalletEvent{Wallet: w, Kind: accounts.WalletOpened})
+
+ // Trezor unlocked, start the heartbeat cycle and account derivation
+ w.paths = make(map[common.Address]accounts.DerivationPath)
+
+ w.deriveReq = make(chan chan struct{})
+ w.deriveQuit = make(chan chan error)
+ w.healthQuit = make(chan chan error)
+
+ defer func() {
+ go w.heartbeat()
+ go w.selfDerive()
+ }()
+ return nil
+}
+
+// openInit is the first phase of a Trezor opening mechanism which initializes
+// device connection and requests the device to display the pinpad.
+func (w *trezorWallet) openInit() error {
+ // If the wallet was already opened, don't try to phase-1 open again
+ if w.device != nil {
+ return accounts.ErrWalletAlreadyOpen
+ }
+ // Otherwise iterate over all USB devices and find this again (no way to directly do this)
+ device, err := w.info.Open()
+ if err != nil {
+ return err
+ }
+ // Wallet successfully connected to, init the connection and start the heartbeat
+ w.device = device
+ w.commsLock = make(chan struct{}, 1)
+ w.commsLock <- struct{}{} // Enable lock
+
+ // Retrieve the Trezor's version number and user label
+ features := new(trezor.Features)
+ if err := w.trezorExchange(&trezor.Initialize{}, features); err != nil {
+ return err
+ }
+ w.version = [3]uint32{features.GetMajorVersion(), features.GetMinorVersion(), features.GetPatchVersion()}
+ w.label = features.GetLabel()
+
+ return nil
+}
+
+// heartbeat is a health check loop for the Trezor wallets to periodically verify
+// whether they are still present or if they malfunctioned. It is needed because:
+// - libusb on Windows doesn't support hotplug, so we can't detect USB unplugs
+func (w *trezorWallet) heartbeat() {
+ w.log.Debug("Trezor health-check started")
+ defer w.log.Debug("Trezor health-check stopped")
+
+ // Execute heartbeat checks until termination or error
+ var (
+ errc chan error
+ err error
+ )
+ for errc == nil && err == nil {
+ // Wait until termination is requested or the heartbeat cycle arrives
+ select {
+ case errc = <-w.healthQuit:
+ // Termination requested
+ continue
+ case <-time.After(heartbeatCycle):
+ // Heartbeat time
+ }
+ // Execute a tiny data exchange to see responsiveness
+ w.stateLock.RLock()
+ if w.device == nil {
+ // Terminated while waiting for the lock
+ w.stateLock.RUnlock()
+ continue
+ }
+ <-w.commsLock // Don't lock state while executing ping
+
+ success := new(trezor.Success)
+ err = w.trezorExchange(&trezor.Ping{}, success)
+
+ w.commsLock <- struct{}{}
+ w.stateLock.RUnlock()
+
+ if err != nil {
+ w.stateLock.Lock() // Lock state to tear the wallet down
+ w.failure = err
+ w.close()
+ w.stateLock.Unlock()
+ }
+ // Ignore non hardware related errors
+ err = nil
+ }
+ // In case of error, wait for termination
+ if err != nil {
+ w.log.Debug("Trezor health-check failed", "err", err)
+ errc = <-w.healthQuit
+ }
+ errc <- err
+}
+
+// Close implements accounts.Wallet, closing the USB connection to the Trezor.
+func (w *trezorWallet) Close() error {
+ // Ensure the wallet was opened
+ w.stateLock.RLock()
+ hQuit, dQuit := w.healthQuit, w.deriveQuit
+ w.stateLock.RUnlock()
+
+ // Terminate the health checks
+ var herr error
+ if hQuit != nil {
+ errc := make(chan error)
+ hQuit <- errc
+ herr = <-errc // Save for later, we *must* close the USB
+ }
+ // Terminate the self-derivations
+ var derr error
+ if dQuit != nil {
+ errc := make(chan error)
+ dQuit <- errc
+ derr = <-errc // Save for later, we *must* close the USB
+ }
+ // Terminate the device connection
+ w.stateLock.Lock()
+ defer w.stateLock.Unlock()
+
+ w.healthQuit = nil
+ w.deriveQuit = nil
+ w.deriveReq = nil
+
+ if err := w.close(); err != nil {
+ return err
+ }
+ if herr != nil {
+ return herr
+ }
+ return derr
+}
+
+// close is the internal wallet closer that terminates the USB connection and
+// resets all the fields to their defaults.
+//
+// Note, close assumes the state lock is held!
+func (w *trezorWallet) close() error {
+ // Allow duplicate closes, especially for health-check failures
+ if w.device == nil {
+ return nil
+ }
+ // Close the device, clear everything, then return
+ w.device.Close()
+ w.device = nil
+
+ w.label, w.version = "", [3]uint32{}
+ w.accounts, w.paths = nil, nil
+
+ return nil
+}
+
+// Accounts implements accounts.Wallet, returning the list of accounts pinned to
+// the Trezor hardware wallet. If self-derivation was enabled, the account list
+// is periodically expanded based on current chain state.
+func (w *trezorWallet) Accounts() []accounts.Account {
+ // Attempt self-derivation if it's running
+ reqc := make(chan struct{}, 1)
+ select {
+ case w.deriveReq <- reqc:
+ // Self-derivation request accepted, wait for it
+ <-reqc
+ default:
+ // Self-derivation offline, throttled or busy, skip
+ }
+ // Return whatever account list we ended up with
+ w.stateLock.RLock()
+ defer w.stateLock.RUnlock()
+
+ cpy := make([]accounts.Account, len(w.accounts))
+ copy(cpy, w.accounts)
+ return cpy
+}
+
+// selfDerive is an account derivation loop that upon request attempts to find
+// new non-zero accounts.
+func (w *trezorWallet) selfDerive() {
+ w.log.Debug("Trezor self-derivation started")
+ defer w.log.Debug("Trezor self-derivation stopped")
+
+ // Execute self-derivations until termination or error
+ var (
+ reqc chan struct{}
+ errc chan error
+ err error
+ )
+ for errc == nil && err == nil {
+ // Wait until either derivation or termination is requested
+ select {
+ case errc = <-w.deriveQuit:
+ // Termination requested
+ continue
+ case reqc = <-w.deriveReq:
+ // Account discovery requested
+ }
+ // Derivation needs a chain and device access, skip if either unavailable
+ w.stateLock.RLock()
+ if w.device == nil || w.deriveChain == nil {
+ w.stateLock.RUnlock()
+ reqc <- struct{}{}
+ continue
+ }
+ select {
+ case <-w.commsLock:
+ default:
+ w.stateLock.RUnlock()
+ reqc <- struct{}{}
+ continue
+ }
+ // Device lock obtained, derive the next batch of accounts
+ var (
+ accs []accounts.Account
+ paths []accounts.DerivationPath
+
+ nextAddr = w.deriveNextAddr
+ nextPath = w.deriveNextPath
+
+ context = context.Background()
+ )
+ for empty := false; !empty; {
+ // Retrieve the next derived Ethereum account
+ if nextAddr == (common.Address{}) {
+ if nextAddr, err = w.trezorDerive(nextPath); err != nil {
+ w.log.Warn("Trezor account derivation failed", "err", err)
+ break
+ }
+ }
+ // Check the account's status against the current chain state
+ var (
+ balance *big.Int
+ nonce uint64
+ )
+ balance, err = w.deriveChain.BalanceAt(context, nextAddr, nil)
+ if err != nil {
+ w.log.Warn("Trezor balance retrieval failed", "err", err)
+ break
+ }
+ nonce, err = w.deriveChain.NonceAt(context, nextAddr, nil)
+ if err != nil {
+ w.log.Warn("Trezor nonce retrieval failed", "err", err)
+ break
+ }
+ // If the next account is empty, stop self-derivation, but add it nonetheless
+ if balance.Sign() == 0 && nonce == 0 {
+ empty = true
+ }
+ // We've just self-derived a new account, start tracking it locally
+ path := make(accounts.DerivationPath, len(nextPath))
+ copy(path[:], nextPath[:])
+ paths = append(paths, path)
+
+ account := accounts.Account{
+ Address: nextAddr,
+ URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
+ }
+ accs = append(accs, account)
+
+ // Display a log message to the user for new (or previously empty accounts)
+ if _, known := w.paths[nextAddr]; !known || (!empty && nextAddr == w.deriveNextAddr) {
+ w.log.Info("Trezor discovered new account", "address", nextAddr, "path", path, "balance", balance, "nonce", nonce)
+ }
+ // Fetch the next potential account
+ if !empty {
+ nextAddr = common.Address{}
+ nextPath[len(nextPath)-1]++
+ }
+ }
+ // Self derivation complete, release device lock
+ w.commsLock <- struct{}{}
+ w.stateLock.RUnlock()
+
+ // Insert any accounts successfully derived
+ w.stateLock.Lock()
+ for i := 0; i < len(accs); i++ {
+ if _, ok := w.paths[accs[i].Address]; !ok {
+ w.accounts = append(w.accounts, accs[i])
+ w.paths[accs[i].Address] = paths[i]
+ }
+ }
+ // Shift the self-derivation forward
+ // TODO(karalabe): don't overwrite changes from wallet.SelfDerive
+ w.deriveNextAddr = nextAddr
+ w.deriveNextPath = nextPath
+ w.stateLock.Unlock()
+
+ // Notify the user of termination and loop after a bit of time (to avoid trashing)
+ reqc <- struct{}{}
+ if err == nil {
+ select {
+ case errc = <-w.deriveQuit:
+ // Termination requested, abort
+ case <-time.After(selfDeriveThrottling):
+ // Waited enough, willing to self-derive again
+ }
+ }
+ }
+ // In case of error, wait for termination
+ if err != nil {
+ w.log.Debug("Trezor self-derivation failed", "err", err)
+ errc = <-w.deriveQuit
+ }
+ errc <- err
+}
+
+// Contains implements accounts.Wallet, returning whether a particular account is
+// or is not pinned into this Trezor instance. Although we could attempt to resolve
+// unpinned accounts, that would be an non-negligible hardware operation.
+func (w *trezorWallet) Contains(account accounts.Account) bool {
+ w.stateLock.RLock()
+ defer w.stateLock.RUnlock()
+
+ _, exists := w.paths[account.Address]
+ return exists
+}
+
+// Derive implements accounts.Wallet, deriving a new account at the specific
+// derivation path. If pin is set to true, the account will be added to the list
+// of tracked accounts.
+func (w *trezorWallet) Derive(path accounts.DerivationPath, pin bool) (accounts.Account, error) {
+ // Try to derive the actual account and update its URL if successful
+ w.stateLock.RLock() // Avoid device disappearing during derivation
+
+ if w.device == nil {
+ w.stateLock.RUnlock()
+ return accounts.Account{}, accounts.ErrWalletClosed
+ }
+ <-w.commsLock // Avoid concurrent hardware access
+ address, err := w.trezorDerive(path)
+ w.commsLock <- struct{}{}
+
+ w.stateLock.RUnlock()
+
+ // If an error occurred or no pinning was requested, return
+ if err != nil {
+ return accounts.Account{}, err
+ }
+ account := accounts.Account{
+ Address: address,
+ URL: accounts.URL{Scheme: w.url.Scheme, Path: fmt.Sprintf("%s/%s", w.url.Path, path)},
+ }
+ if !pin {
+ return account, nil
+ }
+ // Pinning needs to modify the state
+ w.stateLock.Lock()
+ defer w.stateLock.Unlock()
+
+ if _, ok := w.paths[address]; !ok {
+ w.accounts = append(w.accounts, account)
+ w.paths[address] = path
+ }
+ return account, nil
+}
+
+// SelfDerive implements accounts.Wallet, trying to discover accounts that the
+// user used previously (based on the chain state), but ones that he/she did not
+// explicitly pin to the wallet manually. To avoid chain head monitoring, self
+// derivation only runs during account listing (and even then throttled).
+func (w *trezorWallet) SelfDerive(base accounts.DerivationPath, chain ethereum.ChainStateReader) {
+ w.stateLock.Lock()
+ defer w.stateLock.Unlock()
+
+ w.deriveNextPath = make(accounts.DerivationPath, len(base))
+ copy(w.deriveNextPath[:], base[:])
+
+ w.deriveNextAddr = common.Address{}
+ w.deriveChain = chain
+}
+
+// SignHash implements accounts.Wallet, however signing arbitrary data is not
+// supported for Trezor wallets, so this method will always return an error.
+func (w *trezorWallet) SignHash(acc accounts.Account, hash []byte) ([]byte, error) {
+ return nil, accounts.ErrNotSupported
+}
+
+// SignTx implements accounts.Wallet. It sends the transaction over to the Trezor
+// wallet to request a confirmation from the user. It returns either the signed
+// transaction or a failure if the user denied the transaction.
+func (w *trezorWallet) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
+ w.stateLock.RLock() // Comms have own mutex, this is for the state fields
+ defer w.stateLock.RUnlock()
+
+ // If the wallet is closed, abort
+ if w.device == nil {
+ return nil, accounts.ErrWalletClosed
+ }
+ // Make sure the requested account is contained within
+ path, ok := w.paths[account.Address]
+ if !ok {
+ return nil, accounts.ErrUnknownAccount
+ }
+ // All infos gathered and metadata checks out, request signing
+ <-w.commsLock
+ defer func() { w.commsLock <- struct{}{} }()
+
+ // Ensure the device isn't screwed with while user confirmation is pending
+ // TODO(karalabe): remove if hotplug lands on Windows
+ w.hub.commsLock.Lock()
+ w.hub.commsPend++
+ w.hub.commsLock.Unlock()
+
+ defer func() {
+ w.hub.commsLock.Lock()
+ w.hub.commsPend--
+ w.hub.commsLock.Unlock()
+ }()
+
+ return w.trezorSign(path, account.Address, tx, chainID)
+}
+
+// SignHashWithPassphrase implements accounts.Wallet, however signing arbitrary
+// data is not supported for Trezor wallets, so this method will always return
+// an error.
+func (w *trezorWallet) SignHashWithPassphrase(account accounts.Account, passphrase string, hash []byte) ([]byte, error) {
+ return nil, accounts.ErrNotSupported
+}
+
+// SignTxWithPassphrase implements accounts.Wallet, attempting to sign the given
+// transaction with the given account using passphrase as extra authentication.
+// Since the Trezor does not support extra passphrases, it is silently ignored.
+func (w *trezorWallet) SignTxWithPassphrase(account accounts.Account, passphrase string, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
+ return w.SignTx(account, tx, chainID)
+}
+
+// trezorDerive sends a derivation request to the Trezor device and returns the
+// Ethereum address located on that path.
+func (w *trezorWallet) trezorDerive(derivationPath []uint32) (common.Address, error) {
+ address := new(trezor.EthereumAddress)
+ if err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil {
+ return common.Address{}, err
+ }
+ return common.BytesToAddress(address.GetAddress()), nil
+}
+
+// trezorSign sends the transaction to the Trezor wallet, and waits for the user
+// to confirm or deny the transaction.
+func (w *trezorWallet) trezorSign(derivationPath []uint32, address common.Address, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
+ // Create the transaction initiation message
+ data := tx.Data()
+ length := uint32(len(data))
+
+ request := &trezor.EthereumSignTx{
+ AddressN: derivationPath,
+ Nonce: new(big.Int).SetUint64(tx.Nonce()).Bytes(),
+ GasPrice: tx.GasPrice().Bytes(),
+ GasLimit: tx.Gas().Bytes(),
+ Value: tx.Value().Bytes(),
+ DataLength: &length,
+ }
+ if to := tx.To(); to != nil {
+ request.To = (*to)[:] // Non contract deploy, set recipient explicitly
+ }
+ if length > 1024 { // Send the data chunked if that was requested
+ request.DataInitialChunk, data = data[:1024], data[1024:]
+ } else {
+ request.DataInitialChunk, data = data, nil
+ }
+ if chainID != nil { // EIP-155 transaction, set chain ID explicitly (only 32 bit is supported!?)
+ id := uint32(chainID.Int64())
+ request.ChainId = &id
+ }
+ // Send the initiation message and stream content until a signature is returned
+ response := new(trezor.EthereumTxRequest)
+ if err := w.trezorExchange(request, response); err != nil {
+ return nil, err
+ }
+ for response.DataLength != nil && int(*response.DataLength) <= len(data) {
+ chunk := data[:*response.DataLength]
+ data = data[*response.DataLength:]
+
+ if err := w.trezorExchange(&trezor.EthereumTxAck{DataChunk: chunk}, response); err != nil {
+ return nil, err
+ }
+ }
+ // Extract the Ethereum signature and do a sanity validation
+ if len(response.GetSignatureR()) == 0 || len(response.GetSignatureS()) == 0 || response.GetSignatureV() == 0 {
+ return nil, errors.New("reply lacks signature")
+ }
+ signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV()))
+
+ // Create the correct signer and signature transform based on the chain ID
+ var signer types.Signer
+ if chainID == nil {
+ signer = new(types.HomesteadSigner)
+ } else {
+ signer = types.NewEIP155Signer(chainID)
+ signature[64] = signature[64] - byte(chainID.Uint64()*2+35)
+ }
+ // Inject the final signature into the transaction and sanity check the sender
+ signed, err := tx.WithSignature(signer, signature)
+ if err != nil {
+ return nil, err
+ }
+ sender, err := types.Sender(signer, signed)
+ if err != nil {
+ return nil, err
+ }
+ if sender != address {
+ return nil, fmt.Errorf("signer mismatch: expected %s, got %s", address.Hex(), sender.Hex())
+ }
+ return signed, nil
+}
+
+// trezorExchange performs a data exchange with the Trezor wallet, sending it a
+// message and retrieving the response.
+func (w *trezorWallet) trezorExchange(req proto.Message, res proto.Message) error {
+ // Construct the original message payload to chunk up
+ data, err := proto.Marshal(req)
+ if err != nil {
+ return err
+ }
+ payload := make([]byte, 8+len(data))
+ copy(payload, []byte{0x23, 0x23})
+ binary.BigEndian.PutUint16(payload[2:], trezor.Type(req))
+ binary.BigEndian.PutUint32(payload[4:], uint32(len(data)))
+ copy(payload[8:], data)
+
+ // Stream all the chunks to the device
+ chunk := make([]byte, 64)
+ chunk[0] = 0x3f // Report ID magic number
+
+ for len(payload) > 0 {
+ // Construct the new message to stream, padding with zeroes if needed
+ if len(payload) > 63 {
+ copy(chunk[1:], payload[:63])
+ payload = payload[63:]
+ } else {
+ copy(chunk[1:], payload)
+ copy(chunk[1+len(payload):], make([]byte, 63-len(payload)))
+ payload = nil
+ }
+ // Send over to the device
+ w.log.Trace("Data chunk sent to the Trezor", "chunk", hexutil.Bytes(chunk))
+ if _, err := w.device.Write(chunk); err != nil {
+ return err
+ }
+ }
+ // Stream the reply back from the wallet in 64 byte chunks
+ var (
+ kind uint16
+ reply []byte
+ )
+ for {
+ // Read the next chunk from the Trezor wallet
+ if _, err := io.ReadFull(w.device, chunk); err != nil {
+ return err
+ }
+ w.log.Trace("Data chunk received from the Trezor", "chunk", hexutil.Bytes(chunk))
+
+ // Make sure the transport header matches
+ if chunk[0] != 0x3f || (len(reply) == 0 && (chunk[1] != 0x23 || chunk[2] != 0x23)) {
+ return errReplyInvalidHeader
+ }
+ // If it's the first chunk, retrieve the reply message type and total message length
+ var payload []byte
+
+ if len(reply) == 0 {
+ kind = binary.BigEndian.Uint16(chunk[3:5])
+ reply = make([]byte, 0, int(binary.BigEndian.Uint32(chunk[5:9])))
+ payload = chunk[9:]
+ } else {
+ payload = chunk[1:]
+ }
+ // Append to the reply and stop when filled up
+ if left := cap(reply) - len(reply); left > len(payload) {
+ reply = append(reply, payload...)
+ } else {
+ reply = append(reply, payload[:left]...)
+ break
+ }
+ }
+ // Try to parse the reply into the requested reply message
+ if kind == uint16(trezor.MessageType_MessageType_Failure) {
+ // Trezor returned a failure, extract and return the message
+ failure := new(trezor.Failure)
+ if err := proto.Unmarshal(reply, failure); err != nil {
+ return err
+ }
+ return errors.New("trezor: " + failure.GetMessage())
+ }
+ if kind == uint16(trezor.MessageType_MessageType_ButtonRequest) {
+ // Trezor is waitinf for user confirmation, ack and wait for the next message
+ return w.trezorExchange(&trezor.ButtonAck{}, res)
+ }
+ if want := trezor.Type(res); kind != want {
+ return fmt.Errorf("trezor: expected reply type %s, got %s", trezor.Name(want), trezor.Name(kind))
+ }
+ return proto.Unmarshal(reply, res)
+}
diff --git a/accounts/usbwallet/usbwallet.go b/accounts/usbwallet/usbwallet.go
index 938ab1e6a..3ed471693 100644
--- a/accounts/usbwallet/usbwallet.go
+++ b/accounts/usbwallet/usbwallet.go
@@ -17,9 +17,18 @@
// Package usbwallet implements support for USB hardware wallets.
package usbwallet
+import "time"
+
// deviceID is a combined vendor/product identifier to uniquely identify a USB
// hardware device.
type deviceID struct {
Vendor uint16 // The Vendor identifer
Product uint16 // The Product identifier
}
+
+// Maximum time between wallet health checks to detect USB unplugs.
+const heartbeatCycle = time.Second
+
+// Minimum time to wait between self derivation attempts, even it the user is
+// requesting accounts like crazy.
+const selfDeriveThrottling = time.Second