Miniscript 101: A Technical Guide

Article length
10 min read
Published
Aug 27, 2025

1. Introduction

WHAT IS MINISCRIPT?
Bitcoin has always included a powerful scripting language that can lock coins to conditions beyond “one signature unlocks the funds.” With Script, you can combine multiple keys, timelocks, hash preimages, and complex logical branches. In practice, however, Script has rarely been used directly because it is difficult to write correctly, mistakes can permanently lock funds, and the resulting code is nearly impossible to analyze at a glance.

Miniscript (BIP-379) was introduced by Pieter Wuille and collaborators as “a language for writing Bitcoin Scripts in a structured way, enabling analysis, composition, and generic signing.” It solves the usability and safety problems of raw Script while retaining full compatibility with today’s Bitcoin rules.

At its heart, Miniscript is like a box of Lego bricks for Bitcoin spending rules. Each brick is a small, well-defined condition, such as a key must sign, a time must pass, or a secret must be revealed. Bricks can be swapped for other components, allowing flexible construction of alternative spending paths. By combining them with logical operators such as AND, OR, and thresholds, you can build policies that are as simple or as complex as needed. Most importantly, Miniscript policies are analyzable: wallets can check in advance who can spend and under what conditions, reducing the risk of coins being locked by an invalid script.

This structured approach makes it possible to safely express policies such as:
• Require 2-of-3 directors to sign, unless one is unavailable for 6 months, then 1-of-3 is enough.
• Alice and Bob can spend together, or Charlie can recover the funds after 1 year.
• Either reveal a secret hash preimage, or wait until block 1,000,000.

WHY IT MATTERS?
With Miniscript, policies go beyond single-sig or simple multisig. You can define rules such as “A and B together can spend immediately, or C alone after 1 year,” or “2-of-3 required now, but 1-of-3 after 6 months.” These flexible conditions enable practical use cases such as inheritance planning, layered business treasuries, and emergency recovery, making advanced security accessible to everyday Bitcoin users. Importantly, all Miniscript policies are enforced directly on-chain in Bitcoin itself and do not require any additional trust assumptions beyond the Bitcoin network.

2. Core Concepts of Miniscript

Now let’s look at the core building blocks of Miniscript. Each component (a.k.a. a Miniscript fragment) represents a specific condition, and together they can be combined to create flexible and secure spending policies.

2.1 Public key

Public key: pk(k)
The simplest condition in Miniscript is requiring a signature that matches a specific public key. This represents the basic “single-sig” spend and also serves as the foundation for more advanced policies.

  • Example: Spending requires a signature.
  • Miniscript: pk(Alice)
miniscript-fragment-public-key.png
Miniscript fragment: Public key

2.2 Multisig

Multisig: multi(k, ...)
A classic multisig requires k of n keys to sign. Its child elements can only be keys.

  • Example: Spending requires any 2 of 3 signatures.
  • Miniscript: multi(2, Alice, Bob, Charlie)
miniscript-fragment-multisig.png
Miniscript fragment: Multisig

2.3 Timelock

A timelock prevents Bitcoin from being spent until a certain time. It is a native feature of Bitcoin Script and one of the most useful Miniscript building blocks.
Timelocks enforce rules like “coins can only move after 6 months” or “this key becomes valid 30 days after deposit.” Bitcoin nodes reject any transaction that tries to spend too early. Once the time has passed, coins can be spent normally and permanently.
There are two types of timelocks: Absolute and Relative.


Absolute Timelock: after(n)
Locks coins until a specific block height or timestamp is reached. Once the blockchain passes that point, the coins are permanently unlocked.

  • Example: Spending requires a signature and blockchain time after UNIX timestamp 1750000000 (≈ June 2025).
  • Miniscript: and_v(v:pk(Alice),after(1750000000))

Absolute timelocks apply to a fixed future time and cannot be reset after they expire.

miniscript-fragment-absolute-timelock.png
Miniscript fragment: Absolute timelock

 

