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 = <signature> <public key>
scriptPubKey = OP_DUP OP_HASH160 <recipient_pubkey_hash> 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 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig:
<signature> <public_key>
⚖️ 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 <redeem_script_hash> OP_EQUAL
scriptSig:
<data> <redeem_script>
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.
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.