Back to Blog
How to Build Custom Multisig Wallets with Bitcoin Dev Kit
·5 min read

How to Build Custom Multisig Wallets with Bitcoin Dev Kit

Step-by-step guide to building 2-of-3 multisig wallets with BDK's Miniscript support, from basic setups to complex spending policies.

A 2-of-3 multisig wallet sounds straightforward until you actually try to build one. You need to generate keys across multiple devices, derive the right paths, compile descriptors that all parties can verify, coordinate partially signed transactions, and handle the inevitable edge cases. Bitcoin Dev Kit reduces this complexity to a handful of commands and a few lines of Rust.

BDK is a suite of production-ready Rust libraries that handle the cryptographic heavy lifting for custom Bitcoin wallets. Its real power for multisig development lies in Miniscript support, which lets you express spending policies declaratively (like "require 2 of these 3 keys") and have the library generate the correct Bitcoin script automatically.

Understanding Descriptor-Based Multisig

Traditional multisig implementations require developers to manually construct Bitcoin scripts, a process that's error-prone and difficult to audit. BDK takes a different approach: you describe what you want in human-readable policy language, and the library compiles it to valid Miniscript.

A 2-of-3 multisig policy looks like this:

```

thresh(2,pk(KEY1),pk(KEY2),pk(KEY3))

```

This reads exactly as you'd expect: "threshold of 2, from public keys 1, 2, and 3." BDK compiles this into the appropriate witness script hash (WSH) descriptor that Bitcoin nodes understand.

The elegance here is that all three participants can independently verify the policy matches their expectations before any funds move. Each wallet generates the same receive addresses, confirming they're all watching the same multisig output.

Building a 2-of-3 Multisig Wallet Step by Step

The bdk-cli tool provides the fastest path to a working multisig setup. You'll need to install it with the compiler and electrum features enabled.

Step 1: Generate Three Extended Private Keys

Each participant generates their own extended private key. In a real deployment, this happens on separate devices, ideally hardware signers. For development:

```bash

bdk-cli key generate

```

Run this three times, storing each xprv securely. Call them XPRV_00, XPRV_01, and XPRV_02.

Step 2: Derive Extended Public Keys

Each participant derives their xpub at the standard path for native SegWit (m/84'/1'/0'/0 for testnet):

```bash

bdk-cli key derive --xprv $XPRV_00 --path "m/84'/1'/0'/0"

```

Share the resulting xpubs (XPUB_00, XPUB_01, XPUB_02) among all participants. Never share the xprvs.

Step 3: Compile Multisig Descriptors

Here's where BDK's design pays off. Each participant creates a descriptor that includes their own xprv (for signing) and the other parties' xpubs (for verification):

Wallet 0's descriptor:

```

thresh(2,pk($XPRV_00/84h/1h/0h/0/*),pk($XPUB_01),pk($XPUB_02))

```

Wallet 1's descriptor:

```

thresh(2,pk($XPUB_00),pk($XPRV_01/84h/1h/0h/0/*),pk($XPUB_02))

```

Wallet 2's descriptor:

```

thresh(2,pk($XPUB_00),pk($XPUB_01),pk($XPRV_02/84h/1h/0h/0/*))

```

Notice each wallet holds only one private key. The wildcard (*) allows deriving fresh addresses for each transaction.

Step 4: Sync and Verify

After creating wallets from these descriptors, sync each against an Electrum server:

```bash

bdk-cli wallet --descriptor "wsh($DESCRIPTOR)" sync

```

All three wallets should show identical receive addresses and balances. This confirms everyone is working with the same multisig configuration.

Step 5: Create and Sign PSBTs

To spend from the multisig, create a Partially Signed Bitcoin Transaction (PSBT) from any wallet:

```bash

bdk-cli wallet create_tx --to "tb1q...address:50000"

```

The first signer adds their signature:

```bash

bdk-cli wallet sign --psbt $UNSIGNED_PSBT

```

Pass the partially signed PSBT to a second signer, who adds their signature. With two of three signatures collected, broadcast the transaction:

```bash

bdk-cli wallet broadcast --psbt $SIGNED_PSBT

```

Moving Beyond Basic Multisig

The thresh() policy is just the beginning. BDK's Miniscript support enables complex spending conditions without custom script code.

Time-Locked Recovery

An enterprise treasury might require 3-of-5 signatures normally, but allow 2-of-5 after 90 days for disaster recovery:

```

or(thresh(3,pk(A),pk(B),pk(C),pk(D),pk(E)),and(thresh(2,pk(A),pk(B),pk(C),pk(D),pk(E)),older(12960)))

```

The older() condition specifies blocks (12960 blocks ≈ 90 days).

Hierarchical Spending

A company might allow the CFO to spend unilaterally below a threshold, require CFO plus one board member for medium amounts, and require three board members for large transfers. Each tier gets its own UTXO set with appropriate policies.

Production Considerations

BDK excels at rapid development and custom implementations, but production multisig setups warrant additional precautions.

Hardware signers should hold private keys in any serious deployment. BDK's architecture supports external signers; your application can pass PSBTs to hardware devices and receive signatures without ever exposing key material to general-purpose computers.

The sequential PSBT signing workflow shown above works fine for small setups. For organizations with many signers spread across time zones, parallel signing (where each party signs the original unsigned PSBT independently, then signatures are combined) scales better. This mirrors the approach used in Bitcoin Core's multisig workflows.

BDK's Q1 2026 releases, including bdk_wallet 3.0.0 release candidates, added migration utilities for older wallets and improved mobile bindings for Swift, Kotlin, and Flutter. If you're building a mobile multisig app, these bindings let you use the same BDK logic across platforms without maintaining separate codebases.

Why BDK for Multisig Development

The alternative to BDK is implementing descriptor parsing, Miniscript compilation, PSBT handling, and coin selection yourself. That's months of work and a significant attack surface.

BDK's descriptor-first approach means policies are auditable. Anyone can read thresh(2,pk(A),pk(B),pk(C)) and understand what it does. The compiled Miniscript can be verified against the policy. The generated addresses can be checked across multiple independent implementations.

For developers building institutional custody solutions, point-of-sale systems, or any application requiring complex spending conditions, BDK handles the hard parts so you can focus on user experience and business logic. The library runs efficiently on everything from embedded IoT devices to high-performance servers, with WebAssembly compatibility for browser-based signing flows.

Multisig remains one of Bitcoin's most powerful security features. With BDK, building custom multisig wallets that match your exact requirements is finally practical for teams without deep protocol expertise.