<p>&quot;Witness program hash mismatch&quot; in a Taproot script path spend means the Taproot commitment wasn't successfully verified, in other words the internal key tweaked with the taptweak hash (constructed from the script, leaf version, merkle tree hashing partners and the internal key itself) didn't match the taproot output key (see <a href="https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#Script_validation_rules" rel="noreferrer">BIP341</a>).</p>
<p>This could be for many reasons, but here are the more likely ones:</p>
<ul>
<li>You're saying you're &quot;trying to attach a Taproot script&quot; to your UTXO, but you can't attach a script to which the previous output doesn't commit. You need to know before constructing the output what scripts (and their positions in the script tree) will be allowed when spending.</li>
<li>The variable name <code>tweakedSigner</code> suggests it is the internal private/public key pair tweaked with the taptweak hash, which is something you would use for <strong>key path</strong> spending. For script path spending you need the untweaked internal key.</li>
</ul>

CC BY-SA 4.0
2023-10-09T20:27:11.800Z
Awesome, thank you for clarifying!
Sherwin Li
CC BY-SA 4.0
2023-10-05T09:04:55.857Z
2023-10-05T09:04:55.857Z
Vojtěch Strnad
<p>I'm trying to broadcast a transaction to my RPC provider:</p>
<pre><code>curl https://my-quicknode-rpc-provider/ \
    -X POST \
    -H &quot;Content-Type: application/json&quot; \
    --data '{&quot;method&quot;: &quot;sendrawtransaction&quot;, &quot;params&quot;: [&quot;02000000000101cc0fc61320a04525c8dabf30241fe9a64b3f8c28ebf61a9700b8a57a76306bac0000000000ffffffff01ea100000000000002251208dace6f04076ca1ea4eb168dcdad6ad61f695ca1c16a3df6b9586cdca1c71db8034025871482b0c7bb14b8c72d5ac44ce069991505a1aeca1c4de5b8d1857831ca87e6f43a3e784c755595574c798892ecf58c7ae525bccba441cdf46862dd405bb47e208dace6f04076ca1ea4eb168dcdad6ad61f695ca1c16a3df6b9586cdca1c71db8ac0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800387b2270223a226272632d3230222c226f70223a227472616e73666572222c227469636b223a2270657065222c22616d74223a22313030227d6821c18dace6f04076ca1ea4eb168dcdad6ad61f695ca1c16a3df6b9586cdca1c71db800000000&quot;]}'
</code></pre>
<p>but I keep getting this error response from the RPC:</p>
<pre><code>{&quot;result&quot;:null,&quot;error&quot;:{&quot;code&quot;:-26,&quot;message&quot;:&quot;non-mandatory-script-verify-flag (Witness program hash mismatch)&quot;},&quot;id&quot;:null}
</code></pre>
<p>I've verified multiple times that I'm signing with the correct private key. On top of that, this occurs when broadcasting to the network, not during signing my PSBT inputs so I've been having trouble debugging.</p>
<p>For some context, I'm trying to attach a Taproot script to my input UTXO. Here is a code snippet of what I'm doing:</p>
<pre class="lang-javascript prettyprint-override"><code>const hexData = Buffer.from(
  `{&quot;p&quot;:&quot;brc-20&quot;,&quot;op&quot;:&quot;transfer&quot;,&quot;tick&quot;:&quot;${tick}&quot;,&quot;amt&quot;:&quot;${amount.toString()}&quot;}`
).toString(&quot;hex&quot;);
const publicKeyHex = toXOnly(tweakedSigner.publicKey).toString(&quot;hex&quot;);
let inscribeLockScript = bitcoin.script.fromASM(
  `${publicKeyHex} OP_CHECKSIG OP_0 OP_IF ${Buffer.from(&quot;ord&quot;).toString(
    &quot;hex&quot;
  )} OP_1 ${Buffer.from(&quot;text/plain;charset=utf-8&quot;).toString(
    &quot;hex&quot;
  )} OP_0 ${splitByNChars(hexData, 1040).join(&quot; &quot;)} OP_ENDIF`
);
inscribeLockScript = Buffer.from(
  inscribeLockScript.toString(&quot;hex&quot;).replace(&quot;6f726451&quot;, &quot;6f72640101&quot;),
  &quot;hex&quot;
);

const scriptTree: Taptree = {
  output: inscribeLockScript,
};

const inscribeLockRedeem = {
  output: inscribeLockScript,
  redeemVersion: 192,
};

const inscribeP2tr = bitcoin.payments.p2tr({
  internalPubkey: toXOnly(tweakedSigner.publicKey),
  scriptTree,
  network: bitcoin.networks.bitcoin,
  redeem: inscribeLockRedeem,
});

const tapLeafScript = {
  leafVersion: inscribeLockRedeem.redeemVersion!,
  script: inscribeLockRedeem.output || Buffer.from(&quot;&quot;),
  controlBlock: inscribeP2tr.witness![inscribeP2tr.witness!.length - 1],
};

