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.
This commit is contained in:
Sjors Provoost
2025-06-26 10:57:49 +02:00
parent d9570f0838
commit 3662e33669

View File

@@ -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"])