TeachMeBitcoin

Real World OP_IF Usage in HTLC Scripts

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

8. Real World OP_IF Usage in HTLC Scripts

Overview

Hash Time Locked Contracts (HTLCs) are the fundamental building blocks of the Lightning Network and many other Bitcoin payment channel constructions. They rely heavily on OP_IF to create two-path scripts: a payment path (settled with a hash preimage) and a timeout path (settled after a block height or timestamp expires).

What Is an HTLC?

An HTLC locks funds such that:

  1. The recipient can claim the funds by revealing a secret value r such that SHA256(r) == payment_hash.

  2. The sender can reclaim the funds after a specified locktime if the recipient never reveals r.

This mechanism allows payment routing across multiple hops in the Lightning Network: each hop is an HTLC, and the preimage propagates backwards from recipient to sender atomically.

Offered HTLC Script (Simplified)

; Offered HTLC: sender offers payment to receiver

; scriptPubKey:
OP_IF
  ; Payment path: receiver provides preimage
  OP_SHA256 <payment_hash> OP_EQUALVERIFY
  <receiver_pubkey> OP_CHECKSIG
OP_ELSE
  ; Timeout path: sender reclaims after expiry
  <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
  <sender_pubkey> OP_CHECKSIG
OP_ENDIF

; Witness for payment path (receiver claiming):
<receiver_sig>
<preimage_r>
OP_1

; Witness for timeout path (sender reclaiming):
<sender_sig>
OP_0

Full BOLT #3 Offered HTLC Script

The actual HTLC script from the Lightning Network specification (BOLT #3) is more complex, incorporating revocation keys and two-stage settlement:

; BOLT #3 Offered HTLC (commitment transaction output)

OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
  OP_CHECKSIG
OP_ELSE
  <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
  OP_NOTIF
    OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
  OP_ELSE
    OP_SHA256 <payment_hash> OP_EQUALVERIFY
    OP_CHECKSIG
  OP_ENDIF
OP_ENDIF

This script has three paths:

  1. Revocation path: The counterparty possesses the revocation key (used when an old channel state is broadcast).

  2. Timeout path: Neither preimage nor revocation — requires 2-of-2 multisig for cooperative timeout.

  3. Payment path: Preimage of 32 bytes provided — receiver claims with single sig.

Received HTLC Script (BOLT #3)

; BOLT #3 Received HTLC

OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL
OP_IF
  OP_CHECKSIG
OP_ELSE
  <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
  OP_IF
    OP_SHA256 <payment_hash> OP_EQUALVERIFY
    2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG
  OP_ELSE
    OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
    OP_CHECKSIG
  OP_ENDIF
OP_ENDIF

Preimage Size Check with OP_SIZE

A key pattern in HTLC scripts is using OP_SIZE to distinguish between "preimage provided" and "no preimage":

OP_SIZE 32 OP_EQUAL
OP_IF
  ; 32-byte item on stack — treat as preimage
  OP_SHA256 <payment_hash> OP_EQUALVERIFY
  ...
OP_ELSE
  ; Not 32 bytes — timeout path
  ...
OP_ENDIF

OP_SIZE pushes the byte length of the top stack item without consuming it. If the spender provides a 32-byte preimage, OP_SIZE pushes 32, OP_EQUAL confirms it, and the IF branch is taken. If they push OP_0 (for the timeout path), OP_SIZE pushes 0, OP_EQUAL fails, and the ELSE branch is taken.

Security Implications

HTLCs depend critically on the atomicity of the preimage revelation. Because the preimage is the same across all hops, once the recipient reveals it to claim the final payment, every intermediate hop can use the same preimage to claim their own HTLC. The OP_IF structure ensures this propagation is possible within the consensus rules of Bitcoin itself.

☕ 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!