Bitcoin transaction design — UTXO model, Script, and signature schemes

Figures: Satoshi Nakamoto

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.

The transaction layer answers three questions:

  1. What is a coin? An unspent transaction output (UTXO) — not an account balance.
  2. What does a valid spend look like? A transaction that consumes existing UTXOs, proves authorization via cryptographic signatures, and creates new UTXOs.
  3. 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.

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

Coinbase reward or\ntransaction output

Block confirmed,\noutput added to UTXO set

Referenced as input\nin a new transaction

Removed from UTXO set,\nstored in undo data

Created

InUTXOSet

Spent

"Coin" = an entry in the UTXO set.

A wallet's "balance" is the sum

of all UTXOs it can unlock.

UTXO model vs account model

PropertyUTXO model (Bitcoin)Account model (Ethereum)
State representationSet of discrete unspent outputsMap of addresses to balances
SpendingConsume entire UTXOs, create new ones (including change)Debit sender balance, credit receiver balance
PrivacyEach transaction can use fresh addresses; outputs are unlinkable by defaultAddresses accumulate history; balance visible per account
Parallel validationInputs reference distinct UTXOs — transactions touching different UTXOs validate independentlyNonce ordering per account creates serial dependency
Double-spend detectionCheck that referenced UTXO exists and is unspentCheck that sender nonce is correct and balance sufficient
State sizeGrows with unspent outputs (~180 M UTXOs as of 2025)Grows with accounts and contract storage
Change outputsRequired when input total exceeds payment amountNot 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

Transaction

Inputs

Input 0 references

this output

Previous transaction

Output 0

0.7 BTC

locked to Alice

Outputs

Output 0

amount (satoshis)

scriptPubKey (locking script)

Output 1

(change back to sender)

amount

scriptPubKey

Version (4 bytes)

Input 0

prev txid + output index

scriptSig or witness

sequence

Input 1

...

Locktime (4 bytes)

Field-by-field breakdown

FieldSizeDescription
Version4 bytesTransaction format version. v1 is standard; v2 enables BIP 68 relative timelocks.
Marker + Flag2 bytesSegWit indicator (0x00 0x01). Absent in legacy transactions.
Input countvarintNumber of inputs.
InputsvariableEach input: previous txid (32 bytes) + output index (4 bytes) + scriptSig (variable) + sequence (4 bytes).
Output countvarintNumber of outputs.
OutputsvariableEach output: value in satoshis (8 bytes) + scriptPubKey (variable).
WitnessvariablePer-input witness stacks. Present only in SegWit transactions.
Locktime4 bytesEarliest time or block height at which the transaction may be included.

Satoshi era vs v27+ baseline: transaction format

AspectSatoshi era (v0.1)Modern Bitcoin Core, v27+ baseline
FormatLegacy: version + inputs + outputs + locktimeSegWit: version + marker/flag + inputs + outputs + witness + locktime
Witness dataDoes not exist; signatures embedded in scriptSigSegregated into the witness field (BIP 141)
Transaction IDSHA-256d of the entire serialized transactiontxid excludes witness data; wtxid includes it
MalleabilityPossible — third parties can alter scriptSig without invalidating the transactionFixed — witness is excluded from txid computation
VersionAlways 1v1 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

Yes

No

Unlocking script

(scriptSig / witness)

Combine and

push onto stack

Locking script

(scriptPubKey)

Execute opcodes

left to right

Top of stack

= true?

Spend authorized

Spend rejected

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

PatternIntroducedLocking mechanismTypical use
P2PKH (Pay-to-Public-Key-Hash)v0.1 (2009)Hash of public key; spender provides key + ECDSA signatureLegacy addresses starting with 1
P2SH (Pay-to-Script-Hash)BIP 16 (2012)Hash of a redeem script; spender provides the script + data satisfying itMultisig, 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 witnessNative 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 + dataNative 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 spendTaproot addresses starting with bc1p

Script evolution: v0.1 to v27+

AspectSatoshi era (v0.1)Modern Bitcoin Core, v27+ baseline
Available opcodesFull set including OP_CAT, OP_MUL, OP_LSHIFT, etc.Many disabled (2010 security patch); subset re-enabled via tapscript (BIP 342)
Script typesP2PK and P2PKH onlyP2PKH, P2SH, P2WPKH, P2WSH, P2TR
Execution modelscriptSig + scriptPubKey concatenated and executedSeparated evaluation; witness programs have their own validation rules
Size limits10,000 byte script, 201 opcode limitSame 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

