LearnBitcoin

Bitcoin Dev Archive 2021

Taproot Fields for PSBT

8 messages, 22 Jun to 24 Nov 2021. Started by Andrew Chow.

Andrew Chow (2), Salvatore Ingala (2), Jeremy Rubin, Sjors Provoost, Greg Sanders, Pieter Wuille

Permalink Original thread on gnusha.org

Andrew Chow permalink original

Hi All,

I would like to propose a BIP which defines new fields for Taproot support in PSBT.

The full text is below, and the rendered file can be found at https://github.com/achow101/bips/blob/taproot-psbt/bip-taproot-psbt.mediawiki.

Andrew Chow

---

<pre>
   BIP: taproot-psbt
   Layer: Applications
   Title: Taproot Fields for PSBT
   Author: Andrew Chow <andrew@achow101•com>
   Comments-Summary: No comments yet.
   Comments-URI:
https://github.com/bitcoin/bips/wiki/Comments:BIP-taproot-psbt
   Status: draft
   Type: Standards Track
   Created: 2021-06-21
   License: BSD-2-Clause
</pre>

==Introduction==

===Abstract===

This document proposes additional fields for BIP 174 PSBTv0 and BIP 370 PSBTv2 that allow for BIP 340/341/342 Taproot data to be included in a PSBT of any version. These will be fields for signatures and scripts that are relevant to the creation of Taproot inputs.

===Copyright===

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

===Motivation===

BIPs 340, 341, and 342 specify Taproot which provides a wholly new way to create and spend Bitcoin outputs. The existing PSBT fields are unable to support Taproot due to the new signature algorithm and the method by which scripts are embedded inside of a Taproot output. Therefore new fields must be defined to allow PSBTs to carry the information necessary for signing Taproot inputs.

==Specification==

The new per-input types are defined as follows:

{| ! Name ! <tt><keytype></tt> ! <tt><keydata></tt> ! <tt><keydata></tt> Description ! <tt><valuedata></tt> ! <tt><valuedata></tt> Description ! Versions Requiring Inclusion ! Versions Requiring Exclusion ! Versions Allowing Inclusion |- | Taproot Key Spend Signature | <tt>PSBT_IN_TAP_KEY_SIG = 0x13</tt> | None | No key data <ref>'''Why is there no key data for <tt>PSBT_IN_TAP_KEY_SIG</tt>'''The signature in a key path spend corresponds directly with the pubkey provided in the output script. Thus it is not necessary to provide any metadata that attaches the key path spend signature to a particular pubkey.</ref> | <tt><signature></tt> | The 64 or 65 byte Schnorr signature for key path spending a Taproot output. | | | 0, 2 |- | Taproot Script Spend Signature | <tt>PSBT_IN_TAP_SCRIPT_SIG = 0x14</tt> | <tt><xonlypubkey> <leafhash></tt> | The 32 byte X-only public key concatenated with the 32 byte hash of the leaf it is part of. | <tt><signature></tt> | The 64 or 65 byte Schnorr signature for this pubkey and leaf combination. | | | 0, 2 |- | Taproot Leaf Script | <tt>PSBT_IN_TAP_LEAF_SCRIPT = 0x15</tt> | <tt><control block></tt> | The control block for this leaf as specified in BIP 341. The control block contains the merkle tree path to this leaf. | <tt><script> <8-bit uint></tt> | The script for this leaf as would be provided in the witness stack followed by the single byte leaf version. | | | 0, 2 |- | Taproot Key BIP 32 Derivation Path | <tt>PSBT_IN_TAP_BIP32_DERIVATION = 0x16</tt> | <tt><xonlypubkey></tt> | The 32 byte X-only public key | <tt><hashes len> <leaf hash>* <32-bit uint> <32-bit uint>*</tt> | A compact size unsigned integer representing the number of leaf hashes, followed by a list of leaf hashes, followed by the master key fingerprint concatenated with the derivation path of the public key. The derivation path is represented as 32-bit little endian unsigned integer indexes concatenated with each other. Public keys are those needed to spend this output. The leaf hashes are of the leaves which involve this public key. | | | 0, 2 |- | Taproot Internal Key | <tt>PSBT_IN_TAP_INTERNAL_KEY = 0x17</tt> | None | No key data | <tt><pubkey></tt> | The X-only pubkey used as the internal key in this output.<ref>'''Why is the internal key provided?'''The internal key is not necessarily the same key as in the Taproot output script. BIP 341 recommends tweaking the key with the hash of itself. It may be necessary for signers to know what the internal key actually is so that they are able to determine whether an input can be signed by it.</ref> | | | 0, 2 |- | Taproot Merkle Root | <tt>PSBT_IN_TAP_MERKLE_ROOT = 0x18</tt> | None | No key data | <tt><pubkey></tt> | The 32 byte Merkle root hash | | | 0, 2 |}

