Skip to content

Locking & Unlocking: scriptPubKey & scriptSig

We’ve said an output carries a “lock” and an input carries the “key.” It’s time to make that precise, because it is the mechanism by which ownership exists in Bitcoin at all. There are no accounts to authenticate against and no login. Instead, each coin embeds its own spending condition, and to spend it you must supply data that satisfies that condition. Ownership is not a record — it is the ability to answer a challenge.

Every spend involves two pieces of script that come from two different transactions:

created earlier: spent now:
┌────────────────────┐ ┌─────────────────────┐
│ OUTPUT │ │ INPUT │
│ scriptPubKey ◄────┼─────────┤ scriptSig / witness│
│ (the LOCK) │ unlocks │ (the KEY / PROOF) │
└────────────────────┘ └─────────────────────┘
  • scriptPubKey — the locking script, attached to an output when it is created. It encodes the challenge: a condition that any future spender must meet. The classic condition is “provide a signature valid for public key K.”
  • scriptSig (legacy) or the witness (SegWit) — the unlocking script, supplied by the input that spends the output. It is the response: the data that satisfies the challenge, typically <signature> <publicKey>.

The crucial asymmetry: the lock is set by whoever received the coin (it commits to their key), and it can only be opened later by whoever holds the corresponding secret. The receiver dictates the terms; the spender must meet them.

Think of scriptPubKey as a riddle written on the coin and scriptSig/witness as the answer shouted by the spender. To validate a spend, a node combines the two and runs the result through the Bitcoin Script interpreter. If the program finishes with true on top of the stack, the answer satisfied the riddle and the spend is authorized:

[ unlocking script ] + [ locking script ]
(response) (challenge)
Script interpreter
┌────────────┴────────────┐
ends TRUE ends FALSE / fails
spend is VALID spend is REJECTED

In other words: a coin is spendable by exactly whoever can make its locking script evaluate to true. “Owning” a Bitcoin is nothing more, and nothing less, than being able to construct an unlocking script that the locking script accepts.

Because the challenge is a small program, the lock can be much richer than “one signature.” A few shapes you’ll meet again:

Lock says…Spender must provide…
“signature for key K”a signature from K’s private key
”signature for the hash of key K” (P2PKH)the public key and a matching signature
”M of these N signatures” (multisig)any M valid signatures from the N named keys
”reveal a secret R where SHA256(R) = H” (hashlock)the preimage R
”not before block height T” (timelock)a spend that respects the height

These primitives compose. An HTLC is a lock with two answerable paths — “show the secret” or “wait for the refund time.” The expressiveness of the lock is what makes Bitcoin programmable money rather than a fixed payment rail — but, as the next page explains, it is deliberately limited for safety.

Where the proof lives: scriptSig vs witness

Section titled “Where the proof lives: scriptSig vs witness”

For legacy outputs the unlocking data sits in scriptSig, inside the part of the transaction hashed into the txid — which is what made early txids malleable. SegWit moved the unlocking data into a separate witness structure that is excluded from the txid, fixing malleability and discounting the witness’s contribution to transaction weight. Functionally both are “the response to the challenge”; they differ only in where the bytes are stored and whether they affect the id. The exact byte placement and which signed data the proof commits to is governed by SIGHASH flags.

How does locking/unlocking help untrusting strangers agree on one ledger? It turns “who may spend this coin?” into a self-contained, verifiable computation that needs no trusted party. The coin carries its own rules; the spender carries the proof; every node runs the same interpreter and reaches the same verdict — true or false, valid or invalid. No node consults an account database, asks a server, or trusts the spender’s say-so. Ownership becomes an objective, locally-checkable fact, and that objectivity is exactly what lets mutually distrusting strangers agree, transaction by transaction, on a single shared ledger.

  1. Which script is the “lock” and which is the “key”? Which transaction does each come from?
  2. In one sentence, what does it mean to own a Bitcoin, in terms of scripts?
  3. Why are the unlocking and locking scripts run in two stages rather than simply concatenated?
  4. Give two different conditions a scriptPubKey can encode beyond “one signature.”
  5. What is the difference between putting the unlocking data in scriptSig vs the witness, and why does it matter for the txid?