Spend a Native Segwit P2WPKH UTXO
To follow along this tutorial
|
Let’s spend a native Segregated Witness P2WPKH output and create a new legacy P2PKH output.
Create a UTXO to spend from
const bitcoin = require('bitcoinjs-lib')
const { alice, bob } = require('./wallets.json')
const network = bitcoin.networks.regtest
sendtoaddress bcrt1qlwyzpu67l7s9gwv4gzuv4psypkxa4fx4ggs05g 1
gettransaction TX_ID
Find the output index (or vout) under |
Creating the transaction
Now let’s spend the UTXO with BitcoinJS.
const keyPairAlice1 = bitcoin.ECPair.fromWIF(alice[1].wif, network)
const keyPairBob1 = bitcoin.ECPair.fromWIF(bob[1].wif, network)
const p2pkhBob1 = bitcoin.payments.p2pkh({pubkey: keyPairBob1.publicKey, network})
console.log('P2PKH address:')
console.log(p2pkhBob1.address)
const txb = new bitcoin.TransactionBuilder(network)
In order to create our input we will have to provide the previous output script. We can get it by inspecting the funding transaction at
.const p2wpkhAlice1 = bitcoin.payments.p2wpkh({pubkey: keyPairAlice1.publicKey, network})
console.log('Previous output script:')
console.log(p2wpkhAlice1.output.toString('hex'))
The script is composed as follow: 00
version + PUSHBYTES_14 + public key hash (witness program)
The HASH160 of the public key should match the 20-bytes witness program in the previous output script (the segwit UTXO we are spending).
$ bx bitcoin160 03745c9aceb84dcdeddf2c3cdc1edb0b0b5af2f9bf85612d73fa6394758eaee35d
fb8820f35effa054399540b8ca86040d8ddaa4d5
or
bitcoin.crypto.hash160(Buffer.from('03745c9aceb84dcdeddf2c3cdc1edb0b0b5af2f9bf85612d73fa6394758eaee35d', 'hex')).toString('hex')
// txb.addInput(prevTxId, prevOutIndex, sequence, prevOutScript)
txb.addInput('TX_ID', TX_VOUT, null, p2wpkhAlice1.output)
txb.addOutput(p2pkhBob1.address, 999e5)
Let’s calculate our mining fee, subtracting the outputs from the inputs.
100 000 000 - 99 900 000 = 100 000 100 000 satoshis, which is equal to 0,001 BTC.
// txb.sign(index, keyPair, redeemScript, sign.hashType, value, witnessScript)
txb.sign(0, keyPairAlice1, null, null, 1e8, null)
We don’t have to specify any redeem or witness scripts here, since we are spending a native segwit UTXO. But we still need to sign the input value. |
const tx = txb.build()
console.log('Transaction hexadecimal:')
console.log(tx.toHex())
decoderawtransaction TX_HEX
Broadcasting the transaction
sendrawtransaction TX_HEX
sendrawtransaction
returns the transaction ID, with which you can inspect your transaction again.
getrawtransaction TX_ID true (1)
1 | Don’t forget the second argument. If false, it returns the hex string, otherwise it returns a detailed json object. |
Observations
In the vin section we note that scriptSig
is empty and that we have an additional txinwitness
field which contains Alice signature and public key.
The semantics of P2WPKH is the same as the semantics of P2PKH, except that the signature is not placed at the same location as before.
In the vout section we have one witness_v0_keyhash
output, which is the code name for native Segwit.