Legacy pay to public key hash

P2PKH is the standard and most common output type until now, used before the Segregated Witness soft fork, that Pays To PubKey Hash (P2PKH). A P2PKH contains instructions which allow anyone to spend that output if they can prove they control the private key corresponding to the hashed public key. These instructions are called the pubkey script or scriptPubKey.

Note
Refer to the Bitcoin script 101 tutorial for more information on how this scripting language works.

A standard unlocking script in the input of the spending transaction looks like so <Sig> <PubKey>. It spends a standard P2PKH locking script (scriptPubKey) that looks like so OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG.

A P2PKH Bitcoin payment address is a Base58 representation of a hashed public key.

Simple Transaction (1 input, 1 output) - Legacy P2PKH

To follow along this tutorial and enter the commands step-by-step

  • Type node in a terminal after cd into ./code for a Javascript prompt
  • Open the Bitcoin Core GUI console or use bitcoin-cli for the Bitcoin Core commands
  • Use bx aka Libbitcoin-explorer as a handy complement

Let's create a legacy P2PKH transaction with 1 input and 1 output.

Create UTXO to spend from

First we need to create a previous transaction in order to have a UTXO at our disposal.

Import libraries, test wallets and set the network

const bitcoin = require('bitcoinjs-lib')
const { alice, bob } = require('./wallets.json')
const network = bitcoin.networks.regtest

Send 1 BTC to Alice_0 P2PKH address with Bitcoin Core CLI.

Check out Generating and Importing Wallets and your wallets.json
file in the code directory. Replace the address if necessary.

$ sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 1

We have now an UTXO locked with Alice_0 public key hash.
In order to spend it, we refer to it with the transaction id (txid) and the output index (vout), also called outpoint. Fortunately, sendtoaddress returns the id of the transaction.

Get the output index so that we have the outpoint (txid / vout).

Find the output index (or vout) under details > vout.

$ gettransaction "txid"

Creating the simple transaction

Now let's spend the UTXO with BitcoinJS.

Create a bitcoinJS key pair object for Alice_0, the spender of our new UTXO, and the only one capable of spending it.

const keyPairAlice0 = bitcoin.ECPair.fromWIF(alice[0].wif, network)

Create a key pair object and a P2PKH address for the recipient, Bob_0.

const keyPairBob0 = bitcoin.ECPair.fromWIF(bob[0].wif, network)
const p2pkhBob0 = bitcoin.payments.p2pkh({pubkey: keyPairBob0.publicKey, network})

Create a BitcoinJS transaction builder object.
Add the input by filling it with the outpoint (previous values txId and vout).
Add the output with the Bob_0 P2PKH recipient address and the amount of 0.999 btc.

const txb = new bitcoin.TransactionBuilder(network)
txb.addInput('TX_ID', TX_VOUT)
txb.addOutput(p2pkhBob0.address, 999e5)

The miner fee is calculated by subtracting the outputs from the inputs.
100 000 000 - 99 900 000 = 100 000
100 000 satoshis equals 0,001 BTC, this is the miner fee.

The UTXO is locked with Alice_0'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_0 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.

txb.sign(0, keyPairAlice0)

Finally we can build the transaction and get the raw hex serialization.

const tx = txb.build()
console.log('tx.toHex()  ', tx.toHex())

Inspect the raw transaction with Bitcoin Core CLI, check that everything is correct.

$ decoderawtransaction "hexstring"

Broadcasting the transaction

It's time to broadcast the transaction via Bitcoin Core CLI.

$ sendrawtransaction "hexstring"

sendrawtransaction returns the transaction ID, with which you can inspect your transaction again.

Don't forget the second argument. If false, it returns the hex string, otherwise it returns a detailed json object.

$ getrawtransaction "txid" true

Typical Transaction (1 input, 2 outputs) - Legacy P2PKH

To follow along this tutorial and enter the commands step-by-step

  • Type node in a terminal after cd into ./code for a Javascript prompt
  • Open the Bitcoin Core GUI console or use bitcoin-cli for the Bitcoin Core commands
  • Use bx aka Libbitcoin-explorer as a handy complement

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.

Create UTXO to spend from

First we need to create a previous transaction in order to have a UTXO at our disposal.

Import libraries, test wallets and set the network

