As far as I can tell there are three ways you can produce a valid Schnorr signature in a Taproot environment:

  1. For a p2tr output that uses a BIP-0086 commitment (key spend, sign with internal key, tweak with h_tapTweak(internalKey)*G)
  2. For a p2tr output that commits to a script tree root hash (key spend, sign with internal key, tweak with h_tapTweak(internalKey || scriptRoot)*G)
  3. For a p2tr output that commits to a script merkle tree root hash (script spend, sign with any key to satisfy leaf script)

How do I find out which of the above signature "methods" is expected to be produced by a PSBT signer?

The updated BIP-0174 document only mentions all the new Taproot related fields for the inputs and outputs but does not mention how to interpret them and what combinations of values are valid.

I found some test vectors in https://github.com/bitcoin/bitcoin/pull/22558 that gave me some clues, but I'm not sure if I'm missing an important resource that describes the PSBT signing process in more detail?

This is what I was able to scrape together so far:

  1. (p2tr BIP-0086 key spend): Set PSBT_IN_TAP_BIP32_DERIVATION with internal key and zero/empty leaf hashes.
  2. (p2tr script root hash key spend): Set PSBT_IN_TAP_BIP32_DERIVATION with internal key zero/empty leaf hashes, set PSBT_IN_TAP_MERKLE_ROOT to merkle root hash.
  3. (p2tr script spend): Set PSBT_IN_TAP_BIP32_DERIVATION with internal key and the leaf hash of the leaf that is being executed. Also set PSBT_IN_TAP_LEAF_SCRIPT with the control block and the script of the executed leaf.

Does that look correct?

If yes, then what is the significance of the PSBT_IN_TAP_INTERNAL_KEY field compared to using the internal key in the PSBT_IN_TAP_BIP32_DERIVATION field? It feels like I'm missing something here.

1 Answer 1


Yes, that looks correct.

I suppose you are correct that PSBT_IN_TAP_INTERNAL_KEY is not strictly necessary, but one of the main ideas with PSBTs is to include as much information as possible, and to be explicit what the information included is. So instead of inferring the internal key from PSBT_IN_TAP_BIP32_DERIVATION, we explicitly say what it is with PSBT_IN_TAP_INTERNAL_KEY.

It is also possible to have the internal key also be a key inside of a script (dunno why you'd want that, but it could happen). In that case, it would not be possible to infer which key is the internal key from just PSBT_IN_TAP_BIP32_DERIVATION.

  • Thank you for your answer! It makes sense to me to add as much information as possible. But when implementing the signer role it's useful to know what the minimum required fields are in order to perform some validation.
    – guggero
    Apr 28, 2022 at 7:29
  • In your example, I assume that the same key would appear in the PSBT_IN_TAP_BIP32_DERIVATION field twice? Once with no leaf hashes and once with a leaf hash?
    – guggero
    Apr 28, 2022 at 7:30
  • 1
    @guggero no, it would be there once with one leaf hash. A PSBT cannot have duplicate keys.
    – Ava Chow
    Apr 28, 2022 at 14:37
  • Ah, right, I mixed it up in my head with PSBT_IN_TAP_SCRIPT_SIG where the leaf hash is in the key along with the pubkey. Now it all makes sense to me, thanks a lot!
    – guggero
    Apr 28, 2022 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.