◆ Subject Brief

The opcode behind OP_IF — every place it shows up.

A complete map of 0x63: the conditional plumbing that powers HTLCs, every Lightning channel ever opened, the Ordinals envelope, vault proposals, and a dozen more script patterns scattered across Bitcoin's history.

12
Production patterns
80M+
Mainnet appearances
0x63
Single byte
2009
In Bitcoin since block 0

01The opcode

PropertyValue
OpcodeOP_IF = 0x63
CompanionsOP_NOTIF (0x64), OP_ELSE (0x67), OP_ENDIF (0x68)
Disabled siblingsOP_VERIF (0x65), OP_VERNOTIF (0x66) — fail script if encountered, even inside an unexecuted branch
SemanticsPop top of stack. If non-zero, execute <then>; otherwise execute <else> if present. OP_NOTIF inverts.
ActivatedOriginal Bitcoin Script (block 0, January 2009)
Tapscript changeBIP 342 §"MINIMALIF": the popped value must be exactly the empty array (false) or 0x01 (true). Arbitrary truthy values fail at consensus, not just relay.

OP_IF is the foundational branching primitive in Bitcoin Script. Every script that admits more than one spending path uses OP_IF or its sibling OP_NOTIF.

02Pattern catalog

The 12 distinct production patterns that use OP_IF on Bitcoin mainnet — from a 2-byte plain conditional to the 853-byte tapscript leaves carrying every Ordinal inscription.

1
The plain two-branch script
<witness chooses 1 or empty>
OP_IF
   <branch A — pubkey + OP_CHECKSIG>
OP_ELSE
   <branch B — different pubkey or hash check>
OP_ENDIF

The spender selects which branch executes by pushing 1 (or any truthy value) or an empty bytestring before the script runs. This is the foundational pattern; everything below is a specialization.

↳ txbook · ch02 §2.4 + ch16 Exercise C1
2
HTLC — Hashed Time-Locked Contract

The single most consequential OP_IF pattern in Bitcoin's history. An HTLC says: "Either the recipient produces the preimage of a known hash and takes the funds, or after a timeout the sender can reclaim them."

OP_IF
    OP_SHA256 <H = SHA256(preimage)> OP_EQUALVERIFY
    <recipient_pubkey> OP_CHECKSIG
OP_ELSE
    <expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
    <sender_pubkey> OP_CHECKSIG
OP_ENDIF

Powers:

  • Atomic swaps (Bitcoin ↔ Litecoin, Bitcoin Cash, etc.) — same preimage on two chains, different recipients on each side
  • Submarine swaps (on-chain ↔ Lightning) — Loop, Boltz
  • Pre-Lightning payment channels (Spillman, Decker–Wattenhofer)
  • Cross-chain bridges that don't require federations
↳ txbook · ch16 §16.3.3
3
Lightning to_local output

Every commitment transaction in every Lightning channel ever opened has one of these. Encodes "either the counterparty proves I cheated and steals everything (revocation), or I wait to_self_delay blocks and take my own money (delayed self-spend)."

OP_IF
    # Revocation: counterparty has the secret if we breached
    <revocationpubkey>
OP_ELSE
    # Honest delayed self-spend
    <to_self_delay> OP_CHECKSEQUENCEVERIFY OP_DROP
    <local_delayedpubkey>
OP_ENDIF
OP_CHECKSIG

Witness paths:

  • Revocation: push <revocation_sig> then <1> to take the OP_IF branch.
  • Self-spend: push <local_delayed_sig> then <> (empty) to take OP_ELSE.
↳ txbook · ch18 §18.4
4
Lightning offered HTLC

When a Lightning node forwards a payment, the outgoing-direction HTLC output has a nested OP_IF/OP_NOTIF. Three spending paths in one script.

OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
    OP_CHECKSIG                                # Path 1: revocation
OP_ELSE
    <remote_htlcpubkey> OP_SWAP
    OP_SIZE 32 OP_EQUAL
    OP_NOTIF
        # Path 2: HTLC-timeout (we reclaim after timelock)
        OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
    OP_ELSE
        # Path 3: peer claims with preimage
        OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
        OP_CHECKSIG
    OP_ENDIF
OP_ENDIF
This script alone has spawned more papers about Lightning protocol bugs (pinning, replacement-cycling, anchor races) than any other piece of Bitcoin Script.
↳ txbook · ch18 §18.5
5
Lightning received HTLC

Mirror of Pattern 4 for the receiving side of a forwarded payment. Same nested-OP_IF shape with paths reversed:

OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
    OP_CHECKSIG                                # revocation
OP_ELSE
    <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
    OP_IF
        # HTLC-success (we provide preimage)
        OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY
        2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
    OP_ELSE
        # Peer reclaims after timeout
        OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
        OP_CHECKSIG
    OP_ENDIF
OP_ENDIF
↳ txbook · ch18 §18.5
6
Lightning anchor outputs

Uses OP_IFDUP + OP_NOTIF (the sibling family). Anchor outputs let either party CPFP the commitment transaction without needing both signatures.

<funding_pubkey> OP_CHECKSIG OP_IFDUP
OP_NOTIF
    OP_16 OP_CHECKSEQUENCEVERIFY
OP_ENDIF

Reads as: "if you own the funding key, spend immediately; otherwise wait 16 blocks." OP_IFDUP keeps the value on the stack only when truthy — the trick that fits this in 30-something bytes.

↳ txbook · ch18 §18.7
7
Multipath escrow

A general two-path pattern: 2-of-3 multisig or 1-of-1 after timeout. Used by Bisq escrow, OpenBazaar, Lightning Loop, hosted-custody services with timeout fallback.

OP_IF
    # Cooperative — any 2 of {buyer, seller, arbiter}
    2 <buyer> <seller> <arbiter> 3 OP_CHECKMULTISIG
OP_ELSE
    # Buyer alone after timeout
    <expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
    <buyer> OP_CHECKSIG
OP_ENDIF
↳ txbook · ch16 Exercise C1
8
Vault scripts

Proposed but not activated as of 2026. Vaults use OP_IF to express "either trigger the unvault delay path, or sweep to cold storage immediately."

OP_IF
    <unvault_template_hash> OP_CHECKTEMPLATEVERIFY OP_DROP
    <unvault_delay> OP_CSV OP_DROP
    <hot_pubkey> OP_CHECKSIG
OP_ELSE
    <cold_pubkey> OP_CHECKSIG
OP_ENDIF

Status: BIP 119 (OP_CHECKTEMPLATEVERIFY), BIP 345 (OP_VAULT), and related covenant proposals are in active discussion. None has activated.

↳ txbook · ch20 (passing mention)
9
The Ordinals envelope — OP_FALSE OP_IF

The most surprising use of OP_IF in Bitcoin: it's the load-bearing structure of every Ordinals inscription, every BRC-20 token, every recursive inscription, every Runestone commitment that uses Tapscript-based metadata.

<inscriber_pubkey> OP_CHECKSIG
OP_FALSE
OP_IF
    OP_PUSH "ord"
    OP_PUSH 0x01
    OP_PUSH "image/png"           # MIME type
    OP_PUSH 0x00
    OP_PUSH <…content bytes…>
OP_ENDIF

The trick: OP_FALSE ensures the OP_IF branch is never executed. But the Script parser still reads the bytes inside to find the matching OP_ENDIF. So all the data pushes are syntactically present but semantically dead. The transaction signature only needs to satisfy OP_CHECKSIG at the top — the envelope is purely a witness-data carrier.

Why this works only inside Tapscript: the inscription is the script-path leaf of a Taproot output (P2TR, BIP 341/342). The witness discount means each byte costs 1 WU instead of 4 WU, making it economically viable to carry kilobytes of data. Pre-Taproot scripts have a hard 10,000-byte size limit and no witness discount.

↳ txbook · ch19 §19.2
10
Conditional Schnorr multipath (Tapscript era)

Post-Taproot, many multipath conditions migrate from OP_IF to Taproot script-tree leaves — different leaves of the merkle tree replace different OP_IF branches, and the whole tree commitment is the merkle root. This is better than OP_IF for privacy: only the leaf actually spent gets revealed; unused branches stay hidden.

OP_IF still gets used inside individual leaves when the branching isn't worth its own leaf (e.g., a small revocation path bolted onto a single leaf).

↳ txbook · ch12 §12.4
11
Discreet Log Contracts (DLCs)

DLCs use OP_IF only minimally — most of the conditional logic is encoded outside the script via adaptor signatures and Contract Execution Transactions (CETs). The on-chain OP_IF usage is in the refund path:

OP_IF
    <2-of-2 between Alice and Bob>
OP_ELSE
    <refund_locktime> OP_CLTV OP_DROP
    <2-of-2 same pubkeys>
OP_ENDIF

The interesting part of a DLC happens off-chain in adaptor-signature land; on-chain the script is mundane.

12
Old payment channels (Spillman, CLTV-based)

