<p>You are correct that the signature would not actually be present in that hash due to the <code>OP_CODESEPARATOR</code> used. Keep in mind that v0.1.0 was very unpolished code and had a lot of bugs and weird behaviour. Not everything makes sense.</p>
<p>To explain for those that want more context, by the time we reach <code>EvalScript()</code>, the script will be of the form:</p>
<pre><code>txin.scriptSig + OP_CODESEPARATOR + txout.scriptPubKey
</code></pre>
<p>where <code>txin.scriptSig</code> is from the spending transaction input, and will contain the signature, and <code>txout.scriptPubKey</code> is from the previous transaction UTXO being spent and will contain the public key and <code>OP_CHECKSIG</code> opcode. This is exactly what is written in the question.</p>
<p>Starting from the beginning, the signature will be pushed onto the evaluation stack, then we will hit the <code>OP_CODESEPARATOR</code> so <code>pbegincodehash</code> will be updated to that point in the script, then the public key will be pushed onto the evaluation stack, and finally the <code>OP_CHECKSIG</code> is reached.</p>
<p>Exactly as you say, the signature and public key will then be taken off the stack in reverse order and stored in <code>vchSig</code> and <code>vchPubKey</code> respectively.</p>
<p><code>scriptCode</code> is then set to the subscript starting at <code>pbegincodehash</code> until the end of the script. In this case, it starts at the <code>OP_CHECKSIG</code> we encountered previously, so <code>scriptCode</code> will simply contain the public key push and the <code>OP_CHECKSIG</code> opcode.</p>
<p>Thus, when <code>scriptCode.FindAndDelete(CScript(vchSig))</code> is called, it does nothing in this case because <code>vchSig</code> is not part of <code>scriptCode</code>.</p>
<p>However, for the context of why deleting the signature from the script is important for verifying the signatures, let's look a bit further. <code>CheckSig()</code> is called with the signature (<code>vchSig</code>), the public key (<code>vchPubKey</code>), and the <code>scriptCode</code>:</p>
<pre><code>CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType)
</code></pre>
<p>which then calls</p>
<pre><code>SignatureHash(scriptCode, txTo, nIn, nHashType)
</code></pre>
<p>to generate the hash of the message. The hash is generated by deleting all remaining <code>OP_CODESEPARATOR</code>s from the script, setting the scriptSig of all the other inputs to the spending transaction to empty, sets the <code>scriptSig</code> of the current input being signed to <code>scriptCode</code>, and then (ignoring the other signing types) serialises the transaction and hashes it.</p>
<p>Recall that to verify a signature we need the message (which is then hashed), the public key, and the signature itself. The message has to be in exactly the same form as what was originally signed. That is why we have to delete the signature itself from the transaction being signed, because it obviously couldn't have been present at sign time. However, in this case, it does nothing, because there are no signatures after <code>OP_CODESEPARATOR</code> anyway. The clearing of scriptSigs in the <code>SignatureHash()</code> function is more important here because they would all be empty at signing time.</p>
<p>To check this, we can take a look at the <code>SignSignature()</code> function too, which actually generates the signatures. We can see that it passes <code>scriptPrereq + txout.scriptPubKey</code> to the <code>SignatureHash()</code> function above as the <code>scriptCode</code>. <code>scriptPrereq</code> is always empty in this code. So basically <code>scriptCode</code> is always just the <code>scriptPubKey</code>. That matches exactly what we expect.</p>

