diff --git a/bip-wallet-policies.mediawiki b/bip-wallet-policies.mediawiki index 391effb91e..a5cbe7f0cb 100644 --- a/bip-wallet-policies.mediawiki +++ b/bip-wallet-policies.mediawiki @@ -175,7 +175,8 @@ A ''wallet descriptor template'' is a SCRIPT expression. * followed by a non-negative decimal number, with no leading zeros (except for @0) * ''always'' followed by either: ** the string /**, or -** a string of the form //*, for two distinct decimal numbers NUM representing unhardened derivations. +** a string of the form //*, for two distinct decimal numbers NUM representing unhardened derivations, or +** any of the additional, implementation-specific valid derivation path patterns (see [[#Optional_derivation_paths|Optional derivation paths]] below). The /** in the placeholder template represents commonly used paths for receive/change addresses, and is equivalent to <0;1>/*. @@ -236,8 +237,8 @@ In order to allow supporting legacy derivation schemes (for example, using simpl However, care needs to be taken in view of the following considerations: -- Allowing derivation schemes with a different length or cardinality in the same wallet policy would make it difficult to guarantee that there are no repeated pubkeys for every possible address generated by the policy. For example, `@0/<0;1>/*` and `@1/*` would generate the same pubkeys if the second public key in the keys information vector is one of the first two unhardened children of the first public key. This could cause malleability with potential security implications (for example, in policies containing miniscript). -- Allowing naked pubkeys with no /* suffix (for example a descriptor template like wsh(multi(2,@0,@1/<0;1>/*))) would cause a pubkey to be repeated in every output generated from the policy, which would result in a total loss of privacy. +* Allowing derivation schemes with a different length or cardinality in the same wallet policy would make it difficult to guarantee that there are no repeated pubkeys for every possible address generated by the policy. For example, `@0/<0;1>/*` and `@1/*` would generate the same pubkeys if the second public key in the keys information vector is one of the first two unhardened children of the first public key. This could cause malleability with potential security implications (for example, in policies containing miniscript). +* Allowing naked pubkeys with no /* suffix (for example a descriptor template like wsh(multi(2,@0,@1/<0;1>/*))) would cause a pubkey to be repeated in every output generated from the policy, which would result in a total loss of privacy. == Examples == @@ -250,16 +251,18 @@ Common single-signature account patterns: * tr(@0/**) (taproot single-signature account). Common multisignature schemes: -* wsh(multi(2,@0,@1)) - SegWit 2-of-2 multisignature, keys in order. -* sh(sortedmulti(2,@0,@1,@2)) - Legacy 2-of-3 multisignature, sorted keys. +* wsh(multi(2,@0/**,@1/**)) - SegWit 2-of-2 multisignature, keys in order. +* sh(sortedmulti(2,@0/**,@1/**,@2/**)) - Legacy 2-of-3 multisignature, sorted keys. Some miniscript policies in wsh: -* wsh(and_v(v:pk(@0),or_d(pk(@1),older(12960)))) - Trust-minimized second factor, degrading to a single signature after about 90 days. +* wsh(and_v(v:pk(@0/**),or_d(pk(@1/**),older(12960)))) - Trust-minimized second factor, degrading to a single signature after about 90 days. * wsh(thresh(3,pk(@0/**),s:pk(@1/**),s:pk(@2/**),sln:older(12960))) - A 3-of-3 wallet that becomes a 2-of-3 if coins are not spent for about 90 days. -* wsh(or_d(pk(@0),and_v(v:multi(2,@1,@2,@3),older(65535)))) - A singlesig wallet with automatic inheritance to a timelocked 2-of-3 multisig of family members. +* wsh(or_d(pk(@0/**),and_v(v:multi(2,@1/**,@2/**,@3/**),older(65535)))) - A singlesig wallet with automatic inheritance to a timelocked 2-of-3 multisig of family members. == Test Vectors == +=== Valid policies === + [[bip-0044.mediawiki|BIP-44]], first account Descriptor template: pkh(@0/**) Keys info: ["[6738736c/44'/0'/0']xpub6Br37sWxruYfT8ASpCjVHKGwgdnYFEn98DwiN76i2oyY6fgH1LAPmmDcF46xjxJr22gw4jmVjTE2E3URMnRPEPYyo1zoPSUba563ESMXCeb"] @@ -276,9 +279,9 @@ Some miniscript policies in wsh: Descriptor:wpkh([6738736c/84'/0'/2']xpub6CRQzb8u9dmMcq5XAwwRn9gcoYCjndJkhKgD11WKzbVGd932UmrExWFxCAvRnDN3ez6ZujLmMvmLBaSWdfWVn75L83Qxu1qSX4fJNrJg2Gt)
[[bip-0086.mediawiki|BIP-86]], first account - Descriptor template: tr(@0/**)) + Descriptor template: tr(@0/**) Keys info: ["[6738736c/86'/0'/0']xpub6CryUDWPS28eR2cDyojB8G354izmx294BdjeSvH469Ty3o2E6Tq5VjBJCn8rWBgesvTJnyXNAJ3QpLFGuNwqFXNt3gn612raffLWfdHNkYL"] - Descriptor:tr([6738736c/86'/0'/0']xpub6CryUDWPS28eR2cDyojB8G354izmx294BdjeSvH469Ty3o2E6Tq5VjBJCn8rWBgesvTJnyXNAJ3QpLFGuNwqFXNt3gn612raffLWfdHNkYL)) + Descriptor:tr([6738736c/86'/0'/0']xpub6CryUDWPS28eR2cDyojB8G354izmx294BdjeSvH469Ty3o2E6Tq5VjBJCn8rWBgesvTJnyXNAJ3QpLFGuNwqFXNt3gn612raffLWfdHNkYL)
[[bip-0048.mediawiki|BIP-48]] P2WSH multisig Descriptor template: wsh(sortedmulti(2,@0/**,@1/**)) @@ -298,6 +301,21 @@ Miniscript: A singlesig wallet with automatic inheritance to a timelocked 2-of-3 TBD: add examples with taproot scripts and miniscript. +=== Invalid policies === + +The following descriptor templates are invalid: + +* pkh(@0): Key placeholder with no path following it +* pkh(@0/0/*): Key placeholder with an explicit path present +* sh(multi(1,@1/**,@0/**)): Key placeholders out of order +* sh(multi(1,@0/**,@2/**)): Skipped key placeholder @1 +* sh(multi(1,@0/**,@0/**)): Repeated keys w/same path expression +* sh(multi(1,@0/<0;1>/*,@0/<1;2>/*)): Non-disjoint multipath expressions (@0/1/* appears twice) +* sh(multi(1,@0/**,xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU/<0;1>/*)): Expression with a non KP key present +* pkh(@0/<0;1;2>/*): Solved cardinality > 2 + +Remark: some of the descriptor templates above might be valid if optional extensions allowing them are added in the implementation. + == Backwards Compatibility == The @ character used for key placeholders is not part of the syntax of output script descriptors, therefore any valid output descriptor with at least one `KEY` expression is not a valid descriptor template. Vice versa, any descriptor template with at least one key placeholder is not a valid output script descriptor.