8

If the Bitcoin Core Wallet Migration Tool is supposed to be creating descriptors for sparse keys (as it's supposed to support pre deterministic wallets), then why doesn't Bitcoin Core allow using importprivkey on a descriptor wallet?

I'm trying to, and it's telling error code -4 (type of wallet does not support this command).

How can I import a private key to a descriptor wallet?

0

3 Answers 3

10

The migration tool has not been implemented yet, and it is not for manually importing keys. Rather it takes an existing wallet and migrates everything in that wallet.

As the error message says, descriptor wallets do not support importprivkey. You will have to use importdescriptors with the private key you want to import as part of the proper descriptor.

For example, if you wanted to import the P2WPKH address for a private key, you would make a descriptor of the form wpkh(<privkey>). Then use getdescriptorinfo to get the checksum and create wpkh(<privkey>)#<checksum>, and then use importdescriptors to import that descriptor.

15
  • getdescriptorinfo would just tell wpkh(): Uncompressed keys are not allowed
    – Mercedes
    Commented Oct 1, 2022 at 13:21
  • You shouldn't use uncompressed keys in wpkh; they aren't valid. Commented Oct 1, 2022 at 13:57
  • @PieterWuille understood, thanks, now I got checksum.
    – Mercedes
    Commented Oct 1, 2022 at 14:17
  • Importing the descriptor would then answer error code -4 Cannot import descriptor without private keys to a wallet with private keys enabled, but the descriptor was created out of a dumped privkey and the wallet is an newly created descriptors wallet
    – Mercedes
    Commented Oct 1, 2022 at 14:44
  • 1
    The checksum it reports is the checksum for the descriptor you provided. The descriptor it returns is a full, normalized, descriptor including the checksum (for that normalized descriptor). You can either use your input + checksum, or you can use descriptor. The latter will miss private key information if the former included any. Commented Dec 21, 2022 at 19:48
5

To give a bit more context to Ava Chow's answer: the reason why this isn't any easier is that the concept of "importing a private key" is an insufficient method for describing what a wallet should do, and the wrong way to think about wallets in the first place. While it is possible to convert wallets with keys imported to them to approximately equivalent descriptor wallets, this does not mean that it's the best way when importing things. Descriptors and descriptor wallets allow you to be precise about what you want to import, and the importdescriptors RPC lets you do that.

In more detail, this is roughly the philosophy behind the two types of wallets supported by Bitcoin Core:

  • Legacy wallets: A legacy wallet is a collection of private keys, and loosely structured additional information such as scripts and addresses. Any output which can be spent or observed with those keys/scripts/addresses is considered to "belong" to the wallet. If you import a new key to a wallet, this immediately results in treating payments to the P2PK, P2PKH, P2WPKH, P2SH-P2WPKH, and possibly more, addresses derived from that key to be watched. This is inefficient, hard to describe and reason about, and just doesn't scale well with new wallet constructions being added (e.g. P2TR), and even harder to deal with when multisig across devices or participants is added.
  • Descriptor wallets. In a descriptor wallet, the outputs considered part of the wallet can be described exactly using a simple "language" which contains all metadata about how the keys are used. If you want just P2PKH addresses derived from a key, you can say that. If you want P2SH-wrapped P2WSH multisig across multiple devices you can say that too, and it will work exactly the same.

In short: the old model of how we thought of wallets wasn't manageable anymore, and "importing a key" only made sense in that kind of thinking. In the new model, you don't import keys, you import a description of exactly what you want the wallet to do.

7
  • I think I understand all of your point, but I'm still not sure why importprivkey isn't reasonable high level sugar for a larger sequence of commands that import one descriptor wrapping one single isolated key. Isolated keys being wrong doesn't destroy existing isolated keys. I'd suppose it's easier to detect legacy behavior and warn against it by accepting importprivkeys than by having users use the new toolset in a conceptually wrong way, unable to warn of legacy behavior until importdescriptors is seen importing a single isolated key.
    – Mercedes
    Commented Nov 14, 2022 at 22:47
  • 1
    The question is just: what way of wrapping the private key? P2PKH? P2WPKH? P2SH-P2WPKH? P2SH-P2WSH-P2PKH? P2TR? There are many ways of constructing a scriptPubKey whose spendability depends on access to a given private key. The practice of watching all of them just doesn't scale. Descriptors allow one to be explicit about all of this. Commented Nov 14, 2022 at 23:28
  • I take your word for it doesn't scale. Maybe some link can be added explaining further.
    – Mercedes
    Commented Nov 15, 2022 at 16:39
  • 1
    Also worth a read: achow101.com/2020/10/…. Commented Dec 19, 2022 at 22:10
  • @Mercedes You don't need to take my word for it; I gave the explanation above: there isn't just one way of turning a private key into an address. Descriptors add the necessary metadata (whether that means just fixing whether it's P2PKH or P2SH-P2WPKH or whatever, or including other keys if it's multisig, or ...). Commented Dec 19, 2022 at 22:38
-1

Here are example commands which can be used with bitcoin-cli to import wallet using WIF into new wallet:

wallet_name=mywallet
wif=5MyWifPass
bitcoin-cli -named createwallet wallet_name=${wallet_name} descriptors=true disable_private_keys=true
bitcoin-cli getdescriptorinfo "pkh(${wif})" # Legacy: pkh(), for P2SH-SegWit use sh(wpkh())
descriptor=$(bitcoin-cli getdescriptorinfo "pkh(${wif})" | jq -r .descriptor)
bitcoin-cli -rpcwallet=${wallet_name} importdescriptors '[{ "desc": "'${descriptor}'", "internal": false, "timestamp":"now", "label": "'${wallet_name}'"}]'
bitcoin-cli -rpcwallet=${wallet_name} listdescriptors
bitcoin-cli -rpcwallet=${wallet_name} listreceivedbyaddress 1 true

The above needs to be run in shell.

It assumes you've rpcuser and rpcpassword setup in your ~/.bitcoin/bitcoin.conf, otherwise add -rpcuser=youruser -rpcpassword=yourpass to the command.

Related:

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.