Home › Browse › BIP 386

BIP 386: tr() Output Script Descriptors

In plain English: Defines the descriptor function for Taproot outputs, combining a main key with an optional tree of alternative spending conditions. This gives wallets a standard way to describe, back up and recover Taproot wallets.

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

Abstract

This document specifies tr() output script descriptors. tr() descriptors take a key and optionally a tree of scripts and produces a P2TR output script.

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

Motivation

Taproot added one additional standard output script format: P2TR. These expressions allow specifying those formats as a descriptor.

Specification

A new script expression is defined: tr(). A new expression is defined: Tree Expressions

Tree Expression

A Tree Expression (denoted TREE) is an expression which represents a tree of scripts. The way the tree is represented in an output script is dependent on the higher level expressions.

A Tree Expression is:

  • Any Script Expression that is allowed at the level this Tree Expression is in.
  • A pair of Tree Expressions consisting of:
    • An open brace {
    • A Tree Expression
    • A comma ,
    • A Tree Expression
    • A closing brace }

tr()

The tr(KEY) or tr(KEY, TREE) expression can only be used as a top level expression. All key expressions under any tr() expression must create x-only public keys.

tr(KEY) takes a single key expression as an argument and produces a P2TR output script which does not have a script path. Each key produced by the key expression is used as the internal key of a P2TR output as specified by BIP 341. Specifically, "If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as Q = P + int(hashTapTweak(bytes(P)))G."

internal_key:       lift_x(KEY)
32_byte_output_key: internal_key + int(HashTapTweak(bytes(internal_key)))G
scriptPubKey:       OP_1 <32_byte_output_key>

tr(KEY, TREE) 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. The keys produced by the first key expression are used as the internal key as specified by BIP 341. The Tree expression becomes the Taproot script tree as described in BIP 341. A merkle root is computed from this tree and combined with the internal key to create the Taproot output key.

internal_key:       lift_x(KEY)
merkle_root:        HashTapBranch(TREE)
32_byte_output_key: internal_key + int(HashTapTweak(bytes(internal_key) || merkle_root))G
scriptPubKey:       OP_1 <32_byte_output_key>

Modified Key Expression

Key Expressions within a tr() expression must only create x-only public keys. Uncompressed public keys are not allowed, but compressed public keys would be implicitly converted to x-only public keys. The keys derived from extended keys must be serialized as x-only public keys. An additional key expression is defined only for use within a tr() descriptor:

  • A 64 hex character string representing an x-only public key

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(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)
    • 512077aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11
  • tr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)
    • 512077aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11
  • tr(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/0/*,pk(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/1/*))
    • 512078bc707124daa551b65af74de2ec128b7525e10f374dc67b64e00ce0ab8b3e12
    • 512001f0a02a17808c20134b78faab80ef93ffba82261ccef0a2314f5d62b6438f11
    • 512021024954fcec88237a9386fce80ef2ced5f1e91b422b26c59ccfc174c8d1ad25
  • tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(669b8afcec803a0d323e9a17f3ea8e68e8abe5a278020a929adbec52421adbd0))
    • 512017cf18db381d836d8923b1bdb246cfcd818da1a9f0e6e7907f187f0b2f937754
  • tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,{pk(xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334/0),{{pk(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL),pk(02df12b7035bdac8e3bab862a3a83d06ea6b17b6753d52edecba9be46f5d09e076)},pk(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)}})
    • 512071fff39599a7b78bc02623cbe814efebf1a404f5d8ad34ea80f213bd8943f574
  • tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pkh(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1))

Invalid Descriptors

  • Uncompressed private key: tr(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss)
  • Uncompressed public key: tr(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235)
  • tr() nested in wsh: wsh(tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))
  • tr() nested in sh: sh(tr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))

Backwards Compatibility

tr() descriptors use the format and general operation specified in 380. As these are a set of 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.

Tree Expressions are largely incompatible with existing script expressions due to the restrictions in those expressions. Of the script expressions that existed when this BIP was written, only pk() 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 379, which include a pkh() fragment, and the multi_a() and sortedmulti_a() expressions of 387.

Reference Implementation

tr() descriptors have been implemented in Bitcoin Core since version 22.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…