From 9e23ba88649d0e668aaaf7e3c8ef9bce156b765b Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 27 Jan 2023 22:15:27 +0100 Subject: [PATCH] feat(trezorctl): Support SLIP-25 in get-descriptor --- python/.changelog.d/2541.added | 1 + python/src/trezorlib/cli/btc.py | 90 +++++++++++++------ python/src/trezorlib/tools.py | 17 ++++ .../device_tests/bitcoin/test_descriptors.py | 26 +++++- tests/ui_tests/fixtures.json | 64 ++++++------- 5 files changed, 138 insertions(+), 60 deletions(-) create mode 100644 python/.changelog.d/2541.added diff --git a/python/.changelog.d/2541.added b/python/.changelog.d/2541.added new file mode 100644 index 0000000000..b52351ab35 --- /dev/null +++ b/python/.changelog.d/2541.added @@ -0,0 +1 @@ +Support SLIP-25 in get-descriptor. diff --git a/python/src/trezorlib/cli/btc.py b/python/src/trezorlib/cli/btc.py index 9e0df3c244..e3ddf48113 100644 --- a/python/src/trezorlib/cli/btc.py +++ b/python/src/trezorlib/cli/btc.py @@ -27,6 +27,13 @@ from . import ChoiceType, with_client if TYPE_CHECKING: from ..client import TrezorClient +PURPOSE_BIP44 = 44 +PURPOSE_BIP48 = 48 +PURPOSE_BIP49 = 49 +PURPOSE_BIP84 = 84 +PURPOSE_BIP86 = 86 +PURPOSE_SLIP25 = 10025 + INPUT_SCRIPTS = { "address": messages.InputScriptType.SPENDADDRESS, "segwit": messages.InputScriptType.SPENDWITNESS, @@ -49,12 +56,27 @@ OUTPUT_SCRIPTS = { "tr": messages.OutputScriptType.PAYTOTAPROOT, } -BIP_PURPOSE_TO_SCRIPT_TYPE = { - tools.H_(44): messages.InputScriptType.SPENDADDRESS, - tools.H_(49): messages.InputScriptType.SPENDP2SHWITNESS, - tools.H_(84): messages.InputScriptType.SPENDWITNESS, - tools.H_(86): messages.InputScriptType.SPENDTAPROOT, - tools.H_(10025): messages.InputScriptType.SPENDTAPROOT, +BIP_PURPOSE_TO_DEFAULT_SCRIPT_TYPE = { + PURPOSE_BIP44: messages.InputScriptType.SPENDADDRESS, + PURPOSE_BIP49: messages.InputScriptType.SPENDP2SHWITNESS, + PURPOSE_BIP84: messages.InputScriptType.SPENDWITNESS, + PURPOSE_BIP86: messages.InputScriptType.SPENDTAPROOT, + PURPOSE_SLIP25: messages.InputScriptType.SPENDTAPROOT, +} + +SCRIPT_TYPE_TO_BIP_PURPOSES = { + messages.InputScriptType.SPENDADDRESS: (PURPOSE_BIP44,), + messages.InputScriptType.SPENDP2SHWITNESS: (PURPOSE_BIP49,), + messages.InputScriptType.SPENDWITNESS: (PURPOSE_BIP84,), + messages.InputScriptType.SPENDTAPROOT: (PURPOSE_BIP86, PURPOSE_SLIP25), +} + +ACCOUNT_TYPE_TO_BIP_PURPOSE = { + "bip44": PURPOSE_BIP44, + "bip49": PURPOSE_BIP49, + "bip84": PURPOSE_BIP84, + "bip86": PURPOSE_BIP86, + "slip25": PURPOSE_SLIP25, } BIP48_SCRIPT_TYPES = { @@ -100,14 +122,14 @@ def xpub_deserialize(xpubstr: str) -> Tuple[str, messages.HDNodeType]: def guess_script_type_from_path(address_n: List[int]) -> messages.InputScriptType: - if len(address_n) < 1: + if len(address_n) < 1 or not tools.is_hardened(address_n[0]): return messages.InputScriptType.SPENDADDRESS - purpose = address_n[0] - if purpose in BIP_PURPOSE_TO_SCRIPT_TYPE: - return BIP_PURPOSE_TO_SCRIPT_TYPE[purpose] + purpose = tools.unharden(address_n[0]) + if purpose in BIP_PURPOSE_TO_DEFAULT_SCRIPT_TYPE: + return BIP_PURPOSE_TO_DEFAULT_SCRIPT_TYPE[purpose] - if purpose == tools.H_(48) and len(address_n) >= 4: + if purpose == PURPOSE_BIP48 and len(address_n) >= 4: script_type_field = address_n[3] if script_type_field in BIP48_SCRIPT_TYPES: return BIP48_SCRIPT_TYPES[script_type_field] @@ -254,34 +276,47 @@ def _append_descriptor_checksum(desc: str) -> str: def _get_descriptor( client: "TrezorClient", coin: Optional[str], - account: str, - script_type: messages.InputScriptType, + account: int, + purpose: Optional[int], + script_type: Optional[messages.InputScriptType], show_display: bool, ) -> str: - coin = coin or DEFAULT_COIN + if purpose is None: + if script_type is None: + script_type = messages.InputScriptType.SPENDADDRESS + purpose = SCRIPT_TYPE_TO_BIP_PURPOSES[script_type][0] + elif script_type is None: + script_type = BIP_PURPOSE_TO_DEFAULT_SCRIPT_TYPE[purpose] + else: + if purpose not in SCRIPT_TYPE_TO_BIP_PURPOSES[script_type]: + raise ValueError("Invalid script type for account type") + if script_type == messages.InputScriptType.SPENDADDRESS: - acc_type = 44 fmt = "pkh({})" elif script_type == messages.InputScriptType.SPENDP2SHWITNESS: - acc_type = 49 fmt = "sh(wpkh({}))" elif script_type == messages.InputScriptType.SPENDWITNESS: - acc_type = 84 fmt = "wpkh({})" elif script_type == messages.InputScriptType.SPENDTAPROOT: - acc_type = 86 fmt = "tr({})" else: - raise ValueError("Unsupported account type") + raise ValueError("Unsupported script type") - if coin is None or coin == "Bitcoin": + coin = coin or DEFAULT_COIN + if coin == "Bitcoin": coin_type = 0 elif coin == "Testnet" or coin == "Regtest": coin_type = 1 else: raise ValueError("Unsupported coin") - path = f"m/{acc_type}'/{coin_type}'/{account}'" + path = f"m/{purpose}'/{coin_type}'/{account}'" + if purpose == PURPOSE_SLIP25: + if script_type == messages.InputScriptType.SPENDTAPROOT: + path += "/1'" + else: + raise ValueError("Unsupported SLIP25 script type") + n = tools.parse_path(path) pub = btc.get_public_node( client, @@ -290,6 +325,7 @@ def _get_descriptor( coin_name=coin, script_type=script_type, ignore_xpub_magic=True, + unlock_path=get_unlock_path(n), ) fingerprint = pub.root_fingerprint if pub.root_fingerprint is not None else 0 @@ -302,19 +338,23 @@ def _get_descriptor( @click.option( "-n", "--account", required=True, type=int, help="account index (0 = first account)" ) -@click.option("-t", "--script-type", type=ChoiceType(INPUT_SCRIPTS), default="address") +@click.option("-a", "--account-type", type=ChoiceType(ACCOUNT_TYPE_TO_BIP_PURPOSE)) +@click.option("-t", "--script-type", type=ChoiceType(INPUT_SCRIPTS)) @click.option("-d", "--show-display", is_flag=True) @with_client def get_descriptor( client: "TrezorClient", coin: Optional[str], - account: str, - script_type: messages.InputScriptType, + account: int, + account_type: Optional[int], + script_type: Optional[messages.InputScriptType], show_display: bool, ) -> str: """Get descriptor of given account.""" try: - return _get_descriptor(client, coin, account, script_type, show_display) + return _get_descriptor( + client, coin, account, account_type, script_type, show_display + ) except ValueError as e: raise click.ClickException(str(e)) diff --git a/python/src/trezorlib/tools.py b/python/src/trezorlib/tools.py index d33b4e50a6..9e3d901435 100644 --- a/python/src/trezorlib/tools.py +++ b/python/src/trezorlib/tools.py @@ -60,6 +60,23 @@ def H_(x: int) -> int: return x | HARDENED_FLAG +def is_hardened(x: int) -> bool: + """ + Determines if a number in a BIP44 path is hardened. + """ + return x & HARDENED_FLAG != 0 + + +def unharden(x: int) -> int: + """ + Unhardens a number in a BIP44 path. + """ + if not is_hardened(x): + raise ValueError("Unhardened path component") + + return x ^ HARDENED_FLAG + + def btc_hash(data: bytes) -> bytes: """ Double-SHA256 hash as used in BTC diff --git a/tests/device_tests/bitcoin/test_descriptors.py b/tests/device_tests/bitcoin/test_descriptors.py index fb6ebd0b62..6c3fb097b7 100644 --- a/tests/device_tests/bitcoin/test_descriptors.py +++ b/tests/device_tests/bitcoin/test_descriptors.py @@ -24,103 +24,123 @@ VECTORS_DESCRIPTORS = ( # coin, account, script_type, descriptors ( "Bitcoin", 0, + 44, messages.InputScriptType.SPENDADDRESS, "pkh([5c9e228d/44'/0'/0']xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy/<0;1>/*)#t3pfpx6p", ), ( "Bitcoin", 1, + 44, messages.InputScriptType.SPENDADDRESS, "pkh([5c9e228d/44'/0'/1']xpub6BiVtCpG9fQQ1EW99bMSYwySbPWvzTFRQZCFgTmV3samLSZAYU7C3f4Je9vkNh7h1GAWi5Fn93BwoGBy9EAXbWTTgTnVKAbthHpxM1fXVRL/<0;1>/*)#nxtyyv6d", ), ( "Testnet", 0, + 44, messages.InputScriptType.SPENDADDRESS, "pkh([5c9e228d/44'/1'/0']tpubDDKn3FtHc74CaRrRbi1WFdJNaaenZkDWqq9NsEhcafnDZ4VuKeuLG2aKHm5SuwuLgAhRkkfHqcCxpnVNSrs5kJYZXwa6Ud431VnevzzzK3U/<0;1>/*)#jlq3k5tw", ), ( "Testnet", 1, + 44, messages.InputScriptType.SPENDADDRESS, "pkh([5c9e228d/44'/1'/1']tpubDDKn3FtHc74CcBfxJ3zdSNnRacuggmGwv3KEZLJP2LAuqc3HhsQR5ZAVudcQzezzXs7T6QrDtoJJYvgyDUJ9vgWx3Y7Et4Ats1Q25U1LXvU/<0;1>/*)#4uctv92u", ), ( "Bitcoin", 0, + 49, messages.InputScriptType.SPENDP2SHWITNESS, "sh(wpkh([5c9e228d/49'/0'/0']xpub6CVKsQYXc9awxgV1tWbG4foDvdcnieK2JkbpPEBKB5WwAPKBZ1mstLbKVB4ov7QzxzjaxNK6EfmNY5Jsk2cG26EVcEkycGW4tchT2dyUhrx/<0;1>/*))#a49xle58", ), ( "Bitcoin", 1, + 49, messages.InputScriptType.SPENDP2SHWITNESS, "sh(wpkh([5c9e228d/49'/0'/1']xpub6CVKsQYXc9ax22ig3KAZMRiJL1xT9Me1sFX3t34mnVVzr6FkciU74qk7AqBkePQ2sM9pKeWp88KfPT2qcVQ19ykqGHMDioJhwywGuJ96Xt8/<0;1>/*))#udj76d60", ), ( "Testnet", 0, + 49, messages.InputScriptType.SPENDP2SHWITNESS, "sh(wpkh([5c9e228d/49'/1'/0']tpubDCHRnuvE95JrpEVTUmr36sK3K9ADf3s3aztpXzL8coBeCTE8cHV8PjxS6SjWJM3GfPn798gyEa3dRPgjoUDSuNfuC9xz4PHznwKEk2XL7X1/<0;1>/*))#egxlxhl0", ), ( "Testnet", 1, + 49, messages.InputScriptType.SPENDP2SHWITNESS, "sh(wpkh([5c9e228d/49'/1'/1']tpubDCHRnuvE95Jrs9NkLaZwKNdoHBSoCRge6wKunXyxnspvLpx3aZbJcScTnTdsEqT6uFfWdMvBmLs3jhnkBiE7ob3xVQPV8ngDPYAMs93X9xv/<0;1>/*))#wdv0egg7", ), ( "Bitcoin", 0, + 84, messages.InputScriptType.SPENDWITNESS, "wpkh([5c9e228d/84'/0'/0']xpub6DDUPHpUo4pcy43iJeZjbSVWGav1SMMmuWdMHiGtkK8rhKmfbomtkwW6GKs1GGAKehT6QRocrmda3WWxXawpjmwaUHfFRXuKrXSapdckEYF/<0;1>/*)#tdqj4vr6", ), ( "Bitcoin", 1, + 84, messages.InputScriptType.SPENDWITNESS, "wpkh([5c9e228d/84'/0'/1']xpub6DDUPHpUo4pd1hyVtRaknvZvCgdPdEDMKx3bB5UFcx73pEHRDVK4rwEZUgeUbVuYWGMNLvuBHp5WeyPevN2Gv7m9FnLHQE6XaKNRPZcYcHH/<0;1>/*)#7953frdx", ), ( "Testnet", 0, + 84, messages.InputScriptType.SPENDWITNESS, "wpkh([5c9e228d/84'/1'/0']tpubDCZB6sR48s4T5Cr8qHUYSZEFCQMMHRg8AoVKVmvcAP5bRw7ArDKeoNwKAJujV3xCPkBvXH5ejSgbgyN6kREmF7sMd41NdbuHa8n1DZNxSMg/<0;1>/*)#egs8kz3g", ), ( "Testnet", 1, + 84, messages.InputScriptType.SPENDWITNESS, "wpkh([5c9e228d/84'/1'/1']tpubDCZB6sR48s4T6xoXqaYxScvf23kmQvg5QpyFkYnDBjsmviKHLSG9s6cp593Exg87tuMjXXMWDvBRXnJtzppcQf8Z8HdJP1rothfxm4qnPXo/<0;1>/*)#skg78rzf", ), ( "Bitcoin", 0, + 86, messages.InputScriptType.SPENDTAPROOT, "tr([5c9e228d/86'/0'/0']xpub6Bw885JisRbcKmowfBvMmCxaFHodKn1VpmRmctmJJoM8D4DzyP4qJv8ZdD9V9r3SSGjmK2KJEDnvLH6f1Q4HrobEvnCeKydNvf1eir3RHZk/<0;1>/*)#4swej4wz", ), ( "Bitcoin", 1, + 86, messages.InputScriptType.SPENDTAPROOT, "tr([5c9e228d/86'/0'/1']xpub6Bw885JisRbcLp1379q64fdNPGTnHKYGcA9wcWqGcUgkKZkYCwXSCb9Qfw8DGDgYMmcDM8QwQGooqCM3Ym4yq8kS5dBjzZSXUdVUdhyfirD/<0;1>/*)#qpx5cf45", ), ( "Testnet", 0, + 86, messages.InputScriptType.SPENDTAPROOT, "tr([5c9e228d/86'/1'/0']tpubDC88gkaZi5HvJGxGDNLADkvtdpni3mLmx6vr2KnXmWMG8zfkBRggsxHVBkUpgcwPe2KKpkyvTJCdXHb1UHEWE64vczyyPQfHr1skBcsRedN/<0;1>/*)#rlla6vx8", ), ( "Testnet", 1, + 86, messages.InputScriptType.SPENDTAPROOT, "tr([5c9e228d/86'/1'/1']tpubDC88gkaZi5HvKcrFLNkZwcXx1YyShkmPTkSNoP5MHQnSP9vTrKEYKtoeEkX4oEJmNYSm6Y3fFcNV4xbkDE1uZZBmJe1ircegxgVnBW8j4SL/<0;1>/*)#fwrmvr53", ), ) -@pytest.mark.parametrize("coin, account, script_type, descriptors", VECTORS_DESCRIPTORS) -def test_descriptors(client: Client, coin, account, script_type, descriptors): - res = btc._get_descriptor(client, coin, account, script_type, show_display=True) +@pytest.mark.parametrize( + "coin, account, purpose, script_type, descriptors", VECTORS_DESCRIPTORS +) +def test_descriptors(client: Client, coin, account, purpose, script_type, descriptors): + res = btc._get_descriptor( + client, coin, account, purpose, script_type, show_display=True + ) assert res == descriptors diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json index 0142517b17..e3222cf81c 100644 --- a/tests/ui_tests/fixtures.json +++ b/tests/ui_tests/fixtures.json @@ -30,22 +30,22 @@ "T1_bitcoin-test_decred.py::test_decred_multisig_change": "8f95b7d2e65a76068196ab46c8189ba5a137795b43e88699d85ad7e2c164d645", "T1_bitcoin-test_decred.py::test_send_decred": "50fa7dc09dbf22fc4c1e62ee2870e9047e29dd050edbdcf34341a5483d52cdac", "T1_bitcoin-test_decred.py::test_send_decred_change": "b27eb08c244e00f9a2c5fecad0a8efc65fa2eba15f72ad0eb3b42a3ac16d465d", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDADDRESS-pkh([5-7a80e3db": "9b30c98b35338d933fe992e4a47fb259a54f0f6f204610f63c6e6cbff427dbb9", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDP2SHWITNESS-sh-03d56ac2": "09d1f2688240677ac55f2677b62973ee7fe4ca788e9e139b9f6de5a1a66d6205", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDTAPROOT-tr([5c-22751b2f": "f71944d71edb2531faef0a177c2eda4f88bcb0ef77883db18f655d706759b5b0", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDWITNESS-wpkh([-edfbc435": "565050e8908a69cd9866a8696cdc103c19d1299486c682211f608e63b6597648", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDADDRESS-pkh([5-5ab06094": "c7987e946ff4f7f80f2aef9acd226f50ab2439837a188c0601861d0f15ca14c3", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDP2SHWITNESS-sh-5dd6ae4b": "fd3a4f48f9ea6b02a88db9ec8ab21ad72a4aee1e983e4e626b420834b375e190", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDTAPROOT-tr([5c-f4f20781": "c7a98dbc8fdf8b8a62d3ececef56e7ff2613a9491e6734b5683c1e2a5a074bed", -"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDWITNESS-wpkh([-98a75f0a": "0c3090e26ede1019969dee87ce0ea88d46e54ec587c54cf975e1947fe90b5a0e", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDADDRESS-pkh([5-f63bf93f": "a03f1c3753c5a53e05ea9737c7f2583c2935a1a68684d37c0230a1a4d9453bea", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDP2SHWITNESS-sh-fd42e1d9": "84ee5c5a45dbff7bb3d2d79b48e2323c84ff589540f6806b32b286f6bc5ce4e8", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDTAPROOT-tr([5c-a794e72a": "5f990152867980f9b129e85f9fa1963006895c49a33045e2a9363cb9fa493f26", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDWITNESS-wpkh([-e70d0168": "f56e158c4fe862875dc4d655e0a5f203312a6509bf7c16bf462a237feaf78b7b", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDADDRESS-pkh([5-2d5b32fe": "bf7d2992e2732384f0e574732e36342b09ef6a8b50641a29c5d05a13c026fd7b", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDP2SHWITNESS-sh-e8c5303c": "a381684066de8a00048ab82491599140c8e36a8eed9b9c31284e76275b7d396c", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDTAPROOT-tr([5c-ddc924d3": "f24b6c201efc2efbb174a48766df03f5964ea95908abca791714e22bcf9b635d", -"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDWITNESS-wpkh([-996ae319": "cd384fcf3379759dd5fc3f2737ddfb9185a55e506d9d0869f8a85ba31ed1d973", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-44-InputScriptType.SPENDADDRESS-pkh-efa37663": "9b30c98b35338d933fe992e4a47fb259a54f0f6f204610f63c6e6cbff427dbb9", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-49-InputScriptType.SPENDP2SHWITNESS-77f1e2d2": "09d1f2688240677ac55f2677b62973ee7fe4ca788e9e139b9f6de5a1a66d6205", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-84-InputScriptType.SPENDWITNESS-wpk-16507754": "565050e8908a69cd9866a8696cdc103c19d1299486c682211f608e63b6597648", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-86-InputScriptType.SPENDTAPROOT-tr(-2c28c019": "f71944d71edb2531faef0a177c2eda4f88bcb0ef77883db18f655d706759b5b0", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-44-InputScriptType.SPENDADDRESS-pkh-b15b8a1d": "c7987e946ff4f7f80f2aef9acd226f50ab2439837a188c0601861d0f15ca14c3", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-49-InputScriptType.SPENDP2SHWITNESS-965f4fa3": "fd3a4f48f9ea6b02a88db9ec8ab21ad72a4aee1e983e4e626b420834b375e190", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-84-InputScriptType.SPENDWITNESS-wpk-c761bcc8": "0c3090e26ede1019969dee87ce0ea88d46e54ec587c54cf975e1947fe90b5a0e", +"T1_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-86-InputScriptType.SPENDTAPROOT-tr(-686799ea": "c7a98dbc8fdf8b8a62d3ececef56e7ff2613a9491e6734b5683c1e2a5a074bed", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-44-InputScriptType.SPENDADDRESS-pkh-a26143a7": "a03f1c3753c5a53e05ea9737c7f2583c2935a1a68684d37c0230a1a4d9453bea", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-49-InputScriptType.SPENDP2SHWITNESS-195ebda5": "84ee5c5a45dbff7bb3d2d79b48e2323c84ff589540f6806b32b286f6bc5ce4e8", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-84-InputScriptType.SPENDWITNESS-wpk-68f8b526": "f56e158c4fe862875dc4d655e0a5f203312a6509bf7c16bf462a237feaf78b7b", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-86-InputScriptType.SPENDTAPROOT-tr(-07da691f": "5f990152867980f9b129e85f9fa1963006895c49a33045e2a9363cb9fa493f26", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-44-InputScriptType.SPENDADDRESS-pkh-ca853567": "bf7d2992e2732384f0e574732e36342b09ef6a8b50641a29c5d05a13c026fd7b", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-49-InputScriptType.SPENDP2SHWITNESS-5da04067": "a381684066de8a00048ab82491599140c8e36a8eed9b9c31284e76275b7d396c", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-84-InputScriptType.SPENDWITNESS-wpk-adba8950": "cd384fcf3379759dd5fc3f2737ddfb9185a55e506d9d0869f8a85ba31ed1d973", +"T1_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-86-InputScriptType.SPENDTAPROOT-tr(-e31edeff": "f24b6c201efc2efbb174a48766df03f5964ea95908abca791714e22bcf9b635d", "T1_bitcoin-test_firo.py::test_spend_lelantus": "cbb87e77f54c351584dd713a8eaabb99b65a515e57c30bfb9e7a38660ca6895b", "T1_bitcoin-test_fujicoin.py::test_send_p2tr": "bfa5dc1a494ea17fd43d52a315a7f1abe9ad80d7fdaa8b3ec5f92c4118638d1e", "T1_bitcoin-test_getaddress.py::test_bch": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", @@ -710,22 +710,22 @@ "TT_bitcoin-test_decred.py::test_send_decred": "3c08bc0156eaac3e87374bdbbaebe113aeabb7eede6f72fa1152e75e1dbe3f75", "TT_bitcoin-test_decred.py::test_send_decred_change": "de7c4aa4a54dd2145113bfca72c77af33e6a401ed2e8f15b9cfd4911296ad331", "TT_bitcoin-test_decred.py::test_spend_from_stake_generation_and_revocation_decred": "abe5667dbeebfb8a400fa74fd9e33d1c846299d1e0d45d12388c5354faecc3c2", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDADDRESS-pkh([5-7a80e3db": "29cbdd649d97f6a4e249fec463f93b524d0dc9c0fa1b4911923b1e61c372ce41", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDP2SHWITNESS-sh-03d56ac2": "f8210e469118e4bd668ac0dac15f6cb0952718c7d13c42eb7eba54092d1c105e", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDTAPROOT-tr([5c-22751b2f": "0235edd4ddefeb6aac2e86b2e6877240e26aec1c0652f398e5125b850f257c30", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDWITNESS-wpkh([-edfbc435": "e8d4b3dfa80bb359472c63169f3645d6e99aa8914db5aa461284d7c11636e7f4", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDADDRESS-pkh([5-5ab06094": "ee52b28dc418f9c58698883db4bee298bce2c5a26bf7b29dd633b9be3d411511", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDP2SHWITNESS-sh-5dd6ae4b": "7563ba74286cd41791b13308ae54c6afda75aa8fb33b259ab105338a4d7f1eea", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDTAPROOT-tr([5c-f4f20781": "0491a191b94dcbe296bf6436d355335f720bc22039bbdc7aa6f7fcb209577e39", -"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-InputScriptType.SPENDWITNESS-wpkh([-98a75f0a": "8578c74637b47a9dc82a4d6af3f38511c9e42296db2a0deb946d15c6e6cb9f93", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDADDRESS-pkh([5-f63bf93f": "0521a0fe600a1564d8d6bc335b37e0f238e8a7b56a6c1abf8dd336f50c5cbc07", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDP2SHWITNESS-sh-fd42e1d9": "039140b11cbae6d45c1d82a78b36f2749b3f1003509e2c1e450efcdcf9a0c9a6", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDTAPROOT-tr([5c-a794e72a": "4cc69d9eaae551f886bbdaf8d4b6da6f602767c53184a801fe557c50ee0761d5", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-InputScriptType.SPENDWITNESS-wpkh([-e70d0168": "7aedc96f4b55cbceee49bceb609b21904ac54e5cf408e400e1dca97c7f7cfd32", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDADDRESS-pkh([5-2d5b32fe": "884a3583893437b36ec5a3caa39f681336f215a3a4dc2cd93ea6f75fd991ba9d", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDP2SHWITNESS-sh-e8c5303c": "05009bc24c31d1491eda3c5b20cccfd791d6fb23da0c1e2452278f6a66594142", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDTAPROOT-tr([5c-ddc924d3": "af7b0e046a6b7ab526fb65334a50cc3d254c94514f0b243ea6e08e97bbc3c80d", -"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-InputScriptType.SPENDWITNESS-wpkh([-996ae319": "4b971a6769fcfc7b77783e80ac8185934dc9ba708e4e0c09a419bf1d3cf0615b", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-44-InputScriptType.SPENDADDRESS-pkh-efa37663": "29cbdd649d97f6a4e249fec463f93b524d0dc9c0fa1b4911923b1e61c372ce41", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-49-InputScriptType.SPENDP2SHWITNESS-77f1e2d2": "f8210e469118e4bd668ac0dac15f6cb0952718c7d13c42eb7eba54092d1c105e", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-84-InputScriptType.SPENDWITNESS-wpk-16507754": "e8d4b3dfa80bb359472c63169f3645d6e99aa8914db5aa461284d7c11636e7f4", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-86-InputScriptType.SPENDTAPROOT-tr(-2c28c019": "0235edd4ddefeb6aac2e86b2e6877240e26aec1c0652f398e5125b850f257c30", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-44-InputScriptType.SPENDADDRESS-pkh-b15b8a1d": "ee52b28dc418f9c58698883db4bee298bce2c5a26bf7b29dd633b9be3d411511", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-49-InputScriptType.SPENDP2SHWITNESS-965f4fa3": "7563ba74286cd41791b13308ae54c6afda75aa8fb33b259ab105338a4d7f1eea", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-84-InputScriptType.SPENDWITNESS-wpk-c761bcc8": "8578c74637b47a9dc82a4d6af3f38511c9e42296db2a0deb946d15c6e6cb9f93", +"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-1-86-InputScriptType.SPENDTAPROOT-tr(-686799ea": "0491a191b94dcbe296bf6436d355335f720bc22039bbdc7aa6f7fcb209577e39", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-44-InputScriptType.SPENDADDRESS-pkh-a26143a7": "0521a0fe600a1564d8d6bc335b37e0f238e8a7b56a6c1abf8dd336f50c5cbc07", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-49-InputScriptType.SPENDP2SHWITNESS-195ebda5": "039140b11cbae6d45c1d82a78b36f2749b3f1003509e2c1e450efcdcf9a0c9a6", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-84-InputScriptType.SPENDWITNESS-wpk-68f8b526": "7aedc96f4b55cbceee49bceb609b21904ac54e5cf408e400e1dca97c7f7cfd32", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-0-86-InputScriptType.SPENDTAPROOT-tr(-07da691f": "4cc69d9eaae551f886bbdaf8d4b6da6f602767c53184a801fe557c50ee0761d5", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-44-InputScriptType.SPENDADDRESS-pkh-ca853567": "884a3583893437b36ec5a3caa39f681336f215a3a4dc2cd93ea6f75fd991ba9d", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-49-InputScriptType.SPENDP2SHWITNESS-5da04067": "05009bc24c31d1491eda3c5b20cccfd791d6fb23da0c1e2452278f6a66594142", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-84-InputScriptType.SPENDWITNESS-wpk-adba8950": "4b971a6769fcfc7b77783e80ac8185934dc9ba708e4e0c09a419bf1d3cf0615b", +"TT_bitcoin-test_descriptors.py::test_descriptors[Testnet-1-86-InputScriptType.SPENDTAPROOT-tr(-e31edeff": "af7b0e046a6b7ab526fb65334a50cc3d254c94514f0b243ea6e08e97bbc3c80d", "TT_bitcoin-test_firo.py::test_spend_lelantus": "0c6b6d175909f93f8265ab66902bc9a3260742fc6dc3bbcd8f72ede761b87eba", "TT_bitcoin-test_fujicoin.py::test_send_p2tr": "9d639a3a56aa6d1392e43ed2209db8ab3bbc14b79ff698c772ac559272f525c8", "TT_bitcoin-test_getaddress.py::test_address_mac": "9ed7a2e89df204e6d94fa68b19ef01885299143ea040e5b99f1e56e05c44631b",