BIP: 394
Layer: Applications
Title: rawtr() Output Script Descriptors
Authors: jeanpablojp <me@jeanpablo.jp>
Status: Draft
Type: Specification
Assigned: 2026-09-09
License: BSD-2-Clause
Discussion: 2026-03-02: https://github.com/bitcoin/bips/pull/2050#issuecomment-3986205616
2026-08-06: https://groups.google.com/g/bitcoindev/c/CCZN_qQ5C1s
Requires: 341, 380
Abstract
This document specifies rawtr() output script descriptors.
A rawtr() descriptor expresses a Pay-to-Taproot output by its output key directly, without stating an internal key or a script tree.
Motivation
A taproot output key is derived from an internal key and an optional script tree, as described in BIP 341.
The tr() descriptor specified in BIP 386 takes the internal key and the tree, and computes the output key from them.
There is no way to use tr() for an output whose internal structure isn't known, for example an output key received from another party, or one whose script tree the holder does not wish to reveal.
The rawtr() descriptor covers that case by taking the output key itself.
This expression has been implemented in Bitcoin Core since version 24.0, and BIP 390 permits musig() inside rawtr() and uses it in its test vectors.
This document gives the expression a specification of its own.
Specification
A new script expression is defined: rawtr().
The rawtr(KEY) expression can only be used as a top level descriptor.
It takes a single key expression as an argument and produces a P2TR output script.
Unlike tr(), it does not take a tree expression, and the key is used directly as the taproot output key, with no BIP 341 tweak applied.
The output script produced is:
OP_1 <KEY>
Key expressions within a rawtr() expression must only create x-only public keys, as in tr() expressions.
Uncompressed public keys are not allowed. Compressed public keys are allowed, but will be implicitly converted to x-only public keys.
The keys derived from extended keys must be serialized as x-only public keys.
If the private key corresponding to the output key is known, the output can be spent via the key path.
Note that a rawtr() descriptor cannot show whether a script path exists for the output: nothing in it proves that the output key does not commit to a script tree.
Software importing a rawtr() descriptor from an untrusted source should warn that other spending paths may exist.
Rationale
No BIP 341 tweak is applied to the key, since tweaking it would describe a different output than the one the descriptor is for. The expression is top level only, because a P2TR output script is a complete scriptPubKey and there is no context in which it can appear as a sub-expression.
Key expressions are restricted to x-only public keys because a taproot output key is an x-only key.
Compressed public keys are accepted and converted implicitly, as in tr(), so a key expression written for one of the two also works in the other.
The absence of a specification has already produced divergence outside Bitcoin Core.
rust-miniscript renders these outputs as rawtr_not_supported_yet(KEY) and does not parse them back, and the bdk-ffi descriptor tests describe rawtr() as BIP 386, which specifies tr().
Test Vectors
Valid descriptors followed by the scripts they produce. Descriptors involving derived child keys will have the 0th, 1st, and 2nd scripts listed. These vectors were generated with Bitcoin Core's descriptor implementation. Note that the first vector uses the same key as the first tr() vector of BIP 386: with rawtr() the key appears in the script unchanged, while tr() tweaks it. The third vector takes the output key that the BIP 386 vector produced and reproduces its script.
rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)5120a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd
rawtr(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1)5120a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd
rawtr(77aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11)512077aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11
rawtr(03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)5120a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd
rawtr(02a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)5120a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd
rawtr(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/0/*)51208145454b87fc9ec3557478d6eadc2aea290b50f3c469b828abeb542ae8f8849d5120377ad06450813b5f7e10bc94b8b662513398c2d83086f8e67349a00909a5a5a451200a862a965e930b917327d4d08e6309aeb6a4fb0970e133c8ea0d034de04cc3b0
rawtr(xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc/<0;1>/*), a multipath descriptor as specified in BIP 389, expanding into two descriptors:rawtr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)51208145454b87fc9ec3557478d6eadc2aea290b50f3c469b828abeb542ae8f8849d5120377ad06450813b5f7e10bc94b8b662513398c2d83086f8e67349a00909a5a5a451200a862a965e930b917327d4d08e6309aeb6a4fb0970e133c8ea0d034de04cc3b0
rawtr(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*)5120095e95d8c50ae3f3fea93fa8e983f710489f60ff681a658c06eba64622c824b151207512d6bd74e24eeb1ad752d5be800adc5886ded11c5293a9a701db83658b526a5120cc9fd211dc0a1c8bb7a106ff831be0e253bc992f21d08fb8a6fd43fae51b9b89
rawtr(musig(KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74sHUHy8S,03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66)), from the BIP 390 test vectors5120789d937bade6673538f3e28d8368dda4d0512f94da44cf477a505716d26a1575
rawtr(musig(xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL,xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y)/0/*), from the BIP 390 test vectors51209508c08832f3bb9d5e8baf8cb5cfa3669902e2f2da19acea63ff47b93faa9bfc51205ca1102663025a83dd9b5dbc214762c5a6309af00d48167d2d6483808525a29851207dbed1b89c338df6a1ae137f133a19cae6e03d481196ee6f1a5c7d1aeb56b166
Invalid Descriptors
rawtr()nested insh:sh(rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))rawtr()nested inwsh:wsh(rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd))- Script expression instead of a key expression:
rawtr(pk(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd)) - More than one key:
rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,77aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11) - Tree expression, which
rawtr()does not take:rawtr(a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd,pk(77aab6e066f8a7419c5ab714c12c67d25007ed55a43cadcacb4d7a970a093f11)) - Uncompressed private key:
rawtr(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss) - Uncompressed public key:
rawtr(04a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd5b8dec5235a0fa8722476c7709c02559e3aa73aa03918ba2d492eea75abea235) - No key:
rawtr() - X-only key with no point on the curve:
rawtr(0000000000000000000000000000000000000000000000000000000000000005)
Backwards Compatibility
rawtr() descriptors use the format and general operation specified in 380.
This is a wholly new descriptor, and as such is not compatible with any implementation that predates it.
The scripts produced are standard Pay-to-Taproot scripts, so existing software is likely to be familiar with them.
Reference Implementation
rawtr() descriptors have been implemented in Bitcoin Core since version 24.0.
Copyright
This BIP is licensed under the BSD 2-clause license.