TeachMeBitcoin

HTLC execution — Bob claiming with preimage:

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

3. Fully Annotated Lightning HTLC Script

A Hash Time Locked Contract (HTLC) is the core primitive of Lightning Network routing. It creates a conditional payment: "You can claim these funds if you reveal the preimage of this hash — but only until this block height."

The Offered HTLC Script

When Alice routes a payment through Bob to Carol, Alice creates an HTLC output in her commitment transaction with Bob:

Offered HTLC scriptPubKey (Alice → Bob channel, routing to Carol):

OP_DUP OP_HASH160 <revocation_pubkey_hash> OP_EQUAL
OP_IF
    OP_CHECKSIG
OP_ELSE
    <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL
    OP_IF
        OP_HASH160 <payment_hash160> OP_EQUALVERIFY
        OP_2 <local_htlcpubkey> <remote_htlcpubkey> OP_2 OP_CHECKMULTISIG
    OP_ELSE
        OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
        OP_CHECKSIG
    OP_ENDIF
OP_ENDIF

Three Spending Paths Explained

Path 1: Bob claims with payment preimage (success case)
Witness: [0, <bob_sig>, <alice_sig>, <preimage>, ""]

- Bob knows the preimage (Carol revealed it to him)

- Both Alice and Bob sign

- OP_SIZE 32 ensures preimage is exactly 32 bytes

- OP_HASH160 verifies preimage matches payment hash

Path 2: Alice revokes an old state (penalty case)
Witness: [<alice_revocation_sig>]

- Alice uses revocation key if Bob broadcasts an old commitment

- First branch: direct OP_CHECKSIG with revocation key

Path 3: HTLC timeout (payment failed)
Witness: [0, <alice_sig>, ""]

- After CLTV expiry, Alice can reclaim the funds

- Proves payment route failed

Simplified HTLC Execution (Success Path)

# HTLC execution — Bob claiming with preimage:

initial_stack = ["", "<preimage>", "<alice_sig>", "<bob_sig>", "0"]
# Witness items pushed in reverse order

# Step 1: OP_DUP OP_HASH160 <revocation_pubkey_hash> OP_EQUAL
# Top of stack is "0" — not equal to revocation hash
# OP_IF evaluates FALSE → takes OP_ELSE branch

# Step 2: Enter ELSE branch
# <remote_htlcpubkey> pushed
# OP_SWAP: swaps top two items  
# OP_SIZE: pushes byte length of preimage (should be 32)
# OP_EQUAL: checks if size == 32 → TRUE if preimage is 32 bytes

# Step 3: OP_IF (inner) — preimage size is 32, so TRUE
# OP_HASH160 <payment_hash160> OP_EQUALVERIFY
# Verifies preimage hashes to expected payment hash

# Step 4: OP_2 <local_htlcpubkey> <remote_htlcpubkey> OP_2 OP_CHECKMULTISIG
# Requires both alice_sig and bob_sig
# SUCCESS if both valid

Preimage Size Check — Why 32 Bytes

// The size check is critical for security:
<remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL

// Without this check:
// Mallory could provide a 1-byte "preimage" that happens to produce
// the correct HASH160 (birthday attack easier with shorter inputs)
// The 32-byte requirement forces use of full SHA256 preimage space

Technical Insight

This topic covers essential mechanics for Chapter 12. Understanding these details is key to mastering advanced Bitcoin script constructions like Taproot and specialized covenants.

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