Fidel's Bitcoin Development Tutorials

Hands-on tutorials for Bitcoin developers

View the Project on GitHub Fideltodayy/bitcoin-dev-tutorials

Understanding Bitcoin Transactions

This tutorial provides a comprehensive guide to understanding Bitcoin transactions, UTXO management, and the signing process. We’ll explore both simple and complex transaction creation using Bitcoin Core’s command-line interface.

Date: May 15, 2025
Bitcoin Core Version: v27.0.0
Environment: Ubuntu Linux

Table of Contents

  1. Introduction
  2. Basic Concepts
  3. Simple Transactions
  4. Complex Transactions
  5. The Signing Process
  6. Conclusion

Introduction

Bitcoin transactions represent the transfer of value between addresses on the Bitcoin network. Unlike traditional banking systems, Bitcoin doesn’t maintain account balances. Instead, it tracks unspent transaction outputs (UTXOs) - essentially, unspent “coins” associated with specific addresses.

In this tutorial, we’ll explore how to work with Bitcoin transactions using Bitcoin Core in regtest mode, which provides a safe environment for experimentation without using real funds.

Basic Concepts

Addresses

Bitcoin addresses are identifiers that represent possible destinations for bitcoin payments. They’re derived from public keys and come in different formats. Let’s explore the addresses in our wallet:

$ bitcoin-cli listwallets
[
  "testing12"
]

$ bitcoin-cli -rpcwallet=testing12 getaddressesbylabel ""
{
  "bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu": {
    "purpose": "receive"
  }
}

The address format bcrt1q... indicates this is a regtest network address using the native SegWit (bech32) format.

UTXOs

UTXOs (Unspent Transaction Outputs) are the fundamental building blocks of Bitcoin transactions. Think of UTXOs as individual “coins” in your wallet that must be spent whole.

Let’s examine the UTXOs in our wallet:

$ bitcoin-cli -rpcwallet=testing12 listunspent
[
  {
    "txid": "aa5635d32b2d7cab228458c1300ad4b78382f78bb6ad9ab56f90102fde367f0c",
    "vout": 0,
    "address": "bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu",
    "label": "",
    "scriptPubKey": "001461e62e25953117e710ef1ac783ad8f6ba0cd138d",
    "amount": 50.00000000,
    "confirmations": 101,
    "spendable": true,
    "solvable": true,
    "desc": "wpkh([46cef80c/84h/1h/0h/0/0]03757419d3d83b465c86ead7c616685a1f8dabea6e2bd25744b59f81c76170ae9e)#72plk0k8",
    "safe": true
  }
]

Key components of a UTXO:

Wallets and Keys

Bitcoin wallets manage collections of keys that control UTXOs. Modern wallets use Hierarchical Deterministic (HD) derivation to generate many addresses from a single seed.

Let’s check our wallet information:

$ bitcoin-cli -rpcwallet=testing12 getwalletinfo
{
  "walletname": "testing12",
  "walletversion": 169900,
  "format": "sqlite",
  "balance": 50.00000000,
  "unconfirmed_balance": 0.00000000,
  "immature_balance": 5000.00000000,
  "txcount": 101,
  "keypoolsize": 4000,
  "keypoolsize_hd_internal": 4000,
  "private_keys_enabled": true,
  "avoid_reuse": false,
  "scanning": false,
  "descriptors": true
}

This shows we have a descriptor wallet with private keys enabled, managing a balance of 50 BTC.

Simple Transactions

Creating a New Address

First, let’s create a new receiving address:

$ bitcoin-cli -rpcwallet=testing12 getnewaddress "receive_5_btc" "bech32"
bcrt1qupeg2286jw4r4qctzz7s2g4xn9y5rq2legd9uj

We’ve created a new address with the label “receive_5_btc” using the native SegWit (bech32) format.

Sending Bitcoin

Now, let’s send 5 BTC to our new address:

$ bitcoin-cli -rpcwallet=testing12 sendtoaddress bcrt1qupeg2286jw4r4qctzz7s2g4xn9y5rq2legd9uj 5.0
3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39

The command returns a transaction ID. Behind the scenes, Bitcoin Core:

  1. Selected an appropriate UTXO (our 50 BTC)
  2. Created the transaction with two outputs:
    • 5 BTC to our new address
    • 44.99998590 BTC back to a change address (minus 0.00001410 fee)
  3. Signed the transaction with the private key
  4. Broadcast it to the network

