Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: sathio on February 12, 2021, 08:32:01 AM



Title: import multisig wallet into bitcoin core, but Vpub keys are not valid. how to?
Post by: sathio on February 12, 2021, 08:32:01 AM
I'm trying to import an HD multisig wallet created with Electrum into Bitcoin core v0.21.0.0.

I managed to do so with the fantastic cryptoadvance.specter server, but I also would like to import it using the standard bitcoin-cli commands.

This is what I managed to do so far, and it only works if I convert the pub keys Vpub Multi-signature P2WSH to tpub P2PKH, so for example:

Code:
Vpub5fRxfoprsHS9Vnhq1grZcJrWSRmSeBZbLCbnTJcvSDXr3xoBurx8MUt8UmHCsTVPXqk1rNpgt3X3KAvcJzCZvwn9yQymrWhwMJpEYysLqQV
becomes

Code:
tpubD8a2g9FwJxvC3c7YBvwvQL35Ph7jJTN4PnarTPCJAND6HGXSizk4ew1JxWKgqLXZuZSZ6KXZTFfgem2ar1itGNUywE1XJTY9azG4WBr25hn
then I can run this program and it seems to be working fine, unless it's not because the resulting addresses are very different. (the wallet created with Specter matches perfectly the one in Electrum, it finds the correct transactions as well)

Code:
#!/bin/sh

wallet=$1
pub1=$2
pub2=$3

echo "Making wallet '${wallet}' from ${pub1} ${pub2}"

rawdescriptor="wsh(sortedmulti(2,${pub1}/*,${pub2}/*))"
descriptor=$(bitcoin-cli getdescriptorinfo $rawdescriptor | jq -r '.descriptor')
bitcoin-cli deriveaddresses  ${descriptor} "[0,0]"

bitcoin-cli createwallet $wallet true
bitcoin-cli -rpcwallet=$1  importmulti '[{"desc": "'$descriptor'", "internal": false, "range": [0, 1000], "timestamp": 1609459200, "keypool": true, "watchonly": true, "label": "lol"}]' '{ "rescan": true}'
# bitcoin-cli -rpcwallet=$1 rescanblockchain

I can't use the Vpub keys because bitcoin-cli (v0.21.0.0) throws this message:

Code:
key 'vpub5UXsYa6RJKsn5DYT52PanEWhidjBRpt11vx7Y3MP4ShSRnEH9TZrGN2Cg4KjK2GVJNg2ynpZzq8YC1Jr1m3cnTfV8wsNT7EwTaYMy4PCDAg' is not valid.

At this stage i’m only interested into a watch only wallet, so i don’t need to use private keys.

Also, I'm in testnet and I have testnet=1 on my bitcoin.conf

I've tried reading as much as I could but I think i hit a wall now and I don't know how to continue. Any help would be greatly appreciated


Title: Re: import multisig wallet into bitcoin core, but Vpub keys are not valid. how to?
Post by: igor72 on February 12, 2021, 04:16:16 PM
I'm trying to import an HD multisig wallet created with Electrum into Bitcoin core
AFAIK, it's impossible.


Title: Re: import multisig wallet into bitcoin core, but Vpub keys are not valid. how to?
Post by: NotATether on February 12, 2021, 04:42:01 PM
This is what I managed to do so far, and it only works if I convert the pub keys Vpub Multi-signature P2WSH to tpub P2PKH, so for example:

Code:
Vpub5fRxfoprsHS9Vnhq1grZcJrWSRmSeBZbLCbnTJcvSDXr3xoBurx8MUt8UmHCsTVPXqk1rNpgt3X3KAvcJzCZvwn9yQymrWhwMJpEYysLqQV
becomes

Code:
tpubD8a2g9FwJxvC3c7YBvwvQL35Ph7jJTN4PnarTPCJAND6HGXSizk4ew1JxWKgqLXZuZSZ6KXZTFfgem2ar1itGNUywE1XJTY9azG4WBr25hn

You can't convert a P2WSH address into a P2PKH address like that unless you use the same private key to derive both, which is impossible in the case of multisig since there are many private keys (and that there's no multisig P2PKH).

For watch-only purposes shouldn't it be enough to just importaddress the address in the multisig wallet whose balance you want to see?


