Glossary

Miniscript

A structured subset of Bitcoin Script that enables analysis, composition, and generic signing of spending conditions.

Key Takeaways

  • Miniscript is a structured representation of Bitcoin Script that makes spending conditions readable, composable, and statically analyzable: you can determine maximum witness size, required signers, and timelock constraints without executing anything.
  • It operates through three layers: a human-friendly policy language compiles to Miniscript, which compiles to raw Bitcoin Script. This separation lets wallets reason about scripts generically without understanding every opcode combination.
  • Miniscript integrates with output descriptors and Taproot to enable portable, interoperable wallet policies: any compatible wallet can spend from a Miniscript-described output without custom signing logic.

What Is Miniscript?

Miniscript is a language for writing Bitcoin spending conditions in a way that software can automatically analyze and reason about. Raw Bitcoin Script is a stack-based language with over 100 opcodes, and while it can express complex conditions, determining properties like "which keys are needed to spend?" or "what is the maximum transaction weight?" requires essentially simulating every execution path. Miniscript solves this by defining a structured subset of Script where these properties can be computed directly from the expression tree.

Developed by Pieter Wuille, Andrew Poelstra, and Sanket Kanjalkar, Miniscript grew out of work at Blockstream to formalize the most common Script patterns. Rather than inventing a new scripting system, Miniscript maps one-to-one onto valid Bitcoin Script: every Miniscript expression compiles to a Script that the Bitcoin network already understands. The innovation is in constraining the design space so that analysis becomes tractable.

For wallets and applications that manage UTXOs with non-trivial spending conditions, Miniscript replaces ad-hoc Script construction with a principled framework. This matters for multisig setups, time-locked vaults, inheritance schemes, and any scenario where multiple parties or conditions govern access to funds.

How It Works

Miniscript operates through three distinct layers, each serving a different purpose. Understanding these layers clarifies how a human-readable policy becomes an enforceable on-chain script.

Layer 1: Policy Language

The policy language is what humans write. It expresses spending conditions using intuitive combinators:

# 2-of-3 multisig
thresh(2, pk(Alice), pk(Bob), pk(Carol))

# 2-of-3 OR (Alice alone after 1 year)
or(thresh(2, pk(Alice), pk(Bob), pk(Carol)),
   and(pk(Alice), older(52560)))

# Corporate treasury: 3-of-5 board members,
# or CEO + CFO after 90 days
or(thresh(3, pk(Board1), pk(Board2), pk(Board3),
           pk(Board4), pk(Board5)),
   and(thresh(2, pk(CEO), pk(CFO)), older(12960)))

The policy language is deliberately simple. It supports keys (pk), hash locks (sha256, hash256), time locks (after, older), and logical combinators (and, or, thresh). A compiler transforms this into an optimized Miniscript expression.

Layer 2: Miniscript

Miniscript is the intermediate representation. While the policy language describes what conditions you want, Miniscript specifies how they map to Script execution. Each Miniscript fragment has a defined type that indicates how it behaves on the Script stack:

  • B (base): produces a non-zero value on success, zero on failure
  • V (verify): aborts on failure, produces nothing on success
  • K (key): produces a public key on the stack
  • W (wrapped): like B but consumes one extra stack element

These types enforce composition rules. You cannot combine fragments in ways that would produce invalid Script. The type system catches errors at compile time rather than at spend time, which is the core safety guarantee Miniscript provides.

# Policy:
thresh(2, pk(A), pk(B), pk(C))

# Compiles to Miniscript:
multi(2, A, B, C)

# Policy with timelock fallback:
or(and(pk(A), pk(B)), and(pk(C), older(1000)))

# Compiles to Miniscript:
andor(pk(A), s:pk(B), and_v(v:pk(C), older(1000)))

Layer 3: Bitcoin Script

Each Miniscript fragment translates deterministically to Bitcoin Script opcodes. The Miniscript multi(2, A, B, C) becomes:

OP_2 <pubkey_A> <pubkey_B> <pubkey_C> OP_3 OP_CHECKMULTISIG

Because the mapping is deterministic and every Miniscript expression has known stack behavior, wallets can compute the exact witness size before signing. This enables accurate fee estimation for complex spending conditions: a property that raw Script analysis cannot provide reliably.

Static Analysis

The structured nature of Miniscript enables several forms of static analysis that are impractical with raw Script:

  • Maximum witness size: compute the worst-case transaction weight for fee estimation
  • Required signers: determine which key combinations can satisfy the script
  • Timelock compatibility: verify that no execution path mixes block-height and time-based timelocks (which Bitcoin consensus forbids)
  • Malleability analysis: confirm that the script cannot be spent in ways that third parties can modify