Let’s examine the transaction:

$ bitcoin-cli -rpcwallet=testing12 gettransaction 3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39
{
  "amount": 0.00000000,
  "fee": -0.00001410,
  "confirmations": 0,
  "trusted": true,
  "txid": "3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39",
  "walletconflicts": [],
  "time": 1747259243,
  "timereceived": 1747259243,
  "bip125-replaceable": "yes",
  "details": [
    {
      "address": "bcrt1qupeg2286jw4r4qctzz7s2g4xn9y5rq2legd9uj",
      "category": "send",
      "amount": -5.00000000,
      "label": "receive_5_btc",
      "vout": 0,
      "fee": -0.00001410,
      "abandoned": false
    },
    {
      "address": "bcrt1qupeg2286jw4r4qctzz7s2g4xn9y5rq2legd9uj",
      "category": "receive",
      "amount": 5.00000000,
      "label": "receive_5_btc",
      "vout": 0
    }
  ]
}

Confirming Transactions

In Bitcoin, transactions need to be confirmed by being included in a block. In regtest mode, we can mine blocks ourselves:

$ bitcoin-cli -rpcwallet=testing12 generatetoaddress 1 bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu
[
  "18aaff6ca222fa5179ff289c6a3fc867a95b9c2f5e8293cc010b039f42def2b4"
]

This mined one block, confirming our transaction and earning a block reward (50 BTC) to the specified address.

Let’s check the transaction status again:

$ bitcoin-cli -rpcwallet=testing12 gettransaction 3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39
{
  "amount": 0.00000000,
  "fee": -0.00001410,
  "confirmations": 1,
  "blockhash": "18aaff6ca222fa5179ff289c6a3fc867a95b9c2f5e8293cc010b039f42def2b4",
  "blockheight": 102,
  "blocktime": 1747259572,
  "txid": "3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39",
  "walletconflicts": [],
  "time": 1747259243,
  "timereceived": 1747259243,
  "bip125-replaceable": "no"
}

Now the transaction shows 1 confirmation and can no longer be replaced (BIP125-replaceable: “no”).

Complex Transactions

For more control, we can manually construct transactions by selecting specific UTXOs and outputs.

Managing UTXOs Manually

Let’s first check our available UTXOs:

$ bitcoin-cli -rpcwallet=testing12 listunspent
[
  {
    "txid": "3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39",
    "vout": 0,
    "address": "bcrt1qupeg2286jw4r4qctzz7s2g4xn9y5rq2legd9uj",
    "amount": 5.00000000,
    "confirmations": 1,
    "spendable": true,
    "solvable": true,
    "desc": "wpkh([46cef80c/84h/1h/0h/0/1]02fcd22cbaf67c8a8b549fa046edcd897068f12a8fc8a6c55fade62e7e8269fc18)#4fynfz8f",
    "safe": true
  },
  {
    "txid": "3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39",
    "vout": 1,
    "address": "bcrt1qmt685un8qxs36k0x5wd7zjncsxfkz4cvta8syt",
    "amount": 44.99998590,
    "confirmations": 1,
    "spendable": true,
    "solvable": true,
    "desc": "wpkh([46cef80c/84h/1h/0h/1/0]022a8c0fc24826523adc7901a935a91cdfd78b316fb0bfddf72f0fc2246171f905)#v3taf7au",
    "safe": true
  },
  {
    "txid": "aa5635d32b2d7cab228458c1300ad4b78382f78bb6ad9ab56f90102fde367f0c",
    "vout": 0,
    "address": "bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu",
    "amount": 50.00000000,
    "confirmations": 101,
    "spendable": true,
    "solvable": true,
    "desc": "wpkh([46cef80c/84h/1h/0h/0/0]03757419d3d83b465c86ead7c616685a1f8dabea6e2bd25744b59f81c76170ae9e)#72plk0k8",
    "safe": true
  }
]

Creating Multi-Output Transactions

Let’s create a new address for our complex transaction example:

$ bitcoin-cli -rpcwallet=testing12 getnewaddress "complex_tx_demo"
bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r

Now we’ll create a transaction with multiple inputs and outputs manually:

  1. First, create the raw transaction:
