Typical Transaction (1 input, 2 outputs) - Legacy P2PKH
To follow along this tutorial
|
Let’s create a legacy P2PKH transaction with 1 input and 2 outputs. This is a more realistic example that illustrates the notion of change. The second output is actually our change.
Spending a UTXO is like spending a bank note or a coin, you can’t split it. You spend it and you get back the change. |
Creating UTXO to spend
We first need to create a transaction in order to have a UTXO at our disposal that we can spend.
sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 1
We now have an UTXO locked with alice_1 public key hash. In order to spend it, we will refer to it with the transaction id (txid) and the
output index (vout), also called outpoint. Fortunately, sendtoaddress
returns the id of the transaction.
gettransaction TX_ID
Find the output index (or vout) under |
Creating a typical transaction
Now let’s spend the UTXO with BitcoinJS.
const bitcoin = require('bitcoinjs-lib')
const { alice, bob } = require('./wallets.json')
const network = bitcoin.networks.regtest
const keyPairAlice1 = bitcoin.ECPair.fromWIF(alice[1].wif, network)
const psbt = new bitcoin.Psbt({network})
.addInput({
hash: 'TX_ID',
index: TX_OUT,
nonWitnessUtxo: Buffer.from('TX_HEX', 'hex')
}) (1)
.addOutput({
address: bob[1].p2pkh,
value: 5e7, (2)
})
.addOutput({
address: alice[2].p2pkh,
value: 499e5, (3)
})
1 | Outpoint and previous tx hexadecimal |
2 | The actual "spend": bob_1 P2PKH recipient address and the amount of 0.5 BTC |
3 | Alice’s change: alice’s change address (here alice_2) and the amount of 0.499 BTC |
The miner fee is calculated by subtracting the outputs from the inputs. |
The UTXO is locked with alice_1’s public key hash. If she wants to spend it, she needs to prove her ownership of the private key that is linked to the public key, which hash is written in the UTXO.
To do so, alice_1 will sign this transaction that we just built with her private key. BitcoinJS will automatically place the signature into the scriptSig
field of the input 0.
psbt.signInput(0, keyPairAlice1)
psbt.validateSignaturesOfInput(0)
psbt.finalizeAllInputs()
console.log('Transaction hexadecimal:')
console.log(psbt.extractTransaction().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
Don’t forget the second argument. If false, it returns the hex string, otherwise it returns a detailed json object. |