3

My goal

Learn how to send an imported tr(wif) and wpkh() utxo in the same transaction.

What I've tried

I imported a WIF utxo containing a v1 segwit utxo.

bitcoin-cli importdescriptors '[{"desc":"tr(wifkey)#checksum", "timestamp":unixts}]'

I didn't know the checksum, but when importing I got an error that told me what the checksum should be, so I used that.

The balance showed up after import, I assume it was imported correctly.

Learned createrawtransaction, fundrawtransaction, signrawtransactionwithwallet are not acceptable for taproot. This was resulting in "Witness program was passed an empty witness".

It seems psbt commands are more appropriate. However, I couldn't figure out how to successfully sign with cli. I kept getting "complete": false returned.

I then tried bitcoin-qt and attempted to sweep funds to an address as a test. I received this: fail signing

While using bitcoin-cli and running bitcoin-cli listunspent I see:

[
  {
    "txid": "TX_1",
    "vout": x,
    "address": "ADDR_1",
    "label": "xxx1",
    "scriptPubKey": "44_LEGNTH_HEX_STRING",
    "amount": xxxxxx.xxxxxx,
    "confirmations": xxx,
    "spendable": true,
    "solvable": true,
    "desc": "wpkh([FINGERPRINT/84'/0'/0'/0/0]KEY)#CHECKSUM1",
    "parent_descs": [
      "wpkh(xpub_key/84'/0'/0'/0/*)#CHECKSUM-parent"
    ],
    "safe": true
  },
  {
    "txid": "TX_2",
    "vout": xx,
    "address": "ADDR_2",
    "label": "xxx2",
    "scriptPubKey": "68_LENGTH_HEX_STRING",
    "amount": xxxxxx.xxxxxx,
    "confirmations": xxxx,
    "spendable": true,
    "solvable": true,
    "desc": "tr([FINGERPRINT2]KEY2)#CHECKSUM2",
    "parent_descs": [
      "tr(KEY2)#CHECKSUM2"
    ],
    "safe": true
  }
]

Output sanitized

Question

  • What are the methodical steps starting with an imported WIF/taproot utxo + wpkh utxo and creating a signed tx to send funds?
Antoine Poinsot
  • 8,334
  • 2
  • 17
  • 34
Michael Tidwell
  • 472
  • 2
  • 13
  • 1
    You need to use a descriptor wallet, and import the key as a taproot descriptor (if it's just a key path key, it would be tr(WIF), but scripts can also be included there). Further, you need to use PSBT RPCs; the old raw transacrion RPCs in general do not support taproot. – Pieter Wuille Jun 04 '23 at 11:32
  • I'm currently doing createpsbt then walletcreatefundedpsbt but not sure where to go from here. I've tried both walletprocesspsbt and finalizepsbt but they return the base64 encoding and "complete": false. I've tried utxoupdatepsbt but unsure what I would need to do since I've already successfully imported this into my wallet.

    What steps am I missing?

    – Michael Tidwell Jun 04 '23 at 21:51
  • It would be useful if you'd include the exact commands and output you're seeing in your question. If need be, you can try to recreate on regtest / signet / testnet. – Pieter Wuille Jun 04 '23 at 21:58
  • I tried to reproduce everything on regtest, but I keep getting "complete": true and no issues like what I'm seeing on mainnet.

    The main difference I see is when I do getaddressinfo on regtest it shows I'm using an hd key I believe via:

    "desc": "tr([e4b96d59/86'/1'/0'/0/0]d5de651411b49df50bc37a17620755ec019866332794cc3e73a6effbb766aa1c)#kh27dth2",

    on mainnet when I run getaddressinfo I see something similar minus the /86'/1'/0'/0/0.

    – Michael Tidwell Jun 04 '23 at 23:36
  • It would seem that the way you import things on mainnet and on regtest differs then. – Pieter Wuille Jun 04 '23 at 23:55
  • Yeah, I'm trying to reproduce, I did find another discrepancy though, "isrange": false, on mainnet but true on regtest. What does this mean? I get this after running the getdescriptorinfo command – Michael Tidwell Jun 05 '23 at 00:12
  • 1
    A tr(WIF) descriptor is not ranged, so that's clearly not what you're doing on regtest – Pieter Wuille Jun 05 '23 at 00:18
  • When looking at the output of getdescriptorinfo why would solvable be true but hasprivatekeys be false.

    After doing a non ranged tr(wif) import? Shouldn't they both be true?

    – Michael Tidwell Jun 05 '23 at 02:56
  • This is all impossible to say without knowing what your actual commands are. – Pieter Wuille Jun 05 '23 at 03:11
  • bitcoin-cli importdescriptors '[{"desc":"tr(WIF)", "timestamp":UNIXTIME}]'
  • bitcoin-cli listdescriptors
  • (grab the desc for the imported wif = "tr(hex)#CHECKSUM")

    1. bitcoin-cli getdescriptorinfo "DESC"
    – Michael Tidwell Jun 05 '23 at 03:22
  • listdescriptors will give descriptors without private key material (the "hex" you state is the public key); that's why it says hasprivatekeys false. But please update your question to reflect all information, with the commands you did, and the responses you get. It's very hard to discuss this via comments. – Pieter Wuille Jun 05 '23 at 03:27
  • so.. just working through this
    1. bitcoin-cli createpsbt '[{"txid":"TX_ASSOCIATED_WITH_WIF","vout":INDEX}]' '[{"BTC_ADDRESS":AMOUNT},{ "data": "WHAT_IS_SUPPOSED_TO_GO_HERE?"}]'

    I've been putting 00 for data maybe that is incorrect?

    – Michael Tidwell Jun 05 '23 at 03:37
  • Similarly for walletcreatefundedpsbt with the same json parameter. Not sure if 00 is ok. Or how to find out what to put for this. – Michael Tidwell Jun 05 '23 at 03:45
  • 2
    Whatever you want to go in an OP_RETURN goes there. But again, please update your question with whatever your question has now evolved to be – Pieter Wuille Jun 05 '23 at 11:30
  • In the future, especially if you don’t have answers yet, please edit instead of opening a new question. – Murch Jun 06 '23 at 02:38
  • @Murch thanks for the tip. I edited the original post with most up to date info. – Michael Tidwell Jun 06 '23 at 03:11
  • Wrong: "Further, you need to use PSBT RPCs; the old raw transacrion RPCs in general do not support taproot. – Pieter Wuille Jun 4 at 11:32" . As a matter of fact, Bitcoin Core v. 24 RPC commands like createrawtransaction and signrawtransactionwithwallet support Taproot (P2TR). Also, the goal could be acheived without using any PSBT-related RPC. – Greg Tonoski Jun 07 '23 at 12:35
  • There is the example of using the raw transaction RPC commands: https://bitcoin.stackexchange.com/a/117013/135945. – Greg Tonoski Jun 07 '23 at 12:42