const bitcoin = require('bitcoinjs-lib')
const { alice, bob } = require('./wallets.json')
const network = bitcoin.networks.regtest

Send 1 BTC to Alice_0 P2PKH address with Bitcoin Core CLI.

Check out Generating and Importing Wallets and your wallets.json
file in the code directory. Replace the address if necessary.

$ sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 1

We have now an UTXO locked with Alice_0 public key hash.
In order to spend it, we refer to it with the transaction id (txid) and the output index (vout), also called outpoint.
Fortunately, sendtoaddress returns the id of the transaction.

Get the output index so that we have the outpoint (txid / vout).

Find the output index (or vout) under details > vout.

$ gettransaction "txid"

Creating the typical transaction

Now let's spend the UTXO with BitcoinJS.

Create a BitcoinJS key pair object for Alice_0, the spender of our new UTXO, and the only one capable of spending it.

const keyPairAlice0 = bitcoin.ECPair.fromWIF(alice[0].wif, network)

Create an other address the Alice's change.

const keyPairAlice1 = bitcoin.ECPair.fromWIF(alice[1].wif, network)
const p2pkhAlice1 = bitcoin.payments.p2pkh({pubkey: keyPairAlice1.publicKey, network})

Create a key pair object and a P2PKH address for the recipient, Bob_0.

const keyPairBob0 = bitcoin.ECPair.fromWIF(bob[0].wif, network)
const p2pkhBob0 = bitcoin.payments.p2pkh({pubkey: keyPairBob0.publicKey, network})

Create a BitcoinJS transaction builder object.
Add the input by providing the outpoint.
Add the output #1 with the Bob_0 P2PKH recipient address and the amount of 0.5 BTC.
Add the output #2 with alice's change address (the same one or a new one for better privacy) and the amount of 0.499 BTC.

const txb = new bitcoin.TransactionBuilder(network)
txb.addInput('TX_ID', TX_VOUT)
txb.addOutput(p2pkhBob0.address, 5e7) // the actual "spend"
txb.addOutput(p2pkhAlice1.address, 499e5) // Alice's change

The miner fee is calculated by subtracting the outputs from the inputs.
100 000 000 - (50 000 000 + 49 900 000) = 100 000
100 000 satoshis equals 0,001 BTC, this is the miner fee.

The UTXO is locked with Alice_0'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_0 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.

txb.sign(0, keyPairAlice0)

Finally we can build the transaction and get the raw hex serialization.

const tx = txb.build()
console.log('tx.toHex()  ', tx.toHex())

Inspect the raw transaction with Bitcoin Core CLI, check that everything is correct.

$ decoderawtransaction "hexstring"

Broadcasting the transaction

It's time to broadcast the transaction via Bitcoin Core CLI.

$ sendrawtransaction "hexstring"

sendrawtransaction returns the transaction ID, with which you can inspect your transaction again.

Don't forget the second argument. If false, it returns the hex string, otherwise it returns a detailed json object.

$ getrawtransaction "txid" true

UTXO Consolidation (5 inputs, 1 output) - Legacy P2PKH

To follow along this tutorial and enter the commands step-by-step

  • Type node in a terminal after cd into ./code for a Javascript prompt
  • Open the Bitcoin Core GUI console or use bitcoin-cli for the Bitcoin Core commands
  • Use bx aka Libbitcoin-explorer as a handy complement

Let's do UTXO consolidation, also called an aggregating transaction.

The idea is that a single signatory aggregates many small UTXOs into a single big UTXO. This represents the real-world
equivalent of exchanging a pile of coins and currency notes for a single larger note.

Check out Coinjoin Transaction (4 inputs, 4 outputs) - Legacy P2PKH for
multiple signatories.

In legacy P2PKH transaction, each input contains a signature, which quickly increases the size of your transactions if
you need to spend multiple UTXOs, and hence the fees you pay.

Consolidation also gives an opportunity to update the addresses you use for your UTXOs, for example to roll keys over,
switch to multisig, or switch to Segwit bech32 addresses.
Finally, reducing the number of UTXOs frees the UTXOs database (chainstate), making it easier to run a full node,
marginally improving Bitcoin’s decentralisation and overall security, which is always nice.

