Glossary

OP_CHECKMULTISIG

A legacy Bitcoin Script opcode for m-of-n multisignature verification, replaced by OP_CHECKSIGADD in Tapscript.

Key Takeaways

  • OP_CHECKMULTISIG is the original Bitcoin Script opcode for m-of-n multisignature verification: it checks that at least m out of n provided public keys have valid corresponding signatures.
  • The opcode contains a well-known off-by-one bug that consumes an extra stack element beyond what the algorithm uses, and BIP 147 later mandated this dummy element be OP_0 to close a malleability vector.
  • Tapscript (BIP 342) disables OP_CHECKMULTISIG entirely, replacing it with OP_CHECKSIGADD for scripted multisig and enabling MuSig2 key aggregation for n-of-n schemes that look like single-signature spends on chain.

What Is OP_CHECKMULTISIG?

OP_CHECKMULTISIG is a Bitcoin Script opcode that verifies multiple digital signatures against multiple public keys in a single operation. Given m required signatures and n total public keys, it confirms that at least m of the n keys have produced valid signatures over the transaction. This opcode is the foundation of all on-chain multisignature wallets in legacy and SegWit v0 scripts.

Introduced in Bitcoin's earliest versions, OP_CHECKMULTISIG enabled spending policies like "2-of-3" (any two out of three keyholders can spend) or "3-of-5" (three out of five required). These policies power shared custody arrangements, corporate treasury controls, and escrow services. BIP 11 formalized the m-of-n transaction type as a standard output, and BIP 16 (P2SH) later made multisig practical by hashing the full script into a compact address.

Despite its utility, OP_CHECKMULTISIG carries a legacy bug, imposes sigops overhead, and requires all signatures and keys to appear on chain. Modern alternatives in Taproot address each of these shortcomings.

How It Works

OP_CHECKMULTISIG operates on values placed on the script stack. A standard multisig scriptPubKey looks like this:

OP_M <pubkey1> <pubkey2> ... <pubkeyN> OP_N OP_CHECKMULTISIG

To spend, the scriptSig (or witness) provides the corresponding signatures:

OP_0 <sig1> <sig2> ... <sigM>

The leading OP_0 is the dummy element required by the off-by-one bug (explained below). When the script interpreter reaches OP_CHECKMULTISIG, it pops values from the stack in this order:

  1. n: the total number of public keys
  2. n public keys
  3. m: the number of required signatures
  4. m signatures
  5. One extra element (the dummy): consumed but not used

The total number of elements consumed is m + n + 3. After verification, the opcode pushes true (1) on success or false (0) on failure.

The Verification Algorithm

The algorithm uses two pointers that iterate linearly through the signatures and keys. Signatures must appear in the same order as their corresponding public keys in the script:

  1. Start with the first signature and the first public key
  2. Check the current signature against the current public key
  3. If the signature is valid for that key, advance both pointers
  4. If not, advance only the key pointer (that key is permanently skipped)
  5. If remaining keys become fewer than remaining signatures, fail immediately
  6. Continue until all signatures are matched or failure is certain

This ordering requirement means that for a 2-of-3 with keys A, B, C, a witness containing signatures from C then A would be invalid: they must appear in A-then-C order. BIP 67 addresses this by specifying deterministic lexicographic key ordering so that all implementations produce consistent multisig scripts.

The Off-by-One Bug

Satoshi's original implementation of OP_CHECKMULTISIG pops one more element from the stack than the algorithm actually needs. This extra element is consumed and discarded without any validation. Because fixing the bug would change consensus rules and require a hard fork, it has persisted since Bitcoin's launch.

In practice, every OP_CHECKMULTISIG input must push a dummy value (typically OP_0) before the signatures. Initially any value was accepted, which created a transaction malleability vector: a third party could replace the dummy with a different value, changing the transaction's ID without invalidating the signatures. BIP 147 (NULLDUMMY), activated alongside SegWit in 2017, enforces that this dummy element must be an empty byte array. Any other value causes immediate script failure.

Sigops Counting

Bitcoin limits the number of signature operations (sigops) per block to prevent denial of service. OP_CHECKMULTISIG is counted as 20 sigops when it appears in a raw scriptPubKey, regardless of the actual m or n values. This means a simple 2-of-3 multisig consumes the same sigops budget as a hypothetical 20-of-20. Inside P2SH scripts, the actual n value is used instead, but the overhead remains significant compared to single-signature alternatives.

OP_CHECKMULTISIGVERIFY

A companion opcode, OP_CHECKMULTISIGVERIFY, behaves identically to OP_CHECKMULTISIG followed by OP_VERIFY. Instead of pushing true or false onto the stack, it fails the script immediately on invalid signatures and leaves nothing on the stack on success. This variant is used when multisig verification is one step in a larger script and the result does not need to remain on the stack.

Use Cases

