From 096b4902bdc676c30781785bc815b6a876599482 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Mon, 21 Aug 2023 18:40:17 -0500 Subject: [PATCH 1/6] derive correct signmessage address --- src/seedsigner/helpers/embit_utils.py | 15 +++++++++++++-- src/seedsigner/views/seed_views.py | 2 +- tests/test_embit_utils.py | 13 ++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/seedsigner/helpers/embit_utils.py b/src/seedsigner/helpers/embit_utils.py index c33153e8..b32d5d0a 100644 --- a/src/seedsigner/helpers/embit_utils.py +++ b/src/seedsigner/helpers/embit_utils.py @@ -142,12 +142,23 @@ def parse_derivation_path(derivation_path: str) -> dict: } details = dict() + details["wallet_derivation_path"] = "/".join(sections[:-2]) details["script_type"] = lookups["script_types"].get(sections[1]) if not details["script_type"]: details["script_type"] = SettingsConstants.CUSTOM_DERIVATION details["network"] = lookups["networks"].get(sections[2]) - details["is_change"] = sections[-2] == "1" - details["index"] = int(sections[-1]) + + # Check if there's a standard change path + if sections[-2] in ["0", "1"]: + details["is_change"] = sections[-2] == "1" + else: + details["is_change"] = None + + # Check if there's a standard address index + if sections[-1].isdigit(): + details["index"] = int(sections[-1]) + else: + details["index"] = None details["clean_match"] = True for k, v in details.items(): diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py index 6de06db8..a02e7401 100644 --- a/src/seedsigner/views/seed_views.py +++ b/src/seedsigner/views/seed_views.py @@ -2005,7 +2005,7 @@ class SeedSignMessageConfirmAddressView(View): self.controller.sign_message_data = None return - xpub = seed.get_xpub(wallet_path=self.derivation_path, network=addr_format["network"]) + xpub = seed.get_xpub(wallet_path=addr_format["wallet_derivation_path"], network=addr_format["network"]) embit_network = embit_utils.get_embit_network_name(addr_format["network"]) self.address = embit_utils.get_single_sig_address(xpub=xpub, script_type=addr_format["script_type"], index=addr_format["index"], is_change=addr_format["is_change"], embit_network=embit_network) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index 3f22b93d..c3158d79 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -369,8 +369,11 @@ def test_parse_derivation_path(): (SC.TESTNET, SC.CUSTOM_DERIVATION, True): "m/45'/1'/0'/1/5", (SC.REGTEST, SC.CUSTOM_DERIVATION, True): "m/45'/1'/0'/1/5", - # CRAZY custom derivation path - (None, SC.CUSTOM_DERIVATION, False): "m/879345978543'/908327034508534983495'/9085098430894380959043'/0/5", + # CRAZY custom derivation paths + (None, SC.CUSTOM_DERIVATION, False, 5): "m/879345978543'/908327034508534983495'/9085098430894380959043'/0/5", + (None, SC.CUSTOM_DERIVATION, None, 5): "m/9'/78/5", + (None, SC.CUSTOM_DERIVATION, None, 5): "m/9'/78'/5", + (None, SC.CUSTOM_DERIVATION, None, None): "m/9'/78'/5'", } for expected_result, derivation_path in vectors_args.items(): @@ -389,4 +392,8 @@ def test_parse_derivation_path(): assert(actual_result["script_type"] == expected_result[1]) assert(actual_result["is_change"] == expected_result[2]) - assert(actual_result["index"] == int(derivation_path.split("/")[-1])) + + if len(expected_result) == 4: + assert(actual_result["index"] == expected_result[3]) + else: + assert(actual_result["index"] == int(derivation_path.split("/")[-1])) From bd7b25ed98aefb3a488f76cdd5331c5d3e301440 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Mon, 21 Aug 2023 18:46:16 -0500 Subject: [PATCH 2/6] additional safety around "wallet_derivation_path" --- src/seedsigner/helpers/embit_utils.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/seedsigner/helpers/embit_utils.py b/src/seedsigner/helpers/embit_utils.py index b32d5d0a..da8f827a 100644 --- a/src/seedsigner/helpers/embit_utils.py +++ b/src/seedsigner/helpers/embit_utils.py @@ -142,7 +142,6 @@ def parse_derivation_path(derivation_path: str) -> dict: } details = dict() - details["wallet_derivation_path"] = "/".join(sections[:-2]) details["script_type"] = lookups["script_types"].get(sections[1]) if not details["script_type"]: details["script_type"] = SettingsConstants.CUSTOM_DERIVATION @@ -153,13 +152,19 @@ def parse_derivation_path(derivation_path: str) -> dict: details["is_change"] = sections[-2] == "1" else: details["is_change"] = None - + # Check if there's a standard address index if sections[-1].isdigit(): details["index"] = int(sections[-1]) else: details["index"] = None + if details["is_change"] is not None and details["index"] is not None: + # standard change and addr index; safe to truncate to the wallet level + details["wallet_derivation_path"] = "/".join(sections[:-2]) + else: + details["wallet_derivation_path"] = None + details["clean_match"] = True for k, v in details.items(): if v is None: From ef80fd3913489f211d66998de532b3c8ce48a9b4 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Mon, 21 Aug 2023 18:48:25 -0500 Subject: [PATCH 3/6] Update test_embit_utils.py --- tests/test_embit_utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index c3158d79..3e85662c 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -371,9 +371,12 @@ def test_parse_derivation_path(): # CRAZY custom derivation paths (None, SC.CUSTOM_DERIVATION, False, 5): "m/879345978543'/908327034508534983495'/9085098430894380959043'/0/5", + + # non-standard change and/or index (None, SC.CUSTOM_DERIVATION, None, 5): "m/9'/78/5", (None, SC.CUSTOM_DERIVATION, None, 5): "m/9'/78'/5", (None, SC.CUSTOM_DERIVATION, None, None): "m/9'/78'/5'", + (None, SC.CUSTOM_DERIVATION, False, None): "m/9'/0/5'", } for expected_result, derivation_path in vectors_args.items(): From d2e0d96781ea857c3d7c7d949fc7f4024ded2c23 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Mon, 21 Aug 2023 18:53:39 -0500 Subject: [PATCH 4/6] Update seed_views.py --- src/seedsigner/views/seed_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py index a02e7401..7056b978 100644 --- a/src/seedsigner/views/seed_views.py +++ b/src/seedsigner/views/seed_views.py @@ -1988,7 +1988,7 @@ class SeedSignMessageConfirmAddressView(View): # calculate the actual receive address seed = self.controller.storage.seeds[self.seed_num] addr_format = embit_utils.parse_derivation_path(self.derivation_path) - if not addr_format["clean_match"]: + if not addr_format["clean_match"] or addr_format["script_type"] == SettingsConstants.CUSTOM_DERIVATION: raise Exception("Signing messages for custom derivation paths not supported") if addr_format["network"] != SettingsConstants.MAINNET: From 928c4ab19a7534d9588f97cb4719ef8a76c8a2c5 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Tue, 22 Aug 2023 07:29:50 -0500 Subject: [PATCH 5/6] Minor test case update --- tests/test_embit_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_embit_utils.py b/tests/test_embit_utils.py index 3e85662c..1b7bfaa8 100644 --- a/tests/test_embit_utils.py +++ b/tests/test_embit_utils.py @@ -361,7 +361,7 @@ def test_parse_derivation_path(): (SC.TESTNET, SC.TAPROOT, True): "m/86'/1'/0'/1/5", (SC.REGTEST, SC.TAPROOT, True): "m/86'/1'/0'/1/5", - # Try a typical custom derivation path (Unchained Capital) + # Try a typical custom derivation path (Unchained vault keys) (SC.MAINNET, SC.CUSTOM_DERIVATION, False): "m/45'/0'/0'/0/5", (SC.TESTNET, SC.CUSTOM_DERIVATION, False): "m/45'/1'/0'/0/5", (SC.REGTEST, SC.CUSTOM_DERIVATION, False): "m/45'/1'/0'/0/5", @@ -370,7 +370,7 @@ def test_parse_derivation_path(): (SC.REGTEST, SC.CUSTOM_DERIVATION, True): "m/45'/1'/0'/1/5", # CRAZY custom derivation paths - (None, SC.CUSTOM_DERIVATION, False, 5): "m/879345978543'/908327034508534983495'/9085098430894380959043'/0/5", + (None, SC.CUSTOM_DERIVATION, False, 5): "m/123'/9083270/9083270/9083270/9083270/0/5", # non-standard change and/or index (None, SC.CUSTOM_DERIVATION, None, 5): "m/9'/78/5", From 8bb4bd1b6fee5d63f462552d397695d998d7fa34 Mon Sep 17 00:00:00 2001 From: Nick Klockenga Date: Tue, 22 Aug 2023 21:44:13 -0400 Subject: [PATCH 6/6] Resolve conflicts in seed_views.py --- src/seedsigner/views/seed_views.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/seedsigner/views/seed_views.py b/src/seedsigner/views/seed_views.py index 46f5238b..15c3fde9 100644 --- a/src/seedsigner/views/seed_views.py +++ b/src/seedsigner/views/seed_views.py @@ -1997,15 +1997,17 @@ class SeedSignMessageConfirmAddressView(View): def __init__(self): super().__init__() data = self.controller.sign_message_data - seed = self.controller.storage.seeds[data.get("seed_num")] + seed_num = data.get("seed_num") self.derivation_path = data.get("derivation_path") - addr_format = data.get("addr_format") - if self.seed_num is None or not self.derivation_path: + if seed_num is None or not self.derivation_path: raise Exception("Routing error: sign_message_data hasn't been set") + seed = self.controller.storage.seeds[seed_num] + addr_format = data.get("addr_format") + # calculate the actual receive address - seed = self.controller.storage.seeds[self.seed_num] + seed = self.controller.storage.seeds[seed_num] addr_format = embit_utils.parse_derivation_path(self.derivation_path) if not addr_format["clean_match"] or addr_format["script_type"] == SettingsConstants.CUSTOM_DERIVATION: raise Exception("Signing messages for custom derivation paths not supported")