Skip to content

Commit 2caa8e2

Browse files
authored
Merge pull request #1697 from bigspider/bip388-musig
388: Add support for `musig` in descriptor templates
2 parents 8e59f74 + 2faf09d commit 2caa8e2

File tree

1 file changed

+47
-19
lines changed

1 file changed

+47
-19
lines changed

bip-0388.mediawiki

+47-19
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ We set two fundamental design goals:
8080
* Minimize the amount of information that is shown on screen - so that the user can actually validate it.
8181
* Minimize the number of times the user has to validate such information.
8282
83-
Designing a secure protocol for the coordination of a descriptor wallet among distant parties is also a challenging problem that is out of scope in this document. See [[bip-0129.mediawiki|BIP-129 (Bitcoin Secure Multisig Setup)]] for an approach designed for multisignature wallets. Regardless of the approach, the ability for the user to carefully verify all the details of the spending policies using the hardware signer's screen is a prerequisite for security in adversarial environments.
83+
Designing a secure protocol for the coordination of a descriptor wallet among distant parties is also a challenging problem that is out of the scope of this document. See [[bip-0129.mediawiki|BIP-129 (Bitcoin Secure Multisig Setup)]] for an approach designed for multisig wallets. Regardless of the approach, the ability for the user to carefully verify all the details of the spending policies using the hardware signer's screen is a prerequisite for security in adversarial environments.
8484

8585
=== Policy registration as a solution ===
8686

@@ -108,11 +108,11 @@ Once the previously registered policy is correctly identified and approved by th
108108

109109
While reusing a pubkey in different branches of a miniscript is explicitly forbidden by miniscript (as it has certain negative security implications), it is still reasonable to reuse the same xpub in multiple places, albeit with different final steps of derivation (so that the actual pubkeys that are used in the script are indeed different).
110110

111-
In fact, there are many reasonable spending policies with a quadratic size in the number of participants. For example, using Taproot, a 3-of-5 multisignature wallet could use:
112-
* a key path with a 5-of-5 MuSig2 aggregated key
111+
In fact, there are many reasonable spending policies with a quadratic size in the number of participants. For example, using Taproot, a 3-of-5 threshold wallet could use:
112+
* a key path with a 5-of-5 [[bip-0327.mediawiki|MuSig2]] aggregated key
113113
* a script tree with 11 leaves:
114114
** 10 different scripts using a 3-of-3 MuSig2 aggregated key, plus
115-
** a final leaf with a fallback 3-of-5 multisignature using <tt>multi_a</tt> (in case interactive signing is not available).
115+
** a final leaf with a fallback 3-of-5 multisig using <tt>multi_a</tt> (in case interactive signing is not available).
116116
117117
With each xpub being 118 bytes long, the repetition of xpubs makes the descriptor become extremely large.
118118

@@ -133,11 +133,11 @@ A ''wallet descriptor template'' is a <tt>SCRIPT</tt> expression.
133133
<tt>SCRIPT</tt> expressions:
134134
* <tt>sh(SCRIPT)</tt> (top level only): P2SH embed the argument.
135135
* <tt>wsh(SCRIPT)</tt> (top level or inside <tt>sh</tt> only): P2WSH embed the argument.
136-
* <tt>pkh(KP)</tt> (not inside <tt>tr</tt>): P2PKH output for the given public key.
137-
* <tt>wpkh(KP)</tt> (top level or inside <tt>sh</tt> only): P2WPKH output for the given compressed pubkey.
138-
* <tt>multi(k,KP_1,KP_2,...,KP_n)</tt> (inside <tt>sh</tt> or <tt>wsh</tt> only): ''k''-of-''n'' multisig script.
139-
* <tt>sortedmulti(k,KP_1,KP_2,...,KP_n)</tt> (inside <tt>sh</tt> or <tt>wsh</tt> only): ''k''-of-''n'' multisig script with keys sorted lexicographically in the resulting script.
140-
* <tt>tr(KP)</tt> or <tt>tr(KP,TREE)</tt> (top level only): P2TR output with the specified key as internal key, and optionally a tree of script paths.
136+
* <tt>pkh(KEY)</tt> (not inside <tt>tr</tt>): P2PKH output for the given public key.
137+
* <tt>wpkh(KEY)</tt> (top level or inside <tt>sh</tt> only): P2WPKH output for the given compressed pubkey.
138+
* <tt>multi(k,KEY_1,KEY_2,...,KEY_n)</tt> (inside <tt>sh</tt> or <tt>wsh</tt> only): ''k''-of-''n'' multisig script.
139+
* <tt>sortedmulti(k,KEY_1,KEY_2,...,KEY_n)</tt> (inside <tt>sh</tt> or <tt>wsh</tt> only): ''k''-of-''n'' multisig script with keys sorted lexicographically in the resulting script.
140+
* <tt>tr(KEY)</tt> or <tt>tr(KEY,TREE)</tt> (top level only): P2TR output with the specified key as internal key, and optionally a tree of script paths.
141141
* any valid miniscript template (inside <tt>wsh</tt> or <tt>tr</tt> only).
142142
143143
See [[bip-0379.md|BIP-379]] for a precise specification of all the valid miniscript <tt>SCRIPT</tt> expressions.
@@ -147,25 +147,38 @@ See [[bip-0379.md|BIP-379]] for a precise specification of all the valid miniscr
147147
* An open brace <tt>{</tt>, a <tt>TREE</tt> expression, a comma <tt>,</tt>, a <tt>TREE</tt> expression, and a closing brace <tt>}</tt>
148148
149149

