|
| 1 | +:scrollbar: |
| 2 | +:data-uri: |
| 3 | +:toc2: |
| 4 | +:linkattrs: |
| 5 | + |
| 6 | += P2TR End-to-End Tutorial |
| 7 | + |
| 8 | +:numbered: |
| 9 | + |
| 10 | +This tutorial is inspired from the link:https://learnmeabitcoin.com/technical/upgrades/taproot/#example-3-script-path-spend-signature[script-path-spend-signature] example of the _learnmeabitcoin_ tutorial. |
| 11 | + |
| 12 | +Execute in Bitcoin Core `regtest` mode. |
| 13 | + |
| 14 | +== Pre-reqs |
| 15 | + |
| 16 | +=== Bitcoin Core |
| 17 | + |
| 18 | +TO-DO |
| 19 | + |
| 20 | +=== Shell Environment |
| 21 | + |
| 22 | +. *b-reg* command line alias: |
| 23 | ++ |
| 24 | +Configure an alias to the `bitcoin-cli` command that connects to your customized bitcoin-core node running in `regtest` mode. |
| 25 | +. *jq*: ensure json parsing utility is installed and available via your $PATH. |
| 26 | +. *awk* : standard utility for all Linux distros (often packaged as `gawk`). |
| 27 | + |
| 28 | +=== Bitcoin Core Wallet |
| 29 | + |
| 30 | +This tutorial assumes that a bitcoin core wallet is available. |
| 31 | +For example, the following would be sufficient: |
| 32 | + |
| 33 | +----- |
| 34 | +$ export W_NAME=regtest \ |
| 35 | + && export WPASS=regtest |
| 36 | +
|
| 37 | +$ b-reg -named createwallet \ |
| 38 | + wallet_name=$W_NAME \ |
| 39 | + descriptors=true \ |
| 40 | + passphrase="$WPASS" \ |
| 41 | + load_on_startup=true |
| 42 | +----- |
| 43 | + |
| 44 | +== Fund P2TR UTXO |
| 45 | + |
| 46 | +. View (hard-coded) tapscript used in single leaf taptree: |
| 47 | ++ |
| 48 | +----- |
| 49 | +$ b-reg decodescript 206d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0ac | jq -r '.asm' |
| 50 | +
|
| 51 | +6d4ddc0e47d2e8f82cbe2fc2d0d749e7bd3338112cecdc76d8f831ae6620dbe0 OP_CHECKSIG |
| 52 | +----- |
| 53 | ++ |
| 54 | +NOTE: This script includes a 32-byte x-only public key. |
| 55 | +Subsequently, it is not of standard type P2PK. |
| 56 | +As a standalone script, this script would be considered _non-standard_. |
| 57 | +However, as a tapleaf script, it is considered _standard_. |
| 58 | +Tapscript relaxes many script standardness rules. |
| 59 | + |
| 60 | +. Generate a P2TR scripPubKey and address given a taptree as defined in link:https://learnmeabitcoin.com/technical/upgrades/taproot/#example-3-script-path-spend-signature[learnmeabitcoin tutorial] : |
| 61 | ++ |
| 62 | +----- |
| 63 | +$ export BITCOIN_ADDRESS_INFO=$( cargo run --example p2tr_construction ) \ |
| 64 | + && echo $BITCOIN_ADDRESS_INFO | jq -r . |
| 65 | +
|
| 66 | +$ export BITCOIN_NETWORK=regtest \ |
| 67 | + && export P2TR_ADDR=$( echo $BITCOIN_ADDRESS_INFO | jq -r '.bech32m_address' ) \ |
| 68 | + && export FUNDING_SCRIPT_PUBKEY=$( echo $BITCOIN_ADDRESS_INFO | jq -r '.script_pubkey_hex' ) \ |
| 69 | + && echo -en "$P2TR_ADDR\n$FUNDING_SCRIPT_PUBKEY\n" |
| 70 | +----- |
| 71 | ++ |
| 72 | +NOTE: In `regtest`, you can expect a P2TR address that starts with: `bcrt1q` . |
| 73 | + |
| 74 | +. fund this P2TR address with the coinbase reward of a newly generated block: |
| 75 | ++ |
| 76 | +----- |
| 77 | +$ export COINBASE_REWARD_TX_ID=$( b-reg -named generatetoaddress 1 $P2TR_ADDR 1 | jq -r '.[]' ) \ |
| 78 | + && echo $COINBASE_REWARD_TX_ID |
| 79 | +----- |
| 80 | ++ |
| 81 | +NOTE: Sometimes Bitcoin Core does not immediately respond. If so, wait a few seconds and try the above command again. |
| 82 | + |
| 83 | +. view summary of all txs that have funded P2TR address |
| 84 | ++ |
| 85 | +----- |
| 86 | +$ export P2TR_DESC=$( b-reg getdescriptorinfo "addr($P2TR_ADDR)" | jq -r '.descriptor' ) \ |
| 87 | + && echo $P2TR_DESC |
| 88 | +$ b-reg scantxoutset start '[{"desc": "'''$P2TR_DESC'''"}]' |
| 89 | +----- |
| 90 | + |
| 91 | +. grab txid of first tx with unspent funds: |
| 92 | ++ |
| 93 | +----- |
| 94 | +$ export FUNDING_TX_ID=$( b-reg scantxoutset start '[{"desc": "'''$P2TR_DESC'''"}]' | jq -r '.unspents[0].txid' ) \ |
| 95 | + && echo $FUNDING_TX_ID |
| 96 | +----- |
| 97 | + |
| 98 | +. Set FUNDING_UTXO_INDEX env var (used later to correctly identify funding UTXO when generating the spending tx) |
| 99 | ++ |
| 100 | +----- |
| 101 | +$ export FUNDING_UTXO_INDEX=0 |
| 102 | +----- |
| 103 | + |
| 104 | +. view details of funding UTXO to the P2TR address: |
| 105 | ++ |
| 106 | +----- |
| 107 | +$ export FUNDING_UTXO=$( b-reg getrawtransaction $FUNDING_TX_ID 1 | jq -r '.vout['''$FUNDING_UTXO_INDEX''']' ) \ |
| 108 | + && echo $FUNDING_UTXO | jq -r . |
| 109 | +----- |
| 110 | + |
| 111 | +== Spend P2TR UTXO |
| 112 | + |
| 113 | + |
| 114 | +. Determine value (in sats) of funding utxo: |
| 115 | ++ |
| 116 | +----- |
| 117 | +$ export FUNDING_UTXO_AMOUNT_SATS=$(echo $FUNDING_UTXO | jq -r '.value' | awk '{printf "%.0f", $1 * 100000000}') \ |
| 118 | + && echo $FUNDING_UTXO_AMOUNT_SATS |
| 119 | +----- |
| 120 | + |
| 121 | +. Referencing the funding tx (via $FUNDING_TX_ID and $FUNDING_UTXO_INDEX), create the spending tx: |
| 122 | ++ |
| 123 | +----- |
| 124 | +$ export RAW_P2TR_SPEND_TX=$( cargo run --example p2tr_spend | jq -r '.tx_hex' ) \ |
| 125 | + && echo $RAW_P2TR_SPEND_TX |
| 126 | +----- |
| 127 | + |
| 128 | +. Inspect the spending tx: |
| 129 | ++ |
| 130 | +----- |
| 131 | +$ b-reg decoderawtransaction $RAW_P2TR_SPEND_TX |
| 132 | +----- |
| 133 | + |
| 134 | +. Test standardness of the spending tx by sending to local mempool of p2tr enabled Bitcoin Core: |
| 135 | + |
| 136 | +.. Generate additional blocks. |
| 137 | ++ |
| 138 | +This is necessary if you have only previously generated 1 block in your bitcoin core. |
| 139 | ++ |
| 140 | +----- |
| 141 | +$ b-reg -generate 110 |
| 142 | +----- |
| 143 | ++ |
| 144 | +Otherwise, you may see an error from bitcoin core such as the following: |
| 145 | ++ |
| 146 | +_bad-txns-premature-spend-of-coinbase, tried to spend coinbase at depth 1_ |
| 147 | + |
| 148 | +.. Execute: |
| 149 | ++ |
| 150 | +----- |
| 151 | +$ b-reg testmempoolaccept '["'''$RAW_P2TR_SPEND_TX'''"]' |
| 152 | +----- |
| 153 | + |
| 154 | +. Submit tx: |
| 155 | ++ |
| 156 | +----- |
| 157 | +$ export P2TR_SPENDING_TX_ID=$( b-reg sendrawtransaction $RAW_P2TR_SPEND_TX ) \ |
| 158 | + && echo $P2TR_SPENDING_TX_ID |
| 159 | +----- |
| 160 | ++ |
| 161 | +NOTE: Should return same tx id as was included in $RAW_P2TR_SPEND_TX |
| 162 | + |
| 163 | +== Mine P2TR Spend TX |
| 164 | + |
| 165 | +. View tx in mempool: |
| 166 | ++ |
| 167 | +----- |
| 168 | +$ b-reg getrawtransaction $P2TR_SPENDING_TX_ID 1 |
| 169 | +----- |
| 170 | ++ |
| 171 | +NOTE: There will not yet be a field `blockhash` in the response. |
| 172 | + |
| 173 | +. Mine 1 block: |
| 174 | ++ |
| 175 | +----- |
| 176 | +$ b-reg -generate 1 |
| 177 | +----- |
| 178 | + |
| 179 | +. Obtain `blockhash` field of mined tx: |
| 180 | ++ |
| 181 | +----- |
| 182 | +$ export BLOCK_HASH=$( b-reg getrawtransaction $P2TR_SPENDING_TX_ID 1 | jq -r '.blockhash' ) \ |
| 183 | + && echo $BLOCK_HASH |
| 184 | +----- |
| 185 | + |
| 186 | +. View tx in block: |
| 187 | ++ |
| 188 | +----- |
| 189 | +$ b-reg getblock $BLOCK_HASH | jq -r .tx |
| 190 | +----- |
| 191 | + |
| 192 | +== TO-DO |
0 commit comments