<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
  
OP_DUP OP_HASH160  OP_EQUALVERIFY OP_CHECKSIG

The bitcoin.org documentation say this

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 .
* You run OP\_DUP. The stack is now .
* You run OP\_HASH160. The stack is now .
* You push (A expected pubkeyhash). The stack is now .
* 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 .
* 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 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 are handled together:
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:

Checks there are at least two items on top of the stack
Reads the Signature and PubKey as the top two items
Uses EvalChecksig to check if Signature matches PubKey; fSuccess is false if not
Removes the Signature and PubKey from the stack
Puts fSuccess on the stack
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(.. Checks if it is a TapRoot Sig
EvalChecksigPreTapscript(.. 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 Creates hash message for the signature.
VerifyECDSASignature
pubkey.Verify(...)
secp256k12 code.


---

