From f080fe20ee1bbf7b567ea0a20fbe883a3b7192c8 Mon Sep 17 00:00:00 2001 From: scgbckbone Date: Wed, 25 Mar 2026 12:46:26 +0100 Subject: [PATCH] always replace standard derivation from policy with /** before saving --- shared/wallet.py | 6 ++--- testing/conftest.py | 2 +- testing/test_musig2.py | 55 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/shared/wallet.py b/shared/wallet.py index 9f75e6ef..0348d13b 100644 --- a/shared/wallet.py +++ b/shared/wallet.py @@ -489,10 +489,7 @@ class MiniScriptWallet(WalletABC): @staticmethod def _from_bip388_wallet_policy(desc_template, keys_info, validate=True): - desc_str = bip388_wallet_policy_to_descriptor( - desc_template.replace("/<0;1>/*", "/**"), - keys_info - ) + desc_str = bip388_wallet_policy_to_descriptor(desc_template, keys_info) from descriptor import Descriptor desc_obj = Descriptor.from_string(desc_str) if validate: @@ -502,6 +499,7 @@ class MiniScriptWallet(WalletABC): @classmethod def from_bip388_wallet_policy(cls, name, desc_template, keys_info): bip388_validate_policy(desc_template, keys_info) + desc_template = desc_template.replace("/<0;1>/*", "/**") desc_obj = cls._from_bip388_wallet_policy(desc_template, keys_info) msc = cls.from_descriptor_obj(name, desc_obj, desc_template, keys_info) return msc diff --git a/testing/conftest.py b/testing/conftest.py index c4190287..90fa7866 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -3083,7 +3083,7 @@ from test_msg import verify_msg_sign_story, sign_msg_from_text, msg_sign_export, from test_multisig import import_ms_wallet, make_multisig, fake_ms_txn from test_miniscript import (offer_minsc_import, get_cc_key, bitcoin_core_signer, import_miniscript, usb_miniscript_get, usb_miniscript_addr, create_core_wallet, import_duplicate, address_explorer_check, - miniscript_descriptors) + miniscript_descriptors, usb_miniscript_policy) from test_multisig import make_ms_address, make_myself_wallet from test_musig2 import build_musig_wallet from test_notes import need_some_notes, need_some_passwords, goto_notes diff --git a/testing/test_musig2.py b/testing/test_musig2.py index ccc46978..08c16e27 100644 --- a/testing/test_musig2.py +++ b/testing/test_musig2.py @@ -1808,4 +1808,57 @@ def test_modify_PSBT_during_musig_signing(tapscript, use_regtest, clear_miniscri title, story = cap_story() assert "musig needs restart" in story -# EOF \ No newline at end of file + +@pytest.mark.parametrize("der", ["/**", "/<0;1>/*"]) +def test_import_musig_from_b388_policy(der, microsd_path, garbage_collector, clear_miniscript, + pick_menu_item, need_keypress, cap_story, use_mainnet, + press_select, usb_miniscript_policy, goto_home, + usb_miniscript_get): + policy = """{ +"name":"MuSig2", +"desc_template":"tr(musig(@0,@1,@2)%s,{{pk(musig(@0,@1)%s),pk(musig(@1,@2)%s)},pk(musig(@0,@2)%s)})", +"keys_info":[ + "[a0d3c79c/48h/0h/0h/3h]xpub6DyCgL3TMMS3trskRyxP6M6iCqSUYPgC4QECKYkubC1L27aYUnPZJwvw57vK56G1t42KQHhX8MrU5zkt9nispkAMXYDLfiiSyrQ9HT1aQoy", + "[9a1c8a27/48h/0h/0h/3h]xpub6DmrCyYSAz65fVFRAPEsvLZ5jHZYeF6DvprfYp7754XD2srXQr8kAcayGKhakmWiNe7iVEpjmC9JuqicHAQZk1rpWijrvh2AEwL7WaietUN", + "[0f056943/48h/0h/0h/3h]xpub6FQgdFZAHcAeDMVe9KxWoLMxziCjscCExzuKJhRSjM71CA9dUDZEGNgPe4S2SsRumCBXeaTBZ5nKz2cMDiK4UEbGkFXNipHLkm46inpjE9D"] +} +""" + policy = policy % (der, der, der, der) + fname = "musig_b388.json" + fpath = microsd_path(fname) + with open(fpath, "w") as f: + f.write(policy) + + clear_miniscript() + use_mainnet() + goto_home() + pick_menu_item("Settings") + pick_menu_item("Multisig/Miniscript") + pick_menu_item("Import") + need_keypress("1") + try: + pick_menu_item(fname) + except: pass + + time.sleep(.1) + title, story = cap_story() + assert "Create new miniscript wallet" in story + assert "/**" in story + assert "/<0;1>/*" not in story + press_select() + pick_menu_item("MuSig2") + pick_menu_item("Descriptors") + pick_menu_item("BIP-388 Policy") + + contents = usb_miniscript_policy("MuSig2") + assert "/**" in contents["desc_template"] + assert "/<0;1>/*" not in contents["desc_template"] + if der == "/<0;1>/*": + policy = policy.replace(der, "/**") + assert json.loads(policy) == contents + + contents = usb_miniscript_get("MuSig2") + assert "/**" not in contents["desc"] + assert "/<0;1>/*" in contents["desc"] + +# EOF