PropertyECDSA (secp256k1)Schnorr (BIP 340)
Introducedv0.1 (2009)Taproot activation (2021)
Curvesecp256k1secp256k1 (same curve)
Signature size70-72 bytes (DER-encoded)64 bytes (fixed)
VerificationOne equation per signatureOne equation per signature; batch-verifiable
Key aggregationNot natively supportedMuSig2 enables n-of-n aggregation into a single key and signature
LinearityNon-linear — aggregation requires complex protocolsLinear — s₁ + s₂ is a valid signature for the combined key
Provable securityRelies on additional assumptions beyond DLPProvably secure under the discrete logarithm assumption in the random oracle model
LibraryOriginally OpenSSL; migrated to libsecp256k1libsecp256k1 (same library, Schnorr module)

Signing and verification flow

Verifier (node)TransactionSpenderVerifier (node)TransactionSpenderHold private key (k)Construct transactionHash the transaction data (sighash)Sign sighash with private key → signature (σ)Attach signature to input (scriptSig or witness)Broadcast transactionExtract public key (K) from locking scriptRecompute sighash from transaction dataVerify: does σ match K and sighash?Valid → accept into mempool

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.

Structural comparison

Taproot transaction (2021)

Version

Marker + Flag

Inputs

Outputs

(witness program v1)

Witness

(key-path: single Schnorr sig

script-path: control block + script)

Locktime

SegWit transaction (2017)

Version

Marker + Flag

Inputs

(scriptSig empty for native)

Outputs

(scriptPubKey)

Witness

(signatures moved here)

Locktime

Legacy transaction (2009)

Version

Inputs

(scriptSig contains signatures)

Outputs

(scriptPubKey)

Locktime

Key innovations

InnovationMechanismBenefit
Witness discountWitness 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 fixWitness excluded from txid computationEnables reliable transaction chains (prerequisite for Lightning Network)
Script versioningWitness version field allows new script rules via soft forkFuture upgrades (Taproot itself uses witness v1) without breaking existing nodes
Key-path spendSingle Schnorr signature validates against the output key directlyMultisig, 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 revealedComplex contracts expose only the path used; unused branches remain private
Batch verification potentialSchnorr signatures are linearly aggregatableNodes 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.

StrategyApproachTrade-off
Largest-firstPick the biggest UTXO that covers the paymentSimple; 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.
KnapsackRandom selection targeting the payment amount + minimum changeFallback when BnB fails. May produce dust change.
Coin controlUser manually selects which UTXOs to spendMaximum privacy control. Requires user expertise.
Waste metric (v27+)Score candidates by current-vs-long-term fee cost and change costBalances immediate fee against future cost of spending the change UTXO later.

Modern Bitcoin Core (v27+ baseline) uses a multi-strategy pipeline: attempt BnB first (changeless transaction), fall back to knapsack, and score all candidates using the waste metric to pick the lowest-cost option. Satoshi’s v0.1 used a simpler largest-first approach.

7. Two-era comparison

FeatureSatoshi era (v0.1, Jan 2009)Modern Bitcoin Core, v27+ baseline
Value representationUTXOs (unspent transaction outputs)Same
Transaction formatLegacy (version + inputs + outputs + locktime)SegWit (+ marker/flag + witness)
Transaction IDSHA-256d of full serialized transactiontxid (excludes witness) + wtxid (includes witness)
Script typesP2PK, P2PKHP2PKH, P2SH, P2WPKH, P2WSH, P2TR
Signature schemeECDSA via OpenSSLECDSA + Schnorr via libsecp256k1
Signature size70-72 bytes (DER)ECDSA: 70-72 bytes; Schnorr: 64 bytes (fixed)
Key aggregationNot availableMuSig2 (n-of-n Schnorr aggregation)
Opcode availabilityFull set (including later-disabled opcodes)Reduced set; tapscript re-enables selected opcodes
MalleabilityVulnerable — scriptSig can be modified by third partiesFixed — witness is excluded from txid
Weight / size limitNo per-transaction weight; block size limit added in 2010400,000 WU max standard transaction weight
TimelocksAbsolute locktime only (block height or Unix time)Absolute (locktime) + relative (BIP 68 sequence) + script-level (OP_CLTV, OP_CSV)
Replace-by-FeeNot implemented; first-seen policyOpt-in RBF (BIP 125, v0.12); -mempoolfullrbf option added v24.0; full RBF default since v28.0
Fee estimationNone (transactions were free in practice)estimatesmartfee — bucket-based mempool fee estimation
Coin selectionSimple largest-firstBnB + knapsack + waste metric pipeline
Cryptography libraryOpenSSLlibsecp256k1 (constant-time, formally audited)
UTXO storageBerkeley DBLevelDB 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, and tx messages 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.