The new per-output types are defined as follows:

{| ! Name ! <tt><keytype></tt> ! <tt><keydata></tt> ! <tt><keydata></tt> Description ! <tt><valuedata></tt> ! <tt><valuedata></tt> Description ! Versions Requiring Inclusion ! Versions Requiring Exclusion ! Versions Allowing Inclusion |- | Taproot Internal Key | <tt>PSBT_OUT_TAP_INTERNAL_KEY = 0x05</tt> | None | No key data | <tt><pubkey></tt> | The X-only pubkey used as the internal key in this output. | | | 0, 2 |- | Taproot Tree | <tt>PSBT_OUT_TAP_TREE = 0x06</tt> | None | No key data | <tt>{<8-bit uint depth> <8-bit uint leaf version> <scriptlen> <script>}*</tt> | One or more tuples representing the depth, leaf version, and script for a leaf in the Taproot tree, allowing the entire tree to be reconstructed. The tuples must be in depth first search order so that the tree is correctly reconstructed. Each tuple is an 8-bit unsigned integer representing the depth in the Taproot tree for this script, an 8-bit unsigned integer representing the leaf version, the length of the script as a compact size unsigned integer, and the script itself. | | | 0, 2 |- | Taproot Key BIP 32 Derivation Path | <tt>PSBT_OUT_TAP_BIP32_DERIVATION = 0x07</tt> | <tt><xonlypubkey></tt> | The 32 byte X-only public key | <tt><hashes len> <leaf hash>* <32-bit uint> <32-bit uint>*</tt> | A compact size unsigned integer representing the number of leaf hashes, followed by a list of leaf hashes, followed by the master key fingerprint concatenated with the derivation path of the public key. The derivation path is represented as 32-bit little endian unsigned integer indexes concatenated with each other. Public keys are those needed to spend this output. The leaf hashes are of the leaves which involve this public key. | | | 0, 2 |}

===UTXO Types===

BIP 174 recommends using <tt>PSBT_IN_NON_WITNESS_UTXO</tt> for all inputs because of potential attacks involving an updater lying about the amounts in an output. Because a Taproot signature will commit to all of the amounts and output scripts spent by the inputs of the transaction, such attacks are prevented as any such lying would result in an invalid signature. Thus Taproot inputs can use just <tt>PSBT_IN_WITNESS_UTXO</tt>.

==Compatibility==

These are simply new fields added to the existing PSBT format. Because PSBT is designed to be extensible, old software will ignore the new fields.

==Test Vectors==

TBD

==Rationale==

<references/>

==Reference implementation==

The reference implementation of the PSBT format is available at TBD.

==Acknowledgements==

TBD

Salvatore Ingala in reply to Andrew Chow permalink original

Hi Andrew,

I just have a small suggestion on this proposal.

On Tue, 22 Jun 2021 at 23:29, Andrew Chow via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:

Quoted text (9 lines)
> | Taproot Leaf Script
> | <tt>PSBT_IN_TAP_LEAF_SCRIPT = 0x15</tt>
> | <tt><control block></tt>
> | The control block for this leaf as specified in BIP 341. The control
> block contains the merkle tree path to this leaf.
> | <tt><script> <8-bit uint></tt>
> | The script for this leaf as would be provided in the witness stack
> followed by the single byte leaf version.
>

So far, all the defined PSBT types had a relatively short keydata (not much bigger than a couple of pubkeys). I think that is a desirable property to keep, as it is often a reasonable assumption that dictionary keys are not very large. The control block as per BIP 341 can be up to 33 + 32*128 = 4129 bytes long.

Perhaps it would be better to split this into PSBT_IN_TAP_LEAF_SCRIPT and PSBT_IN_TAP_LEAF_CONTROL_BLOCK (both with no keydata)?

