From 30b08d949b6ab6575988fcba0219885a869c09fd Mon Sep 17 00:00:00 2001 From: matejcik Date: Tue, 31 Aug 2021 11:36:13 +0200 Subject: [PATCH] feat(common): add default values to EthereumSignTx fields so that we can avoid Optional types for fields --- common/protob/messages-ethereum.proto | 33 ++++++++--------- core/src/trezor/messages.py | 38 ++++++++++---------- python/src/trezorlib/ethereum.py | 2 +- python/src/trezorlib/messages.py | 42 +++++++++++----------- tests/device_tests/ethereum/test_signtx.py | 24 ------------- 5 files changed, 58 insertions(+), 81 deletions(-) diff --git a/common/protob/messages-ethereum.proto b/common/protob/messages-ethereum.proto index dcccdb0e5..8c779deda 100644 --- a/common/protob/messages-ethereum.proto +++ b/common/protob/messages-ethereum.proto @@ -50,23 +50,24 @@ message EthereumAddress { /** * 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. + * gas_price, gas_limit and chain_id must be provided and non-zero. + * All other fields are optional and default to value `0` if missing. * Note: the first at most 1024 bytes of data MUST be transmitted as part of this message. * @start * @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 string to = 11; // recipient address - 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 - required uint64 chain_id = 9; // Chain Id for EIP 155 - optional uint32 tx_type = 10; // Used for Wanchain + repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node + optional bytes nonce = 2 [default='']; // <=256 bit unsigned big endian + required bytes gas_price = 3; // <=256 bit unsigned big endian (in wei) + required bytes gas_limit = 4; // <=256 bit unsigned big endian + optional string to = 11 [default='']; // recipient address + optional bytes value = 6 [default='']; // <=256 bit unsigned big endian (in wei) + optional bytes data_initial_chunk = 7 [default='']; // The initial data chunk (<= 1024 bytes) + optional uint32 data_length = 8 [default=0]; // Length of transaction payload + required uint64 chain_id = 9; // Chain Id for EIP 155 + optional uint32 tx_type = 10; // Used for Wanchain } /** @@ -114,7 +115,7 @@ message EthereumTxRequest { * @next EthereumTxRequest */ message EthereumTxAck { - optional bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes) + required bytes data_chunk = 1; // Bytes from transaction payload (<= 1024 bytes) } /** @@ -125,7 +126,7 @@ message EthereumTxAck { */ message EthereumSignMessage { repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node - optional bytes message = 2; // message to be signed + required bytes message = 2; // message to be signed } /** @@ -144,7 +145,7 @@ message EthereumMessageSignature { * @next Failure */ message EthereumVerifyMessage { - optional bytes signature = 2; // signature to verify - optional bytes message = 3; // message to verify - optional string address = 4; // address to verify + required bytes signature = 2; // signature to verify + required bytes message = 3; // message to verify + required string address = 4; // address to verify } diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py index 075621691..a03830e4a 100644 --- a/core/src/trezor/messages.py +++ b/core/src/trezor/messages.py @@ -2984,24 +2984,24 @@ if TYPE_CHECKING: class EthereumSignTx(protobuf.MessageType): address_n: "list[int]" - nonce: "bytes | None" - gas_price: "bytes | None" - gas_limit: "bytes | None" - to: "str | None" - value: "bytes | None" - data_initial_chunk: "bytes | None" - data_length: "int | None" + nonce: "bytes" + gas_price: "bytes" + gas_limit: "bytes" + to: "str" + value: "bytes" + data_initial_chunk: "bytes" + data_length: "int" chain_id: "int" tx_type: "int | None" def __init__( self, *, + gas_price: "bytes", + gas_limit: "bytes", chain_id: "int", address_n: "list[int] | None" = None, nonce: "bytes | None" = None, - gas_price: "bytes | None" = None, - gas_limit: "bytes | None" = None, to: "str | None" = None, value: "bytes | None" = None, data_initial_chunk: "bytes | None" = None, @@ -3069,12 +3069,12 @@ if TYPE_CHECKING: return isinstance(msg, cls) class EthereumTxAck(protobuf.MessageType): - data_chunk: "bytes | None" + data_chunk: "bytes" def __init__( self, *, - data_chunk: "bytes | None" = None, + data_chunk: "bytes", ) -> None: pass @@ -3084,13 +3084,13 @@ if TYPE_CHECKING: class EthereumSignMessage(protobuf.MessageType): address_n: "list[int]" - message: "bytes | None" + message: "bytes" def __init__( self, *, + message: "bytes", address_n: "list[int] | None" = None, - message: "bytes | None" = None, ) -> None: pass @@ -3115,16 +3115,16 @@ if TYPE_CHECKING: return isinstance(msg, cls) class EthereumVerifyMessage(protobuf.MessageType): - signature: "bytes | None" - message: "bytes | None" - address: "str | None" + signature: "bytes" + message: "bytes" + address: "str" def __init__( self, *, - signature: "bytes | None" = None, - message: "bytes | None" = None, - address: "str | None" = None, + signature: "bytes", + message: "bytes", + address: "str", ) -> None: pass diff --git a/python/src/trezorlib/ethereum.py b/python/src/trezorlib/ethereum.py index 1b9e6de23..2acb93338 100644 --- a/python/src/trezorlib/ethereum.py +++ b/python/src/trezorlib/ethereum.py @@ -55,7 +55,7 @@ def sign_tx( msg = messages.EthereumSignTx( address_n=n, nonce=int_to_big_endian(nonce), - gas_price=int_to_big_endian(gas_price) if gas_price is not None else None, + gas_price=int_to_big_endian(gas_price), gas_limit=int_to_big_endian(gas_limit), value=int_to_big_endian(value), to=to, diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index 932798e90..a550dec4c 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -4258,8 +4258,8 @@ class EthereumSignTx(protobuf.MessageType): FIELDS = { 1: protobuf.Field("address_n", "uint32", repeated=True, required=False), 2: protobuf.Field("nonce", "bytes", repeated=False, required=False), - 3: protobuf.Field("gas_price", "bytes", repeated=False, required=False), - 4: protobuf.Field("gas_limit", "bytes", repeated=False, required=False), + 3: protobuf.Field("gas_price", "bytes", repeated=False, required=True), + 4: protobuf.Field("gas_limit", "bytes", repeated=False, required=True), 11: protobuf.Field("to", "string", repeated=False, required=False), 6: protobuf.Field("value", "bytes", repeated=False, required=False), 7: protobuf.Field("data_initial_chunk", "bytes", repeated=False, required=False), @@ -4271,22 +4271,22 @@ class EthereumSignTx(protobuf.MessageType): def __init__( self, *, + gas_price: "bytes", + gas_limit: "bytes", chain_id: "int", address_n: Optional[List["int"]] = None, - nonce: Optional["bytes"] = None, - gas_price: Optional["bytes"] = None, - gas_limit: Optional["bytes"] = None, - to: Optional["str"] = None, - value: Optional["bytes"] = None, - data_initial_chunk: Optional["bytes"] = None, - data_length: Optional["int"] = None, + nonce: Optional["bytes"] = b'', + to: Optional["str"] = '', + value: Optional["bytes"] = b'', + data_initial_chunk: Optional["bytes"] = b'', + data_length: Optional["int"] = 0, tx_type: Optional["int"] = None, ) -> None: self.address_n = address_n if address_n is not None else [] - self.chain_id = chain_id - self.nonce = nonce self.gas_price = gas_price self.gas_limit = gas_limit + self.chain_id = chain_id + self.nonce = nonce self.to = to self.value = value self.data_initial_chunk = data_initial_chunk @@ -4364,13 +4364,13 @@ class EthereumTxRequest(protobuf.MessageType): class EthereumTxAck(protobuf.MessageType): MESSAGE_WIRE_TYPE = 60 FIELDS = { - 1: protobuf.Field("data_chunk", "bytes", repeated=False, required=False), + 1: protobuf.Field("data_chunk", "bytes", repeated=False, required=True), } def __init__( self, *, - data_chunk: Optional["bytes"] = None, + data_chunk: "bytes", ) -> None: self.data_chunk = data_chunk @@ -4379,14 +4379,14 @@ class EthereumSignMessage(protobuf.MessageType): MESSAGE_WIRE_TYPE = 64 FIELDS = { 1: protobuf.Field("address_n", "uint32", repeated=True, required=False), - 2: protobuf.Field("message", "bytes", repeated=False, required=False), + 2: protobuf.Field("message", "bytes", repeated=False, required=True), } def __init__( self, *, + message: "bytes", address_n: Optional[List["int"]] = None, - message: Optional["bytes"] = None, ) -> None: self.address_n = address_n if address_n is not None else [] self.message = message @@ -4412,17 +4412,17 @@ class EthereumMessageSignature(protobuf.MessageType): class EthereumVerifyMessage(protobuf.MessageType): MESSAGE_WIRE_TYPE = 65 FIELDS = { - 2: protobuf.Field("signature", "bytes", repeated=False, required=False), - 3: protobuf.Field("message", "bytes", repeated=False, required=False), - 4: protobuf.Field("address", "string", repeated=False, required=False), + 2: protobuf.Field("signature", "bytes", repeated=False, required=True), + 3: protobuf.Field("message", "bytes", repeated=False, required=True), + 4: protobuf.Field("address", "string", repeated=False, required=True), } def __init__( self, *, - signature: Optional["bytes"] = None, - message: Optional["bytes"] = None, - address: Optional["str"] = None, + signature: "bytes", + message: "bytes", + address: "str", ) -> None: self.signature = signature self.message = message diff --git a/tests/device_tests/ethereum/test_signtx.py b/tests/device_tests/ethereum/test_signtx.py index 296e8d4c4..9b6f089ea 100644 --- a/tests/device_tests/ethereum/test_signtx.py +++ b/tests/device_tests/ethereum/test_signtx.py @@ -106,30 +106,6 @@ def test_sanity_checks(client): value=12345678901234567890, ) - # no gas price - with pytest.raises(TrezorFailure): - client.call( - messages.EthereumSignTx( - address_n=parse_path("44'/60'/0'/0/0"), - nonce=b"AAA", - gas_limit=ethereum.int_to_big_endian(10000), - to=TO_ADDR, - value=ethereum.int_to_big_endian(12345678901234567890), - ) - ) - - # no gas limit - with pytest.raises(TrezorFailure): - client.call( - messages.EthereumSignTx( - address_n=parse_path("44'/60'/0'/0/0"), - nonce=b"AAA", - gas_price=ethereum.int_to_big_endian(10000), - to=TO_ADDR, - value=ethereum.int_to_big_endian(12345678901234567890), - ) - ) - def test_data_streaming(client): """Only verifying the expected responses, the signatures are