
Introduction
This page is L1 #2 — Transaction design in the design-document series. It covers the transaction layer end-to-end: how value is represented, transferred, locked, and unlocked. Everything in Bitcoin — mining incentives, block weight, fee markets, wallet UX — rests on the structures described here.
New to these concepts? What owning a bitcoin actually means introduces UTXOs, keys, and transactions with no prior knowledge assumed; this page is the design-document treatment of the same transaction layer, including the Bitcoin Script mechanics that page does not cover. Forensicxs’s 2024 code walkthrough traces the same Forth-based Script system back to the v0.1 source it first shipped in.
The transaction layer answers three questions:
- What is a coin? An unspent transaction output (UTXO) — not an account balance.
- What does a valid spend look like? A transaction that consumes existing UTXOs, proves authorization via cryptographic signatures, and creates new UTXOs.
- How is authorization expressed? Through Bitcoin Script — a stack-based language that evaluates locking and unlocking conditions.
Where behavior differs between the Satoshi-era implementation (v0.1, January 2009) and modern Bitcoin Core (v27+ baseline), both are noted.
The v0.1 transaction path in source
The v0.1 source makes the UTXO model concrete. CTransaction in the pinned commit 4184ab2, src/main.h lines 193–363, stores inputs, outputs, and locktime; ConnectInputs in src/main.cpp lines 772–854 follows each referenced output, rejects an immature coinbase, verifies the signature, checks whether the output is already spent, marks it spent, and computes the fee as input value minus output value. The script side is a separate but connected path: OP_CHECKSIG in src/script.cpp lines 692–901 removes the signature from the script being signed, constructs the legacy signature hash, and verifies the resulting digest against the public key.
These references document the January 2009 implementation rather than claiming that modern Bitcoin Core follows the same internal code path. The later sections therefore keep the v0.1 and modern baselines separate.
The separate v0.1 serialization-boundary analysis maps which bytes enter transaction, block, and signature hashes and how those objects are reused across network and disk paths.
1. The UTXO model
Bitcoin does not track balances. Instead, every transaction creates one or more discrete outputs, each carrying a specific amount and a locking condition. An output that has not yet been consumed by a later transaction is an unspent transaction output (UTXO). The set of all UTXOs at any moment is the complete picture of who can spend what.
UTXO lifecycle
A “coin” is simply an entry in the UTXO set; a wallet’s “balance” is the sum of every UTXO it can unlock.
UTXO model vs account model
| Property | UTXO model (Bitcoin) | Account model (Ethereum) |
|---|---|---|
| State representation | Set of discrete unspent outputs | Map of addresses to balances |
| Spending | Consume entire UTXOs, create new ones (including change) | Debit sender balance, credit receiver balance |
| Privacy | Each transaction can use fresh addresses; outputs are unlinkable by default | Addresses accumulate history; balance visible per account |
| Parallel validation | Inputs reference distinct UTXOs — transactions touching different UTXOs validate independently | Nonce ordering per account creates serial dependency |
| Double-spend detection | Check that referenced UTXO exists and is unspent | Check that sender nonce is correct and balance sufficient |
| State size | Grows with unspent outputs (about 166 million UTXOs in October 2026) | Grows with accounts and contract storage |
| Change outputs | Required when input total exceeds payment amount | Not needed; balance is adjusted in place |
2. Transaction structure
A transaction is a signed message that consumes one or more existing UTXOs (inputs) and creates one or more new UTXOs (outputs). The difference between total input value and total output value is the transaction fee, collected by the miner who includes the transaction in a block.
Transaction anatomy
Field-by-field breakdown
| Field | Size | Description |
|---|---|---|
| Version | 4 bytes | Transaction format version. v1 is standard; v2 enables BIP 68 relative timelocks. |
| Marker + Flag | 2 bytes | SegWit indicator (0x00 0x01). Absent in legacy transactions. |
| Input count | varint | Number of inputs. |
| Inputs | variable | Each input: previous txid (32 bytes) + output index (4 bytes) + scriptSig (variable) + sequence (4 bytes). |
| Output count | varint | Number of outputs. |
| Outputs | variable | Each output: value in satoshis (8 bytes) + scriptPubKey (variable). This is the exact field whose unvalidated integer overflow let a single August 2010 transaction mint 184 billion BTC — see the structural analysis of that incident for the CheckTransaction() per-output and sum-of-outputs bounds v0.3.10 added in response. |
| Witness | variable | Per-input witness stacks. Present only in SegWit transactions. |
| Locktime | 4 bytes | Earliest time or block height at which the transaction may be included. |
Satoshi era vs v27+ baseline: transaction format
| Aspect | Satoshi era (v0.1) | Modern Bitcoin Core, v27+ baseline |
|---|---|---|
| Format | Legacy: version + inputs + outputs + locktime | SegWit: version + marker/flag + inputs + outputs + witness + locktime |
| Witness data | Does not exist; signatures embedded in scriptSig | Segregated into the witness field (BIP 141) |
| Transaction ID | SHA-256d of the entire serialized transaction | txid excludes witness data; wtxid includes it |
| Malleability | Possible — third parties can alter scriptSig without invalidating the transaction | Fixed — witness is excluded from txid computation |
| Version | Always 1 | v1 or v2; v2 enables relative timelocks (BIP 68) |
3. Bitcoin Script
Bitcoin transactions are not locked to public keys directly. Instead, each output carries a small program called a locking script (scriptPubKey), and each input provides an unlocking script (scriptSig or witness data) that satisfies the locking condition. Bitcoin Script is the stack-based language in which these programs are written.
Script evaluation flow
The interpreter processes opcodes sequentially. It pushes data items onto the stack, then executes operations that consume and produce stack elements. If the stack’s top element is nonzero (true) after all opcodes have been processed, the spend is valid.
Common script patterns
| Pattern | Introduced | Locking mechanism | Typical use |
|---|---|---|---|
| P2PKH (Pay-to-Public-Key-Hash) | v0.1 (2009) | Hash of public key; spender provides key + ECDSA signature | Legacy addresses starting with 1 |
| P2SH (Pay-to-Script-Hash) | BIP 16 (2012) | Hash of a redeem script; spender provides the script + data satisfying it | Multisig, wrapped SegWit; addresses starting with 3 |
| P2WPKH (Pay-to-Witness-Public-Key-Hash) | BIP 141 (2017) | Witness program v0 with 20-byte key hash; signature in witness | Native SegWit addresses starting with bc1q |
| P2WSH (Pay-to-Witness-Script-Hash) | BIP 141 (2017) | Witness program v0 with 32-byte script hash; witness provides script + data | Native SegWit multisig and complex scripts |
| P2TR (Pay-to-Taproot) | BIP 341 (2021) | Witness program v1 with 32-byte tweaked public key; key-path or script-path spend | Taproot addresses starting with bc1p |
Script evolution: v0.1 to v27+
| Aspect | Satoshi era (v0.1) | Modern Bitcoin Core, v27+ baseline |
|---|---|---|
| Available opcodes | Full set including OP_CAT, OP_MUL, OP_LSHIFT, etc. | Many disabled (2010 security patch); tapscript (BIP 342) turns the disabled opcodes into OP_SUCCESSx, reserved for future soft forks |
| Script types | P2PK and P2PKH only | P2PKH, P2SH, P2WPKH, P2WSH, P2TR |
| Execution model | scriptSig + scriptPubKey concatenated and executed | Separated evaluation; witness programs have their own validation rules |
| Size limits | None at launch; the 10,000-byte script and 201-opcode limits came with v0.3.7 (July 2010) | Same base limits; tapscript relaxes sigop counting |
4. Signature schemes
Cryptographic signatures are the mechanism by which a spender proves they control the private key associated with a UTXO’s locking condition. Bitcoin has used two signature schemes across its history.
ECDSA vs Schnorr
| Property | ECDSA (secp256k1) | Schnorr (BIP 340) |
|---|---|---|
| Introduced | v0.1 (2009) | Taproot activation (2021) |
| Curve | secp256k1 | secp256k1 (same curve) |
| Signature size | 70-72 bytes (DER-encoded) | 64 bytes (fixed) |
| Verification | One equation per signature | One equation per signature; batch-verifiable |
| Key aggregation | Not natively supported | MuSig2 enables n-of-n aggregation into a single key and signature |
| Linearity | Non-linear — aggregation requires complex protocols | Linear — s₁ + s₂ is a valid signature for the combined key |
| Provable security | Relies on additional assumptions beyond DLP | Provably secure under the discrete logarithm assumption in the random oracle model |
| Library | Originally OpenSSL; migrated to libsecp256k1 | libsecp256k1 (same library, Schnorr module) |
Signing and verification flow
The spender constructs the transaction — its inputs, outputs, and locktime — before signing it; on the receiving side, a verifying node identifies the public key the spend must match before recomputing the digest: from the previous output’s locking script for Taproot’s key-path spend, or from the input’s own unlocking data for P2PKH and P2WPKH.
5. SegWit and Taproot
SegWit (Segregated Witness, 2017) and Taproot (2021) are the two major structural changes to Bitcoin’s transaction format since its creation. Both are backward-compatible soft forks. When Mt. Gox halted withdrawals in February 2014 it blamed transaction malleability, the flaw the fix below closes, but a study of the network over the preceding year found no widespread use of malleability attacks before the exchange closed.
Structural comparison
Key innovations
| Innovation | Mechanism | Benefit |
|---|---|---|
| Witness discount | Witness bytes are counted at 1/4 weight (1 WU instead of 4 WU) | Reduces effective fee for signature-heavy transactions; incentivizes moving data to the witness |
| Transaction malleability fix | Witness excluded from txid computation | Enables reliable transaction chains (prerequisite for Lightning Network) |
| Script versioning | Witness version field allows new script rules via soft fork | Future upgrades (Taproot itself uses witness v1) without breaking existing nodes |
| Key-path spend | Single Schnorr signature validates against the output key directly | Multisig, timelocks, and complex conditions all look like a single-key spend on chain — maximum privacy |
| Script-path spend (MAST) | Merkle tree of alternative scripts; only the executed branch is revealed | Complex contracts expose only the path used; unused branches remain private |
| Batch verification potential | Schnorr signatures are linearly aggregatable | Nodes can verify multiple signatures faster than checking each individually |
6. Coin selection
When a wallet builds a transaction, it must choose which UTXOs to spend as inputs. This is the coin selection problem. The choice affects transaction size (and therefore fees), privacy (which UTXOs become linked on chain), and the future shape of the wallet’s UTXO pool.
| Strategy | Approach | Trade-off |
|---|---|---|
| Largest-first | Pick the biggest UTXO that covers the payment | Simple; tends to consolidate. Creates large change outputs that reveal wallet balance. |
| Branch-and-bound (BnB) | Search for an exact-match combination (no change output needed) | Eliminates change output, saving ~34 bytes. Fails if no exact match exists. |
| Knapsack | Random selection targeting the payment amount + minimum change | Fallback when BnB fails. May produce dust change. |
| Coin control | User manually selects which UTXOs to spend | Maximum privacy control. Requires user expertise. |
| Waste metric (v23+) | Score candidates by current-vs-long-term fee cost and change cost | Balances immediate fee against future cost of spending the change UTXO later. |
Modern Bitcoin Core (v27+ baseline) runs several algorithms (BnB, knapsack, single random draw, and at high fee rates CoinGrinder) and keeps the result with the lowest waste. Satoshi’s v0.1 SelectCoins was the knapsack’s ancestor: an exact match if one existed, otherwise the best of 1,000 randomized subset-sum passes over the smaller coins, compared with the single smallest coin larger than the target.
7. Two-era comparison
| Feature | Satoshi era (v0.1, Jan 2009) | Modern Bitcoin Core, v27+ baseline |
|---|---|---|
| Value representation | UTXOs (unspent transaction outputs) | Same |
| Transaction format | Legacy (version + inputs + outputs + locktime) | SegWit (+ marker/flag + witness) |
| Transaction ID | SHA-256d of full serialized transaction | txid (excludes witness) + wtxid (includes witness) |
| Script types | P2PK, P2PKH | P2PKH, P2SH, P2WPKH, P2WSH, P2TR |
| Signature scheme | ECDSA via OpenSSL | ECDSA + Schnorr via libsecp256k1 |
| Signature size | 70-72 bytes (DER) | ECDSA: 70-72 bytes; Schnorr: 64 bytes (fixed) |
| Key aggregation | Not available | MuSig2 (n-of-n Schnorr aggregation) |
| Opcode availability | Full set (including later-disabled opcodes) | Reduced set; in tapscript the disabled opcodes become OP_SUCCESSx |
| Malleability | Vulnerable — scriptSig can be modified by third parties | Fixed — witness is excluded from txid |
| Weight / size limit | No per-transaction weight; block size limit added in 2010 | 400,000 WU max standard transaction weight |
| Timelocks | Absolute locktime only (block height or Unix time) | Absolute (locktime) + relative (BIP 68 sequence) + script-level (OP_CLTV, OP_CSV) |
| Replace-by-Fee | v0.1 let an unconfirmed transaction be replaced via nSequence (not a fee mechanism); Satoshi disabled it in an August 2010 commit released in v0.3.12, “just to reduce surface area”; first-seen policy afterward | Opt-in RBF (BIP 125, v0.12); -mempoolfullrbf option added v24.0; full RBF default since v28.0 |
| Fee estimation | None (transactions were free in practice) | estimatesmartfee — bucket-based mempool fee estimation |
| Coin selection | Exact match, else 1,000 randomized subset-sum passes or the smallest larger coin (the knapsack’s ancestor) | BnB, knapsack, single random draw and CoinGrinder, chosen by the waste metric |
| Cryptography library | OpenSSL | libsecp256k1 (constant-time, deterministic nonces) |
| UTXO storage | Berkeley DB | LevelDB with in-memory cache (coins cache) |
8. Limits of this page
This page covers the transaction layer in isolation. The following topics are out of scope and addressed in their respective domain pages within the design-document series:
- Block structure and Merkle trees — how transactions are batched into blocks and committed via Merkle roots.
- Mining and proof-of-work — the incentive mechanism that selects which transactions enter the blockchain.
- Mempool policy — relay rules, fee-rate floors, and package relay that govern transaction propagation before confirmation.
- Network-layer transaction relay — how
inv,getdata, andtxmessages propagate transactions across the P2P network. - Lightning Network and payment channels — layer-2 constructions that build on the transaction primitives described here.
- Wallet key derivation — BIP 32/44/84/86 HD key trees and descriptor wallets that generate the addresses used in locking scripts.
The transaction is the object every other design page touches. It is block contents in the block-chain design, the consumer of signatures and hashes in the cryptography design, the coinbase and fee mechanism in the monetary design, the propagation payload in the P2P network design, the UTXO-set update unit in the storage design, the constructed and signed object in the wallet design, and the unit the fee market and the Lightning Network operate on in the ecosystem design.
