OP_CHECKMULTISIG has been the backbone of on-chain multisignature wallets since Bitcoin's early years. Common configurations include:

  • 2-of-3 personal custody: a user holds two keys (one on a mobile device, one as a backup) while a third is held by a service provider for recovery assistance, a pattern used by many custody solutions
  • 3-of-5 corporate treasury: a company distributes keys across executives and requires a quorum to authorize spending, preventing any single point of compromise
  • 2-of-2 escrow: a buyer and seller each hold one key, with an arbitrator holding a third key available to break disputes (implemented as 2-of-3)
  • 1-of-n shared access: any single keyholder can spend, useful for operational wallets where multiple team members need independent access

These patterns are typically wrapped in P2SH (BIP 16) or P2WSH (SegWit) for practical use, keeping the full multisig script out of the output until spending time. For a deeper comparison of multisig wallet implementations, see the multisig wallets guide.

Why Tapscript Replaced It

When Taproot activated in November 2021, it introduced Tapscript (defined in BIP 342) as the new script validation rules for SegWit v1 outputs. Tapscript disables OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY entirely: executing either opcode in a Tapscript causes immediate script failure, similar to OP_RETURN.

The replacement is OP_CHECKSIGADD (opcode 0xba), which takes a fundamentally different approach to multisig verification. Instead of processing all signatures in a single opcode, OP_CHECKSIGADD checks one signature at a time and accumulates a counter:

// Tapscript 2-of-3 multisig
<pubkey1> OP_CHECKSIG
<pubkey2> OP_CHECKSIGADD
<pubkey3> OP_CHECKSIGADD
OP_2 OP_NUMEQUAL

Each OP_CHECKSIGADD pops three values from the stack: a public key, a running counter n, and a signature. If the signature is a valid Schnorr signature for that key, it pushes n + 1. If the signature is an empty byte array (indicating this key is not signing), it pushes n unchanged. The final OP_NUMEQUAL checks that exactly m valid signatures were provided.

This design offers several advantages over OP_CHECKMULTISIG:

  • No off-by-one bug: there is no dummy element, eliminating the malleability workaround
  • Precise sigops accounting: each OP_CHECKSIGADD counts as exactly one sigop, so a 2-of-3 uses 3 sigops instead of 20
  • Batch validation friendly: BIP 340 Schnorr signatures enable batch verification across multiple inputs, improving block validation performance
  • Explicit non-participation: signers who are not participating provide an empty signature rather than being silently skipped by pointer logic

For a comprehensive look at how Taproot and Schnorr change Bitcoin's signature model, see the Taproot and Schnorr signatures explainer.

MuSig2 and the End of On-Chain n-of-n

For the common case of n-of-n multisig (where all keyholders must sign), MuSig2 eliminates the need for any on-chain multisig opcode altogether. MuSig2 is a Schnorr-based key aggregation protocol defined in BIP 327 that combines multiple public keys into a single aggregate key. The resulting signature is indistinguishable from a standard single-key Schnorr signature on chain.

Where a 3-of-3 OP_CHECKMULTISIG transaction exposes three public keys and three signatures in the witness data, a MuSig2 spend reveals only one public key and one signature. This provides:

  • Privacy: observers cannot distinguish a MuSig2 spend from a single-signer spend, hiding the multisig policy entirely
  • Space efficiency: one 32-byte key and one 64-byte signature versus three of each, reducing transaction weight and fees
  • Simplified verification: one signature check instead of three, reducing computational cost for full nodes

MuSig2 requires a two-round signing protocol among all participants and is strictly n-of-n. For threshold schemes (m-of-n where m < n), threshold signature protocols like FROST provide similar on-chain efficiency. Layer 2 protocols like Spark leverage these cryptographic advances to enable efficient multi-party signing without the overhead of legacy multisig opcodes.

Risks and Considerations

Legacy Script Limitations

OP_CHECKMULTISIG remains valid in legacy and SegWit v0 scripts, but new wallet implementations should prefer Taproot alternatives. Legacy multisig transactions are larger, more expensive, and reveal the full spending policy on chain. A 2-of-3 P2WSH multisig spend requires roughly 260 bytes of witness data, compared to 65 bytes for a Taproot key-path spend using MuSig2.

Key Ordering Requirement

Signatures in OP_CHECKMULTISIG must match the order of their corresponding public keys in the script. Providing valid signatures in the wrong order causes the transaction to be rejected. BIP 67 specifies deterministic lexicographic ordering of keys to produce reproducible scripts, but implementations must still ensure the signing order matches. This is a frequent source of bugs in multisig wallet software.

Address Reuse and Privacy

When a multisig UTXO is spent, the full script (including all public keys and the m-of-n policy) is revealed on chain. This exposes how many parties control the wallet and the quorum requirement. In contrast, Taproot key-path spends reveal nothing about the underlying spending policy. For privacy-sensitive applications, migrating to Taproot-based multisig is strongly recommended.

Sigops Budget Impact

In raw scriptPubKey outputs, OP_CHECKMULTISIG always counts as 20 sigops against the block limit, regardless of how many keys are actually involved. This conservative accounting reduces the number of multisig transactions that can fit in a block. Tapscript's OP_CHECKSIGADD counts each key check individually, making more efficient use of the sigops budget.

This glossary entry is for informational purposes only and does not constitute financial or investment advice. Always do your own research before using any protocol or technology.