$ bitcoin-cli -rpcwallet=testing12 createrawtransaction '[{"txid":"3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39","vout":0}, {"txid":"3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39","vout":1}]' '[{"bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r":3.0}, {"bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu":46.99997590}]'
020000000239dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0000000000fdffffff39dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0100000000fdffffff0200a3e111000000001600148768cca14ece7a674c43e9a38aee1cbd61402c17964524180100000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d00000000
  1. Analyze the raw transaction:
$ bitcoin-cli -rpcwallet=testing12 decoderawtransaction 020000000239dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0000000000fdffffff39dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0100000000fdffffff0200a3e111000000001600148768cca14ece7a674c43e9a38aee1cbd61402c17964524180100000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d00000000
{
  "txid": "1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d",
  "hash": "1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d",
  "version": 2,
  "size": 154,
  "vsize": 154,
  "weight": 616,
  "locktime": 0,
  "vin": [
    {
      "txid": "3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967293
    },
    {
      "txid": "3b2c2b3e7188e92eac790e5190faad200ee9159c0ad5decba6c0afaf4d6adc39",
      "vout": 1,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "sequence": 4294967293
    }
  ],
  "vout": [
    {
      "value": 3.00000000,
      "n": 0,
      "scriptPubKey": {
        "asm": "0 8768cca14ece7a674c43e9a38aee1cbd61402c17",
        "desc": "addr(bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r)#9p5le0z9",
        "hex": "00148768cca14ece7a674c43e9a38aee1cbd61402c17",
        "address": "bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r",
        "type": "witness_v0_keyhash"
      }
    },
    {
      "value": 46.99997590,
      "n": 1,
      "scriptPubKey": {
        "asm": "0 61e62e25953117e710ef1ac783ad8f6ba0cd138d",
        "desc": "addr(bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu)#906ktfke",
        "hex": "001461e62e25953117e710ef1ac783ad8f6ba0cd138d",
        "address": "bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu",
        "type": "witness_v0_keyhash"
      }
    }
  ]
}
  1. Sign the transaction:
$ bitcoin-cli -rpcwallet=testing12 signrawtransactionwithwallet 020000000239dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0000000000fdffffff39dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0100000000fdffffff0200a3e111000000001600148768cca14ece7a674c43e9a38aee1cbd61402c17964524180100000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d00000000
{
  "hex": "0200000000010239dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0000000000fdffffff39dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0100000000fdffffff0200a3e111000000001600148768cca14ece7a674c43e9a38aee1cbd61402c17964524180100000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d0247304402205f24b8ba5448b1b68b86ed3eb024da5b5a06006a94ba99a685bba84dbda894f702204e46add3d03dc1209b032fe132bac238f99f29406962660d9cdae9088803c04e012102fcd22cbaf67c8a8b549fa046edcd897068f12a8fc8a6c55fade62e7e8269fc1802473044022052f0e173454a5048698c428bf1a8649ac709e4010b6556cec5e61e5e10ca75fc02206983728e3f79540da665f41157a5b4a5d0dfb8921f44a767172c43b03e21be3f0121022a8c0fc24826523adc7901a935a91cdfd78b316fb0bfddf72f0fc2246171f90500000000",
  "complete": true
}
  1. Broadcast the transaction:
$ bitcoin-cli -rpcwallet=testing12 sendrawtransaction 0200000000010239dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0000000000fdffffff39dc6a4dafafc0a6cbded50a9c15e90e20adfa90510e79ac2ee988713e2b2c3b0100000000fdffffff0200a3e111000000001600148768cca14ece7a674c43e9a38aee1cbd61402c17964524180100000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d0247304402205f24b8ba5448b1b68b86ed3eb024da5b5a06006a94ba99a685bba84dbda894f702204e46add3d03dc1209b032fe132bac238f99f29406962660d9cdae9088803c04e012102fcd22cbaf67c8a8b549fa046edcd897068f12a8fc8a6c55fade62e7e8269fc1802473044022052f0e173454a5048698c428bf1a8649ac709e4010b6556cec5e61e5e10ca75fc02206983728e3f79540da665f41157a5b4a5d0dfb8921f44a767172c43b03e21be3f0121022a8c0fc24826523adc7901a935a91cdfd78b316fb0bfddf72f0fc2246171f90500000000
1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d
  1. Confirm the transaction by mining a block:
