<p><a href="https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki" rel="nofollow noreferrer">BIP 341</a> (BIP-Taproot) discusses this example where you don't require the script path.</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>The BIP also explains <a href="https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-22" rel="nofollow noreferrer">here</a> the rationale for this.</p>
<blockquote>
<p>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.</p>
</blockquote>
<p>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).</p>
<p>The Bitcoin Optech <a href="https://github.com/bitcoinops/taproot-workshop/blob/master/2.2-taptweak.ipynb" rel="nofollow noreferrer">workshop</a> on Taproot explains that you calculate the tweaked public key using:</p>
<pre><code>Q = P + H(P|c)G
</code></pre>
<p>where</p>
<pre><code>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
</code></pre>
<p>If you don't need the script path spend you can calculate the tweaked public key using:</p>
<pre><code>Q = P + H(bytes(P))G
</code></pre>
<p>where <code>bytes(P)</code> is the serialization of P as defined in <a href="https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki" rel="nofollow noreferrer">BIP 340</a> (BIP-Schnorr).</p>
<p>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).</p>

CC BY-SA 4.0
2022-06-07T20:06:24.873Z
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
CC BY-SA 4.0
2022-06-07T21:59:22.900Z
@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.
Michael Folkson
CC BY-SA 4.0
2020-10-04T15:41:34.837Z
2022-06-06T18:19:46.060Z
2022-06-06T18:19:46.060Z
Michael Folkson
<p>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.</p>
<p><a href="https://github.com/mohanson/pybtc/blob/fbe80e99ba2ff63850f9c92022776683b73e87f6/btc/core.py#L169-L178" rel="nofollow noreferrer">https://github.com/mohanson/pybtc/blob/fbe80e99ba2ff63850f9c92022776683b73e87f6/btc/core.py#L169-L178</a></p>
<pre><code>def address_p2tr(pubkey: PubKey) -&gt; str:
    # Taproot.
    # See https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
    if pubkey.y &amp; 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)))
</code></pre>

CC BY-SA 4.0
2024-05-14T06:57:36.003Z
2024-05-14T06:57:36.003Z
Mohanson
<p>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?</p>

<address-generation><taproot><p2tr>
How do I construct a P2TR address if I just want to use the key path?
Michael Folkson
# How do I construct a P2TR address if I just want to use the key path?

(Asked by: username_0 on 2020-10-04)

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?

**Tags:** address-generation, taproot, p2tr


---

## 2 answers

### Answer by username_0 on 2020-10-04. Score: 2 | Accepted answer

[BIP 341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki) (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](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#cite_note-22) 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](https://github.com/bitcoinops/taproot-workshop/blob/master/2.2-taptweak.ipynb) on Taproot explains that you calculate the tweaked public key using:

```
Q = P + H(P|c)G

```

where

```
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](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) (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).

> **Comments:**
> **username_1**: 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.  
> **username_0**: @username_1: 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.  

---

### Answer by username_2 on 2024-05-14. Score: 0

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.

<https://github.com/username_2/pybtc/blob/fbe80e99ba2ff63850f9c92022776683b73e87f6/btc/core.py#L169-L178>

```
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)))

```


---