For this example we will move five P2PKH UTXOs, referencing each of them with five inputs, to one Segwit P2WPKH UTXO.
Note that with a P2WPKH UTXO we don't have this issue anymore since an input spending it will not contain anything.
Check out Spend a Native Segwit P2WPKH UTXO for an illustration.

Create UTXOs to spend from

First we need to create five previous transactions in order to have five UTXOs at our disposal.

Import libraries, test wallets and set the network

const bitcoin = require('bitcoinjs-lib')
const { alice, bob } = require('./wallets.json')
const network = bitcoin.networks.regtest

UTXO consolidation makes sense if we have multiple payments to a single address, or multiple payments to different
addresses controlled by a single person or entity.

Let's use different addresses, all controlled by Alice.
We will have three payments to Alice_0 P2PKH address, one to Alice_1 P2PKH address and one to Alice_2 P2PKH address.

Let's send this five payments, of 0.2 BTC each.

Check out Generating and Importing Wallets and your wallets.json
file in the code directory. Replace the address if necessary.

$ sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 0.2
$ sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 0.2
$ sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 0.2
$ sendtoaddress mgZt5Fqzszdwf8hDgZt3mUf7js611aKRPc 0.2
$ sendtoaddress n3ZLcnCtfRucM4WLnXqukm9bTdb1PWeETk 0.2

We have now five UTXOs locked with Alice public keys hash.
In order to spend it, we refer to it with the transaction id (txid) and the output index (vout), also called outpoint.

Get the output indexes of the five transactions, so that we have their outpoint (txid / vout).

Find the output index (or vout) under details > vout.

$ gettransaction "txid"
$ gettransaction "txid"
$ gettransaction "txid"
$ gettransaction "txid"
$ gettransaction "txid"

Creating the aggregating transaction

Now let's spend the UTXOs with BitcoinJS, consolidating them into a single P2WPKH UTXO.

Create Alice's key pairs.

const keyPairAlice0 = bitcoin.ECPair.fromWIF(alice[0].wif, network)
const keyPairAlice1 = bitcoin.ECPair.fromWIF(alice[1].wif, network)
const keyPairAlice2 = bitcoin.ECPair.fromWIF(alice[2].wif, network)
const p2wpkhAlice0 = bitcoin.payments.p2wpkh({pubkey: keyPairAlice0.publicKey, network})

Create a BitcoinJS transaction builder object.
Add the five inputs by providing the outpoints.
Add the P2WPKH output with an amount of 0.999 BTC.

const txb = new bitcoin.TransactionBuilder(network)
txb.addInput('TX_ID', TX_VOUT)
txb.addInput('TX_ID', TX_VOUT)
txb.addInput('TX_ID', TX_VOUT)
txb.addInput('TX_ID', TX_VOUT)
txb.addInput('TX_ID', TX_VOUT)
txb.addOutput(p2wpkhAlice0.address, 999e5) 

The miner fee is calculated by subtracting the outputs from the inputs.
(20 000 000 + 20 000 000 + 20 000 000 + 20 000 000 + 20 000 000) - 99 900 000 = 100 000
100 000 satoshis equals 0,001 BTC, this is the miner fee.

Alice adds the correct signature to each input.

txb.sign(0, keyPairAlice0)
txb.sign(1, keyPairAlice0)
txb.sign(2, keyPairAlice0)
txb.sign(3, keyPairAlice1)
txb.sign(4, keyPairAlice2)

Finally we can build the transaction and get the raw hex serialization.

const tx = txb.build()
console.log('tx.toHex()  ', tx.toHex())

Inspect the raw transaction with Bitcoin Core CLI, check that everything is correct.

$ decoderawtransaction "hexstring"

Broadcasting the transaction

It's time to broadcast the transaction via Bitcoin Core CLI.

$ sendrawtransaction "hexstring"

Inspect the transaction.

$ getrawtransaction "txid" true

Observations

We note that each input contains a 71 bytes signature (on average), resulting in a large and costly transaction.
Spending Segwit UTXOs results in much smaller transaction since the inputs are empty.
Also, the implementation of Schnorr signatures into Bitcoin would allow to aggregate all those signatures into one.

Batching Transaction (1 input, 5 outputs) - Legacy P2PKH

