Locking script
17. OP_CHECKMULTISIG — M-of-N Signature Verification
Overview
OP_CHECKMULTISIG implements M-of-N threshold signature verification in a single opcode. It verifies that at least M valid signatures from a provided set of N public keys are present.
Opcode value: 0xae (decimal 174)
Input: <extra_null> <sig1> ... <sigM> <M> <pubkey1> ... <pubkeyN> <N>
Output: 0x01 (success) or 0x00 (failure)
Stack Layout
Stack before OP_CHECKMULTISIG (bottom to top):
<OP_0> ← dummy element (required due to bug — see topic 18)
<sig1>
<sig2>
...
<sigM>
<M> ← minimum signatures required
<pubkey1>
<pubkey2>
...
<pubkeyN>
<N> ← total public keys ← TOP OF STACK
Standard Script Patterns
2-of-3 Multisig (P2MS)
# Locking script
OP_2
<pubKey1>
<pubKey2>
<pubKey3>
OP_3
OP_CHECKMULTISIG
# Unlocking script (must include OP_0 due to the off-by-one bug)
OP_0
<sig1>
<sig2>
1-of-2 Multisig
scriptPubKey:
OP_1 <pubKeyA> <pubKeyB> OP_2 OP_CHECKMULTISIG
scriptSig:
OP_0 <sigA> (or <sigB>)
The Matching Algorithm
OP_CHECKMULTISIG uses a specific matching algorithm:
def checkmultisig(sigs, pubkeys, tx, input_index):
"""
Greedy matching: iterate signatures against public keys in order.
A pubkey, once matched, is consumed (cannot match multiple sigs).
Order matters: sigs must be in same order as their pubkeys.
"""
sigs_remaining = list(sigs)
pubkeys_remaining = list(pubkeys)
while sigs_remaining and pubkeys_remaining:
sig = sigs_remaining[0]
pubkey = pubkeys_remaining[0]
if verify_sig(sig, pubkey, tx, input_index):
sigs_remaining.pop(0) # This sig matched, consume it
pubkeys_remaining.pop(0) # Consume pubkey regardless
return len(sigs_remaining) == 0 # All sigs must have matched
Order Requirement
This is critical: signatures must appear in the same relative order as their corresponding public keys:
Public keys: [Alice, Bob, Carol]
Valid: OP_0 <Alice_sig> <Bob_sig>
Valid: OP_0 <Alice_sig> <Carol_sig>
Valid: OP_0 <Bob_sig> <Carol_sig>
INVALID: OP_0 <Bob_sig> <Alice_sig> ← Wrong order!
Script Size Limits
Maximum N: 20 public keys (consensus rule)
Maximum M: 20 (but M ≤ N required)
Script size limit: 10,000 bytes
Signature operations: Each CHECKMULTISIG counts as N sigops
(or 20 sigops if N is not a data push — worst case)
# P2SH sigop counting:
# Standard 2-of-3: counts as 3 sigops (N value)
# Non-standard: counts as 20 sigops
TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation: