<p>James Chiang explained how the CHECKSIGADD opcode works in this Bitcoin Optech <a href="https://youtu.be/nXGe9_M5pjk?t=119" rel="nofollow noreferrer">workshop</a>. (The code for CHECKSIGADD in the Bitcoin Core codebase is <a href="https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1083" rel="nofollow noreferrer">here</a>.)</p>
<blockquote>
<p>As you can see on the left we have an output script that uses CHECKSIGADD and CHECKSIG opcodes to express a n-of-n multisig output.</p>
</blockquote>
<pre><code>pk0
checksig
pk1
checksigadd
pk2
checksigadd
3
equal
</code></pre>
<blockquote>
<p>This is our initial stack which is populated with 3 signatures:</p>
</blockquote>
<pre><code>sig0
sig1
sig2
</code></pre>
<blockquote>
<p>In the first step we will push this public key (pk0) onto the stack and evaluate that against sig0 with the opcode CHECKSIG. Let’s assume this evaluates to TRUE. Since it evaluates to TRUE we will now have a <code>1</code> byte on the top of the stack:</p>
</blockquote>
<pre><code>1
sig1
sig2
</code></pre>
<blockquote>
<p>We will use a counter.</p>
</blockquote>
<pre><code>2
sig2
</code></pre>
<blockquote>
<p>As we evaluate the signatures against other public keys, if that script evaluates successfully we will then have a counter of <code>3</code> on the stack and that counter can then be compared to the one encoded in the output script. If they are equal we have successfully spent a 3-of-3 multisig output which uses CHECKSIGADD to encode that multisig.</p>
</blockquote>
<pre><code>3
</code></pre>
<blockquote>
<p>How does it compare to its predecessor CHECKMULTISIG?</p>
</blockquote>
<p>CHECKMULTISIG doesn't (it is still used for SegWit v0 spends) use an increasing counter. The equivalent locking script using CHECKMULTISIG would be:</p>
<pre><code>3
pk0
pk1
pk2
3
checkmultisig
</code></pre>
<p>CHECKMULTISIG also contains a longstanding bug which means the unlocking script requires a <code>0</code> at the bottom to satisfy the locking script.</p>
<pre><code>sig0
sig1
sig2
0
</code></pre>
<p>The operation of CHECKMULTISIG is explained in this StackExchange <a href="https://bitcoin.stackexchange.com/questions/40669/checkmultisig-a-worked-out-example">question</a>.</p>

CC BY-SA 4.0
2022-07-13T12:19:30.117Z
2022-07-15T14:01:59.257Z
2022-07-15T14:01:59.257Z
Michael Folkson
<p>How does the CHECKSIGADD opcode (defined in the Tapscript BIP) <a href="https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki" rel="nofollow noreferrer">BIP342</a> work? How does it compare to its predecessor CHECKMULTISIG?</p>
<p>The design of CHECKSIGADD was discussed in this StackExchange <a href="https://bitcoin.stackexchange.com/questions/114446/why-do-invalid-signatures-in-op-checksigadd-not-push-to-the-stack/">question</a>.</p>

<script><multi-signature><taproot><opcodes>
How does the CHECKSIGADD opcode work? How does it compare to its predecessor CHECKMULTISIG?
Michael Folkson
# How does the CHECKSIGADD opcode work? How does it compare to its predecessor CHECKMULTISIG?

(Asked by: username_0 on 2022-07-13)

How does the CHECKSIGADD opcode (defined in the Tapscript BIP) [BIP342](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki) work? How does it compare to its predecessor CHECKMULTISIG?

The design of CHECKSIGADD was discussed in this StackExchange [question](https://bitcoin.stackexchange.com/questions/114446/why-do-invalid-signatures-in-op-checksigadd-not-push-to-the-stack/).

**Tags:** script, multi-signature, taproot, opcodes


---

## 1 answers

### Answer by username_0 on 2022-07-13. Score: 2 | Accepted answer

James Chiang explained how the CHECKSIGADD opcode works in this Bitcoin Optech workshop. (The code for CHECKSIGADD in the Bitcoin Core codebase is here.)

As you can see on the left we have an output script that uses CHECKSIGADD and CHECKSIG opcodes to express a n-of-n multisig output.

pk0
checksig
pk1
checksigadd
pk2
checksigadd
3
equal


This is our initial stack which is populated with 3 signatures:

sig0
sig1
sig2


In the first step we will push this public key (pk0) onto the stack and evaluate that against sig0 with the opcode CHECKSIG. Let’s assume this evaluates to TRUE. Since it evaluates to TRUE we will now have a 1 byte on the top of the stack:

1
sig1
sig2


We will use a counter.

2
sig2


As we evaluate the signatures against other public keys, if that script evaluates successfully we will then have a counter of 3 on the stack and that counter can then be compared to the one encoded in the output script. If they are equal we have successfully spent a 3-of-3 multisig output which uses CHECKSIGADD to encode that multisig.

3


How does it compare to its predecessor CHECKMULTISIG?

CHECKMULTISIG doesn't (it is still used for SegWit v0 spends) use an increasing counter. The equivalent locking script using CHECKMULTISIG would be:
3
pk0
pk1
pk2
3
checkmultisig

CHECKMULTISIG also contains a longstanding bug which means the unlocking script requires a 0 at the bottom to satisfy the locking script.
sig0
sig1
sig2
0

The operation of CHECKMULTISIG is explained in this StackExchange question.


---

