<p>I'm just guessing, but by having the transaction commit to the scriptCode, we ensure that the signer knows what script they're signing for.  A hardware wallet, for example, can only be certain that outpoint 1234...cdef:0 pays a particular script if we give it the transaction that created that outpoint (so that it can hash that transaction, verify the txid, extract the scriptPubKey, and compare that to a provided witnessScript).  Because a transaction (without witness data) can be up to almost a megabyte in size and a spending transaction can refer to thousands of previous transactions, we create a situation where low-resource devices such as hardware wallets have a hard time verifying what they're signing.</p>

<p>By contrast, with BIP143, we need only tell the wallet each of the scriptCodes it's supposed to sign for.  BIP141 allows these to be up to 10,000 bytes, which is just 1/100th the maximum size of a transaction.  The wallet can examine these scriptCodes, ensure they agree with what the wallet expects, and commit to them in its signature knowing that if the person sending them the scriptCode lied about the actual scriptCode, the signature will be invalid.</p>

<p>This is the same reason the BIP143 signature format commits to the value of each input.  Before it had to process previous transactions in order to get their output amounts; now it just accepts whatever data it receives and signs it knowing that, if someone lied to it about the amount, the signature will be invalid.</p>

CC BY-SA 4.0
2019-02-21T12:58:51.570Z
"... knowing that if the person sending them the scriptCode lied about the actual scriptCode, the signature will be invalid."
I'm in deep waters here, but I think the signature would be invalid even if it didn't directly commit to the scriptCode, because the signature already indirectly commits to the scriptCode via the outpoint->WSH->scriptCode path. So this doesn't really answer the question, I'm afraid.
Kalle Rosenbaum
CC BY-SA 4.0
2019-02-21T21:06:10.493Z
You're correct that commiting to the outpoint commits to the prevout scriptPubKey and that the prevout scriptPubKey commits to the script, but the point of the answer is that proving to wallet that a particular outpoint corresponds to a particular witnessScript requires up to ~1 MB data plus the witnessScript.  By commiting directly to the scriptCode, now the only data required for the proof is the scriptCode (which is the same as the witnessScript in normal usage).
David A. Harding
CC BY-SA 4.0
2019-02-22T20:50:10.397Z
Consider a transaction with a single p2wsh input. The hardware wallet gets an unsigned transaction (Tx), the supposed input UTXO (U), and the supposed witness script (WS). It also probably gets a key derivation path, but that's irrelevant for this discussion. This information, [Tx, U, WS], **doesn't itself prove that the outpoint commits to WS**. Further, if the input is signed based on [Tx, U, WS], and if U and WS are false, the signature will be invalid regardless whether the signature commits to scriptCode or not. Am I wrong here? Thank you for your patience.
Kalle Rosenbaum
CC BY-SA 4.0
2019-02-23T19:38:01.277Z
Yes, I'm wrong here. Private conversation with @David made me realize that the signature would not be invalid if BIP143 omitted scriptCode. Slip of mind. So yes, we must commit to scriptCode.
Kalle Rosenbaum
CC BY-SA 4.0
2019-02-20T18:02:34.680Z
2019-02-20T18:02:34.680Z
David A. Harding
<p>When a segwit input is signed, the signature will commit to the witness script (or a p2pkh-like script in case of p2wpkh). This is specified in <a href="https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification" rel="nofollow noreferrer">BIP143</a>:</p>

<blockquote>
  <ul>
  <li>For <code>P2WPKH</code> witness program, the <code>scriptCode</code> is <code>0x1976a914{20-byte-pubkey-hash}88ac</code>.</li>
  <li>For <code>P2WSH</code> witness program,
  
  <ul>
  <li>if the <code>witnessScript</code> does not contain any <code>OP_CODESEPARATOR</code>, the <code>scriptCode</code> is the <code>witnessScript</code> serialized as scripts inside <code>CTxOut</code>.</li>
  <li>if the <code>witnessScript</code> contains any <code>OP_CODESEPARATOR</code>, the <code>scriptCode</code> is the <code>witnessScript</code> but removing everything up to and including the last executed <code>OP_CODESEPARATOR</code> before the signature checking opcode being executed, serialized as scripts inside <code>CTxOut</code>. (The exact semantics is demonstrated in the examples below)</li>
  </ul></li>
  </ul>
</blockquote>

<p>What's the rationale behind this? Why doesn't the hash commit to the pubkey script as in legacy (p2pkh and p2sh) payments? This difference complicates signing/verification code a bit, so I suppose there must be some good reason for it.</p>

<p>Maybe my question should be: Why does the hash commit to any script at all for segwit inputs? In legacy signatures, putting scriptPubkey in scriptSig for the current input is a (complicated, see below) way to avoid signature reuse between inputs. But in segwit, this is accomplished with the <code>outpoint</code> part of the hashing algorithm. So couldn't we just skip the <code>scriptCode</code> part?</p>

