Feedback on a simple 2-path vault design (2-of-2 + CLTV recovery) and use of pruned nodes for UTXO retrieval

149 views
Skip to first unread message

victor perez

unread,
Dec 11, 2025, 6:31:56 AM (6 days ago) Dec 11
to Bitcoin Development Mailing List

Hello everyone,

I’m working on a small non-custodial vault system and would like to collect feedback on the safety and correctness of a simple script design, as well as on a question regarding pruned nodes and PSBT workflows.

Vault design

The vault uses two spending paths:

  1. Normal spending path (immediate):
    2-of-2 multisig (key A + key B required)

  2. Recovery path (delayed):
    After a predefined block height (CLTV), key B alone can spend:

    <CLTV_height> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey_B> OP_CHECKSIG

Both paths behave as expected on regtest, including enforcement of the CLTV height.

The goal is a simple inheritance/emergency mechanism:
– before the delay expires → strict 2-of-2
– after the delay → key B alone can recover funds
No custodial component; all spending is done via PSBTs signed on two Ledger devices.

Main question

For the client software, I would like to use a remote pruned Bitcoin Core node (for storage and deployment reasons).
The client retrieves UTXOs, fetches the required previous outputs for PSBT construction, and broadcasts the final transaction via RPC.

Is a pruned node fully reliable for such a workflow?
Specifically:

  • returning all UTXOs belonging to the vault address,

  • providing scriptPubKey, value, and other fields required in a PSBT input,

  • validating the timelocked script spend,

  • broadcasting the final transaction.

Are there any known limitations, edge cases, or risks associated with relying on a pruned node in this context, especially when spending from a script with multiple paths (2-of-2 + CLTV recovery)?

Any comments on the script design itself (safety, best practices, or possible improvements, including Taproot-based approaches) would also be very welcome.

Thanks for your time and insights.

Best regards,
Victor

Antoine Poinsot

unread,
Dec 11, 2025, 9:23:38 AM (5 days ago) Dec 11
to victor perez, Bitcoin Development Mailing List
Hi Victor,

Can we as a community stop calling everything vaults? We've seen vanilla multisig wallets being called vaults, then CTV transaction chains, and now a decaying multisig. Not trying to blame you in particular, but a vault in Bitcoin has (or used to have?) a specific meaning, and regardless grouping constructions with very different properties under a single label only creates confusion.

What you present is essentially Liana: https://github.com/wizardsardine/liana. Except that Liana uses relative timelocks (CSV) because absolute timelocks (CLTV) put an expiration date on your descriptor, which adds lots of friction and can be quite confusing to less technical users.

By default Liana comes bundled with a pruned Bitcoin Core node and uses its watchonly wallet functionality to track your coins. For a remote node, Bitcoin Core's RPC interface is not adapted and Liana lets you configure an Electrum server instead.

Regards,
Antoine
--
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/82546937-996d-495d-8a4e-66654306447cn%40googlegroups.com.

victor perez

unread,
Dec 13, 2025, 5:05:30 AM (4 days ago) Dec 13
to Antoine Poinsot, Bitcoin Development Mailing List

Hi Antoine,

Thanks a lot for your message and for pointing this out — I completely understand your remark about the terminology. You’re right: using “vault” too loosely contributes to confusion, especially when Bitcoin vaults historically referred to a very specific construction with enforced spending paths and secure delays.
I’ll adjust my wording going forward and be more precise about what the system implements.

The construction I’m working on is indeed essentially a 2-of-2 multisig with a CSV-based recovery path, very similar in spirit to Liana. My goal is mostly educational and exploratory for now: understanding the full lifecycle (descriptor, address generation, UTXO tracking, PSBT building, hardware signing, recovery flow). I’m not trying to innovate or redefine the term “vault”, but rather build a usable multisig recovery system before exploring more advanced designs.

Your point about absolute timelocks (CLTV) is well taken. I switched to CSV for the same reason you mentioned: CLTV introduces an implicit expiration that is difficult to communicate to non-technical users. CSV makes the construction more flexible and avoids descriptor obsolescence.

Regarding node operation:
For the moment I’m running a full Bitcoin Core node (non-pruned) because it simplifies UTXO retrieval during development. I hadn’t implemented pruned-node compatibility yet, but seeing that Liana handles this cleanly with a pruned watch-only wallet + Electrum fallback is extremely helpful context. I’ll definitely study how Liana approaches this architecture before going further.

My intention isn’t to reinvent Liana, but rather to build something minimal for learning, and then expand it into a broader project (inheritance flows, user-friendly recovery logic, analytics, etc.) once the foundations are solid.

