Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Rust Protobuf #1541

Merged
merged 24 commits into from Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
766c561
feat(core): Add Rust Protobuf codec
jpochyla Mar 23, 2021
401ddd7
refactor: rework pb2py generator
matejcik Mar 23, 2021
f32ddd7
refactor(core): prepare new templates for enums and messages
matejcik Mar 23, 2021
105aeba
chore(core): regenerate with new templates
matejcik Jun 7, 2021
8951aca
refactor(core): Switch to new Protobuf API
jpochyla Mar 23, 2021
584bb2c
build(core): update build process for new protobuf
mmilata Jun 7, 2021
0b8fc90
refactor(core): fix imports and use new protobuf API in apps
jpochyla Mar 23, 2021
92b6ecf
refactor(core): create and use protobuf uvarint writer
matejcik May 27, 2021
8c2618e
fix(tests): Adjust the expected error message
jpochyla Mar 23, 2021
f686956
fix(core/tests): fix equality testing for new message types
matejcik Jun 1, 2021
f45b050
fix(common/protob): use proper field type for backup type on debuglink
matejcik May 31, 2021
278eb04
feat(common/protob): mark values as bitcoin_only in protobuf definitions
matejcik May 31, 2021
3603f65
chore(common/tools): drop outdated and unused CoinDef generator
matejcik May 31, 2021
7830bc9
feat(core/rust): propagate bitcoin_only flag to Rust build
matejcik May 31, 2021
0afcd6d
fix(core): exclude get/set U2F counter from BITCOIN_ONLY
matejcik Jun 1, 2021
2b6900c
refactor(python): rework trezorlib protobuf codec
matejcik Jun 1, 2021
80ca3e2
fix(core): properly exclude altcoins from all_modules
matejcik Jun 1, 2021
e627f17
chore(tests): put enum names into UI fixture names (hashes are unchan…
matejcik Jun 2, 2021
db86ba3
build: use mypy version from git
matejcik Jun 1, 2021
aa802bc
style: ignore yaml files in venv
matejcik Jun 2, 2021
049da13
fix(legacy): fix protobuf build [no changelog]
matejcik Jun 2, 2021
d136665
fix(tests): properly include tests whose expected hash is missing
matejcik Jun 2, 2021
e57f03f
ci: update coverage exclusion list
matejcik Jun 3, 2021
4a007ef
docs(core): add changelog entry for Rust protobuf
matejcik Jun 7, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 3 additions & 2 deletions .yamllint.yml
@@ -1,9 +1,10 @@
extends: default

ignore: |
/.venv
vendor/
common/defs/ethereum/chains/
common/defs/ethereum/tokens/
/common/defs/ethereum/chains/
/common/defs/ethereum/tokens/

rules:
# fix for truthy warning on github action files
Expand Down
6 changes: 6 additions & 0 deletions common/protob/messages-bitcoin.proto
Expand Up @@ -418,6 +418,7 @@ message PrevOutput {
*/
message TxAckInput {
option (wire_type) = 22;
option (include_in_bitcoin_only) = true;

required TxAckInputWrapper tx = 1;

Expand All @@ -437,6 +438,7 @@ message TxAckInput {
*/
message TxAckOutput {
option (wire_type) = 22;
option (include_in_bitcoin_only) = true;

required TxAckOutputWrapper tx = 1;

Expand All @@ -456,6 +458,7 @@ message TxAckOutput {
*/
message TxAckPrevMeta {
option (wire_type) = 22;
option (include_in_bitcoin_only) = true;

required PrevTx tx = 1;
}
Expand All @@ -471,6 +474,7 @@ message TxAckPrevMeta {
*/
message TxAckPrevInput {
option (wire_type) = 22;
option (include_in_bitcoin_only) = true;

required TxAckPrevInputWrapper tx = 1;

Expand All @@ -491,6 +495,7 @@ message TxAckPrevInput {
*/
message TxAckPrevOutput {
option (wire_type) = 22;
option (include_in_bitcoin_only) = true;

required TxAckPrevOutputWrapper tx = 1;

Expand All @@ -509,6 +514,7 @@ message TxAckPrevOutput {
*/
message TxAckPrevExtraData {
option (wire_type) = 22;
option (include_in_bitcoin_only) = true;

required TxAckPrevExtraDataWrapper tx = 1;

Expand Down
5 changes: 3 additions & 2 deletions common/protob/messages-debug.proto
Expand Up @@ -6,6 +6,7 @@ option java_package = "com.satoshilabs.trezor.lib.protobuf";
option java_outer_classname = "TrezorMessageDebug";

import "messages-common.proto";
import "messages-management.proto";

/**
* Request: "Press" the button on the device
Expand Down Expand Up @@ -78,14 +79,14 @@ message DebugLinkState {
optional string pin = 2; // current PIN, blank if PIN is not set/enabled
optional string matrix = 3; // current PIN matrix
optional bytes mnemonic_secret = 4; // current mnemonic secret
optional hw.trezor.messages.common.HDNodeType node = 5; // current BIP-32 node
optional common.HDNodeType node = 5; // current BIP-32 node
optional bool passphrase_protection = 6; // is node/mnemonic encrypted using passphrase?
optional string reset_word = 7; // word on device display during ResetDevice workflow
optional bytes reset_entropy = 8; // current entropy during ResetDevice workflow
optional string recovery_fake_word = 9; // (fake) word on display during RecoveryDevice workflow
optional uint32 recovery_word_pos = 10; // index of mnemonic word the device is expecting during RecoveryDevice workflow
optional uint32 reset_word_pos = 11; // index of mnemonic word the device is expecting during ResetDevice workflow
optional uint32 mnemonic_type = 12; // current mnemonic type (BIP-39/SLIP-39)
optional management.BackupType mnemonic_type = 12; // current mnemonic type (BIP-39/SLIP-39)
repeated string layout_lines = 13; // current layout text
}

Expand Down
16 changes: 10 additions & 6 deletions common/protob/messages-management.proto
Expand Up @@ -5,6 +5,8 @@ package hw.trezor.messages.management;
option java_package = "com.satoshilabs.trezor.lib.protobuf";
option java_outer_classname = "TrezorMessageManagement";

import "messages.proto";

/**
* Type of the mnemonic backup given/received by the device during reset/recovery.
*/
Expand Down Expand Up @@ -75,11 +77,13 @@ message Features {
optional bool recovery_mode = 29; // is recovery mode in progress
repeated Capability capabilities = 30; // list of supported capabilities
enum Capability {
Capability_Bitcoin = 1;
Capability_Bitcoin_like = 2; // Altcoins based on the Bitcoin source code
option (has_bitcoin_only_values) = true;

Capability_Bitcoin = 1 [(bitcoin_only) = true];
Capability_Bitcoin_like = 2; // Altcoins based on the Bitcoin source code
Capability_Binance = 3;
Capability_Cardano = 4;
Capability_Crypto = 5; // generic crypto operations for GPG, SSH, etc.
Capability_Crypto = 5 [(bitcoin_only) = true]; // generic crypto operations for GPG, SSH, etc.
Capability_EOS = 6;
Capability_Ethereum = 7;
Capability_Lisk = 8;
Expand All @@ -89,9 +93,9 @@ message Features {
Capability_Stellar = 12;
Capability_Tezos = 13;
Capability_U2F = 14;
Capability_Shamir = 15;
Capability_ShamirGroups = 16;
Capability_PassphraseEntry = 17; // the device is capable of passphrase entry directly on the device
Capability_Shamir = 15 [(bitcoin_only) = true];
Capability_ShamirGroups = 16 [(bitcoin_only) = true];
Capability_PassphraseEntry = 17 [(bitcoin_only) = true]; // the device is capable of passphrase entry directly on the device
}
optional BackupType backup_type = 31; // type of device backup (BIP-39 / SLIP-39 basic / SLIP-39 advanced)
optional bool sd_card_present = 32; // is SD card present
Expand Down
193 changes: 111 additions & 82 deletions common/protob/messages.proto
Expand Up @@ -11,6 +11,24 @@ option java_outer_classname = "TrezorMessage";

import "google/protobuf/descriptor.proto";

/************************* WARNING ***********************
Due to the way extensions are accessed in pb2py, there needs to be a globally unique
name-ID mapping for extensions. That means that two different extensions, e.g. for
EnumValueOptions and FieldOptions, MUST NOT have the same ID.

Using the same ID indicates the same purpose (protobuf does not allow multiple
extensions with the same name), such as EnumValueOptions.bitcoin_only and
MessageOptions.include_in_bitcoin_only. pb2py can then find the extension under
either name.

The convention to achieve this is as follows:
- extensions specific to a type have the same prefix:
* 50xxx for EnumValueOptions
* 51xxx for EnumOptions
* 52xxx for MessageOptions
* 53xxx for FieldOptions
- extensions that might be used across types have the same "global" prefix 60xxx
*/
/**
* Options for specifying message direction and type of wire (normal/debug)
*/
Expand All @@ -22,122 +40,133 @@ extend google.protobuf.EnumValueOptions {
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
optional bool wire_no_fsm = 50008; // message is not handled by Trezor unless the USB stack is in tiny mode

optional bool bitcoin_only = 60000; // enum value is available on BITCOIN_ONLY build
// (messages not marked bitcoin_only will be EXCLUDED)
}

/** Options for tagging enum types */
extend google.protobuf.EnumOptions {
optional bool has_bitcoin_only_values = 51001; // indicate that some values should be excluded on BITCOIN_ONLY builds
}

/** Options for tagging message types */
extend google.protobuf.MessageOptions {
optional bool unstable = 50001; // indicate that a message definition might change at any time
optional uint32 wire_type = 50002; // override wire type specified in the MessageType enum
}
optional bool unstable = 52001; // indicate that a message definition might change at any time
optional uint32 wire_type = 52002; // override wire type specified in the MessageType enum

optional bool include_in_bitcoin_only = 60000; // message is available on BITCOIN_ONLY build
// intentionally identical to `bitcoin_only` from enum
}

/** Options for tagging field types */
extend google.protobuf.FieldOptions {
optional bool experimental = 52001; // indicate that a field is intended for development and beta testing only
optional bool experimental = 53001; // indicate that a field is intended for development and beta testing only
}


/**
* Mapping between Trezor wire identifier (uint) and a protobuf message
*/
enum MessageType {
option (has_bitcoin_only_values) = true;

// Management
MessageType_Initialize = 0 [(wire_in) = true, (wire_tiny) = 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_GetEntropy = 9 [(wire_in) = true];
MessageType_Entropy = 10 [(wire_out) = true];
MessageType_LoadDevice = 13 [(wire_in) = true];
MessageType_ResetDevice = 14 [(wire_in) = true];
MessageType_Features = 17 [(wire_out) = true];
MessageType_PinMatrixRequest = 18 [(wire_out) = true];
MessageType_PinMatrixAck = 19 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
MessageType_Cancel = 20 [(wire_in) = true, (wire_tiny) = true];
MessageType_LockDevice = 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, (wire_no_fsm) = true];
MessageType_ApplyFlags = 28 [(wire_in) = true];
MessageType_BackupDevice = 34 [(wire_in) = true];
MessageType_EntropyRequest = 35 [(wire_out) = true];
MessageType_EntropyAck = 36 [(wire_in) = true];
MessageType_PassphraseRequest = 41 [(wire_out) = true];
MessageType_PassphraseAck = 42 [(wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
MessageType_RecoveryDevice = 45 [(wire_in) = true];
MessageType_WordRequest = 46 [(wire_out) = true];
MessageType_WordAck = 47 [(wire_in) = true];
MessageType_GetFeatures = 55 [(wire_in) = true];
MessageType_Initialize = 0 [(bitcoin_only) = true, (wire_in) = true, (wire_tiny) = true];
MessageType_Ping = 1 [(bitcoin_only) = true, (wire_in) = true];
MessageType_Success = 2 [(bitcoin_only) = true, (wire_out) = true];
MessageType_Failure = 3 [(bitcoin_only) = true, (wire_out) = true];
MessageType_ChangePin = 4 [(bitcoin_only) = true, (wire_in) = true];
MessageType_WipeDevice = 5 [(bitcoin_only) = true, (wire_in) = true];
MessageType_GetEntropy = 9 [(bitcoin_only) = true, (wire_in) = true];
MessageType_Entropy = 10 [(bitcoin_only) = true, (wire_out) = true];
MessageType_LoadDevice = 13 [(bitcoin_only) = true, (wire_in) = true];
MessageType_ResetDevice = 14 [(bitcoin_only) = true, (wire_in) = true];
MessageType_Features = 17 [(bitcoin_only) = true, (wire_out) = true];
MessageType_PinMatrixRequest = 18 [(bitcoin_only) = true, (wire_out) = true];
MessageType_PinMatrixAck = 19 [(bitcoin_only) = true, (wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
MessageType_Cancel = 20 [(bitcoin_only) = true, (wire_in) = true, (wire_tiny) = true];
MessageType_LockDevice = 24 [(bitcoin_only) = true, (wire_in) = true];
MessageType_ApplySettings = 25 [(bitcoin_only) = true, (wire_in) = true];
MessageType_ButtonRequest = 26 [(bitcoin_only) = true, (wire_out) = true];
MessageType_ButtonAck = 27 [(bitcoin_only) = true, (wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
MessageType_ApplyFlags = 28 [(bitcoin_only) = true, (wire_in) = true];
MessageType_BackupDevice = 34 [(bitcoin_only) = true, (wire_in) = true];
MessageType_EntropyRequest = 35 [(bitcoin_only) = true, (wire_out) = true];
MessageType_EntropyAck = 36 [(bitcoin_only) = true, (wire_in) = true];
MessageType_PassphraseRequest = 41 [(bitcoin_only) = true, (wire_out) = true];
MessageType_PassphraseAck = 42 [(bitcoin_only) = true, (wire_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
MessageType_RecoveryDevice = 45 [(bitcoin_only) = true, (wire_in) = true];
MessageType_WordRequest = 46 [(bitcoin_only) = true, (wire_out) = true];
MessageType_WordAck = 47 [(bitcoin_only) = true, (wire_in) = true];
MessageType_GetFeatures = 55 [(bitcoin_only) = true, (wire_in) = true];
MessageType_SdProtect = 79 [(bitcoin_only) = true, (wire_in) = true];
MessageType_ChangeWipeCode = 82 [(bitcoin_only) = true, (wire_in) = true];
MessageType_EndSession = 83 [(bitcoin_only) = true, (wire_in) = true];
MessageType_DoPreauthorized = 84 [(bitcoin_only) = true, (wire_in) = true];
MessageType_PreauthorizedRequest = 85 [(bitcoin_only) = true, (wire_out) = true];
MessageType_CancelAuthorization = 86 [(bitcoin_only) = true, (wire_in) = true];
MessageType_RebootToBootloader = 87 [(bitcoin_only) = true, (wire_in) = true];

MessageType_SetU2FCounter = 63 [(wire_in) = true];
MessageType_SdProtect = 79 [(wire_in) = true];
MessageType_GetNextU2FCounter = 80 [(wire_in) = true];
MessageType_NextU2FCounter = 81 [(wire_out) = true];
MessageType_ChangeWipeCode = 82 [(wire_in) = true];
MessageType_EndSession = 83 [(wire_in) = true];
MessageType_DoPreauthorized = 84 [(wire_in) = true];
MessageType_PreauthorizedRequest = 85 [(wire_out) = true];
MessageType_CancelAuthorization = 86 [(wire_in) = true];
MessageType_RebootToBootloader = 87 [(wire_in) = true];

// Deprecated messages, kept for protobuf compatibility.
// Both are marked wire_out so that we don't need to implement incoming handler for legacy
MessageType_Deprecated_PassphraseStateRequest = 77 [deprecated = true];
MessageType_Deprecated_PassphraseStateAck = 78 [deprecated = true];

// Bootloader
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_SelfTest = 32 [(wire_in) = true, (wire_bootloader) = true];
MessageType_FirmwareErase = 6 [(bitcoin_only) = true, (wire_in) = true, (wire_bootloader) = true];
MessageType_FirmwareUpload = 7 [(bitcoin_only) = true, (wire_in) = true, (wire_bootloader) = true];
MessageType_FirmwareRequest = 8 [(bitcoin_only) = true, (wire_out) = true, (wire_bootloader) = true];
MessageType_SelfTest = 32 [(bitcoin_only) = true, (wire_in) = true, (wire_bootloader) = true];

// Bitcoin
MessageType_GetPublicKey = 11 [(wire_in) = true];
MessageType_PublicKey = 12 [(wire_out) = true];
MessageType_SignTx = 15 [(wire_in) = true];
MessageType_TxRequest = 21 [(wire_out) = true];
MessageType_TxAck = 22 [(wire_in) = true];
MessageType_GetAddress = 29 [(wire_in) = true];
MessageType_Address = 30 [(wire_out) = true];
MessageType_SignMessage = 38 [(wire_in) = true];
MessageType_VerifyMessage = 39 [(wire_in) = true];
MessageType_MessageSignature = 40 [(wire_out) = true];
MessageType_GetOwnershipId = 43 [(wire_in) = true];
MessageType_OwnershipId = 44 [(wire_out) = true];
MessageType_GetOwnershipProof = 49 [(wire_in) = true];
MessageType_OwnershipProof = 50 [(wire_out) = true];
MessageType_AuthorizeCoinJoin = 51 [(wire_in) = true];
MessageType_GetPublicKey = 11 [(bitcoin_only) = true, (wire_in) = true];
MessageType_PublicKey = 12 [(bitcoin_only) = true, (wire_out) = true];
MessageType_SignTx = 15 [(bitcoin_only) = true, (wire_in) = true];
MessageType_TxRequest = 21 [(bitcoin_only) = true, (wire_out) = true];
MessageType_TxAck = 22 [(bitcoin_only) = true, (wire_in) = true];
MessageType_GetAddress = 29 [(bitcoin_only) = true, (wire_in) = true];
MessageType_Address = 30 [(bitcoin_only) = true, (wire_out) = true];
MessageType_SignMessage = 38 [(bitcoin_only) = true, (wire_in) = true];
MessageType_VerifyMessage = 39 [(bitcoin_only) = true, (wire_in) = true];
MessageType_MessageSignature = 40 [(bitcoin_only) = true, (wire_out) = true];
MessageType_GetOwnershipId = 43 [(bitcoin_only) = true, (wire_in) = true];
MessageType_OwnershipId = 44 [(bitcoin_only) = true, (wire_out) = true];
MessageType_GetOwnershipProof = 49 [(bitcoin_only) = true, (wire_in) = true];
MessageType_OwnershipProof = 50 [(bitcoin_only) = true, (wire_out) = true];
MessageType_AuthorizeCoinJoin = 51 [(bitcoin_only) = true, (wire_in) = true];

// Crypto
MessageType_CipherKeyValue = 23 [(wire_in) = true];
MessageType_CipheredKeyValue = 48 [(wire_out) = true];
MessageType_SignIdentity = 53 [(wire_in) = true];
MessageType_SignedIdentity = 54 [(wire_out) = true];
MessageType_GetECDHSessionKey = 61 [(wire_in) = true];
MessageType_ECDHSessionKey = 62 [(wire_out) = true];
MessageType_CosiCommit = 71 [(wire_in) = true];
MessageType_CosiCommitment = 72 [(wire_out) = true];
MessageType_CosiSign = 73 [(wire_in) = true];
MessageType_CosiSignature = 74 [(wire_out) = true];
MessageType_CipherKeyValue = 23 [(bitcoin_only) = true, (wire_in) = true];
MessageType_CipheredKeyValue = 48 [(bitcoin_only) = true, (wire_out) = true];
MessageType_SignIdentity = 53 [(bitcoin_only) = true, (wire_in) = true];
MessageType_SignedIdentity = 54 [(bitcoin_only) = true, (wire_out) = true];
MessageType_GetECDHSessionKey = 61 [(bitcoin_only) = true, (wire_in) = true];
MessageType_ECDHSessionKey = 62 [(bitcoin_only) = true, (wire_out) = true];
MessageType_CosiCommit = 71 [(bitcoin_only) = true, (wire_in) = true];
MessageType_CosiCommitment = 72 [(bitcoin_only) = true, (wire_out) = true];
MessageType_CosiSign = 73 [(bitcoin_only) = true, (wire_in) = true];
MessageType_CosiSignature = 74 [(bitcoin_only) = true, (wire_out) = true];

// Debug
MessageType_DebugLinkDecision = 100 [(wire_debug_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
MessageType_DebugLinkGetState = 101 [(wire_debug_in) = true, (wire_tiny) = 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];
MessageType_DebugLinkLayout = 9001 [(wire_debug_out) = true];
MessageType_DebugLinkReseedRandom = 9002 [(wire_debug_in) = true];
MessageType_DebugLinkRecordScreen = 9003 [(wire_debug_in) = true];
MessageType_DebugLinkEraseSdCard = 9005 [(wire_debug_in) = true];
MessageType_DebugLinkWatchLayout = 9006 [(wire_debug_in) = true];
MessageType_DebugLinkDecision = 100 [(bitcoin_only) = true, (wire_debug_in) = true, (wire_tiny) = true, (wire_no_fsm) = true];
MessageType_DebugLinkGetState = 101 [(bitcoin_only) = true, (wire_debug_in) = true, (wire_tiny) = true];
MessageType_DebugLinkState = 102 [(bitcoin_only) = true, (wire_debug_out) = true];
MessageType_DebugLinkStop = 103 [(bitcoin_only) = true, (wire_debug_in) = true];
MessageType_DebugLinkLog = 104 [(bitcoin_only) = true, (wire_debug_out) = true];
MessageType_DebugLinkMemoryRead = 110 [(bitcoin_only) = true, (wire_debug_in) = true];
MessageType_DebugLinkMemory = 111 [(bitcoin_only) = true, (wire_debug_out) = true];
MessageType_DebugLinkMemoryWrite = 112 [(bitcoin_only) = true, (wire_debug_in) = true];
MessageType_DebugLinkFlashErase = 113 [(bitcoin_only) = true, (wire_debug_in) = true];
MessageType_DebugLinkLayout = 9001 [(bitcoin_only) = true, (wire_debug_out) = true];
MessageType_DebugLinkReseedRandom = 9002 [(bitcoin_only) = true, (wire_debug_in) = true];
MessageType_DebugLinkRecordScreen = 9003 [(bitcoin_only) = true, (wire_debug_in) = true];
MessageType_DebugLinkEraseSdCard = 9005 [(bitcoin_only) = true, (wire_debug_in) = true];
MessageType_DebugLinkWatchLayout = 9006 [(bitcoin_only) = true, (wire_debug_in) = true];

// Ethereum
MessageType_EthereumGetPublicKey = 450 [(wire_in) = true];
Expand Down