I was curious and had it also on my long-term agenda to walk through the steps required to successfully import e.g. a Native Segwit derivation from a Bitcoin Core descriptor wallet (which usually contains descriptors for all main four address types) into an Electrum wallet.
I'm not entirely sure if my steps haven't been already documented somewhere in the forum. Anyway, you learn more when you do the steps on your own.
I created a sample test wallet as descriptor wallet with keys in my Bitcoin Core v28.0.0 node. The descriptors will be published here, so anybody can check and verify to get to the same result and/or do the walkthrough with their own sample wallet.
With
getnewaddress "" "bech32" in Bitcoin Core's console window, executed twice, I got the following two receive addresses of this brand new sample wallet, their full derivation path added as second column:
bc1qjvr5fjgccey8q6u88l9h382w6pj4n63wqy8qnf | | m/84h/0h/0h/0/0 |
bc1qkv0cysnqztsrfs296jtcsag85dcjdxu7nrn3yr | | m/84h/0h/0h/0/1 |
Important:If you do theses steps with a real funded wallet, do this in a safe computing environment. Boot Tails or another suitable Live Linux from trusty media storage, download only necessary software from their designated safe sources, verify it's genuine. I recommend to disconnect any network connection when you work with private keys or BIP32 master private keys.
It would be utterly stupid to execute the steps with your daily internet-shit machine whoes safety status you likely only can guess.
For obvious reasons, you should
NOT use any of my published descriptors for any wallet with real coins! Stealing bots will digest publicly available descriptors/private keys into their databases.
Here is the output of
listdescriptors true in the Bitcoin Core console (you can also do it on your command-line with
bitcoin-cli -rpcwallet=walletname listdescriptors true):
{
"wallet_name": "test_241231a",
"descriptors": [
{
"desc": "pkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/44h/0h/0h/0/*)#xdela9vv",
"timestamp": 1735682264,
"active": true,
"internal": false,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "pkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/44h/0h/0h/1/*)#heu7qsu5",
"timestamp": 1735682265,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "sh(wpkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/49h/0h/0h/0/*))#sx9dcfdz",
"timestamp": 1735682265,
"active": true,
"internal": false,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "sh(wpkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/49h/0h/0h/1/*))#k9dgryxk",
"timestamp": 1735682265,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "tr(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/86h/0h/0h/0/*)#k3vnmjz5",
"timestamp": 1735682265,
"active": true,
"internal": false,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "tr(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/86h/0h/0h/1/*)#89fjx8jv",
"timestamp": 1735682265,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "wpkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/84h/0h/0h/0/*)#hm3e6zds",
"timestamp": 1735682265,
"active": true,
"internal": false,
"range": [
0,
999
],
"next": 0,
"next_index": 0
},
{
"desc": "wpkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/84h/0h/0h/1/*)#x05c8hag",
"timestamp": 1735682265,
"active": true,
"internal": true,
"range": [
0,
999
],
"next": 0,
"next_index": 0
}
]
}
For Native Segwit the derivation path is m/84h/0h/0h/0/* for receiving addresses and m/84h/0h/0h/1/* for internal/change addresses. The relevant descriptors are:
wpkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/84h/0h/0h/0/*)#hm3e6zds
wpkh(xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM/84h/0h/0h/1/*)#x05c8hag
The
BIP32 Root Key in my example is
xprv9s21ZrQH143K3aNoaX2m4sAT3zYjcjsYwsiCXQw7VfrmhyeHS1dUK2qw4GcVPqkWcrXM1h5ttaz561yiTKYsMGLSBMhh6KPMKZPrSTBj7EM
and has to be entered in an offline copy of the iancoleman script (online version
https://iancoleman.io/bip39/, download and verify offline version from
https://github.com/iancoleman/bip39/releases/latest/):
Don't click on Generate or anything else when you start with a clean empty offline iancoleman script page! The first entry into the script is the copied xprv key into the box labeled BIP32 Root Key.
Scroll down a bit in the script to section Derivation Path and bring the tab BIP84 to the front (click on BIP84). In my example it should look like this:
We need what's labeled as
Account Extended Private Key in the iancoleman script, because Electrum uses the following derivation when you create a standard, aka Native Segwit wallet with the option "Use a master key":
m/0/* for receiving,
m/1/* for internal/change addresses. The
m for Electrum has to be the underlined part of the standard BIP84 derivation
m/84h/0h/0h/0/*, which is the mentioned Account Extended Private Key.
But we can't feed the Account Extended Private Key
xprv9z8Q3KxjwMBqjVSyboUx8seHNQ75NUWq8uSSXDmjjJktrW72mkw2AFjX3LVXCv2ojfVqCwnHaZVRRrFvR1M2P7Rbh5cthVJZz8fLEtpSDPW
as master key in Electrum, because with a
xprv key Electrum derives legacy addresses, those that start with
1..., as in the Electrum GUI at this step you don't have any option to specify a particular address type. Bummer?
We need the Account Extended Private Key in the
zprv form! Fortunately you can convert a
xprv to
zprv (or
yprv) and vice-versa.
Post edit:
See below post from nc50lc which shows how to do the conversion in the Electrum console! No additional Python or external commands needed which is great!
I checked in my reply to nc50lc's post that it works as suggested.I used few lines of Python code which I found here:
https://gist.github.com/openoms/4e8a527e4c9757162a53f2dc96e3d229Below code is already with the
xprv from my example and the resulting
zprv we need for Electrum:
import base58
x = 'xprv9z8Q3KxjwMBqjVSyboUx8seHNQ75NUWq8uSSXDmjjJktrW72mkw2AFjX3LVXCv2ojfVqCwnHaZVRRrFvR1M2P7Rbh5cthVJZz8fLEtpSDPW'
zp = b'\x04\xb2\x43\x0c'
base58.b58encode_check(zp + base58.b58decode_check(x)[4:]).decode('ascii')
# output: 'zprvAdnvefJaEiGoS5qDGX4CZ3qHiLPyFiVpy8Ut61ZWVKWexhjVH5G9QP3o5kQhCjLeYwjShtyQVtCXCRV3rQB3yanoRm1jsJwYXand24Ck8v3'
# xprv = b'\x04\x88\xad\xe4'
# yprv = b'\x04\x9d\x78\x78'
# zprv = b'\x04\xb2\x43\x0c'
# xpub = b'\x04\x88\xb2\x1e'
# ypub = b'\x04\x9d\x7c\xb2'
# zpub = b'\x04\xb2\x47\x46'
(I had Python3 and pip already installed, so for this solution you'd need that too. You have to install the base58 library with
pip install base58. I didn't do anything fancy, just executed python3 without further parameters and pasted the lines into the Python prompt, quick'n'dirty:
>>> import base58
>>> x = 'xprv9z8Q3KxjwMBqjVSyboUx8seHNQ75NUWq8uSSXDmjjJktrW72mkw2AFjX3LVXCv2ojfVqCwnHaZVRRrFvR1M2P7Rbh5cthVJZz8fLEtpSDPW'
>>> zp = b'\x04\xb2\x43\x0c'
>>> base58.b58encode_check(zp + base58.b58decode_check(x)[4:]).decode('ascii')
'zprvAdnvefJaEiGoS5qDGX4CZ3qHiLPyFiVpy8Ut61ZWVKWexhjVH5G9QP3o5kQhCjLeYwjShtyQVtCXCRV3rQB3yanoRm1jsJwYXand24Ck8v3'
>>>
Finally we can take this resulting
zprv master key to feed it into Electrum. Start Electrum, create new wallet, at "What kind of wallet do you want to create?" you select
Standard wallet and click Next, for Keystore you choose
Use a master key and click Next.
At "Create keystore from a master key" you paste the
zprv key from our little conversion, i.e. in my example I entered
zprvAdnvefJaEiGoS5qDGX4CZ3qHiLPyFiVpy8Ut61ZWVKWexhjVH5G9QP3o5kQhCjLeYwjShtyQVtCXCRV3rQB3yanoRm1jsJwYXand24Ck8v3
The resulting Electrum wallet now has the same addresses as the Bitcoin Core descriptor wallet. Mission accomplished, even when it's a bit fiddly. The first two receiving addresses are the same as taken from the Bitcoin Core wallet (you can check also that addresses match with what the iancoleman script lists.
bc1qjvr5fjgccey8q6u88l9h382w6pj4n63wqy8qnf | | m/84h/0h/0h/0/0 | | Electrum derivation: m/0/0 |
bc1qkv0cysnqztsrfs296jtcsag85dcjdxu7nrn3yr | | m/84h/0h/0h/0/1 | | Electrum derivation: m/0/1 |