Antoine Poinsot b22f22f0bc
Merge #985: Taproot support
4bb2372a63bb4b36ca9f0dd91d2373cff3e9e9a4 qa: drop specific value assertions in coin selection test (Antoine Poinsot)
7eb024afbc43ac73aa29d6b892bc4833067c5a3f fuzz: alternate between generating wsh() and tr() descs (Antoine Poinsot)
b9a462519791b64165719891c6f0e9c867a07372 ci: run functional tests both under Taproot and P2WSH (Antoine Poinsot)
687a0c2816290d09bda8f1323232bc4c643e9a35 qa: adapt hardcoded coin selection tests to Taproot (Antoine Poinsot)
ecef6bff5eaf00305941c04d93a8bac8003f9d34 qa: functional tests lianad using Taproot descriptors (Antoine Poinsot)
96d30db5b868c8f2e6ecc45f1bf6759df582569e signer: taproot support in hot signer (Antoine Poinsot)
80a7dc32aad43fe4c6a1cd0fc41d4ac1bb8a7de6 signer: move p2wsh signing into a dedicated function (Antoine Poinsot)
d6222583be148a6b12caed7b0ede00be317d89c6 command: also update Taproot sigs in 'updatespend' (Antoine Poinsot)
714bd3c4eda1420142b5761623808f73c64578c6 spend: check for either p2wsh or Taproot sigs in sanity checks (Antoine Poinsot)
e05039f67b3d7a44cd9079f3a57d75a3161cb3f1 spend: don't populate non_witness_utxo for Taproot (Antoine Poinsot)
8596ca76f3547c77cf64c556966ee1651550f231 bitcoind: compare descriptors, not their string representation. (Antoine Poinsot)
602c862118ff43616b24b5d252321a98a83d2454 bitcoind: sanity check min supported version for Taproot descriptor (Antoine Poinsot)
d3b7e4cc44c59b8aad77b0cf0d9ae29095db65f9 config: unit test a valid config with a Taproot descriptor (Antoine Poinsot)
6cf8eaab3b92a7f5bcc9c35490dc9766d071ca00 config: deser_from_str isn't descriptor specific. (Antoine Poinsot)
04f4b8a744cdcc52e345948ed9636640d641c528 descriptors: Taproot support (Antoine Poinsot)
c897d41965cf077fda63cc39c31cb75f400d757e descriptors: encapsulate key matching logic (Antoine Poinsot)
85fdc40366dcb3c5c8cf91be1b1cc59727402e04 descriptor: encapsulate PSBT in/out information update (Antoine Poinsot)

