As a Rust blockchain developer on a mission to build secure, low-level systems, I recently took a deep dive into the core mechanics of Bitcoin transactions. This blog post breaks down what I learned into clear, precise steps with a developer's eye — ideal for engineers, or anyone serious about understanding how real digital money moves.


🔊 TL;DR (But Detailed)

Bitcoin transactions follow a strict sequence: they are created, signed, verified, broadcast, and finally, confirmed into blocks. Each transaction uses two key components:

  • scriptSig: the unlocking script (included by the sender)
  • scriptPubKey: the locking script (included in the output by the sender, meant for the recipient)

⛓️ Step-by-Step Bitcoin Transaction Lifecycle

1️⃣ Sender Creates a Transaction

  • Selects UTXOs to spend (inputs)
  • Signs each input using their private key
  • Includes their public key in the scriptSig
  • Creates a new output (scriptPubKey) locked to the recipient’s public key hash (address)
scriptSig =  
scriptPubKey = OP_DUP OP_HASH160  OP_EQUALVERIFY OP_CHECKSIG

2️⃣ Nodes Validate the Transaction

  • All Bitcoin full nodes independently verify:
    • Is the signature valid for the transaction?
    • Does the public key hash match the one in the locking script?
  • The signature is verified using ECDSA math, not decryption

If all checks pass → ✅ added to mempool and possibly mined into a block


3️⃣ Recipient’s Wallet Detects the UTXO

  • Monitors blockchain or queries a full node
  • Matches scriptPubKey (locking script) against recipient’s address
  • If matched, adds the UTXO to recipient’s spendable balance

4️⃣ Recipient Sends Bitcoin to Another Person

  • Uses wallet to:
    • Select UTXOs
    • Sign them with private key
    • Include public key in new scriptSig
    • Lock outputs to new recipient’s public key hash

Repeat the cycle ♻️


🔐 scriptSig vs. scriptPubKey

Script Purpose Location
scriptSig Unlock the previous UTXO Transaction input
scriptPubKey Lock the Bitcoin to a new address Transaction output

Example (Pay-to-PubKey-Hash):

scriptPubKey:
OP_DUP OP_HASH160  OP_EQUALVERIFY OP_CHECKSIG

scriptSig:

⚖️ What Is P2SH (Pay-to-Script-Hash)?

P2SH enhances Bitcoin's flexibility:

  • Instead of locking to a pubkey hash, you lock to a script hash
  • Recipient provides the redeem script and required data during spending

Example:

scriptPubKey (P2SH):
OP_HASH160  OP_EQUAL

scriptSig:

Used for:

  • Multi-signature wallets
  • Escrow contracts
  • Timelocked transactions

✅ Final Words

I aim to become protocol-native architect, and this journey into Bitcoin scripting is just the beginning.

Stay tuned for upcoming posts, where I’ll explore:

  • How to build a Bitcoin wallet UTXO scanner in Rust
  • Simulating script execution using Rust enums
  • Comparing UTXO-based vs. account-based models

Thanks for reading! If you found this helpful, feel free to connect or collaborate. Let’s build trustless systems, together.