Thanks again for taking the time to point me in the right direction — it’s really appreciated.
If you have any recommendations on what pitfalls to avoid or reading material on robust recovery designs, I’d be glad to hear them.

Best regards

Victor 

Antoine Poinsot

unread,
Dec 13, 2025, 12:08:27 PM (3 days ago) Dec 13
to victor perez, Bitcoin Development Mailing List
Hi Victor,

> If you have any recommendations on what pitfalls to avoid or reading material on robust recovery designs, I’d be glad to hear them.

Since you mentioned that your purpose was educational, i would recommend, ordered by amount of time investment:
1. Go through the flow of using your construction with the Bitcoin Core wallet API, which implements all those functionalities. For instance you could take advantage of the multi-wallet functionality to simulate different signers + one funding wallet. Have a Python script generating the keys and registering the descriptor for each, and then receive coins from the funding wallet and go through the PSBT signing flow for both spending paths to send them back to the funder. You could do that on Signet with an intentionally low recovery timelock, but using regtest will let you iterate faster.
2. Implement this flow yourself using the BDK [0] library. This will introduce you to more of the details of descriptor scanning using different "chain sources", PSBT processing, all this without having to reimplement all the minutiae. That said once you've got a prototype working you can start diving deeper into the implementation of the BDK library, and if you are interested, into the implementation of the Miniscript language in the Rust-Miniscript library [1]. Since you asked about the pitfalls of implementing such a construction, this is where you'll learn about a lot (but not all) of them. The inner working of Bitcoin Script is both critical to the safety of your funds, and at times very surprising. Nowadays, it is neatly abstracted to higher layers by Miniscript in a safe(r) manner. Digging down this rabbit hole will teach you why a lot of things work the way they do.
3. Investigate how hardware signing devices interface with more complicated wallet spending policies. Learn about Salvatore Ingala's "wallet policies" [2] and try implementing signing against one of the compatible hardware signers out there: Ledger, Specter DIY, Bitbox, Coldcard (Edge), Jade. For the details of communications with those devices you may want to look into the Wizardsardine team's "async-hwi" and associated libraries [3].
4. Finally, the devil is in the details. You asked about robust designs, and that's what most time consuming. You can build a prototype that implements the core functionalities in a few weeks, maybe a few days now with BDK. But a robust software that can adapt to various usage types with a reasonable UX, different recovery configurations, interface with various signers and chain sources, can take years to get right. If you are interested in that aspect i'd recommend playing with more mature Miniscript-using projects such as Liana or Anchorwatch and digging through their open source codebase. Maybe also Nunchuk which is another mature wallet that i hear started integrating support for Miniscript descriptors.

I'd recommend joining the discussion groups of the projects i mentioned here, and maybe ##miniscript on Libera for the more technical Miniscript questions (Bitcoin Stackexchange is good for that too).

Best,
Antoine Poinsot 




-------- Original Message --------

victor perez

unread,
Dec 14, 2025, 9:09:47 AM (2 days ago) Dec 14
to Antoine Poinsot, Bitcoin Development Mailing List
Hi Antoine,

Thank you very much for your detailed reply—it's extremely helpful.

Following your advice, I'm going to simplify my work and first focus on a single spending path: a clean 2-of-2 (A + B) multisig, signed with two Ledgers. My goal is to get this flow stable end-to-end (descriptor creation, UTXO handling, PSBT flow, hardware signing, broadcast) before adding the recovery path with a timelock.

Just to clarify the scope: my application is not meant to be a second Liana. It's an educational and experimental Ruby on Rails environment that I use to better understand Bitcoin in practice.

The app combines several independent modules:

  - A vault module, where I experiment with descriptors, Miniscript/Taproot constructions, PSBTs, and hardware signing.
  - A BRC-20 and on-chain analytics module, which helps me explore data intelligence by extracting and analysing blockchain data.
  - A donation module in sats connected to my BTCPay Server.
  - Various dashboards for visualizing Bitcoin data.

I should mention that I am currently not using regtest. All my experiments are done directly on mainnet with real BTC, because it helps me stay fully aware of real-world constraints and forces me to design things carefully. That said, based on your recommendations, I will start integrating regtest into my workflow so I can iterate faster and test edge-cases more safely.

Your pointers toward Bitcoin Core's wallet API, BDK, Miniscript, and hardware-wallet policies give me a very clear roadmap for progressing in a structured way.

Thanks again for your time and guidance—it truly helps.

Best regards,
Victor

Reply all
Reply to author
Forward
0 new messages