Skip to content
BIP ATLAS

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 revision
bitcoin/bips @ 3a10b5b
Source checked
1 October 2026
Review state
Draft — independent technical review applied; awaiting human sign-off
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

Pinned source · Reader view on bips.dev
SHA-256 34e6510bb2eba9445a68eacf3d24d5a4e5f24481477488d5552f674ac81dd5fe
Git blob 88fd273a186a916a04ae3f3f48c2ba05396db494

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

Pinned source · Reader view on bips.dev
SHA-256 f0f6060332f82454f61015815c824eea4b7b6684ce4892ef42d23e4e782fa817
Git blob b3ccf49abf79497eba495f42d73d759db046b139

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

Pinned source · Reader view on bips.dev
SHA-256 6cd2574998ca0d2141d1c487e70da2dfab47abd6a2dfcc3680af2c241f01fe9d
Git blob aaad5426fb11c68df91272f4062183a551ecb52c

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

Pinned source · Reader view on bips.dev
SHA-256 c46f75e5869386c1852dd187725293822b9e3b761342a966fbcf99adaa112aa2
Git blob 04e732756c934f234563127411048d289a5492b9

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

Pinned source · Reader view on bips.dev
SHA-256 9d6b32a619e021f50f4b1a07ed8f9d08cfea599c8f484e6b1360ada9aae8541c
Git blob 8db844d02515aadf6e16db788f105638edc3fd01

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

Pinned source · Reader view on bips.dev
SHA-256 8c4963492f1d5b492808e5ece8be75f7f66def37f35d091074fdbfa98a6ddd08
Git blob e14aa3829796d94f0b439e3202dd7fa23d504900

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

Pinned source · Reader view on bips.dev
SHA-256 770121b4b33a50bfadfebcd94931dd0ad04159b9fbc1d3b3c3ae17fc0cc16de8
Git blob 85a63f0b53fb965641eaa291052b23abdf837506

FIG. A13.1 Characters into symbols
  1. rg29
  2. ag018
  3. wg214
  4. (g010
  5. dg021
  6. eg022
  7. ag018
  8. dg021
  9. bg019
  10. eg022
  11. eg022
  12. fg023
  13. )g011
  1. 9
  2. 18
  3. 14
  4. 20
  5. 10
  6. 21
  7. 22
  8. 0
  9. 18
  10. 21
  11. 19
  12. 0
  13. 22
  14. 22
  15. 23
  16. 0
  17. 11
  18. 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.

BIP 380’s own checksum vector. Each character becomes a position and a group; the checksum is computed over the resulting symbols.567

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

FIG. A13.2 Reading a descriptor Interactive

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)

  1. child 00014326b2249e3a25d5dc60935f044ee835d090ba859
  2. child 10014af0bd98abc2f2cae66e36896a39ffe2d32984fb7
  3. child 200141fa798efd1cbf95cebf912c031b8a4a6e9fb9f27

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.

12345
  1. The script expression says what kind of output

    outline
    wpkh(KEY)

    wpkh(KEY): pay to the hash of one compressed key, SegWit v0.

  2. 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.

  3. The key itself: an extended public key

    key
    xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH

    Public only, so the descriptor reveals scripts but cannot spend.

  4. 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.

  5. 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.

Descriptors published in BIPs 380–386, split into their parts, expanded, and checked. Every expansion matches the scripts the BIPs list.81518192021

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

FIG. A13.3 Where each expression may go
Script expressions, the BIP that defines each, where it may appear and what it produces
ExpressionBIPMay appearProduces
pk(KEY)381top level, in sh(), in wsh(), in a tr() tree<KEY> OP_CHECKSIG
pkh(KEY)381top level, in sh(), in wsh()OP_DUP OP_HASH160 <KEY_hash160> OP_EQUALVERIFY OP_CHECKSIG
sh(SCRIPT)381top levelOP_HASH160 <SCRIPT_hash160> OP_EQUAL
wpkh(KEY)382top level, in sh()OP_0 <KEY_hash160>
wsh(SCRIPT)382top level, in sh()OP_0 <SCRIPT_sha256>
multi(NUM, KEY, ..., KEY)383top level, in sh(), in wsh()k KEY_1 … KEY_n n OP_CHECKMULTISIG
sortedmulti(NUM, KEY, ..., KEY)383top level, in sh(), in wsh()as multi(), keys sorted
combo(KEY)384top levelP2PK, P2PKH (+ P2WPKH, P2SH-P2WPKH if compressed)
raw(HEX)385top levelthe script itself
addr(ADDR)385top levelthe address's output script
tr(KEY)386top levelOP_1 <32_byte_output_key>
tr(KEY, TREE)386top levelOP_1 <32_byte_output_key>
musig(KEY, KEY, ..., KEY)390not covered here—
sp(KEY)392not covered here—
sp(KEY, KEY)392not 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.