Title: Re: import multisig wallet into bitcoin core, but Vpub keys are not valid. how to?
Post by: HCP on February 16, 2021, 12:33:54 AM
I can't use the Vpub keys because bitcoin-cli (v0.21.0.0) throws this message:

Code:
key 'vpub5UXsYa6RJKsn5DYT52PanEWhidjBRpt11vx7Y3MP4ShSRnEH9TZrGN2Cg4KjK2GVJNg2ynpZzq8YC1Jr1m3cnTfV8wsNT7EwTaYMy4PCDAg' is not valid.
I just did a quick test and it seems to work OK when using Legacy Electrum MultiSig wallets (see example below)... However, when attempting to use "Vpubs" from an Electrum SegWit multisig... I also get the "key 'Vpub5g.....FA5' is not valid (code -5)" error ??? :-\

Seems like Bitcoin Core is not recognising the "Vpub" as being a valid key for whatever reason? ???




A couple of points to note for anyone following along at home:

1. the "child path" you will need to use in your descriptor is: /0/*
2. If you don't want to generate 1000 addresses (the default 'range' setting), then include a "range" in the descriptor
3. You will need a "descriptor checksum" to use importmulti (use the getdescriptorinfo call to generate the checksum for your descriptor)


So, I created 3 "standard" wallets in Electrum Testnet... and then created a 2-of-3 MultiSig... this MultiSig uses the three tpubs:
Code:
tpubD6NzVbkrYhZ4XgEBrr2NwxfyEehaHfm83BqX79y1QMs5ewSkpyQgSFQ9vSfEqiDeHuNU55gABbDMDtfyfVBq6pBgeJmSUxisnqKG89Mgtu3
tpubD6NzVbkrYhZ4XkeJ7kHEo6Bu8fFRM7b5rsYCBBVFesJRNcxuMXhqDCPKiiWxke7mrRDrQAghGsn3MH3xQYFEPbAsutnyMVo835YeToYVB2R
tpubD6NzVbkrYhZ4WP2J1AQDCCzzAJFtbxwrwNAPdGrj7f8fpEKC1yQC3Dio9EvMGF6AGY6oN46Bbea6pgV1hXuTGegPcy5mMY2eUy8gwnesrsF

https://talkimg.com/images/2023/11/15/zIWxJ.png

https://talkimg.com/images/2023/11/15/zIqPC.png

https://talkimg.com/images/2023/11/15/zI0jb.png


This wallet generated the following addresses:
https://talkimg.com/images/2023/11/15/zIlOv.png



So... our "descriptor" will be:
Code:
"sh(sortedmulti(2,tpubD6NzVbkrYhZ4XgEBrr2NwxfyEehaHfm83BqX79y1QMs5ewSkpyQgSFQ9vSfEqiDeHuNU55gABbDMDtfyfVBq6pBgeJmSUxisnqKG89Mgtu3/0/*,tpubD6NzVbkrYhZ4XkeJ7kHEo6Bu8fFRM7b5rsYCBBVFesJRNcxuMXhqDCPKiiWxke7mrRDrQAghGsn3MH3xQYFEPbAsutnyMVo835YeToYVB2R/0/*,tpubD6NzVbkrYhZ4WP2J1AQDCCzzAJFtbxwrwNAPdGrj7f8fpEKC1yQC3Dio9EvMGF6AGY6oN46Bbea6pgV1hXuTGegPcy5mMY2eUy8gwnesrsF/0/*))"
NOTE the /0/* child paths


Ok, so we have our descriptor, now we need the checksum:
Code:
getdescriptorinfo DESCRIPTOR_STRING_GOES_HERE

Code:
getdescriptorinfo "sh(sortedmulti(2,tpubD6NzVbkrYhZ4XgEBrr2NwxfyEehaHfm83BqX79y1QMs5ewSkpyQgSFQ9vSfEqiDeHuNU55gABbDMDtfyfVBq6pBgeJmSUxisnqKG89Mgtu3/0/*,tpubD6NzVbkrYhZ4XkeJ7kHEo6Bu8fFRM7b5rsYCBBVFesJRNcxuMXhqDCPKiiWxke7mrRDrQAghGsn3MH3xQYFEPbAsutnyMVo835YeToYVB2R/0/*,tpubD6NzVbkrYhZ4WP2J1AQDCCzzAJFtbxwrwNAPdGrj7f8fpEKC1yQC3Dio9EvMGF6AGY6oN46Bbea6pgV1hXuTGegPcy5mMY2eUy8gwnesrsF/0/*))"


This should generate something like:
Code:
{
  "descriptor": "sh(sortedmulti(2,tpubD6NzVbkrYhZ4XgEBrr2NwxfyEehaHfm83BqX79y1QMs5ewSkpyQgSFQ9vSfEqiDeHuNU55gABbDMDtfyfVBq6pBgeJmSUxisnqKG89Mgtu3/0/*,tpubD6NzVbkrYhZ4XkeJ7kHEo6Bu8fFRM7b5rsYCBBVFesJRNcxuMXhqDCPKiiWxke7mrRDrQAghGsn3MH3xQYFEPbAsutnyMVo835YeToYVB2R/0/*,tpubD6NzVbkrYhZ4WP2J1AQDCCzzAJFtbxwrwNAPdGrj7f8fpEKC1yQC3Dio9EvMGF6AGY6oN46Bbea6pgV1hXuTGegPcy5mMY2eUy8gwnesrsF/0/*))#7mwe6979",
  "checksum": "7mwe6979",
  "isrange": true,
  "issolvable": true,
  "hasprivatekeys": false
}
And we can see that it has handily calculated the checksum (7mwe6979)... and also appended it for us! ;)


So... our "descriptor#checksum" string is now:
Code:
"sh(sortedmulti(2,tpubD6NzVbkrYhZ4XgEBrr2NwxfyEehaHfm83BqX79y1QMs5ewSkpyQgSFQ9vSfEqiDeHuNU55gABbDMDtfyfVBq6pBgeJmSUxisnqKG89Mgtu3/0/*,tpubD6NzVbkrYhZ4XkeJ7kHEo6Bu8fFRM7b5rsYCBBVFesJRNcxuMXhqDCPKiiWxke7mrRDrQAghGsn3MH3xQYFEPbAsutnyMVo835YeToYVB2R/0/*,tpubD6NzVbkrYhZ4WP2J1AQDCCzzAJFtbxwrwNAPdGrj7f8fpEKC1yQC3Dio9EvMGF6AGY6oN46Bbea6pgV1hXuTGegPcy5mMY2eUy8gwnesrsF/0/*))#7mwe6979"



And now we can just use importmulti:
Code:
importmulti '[{"desc":"sh(sortedmulti(2,tpubD6NzVbkrYhZ4XgEBrr2NwxfyEehaHfm83BqX79y1QMs5ewSkpyQgSFQ9vSfEqiDeHuNU55gABbDMDtfyfVBq6pBgeJmSUxisnqKG89Mgtu3/0/*,tpubD6NzVbkrYhZ4XkeJ7kHEo6Bu8fFRM7b5rsYCBBVFesJRNcxuMXhqDCPKiiWxke7mrRDrQAghGsn3MH3xQYFEPbAsutnyMVo835YeToYVB2R/0/*,tpubD6NzVbkrYhZ4WP2J1AQDCCzzAJFtbxwrwNAPdGrj7f8fpEKC1yQC3Dio9EvMGF6AGY6oN46Bbea6pgV1hXuTGegPcy5mMY2eUy8gwnesrsF/0/*))#7mwe6979","range":10,"timestamp":"now"}]'

Important things to note for this example... we use sortedmulti() as the keys need to be order lexographically... I specified the "range" as 10 for brevity... if you leave the range out, Bitcoin Core will default to generating 1000 addresses! :o and you'll understand why we don't want 1000 for our test in a bit ;)

"timestamp":"now" basically says, I've only just created these keys, so don't bother rescanning... again, this was to save time testing purposes... so the result won't actually show the transaction history for these addresses... (for the record, I actually did a rescanblockchain 1905760 to scan from block 1905760 and it found the appropriate transactions ;))

Anyway... this command gives:
Code:

[
  {
    "success": true,
    "warnings": [
      "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."
    ]
  }
]

GREAT SUCCESS! and looking in "Receiving Addresses" in Bitcoin Core (Testnet):
https://talkimg.com/images/2023/11/15/zs2CH.png

We have the same addresses as generated by Electrum... (just displayed in a different order! Now do you understand why we set the range to  10 and not 1000??!? ;) :P)