Spending bitcoin UTXO using libbitcoin (bx)

The Times

1- Generate random seed and hd master private key

hd_master_private=$(bx seed --bit_length 512 | bx hd-new)

2- generate hd master public key

hd_master_public=$(bx hd-to-public $hd_master_private)

3- generate private key for spending account 0

m/44'/1'/0'/0

we first fund to this account for future spends

hd_m_44h_1h_0h_0=$(bx hd-private --hard --index 44 $hd_master_private | bx hd-private --hard --index 1 | bx hd-private --hard --index 0 | bx hd-private --index 0)
  • 44 : purpose always set to 44 BIP44 hardened
  • 0/1 : 0 for mainnet, 1 for testnet hardened
  • 0` First account/Individual wallet account key
  • 0/1 unhardened : Keys of receiving address/keys of change address

4- Generate private key for account 0,index 0 m/44'/1'/0'/0/0

  • 0 : Address index
hd_m_44h_1h_0h_0_0=$(bx hd-private --index 0 $hd_m_44h_1h_0h_0)

5- Convert the HD BIP32 private key to private EC point

private_hd_m_44h_1h_0h_0_0=$(bx hd-to-ec $hd_m_44h_1h_0h_0_0)

6- Derive the HD BIP32 public key from the HD BIP32 private key,then convert the HD BIP32 to public EC point

public_hd_m_44h_1h_0h_0_0=$(bx hd-to-public $private_hd_m_44h_1h_0h_0_0 | bx hd-to-ec )

7- Get the public key hash

publickeyhash_hd_m_44h_1h_0h_0_0=$(bx sha256 $public_hd_m_44h_1h_0h_0_0 | bx ripemd160)

8- Derive the address

address_hd_m_44h_1h_0h_0_0=$(bx ec-to-address --version 111 $public_hd_m_44h_1h_0h_0_0)
address_hd_m_44h_1h_0h_0_0=$(bx hd-to-public $private_hd_m_44h_1h_0h_0_0 | bx hd-to-ec | bx ec-to-address --version 111)

9- store useful values for future processing

previous_txid= ```
previous_output_index= XXX
previous_output_amount= XXX

10- Generate destination key pairs account 1 m/44'/1'/1'/0

hd_m_44h_1h_1h_0=$(bx hd-private --hard --index 44 $hd_master_private | bx hd-private --hard --index 1 | bx hd-private --hard --index 1 | bx hd-private --index 0)

11-

hd_m_44h_1h_1h_0_0=$(bx hd-private --index 0 $hd_m_44h_1h_1h_0)
publickeyhash_hd_m_44h_1h_1h_0_0=$(bx hd-to-public $hd_m_44h_1h_1h_0_0 | bx hd-to-ec | bx sha256 | bx ripemd160)

12- Build output script for destination

output_script0=$(bx script-encode "DUP HASH160 ["$publickeyhash_hd_m_44h_1h_1h_0_0"] EQUALVERIFY CHECKSIG")
echo $output_script0

13- Calculate transaction byte size

tx_byte_count=$(expr 4 + 1 + 1 \* 148 + 1 + 1 \* 34 + 4)

14- Calculate output amount

tx_total_output_amount=$(expr $previous_output_amount - 1 \* 400 - $tx_byte_count \* 1)

15- Spent amount evenly for each output / 1 output in our case

single_output_amount=$(expr $tx_total_output_amount / 1)

16- Construct transaction template for signing

my_tx=$(bx tx-encode --input $previous_txid:$previous_output_index:4294967295 --output $output_script0:$single_output_amount)

17- Fetch previous output script

previous_output_script=$(bx fetch-tx --format json $previous_txid | jq -r ".transaction.outputs[1].script")

dup hash160 [35afb72a7b4e056b28ff34e650f71cc399dbdf72] equalverify checksig

18- Sign transaction with previous output script

signature=$(bx input-sign --sign_type all --index 0 $private_hd_m_44h_1h_0h_0 "$previous_output_script" $my_tx)

19- Set the input script to the finalized transaction

my_tx=$(bx input-set --index 0 "[$signature] [$publickey_44h_1h_0h_0_0]" $my_tx)

20- Validate the transaction

bx validate-tx $my_tx

21- Send transaction

bx send-tx $my_tx

22- Get the transaction id

bx bitcoin256 $my_tx
0