BIPs 0380–0386
How do you describe a wallet in one line?
A seed says which keys a wallet has, not which scripts they pay to. An output script descriptor spells out both, in a short string with its own typo check.
Restore a seed into a new wallet and it knows your keys. What it does not know is what you did with them: which kinds of output script, at which derivation paths. The authors of BIP 380 saw that as the weak spot of backups made of private keys alone, made worse once SegWit added new output types, and worse again because wallets did not all follow the same paths.1
Their answer, assigned in 2021 as BIPs 380 to 386 and recorded as deployed, is a small language. An output script descriptor names the script type explicitly and gives each key with its derivation, so a backup or a watch-only export can say exactly which scripts to produce.234
Source details
This chapter is an independent explanation, not the proposals themselves. Preamble fields are shown as recorded in the pinned files, with author e-mail addresses omitted. Status is the proposal’s own field, not an endorsement or a sign of consensus.
BIP 380: Output Script Descriptors General Operation
- BIP
- 380
- Layer
- Applications
- Title
- Output Script Descriptors General Operation
- Authors
- Pieter Wuille
Ava Chow - Status
- Deployed
- Type
- Specification
- Assigned
- 2021-06-27
- License
- BSD-2-Clause
BIP 381: Non-Segwit Output Script Descriptors
- BIP
- 381
- Layer
- Applications
- Title
- Non-Segwit Output Script Descriptors
- Authors
- Pieter Wuille
Ava Chow - Status
- Deployed
- Type
- Specification
- Assigned
- 2021-06-27
- License
- BSD-2-Clause
- Requires
- 380
BIP 382: Segwit Output Script Descriptors
- BIP
- 382
- Layer
- Applications
- Title
- Segwit Output Script Descriptors
- Authors
- Pieter Wuille
Ava Chow - Status
- Deployed
- Type
- Specification
- Assigned
- 2021-06-27
- License
- BSD-2-Clause
- Requires
- 380
BIP 383: Multisig Output Script Descriptors
- BIP
- 383
- Layer
- Applications
- Title
- Multisig Output Script Descriptors
- Authors
- Pieter Wuille
Ava Chow - Status
- Deployed
- Type
- Specification
- Assigned
- 2021-06-27
- License
- BSD-2-Clause
- Requires
- 380
BIP 384: combo() Output Script Descriptors
- BIP
- 384
- Layer
- Applications
- Title
- combo() Output Script Descriptors
- Authors
- Pieter Wuille
Ava Chow - Status
- Deployed
- Type
- Specification
- Assigned
- 2021-06-27
- License
- BSD-2-Clause
- Requires
- 380
BIP 385: raw() and addr() Output Script Descriptors
- BIP
- 385
- Layer
- Applications
- Title
- raw() and addr() Output Script Descriptors
- Authors
- Pieter Wuille
Ava Chow - Status
- Deployed
- Type
- Specification
- Assigned
- 2021-06-27
- License
- BSD-2-Clause
- Requires
- 380
BIP 386: tr() Output Script Descriptors
- BIP
- 386
- Layer
- Applications
- Title
- tr() Output Script Descriptors
- Authors
- Pieter Wuille
Ava Chow - Status
- Deployed
- Type
- Specification
- Assigned
- 2021-06-27
- License
- BSD-2-Clause
- Requires
- 380
- rg29
- ag018
- wg214
- (g010
- dg021
- eg022
- ag018
- dg021
- bg019
- eg022
- eg022
- fg023
- )g011
- 9
- 18
- 14
- 20
- 10
- 21
- 22
- 0
- 18
- 21
- 19
- 0
- 22
- 22
- 23
- 0
- 11
- 0
18 symbols → BCH polymod → #89f8spxm (matches the published checksum)
Each character becomes its position within one of three groups (32, 32 and 31 characters); after every third character one more symbol records the three group numbers, and a final one records the groups of any leftover characters (shaded). Computed by the tested checksum model, a transcription of BIP 380’s Python code; checked against the BIP’s vector.
Functions wrapped around keys
A descriptor is one script expression at the top, optionally followed by # and an eight-character checksum. Script expressions are written like functions: a name, then arguments in parentheses that fill a script template. An argument can be another script expression or a key expression.89
So sh(wpkh(KEY)) reads from the outside in: pay to the hash of a script, and that script pays to the hash of one key. Each BIP after 380 adds a few such functions. BIP 381 covers the three main standard formats from before SegWit, pk(), pkh() and sh(); BIP 382 adds wpkh() and wsh(); BIP 386 adds tr().10111213
The templates are the familiar ones. pk() becomes the key followed by OP_CHECKSIG; pkh() becomes OP_DUP OP_HASH160, the key’s 20-byte hash, OP_EQUALVERIFY and OP_CHECKSIG; wpkh() becomes OP_0 and the same hash. A descriptor adds no new kind of output. It only names, in a fixed form, the outputs wallets already make.101114
The rules about where each may appear are part of the language. sh() only at the top; wpkh() and wsh() at the top or inside sh(); keys under wpkh() and wsh() must be compressed; everything under tr() is x-only. A descriptor that breaks one of these is not a valid descriptor, whatever its checksum says.101112
The authors also wanted the result to be readable. Because descriptors reuse familiar terms and existing encodings, they describe them as engineer readable: someone who knows the formats can tell at a glance what a descriptor produces.4
A key, with its history
Key expressions carry the derivation that wallet backups used to lose. One can start with origin information in brackets: the fingerprint of the key where derivation began and the steps taken from it. Then comes the key itself: a hex public key, a WIF private key, or an extended key followed by further steps. Hardened steps are marked h or an apostrophe, interchangeably.15
The origin records where a key came from: the fingerprint of the key where derivation started and the steps since. That lets software holding the root recognise the key as its own. The script does not change: BIP 381 lists the same pkh() with an origin written with apostrophes or with h, and with a private key or its public key, and all of them produce one and the same script.151617
A final /* turns one key into a range. The descriptor then stands for an output script at every child index, not for one script. BIP 382’s ranged wpkh() example lists its first three, and the figure below derives them.1819
A · Interactive
Static view: the first descriptor with its first key highlighted and its checksum (none is written) computed. With JavaScript you can pick any of 8 published descriptors and highlight each key.
Public keys only: reveals scripts, cannot spendRanged: one script per child index
wpkh([ffffffff/13']xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH/1/2/*)
script expression number key origin key derivation range checksum
Key 1 of 1 · extended public key (xpub)
- origin (normalized, h for hardened)
[ffffffff/13h]- derivation after the key
/1/2/*- public key, child 0
021a45661073…da98c589- public key, child 1
02c99d4ca620…078a9b19- public key, child 2
026837916016…fd862b81
Output scripts
wpkh(KEY)
- child 0
0014326b2249e3a25d5dc60935f044ee835d090ba859 - child 1
0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7 - child 2
00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27
Children 0–2 shown, as the BIP lists them; the range continues.
Checksum
183 symbols from 137 characterscomputed: #66s997t5written: none
no checksum written (optional for parsing)
The checksum catches typos. It is not a signature: anyone can compute it for any descriptor, so a matching checksum says nothing about who wrote it.
Source: BIP 382, line 67. Parsed and expanded at build time by the tested descriptor model; the scripts match those the BIP lists.
B · Worked example
BIP 382’s ranged descriptor wpkh([ffffffff/13']xpu…, read part by part and expanded for its first three children.
The script expression says what kind of output
- outline
wpkh(KEY)
wpkh(KEY): pay to the hash of one compressed key, SegWit v0.
Key origin: where this key sits in someone's tree
- origin
[ffffffff/13h]
A fingerprint and the steps already taken. Information about the key; it changes no script.
The key itself: an extended public key
- key
xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH
Public only, so the descriptor reveals scripts but cannot spend.
Derivation after the key, ending in a range
- steps
/1/2/*- child 0 key
021a45661073b3902a29ab5d1bf2545d3bc09420d8ff1f574e5eebd3c4da98c589- child 1 key
02c99d4ca62021dadf698e56d7d0542660dfe6f090e466d0232026052b078a9b19- child 2 key
02683791601676cdefeabbc87d3740f31050b83419c9cc40d0aaf83c64fd862b81
/* stands for every unhardened child: one descriptor, many keys.
Each child key fills the template
- child 0 script
0014326b2249e3a25d5dc60935f044ee835d090ba859- child 1 script
0014af0bd98abc2f2cae66e36896a39ffe2d32984fb7- child 2 script
00141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27
OP_0 <HASH160(key)>, matching the scripts BIP 382 lists.
Source: BIP 382, line 67; parsed and expanded by the tested descriptor model, checked against lines 68, 69, 70.
Whether a descriptor is a secret depends on what is inside it. With only public keys it reveals every script it stands for, which is a privacy matter, but it cannot spend. With a WIF key or an xprv inside, it is as sensitive as those keys. For exporting without private keys, BIP 380 says the exporter should derive the extended public key at the last hardened step, and the steps taken must then be added to the origin.2022
A checksum for typos
BIP 380 gives descriptors a checksum like bech32’s. Characters are restricted to a fixed set of 95, which BIP 380 describes as three groups of 32 (the last group is one short), in an order chosen so that the checksum can identify more errors. Each character becomes its position in its group, and after every third character an extra symbol records the three group numbers.5623
The guarantees are stated precisely. Any single symbol error is always detected; any two or three in a descriptor up to 49,154 characters; any four up to 507; any five up to 77. Random errors slip through with a chance of 1 in 2^40. The figure checks BIP 380’s own example, raw(deadbeef)#89f8spxm, and the same string with one letter changed, which fails.723
BIP 380’s test vectors walk through the ways a checksum can be wrong: missing after the #, one character too long or too short, an error in the payload, an error in the checksum itself, and a character outside the set. All are rejected; a descriptor with no # at all simply has no checksum, which parsing allows.7824
It is not a signature. The checksum is computed from the text alone, with no key, so anyone who changes a descriptor can compute a fresh, valid checksum for it. It catches typos; it says nothing about who wrote the descriptor.21
The expressions
BIP 383 adds multisig. multi(k, KEY_1, …, KEY_n) produces a k-of-n CHECKMULTISIG script with k at most n, and sortedmulti() sorts the derived keys first. Ranged keys in a multisig advance together, each using the same child index. The number of keys is limited by context: 3 at the top level, 15 compressed keys (or 7 uncompressed) directly inside sh() because of the 520-byte push limit, 20 otherwise.25
BIP 384’s combo() eases the move from older wallets: from one key it produces P2PK and P2PKH scripts, and for a compressed key P2WPKH and P2SH-P2WPKH as well. BIP 385’s raw() and addr() wrap any script or address, so anything a wallet already watches can be written as a descriptor.2627
| Expression | BIP | May appear | Produces |
|---|---|---|---|
pk(KEY) | 381 | top level, in sh(), in wsh(), in a tr() tree | <KEY> OP_CHECKSIG |
pkh(KEY) | 381 | top level, in sh(), in wsh() | OP_DUP OP_HASH160 <KEY_hash160> OP_EQUALVERIFY OP_CHECKSIG |
sh(SCRIPT) | 381 | top level | OP_HASH160 <SCRIPT_hash160> OP_EQUAL |
wpkh(KEY) | 382 | top level, in sh() | OP_0 <KEY_hash160> |
wsh(SCRIPT) | 382 | top level, in sh() | OP_0 <SCRIPT_sha256> |
multi(NUM, KEY, ..., KEY) | 383 | top level, in sh(), in wsh() | k KEY_1 … KEY_n n OP_CHECKMULTISIG |
sortedmulti(NUM, KEY, ..., KEY) | 383 | top level, in sh(), in wsh() | as multi(), keys sorted |
combo(KEY) | 384 | top level | P2PK, P2PKH (+ P2WPKH, P2SH-P2WPKH if compressed) |
raw(HEX) | 385 | top level | the script itself |
addr(ADDR) | 385 | top level | the address's output script |
tr(KEY) | 386 | top level | OP_1 <32_byte_output_key> |
tr(KEY, TREE) | 386 | top level | OP_1 <32_byte_output_key> |
musig(KEY, KEY, ..., KEY) | 390 | not covered here | — |
sp(KEY) | 392 | not covered here | — |
sp(KEY, KEY) | 392 | not covered here | — |
Rows from BIP 380’s Appendix B (lines 302–344); placement rules from BIPs 381–386 as the tested model enforces them. BIPs 390 and 392 are outside this chapter’s pinned sources.
tr() is the newest of the set. tr(KEY) produces a Taproot output with no usable script path; tr(KEY, TREE) adds a tree of scripts written with braces. When BIP 386 was written only pk() could be a leaf; Miniscript and multi_a() came later, and this chapter’s model stops at pk().121929
The BIPs record descriptors in Bitcoin Core since version 0.17, and tr() since 22.0. The index in BIP 380 keeps growing: it already lists musig() and sp(), defined in later BIPs.2830
The authors’ last argument is about layers. Alternative version bytes for extended keys, they write, mix key derivation with script type and only cover one path and one script type. A descriptor keeps the two apart: the key expression says where a key comes from, the script expression says what it pays to.431
Evidence
Each numbered marker in the text points here, and the ↩ links lead back to every place that cites an entry. Quotes are verbatim from the BIP files at commit
3a10b5b, including their wiki markup; links open
the exact lines; the quoted text sits under each entry. Labels say what kind of statement each is: a rule, the author’s rationale, history,
a test vector, or our own inference.
-
↩ Author’s rationale The authors' motivation: backups of private keys alone, now mostly BIP 39 mnemonics, do not tell a restored wallet which output scripts to produce, and missing derivation-path information adds more incompatibilities.
BIP 380 L26–29 BIP 380 L32 BIP 380 L32–33
Quoted source text (3)
Typically backups have consisted of solely the private keys, nowadays primarily in the form of BIP 39 mnemonics. However this backup solution is insufficient, especially since the introduction of Segregated Witness which added new output types. Given just the private keys, it is not possible for restored wallets to know which kinds of output scripts and addresses to produce.
Although BIPs 44, 49, and 84 have specified standard BIP 32 derivation paths for different output scripts and addresses, not all wallets support those derivation paths nor use them.
The lack of derivation path information in these backups and exports leads to further incompatibilities between wallets.
-
↩ History BIPs 380 to 386 are application-layer specifications by Pieter Wuille and Ava Chow, assigned in 2021 and recorded as Deployed; 381 to 386 each require BIP 380.
Quoted source text (2)
Layer: Applications Title: Output Script Descriptors General Operation Authors: Pieter Wuille <pieter@wuille.net> Ava Chow <me@achow101.com> Status: Deployed Type: Specification Assigned: 2021-06-27
Title: tr() Output Script Descriptors Authors: Pieter Wuille <pieter@wuille.net> Ava Chow <me@achow101.com> Status: Deployed Type: Specification Assigned: 2021-06-27 License: BSD-2-Clause Requires: 380
-
↩ Rule Output script descriptors are a simple language for describing collections of output scripts; BIP 380 gives the general syntax, the checksum and the common expressions.
Quoted source text (1)
Output Script Descriptors are a simple language which can be used to describe collections of output scripts. There can be many different descriptor fragments and functions. This document describes the general syntax for descriptors, descriptor checksums, and common expressions.
-
↩ a b c Author’s rationale Descriptors state script types explicitly in script expressions and derivation paths in key expressions, so backups and exports can specify the exact scripts, subscripts and keys, in a form meant to be readable at a glance.
Quoted source text (2)
Script types are specified explicitly through the use of Script Expressions. Key derivation paths are specified explicitly in Key Expressions. These allow for creating wallet backups and exports which specify the exact scripts, subscripts (redeemScript, witnessScript, etc.), and keys to produce.
the use of common terminology and existing standards allow for Output Script Descriptors to be engineer readable so that the results can be understood at a glance.
-
↩ a b Rule Each character becomes its position within its group, and after every third character a symbol for the three group numbers is inserted, so a change to only the position or only the group affects a single symbol.
Quoted source text (1)
The entire descriptor string is first processed into an array of symbols. The symbol for each character is its position within its group. After every 3rd symbol, a 4th symbol is inserted which represents the group numbers combined together. This means that a change that only affects the position within a group, or only a group number change, will only affect a single symbol.
-
↩ a b Rule Descriptors may only use a fixed character set, which BIP 380 writes as three groups of 32 (its own code has 95 characters, the last group one short) in an order chosen so the checksum can identify more errors.
Quoted source text (2)
The expressions used in descriptors must only contain characters within this character set so that the descriptor checksum will work.
This character set is written as 3 groups of 32 characters in this specific order so that the checksum below can identify more errors. The first group are the most common "unprotected" characters (i.e. things such as hex and keypaths that do not already have their own checksums).
-
↩ a b c Test vector This site's checksum code, transcribed from BIP 380's Python, reproduces the published checksum #89f8spxm for raw(deadbeef) and gives the expected verdict for each of BIP 380's checksum vectors; a test confirms every single-character substitution from the first group in that descriptor is detected.
Quoted source text (1)
* Valid checksum: <tt>raw(deadbeef)#89f8spxm</tt>
-
↩ a b c Rule A descriptor is a top-level script expression, optionally followed by # and an 8-character checksum; the checksum is optional for parsing, but applications may reject descriptors without one.
Quoted source text (1)
The top level expression is a <tt>SCRIPT</tt>. This expression may be followed by <tt>#CHECKSUM</tt>, where <tt>CHECKSUM</tt> is an 8 character alphanumeric descriptor checksum. Although the checksum is optional for parsing, applications may choose to reject descriptors that do not contain a checksum.
-
↩ Rule Script expressions are written as functions whose arguments fill a script template; the arguments may be script expressions, key expressions or something else.
Quoted source text (1)
Script Expressions (denoted <tt>SCRIPT</tt>) are expressions which correspond directly with a Bitcoin script. These expressions are written as functions and take arguments. Such expressions have a script template which is filled with the arguments correspondingly.
-
↩ a b c d Rule BIP 381 defines pk() (P2PK, allowed at any level), pkh() (P2PKH; top level or inside sh() or wsh()) and sh() (P2SH, top level only, whose argument becomes the redeemScript), the three main standard formats before SegWit.
BIP 381 L27–28 BIP 381 L36 BIP 381 L48 BIP 381 L60–63
Quoted source text (4)
Prior to the activation of Segregated Witness, there were 3 main standard output script formats: P2PK, P2PKH, and P2SH.
The <tt>pk(KEY)</tt> expression can be used in any context or level of a descriptor.
The <tt>pkh(KEY)</tt> expression can be used as a top level expression, or inside of either a <tt>sh()</tt> or <tt>wsh()</tt> descriptor.
The <tt>sh(SCRIPT)</tt> expression can only be used as a top level expression. It takes a single script expression as an argument and produces a P2SH output script. <tt>sh()</tt> expressions also create a redeemScript which is required in order to spend outputs which use its output script.
-
↩ a b c d Rule BIP 382 defines wpkh() and wsh() for SegWit's P2WPKH and P2WSH, usable at the top level or inside sh(); only compressed public keys are allowed in wpkh() and anywhere under wsh().
Quoted source text (2)
The <tt>wpkh(KEY)</tt> expression can be used as a top level expression, or inside of a <tt>sh()</tt> descriptor. It takes a single key expression as an argument and produces a P2WPKH output script. Only keys which are/have compressed public keys can be contained in a <tt>wpkh()</tt> expression.
Any key expression found in any script expression contained by a <tt>wsh()</tt> expression must only produce compressed public keys.
-
↩ a b c d Rule tr(KEY) produces a P2TR output with no usable script path (the key is tweaked to commit to an unspendable one); tr(KEY, TREE) adds a script tree written with braces; all keys under tr() are x-only, and uncompressed keys are not allowed.
BIP 386 L49–50 BIP 386 L52 BIP 386 L63–66 BIP 386 L78
Quoted source text (4)
The <tt>tr(KEY)</tt> or <tt>tr(KEY, TREE)</tt> expression can only be used as a top level expression. All key expressions under any <tt>tr()</tt> expression must create x-only public keys.
<tt>tr(KEY)</tt> takes a single key expression as an argument and produces a P2TR output script which does not have a script path.
<tt>tr(KEY, TREE)</tt> takes a key expression as the first argument, and a tree expression as the second argument and produces a P2TR output script which has a script path.
Uncompressed public keys are not allowed, but compressed public keys would be implicitly converted to x-only public keys.
-
↩ History BIP 381 counts three main standard output formats before SegWit: P2PK, P2PKH and P2SH.
Quoted source text (1)
Prior to the activation of Segregated Witness, there were 3 main standard output script formats: P2PK, P2PKH, and P2SH.
-
↩ Rule Each script expression fills a fixed template: pk() gives <KEY> OP_CHECKSIG, pkh() gives OP_DUP OP_HASH160 <KEY_hash160> OP_EQUALVERIFY OP_CHECKSIG, and wpkh() gives OP_0 <KEY_hash160>.
BIP 381 L43 BIP 381 L55 BIP 382 L41
Quoted source text (3)
<KEY> OP_CHECKSIG
OP_DUP OP_HASH160 <KEY_hash160> OP_EQUALVERIFY OP_CHECKSIG
OP_0 <KEY_hash160>
-
↩ a b c Rule A key expression is optional origin information (an 8-hex-character fingerprint and the derivation steps from it, in brackets), then a hex public key, a WIF private key, or an xpub or xprv followed by derivation steps and optionally /* or /*h; h and ' both mark hardened steps.
BIP 380 L70–74 BIP 380 L75–82 BIP 380 L89
Quoted source text (3)
* Optionally, key origin information, consisting of: ** An open bracket <tt>[</tt> ** Exactly 8 hex characters for the fingerprint of the key where the derivation starts (see BIP 32 for details)
** A [[https://en.bitcoin.it/wiki/Wallet_import_format|WIF]] encoded private key ** <tt>xpub</tt> encoded extended public key or <tt>xprv</tt> encoded extended private key (as defined in BIP 32) *** Followed by zero or more <tt>/NUM</tt> or <tt>/NUMh</tt> path elements indicating BIP 32 derivation steps to be taken after the given extended key. *** Optionally followed by a single <tt>/*</tt> or <tt>/*h</tt> final step to denote all direct unhardened or hardened children.
the hardened indicator <tt>h</tt> may be replaced with alternative hardened indicator of <tt>'</tt>.
-
↩ Test vector Key origin information describes where a key came from and does not change the script: BIP 381 lists pkh() with an origin, written with ' or with h, and with a WIF key or its public key, all producing the same script.
Quoted source text (2)
These represent a public or private key and, optionally, information about the origin of that key.
* <tt>pkh([deadbeef/1/2'/3/4']L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)</tt> ** <tt>76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac</tt> * <tt>pkh([deadbeef/1/2'/3/4']03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)</tt> ** <tt>76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac</tt> * <tt>pkh([deadbeef/1/2h/3/4h]03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)</tt> ** <tt>76a9149a1c78a507689f6f54b847ad1cef1e614ee23f1e88ac</tt>
-
↩ Editorial inference The origin information exists so that software holding the root key can tell which of its keys a descriptor key is; the script itself does not depend on it.
Quoted source text (1)
** Exactly 8 hex characters for the fingerprint of the key where the derivation starts (see BIP 32 for details) ** Followed by zero or more <tt>/NUM</tt> or <tt>/NUMh</tt> path elements to indicate the unhardened or hardened derivation steps between the fingerprint and the key that follows.
-
↩ a b c Rule When the final step is /* or /*', an output script is produced for every child index.
Quoted source text (1)
When the final step is <tt>/*</tt> or <tt>/*'</tt>, an output script will be produced for every child key index.
-
↩ a b c Test vector This site's descriptor model expands every valid descriptor listed in BIPs 381 to 386 to exactly the scripts the BIPs list (for ranged ones, the children each BIP lists: 0 to 2, or 0 and 1 for combo()) and rejects every listed invalid descriptor; the one listed valid descriptor with a Miniscript leaf, tr(…, pkh(…)), is outside the model's scope and is refused as such.
Quoted source text (2)
Valid descriptors followed by the scripts they produce. Descriptors involving derived child keys will have the 0th, 1st, and 2nd scripts listed.
* <tt>tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))</tt>
-
↩ a b c Editorial inference A descriptor whose keys are all public reveals the scripts it stands for but cannot spend them; one that contains a WIF key or an xprv is as sensitive as those keys.
Quoted source text (1)
** A [[https://en.bitcoin.it/wiki/Wallet_import_format|WIF]] encoded private key ** <tt>xpub</tt> encoded extended public key or <tt>xprv</tt> encoded extended private key (as defined in BIP 32)
-
↩ a b Editorial inference The checksum is computed from the descriptor text alone, with no key, so anyone can produce a valid checksum for any descriptor: it catches typos, not tampering.
Quoted source text (1)
def descsum_create(s): """Add a checksum to a descriptor without""" symbols = descsum_expand(s) + [0, 0, 0, 0, 0, 0, 0, 0] checksum = descsum_polymod(symbols) ^ 1
-
↩ Rule When a descriptor is exported without private keys, BIP 380 says the exporter should derive the extended public key at the last hardened step, and the steps taken to get there must be added to the key origin.
Quoted source text (1)
When a descriptor is exported without private keys, it is necessary to do additional derivation to remove any intermediate hardened derivation steps for the exported descriptor to be useful. The exporter should derive the extended public key at the last hardened derivation step and use that extended public key as the key in the descriptor. The derivation steps that were taken to get to that key must be added to the previous key origin information.
-
↩ a b Rule The checksum is an error-correcting code similar to bech32: any 1 symbol error is always detected, any 2 or 3 in descriptors up to 49,154 characters, any 4 up to 507, any 5 up to 77, and random errors go undetected with a chance of 1 in 2^40.
BIP 380 L118 BIP 380 L127–132 BIP 380 L132
Quoted source text (3)
The checksum is an error correcting checksum similar to bech32.
* Any 1 symbol error is always detected. * Any 2 or 3 symbol error in a descriptor of up to 49154 characters is always detected. * Any 4 symbol error in a descriptor of up to 507 characters is always detected. * Any 5 symbol error in a descriptor of up to 77 characters is always detected.
* Random errors have a chance of 1 in 240 of being undetected.
-
↩ Rule BIP 380's checksum vectors cover a valid checksum, a missing one, one character too many or too few, an error in the payload, an error in the checksum, and a character outside the set.
Quoted source text (1)
* Valid checksum: <tt>raw(deadbeef)#89f8spxm</tt> * No checksum: <tt>raw(deadbeef)</tt> * Missing checksum: <tt>raw(deadbeef)#</tt> * Too long checksum (9 chars): <tt>raw(deadbeef)#89f8spxmx</tt> * Too short checksum (7 chars): <tt>raw(deadbeef)#89f8spx</tt> * Error in payload: <tt>raw(deedbeef)#89f8spxm</tt> * Error in checksum: <tt>raw(deedbeef)##9f8spxm</tt> * Invalid characters in payload: <tt>raw(Ü)#00000000</tt>
-
↩ a b Rule multi(k, KEY_1, …, KEY_n) and sortedmulti() produce a k-of-n CHECKMULTISIG script with k ≤ n; sortedmulti() sorts the derived keys, extended keys advance in lockstep, and the number of keys is limited to 3 at the top level, 15 compressed keys in sh() (the 520-byte push limit), and 20 otherwise.
BIP 383 L33–35 BIP 383 L41–47 BIP 383 L60–61 BIP 383 L65–66
Quoted source text (4)
They are written as <tt>multi(k,KEY_1,KEY_2,...,KEY_n)</tt>. <tt>k</tt> is the threshold - the number of keys that must sign the input for the script to be valid. <tt>KEY_1,KEY_2,...,KEY_n</tt> are the key expressions for the multisig. <tt>k</tt> must be less than or equal to <tt>n</tt>.
When used at the top level, there can only be at most 3 keys. When used inside of a <tt>sh()</tt> expression, the output script produced is the redeem script, which is pushed as a single element in the spending scriptSig and must therefore not exceed the 520 byte limit on the size of a script element. This allows at most 15 compressed public keys, or at most 7 uncompressed ones, as an uncompressed key takes 66 bytes of the script rather than 34. Otherwise the maximum number of keys is 20.
The only change for <tt>sortedmulti()</tt> is that the 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.
When one or more the key expressions in a <tt>multi()</tt> or <tt>sortedmulti()</tt> expression are extended keys, the derived keys use the same child index.
-
↩ a b Rule combo(KEY), top level only, produces P2PK and P2PKH scripts, plus P2WPKH and P2SH-P2WPKH for a compressed key, to ease the move from key-based to descriptor-based wallets.
Quoted source text (2)
In order to make the transition from traditional key based wallets to descriptor based wallets easier, it is useful to be able to take a key and produce the scripts which have traditionally been produced by wallet software.
This expression can only be used as a top level expression. It takes a single key expression as an argument and produces either 2 or 4 output scripts, depending on the key.
-
↩ a b Rule raw(HEX) and addr(ADDR), top level only, wrap an arbitrary script or an address as a descriptor.
Quoted source text (2)
In order to make descriptors maximally compatible with scripts in use today, it is useful to be able to wrap any arbitrary output script or an address into a descriptor.
The <tt>raw(HEX)</tt> expression can only be used as a top level descriptor. As the argument, it takes a hex string representing a Bitcoin script.
-
↩ a b Rule BIP 380's appendix indexes the script expressions and the BIPs that define them, and leaves room for future ones such as musig() (BIP 390) and sp() (BIP 392).
BIP 380 L299–300 BIP 380 L339–343
Quoted source text (2)
Script expressions will be specified in additional BIPs. This Table lists all available Script expressions and the BIPs specifying them.
| <tt>musig(KEY, KEY, ..., KEY)</tt> | [[bip-0390.mediawiki|390]] |- | <tt>sp(KEY)</tt>, <tt>sp(KEY, KEY)</tt> | [[bip-0392.mediawiki|392]]
-
↩ History Of the script expressions that existed when BIP 386 was written, only pk() can be used in a tree; Miniscript (BIP 379) and BIP 387's multi_a() came later.
Quoted source text (1)
Of the script expressions that existed when this BIP was written, only <tt>pk()</tt> can be used in a tree expression. Script expressions specified since then that can be used in a tree expression are the Miniscript expressions of [[bip-0379.md|379]], which include a <tt>pkh()</tt> fragment, and the <tt>multi_a()</tt> and <tt>sortedmulti_a()</tt> expressions of [[bip-0387.mediawiki|387]].
-
↩ History The BIPs record descriptors as implemented in Bitcoin Core since version 0.17, and tr() since version 22.0.
Quoted source text (2)
Descriptors have been implemented in Bitcoin Core since version 0.17.
<tt>tr()</tt> descriptors have been implemented in Bitcoin Core since version 22.0.
-
↩ Author’s rationale The authors call alternative version bytes for extended keys a layer violation, since key derivation should be separate from script type, and specific to one path and script type.
Quoted source text (1)
Solutions such as introducing different version bytes for extended key serialization both are a layer violation (key derivation should be separate from script type meaning) and specific only to a particular derivation path and script type.