A Bitcoin transaction moves value by consuming UTXOs and creating new ones. Everything else, wallets, Lightning channels, exchanges, eventually serializes to this structure.
Why this matters
If you cannot read a raw transaction, debugging stuck payments, wrong fees, or bad scripts becomes guesswork.
Analogy
A transaction is a signed instruction: “Take these coins (inputs) and lock them under these new conditions (outputs).” Miners include the instruction in a block; nodes verify the signatures and rules.
Core fields
- version
- inputs: previous txid + vout, scriptSig/witness, sequence
- outputs: value + scriptPubKey
- locktime
SegWit moves signatures into the witness, changing fee measurement to weight/vbytes.
Loading diagram…
Regtest practice
bitcoin-cli -regtest getnewaddress
bitcoin-cli -regtest generatetoaddress 101 "$(bitcoin-cli -regtest getnewaddress)"
bitcoin-cli -regtest sendtoaddress <addr> 1.5
bitcoin-cli -regtest getrawtransaction <txid> trueDecode the JSON and identify vin/vout, fees, and scripts.
type TxOut = { valueSats: number; scriptPubKey: string };
type BuiltTx = { inputs: { txid: string; vout: number }[]; outputs: TxOut[] };What signatures cover
A signature commits to a sighash, a digest of (parts of) the transaction. That is why you must finalize amounts and outputs before signing, and why PSBT workflows exist for multi-party construction.
Common mistakes
- Changing outputs after signing (invalidates signatures)
- Mixing mainnet txids into regtest experiments
- Forgetting change outputs
Virtual size and fees
SegWit transactions are priced by weight / vbytes, not legacy serialized size alone. When estimating:
const feeSats = Math.ceil(feeRateSatPerVb * vsize);Underpaying relative to the mempool means waiting; overpaying wastes money. Product UX should expose slow/medium/fast targets.
Sighash flags (builder intuition)
Most wallets use sighash types that commit to all inputs and outputs so the signed transaction cannot be altered meaningfully. Special flags exist for advanced contracts, avoid them until you can explain why you need them.
Decode practice
Use the Decoding Bitcoin transaction decoder on a sample or your own hex, then verify the same fields locally:
TXID=$(bitcoin-cli -regtest sendtoaddress "$(bitcoin-cli -regtest getnewaddress)" 0.5)
bitcoin-cli -regtest getrawtransaction "$TXID" true | jq '.vin,.vout,.fee'Trace which UTXOs were consumed and which new locks were created. Classroom-style drills live in transaction exercises.
Worked mental model
Re-read the diagrams in this lesson once out loud in plain language. If you cannot explain the flow to a friend without jargon, pause and revisit Mastering Bitcoin / Mastering Lightning chapters linked in Resources. Chapter references are intentional, not decorative.
Hands-on habit
Every protocol idea should be paired with one local experiment:
- Reproduce the happy path on regtest (or Polar for Lightning)
- Break it on purpose (wrong fee, expired invoice, offline peer)
- Write down what error you saw and which layer produced it (wallet, node, mempool, peer)
That habit turns reading into builder instinct.
Glossary check
Pick three terms from this lesson and define them in one sentence each without opening notes. Weak definitions mean the lesson is not finished yet.
Resource order
Use Resources in order: narrative book chapter first, then BIP/BOLT for precision, then implementation docs for commands. Jumping straight to RPC flags without the mental model creates brittle knowledge.
Next steps
Study Bitcoin Script, the tiny language that defines how outputs can be unlocked.