From 3662e3366978e1ecff1924da100cd2606899126e Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Thu, 26 Jun 2025 10:57:49 +0200 Subject: [PATCH] test: use derivehdkey in M-of-N multisig demo Use derivehdkey instead of extracting each participant xpub (and derivation info) from the listdescriptors output. Additionally use the new <0;1> descriptor syntax. Finally this commits adds a few debug log lines, and expand the explanation for why we use m/44h/1h/0h. --- .../wallet_multisig_descriptor_psbt.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/test/functional/wallet_multisig_descriptor_psbt.py b/test/functional/wallet_multisig_descriptor_psbt.py index 527215fa364..d80770a20d2 100755 --- a/test/functional/wallet_multisig_descriptor_psbt.py +++ b/test/functional/wallet_multisig_descriptor_psbt.py @@ -13,6 +13,8 @@ from test_framework.util import ( assert_equal, ) +from test_framework.descriptors import descsum_create + class WalletMultisigDescriptorPSBTTest(BitcoinTestFramework): def set_test_params(self): @@ -25,12 +27,13 @@ class WalletMultisigDescriptorPSBTTest(BitcoinTestFramework): @staticmethod def _get_xpub(wallet): - """Extract the wallet's xpubs using `listdescriptors` and pick the one from the `pkh` descriptor since it's least likely to be accidentally reused (legacy addresses).""" - pkh_descriptor = next(filter(lambda d: d["desc"].startswith("pkh(") and not d["internal"], wallet.listdescriptors()["descriptors"])) + """Derive an xpub at m/44h/1h/0h using `derivehdkey`. This derivation matches the `pkh` descriptor since it's least likely to be accidentally reused (legacy addresses).""" + # Ideally we would use m/87h/1h/0h but the wallet currently can't sign + # for a derivation path that's not used in one of its descriptors. + hdkey_info = wallet.derivehdkey("m/44h/1h/0h") # Keep all key origin information (master key fingerprint and all derivation steps) for proper support of hardware devices # See section 'Key origin identification' in 'doc/descriptors.md' for more details... - # Replace the change index with the multipath convention - return pkh_descriptor["desc"].split("pkh(")[1].split(")")[0].replace("/0/*", "/<0;1>/*") + return f"{hdkey_info['origin']}{hdkey_info['xpub']}/<0;1>/*" @staticmethod def _check_psbt(psbt, to, value, multisig): @@ -49,14 +52,14 @@ class WalletMultisigDescriptorPSBTTest(BitcoinTestFramework): for i in range(self.N): self.node.createwallet(wallet_name=f"{self.name}_{i}", blank=True, disable_private_keys=True) multisig = self.node.get_wallet_rpc(f"{self.name}_{i}") - multisig_desc = f"wsh(sortedmulti({self.M},{','.join(xpubs)}))" - checksum = multisig.getdescriptorinfo(multisig_desc)["checksum"] + desc = descsum_create(f"wsh(sortedmulti({self.M},{','.join(xpubs)}))") + self.log.debug(desc) result = multisig.importdescriptors([ - { # Multipath descriptor expands to receive and change - "desc": f"{multisig_desc}#{checksum}", + { + "desc": desc, "active": True, "timestamp": "now", - } + }, ]) assert all(r["success"] for r in result) yield multisig @@ -121,6 +124,7 @@ class WalletMultisigDescriptorPSBTTest(BitcoinTestFramework): self.log.info("Finally, collect the signed PSBTs with combinepsbt, finalizepsbt, then broadcast the resulting transaction...") combined = coordinator_wallet.combinepsbt(psbts) + self.log.debug(coordinator_wallet.analyzepsbt(combined)) finalized = coordinator_wallet.finalizepsbt(combined) coordinator_wallet.sendrawtransaction(finalized["hex"])