Advanced Transactions and Scripting

This chapter covers advanced transactions and scripting. Here, we will learn about different transaction types and the scripts that create them. You'll use concepts like pay-to-script-hash and multi-sig in almost any Bitcoin development project.

A bug in CHECKMULTISIG execution

There is a bug in CHECKMULTISIG's execution that requires a slight workaround. When CHECKMULTISIG executes, it should consume M+N+2 items on the stack as parameters. However, due to the bug, CHECKMULTISIG will pop an extra value or one value more than expected.

Let’s look at this in greater detail using the previous validation example:

<SignatureB><SignatureC> 2 <PublicKeyA><PublicKeyB><PublicKeyC> 3 CHECKMULTISIG

 

First, CHECKMULTISIG pops the top item, which is N (in this example "3"). Then it pops N items, which are the public keys that can sign. In this example, public keys A, B, and C. Then, it pops one item, which is M, the quorum (how many signatures are needed). Here M = 2. At this point, CHECKMULTISIG should pop the final M items, which are the signatures, and see if they are valid. However, unfortunately, a bug in the implementation causes CHECKMULTISIG to pop one more item (M+1 total) than it should. The extra item is disregarded when checking the signatures so it has no direct effect on CHECKMULTISIG itself. However, an extra value must be present because if it is not present, when CHECKMULTISIG attempts to pop on an empty stack, it will cause a stack error and script failure (marking the transaction as invalid). Because the extra item is disregarded it can be anything, but customarily 0 is used.

Because this bug became part of the consensus rules, it must now be replicated forever. Therefore the correct script validation would look like this:

0<Signature B><Signature C>2<PublicKey A><PublicKey B><PublicKey C>3 CHECKMULTISIG

 

Thus the unlocking script actually used in multisig is not:

<SignatureB><SignatureC>

 

but instead it is:

0<Signature B><Signature C>

 

From now on, if you see a multisig unlocking script, you should expect to see an extra 0 in the beginning, whose only purpose is as a workaround to a bug that accidentally became a consensus rule.