150-
<tt>KP</tt> expressions (key placeholders) consist of
151-
* a single character <tt>@</tt>
152-
* followed by a non-negative decimal number, with no leading zeros (except for <tt>@0</tt>)
150+
<tt>KEY</tt> expressions consist of
151+
* a <tt>KP</tt> expression
153152
* ''always'' followed by either:
154153
** the string <tt>/**</tt>, or
155154
** a string of the form <tt>/<NUM;NUM>/*</tt>, for two distinct decimal numbers <tt>NUM</tt> representing unhardened derivations, or
156155
** any of the additional, implementation-specific valid derivation path patterns (see [[#optional-derivation-paths|Optional derivation paths]] below).
157156
157+
<tt>KP</tt> expressions (key placeholders) consist of either:
158+
* a <tt>KI</tt> (key index) expression, or
159+
* (only inside <tt>tr</tt>): <tt>musig(KI_1,KI_2,...,KI_n)</tt>
160+
161+
A <tt>KI</tt> (key index) expression consists of:
162+
* a single character <tt>@</tt>
163+
* followed by a non-negative decimal number, with no leading zeros (except for <tt>@0</tt>)
164+
158165
The <tt>/**</tt> in the placeholder template represents commonly used paths for receive/change addresses, and is equivalent to <tt><0;1>/*</tt>.
159166

160167
Note that while [[bip-0389.mediawiki|BIP-389]] allows multipath <tt>/<NUM;NUM;...;NUM></tt> expressions with an arbitrary number of options, this specification restricts it to exactly 2 choices (with the typical meaning of receive/change addresses).
161168

162-
The placeholder <tt>@i</tt> for some number ''i'' represents the ''i''-th key in the vector of key information items (which must be of size at least ''i + 1'', or the wallet policy is invalid).
169+
<tt>SCRIPT</tt>, <tt>TREE</tt> and <tt>KEY</tt> expressions map directly to the corresponding concepts defined in [[bip-0380.mediawiki|BIP-380]] for output script descriptors.
170+
171+
Each <tt>KEY</tt> expression always corresponds to a precise public key in the final bitcoin Script. Therefore, all the derivation steps in the BIP-32 hierarchy are included in a <tt>KEY</tt> expression.
172+
173+
Each <tt>KP</tt> (key placeholder) expression, on the other hand, maps to the root of all the corresponding public keys for all the possible UTXOs that belong to the account represented in the wallet policy. Therefore, no derivation steps are allowed in a <tt>KP</tt> expression.
174+
175+
A <tt>KI</tt> (key index) <tt>@i</tt> for some number ''i'' represents the ''i''-th key in the vector of key information items (which must be of size at least ''i + 1'', or the wallet policy is invalid).
163176

164177
Note: while descriptor templates for miniscript are not formally defined in this version of the document (pending standardization), it is straightforward to adapt this approach by adding additional <tt>SCRIPT</tt> expressions.
165178

166179
==== Key information vector ====
167180

168-
Each element of the key origin information vector is a <tt>KEY</tt> expression.
181+
Each element of the key origin information vector is a <tt>KEY_INFO</tt> expression, containing an extended public key, and (optionally) its key origin.
169182

170183
* Optionally, key origin information, consisting of:
171184
** An open bracket <tt>[</tt>
@@ -180,7 +193,9 @@ A wallet policy must have at least one key placeholder and the corresponding key
180193

181194
The public keys obtained by deserializing elements of the key information vector must be pairwise distinct<ref>'''Why must public keys be distinct?''' Reusing pubkeys could be insecure in the context of wallet policies containing [https://bitcoin.sipa.be/miniscript/ miniscript]. Avoiding repeated public keys altogether avoids the problem at the source.</ref>.
182195

183-
If two key placeholders are <tt>@i/<M;N>/*</tt> and <tt>@i/<P;Q>/*</tt> for the same index <tt>i</tt>, then the sets <tt>{M, N}</tt> and <tt>{P, Q}</tt> must be disjoint.
196+
If two <tt>KEY</tt> are <tt>KP/<M;N>/*</tt> and <tt>KP/<P;Q>/*</tt> for the same key placeholder <tt>KP</tt>, then the sets <tt>{M, N}</tt> and <tt>{P, Q}</tt> must be disjoint. Two <tt>musig</tt> key placeholders are the same if they have exactly the same set of key indexes (regardless of the order).
197+
198+
Repeated <tt>KI</tt> expressions are not allowed inside a <tt>musig</tt> placeholder.
184199

185200
The key information vector should be ordered so that placeholder <tt>@i</tt> never appears for the first time before an occurrence of <tt>@j</tt> for some <tt>j < i</tt>; for example, the first placeholder is always <tt>@0</tt>, the next one is <tt>@1</tt>, etc.
186201

@@ -224,9 +239,10 @@ Common single-signature account patterns:
224239
* <tt>sh(wpkh(@0/**))</tt> (nested segwit).
225240
* <tt>tr(@0/**)</tt> (taproot single-signature account).
226241
227-
Common multisignature schemes:
228-
* <tt>wsh(multi(2,@0/**,@1/**))</tt> - SegWit 2-of-2 multisignature, keys in order.
229-
* <tt>sh(sortedmulti(2,@0/**,@1/**,@2/**))</tt> - Legacy 2-of-3 multisignature, sorted keys.
242+
Common multisig schemes:
243+
* <tt>wsh(multi(2,@0/**,@1/**))</tt> - SegWit 2-of-2 multisig, keys in order.
244+
* <tt>sh(sortedmulti(2,@0/**,@1/**,@2/**))</tt> - Legacy 2-of-3 multisig, sorted keys.
245+
* <tt>tr(musig(@0/**,@1/**))</tt> - MuSig2 2-of-2 in the taproot keypath
230246
231247
Some miniscript policies in <tt>wsh</tt>:
232248
* <tt>wsh(and_v(v:pk(@0/**),or_d(pk(@1/**),older(12960))))</tt> - Trust-minimized second factor, degrading to a single signature after about 90 days.
@@ -277,6 +293,10 @@ Taproot wallet policy with sortedmulti_a and a miniscript leaf
277293
Keys info: ["[6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa", "xpub6Fc2TRaCWNgfT49nRGG2G78d1dPnjhW66gEXi7oYZML7qEFN8e21b2DLDipTZZnfV6V7ivrMkvh4VbnHY2ChHTS9qM3XVLJiAgcfagYQk6K", "xpub6GxHB9kRdFfTqYka8tgtX9Gh3Td3A9XS8uakUGVcJ9NGZ1uLrGZrRVr67DjpMNCHprZmVmceFTY4X4wWfksy8nVwPiNvzJ5pjLxzPtpnfEM", "xpub6GjFUVVYewLj5no5uoNKCWuyWhQ1rKGvV8DgXBG9Uc6DvAKxt2dhrj1EZFrTNB5qxAoBkVW3wF8uCS3q1ri9fueAa6y7heFTcf27Q4gyeh6"]
278294
Descriptor: tr([6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa/<0;1>/*,{sortedmulti_a(1,xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa/<2;3>/*,xpub6Fc2TRaCWNgfT49nRGG2G78d1dPnjhW66gEXi7oYZML7qEFN8e21b2DLDipTZZnfV6V7ivrMkvh4VbnHY2ChHTS9qM3XVLJiAgcfagYQk6K/<0;1>/*),or_b(pk(xpub6GxHB9kRdFfTqYka8tgtX9Gh3Td3A9XS8uakUGVcJ9NGZ1uLrGZrRVr67DjpMNCHprZmVmceFTY4X4wWfksy8nVwPiNvzJ5pjLxzPtpnfEM/<0;1>/*),s:pk(xpub6GjFUVVYewLj5no5uoNKCWuyWhQ1rKGvV8DgXBG9Uc6DvAKxt2dhrj1EZFrTNB5qxAoBkVW3wF8uCS3q1ri9fueAa6y7heFTcf27Q4gyeh6/<0;1>/*))})
279295
<br>
296+
Taproot MuSig2 3-of-3 in the key path, with three 2-of-2 MuSig2 recovery paths after 90 days in the script paths
297+
Descriptor template: tr(musig(@0,@1,@2)/**,{and_v(v:pk(musig(@0,@1)/**),older(12960)),{and_v(v:pk(musig(@0,@2)/**),older(12960)),and_v(v:pk(musig(@1,@2)/**),older(12960))}})
298+
Keys info: ["[6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa", "[b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js", "[a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2"]
299+
Descriptor: tr(musig([6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa,[b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js,[a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2)/<0;1>/*,{and_v(v:pk(musig([6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa,[b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js)/<0;1>/*),older(12960)),{and_v(v:pk(musig([6738736c/48'/0'/0'/100']xpub6FC1fXFP1GXQpyRFfSE1vzzySqs3Vg63bzimYLeqtNUYbzA87kMNTcuy9ubr7MmavGRjW2FRYHP4WGKjwutbf1ghgkUW9H7e3ceaPLRcVwa,[a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2)/<0;1>/*),older(12960)),and_v(v:pk(musig([b2b1f0cf/44'/0'/0'/100']xpub6EYajCJHe2CK53RLVXrN14uWoEttZgrRSaRztujsXg7yRhGtHmLBt9ot9Pd5ugfwWEu6eWyJYKSshyvZFKDXiNbBcoK42KRZbxwjRQpm5Js,[a666a867/44'/0'/0'/100']xpub6Dgsze3ujLi1EiHoCtHFMS9VLS1UheVqxrHGfP7sBJ2DBfChEUHV4MDwmxAXR2ayeytpwm3zJEU3H3pjCR6q6U5sP2p2qzAD71x9z5QShK2)/<0;1>/*),older(12960))}})
280300

281301
=== Invalid policies ===
282302

@@ -290,6 +310,7 @@ The following descriptor templates are invalid:
290310
* <tt>sh(multi(1,@0/<0;1>/*,@0/<1;2>/*))</tt>: Non-disjoint multipath expressions (<tt>@0/1/*</tt> appears twice)
291311
* <tt>sh(multi(1,@0/**,xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU/<0;1>/*))</tt>: Expression with a non-KP key present
292312
* <tt>pkh(@0/<0;1;2>/*)</tt>: Solved cardinality > 2
313+
* <tt>tr(musig(@0/**,@1/**))</tt>: Derivation before aggregation is not allowed in wallet policies (despite being allowed in [[bip-0390.mediawiki|BIP-390]])
293314
294315
Remark: some of the examples of invalid descriptor templates may be valid via optional extensions.
295316

@@ -311,7 +332,14 @@ Wallet policies are implemented in
311332
For development and testing purposes, we provide a [[bip-0388/wallet_policies.py|Python 3.7 reference implementation]] of simple classes to handle wallet policies, and the conversion to/from output script descriptors.
312333
The reference implementation is for demonstration purposes only and not to be used in production environments.
313334

314-
==Footnotes==
335+
== Change Log ==
336+
337+
* '''1.1.0''' (2024-11):
338+
** Added support for <tt>musig</tt> key placeholders in descriptor templates.
339+
* '''1.0.0''' (2024-05):
340+
** Initial version.
341+
342+
== Footnotes ==
315343

316344
<references />
317345

0 commit comments

Comments
 (0)