How to Read Bitcoin Scripts? Locking Conditions and Spend Verification

 / 
6

To read Bitcoin scripts, the most direct starting point is to combine a transaction's input script and output script, then run them left to right on the same stack. The output script (scriptPubKey) is the locking condition, and the input script (scriptSig) or witness data is the unlocking material. The standard for passing verification is narrow: after execution ends, exactly one non-zero value must remain on the stack. If the stack is empty, the top value is 0, or more than one element remains, the script fails.

OKX Exchange
A leading global cryptocurrency platform,suitable for both beginners and experienced traders.
New user benefit: 20% off trading fees upon registration!!

A common misunderstanding is treating the locking script as "another way of writing an address." An address is just the encoded result of a locking script. The script itself is the real condition. Understanding scripts means understanding "what must be satisfied to spend this money," not memorizing address prefixes.

The Most Standard Example: How P2PKH Runs Step by Step

P2PKH is the script behind traditional addresses (starting with 1) and the best starting point for reading scripts. Its locking script is:

OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG

The unlocking script needs to provide a signature and a public key:

When miners verify, they first push the unlocking script onto the stack, then execute the locking script. The process is as follows:

  1. Push , stack: [sig]
  2. Push , stack: [sig, pubKey]
  3. OP_DUP duplicates the top of the stack, stack: [sig, pubKey, pubKey]
  4. OP_HASH160 hashes the top of the stack, stack: [sig, pubKey, hash160(pubKey)]
  5. Push from the locking script, stack: [sig, pubKey, hash160(pubKey), pubKeyHash]
  6. OP_EQUALVERIFY compares the top two values. If equal, it consumes them and continues; if not, the entire script fails. This step confirms that "the public key you provided actually hashes to the value specified in the locking script"
  7. Now the stack has [sig, pubKey] left. OP_CHECKSIG pops these two values and uses the public key to verify if the signature is valid. If valid, it pushes 1, stack: [1]

At the end, the stack has only one 1, so verification passes. If the signature is wrong, OP_CHECKSIG pushes 0, and the script fails.

The key checks here: OP_EQUALVERIFY blocks "public key mismatch," and OP_CHECKSIG blocks "invalid signature." Each check handles a different part; both are necessary.

P2SH: Locking the Hash of a Script, Not the Hash of a Public Key

P2SH solves the problem of "senders not wanting to care about what complex script the receiver uses." Its locking script is very short:

OP_HASH160 OP_EQUAL

The unlocking script needs to provide the original redeemScript (plus signatures and other data that satisfy that script), and the last step pushes the redeemScript onto the stack. When OP_EQUAL executes, it verifies that "the hash of the redeemScript you provided matches the in the locking script." After matching, the node will execute the redeemScript as a script again. That is the real signature check or condition check.

When reading P2SH scripts, you cannot just look at the locking script and think you understand the conditions. The locking script only tells you "a script with a certain hash is needed." The real spending conditions are in the redeemScript. If you see an address starting with 3, it corresponds to this structure.

After SegWit: Scripts Still Exist, but in the Witness

Native SegWit (P2WPKH, addresses starting with bc1q) has an even shorter locking script:

OP_0 <20-byte pubKeyHash>

It does not look like an "executable condition" but more like a version number plus some data. The actual signature and public key are placed in the transaction's witness field, not in the scriptSig. The verifying node recognizes OP_0 as a version 0 witness program, then follows the corresponding rules to take the signature and public key from the witness, uses them to match <20-byte pubKeyHash>, and verifies the signature.

When reading SegWit scripts, do not just stare at the scriptPubKey looking for OP_CHECKSIG. Part of the condition has been moved into the witness verification path. The locking script itself only tells the node "which set of rules to use for checking."

Taproot (P2TR, addresses starting with bc1p) goes even further. Its locking script is just a tweaked x-only public key:

OP_1 <32-byte tweaked pubkey>

If spending via the key path, the signature is verified directly with this public key, and on-chain it looks the same as a single signature. If spending via the script path, only one branch of the script tree is revealed. For ordinary readers, when you see a P2TR output, you should know that "the conditions may be hidden in a leaf of the script tree," not just in the locking script itself.

When Verification Fails, Where Is the Problem?

Script execution failure is not caused by a single reason. By checking in execution order, you can locate the specific step:

Stack state error: During execution, there are not enough elements on the stack to pop (for example, OP_CHECKSIG needs two elements but the stack only has one). The script fails immediately. This usually means the unlocking script did not provide complete data.

OP_EQUALVERIFY or OP_EQUAL fails: The public key hash does not match, or the redeemScript hash does not match. This means the unlocking script contains the wrong public key or script.

OP_CHECKSIG returns 0: The public key and hash match, but the signature verification fails. The signature may not correspond to the current state of this transaction, or the signature itself has been tampered with.

Multiple values remain on the stack after execution: Some scripts are written incorrectly, or the unlocking script pushed extra data, so the stack is not clean at the end. Bitcoin requires exactly one non-zero value. Even one extra element means failure.

A practical habit: if you see a spend marked as invalid in a block explorer, first look at the combined result of scriptSig and scriptPubKey, then see what remains on the stack at the end. Most problems are caused by "wrong data provided," not the script itself being written incorrectly.

Two Habits Worth Developing When Reading Scripts

First identify the type, then look at details. If you see OP_DUP OP_HASH160 ... OP_EQUALVERIFY OP_CHECKSIG, you know it is P2PKH. If you see OP_HASH160 ... OP_EQUAL and the end of the unlocking script contains script data, you know it is P2SH. If you see OP_0 <20 bytes>, you know it is P2WPKH. Once the type is determined, the general framework of the verification path is determined.

Distinguish "locking" from "spending". The locking script is fixed when the UTXO is created. The spending script is what you provide when you spend the money. To read the conditions corresponding to an address, read the locking script. To judge whether a spend can pass, combine the unlocking script and the locking script and run them together. Do not mix the two.

If you have a specific script string in hand, you can first split it opcode by opcode, mark which parts are pushed data and which are operators, then walk through the stack changes. The place where it cannot proceed is where verification will fail.

OKX Exchange
A leading global cryptocurrency platform,suitable for both beginners and experienced traders.
New user benefit: 20% off trading fees upon registration!!

References

  1. Bitcoin Wiki·Script
  2. Bitcoin Core Onboarding·Script Appendix
  3. Bitcoin Wiki·Segregated Witness
  4. Narayanan et al.·Bitcoin and Cryptocurrency Technologies (P2SH chapter)
  5. BYDFi·Bitcoin Scripting in 2026: How Taproot Rewrote the Rules
  6. IACR eprint·Bitcoin Script Execution (P2PKH stack process table)