§ 19 · III Advanced · Expert · 11 min
Bitcoin Scripting
Your Bitcoin isn't sitting in a wallet. It's locked inside a tiny program — a few lines of code that say "to spend this, prove you have the right key." That program is written in Bitcoin Script, and understanding it is understanding Bitcoin at its deepest level.
Sources: Bitcoin Wiki — Script · lopp.net scripting
Programmable money: transaction scripts and smart contracts.
Sections 15–21 are technical. Each was drafted with Claude at Marius's direction and approved by Marius.
Bitcoin Script: The Programming Language Behind Every Transaction
Every Bitcoin transaction isn't just a value transfer — it's a script execution. Bitcoin Script is a simple, stack-based programming language that defines the conditions under which bitcoin can be spent. It's not Turing-complete (by design), but it's expressive enough to define complex spending conditions while remaining safe and predictable to execute on thousands of nodes simultaneously.
Stack-Based Execution
Bitcoin Script is a stack-based language — operations push data onto a stack or pop data off it to perform computations. A transaction is valid if, when the locking script (from the previous output) and the unlocking script (from the spending input) are executed together, the stack ends with a single TRUE value.
- scriptPubKey (locking script): Defines conditions to spend the output; set by the sender
- scriptSig (unlocking script): Provides data that satisfies the locking conditions; provided by the spender
- Witness (SegWit): Post-SegWit signature data stored separately from the transaction
P2PKH Script Execution: Step by Step
ScriptPubKey (Locking):
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
ScriptSig (Unlocking):
<signature> <publicKey>
Stack execution:
1. Push <signature> → Stack: [sig]
2. Push <publicKey> → Stack: [sig, pubKey]
3. OP_DUP → Stack: [sig, pubKey, pubKey]
4. OP_HASH160 → Stack: [sig, pubKey, hash(pubKey)]
5. Push <pubKeyHash> → Stack: [sig, pubKey, hash(pubKey), pubKeyHash]
6. OP_EQUALVERIFY → Hashes match! Stack: [sig, pubKey]
7. OP_CHECKSIG → Signature valid! Stack: [TRUE]
Script Execution: Unlocking a UTXO
Why Not Turing-Complete?
Satoshi deliberately made Bitcoin Script not Turing-complete — it has no loops. This means every script terminates, execution time is bounded, and nodes can safely validate scripts without risk of infinite loops or resource exhaustion. Ethereum chose Turing-completeness (with gas limits to prevent infinite loops artificially) — a different trade-off with different security properties. Bitcoin's approach prioritises safety and predictability.
"Bitcoin Script is simple by design. It handles its use cases perfectly and nothing else. That limitation is its strength." — Bitcoin developer philosophy
Want to go deeper?
Bitcoin OP_CODES: The Instructions That Execute Bitcoin's Logic
OP_CODEs (operation codes) are the instructions that make up Bitcoin Script. Each OP_CODE is a single byte that tells the Script interpreter to perform a specific operation: push data, check a signature, hash data, compare values, or control execution flow. There are currently 80+ active OP_CODEs in Bitcoin, each with a specific function in building spending conditions.
Key OP_CODEs to Know
- OP_DUP: Duplicates the top stack item — used in P2PKH to duplicate the public key before checking it against the address hash
- OP_HASH160: Performs SHA-256 then RIPEMD-160 on the top stack item — produces a 20-byte hash used in addresses
- OP_EQUALVERIFY: Checks two stack items are equal; fails the script if not
- OP_CHECKSIG: Verifies a digital signature against a public key and the transaction hash
- OP_CHECKMULTISIG: Verifies multiple signatures against multiple keys — enables multisig
- OP_CHECKLOCKTIMEVERIFY (CLTV): Fails if the transaction is broadcast before a specified block height or timestamp
- OP_CHECKSEQUENCEVERIFY (CSV): Relative timelock — fails if the output hasn't aged by a specified number of blocks
| OP_CODE | Hex | Function | Common Use |
|---|---|---|---|
| OP_DUP | 0x76 |
Duplicates the top stack item | P2PKH — duplicate pubKey before hashing |
| OP_HASH160 | 0xa9 |
SHA-256 then RIPEMD-160 of top item | P2PKH and P2SH — produce 20-byte address hash |
| OP_EQUAL | 0x87 |
Returns 1 if top two items are equal, 0 otherwise | P2SH — verify redeem script hash matches |
| OP_CHECKSIG | 0xac |
Verifies signature against pubkey and tx hash | P2PKH, P2WPKH, P2TR — standard single-sig spend |
| OP_CHECKMULTISIG | 0xae |
Verifies M-of-N signatures against N pubkeys | P2SH multisig — 2-of-3 corporate custody |
| OP_CHECKLOCKTIMEVERIFY | 0xb1 |
Fails if tx nLockTime is before specified value | Absolute timelocks — inheritance scripts, vaults |
| OP_CHECKSEQUENCEVERIFY | 0xb2 |
Fails if input sequence age is below specified value | Relative timelocks — Lightning HTLC channels |
| OP_IF | 0x63 |
Conditional execution — executes branch if top is TRUE | HTLC branching, Tapscript conditional spending paths |
Source: Bitcoin Wiki — OP_CODE reference
"OP_CODEs are the atoms of Bitcoin's programmable money. Combine them correctly and you can express almost any spending condition imaginable within Bitcoin's security model." — Bitcoin Script developer
Disabled OP_CODEs
Several OP_CODEs from Satoshi's original implementation were disabled early (OP_CAT, OP_MUL, etc.) due to potential security concerns. There's ongoing research and debate about re-enabling some of them — most notably OP_CAT, which enables concatenating stack items and unlocks powerful scripting capabilities. This debate will likely come to a head in upcoming protocol improvement discussions.
Want to go deeper?
Bitcoin Script Types: P2PKH, P2SH, P2WPKH, P2TR and More
Over Bitcoin's history, several standard script patterns have emerged — each building on the previous generation, improving privacy, efficiency, and functionality. Understanding these script types explains why Bitcoin addresses have different formats (1..., 3..., bc1q..., bc1p...) and why choosing the right address type matters for fees, privacy, and compatibility.
The Standard Script Types
- P2PK (Pay-to-Public-Key): Earliest form; spends directly to a raw public key. No longer recommended — public key is exposed before spending.
- P2PKH (Pay-to-Public-Key-Hash): Pays to a hash of a public key. "1..." addresses. Most common for many years; still widely used.
- P2SH (Pay-to-Script-Hash): Hides complex spending scripts until redemption. "3..." addresses. Enables multisig and other complex conditions.
- P2WPKH (Pay-to-Witness-Public-Key-Hash): SegWit P2PKH. "bc1q..." (bech32) addresses. Lower fees than P2PKH due to discounted witness data.
- P2WSH (Pay-to-Witness-Script-Hash): SegWit P2SH. "bc1q..." bech32. Discounted complex scripts.
- P2TR (Pay-to-Taproot): Taproot output. "bc1p..." (bech32m) addresses. Schnorr signatures; MAST; script paths indistinguishable from key paths on-chain.
"Each new script type in Bitcoin's history has been more efficient, more private, or more capable than the last. The progression from P2PKH to P2TR tells the story of Bitcoin's cryptographic maturation." — Bitcoin developer analysis
| Type | Introduced | Address Prefix | Typical Size (bytes) | Key Feature |
|---|---|---|---|---|
| P2PKH | 2009 | 1... |
~148 input / ~34 output | Standard single-key payment; public key hashed for privacy until spend |
| P2SH | 2012 (BIP 16) | 3... |
~295 input (2-of-3 multisig) / ~32 output | Hides complex scripts until redemption; enables multisig and custom conditions |
| P2WPKH | 2017 (SegWit) | bc1q... (bech32) |
~68 vbytes input / ~31 output | Segregated witness lowers fees; fixes transaction malleability |
| P2WSH | 2017 (SegWit) | bc1q... (bech32) |
~105 vbytes input (2-of-3) / ~43 output | SegWit equivalent of P2SH; discounted complex scripts in witness |
| P2TR | 2021 (Taproot) | bc1p... (bech32m) |
~57.5 vbytes input (key path) / ~43 output | Schnorr signatures; MAST script trees; cooperative spends look identical on-chain |
Sources: Bitcoin Wiki — Script · Bitcoin Stack Exchange — transaction sizes
Want to go deeper?
Timelocks: Programming Time into Bitcoin Transactions
Bitcoin Script includes the ability to lock outputs until a future point in time — either an absolute time (this output cannot be spent before block 800,000) or a relative time (this output cannot be spent until 144 blocks after it was confirmed). These timelock mechanisms are simple in concept but powerful in application — they underpin Lightning Network channels, payment escrows, vaults, and advanced custody arrangements.
The Four Timelock Mechanisms
- nLocktime (transaction-level): The entire transaction cannot be mined before a specified block height or Unix timestamp. The oldest timelock mechanism, used in basic delayed payments.
- OP_CHECKLOCKTIMEVERIFY / CLTV (BIP 65): Script-level absolute timelock. An output cannot be spent by a particular branch of the script until a specified block height or time.
- nSequence (input-level relative): An input can specify that it must be at least N blocks or N seconds old since the output it's spending was confirmed.
- OP_CHECKSEQUENCEVERIFY / CSV (BIP 112): Script-level relative timelock. The most flexible and widely used form in modern applications.
| Mechanism | Scope | Absolute / Relative | Granularity | Use Case |
|---|---|---|---|---|
| nLockTime | Transaction-level | Absolute | Block height or Unix timestamp | Delayed broadcast — tx cannot be mined before specified time |
| nSequence | Input-level | Relative | Blocks or 512-second intervals | Relative delay since UTXO confirmation; also signals RBF opt-in |
| OP_CLTV (BIP 65) | Script-level | Absolute | Block height or Unix timestamp | Lock script branch until specific block — inheritance, escrow |
| OP_CSV (BIP 112) | Script-level | Relative | Blocks or 512-second intervals | Lightning HTLC expiry, channel closing delays, vaults |
Sources: Bitcoin Wiki — Timelocks · BIP 65 · BIP 112
Timelocks in Lightning Network
Lightning Network's security relies critically on timelocks. Channel state updates use HTLC (Hash Time-Locked Contracts) — combining hashlock (must reveal a pre-image to claim) and timelock (if not claimed within N blocks, funds return to sender). This allows trustless routing across multiple payment channels, even through parties you don't trust.
"Timelocks turn Bitcoin from a system that can only transfer value now into one that can make credible commitments about the future. That's a qualitative change in what's possible." — Bitcoin developer insight
Want to go deeper?
Transaction Construction: Building a Valid Bitcoin Transaction
Every Bitcoin transaction you broadcast to the network is a precisely structured data object that must conform to Bitcoin's serialisation format. Understanding how transactions are constructed — from selecting UTXOs to calculating fees to signing inputs — turns Bitcoin from a mysterious process into a comprehensible mechanical system. This knowledge is essential for developers building Bitcoin applications.
Transaction Structure
A raw Bitcoin transaction contains:
- Version (4 bytes): Indicates which transaction format rules apply
- Inputs (variable): List of UTXOs being spent; each includes: previous TXID + output index + scriptSig + sequence
- Outputs (variable): List of new UTXOs created; each includes: value in satoshis + scriptPubKey (locking script)
- Locktime (4 bytes): Minimum block height/time before transaction is valid
- Witness data (SegWit only): Signatures and public keys stored separately from the transaction body
Transaction Fee Calculation
Bitcoin transactions don't have a fee field — the fee is implicit: the difference between the sum of input values and the sum of output values. Miners claim this difference as their fee reward.
Fee rate is measured in satoshis per virtual byte (sat/vB). A typical P2WPKH transaction is ~141 vbytes. At a fee rate of 10 sat/vB, the fee = 1,410 satoshis.
"Building a transaction from scratch teaches you more about Bitcoin in an hour than reading about it for a week. Computers don't care about abstractions — everything is bytes." — Bitcoin developer advice
Tools for Transaction Construction
- Bitcoin Core's CLI (bitcoin-cli) — raw transaction commands
- Sparrow Wallet — visual PSBT construction and signing
- bitcoin-dev libraries: bitcoinjs-lib (JS), python-bitcoinlib (Python), rust-bitcoin (Rust)
Want to go deeper?
Key Takeaways
- Bitcoin Script is a stack-based, non-Turing-complete language — deliberately limited to ensure safe, predictable, bounded execution on all nodes.
- OP_CODEs are single-byte instructions: OP_CHECKSIG verifies signatures, OP_CHECKLOCKTIMEVERIFY enforces absolute timelocks, OP_CHECKMULTISIG enables multisig.
- Script types have evolved from P2PK → P2PKH → P2SH → P2WPKH → P2TR, each generation more efficient, more private, or more capable.
- Timelocks (CLTV for absolute, CSV for relative) allow programming time-based spending conditions — essential for Lightning Network's security model.
- Transaction fees are implicit: the difference between total inputs and total outputs; measured in sat/vB for mempool prioritisation.
Related Reading
Mark as read
Frequently Asked Questions
What is Bitcoin Script?
Bitcoin Script is a simple, stack-based programming language used to define spending conditions for Bitcoin. Every transaction includes a script that specifies who can spend the output and under what conditions — from simple single-signature payments to complex multi-party contracts with timelocks.
What are OP_CODES in Bitcoin?
OP_CODES are the individual instructions in Bitcoin Script. They perform operations like checking signatures (OP_CHECKSIG), verifying timelocks (OP_CHECKLOCKTIMEVERIFY), and manipulating data on the stack. There are about 100 defined opcodes, though many are disabled for security reasons.
What is a timelock transaction?
A timelock transaction restricts when Bitcoin can be spent. CLTV (CheckLockTimeVerify) locks funds until a specific block height or date. CSV (CheckSequenceVerify) locks funds for a relative time period after confirmation. These enable features like payment channels, inheritance plans, and escrow contracts.
Continue Learning
See also: Bitcoin Glossary · Cryptography & Bitcoin · How Bitcoin Works
Further Reading
- Bitcoin scripting — lopp.net — Jameson Lopp's scripting resources.
- Script — Bitcoin wiki — Full OP_CODE reference.
- Bitcoin developer guide — Transactions and scripting explained.
- Transaction — Bitcoin wiki — Full transaction format documentation.
- Miniscript — Bitcoin Optech — structured approach to Bitcoin Script composition (Public Domain).
- Learning Bitcoin Script — Blockchain Commons — hands-on scripting tutorials from the CLI course (CC BY 4.0).
- Transaction Reference — developer.bitcoin.org — official Script and transaction documentation (MIT).
Claude drafted this text at Marius's direction and did the research Marius asked for; Marius reviewed and corrected it until approving it. Earlier versions were also researched with Perplexity. References curated from: Jameson Lopp (PD) · Mastering Bitcoin by A. Antonopoulos & D. Harding (CC BY-SA 4.0) · Blockchain Commons (CC BY 4.0) · Bitcoin Optech (PD) · developer.bitcoin.org (MIT).
Help Improve This Section
Have expertise on this topic? We welcome corrections, expansions, and translations. All content is CC BY-SA 4.0 licensed with full author credit. Suggested corrections are reviewed by Marius before anything goes live.
Email Your Contribution →