CC BY-SA 4.0
2021-12-20T16:26:39.317Z
There are some exotic scriptSigs which contain additional OP_CODESEPARATORs and could have a signature, pubkey, and OP_CHECKSIG that all occur after an OP_CODESEPARATOR, and before another one. In that case, `FindAndDelete` would be doing something in order to remove the signature from the script. IIRC the TumbleBit protocol uses a construction like this.
Ava Chow
CC BY-SA 4.0
2021-12-20T12:11:23.417Z
2021-12-20T12:11:23.417Z
meshcollider
<p>I'm doing my homework by reading the C++ code of the 0.1.0 release of Bitcoin available <a href="https://satoshi.nakamotoinstitute.org/code/" rel="nofollow noreferrer">here</a>. I'm interested in better understanding how to validate transaction 1 of block 170. This transaction has one input, that points to output 0 of transaction 0 of block 9.</p>
<p><code>script.cpp</code> contains a function <code>EvalScript()</code>. This function is called to execute the following script:</p>
<pre><code>---- Bloc 170 / Transaction 1 / Input 0 / ScriptSig -----
PUSH 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901
---- Separator -----
OP_CODESEPARATOR
---- Bloc 9 / Transaction 0 / Output 0 / ScriptPubKey -----
PUSH 0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3
OP_CHECKSIG
</code></pre>
<p>I had a look at the code for <code>OP_CHECKSIG</code>. This code creates a script that is going to replace the one that lies in ScriptSign of input 0 of a copy of transaction 1 of block 170 later in another function <code>SignatureHash()</code>. The first steps are pretty straightforward:</p>
<pre><code>valtype&amp; vchSig    = stacktop(-2);
valtype&amp; vchPubKey = stacktop(-1);
</code></pre>
<p>This puts the signature (DER format) followed by the hashtype (0x01, so SIGHASH_ALL) in <code>vchSig</code>, and the public key prefixed with compression flag (0x04, so no compression) in <code>vchPubKey</code>.</p>
<pre><code>CScript scriptCode(pbegincodehash, pend);
</code></pre>
<p>This creates a script that is nothing more than ScriptPubKey of Block 9 / Transaction 0 / Output 0.</p>
<p>And then...:</p>
<pre><code>// Drop the signature, since there's no way for a signature to sign itself
scriptCode.FindAndDelete(CScript(vchSig));
</code></pre>
<p>I don't understand this. How could the signature that lies in ScriptSig of input 0 of transaction 1 of block 170 be found in ScriptPubKey of output 0 of transaction 0 of block 9, a previous block?</p>
<p>Of course, I know that this very transaction is a very basic one considering how complex a Bitcoin transaction can be, as explained by Satoshi himself <a href="https://satoshi.nakamotoinstitute.org/posts/bitcointalk/threads/69/#2" rel="nofollow noreferrer">here</a>. But what would be a transaction where this code would be useful?</p>

<transactions><signature><validation><opcodes>
Meaning of "Drop the signature" comments in OP_CHECKSIG code (Bitcoin v0.1.0)
StashOfCode
# Meaning of "Drop the signature" comments in OP_CHECKSIG code (Bitcoin v0.1.0)

(Asked by: username_0 on 2021-11-28)

I'm doing my homework by reading the C++ code of the 0.1.0 release of Bitcoin available [here](https://satoshi.nakamotoinstitute.org/code/). I'm interested in better understanding how to validate transaction 1 of block 170. This transaction has one input, that points to output 0 of transaction 0 of block 9.

`script.cpp` contains a function `EvalScript()`. This function is called to execute the following script:

```
---- Bloc 170 / Transaction 1 / Input 0 / ScriptSig -----
PUSH 304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901
---- Separator -----
OP_CODESEPARATOR
---- Bloc 9 / Transaction 0 / Output 0 / ScriptPubKey -----
PUSH 0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3
OP_CHECKSIG

```

I had a look at the code for `OP_CHECKSIG`. This code creates a script that is going to replace the one that lies in ScriptSign of input 0 of a copy of transaction 1 of block 170 later in another function `SignatureHash()`. The first steps are pretty straightforward:

```
valtype& vchSig    = stacktop(-2);
valtype& vchPubKey = stacktop(-1);

```

This puts the signature (DER format) followed by the hashtype (0x01, so SIGHASH\_ALL) in `vchSig`, and the public key prefixed with compression flag (0x04, so no compression) in `vchPubKey`.

```
CScript scriptCode(pbegincodehash, pend);

```