Pre-Lightning, Mike Hearn's Spillman channels and Jeremy Spilman's CLTV refund construction:

OP_IF
    2 <alice> <bob> 2 OP_CHECKMULTISIG
OP_ELSE
    <refund_locktime> OP_CLTV OP_DROP
    <alice> OP_CHECKSIG
OP_ENDIF

Effectively dead in practice (replaced by Lightning), but historically significant — these were the proof of concept that taught the community payment channels could work on Bitcoin without consensus changes.

↳ txbook · ch18 §18.1

03Sibling opcodes

Wherever OP_IF appears, you may also see:

OpcodeHexUsed in
OP_IF0x63Patterns 1–5, 7–9, 11–12
OP_NOTIF0x64Patterns 4 (offered HTLC), 6 (anchors)
OP_ELSE0x67All multi-branch patterns
OP_ENDIF0x68All — required to close every OP_IF/OP_NOTIF
OP_VERIF0x65Disabled — fails script unconditionally
OP_VERNOTIF0x66Disabled — same

The disabled cousins fail even inside an unexecuted OP_IF branch (per BIP 16 mandatory script flags). This is unusual: most invalid opcodes only fail when actually executed.

04Verified specimen — Inscription #0

The cleanest single example of OP_IF in production: Inscription #0, the first Ordinal ever, mined by Casey Rodarmor on December 14, 2022.

txid6fb976ab49dcec017f1e201e84395983204ae1a7c2abf7ced0a85d692e442799
Block767,430
Date2022-12-14 20:32 UTC
Size1,040 bytes total · 1,286 WU · 321.5 vbytes
Output typeP2TR (Taproot)
Witness3 items: 64-byte Schnorr sig, 853-byte tapscript leaf (containing the envelope), 33-byte control block
ContentA 793-byte pixel-art skull (image/png), inscribed inside OP_FALSE OP_IF … OP_ENDIF

The 853-byte tapscript leaf is structured exactly as Pattern 9 above: a <schnorr-pubkey> OP_CHECKSIG lead, then OP_FALSE OP_IF, then the Ordinals envelope ("ord" marker + content-type tag + content data), then OP_ENDIF. Every Ordinal minted since (80+ million as of 2026) follows this exact pattern.

05Where each pattern lives in the txbook

ChapterOP_IF use covered
ch02 — The Script MachineOpcode introduction; minimalif rule
ch12 — TaprootTapscript MINIMALIF rule; script-tree as OP_IF alternative
ch13 — TapscriptOP_IF inside leaves; Tapscript dialect restrictions
ch16 — TimelocksHTLC primitive, multipath escrow exercise
ch18 — LightningAll four BOLT 3 outputs (to_local, offered/received HTLC, anchor)
ch19 — OrdinalsThe OP_FALSE OP_IF envelope
ch20 — RunesRunestone commitment vs. inscription envelope
appA — Opcode ReferenceFull OP_IF / OP_NOTIF / OP_ELSE / OP_ENDIF spec rows

06Note on "every transaction"

Counting individual on-chain transactions containing OP_IF is intractable and not useful: the opcode is plumbing. Order-of-magnitude estimates as of April 2026:

PatternApprox. mainnet usage
Lightning channel closures (commitment txs + HTLC txs)100,000+
Ordinals inscriptions80M+
Atomic swapslow thousands
CPFP/anchor commitmentshigh thousands
Multipath escrow (Bisq, OpenBazaar)tens of thousands

Total OP_IF appearances on mainnet are in the tens of millions, but virtually all of them fall into one of the 12 patterns above. The thing that distinguishes them is the surrounding script — the OP_IF itself is just the conditional plumbing.

07Specifications

SpecWhere to read it
Original Bitcoin ScriptBitcoin v0.1 source, January 2009 — script.cpp
BIP 16 (P2SH)github.com/bitcoin/bips · bip-0016 — mandatory script flags
BIP 65 (CLTV)github.com/bitcoin/bips · bip-0065 — used by HTLCs and vaults
BIP 112 (CSV)github.com/bitcoin/bips · bip-0112 — used by Lightning to_local
BIP 141 (SegWit)github.com/bitcoin/bips · bip-0141 — moves Lightning scripts into witness
BIP 342 (Tapscript)github.com/bitcoin/bips · bip-0342 — MINIMALIF rule
BOLT 3 (Lightning)lightning/bolts · 03-transactions — every Lightning script form
Ordinals protocoldocs.ordinals.com — the OP_FALSE OP_IF envelope spec