<blockquote>
<p>... other documentation on Bitcoin Script language?</p>
</blockquote>
<p>Looking at <a href="https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp" rel="nofollow noreferrer">Bitcoin Core's interpreter.cpp</a> can be helpful. It contains a big <code>switch(opcode) ... </code> statement for all the opcodes.</p>
<blockquote>
<p>Now I want to understand how the code is running inside the stack and
how the OP_CHECKSIG work.</p>
</blockquote>
<p>The <a href="https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L1058" rel="nofollow noreferrer"><code>OP_CHECKSIG</code> and <code>OP_CHECKSIGVERIFY</code> cases</a> are handled together:</p>
<pre class="lang-cpp prettyprint-override"><code>case OP_CHECKSIG:
case OP_CHECKSIGVERIFY:
{
    // (sig pubkey -- bool)
    if (stack.size() &lt; 2)
        return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);

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

    bool fSuccess = true;
    if (!EvalChecksig(vchSig, vchPubKey, pbegincodehash, pend, execdata, flags, checker, sigversion, serror, fSuccess)) return false;
    popstack(stack);
    popstack(stack);
    stack.push_back(fSuccess ? vchTrue : vchFalse);
    if (opcode == OP_CHECKSIGVERIFY)
    {
        if (fSuccess)
            popstack(stack);
        else
            return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY);
    }
}
break;
</code></pre>
<p>The code:</p>
<ol>
<li>Checks there are at least two items on top of the stack</li>
<li>Reads the Signature and PubKey as the top two items</li>
<li>Uses <code>EvalChecksig</code> to check if Signature matches PubKey; <code>fSuccess</code> is false if not</li>
<li>Removes the Signature and PubKey from the stack</li>
<li>Puts <code>fSuccess</code> on the stack</li>
<li>If it's <code>OP_CHECKSIGVERIFY</code> it removes <code>fSuccess</code> and throws an error (causing transaction failure) if <code>fSuccess == False</code></li>
</ol>
<p>To go deeper, you can follow the path of function calls from <code>EvalChecksig(..</code> onwards. E.g.</p>
<ul>
<li><a href="https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L391" rel="nofollow noreferrer"><code>EvalChecksig(..</code></a> <em>Checks if it is a TapRoot Sig</em></li>
<li><a href="https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L320" rel="nofollow noreferrer"><code>EvalChecksigPreTapscript(..</code></a> <em>Gets the script from <code>pbegincodehash</code> - the last <code>OP_CODESEPARATOR</code> (for message hash creation) or the start of the script  if no <code>OP_CODESEPARATOR</code> seen (as in OP's example). Also checks encoding.</em></li>
<li><a href="https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L1648" rel="nofollow noreferrer"><code>CheckECDSASignature</code></a> <em>Creates hash message for the signature.</em></li>
<li><code>VerifyECDSASignature</code></li>
<li><a href="https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/pubkey.cpp#L267" rel="nofollow noreferrer"><code>pubkey.Verify(...)</code></a></li>
<li><a href="https://github.com/bitcoin/bitcoin/blob/master/src/secp256k1/src/ecdsa.h" rel="nofollow noreferrer"><code>secp256k12</code> code</a>.</li>
</ul>

CC BY-SA 4.0
2024-04-24T07:25:12.550Z
2024-04-24T07:25:12.550Z
Lee
<p>Let's run through the program.</p>

<ul>
<li>The stack starts as <code>&lt;A sig&gt; &lt;A pubkey&gt;</code>.</li>
<li>You run OP_DUP. The stack is now <code>&lt;A sig&gt; &lt;A pubkey&gt; &lt;A pubkey&gt;</code>.</li>
<li>You run OP_HASH160. The stack is now <code>&lt;A sig&gt; &lt;A pubkey&gt; &lt;A pubkeyhash&gt;</code>.</li>
<li>You push (A expected pubkeyhash). The stack is now <code>&lt;A sig&gt; &lt;A pubkey&gt; &lt;A pubkeyhash&gt; &lt;A expected pubkeyhash&gt;</code>.</li>
<li>You run OP_EQUALVERIFY. If the initial public key on the stack does matches the expected one, the execution aborts and the script fails. If it matches, the resulting stack is <code>&lt;A sig&gt; &lt;A pubkey&gt;</code>.</li>
<li>You run OP_CHECKSIG. If the signature matches, the resulting stack is <code>1</code>, which means success.</li>
</ul>

<p>Without the OP_DUP, it would be impossible to verify the public key both against the signature and against the expected public key hash.</p>

CC BY-SA 4.0
2019-09-17T15:19:58.723Z
This kind of stack-oriented scripting reminds me of [Postscript](https://en.wikipedia.org/wiki/PostScript#The_language) which has operators such as `dup`, `exch` and `pop`. I have often used `dup` at the start of a Postscript subroutine so that a parameter can be used for multiple operations, each of which consumes items from the stack.
RedGrittyBrick
CC BY-SA 4.0
2019-09-16T16:21:20.973Z
2019-09-16T16:37:38.770Z
2019-09-16T16:37:38.770Z
Pieter Wuille
<p>I have this Script P2PKH</p>

<pre><code>&lt;A Signature&gt; &lt;A Public Key&gt; 
OP_DUP OP_HASH160 &lt;A Public Key Hash&gt; OP_EQUALVERIFY OP_CHECKSIG
</code></pre>

<p>The bitcoin.org documentation say <a href="https://en.bitcoin.it/wiki/OP_CHECKSIG" rel="nofollow noreferrer">this</a></p>

<blockquote>
  <p>The entire transaction's outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise.</p>
</blockquote>

<p>Now I want to understand how the code is running inside the stack and how the OP_CHECKSIG work.</p>

<p>My question comes from the fact, why use another operator (OP_CHECKSIG) if is used the operator OP_EQUALVERIFY to does control ?</p>

<p>But I have another question on OP_DUP, the documentation say this</p>

<blockquote>
  <p>Duplicates the top stack item.</p>
</blockquote>

<p>Why when the bitcoin run the script need to duplicate the items inside the stack?</p>

<p>to close, exist other documentation on Bitcoin Script language?</p>

<bitcoin-core><script><transaction-verification><p2pkh><checksig>
How does this simple script use the OP_CHECKSIG opcode?
vincenzopalazzo
# How does this simple script use the OP_CHECKSIG opcode?

(Asked by: username_0 on 2019-09-16)

I have this Script P2PKH

```
<A Signature> <A Public Key> 
OP_DUP OP_HASH160 <A Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

```

The bitcoin.org documentation say [this](https://en.bitcoin.it/wiki/OP_CHECKSIG)

> The entire transaction's outputs, inputs, and script (from the most recently-executed OP\_CODESEPARATOR to the end) are hashed. The signature used by OP\_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise.

Now I want to understand how the code is running inside the stack and how the OP\_CHECKSIG work.

My question comes from the fact, why use another operator (OP\_CHECKSIG) if is used the operator OP\_EQUALVERIFY to does control ?

But I have another question on OP\_DUP, the documentation say this

> Duplicates the top stack item.

Why when the bitcoin run the script need to duplicate the items inside the stack?

to close, exist other documentation on Bitcoin Script language?

**Tags:** bitcoin-core, script, transaction-verification, p2pkh, checksig


---

## 2 answers

### Answer by username_2 on 2019-09-16. Score: 5 | Accepted answer

Let's run through the program.

* The stack starts as `<A sig> <A pubkey>`.
* You run OP\_DUP. The stack is now `<A sig> <A pubkey> <A pubkey>`.
* You run OP\_HASH160. The stack is now `<A sig> <A pubkey> <A pubkeyhash>`.
* You push (A expected pubkeyhash). The stack is now `<A sig> <A pubkey> <A pubkeyhash> <A expected pubkeyhash>`.
* You run OP\_EQUALVERIFY. If the initial public key on the stack does matches the expected one, the execution aborts and the script fails. If it matches, the resulting stack is `<A sig> <A pubkey>`.
* You run OP\_CHECKSIG. If the signature matches, the resulting stack is `1`, which means success.

Without the OP\_DUP, it would be impossible to verify the public key both against the signature and against the expected public key hash.

> **Comments:**
> **username_3**: This kind of stack-oriented scripting reminds me of [Postscript](https://en.wikipedia.org/wiki/PostScript#The_language) which has operators such as `dup`, `exch` and `pop`. I have often used `dup` at the start of a Postscript subroutine so that a parameter can be used for multiple operations, each of which consumes items from the stack.  

---

### Answer by username_1 on 2024-04-24. Score: 0

> ... other documentation on Bitcoin Script language?

Looking at [Bitcoin Core's interpreter.cpp](https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp) can be helpful. It contains a big `switch(opcode) ...`  statement for all the opcodes.

> Now I want to understand how the code is running inside the stack and
> how the OP\_CHECKSIG work.

The [`OP_CHECKSIG` and `OP_CHECKSIGVERIFY` cases](https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L1058) are handled together:

```cpp
case OP_CHECKSIG:
case OP_CHECKSIGVERIFY:
{
    // (sig pubkey -- bool)
    if (stack.size() < 2)
        return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);

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

    bool fSuccess = true;
    if (!EvalChecksig(vchSig, vchPubKey, pbegincodehash, pend, execdata, flags, checker, sigversion, serror, fSuccess)) return false;
    popstack(stack);
    popstack(stack);
    stack.push_back(fSuccess ? vchTrue : vchFalse);
    if (opcode == OP_CHECKSIGVERIFY)
    {
        if (fSuccess)
            popstack(stack);
        else
            return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY);
    }
}
break;

```

The code:

1. Checks there are at least two items on top of the stack
2. Reads the Signature and PubKey as the top two items
3. Uses `EvalChecksig` to check if Signature matches PubKey; `fSuccess` is false if not
4. Removes the Signature and PubKey from the stack
5. Puts `fSuccess` on the stack
6. If it's `OP_CHECKSIGVERIFY` it removes `fSuccess` and throws an error (causing transaction failure) if `fSuccess == False`

To go deeper, you can follow the path of function calls from `EvalChecksig(..` onwards. E.g.

* [`EvalChecksig(..`](https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L391) *Checks if it is a TapRoot Sig*
* [`EvalChecksigPreTapscript(..`](https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L320) *Gets the script from `pbegincodehash` - the last `OP_CODESEPARATOR` (for message hash creation) or the start of the script if no `OP_CODESEPARATOR` seen (as in OP's example). Also checks encoding.*
* [`CheckECDSASignature`](https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/script/interpreter.cpp#L1648) *Creates hash message for the signature.*
* `VerifyECDSASignature`
* [`pubkey.Verify(...)`](https://github.com/bitcoin/bitcoin/blob/a7129f827c9de1330dea1fec739ca210e6bda3cb/src/pubkey.cpp#L267)
* [`secp256k12` code](https://github.com/bitcoin/bitcoin/blob/master/src/secp256k1/src/ecdsa.h).


---

