diff options
-rw-r--r-- | README.mediawiki | 35 | ||||
-rw-r--r-- | bip-0015.mediawiki | 2 | ||||
-rw-r--r-- | bip-0039/bip-0039-wordlists.md | 6 | ||||
-rw-r--r-- | bip-0143.mediawiki | 2 | ||||
-rw-r--r-- | bip-0174.mediawiki | 60 | ||||
-rw-r--r-- | bip-0301.mediawiki | 2 | ||||
-rw-r--r-- | bip-0327.mediawiki | 3 | ||||
-rw-r--r-- | bip-0328.mediawiki | 80 | ||||
-rw-r--r-- | bip-0340/test-vectors.py | 4 | ||||
-rw-r--r-- | bip-0352.mediawiki | 27 | ||||
-rw-r--r-- | bip-0352/bitcoin_utils.py | 3 | ||||
-rwxr-xr-x | bip-0352/reference.py | 15 | ||||
-rw-r--r-- | bip-0352/ripemd160.py | 130 | ||||
-rw-r--r-- | bip-0352/send_and_receive_test_vectors.json | 89 | ||||
-rw-r--r-- | bip-0353.mediawiki | 130 | ||||
-rw-r--r-- | bip-0373.mediawiki | 216 | ||||
-rw-r--r-- | bip-0379.md | 423 | ||||
-rw-r--r-- | bip-0380.mediawiki | 3 | ||||
-rw-r--r-- | bip-0390.mediawiki | 117 |
19 files changed, 1319 insertions, 28 deletions
diff --git a/README.mediawiki b/README.mediawiki index 455d522..fbddd61 100644 --- a/README.mediawiki +++ b/README.mediawiki @@ -1016,6 +1016,13 @@ Those proposing changes should consider that ultimately consent may rest with th | Informational | Draft |- +| [[bip-0328.mediawiki|328]] +| Applications +| Derivation Scheme for MuSig2 Aggregate Keys +| Ava Chow +| Informational +| Draft +|- | [[bip-0329.mediawiki|329]] | Applications | Wallet Labels Export Format @@ -1121,6 +1128,13 @@ Those proposing changes should consider that ultimately consent may rest with th | Standard | Proposed |- +| [[bip-0353.mediawiki|353]] +| Applications +| DNS Payment Instructions +| Matt Corallo, Bastien Teinturier +| Standard +| Draft +|- | [[bip-0370.mediawiki|370]] | Applications | PSBT Version 2 @@ -1142,6 +1156,20 @@ Those proposing changes should consider that ultimately consent may rest with th | Standard | Draft |- +| [[bip-0373.mediawiki|373]] +| Applications +| MuSig2 PSBT Fields +| Ava Chow +| Standard +| Draft +|- +| [[bip-0379.md|379]] +| Applications +| Miniscript +| Pieter Wuille, Andrew Poelstra, Sanket Kanjalkar, Antoine Poinsot, Ava Chow +| Informational +| Draft +|- | [[bip-0380.mediawiki|380]] | Applications | Output Script Descriptors General Operation @@ -1212,6 +1240,13 @@ Those proposing changes should consider that ultimately consent may rest with th | Informational | Draft |- +| [[bip-0390.mediawiki|390]] +| Applications +| musig() Descriptor Key Expression +| Ava Chow +| Informational +| Draft +|- | [[bip-0431.mediawiki|431]] | Applications | Topology Restrictions for Pinning diff --git a/bip-0015.mediawiki b/bip-0015.mediawiki index 1e9a9bc..635fb7f 100644 --- a/bip-0015.mediawiki +++ b/bip-0015.mediawiki @@ -36,7 +36,7 @@ Their FirstBits alias becomes: It is enough information to be given the FirstBits alias ''1brmlab''. When someone wishes to make a purchase, without FirstBits, they either have to type out their address laboriously by hand, scan their QR code (which requires a mobile handset that this author does not own) or find their address on the internet to copy and paste into the client to send bitcoins. FirstBits alleviates this impracticality by providing an easy method to make payments. -Together with [[vanitygen|Vanitygen (vanity generator)]], it becomes possible to create memorable unique named addresses. Addresses that are meaningful, rather than an odd assemblage of letters and numbers but add context to the destination. +Together with Vanitygen (vanity generator), it becomes possible to create memorable unique named addresses. Addresses that are meaningful, rather than an odd assemblage of letters and numbers but add context to the destination. However FirstBits has its own problems. One is that the possible aliases one is able to generate is limited by the available computing power available. It may not be feasible to generate a complete or precise alias that is wanted- only approximates may be possible. It is also computationally resource intensive which means a large expenditure of power for generating unique aliases in the future, and may not scale up to the level of individuals at home or participants with hand-held devices in an environment of ubiquitous computing. diff --git a/bip-0039/bip-0039-wordlists.md b/bip-0039/bip-0039-wordlists.md index 5acf87d..7cf8fcb 100644 --- a/bip-0039/bip-0039-wordlists.md +++ b/bip-0039/bip-0039-wordlists.md @@ -28,7 +28,7 @@ for two smaller words (This would be a problem with any of the 3 character sets ### Spanish -1. Words can be uniquely determined typing the first 4 characters (sometimes less). +1. Words can be uniquely determined by typing the first 4 characters (sometimes less). 2. Special Spanish characters like 'ñ', 'ü', 'á', etc... are considered equal to 'n', 'u', 'a', etc... in terms of identifying a word. Therefore, there is no need to use a Spanish keyboard to introduce the passphrase, an application with the Spanish wordlist will be able to identify the words after the first 4 chars have been typed even if the chars with accents have been replaced with the equivalent without accents. @@ -92,7 +92,7 @@ Credits: @zizelevak (Jan Lansky zizelevak@gmail.com) Words chosen using the following rules: 1. Words are 4-8 letters long. -2. Words can be uniquely determined typing the first 4 letters. +2. Words can be uniquely determined by typing the first 4 letters. 3. Only words containing all letters without diacritical marks. (It was the hardest task, because one third of all Czech letters has diacritical marks.) 4. Only nouns, verbs and adverbs, no other word types. All words are in basic form. 5. No personal names or geographical names. @@ -104,7 +104,7 @@ Words chosen using the following rules: Credits: @alegotardo @bitmover-studio @brenorb @kuthullu @ninjastic @sabotag3x @Trimegistus -1. Words can be uniquely determined typing the first 4 characters. +1. Words can be uniquely determined by typing the first 4 characters. 2. No accents or special characters. 3. No complex verb forms. 4. No plural words, unless there's no singular form. diff --git a/bip-0143.mediawiki b/bip-0143.mediawiki index 9935eaa..d7e514e 100644 --- a/bip-0143.mediawiki +++ b/bip-0143.mediawiki @@ -114,7 +114,7 @@ Refer to the reference implementation, reproduced below, for the precise algorit ss << hashSequence; // The input being signed (replacing the scriptSig with scriptCode + amount) // The prevout may already be contained in hashPrevout, and the nSequence - // may already be contain in hashSequence. + // may already be contained in hashSequence. ss << txTo.vin[nIn].prevout; ss << static_cast<const CScriptBase&>(scriptCode); ss << amount; diff --git a/bip-0174.mediawiki b/bip-0174.mediawiki index 95a5573..94a52f2 100644 --- a/bip-0174.mediawiki +++ b/bip-0174.mediawiki @@ -483,6 +483,52 @@ The currently defined per-input types are defined as follows: | 0, 2 | [[bip-0371.mediawiki|371]] |- +| MuSig2 Participant Public Keys +| <tt>PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS = 0x1a</tt> +| <33 byte plain aggregate pubkey> +| The MuSig2 aggregate plain public key from the <tt>KeyAgg</tt> algorithm. This key may or may not +be in the script directly (as x-only). It may instead be a parent public key from which the public keys in the +script were derived. +| <tt><33 byte compressed pubkey>*</tt> +| A list of the compressed public keys of the participants in the MuSig2 aggregate key in the order +required for aggregation. If sorting was done, then the keys must be in the sorted order. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- +| MuSig2 Public Nonce +| <tt>PSBT_IN_MUSIG2_PUB_NONCE = 0x1b</tt> +| <tt><33 byte compressed pubkey> <33 byte plain pubkey> <32 byte hash or omitted></tt> +| The compressed public key of the participant providing this nonce, followed by the plain public +key the participant is providing the nonce for, followed by the BIP 341 tapleaf hash of +the Taproot leaf script that will be signed. If the aggregate key is the taproot internal key or the +taproot output key, then the tapleaf hash must be omitted. The plain public key must be +the key found in the script and not the aggregate public key that it was derived from, if it was +derived from an aggregate key. +| <tt><66 byte public nonce></tt> +| The public nonce produced by the <tt>NonceGen</tt> algorithm. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- +| MuSig2 Participant Partial Signature +| <tt>PSBT_IN_MUSIG2_PARTIAL_SIG = 0x1c</tt> +| <tt><33 byte compressed pubkey> <33 byte plain pubkey> <32 byte hash or omitted></tt> +| The compressed public key of the participant providing this partial signature, followed by the +plain public key the participant is providing the signature for, followed by the BIP 341 tapleaf hash +of the Taproot leaf script that will be signed. If the aggregate key is the taproot internal key or +the taproot output key, then the tapleaf hash must be omitted. Note that the plain public key must +be the key found in the script and not the aggregate public key that it was derived from, if it was +derived from an aggregate key. +| <tt><32 byte partial signature></tt> +| The partial signature produced by the <tt>Sign</tt> algorithm. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- | Proprietary Use Type | <tt>PSBT_IN_PROPRIETARY = 0xFC</tt> | <tt><compact size uint identifier length> <bytes identifier> <compact size uint subtype> <bytes subkeydata></tt> @@ -599,6 +645,20 @@ determine which outputs are change outputs and verify that the change is returni | 0, 2 | [[bip-0371.mediawiki|371]] |- +| MuSig2 Participant Public Keys +| <tt>PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS = 0x08</tt> +| <33 byte plain aggregate pubkey> +| The MuSig2 aggregate plain public key from the <tt>KeyAgg</tt> algorithm. This key may or may not +be in the script directly. It may instead be a parent public key from which the public keys in the +script were derived. +| <tt><33 byte compressed pubkey>*</tt> +| A list of the compressed public keys of the participants in the MuSig2 aggregate key in the order +required for aggregation. If sorting was done, then the keys must be in the sorted order. +| +| +| 0, 2 +| [[bip-0373.mediawiki|373]] +|- | Proprietary Use Type | <tt>PSBT_OUT_PROPRIETARY = 0xFC</tt> | <tt><compact size uint identifier length> <bytes identifier> <compact size uint subtype> <bytes subkeydata></tt> diff --git a/bip-0301.mediawiki b/bip-0301.mediawiki index e1522f8..966db25 100644 --- a/bip-0301.mediawiki +++ b/bip-0301.mediawiki @@ -78,7 +78,7 @@ Bip301 makes this specialization-of-labor trustless on layer1. If Mary takes Sim ==Specification== -Bip300 consists of two messages: "BMM Accept" and "BMM Request". These govern something called "h*". +Bip301 consists of two messages: "BMM Accept" and "BMM Request". These govern something called "h*". So we will discuss: diff --git a/bip-0327.mediawiki b/bip-0327.mediawiki index 181926b..b659629 100644 --- a/bip-0327.mediawiki +++ b/bip-0327.mediawiki @@ -190,9 +190,6 @@ The aggregate public key can be ''tweaked'', which modifies the key as defined i In order to apply a tweak, the KeyAgg Context output by ''KeyAgg'' is provided to the ''ApplyTweak'' algorithm with the ''is_xonly_t'' argument set to false for plain tweaking and true for X-only tweaking. The resulting KeyAgg Context can be used to apply another tweak with ''ApplyTweak'' or obtain the aggregate public key with ''GetXonlyPubkey'' or ''GetPlainPubkey''. -In addition to individual public keys, the ''KeyAgg'' algorithm accepts tweaks, which modify the aggregate public key as defined in the [[#tweaking-definition|Tweaking Definition]] subsection. -For example, if ''KeyAgg'' is run with ''v = 2'', ''is_xonly_t<sub>1</sub> = false'', ''is_xonly_t<sub>2</sub> = true'', then the aggregate key is first plain tweaked with ''tweak<sub>1</sub>'' and then X-only tweaked with ''tweak<sub>2</sub>''. - The purpose of supporting tweaking is to ensure compatibility with existing uses of tweaking, i.e., that the result of signing is a valid signature for the tweaked public key. The MuSig2 algorithms take arbitrary tweaks as input but accepting arbitrary tweaks may negatively affect the security of the scheme.<ref>It is an open question whether allowing arbitrary tweaks from an adversary affects the unforgeability of MuSig2.</ref> Instead, signers should obtain the tweaks according to other specifications. diff --git a/bip-0328.mediawiki b/bip-0328.mediawiki new file mode 100644 index 0000000..3c07dab --- /dev/null +++ b/bip-0328.mediawiki @@ -0,0 +1,80 @@ +<pre> + BIP: 328 + Layer: Applications + Title: Derivation Scheme for MuSig2 Aggregate Keys + Author: Ava Chow <me@achow101.com> + Comments-Summary: No comments yet. + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0328 + Status: Draft + Type: Informational + Created: 2024-01-15 + License: CC0-1.0 +</pre> + +==Abstract== + +This document specifies how BIP 32 extended public keys can be constructed from a BIP 327 MuSig2 +aggregate public key and how such keys should be used for key derivation. + +==Copyright== + +This BIP is licensed under the Creative Commons CC0 1.0 Universal license. + +==Motivation== + +Multiple signers can create a single aggregate public key with MuSig2 that is indistinguishable +from a random public key. The cosigners need a method for generating additional aggregate pubkeys +to follow the best practice of using a new address for every payment. + +The obvious method is for the cosigners to generate multiple public keys and produce a +new aggregate pubkey every time one is needed. This is similar to how multisig using Bitcoin script +works where all of the cosigners share their extended public keys and do derivation to produce +the multisig script. The same could be done with MuSig2 and instead of producing a multisig script, +the result would be a MuSig2 aggregate pubkey. + +However, it is much simpler to be able to derive from a single extended public key instead of having +to derive from many extended public keys and aggregate them. As MuSig2 produces a normal looking +public key, the aggregate public can be used in this way. This reduces the storage and computation +requirements for generating new aggregate pubkeys. + +==Specification== + +A synthetic xpub can be created from a BIP 327 MuSig2 plain aggregate public key by setting +the depth to 0, the child number to 0, and attaching a chaincode with the byte string +<tt>868087ca02a6f974c4598924c36b57762d32cb45717167e300622c7167e38965</tt><ref>'''Where does this +constant chaincode come from?''' It is the SHA256 of the text <tt>MuSig2MuSig2MuSig2</tt></ref>. +This fixed chaincode should be used by all such synthetic xpubs following this specification. +Unhardened child public keys can be derived from the synthetic xpub as with any other xpub. Since +the aggregate public key is all that is necessary to produce the synthetic xpub, any aggregate +public key that will be used in this way shares the same privacy concerns as typical xpubs. + +Furthermore, as there is no aggregate private key, only unhardened derivation from the aggregate +public key is possible. + +When signing, all signers must compute the tweaks used in the BIP 32 derivation for the child key +being signed for. The I<sub>L</sub> value computed in ''CKDpub'' is the tweak used at each +derivation step. These are provided in the session context, each with a tweak mode of plain +(''is_xonly_t = false''). When the ''Sign'' algorithm is used, the tweaks will be applied to the +partial signatures. + +==Test Vectors== + +TBD + +==Backwards Compatibility== + +Once a synthetic xpub is created, it is fully backwards compatible with BIP 32 - only unhardened +derivation can be done, and the signers will be able to produce a signature for any derived children. + +==Rationale== + +<references/> + +==Reference Implementation== + +TBD + +==Acknowledgements== + +Thanks to Pieter Wuille, Andrew Poelstra, Sanket Kanjalkar, Salvatore Ingala, and all others who +participated in discussions on this topic. diff --git a/bip-0340/test-vectors.py b/bip-0340/test-vectors.py index 9a5a140..5a131c4 100644 --- a/bip-0340/test-vectors.py +++ b/bip-0340/test-vectors.py @@ -24,14 +24,14 @@ def vector0(): assert(y(P) % 2 == 0) # For historical reasons (pubkey tiebreaker was squareness and not evenness) - # we should have at least one test vector where the the point reconstructed + # we should have at least one test vector where the point reconstructed # from the public key has a square and one where it has a non-square Y # coordinate. In this one Y is non-square. pubkey_point = lift_x(pubkey) assert(not has_square_y(pubkey_point)) # For historical reasons (R tiebreaker was squareness and not evenness) - # we should have at least one test vector where the the point reconstructed + # we should have at least one test vector where the point reconstructed # from the R.x coordinate has a square and one where it has a non-square Y # coordinate. In this one Y is non-square. R = lift_x(sig[0:32]) diff --git a/bip-0352.mediawiki b/bip-0352.mediawiki index 4cbf9d7..483bed3 100644 --- a/bip-0352.mediawiki +++ b/bip-0352.mediawiki @@ -98,9 +98,8 @@ In our simplified example we have been referring to Alice's transactions as havi Alice performs the tweak with the sum of her input private keys in the following manner: -* Let ''A = A<sub>1</sub> + A<sub>2</sub> + ... + A<sub>n</sub>'' -* Let ''input_hash = hash(outpoint<sub>L</sub> || A)'', where ''outpoint<sub>L</sub>'' is the smallest outpoint lexicographically<ref name="why_smallest_outpoint">'''Why use the lexicographically smallest outpoint for the hash?''' Recall that the purpose of including the input hash is so that the sender and receiver can both come up with a deterministic nonce that ensures that a unique address is generated each time, even when reusing the same scriptPubKey as an input. Choosing the smallest outpoint lexicographically satisifes this requirement, while also ensuring that the generated output is not dependent on the final ordering of inputs in the transaction. Using a single outpoint also works well with memory constrained devices (such as hardware signing devices) as it does not require the device to have the entire transaction in memory in order to generate the silent payment output.</ref> * Let ''a = a<sub>1</sub> + a<sub>2</sub> + ... + a<sub>n</sub>'' +* Let ''input_hash = hash(outpoint<sub>L</sub> || (a·G))'', where ''outpoint<sub>L</sub>'' is the smallest outpoint lexicographically<ref name="why_smallest_outpoint">'''Why use the lexicographically smallest outpoint for the hash?''' Recall that the purpose of including the input hash is so that the sender and receiver can both come up with a deterministic nonce that ensures that a unique address is generated each time, even when reusing the same scriptPubKey as an input. Choosing the smallest outpoint lexicographically satisifes this requirement, while also ensuring that the generated output is not dependent on the final ordering of inputs in the transaction. Using a single outpoint also works well with memory constrained devices (such as hardware signing devices) as it does not require the device to have the entire transaction in memory in order to generate the silent payment output.</ref> * Let ''P<sub>0</sub> = B + hash(input_hash·a·B || 0)·G'' ''' Spend and Scan Key ''' @@ -280,13 +279,6 @@ The sender performs the tweak using the private key for the nested ''P2WPKH'' ou The receiver obtains the public key from the ''scriptSig''. The receiver MUST parse the ''scriptSig'' for the public key, even if the ''scriptSig'' does not match the template specified (e.g. <code><dummy> OP_DROP <Signature> <Public Key></code>). This is to address the [https://en.bitcoin.it/wiki/Transaction_malleability third-party malleability of ''P2PKH'' ''scriptSigs'']. -=== Input hash === - -The sender and receiver MUST calculate an input hash for the transaction in the following manner: - -* Let ''A = A<sub>1</sub> + A<sub>2</sub> + ... + A<sub>n</sub>'', where each ''A<sub>i</sub>'' is the public key of an input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list<ref name="why_include_A"></ref> -* Let ''input_hash = hash<sub>BIP0352/Inputs</sub>(outpoint<sub>L</sub> || A)'', where ''outpoint<sub>L</sub>'' is the smallest outpoint lexicographically by txid and vout used in the transaction<ref name="why_smallest_outpoint"></ref> - === Sender === ==== Selecting inputs ==== @@ -301,10 +293,11 @@ The sending wallet performs coin selection as usual with the following restricti After the inputs have been selected, the sender can create one or more outputs for one or more silent payment addresses in the following manner: -* Generate the ''input_hash'' with the smallest outpoint lexicographically, using the method described above * Collect the private keys for each input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list * For each private key ''a<sub>i</sub>'' corresponding to a [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] taproot output, check that the private key produces a point with an even Y coordinate and negate the private key if not<ref name="why_negate_taproot_private_keys">'''Why do taproot private keys need to be checked?''' Recall from [https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki BIP340] that each X-only public key has two corresponding private keys, ''d'' and ''n - d''. To maintain parity between sender and receiver, it is necessary to use the private key corresponding to the even Y coordinate when performing the ECDH step since the receiver will assume the even Y coordinate when summing the taproot X-only public keys.</ref> * Let ''a = a<sub>1</sub> + a<sub>2</sub> + ... + a<sub>n</sub>'', where each ''a<sub>i</sub>'' has been negated if necessary +** If ''a = 0'', fail +* Let ''input_hash = hash<sub>BIP0352/Inputs</sub>(outpoint<sub>L</sub> || A)'', where ''outpoint<sub>L</sub>'' is the smallest ''outpoint'' lexicographically used in the transaction<ref name="why_smallest_outpoint"></ref> and ''A = a·G'' * Group receiver silent payment addresses by ''B<sub>scan</sub>'' (e.g. each group consists of one ''B<sub>scan</sub>'' and one or more ''B<sub>m</sub>'') * For each group: ** Let ''ecdh_shared_secret = input_hash·a·B<sub>scan</sub>'' @@ -335,8 +328,9 @@ A scan and spend key pair using BIP32 derivation are defined (taking inspiration If each of the checks in ''[[#scanning-silent-payment-eligible-transactions|Scanning silent payment eligible transactions]]'' passes, the receiving wallet must: -* Generate the ''input_hash'' with the smallest outpoint lexicographically, using the method described above * Let ''A = A<sub>1</sub> + A<sub>2</sub> + ... + A<sub>n</sub>'', where each ''A<sub>i</sub>'' is the public key of an input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list +** If ''A'' is the point at infinity, skip the transaction +* Let ''input_hash = hash<sub>BIP0352/Inputs</sub>(outpoint<sub>L</sub> || A)'', where ''outpoint<sub>L</sub>'' is the smallest ''outpoint'' lexicographically used in the transaction<ref name="why_smallest_outpoint"></ref> * Let ''ecdh_shared_secret = input_hash·b<sub>scan</sub>·A'' * Check for outputs: ** Let ''outputs_to_check'' be the taproot output keys from all taproot outputs in the transaction (spent and unspent). @@ -483,6 +477,17 @@ A malicious notification could potentially cause the following issues: Wallet designers can choose which tradeoffs they find appropriate. For example, a wallet could check the block filter to at least probabilistically confirm the likely existence of the UTXO, thus efficiently cutting down on spam. The payment could then be marked as unconfirmed until a scan is performed and the existence of the UTXO in accordance to the silent payment specification is verified. +== Change Log == + +To help implementers understand updates to this document, we attach a version number that resembles ''semantic versioning'' (<code>MAJOR.MINOR.PATCH</code>). +The <code>MAJOR</code> version is incremented if changes to the BIP are introduced that are incompatible with prior versions. +The <code>MINOR</code> version is incremented whenever the inputs or the output of an algorithm changes in a backward-compatible way or new backward-compatible functionality is added. +The <code>PATCH</code> version is incremented for other changes that are noteworthy (bug fixes, test vectors, important clarifications, etc.). + +* '''1.0.1''' (2024-06-22): +** Add steps to fail if private key sum is zero (for sender) or public key sum is point at infinity (for receiver), add corresponding test vectors. +* '''1.0.0''' (2024-05-08): +** Initial version, merged as BIP-352. == Acknowledgements == diff --git a/bip-0352/bitcoin_utils.py b/bip-0352/bitcoin_utils.py index 443c096..ee55f2d 100644 --- a/bip-0352/bitcoin_utils.py +++ b/bip-0352/bitcoin_utils.py @@ -1,6 +1,7 @@ import hashlib import struct from io import BytesIO +from ripemd160 import ripemd160 from secp256k1 import ECKey from typing import Union @@ -127,7 +128,7 @@ class CTxInWitness: def hash160(s: Union[bytes, bytearray]) -> bytes: - return hashlib.new("ripemd160", hashlib.sha256(s).digest()).digest() + return ripemd160(hashlib.sha256(s).digest()) def is_p2tr(spk: bytes) -> bool: diff --git a/bip-0352/reference.py b/bip-0352/reference.py index 9f43695..b4eaf94 100755 --- a/bip-0352/reference.py +++ b/bip-0352/reference.py @@ -117,7 +117,7 @@ def decode_silent_payment_address(address: str, hrp: str = "tsp") -> Tuple[ECPub return B_scan, B_spend -def create_outputs(input_priv_keys: List[Tuple[ECKey, bool]], input_hash: bytes, recipients: List[str], hrp="tsp") -> List[str]: +def create_outputs(input_priv_keys: List[Tuple[ECKey, bool]], outpoints: List[COutPoint], recipients: List[str], hrp="tsp") -> List[str]: G = ECKey().set(1).get_pubkey() negated_keys = [] for key, is_xonly in input_priv_keys: @@ -127,6 +127,10 @@ def create_outputs(input_priv_keys: List[Tuple[ECKey, bool]], input_hash: bytes, negated_keys.append(k) a_sum = sum(negated_keys) + if not a_sum.valid: + # Input privkeys sum is zero -> fail + return [] + input_hash = get_input_hash(outpoints, a_sum * G) silent_payment_groups: Dict[ECPubKey, List[ECPubKey]] = {} for recipient in recipients: B_scan, B_m = decode_silent_payment_address(recipient, hrp=hrp) @@ -236,9 +240,8 @@ if __name__ == "__main__": sending_outputs = [] if (len(input_pub_keys) > 0): - A_sum = reduce(lambda x, y: x + y, input_pub_keys) - input_hash = get_input_hash([vin.outpoint for vin in vins], A_sum) - sending_outputs = create_outputs(input_priv_keys, input_hash, given["recipients"], hrp="sp") + outpoints = [vin.outpoint for vin in vins] + sending_outputs = create_outputs(input_priv_keys, outpoints, given["recipients"], hrp="sp") # Note: order doesn't matter for creating/finding the outputs. However, different orderings of the recipient addresses # will produce different generated outputs if sending to multiple silent payment addresses belonging to the @@ -297,6 +300,10 @@ if __name__ == "__main__": add_to_wallet = [] if (len(input_pub_keys) > 0): A_sum = reduce(lambda x, y: x + y, input_pub_keys) + if A_sum.get_bytes() is None: + # Input pubkeys sum is point at infinity -> skip tx + assert expected["outputs"] == [] + continue input_hash = get_input_hash([vin.outpoint for vin in vins], A_sum) pre_computed_labels = { (generate_label(b_scan, label) * G).get_bytes(False).hex(): generate_label(b_scan, label).hex() diff --git a/bip-0352/ripemd160.py b/bip-0352/ripemd160.py new file mode 100644 index 0000000..1280136 --- /dev/null +++ b/bip-0352/ripemd160.py @@ -0,0 +1,130 @@ +# Copyright (c) 2021 Pieter Wuille +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test-only pure Python RIPEMD160 implementation.""" + +import unittest + +# Message schedule indexes for the left path. +ML = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +] + +# Message schedule indexes for the right path. +MR = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +] + +# Rotation counts for the left path. +RL = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +] + +# Rotation counts for the right path. +RR = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +] + +# K constants for the left path. +KL = [0, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e] + +# K constants for the right path. +KR = [0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0] + + +def fi(x, y, z, i): + """The f1, f2, f3, f4, and f5 functions from the specification.""" + if i == 0: + return x ^ y ^ z + elif i == 1: + return (x & y) | (~x & z) + elif i == 2: + return (x | ~y) ^ z + elif i == 3: + return (x & z) | (y & ~z) + elif i == 4: + return x ^ (y | ~z) + else: + assert False + + +def rol(x, i): + """Rotate the bottom 32 bits of x left by i bits.""" + return ((x << i) | ((x & 0xffffffff) >> (32 - i))) & 0xffffffff + + +def compress(h0, h1, h2, h3, h4, block): + """Compress state (h0, h1, h2, h3, h4) with block.""" + # Left path variables. + al, bl, cl, dl, el = h0, h1, h2, h3, h4 + # Right path variables. + ar, br, cr, dr, er = h0, h1, h2, h3, h4 + # Message variables. + x = [int.from_bytes(block[4*i:4*(i+1)], 'little') for i in range(16)] + + # Iterate over the 80 rounds of the compression. + for j in range(80): + rnd = j >> 4 + # Perform left side of the transformation. + al = rol(al + fi(bl, cl, dl, rnd) + x[ML[j]] + KL[rnd], RL[j]) + el + al, bl, cl, dl, el = el, al, bl, rol(cl, 10), dl + # Perform right side of the transformation. + ar = rol(ar + fi(br, cr, dr, 4 - rnd) + x[MR[j]] + KR[rnd], RR[j]) + er + ar, br, cr, dr, er = er, ar, br, rol(cr, 10), dr + + # Compose old state, left transform, and right transform into new state. + return h1 + cl + dr, h2 + dl + er, h3 + el + ar, h4 + al + br, h0 + bl + cr + + +def ripemd160(data): + """Compute the RIPEMD-160 hash of data.""" + # Initialize state. + state = (0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0) + # Process full 64-byte blocks in the input. + for b in range(len(data) >> 6): + state = compress(*state, data[64*b:64*(b+1)]) + # Construct final blocks (with padding and size). + pad = b"\x80" + b"\x00" * ((119 - len(data)) & 63) + fin = data[len(data) & ~63:] + pad + (8 * len(data)).to_bytes(8, 'little') + # Process final blocks. + for b in range(len(fin) >> 6): + state = compress(*state, fin[64*b:64*(b+1)]) + # Produce output. + return b"".join((h & 0xffffffff).to_bytes(4, 'little') for h in state) + + +class TestFrameworkKey(unittest.TestCase): + def test_ripemd160(self): + """RIPEMD-160 test vectors.""" + # See https://homes.esat.kuleuven.be/~bosselae/ripemd160.html + for msg, hexout in [ + (b"", "9c1185a5c5e9fc54612808977ee8f548b2258d31"), + (b"a", "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"), + (b"abc", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"), + (b"message digest", "5d0689ef49d2fae572b881b123a85ffa21595f36"), + (b"abcdefghijklmnopqrstuvwxyz", + "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"), + (b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "12a053384a9c0c88e405a06c27dcf49ada62eb2b"), + (b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "b0e20b6e3116640286ed3a87a5713079b21f5189"), + (b"1234567890" * 8, "9b752e45573d4b39f4dbd3323cab82bf63326bfb"), + (b"a" * 1000000, "52783243c1697bdbe16d37f97f68f08325dc1528") + ]: + self.assertEqual(ripemd160(msg).hex(), hexout) diff --git a/bip-0352/send_and_receive_test_vectors.json b/bip-0352/send_and_receive_test_vectors.json index f9b205b..264f7be 100644 --- a/bip-0352/send_and_receive_test_vectors.json +++ b/bip-0352/send_and_receive_test_vectors.json @@ -2669,5 +2669,92 @@ } } ] + }, + { + "comment": "Input keys sum up to zero / point at infinity: sending fails, receiver skips tx", + "sending": [ + { + "given": { + "vin": [ + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 0, + "scriptSig": "", + "txinwitness": "024730440220085003179ce1a3a88ce0069aa6ea045e140761ab88c22a26ae2a8cfe983a6e4602204a8a39940f0735c8a4424270ac8da65240c261ab3fda9272f6d6efbf9cfea366012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + }, + "private_key": "a6df6a0bb448992a301df4258e06a89fe7cf7146f59ac3bd5ff26083acb22ceb" + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 1, + "scriptSig": "", + "txinwitness": "0247304402204586a68e1d97dd3c6928e3622799859f8c3b20c3c670cf654cc905c9be29fdb7022043fbcde1689f3f4045e8816caf6163624bd19e62e4565bc99f95c533e599782c012103557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149860538b5575962776ed0814ae222c7d60c72d7b" + } + }, + "private_key": "592095f44bb766d5cfe20bda71f9575ed2df6b9fb9addc7e5fdffe0923841456" + } + ], + "recipients": [ + "sp1qqtrqglu5g8kh6mfsg4qxa9wq0nv9cauwfwxw70984wkqnw2uwz0w2qnehen8a7wuhwk9tgrzjh8gwzc8q2dlekedec5djk0js9d3d7qhnq6lqj3s" + ] + }, + "expected": { + "outputs": [ + [] + ] + } + } + ], + "receiving": [ + { + "given": { + "vin": [ + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 0, + "scriptSig": "", + "txinwitness": "024730440220085003179ce1a3a88ce0069aa6ea045e140761ab88c22a26ae2a8cfe983a6e4602204a8a39940f0735c8a4424270ac8da65240c261ab3fda9272f6d6efbf9cfea366012102557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149d9e24f9fab4e35bf1a6df4b46cb533296ac0792" + } + } + }, + { + "txid": "3a286147b25e16ae80aff406f2673c6e565418c40f45c071245cdebc8a94174e", + "vout": 1, + "scriptSig": "", + "txinwitness": "0247304402204586a68e1d97dd3c6928e3622799859f8c3b20c3c670cf654cc905c9be29fdb7022043fbcde1689f3f4045e8816caf6163624bd19e62e4565bc99f95c533e599782c012103557ef3e55b0a52489b4454c1169e06bdea43687a69c1f190eb50781644ab6975", + "prevout": { + "scriptPubKey": { + "hex": "00149860538b5575962776ed0814ae222c7d60c72d7b" + } + } + } + ], + "outputs": [ + "0000000000000000000000000000000000000000000000000000000000000000" + ], + "key_material": { + "spend_priv_key": "0000000000000000000000000000000000000000000000000000000000000001", + "scan_priv_key": "0000000000000000000000000000000000000000000000000000000000000002" + }, + "labels": [] + }, + "expected": { + "addresses": [ + "sp1qqtrqglu5g8kh6mfsg4qxa9wq0nv9cauwfwxw70984wkqnw2uwz0w2qnehen8a7wuhwk9tgrzjh8gwzc8q2dlekedec5djk0js9d3d7qhnq6lqj3s" + ], + "outputs": [] + } + } + ] } -]
\ No newline at end of file +] diff --git a/bip-0353.mediawiki b/bip-0353.mediawiki new file mode 100644 index 0000000..1646672 --- /dev/null +++ b/bip-0353.mediawiki @@ -0,0 +1,130 @@ +<pre> + BIP: 353 + Layer: Applications + Title: DNS Payment Instructions + Author: Matt Corallo <bip353@bluematt.me> + Bastien Teinturier <bastien@acinq.fr> + Comments-Summary: No comments yet. + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0353 + Status: Draft + Type: Standards Track + Created: 2024-02-10 + License: CC0-1.0 + Post-History: 2024-02-13: https://groups.google.com/g/bitcoindev/c/uATaflkYglQ [bitcoin-dev] Mapping Human-Readable Names to Payment Instructions +</pre> + + +==Copyright== + +This BIP is licensed under the CC0-1.0 license. + +==Abstract== +This BIP proposes a standard format for encoding [[bip-0021.mediawiki|BIP 21]] URI schemes in DNS TXT records. + +==Motivation== +Various Bitcoin and other cryptocurrency applications have developed human-readable names for payment instructions over time, with marketplace adoption signaling strong demand for it from users. + +The DNS provides a standard, global, hierarchical namespace mapping human-readable labels to records of various forms. Using DNSSEC, the DNS provides cryptographic guarantees using a straightforward PKI which follows the hierarchical nature of the DNS, allowing for stateless and even offline validation of DNS records from a single trusted root. + +Further, because DNS queries are generally proxied through ISP-provided or other resolvers, DNS queries usually do not directly expose the queryer's IP address. Further, because of the prevalence of open resolvers, the simplicity of the protocol, and broad availability of DNS recursive resolver implementations, finding a proxy for DNS records is trivial. + +Thus, using TXT records to store Bitcoin payment instructions allows for human-readable Bitcoin payment destinations which can be trivially verified on hardware wallets and which can be resolved relatively privately. + +==Specification== + +=== General rules for handling === +Bitcoin wallets MUST NOT prefer to use DNS-based resolving when methods with explicit public keys or addresses are available. In other words, if a standard Bitcoin address or direct BIP 21 URI is available or would suffice, Bitcoin wallets MUST prefer to use that instead. + +=== Records === +Payment instructions are indexed by both a user and a domain. Instructions for a given `user` and `domain` are stored at `user`.user._bitcoin-payment.`domain` in a single TXT record. + +All payment instructions MUST be DNSSEC-signed. + +Payment instructions MAY resolve through CNAME or DNAME records as long as all such records and the ultimate records pointed to by them are DNSSEC signed. + +User and domain names which are not expressible using standard printable ASCII MUST be encoded using the punycode IDN encoding defined in [[https://datatracker.ietf.org/doc/html/rfc3492|RFC 3492]] and [[https://datatracker.ietf.org/doc/html/rfc5891|RFC 5891]]. + +Note that because resolvers are not required to support resolving non-ASCII identifiers, wallets SHOULD avoid using non-ASCII identifiers. + +=== Resolution === + +Clients resolving Bitcoin payment instructions MUST ignore any TXT records at the same label which do not begin with (ignoring case) "bitcoin:". Resolvers encountering multiple "bitcoin:"-matching TXT records at the same label MUST treat the records as invalid and refuse to use any payment instructions therein. + +Clients resolving Bitcoin payment instructions MUST fully validate DNSSEC signatures leading to the DNS root (including any relevant CNAME or DNAME records) and MUST NOT accept DNSSEC signatures which use SHA-1 or RSA with keys shorter than 1024 bits. Resolvers MAY accept SHA-1 DS records. + +Clients resolving Bitcoin payment instructions MUST NOT trust a remote resolver to validate DNSSEC records on their behalf. + +Clients resolving Bitcoin payment instructions MUST support resolving through CNAME or DNAME records. + +Resolvers MAY support resolving non-ASCII user and domain identifiers. Resolvers which do support non-ASCII user and domain identifiers MUST take precautions to prevent homograph attacks and SHOULD consider denying paste functionality when entering non-ASCII identifiers. Wallets which do not take any such precautions MUST instead display non-ASCII user and domain identifiers using their raw punycode. As such, wallets SHOULD NOT create identifiers which are not entirely printable ASCII. + +While clients MAY cache the payment instructions they receive from the DNS, clients MUST NOT cache the payment instructions received from the DNS for longer than the TTL provided by their DNS resolver, and further MUST NOT cache the payment instructions for longer than the lowest initial TTL (which is signed as a part of DNSSEC signatures) received in the full DNSSEC chain leading from the DNS root to the resolved TXT record. + +=== Address Reuse === + +Payment instructions with on-chain addresses which will be re-used SHOULD be rotated as regularly as possible to reduce address reuse. Such payment instructions SHOULD also use a relatively short DNS TTL to ensure regular rotation takes effect quickly. In cases where this is not practical, payment instructions SHOULD NOT contain on-chain addresses (i.e. the URI path SHOULD be empty). + +Payment instructions which do contain on-chain addresses which will be re-used SHOULD be rotated after any transaction to such an address is confirmed on-chain. + +=== Display === + +Wallets SHOULD parse recipient information in the form `user`@`domain` or ₿`user`@`domain` and resolve such entry into recipient information using the above record. Similarly, wallets accepting payment information from external devices (e.g. hardware wallets) SHOULD accept RFC 9102-formatted proofs (as a series of unsorted `AuthenticationChain` records) and, if they verify, SHOULD display the recipient in the form ₿`user`@`domain`. For the avoidance of doubt, the ₿ is *not* included in the DNS label which is resolved. + +Wallets providing users the ability to "copy" their address information generally SHOULD copy the underlying URI directly in order to avoid the DNS indirection. However, wallets providing users the ability to copy their human-readable address information MUST include the ₿ prefix (i.e. copy it in the form ₿`user`@`domain`). + +== Rationale == + +=== Display === + +There are several ways in which human-readable payment instructions could be displayed in wallets. In order to ensure compatibility with existing human-readable names schemes, @ is used as the separator between the `user` and `domain` parts. However, simply using the @ separator can lead to confusion between email addresses on a given domain and payment instructions on a domain. In order to somewhat reduce the incidence of such confusion, a ₿ prefix is used. + +=== Rotation === + +On-chain addresses which are re-used (i.e. not including schemes like [[bip-0352.mediawiki|Silent Payments]]) need to be rotated to avoid contributing substantially to address reuse. However, rotating them on a timer or any time a transaction enters the mempool could lead to substantial overhead from excess address generation. Instead, rotating addresses any time a transaction is confirmed on-chain ensures address rotation happens often while bounding the maximum number of addresses needed to one per block, which grows very slowly and will not generate an address set too large to handle while scanning the chain going forward. + +=== Alternatives === +There are many existing schemes to resolve human-readable names to cryptocurrency payment instructions. Sadly, these current schemes suffer from a myriad of drawbacks, including (a) lacking succinct proofs of namespace to public key mappings, (b) revealing sender IP addresses to recipients or other intermediaries as a side-effect of payment, (c) relying on the bloated TLS Certificate Authority infrastructure, or (d) lacking open access, not allowing anyone to create a namespace mapping. + +==== DNS Rather than blockchain-based solutions ==== +There are many blockchain-based alternatives to the DNS which feature better censorship-resistance and, in many cases, security. However, here we chose to use the standard ICANN-managed DNS namespace as many blockchain-based schemes suffer from (a), above (though in some cases this could be addressed with cryptographic SNARK schemes). Further, because they do not have simple client-side querying ability, many of these schemes use trusted intermediaries which resolve names on behalf of clients. This reintroduces drawbacks (b) and often (c) as well. + +Finally, it is worth noting that none of the blockchain-based alternatives to the DNS have had material adoption outside of their specific silos, and committing Bitcoin wallets to rely on a separate system which doesn't see broad adoption may not be sustainable. + +==== DNS Rather than HTTP-based solutions ==== +HTTP(s)-based payment instruction resolution protocols suffer from drawbacks (a), (b), and (c), above, and generally shouldn't be considered a serious alternative for payment instruction resolution. + +==== Private DNS Querying ==== +While public recursive DNS resolvers are very common (e.g. 1.1.1.1, 8.8.8.8, and 9.9.9.9), using such resolvers directly (even after validating DNSSEC signatures) introduces drawback (b), at least in regard to a centralized intermediary. Resolving payment instructions recursively locally using a resolver on the same local network or in the paying application would instead introduce drawback (b) directly to the recipient, which may well be worse. + +For payers not using VPN or other proxying technologies, they generally trust their ISP to not snoop on their DNS requests anyway, so using ISP-provided recursive DNS resolvers is likely the best option. + +However, for the best privacy, payers are encouraged to perform DNS resolution over Tor or another VPN technology. + +Lightning payers should consider utilizing DNS resolution over native onion messages, using the protocol described in [[https://github.com/lightning/blips/blob/master/blip-0032.md|BLIP 32]] + +=== DNS Enumeration === + +In most cases where payments are accepted from any third-party, user enumeration is practical by simply attempting to send small value payments to a list of possible user names. However, storing all valid users in the DNS directly may make such enumeration marginally more practical. Thus, those wishing to avoid such enumeration should carefully ensure all DNS names return valid payment instructions. Note when doing so that wildcard records are identified as such by the DNSSEC RRSIG labels counter and are differentiable from non-wildcard records. + +== Backwards Compatibility == + +This work is intended to extend and subsume the existing "Lightning Address" scheme, which maps similar names (without the ₿ prefix) using HTTPS servers to Lightning BOLT 11 payment instructions. Wallets implementing this scheme MAY fall back to existing "Lightning Address" logic if DNS resolution fails but SHOULD NOT do so after this scheme is sufficiently broadly deployed to avoid leaking sender IP address information. + +== Examples == + +`matt@mattcorallo.com` resolves to +`matt.user._bitcoin-payment.mattcorallo.com. 3600 IN TXT "bitcoin:?lno=lno1qsgqmqvgm96frzdg8m0gc6nzeqffvzsqzrxqy32afmr3jn9ggkwg3egfwch2hy0l6jut6vfd8vpsc3h89l6u3dm4q2d6nuamav3w27xvdmv3lpgklhg7l5teypqz9l53hj7zvuaenh34xqsz2sa967yzqkylfu9xtcd5ymcmfp32h083e805y7jfd236w9afhavqqvl8uyma7x77yun4ehe9pnhu2gekjguexmxpqjcr2j822xr7q34p078gzslf9wpwz5y57alxu99s0z2ql0kfqvwhzycqq45ehh58xnfpuek80hw6spvwrvttjrrq9pphh0dpydh06qqspp5uq4gpyt6n9mwexde44qv7lstzzq60nr40ff38u27un6y53aypmx0p4qruk2tf9mjwqlhxak4znvna5y"` +Note that `lno` indicates a value containing a lightning BOLT12 offer. + +== Reference Implementations == +* A DNSSEC proof generation and validation implementation can be found at https://git.bitcoin.ninja/index.cgi?p=dnssec-prover;a=summary +* A lightning-specific name to payment instruction resolver can be found at https://git.bitcoin.ninja/index.cgi?p=lightning-resolver;a=summary +* Reference implementations for parsing the URI contents can be found in [[bip-0021.mediawiki|BIP 21]]. + +== Acknowledgements == + +Thanks to Rusty Russell for the concrete address rotation suggestion. + +Thanks to the Bitcoin Design Community, and especially Christoph Ono for lots of discussion, analysis, and UX mockups in how human-readable payment instructions should be displayed. + +Thanks to Andrew Kaizer for the suggestion to explicitly restrict cache lifetime to the relevant DNS TTLs. diff --git a/bip-0373.mediawiki b/bip-0373.mediawiki new file mode 100644 index 0000000..d9dec45 --- /dev/null +++ b/bip-0373.mediawiki @@ -0,0 +1,216 @@ +<pre> + BIP: 373 + Layer: Applications + Title: MuSig2 PSBT Fields + Author: Ava Chow <me@achow101.com> + Comments-Summary: No comments yet. + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0373 + Status: Draft + Type: Standards Track + Created: 2024-01-15 + License: CC0-1.0 +</pre> + +==Introduction== + +===Abstract=== + +This document proposes additional fields for BIP 174 PSBTv0 and BIP 370 PSBTv2 that allow for BIP +327 MuSig2 Multi-Signature data to be included in a PSBT of any version. These will be fields for +the participants' keys, the public nonces, and the partial signatures produced with MuSig2. + +===Copyright=== + +This BIP is licensed under the Creative Commons CC0 1.0 Universal license. + +===Motivation=== + +BIP 327 specifies a way to create BIP 340 compatible public keys and signatures using the MuSig2 +Multi-Signature scheme. The existing PSBT fields are unable to support MuSig2 as it introduces new +concepts and additional rounds of communication. Therefore new fields must be defined to allow PSBTs +to carry the information necessary to produce a valid signature with MuSig2. + +==Specification== + +The new per-input types are defined as follows: + +{| +! Name +! <tt><keytype></tt> +! <tt><keydata></tt> +! <tt><valuedata></tt> +! Versions Requiring Inclusion +! Versions Requiring Exclusion +! Versions Allowing Inclusion +|- +| rowspan="2"|MuSig2 Participant Public Keys +| rowspan="2"|<tt>PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS = 0x1a</tt> +| <tt><33 byte plain aggregate pubkey></tt> +| <tt><33 byte compressed pubkey>*</tt> +| rowspan="2"| +| rowspan="2"| +| rowspan="2"| 0, 2 +|- +| The MuSig2 aggregate plain public key<ref>'''Why the plain aggregate public key instead of x-only?''' +BIP 32 requires public keys to include their evenness byte. Aggregate public keys are expected to be +derived from, following [[bip-0328.mediawiki|BIP 328]], and therefore will +need to include the evenness. Furthermore, PSBT_IN_TAP_BIP32_DERIVATION fields include fingerprints +to identify master keys, and these fingerprints require full compressed public keys. By including +the aggregate key as a full public key, signers that are unaware of the MuSig2 outside of the PSBT +will still be able to identify which keys are derived from the aggregate key by computing and then +comparing the fingerprints. This is necessary for the signer to apply the correct tweaks to their +partial signature.</ref> from the <tt>KeyAgg</tt> algorithm. This key may or may not +be in the script directly (as x-only). It may instead be a parent public key from which the public keys in the +script were derived. +| A list of the compressed public keys of the participants in the MuSig2 aggregate key in the order +required for aggregation. If sorting was done, then the keys must be in the sorted order. +|- +| rowspan="2"|MuSig2 Public Nonce +| rowspan="2"|<tt>PSBT_IN_MUSIG2_PUB_NONCE = 0x1b</tt> +| <tt><33 byte compressed pubkey> <33 byte plain pubkey> <32 byte hash or omitted></tt> +| <tt><66 byte public nonce></tt> +| rowspan="2"| +| rowspan="2"| +| rowspan="2"| 0, 2 +|- +| The compressed public key of the participant providing this nonce, followed by the plain public +key the participant is providing the nonce for, followed by the BIP 341 tapleaf hash of +the Taproot leaf script that will be signed. If the aggregate key is the taproot internal key or the +taproot output key, then the tapleaf hash must be omitted. The plain public key must be +the key found in the script and not the aggregate public key that it was derived from, if it was +derived from an aggregate key. +| The public nonce produced by the <tt>NonceGen</tt> algorithm. +|- +| rowspan="2"|MuSig2 Participant Partial Signature +| rowspan="2"|<tt>PSBT_IN_MUSIG2_PARTIAL_SIG = 0x1c</tt> +| <tt><33 byte compressed pubkey> <33 byte plain pubkey> <32 byte hash or omitted></tt> +| <tt><32 byte partial signature></tt> +| rowspan="2"| +| rowspan="2"| +| rowspan="2"| 0, 2 +|- +| The compressed public key of the participant providing this partial signature, followed by the +plain public key the participant is providing the signature for, followed by the BIP 341 tapleaf hash +of the Taproot leaf script that will be signed. If the aggregate key is the taproot internal key or +the taproot output key, then the tapleaf hash must be omitted. Note that the plain public key must +be the key found in the script and not the aggregate public key that it was derived from, if it was +derived from an aggregate key. +| The partial signature produced by the <tt>Sign</tt> algorithm. +|} + +The new per-output types are defined as follows: + +{| +! Name +! <tt><keytype></tt> +! <tt><keydata></tt> +! <tt><valuedata></tt> +! Versions Requiring Inclusion +! Versions Requiring Exclusion +! Versions Allowing Inclusion +|- +| rowspan="2"|MuSig2 Participant Public Keys +| rowspan="2"|<tt>PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS = 0x08</tt> +| <tt><33 byte compressed pubkey></tt> +| <tt><33 byte compressed pubkey>*</tt> +| rowspan="2"| +| rowspan="2"| +| rowspan="2"|0, 2 +|- +| The MuSig2 aggregate plain public key from the <tt>KeyAgg</tt> algorithm. This key may or may not +be in the script directly. It may instead be a parent public key from which the public keys in the +script were derived. +| A list of the compressed public keys of the participants in the MuSig2 aggregate key in the order +required for aggregation. If sorting was done, then the keys must be in the sorted order. +|} + +==Roles== + +===Updater=== + +When an updater observes a Taproot output which involves a MuSig2 aggregate public key that it is +aware if, it can add a <tt>PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS</tt> field containing the public keys +of the participants. This aggregate public key may be directly in the script, the Taproot internal +key, the Taproot output key, or a public key from which the key in the script was derived from. + +An aggregate public key that appears directly in the script or internal key may be from the result +of deriving child pubkeys from participant xpubs. If the updater has this derivation information, it +should also add <tt>PSBT_IN_TAP_BIP32_DERIVATION</tt> for each participant public key. + +If the public key found was derived from an aggregate public key, then all MuSig2 PSBT fields for +that public key should contain the aggregate public key rather than the found pubkey itself. The +updater should also add <tt>PSBT_IN_TAP_BIP32_DERIVATION</tt> that contains the derivation path used +to derive the found pubkey from the aggregate pubkey. +Derivation from the aggregate pubkey can be assumed to follow [[bip-0328.mediawiki|BIP 328]] +if there is no <tt>PSBT_IN_GLOBAL_XPUB</tt> that specifies the synthetic xpub for the aggregate +public key. + +Updaters should add <tt>PSBT_OUT_MUSIG2_PARTICIPANT_PUBKEYS</tt> and +<tt>PSBT_OUT_TAP_BIP32_DERIVATION</tt> similarly to inputs to aid in change detection. + +===Signer=== + +To determine whether a signer is a participant in the MuSig2 aggregate key, the signer should first +look at all <tt>PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS</tt> and see if any key which it knows the +private key for appears as a participant in any aggregate pubkey. Signers should also check whether +any of the keys in <tt>PSBT_IN_TAP_BIP32_DERIVATION</tt> belong to it, and if any of those keys +appear in as a participant in <tt>PSBT_IN_MUSIG2_PARTICIPANT_PUBKEYS</tt>. + +For each aggregate public key that the signer is a participant of that it wants +to produce a signature for, if the signer does not find an existing +<tt>PSBT_IN_MUSIG2_PUB_NONCE</tt> field for its key, then it should add one using +the <tt>NonceGen</tt> algorithm (or one of its variations) to produce a public +nonce that is added in a <tt>PSBT_IN_MUSIG2_PUB_NONCE</tt> field. However +signers must keep in mind that '''improper nonce usage can compromise private +keys.''' Please see BIP 327 for best practices on nonce generation and usage. + +Once all signers have added their <tt>PSBT_IN_MUSIG2_PUB_NONCE</tt> fields, each signer will perform +the <tt>NonceAgg</tt> algorithm followed by the <tt>Sign</tt> algorithm in order to produce the +partial signature for their key. The result will be added to the PSBT in a +<tt>PSBT_IN_MUSIG2_PARTIAL_SIG</tt> field. + +Signers must remember to apply any relevant tweaks such as a tweak that is the result of performing +BIP 32 unhardened dervation with the aggregate public key as the parent key. + +If all other signers have provided a <tt>PSBT_IN_MUSIG2_PARTIAL_SIG</tt>, then the final signer may +perform the <tt>PartialSigAgg</tt> algorithm and produce a BIP 340 compatible signature that can be +placed into a <tt>PSBT_IN_TAP_KEY_SIG</tt> or a <tt>PSBT_IN_TAP_SCRIPT_SIG</tt>. + +===Finalizer=== + +A finalizer may perform the same <tt>PartialSigAgg</tt> step as the final signer if it has not +already been done. + +Otherwise, the resulting signature is a BIP 340 compatible signature and finalizers should treat it +as such. + +==Backwards Compatibility== + +These are simply new fields added to the existing PSBT format. Because PSBT is designed to be +extensible, old software will ignore the new fields. + +Reusing <tt>PSBT_IN_TAP_BIP32_DERIVATION</tt> to provide derivation paths for participant public +keys may cause software unaware of MuSig2 to produce a signature for that public key. This is still +safe. If that public key does not directly appear in the leaf script that was signed, then the +signature produced will not be useful and so cannot be replayed. If the public key does directly +appear in the leaf script, then the signer will have validated the script as if it did not involve a +MuSig2 and will have found it acceptable in order for it to have produced a signature. In either +case, producing a signature does not give rise to the possibility of losing funds. + +==Test Vectors== + +TBD + +==Rationale== + +<references/> + +==Reference implementation== + +The reference implementation of the PSBT format is available at TBD. + +==Acknowledgements== + +Thanks to Sanket Kanjalkar whose notes on this topic formed the initial basis of this BIP. Also +thanks to Pieter Wuille, Jonas Nick, Tim Ruffing, Marko Bencun, Salvatore Ingala, and all others who +have participated in discussions about these fields. diff --git a/bip-0379.md b/bip-0379.md new file mode 100644 index 0000000..10755d4 --- /dev/null +++ b/bip-0379.md @@ -0,0 +1,423 @@ +<pre> + BIP: 379 + Layer: Applications + Title: Miniscript + Author: Pieter Wuille <pieter@wuille.net> + Andrew Poelstra <andrew.poelstra@gmail.com> + Sanket Kanjalkar <sanket1729@gmail.com> + Antoine Poinsot <darosior@protonmail.com> + Ava Chow <me@achow101.com> + Comments-Summary: No comments yet. + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0379 + Status: Draft + Type: Informational + Created: 2023-10-10 + License: CC0-1.0 +</pre> + +## Abstract + +This document specifies Miniscript, a language for writing (a subset of) Bitcoin Scripts in a +structured way, enabling analysis, composition, generic signing and more. + +## Copyright + +This document is licensed under the Creative Commons CC0 1.0 Universal license. + +## Motivation + +Bitcoin Script is an unusual stack-based language with many edge cases, designed for implementing +spending conditions consisting of various combinations of signatures, hash locks, and time locks. +Yet, despite being limited in functionality, it is still highly nontrivial to: + +* Given a combination of spending conditions, finding the most economical script to implement it. +* Given two scripts, construct a script that implements a composition of their spending conditions (e.g. a multisig where one of the "keys" is another multisig). +* Given a script, find out what spending conditions it permits. +* Given a script and access to a sufficient set of private keys, construct a general satisfying witness for it. +* Given a script, be able to predict the cost of spending an output. +* Given a script, know whether particular resource limitations like the ops limit might be hit when spending. + +Miniscript functions as a representation for scripts that makes this sort of operations possible. +It has a structure that allows composition. It is very easy to statically analyze for various +properties (spending conditions, correctness, security properties, malleability, ...). It can be +targeted by spending policy compilers. Finally, compatible scripts can easily be converted to +Miniscript form - avoiding the need for additional metadata for e.g. signing devices that support +it. + +## Specification + +These specifications apply to P2WSH ([BIP 141](bip-0141.mediawiki)) and Tapscript ([BIP 342](bip-0342.mediawiki)) scripts, with only minor +variations between the two. Differences are noted inline. Unless explicitly stated otherwise, +specifications apply to both. P2SH and bare scripts are excluded from this specification. + +### Translation Table + +Miniscript consists of a set of script *fragments* which are designed to be safely and correctly composabe. + +This table shows all Miniscript *fragments* and their associated semantics and Bitcoin Script. +Fragments that do not change the semantics of their subexpressions are called *wrappers*. Normal +fragments use a `fragment(arg1,arg2,...)` notation, while wrappers are written using +prefixes separated from other fragments by a colon. The colon is dropped between subsequent +wrappers; e.g. `dv:older(144)` is the `d:` wrapper applied to the +`v:` wrapper applied to the `older` fragment for 144 blocks. + +The `pk`, `pkh`, and `and_n` fragments and `t:`, +`l:`, and `u:` wrappers are syntactic sugar for other Miniscripts, as listed +in the table below. Note that `<20>` are in hex representation in this document. + +Miniscript fragments are expected to be used in [BIP 382](bip-0382.mediawiki) `wsh()` descriptors +and [BIP 386](bip-0386.mediawiki) `tr()` descriptors. Key expressions are specified in +[BIP 380](bip-0380.mediawiki#user-content-Key_Expressions). Additionally, BIPs 382 and 386 specify +restrictions on key expressions and what they resolve to - these apply to key expressions in +Miniscript. BIP 382's key expression restrictions apply to Miniscript in P2WSH contexts, and BIP +386's key expression restrictions apply to Miniscript in P2TR contexts. From a user's perspective, +Miniscript is not a separate language, but rather a significant expansion of the descriptor language. + +| Semantics | Miniscript Fragment | Bitcoin Script +|----------------------------------------------------------|-------------------------------|--------------- +| false | `0` | `0` +| true | `1` | `1` +| check(key) | `pk_k(key)` | `<key>` +| | `pk_h(key)` | `DUP HASH160 <HASH160(key)> EQUALVERIFY ` +| | `pk(key)` = `c:pk_k(key)` | `<key> CHECKSIG` +| | `pkh(key)` = `c:pk_h(key)` | `DUP HASH160 <HASH160(key)> EQUALVERIFY CHECKSIG` +| nSequence ≥ n (and compatible) | `older(n)` | `<n> CHECKSEQUENCEVERIFY` +| nLockTime ≥ n (and compatible) | `after(n)` | `<n> CHECKLOCKTIMEVERIFY` +| len(x) = 32 and SHA256(x) = h | `sha256(h)` | `SIZE <20> EQUALVERIFY SHA256 <h> EQUAL` +| len(x) = 32 and HASH256(x) = h | `hash256(h)` | `SIZE <20> EQUALVERIFY HASH256 <h> EQUAL` +| len(x) = 32 and RIPEMD160(x) = h | `ripemd160(h)` | `SIZE <20> EQUALVERIFY RIPEMD160 <h> EQUAL` +| len(x) = 32 and HASH160(x) = h | `hash160(h)` | `SIZE <20> EQUALVERIFY HASH160 <h> EQUAL` +| (X and Y) or Z | `andor(X,Y,Z)` | `[X] NOTIF [Z] ELSE [Y] ENDIF` +| X and Y | `and_v(X,Y)` | `[X] [Y]` +| | `and_b(X,Y)` | `[X] [Y] BOOLAND` +| | `and_n(X,Y)` = `andor(X,Y,0)` | `[X] NOTIF 0 ELSE [Y] ENDIF` +| X or Z | `or_b(X,Z)` | `[X] [Z] BOOLOR` +| | `or_c(X,Z)` | `[X] NOTIF [Z] ENDIF` +| | `or_d(X,Z)` | `[X] IFDUP NOTIF [Z] ENDIF` +| | `or_i(X,Z)` | `IF [X] ELSE [Z] ENDIF` +| X_1 + ... + X_n = k | `thresh(k,X_1,...,X_n)` | `[X_1] [X_2] ADD ... [X_n] ADD ... <k> EQUAL` +| check(key_1) + ... + check(key_n) = k *(P2WSH only)* | `multi(k,key_1,...,key_n)` | `<k> <key_1> ... <key_n> <n> CHECKMULTISIG` +| check(key_1) + ... + check(key_n) = k *(Tapscript only)* | `multi_a(k,key_1,...,key_n)` | `<key_1> CHECKSIG <key_2> CHECKSIGADD ... <key_n> CHECKSIGADD <k> NUMEQUAL` +| X (identities) | `a:X` | `TOALTSTACK [X] FROMALTSTACK` +| | `s:X` | `SWAP [X]` +| | `c:X` | `[X] CHECKSIG` +| | `t:X` = `and_v(X,1)` | `[X] 1` +| | `d:X` | `DUP IF [X] ENDIF` +| | `v:X` | `[X] VERIFY (or VERIFY version of last opcode in [X])` +| | `j:X` | `SIZE 0NOTEQUAL IF [X] ENDIF` +| | `n:X` | `[X] 0NOTEQUAL` +| | `l:X` = `or_i(0,X)` | `IF 0 ELSE [X] ENDIF` +| | `u:X` = `or_i(X,0)` | `IF [X] ELSE 0 ENDIF` + +### Type System + +Not every Miniscript expression can be composed with every other. Some return their result by +putting true or false on the stack; others can only abort or continue. Some require subexpressions +that consume an exactly known number of arguments, while others need a subexpression that has a +nonzero top stack element to satisfy. To model all these properties, we define a correctness type +system for Miniscript. + +#### Correctness + +Every miniscript expression has one of four basic types: "**B**" (base), "**V**" (verify), +"**K**" (key) and "**W**" (wrapped). Then there are 5 type modifiers that guarantee additional +properties: "**z**" (zero-arg), "**o**" (one-arg), "**n**" (nonzero), "**d**" +(dissatisfiable), and "**u**" (unit). + +The following table lists the correctness requirements for each of the Miniscript expressions, and +its type properties in function of those of their subexpressions. + +| Miniscript | Requires | Type | Properties +|------------------------------|-------------------------------------------------------|-------------|----------- +| `0` | | B | z; u; d +| `1` | | B | z; u +| `pk_k(key)` | | K | o; n; d; u +| `pk_h(key)` | | K | n; d; u +| `older(n)`, `after(n)` | 1 ≤ n < 2<sup>31</sup> | B | z +| `sha256(h)` | | B | o; n; d; u +| `ripemd160(h)` | | B | o; n; d; u +| `hash256(h)` | | B | o; n; d; u +| `hash160(h)` | | B | o; n; d; u +| `andor(X,Y,Z)` | X is Bdu; Y and Z are both B, K, or V | same as Y/Z | z=z<sub>X</sub>z<sub>Y</sub>z<sub>Z</sub>; o=z<sub>X</sub>o<sub>Y</sub>o<sub>Z</sub> or o<sub>X</sub>z<sub>Y</sub>z<sub>Z</sub>; u=u<sub>Y</sub>u<sub>Z</sub>; d=d<sub>Z</sub> +| `and_v(X,Y)` | X is V; Y is B, K, or V | same as Y | z=z<sub>X</sub>z<sub>Y</sub>; o=z<sub>X</sub>o<sub>Y</sub> or z<sub>Y</sub>o<sub>X</sub>; n=n<sub>X</sub> or z<sub>X</sub>n<sub>Y</sub>; u=u<sub>Y</sub> +| `and_b(X,Y)` | X is B; Y is W | B | z=z<sub>X</sub>z<sub>Y</sub>; o=z<sub>X</sub>o<sub>Y</sub> or z<sub>Y</sub>o<sub>X</sub>; n=n<sub>X</sub> or z<sub>X</sub>n<sub>Y</sub>; d=d<sub>X</sub>d<sub>Y</sub>; u +| `or_b(X,Z)` | X is Bd; Z is Wd | B | z=z<sub>X</sub>z<sub>Z</sub>; o=z<sub>X</sub>o<sub>Z</sub> or z<sub>Z</sub>o<sub>X</sub>; d; u +| `or_c(X,Z)` | X is Bdu; Z is V | V | z=z<sub>X</sub>z<sub>Z</sub>; o=o<sub>X</sub>z<sub>Z</sub> +| `or_d(X,Z)` | X is Bdu; Z is B | B | z=z<sub>X</sub>z<sub>Z</sub>; o=o<sub>X</sub>z<sub>Z</sub>; d=d<sub>Z</sub>; u=u<sub>Z</sub> +| `or_i(X,Z)` | both are B, K, or V | same as X/Z | o=z<sub>X</sub>z<sub>Z</sub>; u=u<sub>X</sub>u<sub>Z</sub>; d=d<sub>X</sub> or d<sub>Z</sub> +| `thresh(k,X_1,...,X_n)` | 1 ≤ k ≤ n; X<sub>1</sub> is Bdu; others are Wdu | B | z=all are z; o=all are z except one is o; d; u +| `multi(k,key_1,...,key_n)` | 1 ≤ k ≤ n ≤ 20 | B | n; d; u +| `multi_a(k,key_1,...,key_n)` | 1 ≤ k ≤ n | B | d; u +| `a:X` | X is B | W | d=d<sub>X</sub>; u=u<sub>X</sub> +| `s:X` | X is Bo | W | d=d<sub>X</sub>; u=u<sub>X</sub> +| `c:X` | X is K | B | o=o<sub>X</sub>; n=n<sub>X</sub>; d=d<sub>X</sub>; u +| `d:X` | X is Vz | B | o; n; d; *(Tapscript only)* u +| `v:X` | X is B | V | z=z<sub>X</sub>; o=o<sub>X</sub>; n=n<sub>X</sub> +| `j:X` | X is Bn | B | o=o<sub>X</sub>; n; d; u=u<sub>X</sub> +| `n:X` | X is B | B | z=z<sub>X</sub>; o=o<sub>X</sub>; n=n<sub>X</sub>; d=d<sub>X</sub>; u + +#### Timelock Type Mixing + +There is one additional correctness property that Miniscript expressions must satisfy: +the four timelock types (absolute time based, absolute height based, relative time based, and +relative height based) must not be mixed in an incompatible way. + +Within `and` combinators and the `thresh` combinator where k >= 2, it is illegal for both absolute +height based and time based timelocks to appear, or for both relative height based and time based +timelocks to appear. + +For all other combinators, it is legal to mix timelock types. It is also always legal to +mix absolute and relative timelocks (even if one is height based and the other is time based). + +#### Malleability + +Malleability is the ability for a third party (someone who does *not* hold a participating private +key) to modify an existing satisfaction into another valid satisfaction. To analyze the +malleability guarantees of a script we define three additional type properties: "**s**" (signed), +"**f**" (forced) and "**e**" (expressive). + +The following table lists the malleability properties and requirement of each fragment. + +| Miniscript | Requires | Properties +|------------------------------|---------------------------------------------------------------------|----------- +| `0` | | s, e +| `1` | | f +| `pk_k(key)` | | s, e +| `pk_h(key)` | | s, e +| `older(n)` | | f +| `after(n)` | | f +| `sha256(h)` | | +| `ripemd160(h)` | | +| `hash256(h)` | | +| `hash160(h)` | | +| `andor(X,Y,Z)` | e<sub>X</sub> and (s<sub>X</sub> or s<sub>Y</sub> or s<sub>Z</sub>) | s=s<sub>Z</sub> and (s<sub>X</sub> or s<sub>Y</sub>); f=f<sub>Z</sub> and (s<sub>X</sub> or f<sub>Y</sub>); e=e<sub>Z</sub> and (s<sub>X</sub> or f<sub>Y</sub>) +| `and_v(X,Y)` | | s=s<sub>X</sub> or s<sub>Y</sub>; f=s<sub>X</sub> or f<sub>Y</sub> +| `and_b(X,Y)` | | s=s<sub>X </sub>or s<sub>Y;</sub> f=f<sub>Xf</sub><sub>Y</sub> or s<sub>X</sub>f<sub>X</sub> or s<sub>Y</sub>f<sub>Y</sub>; e=e<sub>X</sub>e<sub>Y</sub>s<sub>X</sub>s<sub>Y</sub> +| `or_b(X,Z)` | e<sub>Xe</sub><sub>Z </sub>and (s<sub>X</sub> or s<sub>Z</sub>) | s=s<sub>X</sub>s<sub>Z</sub>; e +| `or_c(X,Z)` | e<sub>X</sub> and (s<sub>X</sub> or s<sub>Z</sub>) | s=s<sub>X</sub>s<sub>Z</sub>; f +| `or_d(X,Z)` | e<sub>X</sub> and (s<sub>X</sub> or s<sub>Z</sub>) | s=s<sub>X</sub>s<sub>Z</sub>; f=f<sub>Z</sub>; e=e<sub>Z</sub> +| `or_i(X,Z)` | s<sub>X</sub> or s<sub>Z</sub> | s=s<sub>X</sub>s<sub>Z</sub>; f=f<sub>X</sub>f<sub>Z</sub>; e=e<sub>X</sub>f<sub>Z</sub> or e<sub>Z</sub>f<sub>X</sub> +| `thresh(k,X_1,...,X_n)` | all are e; at most k are non-s | s=at most k-1 are non-s; e=all are s +| `multi(k,key_1,...,key_n)` | | s; e +| `multi_a(k,key_1,...,key_n)` | | s; e +| `a:X` | | s=s<sub>X</sub>; f=f<sub>X</sub>; e=e<sub>X</sub> +| `s:X` | | s=s<sub>X</sub>; f=f<sub>X</sub>; e=e<sub>X</sub> +| `c:X` | | s; f=f<sub>X</sub>; e=e<sub>X</sub> +| `d:X` | | s=s<sub>X</sub>; e +| `v:X` | | s=s<sub>X</sub>; f +| `j:X` | | s=s<sub>X</sub>; e=f<sub>X +| `n:X` | | s=s<sub>X</sub>; f=f<sub>X</sub>; e=e<sub>X</sub> + +### Satisfaction + +The following table shows all valid satisfactions and dissatisfactions for every Miniscript, using +satisfactions and dissatisfactions of its subexpressions. Multiple possibilities are separated by +semicolons. Some options are inefficient and provably unnecessary to the satisfaction algorithm +described below, but are valid according to script rules and could be used by a malleator or other +non-standard actor. These are called *non-canonical* options, and are listed for completeness, but +~~[struckthrough]~~. The fragments where a satisfaction or dissatisfaction does not exist will +contain *(none)*. The fragments where the satisfaction or dissatisfaction is to provide no data +will contain *(empty)*. + +| Miniscript | Dissatisfactions (dsat) | Satisfactions (sat) +|------------------------------|---------------------------------------------------------|-------------------- +| `0` | *(empty)* | *(none)* +| `1` | *(none)* | *(empty)* +| `pk_k(key)` | 0 | sig +| `pk_h(key)` | 0 key | sig key +| `older(n)` | *(none)* | *(empty)* +| `after(n)` | *(none)* | *(empty)* +| `sha256(h)` | any 32-byte vector except the preimage | preimage +| `ripemd160(h)` | any 32-byte vector except the preimage | preimage +| `hash256(h)` | any 32-byte vector except the preimage | preimage +| `hash160(h)` | any 32-byte vector except the preimage | preimage +| `andor(X,Y,Z)` | dsat(Z) dsat(X); ~~[dsat(Y) sat(X)]~~ | sat(Y) sat(X); sat(Z) dsat(X) +| `and_v(X,Y)` | *(none)*; ~~[dsat(Y) sat(X)]~~ | sat(Y) sat(X) +| `and_b(X,Y)` | dsat(Y) dsat(X); ~~[sat(Y) dsat(X)]; [dsat(Y) sat(X)]~~ | sat(Y) sat(X) +| `or_b(X,Z)` | dsat(Z) dsat(X) | dsat(Z) sat(X); sat(Z) dsat(X); ~~[sat(Z) sat(X)]~~ +| `or_c(X,Z)` | *(none)* | sat(X); sat(Z) dsat(X) +| `or_d(X,Z)` | dsat(Z) dsat(X) | sat(X); sat(Z) dsat(X) +| `or_i(X,Z)` | dsat(X) 1; dsat(Z) 0 | sat(X) 1; sat(Z) 0 +| `thresh(k,X_1,...,X_n)` | All dsats; ~~[Sats/dsats with 1 ≤ #(sats) ≠ k]~~ | Sats/dsats with #(sats) = k +| `multi(k,key_1,...,key_n)` | 0 0 ... 0 (k+1 times) | 0 sig ... sig +| `multi_a(k,key_1,...,key_n)` | 0 ... 0 (n times); ~~[sig/0 with #(sig) ≠ k]~~ | sig/0 with #(sig) = k and #(sigs/0) = n +| `a:X` | dsat(X) | sat(X) +| `s:X` | dsat(X) | sat(X) +| `c:X` | dsat(X) | sat(X) +| `d:X` | 0 | sat(X) 1 +| `v:X` | *(none)* | sat(X) +| `j:X` | 0; ~~[dsat(X) (if nonzero top stack)]~~ | sat(X) +| `n:X` | dsat(X) | sat(X) + +#### Non-malleable Satisfaction Algorithm + +In order to produce non-malleable satisfactions we make use of a function that returns the optimal +satisfaction and dissatisfaction for a given expression (if any exist), or a special DONTUSE ("don't use") value, +together with an optional HASSIG ("has signature") marker that tracks whether the solution contains at least one +signature. To implement the function: +* Invoke the function recursively for all subexpressions, obtaining all their satisfactions/dissatisfactions. +* Iterate over all the valid satisfactions/dissatisfactions in the table above (including the non-canonical ones), taking into account: + * The dissatisfactions for `sha256`, `ripemd160`, `hash256`, and `hash160` are always malleable, so instead use DONTUSE there. + * The non-canonical options for `and_b`, `or_b`, and `thresh` are always overcomplete, so instead use DONTUSE there as well (with HASSIG flag if the original non-canonical solution had one). + * The satisfactions for `pk_k`, `pk_h`, and `multi` can be marked HASSIG. + * When constructing solutions by combining results for subexpressions, the result is DONTUSE if any of the constituent results is DONTUSE. Furthermore, the result gets the HASSIG tag if any of the constituents does. +* If among all valid solutions (including DONTUSE ones) more than one does not have the HASSIG marker, return DONTUSE. +* If instead exactly one does not have the HASSIG marker, return that solution. +* If all valid solutions have the HASSIG marker, but all of them are DONTUSE, return DONTUSE-HASSIG. The HASSIG marker is important because while this represents a choice between multiple options that would cause malleability if used, they are not available to the attacker, and we may be able to avoid them entirely still. +* Otherwise, all not-DONTUSE options are valid, so return the smallest one (in terms of witness size). + +To produce an overall satisfaction, invoke the function on the toplevel expression. If no valid +satisfaction is returned, or it is DONTUSE, fail. Otherwise, if any timelocking is used in the +script but the result does not have the HASSIG flag, also fail. If the satisfaction is both not +DONTUSE and HASSIG, return it. + + +## Discussion + +## Security + +Miniscript primarily aims to provide guarantees on the correctness of a Bitcoin Script. That is, to +guarantee **consensus soundness** and **standardness completeness**. Consensus soundness means +it is not possible to construct a consensus-valid witness for a Bitcoin Script unless the Miniscript +spending conditions are met. Standardness completeness means a standardness-valid witness can be +created for all spending paths of a Miniscript, assuming the resource limits are respected and there +is no timelock mixing. + +Additionally, Miniscript can guarantee the non-malleability and maximum size of a witness. These can +assist in assessing the soundness of protocols where transaction fees (and therefore transaction +size) are security-critical parameters. + +Hash preimages are constrained to 32 bytes to disallow various forms of griefing, including making +non-standard (un-relayable) transactions, consensus-invalid swaps across blockchains, as well as +ensure that satisfaction cost can be accurately calculated. + +In order for these properties to not just apply to script, but to an entire transaction, it's +important that the witness commits to all data relevant for verification. In practice this means +that scripts whose conditions can be met without any digital signature are insecure. Besides being +trivially insecure, note how a transaction lacking a signature check allows an attacker to change +its nLockTime and nSequence fields to meet additional timelock conditions. + +### Type System + +To statically verify the correctness and malleability guarantees discussed in the previous section, +we define a type system. See the specifications above for a reference of each fragment's +requirements and properties. Here we give more information about each type. + +Every expression has one of four basic types: +* "**B**" Base expressions. These take their inputs from the top of the stack. When satisfied, they push a nonzero value of up to 4 bytes onto the stack. When dissatisfied, they push an exact 0 onto the stack (if dissatisfaction without aborting is possible at all). This type is used for most expressions, and required for the top level expression. An example is `older(n)` = `<n> CHECKSEQUENCEVERIFY`. +* "**V**" Verify expressions. Like "B", these take their inputs from the top of the stack. Upon satisfaction however, they continue without pushing anything. They cannot be dissatisfied (will abort instead). A "V" can be obtained using the `v:` wrapper on a "B" expression, or by combining other "V" expressions using `and_v`, `or_i`, `or_c`, or `andor`. An example is `v:pk(key)` = `<key> CHECKSIGVERIFY`. +* "**K**" Key expressions. They again take their inputs from the top of the stack, but instead of verifying a condition directly they always push a public key onto the stack, for which a signature is still required to satisfy the expression. A "K" can be converted into a "B" using the `c:` wrapper. An example is `pk_h(key)` = `DUP HASH160 <Hash160(key)> EQUALVERIFY`. +* "**W**" Wrapped expressions. They take their inputs from one below the top of the stack, and push a nonzero (in case of satisfaction) or zero (in case of dissatisfaction) either on top of the stack, or one below. So for example a 3-input "W" would take the stack "A B C D E F" and turn it into "A B F 0" or "A B 0 F" in case of dissatisfaction, and "A B F n" or "A B n F" in case of satisfaction (with n a nonzero value). Every "W" is either `s:B` (SWAP B) or `a:B` (TOALTSTACK B FROMALTSTACK). An example is `s:pk(key)` = `SWAP <key> CHECKSIG`. + +Then there are 6 type modifiers, which guarantee additional properties: +* "**z**" Zero-arg: this expression always consumes exactly 0 stack elements. +* "**o**" One-arg: this expression always consumes exactly 1 stack element. +* "**n**" Nonzero: this expression always consumes at least 1 stack element, no satisfaction for this expression requires the top input stack element to be zero. +* "**d**" Dissatisfiable: a dissatisfaction for this expression can unconditionally be constructed. This implies the dissatisfaction cannot include any signature or hash preimage, and cannot rely on timelocks being satisfied. +* "**u**" Unit: when satisfied, this expression will put an exact 1 on the stack (as opposed to any nonzero value). +* "**k**" No timelock mixing. This expression does not contain a mix of heightlock and timelock of the same type. If the miniscript does not have the "k" property, the miniscript template will not match the user expectation of the corresponding spending policy. + +Finally to analyze malleability guarantees we introduce 3 new type modifiers: +* "**s**" Signed: satisfying this expression always requires a signature (predicting whether all satisfactions will be HASSIG). +* "**f**" Forced: dissatisfying this expression always requires a signature (predicting whether all dissatisfactions will be HASSIG). +* "**e**" Expressive: this requires a unique unconditional dissatisfaction to exist, and forces all conditional dissatisfactions (if any) to require a signature. + + +### Malleability + +Since Segwit, malleating a transaction no longer breaks the validity of unconfirmed descendant +transactions. However, unintentional malleability may still have a number of much weaker undesirable +effects. If a witness can be stuffed with additional data, the transaction's feerate will go down, +potentially to the point where its ability to propagate and get confirmed is impacted. Additionally, +malleability can be exploited to add roundtrips to BIP152 block propagation, by trying to get +different miners to mine different versions of the same transaction. Finally, malleability may +interfere with the usage of hash locks as a mechanism for publishing preimages. + +Using the malleability type properties it is possible to determine statically whether a script can +be non-malleably satisfied under all circumstances. In many cases it is reasonable to only accept +such guaranteed-non-malleable scripts, as unexpected behavior can occur when using other scripts. + +For example, when running the non-malleable satisfaction algorithm above, adding available +preimages, or increasing the nLockTime/nSequence values actually may make it fail where it succeeded +before. This is because a larger set of met conditions may mean an existing satisfaction goes from +non-malleable to malleable. Restricting things to scripts that are guaranteed to be satisfiable in a +non-malleable way avoids this problem. + +When analysing Miniscripts for resource limits, restricting yourself to just non-malleable solutions +(or even non-malleable scripts) also leads to tighter bounds, as all non-canonical satisfactions and +dissatisfactions can be left out of consideration. + +The malleability analysis makes the following assumptions: +* The attacker does not have access to any of the private keys of public keys that participate in the Script. Participants with private keys inherently have the ability to produce different satisfactions by creating multiple signatures. While it is also interesting to study the impact rogue participants can have, we treat it as a distinct problem. +* The attacker only has access to hash preimages that honest users have access to as well. This is a reasonable assumption because hash preimages are revealed once globally, and then available to everyone. On the other hand, making the assumption that attackers may have access to more preimages than honest users makes a large portion of scripts impossible to satisfy in a non-malleable way. +* The attacker gets to see exactly one satisfying witness of any transaction. If he sees multiple, it becomes possible for the attacker to mix and match different satisfactions. This is very hard to reason about. +* We restrict this analysis to scripts where no public key is repeated. If signatures constructed for one part of the script can be bound to other checks in the same script, a variant of the mixing from the previous point becomes available that is equally hard to reason about. Furthermore this situation can be avoided by using separate keys. +* The attacker is constrained by common standardness rules. A miner may be able to malleate a witness considered non-malleable by Miniscript. + +#### Non-Malleable Satisfaction + +Malleable satisfactions or dissatisfactions appear whenever options are available to attackers distinct from the one taken by honest users. This can happen for multiple reasons: +1. Two or more options for a satisfaction or dissatisfaction are listed in the table above which are both available to attackers directly. Regardless of which option is used in the honest solution, the attacker can change the solution to the other one. +2. Two or more options for a satisfaction or dissatisfaction are listed in the table above, only one of which is available to attackers, but the honest solution uses another one. In that case, the attacker can modify the solution to pick the one available to him. +3. The honest users pick a solution that contains a satisfaction which can be turned into a dissatisfaction without invalidating the overall witness. Those are called overcomplete solutions. + +Because we assume attackers never have access to private keys, we can treat any solution that +includes a signature as one that is unavailable to attackers. For others, the worst case is that the +attacker has access to every solution the honest users have, but no others: for preimages this is an +explicit assumption, while timelock availability is determined by the nLockTime and nSequence fields +in the transaction. As long as the overall satisfaction includes at least one signature, those +values are fixed, and timelock availability is identical for attackers and honest users. + +The description of the non-malleable satisfaction algorithm can be used to show that no +non-canonical solutions listed in the satisfaction table can occur inside non-malleable +satisfaction: +* Some of the non-canonical options (the `or_b`, `and_b`, and `thresh` ones) are overcomplete, and thus can clearly not appear in non-malleable satisfactions. +* The fact that non-"d" expressions cannot be dissatisfied in valid witnesses rules out the usage of the non-canonical `and_v` dissatisfaction. +* "d" expressions are defined to be unconditionally dissatisfiable, which implies that for those a non-HASSIG dissatisfaction must exist. Non-HASSIG solutions must be preferred over HASSIG ones (reason 2), and when multiple non-HASSIG ones exist, none can be used (reason 1). This lets us rule out the other non-canonical options in the table: + * `j:X` is always "d", its non-HASSIG dissatisfaction "0" always exists, and thus rules out any usage of "dsat(X)". + * If `andor(X,Y,Z)` is "d", a non-HASSIG dissatisfaction "dsat(Z) dsat(X)" must exist, and thus rules out any usage of "dsat(Y) sat(X)". + * If `and_b(X,Y)` is "d", a non-HASSIG dissatisfaction "dsat(Y) dsat(X)" must exist, and thus rules out any usage of "dsat(Y) sat(X)" and "sat(Y) dsat(X)". Those are also overcomplete. + * `thresh(k,...)` is always "d", a non-HASSIG dissatisfaction with just dissatisfactions must exist due to typing rules, and thus rules out usage of the other dissatisfactions. They are also overcomplete. + + +### Resource Limits + +Various types of Bitcoin Scripts have different resource limitations, either through consensus or standardness. Some of them affect otherwise valid Miniscripts: +* In P2WSH, scripts larger than 3600 bytes are invalid by standardness. In Tapscript, scripts are implicitly bounded by the maximum size of a block (1 million virtual bytes). +* In P2WSH, script satisfactions where the total number of non-push opcodes plus the number of keys participating in all executed `CHECKMULTISIG` is above 201 are invalid by consensus. +* In both Tapscript and P2WSH, script satisfactions which make the stack exceed 1000 elements before or during execution are invalid. +* In P2WSH, satisfactions with a witness consisting of over 100 stack elements (excluding the script itself) are invalid by standardness. + +A static analysis can be performed on a Miniscript to verify if none, all or any of the spending +paths hit any of the limits. + + +## Test Vectors + +TBD + +## Backwards Compatibility + +Miniscript's syntax is compatible with BIP 380 Output Script Descriptors, and should be considered +an extension to it that provides a new type of Script expression that is only valid in +`wsh()` and `tr()` contexts. As these are wholly new expressions, they are not +compatible with any existing implementation of descriptors. Additionally, the scripts produced are +unlikely to be standard scripts. + +The `pk()`, `pkh()`, `multi()`, and `multi_a()` +fragments overlap with existing descriptors. These parse to the same semantic meanings as those +descriptors and produce the same scripts. + +## Reference Implementation + +A first reference implementation and documentation for Miniscript in P2WSH was originally published at +https://github.com/sipa/miniscript . + +The reference implementation for Miniscript in P2WSH was introduced in Bitcoin Core through PRs +[24147](https://github.com/bitcoin/bitcoin/pull/24147), [24148](https://github.com/bitcoin/bitcoin/pull/24148), and +[24149](https://github.com/bitcoin/bitcoin/pull/24149). The last one to be merged was released in Bitcoin +Core version 25.0. + +The reference implementation for Miniscript in Tapscript was introduced in Bitcoin Core in PR +[27255](https://github.com/bitcoin/bitcoin/pull/27255). This PR was merged and released in Bitcoin Core +version 26.0. diff --git a/bip-0380.mediawiki b/bip-0380.mediawiki index 27b7908..823a92c 100644 --- a/bip-0380.mediawiki +++ b/bip-0380.mediawiki @@ -332,4 +332,7 @@ This Table lists all available Script expressions and the BIPs specifying them. |- | <tt>tr(KEY)</tt>, <tt>tr(KEY, TREE)</tt> | [[bip-0386.mediawiki|386]] +|- +| <tt>musig(KEY, KEY, ..., KEY)</tt> +| [[bip-0390.mediawiki|390]] |} diff --git a/bip-0390.mediawiki b/bip-0390.mediawiki new file mode 100644 index 0000000..05f5734 --- /dev/null +++ b/bip-0390.mediawiki @@ -0,0 +1,117 @@ +<pre> + BIP: 390 + Layer: Applications + Title: musig() Descriptor Key Expression + Author: Ava Chow <me@achow101.com> + Comments-Summary: No comments yet. + Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0390 + Status: Draft + Type: Informational + Created: 2024-01-15 + License: CC0-1.0 +</pre> + +==Abstract== + +This document specifies a <tt>musig()</tt> key expression for output script descriptors. +<tt>musig()</tt> expressions take multiple keys and produce an aggregate public key using BIP 327. + +==Copyright== + +This BIP is licensed under the Creative Commons CC0 1.0 Universal license. + +==Motivation== + +BIP 327 introduces the MuSig2 Multi-Signature scheme. It is useful to have a way for keys to be used +in a MuSig2 aggregate key to be expressed in descriptors so that wallets can more easily use MuSig2. + +==Specification== + +A new key expression is defined: <tt>musig()</tt>. + +===<tt>musig(KEY, KEY, ..., KEY)</tt>=== + +The <tt>musig(KEY, KEY, ..., KEY)</tt> expression can only be used inside of a <tt>tr()</tt> +expression as a key expression. It additionally cannot be nested within another <tt>musig()</tt> +expression. Repeated participant public keys are not allowed. The aggregate public key is produced +by using the <tt>KeyAgg</tt> algorithm on all KEYs specified in the expression after performing all +specified derivation. As with script expressions, KEY can contain child derivation specified by +<tt>/*</tt>. A new aggregate public key will be computed for each child index. Keys must be sorted +with the <tt>KeySort</tt> algorithm after all derivation and prior to aggregation<ref>'''Why must +the keys be sorted prior to aggregation?''' Although the descriptor's written form sets an order +for the keys that could be used for aggregation, the order should not matter as MuSig2 philosophically +operates over a set of keys, with the order merely being an implementation detail in aggregation +itself. Requiring sorting of keys prior to aggregation enforces this philosophy as keys can be +written in the descriptor in any order with the end result still being the same. Furthermore, this +aids with recovery where the descriptor was not backed up as users will not need to also have +backed up, or guess, the correct order of keys.</ref>. + +===<tt>musig(KEY, KEY, ..., KEY)/NUM/.../*</tt>=== + +<tt>musig(KEY, KEY, ..., KEY)/NUM/.../*</tt> expressions are also allowed, with the same usage +restrictions as in the previous section. The aggregate public key +is first computed as described above, with the keys also being sorted after all derivation and prior +to aggreation. Then further BIP 32 derivation will be performed on the aggregate public key as described in +[[bip-0328.mediawiki|BIP 328]]. As there is no aggregate private key, +only unhardened derivation from the aggregate public key is allowed, and thus the derivation steps +following the <tt>musig()</tt> expression cannot contain +<tt>/NUMh</tt> or <tt>/NUM'</tt> derivation steps nor <tt>/*h</tt>, or <tt>/*'</tt> child derivation. +For these <tt>musig()</tt> expressions, the KEY expressions contained within must be xpubs or derived from +xpubs, and cannot contain child derivation as specified by a <tt>/*</tt>, <tt>/*'</tt>, or <tt>/*h</tt>. + +==Test Vectors== + +Valid descriptors containing followed by the scripts they produce. Descriptors involving derived child keys +will have the 0th, 1st, and 2nd scripts listed. + +* <tt>rawtr(musig(KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74sHUHy8S,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +** <tt>5120789d937bade6673538f3e28d8368dda4d0512f94da44cf477a505716d26a1575</tt> +* <tt>tr(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +** <tt>512079e6c3e628c9bfbce91de6b7fb28e2aec7713d377cf260ab599dcbc40e542312</tt> +* <tt>rawtr(musig(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y)/0/*)</tt> +** <tt>51209508c08832f3bb9d5e8baf8cb5cfa3669902e2f2da19acea63ff47b93faa9bfc</tt> +** <tt>51205ca1102663025a83dd9b5dbc214762c5a6309af00d48167d2d6483808525a298</tt> +** <tt>51207dbed1b89c338df6a1ae137f133a19cae6e03d481196ee6f1a5c7d1aeb56b166</tt> +* <tt>tr(musig(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y)/0/*,pk(f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9))</tt> +** <tt>51201d377b637b5c73f670f5c8a96a2c0bb0d1a682a1fca6aba91fe673501a189782</tt> +** <tt>51208950c83b117a6c208d5205ffefcf75b187b32512eb7f0d8577db8d9102833036</tt> +** <tt>5120a49a477c61df73691b77fcd563a80a15ea67bb9c75470310ce5c0f25918db60d</tt> +* <tt>tr(f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,pk(musig(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y)/0/*))</tt> +** <tt>512068983d461174afc90c26f3b2821d8a9ced9534586a756763b68371a404635cc8</tt> +** <tt>5120368e2d864115181bdc8bb5dc8684be8d0760d5c33315570d71a21afce4afd43e</tt> +** <tt>512097a1e6270b33ad85744677418bae5f59ea9136027223bc6e282c47c167b471d5</tt> + +Invalid descriptors + +* <tt>musig()</tt> is not allowed in <tt>pk()</tt>: <tt>pk(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +* <tt>musig()</tt> is not allowed in <tt>pkh()</tt>: <tt>pkh(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +* <tt>musig()</tt> is not allowed in <tt>wpkh()</tt>: <tt>wpkh(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +* <tt>musig()</tt> is not allowed in <tt>combo()</tt>: <tt>combo(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +* <tt>musig()</tt> is not allowed in <tt>sh(wpkh())</tt>: <tt>sh(wpkh(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66)))</tt> +* <tt>musig()</tt> is not allowed in <tt>sh(wsh())</tt>: <tt>sh(wsh(pk(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))))</tt> +* <tt>musig()</tt> is not allowed in <tt>wsh()</tt>: <tt>wsh(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +* <tt>musig()</tt> is not allowed in <tt>sh()</tt>: <tt>sh(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> +* Ranged <tt>musig()</tt> requires all participants to be xpubs: <tt>tr(musig(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66)/0/0)</tt> +* Cannot have ranged participants if <tt>musig()</tt> is also ranged: <tt>tr(musig(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y)/0/*)</tt> +* <tt>musig()</tt> cannot have hardened derivation steps: <tt>tr(musig(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y)/0h/*)</tt> +* <tt>musig()</tt> cannot have hardened child derivation: <tt>tr(musig(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y)/0/*h)</tt> + +==Backwards Compatibility== + +<tt>musig()</tt> expressions use the format and general operation specified in +[[bip-0380.mediawiki|BIP 380]]. As these are a set of wholly new expressions, they are not compatible +with any implementation. However the keys are produced using a standard process so existing software +are likely to be familiar with them. + +==Rationale== + +<references/> + +==Reference Implementation== + +TBD + +==Acknowledgements== + +Thanks to Pieter Wuille, Andrew Poelstra, Sanket Kanjalkar, Salvatore Ingala, and all others who +participated in discussions on this topic. |