Home › Browse › BIP 387

BIP 387: Tapscript Multisig Output Script Descriptors

In plain English: Defines descriptor functions for multisignature setups inside Taproot scripts, which require a different construction than older multisig. One form keeps keys in the given order and the other sorts them, helping wallets describe Taproot multisig wallets consistently.

Status
Deployed
Type
Specification
Layer
Applications
Authors
Pieter Wuille, Ava Chow
Assigned
Last changed
Requires
BIP 380
Topics
Transactions
Source
bip-0387.mediawiki on GitHub · Markdown

Abstract

This document specifies multi_a() and sortedmulti_a() output script descriptors. Like BIP 383's multi() and sortedmulti(), both functions take a threshold and one or more public keys and produce a multisig script. The primary distinction is that multi_a() and sortedmulti_a() only produce tapscripts and are only allowed in a tapscript context.

This BIP is licensed under the BSD 2-clause license.

Motivation

The most common complex script used in Bitcoin is a threshold multisig. These expressions allow specifying multisig scripts as a descriptor.

Specification

Two new script expressions are defined: multi_a() and sortedmulti_a(). Both expressions produce the scripts of the same template and take the same arguments. They are written as multi_a(k,KEY_1,KEY_2,...,KEY_n). k is the threshold - the number of keys that must sign the input for the script to be valid. KEY_1,KEY_2,...,KEY_n are the key expressions for the multisig. k must be less than or equal to n.

multi_a() and sortedmulti_a() expressions can only be used inside of a tr() descriptor. The maximum number of keys is 999.

The output script produced also depends on the value of k. If k is less than or equal to 16:

KEY_1 OP_CHECKSIG KEY_2 OP_CHECKSIGADD ... KEY_n OP_CHECKSIGADD OP_k OP_NUMEQUAL

if k is greater than 16:

KEY_1 OP_CHECKSIG KEY_2 OP_CHECKSIGADD ... KEY_n OP_CHECKSIGADD k OP_NUMEQUAL

sortedmulti_a()

The only change for sortedmulti_a() is that the x-only public keys are sorted lexicographically prior to the creation of the output script. This sorting is on the keys that are to be put into the output script, i.e. after all extended keys are derived.

Multiple Extended Keys

When one or more of the key expressions in a multi_a() or sortedmulti_a() expression are extended keys, the derived keys use the same child index. This changes the keys in lockstep and allows for output scripts to be indexed in the same way that the derived keys are indexed.

Test Vectors

Valid descriptors followed by the scripts they produce. Descriptors involving derived child keys will have the 0th, 1st, and 2nd scripts listed.

  • tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,multi_a(1,KzoAz5CanayRKex3fSLQ2BwJpN7U52gZvxMyk78nDMHuqrUxuSJy))
    • 5120eb5bd3894327d75093891cc3a62506df7d58ec137fcd104cdd285d67816074f3
  • tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,multi_a(1,669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))
    • 5120eb5bd3894327d75093891cc3a62506df7d58ec137fcd104cdd285d67816074f3
  • tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))
    • 51202eea93581594a43c0c8423b70dc112e5651df63984d108d4fc8ccd3b63b4eafa
  • tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,sortedmulti_a(2,[00000000/111'/222]xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc,xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L/0))
    • 512016fa6a6ba7e98c54b5bf43b3144912b78a61b60b02f6a74172b8dcb35b12bc30
  • tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,sortedmulti_a(2,xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/*,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y/0/0/*))
    • 5120abd47468515223f58a1a18edfde709a7a2aab2b696d59ecf8c34f0ba274ef772
    • 5120fe62e7ed20705bd1d3678e072bc999acb014f07795fa02cb8f25a7aa787e8cbd
    • 51201311093750f459039adaa2a5ed23b0f7a8ae2c2ffb07c5390ea37e2fb1050b41
  • tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(2,xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/2147483647'/0,xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt/1/2/*,xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi/10/20/30/40/*'))
    • 5120e4c8f2b0a7d3a688ac131cb03248c0d4b0a59bbd4f37211c848cfbd22a981192
    • 5120827faedaa21e52fca2ac83b53afd1ab7d4d1e6ce67ff42b19f2723d48b5a19ab
    • 5120647495ed09de61a3a324704f9203c130d655bf3141f9b748df8f7be7e9af55a4

Invalid descriptors

  • Unsupported top level: multi_a(1,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0)
  • Unsupported sh() context: sh(multi_a(1,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))
  • Unsupported wsh() context: wsh(multi_a(1,03669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))
  • Invalid threshold: tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(a,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))
  • Threshold of 0: tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(0,03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))
  • Uncompressed pubkey: tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(1,04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235))
  • Threshold larger than keys: tr(50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0,multi_a(3,L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss))

Backwards Compatibility

multi_a() and sortedmulti_a() descriptors use the format and general operation specified in 380. As these are wholly new descriptors, they are not compatible with any implementation. However, the scripts produced are standard scripts, so existing software are likely to be familiar with them.

Reference Implementation

multi_a() and sortedmulti_a() descriptors were implemented in Bitcoin Core in https://github.com/bitcoin/bitcoin/pull/24043 and have been available since version 24.0.

Related proposals

  • BIP 11: M-of-N Standard Transactions: Deployed. Made "M-of-N" transactions, which require any M signatures out of N possible keys, a standard type that nodes relay. This enabled shared-control arrangements such as escrow or wallets needing two of…
  • BIP 12: OP_EVAL: Closed. Proposed a new script command, OP_EVAL, that would let the receiver of coins define the conditions for spending them instead of the sender. It was abandoned over security concerns and replaced by…
  • BIP 16: Pay to Script Hash: Deployed. Introduced Pay to Script Hash (P2SH), letting a sender pay to a short fingerprint of spending rules that the recipient reveals only when spending. This shifted the cost and complexity of setups like…
  • BIP 31: Pong message: Deployed. Adds a "pong" reply that a node sends back when it receives a "ping" containing a random number. This lets software reliably tell whether a connection to another node is still alive.
  • BIP 47: Reusable Payment Codes for Hierarchical Deterministic Wallets: Deployed. Introduces reusable payment codes that someone can publish once, for example on a website, without the privacy loss of reusing an address. Senders use the code to derive fresh addresses for each…
  • BIP 53: Disallow 64-byte transactions: Draft. Proposes making transactions that are exactly 64 bytes long (excluding signature data) invalid. Such transactions can be confused with internal pieces of a block's Merkle tree, the structure…