Best, Salvatore Ingala

Andrew Chow in reply to Salvatore Ingala permalink original

Hi Salvatore,

On 6/28/21 6:03 AM, Salvatore Ingala wrote:

Quoted text (20 lines)
> Hi Andrew,
>
> I just have a small suggestion on this proposal.
>
> On Tue, 22 Jun 2021 at 23:29, Andrew Chow via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:
>
>> | Taproot Leaf Script
>> | <tt>PSBT_IN_TAP_LEAF_SCRIPT = 0x15</tt>
>> | <tt><control block></tt>
>> | The control block for this leaf as specified in BIP 341. The control
>> block contains the merkle tree path to this leaf.
>> | <tt><script> <8-bit uint></tt>
>> | The script for this leaf as would be provided in the witness stack
>> followed by the single byte leaf version.
>
> So far, all the defined PSBT types had a relatively short keydata (not much bigger than a couple of pubkeys).
> I think that is a desirable property to keep, as it is often a reasonable assumption that dictionary keys are not very large.
> The control block as per BIP 341 can be up to 33 + 32*128 = 4129 bytes long.
>
> Perhaps it would be better to split this into PSBT_IN_TAP_LEAF_SCRIPT and PSBT_IN_TAP_LEAF_CONTROL_BLOCK (both with no keydata)?

A taproot tree can have multiple leaf scripts, and since it is possible that the actual script to be used is not known at the time scripts and control blocks are added to the PSBT, it would not be sufficient to only have two fields with no keydata. It would not be possible to specify multiple leaf scripts.

Furthermore, it is possible to have the same leaf script appear multiple times in the tree. So it is not sufficient to use the leaf hash as the keydata as a script that appears multiple times would only have one control block possible, where in reality it would have more than one.

Thus the only way to allow multiple different leaf scripts, and the same leaf script to appear multiple times, is to use the control block as keydata.

Andrew Chow

Quoted text (2 lines)
> Best,
> Salvatore Ingala
Salvatore Ingala in reply to Andrew Chow permalink original

Hi Andrew,

Thanks for the clarification, I was indeed reading it under the mistaken assumption that only one leaf would be added to the PSBT.

En passant, for the less experienced readers, it might be helpful if the key types that are possibly present multiple times (with different keydata) were somehow labeled in the tables.

Best, Salvatore Ingala

Jeremy Rubin in reply to Salvatore Ingala permalink original

Suggestion:

It should be allowed that different keys can specify different sighash flags.

As an example, if chaperone signatures were desired with anyprevout, it would be required to specify that the anyprevout key sign with APO and the chaperone sign with ALL. As another example, Sapio emulator oracles sign with SIGHASH_ALL whereas other signatories might be instructed to sign with a different flag.

The current sighashtype key is per-input: - If a sighash type is provided, the signer must check that the sighash is acceptable. If unacceptable, they must fail. - If a sighash type is not provided, the signer should sign using SIGHASH_ALL, but may use any sighash type they wish.

So a new per-key mapping can be added safely.

I have no strong opinions on the format for said per-key sighash hints.

Why do this now? Well, I requested it when spec'ing V2 as well, but it would be nice to get it spec'd and implemented.

Sjors Provoost in reply to Andrew Chow permalink original

Hi Andrew,

I'm confused why PSBT_IN_TAP_BIP32_DERIVATION and PSBT_OUT_TAP_BIP32_DERIVATION contain not just the derivation path for the xonlypubkey, but also the tapleaf merkle path.

First I thought it was perhaps necessary in order for a signer to guess which script leaves it can sign with its own keys. But you can't really know that without actually seeing the script. When a signer looks at a script, it presumably already knows the leaf path.

- Sjors
Quoted text (8 lines)
> Op 22 jun. 2021, om 23:22 heeft Andrew Chow via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> het volgende geschreven:
>
> Hi All,
>
> I would like to propose a BIP which defines new fields for Taproot
> support in PSBT.
>
> The full text is below, and the rendered file can be found at

Now at: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki>