This creates a script that is nothing more than ScriptPubKey of Block 9 / Transaction 0 / Output 0.

And then...:

```
// Drop the signature, since there's no way for a signature to sign itself
scriptCode.FindAndDelete(CScript(vchSig));

```

I don't understand this. How could the signature that lies in ScriptSig of input 0 of transaction 1 of block 170 be found in ScriptPubKey of output 0 of transaction 0 of block 9, a previous block?

Of course, I know that this very transaction is a very basic one considering how complex a Bitcoin transaction can be, as explained by Satoshi himself [here](https://satoshi.nakamotoinstitute.org/posts/bitcointalk/threads/69/#2). But what would be a transaction where this code would be useful?

**Tags:** transactions, signature, validation, opcodes


---

## 1 answers

### Answer by username_1 on 2021-12-20. Score: 4

You are correct that the signature would not actually be present in that hash due to the `OP_CODESEPARATOR` used. Keep in mind that v0.1.0 was very unpolished code and had a lot of bugs and weird behaviour. Not everything makes sense.

To explain for those that want more context, by the time we reach `EvalScript()`, the script will be of the form:

```
txin.scriptSig + OP_CODESEPARATOR + txout.scriptPubKey

```

where `txin.scriptSig` is from the spending transaction input, and will contain the signature, and `txout.scriptPubKey` is from the previous transaction UTXO being spent and will contain the public key and `OP_CHECKSIG` opcode. This is exactly what is written in the question.

Starting from the beginning, the signature will be pushed onto the evaluation stack, then we will hit the `OP_CODESEPARATOR` so `pbegincodehash` will be updated to that point in the script, then the public key will be pushed onto the evaluation stack, and finally the `OP_CHECKSIG` is reached.

Exactly as you say, the signature and public key will then be taken off the stack in reverse order and stored in `vchSig` and `vchPubKey` respectively.

`scriptCode` is then set to the subscript starting at `pbegincodehash` until the end of the script. In this case, it starts at the `OP_CHECKSIG` we encountered previously, so `scriptCode` will simply contain the public key push and the `OP_CHECKSIG` opcode.

Thus, when `scriptCode.FindAndDelete(CScript(vchSig))` is called, it does nothing in this case because `vchSig` is not part of `scriptCode`.

However, for the context of why deleting the signature from the script is important for verifying the signatures, let's look a bit further. `CheckSig()` is called with the signature (`vchSig`), the public key (`vchPubKey`), and the `scriptCode`:

```
CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType)

```

which then calls

```
SignatureHash(scriptCode, txTo, nIn, nHashType)

```

to generate the hash of the message. The hash is generated by deleting all remaining `OP_CODESEPARATOR`s from the script, setting the scriptSig of all the other inputs to the spending transaction to empty, sets the `scriptSig` of the current input being signed to `scriptCode`, and then (ignoring the other signing types) serialises the transaction and hashes it.

Recall that to verify a signature we need the message (which is then hashed), the public key, and the signature itself. The message has to be in exactly the same form as what was originally signed. That is why we have to delete the signature itself from the transaction being signed, because it obviously couldn't have been present at sign time. However, in this case, it does nothing, because there are no signatures after `OP_CODESEPARATOR` anyway. The clearing of scriptSigs in the `SignatureHash()` function is more important here because they would all be empty at signing time.

To check this, we can take a look at the `SignSignature()` function too, which actually generates the signatures. We can see that it passes `scriptPrereq + txout.scriptPubKey` to the `SignatureHash()` function above as the `scriptCode`. `scriptPrereq` is always empty in this code. So basically `scriptCode` is always just the `scriptPubKey`. That matches exactly what we expect.

> **Comments:**
> **username_2**: There are some exotic scriptSigs which contain additional OP_CODESEPARATORs and could have a signature, pubkey, and OP_CHECKSIG that all occur after an OP_CODESEPARATOR, and before another one. In that case, `FindAndDelete` would be doing something in order to remove the signature from the script. IIRC the TumbleBit protocol uses a construction like this.  

---

