<p>I've been studying all the ways Taproot transactions can be spent and I can get all of them to work except for when script path spending is used and the script is executed. Transaction <a href="https://explorer.blockstream.com/tx/0c045625cd9402f51a57c5df31909ba001e47b1dec05bfbd568e147328eaf829" rel="nofollow noreferrer">0c045625...</a> is a good example. I'll focus on input 0 here.</p>
<p>I have successfully recreated the merkle tree of tagged hashes to match the witness program from the previous output, which I thought would be the hard part but it turned out to be quite easy.</p>
<p>But when the script finally executes, it still has to succeed, which means in most cases the signatures will also have to be verified. I can successfully verify signatures in key path spending inputs, but none of the script path spending ones.</p>
<p>Here is the segwit data for input 0 (the first two fields are the signatures):</p>
<pre><code>107cc602f65b07acc72c1e71f9e443059256a844d3340deea90ca29d656c63e49eb0216be7e31a5e8ab02aa9e719ba43f05af84e86cf1912fbdf57ebbcf4cd5801
7a0c65d587f0859d7cf50009162b16c79fec22ecc485d0f8faf555f3718cda9a4891186a4a26ce7365516a0017806a6c3475d341866cd8b20c7891d02e2bc523
20c041f567623260a7b7caba5158cc0b864d735d36329db41fa41ffbb09ac86f71ad204cb206cf18865fd546b018324a8e94212dad909b3cd778bce22a219b9ac391ebac
c110551a18489887bdb3242f46719e7d375b0cc5c3062ff8430b8d20e904783e8cc913b7fd44a48042cfda824efc872816549871226770204d0884c60ba693a315
</code></pre>
<p>Here is the parsed witness script for input 0:</p>
<pre><code>c041f567623260a7b7caba5158cc0b864d735d36329db41fa41ffbb09ac86f71
OP_CHECKSIGVERIFY
4cb206cf18865fd546b018324a8e94212dad909b3cd778bce22a219b9ac391eb
OP_CHECKSIG
</code></pre>
<p>Using Schnorr signatures, I can not get these public keys to verify the signatures. The signatures use sighash byte 01, or the default 00.</p>
<p>As for the data to be signed, I've tried verifying these signatures using <code>TapSighash</code> tagged hashes of the data (like I do for key path spending), or just using a single or double SHA256 of the data, but nothing works.</p>
<p>As for the public key to verify the signatures, I've tried using the public keys in the script directly, or applied as tweaks to an xonly public key parsed from the witness program, and vice versa, but nothing I've used to tweak any of these 32-byte pubkeys works either.</p>
<p>Since the public keys are 32 bytes and the signatures are 64 (and it's a Taproot transaction), I assume these must be verifiable using Schnorr signatures.</p>
<p>What am I missing? All the other stuff I've done with Schnorr signatures works, and it is pretty simple. So there has to be a step I am missing.</p>
<p>For input 0 in the transaction linked to above, here is the data that my program is using to attempt to verify these signatures:</p>
<p>Witness Program:</p>
<pre><code>0c96a8191c84ba0a4b64d8766a95ed49508bc24e768ee1945d21e8e850c8cbf3
</code></pre>
<p>Public Keys:</p>
<pre><code>c041f567623260a7b7caba5158cc0b864d735d36329db41fa41ffbb09ac86f71
4cb206cf18865fd546b018324a8e94212dad909b3cd778bce22a219b9ac391eb
</code></pre>
<p>Signatures:</p>
<pre><code>107cc602f65b07acc72c1e71f9e443059256a844d3340deea90ca29d656c63e49eb0216be7e31a5e8ab02aa9e719ba43f05af84e86cf1912fbdf57ebbcf4cd5801
7a0c65d587f0859d7cf50009162b16c79fec22ecc485d0f8faf555f3718cda9a4891186a4a26ce7365516a0017806a6c3475d341866cd8b20c7891d02e2bc523
</code></pre>
<p>Hash of Data to Sign (using only a single SHA256 of the serialized pieces of data, which seems to be the Taproot convention):</p>
<pre><code>30264f68fd7f000080bbbe5b9e550000d0244f68fd7f000040bbbe5b9e550000
</code></pre>
<p>When a script path is used to redeem a Taproot output, and the script is executed, how are these pieces of data used to verify the signatures when OP_CHECKSIG is called?</p>

CC BY-SA 4.0
2022-08-30T18:45:39.483Z
Did you construct the hash being signed according to the rules in BIP342? The rules are slightly different for script path spending and key path spending.
Pieter Wuille
CC BY-SA 4.0
2022-08-31T16:35:27.873Z
That was it. The extension described in BIP342 was missing. After I added that, it worked.
Zephyrus
CC BY-SA 4.0
2023-10-20T23:09:34.837Z
@Zephyrus Could you make your solution into an answer and mark it as accepted, so that the question doesn't show as being unanswered?
Vojtěch Strnad
<taproot><schnorr-signatures><message-signing><message-verification><key-tweaking>
How does OP_CHECKSIG work for Taproot script path spending?
Zephyrus
# How does OP_CHECKSIG work for Taproot script path spending?

(Asked by: username_0 on 2022-08-30)

I've been studying all the ways Taproot transactions can be spent and I can get all of them to work except for when script path spending is used and the script is executed. Transaction [0c045625...](https://explorer.blockstream.com/tx/0c045625cd9402f51a57c5df31909ba001e47b1dec05bfbd568e147328eaf829) is a good example. I'll focus on input 0 here.

I have successfully recreated the merkle tree of tagged hashes to match the witness program from the previous output, which I thought would be the hard part but it turned out to be quite easy.

But when the script finally executes, it still has to succeed, which means in most cases the signatures will also have to be verified. I can successfully verify signatures in key path spending inputs, but none of the script path spending ones.

Here is the segwit data for input 0 (the first two fields are the signatures):

```
107cc602f65b07acc72c1e71f9e443059256a844d3340deea90ca29d656c63e49eb0216be7e31a5e8ab02aa9e719ba43f05af84e86cf1912fbdf57ebbcf4cd5801
7a0c65d587f0859d7cf50009162b16c79fec22ecc485d0f8faf555f3718cda9a4891186a4a26ce7365516a0017806a6c3475d341866cd8b20c7891d02e2bc523
20c041f567623260a7b7caba5158cc0b864d735d36329db41fa41ffbb09ac86f71ad204cb206cf18865fd546b018324a8e94212dad909b3cd778bce22a219b9ac391ebac
c110551a18489887bdb3242f46719e7d375b0cc5c3062ff8430b8d20e904783e8cc913b7fd44a48042cfda824efc872816549871226770204d0884c60ba693a315

```

Here is the parsed witness script for input 0:

```
c041f567623260a7b7caba5158cc0b864d735d36329db41fa41ffbb09ac86f71
OP_CHECKSIGVERIFY
4cb206cf18865fd546b018324a8e94212dad909b3cd778bce22a219b9ac391eb
OP_CHECKSIG

```

Using Schnorr signatures, I can not get these public keys to verify the signatures. The signatures use sighash byte 01, or the default 00.

As for the data to be signed, I've tried verifying these signatures using `TapSighash` tagged hashes of the data (like I do for key path spending), or just using a single or double SHA256 of the data, but nothing works.

As for the public key to verify the signatures, I've tried using the public keys in the script directly, or applied as tweaks to an xonly public key parsed from the witness program, and vice versa, but nothing I've used to tweak any of these 32-byte pubkeys works either.

Since the public keys are 32 bytes and the signatures are 64 (and it's a Taproot transaction), I assume these must be verifiable using Schnorr signatures.

What am I missing? All the other stuff I've done with Schnorr signatures works, and it is pretty simple. So there has to be a step I am missing.

For input 0 in the transaction linked to above, here is the data that my program is using to attempt to verify these signatures:

Witness Program:

```
0c96a8191c84ba0a4b64d8766a95ed49508bc24e768ee1945d21e8e850c8cbf3

```

Public Keys:

```
c041f567623260a7b7caba5158cc0b864d735d36329db41fa41ffbb09ac86f71
4cb206cf18865fd546b018324a8e94212dad909b3cd778bce22a219b9ac391eb

```

Signatures:

```
107cc602f65b07acc72c1e71f9e443059256a844d3340deea90ca29d656c63e49eb0216be7e31a5e8ab02aa9e719ba43f05af84e86cf1912fbdf57ebbcf4cd5801
7a0c65d587f0859d7cf50009162b16c79fec22ecc485d0f8faf555f3718cda9a4891186a4a26ce7365516a0017806a6c3475d341866cd8b20c7891d02e2bc523

```

Hash of Data to Sign (using only a single SHA256 of the serialized pieces of data, which seems to be the Taproot convention):

```
30264f68fd7f000080bbbe5b9e550000d0244f68fd7f000040bbbe5b9e550000

```

When a script path is used to redeem a Taproot output, and the script is executed, how are these pieces of data used to verify the signatures when OP\_CHECKSIG is called?

**Tags:** taproot, schnorr-signatures, message-signing, message-verification, key-tweaking

> **Comments:**
> **username_1**: Did you construct the hash being signed according to the rules in BIP342? The rules are slightly different for script path spending and key path spending.  
> **username_0**: That was it. The extension described in BIP342 was missing. After I added that, it worked.  
> **username_2**: @username_0 Could you make your solution into an answer and mark it as accepted, so that the question doesn't show as being unanswered?  

---

## 0 answers

