From 722c465f9589523763c8b6a6544ee16dd6a0d958 Mon Sep 17 00:00:00 2001 From: qlrddev Date: Wed, 10 Dec 2025 12:21:21 -0300 Subject: [PATCH 1/2] feat: add signet and regtest networks This commit add the options `signet` and `regtest` to `DefaultWallet` at `src/krux/krux_settings` as well `Signet` and `Regtest` names to `src/krux/wallet_settings`. To be in coherent with the change, it was added the options string to menubar as well added theme colors for it. It's worth to note that regtest and signet could be added to test vectors as well used to create new vector for integration tests. --- src/krux/key.py | 10 +++++-- src/krux/krux_settings.py | 6 +++- src/krux/pages/__init__.py | 28 +++++++++++++++---- src/krux/pages/settings_page.py | 10 +++++-- src/krux/pages/utils.py | 13 +++++++-- src/krux/pages/wallet_settings.py | 19 +++++++++---- src/krux/settings.py | 2 ++ src/krux/themes.py | 29 +++++++++++++++++-- src/krux/wallet.py | 46 ++++++++++++++++++++----------- 9 files changed, 125 insertions(+), 38 deletions(-) diff --git a/src/krux/key.py b/src/krux/key.py index 7559f4e0f..448fd7be9 100644 --- a/src/krux/key.py +++ b/src/krux/key.py @@ -360,7 +360,13 @@ def get_policy_type_name(policy_type): def get_network_name(network): - """Returns human-readable name for a network object (Mainnet or Testnet)""" + """Returns human-readable name for a network object""" if not network: return None - return "Mainnet" if network == NETWORKS["main"] else "Testnet" + if network == NETWORKS["test"]: + return "Testnet" + if network == NETWORKS["signet"]: + return "Signet" + if network == NETWORKS["regtest"]: + return "Regtest" + return "Mainnet" diff --git a/src/krux/krux_settings.py b/src/krux/krux_settings.py index c78150501..8edf43f86 100644 --- a/src/krux/krux_settings.py +++ b/src/krux/krux_settings.py @@ -30,6 +30,8 @@ FLASH_PATH, MAIN_TXT, TEST_TXT, + SIGNET_TXT, + REGTEST_TXT, ) from .key import ( @@ -138,7 +140,9 @@ class DefaultWallet(SettingsNamespace): """Bitcoin-specific settings""" namespace = "settings.wallet" - network = CategorySetting("network", MAIN_TXT, [MAIN_TXT, TEST_TXT]) + network = CategorySetting( + "network", MAIN_TXT, [MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT] + ) script_type = CategorySetting( "script_type", "Native Segwit - 84", SINGLESIG_SCRIPT_NAMES ) diff --git a/src/krux/pages/__init__.py b/src/krux/pages/__init__.py index 5e954c093..307606a4b 100644 --- a/src/krux/pages/__init__.py +++ b/src/krux/pages/__init__.py @@ -21,11 +21,16 @@ # THE SOFTWARE. import gc import time +from krux.settings import REGTEST_TXT, SIGNET_TXT, TEST_TXT import lcd import _thread from ..context import Context from .keypads import Keypad -from ..themes import theme, WHITE, GREEN, DARKGREY +from ..themes import ( + theme, + WHITE, + DARKGREY, +) from ..input import ( BUTTON_ENTER, BUTTON_PAGE, @@ -904,21 +909,32 @@ def draw_wallet_indicator(self): def draw_network_indicator(self): """Draws test at top if testnet is enabled""" - if self.ctx.is_logged_in() and self.ctx.wallet.key.network["name"] == "Testnet": + if self.ctx.is_logged_in(): + netname = self.ctx.wallet.key.network["name"].lower() + + if netname == TEST_TXT: + color = theme.test_color + elif netname == SIGNET_TXT: + color = theme.signet_color + elif netname == REGTEST_TXT: + color = theme.regtest_color + else: + color = theme.main_color + if not kboard.is_m5stickv: self.ctx.display.draw_string( 12, STATUS_BAR_HEIGHT - FONT_HEIGHT - 1, - "Test", - GREEN, + netname, + color, theme.info_bg_color, ) else: self.ctx.display.draw_string( 6, STATUS_BAR_HEIGHT - FONT_HEIGHT - 1, - "T", - GREEN, + netname[0] if netname != "" else "", + color, theme.info_bg_color, ) diff --git a/src/krux/pages/settings_page.py b/src/krux/pages/settings_page.py index 16045a923..f74b5590c 100644 --- a/src/krux/pages/settings_page.py +++ b/src/krux/pages/settings_page.py @@ -23,7 +23,7 @@ import lcd from ..display import FONT_HEIGHT, FONT_WIDTH, PORTRAIT -from ..themes import theme, MAIN_TXT_COLOR, TEST_TXT_COLOR +from ..themes import theme from ..settings import ( CategorySetting, NumberSetting, @@ -36,6 +36,8 @@ Settings, MAIN_TXT, TEST_TXT, + SIGNET_TXT, + REGTEST_TXT, TouchSettings, ButtonsSettings, t, @@ -63,8 +65,10 @@ DISPLAY_TEST_TIME = 5000 # 5 seconds CATEGORY_SETTING_COLOR_DICT = { - MAIN_TXT: MAIN_TXT_COLOR, - TEST_TXT: TEST_TXT_COLOR, + MAIN_TXT: theme.main_color, + TEST_TXT: theme.test_color, + SIGNET_TXT: theme.signet_color, + REGTEST_TXT: theme.regtest_color, True: theme.go_color, False: theme.no_esc_color, } diff --git a/src/krux/pages/utils.py b/src/krux/pages/utils.py index 73447e80a..0e96b7e40 100644 --- a/src/krux/pages/utils.py +++ b/src/krux/pages/utils.py @@ -189,6 +189,15 @@ def generate_wallet_info(self, network, policy, script, derivation, is_login=Fal @staticmethod def get_network_color(network_name: str): """Returns the correct theme color to write network""" - from ..themes import TEST_TXT_COLOR, MAIN_TXT_COLOR + from ..themes import theme + + if network_name == "Testnet": + return theme.test_color + + if network_name == "Signet": + return theme.signet_color + + if network_name == "Regtest": + return theme.regtest_color - return MAIN_TXT_COLOR if network_name == "Mainnet" else TEST_TXT_COLOR + return theme.main_color diff --git a/src/krux/pages/wallet_settings.py b/src/krux/pages/wallet_settings.py index 459d6f3b3..c6a8de669 100644 --- a/src/krux/pages/wallet_settings.py +++ b/src/krux/pages/wallet_settings.py @@ -47,10 +47,7 @@ NAME_MINISCRIPT, ) -from ..settings import ( - MAIN_TXT, - TEST_TXT, -) +from ..settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT from ..key import P2PKH, P2SH, P2SH_P2WPKH, P2SH_P2WSH, P2WPKH, P2WSH, P2TR @@ -306,13 +303,25 @@ def _coin_type(self): [ ("Mainnet", lambda: None), ("Testnet", lambda: None), + ("Signet", lambda: None), + ("Regtest", lambda: None), ], disable_statusbar=True, ) index, _ = submenu.run_loop() if index == submenu.back_index: return None - return NETWORKS[TEST_TXT] if index == 1 else NETWORKS[MAIN_TXT] + + if index == 1: + return NETWORKS[TEST_TXT] + + if index == 2: + return NETWORKS[SIGNET_TXT] + + if index == 3: + return NETWORKS[REGTEST_TXT] + + return NETWORKS[MAIN_TXT] def _policy_type(self): """Policy type selection menu""" diff --git a/src/krux/settings.py b/src/krux/settings.py index 51ff5dd7e..3c227f43f 100644 --- a/src/krux/settings.py +++ b/src/krux/settings.py @@ -42,6 +42,8 @@ # Network settings MAIN_TXT = "main" TEST_TXT = "test" +SIGNET_TXT = "signet" +REGTEST_TXT = "regtest" THIN_SPACE = " " # "\u2009" ELLIPSIS = "…" # "\u2026" diff --git a/src/krux/themes.py b/src/krux/themes.py index cc1086761..4ad1d0daa 100644 --- a/src/krux/themes.py +++ b/src/krux/themes.py @@ -34,6 +34,7 @@ WHITE = 0xFFFF GREEN = 0xE007 DARKGREEN = 0x8005 +LIGHT_GREEN = 0x1005 RED = 0x00F8 LIGHT_PINK = 0xDFFC PINK = 0x1FF8 @@ -45,9 +46,6 @@ LIGHTBLUE = 0xBD0E CYAN = 0xFF07 -MAIN_TXT_COLOR = ORANGE -TEST_TXT_COLOR = GREEN - THEMES = { ThemeSettings.DARK_THEME_NAME: { @@ -62,6 +60,10 @@ "toggle": CYAN, "error": RED, "highlight": LIGHTBLUE, + "main": WHITE, + "test": GREEN, + "signet": LIGHT_PINK, + "regtest": LIGHT_GREEN, }, ThemeSettings.LIGHT_THEME_NAME: { "background": WHITE, @@ -75,6 +77,10 @@ "toggle": BLUE, "error": RED, "highlight": BLUE, + "main": BLACK, + "test": DARKGREEN, + "signet": PURPLE, + "regtest": BLUE, }, ThemeSettings.ORANGE_THEME_NAME: { "background": BLACK, @@ -88,6 +94,10 @@ "toggle": CYAN, "error": RED, "highlight": YELLOW, + "main": ORANGE, + "test": GREEN, + "signet": LIGHT_PINK, + "regtest": LIGHT_GREEN, }, ThemeSettings.PINK_THEME_NAME: { "background": BLACK, @@ -101,6 +111,10 @@ "toggle": CYAN, "error": RED, "highlight": PINK, + "main": LIGHT_PINK, + "test": GREEN, + "signet": PINK, + "regtest": LIGHT_GREEN, }, ThemeSettings.GREEN_THEME_NAME: { "background": BLACK, @@ -114,10 +128,15 @@ "toggle": CYAN, "error": RED, "highlight": CYAN, + "main": GREEN, + "test": CYAN, + "signet": LIGHT_PINK, + "regtest": LIGHT_GREEN, }, } +# pylint: disable=too-many-instance-attributes class Theme: """Themes handler""" @@ -141,6 +160,10 @@ def update(self): self.toggle_color = THEMES[current_theme]["toggle"] self.error_color = THEMES[current_theme]["error"] self.highlight_color = THEMES[current_theme]["highlight"] + self.main_color = THEMES[current_theme]["main"] + self.test_color = THEMES[current_theme]["test"] + self.signet_color = THEMES[current_theme]["signet"] + self.regtest_color = THEMES[current_theme]["regtest"] theme = Theme() diff --git a/src/krux/wallet.py b/src/krux/wallet.py index 732c3235d..0289bc969 100644 --- a/src/krux/wallet.py +++ b/src/krux/wallet.py @@ -22,6 +22,7 @@ from embit.descriptor.descriptor import Descriptor from embit.descriptor.arguments import Key from embit.networks import NETWORKS +from .settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT from .krux_settings import t from .qr import FORMAT_BBQR, FORMAT_NONE from .key import ( @@ -54,6 +55,20 @@ def __init__(self, key): self.policy = None self.persisted = False self._network = None + + if ( + key is not None + and key.network is not None + and key.network + in ( + NETWORKS[MAIN_TXT], + NETWORKS[TEST_TXT], + NETWORKS[SIGNET_TXT], + NETWORKS[REGTEST_TXT], + ) + ): + self._network = key.network + if self.key and self.key.policy_type == TYPE_SINGLESIG: if self.key.script_type == P2PKH: self.descriptor = Descriptor.from_string( @@ -90,20 +105,19 @@ def get_scriptpubkey_type(self): def which_network(self): """Returns network (NETWORKS.keys()) using current wallet key, else from descriptor""" - if self._network is None: - if self.key: - self._network = [ - k for k, v in NETWORKS.items() if v == self.key.network - ][0] - else: - # use first key; restrict networks to "main" and "test", version to pubkeys - version = self.descriptor.keys[0].key.version - for em_network in ("main", "test"): - for em_vertype in ("xpub", "ypub", "zpub", "Ypub", "Zpub"): - if version == NETWORKS[em_network][em_vertype]: - self._network = em_network - break - return self._network + if self._network is not None: + for net in (TEST_TXT, SIGNET_TXT, REGTEST_TXT): + if self._network == NETWORKS[net]: + return net + + if self.descriptor: + version = self.descriptor.keys[0].key.version + for net in (TEST_TXT, SIGNET_TXT, REGTEST_TXT): + for ver in ("xpub", "ypub", "zpub", "Ypub", "Zpub"): + if version == NETWORKS[net][ver]: + return net + + return MAIN_TXT def is_multisig(self): """Returns a boolean indicating whether or not the wallet is multisig""" @@ -163,7 +177,7 @@ def _determine_descriptor_policy(self, descriptor): def _determine_descriptor_network(self, descriptor): """Returns the network from descriptor's xpub version""" version = descriptor.keys[0].key.version - for em_network in ("main", "test"): + for em_network in (MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT): for em_vertype in ("xpub", "ypub", "zpub", "Ypub", "Zpub"): if version == NETWORKS[em_network][em_vertype]: return NETWORKS[em_network] @@ -513,7 +527,7 @@ def parse_address(address_data): if not isinstance(sc, Script): try: - address_to_scriptpubkey(addr) + sc = address_to_scriptpubkey(addr) except: raise ValueError("invalid address") From fb7ce3c029ffa91e89eb02061c2d397d223072e1 Mon Sep 17 00:00:00 2001 From: qlrddev Date: Sun, 28 Dec 2025 17:31:41 -0300 Subject: [PATCH 2/2] test: add change of networks This commit add tests on `Customize` menu button and change `Networks` from `Mainnet` to `Testnet/Signet/Regtest`. --- tests/pages/__init__.py | 3 +- tests/pages/home_pages/test_addresses.py | 79 +++++++-- tests/pages/home_pages/test_home.py | 202 ++++++++++++++++++--- tests/pages/test_login.py | 4 +- tests/shared_mocks.py | 2 +- tests/test_wallet.py | 217 ++++++++++++++++++++--- 6 files changed, 440 insertions(+), 67 deletions(-) diff --git a/tests/pages/__init__.py b/tests/pages/__init__.py index f9543cf09..b13ac00e1 100644 --- a/tests/pages/__init__.py +++ b/tests/pages/__init__.py @@ -4,11 +4,10 @@ def create_ctx(mocker, btn_seq, wallet=None, printer=None, touch_seq=None): """Helper to create mocked context obj""" from krux.krux_settings import Settings, THERMAL_ADAFRUIT_TXT - from krux.context import Context HASHED_IMAGE_BYTES = b"3\x0fr\x7fKY\x15\t\x83\xaab\x92\x0f&\x820\xb4\x14\x87\x19\xee\x95F\x9c\x8f\x0c\xbdo\xbc\x1d\xcbT" - ctx: Context = mock_context(mocker) + ctx = mock_context(mocker) ctx.power_manager.battery_charge_remaining.return_value = 1 ctx.input.wait_for_button = mocker.MagicMock(side_effect=btn_seq) ctx.input.wait_for_fastnav_button = ctx.input.wait_for_button diff --git a/tests/pages/home_pages/test_addresses.py b/tests/pages/home_pages/test_addresses.py index ed52758e1..b6c9f475d 100644 --- a/tests/pages/home_pages/test_addresses.py +++ b/tests/pages/home_pages/test_addresses.py @@ -247,6 +247,36 @@ def test_scan_address(mocker, m5stickv, tdata): [], False, ), + # 21 - Single-sig testnet, not loaded, owned address, search successful + ( + tdata.SINGLESIG_ACTION_KEY_TEST_P2WPKH, + None, + False, + "tb1q4fhuxhrmz26kkuxxwataqw323cs2l3mgerz6kp", + True, + [BUTTON_ENTER, BUTTON_ENTER, BUTTON_ENTER], + True, + ), + # 22 - Single-sig signet, not loaded, owned address, search successful + ( + tdata.SINGLESIG_ACTION_KEY_SIGNET_P2WPKH, + None, + False, + "tb1q4fhuxhrmz26kkuxxwataqw323cs2l3mgerz6kp", + True, + [BUTTON_ENTER, BUTTON_ENTER, BUTTON_ENTER], + True, + ), + # 23 - Single-sig regtest, not loaded, owned address, search successful + ( + tdata.SINGLESIG_ACTION_KEY_REGTEST_P2WPKH, + None, + False, + "bcrt1q4fhuxhrmz26kkuxxwataqw323cs2l3mgm2mhpg", + True, + [BUTTON_ENTER, BUTTON_ENTER, BUTTON_ENTER], + True, + ), ] case_num = 0 for case in cases: @@ -564,23 +594,44 @@ def test_export_address(mocker, m5stickv, tdata): BUTTON_PAGE, # move to back BUTTON_ENTER, # exit screen ] - wallet = Wallet(tdata.SINGLESIG_ACTION_KEY_TEST_P2WPKH) - ctx = create_ctx(mocker, btn_seq, wallet, None) - addresses_ui = Addresses(ctx) - # SDHandler - mocker.patch( - "os.listdir", - return_value=["somefile", "otherfile"], - ) + cases = [ + ( + tdata.SINGLESIG_ACTION_KEY, + "49,bc1qlrznrpahpuxmtsattnexgka5p27xrzlsftl8jf\n", + ), + ( + tdata.SINGLESIG_ACTION_KEY_TEST_P2WPKH, + "49,tb1q8e9cxkrvg2d3q72wp9t33739pcnygrdyp2dm38\n", + ), + ( + tdata.SINGLESIG_ACTION_KEY_SIGNET_P2WPKH, + "49,tb1q8e9cxkrvg2d3q72wp9t33739pcnygrdyp2dm38\n", + ), + ( + tdata.SINGLESIG_ACTION_KEY_REGTEST_P2WPKH, + "49,bcrt1q8e9cxkrvg2d3q72wp9t33739pcnygrdyrr5kxw\n", + ), + ] - mocker.spy(addresses_ui, "export_address") + for i, case in enumerate(cases): + print(f"Case {i}:") + wallet = Wallet(case[0]) + ctx = create_ctx(mocker, btn_seq, wallet, None) + addresses_ui = Addresses(ctx) - m = mock_open() - with patch("builtins.open", m): - addresses_ui.addresses_menu() - m().write.assert_any_call("0,tb1q4fhuxhrmz26kkuxxwataqw323cs2l3mgerz6kp\n") - m().write.assert_any_call("49,tb1q8e9cxkrvg2d3q72wp9t33739pcnygrdyp2dm38\n") + # SDHandler + mocker.patch( + "os.listdir", + return_value=["somefile", "otherfile"], + ) + + mocker.spy(addresses_ui, "export_address") + + m = mock_open() + with patch("builtins.open", m): + addresses_ui.addresses_menu() + m().write.assert_any_call(case[1]) addresses_ui.export_address.assert_called() diff --git a/tests/pages/home_pages/test_home.py b/tests/pages/home_pages/test_home.py index 2ee00eaaf..3194dc7da 100644 --- a/tests/pages/home_pages/test_home.py +++ b/tests/pages/home_pages/test_home.py @@ -64,11 +64,17 @@ def tdata(mocker): ) SINGLESIG_ACTION_KEY = Key(ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["main"]) SINGLESIG_ACTION_KEY_TEST = Key( - ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["test"], script_type=P2TR + ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["test"], script_type=P2WPKH ) SINGLESIG_ACTION_KEY_TEST_P2WPKH = Key( ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["test"], script_type=P2WPKH ) + SINGLESIG_ACTION_KEY_SIGNET_P2WPKH = Key( + ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["signet"], script_type=P2WPKH + ) + SINGLESIG_ACTION_KEY_REGTEST_P2WPKH = Key( + ACTION_MNEMONIC, TYPE_SINGLESIG, NETWORKS["regtest"], script_type=P2WPKH + ) LEGACY1_KEY = Key( TEST_12_WORD_MNEMONIC, TYPE_SINGLESIG, @@ -176,6 +182,8 @@ def tdata(mocker): "SINGLESIG_ACTION_KEY", "SINGLESIG_ACTION_KEY_TEST", "SINGLESIG_ACTION_KEY_TEST_P2WPKH", + "SINGLESIG_ACTION_KEY_SIGNET_P2WPKH", + "SINGLESIG_ACTION_KEY_REGTEST_P2WPKH", "LEGACY1_KEY", "LEGACY1_MULTISIG_KEY", "NESTEDSW1_KEY", @@ -231,6 +239,8 @@ def tdata(mocker): SINGLESIG_ACTION_KEY, SINGLESIG_ACTION_KEY_TEST, SINGLESIG_ACTION_KEY_TEST_P2WPKH, + SINGLESIG_ACTION_KEY_SIGNET_P2WPKH, + SINGLESIG_ACTION_KEY_REGTEST_P2WPKH, LEGACY1_KEY, LEGACY1_MULTISIG_KEY, NESTEDSW1_KEY, @@ -414,25 +424,111 @@ def test_change_passphrase_menu(mocker, amigo, tdata): def test_cancel_customize_wallet_menu(mocker, amigo, tdata): from krux.pages.home_pages.home import Home from krux.wallet import Wallet - from krux.input import BUTTON_ENTER, BUTTON_PAGE_PREV + from krux.input import BUTTON_ENTER, BUTTON_PAGE_PREV, BUTTON_PAGE - BTN_SEQUENCE = [ - BUTTON_PAGE_PREV, # Move to No - BUTTON_ENTER, # Press No + cases = [ + # Case 0: Start with a mainnet wallet and cancel customization + ( + [ + BUTTON_PAGE_PREV, # Move to No + BUTTON_ENTER, # Press No + ], + "Mainnet", + "Mainnet", + ), + # Case 1: Start with a mainnet wallet, start the customization and cancel it + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Mainnet", + ), + # Case 2: Start with a mainnet wallet, start the customization and cancel it + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Mainnet", + ), + # Case 3: Start with a mainnet wallet, start the customization and select mainnet + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_ENTER, # Press Mainnet + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Mainnet", + ), + # Case 4: Start with a mainnet wallet, start the customization and select testnet + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE, # Move to Testnet + BUTTON_ENTER, # Press Testnet + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Testnet", + ), + # Case 5: Start with a mainnet wallet, start the customization and select signet + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE, # Move to Testnet + BUTTON_PAGE, # Move to Signet + BUTTON_ENTER, # Press Signet + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Signet", + ), + # Case 6: Start with a mainnet wallet, start the customization and select regtest + ( + [ + BUTTON_ENTER, # Choose Yes + BUTTON_ENTER, # Choose network + BUTTON_PAGE, # Move to Testnet + BUTTON_PAGE, # Move to Signet + BUTTON_PAGE, # Move to Regtest + BUTTON_ENTER, # Press Regtest + BUTTON_PAGE_PREV, # Move to Back + BUTTON_ENTER, # Press Back + ], + "Mainnet", + "Regtest", + ), ] - # Wallet before customization - wallet = Wallet(tdata.SINGLESIG_SIGNING_KEY) - assert wallet.key.network["name"] == "Mainnet" + for n, case in enumerate(cases): + print(f"Case {n}: {case}") - ctx = create_ctx(mocker, BTN_SEQUENCE, wallet=wallet) - home = Home(ctx) - home.customize() + # Wallet before customization + wallet = Wallet(tdata.SINGLESIG_SIGNING_KEY) + assert wallet.key.network["name"] == case[1] - # Wallet after cancel customization - # should remain the same as before - assert ctx.input.wait_for_button.call_count == len(BTN_SEQUENCE) - assert ctx.wallet.key.network["name"] == "Mainnet" + ctx = create_ctx(mocker, case[0], wallet=wallet) + home = Home(ctx) + home.customize() + + # Wallet after customization + assert ctx.input.wait_for_button.call_count == len(case[0]) + assert ctx.wallet.key.network["name"] == case[2] def test_customize_wallet_menu(mocker, amigo, tdata): @@ -440,23 +536,71 @@ def test_customize_wallet_menu(mocker, amigo, tdata): from krux.wallet import Wallet from krux.input import BUTTON_ENTER, BUTTON_PAGE, BUTTON_PAGE_PREV - BTN_SEQUENCE = [ - BUTTON_ENTER, # Agree to customize - BUTTON_ENTER, # Enter "Network" - BUTTON_PAGE, # Change to "Testnet" - BUTTON_ENTER, # Confirm "Testnet" - BUTTON_PAGE_PREV, # Go to Back - BUTTON_ENTER, # Exit + cases = [ + # Mainet -> Mainnet + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + BUTTON_ENTER, # Confirm "Mainnet" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Mainnet", + ), + # Mainet -> Testnet + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + BUTTON_PAGE, # Change to "Testnet" + BUTTON_ENTER, # Confirm "Testnet" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Testnet", + ), + # Mainet -> Signet + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + *([BUTTON_PAGE] * 2), # Change to "Signet" + BUTTON_ENTER, # Confirm "Signet" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Signet", + ), + # Mainet -> Regtest + ( + [ + BUTTON_ENTER, # Agree to customize + BUTTON_ENTER, # Enter "Network" + *([BUTTON_PAGE] * 3), # Change to "Regtest" + BUTTON_ENTER, # Confirm "Regtest" + BUTTON_PAGE_PREV, # Go to Back + BUTTON_ENTER, # Exit + ], + "Mainnet", + "Regtest", + ), ] - wallet = Wallet(tdata.SINGLESIG_SIGNING_KEY) - ctx = create_ctx(mocker, BTN_SEQUENCE, wallet=wallet) - assert ctx.wallet.key.network["name"] == "Mainnet" - home = Home(ctx) - home.customize() + for n, case in enumerate(cases): + print(f"Case {n}: {case}") + wallet = Wallet(tdata.SINGLESIG_12_WORD_KEY) + ctx = create_ctx(mocker, case[0], wallet=wallet) + assert ctx.wallet.key.network["name"] == case[1] + home = Home(ctx) + home.customize() - assert ctx.input.wait_for_button.call_count == len(BTN_SEQUENCE) - assert ctx.wallet.key.network["name"] == "Testnet" + assert ctx.wallet.key.network["name"] == case[2] + assert ctx.input.wait_for_button.call_count == len(case[0]) + n += 1 def test_cancel_load_bip85_menu(mocker, amigo, tdata): diff --git a/tests/pages/test_login.py b/tests/pages/test_login.py index 2023fbab3..8a120f395 100644 --- a/tests/pages/test_login.py +++ b/tests/pages/test_login.py @@ -13,7 +13,9 @@ def mock_retro_compatibility(mocker, amigo): class MockDefaultWallet: namespace = "settings.wallet" - network = CategorySetting("network", "main", ["main", "test"]) + network = CategorySetting( + "network", "main", ["main", "test", "signet", "regtest"] + ) script_type = CategorySetting("script_type", "test", ["test"]) multisig = CategorySetting("multisig", True, [True, False]) diff --git a/tests/shared_mocks.py b/tests/shared_mocks.py index ee6a7097f..c6498660e 100644 --- a/tests/shared_mocks.py +++ b/tests/shared_mocks.py @@ -791,7 +791,7 @@ def board_embed_fire(): ) -def mock_context(mocker): +def mock_context(mocker: MagicMock): import board if board.config["type"] == "m5stickv": diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 19a445d36..1c8bd3955 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -1,3 +1,4 @@ +from re import S import pytest from ur.ur_decoder import URDecoder @@ -9,6 +10,7 @@ def tdata(mocker): from ur.ur import UR from krux.bbqr import encode_bbqr from embit.networks import NETWORKS + from krux.settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT from krux.key import ( Key, P2PKH, @@ -28,15 +30,48 @@ def tdata(mocker): TEST_MNEMONIC2 = "brush badge sing still venue panther kitchen please help panel bundle excess sign couch stove increase human once effort candy goat top tiny major" TEST_MNEMONIC3 = "range fatigue into stadium endless kitchen royal present rally welcome scatter twice" - SINGLESIG_KEY = Key( - TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"] - ) # default account=0, script=P2WPKH - LEGACY1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"], "", 1, P2PKH) + SINGLESIG_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT]) + SINGLESIG_KEY_TESTNET = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT]) + SINGLESIG_KEY_SIGNET = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT]) + SINGLESIG_KEY_REGTEST = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT]) + # default account=0, script=P2WPKH + + LEGACY1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT], "", 1, P2PKH) + LEGACY1_KEY_TESTNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT], "", 1, P2PKH + ) + LEGACY1_KEY_SIGNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT], "", 1, P2PKH + ) + LEGACY1_KEY_REGTEST = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT], "", 1, P2PKH + ) + # default account=1, script=P2PKH + NESTEDSW1_KEY = Key( - TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"], "", 1, P2SH_P2WPKH + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT], "", 1, P2SH_P2WPKH ) - TAPROOT1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS["main"], "", 1, P2TR) + NESTEDSW1_KEY_TESTNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT], "", 1, P2SH_P2WPKH + ) + NESTEDSW1_KEY_SIGNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT], "", 1, P2SH_P2WPKH + ) + NESTEDSW1_KEY_REGTEST = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT], "", 1, P2SH_P2WPKH + ) + # default account=1, script=P2WSH_P2WPKH + TAPROOT1_KEY = Key(TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[MAIN_TXT], "", 1, P2TR) + TAPROOT1_KEY_TESTNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[TEST_TXT], "", 1, P2TR + ) + TAPROOT1_KEY_SIGNET = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[SIGNET_TXT], "", 1, P2TR + ) + TAPROOT1_KEY_REGTEST = Key( + TEST_MNEMONIC1, TYPE_SINGLESIG, NETWORKS[REGTEST_TXT], "", 1, P2TR + ) # p2sh wallet without cosigner indexes MULTISIG_LEGACY_NO_COSIGNER_1 = Key( TEST_MNEMONIC1, TYPE_MULTISIG, NETWORKS["main"], "", None, P2SH @@ -93,6 +128,7 @@ def tdata(mocker): # MULTISIG_NATIVE_SW_3 [d3a80c8b/48h/0h/0h/2h]xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv KRUX_LEGACY1_DESCRIPTOR = "pkh([55f8fc5d/44h/0h/1h]xpub6C1dUaopHgps6X75i61KaJEDm4qkFeqjhm4by1ebvpgAsKDaEhGLgNX88bvuWPm4rSVe7GsYvQLDAXXLnxNsAbd3VwRihgM3q1kEkixBAbE)" + KRUX_LEGACY1_DESCRIPTOR_TESTNET = "pkh([55f8fc5d/44h/1h/1h]tpubDCxMZswvJHvfY7cXBB1DusWNpcc6MV2Dv6eTFAYfY4xPewEbzCUUhfRiYaga2u71R3dbVx4PijdjpNRdxxvvjcZq3aMYcDASTZzYK44fegG/<0;1>/*)" KRUX_LEGACY1_XPUB = "[55f8fc5d/44h/0h/1h]xpub6C1dUaopHgps6X75i61KaJEDm4qkFeqjhm4by1ebvpgAsKDaEhGLgNX88bvuWPm4rSVe7GsYvQLDAXXLnxNsAbd3VwRihgM3q1kEkixBAbE" # This is a non-extended pubkey (the first-one) derived from KRUX_LEGACY1_DESCRIPTOR @@ -101,6 +137,7 @@ def tdata(mocker): ) KRUX_NESTEDSW1_DESCRIPTOR = "sh(wpkh([55f8fc5d/49h/0h/1h]xpub6Ca1JGnSFNZ7jjwturEn944t8B9kBgiTKtmr3maTbryEyDyYY9xycVSQaFxeUPjbHyX7MUvLUbdoDVK7XZ7Fib9We4BQRRk8bZjW2UPRjHV))" + KRUX_NESTEDSW1_DESCRIPTOR_TESTNET = "sh(wpkh([55f8fc5d/49h/1h/1h]tpubDDYHYR15Go9atMZsjP6yuGBdL8qJJGHbfbJQBssrGPmaJYaLhoqchx4mn5tLwziyWXyML37NpbF5goGPEcfvtiKR1UJhMk4ArVh28wGmU98/<0;1>/*))" KRUX_NESTEDSW1_XPUB = "[55f8fc5d/49h/0h/1h]xpub6Ca1JGnSFNZ7jjwturEn944t8B9kBgiTKtmr3maTbryEyDyYY9xycVSQaFxeUPjbHyX7MUvLUbdoDVK7XZ7Fib9We4BQRRk8bZjW2UPRjHV" KRUX_NESTEDSW1_YPUB = "[55f8fc5d/49h/0h/1h]ypub6XQGbwTMQ46bb391kD2QM9APJ9JC8JhxF1J4qAULysM82Knmnp8YEZ6YbTvEUJPWhcdv6xWtwFzM6mvgFFXGWpq7WPsq1LZcsHo9R97uuE4" KRUX_NESTEDSW1_YPUB_DESCRIPTOR = "sh(wpkh(" + KRUX_NESTEDSW1_YPUB + "))" @@ -109,8 +146,8 @@ def tdata(mocker): KRUX_NATIVESW1_XPUB = "[55f8fc5d/84h/0h/1h]xpub6DPMTPxGMqdu43FvwYdC6eHCPJWckCkx1rLJ1HEG7259GyWQD5P17WB2oowP9SpQdC8ogrmXfwfoazvf6Te8svtxWh4UTwTqyRdG5G54FxW" KRUX_NATIVESW1_ZPUB = "[55f8fc5d/84h/0h/1h]zpub6s3t4jJ6fCirkdeAcGCSWpUCjEoWdSjwr5Nja522s2puPB8riPi8MdVJrDrZ9G8FSUNRBoxebGNuMa9nXrUAUQGAFNTKdm6pWskYrMahu1i" KRUX_NATIVESW1_ZPUB_DESCRIPTOR = "wpkh(" + KRUX_NATIVESW1_ZPUB + ")" - KRUX_TAPROOT1_DESCRIPTOR = "tr([55f8fc5d/86h/0h/1h]xpub6CNGwJbVG9sQsJjtwLiemRFAfvDafL8zRthnHWNQbRz1PwAm28T1v5hLmJhFft71oEDCbA3xHemnScW5VWheP1BxXNVnoYboyw6t4wuKu5q)" + KRUX_TAPROOT1_DESCRIPTOR_TESTNET = "tr([55f8fc5d/86h/1h/1h]tpubDD6e1Di1uHy5PizN7knRiWgfiHQCY7iLM1a7N5ie1XXAe6GGjhJTJgZjVA38E4HsUVtFqWU6m2QhtgB5YiRMdV324yRjGoXRuT3yLFsvqiG/<0;1>/*)" KRUX_TAPROOT1_XPUB = "[55f8fc5d/86h/0h/1h]xpub6CNGwJbVG9sQsJjtwLiemRFAfvDafL8zRthnHWNQbRz1PwAm28T1v5hLmJhFft71oEDCbA3xHemnScW5VWheP1BxXNVnoYboyw6t4wuKu5q" SPECTER_SINGLESIG_DESCRIPTOR = "wpkh([55f8fc5d/84h/0h/0h]xpub6DPMTPxGMqdtzMwpqT1dDQaVdyaEppEm2qYSaJ7ANsuES7HkNzrXJst1Ed8D7NAnijUdgSDUFgph1oj5LKKAD5gyxWNhNP2AuDqaKYqzphA/0/*)" @@ -213,7 +250,7 @@ def tdata(mocker): xpub6F2P6Pz5KLPgCc6pTBd2xxCunaSYWc8CdkL28W5z15pJrN3aCYY7mCUAkCMtqrgT2wdhAGgRnJxAkCCUpGKoXKxQ57yffEGmPwtYA3DEXwu d3a80c8b: - xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv + xpub6FKYY6y3oVi7ihSCszFKRSSINGLESIG_KEY_TESTNET eZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv """ BLUEWALLET_MULTISIG_WALLET_DATA_INVALID_KEYS = """ @@ -260,8 +297,8 @@ def tdata(mocker): ) UNAMBIGUOUS_SINGLESIG_DESCRIPTOR = "wpkh([55f8fc5d/84h/0h/0h]xpub6DPMTPxGMqdtzMwpqT1dDQaVdyaEppEm2qYSaJ7ANsuES7HkNzrXJst1Ed8D7NAnijUdgSDUFgph1oj5LKKAD5gyxWNhNP2AuDqaKYqzphA/<0;1>/*)" + UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET = "wpkh([55f8fc5d/84h/1h/0h]tpubDCDuqu5HtBX2aD7wxvnHcj1DgFN1UVgzLkA1Ms4Va4P7TpJ3jDknkPLwWT2SqrKXNNAtJBCPcbJ8Tcpm6nLxgFapCZyhKgqwcEGv1BVpD7s/<0;1>/*)" AMBIGUOUS_SINGLESIG_DESCRIPTOR = "wpkh([55f8fc5d/84h/0h/0h]xpub6DPMTPxGMqdtzMwpqT1dDQaVdyaEppEm2qYSaJ7ANsuES7HkNzrXJst1Ed8D7NAnijUdgSDUFgph1oj5LKKAD5gyxWNhNP2AuDqaKYqzphA)" - UNAMBIGUOUS_MULTISIG_DESCRIPTOR = "wsh(sortedmulti(2,[55f8fc5d/48h/0h/0h/2h]xpub6EKmKYGYc1WY6t9d3d9SksR8keSaPZbFa6tqsGiH4xVxx8d2YyxSX7WG6yXEX3CmG54dPCxaapDw1XsjwCmfoqP7tbsAeqMVfKvqSAu4ndy/<0;1>/*,[3e15470d/48h/0h/0h/2h]xpub6F2P6Pz5KLPgCc6pTBd2xxCunaSYWc8CdkL28W5z15pJrN3aCYY7mCUAkCMtqrgT2wdhAGgRnJxAkCCUpGKoXKxQ57yffEGmPwtYA3DEXwu/<0;1>/*,[d3a80c8b/48h/0h/0h/2h]xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv/<0;1>/*))" AMBIGUOUS_MULTISIG_DESCRIPTOR = "wsh(sortedmulti(2,[55f8fc5d/48h/0h/0h/2h]xpub6EKmKYGYc1WY6t9d3d9SksR8keSaPZbFa6tqsGiH4xVxx8d2YyxSX7WG6yXEX3CmG54dPCxaapDw1XsjwCmfoqP7tbsAeqMVfKvqSAu4ndy,[3e15470d/48h/0h/0h/2h]xpub6F2P6Pz5KLPgCc6pTBd2xxCunaSYWc8CdkL28W5z15pJrN3aCYY7mCUAkCMtqrgT2wdhAGgRnJxAkCCUpGKoXKxQ57yffEGmPwtYA3DEXwu,[d3a80c8b/48h/0h/0h/2h]xpub6FKYY6y3oVi7ihSCszFKRSeZj5SzrfSsUFXhKqjMV4iigrLhxwMX3mrjioNyLTZ5iD3u4wU9S3tyzpJGxhd5geaXoQ68jGz2M6dfh2zJrUv))" @@ -283,9 +320,21 @@ def tdata(mocker): "TEST_MNEMONIC2", "TEST_MNEMONIC3", "SINGLESIG_KEY", + "SINGLESIG_KEY_TESTNET", + "SINGLESIG_KEY_SIGNET", + "SINGLESIG_KEY_REGTEST", "LEGACY1_KEY", + "LEGACY1_KEY_TESTNET", + "LEGACY1_KEY_SIGNET", + "LEGACY1_KEY_REGTEST", "NESTEDSW1_KEY", + "NESTEDSW1_KEY_TESTNET", + "NESTEDSW1_KEY_SIGNET", + "NESTEDSW1_KEY_REGTEST", "TAPROOT1_KEY", + "TAPROOT1_KEY_TESTNET", + "TAPROOT1_KEY_SIGNET", + "TAPROOT1_KEY_REGTEST", "MULTISIG_LEGACY_NO_COSIGNER_1", "MULTISIG_LEGACY_NO_COSIGNER_2", "MULTISIG_LEGACY_NO_COSIGNER_3", @@ -301,9 +350,11 @@ def tdata(mocker): "MINISCRIPT_KEY", "TAP_MINISCRIPT_KEY", "KRUX_LEGACY1_DESCRIPTOR", + "KRUX_LEGACY1_DESCRIPTOR_TESTNET", "KRUX_LEGACY1_XPUB", "KRUX_LEGACY1_RAW_PUBKEY", "KRUX_NESTEDSW1_DESCRIPTOR", + "KRUX_NESTEDSW1_DESCRIPTOR_TESTNET", "KRUX_NESTEDSW1_XPUB", "KRUX_NESTEDSW1_YPUB", "KRUX_NESTEDSW1_YPUB_DESCRIPTOR", @@ -312,6 +363,7 @@ def tdata(mocker): "KRUX_NATIVESW1_ZPUB", "KRUX_NATIVESW1_ZPUB_DESCRIPTOR", "KRUX_TAPROOT1_DESCRIPTOR", + "KRUX_TAPROOT1_DESCRIPTOR_TESTNET", "KRUX_TAPROOT1_XPUB", "SPECTER_SINGLESIG_DESCRIPTOR", "SPECTER_SINGLESIG_WALLET_DATA", @@ -341,6 +393,7 @@ def tdata(mocker): "UR_BYTES_MULTISIG_DESCRIPTOR", "UR_BYTES_MULTISIG_WALLET_DATA", "UNAMBIGUOUS_SINGLESIG_DESCRIPTOR", + "UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET", "AMBIGUOUS_SINGLESIG_DESCRIPTOR", "UNAMBIGUOUS_MULTISIG_DESCRIPTOR", "AMBIGUOUS_MULTISIG_DESCRIPTOR", @@ -358,9 +411,21 @@ def tdata(mocker): TEST_MNEMONIC2, TEST_MNEMONIC3, SINGLESIG_KEY, + SINGLESIG_KEY_TESTNET, + SINGLESIG_KEY_SIGNET, + SINGLESIG_KEY_REGTEST, LEGACY1_KEY, + LEGACY1_KEY_TESTNET, + LEGACY1_KEY_SIGNET, + LEGACY1_KEY_REGTEST, NESTEDSW1_KEY, + NESTEDSW1_KEY_TESTNET, + NESTEDSW1_KEY_SIGNET, + NESTEDSW1_KEY_REGTEST, TAPROOT1_KEY, + TAPROOT1_KEY_TESTNET, + TAPROOT1_KEY_SIGNET, + TAPROOT1_KEY_REGTEST, MULTISIG_LEGACY_NO_COSIGNER_1, MULTISIG_LEGACY_NO_COSIGNER_2, MULTISIG_LEGACY_NO_COSIGNER_3, @@ -376,9 +441,11 @@ def tdata(mocker): MINISCRIPT_KEY, TAP_MINISCRIPT_KEY, KRUX_LEGACY1_DESCRIPTOR, + KRUX_LEGACY1_DESCRIPTOR_TESTNET, KRUX_LEGACY1_XPUB, KRUX_LEGACY1_RAW_PUBKEY, KRUX_NESTEDSW1_DESCRIPTOR, + KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, KRUX_NESTEDSW1_XPUB, KRUX_NESTEDSW1_YPUB, KRUX_NESTEDSW1_YPUB_DESCRIPTOR, @@ -387,6 +454,7 @@ def tdata(mocker): KRUX_NATIVESW1_ZPUB, KRUX_NATIVESW1_ZPUB_DESCRIPTOR, KRUX_TAPROOT1_DESCRIPTOR, + KRUX_TAPROOT1_DESCRIPTOR_TESTNET, KRUX_TAPROOT1_XPUB, SPECTER_SINGLESIG_DESCRIPTOR, SPECTER_SINGLESIG_WALLET_DATA, @@ -416,6 +484,7 @@ def tdata(mocker): UR_BYTES_MULTISIG_DESCRIPTOR, UR_BYTES_MULTISIG_WALLET_DATA, UNAMBIGUOUS_SINGLESIG_DESCRIPTOR, + UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, AMBIGUOUS_SINGLESIG_DESCRIPTOR, UNAMBIGUOUS_MULTISIG_DESCRIPTOR, AMBIGUOUS_MULTISIG_DESCRIPTOR, @@ -432,52 +501,160 @@ def tdata(mocker): def test_init_singlesig(mocker, m5stickv, tdata): from embit.descriptor import Descriptor + from krux.key import get_network_name from krux.wallet import Wallet, to_unambiguous_descriptor + from krux.settings import MAIN_TXT, TEST_TXT, SIGNET_TXT, REGTEST_TXT + from embit.networks import NETWORKS cases = [ - # key, descriptor, label, policy - (None, None, None, None), + # key, descriptor, label, policy, network + # Case 0: All None + (None, None, None, None, None), + # Case 1: Single sig, p2wpkh, mainnet ( tdata.SINGLESIG_KEY, tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR, "Single-sig", {"type": "p2wpkh"}, + NETWORKS[MAIN_TXT], ), + # Case 2: Single sig, p2wpkh, testnet + ( + tdata.SINGLESIG_KEY_TESTNET, + tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2wpkh"}, + NETWORKS[TEST_TXT], + ), + # Case 3: Single sig, p2wpkh, signet + ( + tdata.SINGLESIG_KEY_SIGNET, + tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2wpkh"}, + NETWORKS[SIGNET_TXT], + ), + # Case 4: Single sig, p2wpkh, regtest + ( + tdata.SINGLESIG_KEY_REGTEST, + tdata.UNAMBIGUOUS_SINGLESIG_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2wpkh"}, + NETWORKS[REGTEST_TXT], + ), + # Case 5: Single sig, p2pkh, mainnet ( tdata.LEGACY1_KEY, tdata.KRUX_LEGACY1_DESCRIPTOR, "Single-sig", {"type": "p2pkh"}, + NETWORKS[MAIN_TXT], + ), + # Case 6: Single sig, p2pkh, testnet + ( + tdata.LEGACY1_KEY_TESTNET, + tdata.KRUX_LEGACY1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2pkh"}, + NETWORKS[TEST_TXT], ), + # Case 7: Single sig, p2pkh, signet + ( + tdata.LEGACY1_KEY_SIGNET, + tdata.KRUX_LEGACY1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2pkh"}, + NETWORKS[SIGNET_TXT], + ), + # Case 8: Single sig, p2pkh, regtest + ( + tdata.LEGACY1_KEY_REGTEST, + tdata.KRUX_LEGACY1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2pkh"}, + NETWORKS[REGTEST_TXT], + ), + # Case 9: Single sig, p2sh-p2wpkh, mainnet ( tdata.NESTEDSW1_KEY, tdata.KRUX_NESTEDSW1_DESCRIPTOR, "Single-sig", {"type": "p2sh-p2wpkh"}, + NETWORKS[MAIN_TXT], + ), + # Case 10: Single sig, p2sh-p2wpkh, testnet + ( + tdata.NESTEDSW1_KEY_TESTNET, + tdata.KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2sh-p2wpkh"}, + NETWORKS[TEST_TXT], + ), + # Case 11: Single sig, p2sh-p2wpkh, signet + ( + tdata.NESTEDSW1_KEY_SIGNET, + tdata.KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2sh-p2wpkh"}, + NETWORKS[SIGNET_TXT], + ), + # Case 12: Single sig, p2sh-p2wpkh, regtest + ( + tdata.NESTEDSW1_KEY_REGTEST, + tdata.KRUX_NESTEDSW1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2sh-p2wpkh"}, + NETWORKS[REGTEST_TXT], ), + # Case 13: Single sig, p2tr, mainnet ( tdata.TAPROOT1_KEY, tdata.KRUX_TAPROOT1_DESCRIPTOR, "Single-sig", {"type": "p2tr"}, + NETWORKS[MAIN_TXT], + ), + # Case 14: Single sig, p2tr, testnet + ( + tdata.TAPROOT1_KEY_TESTNET, + tdata.KRUX_TAPROOT1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2tr"}, + NETWORKS[TEST_TXT], + ), + # Case 15: Single sig, p2tr, sigtnet + ( + tdata.TAPROOT1_KEY_SIGNET, + tdata.KRUX_TAPROOT1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2tr"}, + NETWORKS[SIGNET_TXT], + ), + # Case 16: Single sig, p2tr, regtest + ( + tdata.TAPROOT1_KEY_REGTEST, + tdata.KRUX_TAPROOT1_DESCRIPTOR_TESTNET, + "Single-sig", + {"type": "p2tr"}, + NETWORKS[REGTEST_TXT], ), ] - for _case in cases: + for i, _case in enumerate(cases): + print(f"Case {i}") wallet = Wallet(_case[0]) - assert isinstance(wallet, Wallet) if wallet.descriptor: # don't fail simply because of a difference between ambiguous and unambiguous - try: - assert wallet.descriptor.to_string() == _case[1] - except AssertionError: - test_descr = to_unambiguous_descriptor( - Descriptor.from_string(_case[1]) - ).to_string() - assert wallet.descriptor.to_string() == test_descr + test_descr = to_unambiguous_descriptor( + Descriptor.from_string(_case[1]) + ).to_string() + assert wallet.descriptor.to_string() == test_descr assert wallet.label == _case[2] assert wallet.policy == _case[3] + if wallet.key: + assert get_network_name(wallet.key.network) == _case[4]["name"] + def test_init_multisig(mocker, m5stickv, tdata): from krux.wallet import Wallet