$ bitcoin-cli -rpcwallet=testing12 generatetoaddress 1 bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu
[
  "4ef58653766dea3ac453cc089fa3db295cf27b9b132fe1aeead5119904858d2f"
]
  1. Check the confirmed transaction:
$ bitcoin-cli -rpcwallet=testing12 gettransaction 1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d
{
  "amount": 0.00000000,
  "fee": -0.00001000,
  "confirmations": 1,
  "blockhash": "4ef58653766dea3ac453cc089fa3db295cf27b9b132fe1aeead5119904858d2f",
  "blockheight": 103,
  "blocktime": 1747260841,
  "txid": "1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d",
  "walletconflicts": [],
  "time": 1747260810,
  "timereceived": 1747260810,
  "bip125-replaceable": "no",
  "details": [
    {
      "address": "bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r",
      "category": "send",
      "amount": -3.00000000,
      "label": "complex_tx_demo",
      "vout": 0,
      "fee": -0.00001000,
      "abandoned": false
    },
    {
      "address": "bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu",
      "category": "send",
      "amount": -46.99997590,
      "label": "",
      "vout": 1,
      "fee": -0.00001000,
      "abandoned": false
    }
  ]
}

This complex transaction demonstrates:

  1. Manual UTXO selection (choosing specific inputs)
  2. Multiple outputs with different amounts
  3. The manual transaction creation workflow:
    • Create raw transaction
    • Sign it with wallet’s private keys
    • Broadcast to network
    • Confirm in a block

The Signing Process

HD Wallet Structure

Modern Bitcoin wallets use Hierarchical Deterministic (HD) derivation paths to generate addresses. Let’s examine this structure:

$ bitcoin-cli -rpcwallet=testing12 getdescriptorinfo "wpkh(tpubD6NzVbkrYhZ4XxixgdWLG48bqd1CRWNyhQmoBt9oV5hYKoUee6N2ijYExCYw5vgsu4oJbdVS1cw3ctHN826FG8DFkTW7KDmmnUPS4oc1n9v/84h/1h/0h/0/*)"
{
  "descriptor": "wpkh(tpubD6NzVbkrYhZ4XxixgdWLG48bqd1CRWNyhQmoBt9oV5hYKoUee6N2ijYExCYw5vgsu4oJbdVS1cw3ctHN826FG8DFkTW7KDmmnUPS4oc1n9v/84h/1h/0h/0/*)#33ju6w7y",
  "checksum": "33ju6w7y",
  "isrange": true,
  "issolvable": true,
  "hasprivatekeys": false
}

Key components:

Public and Private Keys

Let’s examine an address to understand the relationship between keys and addresses:

$ bitcoin-cli -rpcwallet=testing12 getaddressinfo bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r
{
  "address": "bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r",
  "scriptPubKey": "00148768cca14ece7a674c43e9a38aee1cbd61402c17",
  "ismine": true,
  "solvable": true,
  "desc": "wpkh([46cef80c/84h/1h/0h/0/2]02180724b294c2d7ada8eac07c4d7aefea00cce502eeb9411d355ead8fe2f587ce)#0m0uxn8p",
  "iswatchonly": false,
  "isscript": false,
  "iswitness": true,
  "witness_version": 0,
  "witness_program": "8768cca14ece7a674c43e9a38aee1cbd61402c17",
  "pubkey": "02180724b294c2d7ada8eac07c4d7aefea00cce502eeb9411d355ead8fe2f587ce",
  "ischange": false,
  "hdkeypath": "m/84h/1h/0h/0/2",
  "hdmasterfingerprint": "46cef80c"
}

The key hierarchy shows:

Creating Signatures

Modern descriptor wallets don’t allow directly dumping private keys. Instead, let’s examine how signatures are created by walking through a signing process step-by-step.

Let’s use our address with 3 BTC to create a simple transaction example:

$ bitcoin-cli -rpcwallet=testing12 listunspent 1 9999999 "[\"bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r\"]"
[
  {
    "txid": "1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d",
    "vout": 0,
    "address": "bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r",
    "label": "complex_tx_demo",
    "scriptPubKey": "00148768cca14ece7a674c43e9a38aee1cbd61402c17",
    "amount": 3.00000000,
    "confirmations": 1,
    "spendable": true,
    "solvable": true,
    "desc": "wpkh([46cef80c/84h/1h/0h/0/2]02180724b294c2d7ada8eac07c4d7aefea00cce502eeb9411d355ead8fe2f587ce)#0m0uxn8p",
    "safe": true
  }
]
  1. Create a raw transaction:
$ bitcoin-cli -rpcwallet=testing12 createrawtransaction '[{"txid":"1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d","vout":0}]' '[{"bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu":1.0}, {"bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r":1.99999}]'
02000000016d55dbcb5290eef992aa000325e9878191cc7b4a740c0805d4e89cc0f0c74b1d0000000000fdffffff0200e1f5050000000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d18beeb0b000000001600148768cca14ece7a674c43e9a38aee1cbd61402c1700000000
  1. Convert to PSBT and examine what’s needed for signing:
$ bitcoin-cli -rpcwallet=testing12 analyzepsbt $(bitcoin-cli -rpcwallet=testing12 converttopsbt 02000000016d55dbcb5290eef992aa000325e9878191cc7b4a740c0805d4e89cc0f0c74b1d0000000000fdffffff0200e1f5050000000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d18beeb0b000000001600148768cca14ece7a674c43e9a38aee1cbd61402c1700000000)
{
  "inputs": [
    {
      "has_utxo": false,
      "is_final": false,
      "next": "updater"
    }
  ],
  "next": "updater"
}
  1. Sign the transaction with the wallet:
$ bitcoin-cli -rpcwallet=testing12 walletprocesspsbt $(bitcoin-cli -rpcwallet=testing12 converttopsbt 02000000016d55dbcb5290eef992aa000325e9878191cc7b4a740c0805d4e89cc0f0c74b1d0000000000fdffffff0200e1f5050000000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d18beeb0b000000001600148768cca14ece7a674c43e9a38aee1cbd61402c1700000000)
{
  "psbt": "cHNidP8BAHECAAAAAW1V28tSkO75kqoAAyXph4GRzHtKdAwIBdTonMDwx0sdAAAAAAD9////AgDh9QUAAAAAFgAUYeYuJZUxF+cQ7xrHg62Pa6DNE40YvusLAAAAABYAFIdozKFOznpnTEPpo4ruHL1hQCwXAAAAAAABAJoCAAAAAjncak2vr8Cmy97VCpwV6Q4grfqQUQ55rC7piHE+Kyw7AAAAAAD9////OdxqTa+vwKbL3tUKnBXpDiCt+pBRDnmsLumIcT4rLDsBAAAAAP3///8CAKPhEQAAAAAWABSHaMyhTs56Z0xD6aOK7hy9YUAsF5ZFJBgBAAAAFgAUYeYuJZUxF+cQ7xrHg62Pa6DNE40AAAAAAQEfAKPhEQAAAAAWABSHaMyhTs56Z0xD6aOK7hy9YUAsFwEIawJHMEQCIBDdQd8B7glrue557EfvYpWWOnSV3dkaJcwd+d20a7FAAiB+YlP7o9fpq0xq0GSk8VuV5C6PAHnLJ64obLn+sB9ffwEhAhgHJLKUwtetqOrAfE167+oAzOUC7rlBHTVerY/i9YfOACICA3V0GdPYO0ZchurXxhZoWh+Nq+puK9JXRLWfgcdhcK6eGEbO+AxUAACAAQAAgAAAAIAAAAAAAAAAAAAiAgIYBySylMLXrajqwHxNeu/qAMzlAu65QR01Xq2P4vWHzhhGzvgMVAAAgAEAAIAAAACAAAAAAAIAAAAA",
  "complete": true,
  "hex": "020000000001016d55dbcb5290eef992aa000325e9878191cc7b4a740c0805d4e89cc0f0c74b1d0000000000fdffffff0200e1f5050000000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d18beeb0b000000001600148768cca14ece7a674c43e9a38aee1cbd61402c1702473044022010dd41df01ee096bb9ee79ec47ef6295963a7495ddd91a25cc1df9ddb46bb14002207e6253fba3d7e9ab4c6ad064a4f15b95e42e8f0079cb27ae286cb9feb01f5f7f012102180724b294c2d7ada8eac07c4d7aefea00cce502eeb9411d355ead8fe2f587ce00000000"
}
  1. Decode the signed transaction to see the signature:
