From 11a3be74588576bbf20953afed3a2265da3873cd Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Tue, 22 Sep 2026 14:52:10 +0200 Subject: [PATCH] bip138: clarify MuSig participant eligibility MuSig aggregation hides participant keys, so account xpubs do not need individual trailing derivation. Specify that encryption uses participant roots rather than the aggregate key. Add MuSig2 test vectors: one for a bare aggregate and one for aggregate derivation. --- bip-0138.md | 23 +++++++++++++++-------- bip-0138/test_vectors/recipient_keys.json | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/bip-0138.md b/bip-0138.md index 4bf4eb52..f1f2a268 100644 --- a/bip-0138.md +++ b/bip-0138.md @@ -11,7 +11,7 @@ https://groups.google.com/g/bitcoindev/c/5NgJbpVDgEc/m/TtGK9sF9BgAJ https://github.com/bitcoin/bips/pull/1951 Version: 0.1.2 - Requires: 32, 340, 380, 388, 389 + Requires: 32, 340, 380, 388, 389, 390 ``` ## Introduction @@ -138,8 +138,8 @@ accounts whose xpub was never sent to such a server, such as BIP48 or BIP87 acco ### Descriptor key requirements -Only key expressions of the extended-public-key type with a trailing -derivation step or wildcard contribute to $\{p_1, \dots, p_n\}$. Without +Outside `musig()`, only key expressions of the extended-public-key type with a +trailing derivation step or wildcard contribute to $\{p_1, \dots, p_n\}$. Without that derivation, the xpub's root pubkey, used to seed $s$, would also be the on-chain pubkey of every spend, so observing one spend would let anyone recompute $s$ and decrypt the backup.[^trailing-derivation] The @@ -150,9 +150,9 @@ rule generalizes to any network prefix (`xpub`/`tpub`/`Vpub`/...). a wildcard, breaks the identity between the xpub root pubkey and the on-chain pubkey. Fixed-derivation expressions like `xpub.../0/5` are allowed because the on-chain key (`xpub/0/5`) already differs from the - encryption seed (the xpub root). Literal pubkeys and bare xpubs are - disallowed for the same reason: the literal value is exactly what goes - on-chain, so $s$ would become recoverable from a single observed spend. + encryption seed (the xpub root). Outside `musig()`, literal pubkeys and + bare xpubs are disallowed for the same reason: the literal value is exactly + what goes on-chain, so $s$ would become recoverable from a single observed spend. Allowed forms (origin information `[...]` is optional and orthogonal): @@ -163,11 +163,18 @@ Allowed forms (origin information `[...]` is optional and orthogonal): | `//*` (fixed derivation followed by a wildcard) | `xpub.../0/*` | | `/` (multipath, no wildcard) | `xpub.../<0;1>` | | `//*` (multipath followed by a wildcard) | `xpub.../<0;1>/*` | +| `` (only as a `musig()` participant) | `xpub...` | + +Within a [BIP390](bip-0390.mediawiki) `musig()` expression, participant xpubs +are allowed with or without trailing derivation: the aggregate on-chain key +does not reveal the individual participant keys. For encryption, use each +participant's xpub root rather than the aggregate key. Literal public-key +participants remain excluded. Implementations: -- MUST exclude every other form (literal pubkeys, bare xpubs, ...) from - $\{p_1, \dots, p_n\}$. +- MUST exclude every other form (literal pubkeys, bare xpubs outside `musig()`, + ...) from $\{p_1, \dots, p_n\}$. - MUST refuse to encode a backup if the resulting set is empty. - MUST make the user aware of each excluded expression, since the cosigner holding that key will be unable to decrypt the backup with diff --git a/bip-0138/test_vectors/recipient_keys.json b/bip-0138/test_vectors/recipient_keys.json index de127951..05f4c8f0 100644 --- a/bip-0138/test_vectors/recipient_keys.json +++ b/bip-0138/test_vectors/recipient_keys.json @@ -71,5 +71,25 @@ "pk(04ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b517089e956909c4c07e8529f45f3ff8904d28df5a181619e21bdf748a896322530039)" ], "expected_keys": null + }, + { + "description": "Bare MuSig participant xpubs", + "descriptors": [ + "tr(musig(tpubDEPBvXvhta3pjVaKokqC3eeMQnszj9ehFaA2zD5nSdkaccwGAizu8jVB2NeSpvmP2P52MBoZvNCixqXRJnTyXx51FQzARR63tjxQSyP3Btw,tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba))" + ], + "expected_keys": [ + "8b42cd4776376c82791b494155151f56c2d7b471e0c7a526a7ce60dd872e3867", + "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708" + ] + }, + { + "description": "Derivation after MuSig aggregation", + "descriptors": [ + "tr(musig(tpubDEPBvXvhta3pjVaKokqC3eeMQnszj9ehFaA2zD5nSdkaccwGAizu8jVB2NeSpvmP2P52MBoZvNCixqXRJnTyXx51FQzARR63tjxQSyP3Btw,tpubDC5FSnBiZDMmhiuCmWAYsLwgLYrrT9rAqvTySfuCCrgsWz8wxMXUS9Tb9iVMvcRbvFcAHGkMD5Kx8koh4GquNGNTfohfk7pgjhaPCdXpoba)/<0;1>/*)" + ], + "expected_keys": [ + "8b42cd4776376c82791b494155151f56c2d7b471e0c7a526a7ce60dd872e3867", + "ebd252ca0877aae09b9d058219682775aa3cbcd049c12f07832f2cf6a3b51708" + ] } ]