From 3c411f2c3f3f8c6c9d73c1f03429afd891d1a867 Mon Sep 17 00:00:00 2001 From: Michael Hatton Date: Wed, 18 Aug 2021 11:19:59 -0400 Subject: [PATCH 1/8] Changes from original PR --- common/protob/messages-ethereum.proto | 4 +- core/.changelog.d/1741.added | 1 + core/src/apps/ethereum/sign_tx.py | 4 +- crypto/address.c | 2 +- crypto/address.h | 2 +- legacy/firmware/.changelog.d/1741.added | 1 + legacy/firmware/ethereum.c | 48 +++++++++++-------- legacy/firmware/ethereum_tokens.c.mako | 2 +- legacy/firmware/ethereum_tokens.h.mako | 4 +- legacy/firmware/fsm_msg_ethereum.h | 2 +- python/src/trezorlib/messages.py | 4 +- .../test_msg_ethereum_signtx_eip155.py | 40 ++++++++++++++++ vendor/micropython | 2 +- 13 files changed, 82 insertions(+), 34 deletions(-) create mode 100644 core/.changelog.d/1741.added create mode 100644 legacy/firmware/.changelog.d/1741.added diff --git a/common/protob/messages-ethereum.proto b/common/protob/messages-ethereum.proto index 9fab13c2c54..606d1d14a7d 100644 --- a/common/protob/messages-ethereum.proto +++ b/common/protob/messages-ethereum.proto @@ -65,7 +65,7 @@ message EthereumSignTx { optional bytes value = 6; // <=256 bit unsigned big endian (in wei) optional bytes data_initial_chunk = 7; // The initial data chunk (<= 1024 bytes) optional uint32 data_length = 8; // Length of transaction payload - optional uint32 chain_id = 9; // Chain Id for EIP 155 + optional uint64 chain_id = 9; // Chain Id for EIP 155 optional uint32 tx_type = 10; // (only for Wanchain) } @@ -78,7 +78,7 @@ message EthereumSignTx { */ 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 uint64 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) } diff --git a/core/.changelog.d/1741.added b/core/.changelog.d/1741.added new file mode 100644 index 00000000000..fe5e9ab41aa --- /dev/null +++ b/core/.changelog.d/1741.added @@ -0,0 +1 @@ +Ethereum: support 64-bit chain IDs diff --git a/core/src/apps/ethereum/sign_tx.py b/core/src/apps/ethereum/sign_tx.py index 5468e298262..6ced6ef6e71 100644 --- a/core/src/apps/ethereum/sign_tx.py +++ b/core/src/apps/ethereum/sign_tx.py @@ -17,7 +17,7 @@ ) # maximum supported chain id -MAX_CHAIN_ID = 2147483629 +MAX_CHAIN_ID = (0xFFFF_FFFF_FFFF_FFFF - 35) / 2 @with_keychain_from_chain_id @@ -157,7 +157,7 @@ def check(msg: EthereumSignTx): if msg.tx_type not in [1, 6, None]: raise wire.DataError("tx_type out of bounds") - if msg.chain_id < 0: + if msg.chain_id < 1: raise wire.DataError("chain_id out of bounds") if msg.data_length > 0: diff --git a/crypto/address.c b/crypto/address.c index 8f3aa9734ab..6379489b097 100644 --- a/crypto/address.c +++ b/crypto/address.c @@ -58,7 +58,7 @@ bool address_check_prefix(const uint8_t *addr, uint32_t address_type) { #include "sha3.h" void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, - uint32_t chain_id) { + uint64_t chain_id) { const char *hex = "0123456789abcdef"; for (int i = 0; i < 20; i++) { address[i * 2] = hex[(addr[i] >> 4) & 0xF]; diff --git a/crypto/address.h b/crypto/address.h index 8147f2c35a8..e799484ee9a 100644 --- a/crypto/address.h +++ b/crypto/address.h @@ -34,7 +34,7 @@ void address_write_prefix_bytes(uint32_t address_type, uint8_t *out); bool address_check_prefix(const uint8_t *addr, uint32_t address_type); #if USE_ETHEREUM void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, - uint32_t chain_id); + uint64_t chain_id); #endif #endif diff --git a/legacy/firmware/.changelog.d/1741.added b/legacy/firmware/.changelog.d/1741.added new file mode 100644 index 00000000000..fe5e9ab41aa --- /dev/null +++ b/legacy/firmware/.changelog.d/1741.added @@ -0,0 +1 @@ +Ethereum: support 64-bit chain IDs diff --git a/legacy/firmware/ethereum.c b/legacy/firmware/ethereum.c index edb51f299db..7da5a188193 100644 --- a/legacy/firmware/ethereum.c +++ b/legacy/firmware/ethereum.c @@ -37,14 +37,16 @@ #include "transaction.h" #include "util.h" -/* maximum supported chain id. v must fit in an uint32_t. */ -#define MAX_CHAIN_ID 2147483629 +/* maximum supported chain id. + * signature_v must also fit in an uint64_t. + */ +#define MAX_CHAIN_ID ((0xFFFFFFFFFFFFFFFF - 35) >> 1) static bool ethereum_signing = false; static uint32_t data_total, data_left; static EthereumTxRequest msg_tx_request; static CONFIDENTIAL uint8_t privkey[32]; -static uint32_t chain_id; +static uint64_t chain_id; static uint32_t tx_type; struct SHA3_CTX keccak_ctx = {0}; @@ -118,20 +120,24 @@ static void hash_rlp_field(const uint8_t *buf, size_t size) { * Push an RLP encoded number to the hash buffer. * Ethereum yellow paper says to convert to big endian and strip leading zeros. */ -static void hash_rlp_number(uint32_t number) { +static void hash_rlp_number(uint64_t number) { if (!number) { return; } - uint8_t data[4] = {0}; - data[0] = (number >> 24) & 0xff; - data[1] = (number >> 16) & 0xff; - data[2] = (number >> 8) & 0xff; - data[3] = (number)&0xff; + uint8_t data[8] = {0}; + data[0] = (number >> 56) & 0xff; + data[1] = (number >> 48) & 0xff; + data[2] = (number >> 40) & 0xff; + data[3] = (number >> 32) & 0xff; + data[4] = (number >> 24) & 0xff; + data[5] = (number >> 16) & 0xff; + data[6] = (number >> 8) & 0xff; + data[7] = (number)&0xff; int offset = 0; while (!data[offset]) { offset++; } - hash_rlp_field(data + offset, 4 - offset); + hash_rlp_field(data + offset, 8 - offset); } /* @@ -153,18 +159,18 @@ static int rlp_calculate_length(int length, uint8_t firstbyte) { } } -static int rlp_calculate_number_length(uint32_t number) { - if (number <= 0x7f) { - return 1; - } else if (number <= 0xff) { - return 2; - } else if (number <= 0xffff) { - return 3; - } else if (number <= 0xffffff) { - return 4; - } else { - return 5; +/* If number is less than 0x80 the RLP encoding is iteself (1 byte). + * If it is 0x80 or larger, RLP encoding is 1 + length in bytes. + */ +static int rlp_calculate_number_length(uint64_t number) { + int length = 1; + if (number >= 0x80) { + while (number) { + length++; + number = number >> 8; + } } + return length; } static void send_request_chunk(void) { diff --git a/legacy/firmware/ethereum_tokens.c.mako b/legacy/firmware/ethereum_tokens.c.mako index a16d60da934..19737f84db8 100644 --- a/legacy/firmware/ethereum_tokens.c.mako +++ b/legacy/firmware/ethereum_tokens.c.mako @@ -13,7 +13,7 @@ const TokenType tokens[TOKENS_COUNT] = { static const TokenType _UnknownToken = { 0, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", " UNKN", 0 }; const TokenType *UnknownToken = &_UnknownToken; -const TokenType *tokenByChainAddress(uint32_t chain_id, const uint8_t *address) +const TokenType *tokenByChainAddress(uint64_t chain_id, const uint8_t *address) { if (!address) return 0; for (int i = 0; i < TOKENS_COUNT; i++) { diff --git a/legacy/firmware/ethereum_tokens.h.mako b/legacy/firmware/ethereum_tokens.h.mako index 12008d7efdb..160506c3d33 100644 --- a/legacy/firmware/ethereum_tokens.h.mako +++ b/legacy/firmware/ethereum_tokens.h.mako @@ -10,7 +10,7 @@ #define TOKENS_COUNT ${len(erc20_list)} typedef struct { - uint32_t chain_id; + uint64_t chain_id; const char * const address; const char * const ticker; int decimals; @@ -20,6 +20,6 @@ extern const TokenType tokens[TOKENS_COUNT]; extern const TokenType *UnknownToken; -const TokenType *tokenByChainAddress(uint32_t chain_id, const uint8_t *address); +const TokenType *tokenByChainAddress(uint64_t chain_id, const uint8_t *address); #endif diff --git a/legacy/firmware/fsm_msg_ethereum.h b/legacy/firmware/fsm_msg_ethereum.h index aed40d45fdd..3bff27347a8 100644 --- a/legacy/firmware/fsm_msg_ethereum.h +++ b/legacy/firmware/fsm_msg_ethereum.h @@ -94,7 +94,7 @@ void fsm_msgEthereumGetAddress(const EthereumGetAddress *msg) { uint32_t slip44 = (msg->address_n_count > 1) ? (msg->address_n[1] & 0x7fffffff) : 0; bool rskip60 = false; - uint32_t chain_id = 0; + uint64_t chain_id = 0; // constants from trezor-common/defs/ethereum/networks.json switch (slip44) { case 137: diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index 106a1f35a21..4d1263400e0 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -3941,7 +3941,7 @@ class EthereumSignTx(protobuf.MessageType): 6: protobuf.Field("value", "bytes", repeated=False, required=False), 7: protobuf.Field("data_initial_chunk", "bytes", repeated=False, required=False), 8: protobuf.Field("data_length", "uint32", repeated=False, required=False), - 9: protobuf.Field("chain_id", "uint32", repeated=False, required=False), + 9: protobuf.Field("chain_id", "uint64", repeated=False, required=False), 10: protobuf.Field("tx_type", "uint32", repeated=False, required=False), } @@ -3975,7 +3975,7 @@ class EthereumTxRequest(protobuf.MessageType): MESSAGE_WIRE_TYPE = 59 FIELDS = { 1: protobuf.Field("data_length", "uint32", repeated=False, required=False), - 2: protobuf.Field("signature_v", "uint32", repeated=False, required=False), + 2: protobuf.Field("signature_v", "uint64", repeated=False, required=False), 3: protobuf.Field("signature_r", "bytes", repeated=False, required=False), 4: protobuf.Field("signature_s", "bytes", repeated=False, required=False), } diff --git a/tests/device_tests/test_msg_ethereum_signtx_eip155.py b/tests/device_tests/test_msg_ethereum_signtx_eip155.py index 43260dd5539..42f34d24c99 100644 --- a/tests/device_tests/test_msg_ethereum_signtx_eip155.py +++ b/tests/device_tests/test_msg_ethereum_signtx_eip155.py @@ -101,6 +101,46 @@ "1447ba45be9fca42bcbf250389403245c8c1b0476e60b96dea320b0a596b5528", ), ), + # Previous max chain id + ( + 2147483639, + 1, + ( + 4294967314, + "f06ba56a3d3602a3d39a614375b2867f8a867354ba17fde98a5cb5f1806320d1", + "7bc197e0f656e52183805abada49c7d41f5d2b929f1ae0ebe99618286dfed116", + ), + ), + # PALM + ( + 11297108109, + 60, + ( + 22594216254, + "9d05ca7cdcf971f3114c0ef8d636c5aae1353bb227e04ec1198c60d874e676c0", + "35414067209e27fb690d9387264c74e334e25a117705f3583fb24434a952c9ca", + ), + ), + # PALM + ( + 11297108109, + 1, + ( + 22594216253, + "cccccef8f6636f316e69a1239436f9d61021501ba20ed72b6528c84b2f727980", + "614cb533a5d73cbf92ba4683c87c9238d0547572ee8f0f821ab1decdfc9639b8", + ), + ), + # Max uint64 + ( + 0xFFFF_FFFF_FFFF_FFFF, + 1, + ( + 36893488147419103266, + "7bf581e8c7ff7d0e94d25eaa476de928d444b180fe50a91374b8883ff5dee3a8", + "3a3efa7a3f97043a999b3183d958a03126ec2652608c376c4626850b9b6a33fa", + ), + ), ) diff --git a/vendor/micropython b/vendor/micropython index f7e780ae16b..c0013200d9a 160000 --- a/vendor/micropython +++ b/vendor/micropython @@ -1 +1 @@ -Subproject commit f7e780ae16bc62519e6b78672e43ecae9138ed0a +Subproject commit c0013200d9a951276b6706616cfeb910ac9afb34 From 0999646cb376acc5dbcb9646594507614eb8023d Mon Sep 17 00:00:00 2001 From: arbitrarylink Date: Thu, 19 Aug 2021 12:12:12 -0400 Subject: [PATCH 2/8] Now that we are rejecting chain_ids of 0, we need to have the tests set the chain_ids to at least 1. --- .../device_tests/test_msg_ethereum_signtx.py | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/tests/device_tests/test_msg_ethereum_signtx.py b/tests/device_tests/test_msg_ethereum_signtx.py index 62acffb2d76..20cc769daf8 100644 --- a/tests/device_tests/test_msg_ethereum_signtx.py +++ b/tests/device_tests/test_msg_ethereum_signtx.py @@ -185,6 +185,7 @@ def test_ethereum_signtx_nodata(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/100"), + chain_id=1, nonce=0, gas_price=20, gas_limit=20, @@ -192,14 +193,14 @@ def test_ethereum_signtx_nodata(self, client): value=10, ) - assert sig_v == 27 + assert sig_v == 37 assert ( sig_r.hex() - == "2f548f63ddb4cf19b6b9f922da58ff71833b967d590f3b4dcc2a70810338a982" + == "364ea282d85ca0e0615ccda301b7b8a56831491284dff36f6738b6110390e154" ) assert ( sig_s.hex() - == "428d35f0dca963b5196b63e7aa5e0405d8bff77d6aee1202183f1f68dacb4483" + == "361a1771b74ca7136a3aef7624ed0818658dc3700e8ae6a1fbce42c4beb59d91" ) with client: @@ -214,20 +215,21 @@ def test_ethereum_signtx_nodata(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/100"), + chain_id=1, nonce=123456, gas_price=20000, gas_limit=20000, to=TO_ADDR, value=12345678901234567890, ) - assert sig_v == 27 + assert sig_v == 38 assert ( sig_r.hex() - == "3bf0470cd7f5ad8d82613199f73deadc55c3c9f32f91b1a21b5ef644144ebd58" + == "60709d8966ea6c63e4c89cfee847d6fe58a96eb17e6240cb1d7a14b4c3f05915" ) assert ( sig_s.hex() - == "48b3ef1b2502febdf35e9ff4df0ba1fda62f042fad639eb4852a297fc9872ebd" + == "4ff112527ec146b493982a4b42def6babccf27facd6f3554d0d26ba18a88e544" ) @pytest.mark.setup_client(mnemonic=MNEMONIC12) @@ -245,6 +247,7 @@ def test_ethereum_signtx_data(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=0, gas_price=20, gas_limit=20, @@ -252,14 +255,14 @@ def test_ethereum_signtx_data(self, client): value=10, data=b"abcdefghijklmnop" * 16, ) - assert sig_v == 27 + assert sig_v == 37 assert ( sig_r.hex() - == "e90f9e3dbfb34861d40d67570cb369049e675c6eebfdda6b08413a2283421b85" + == "88ba4067fb0b71fcd9dd840cfe4d040fc545336287882036ea31826232ba5137" ) assert ( sig_s.hex() - == "763912b8801f76cbea7792d98123a245514beeab2f3afebb4bab637888e8393a" + == "0d855eb6993c2361d58e1789a364567ce97a7df07bb998236500d16af8b3a1a2" ) with client: @@ -284,6 +287,7 @@ def test_ethereum_signtx_data(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=123456, gas_price=20000, gas_limit=20000, @@ -291,14 +295,14 @@ def test_ethereum_signtx_data(self, client): value=12345678901234567890, data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!", ) - assert sig_v == 27 + assert sig_v == 38 assert ( sig_r.hex() - == "dd96d82d791118a55601dfcede237760d2e9734b76c373ede5362a447c42ac48" + == "a95a65ef61cafb89ab0e593b2577e3ca23177404b38189375cfc839f0fce9b9e" ) assert ( sig_s.hex() - == "60a77558f28d483d476f9507cd8a6a4bb47b86611aaff95fd5499b9ee9ebe7ee" + == "45efb6846b33da028b77faf920c5154c5302ee55fe34b75c9b7addb40aac40a9" ) @pytest.mark.setup_client(mnemonic=MNEMONIC12) @@ -325,6 +329,7 @@ def test_ethereum_signtx_message(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=0, gas_price=20000, gas_limit=20000, @@ -332,14 +337,14 @@ def test_ethereum_signtx_message(self, client): value=0, data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!", ) - assert sig_v == 27 + assert sig_v == 38 assert ( sig_r.hex() - == "81af16020d3c6ad820cab2e2b0834fa37f4a9b0c2443f151a4e2f12fe1081b09" + == "f1a42daa34cc6ee433fc8329a4b41f8d16967863d1588ae364564bc9e6e9c5f1" ) assert ( sig_s.hex() - == "7b34b5d8a43771d493cd9fa0c7b27a9563e2a31799fb9f0c2809539a848b9f47" + == "7952c81accea9c9a8d3ed602e7316105fdf7203d6b8a80c4fcfe134a08b15388" ) def test_ethereum_signtx_newcontract(self, client): @@ -348,6 +353,7 @@ def test_ethereum_signtx_newcontract(self, client): ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=123456, gas_price=20000, gas_limit=20000, @@ -377,6 +383,7 @@ def test_ethereum_signtx_newcontract(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=0, gas_price=20000, gas_limit=20000, @@ -384,14 +391,14 @@ def test_ethereum_signtx_newcontract(self, client): value=12345678901234567890, data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!", ) - assert sig_v == 28 + assert sig_v == 37 assert ( sig_r.hex() - == "c86bda9de238b1c602648996561e7270a3be208da96bbf23474cb8e4014b9f93" + == "07f6c40dcd3bc875c106304eda9eebb25716c0cf62127478ed22bc24128dbeb7" ) assert ( sig_s.hex() - == "18742403f75a05e7fa9868c30b36f1e55628de02d01c03084c1ff6775a13137c" + == "7efeedb81b22f2a3f88e7fd3b4119902f09280f4d179eda275b6fdf25e0fdac6" ) def test_ethereum_sanity_checks(self, client): @@ -400,6 +407,7 @@ def test_ethereum_sanity_checks(self, client): ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=123456, gas_price=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, gas_limit=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -412,6 +420,7 @@ def test_ethereum_sanity_checks(self, client): client.call( messages.EthereumSignTx( address_n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=b"AAA", gas_limit=ethereum.int_to_big_endian(10000), to=TO_ADDR, @@ -424,6 +433,7 @@ def test_ethereum_sanity_checks(self, client): client.call( messages.EthereumSignTx( address_n=parse_path("44'/60'/0'/0/0"), + chain_id=1, nonce=b"AAA", gas_price=ethereum.int_to_big_endian(10000), to=TO_ADDR, From 01437702078e7e7babd34a35ff8467d5cfd66f4a Mon Sep 17 00:00:00 2001 From: arbitrarylink Date: Thu, 19 Aug 2021 17:50:59 -0400 Subject: [PATCH 3/8] Ran 'make gen' and uploaded changed files. --- python/src/trezorlib/messages.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index 493b7d3e7ba..dd0b5bccabc 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -3984,7 +3984,7 @@ class EthereumSignTxEIP1559(protobuf.MessageType): 7: protobuf.Field("value", "bytes", repeated=False, required=True), 8: protobuf.Field("data_initial_chunk", "bytes", repeated=False, required=False), 9: protobuf.Field("data_length", "uint32", repeated=False, required=True), - 10: protobuf.Field("chain_id", "uint32", repeated=False, required=True), + 10: protobuf.Field("chain_id", "uint64", repeated=False, required=True), 11: protobuf.Field("access_list", "EthereumAccessList", repeated=True, required=False), } From 8b7c4ecd616c8c148ca428cac04e11cf54c379f5 Mon Sep 17 00:00:00 2001 From: arbitrarylink Date: Thu, 19 Aug 2021 18:02:08 -0400 Subject: [PATCH 4/8] Ran make style_check and fixed reported errors --- core/src/apps/ethereum/sign_tx.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/apps/ethereum/sign_tx.py b/core/src/apps/ethereum/sign_tx.py index 1647d887fcd..98354de3059 100644 --- a/core/src/apps/ethereum/sign_tx.py +++ b/core/src/apps/ethereum/sign_tx.py @@ -172,10 +172,12 @@ def check(msg: EthereumSignTx): if not check_gas(msg) or not check_to(msg): raise wire.DataError("Safety check failed") + def check_chain_id(msg: EthereumSignTx): if msg.chain_id < 1: raise wire.DataError("chain_id out of bounds") + def check_data(msg: EthereumSignTx): if msg.data_length > 0: if not msg.data_initial_chunk: From de5fd297c33d905f9129318a02e0a1198f1c5e01 Mon Sep 17 00:00:00 2001 From: arbitrarylink Date: Thu, 19 Aug 2021 18:21:11 -0400 Subject: [PATCH 5/8] Added changelog files --- core/.changelog.d/1771.added | 1 + legacy/firmware/.changelog.d/1771.added | 1 + 2 files changed, 2 insertions(+) create mode 100644 core/.changelog.d/1771.added create mode 100644 legacy/firmware/.changelog.d/1771.added diff --git a/core/.changelog.d/1771.added b/core/.changelog.d/1771.added new file mode 100644 index 00000000000..fe5e9ab41aa --- /dev/null +++ b/core/.changelog.d/1771.added @@ -0,0 +1 @@ +Ethereum: support 64-bit chain IDs diff --git a/legacy/firmware/.changelog.d/1771.added b/legacy/firmware/.changelog.d/1771.added new file mode 100644 index 00000000000..fe5e9ab41aa --- /dev/null +++ b/legacy/firmware/.changelog.d/1771.added @@ -0,0 +1 @@ +Ethereum: support 64-bit chain IDs From 6bf9adf4f3269d325b2b8946b7643bcc326ae273 Mon Sep 17 00:00:00 2001 From: arbitrarylink Date: Wed, 25 Aug 2021 13:07:08 -0400 Subject: [PATCH 6/8] Reverted changes concerning chain_id 0 being rejected. --- core/src/apps/ethereum/sign_tx.py | 6 --- python/.changelog.d/1771.added | 1 + .../device_tests/test_msg_ethereum_signtx.py | 46 ++++++++----------- 3 files changed, 19 insertions(+), 34 deletions(-) create mode 100644 python/.changelog.d/1771.added diff --git a/core/src/apps/ethereum/sign_tx.py b/core/src/apps/ethereum/sign_tx.py index 98354de3059..141c5d46089 100644 --- a/core/src/apps/ethereum/sign_tx.py +++ b/core/src/apps/ethereum/sign_tx.py @@ -165,7 +165,6 @@ def check(msg: EthereumSignTx): if msg.tx_type not in [1, 6, None]: raise wire.DataError("tx_type out of bounds") - check_chain_id(msg) check_data(msg) # safety checks @@ -173,11 +172,6 @@ def check(msg: EthereumSignTx): raise wire.DataError("Safety check failed") -def check_chain_id(msg: EthereumSignTx): - if msg.chain_id < 1: - raise wire.DataError("chain_id out of bounds") - - def check_data(msg: EthereumSignTx): if msg.data_length > 0: if not msg.data_initial_chunk: diff --git a/python/.changelog.d/1771.added b/python/.changelog.d/1771.added new file mode 100644 index 00000000000..fe5e9ab41aa --- /dev/null +++ b/python/.changelog.d/1771.added @@ -0,0 +1 @@ +Ethereum: support 64-bit chain IDs diff --git a/tests/device_tests/test_msg_ethereum_signtx.py b/tests/device_tests/test_msg_ethereum_signtx.py index 20cc769daf8..62acffb2d76 100644 --- a/tests/device_tests/test_msg_ethereum_signtx.py +++ b/tests/device_tests/test_msg_ethereum_signtx.py @@ -185,7 +185,6 @@ def test_ethereum_signtx_nodata(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/100"), - chain_id=1, nonce=0, gas_price=20, gas_limit=20, @@ -193,14 +192,14 @@ def test_ethereum_signtx_nodata(self, client): value=10, ) - assert sig_v == 37 + assert sig_v == 27 assert ( sig_r.hex() - == "364ea282d85ca0e0615ccda301b7b8a56831491284dff36f6738b6110390e154" + == "2f548f63ddb4cf19b6b9f922da58ff71833b967d590f3b4dcc2a70810338a982" ) assert ( sig_s.hex() - == "361a1771b74ca7136a3aef7624ed0818658dc3700e8ae6a1fbce42c4beb59d91" + == "428d35f0dca963b5196b63e7aa5e0405d8bff77d6aee1202183f1f68dacb4483" ) with client: @@ -215,21 +214,20 @@ def test_ethereum_signtx_nodata(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/100"), - chain_id=1, nonce=123456, gas_price=20000, gas_limit=20000, to=TO_ADDR, value=12345678901234567890, ) - assert sig_v == 38 + assert sig_v == 27 assert ( sig_r.hex() - == "60709d8966ea6c63e4c89cfee847d6fe58a96eb17e6240cb1d7a14b4c3f05915" + == "3bf0470cd7f5ad8d82613199f73deadc55c3c9f32f91b1a21b5ef644144ebd58" ) assert ( sig_s.hex() - == "4ff112527ec146b493982a4b42def6babccf27facd6f3554d0d26ba18a88e544" + == "48b3ef1b2502febdf35e9ff4df0ba1fda62f042fad639eb4852a297fc9872ebd" ) @pytest.mark.setup_client(mnemonic=MNEMONIC12) @@ -247,7 +245,6 @@ def test_ethereum_signtx_data(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=0, gas_price=20, gas_limit=20, @@ -255,14 +252,14 @@ def test_ethereum_signtx_data(self, client): value=10, data=b"abcdefghijklmnop" * 16, ) - assert sig_v == 37 + assert sig_v == 27 assert ( sig_r.hex() - == "88ba4067fb0b71fcd9dd840cfe4d040fc545336287882036ea31826232ba5137" + == "e90f9e3dbfb34861d40d67570cb369049e675c6eebfdda6b08413a2283421b85" ) assert ( sig_s.hex() - == "0d855eb6993c2361d58e1789a364567ce97a7df07bb998236500d16af8b3a1a2" + == "763912b8801f76cbea7792d98123a245514beeab2f3afebb4bab637888e8393a" ) with client: @@ -287,7 +284,6 @@ def test_ethereum_signtx_data(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=123456, gas_price=20000, gas_limit=20000, @@ -295,14 +291,14 @@ def test_ethereum_signtx_data(self, client): value=12345678901234567890, data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!", ) - assert sig_v == 38 + assert sig_v == 27 assert ( sig_r.hex() - == "a95a65ef61cafb89ab0e593b2577e3ca23177404b38189375cfc839f0fce9b9e" + == "dd96d82d791118a55601dfcede237760d2e9734b76c373ede5362a447c42ac48" ) assert ( sig_s.hex() - == "45efb6846b33da028b77faf920c5154c5302ee55fe34b75c9b7addb40aac40a9" + == "60a77558f28d483d476f9507cd8a6a4bb47b86611aaff95fd5499b9ee9ebe7ee" ) @pytest.mark.setup_client(mnemonic=MNEMONIC12) @@ -329,7 +325,6 @@ def test_ethereum_signtx_message(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=0, gas_price=20000, gas_limit=20000, @@ -337,14 +332,14 @@ def test_ethereum_signtx_message(self, client): value=0, data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!", ) - assert sig_v == 38 + assert sig_v == 27 assert ( sig_r.hex() - == "f1a42daa34cc6ee433fc8329a4b41f8d16967863d1588ae364564bc9e6e9c5f1" + == "81af16020d3c6ad820cab2e2b0834fa37f4a9b0c2443f151a4e2f12fe1081b09" ) assert ( sig_s.hex() - == "7952c81accea9c9a8d3ed602e7316105fdf7203d6b8a80c4fcfe134a08b15388" + == "7b34b5d8a43771d493cd9fa0c7b27a9563e2a31799fb9f0c2809539a848b9f47" ) def test_ethereum_signtx_newcontract(self, client): @@ -353,7 +348,6 @@ def test_ethereum_signtx_newcontract(self, client): ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=123456, gas_price=20000, gas_limit=20000, @@ -383,7 +377,6 @@ def test_ethereum_signtx_newcontract(self, client): sig_v, sig_r, sig_s = ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=0, gas_price=20000, gas_limit=20000, @@ -391,14 +384,14 @@ def test_ethereum_signtx_newcontract(self, client): value=12345678901234567890, data=b"ABCDEFGHIJKLMNOP" * 256 + b"!!!", ) - assert sig_v == 37 + assert sig_v == 28 assert ( sig_r.hex() - == "07f6c40dcd3bc875c106304eda9eebb25716c0cf62127478ed22bc24128dbeb7" + == "c86bda9de238b1c602648996561e7270a3be208da96bbf23474cb8e4014b9f93" ) assert ( sig_s.hex() - == "7efeedb81b22f2a3f88e7fd3b4119902f09280f4d179eda275b6fdf25e0fdac6" + == "18742403f75a05e7fa9868c30b36f1e55628de02d01c03084c1ff6775a13137c" ) def test_ethereum_sanity_checks(self, client): @@ -407,7 +400,6 @@ def test_ethereum_sanity_checks(self, client): ethereum.sign_tx( client, n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=123456, gas_price=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, gas_limit=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, @@ -420,7 +412,6 @@ def test_ethereum_sanity_checks(self, client): client.call( messages.EthereumSignTx( address_n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=b"AAA", gas_limit=ethereum.int_to_big_endian(10000), to=TO_ADDR, @@ -433,7 +424,6 @@ def test_ethereum_sanity_checks(self, client): client.call( messages.EthereumSignTx( address_n=parse_path("44'/60'/0'/0/0"), - chain_id=1, nonce=b"AAA", gas_price=ethereum.int_to_big_endian(10000), to=TO_ADDR, From efcc01fd941fd7a8119e56123b949c62af74b305 Mon Sep 17 00:00:00 2001 From: arbitrarylink Date: Thu, 26 Aug 2021 14:51:57 -0400 Subject: [PATCH 7/8] Adds tests for MAX_CHAIN_ID and MAX_CHAIN_ID+1. Also reverts MAX_CHAIN_ID to the previous value. --- core/src/apps/ethereum/sign_tx.py | 2 +- .../test_msg_ethereum_signtx_eip155.py | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/core/src/apps/ethereum/sign_tx.py b/core/src/apps/ethereum/sign_tx.py index 141c5d46089..cca7d64f4ec 100644 --- a/core/src/apps/ethereum/sign_tx.py +++ b/core/src/apps/ethereum/sign_tx.py @@ -17,7 +17,7 @@ ) # maximum supported chain id -MAX_CHAIN_ID = (0xFFFF_FFFF_FFFF_FFFF - 35) / 2 +MAX_CHAIN_ID = 2147483629 @with_keychain_from_chain_id diff --git a/tests/device_tests/test_msg_ethereum_signtx_eip155.py b/tests/device_tests/test_msg_ethereum_signtx_eip155.py index 42f34d24c99..284748c935f 100644 --- a/tests/device_tests/test_msg_ethereum_signtx_eip155.py +++ b/tests/device_tests/test_msg_ethereum_signtx_eip155.py @@ -20,6 +20,8 @@ from trezorlib import ethereum from trezorlib.tools import parse_path +MAX_CHAIN_ID = 2147483629 + VECTORS_CHAIN_IDS = ( # chain_id, slip44, sig_v, sig_r, sig_s # Ethereum ( @@ -131,6 +133,26 @@ "614cb533a5d73cbf92ba4683c87c9238d0547572ee8f0f821ab1decdfc9639b8", ), ), + # MAX_CHAIN_ID + ( + MAX_CHAIN_ID, + 1, + ( + 4294967293, + "97f217d851c9f54013d7792d3b06492abbeda334191687323f08e03e979bd6c9", + "6a5f60d9abb1fa76be8ab76d3c879e1f0187e432692e3e9adce60642f06abe74", + ), + ), + # MAX_CHAIN_ID+1 + ( + MAX_CHAIN_ID+1, + 1, + ( + 4294967296, + "f643499025c61025d27f7815ed1b1dcd92233548ebdd13bdd056e9cf3f84a853", + "33f363b014e5a404bec8479bb08649a6843f65c1f3166d3289211fb5361dab45", + ), + ), # Max uint64 ( 0xFFFF_FFFF_FFFF_FFFF, From 208da5d4708b693de8b13f56b96a1dbda5dcf11e Mon Sep 17 00:00:00 2001 From: arbitrarylink Date: Fri, 27 Aug 2021 08:48:45 -0400 Subject: [PATCH 8/8] Added missing whitespace around arithmetic operator. --- tests/device_tests/test_msg_ethereum_signtx_eip155.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/device_tests/test_msg_ethereum_signtx_eip155.py b/tests/device_tests/test_msg_ethereum_signtx_eip155.py index 284748c935f..0dfcfc931d7 100644 --- a/tests/device_tests/test_msg_ethereum_signtx_eip155.py +++ b/tests/device_tests/test_msg_ethereum_signtx_eip155.py @@ -145,7 +145,7 @@ ), # MAX_CHAIN_ID+1 ( - MAX_CHAIN_ID+1, + MAX_CHAIN_ID + 1, 1, ( 4294967296,