$ bitcoin-cli -rpcwallet=testing12 decoderawtransaction 020000000001016d55dbcb5290eef992aa000325e9878191cc7b4a740c0805d4e89cc0f0c74b1d0000000000fdffffff0200e1f5050000000016001461e62e25953117e710ef1ac783ad8f6ba0cd138d18beeb0b000000001600148768cca14ece7a674c43e9a38aee1cbd61402c1702473044022010dd41df01ee096bb9ee79ec47ef6295963a7495ddd91a25cc1df9ddb46bb14002207e6253fba3d7e9ab4c6ad064a4f15b95e42e8f0079cb27ae286cb9feb01f5f7f012102180724b294c2d7ada8eac07c4d7aefea00cce502eeb9411d355ead8fe2f587ce00000000
{
  "txid": "6de0471a5f32c933824c35a00854d81d775453d7c202262605dc641f2b1d1ec2",
  "hash": "e53c17de4084128ec40ff42ed350878106c3041c98a8b3ea4f6c472c17458795",
  "version": 2,
  "size": 222,
  "vsize": 141,
  "weight": 561,
  "locktime": 0,
  "vin": [
    {
      "txid": "1d4bc7f0c09ce8d405080c744a7bcc918187e9250300aa92f9ee9052cbdb556d",
      "vout": 0,
      "scriptSig": {
        "asm": "",
        "hex": ""
      },
      "txinwitness": [
        "3044022010dd41df01ee096bb9ee79ec47ef6295963a7495ddd91a25cc1df9ddb46bb14002207e6253fba3d7e9ab4c6ad064a4f15b95e42e8f0079cb27ae286cb9feb01f5f7f01",
        "02180724b294c2d7ada8eac07c4d7aefea00cce502eeb9411d355ead8fe2f587ce"
      ],
      "sequence": 4294967293
    }
  ],
  "vout": [
    {
      "value": 1.00000000,
      "n": 0,
      "scriptPubKey": {
        "asm": "0 61e62e25953117e710ef1ac783ad8f6ba0cd138d",
        "desc": "addr(bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu)#906ktfke",
        "hex": "001461e62e25953117e710ef1ac783ad8f6ba0cd138d",
        "address": "bcrt1qv8nzufv4xyt7wy80rtrc8tv0dwsv6yudkqxgsu",
        "type": "witness_v0_keyhash"
      }
    },
    {
      "value": 1.99999000,
      "n": 1,
      "scriptPubKey": {
        "asm": "0 8768cca14ece7a674c43e9a38aee1cbd61402c17",
        "desc": "addr(bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r)#9p5le0z9",
        "hex": "00148768cca14ece7a674c43e9a38aee1cbd61402c17",
        "address": "bcrt1qsa5veg2weeaxwnzrax3c4msuh4s5qtqh74qh7r",
        "type": "witness_v0_keyhash"
      }
    }
  ]
}

The signature process involves:

  1. The wallet looks up the private key for the address being spent
    • It derives this from the HD seed using the path m/84h/1h/0h/0/2
    • Private keys are never revealed, only used internally
  2. It creates a signature using:
    • The transaction data (minus the signature itself)
    • The private key
    • A signing algorithm (ECDSA in this case)
  3. It places the signature data in the txinwitness array:
    • First item: The signature with sighash flag (01 = SIGHASH_ALL)
    • Second item: The public key

This proves ownership of the address without revealing the private key.

Conclusion

In this tutorial, we’ve explored the foundations of Bitcoin transactions:

  1. Bitcoin Address Management
    • Creating and identifying addresses
    • Understanding address formats (Native SegWit/bech32)
  2. UTXO Model
    • How Bitcoin tracks funds as unspent transaction outputs
    • Managing and selecting UTXOs for spending
  3. Transaction Creation
    • Simple transactions using high-level commands
    • Complex transactions with multiple inputs and outputs
    • Transaction fees and change management
  4. Signing Process
    • HD wallet key derivation
    • Public/private key relationships
    • How signatures prove ownership without revealing private keys

These concepts form the building blocks of all Bitcoin applications. By understanding these fundamentals, you’re equipped to develop more sophisticated Bitcoin applications, create custom transaction types, or integrate Bitcoin functionality into your projects.

Remember that this tutorial used regtest mode, which is perfect for learning and development. When working with real Bitcoin on testnet or mainnet, always exercise caution with private keys and verify transactions carefully before broadcasting them.

For more advanced topics, consider exploring:

Happy coding!