Every Bitcoin wallet you have ever used runs a tiny program. Coins are not "in" an address; they sit behind a spending condition written in Bitcoin Script, the programming language built into the protocol since block one. A normal single-sig wallet compiles to the simplest program there is: this key must sign. But Script can express far more than that, and it always could. The problem was never power. The problem was that raw Script is brutal to write by hand: one mistake can lock coins forever, and a finished script is nearly impossible to audit at a glance.
Miniscript (BIP-379, from Pieter Wuille and collaborators) fixes the usability, not the rules. It is a structured way of writing Script out of small, well-defined pieces, so that software can analyze a policy before funding it, compose conditions safely, and sign for it generically. Everything still compiles down to ordinary Bitcoin Script, enforced by every node on the network. No company, no sidecar protocol, no extra trust.
The Building Blocks
Each piece states one condition. A few of the important ones:
- A key must sign.
pk(Alice)is the whole of single-sig, now just one brick among many. - k of n keys must sign.
multi(2,Alice,Bob,Charlie)is the classic 2-of-3. - A secret must be revealed. Hashlocks require the spender to publish a value matching a known hash, the same trick that powers Lightning channels and atomic swaps.
Then come timelocks, the pieces that make the interesting policies possible. after(n) is absolute: the coins unlock at a specific block height or date, permanently. older(n) is relative: the coins must sit unmoved for a duration after they confirm. So and_v(v:pk(Alice),older(12960)) reads: Alice can spend, but only once the coins have rested about ninety days. One caveat worth knowing: the chain measures time by the median of the last eleven blocks, so calendar dates are close approximations, not appointments.
Finally, the combinators glue conditions together: and, or, an if/else form called andor, and thresh(k, ...), a threshold whose members can be whole expressions rather than bare keys. That last detail is the quiet superpower: "two of: Alice, Bob, or ninety days have passed" is a perfectly valid policy.
What You Can Build
Snap those pieces together and wallets start doing things no bank account can:
- Decaying multisig (inheritance without a custodian). Day to day, a 2-of-3 controls the funds. If the wallet sits untouched for six months, a designated backup key can spend on its own:
andor(pk(Backup),older(26000),multi(2,A,B,C)). While you are alive and active the backup path never wakes up; if you are gone, your heir waits out the clock and recovers everything. If that sounds familiar, it should: this is exactly the mechanism behind Liana's recovery paths. - A treasury with layered approvals. Routine spending needs two finance leads plus an automated co-signer; anything the co-signer refuses needs an executive's key instead; and if all else fails, the two leads alone can spend after a seven-day delay. Three tiers of control, enforced by the coins themselves.
- Escrow without a middleman holding funds. Buyer and seller sign together to settle, or after a timeout either of them plus an arbiter can. The arbiter can break ties but can never run off with the money.
The common thread: the rules are not a company's promise or a lawyer's letter. They are enforced on-chain by the same consensus that enforces the 21 million cap.
Taproot Makes It Private
A fair objection: does publishing all these conditions on-chain leak your security setup? With Taproot, no. A Taproot output commits to a tree of alternative spending branches plus one key path. Spend by the key path and the output looks like plain single-sig; nobody learns the tree existed. Spend by a branch and only that one branch is revealed, while the others stay hidden forever. Your inheritance clause, your emergency path, your arbiter: all invisible until the day one of them is actually used.
MuSig2 goes further, letting several signers cooperate to produce one aggregated Schnorr signature, so even a multi-party key path spends looking like one person with one key. Signing device support for MuSig2 has not landed yet, so treat that piece as near-future rather than today.
The Fine Print
Two things keep Miniscript honest in practice. First, the descriptor rule gets stricter. Your policy lives in the wallet descriptor, and with Miniscript the descriptor carries the whole structure: keys, timelocks, branches. Every seed backup needs a descriptor copy beside it, because all your keys together cannot reconstruct a policy nobody wrote down. Run the backup verification playbook on the whole arrangement, not just the seeds.
Second, complexity is a cost you pay forever. Every extra path is one more thing to back up, rehearse, and explain to the people who inherit it. A policy you cannot restore from paper under stress is not security; it is a puzzle with your savings inside. Start with the simplest policy that solves your actual problem, prove the recovery works with a small amount, and only then add cleverness.
Who Speaks It
In the stack we already use: Liana is built on Miniscript from the ground up, and both Krux (including Taproot Miniscript) and Specter DIY can read a descriptor, show you the policy in plain language, and sign for it, air-gapped as always. SeedSigner does not support Miniscript yet, which is the one reason we steer Liana users toward the other two builds.
The takeaway. Bitcoin has always been programmable money. Miniscript is what makes that programmability safe enough to actually use: spending rules you can read, verify, and hand to a signing device, with nothing enforced by anyone but the network itself.
Keep going. See Multisig for the m-of-n foundations, Owning Your Keys to put a timelocked recovery path into practice with Liana, and Krux or Specter DIY for a signer that can sign it. Questions welcome at any meetup.