Bitcoin Forum
November 08, 2024, 03:18:30 AM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Bitcoin core create a watch only wallet and sign transactions offline [Tutorial]  (Read 496 times)
TracaChang (OP)
Jr. Member
*
Offline Offline

Activity: 32
Merit: 128


View Profile
April 03, 2022, 12:38:48 PM
Last edit: April 05, 2022, 06:33:16 PM by TracaChang
Merited by LoyceV (42), ABCbits (14), Jet Cash (10), NotATether (10), o_e_l_e_o (4), hosseinimr93 (2), igor72 (2), BitMaxz (1), nc50lc (1), DdmrDdmr (1)
 #1

This steps can be done with 2 PCs (recommended), or if you only have one PC you can use a linux distribution like tails.

The first step will be to download Bitcoin Core, verify signatures and transfer to a USB Flash Drive (since the second PC or when booting with tails will never be connected to the internet).

-----------------------------------------
Offline PC or with tails
-----------------------------------------
Open Bitcoin-qt with double click which is located in bitcoin-22.0/bin/

Bitcoin-qt will boot and ask us where to store data, just click ok, nothing will be downloaded since we are not even connected to the internet.



Create a new wallet, select encrypt and descriptor wallet:



After creating the wallet, do a backup and store it in a another device like a USB Flash Drive (if you are using tails after shutting down all will be deleted). To do a backup just click File -> Backup wallet

Now we will get the information needed in order to create a watch wallet only.

Open the console (window → console, or Ctrl+T) and type:

Code:
listdescriptors
note: Tthis command is available since version 0.22



With this command we will get a list of 6 descriptors in total. We will be using those with path derivation 84'/0'/0.(We will be using this derivation for native segwit, bech32).