To follow along this tutorial and enter the commands step-by-step

  • Type node in a terminal after cd into ./code for a Javascript prompt
  • Open the Bitcoin Core GUI console or use bitcoin-cli for the Bitcoin Core commands
  • Use bx aka Libbitcoin-explorer as a handy complement

Let's create a batching transaction, also called distributing transaction.

It is a transaction that distributes one input to multiple outputs representing multiple recipients. This type of
transaction is sometimes used by commercial entities to distribute funds, such as when processing payroll payments to
multiple employees.

For this example we will spend a legacy P2PKH UTXO and spend it to five different P2PKH addresses.

Create a UTXO to spend from

First we need to create a previous transaction in order to have an UTXO at our disposal.

Import libraries, test wallets and set the network

const bitcoin = require('bitcoinjs-lib')
const { alice, bob, carol, dave } = require('./wallets.json')
const network = bitcoin.networks.regtest

Send 1.001 BTC to Alice_0 P2PKH address with Bitcoin Core CLI (0.001 will be spent on the mining fees).

Check out Generating and Importing Wallets and your wallets.json
file in the code directory. Replace the address if necessary.

$ sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 1.001

We have now a UTXO locked with Alice public keys hash.
In order to spend it, we refer to it with the transaction id (txid) and the output index (vout), also called outpoint.

Get the output indexes of the five transactions, so that we have their outpoint (txid / vout).

Find the output index (or vout) under details > vout.

$ gettransaction "txid"

Creating the batching transaction

Now let's spend the UTXO with BitcoinJS.

Create a BitcoinJS key pair for Alice_0, the spender of our new UTXO.

const keyPairAlice0 = bitcoin.ECPair.fromWIF(alice[0].wif, network)

Create five different P2PKH addresses.

const keyPairBob0 = bitcoin.ECPair.fromWIF(bob[0].wif, network)
const p2pkhBob0 = bitcoin.payments.p2pkh({pubkey: keyPairBob0.publicKey, network})
const keyPairBob1 = bitcoin.ECPair.fromWIF(bob[1].wif, network)
const p2pkhBob1 = bitcoin.payments.p2pkh({pubkey: keyPairBob1.publicKey, network})
const keyPairBob2 = bitcoin.ECPair.fromWIF(bob[2].wif, network)
const p2pkhBob2 = bitcoin.payments.p2pkh({pubkey: keyPairBob2.publicKey, network})
const keyPairCarol0 = bitcoin.ECPair.fromWIF(carol[0].wif, network)
const p2pkhCarol0 = bitcoin.payments.p2pkh({pubkey: keyPairCarol0.publicKey, network})
const keyPairDave0 = bitcoin.ECPair.fromWIF(dave[0].wif, network)
const p2pkhDave0 = bitcoin.payments.p2pkh({pubkey: keyPairDave0.publicKey, network})

Create a BitcoinJS transaction builder object.
Add the input by providing the outpoint.

const txb = new bitcoin.TransactionBuilder(network)
txb.addInput('TX_ID', TX_VOUT)

Add the outputs, distributing 0.2 BTC to each five addresses.

txb.addOutput(p2pkhBob0.address, 2e7)
txb.addOutput(p2pkhBob1.address, 2e7) 
txb.addOutput(p2pkhBob2.address, 2e7)
txb.addOutput(p2pkhCarol0.address, 2e7) 
txb.addOutput(p2pkhDave0.address, 2e7)

The miner fee is calculated by subtracting the outputs from the inputs.
100 100 000 - (20 000 000 + 20 000 000 + 20 000 000 + 20 000 000 + 20 000 000) = 100 000
100 000 satoshis equals 0,001 BTC, this is the miner fee.

Alice_0 signs the transaction that we just built with her private key.
BitcoinJS will automatically place the signature into the scriptSig field of the input 0.

txb.sign(0, keyPairAlice0)

Finally we can build the transaction and get the raw hex serialization.

const tx = txb.build()
console.log('tx.toHex()  ', tx.toHex())

Inspect the raw transaction with Bitcoin Core CLI, check that everything is correct.

$ decoderawtransaction "hexstring"

Broadcasting the transaction

It's time to broadcast the transaction via Bitcoin Core CLI.

$ sendrawtransaction "hexstring"

Inspect the transaction.

$ getrawtransaction "txid" true

Observations

