mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 12:28:09 +00:00
refactor(common/protob): make bitcoin_only options file-level
This commit is contained in:
parent
13866f7ebd
commit
13417d7e5a
@ -5,6 +5,8 @@ package hw.trezor.messages.bitcoin;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageBitcoin";
|
option java_outer_classname = "TrezorMessageBitcoin";
|
||||||
|
|
||||||
|
option (include_in_bitcoin_only) = true;
|
||||||
|
|
||||||
import "messages.proto";
|
import "messages.proto";
|
||||||
import "messages-common.proto";
|
import "messages-common.proto";
|
||||||
|
|
||||||
@ -418,7 +420,6 @@ message PrevOutput {
|
|||||||
*/
|
*/
|
||||||
message TxAckInput {
|
message TxAckInput {
|
||||||
option (wire_type) = 22;
|
option (wire_type) = 22;
|
||||||
option (include_in_bitcoin_only) = true;
|
|
||||||
|
|
||||||
required TxAckInputWrapper tx = 1;
|
required TxAckInputWrapper tx = 1;
|
||||||
|
|
||||||
@ -438,7 +439,6 @@ message TxAckInput {
|
|||||||
*/
|
*/
|
||||||
message TxAckOutput {
|
message TxAckOutput {
|
||||||
option (wire_type) = 22;
|
option (wire_type) = 22;
|
||||||
option (include_in_bitcoin_only) = true;
|
|
||||||
|
|
||||||
required TxAckOutputWrapper tx = 1;
|
required TxAckOutputWrapper tx = 1;
|
||||||
|
|
||||||
@ -458,7 +458,6 @@ message TxAckOutput {
|
|||||||
*/
|
*/
|
||||||
message TxAckPrevMeta {
|
message TxAckPrevMeta {
|
||||||
option (wire_type) = 22;
|
option (wire_type) = 22;
|
||||||
option (include_in_bitcoin_only) = true;
|
|
||||||
|
|
||||||
required PrevTx tx = 1;
|
required PrevTx tx = 1;
|
||||||
}
|
}
|
||||||
@ -474,7 +473,6 @@ message TxAckPrevMeta {
|
|||||||
*/
|
*/
|
||||||
message TxAckPrevInput {
|
message TxAckPrevInput {
|
||||||
option (wire_type) = 22;
|
option (wire_type) = 22;
|
||||||
option (include_in_bitcoin_only) = true;
|
|
||||||
|
|
||||||
required TxAckPrevInputWrapper tx = 1;
|
required TxAckPrevInputWrapper tx = 1;
|
||||||
|
|
||||||
@ -495,7 +493,6 @@ message TxAckPrevInput {
|
|||||||
*/
|
*/
|
||||||
message TxAckPrevOutput {
|
message TxAckPrevOutput {
|
||||||
option (wire_type) = 22;
|
option (wire_type) = 22;
|
||||||
option (include_in_bitcoin_only) = true;
|
|
||||||
|
|
||||||
required TxAckPrevOutputWrapper tx = 1;
|
required TxAckPrevOutputWrapper tx = 1;
|
||||||
|
|
||||||
@ -514,7 +511,6 @@ message TxAckPrevOutput {
|
|||||||
*/
|
*/
|
||||||
message TxAckPrevExtraData {
|
message TxAckPrevExtraData {
|
||||||
option (wire_type) = 22;
|
option (wire_type) = 22;
|
||||||
option (include_in_bitcoin_only) = true;
|
|
||||||
|
|
||||||
required TxAckPrevExtraDataWrapper tx = 1;
|
required TxAckPrevExtraDataWrapper tx = 1;
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ package hw.trezor.messages.bootloader;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageBootloader";
|
option java_outer_classname = "TrezorMessageBootloader";
|
||||||
|
|
||||||
|
import "messages.proto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload)
|
* Request: Ask device to erase its firmware (so it can be replaced via FirmwareUpload)
|
||||||
* @start
|
* @start
|
||||||
|
@ -5,6 +5,10 @@ package hw.trezor.messages.common;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageCommon";
|
option java_outer_classname = "TrezorMessageCommon";
|
||||||
|
|
||||||
|
option (include_in_bitcoin_only) = true;
|
||||||
|
|
||||||
|
import "messages.proto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response: Success of the previous request
|
* Response: Success of the previous request
|
||||||
* @end
|
* @end
|
||||||
|
@ -5,6 +5,10 @@ package hw.trezor.messages.crypto;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageCrypto";
|
option java_outer_classname = "TrezorMessageCrypto";
|
||||||
|
|
||||||
|
option (include_in_bitcoin_only) = true;
|
||||||
|
|
||||||
|
import "messages.proto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request: Ask device to encrypt or decrypt value of given key
|
* Request: Ask device to encrypt or decrypt value of given key
|
||||||
* @start
|
* @start
|
||||||
|
@ -5,6 +5,9 @@ package hw.trezor.messages.debug;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageDebug";
|
option java_outer_classname = "TrezorMessageDebug";
|
||||||
|
|
||||||
|
option (include_in_bitcoin_only) = true;
|
||||||
|
|
||||||
|
import "messages.proto";
|
||||||
import "messages-common.proto";
|
import "messages-common.proto";
|
||||||
import "messages-management.proto";
|
import "messages-management.proto";
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ package hw.trezor.messages.management;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageManagement";
|
option java_outer_classname = "TrezorMessageManagement";
|
||||||
|
|
||||||
|
option (include_in_bitcoin_only) = true;
|
||||||
|
|
||||||
import "messages.proto";
|
import "messages.proto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,6 +5,8 @@ package hw.trezor.messages.webauthn;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageWebAuthn";
|
option java_outer_classname = "TrezorMessageWebAuthn";
|
||||||
|
|
||||||
|
import "messages.proto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request: List resident credentials
|
* Request: List resident credentials
|
||||||
* @start
|
* @start
|
||||||
|
@ -9,6 +9,8 @@ package hw.trezor.messages;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessage";
|
option java_outer_classname = "TrezorMessage";
|
||||||
|
|
||||||
|
option (include_in_bitcoin_only) = true;
|
||||||
|
|
||||||
import "google/protobuf/descriptor.proto";
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
/************************* WARNING ***********************
|
/************************* WARNING ***********************
|
||||||
@ -18,7 +20,7 @@ EnumValueOptions and FieldOptions, MUST NOT have the same ID.
|
|||||||
|
|
||||||
Using the same ID indicates the same purpose (protobuf does not allow multiple
|
Using the same ID indicates the same purpose (protobuf does not allow multiple
|
||||||
extensions with the same name), such as EnumValueOptions.bitcoin_only and
|
extensions with the same name), such as EnumValueOptions.bitcoin_only and
|
||||||
MessageOptions.include_in_bitcoin_only. pb2py can then find the extension under
|
FileOptions.include_in_bitcoin_only. pb2py can then find the extension under
|
||||||
either name.
|
either name.
|
||||||
|
|
||||||
The convention to achieve this is as follows:
|
The convention to achieve this is as follows:
|
||||||
@ -54,9 +56,6 @@ extend google.protobuf.EnumOptions {
|
|||||||
extend google.protobuf.MessageOptions {
|
extend google.protobuf.MessageOptions {
|
||||||
optional bool unstable = 52001; // indicate that a message definition might change at any time
|
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 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 */
|
/** Options for tagging field types */
|
||||||
@ -64,6 +63,12 @@ extend google.protobuf.FieldOptions {
|
|||||||
optional bool experimental = 53001; // 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Options for tagging files with protobuf definitions */
|
||||||
|
extend google.protobuf.FileOptions {
|
||||||
|
optional bool include_in_bitcoin_only = 60000; // definitions are available on BITCOIN_ONLY build
|
||||||
|
// intentionally identical to `bitcoin_only` from enum
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping between Trezor wire identifier (uint) and a protobuf message
|
* Mapping between Trezor wire identifier (uint) and a protobuf message
|
||||||
|
@ -65,10 +65,15 @@ INT_TYPES = (
|
|||||||
|
|
||||||
MESSAGE_TYPE_ENUM = "MessageType"
|
MESSAGE_TYPE_ENUM = "MessageType"
|
||||||
|
|
||||||
|
LengthDelimited = c.Struct(
|
||||||
|
"len" / c.VarInt,
|
||||||
|
"bytes" / c.Bytes(c.this.len),
|
||||||
|
)
|
||||||
|
|
||||||
ListOfSimpleValues = c.GreedyRange(
|
ListOfSimpleValues = c.GreedyRange(
|
||||||
c.Struct(
|
c.Struct(
|
||||||
"key" / c.VarInt,
|
"key" / c.VarInt,
|
||||||
"value" / c.VarInt,
|
"value" / c.Switch(c.this.key & 0b111, {0: c.VarInt, 2: LengthDelimited}),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -76,7 +81,8 @@ ListOfSimpleValues = c.GreedyRange(
|
|||||||
def parse_protobuf_simple(data):
|
def parse_protobuf_simple(data):
|
||||||
"""Micro-parse protobuf-encoded data.
|
"""Micro-parse protobuf-encoded data.
|
||||||
|
|
||||||
Assume every field is of type 0 (varint), and parse to a dict of fieldnum: value.
|
Assume every value is of type 0 (varint) or 2 (length-delimited),
|
||||||
|
and parse to a dict of fieldnum: value.
|
||||||
"""
|
"""
|
||||||
return {v.key >> 3: v.value for v in ListOfSimpleValues.parse(data)}
|
return {v.key >> 3: v.value for v in ListOfSimpleValues.parse(data)}
|
||||||
|
|
||||||
@ -339,33 +345,28 @@ class Descriptor:
|
|||||||
ext.name: ext.number for file in self.files for ext in file.extension
|
ext.name: ext.number for file in self.files for ext in file.extension
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.bitcoin_only:
|
||||||
|
self.files = [
|
||||||
|
f
|
||||||
|
for f in self.files
|
||||||
|
if self.get_extensions(f).get("include_in_bitcoin_only")
|
||||||
|
]
|
||||||
|
logging.debug(f"found {len(self.files)} bitcoin-only files")
|
||||||
|
|
||||||
# find message_type enum
|
# find message_type enum
|
||||||
top_level_enums = itertools.chain.from_iterable(f.enum_type for f in self.files)
|
top_level_enums = itertools.chain.from_iterable(f.enum_type for f in self.files)
|
||||||
self.message_type_enum = find_by_name(top_level_enums, MESSAGE_TYPE_ENUM, ())
|
self.message_type_enum = find_by_name(top_level_enums, MESSAGE_TYPE_ENUM, ())
|
||||||
self.convert_enum_value_names(self.message_type_enum)
|
self.convert_enum_value_names(self.message_type_enum)
|
||||||
|
|
||||||
# top-level message inclusion filter that takes bitcoin_only into account
|
|
||||||
def should_include_message(message: ProtoMessage):
|
|
||||||
return (
|
|
||||||
# include all messages when not in bitcoin_only mode
|
|
||||||
not self.bitcoin_only
|
|
||||||
# include all non-wire messages
|
|
||||||
or message.wire_type is None
|
|
||||||
# include messages that are marked bitcoin_only
|
|
||||||
or message.extensions.get("bitcoin_only")
|
|
||||||
)
|
|
||||||
|
|
||||||
# find messages and enums
|
# find messages and enums
|
||||||
self.messages = []
|
self.messages = []
|
||||||
self.enums = []
|
self.enums = []
|
||||||
|
|
||||||
for file in self.files:
|
for file in self.files:
|
||||||
messages = (
|
messages = [
|
||||||
ProtoMessage.from_message(self, m)
|
ProtoMessage.from_message(self, m)
|
||||||
for m in self._filter_items(file.message_type)
|
for m in self._filter_items(file.message_type)
|
||||||
)
|
]
|
||||||
# use exclusion list on top-level messages
|
|
||||||
messages = [m for m in messages if should_include_message(m)]
|
|
||||||
self.messages += messages
|
self.messages += messages
|
||||||
self.enums += self._filter_items(file.enum_type)
|
self.enums += self._filter_items(file.enum_type)
|
||||||
|
|
||||||
@ -379,7 +380,6 @@ class Descriptor:
|
|||||||
for enum in self.enums:
|
for enum in self.enums:
|
||||||
self.convert_enum_value_names(enum)
|
self.convert_enum_value_names(enum)
|
||||||
|
|
||||||
|
|
||||||
def _filter_items(self, iter):
|
def _filter_items(self, iter):
|
||||||
return [
|
return [
|
||||||
item
|
item
|
||||||
@ -402,7 +402,7 @@ class Descriptor:
|
|||||||
# the API provides access to unknown fields, it hides the extensions.
|
# the API provides access to unknown fields, it hides the extensions.
|
||||||
# What we do is re-encode the options descriptor...
|
# What we do is re-encode the options descriptor...
|
||||||
options_bytes = something.options.SerializeToString()
|
options_bytes = something.options.SerializeToString()
|
||||||
# ...and re-parse it as a dict of uvarints...
|
# ...and re-parse it as a dict of uvarints/strings...
|
||||||
simple_values = parse_protobuf_simple(options_bytes)
|
simple_values = parse_protobuf_simple(options_bytes)
|
||||||
# ...and extract the value corresponding to the extension we care about.
|
# ...and extract the value corresponding to the extension we care about.
|
||||||
return simple_values.get(extension_num, default)
|
return simple_values.get(extension_num, default)
|
||||||
|
@ -9,7 +9,7 @@ First packet has the following structure:
|
|||||||
| offset | length | type | contents |
|
| offset | length | type | contents |
|
||||||
|--------|--------|-------------|---------------------------------------------------------------------------------------|
|
|--------|--------|-------------|---------------------------------------------------------------------------------------|
|
||||||
| 0 | 3 | char[3] | '?##' magic constant |
|
| 0 | 3 | char[3] | '?##' magic constant |
|
||||||
| 3 | 2 | BE uint16_t | numerical [message type](messages.proto#L14) |
|
| 3 | 2 | BE uint16_t | numerical [message type](messages.proto#L76) |
|
||||||
| 5 | 4 | BE uint32_t | message size |
|
| 5 | 4 | BE uint32_t | message size |
|
||||||
| 9 | 55 | uint8_t[55] | first 55 bytes of message encoded in Protocol Buffers (padded with zeroes if shorter) |
|
| 9 | 55 | uint8_t[55] | first 55 bytes of message encoded in Protocol Buffers (padded with zeroes if shorter) |
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user