{
    "meta": {
        "title": "D-Central — Bitcoin Output Script Descriptors Reference",
        "description": "Every descriptor expression defined in BIP-380 through BIP-392 (17 rows): the output script each produces, nesting rules, defining BIP and BIP status. rawtr() included and flagged as a Bitcoin Core extension with no defining BIP.",
        "generated": "2026-07-26T05:42:40+00:00",
        "version": "1.0",
        "as_of": "2026-07-26",
        "license": "https://creativecommons.org/licenses/by/4.0/",
        "license_name": "CC BY 4.0",
        "source": "https://d-central.tech/bitcoin-output-descriptors-reference/",
        "method": "Extracted from the raw BIP texts (bitcoin/bips master: bip-0380 through bip-0392, fetched 2026-07-26). Purposes and nesting rules are faithful paraphrases of the spec text; BIP Status lines transcribed verbatim from the BIP headers. BIP-388 (wallet policies) defines no descriptor functions and BIP-391 is Closed — both deliberately excluded.",
        "provenance": "bitcoin/bips (github.com/bitcoin/bips) BIP-0380..0392.",
        "record_count": 17
    },
    "rows": [
        {
            "expr": "pk(KEY)",
            "kind": "script",
            "bip": "BIP381",
            "status": "Deployed",
            "output_type": "P2PK — <KEY> OP_CHECKSIG",
            "purpose": "Takes a single key expression and produces a pay-to-pubkey output script.",
            "nesting": "Any context: top level, inside sh() or wsh(), and the original script expression allowed inside tr() TREEs."
        },
        {
            "expr": "pkh(KEY)",
            "kind": "script",
            "bip": "BIP381",
            "status": "Deployed",
            "output_type": "P2PKH — OP_DUP OP_HASH160 <KEY_hash160> OP_EQUALVERIFY OP_CHECKSIG",
            "purpose": "Takes a single key expression and produces a pay-to-pubkey-hash output script.",
            "nesting": "Top level, or inside sh() or wsh(). Not allowed inside tr() trees."
        },
        {
            "expr": "sh(SCRIPT)",
            "kind": "script",
            "bip": "BIP381",
            "status": "Deployed",
            "output_type": "P2SH — OP_HASH160 <SCRIPT_hash160> OP_EQUAL",
            "purpose": "Takes a script expression and produces a P2SH output script; its argument's output script is the redeemScript needed to spend.",
            "nesting": "Top level ONLY."
        },
        {
            "expr": "wpkh(KEY)",
            "kind": "script",
            "bip": "BIP382",
            "status": "Deployed",
            "output_type": "P2WPKH — OP_0 <KEY_hash160>",
            "purpose": "Takes a single key expression and produces a P2WPKH output script. Only compressed public keys are allowed.",
            "nesting": "Top level, or inside sh() (P2SH-P2WPKH). Not allowed inside wsh()."
        },
        {
            "expr": "wsh(SCRIPT)",
            "kind": "script",
            "bip": "BIP382",
            "status": "Deployed",
            "output_type": "P2WSH — OP_0 <SCRIPT_sha256>",
            "purpose": "Takes a script expression and produces a P2WSH output script; its argument's output script is the witnessScript. All keys under it must be compressed.",
            "nesting": "Top level, or inside sh() (P2SH-P2WSH). Cannot nest inside another wsh()."
        },
        {
            "expr": "multi(k,KEY_1,...,KEY_n)",
            "kind": "script",
            "bip": "BIP383",
            "status": "Deployed",
            "output_type": "Multisig — k KEY_1 ... KEY_n n OP_CHECKMULTISIG",
            "purpose": "Threshold multisig: k of n keys must sign, keys in the order given. Extended keys derive in lockstep (same child index).",
            "nesting": "Top level (max 3 keys), inside sh() (max 15 compressed keys), or inside wsh() (max 20 keys)."
        },
        {
            "expr": "sortedmulti(k,KEY_1,...,KEY_n)",
            "kind": "script",
            "bip": "BIP383",
            "status": "Deployed",
            "output_type": "Same multisig template as multi()",
            "purpose": "Identical to multi() except public keys are sorted lexicographically before script creation (after derivation).",
            "nesting": "Same as multi(): top level, inside sh(), or inside wsh()."
        },
        {
            "expr": "combo(KEY)",
            "kind": "script",
            "bip": "BIP384",
            "status": "Deployed",
            "output_type": "2 or 4 scripts: P2PK + P2PKH always; plus P2WPKH + P2SH-P2WPKH if the key is compressed",
            "purpose": "Compatibility descriptor producing every script traditionally generated by key-based wallets for one key.",
            "nesting": "Top level ONLY."
        },
        {
            "expr": "raw(HEX)",
            "kind": "script",
            "bip": "BIP385",
            "status": "Deployed",
            "output_type": "The literal script encoded by HEX",
            "purpose": "Encapsulates an arbitrary raw output script, given as hex, as a descriptor.",
            "nesting": "Top level ONLY."
        },
        {
            "expr": "addr(ADDR)",
            "kind": "script",
            "bip": "BIP385",
            "status": "Deployed",
            "output_type": "The output script produced by the address ADDR",
            "purpose": "Encapsulates any Bitcoin address as a descriptor.",
            "nesting": "Top level ONLY."
        },
        {
            "expr": "tr(KEY) / tr(KEY,TREE)",
            "kind": "script",
            "bip": "BIP386",
            "status": "Deployed",
            "output_type": "P2TR — OP_1 <32_byte_output_key>",
            "purpose": "Produces a taproot output. tr(KEY) uses KEY as the BIP-341 internal key with an unspendable script path; tr(KEY,TREE) additionally commits to a taproot script tree whose merkle root tweaks the internal key. All keys must produce x-only keys; uncompressed keys are forbidden.",
            "nesting": "Top level ONLY. TREE is either an allowed script expression or {TREE,TREE} pairs."
        },
        {
            "expr": "multi_a(k,KEY_1,...,KEY_n)",
            "kind": "script",
            "bip": "BIP387",
            "status": "Deployed",
            "output_type": "Tapscript multisig — KEY_1 OP_CHECKSIG KEY_2 OP_CHECKSIGADD ... k OP_NUMEQUAL",
            "purpose": "Threshold multisig for tapscript using OP_CHECKSIGADD. Max 999 keys; extended keys derive in lockstep.",
            "nesting": "ONLY inside a tr() descriptor; invalid at top level, in sh(), or in wsh()."
        },
        {
            "expr": "sortedmulti_a(k,KEY_1,...,KEY_n)",
            "kind": "script",
            "bip": "BIP387",
            "status": "Deployed",
            "output_type": "Same tapscript multisig template as multi_a()",
            "purpose": "Identical to multi_a() except x-only keys are sorted lexicographically before script creation (after derivation).",
            "nesting": "ONLY inside tr()."
        },
        {
            "expr": "sp(KEY) / sp(KEY,KEY)",
            "kind": "script",
            "bip": "BIP392",
            "status": "Draft",
            "output_type": "P2TR outputs as computed for silent payments (BIP-352)",
            "purpose": "Descriptor for BIP-352 silent payments. sp(KEY) takes a Bech32m-encoded spscan (watch-only) or spspend key; sp(KEY,KEY) takes a private scan key plus any single-key spend expression (musig() allowed). Uncompressed keys forbidden.",
            "nesting": "Top level ONLY."
        },
        {
            "expr": "musig(KEY,...,KEY)",
            "kind": "key",
            "bip": "BIP390",
            "status": "Draft",
            "output_type": "Not a script — a key expression producing a BIP-327 MuSig2 aggregate public key",
            "purpose": "Aggregates the listed participant keys with BIP-327 KeyAgg after derivation, with mandatory KeySort before aggregation. A /NUM/.../* suffix does further unhardened BIP-328 derivation on the aggregate key (participants must then be xpubs without their own /* or multipath).",
            "nesting": "Key-expression position only, inside tr(), rawtr(), or sp(); cannot nest inside another musig()."
        },
        {
            "expr": "KEY/<NUM;NUM;...> (multipath)",
            "kind": "key",
            "bip": "BIP389",
            "status": "Draft",
            "output_type": "Not a script — expands one descriptor into N descriptors (one per tuple value)",
            "purpose": "One derivation step in an extended-key path may be a tuple; the descriptor is treated as multiple descriptors, commonly /<0;1> for receive/change. All multipath expressions in one descriptor must have equal tuple lengths; duplicates forbidden; one multipath specifier per key expression; not allowed in key origins.",
            "nesting": "A modification of BIP-380 key expressions — usable wherever ranged extended keys are."
        },
        {
            "expr": "rawtr(KEY)",
            "kind": "script",
            "bip": "— (no BIP)",
            "status": "Bitcoin Core extension (since v24.0)",
            "output_type": "P2TR — OP_1 <KEY as the output key directly>",
            "purpose": "Uses KEY directly as the taproot output key with no tweaking — no BIP defines it, but BIP-390 references it as a valid musig() context and Bitcoin Core supports it.",
            "nesting": "Top level ONLY."
        }
    ]
}