We note that we have five outputs, locking 0.2 BTC each to five different public key hash / addresses.

Coinjoin Transaction (4 inputs, 4 outputs) - Legacy P2PKH

To follow along this tutorial and enter the commands step-by-step

  • Type node in a terminal after cd into ./code for a Javascript prompt
  • Open the Bitcoin Core GUI console or use bitcoin-cli for the Bitcoin Core commands
  • Use bx aka Libbitcoin-explorer as a handy complement

What is Coinjoin

The signatures, one per input, inside a transaction are completely independent of each other. This means that it's
possible for Bitcoin users to agree on a set of inputs to spend, and a set of outputs to pay to, and then to individually
and separately sign a transaction and later merge their signatures. The transaction is not valid and won't be accepted
by the network until all signatures are provided, and no one will sign a transaction which is not to their liking.

To use this to increase privacy, the N users would agree on a uniform output size and provide inputs amounting to at
least that size. The transaction would have N outputs of that size and potentially N more change outputs if some of the
users provided input in excess of the target. All would sign the transaction, and then the transaction could be transmitted.
No risk of theft at any point.

Consider the following transactions made at the same time: A purchases an item from B, C purchases an item from D, and E
purchases an item from F. Without Coinjoin, the public blockchain ledger would record three separate transactions for
each input-output match. With Coinjoin, only one single transaction is recorded. The ledger would show that bitcoins
were paid from A, C, and E addresses to B, D, and F. By masking the deals made by all parties, an observer can’t, with
full certainty, determine who sent bitcoins to whom.

To read more about Coinjoin

What we will do

Let's create a Coinjoin transaction mixing four different transactions.

We will do the following:

  • Alice_0 -> Bob_0
  • Carol_0 -> Dave_0
  • Eve_0 -> Mallory_0
  • Mallory_1 -> Alice_1

The four signatories agree on a uniform output amount of 0.2 BTC.

We will create four UTXOs to spend from, with different amounts but with at least 0.2 BTC. If someone spend a UTXO that
is more than 0.2 BTC, we will create a additional output for his change.

Create UTXOs to spend from

First we need to create four previous transactions in order to have the UTXOs at our disposal.

Import libraries, test wallets and set the network

const bitcoin = require('bitcoinjs-lib')
const { alice, bob, carol, dave, eve, mallory } = require('./wallets.json')
const network = bitcoin.networks.regtest

Send 0.2 BTC to Alice_0 P2PKH address.
Send 0.2 BTC to Carol_0 P2PKH address.
Send 0.25 BTC to Eve_0 P2PKH address.
Send 0.3 BTC to Mallory_1 P2PKH address.

Check out Generating and Importing Wallets and your wallets.json file in the code directory. Replace the address if necessary.

$ sendtoaddress n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq 0.2
$ sendtoaddress mh1HAVWhKkzcvF41MNRKfakVvPV2sfaf3R 0.2
$ sendtoaddress mqbYBESF4bib4VTmsqe6twxMDKtVpeeJpt 0.25
$ sendtoaddress mxHHs4fNt1mBh4gz5MWegw4KYbGwPLXSUk 0.3

Get the output indexes of the four transactions, so that we have their outpoint (txid / vout).

Find the output index (or vout) under details > vout.

$ gettransaction "txid"
$ gettransaction "txid"
$ gettransaction "txid"
$ gettransaction "txid"

Creating the Coinjoin transaction

Now let's spend the UTXOs and create new ones.
A facilitator, let's say Alice_0, will create the transaction, sign his input, then pass the partially-signed transaction
to the next participant and so on until everybody has signed and someone broadcast it.

Create a key pair for each spender (Alice_0, Carol_0, Eve_0, Mallory_1), so that they can sign.

const keyPairAlice0 = bitcoin.ECPair.fromWIF(alice[0].wif, network)
const keyPairCarol0 = bitcoin.ECPair.fromWIF(carol[0].wif, network)
const keyPairEve0 = bitcoin.ECPair.fromWIF(eve[0].wif, network)
const keyPairMallory1 = bitcoin.ECPair.fromWIF(mallory[1].wif, network)

Create an address for each recipient (Bob_0, Dave_0, Mallory_0, Alice_1), so that they can receive.

