Bitcoin Forum
May 05, 2024, 08:16:26 AM *
News: Latest Bitcoin Core release: 27.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 373 times)
TracaChang (OP)
Jr. Member
*
Offline Offline

Activity: 32
Merit: 127


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), 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:
"You Asked For Change, We Gave You Coins" -- casascius
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714896986
Hero Member
*
Offline Offline

Posts: 1714896986

View Profile Personal Message (Offline)

Ignore
1714896986
Reply with quote  #2

1714896986
Report to moderator
darkv0rt3x
Hero Member
*****
Offline Offline

Activity: 1204
Merit: 658


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: 2408
Merit: 5588


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).

.
.HUGE.
▄██████████▄▄
▄█████████████████▄
▄█████████████████████▄
▄███████████████████████▄
▄█████████████████████████▄
███████▌██▌▐██▐██▐████▄███
████▐██▐████▌██▌██▌██▌██
█████▀███▀███▀▐██▐██▐█████

▀█████████████████████████▀

▀███████████████████████▀

▀█████████████████████▀

▀█████████████████▀

▀██████████▀▀
█▀▀▀▀











█▄▄▄▄
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
.
CASINSPORTSBOOK
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀▀█











▄▄▄▄█
TracaChang (OP)
Jr. Member
*
Offline Offline

Activity: 32
Merit: 127


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: 2408
Merit: 5588


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".

.
.HUGE.
▄██████████▄▄
▄█████████████████▄
▄█████████████████████▄
▄███████████████████████▄
▄█████████████████████████▄
███████▌██▌▐██▐██▐████▄███
████▐██▐████▌██▌██▌██▌██
█████▀███▀███▀▐██▐██▐█████

▀█████████████████████████▀

▀███████████████████████▀

▀█████████████████████▀

▀█████████████████▀

▀██████████▀▀
█▀▀▀▀











█▄▄▄▄
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
.
CASINSPORTSBOOK
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀▀█











▄▄▄▄█
LoyceV
Legendary
*
Offline Offline

Activity: 3304
Merit: 16596


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}]"

nc50lc
Legendary
*
Offline Offline

Activity: 2408
Merit: 5588


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.

.
.HUGE.
▄██████████▄▄
▄█████████████████▄
▄█████████████████████▄
▄███████████████████████▄
▄█████████████████████████▄
███████▌██▌▐██▐██▐████▄███
████▐██▐████▌██▌██▌██▌██
█████▀███▀███▀▐██▐██▐█████

▀█████████████████████████▀

▀███████████████████████▀

▀█████████████████████▀

▀█████████████████▀

▀██████████▀▀
█▀▀▀▀











█▄▄▄▄
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
.
CASINSPORTSBOOK
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀▀█











▄▄▄▄█
LoyceV
Legendary
*
Offline Offline

Activity: 3304
Merit: 16596


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]

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.
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!