psbt.addInput({
  hash: utxo.hash,
  index: utxo.index,
  witnessUtxo: {
    script: inscribeP2tr.output!,
    value: utxo.value,
  },
  tapInternalKey: toXOnly(tweakedSigner.publicKey),
  tapLeafScript: [tapLeafScript],
});
</code></pre>
<p>I'm fairly new to this so any help would be appreciated!</p>

<taproot><javascript><bitcoinjs><p2tr>
"Witness program hash mismatch" code -26 when broadcasting a transaction
Sherwin Li
# "Witness program hash mismatch" code -26 when broadcasting a transaction

(Asked by: username_0 on 2023-10-05)

I'm trying to broadcast a transaction to my RPC provider:

```
curl https://my-quicknode-rpc-provider/ \
    -X POST \
    -H "Content-Type: application/json" \
    --data '{"method": "sendrawtransaction", "params": ["02000000000101cc0fc61320a04525c8dabf30241fe9a64b3f8c28ebf61a9700b8a57a76306bac0000000000ffffffff01ea100000000000002251208dace6f04076ca1ea4eb168dcdad6ad61f695ca1c16a3df6b9586cdca1c71db8034025871482b0c7bb14b8c72d5ac44ce069991505a1aeca1c4de5b8d1857831ca87e6f43a3e784c755595574c798892ecf58c7ae525bccba441cdf46862dd405bb47e208dace6f04076ca1ea4eb168dcdad6ad61f695ca1c16a3df6b9586cdca1c71db8ac0063036f7264010118746578742f706c61696e3b636861727365743d7574662d3800387b2270223a226272632d3230222c226f70223a227472616e73666572222c227469636b223a2270657065222c22616d74223a22313030227d6821c18dace6f04076ca1ea4eb168dcdad6ad61f695ca1c16a3df6b9586cdca1c71db800000000"]}'

```

but I keep getting this error response from the RPC:

```
{"result":null,"error":{"code":-26,"message":"non-mandatory-script-verify-flag (Witness program hash mismatch)"},"id":null}

```

I've verified multiple times that I'm signing with the correct private key. On top of that, this occurs when broadcasting to the network, not during signing my PSBT inputs so I've been having trouble debugging.

For some context, I'm trying to attach a Taproot script to my input UTXO. Here is a code snippet of what I'm doing:

```javascript
const hexData = Buffer.from(
  `{"p":"brc-20","op":"transfer","tick":"${tick}","amt":"${amount.toString()}"}`
).toString("hex");
const publicKeyHex = toXOnly(tweakedSigner.publicKey).toString("hex");
let inscribeLockScript = bitcoin.script.fromASM(
  `${publicKeyHex} OP_CHECKSIG OP_0 OP_IF ${Buffer.from("ord").toString(
    "hex"
  )} OP_1 ${Buffer.from("text/plain;charset=utf-8").toString(
    "hex"
  )} OP_0 ${splitByNChars(hexData, 1040).join(" ")} OP_ENDIF`
);
inscribeLockScript = Buffer.from(
  inscribeLockScript.toString("hex").replace("6f726451", "6f72640101"),
  "hex"
);

const scriptTree: Taptree = {
  output: inscribeLockScript,
};

const inscribeLockRedeem = {
  output: inscribeLockScript,
  redeemVersion: 192,
};

const inscribeP2tr = bitcoin.payments.p2tr({
  internalPubkey: toXOnly(tweakedSigner.publicKey),
  scriptTree,
  network: bitcoin.networks.bitcoin,
  redeem: inscribeLockRedeem,
});

const tapLeafScript = {
  leafVersion: inscribeLockRedeem.redeemVersion!,
  script: inscribeLockRedeem.output || Buffer.from(""),
  controlBlock: inscribeP2tr.witness![inscribeP2tr.witness!.length - 1],
};

psbt.addInput({
  hash: utxo.hash,
  index: utxo.index,
  witnessUtxo: {
    script: inscribeP2tr.output!,
    value: utxo.value,
  },
  tapInternalKey: toXOnly(tweakedSigner.publicKey),
  tapLeafScript: [tapLeafScript],
});

```

I'm fairly new to this so any help would be appreciated!

**Tags:** taproot, javascript, bitcoinjs, p2tr


---

## 1 answers

### Answer by username_1 on 2023-10-05. Score: 5 | Accepted answer

"Witness program hash mismatch" in a Taproot script path spend means the Taproot commitment wasn't successfully verified, in other words the internal key tweaked with the taptweak hash (constructed from the script, leaf version, merkle tree hashing partners and the internal key itself) didn't match the taproot output key (see [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#Script_validation_rules)).

This could be for many reasons, but here are the more likely ones:

* You're saying you're "trying to attach a Taproot script" to your UTXO, but you can't attach a script to which the previous output doesn't commit. You need to know before constructing the output what scripts (and their positions in the script tree) will be allowed when spending.
* The variable name `tweakedSigner` suggests it is the internal private/public key pair tweaked with the taptweak hash, which is something you would use for **key path** spending. For script path spending you need the untweaked internal key.

> **Comments:**
> **username_0**: Awesome, thank you for clarifying!  

---

