Script Language
Bitcoin's powerful transaction programming language
A Note from Satoshi
Long before I released Bitcoin, I recognized that a digital currency system needed more than just basic transactions. It would require a flexible, programmable foundation that could support evolving use cases while maintaining security and determinism.
The scripting system in Bitcoin wasn't an afterthought—it was a deliberate design decision. I chose a stack-based language with simple operations, drawing inspiration from Forth and other minimalist programming languages. This approach allowed for verification without the security risks of Turing-completeness.
Script is purposefully limited. It can't access the blockchain, previous transactions, or external data. It only answers one question: "Are the conditions for spending these coins satisfied?" This constraint is a feature, not a limitation. By narrowly focusing on validation logic, Script keeps the system secure and predictable while still enabling remarkable flexibility.
While many consider Bitcoin Script arcane or limited today, I built it with an eye to the future. Most of its capabilities remain dormant, waiting for creative minds to unlock new ways of defining ownership and conditional transfers that go far beyond what traditional financial systems can accomplish.
"The design supports a tremendous variety of possible transaction types that I designed in from the beginning. Anyone can create new transaction types by programming Bitcoin Script."
Technical Foundation
Bitcoin Script is a stack-based, non-Turing-complete language designed specifically for defining conditions that must be satisfied to spend Bitcoin. Unlike conventional programming languages, Script doesn't use variables, loops, or functions—it operates purely through stack manipulations and predefined operations.
Execution Model
Bitcoin Script uses a simple but powerful execution model:
- Scripts execute on a stack-based virtual machine
- Each operation (opcode) manipulates data on a single stack
- Data is processed in postfix notation (operators follow operands)
- Script execution is deterministic with no side effects
- A script succeeds if it completes without errors and leaves TRUE on the stack
Stack-Based Language
Bitcoin Script relies on a data structure called a stack, where elements can only be pushed onto or popped from the top:
// Stack operations example:
1 2 OP_ADD
Stack evolution:
[] -> [1] -> [1, 2] -> [3]
Locking Script (scriptPubKey)
Defines the conditions required to spend the bitcoin. Part of the transaction output.
Example: "Provide a public key hashing to X and a valid signature."
Unlocking Script (scriptSig)
Provides data satisfying the locking script. Part of the transaction input.
Example: "Here's my public key and signature."
Script Execution Process
When a transaction is validated, Bitcoin combines the unlocking and locking scripts:
Combine Scripts
The unlocking script (scriptSig) is concatenated with the locking script (scriptPubKey).
validation_script = scriptSig + scriptPubKey
Initialize Empty Stack
An empty stack is created.
stack = []
Execute Script
Executed left-to-right, each operation pushes data or manipulates the stack.
Operations:
- Push data
- Pop values, operate, push result
- Modify stack elements
- Conditional evaluation
Check Final State
Execution must complete without errors and leave a single TRUE value (non-zero) on the stack.
Standard Script Types
While Script allows complex conditions, most Bitcoin transactions use a few standard templates for efficiency and compatibility:
P2PKH (Pay-to-Public-Key-Hash)
The most common type. Locks coins to the hash of a public key.
Locking Script (scriptPubKey):OP_DUP OP_HASH160 <PublicKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Unlocking Script (scriptSig):<Signature> <PublicKey>
Requires a valid signature from the public key that hashes to the specified hash.
P2SH (Pay-to-Script-Hash)
Locks coins to the hash of another script (redeemScript).
Locking Script (scriptPubKey):OP_HASH160 <ScriptHash> OP_EQUAL
Unlocking Script (scriptSig):...arguments... <redeemScript>
Allows complex scripts (e.g., multisig) without burdening the UTXO set. The redeemScript itself is revealed and executed during spending.
P2WPKH (Pay-to-Witness-Public-Key-Hash)
SegWit version of P2PKH. Uses witness data.
Locking Script (scriptPubKey):0 <PublicKeyHash (20 bytes)>
Witness Data:<Signature> <PublicKey>
Moves signature data to the witness field, reducing transaction size and fixing malleability.
P2WSH (Pay-to-Witness-Script-Hash)
SegWit version of P2SH.
Locking Script (scriptPubKey):0 <ScriptHash (32 bytes)>
Witness Data:...arguments... <witnessScript>
SegWit equivalent for complex scripts, offering size and malleability benefits.
P2TR (Pay-to-Taproot)
Introduced with Taproot upgrade (BIP 341).
Locking Script (scriptPubKey):1 <OutputKey (32 bytes)>
Spending Path (Key or Script):
Key path or Script path spending using witness data.
Enhances privacy and efficiency. Allows spending via a key path (looks like P2PKH) or complex script paths (revealed only if used).
OP_RETURN
Creates provably unspendable outputs used for embedding data.
Locking Script (scriptPubKey):OP_RETURN <Data (up to 80 bytes)>
Allows small amounts of arbitrary data to be stored on the blockchain without polluting the UTXO set.
Script Evolution: SegWit and Taproot
Bitcoin Script has evolved through soft forks like Segregated Witness (SegWit) and Taproot, enhancing efficiency, privacy, and capabilities.
Segregated Witness (SegWit)
Introduced P2WPKH and P2WSH, moving signature data (witness) outside the main transaction block.
Taproot (BIP 341, 342)
Introduced P2TR, Schnorr signatures, and TapScript, further improving privacy and script capabilities.
Script Capabilities and Limitations
Bitcoin Script includes a broad set of operations but is intentionally limited for security and determinism.
Stack Operations
- OP_DUP, OP_SWAP, OP_DROP...
Arithmetic & Logic
- OP_ADD, OP_EQUAL, OP_BOOLAND...
Cryptographic
- OP_SHA256, OP_CHECKSIG, OP_CLTV...
Deliberate Limitations
No Loops:
Ensures termination, prevents DoS.
No State:
Self-contained, deterministic execution.
No Blockchain Access:
Validation independent of chain state.
Disabled Opcodes:
Precaution against potential exploits (e.g., OP_CAT).
Script Debugging and Analysis
Understanding script execution is crucial:
Script Tracing
Step-by-step execution showing stack changes:
OP_3: [3] OP_DUP: [3, 3] OP_ADD: [6]
Testing Resources
- Bitcoin Core tests
- Online debuggers
- btcdeb
Best Practices
Start Simple
Build complexity gradually
Test Thoroughly
Use testnet extensively
Consider Edge Cases
Verify all execution paths
Script Reference
Bitcoin Wiki: Script
Script Debugger
btcdeb