TeachMeBitcoin

Locking script

From TeachMeBitcoin, the free encyclopedia Reading time: 2 min

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
☕ Help support TeachMeBitcoin

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:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!