liberlume-content-v3
lang: en
title: Bitcoin's locks
summary: Every coin on Bitcoin sits behind a lock: the scriptPubKey, the program that states under which conditions it can be spent. A reference piece on the lock types, from the first outputs of 2009 to Taproot and the quantum-resistant proposals: P2PK, P2PKH, bare multisig, P2SH, SegWit (P2WPKH and P2WSH), P2TR, each shown byte by byte on a real transaction verifiable with a node. What each type exposes of the public key, why a lock and an address are not the same thing, and how to read the language of scripts: pushes, ops and the stack.
btc-anchor: 961200,000000000000000000011cfa417c07445190afe0a7be85c1c3d8d3ffaf119931
prev: sha256:6e0590b74dd1550cdb0ba04d1b0ad8536521e2aa94ec5ad606443d8e1a800643
--- body ---
Every coin on Bitcoin sits behind a lock: a small program, the scriptPubKey,
that states under which conditions the coin can be spent. Spending means
presenting what the lock asks for, normally a signature proving possession of
the right key. The lock types are few, born one after another along the
history of the protocol, and each answers the same question in its own way:
**how much of what locks the coin can be seen from the outside**. Some locks
place the public key in the clear on the output from the first instant; others
expose only its hash, and the key shows only when the coin moves. That is what
this piece looks at: what shape the locks have, how they changed, what tells
one from another.
This text stays at the overview level: the chronology of the types, the tables
that line them up, and the byte form of each lock. How a whole transaction is
actually built and signed, its format piece by piece, is matter for a second,
more technical pass. Readers arriving from the pieces on
[quantum computing](/en/bitcoin-and-quantum-computing/) and its
[measured numbers](/en/bitcoin-and-quantum-computing-data-july-2026/) will
find here the mechanism those pieces take as known.
## A lock and an address are not the same thing
Best to clear this up right away, because it is the most common
misunderstanding. The lock is the scriptPubKey, the script that sits on the
output and fixes its spending conditions. The **address** is not the lock: it
is just a compact way of writing it, an encoding designed to fit in a message,
with an integrity check that keeps a mistyped character from slipping through.
From an address the wallet derives the lock to put on the output; on the
ledger there are no addresses, there are scripts.
Keeping the two apart explains several asymmetries. Some lock types have no
address of their own (the oldest ones). Different encodings coexist at the
same time, one per family of locks. And the very same address, reused to
receive twice, produces two outputs with the same lock: when the first is
spent, the key becomes public, and the second finds itself uncovered without
anyone having touched it.
## The language of locks
A lock is a program, and the language it is written in is called Script: a
sequence of instructions, the **ops** (opcodes), executed on a stack of data.
Whoever spends presents their unlocking data, normally a signature and a key,
sometimes a whole script; nodes put that data on the stack and then run the
lock: if "true" is left on the stack at the end, the spend is valid. That is
all: there is no gatekeeper deciding, there is a program that every node in
the world re-runs and that gives everyone the same outcome.
When a block reaches a node, the checks run in a precise order, from cheapest
to most expensive: first the header and the proof-of-work, which cost one
hash; then the shape of the block; then, for each transaction, that the coins
being spent really exist and are not already spent; and only at the end are
the locks executed, that is, the signatures verified. It is the step that
costs the most, and it comes last on purpose: whoever sends garbage is stopped
before making everyone pay for it. For many transactions, moreover, the node
has already done that work when it saw them go by, and it remembers. The locks
in this piece are that last link.
The allowed operations are few and concrete: putting data on the stack,
duplicating and comparing it (`OP_DUP`, `OP_EQUAL`), computing its hash
(`OP_HASH160`, `OP_SHA256`), verifying signatures (`OP_CHECKSIG`,
`OP_CHECKMULTISIG`), opening a branch (`OP_IF`), binding the spend to time
(`OP_CHECKLOCKTIMEVERIFY`, `OP_CHECKSEQUENCEVERIFY`). Loops are missing on
purpose: a script cannot repeat itself, so every verification is certain to
end and costs a predictable amount of time. In 2010, after some flaws were
found, part of the ops were disabled (`OP_CAT` and others): the language has
been narrower than it was born ever since.
The families, in a table; the locks of the chronology all live in the first
five rows.
| family | main ops | what they are for |
|---|---|---|
| constants and pushes | `OP_0`…`OP_16`, the direct pushes | putting data on the stack (signatures, keys, hashes) |
| stack | `OP_DUP`, `OP_DROP`, `OP_SWAP` | duplicating and reordering what sits on top |
| comparison | `OP_EQUAL`, `OP_EQUALVERIFY` | comparing the two elements on top |
| hash | `OP_HASH160`, `OP_SHA256` | computing hashes |
| signatures | `OP_CHECKSIG`, `OP_CHECKMULTISIG` (in tapscript: `OP_CHECKSIGADD`) | verifying signatures against keys |
| flow | `OP_IF` / `OP_ELSE` / `OP_ENDIF`, `OP_VERIFY`, `OP_RETURN` | branches, halts, outputs declared unspendable |
| time | `OP_CHECKLOCKTIMEVERIFY`, `OP_CHECKSEQUENCEVERIFY` | binding the spend to a height or a delay |
| arithmetic (reduced) | `OP_ADD`, `OP_SUB`, the numeric comparisons | small sums on small numbers |
| disabled (2010) | `OP_CAT`, `OP_MUL`, `OP_LSHIFT`… | removed after the flaws; some are being discussed again today |
Best seen on a real lock. This is P2PKH, the lock of addresses starting with
`1`, taken from the most famous of payments (the ten thousand pizza bitcoins,
2010), byte by byte:
The P2PKH lock byte by byte: the scriptPubKey of output 0 (10,000 BTC) of a real transaction, the 10,000 BTC output of the pizza transaction, block 57043 (2010). Boxes: blue = ops, yellow = data, grey = length; the numbers above the boxes are their byte counts. Verifiable with getrawtransaction a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d.
Each box is a byte, or a group of bytes, with its hexadecimal value inside and
the byte count above. Blue boxes are **ops**, the instructions; yellow ones
are **data**; grey ones are a special kind of byte, the **push**, worth
pausing on because it returns in every lock. A push byte orders nothing: it
declares "the next N bytes are data, put them on the stack as they are". The
grey `14`, for instance, is the number twenty, and announces that twenty bytes
follow, the hash of the key. This is how the script separates data from
instructions without ambiguity: a value is never mistaken for a command,
because its push always introduces it.
Before following an execution, it is worth making clear who brings what,
because not everything comes from whoever spends.
The node already has the lock. Whoever spends does not send it: it is written
on the output of an earlier transaction, normally confirmed some time before,
and every node keeps it in the UTXO set, the collection of all coins spendable
at that moment. The spending transaction merely points at it, saying which past
transaction and which of its outputs. It could not be otherwise: if the lock
came from whoever spends, everyone would bring their own.
Only one thing arrives from outside, the unlocking data: it travels inside the
spending transaction, in the scriptSig, and from SegWit onwards in a separate
area of the transaction, the witness.
And the message, the text the signature is verified against, does not travel at
all. It is the spending transaction reduced to a number by fixed rules, rules
that leave the unlocking data out: if they included it, the signature would
have to cover itself. Whoever signs computes it before signing, the node
recomputes it on its own from what it received, and the two numbers match only
if the transaction has stayed the same. Nobody transmits it because nobody
needs to receive it: both sides have the transaction.
One thing stays outside all this, the private key, which appears neither in the
lock, nor in the unlocking data, nor in the message.
How much whoever spends has to bring depends on the type of lock: where
there is a hash the key must be shown, because the node does not have it; where
the key is already there, the signature is enough.
Ops do not "fire" on call: the script is walked left to right, one element at
a time, and each op acts when its turn comes, on what the previous steps left
on the stack. First, though, the unlocking data is stacked: whoever spends
puts their signature and their key up front, and only then does the lock run.
Unlock first, lock after, on the same stack. In the P2PKH above the order is
this:
1. the unlocking data goes on the stack: the signature and the public key;
2. `OP_DUP` duplicates the key, `OP_HASH160` computes its hash;
3. `OP_EQUALVERIFY` compares that hash with the twenty bytes written in the
lock: if they do not match, execution stops here and the spend is void;
4. `OP_CHECKSIG` verifies the signature against the key: if it holds, it
leaves "true" on the stack and the spend is valid.
These are the four ops and the single push that can be read in the strip,
executed in that order.
Step 4 deserves a closer look, because that is where the mechanism closes.
`OP_CHECKSIG` does not compare two values: it rebuilds the text the signature
was meant to cover, that is, the transaction reduced to a number by fixed
rules, and then verifies that a certain relation holds between that number,
the public key and the two numbers of the signature. The relation holds only
if the signer possessed the private key, and holds only for that transaction:
the same signature, moved onto another one, would not. Which parts of the
transaction enter the count is declared by the signature itself, with one byte
at its tail.
What the check establishes stops there, though: that the signer possessed the
key at that moment, and consented to that spend. Not who they were, not
whether the key was theirs alone, not whether it had been taken from them. On
Bitcoin ownership is defined exactly like this, as possession of the key, and
the lock has no way of looking further.
Then there is a limit of the same kind: `OP_CHECKSIG` judges the signature it
receives, not the way it was produced. That side has conditions of its own
too, all on the signer's side: the most delicate one concerns the
[**nonce**](/en/signature-nonce/), the number every signature consumes exactly
once and that must never repeat.
One question about the language remains, and it carries all that follows: if
it allows arbitrary combinations, why are the lock types a handful? Because
nodes, when deciding whether to relay a transaction, recognize a few fixed
shapes, the **standard** scripts: outside those shapes a lock can be valid
under consensus rules yet travel poorly on the network. The types in the next
table are precisely those shapes, and their chronology is the story of how the
list grew longer. Over time *where* the unlocking data lives has changed as
well (inside the body of the transaction, then in a section of its own: more
under SegWit), but the stack mechanism has stayed the same.
## A handful of types
Before the chronology, the overview. This table is for consulting, not
studying: it pays to come back to it while reading the sections that follow.
| lock | shape (schematic) | address | when the key shows |
|---|---|---|---|
| **P2PK** | ` OP_CHECKSIG` | none | at once: the key is already on the output |
| **P2PKH** | `OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG` | `1…` | at the first spend |
| **bare multisig** | `m n OP_CHECKMULTISIG` | none | at once: the keys are on the output |
| **P2SH** | `OP_HASH160