Output Descriptors and Wallet Integration

Miniscript becomes most powerful when combined with output descriptors. Descriptors are a standard way to describe how a wallet generates addresses, including the derivation paths for keys. A Miniscript-aware descriptor fully specifies both the spending policy and the key derivation:

# Descriptor with Miniscript spending policy
wsh(andor(
  pk([fingerprint/48h/0h/0h/2h]xpub.../0/*),
  s:pk([fingerprint/48h/0h/0h/2h]xpub.../0/*),
  and_v(
    v:pk([fingerprint/48h/0h/0h/2h]xpub.../0/*),
    older(52560)
  )
))

Any wallet that supports Miniscript descriptors can import this string and immediately understand the spending policy, derive the correct addresses, construct valid PSBTs, and determine what signatures are needed. This portability eliminates vendor lock-in for complex wallet configurations.

Taproot Integration

Taproot (BIP 341) introduced a tree-based script structure where multiple spending paths can be committed to a single output. Miniscript has been extended to support Tapscript, the script version used inside Taproot trees. This combination is especially powerful:

  • Each leaf of a Taproot tree can contain a separate Miniscript expression, enabling complex policies with efficient on-chain footprints
  • The key-path spend (a single Schnorr signature) serves as the fast, private default: Miniscript conditions only appear on-chain when the key-path is unavailable
  • Tapscript replaces OP_CHECKMULTISIG with OP_CHECKSIGADD, and Miniscript for Tapscript generates the correct opcodes automatically

For a deeper look at how Taproot restructures Bitcoin transactions, see Taproot and Schnorr Signatures Explained.

Use Cases

Multisig Wallets

Traditional multisig requires all participating wallets to agree on a single script template. Adding a timelock recovery path or changing the threshold means writing custom Script and hoping every wallet can sign it. Miniscript standardizes this: a 2-of-3 with a time-locked recovery key is just a descriptor string that any compatible wallet can handle.

Inheritance and Estate Planning

Miniscript enables time-gated recovery policies. A user can construct a policy where their primary key controls funds normally, but after a year of inactivity a trusted family member or attorney can recover the coins using an alternative key. The timelock is enforced by consensus, not by any third party.

Institutional Custody

Enterprises managing Bitcoin often need complex governance: board approval thresholds, emergency recovery paths, and compliance-mandated spending limits. Miniscript lets these policies be formally specified, analyzed for correctness, and implemented across different signing devices without custom firmware.

Vault Constructions

Vaults restrict how quickly funds can move, providing a window to detect and respond to theft. Miniscript can express vault-like policies using timelocks combined with multi-key requirements, and the static analysis guarantees ensure the policy cannot be bypassed through unexpected execution paths.

Wallet and Tooling Support

Miniscript support has been growing across the Bitcoin ecosystem:

  • Bitcoin Core: added Miniscript descriptor support for watch-only wallets in version 24.0, and signing support for P2WSH Miniscript descriptors in version 25.0, with Tapscript Miniscript support added in version 28.0
  • rust-miniscript: the reference implementation library, maintained by the original authors, used by most Miniscript-aware tools
  • Liana: an open-source wallet built specifically around Miniscript descriptors, supporting recovery paths and complex policies through a graphical interface
  • Hardware signing devices: Ledger has added Miniscript support, enabling hardware-secured signing for complex policies

Risks and Considerations

Script Size Limits

Complex Miniscript policies can produce large scripts. Bitcoin consensus limits script sizes (10,000 bytes for P2WSH, 10,000 bytes per Tapscript leaf), and stack element counts are also constrained. Miniscript's static analysis can flag policies that approach or exceed these limits before they are used, but users must be aware that not every conceivable policy fits within consensus rules.

Fee Implications

Larger scripts mean larger witnesses, which increase transaction fees. The worst-case witness size (all possible signers providing signatures, all hash preimages revealed) determines the fee the sender should reserve. Miniscript makes this cost transparent and calculable, but complex policies will always cost more to spend than simple single-key outputs.

Tooling Maturity

While Miniscript support is expanding, not all wallets and signing devices support it yet. Users who create Miniscript-based outputs must ensure that their signing infrastructure can actually satisfy the spending conditions. Importing a Miniscript descriptor into a wallet that does not fully support it could result in funds that are visible but unspendable from that wallet.

Policy Correctness

Miniscript guarantees that a policy compiles to valid, analyzable Script, but it cannot guarantee that the policy itself reflects what the user intended. A 2-of-3 threshold with the wrong keys or an incorrect timelock value will compile and function perfectly: it will just enforce the wrong conditions. Careful review of policies before committing funds is essential, especially for high-value or irreversible custody arrangements.

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.