Copy in a text file both of them and save it to the USB flash drive, in this example my .txt file will look like this:

  
Code:
 {
    "desc”: "wpkh([66bb13d5/84'/0'/0']xpub6CtDSW4S3XVd5uYp9CgsLTZKQcKieJSmjehcvfVJBSy1rPbkKNU3T6UmZ3mn7DoSsTsM6uH8ZKem7LQh3PHyrBAtZopSvF2tonEE7foTWFe/1/*)#a9twa6j5",
    "timestamp": 1647182091,
    "active": true,
    "internal": true,
    "range": [
    0,
    999
    ],
    "next": 0
    },
    {
    "desc": "wpkh([66bb13d5/84'/0'/0']xpub6CtDSW4S3XVd5uYp9CgsLTZKQcKieJSmjehcvfVJBSy1rPbkKNU3T6UmZ3mn7DoSsTsM6uH8ZKem7LQh3PHyrBAtZopSvF2tonEE7foTWFe/0/*)#v3w0q0zv",
    "timestamp": 1647182091,
    "active": true,
    "internal": false,
    "range": [
    0,
    1000
    ],
    "next": 1
    }

One descriptor has the value internal:false while the other internal:true. Internal false will provide the information needed for the watch-only wallet to generate receiving addresses while internal true is for the change addresses.

We can shutdown the PC/tails.

-----------------------------------------
Online PC.
-----------------------------------------

Your online PC must have bitcoin core installed and synched.

Create a watch wallet only: Select Disable Private Keys, Make Blank Wallet and Descriptor Wallet.



Open the .txt where you saved both descriptors, go to console and import the both descriptors with their timestamp with the command importdescriptors.

In my example command will look like this:

first descriptor:

Code:
importdescriptors "[{\"desc\": \"wpkh([66bb13d5/84'/0'/0']xpub6CtDSW4S3XVd5uYp9CgsLTZKQcKieJSmjehcvfVJBSy1rPbkKNU3T6UmZ3mn7DoSsTsM6uH8ZKem7LQh3PHyrBAtZopSvF2tonEE7foTWFe/1/*)#a9twa6j5\", \"range\": [0, 1000], \"timestamp\": 1647182091, \"internal\": true, \"watchonly\": true, \"active\": true}]"

second descriptor:

Code:
importdescriptors "[{\"desc\": \"wpkh([66bb13d5/84'/0'/0']xpub6CtDSW4S3XVd5uYp9CgsLTZKQcKieJSmjehcvfVJBSy1rPbkKNU3T6UmZ3mn7DoSsTsM6uH8ZKem7LQh3PHyrBAtZopSvF2tonEE7foTWFe/0/*)#v3w0q0zv\", \"range\": [0, 1000], \"timestamp\": 1647182091, \"internal\": false, \"watchonly\": true, \"active\": true}]"



This will import the descriptor with an initial keypool of 1000 (which is the default), any new addresses you request will come from their descriptors. If all correct it will return “success”: true

After this our watch wallet only it is fully functional allowing us to receive payments and create unsigned transactions.

Before receive any payment in the watch wallet only please be sure you have the wallet.dat backup of the offline wallet

For this tutorial I have received two transactions as you can see:


Now to spend them, just do as usual, enter the address to pay to, set fees:

click Create Unsigned:

Then click save and you will get a .psbt file which we will copy to a USB Flash Drive in order to sign with the offline wallet.

-----------------------------------------
Offline PC or with tails
-----------------------------------------
If you boot with tails you will have to copy the bitcoin client, copy the backup of the wallet.dat in the bitcoin folder ~/.bitcoin/wallets/wallet.dat

File→Load PSBT from file

Review the information and click sign transaction.

If you are using bitcoin core 0.22 and your wallet is encrypted (which should be if you have followed all the steps in this tutorial) you will get an error (Could not sign any more inputs), passphrase is not even asked. This will be fixed in the next release.

To sign we must unlock wallet first:

window→console and type:

walletpassphrase “mypassprhase” 120

Between “” you enter your passphrase and 120 can be replaced by any number, in this case wallet will remain unlocked for 120 seconds and after that time, it will lock automatically.

After the transaction is signed, click save, and save the signed psbt file to the USB flash drive.


-----------------------------------------
Online PC
-----------------------------------------

File→Load psbt from file


Click Broadcast Tx and done:
darkv0rt3x
Hero Member
*****
Offline Offline

Activity: 1274
Merit: 681


I rather die on my feet than to live on my knees


View Profile
April 04, 2022, 08:18:13 PM
 #2

What version of Bitcoin Core are you using? I can't find that listdescriptors command in the version I am using. Right now, I'm using Bitcoin Core v0.21.1. However I can find importdescriptors "requests" whic I find it weird to have this command and not the listdescriptors one.

Is it specific of v0.22 ?

Bitcoin is energy. Bitcoin is freedom
I rather die on my feet than living on my knees!
nc50lc
Legendary
*
Offline Offline

Activity: 2590
Merit: 6344


Self-proclaimed Genius


View Profile
April 05, 2022, 02:40:40 AM
Merited by ABCbits (1)
 #3

Is it specific of v0.22 ?
Yes.
See the release note for version 22.0, here: github.com/bitcoin/bitcoin/blob/master/doc/release-notes/release-notes-22.0.md

I think the lack of info is partly my fault because I've suggested him to use that command to get the 'change address' parent descriptor while not informing him that the command is only available to the latest version (v22.0).

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
TracaChang (OP)
Jr. Member
*
Offline Offline

Activity: 32
Merit: 128


View Profile
April 05, 2022, 06:28:13 PM
 #4


Tutorial updated specifying that this command is only available for version 0.22 to avoid confusions, thanks!
mirkorainer
Newbie
*
Offline Offline

Activity: 5
Merit: 0


View Profile
August 19, 2022, 06:53:11 PM
Last edit: August 19, 2022, 07:05:52 PM by mirkorainer
 #5

I have done this and it shows success in the console output for Bitcoin Core 0.22

However, I do not see the balance I would expect.

Will Bitcoin Core only show balances for UTXOs created after you`importdescriptors`? Or am I screwing this up somehow?

Edit: It would seem like it will only see UTXOs that happen after I did the import. This could be worth mentioning. To test, I just reused an address (I DON'T DO IT EVERYTIME, OK!) and sent myself a small amount. I now see this TX show up in Bitcoin Core with the watch-only wallet setup as per this guide.

Edit#2: Forgot about `rescanblockchain`. Used that and it worked. Don't forget to specify a blockheight to start at unless your wallet is super old. (I rescanned starting just before my first TXid block height)
nc50lc
Legendary
*
Offline Offline

Activity: 2590
Merit: 6344


Self-proclaimed Genius


View Profile
August 20, 2022, 03:18:44 AM
 #6

Will Bitcoin Core only show balances for UTXOs created after you`importdescriptors`? Or am I screwing this up somehow?
This will depend on the value of "timestamp" in 'importdescriptors'.
In the example in the OP, he used "1647182091" which is the epoch date of "Sunday, March 13, 2022" so Bitcoin Core will only rescan blocks past that time.
If you want to rescan from the genesis block, set it to "0"; if you do not wish to rescan, set it to "now".

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
LoyceV
Legendary
*
Offline Offline

Activity: 3486
Merit: 17644


Thick-Skinned Gang Leader and Golden Feather 2021


View Profile WWW
August 20, 2022, 09:44:24 AM
 #7

Isn't this much easier without using a Descriptor Wallet? You can just create a new wallet and untick it.

I must admit I've never used a Descriptor Wallet, and no doubt the developers had a good reason for it, but importaddress:
Code:
importaddress "address" ( "label" rescan p2sh )
looks much easier than this:
Code:
importdescriptors "[{\"desc\": \"wpkh([66bb13d5/84'/0'/0']xpub6CtDSW4S3XVd5uYp9CgsLTZKQcKieJSmjehcvfVJBSy1rPbkKNU3T6UmZ3mn7DoSsTsM6uH8ZKem7LQh3PHyrBAtZopSvF2tonEE7foTWFe/0/*)#v3w0q0zv\", \"range\": [0, 1000], \"timestamp\": 1647182091, \"internal\": false, \"watchonly\": true, \"active\": true}]"

▄▄███████████████████▄▄
▄█████████▀█████████████▄
███████████▄▐▀▄██████████
███████▀▀███████▀▀███████
██████▀███▄▄████████████
█████████▐█████████▐█████
█████████▐█████████▐█████
██████████▀███▀███▄██████
████████████████▄▄███████
███████████▄▄▄███████████
█████████████████████████
▀█████▄▄████████████████▀
▀▀███████████████████▀▀
Peach
BTC bitcoin
Buy and Sell
Bitcoin P2P
.
.
▄▄███████▄▄
▄████████
██████▄
▄██
█████████████████▄
▄███████
██████████████▄
███████████████████████
█████████████████████████
████████████████████████
█████████████████████████
▀███████████████████████▀
▀█████████████████████▀
▀██████████████████▀
▀███████████████▀
▀▀███████▀▀

▀▀▀▀███▀▀▀▀
EUROPE | AFRICA
LATIN AMERICA
▄▀▀▀











▀▄▄▄


███████▄█
███████▀
██▄▄▄▄▄░▄▄▄▄▄
████████████▀
▐███████████▌
▐███████████▌
████████████▄
██████████████
███▀███▀▀███▀
.
Download on the
App Store
▀▀▀▄











▄▄▄▀
▄▀▀▀











▀▄▄▄


▄██▄
██████▄
█████████▄
████████████▄
███████████████
████████████▀
█████████▀
██████▀
▀██▀
.
GET IT ON
Google Play
▀▀▀▄











▄▄▄▀
nc50lc
Legendary
*
Offline Offline

Activity: 2590
Merit: 6344


Self-proclaimed Genius


View Profile
August 21, 2022, 04:20:50 AM
Merited by LoyceV (4), hosseinimr93 (1)
 #8

Isn't this much easier without using a Descriptor Wallet? You can just create a new wallet and untick it.
The difference with importaddress is, this method can create an HD watching-only wallet.
AFAIK, there's no other method to create an HD watching-only wallet in Core without using parent descriptors.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
LoyceV
Legendary
*
Offline Offline

Activity: 3486
Merit: 17644


Thick-Skinned Gang Leader and Golden Feather 2021


View Profile WWW
August 21, 2022, 07:12:28 AM
 #9

The difference with importaddress is, this method can create an HD watching-only wallet.
Thanks, I didn't catch that part. That does make it worth the effort. Allow me to add more Merit.

@OP: can you fix the img links, so the images show up when you reach Jr. Member (only 10 posts to go)?
For example:
Code:
[img]https://ibb.co/wJT1tFY[/img]
Should be:
Code:
[img]https://i.ibb.co/dbSyZw7/01.png[/img]

▄▄███████████████████▄▄
▄█████████▀█████████████▄
███████████▄▐▀▄██████████
███████▀▀███████▀▀███████
██████▀███▄▄████████████
█████████▐█████████▐█████
█████████▐█████████▐█████
██████████▀███▀███▄██████
████████████████▄▄███████
███████████▄▄▄███████████
█████████████████████████
▀█████▄▄████████████████▀
▀▀███████████████████▀▀
Peach
BTC bitcoin
Buy and Sell
Bitcoin P2P
.
.
▄▄███████▄▄
▄████████
██████▄
▄██
█████████████████▄
▄███████
██████████████▄
███████████████████████
█████████████████████████
████████████████████████
█████████████████████████
▀███████████████████████▀
▀█████████████████████▀
▀██████████████████▀
▀███████████████▀
▀▀███████▀▀

▀▀▀▀███▀▀▀▀
EUROPE | AFRICA
LATIN AMERICA
▄▀▀▀











▀▄▄▄


███████▄█
███████▀
██▄▄▄▄▄░▄▄▄▄▄
████████████▀
▐███████████▌
▐███████████▌
████████████▄
██████████████
███▀███▀▀███▀
.
Download on the
App Store
▀▀▀▄











▄▄▄▀
▄▀▀▀











▀▄▄▄


▄██▄
██████▄
█████████▄
████████████▄
███████████████
████████████▀
█████████▀
██████▀
▀██▀
.
GET IT ON
Google Play
▀▀▀▄











▄▄▄▀
mirkorainer
Newbie
*
Offline Offline

Activity: 5
Merit: 0


View Profile
August 31, 2022, 01:12:12 AM
 #10

Will Bitcoin Core only show balances for UTXOs created after you`importdescriptors`? Or am I screwing this up somehow?
This will depend on the value of "timestamp" in 'importdescriptors'.
In the example in the OP, he used "1647182091" which is the epoch date of "Sunday, March 13, 2022" so Bitcoin Core will only rescan blocks past that time.
If you want to rescan from the genesis block, set it to "0"; if you do not wish to rescan, set it to "now".

Thank you for sharing this! This is a better solution than my findings.
davidaw6812
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
May 05, 2024, 10:55:48 AM
 #11

hey ,

i don't understand why i create watch only wallet command for importdescriptor

error message


Executing command using "watch only wallet" wallet

importdescriptors "[{\"desc\":
\"wpkh([14e61600/84'/0'/0']xpub6BuMVZnKofsTGQSP4TkmvYLzV1MpHAceDteJgveizpvCR6PGxhaGuCvgQJz5wKjS47fESUv8Aqk sJnAYLk4uTUS4cjsyLncUzaQM7hKNXCZ/1/*)#m5n2mwfm\",
\"range\": [0,999], \"timestamp\": 1714782715, \"internal\": true, \"watchonly\": true, \"active\": true}]"


[
  {
    "success": false,
    "error": {
      "code": -5,
      "message": "Provided checksum 'm5n2mwfm' does not match computed checksum 'g9v4p57c'"
    }
  }
]


somebody can answer to me?

i follow this man teach bitcoin core offline transaction step

website : https://medium.com/@ChangTraca/bitcoin-core-as-cold-storage-sign-transactions-offline-and-generate-receiving-addresses-from-the-f0b2de8436b5

i use window system , is this reason use linux system only ?

 
nc50lc
Legendary
*
Offline Offline

Activity: 2590
Merit: 6344


Self-proclaimed Genius


View Profile
May 05, 2024, 02:22:01 PM
 #12

   "error": {
      "code": -5,
      "message": "Provided checksum 'm5n2mwfm' does not match computed checksum 'g9v4p57c'"
That message contains the reason for the error.
The provided checksum which is the string starting with "#" sign after the descriptor isn't correct.

Just change it with the correct checksum "g9v4p57c" and it will be imported to your watch-only wallet.

But if it's from listdescriptors command of your offline Bitcoin Core, the checksum should already be correct.
Anyways, check your setup if your offline wallet can sign low value transactions created in your watch-only wallet before funding it with your intended amount.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
davidaw6812
Newbie
*
Offline Offline

Activity: 3
Merit: 0


View Profile
May 05, 2024, 02:47:46 PM
 #13

yes , it is come from offline bitcoin core create new wallet generate new address

listdescriptor command :


 {
      "desc": \"wpkh([14e61600/84h/0h/0h]xpub6BuMVZnKofsTGQSP4TkmvYLzV1MpHAceDteJgveizpvCR6PGxhaGuCvgQJz5wKjS47fESUv8Aqk sJnAYLk4uTUS4cjsyLncUzaQM7hKNXCZ/0/*)#2qktxmer",
      "timestamp": 1714782714,
      "active": true,
      "internal": false,
      "range": [
        0,
        1000
      ],
      "next": 1,
      "next_index": 1
    },



    {
      "desc": "wpkh([14e61600/84h/0h/0h]xpub6BuMVZnKofsTGQSP4TkmvYLzV1MpHAceDteJgveizpvCR6PGxhaGuCvgQJz5wKjS47fESUv8Aqk sJnAYLk4uTUS4cjsyLncUzaQM7hKNXCZ/1/*)#m5n2mwfm",
      "timestamp": 1714782715,
      "active": true,
      "internal": true,
      "range": [
        0,
        999
      ],
      "next": 0,
      "next_index": 0
    },


but online computer i create watch only wallet importdescriptor command show checksum error ? i don't understand what happen ?




 
nc50lc
Legendary
*
Offline Offline

Activity: 2590
Merit: 6344


Self-proclaimed Genius


View Profile
May 06, 2024, 04:19:42 AM
 #14

but online computer i create watch only wallet importdescriptor command show checksum error ? i don't understand what happen ?
Okay, so you didn't copied it 1:1 but used single quotations marks (') for hardened derivation instead of the character used by the descriptor which is "h".

Using getdescriptorinfo command shows that the computed checksum changes if the character is changed:
Code:
getdescriptorinfo "wpkh([14e61600/84'/0'/0']xpub...7hKNXCZ/1/*)"
Result: "checksum": "g9v4p57c",
Code:
getdescriptorinfo "wpkh([14e61600/84h/0h/0h]xpub...7hKNXCZ/1/*)"
Result: "checksum": "m5n2mwfm",

You can use either character but edit the checksum to its corresponding descriptor,
just make sure that the derivation path indices and extended public key (xpub) are correct.

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!