<p>It seems to me that there is another reason for why we hash the scriptPubkey for legacy signatures and the witness script for segwit signatures, since there are simpler ways to avoid signature reuse:</p>

<ul>
<li>Legacy: We could just have added a dummy byte somewhere in the current input</li>
<li>Segwit: Current input's outpoint already solves the problem.</li>
</ul>

<segregated-witness><signature><sighash><bip143>
Why hash witness script instead of pubkey script in signature?
Kalle Rosenbaum
# Why hash witness script instead of pubkey script in signature?

(Asked by: username_0 on 2019-02-20)

When a segwit input is signed, the signature will commit to the witness script (or a p2pkh-like script in case of p2wpkh). This is specified in [BIP143](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification):

> * For `P2WPKH` witness program, the `scriptCode` is `0x1976a914{20-byte-pubkey-hash}88ac`.
> * For `P2WSH` witness program,
>   + if the `witnessScript` does not contain any `OP_CODESEPARATOR`, the `scriptCode` is the `witnessScript` serialized as scripts inside `CTxOut`.
>   + if the `witnessScript` contains any `OP_CODESEPARATOR`, the `scriptCode` is the `witnessScript` but removing everything up to and including the last executed `OP_CODESEPARATOR` before the signature checking opcode being executed, serialized as scripts inside `CTxOut`. (The exact semantics is demonstrated in the examples below)

What's the rationale behind this? Why doesn't the hash commit to the pubkey script as in legacy (p2pkh and p2sh) payments? This difference complicates signing/verification code a bit, so I suppose there must be some good reason for it.

Maybe my question should be: Why does the hash commit to any script at all for segwit inputs? In legacy signatures, putting scriptPubkey in scriptSig for the current input is a (complicated, see below) way to avoid signature reuse between inputs. But in segwit, this is accomplished with the `outpoint` part of the hashing algorithm. So couldn't we just skip the `scriptCode` part?

It seems to me that there is another reason for why we hash the scriptPubkey for legacy signatures and the witness script for segwit signatures, since there are simpler ways to avoid signature reuse:

* Legacy: We could just have added a dummy byte somewhere in the current input
* Segwit: Current input's outpoint already solves the problem.

**Tags:** segregated-witness, signature, sighash, bip143


---

## 1 answers

### Answer by username_1 on 2019-02-20. Score: 3 | Accepted answer

I'm just guessing, but by having the transaction commit to the scriptCode, we ensure that the signer knows what script they're signing for. A hardware wallet, for example, can only be certain that outpoint 1234...cdef:0 pays a particular script if we give it the transaction that created that outpoint (so that it can hash that transaction, verify the txid, extract the scriptPubKey, and compare that to a provided witnessScript). Because a transaction (without witness data) can be up to almost a megabyte in size and a spending transaction can refer to thousands of previous transactions, we create a situation where low-resource devices such as hardware wallets have a hard time verifying what they're signing.

By contrast, with BIP143, we need only tell the wallet each of the scriptCodes it's supposed to sign for. BIP141 allows these to be up to 10,000 bytes, which is just 1/100th the maximum size of a transaction. The wallet can examine these scriptCodes, ensure they agree with what the wallet expects, and commit to them in its signature knowing that if the person sending them the scriptCode lied about the actual scriptCode, the signature will be invalid.

This is the same reason the BIP143 signature format commits to the value of each input. Before it had to process previous transactions in order to get their output amounts; now it just accepts whatever data it receives and signs it knowing that, if someone lied to it about the amount, the signature will be invalid.

> **Comments:**
> **username_0**: "... knowing that if the person sending them the scriptCode lied about the actual scriptCode, the signature will be invalid." I'm in deep waters here, but I think the signature would be invalid even if it didn't directly commit to the scriptCode, because the signature already indirectly commits to the scriptCode via the outpoint->WSH->scriptCode path. So this doesn't really answer the question, I'm afraid.  
> **username_1**: You're correct that commiting to the outpoint commits to the prevout scriptPubKey and that the prevout scriptPubKey commits to the script, but the point of the answer is that proving to wallet that a particular outpoint corresponds to a particular witnessScript requires up to ~1 MB data plus the witnessScript.  By commiting directly to the scriptCode, now the only data required for the proof is the scriptCode (which is the same as the witnessScript in normal usage).  
> **username_0**: Consider a transaction with a single p2wsh input. The hardware wallet gets an unsigned transaction (Tx), the supposed input UTXO (U), and the supposed witness script (WS). It also probably gets a key derivation path, but that's irrelevant for this discussion. This information, [Tx, U, WS], **doesn't itself prove that the outpoint commits to WS**. Further, if the input is signed based on [Tx, U, WS], and if U and WS are false, the signature will be invalid regardless whether the signature commits to scriptCode or not. Am I wrong here? Thank you for your patience.  
> **username_0**: Yes, I'm wrong here. Private conversation with @David made me realize that the signature would not be invalid if BIP143 omitted scriptCode. Slip of mind. So yes, we must commit to scriptCode.  

---

