TeachMeBitcoin

OP_IF - Conditional Execution Basics

From TeachMeBitcoin, the free encyclopedia Reading time: 4 min

1. OP_IF — Conditional Execution Basics

Overview

OP_IF is one of the most powerful and foundational opcodes in Bitcoin Script. It introduces the concept of conditional execution — the ability for a script to take different paths based on runtime values on the stack. Without OP_IF, Bitcoin Script would be a purely linear sequence of operations with no branching logic whatsoever. With it, script authors can encode complex spending conditions that adapt to different scenarios, signatories, and time constraints.

At its core, OP_IF peeks at the top item on the main stack. If the value is non-zero (truthy), execution continues into the OP_IF branch. If the value is zero or an empty byte array (falsy), execution skips to the matching OP_ELSE or OP_ENDIF.

Opcode Reference

Opcode:     OP_IF
Hex:        0x63
Byte value: 99 (decimal)
Category:   Flow Control

How It Works

When the Bitcoin Script interpreter encounters OP_IF, it pops the top element from the stack and evaluates it as a boolean:

Stack before OP_IF:
[ ..., <condition> ]   <-- top of stack

OP_IF pops <condition>:
  if <condition> != 0:
      execute IF-branch
  else:
      skip to OP_ELSE / OP_ENDIF

Basic Syntax

A minimal OP_IF block looks like this:

<condition>
OP_IF
  <opcodes executed if condition is true>
OP_ENDIF

With an else branch:

<condition>
OP_IF
  <opcodes executed if condition is true>
OP_ELSE
  <opcodes executed if condition is false>
OP_ENDIF

Stack Behavior Detail

It is critical to understand that OP_IF consumes the top stack element. The condition value is removed from the stack before the branch body executes. This means whatever value was used as the condition is no longer present inside the branch body.

Initial stack (top on right): [ 0x01 0x02  <1> ]

OP_IF          --> pops <1>, enters IF branch
  OP_ADD       --> operates on 0x01 and 0x02
OP_ENDIF
Result stack: [ 0x03 ]

Compare with a false condition:

Initial stack: [ 0x01 0x02  <0> ]

OP_IF          --> pops <0>, skips IF branch
OP_ENDIF
Result stack: [ 0x01 0x02 ]  <-- untouched

Script Validation Rules for OP_IF

The Bitcoin consensus rules enforce strict structural requirements for OP_IF:

  1. Every OP_IF must be closed by a matching OP_ENDIF. A script without proper closure is immediately invalid.

  2. Nesting is allowed — an OP_IF inside another OP_IF is perfectly valid (see section 5).

  3. OP_IF cannot appear in a script without a corresponding OP_ENDIF, even if that branch is never executed at runtime.

  4. In SegWit v0 (P2WSH) and Tapscript (SegWit v1), there is an additional restriction: the argument to OP_IF must be exactly 0x00 or 0x01 (the minimal push rule). Passing a non-minimal boolean (such as 0x02 to mean "true") causes script failure.

; Valid SegWit OP_IF usage
OP_1          ; pushes 0x01 — minimal true
OP_IF
  OP_DROP
OP_ENDIF

; Invalid in SegWit — non-minimal boolean
OP_2          ; pushes 0x02 — NOT a minimal boolean
OP_IF         ; SCRIPT FAILS in SegWit context
  OP_DROP
OP_ENDIF

Why OP_IF Matters

Before OP_IF, every Bitcoin output could only have one fixed spending condition. With OP_IF, you can express logic such as:

These use cases underpin technologies like Hash Time Locked Contracts (HTLCs), Lightning Network channels, DLCs (Discreet Log Contracts), and Taproot script trees.

Simple Example: Choosing Between Two Keys

; Locking script (scriptPubKey)
OP_IF
  <Alice_pubkey> OP_CHECKSIG
OP_ELSE
  <Bob_pubkey> OP_CHECKSIG
OP_ENDIF

; Unlocking script (scriptSig) for Alice's path:
<Alice_signature> OP_1

; Unlocking script for Bob's path:
<Bob_signature> OP_0

Here, the spending party pushes either OP_1 (to take the Alice path) or OP_0 (to take the Bob path), followed by their respective signature.

Common Pitfalls

☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!