I want to create a P2TR (Pay to Taproot) address but I just want access to the key path spend, I have no use for the script path spend in this specific example. What should I do in regard to the script path in that case?

2 Answers 2


BIP 341 (BIP-Taproot) discusses this example where you don't require the script path.

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.

The BIP also explains here the rationale for this.

If the taproot output key is an aggregate of keys, there is the possibility for a malicious party to add a script path without being noticed by the other parties. This allows to bypass the multiparty policy and to steal the coins.

Committing to an unspendable script path provides the ability to prove to a third party observer that there is no hidden script path. If there was no tweak at all any key aggregation scheme would need to be revealed to that observer including individual pubkeys to get the same effect (and even this may not be enough for certain key aggregation schemes).

The Bitcoin Optech workshop on Taproot explains that you calculate the tweaked public key using:

Q = P + H(P|c)G


Q is the tweaked public key
P is the initial public key (P = xG where x is the private key)
H is the hash function
| is concatenation
c is the commitment to the script path spend
G is the generator point

If you don't need the script path spend you can calculate the tweaked public key using:

Q = P + H(bytes(P))G

where bytes(P) is the serialization of P as defined in BIP 340 (BIP-Schnorr).

This tweaked public key Q will be your Taproot (P2TR) address. Remember we don't hash (tweaked) public keys with Taproot (SegWit v1) like we do with P2PKH, P2SH, P2WSH (SegWit v0).

  • How does it work that 'Committing to an unspendable script path provides the ability to prove to a third party observer that there is no hidden script path"? Couldn't there still be, in the resulting script tree, a hidden script path? I just don't get what this means.
    – davidbak
    Jun 7, 2022 at 20:06
  • @davidbak: You are effectively revealing that there is a single script path that is hashed and this is what is tweaking your internal public key. For there to be additional script paths you are relying on the equivalent of hash collisions. Not only is the tweak the hash of single script path but the same tweak is also the hash of another (potentially multiple encoded in a Merkle tree) script path. So theoretically possible but practically extremely unlikely. Jun 7, 2022 at 21:59

You can read the following code, the key point is that the root of TapRoot should be an empty array so only the public key is hashed.


def address_p2tr(pubkey: PubKey) -> str:
    # Taproot.
    # See https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
    if pubkey.y & 1 != 0:
        # Taproot requires that the y coordinate of the public key is even.
        pubkey = PubKey(pubkey.x, btc.secp256k1.P - pubkey.y)
    adjust_prikey = btc.secp256k1.Fr(int.from_bytes(hashtag('TapTweak', bytearray(pubkey.x.to_bytes(32)))))
    adjust_pubkey = btc.secp256k1.G * adjust_prikey
    output_pubkey = btc.secp256k1.Pt(btc.secp256k1.Fq(pubkey.x), btc.secp256k1.Fq(pubkey.y)) + adjust_pubkey
    return btc.bech32.encode(btc.config.current.prefix.bech32, 1, bytearray(output_pubkey.x.x.to_bytes(32)))

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.