From 8c7c7a71353a6054f80eeb5ce4be0f946cec89a5 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Mon, 28 Aug 2023 13:08:06 +0200 Subject: [PATCH 1/2] doc: polish the Bitcoin Core recovery document --- doc/RECOVER.md | 238 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 156 insertions(+), 82 deletions(-) diff --git a/doc/RECOVER.md b/doc/RECOVER.md index 36ee185a..cd854cae 100644 --- a/doc/RECOVER.md +++ b/doc/RECOVER.md @@ -1,48 +1,65 @@ -Here a step by step walkthrough to recover a Liana wallet only using bitcoin-core and HWI utility. -Commands are given for signet, but you can run it in mainnet simply by not using the signet options. +# Recover your Liana wallet using Bitcoin Core -We assume you already have a bitcoind/bitcoin-cli running on your machine. +This document walks you through the step of recovering a Liana wallet using `bitcoind` and +`bitcoin-cli`. You will need a couple things in order to follow this guide: +- Your Liana wallet descriptor. +- The date at which you created the Liana wallet (approximately). +- The necessary signing devices. In this example we'll use a Ledger Nano S and [HWI](https://github.com/bitcoin-core/HWI). +- An address to sweep the funds to. Here we'll use `tb1qed7lyessqcecav5uxultf6zc8nefd9kalgaa7dwrglcc6ld5vd3qe20spe`. +- An installed and synchronized `bitcoind`. If you don't have Bitcoin Core yet you can download it + [here](https://bitcoincore.org/en/download/). The minimum supported version for this guide is + 25.0. -### Create wallet in bitcoin core +This document **is not** about the similarly named "timelocked recovery path" feature. You can spend +your coins through (one of) the timelocked recovery path(s) using Bitcoin Core too, but this +document is about the instructions for recovering your coins using the Bitcoin Core wallet in the +improbable case you cannot access the Liana wallet for whatever reason. +Here's a list of the steps we'll undertake: +1. Create a dedicated watchonly wallet on Bitcoin Core, and import the Liana wallet descriptor there. +2. Scan the blockchain for your coins since the birthdate of your wallet. +3. Create a transaction that sweeps all your coins to the prepared address. +4. Sign this transaction using the appropriate devices. +5. Broadcast the transaction. + +NB: this guide was written with an example on Linux. It should be trivial to follow on any other +operating system though, with only minor adaptations needed to the examples. + +## Create a Bitcoin Core wallet and import the Liana descriptor + +Your Liana wallet descriptor is probably of the form: +``` +wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/<0;1>/\*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/<0;1>/\*),older(3))))#8ldsjayd +``` +Note the curious `<0;1>` step in the xpubs' derivation path. It's called a +[multipath](https://github.com/bitcoin/bips/blob/master/bip-0389.mediawiki), a way to compress two +derivation steps in a single expression so you only have to backup a single descriptor instead of +two (one for deriving receive addresses and the other for change addresses). + +Bitcoin Core 25.0 does not yet support multipath descriptors. So we'll have to split the descriptor +in two: one for receive and one for change. To do so: +- Make two copies of your descriptor, without the checksum (the part following the `#`). +- For each of them walk through the xpubs. +- Replace each multipath expression with the first index (here `0`) for the first copy and the + second index for the second copy (here `1`). + +For our example descriptor above this gives us: +``` +wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/0/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/0/*),older(3)))) +``` +and +``` +wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/1/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/1/*),older(3)))) +``` + +We'll need a checksum for each in order to be able to import them on the Bitcoin Core wallet. For +this use the `getdescriptorinfo` command, gather the `checksum` field and append it to the +descriptor after a `#`. For instance with the first descriptor above: ```shell -bitcoin-cli -signet createwallet 'liana' true +bitcoin-cli getdescriptorinfo wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/0/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/0/*),older(3)))) ``` - -output: +Output: ``` -{ - "name": "liana" -} -``` - -### Process & import descriptor - -As PR[#22838](https://github.com/bitcoin/bitcoin/pull/22838) not (yet) merged in bitcoin core, we need to 'split' -descriptor in 2: - - 1 for receive addresses - - 1 for changes addresses. - -#### Original descriptor: - - wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/`<0;1>`/\*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/`<0;1>`/\*),older(3))))`#8ldsjayd` - -Here we need to process 2 descriptors from the original one, replacing `<0;1>` by `0` for the receive descriptor and `1` for change descriptor, checksum might to be updated for each ones. - -#### Processed descriptors: - - - wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/`0`/\*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/`0`/\*),older(3)))) - - - - wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/`1`/\*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/`1`/\*),older(3)))) - -Now we got the descriptors without checksums, we can process it using bitcoin-cli getdescriptorinfo method: - -```shell -bitcoin-cli -signet getdescriptorinfo "wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/0/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/0/*),older(3))))" -``` - -output: -``` { "descriptor": "wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/0/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/0/*),older(3))))#nhtumqkr", "checksum": "nhtumqkr", @@ -51,34 +68,34 @@ output: "hasprivatekeys": false } ``` - -```shell -bitcoin-cli -signet getdescriptorinfo "wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/1/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/1/*),older(3))))" +So the resulting descriptor is +``` +wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/0/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/0/*),older(3))))#nhtumqkr ``` -output: -``` +Make sure to do this for both descriptors, and then create the dedicated watchonly wallet on Bitcoin Core: +```shell +bitcoin-cli -signet createwallet liana_recovery true +``` +Output: +``` { - "descriptor": "wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/1/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/1/*),older(3))))#vpa5k5p6", - "checksum": "vpa5k5p6", - "isrange": true, - "issolvable": true, - "hasprivatekeys": false + "name": "liana_recovery" } ``` -The command to pass to bitcoin-cli to import descriptors should look like this: - -bitcoin-cli -signet -rpcwallet=liana importdescriptors "[{\"desc\": \"``\", \"range\": [0,10000], \"timestamp\": ``}, {\"desc\": \"``\", \"range\": [0,10000], \"timestamp\": ``}]" - - - `` should be replaced by unix timestamp of your wallet birthdate(if you don't know about the wallet birthdate you can use 1671577200 -Liana V0.1 birthdate-, note that using a lower timestamp than the wallet birthdate will increase the rescan duration) - - `` and `` sould be replaced by relevant descriptors (including new generated checksums): - +We are now going to import the receive and change descriptors to the wallet. This process will take +care of rescanning the block chain for transactions involving these descriptors. Make sure you have +your wallet birthdate in a timestamp format (we'll use `1682920310`, May 1st 2023). In order to do +this we are going to use the `importdescriptors` command and pass it our two descriptors (with the +checksum appended) along with the wallet birthdate as a timestamp. Note this command may take a +while as it's going to be rescanning the block chain. The farther in the past the birthdate, the +longer it will take. If the command times out you will be able to inspect the progress using the +`getwalletinfo` command. ```shell bitcoin-cli -signet -rpcwallet=liana importdescriptors "[{\"desc\": \"wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/0/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/0/*),older(3))))#nhtumqkr\", \"range\": [0,10000], \"timestamp\": 1682920310, \"active\": true, \"internal\":false}, {\"desc\": \"wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/1/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/1/*),older(3))))#vpa5k5p6\", \"range\": [0,10000], \"timestamp\": 1682920310, \"active\": true, \"internal\":true}]" ``` - -output: +Output: ```shell [ { @@ -90,14 +107,46 @@ output: ] ``` -### Build the sweep transaction - -```shell -bitcoin-cli -signet -rpcwallet=liana sendall '["tb1qed7lyessqcecav5uxultf6zc8nefd9kalgaa7dwrglcc6ld5vd3qe20spe"]' null "unset" 20 +Alright! You should now be able to see your coins on the wallet. You can check your balance with the +`getbalance` command or list all the unspent coins using `listunspent`. For instance in our case: +```shell +$ bitcoin-cli -signet -rpcwallet=liana_recovery listunspent +[ + { + "txid": "054166e08bd3e019031ec2e4f6a755913e924f218b6c0ab792c2fd4d911a1011", + "vout": 1, + "address": "tb1qhvrkp9qpzp2cmk7ct745zpkuw3ak45hwvczx5534x89ymg3ae0vsfwyd7j", + "label": "", + "witnessScript": "2103d040bf48b05dfa7234fe39240edc3d89cc909d65b4fd55338ffa162985d4c5c9ac736476a9142517bf2e04d18ae59db290617eb60183d4893f6188ad53b268", + "scriptPubKey": "0020bb0760940110558ddbd85fab4106dc747b6ad2ee66046a523531ca4da23dcbd9", + "amount": 0.00010000, + "confirmations": 152, + "spendable": true, + "solvable": true, + "desc": "wsh(or_d(pk([a5c6b76e/48'/1'/0'/2'/0/1]03d040bf48b05dfa7234fe39240edc3d89cc909d65b4fd55338ffa162985d4c5c9),and_v(v:pkh([c477fd13/48'/1'/0'/2'/0/1]02113af9bac303954c884a077e1840b98fe0b8713ccace07adcbacf322e8f72fbd),older(3))))#8vukwv7f", + "parent_descs": [ + "wsh(or_d(pk([a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh/0/*),and_v(v:pkh([c477fd13/48'/1'/0'/2']tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH/0/*),older(3))))#nhtumqkr" + ], + "safe": true + } +] ``` -(here we define fee at `20 sats/VBytes`) -output: +## Sweep the coins out of the wallet + +### Craft the sweep transaction + +We are now going to create a PSBT that spends all the coins in the wallet to the pre-defined +address. Note merging all your coins into one is usually a bad practice for privacy purpose. +You can also spend them one by one or in other way if you wish. Here we are simply going to present +the simplest way of recovering from disaster. + +We'll use the `sendall` command to sweep all the funds of the wallet to the pre-defined address +using a specific feerate. We'll use `20` sats/vbyte but use anything that fits. +```shell +bitcoin-cli -signet -rpcwallet=liana -named sendall recipients='["tb1qed7lyessqcecav5uxultf6zc8nefd9kalgaa7dwrglcc6ld5vd3qe20spe"]' 20 +``` +Output: ``` { "psbt": "cHNidP8BAF4CAAAAATEgOFWAFkRN09sCK0V1ES9UyMiUQRJrb0AG4j1y0q++AQAAAAD9////ARg4DwAAAAAAIgAgy33yZhAGM46ynDc+tOhYPPKWlt36O981w0fxjX20Y2IAAAAAAAEAfQIAAAABnk7wzbybA7Z6kvlO7hFYl5x2BN3L0otR5M5udXzGN/oBAAAAAP7///8CrKE2EQAAAAAWABRnUU8zi4M3eMplKigSvOdhtGuSdUBCDwAAAAAAIgAgxBhOa53udP66VGgn+vs7sboB8aXyJj4WddV6PsUjJvHoZAIAAQErQEIPAAAAAAAiACDEGE5rne50/rpUaCf6+zuxugHxpfImPhZ11Xo+xSMm8QEFQSEDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoCsc2R2qRRX/S6WeWl7J1PJvN+73IONRKHJYYitU7JoIgYDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoAcpca3bjAAAIABAACAAAAAgAIAAIAAAAAAAAAAACIGA2u7xjrIFe7ShVfXgPOqQwzKtxYkFeV52rNpNyzHfrNdHMR3/RMwAACAAQAAgAAAAIACAACAAAAAAAAAAAAAAA==", @@ -105,10 +154,19 @@ output: } ``` -### Install hwi -As [PR647(wallet policies)](https://github.com/bitcoin-core/HWI/pull/647) is not (yet) merged into HWI we need to install it from git: +### Sign the sweep transaction -#### Download the sources +This part may depend on the signing devices you used with Liana. In general there should be plenty +of documentation available for each signer about how, given a PSBT, to sign it and potentially pass +it on to the next signer. Here we'll detail the signing process with a Ledger Nano S(+). + +#### Install HWI + +You will need the [`HWI`](https://github.com/bitcoin-core/HWI) tool to interface with the Ledger. +However, Salvatore's wallet policies (required to sign for Miniscript descriptors) are at the time +of writing not yet merged so we'll have to use his branch. + +Get the HWI-with-wallet-policy pull request code: ```shell git clone https://github.com/bitcoin-core/HWI cd HWI @@ -116,7 +174,7 @@ git fetch origin pull/647/head git checkout FETCH_HEAD ``` -#### Virtual environment & install +And install it in a virtual environment (you may have to install Python and `pip`): ```shell python3 -m venv venv . venv/bin/activate @@ -124,37 +182,54 @@ pip install poetry poetry install ``` -### Register policy on ledger nano: +#### Sign with the Ledger -Here we need to do (one more time) some processing on the descriptor format: the XPUBs might be extracted from descriptor and supplied as a list of keys (fingerprint + derivation path might be specified only for te key stored in the ledger nano) +Register the descriptor on the Ledger. It's using a specific syntax to register both descriptors at +once: the wallet policies. You'll once again have to process the descriptor: +1. Take the original descriptor (with the `<0;1>` multipaths derivation steps). +2. Replace all xpubs with an `@` followed by an index number (`@0` for the first, `@1` for the + second, etc..). +3. Compile a list of the xpubs **in the same order**. +4. Replace all `/<0;1>/*` derivation steps by `/**`. NOTE: **do not** replace those if the multipath + step is anything other than `/<0;1>/*`. For instance if it's `/<2;3>/*` **leave it intact**. +For instance in our case the result is this wallet policy: +``` +wsh(or_d(pk(@0/**),and_v(v:pkh(@1/**),older(3)))) +``` +With the following list of xpubs: +``` +["[a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh","tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH"] +``` + +We can finally register it on the Ledger: ```shell python3 -m hwi --chain test --device-type ledger registerpolicy --policy "wsh(or_d(pk(@0/**),and_v(v:pkh(@1/**),older(3))))" --name "Liana" --keys "[\"[a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh\",\"tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH\"]" ``` - -output +Output ``` {"proof_of_registration": "34602db12b76200ea96386c4cd10b8b1d60b84e060d2d6120073c06367a9506d"} ``` +(The resulting proof of registration will be different in your case.) -### Sign PSBT with ledger nano: - +Then go ahead and sign the PSBT we've previously crafted: ```shell python3 -m hwi --chain test --device-type ledger signtx cHNidP8BAF4CAAAAATEgOFWAFkRN09sCK0V1ES9UyMiUQRJrb0AG4j1y0q++AQAAAAD9////ARg4DwAAAAAAIgAgy33yZhAGM46ynDc+tOhYPPKWlt36O981w0fxjX20Y2IAAAAAAAEAfQIAAAABnk7wzbybA7Z6kvlO7hFYl5x2BN3L0otR5M5udXzGN/oBAAAAAP7///8CrKE2EQAAAAAWABRnUU8zi4M3eMplKigSvOdhtGuSdUBCDwAAAAAAIgAgxBhOa53udP66VGgn+vs7sboB8aXyJj4WddV6PsUjJvHoZAIAAQErQEIPAAAAAAAiACDEGE5rne50/rpUaCf6+zuxugHxpfImPhZ11Xo+xSMm8QEFQSEDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoCsc2R2qRRX/S6WeWl7J1PJvN+73IONRKHJYYitU7JoIgYDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoAcpca3bjAAAIABAACAAAAAgAIAAIAAAAAAAAAAACIGA2u7xjrIFe7ShVfXgPOqQwzKtxYkFeV52rNpNyzHfrNdHMR3/RMwAACAAQAAgAAAAIACAACAAAAAAAAAAAAAAA== --policy "wsh(or_d(pk(@0/**),and_v(v:pkh(@1/**),older(3))))" --name "Liana" --keys "[\"[a5c6b76e/48'/1'/0'/2']tpubDF5861hj6vR3iJr3aPjGJz4rNbqDCRujQ21mczzKT5SiedaQqNVgHC8HT9ceyxvMFRoPMx4P6HAcL3NZrUPhRUbwCyj3TKSa64bAfnE3sLh\",\"tpubDFn7iPbFqGrTQ2aRACNsUK1MXQR4Z6dYfU2nD1WA9ifSaia642j3Wah4n5pBUEpERNWGJsyv3Dv5qwBabC9TLQrwSboKzukw9wmurGu7XVH\"]" --extra "{\"proof_of_registration\": \"34602db12b76200ea96386c4cd10b8b1d60b84e060d2d6120073c06367a9506d\"}" ``` - -output: +Output: ``` {"psbt": "cHNidP8BAF4CAAAAATEgOFWAFkRN09sCK0V1ES9UyMiUQRJrb0AG4j1y0q++AQAAAAD9////ARg4DwAAAAAAIgAgy33yZhAGM46ynDc+tOhYPPKWlt36O981w0fxjX20Y2IAAAAAAAEAfQIAAAABnk7wzbybA7Z6kvlO7hFYl5x2BN3L0otR5M5udXzGN/oBAAAAAP7///8CrKE2EQAAAAAWABRnUU8zi4M3eMplKigSvOdhtGuSdUBCDwAAAAAAIgAgxBhOa53udP66VGgn+vs7sboB8aXyJj4WddV6PsUjJvHoZAIAAQErQEIPAAAAAAAiACDEGE5rne50/rpUaCf6+zuxugHxpfImPhZ11Xo+xSMm8SICAxT3fpXMWDFL24VudUzehc3OSxbUFU2G2QVMbhBKRx6ASDBFAiEA1h9wI6XI+3Jz61f3rrR9L/6guHbcG7/Dl0a2CmEhWlICIFcwZKqKWe96gUkIQctln6K9R9U4nHx3qJxrHUhmkuf/AQEFQSEDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoCsc2R2qRRX/S6WeWl7J1PJvN+73IONRKHJYYitU7JoIgYDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoAcpca3bjAAAIABAACAAAAAgAIAAIAAAAAAAAAAACIGA2u7xjrIFe7ShVfXgPOqQwzKtxYkFeV52rNpNyzHfrNdHMR3/RMwAACAAQAAgAAAAIACAACAAAAAAAAAAAAAAA==", "signed": true} ``` -### Finalize PSBT: +### Broadcast the sweep transaction +Once you've gotten enough signatures for the PSBT, you are ready to broadcast the sweep transaction. + +First, finalize the PSBT: ```shell bitcoin-cli -signet finalizepsbt cHNidP8BAF4CAAAAATEgOFWAFkRN09sCK0V1ES9UyMiUQRJrb0AG4j1y0q++AQAAAAD9////ARg4DwAAAAAAIgAgy33yZhAGM46ynDc+tOhYPPKWlt36O981w0fxjX20Y2IAAAAAAAEAfQIAAAABnk7wzbybA7Z6kvlO7hFYl5x2BN3L0otR5M5udXzGN/oBAAAAAP7///8CrKE2EQAAAAAWABRnUU8zi4M3eMplKigSvOdhtGuSdUBCDwAAAAAAIgAgxBhOa53udP66VGgn+vs7sboB8aXyJj4WddV6PsUjJvHoZAIAAQErQEIPAAAAAAAiACDEGE5rne50/rpUaCf6+zuxugHxpfImPhZ11Xo+xSMm8SICAxT3fpXMWDFL24VudUzehc3OSxbUFU2G2QVMbhBKRx6ASDBFAiEA1h9wI6XI+3Jz61f3rrR9L/6guHbcG7/Dl0a2CmEhWlICIFcwZKqKWe96gUkIQctln6K9R9U4nHx3qJxrHUhmkuf/AQEFQSEDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoCsc2R2qRRX/S6WeWl7J1PJvN+73IONRKHJYYitU7JoIgYDFPd+lcxYMUvbhW51TN6Fzc5LFtQVTYbZBUxuEEpHHoAcpca3bjAAAIABAACAAAAAgAIAAIAAAAAAAAAAACIGA2u7xjrIFe7ShVfXgPOqQwzKtxYkFeV52rNpNyzHfrNdHMR3/RMwAACAAQAAgAAAAIACAACAAAAAAAAAAAAAAA== ``` - -output: +Output: ``` { "hex": "02000000000101312038558016444dd3db022b4575112f54c8c89441126b6f4006e23d72d2afbe0100000000fdffffff0118380f0000000000220020cb7df2661006338eb29c373eb4e8583cf29696ddfa3bdf35c347f18d7db4636202483045022100d61f7023a5c8fb7273eb57f7aeb47d2ffea0b876dc1bbfc39746b60a61215a520220573064aa8a59ef7a81490841cb659fa2bd47d5389c7c77a89c6b1d486692e7ff0141210314f77e95cc58314bdb856e754cde85cdce4b16d4154d86d9054c6e104a471e80ac736476a91457fd2e9679697b2753c9bcdfbbdc838d44a1c96188ad53b26800000000", @@ -162,8 +237,7 @@ output: } ``` -### Broadcast PSBT: - +And broadcast the resulting transaction: ```shell bitcoin-cli -signet sendrawtransaction 02000000000101312038558016444dd3db022b4575112f54c8c89441126b6f4006e23d72d2afbe0100000000fdffffff0118380f0000000000220020cb7df2661006338eb29c373eb4e8583cf29696ddfa3bdf35c347f18d7db4636202483045022100d61f7023a5c8fb7273eb57f7aeb47d2ffea0b876dc1bbfc39746b60a61215a520220573064aa8a59ef7a81490841cb659fa2bd47d5389c7c77a89c6b1d486692e7ff0141210314f77e95cc58314bdb856e754cde85cdce4b16d4154d86d9054c6e104a471e80ac736476a91457fd2e9679697b2753c9bcdfbbdc838d44a1c96188ad53b26800000000 -``` \ No newline at end of file +``` From b5b96b95937ef914aed237b7829a71ff3672c3f4 Mon Sep 17 00:00:00 2001 From: Antoine Poinsot Date: Mon, 28 Aug 2023 13:13:26 +0200 Subject: [PATCH 2/2] README: mention the guide on recovering a backup on Core --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index b7be177c..1786decd 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,14 @@ For the daemon, see the [`createrecovery`](doc/API.md#createrecovery) command. I 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](doc/RECOVER.md). + + ### Reproducible builds Releases of Liana are reproducibly built. Linux binaries are also bootstrappable. See