Relative Timelock: older(n)
Locks coins for a specific duration after they are confirmed. This duration can be defined in blocks or in calendar time (days, hours). Each UTXO starts its countdown when created, and once the required time has passed, the coins are unlocked.

  • Example: Spending requires a signature and at least 12,960 blocks (~90 days) since the coins were received.
  • Miniscript: and_v(v:pk(Alice),older(12960)

Relative timelocks apply to individual UTXOs, not the entire wallet. They can be reset by “refreshing” the coins, meaning moving them to a new address within the same wallet.

miniscript-fragment-relative-timelock.png
Miniscript fragment: Relative timelock

 


When setting a timelock, the calendar date shown is only an approximation. If the timelock is based on block height, it becomes valid once that block is reached. If it is based on calendar time, Bitcoin uses median block time (specifically, the median time of the last 11 blocks), which may differ slightly from real-world time, so the transaction may not become valid at the exact expected moment.

2.4 Hashlock

A hashlock requires revealing a secret (preimage) that matches a known hash. Until the secret is revealed, the coins cannot be spent.

  • Example: Spending requires a signature and the preimage of SHA256 hash H
  • Miniscript: and_v(v:pk(Alice),sha256(H))


Hashlock types in Miniscript

  • sha256(H) — preimage must hash to SHA‑256 H (expects a 64‑hex string).
  • hash256(H) — preimage must hash to double‑SHA‑256 H (64‑hex).
  • ripemd160(H) — preimage must hash to RIPEMD‑160 H (40‑hex).
  • hash160(H) — preimage must hash to HASH160 H (RIPEMD160(SHA256), 40‑hex)
miniscript-fragment-hashlock.png
Miniscript fragment: Hashlock

2.5 Logical Foundation: AND, OR, ANDOR

These three logic blocks are the foundation of Miniscript. They describe how different conditions fit together, often with timelocks.

AND: Coins are locked until both conditions are true.

  • Example: Spending requires Alice’s signature and at least 12,960 blocks (~90 days) since the coins were received.
  • Miniscript: and_v(v:pk(Alice),older(12960))
miniscript-fragment-and.png
Miniscript fragment: AND

 


OR: Coins are locked until at least one of two conditions is true.

  • Example: Spending requires either of the two keys.
  • Miniscript: or_d(pk(Alice),pk(Bob))
miniscript-fragment-or.png
Miniscript fragment: OR

 


ANDOR: Coins are locked with an if/else rule: if the first condition is true, the second must also hold; if the first condition is false, the third condition must hold instead.

  • Example: If Alice signs, Bob’s signature is also required. If Alice does not sign, Charlie’s signature is required.
  • Miniscript: andor(pk(Alice), pk(Bob), pk(Charlie))
miniscript-fragment-and-or.png
Miniscript fragment: ANDOR

2.6 Threshold

Threshold: thresh(k, ...)
A threshold is more flexible than multisig. It requires k of n conditions to be true, but unlike multisig, the child elements are not limited to public keys. They can include logical expressions, timelocks, hashlocks, and more in addition to public keys.

  • Example: Spending requires both Alice’s and Bob’s signatures. After 90 days, either one of them can spend.
  • Miniscript: thresh(2,pk(Alice),s:pk(Bob),sln:older(12960))
miniscript-fragment-threshold.png
Miniscript fragment: Threshold

2.7 Taproot Scripts

Taproot lets you commit to multiple spending branches while revealing only the one you actually use. It provides two ways to spend:

  • Key Path: Spend with a single aggregated public key. On-chain this looks like a normal single-sig transaction, even if multiple parties contributed to the key (for example with MuSig2).
  • Script Path: Spend by using one of the committed Taproot branches. Only the branch you use is revealed, while the rest remain hidden.

This structure combines efficiency with privacy: everyday use can go through the key path, while more complex policies remain hidden until needed.

  • Example: Day-to-day spending uses an aggregated Alice’ key in the key path. If that is not available, the script path allows Charlie to sign for immediate spending, or Bob to spend after 90 days.
  • Miniscript: tr(pk(Alice), {and_v(v:pk(Bob),older(12960)),pk(Charlie)})
miniscript-fragment-taproot-scripts.png
Miniscript fragment: Taproot scripts

2.8 Musig2

MuSig2 is a Schnorr-based multisignature scheme that lets multiple participants jointly produce a single aggregated signature. On-chain, this signature looks no different from a regular single-sig. This improves both privacy and efficiency, while reducing transaction size and fees.

  • Example: Spending requires any two of Alice, Bob, and Charlie. On-chain, it looks like a single signature, so no one can tell it’s from a multi-party wallet. This makes it more private and efficient.
  • Miniscript: tr(musig(Alice, Charlie), {pk(musig(Alice, Bob)),pk(musig(Bob, Charlie))})
miniscript-fragment-musig2.png
Miniscript fragment: Musig2

3. Using Miniscript in Nunchuk

3.1 Create miniscript wallet

Nunchuk makes it easy to build advanced spending policies with Miniscript. You can either start from ready-made templates or enter your own custom script.

To create a Miniscript wallet in Nunchuk: Home → Create new wallet → Miniscript.

  • Templates: Choose from options such as Expanding Multisig, Decaying Multisig, or Flexible Multisig. Each template lets you adjust parameters like number of keys and time delays, without writing code.
create-miniscript-wallet-via-timelock.png
Create miniscript wallet via template

 

  • Custom Script: For advanced users, you can paste a raw Miniscript policy or import one from a file. Nunchuk automatically analyzes the script, checks for correctness, and shows you the spending conditions in plain language.
create-miniscript-wallet-using-a-custom-script.png
Create a miniscript wallet using a custom script

3.2 Miniscript group wallet

A Group Wallet in Nunchuk lets multiple people on multiple devices co-manage a Bitcoin wallet with end-to-end encryption. Each participant controls their own keys, and spending policies are enforced collectively without relying on a custodian. When combined with Miniscript, Group Wallets support advanced multi-party conditions that mirror real-world governance. As with a regular Miniscript wallet, you can start from ready-made templates or create your own custom script.


To create a Miniscript group wallet in Nunchuk: Home → Create new wallet → Group wallet → Settings → Miniscript.

minisciprt-group-wallet.png
Example: A company sets up a Group Wallet with two executives and four board members. For day-to-day operations, both executives must sign. As an alternative path, any three of the four board members can approve a transaction.

3.3 Miniscript wallet recovery

Beyond the usual secrets needed to recover a Bitcoin wallet, such as private keys and preimages, it is also essential to back up the wallet configuration file, either in Output Descriptors or BSMS format.

BSMS is a wrapper around Output Descriptors that includes metadata, such as the wallet’s first address. This metadata acts as a checksum and makes it easier to quickly identify the wallet. The configuration file serves as a map that defines how the wallet is constructed. The same requirement applies to Miniscript Group Wallets: without this file, the wallet cannot be reconstructed, even if all participants still hold their keys.

To recover a Miniscript wallet in Nunchuk:
Home → Create new wallet → Recover existing wallet → Recover using BSMS/descriptors.

To recover a Miniscript group wallet: 
Home → Create new wallet → Recover existing wallet → Recover group wallet.

miniscript-wallet-recovery.png
Recover a Miniscript wallet or Miniscript group wallet

 

BSMS 1.0
tr(xpub661MyMwAqRbcGgLWCDJNFcLYg8KgQimdffZdRobPJ585b93QjtCgqbPCo54DP3kpzwFpaZxoi6Snia3VDSV4oV81H4BxfaUbAzP2EpGHWDr/<0;1>/*,{multi_a(2,[8a0ba421/87'/0'/0']xpub6DWv19xigzHyBJJvE4iMTyTxQrn5TkBAr8k4gUJ8gycB8U7S7s8QRfBTa4Je2on9FE7jiUa3ijxuNyygEcpe8CGQUEz6W2PGtZ8SUJWc8fC/<0;1>/*,[d33f8331/87'/0'/0']xpub6C3RqV6jatGDLEiGpi92fsDLApCLC6SB28bMjwSaU4w3sdxmhWJRmzsxPDr8zv2hkyt1czkd3siMHJ6uAzN4T1gC5W6Vdd75XyJknN9N1Zb/<0;1>/*,[45c72f63/87'/0'/0']xpub6Ci35gULWq49uY6txiEHLJd8R9ESbadyed8zPACMgi6Cu5cd4BLG9p1ZDP3PnGNNaEHbGuy1uzEJDsEdWQck1C75DkaB13P8kX8UZkc7E8i/<0;1>/*),and_v(v:multi_a(1,[1e897bbf/87'/0'/0']xpub6CSCZZo8sDS2wjXUitr4FQUZwenEL1KcZrgYvi2mvSnVbYztYBxVLj5mKYcpNvB6RkLNEQzaaf8SWquzdhC6ncwasXk8STEjKwYRrd1QZcZ/<0;1>/*,[0cd15c3e/87'/0'/0']xpub6C3JCSGe5J2iqZymN7pKrYisD9po9FRqSRNot6561iLrzFjrPMNm8qn5VeYgTdWAtR66Kfr9oZWrjxSDLxB7GQ5dEi7hiUbjHyDxjaQxww6/<0;1>/*,[03c341e8/87'/0'/0']xpub6Bw2SYRUCc3Pcsgk39WkvkewHnxSLSERZmkUPBy91nrzKXehFBNLEzF2uJ2YiBhrS7kqagpGxBqhVziYawzUHePkB7pQGBMAnQmoYAxEAwz/<0;1>/*),after(1758819600))})#t6aeduyr
No path restrictions
bc1pzmlufvqn5dpcquqysj4fr9skwxjj60wg7zyrpk4j8ftccz9ck9rs9fmjam

Example BSMS file of a Miniscript wallet

4. Use Cases & Examples

4.1 Use Cases

Miniscript opens the door to policies that go far beyond basic multisig. Some real-world scenarios include:

  • Inheritance Planning: A vault that heirs can unlock after a defined delay, while the owner retains full control during their lifetime.
  • Business Treasury: Require multiple executives to sign for spending, with hidden fallback paths for emergencies.
  • Escrow & Trading: Use hashlocks and timelocks to enable atomic swaps or safe escrows without intermediaries.
  • Insurance: An insurance provider can enforce payout conditions where multiple signatures are required, or funds are released only after a verifiable claim event with a timelock safeguard.
  • Lending: Loans can be secured with Bitcoin collateral that enforces repayment or liquidation rules through threshold conditions, timelocks, and recovery paths, reducing the need for trusted intermediaries.
  • Emergency Recovery: A wallet that is normally secured with 2-of-3 multisig, but after inactivity, a recovery key or a set of recovery keys can unlock the funds.
  • Privacy-Preserving Custody: With Taproot and MuSig2, even complex multi-party policies can look like a simple single-sig on-chain, protecting privacy while retaining strong security.

4.2 Examples

A) Timelocked inheritance (set‑and‑forget recovery)

  • Policy idea: 2‑of‑3 today; if you’re offline for 6 months, a designated backup key can recover.
  • Why it matters: Reduce permanent loss without giving anyone immediate control.
  • How it works: A threshold of signatures or a timelocked recovery path.
  • Miniscript example:
andor(
      pk(backup_key),
      older(4224679),
      multi(2,A,B,C)
      )

B) Business treasury with layered approvals

  • Policy idea:
    • Day-to-day spending: Any 2 finance leads + a machine-operated co-signer (e.g., HSM/KMS).
    • High-value escalations: Any 2 finance leads + CFO.
    • Delayed/Emergency access: Any 2 finance leads after a 7-day delay.
  • Why it matters: Everyday agility with serious guardrails.
  • How it works: Threshold/AND plus OR branches and an optional timelock. Teams choose which branch to use operationally.
  • Miniscript example:
and_v(
      or_c(
           pk(HSM),
           or_i(
           		v:pk(CFO),
           		v:older(4195485)
           		)
           ),
      multi(2,LeadA,LeadB,LeadC))

C) Escrow you control for OTC trades

  • Policy idea: Buyer + Seller, or either party + Arbiter after a timeout.
  • Why it matters: No custodian. Clear, rule‑based resolution paths.
  • How it works: OR logic with a timelocked fallback.
  • Miniscript example:
thresh(2,
	   pk(Buyer),
	   s:pk(Seller),
	   sj:and_v(
	   			v:pk(Arbiter),
	   			n:older(4194472)
	   			)
	   )

D) Private, multi‑party wallet with compact on‑chain footprint

  • Policy idea: Three devices share control; the spend can use an aggregated key so the number of signers isn’t revealed.
  • Why it matters: Team security without broadcasting governance.
  • How it works: Optional Taproot and MuSig2. MuSig2 aggregates multiple signers into one combined key; Taproot hides unused branches. In a script path, only the executed branch is revealed.
  • Miniscript example (Taproot):
tr(
	musig(A,B),
   	{
   		pk(musig(A,C)),
   		pk(musig(B,C))
   	}
  )

5. Conclusion

Bitcoin has always had the capability for rich spending conditions, but its low-level scripting language was too difficult and risky for most users. Miniscript changes that by providing a structured, safe, and composable language for expressing policies.

With Miniscript, advanced use cases like inheritance planning, business treasuries, atomic swaps, and privacy-preserving custody are now accessible and practical.

As wallets like Nunchuk bring Miniscript into user-friendly interfaces, the Bitcoin ecosystem gains a powerful new standard. Complex contracts can finally be expressed in a way that is safe, analyzable, and accessible — unlocking the next generation of Bitcoin custody and smart contract design.

 


Footnote: Hardware support

(Last update: Aug 27, 2025)

  • Supports Native Segwit Miniscript: Tapsigner, Coldcard (EDGE firmware v6.3.3 and above), Jade (firmware v1.0.38 and above), Jade Plus (firmware v1.0.38 and above), Ledger (firmware v2.1.0 and above), Specter DIY (firmware v1.5.0 and above) 
  • Supports Taproot Miniscript: Coldcard (EDGE firmware v6.3.3 and above), Ledger (firmware v2.2.1 and above), Specter DIY (firmware v1.9.0 and above)
  • Supports MuSig2: None (currently only software keys are supported)

 

Share

More from us

Join our newsletter

Subscribe to get our latest news, updates and special offers
Newsletter

Download our app

App Store DownloadPlay Store Download
Mac DownloadWindows DownloadLinux Download