Pull request description:

  This introduces Taproot support in the Liana daemon / core library.

  We start by introducing support for `tr()` descriptors alongside `wsh()` descriptors in the Taproot modules. For Taproot-Liana descriptors whose primary spending path isn't a single key, we deterministically derive an unspendable internal key as per https://delvingbitcoin.org/t/unspendable-keys-in-descriptors/304/21. This is to allow signing devices to not display the internal key as a spendable key when verifying a descriptor. Currently signing device vendors signaled willingness to implement this scheme.

  We then adapt the PSBT management logic to use Taproot fields when necessary and upgrade the hot signer to provide Schnorr signatures depending on the PSBT information.

  Finally, the functional tests are adapted to be able to run the whole test suite under either P2WSH or Taproot. This is done in a somewhat hacky way as i bailed out of re-implementing a Taproot PSBT signer and finalizer in Python after implementing [TapMiniscript support in upstream python-bip380](https://github.com/darosior/python-bip380/pull/23). Instead we use a small Rust program to sign PSBTs for now and we skip a test which explicitly requires an external finalizer.

ACKs for top commit:
  darosior:
    ACK 4bb2372a63bb4b36ca9f0dd91d2373cff3e9e9a4 -- this underwent multiple rounds of review, Edouard tested it in his follow-up PR to the GUI and i wrote a couple fuzz targets exercising part of the logic introduced here

Tree-SHA512: 426032f0bcf8a27e43cf3d158da011bda648cb56534ea678d3c4a43c3f59047e4bb7f83469fd38f70ac962d1a9721e9c1f68baa60bf597bf08fa3c39fc00ebe8
2024-03-14 11:20:56 +01:00
2024-03-13 19:21:52 +01:00
2023-12-12 15:42:15 +01:00
2024-01-04 14:32:57 +01:00
2023-12-15 13:29:48 +01:00
2023-05-11 11:44:57 +02:00

Liana

The missing safety net for your bitcoins.

About

Liana is a simple Bitcoin wallet that features a timelocked recovery path for all your coins. That is, your coins are spendable as with a regular wallet but a secondary key becomes available after a configurable period of time should the primary one not be accessible anymore.

Liana can be used for inheritance, decaying multisigs or safer backups.

https://wizardsardine.com/liana

Usage

TL;DR: if you just want to quickly try Liana on Bitcoin Signet, check out the guide!

As a Bitcoin wallet, Liana needs to be able to connect to the Bitcoin network. The software has been developed such as multiple ways to connect to the Bitcoin network may be available. However for now only the connection through bitcoind is implemented.

Therefore in order to use Liana you need to have the Bitcoin Core daemon (bitcoind) running on your machine for the desired network (mainnet, signet, testnet or regtest). The bitcoind installation may be pruned (note this may affect block chain rescans) up to the maximum (around 550MB of blocks).

The minimum supported version of Bitcoin Core is 24.0.1. If you don't have Bitcoin Core installed on your machine yet, you can download it there.

Installing the software

The recommended installation method for regular users is to download an executable software release. If you prefer to build the project from source, see doc/BUILD.md instead.

Head to the release page and download the right executable for your platform. If you are not sure what is the "right" executable for your platform, choose:

  • Liana.zip if you are on MacOS,
  • liana-4.0.exe if you are on Windows,
  • liana_4.0.deb if you are running a Debian-based Linux (such as Ubuntu). Use apt install ./liana_4.0.deb as root (or preceded by sudo) to install it.
  • liana-4.0.tar.gz if you use another Linux distribution. Note you may have to compile the software yourself if you are on Linux. See the section below.

For every file available on the release page, there is an accompanying .asc file with the same name. This is a GPG signature made with Antoine Poinsot's key: 590B7292695AFFA5B672CBB2E13FC145CD3F4304. This key is available elsewhere for cross-checking, such as on his Twitter profile or his personal website. It is recommended you verify your download against this key.

For Arch users, a liana-bin is also available at the AUR. You can install it using your favourite wrapper (eg paru -S liana-bin or yay -S liana-bin), or manually:

git clone https://aur.archlinux.org/liana-bin.git
cd liana-bin
cat PKGBUILD # Review the PKGBUILD script
makepkg -si

A note on Linux binaries and glibc version

Skip this section if you are not running Linux or don't plan on using a released binary.

Due to technical limitations in our reproducible builds system, the Linux binaries currently link against glibc version 2.33. This means you can't run a released Linux binary if your system has an older glibc. This is the case most notably of Ubuntu 20 (Focal) and below, and Debian 11 (Bullseye) and below.

The simplest workaround is to simply build the project yourself. Fear not, it's really trivial if you are a Linux user. Instructions here.

See this issue for details.

Apple, Windows, codesigned and notarized binaries

We distribute both a non-codesigned and a codesigned-and-notarized MacOS application (Liana-noncodesigned.zip and Liana.zip). To run the non-codesigned app, see this Apple support guide (section "If you want to open an app that hasnt been notarized or is from an unidentified developer").

We do not yet distribute codesigned binaries for Windows at this time.

Wallet usage tips and tricks

Script descriptor backup

In Bitcoin, the conditions for spending a certain amount of coins are expressed using Script. In order to be able to recover your coins, you need to back up both:

  • The Script template, in the form of a standard Output Script Descriptor
  • The private key(s) corresponding to the public key(s) used in the Script

By so doing, any software that understands the Output Script Descriptor standard will be able to retrieve your coins. By using your private key(s) you would then be able to sign a transaction spending them.

But without the descriptor you won't be able to recover from your backup. Note however it is simpler to have redundancy for your descriptor backup. A thief getting access to it would be able to learn your balance (and transaction history), but would not be able to steal your funds. Therefore you may afford a greater number of backups of your descriptor(s) and using less secure mediums than for storing your private key(s).

On refreshing coins

You can use Liana just like a regular wallet. Simply be aware that if you are using a relative timelock (the only type of timelocks supported for now), time starts ticking when you receive a payment. That is if you want the recovery path to never be available, each coin must be spent at least once every N blocks. (With N the configured value of the timelock.)

The GUI provide simple shortcuts to refresh one or more coin(s) if the recovery path is close to become available. This is achieved by making a transaction to yourself (if you don't need to make a payment.)

Signing devices and "hot" keys

Liana can be used as a hot wallet. Note that mnemonics would be stored in clear on your drive. We strongly recommend using a hardware signing device for any non-trivial amount.

For now, the following signing devices are supported:

  • Ledger Nano S and S+
  • BitBox02
  • Specter DIY

With more signing devices implementing Miniscript capability, support for new ones will be added in the near future. For more information (such as minimum supported versions) please read the signing devices documentation.

Using the daemon

Liana can be run as a headless server using the lianad program.

You can use the liana-cli program to send commands to it. It will need the path to the same configuration as the daemon. You can find a full documentation of the JSONRPC API exposed by lianad at doc/API.md. For instance:

$ liana-cli --conf ./signet_config.toml getinfo
{
  "result": {
    "block_height": 3083,
    "descriptors": {
      "main": {
        "change_desc": "wsh(or_i(and_v(v:thresh(1,pkh([b883f127/48'/1'/2'/2']tpubDEP7MLK6TGe1EWhKGpMWdQQCvMmS6pRjCyN7PW24afniPJYdfeMMUb2fau3xTku6EPgA68oGuR4hSCTUpu2bqaoYrLn2UmhkytXXSzxcaqt/1/*),a:pkh([636adf3f/48'/1'/2'/2']tpubDFnPUtXZhnftEFD5vg4LfVoApf5ZVB8Nkrf8CNe9pT9j1EEPXssJnMgAjmvbTChHugnkfVfsmGafFnE6gwoifJNybSasAJ316dRpsP86EFb/1/*),a:pkh([b883f127/48'/1'/3'/2']tpubDFPMBua4idthySDayX1GxgXgPbpaEVfU7GwMc1HAfneknhqov5syrNuq4NVdSVWa2mPVP3BD6f2pGB98pMsbnVvWqrxcLgwv9PbEWyLJ6cW/1/*)),older(20)),or_i(and_v(v:pkh([636adf3f/48'/1'/1'/2']tpubDDvF2khuoBBj8vcSjQfa7iKaxsQZE7YjJ7cJL8A8eaneadMPKbHSpoSr4JD1F5LUvWD82HCxdtSppGfrMUmiNbFxrA2EHEVLnrdCFNFe75D/1/*),older(19)),or_d(multi(2,[636adf3f/48'/1'/0'/2']tpubDEE9FvWbG4kg4gxDNrALgrWLiHwNMXNs8hk6nXNPw4VHKot16xd2251vwi2M6nsyQTkak5FJNHVHkCcuzmvpSbWHdumX3DxpDm89iTfSBaL/1/*,[b883f127/48'/1'/0'/2']tpubDET11c81MZjJvsqBikGXfn1YUzXofoYQ4HkueCrH7kE94MYkdyBvGzyikBd2KrcBAFZWDB6nLmTa8sJ381rWSQj8qFvqiidxqn6aQv1wrJw/1/*),and_v(v:pkh([b883f127/48'/1'/1'/2']tpubDEA6SKh5epTZXebgZtcNxpLj6CeZ9UhgHGoGArACFE7QHCgx76vwkzJMP5wQ9yYEc6g9qSGW8EVzn4PhRxiFz1RUvAXBg7txFnvZFv62uFL/1/*),older(18))))))#056xvvp3",
        "multi_desc": "wsh(or_i(and_v(v:thresh(1,pkh([b883f127/48'/1'/2'/2']tpubDEP7MLK6TGe1EWhKGpMWdQQCvMmS6pRjCyN7PW24afniPJYdfeMMUb2fau3xTku6EPgA68oGuR4hSCTUpu2bqaoYrLn2UmhkytXXSzxcaqt/<0;1>/*),a:pkh([636adf3f/48'/1'/2'/2']tpubDFnPUtXZhnftEFD5vg4LfVoApf5ZVB8Nkrf8CNe9pT9j1EEPXssJnMgAjmvbTChHugnkfVfsmGafFnE6gwoifJNybSasAJ316dRpsP86EFb/<0;1>/*),a:pkh([b883f127/48'/1'/3'/2']tpubDFPMBua4idthySDayX1GxgXgPbpaEVfU7GwMc1HAfneknhqov5syrNuq4NVdSVWa2mPVP3BD6f2pGB98pMsbnVvWqrxcLgwv9PbEWyLJ6cW/<0;1>/*)),older(20)),or_i(and_v(v:pkh([636adf3f/48'/1'/1'/2']tpubDDvF2khuoBBj8vcSjQfa7iKaxsQZE7YjJ7cJL8A8eaneadMPKbHSpoSr4JD1F5LUvWD82HCxdtSppGfrMUmiNbFxrA2EHEVLnrdCFNFe75D/<0;1>/*),older(19)),or_d(multi(2,[636adf3f/48'/1'/0'/2']tpubDEE9FvWbG4kg4gxDNrALgrWLiHwNMXNs8hk6nXNPw4VHKot16xd2251vwi2M6nsyQTkak5FJNHVHkCcuzmvpSbWHdumX3DxpDm89iTfSBaL/<0;1>/*,[b883f127/48'/1'/0'/2']tpubDET11c81MZjJvsqBikGXfn1YUzXofoYQ4HkueCrH7kE94MYkdyBvGzyikBd2KrcBAFZWDB6nLmTa8sJ381rWSQj8qFvqiidxqn6aQv1wrJw/<0;1>/*),and_v(v:pkh([b883f127/48'/1'/1'/2']tpubDEA6SKh5epTZXebgZtcNxpLj6CeZ9UhgHGoGArACFE7QHCgx76vwkzJMP5wQ9yYEc6g9qSGW8EVzn4PhRxiFz1RUvAXBg7txFnvZFv62uFL/<0;1>/*),older(18))))))#yl5jehy9",
        "receive_desc": "wsh(or_i(and_v(v:thresh(1,pkh([b883f127/48'/1'/2'/2']tpubDEP7MLK6TGe1EWhKGpMWdQQCvMmS6pRjCyN7PW24afniPJYdfeMMUb2fau3xTku6EPgA68oGuR4hSCTUpu2bqaoYrLn2UmhkytXXSzxcaqt/0/*),a:pkh([636adf3f/48'/1'/2'/2']tpubDFnPUtXZhnftEFD5vg4LfVoApf5ZVB8Nkrf8CNe9pT9j1EEPXssJnMgAjmvbTChHugnkfVfsmGafFnE6gwoifJNybSasAJ316dRpsP86EFb/0/*),a:pkh([b883f127/48'/1'/3'/2']tpubDFPMBua4idthySDayX1GxgXgPbpaEVfU7GwMc1HAfneknhqov5syrNuq4NVdSVWa2mPVP3BD6f2pGB98pMsbnVvWqrxcLgwv9PbEWyLJ6cW/0/*)),older(20)),or_i(and_v(v:pkh([636adf3f/48'/1'/1'/2']tpubDDvF2khuoBBj8vcSjQfa7iKaxsQZE7YjJ7cJL8A8eaneadMPKbHSpoSr4JD1F5LUvWD82HCxdtSppGfrMUmiNbFxrA2EHEVLnrdCFNFe75D/0/*),older(19)),or_d(multi(2,[636adf3f/48'/1'/0'/2']tpubDEE9FvWbG4kg4gxDNrALgrWLiHwNMXNs8hk6nXNPw4VHKot16xd2251vwi2M6nsyQTkak5FJNHVHkCcuzmvpSbWHdumX3DxpDm89iTfSBaL/0/*,[b883f127/48'/1'/0'/2']tpubDET11c81MZjJvsqBikGXfn1YUzXofoYQ4HkueCrH7kE94MYkdyBvGzyikBd2KrcBAFZWDB6nLmTa8sJ381rWSQj8qFvqiidxqn6aQv1wrJw/0/*),and_v(v:pkh([b883f127/48'/1'/1'/2']tpubDEA6SKh5epTZXebgZtcNxpLj6CeZ9UhgHGoGArACFE7QHCgx76vwkzJMP5wQ9yYEc6g9qSGW8EVzn4PhRxiFz1RUvAXBg7txFnvZFv62uFL/0/*),older(18))))))#v3g9rzum"
      }
    },
    "network": "regtest",
    "rescan_progress": null,
    "sync": 1.0,
    "version": "1.0.0"
  }
}

Note also that you might connect the GUI to a running lianad. If the GUI detects a daemon is already running, it will plug to it and communicate through the JSONRPC API.

Using the recovery path

You may sweep the coins whose timelocked recovery path is available. You will need to sign the transaction using the recovery key(s), hence make sure to connect the appropriate signing device(s).

In the GUI, this option is available in the "Settings" menu at the "Recovery" section. Click on the "Recover funds" button, enter the destination for the sweep and the feerate you want to use for the sweep transaction. Then sign it with the recovery key and broadcast it.

For the daemon, see the createrecovery command. It will create a sweep PSBT to the requested address with the specified feerate, filled with all available coins.

Recovering a Liana wallet backup on another wallet

You can always restore a Liana wallet backup using the Liana software. In the extremely unlikely scenario that you lose access to a Liana software (all copies of the binaries and source code are entirely wiped from the surface of the planet) or are otherwise unable to use it, we've got a guide on how to recover a Liana wallet backup with Bitcoin Core 25.0 and above.

Reproducible builds

Releases of Liana are reproducibly built. Linux binaries are also bootstrappable. See contrib/reproducible for details and instructions if you want to check a release.

All commits on master are merge commits signed using a set of trusted GPG keys. We use the github-merge script for this purpose. Given a set of trusted keys (basically mine and Edouard Paris') and a trusted git root commit you can verify the integrity of the master branch using the verify-commits script from our maintainer-tools repository. For instance:

$ ../maintainer-tools/verify-commits/verify-commits.py liana
...
There is a valid path from "9490159e7ca69678bb6995cd56d09b0a65a5b484" to da9149ccde5bf99cb70769b792fd003b079fc9ed where all commits are signed!

It's worth mentioning we didn't invent anything here: we're just reusing the great tooling developed by the Bitcoin Core contributors over the years.

Note you necessarily won't be able to reproduce codesigned binaries. We may provide detached signatures in the future.

About the software project

Liana is an open source project. It is hosted at Github.

Contributions are very welcome. For guidelines, see CONTRIBUTING.md.

Liana is separated in two main components: the daemon and the Graphical User Interface.

Liana daemon

The daemon contains the core logic of the wallet. It is both a library (a Rust crate) that exposes a command interface and a standalone UNIX daemon that exposes a JSONRPC API through a Unix Domain Socket.

The code for the daemon can be found in the src/ folder at the root of this repository.

Liana GUI

The GUI contains both an installer that guides a user through setting up a Liana wallet, as well as a graphical interface to the daemon using the iced library.

The code for the GUI can be found in the gui/src/ folder.

Security

See SECURITY.md for details about reporting a security vulnerability or any bug that could potentially impact the security of users' funds.

License

Released under the BSD 3-Clause Licence. See the LICENCE file.

Description
A fork of https://github.com/wizardsardine/liana with removed loopback restrictions to allow connecting to a custom remote bitcoin core node
Readme
Languages
Rust 90.4%
Python 8.5%
Shell 0.5%
Scheme 0.3%
Nix 0.3%