BIP 380’s index of script expressions, with the placement rules the model enforces.10111225262728

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.

  1. ↩ 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.

    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.

    BIP 380, lines 26–29

    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.

    BIP 380, line 32

    The lack of derivation path information in these backups and exports leads to further incompatibilities between wallets.

    BIP 380, lines 32–33
  2. ↩ 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

    BIP 380, lines 3–9

    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

    BIP 386, lines 4–11
  3. ↩ 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.

    BIP 380, lines 15–17
  4. ↩ 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.

    BIP 380, lines 39–43

    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.

    BIP 380, line 43
  5. ↩ 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.

    BIP 380, lines 184–187
  6. ↩ 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.

    BIP 380, line 101

    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).

    BIP 380, lines 111–112
  7. ↩ 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>

    BIP 380, lines 204–209
  8. ↩ 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.

    BIP 380, lines 48–50
  9. ↩ 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.

    BIP 380, lines 54–61
  10. ↩ 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.

    Quoted source text (4)

    Prior to the activation of Segregated Witness, there were 3 main standard output script formats: P2PK, P2PKH, and P2SH.

    BIP 381, lines 27–28

    The <tt>pk(KEY)</tt> expression can be used in any context or level of a descriptor.

    BIP 381, line 36

    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.

    BIP 381, line 48

    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.

    BIP 381, lines 60–63
  11. ↩ 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.

    BIP 382, lines 35–37

    Any key expression found in any script expression contained by a <tt>wsh()</tt> expression must only produce compressed public keys.

    BIP 382, line 50
  12. ↩ 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.

    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.

    BIP 386, lines 49–50

    <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.

    BIP 386, line 52

    <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.

    BIP 386, lines 63–66

    Uncompressed public keys are not allowed, but compressed public keys would be implicitly converted to x-only public keys.

    BIP 386, line 78
  13. ↩ 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.

    BIP 381, line 27
  14. ↩ 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>.

    Quoted source text (3)

    <KEY> OP_CHECKSIG

    BIP 381, line 43

    OP_DUP OP_HASH160 <KEY_hash160> OP_EQUALVERIFY OP_CHECKSIG

    BIP 381, line 55

    OP_0 <KEY_hash160>

    BIP 382, line 41
  15. ↩ 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.

    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)

    BIP 380, lines 70–74

    ** 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.

    BIP 380, lines 75–82

    the hardened indicator <tt>h</tt> may be replaced with alternative hardened indicator of <tt>'</tt>.

    BIP 380, line 89
  16. ↩ 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.

    BIP 380, line 66

    * <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>

    BIP 381, lines 78–83
  17. ↩ 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.

    BIP 380, lines 72–73
  18. ↩ 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.

    BIP 380, line 85
  19. ↩ 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.

    BIP 381, line 72

    * <tt>tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))</tt>

    BIP 386, line 100
  20. ↩ 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)

    BIP 380, lines 79–80
  21. ↩ 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

    BIP 380, lines 192–196
  22. ↩ 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.

    BIP 380, lines 93–95
  23. ↩ 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.

    Quoted source text (3)

    The checksum is an error correcting checksum similar to bech32.

    BIP 380, line 118

    * 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.

    BIP 380, lines 127–132

    * Random errors have a chance of 1 in 240 of being undetected.

    BIP 380, line 132
  24. ↩ 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>

    BIP 380, lines 204–211
  25. ↩ 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.

    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>.

    BIP 383, lines 33–35

    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.

    BIP 383, lines 41–47

    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.

    BIP 383, lines 60–61

    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.

    BIP 383, lines 65–66
  26. ↩ 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.

    BIP 384, line 25

    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.

    BIP 384, lines 30–33
  27. ↩ 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.

    BIP 385, line 26

    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.

    BIP 385, lines 34–36
  28. ↩ 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).

    Quoted source text (2)

    Script expressions will be specified in additional BIPs. This Table lists all available Script expressions and the BIPs specifying them.

    BIP 380, lines 299–300

    | <tt>musig(KEY, KEY, ..., KEY)</tt> | [[bip-0390.mediawiki|390]] |- | <tt>sp(KEY)</tt>, <tt>sp(KEY, KEY)</tt> | [[bip-0392.mediawiki|392]]

    BIP 380, lines 339–343
  29. ↩ 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]].

    BIP 386, lines 116–118
  30. ↩ 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.

    BIP 380, line 268

    <tt>tr()</tt> descriptors have been implemented in Bitcoin Core since version 22.0.

    BIP 386, line 122
  31. ↩ 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.

    BIP 380, line 36