feat(core/ethereum, legacy/ethereum): add support to Ledger Live legacy derivation path

pull/2569/head
Martin Novak 1 year ago committed by marnova
parent 38548f02f2
commit 58276a7443

@ -62,6 +62,15 @@
"result": {
"address": "0xe432a7533D689ceed00B7EE91d9368b8A1693bD2"
}
},
{
"name": "Ledger Live legacy path",
"parameters": {
"path": "m/44'/60'/0'/0"
},
"result": {
"address": "0x1ec5C1854e3E9F1674c34D6C2Be1bf13DFc0Fd8F"
}
}
]
}

@ -39,5 +39,18 @@
"public_key": "0327ceefada0c89b5ed12d163d5e3dc3b8f326321503a9bdbf6414367f3780b192",
"xpub": "xpub6GBpXvAiKQnvjHgC5qSoM3mJs4BGaRHeq8AYUf3bTyEyNx1fwhrDaX17wSwTzyjrbz2N85RLeJZqVsEJtGhsXZNJT7yMZ4mEs5T41jhg8U7"
}
},
{
"name": "Ledger Live legacy path",
"parameters": {
"path": "m/44'/60'/0'/1"
},
"result": {
"fingerprint": 2566851101,
"child_num": 1,
"chain_code": "ded4dad64a99243f1040d7994f9ac1e2bd7f404f14308084744f4f4efac4cd17",
"public_key": "02d9e22cf1119a98b17c7c82d55d33d3b6dcd15c1220a1918a81dcfcb37a49e912",
"xpub": "xpub6Ef8Pj4PmrkToDvoWvVTSkPAgmiGXEKEs4TLZWibTXxjLFj6rNhAZmE4KUWkyZ3qzaL2vGosbohmRZnfHvhji3MqMys9vM8tcEhbFxaBwi8"
}
} ]
}

@ -63,6 +63,25 @@
"sig_s": "2fd3882fbeb8968041d463d7c61526cdb36a80f53b2b217221b879b0d275d179"
}
},
{
"name": "Ledger Live legacy path",
"parameters": {
"data": "",
"path": "m/44'/60'/0'/0",
"to_address": "0xd0d6d6c5fe4a677d343cc433536bb717bae167dd",
"chain_id": 1,
"nonce": "0x0",
"gas_price": "0x14",
"gas_limit": "0x14",
"tx_type": 1,
"value": "0x64"
},
"result": {
"sig_v": 38,
"sig_r": "c26125fbe5f19f3fa5dd68dd5c3d10d8ba2fbf1064f7e712c33cecc0316295cf",
"sig_s": "49ceabe380eb4609d26e663174b6089e5ac05bf12bd36ef439ef108dc17dbe90"
}
},
{
"name": "nodata_1",
"parameters": {

@ -231,6 +231,25 @@
"sig_r": "7bf581e8c7ff7d0e94d25eaa476de928d444b180fe50a91374b8883ff5dee3a8",
"sig_s": "3a3efa7a3f97043a999b3183d958a03126ec2652608c376c4626850b9b6a33fa"
}
},
{
"name": "Ledger Live legacy path",
"parameters": {
"chain_id": 1,
"path": "m/44'/60'/0'/0",
"nonce": "0x0",
"gas_price": "0x4a817c800",
"gas_limit": "0x5208",
"value": "0x2540be400",
"to_address": "0x8eA7a3fccC211ED48b763b4164884DDbcF3b0A98",
"tx_type": null,
"data": ""
},
"result": {
"sig_v": 37,
"sig_r": "08a16c651ffdf9e59c1bd8398d788bc98c86d6c0d7f6bc07977d557b0851c01b",
"sig_s": "1e2adc9ef0b7f17a6385230783349706c0cc0bfef40c45ea5b23c09543b17c28"
}
}
]
}