Quoted text (20 lines)
> -
> | Taproot Key BIP 32 Derivation Path
> | <tt>PSBT_IN_TAP_BIP32_DERIVATION = 0x16</tt>
> | <tt><xonlypubkey></tt>
> | The 32 byte X-only public key
> | <tt><hashes len> <leaf hash>* <32-bit uint> <32-bit uint>*</tt>
> | A compact size unsigned integer representing the number of leaf
> hashes, followed by a list of leaf hashes, followed by the master key
> fingerprint concatenated with the derivation path of the public key. The
> derivation path is represented as 32-bit little endian unsigned integer
> indexes concatenated with each other. Public keys are those needed to
> spend this output. The leaf hashes are of the leaves which involve this
> public key.

> |-
> | Taproot Key BIP 32 Derivation Path
> | <tt>PSBT_OUT_TAP_BIP32_DERIVATION = 0x07</tt>
> | <tt><xonlypubkey></tt>
> | The 32 byte X-only public key
> | <tt><hashes len> <leaf hash>* <32-bit uint> <32-bit uint>*</tt>
>
Greg Sanders in reply to Sjors Provoost permalink original

I may be misunderstanding the question, but it seems essential data for the finalizer role, which may not know such information on its own.

On Wed, Nov 24, 2021 at 11:15 PM Sjors Provoost via bitcoin-dev < bitcoin-dev@lists•linuxfoundation•org> wrote:

Quoted text (58 lines)
> Hi Andrew,
>
> I'm confused why PSBT_IN_TAP_BIP32_DERIVATION and
> PSBT_OUT_TAP_BIP32_DERIVATION
> contain not just the derivation path for the xonlypubkey, but also the
> tapleaf merkle path.
>
> First I thought it was perhaps necessary in order for a signer to guess
> which
> script leaves it can sign with its own keys. But you can't really know
> that without
> actually seeing the script. When a signer looks at a script, it presumably
> already
> knows the leaf path.
>
> - Sjors
>
> Op 22 jun. 2021, om 23:22 heeft Andrew Chow via bitcoin-dev <
> bitcoin-dev@lists•linuxfoundation•org> het volgende geschreven:
>
> Hi All,
>
> I would like to propose a BIP which defines new fields for Taproot
> support in PSBT.
>
> The full text is below, and the rendered file can be found at
>
>
> Now at: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
>
> -
> | Taproot Key BIP 32 Derivation Path
> | <tt>PSBT_IN_TAP_BIP32_DERIVATION = 0x16</tt>
> | <tt><xonlypubkey></tt>
> | The 32 byte X-only public key
> | <tt><hashes len> <leaf hash>* <32-bit uint> <32-bit uint>*</tt>
> | A compact size unsigned integer representing the number of leaf
> hashes, followed by a list of leaf hashes, followed by the master key
> fingerprint concatenated with the derivation path of the public key. The
> derivation path is represented as 32-bit little endian unsigned integer
> indexes concatenated with each other. Public keys are those needed to
> spend this output. The leaf hashes are of the leaves which involve this
> public key.
>
>
> |-
> | Taproot Key BIP 32 Derivation Path
> | <tt>PSBT_OUT_TAP_BIP32_DERIVATION = 0x07</tt>
> | <tt><xonlypubkey></tt>
> | The 32 byte X-only public key
> | <tt><hashes len> <leaf hash>* <32-bit uint> <32-bit uint>*</tt>
>
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation•org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
Pieter Wuille in reply to Sjors Provoost permalink original

On Wednesday, November 24th, 2021 at 7:44 AM, Sjors Provoost via bitcoin-dev <bitcoin-dev@lists•linuxfoundation•org> wrote:

Quoted text (9 lines)
> Hi Andrew,
>
> I'm confused why PSBT_IN_TAP_BIP32_DERIVATION and PSBT_OUT_TAP_BIP32_DERIVATION
> contain not just the derivation path for the xonlypubkey, but also the tapleaf merkle path.
>
> First I thought it was perhaps necessary in order for a signer to guess which
> script leaves it can sign with its own keys. But you can't really know that without
> actually seeing the script. When a signer looks at a script, it presumably already
> knows the leaf path.

No, that's exactly it. Signers aren't expected to know or understand scripts ahead of time. With a field telling them which keys are present in which leaves, and how those keys are derived, they can sign without fully understanding the script, or needing the ability to parse the relevant script at all. The actual script information is there too of course, for those that do want to analyze it, or factor that into the decision whether to sign or not.

Cheers,