Skip to content

Commit b917c71

Browse files
committed
qa: Tapscript Miniscript signing functional tests
1 parent 5dc341d commit b917c71

File tree

1 file changed

+56
-2
lines changed

1 file changed

+56
-2
lines changed

test/functional/wallet_miniscript.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"tpubD6NzVbkrYhZ4XRMcMFMMFvzVt6jaDAtjZhD7JLwdPdMm9xa76DnxYYP7w9TZGJDVFkek3ArwVsuacheqqPog8TH5iBCX1wuig8PLXim4n9a",
2323
"tpubD6NzVbkrYhZ4WsqRzDmkL82SWcu42JzUvKWzrJHQ8EC2vEHRHkXj1De93sD3biLrKd8XGnamXURGjMbYavbszVDXpjXV2cGUERucLJkE6cy",
2424
"tpubDEFLeBkKTm8aiYkySz8hXAXPVnPSfxMi7Fxhg9sejUrkwJuRWvPdLEiXjTDbhGbjLKCZUDUUibLxTnK5UP1q7qYrSnPqnNe7M8mvAW1STcc",
25+
"tpubD6NzVbkrYhZ4WR99ygpiJvPMAJiwahjLgGywc5vJx2gUfKUfEPCrbKmQczDPJZmLcyZzRb5Ti6rfUb89S2WFyPH7FDtD6RFDA1hdgTEgEUL",
2526
]
2627
PUBKEYS = [
2728
"02aebf2d10b040eb936a6f02f44ee82f8b34f5c1ccb20ff3949c2b28206b7c1068",
@@ -148,6 +149,56 @@
148149
"sigs_count": 2,
149150
"stack_size": 8,
150151
},
152+
# Each leaf needs two sigs. We've got one key on each. Will sign both but can't finalize.
153+
{
154+
"desc": f"tr({TPUBS[0]}/*,{{and_v(v:pk({TPRVS[0]}/*),pk({TPUBS[1]})),and_v(v:pk({TPRVS[1]}/*),pk({TPUBS[2]}))}})",
155+
"sequence": None,
156+
"locktime": None,
157+
"sigs_count": 2,
158+
"stack_size": None,
159+
},
160+
# The same but now the two leaves are identical. Will add a single sig that is valid for both. Can't finalize.
161+
{
162+
"desc": f"tr({TPUBS[0]}/*,{{and_v(v:pk({TPRVS[0]}/*),pk({TPUBS[1]})),and_v(v:pk({TPRVS[0]}/*),pk({TPUBS[1]}))}})",
163+
"sequence": None,
164+
"locktime": None,
165+
"sigs_count": 1,
166+
"stack_size": None,
167+
},
168+
# The same but we have the two necessary privkeys on one of the leaves. Also it uses a pubkey hash.
169+
{
170+
"desc": f"tr({TPUBS[0]}/*,{{and_v(v:pk({TPRVS[0]}/*),pk({TPUBS[1]})),and_v(v:pkh({TPRVS[1]}/*),pk({TPRVS[2]}))}})",
171+
"sequence": None,
172+
"locktime": None,
173+
"sigs_count": 3,
174+
"stack_size": 5,
175+
},
176+
# A key immediately or one of two keys after a timelock. If both paths are available it'll use the
177+
# non-timelocked path because it's a smaller witness.
178+
{
179+
"desc": f"tr({TPUBS[0]}/*,{{pk({TPRVS[0]}/*),and_v(v:older(42),multi_a(1,{TPRVS[1]},{TPRVS[2]}))}})",
180+
"sequence": 42,
181+
"locktime": None,
182+
"sigs_count": 3,
183+
"stack_size": 3,
184+
},
185+
# A key immediately or one of two keys after a timelock. If the "primary" key isn't available though it'll
186+
# use the timelocked path. Same remark for multi_a.
187+
{
188+
"desc": f"tr({TPUBS[0]}/*,{{pk({TPUBS[1]}/*),and_v(v:older(42),multi_a(1,{TPRVS[0]},{TPRVS[1]}))}})",
189+
"sequence": 42,
190+
"locktime": None,
191+
"sigs_count": 2,
192+
"stack_size": 4,
193+
},
194+
# Liquid-like federated pegin with emergency recovery privkeys, but in a Taproot.
195+
{
196+
"desc": f"tr({TPUBS[1]}/*,{{and_b(pk({TPUBS[2]}/*),a:and_b(pk({TPUBS[3]}),a:and_b(pk({TPUBS[4]}),a:and_b(pk({TPUBS[5]}),s:pk({PUBKEYS[0]}))))),and_v(v:thresh(2,pkh({TPRVS[0]}),a:pkh({TPRVS[1]}),a:pkh({TPUBS[6]})),older(42))}})",
197+
"sequence": 42,
198+
"locktime": None,
199+
"sigs_count": 2,
200+
"stack_size": 8,
201+
},
151202
]
152203

153204

@@ -201,6 +252,7 @@ def signing_test(
201252
self, desc, sequence, locktime, sigs_count, stack_size, sha256_preimages
202253
):
203254
self.log.info(f"Importing private Miniscript descriptor '{desc}'")
255+
is_taproot = desc.startswith("tr(")
204256
desc = descsum_create(desc)
205257
res = self.ms_sig_wallet.importdescriptors(
206258
[
@@ -216,7 +268,8 @@ def signing_test(
216268
assert res[0]["success"], res
217269

218270
self.log.info("Generating an address for it and testing it detects funds")
219-
addr = self.ms_sig_wallet.getnewaddress()
271+
addr_type = "bech32m" if is_taproot else "bech32"
272+
addr = self.ms_sig_wallet.getnewaddress(address_type=addr_type)
220273
txid = self.funder.sendtoaddress(addr, 0.01)
221274
self.wait_until(lambda: txid in self.funder.getrawmempool())
222275
self.funder.generatetoaddress(1, self.funder.getnewaddress())
@@ -248,7 +301,8 @@ def signing_test(
248301
psbt = psbt.to_base64()
249302
res = self.ms_sig_wallet.walletprocesspsbt(psbt=psbt, finalize=False)
250303
psbtin = self.nodes[0].rpc.decodepsbt(res["psbt"])["inputs"][0]
251-
assert len(psbtin["partial_signatures"]) == sigs_count
304+
sigs_field_name = "taproot_script_path_sigs" if is_taproot else "partial_signatures"
305+
assert len(psbtin[sigs_field_name]) == sigs_count
252306
res = self.ms_sig_wallet.finalizepsbt(res["psbt"])
253307
assert res["complete"] == (stack_size is not None)
254308

0 commit comments

Comments
 (0)