@ -120,6 +120,25 @@
"sig_r": "07f8c967227c5a190cb90525c3387691a426fe61f8e0503274280724060ea95c",
"sig_s": "0bf83eaf74e24aa9146b23e06f9edec6e25acb81d3830e8d146b9e7b6923ad1e"
}
},
{
"name": "Ledger Live legacy path",
"parameters": {
"data": "",
"path": "m/44'/60'/0'/0",
"to_address": "0x1d1c328764a41bda0492b66baa30c4a339ff85ef",
"chain_id": 1,
"nonce": "0x0",
"gas_limit": "0x14",
"max_gas_fee": "0x14",
"max_priority_fee": "0x1",
"value": "0xa"
},
"result": {
"sig_v": 1,
"sig_r": "3a5e8fa47bfdb758837643485b2951f6c54894996f124dce6282662289ebcf79",
"sig_s": "5b5b9e0f9af273466cc1e991cb86fadb2abedeb4de150163a8dbf348422b5fe2"
}
}
]
}

@ -0,0 +1 @@
Support Ledger Live legacy derivation path "m/44'/coin_type'/0'/account"

@ -337,6 +337,9 @@ PATTERN_BIP44_PUBKEY = "m/44'/coin_type'/account'/*"
# SEP-0005 for non-UTXO-based currencies, defined by Stellar:
# https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0005.md
PATTERN_SEP5 = "m/44'/coin_type'/account'"
# SEP-0005 Ledger Live legacy path
# https://github.com/trezor/trezor-firmware/issues/1749
PATTERN_SEP5_LEDGER_LIVE_LEGACY = "m/44'/coin_type'/0'/account"
async def validate_path(

@ -38,8 +38,13 @@ if TYPE_CHECKING:
# account-based, rather than UTXO-based. Unfortunately, lot of Ethereum
# tools (MEW, Metamask) do not use such scheme and set a = 0 and then
# iterate the address index i. For compatibility, we allow this scheme as well.
# Also to support "Ledger Live" legacy paths we allow 44'/60'/0'/a paths.
PATTERNS_ADDRESS = (paths.PATTERN_BIP44, paths.PATTERN_SEP5)
PATTERNS_ADDRESS = (
paths.PATTERN_BIP44,
paths.PATTERN_SEP5,
paths.PATTERN_SEP5_LEDGER_LIVE_LEGACY,
)
def _schemas_from_address_n(

@ -26,6 +26,8 @@ class TestEthereumKeychain(unittest.TestCase):
valid_addresses = (
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED],
[44 | HARDENED, slip44_id | HARDENED, 19 | HARDENED],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 0],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 99],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 0, 0],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 0, 999],
)
@ -38,7 +40,8 @@ class TestEthereumKeychain(unittest.TestCase):
[44 | HARDENED, 0 | HARDENED, 0 | HARDENED],
[42 | HARDENED, slip44_id | HARDENED, 0 | HARDENED],
[0 | HARDENED, slip44_id | HARDENED, 0 | HARDENED],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 0],
[44 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0],
[44 | HARDENED, slip44_id | HARDENED, 1 | HARDENED, 0],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 0 | HARDENED, 0],
[44 | HARDENED, slip44_id | HARDENED, 0 | HARDENED, 0 | HARDENED, 0 | HARDENED],
)
@ -61,6 +64,11 @@ class TestEthereumKeychain(unittest.TestCase):
keychain = self.from_address_n([44 | HARDENED, 60 | HARDENED, 0 | HARDENED])
self._check_keychain(keychain, 60)
def test_from_address_n_ledger_live_legacy(self):
# valid keychain m/44'/60'/0'/0
keychain = self.from_address_n([44 | HARDENED, 60 | HARDENED, 0 | HARDENED, 0])
self._check_keychain(keychain, 60)
def test_from_address_n_unknown(self):
# try Bitcoin slip44 id m/44'/0'/0'
schemas = tuple(_schemas_from_address_n(PATTERNS_ADDRESS, [44 | HARDENED, 0 | HARDENED, 0 | HARDENED]))
@ -84,6 +92,16 @@ class TestEthereumKeychain(unittest.TestCase):
),
)
)
await_result( # Ethereum from Ledger Live legacy path
handler(
wire.DUMMY_CONTEXT,
EthereumGetAddress(
address_n=[44 | HARDENED, 60 | HARDENED, 0 | HARDENED, 0]
),
)
)
await_result(
handler(
wire.DUMMY_CONTEXT,
@ -124,6 +142,18 @@ class TestEthereumKeychain(unittest.TestCase):
)
)
await_result( # Ethereum from Ledger Live legacy path
handler_chain_id(
wire.DUMMY_CONTEXT,
EthereumSignTx(
address_n=[44 | HARDENED, 60 | HARDENED, 0 | HARDENED, 0],
chain_id=1,
gas_price=b"",
gas_limit=b"",
),
)
)
await_result( # Ethereum Classic
handler_chain_id(
wire.DUMMY_CONTEXT,

@ -19,6 +19,7 @@ algorithm, extended to work on other curves.
| -------- | --------- | ------------------ | ----------- | -------------- |
| Bitcoin | secp256k1 | `44'/c'/a'/y/i` | yes | [1](#Bitcoin) |
| Ethereum | secp256k1 | `44'/c'/0'/0/a` | yes | [2](#Ethereum) |
| Ethereum | secp256k1 | `44'/c'/0'/a` | yes | [2](#Ethereum) |
| Ripple | secp256k1 | `44'/144'/a'/0/0` | | [3](#Ripple) |
| EOS | secp256k1 | `44'/194'/a'/0/0` | | [3](#Ripple) |
| Binance | secp256k1 | `44'/714'/a'/0/0` | | [3](#Ripple) |
@ -68,7 +69,8 @@ sends `44'/60'/0'/0` for getPublicKey.
2. <a name="Ethereum"></a> We believe this should be `44'/c'/a'`, because Ethereum is
account-based, rather than UTXO-based. Unfortunately, lot of Ethereum tools (MEW,
Metamask) do not use such scheme and set `a = 0` and then iterate the address index
`i`. Therefore for compatibility reasons we use the same scheme.
`i`. Therefore for compatibility reasons we use the same scheme. Also to support
"Ledger Live" legacy paths we allow `44'/60'/0'/a` paths.
3. <a name="Ripple"></a> Similar to Ethereum this should be `44'/c'/a'`. But for
compatibility with other HW vendors we use `44'/c'/a'/0/0`.

@ -0,0 +1 @@
Support Ledger Live legacy derivation path "m/44'/coin_type'/0'/account"

@ -1077,6 +1077,15 @@ bool ethereum_path_check(uint32_t address_n_count, const uint32_t *address_n,
return valid;
}
if (address_n_count == 4) {
// Also to support "Ledger Live" legacy paths
// https://github.com/trezor/trezor-firmware/issues/1749
// m/44'/coin_type'/0'/account
valid = valid && (address_n[2] == (PATH_HARDENED | 0));
valid = valid && (address_n[3] <= PATH_MAX_ACCOUNT);
return valid;
}
// We believe Ethereum should use the SEP-0005 scheme for everything, because
// it is account-based, rather than UTXO-based. Unfortunately, a lot of
// Ethereum tools (MEW, Metamask) do not use such scheme and set account = 0

@ -335,11 +335,13 @@
"T1_bitcoin-test_zcash.py::test_version_group_id_missing": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1_ethereum-test_getaddress.py::test_getaddress[ETC]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getaddress.py::test_getaddress[GoChain]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getaddress.py::test_getaddress[Ledger Live legacy path]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getaddress.py::test_getaddress[Wanchain]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getaddress.py::test_getaddress[parameters0-result0]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getaddress.py::test_getaddress[parameters1-result1]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getaddress.py::test_getaddress[parameters2-result2]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getaddress.py::test_getaddress[parameters3-result3]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getpublickey.py::test_ethereum_getpublickey[Ledger Live legacy path]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getpublickey.py::test_ethereum_getpublickey[parameters0-result0]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getpublickey.py::test_ethereum_getpublickey[parameters1-result1]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
"T1_ethereum-test_getpublickey.py::test_ethereum_getpublickey[parameters2-result2]": "37e446e17465ce9823c34c9162d94e4ad3c84faa86bae7966c753be5c5fd77a2",
@ -375,6 +377,8 @@
"T1_ethereum-test_signtx.py::test_signtx[Auxilium]": "05d5ac917c9d3032fb4658b7f502748b412ffe435fc788c62733e00b948da5f7",
"T1_ethereum-test_signtx.py::test_signtx[ETC]": "05b7842c03625104ae3459a55097bc96e878eca465bf69ea2691407868e5dd4b",
"T1_ethereum-test_signtx.py::test_signtx[Ethereum]": "90feef1fdcd162209a948c127df638c09bee0444fee40f2d30dbff21658d83ef",
"T1_ethereum-test_signtx.py::test_signtx[Ledger Live legacy path0]": "37aa64fbab44b89757833df6ee78e302c97fe24c4cb74175f1843f635cb2dbec",
"T1_ethereum-test_signtx.py::test_signtx[Ledger Live legacy path1]": "90feef1fdcd162209a948c127df638c09bee0444fee40f2d30dbff21658d83ef",
"T1_ethereum-test_signtx.py::test_signtx[Palm]": "9d3f44b5d6089919a9e50c3344e5210bdf4a127db33d91b4eeaf93403acb5578",
"T1_ethereum-test_signtx.py::test_signtx[Pirl]": "159bb61626157fa11dbd7775d09b95af8b1269432ed83a649a04e700d944aa02",
"T1_ethereum-test_signtx.py::test_signtx[Rinkeby]": "796c65c23c551065757a839dcac90a67841a12e4a6e520bb2f97e575d3b09368",
@ -392,6 +396,7 @@
"T1_ethereum-test_signtx.py::test_signtx[nodata_2_bigvalue]": "538f7be885ce6ea3a6dc842ef10797fa45184d7737f6f179c42d36fe92fadd45",
"T1_ethereum-test_signtx.py::test_signtx[unknown_erc20_token]": "df41efe4c5336fc188d3f754d2fe0b830588e57eaa32c98607b0bc4057851fcc",
"T1_ethereum-test_signtx.py::test_signtx[wanchain]": "37aa64fbab44b89757833df6ee78e302c97fe24c4cb74175f1843f635cb2dbec",
"T1_ethereum-test_signtx.py::test_signtx_eip1559[Ledger Live legacy path]": "5b008a081b4ef9e7b47c9d0c1fc4bb24d729d77841193694232bd2da4a386515",
"T1_ethereum-test_signtx.py::test_signtx_eip1559[data_1]": "171ffadf61a2520274bedf6a8543127f23a8948c2689e034f996e170289b1822",
"T1_ethereum-test_signtx.py::test_signtx_eip1559[data_2_bigdata]": "28d2a0d397b4e9865ca8286cc1a3669c3a7d34bb31b430662354bf3ec69d1cc5",
"T1_ethereum-test_signtx.py::test_signtx_eip1559[known_erc20]": "b8e205a40711e377f2185cec6e085fa2f6a4d5bbc6a03d9cf2758058b6c1e17b",
@ -1328,11 +1333,13 @@
"TT_eos-test_signtx.py::test_eos_signtx_vote_proxy": "383e507f499274b5470e43631a74284d05163971cab80d0bf510807eaf5119fe",
"TT_ethereum-test_getaddress.py::test_getaddress[ETC]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getaddress.py::test_getaddress[GoChain]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getaddress.py::test_getaddress[Ledger Live legacy path]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getaddress.py::test_getaddress[Wanchain]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getaddress.py::test_getaddress[parameters0-result0]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getaddress.py::test_getaddress[parameters1-result1]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getaddress.py::test_getaddress[parameters2-result2]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getaddress.py::test_getaddress[parameters3-result3]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getpublickey.py::test_ethereum_getpublickey[Ledger Live legacy path]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getpublickey.py::test_ethereum_getpublickey[parameters0-result0]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getpublickey.py::test_ethereum_getpublickey[parameters1-result1]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
"TT_ethereum-test_getpublickey.py::test_ethereum_getpublickey[parameters2-result2]": "95a40f79fa7ffceb10e89b513c203b4937112b8d764cdba3c1df538355dc129c",
@ -1370,6 +1377,8 @@
"TT_ethereum-test_signtx.py::test_signtx[Auxilium]": "8210914d4e083ac53f0feec2bbbda3dffc2dc7ea13aad9ac1ba42cfdfd3a7fb1",
"TT_ethereum-test_signtx.py::test_signtx[ETC]": "1be13e9824e3a299514e008dd223caf250e7a0729a707ec90b2f7bc4417b7c93",
"TT_ethereum-test_signtx.py::test_signtx[Ethereum]": "42027bef9ba5f823920c3781732217b22b363422a5cc48b0d9f4e737e29be3a5",
"TT_ethereum-test_signtx.py::test_signtx[Ledger Live legacy path0]": "e16fc853b349cf9dbf1aa23e44365290580b1db602e6194e5c44b1cde454c8c5",
"TT_ethereum-test_signtx.py::test_signtx[Ledger Live legacy path1]": "42027bef9ba5f823920c3781732217b22b363422a5cc48b0d9f4e737e29be3a5",
"TT_ethereum-test_signtx.py::test_signtx[Palm]": "ec2e670528d40506adf44c3e4d60f3a233b41a05d2ec9d055a394cce6a2dca67",
"TT_ethereum-test_signtx.py::test_signtx[Pirl]": "7c3f0d3adb00139fa9e161c180d5a051198347f1dc0ce910ca73c776d119f767",
"TT_ethereum-test_signtx.py::test_signtx[Rinkeby]": "986aee9ca42dc1d319a2f3f5d5dc6b205c80c8314e70fb39efb4afea66625299",
@ -1390,6 +1399,7 @@
"TT_ethereum-test_signtx.py::test_signtx_data_pagination[input_flow_go_back]": "f03b50df7f4a161078fa903c44f37272961b70358d4014d30a12888e1fd2caf1",
"TT_ethereum-test_signtx.py::test_signtx_data_pagination[input_flow_scroll_down]": "189a52153189b8dac3ec2854f0d93f5207619b6a7499085e51596d8dc580e184",
"TT_ethereum-test_signtx.py::test_signtx_data_pagination[input_flow_skip]": "f03b50df7f4a161078fa903c44f37272961b70358d4014d30a12888e1fd2caf1",
"TT_ethereum-test_signtx.py::test_signtx_eip1559[Ledger Live legacy path]": "14f159d0b62d7697bcbcd56ed41b8affa86ffea1d7aa6f2d0c3ce168fb990431",
"TT_ethereum-test_signtx.py::test_signtx_eip1559[data_1]": "2cc563c2ca3e4144ccabdb4700bbc62b7895840cfb06012a955e8b4a46462eef",
"TT_ethereum-test_signtx.py::test_signtx_eip1559[data_2_bigdata]": "8ed9263431c350c501d2a69d699818d8208f334b19f5231b8dce5912f5b5d611",
"TT_ethereum-test_signtx.py::test_signtx_eip1559[known_erc20]": "063198d50c0a9d5cb6b40d546f2f0af9cf1cb2e27ef385a18b46228f79ab5ff9",

Loading…
Cancel
Save