Skip to content

Multisig & Output Descriptors

Single-key custody has a brutal failure mode: one secret, one point of failure. Lose it and your coins are frozen; leak it and they’re stolen. Multisig breaks that single point of failure by requiring k of n keys to authorize a spend. And once a wallet is more than one key, you need a precise way to describe it — which is what output descriptors were invented for.

A multisig output locks coins so that spending them requires signatures from at least k of a set of n public keys:

2-of-3 multisig:
keys: A B C (any 2 of these 3 must sign)
spend: A + B ✓
A + C ✓
B + C ✓
A only ✗ (one signature is not enough)

The power is in choosing k and n to match a real threat model:

SetupGood for
2-of-2Two-party control — both must agree (e.g. you + a co-signer). Also the shape of a Lightning channel.
2-of-3Personal security with backup: you hold 2 keys in different places, a trusted third party or service holds 1. Lose one key and you can still recover.
3-of-5Business treasuries / boards — no single executive can move funds, survives losing a couple of keys.

Modern multisig is cleanest with Taproot key aggregation (MuSig2), where a cooperative multisig can be made to look like an ordinary single-key spend on-chain — see Taproot, Schnorr & MuSig2. Classic (pre-Taproot) multisig instead reveals all the public keys and the policy on-chain.

Output descriptors: saying exactly what you can spend

Section titled “Output descriptors: saying exactly what you can spend”

Here’s the problem multisig exposes: a seed phrase alone is not enough to recover a multisig wallet. The seed gives you your keys, but to watch and spend you also need to know the other public keys, the threshold k, the script type, and the derivation paths. Lose that metadata and your funds can be unrecoverable even though you still hold your seed.

Output descriptors (sometimes “descriptor wallets”) solve this with a compact, explicit string that fully describes a set of scripts:

wpkh([d34db33f/84'/0'/0']xpub6.../0/*)
│ │ │ │
│ └ key origin: the │ └ wildcard: every index in this branch
│ master fingerprint │
│ + derivation path └ the extended public key
└ script type: wpkh = native SegWit single-sig

A 2-of-3 multisig descriptor names the threshold and all three keys at once:

wsh(multi(2,
[fp1/48'/0'/0'/2']xpubA.../0/*,
[fp2/48'/0'/0'/2']xpubB.../0/*,
[fp3/48'/0'/0'/2']xpubC.../0/*))

From this one string, any descriptor-aware wallet can regenerate every address and verify every incoming payment — no guessing about script type or paths. Descriptors also carry a checksum so a corrupted backup is detected rather than silently producing the wrong addresses.

Since no single device holds all the keys, multisig needs a way to pass an unsigned transaction between signers. That’s PSBT (Partially Signed Bitcoin Transaction, BIP174): a standard container that carries a transaction plus everything each signer needs, gathering signatures one device at a time until the threshold is met, then finalizing into a broadcastable transaction. It’s the same tool that lets an air-gapped hardware wallet sign without ever touching the internet.

Under the hood — the multisig “off-by-one” baked into Bitcoin forever

Section titled “Under the hood — the multisig “off-by-one” baked into Bitcoin forever”

Classic multisig is enforced on-chain by the opcode OP_CHECKMULTISIG, and it carries one of Bitcoin’s most famous bugs. The original implementation pops one more item off the stack than it should when counting signatures. Satoshi never fixed it — changing it would have split the chain — so the quirk became a permanent consensus rule. Every multisig spend must therefore push a throwaway dummy element (by convention OP_0, an empty value) just to feed that extra pop:

scriptSig: OP_0 <sig A> <sig B> ← the leading OP_0 is the "wasted" dummy
script: OP_2 <pub A> <pub B> <pub C> OP_3 OP_CHECKMULTISIG

It’s harmless once you know it’s there, but it’s a perfect illustration of how, in a consensus system, even a small bug becomes immortal: you can’t patch it without everyone agreeing to a brand-new chain. Modern Taproot multisig sidesteps OP_CHECKMULTISIG entirely with key aggregation (MuSig2) — see Taproot, Schnorr & MuSig2.

Step back from the k-of-n tables and ask the five questions that turn an implementer into an architect:

  • Why does it exist? To break single-key custody’s brutal single point of failure: a multisig output requires k of n keys to spend, and an output descriptor is the precise, portable string that records exactly which keys, threshold, script type, and paths reconstruct that wallet.
  • What problem does it solve? Shared and resilient control with no escrow agent — 2-of-3 kills both the “single key stolen” and “single key lost” failure modes at once — plus the recovery gap multisig exposes: a seed alone can’t restore it, so the descriptor (with its built-in checksum) carries the metadata that makes the wallet recoverable in any descriptor-aware software.
  • What are the trade-offs? More keys means more to back up and coordinate; PSBT (BIP174) has to ferry an unsigned transaction between devices to gather signatures. Classic on-chain multisig also leaks all keys and the policy, costs more bytes, and inherits the immortal OP_CHECKMULTISIG off-by-one (the throwaway OP_0 dummy) — quirks Taproot/MuSig2 sidesteps by making cooperative multisig look single-sig.
  • When is this the wrong design? For small balances or solo day-to-day spending, single-sig is simpler and cheaper — the coordination overhead of multiple signers and descriptor backups isn’t worth it until the funds justify eliminating a single point of failure.
  • What breaks if I remove it? Drop multisig and you’re back to one secret = total loss or total theft; drop descriptors and a multisig backup of “just the seeds” silently produces the wrong addresses or becomes unrecoverable, because the threshold, co-signer xpubs, and paths are gone.

How does this help untrusting strangers agree on one ledger? Multisig lets parties who don’t fully trust each other — co-founders, a user and a custody service, family members — share control of coins under rules the ledger itself enforces, with no escrow agent who could run off with the funds. Descriptors then make that arrangement portable and verifiable across software, so the agreement doesn’t depend on trusting any one vendor’s app. It’s trust-minimization applied to custody itself.

  1. In a 2-of-3 multisig, why is losing a single key recoverable while a single-key wallet’s loss is not?
  2. Why is a seed phrase alone insufficient to recover a multisig wallet?
  3. Read this descriptor aloud in plain English: wpkh([fp/84'/0'/0']xpub.../0/*).
  4. What problem does PSBT solve that arises specifically because multisig keys live on separate devices?
  5. What two things make up a complete backup of a 2-of-3 multisig wallet?
Show answers
  1. In 2-of-3, a single lost or stolen key is not catastrophic: a thief with one key can’t reach the threshold and can’t spend, and you with the other two can still recover and move funds to a fresh setup. A single-key wallet has no such margin — lose that one secret and the coins are frozen; leak it and they’re stolen.
  2. The seed gives you only your keys, but spending and watching a multisig also requires the other public keys, the threshold k, the script type, and the derivation paths. Lose that metadata and funds can be unrecoverable even though you still hold your seed.
  3. “Pay to a native-SegWit single-sig wallet (wpkh) whose key comes from the master with fingerprint fp, derived at path 84'/0'/0', using every address index in this branch (/0/*).”
  4. Since no single device holds all the keys, PSBT (Partially Signed Bitcoin Transaction, BIP174) is the standard container that carries an unsigned transaction between signers, gathering signatures one device at a time until the threshold is met, then finalizing into a broadcastable transaction.
  5. All the seeds (or your seed plus the others’ xpubs) AND the output descriptor — the descriptor records the threshold, all keys, script type, and paths. Backing up only the words is the classic painful mistake; for multisig it isn’t enough.