I think I have found something that isn't properly implemented in the following workflow. What I have been trying to do for the past month or so is figure out how to do a 2 laptop setup, one online and one offline, and be able to use the PSBT solution to quickly craft transactions using the GUI. I want to use Coin Control, pick what UTXO's I want to use for the transaction, and then generate this PSBT file, and then sign it in the offline node and then broadcast it into the online node.
But im using an old wallet, so first I need to migrate the wallet, so it gets converted, since to do the PSBT thing you need the descriptors of the addresses, this new wallet format that contains this information. So im assuming "File->Migrate Wallet" will convert the 2013 wallet im using (not sure exactly version was used to create this file, but around 2013) into the new format (and hopefully, it does not screw up your wallet.dat file during this migration, I would like to know how to check if the migration is successful btw) and then I can use PSBT files with this wallet, but I still need to create a watch-only wallet for this format.
Could you please check that this is correct?
Prepare the two laptops
Laptop 2 (offline signer):
Physically remove WiFi and Bluetooth radios if possible. Physically disconnect any network cable. Once powered up into Debian, run: rfkill block all.
Copy over Knots via USB after verifying the signatures.
Create a private wallet directory (permissions 700), e.g. ~/knots_wallets/legacy/, and put a copy of wallet.dat inside as wallet.dat.
Laptop 1 (online full node):
Run Knots as a full, non-pruned node (already done – just finish the IBD).
You’ll import a watch-only wallet here later.
Safest way to load and migrate the old wallet (offline only)
Knots should be able to open old Berkeley DB wallets as “legacy” wallets. The modern standard is a descriptor wallet. Migrating is one-way, which should be fine here since we are ensuring that we have backups.
On Laptop 2 (offline):
1. Start Knots with your legacy wallet (GUI: “Open wallet” and point at the folder, or CLI with -walletdir pointing to ~/knots_wallets).
2. Take another fresh backup from Knots (“Backup wallet”) so you have a post-open snapshot (just being paranoid here).
3. Upgrade to descriptor (this might be labeled as “Migrate wallet” in the GUI; via RPC it’s upgradewallet). This creates internal descriptors for your keys/addresses. Note that I have not done this myself, so I am relying on various search results (there is some discrepency on the label – maybe due to different Knots/Core versions). Let me know if you can’t find anything that seems relevant here, and I’ll do some more digging.
4. After upgrade, export public descriptors (GUI export if present, or RPC):
listdescriptors false > exports public (no private) descriptors, including active and internal (change) ones, with useful timestamps.
Save those descriptors to a text file on a clean USB (this file is safe to move – no secrets if you used false for listdescriptors).
Build the online watch-only wallet
On Laptop 1 (online):
1. Create a new empty wallet (GUI: “Create wallet” > disable private keys / “watch-only”).
2. Import the public descriptors you exported from offline:
GUI import (if present), or RPC importdescriptors with the JSON from your file.
Make sure the active, internal, range (for HD paths), and timestamp fields are preserved so Knots rescans correctly.
3. Let it rescan the chain (can take a while). When done, balances and UTXOs should show as watch-only.
Sanity check:
On the offline wallet, generate a receive address and write it down.
On the online watch-only wallet, derive/show a receive address. It should match. (Matching here proves the descriptors line up.)
PSBT flow
Create (online):
In the online watch-only wallet, enable Coin Control. Pick the UTXOs, set outputs, and choose “Create PSBT” (GUI) or walletcreatefundedpsbt (RPC). Save the .psbt to USB.
Sign (offline):
On the offline wallet, open/sign the PSBT (GUI: “Load PSBT” > “Sign”; RPC: walletprocesspsbt). Save the partially or fully signed PSBT back to USB.
Broadcast (online):
On the online node, Finalize & Broadcast (GUI) or finalizepsbt then sendrawtransaction with the hex.
Verify the txid and watch it confirm.
These instructions I think were generated with the help of AI by someone. I have not tried this yet, but first of all, you are supposed to use "File->Migrate Wallet". This gives you the new wallet.dat file (not sure if it overwrites it??) and then, you can proceed to export the descriptors data from the file, so you can import it into the watch-only wallet on your online laptop, which I just created.
The problem I see is... okay, why isn't there in the GUI, something to export this into a .json file, so you can import this file in the watch-only wallet, instead of having to copy-paste the output it gives on the console, and then apparently having to manually modify things because they don't meet the required format that it's expected with the import function?
Because apparently this is what is going on:
When you want to create the watch-only wallet, there is an option in the GUI to create it (by disabling the private keys, and enabling the descriptor wallet option to be able to use PSBT easier method) but the thing is.. okay great, they bothered to add this in the GUI, but then what, you've got this empty wallet, and there are no options in the GUI to import the stuff you need to actually use a watch-only wallet. So I had to look it up and see how it's done with the console. I found that guide above. This is the first thing I would complain about, add some export/import option on the GUI, because at least im not seeing anything.
But then there's this thing going on if you do with the console. Basically you have to go into your offline laptop, and generate a .json file, which you will be importing in the watch-only wallet on the online computer. Once again, no GUI option to do this, so I had to look it up and found out you have to use this:
listdescriptors false > exports public (no private) descriptors, including active and internal (change) ones, with useful timestamps.
So this lists the stuff you need, but you have to copy-paste this stuff in the right way. Why is there no way to export a .json file with the correct format so you can easily import this in the watch-only wallet? This would improve this workflow a lot. But what we have now, it is what it is. So my question is, what is exactly going on that needs to be modified so the format is correct to import it into the watch-only wallet? Because it appears the output from
listdescriptors false will not work if you simply copy paste it into a .json file. See this:
From the offline box, you should have gotten something like:
{
"wallet_name": "cold_migrated",
"descriptors": [
{
"desc": "wpkh([abcd1234/84h/0h/0h]xpub.../0/*)#u5t4kl9d",
"active": true,
"timestamp": 1388534400,
"range": [0, 999],
"internal": false
},
{
"desc": "wpkh([abcd1234/84h/0h/0h]xpub.../1/*)#p8d0yq56",
"active": true,
"timestamp": 1388534400,
"range": [0, 999],
"internal": true
}
]
}
The
importdescriptors RPC expects an array of objects with just the needed fields:
[
{
"desc": "wpkh([abcd1234/84h/0h/0h]xpub.../0/*)#u5t4kl9d",
"active": true,
"internal": false,
"timestamp": 1388534400,
"range": [0, 999],
"label": "external"
},
{
"desc": "wpkh([abcd1234/84h/0h/0h]xpub.../1/*)#p8d0yq56",
"active": true,
"internal": true,
"timestamp": 1388534400,
"range": [0, 999],
"label": "change"
}
]
So apparently, I would need to remove
"{
"wallet_name": "cold_migrated",
"descriptors": "
And copy-paste only what is cointained inside "[.....]"
But then, there's also a difference in
"internal": false / "internal": true
that is seen in the output, but that is not seen in the expected format to import it, which also has this
"label": "external" / "label": "change"
which is not seen in the output... so what im supposed to do there? This would already worry the end user, which would think something may go wrong during this import/export workflow, let alone if you need to manually go address by address fixing things to match the expected import format, even tho im not sure this information is correct, so im asking here what's going on with this, and what would be the best way to finally get this done. I wanted to try this with testnet coins first, but I would need to download Bitcoin Core from 10 years ago, generate a new wallet, get some coins, open this wallet on the new Bitcoin version (im using Knots 28 right now) then proceed to Migrate the wallet, see if it works, and then do the stuff seen above, but I do not want to download and validate the blockchain again because it took forever, and it will probably be slower on an older version, so hopefully I can get some advice here. And im also reporting that this whole workflow needs to be polished, because unless im doing something wrong, this seems rather convoluted to do a simple import/export action, but for now, let's see if I could get this one with what we have.