const keyPairBob0 = bitcoin.ECPair.fromWIF(bob[0].wif, network)
const p2pkhBob0 = bitcoin.payments.p2pkh({pubkey: keyPairBob0.publicKey, network})

const keyPairDave0 = bitcoin.ECPair.fromWIF(dave[0].wif, network)
const p2pkhDave0 = bitcoin.payments.p2pkh({pubkey: keyPairDave0.publicKey, network})

const keyPairMallory0 = bitcoin.ECPair.fromWIF(mallory[0].wif, network)
const p2pkhMallory0 = bitcoin.payments.p2pkh({pubkey: keyPairMallory0.publicKey, network})

const keyPairAlice1 = bitcoin.ECPair.fromWIF(alice[1].wif, network)
const p2pkhAlice1 = bitcoin.payments.p2pkh({pubkey: keyPairAlice1.publicKey, network})

We also have two more recipients that will get back their change (Eve_0 and Mallory_1).

const p2pkhEve0 = bitcoin.payments.p2pkh({pubkey: keyPairEve0.publicKey, network})
const p2pkhMallory1 = bitcoin.payments.p2pkh({pubkey: keyPairMallory1.publicKey, network})

Create a BitcoinJS transaction builder object.

const txb = new bitcoin.TransactionBuilder(network)

Add each inputs by providing the outpoints.

txb.addInput('TX_ID', TX_VOUT)
txb.addInput('TX_ID', TX_VOUT)
txb.addInput('TX_ID', TX_VOUT)
txb.addInput('TX_ID', TX_VOUT)

Add each 0.2 BTC payment outputs.

txb.addOutput(p2pkhBob0.address, 2e7)
txb.addOutput(p2pkhDave0.address, 2e7)
txb.addOutput(p2pkhMallory0.address, 2e7)
txb.addOutput(p2pkhAlice1.address, 2e7)

Add the change outputs of Eve_0 and Mallory_1. These UTXOs will not be coinjoined. One might reasonably assume that the
4950000 satoshis UTXO belongs to Eve_0 and that the 9950000 satoshis UTXO belongs to Mallory_1.
Let's also subtract the mining fees (0.0005 BTC each) from them.
We can have different policies regarding who has to pay for the mining fees, it is just easier that way for our example.

txb.addOutput(p2pkhEve0.address, 5e6 - 5e4)
txb.addOutput(p2pkhMallory1.address, 1e7 - 5e4)

The miner fee is calculated by subtracting the outputs from the inputs.
(20000000 + 20000000 + 25000000 + 30000000)ins - (20000000 + 20000000 + 20000000 + 20000000 + 4950000 + 9950000)outs
= 100 000
100 000 satoshis equals 0,001 BTC, this is the mining fee.

Each participant signs their input with the default SIGHASH_ALL flag, which prevents inputs or outputs from being
manipulated after the fact.

txb.sign(0, keyPairAlice0)
txb.sign(1, keyPairCarol0)
txb.sign(2, keyPairEve0)
txb.sign(3, keyPairMallory1)

Finally we can build the transaction and get the raw hex serialization.

const tx = txb.build()
console.log('tx.toHex()  ', tx.toHex())

Inspect the raw transaction with Bitcoin Core CLI, check that everything is correct.

$ decoderawtransaction "hexstring"

Broadcasting the transaction

It's time to broadcast the transaction via Bitcoin Core CLI.

$ sendrawtransaction "hexstring"

Inspect the transaction.

Don't forget the second argument to returns a detailed json object.

$ getrawtransaction "txid" true

Base58Check encoding and decoding of P2PKH address

A P2PKH address is a public key hash encoded in Base58Check.
Starting from a public key hash, we add a version byte at the beginning and a checksum at the end, then we encode this in Base58.
To have a better understanding of this encoding have a look at addressEncoding.js.

A Bitcoin user usually send money to an address, but in fact the corresponding public key hash is stored into the blockchain.

Encode a public key hash to a P2PKH address

$ cd code 
$ npm run Base58CheckEncodeP2PKH fb8820f35effa054399540b8ca86040d8ddaa4d5

Decode a P2PKH address to a public key hash

$ cd code 
$ npm run Base58CheckDecodeP2PKH n4SvybJicv79X1Uc4o3fYXWGwXadA53FSq

What's Next?

Native Segwit p2wpkh