Recipient (Bob) creates the payment secret:
13. HTLC Scripts: Combining Hash and Timelocks
What Is an HTLC?
A Hash Time-Locked Contract (HTLC) is the core building block of the Lightning Network and cross-chain atomic swaps. It combines two cryptographic primitives:
-
Hash Lock: Payment is only possible if the recipient can reveal a secret
preimagesuch thatHASH(preimage) == H. This enables trustless payment routing. -
Time Lock: If the secret is not revealed within a timeout period, the sender can reclaim the funds.
The combination of these two elements enables payments to be routed across untrusted intermediaries without requiring trust — the intermediary either knows the preimage (and gets paid) or doesn't (and the funds time out safely back to the sender).
The Hash Lock Mechanism
import hashlib
import secrets
# Recipient (Bob) creates the payment secret:
preimage = secrets.token_bytes(32) # 32 random bytes
payment_hash = hashlib.sha256(preimage).digest() # H = SHA256(preimage)
print(f"Preimage: {preimage.hex()}")
print(f"Payment Hash: {payment_hash.hex()}")
# Bob shares payment_hash (H) with Alice (the payer).
# Alice creates an HTLC locked to H.
# Bob claims the HTLC by revealing preimage.
# Alice (or intermediate nodes) learn preimage when Bob reveals it.
On-Chain HTLC Script (P2WSH)
# Offered HTLC: Alice → Bob (Alice offering, Bob receiving)
# Bob can claim by revealing preimage within timeout
# Alice can reclaim after CLTV timeout
witnessScript:
OP_DUP OP_HASH160 <RevocationPubKeyHash> OP_EQUAL
OP_IF
OP_CHECKSIG
OP_ELSE
<RemotePubKey> OP_SWAP OP_SIZE 32 OP_EQUAL
OP_IF
OP_HASH160 <PaymentHashRIPEMD160> OP_EQUALVERIFY
2 OP_SWAP <LocalPubKey> 2 OP_CHECKMULTISIG
OP_ELSE
OP_DROP <CLTVExpiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_CHECKSIG
OP_ENDIF
OP_ENDIF
# Path 1 (Revocation): Bob uses revocation key to punish Alice for old state
# Path 2 (Success): Bob reveals 32-byte preimage → receives payment
# Path 3 (Timeout): Alice reclaims after CLTV expiry block
Received HTLC Script
# Received HTLC: Alice receiving payment from remote
# Similar structure but the roles are reversed
witnessScript:
OP_DUP OP_HASH160 <RevocationPubKeyHash> OP_EQUAL
OP_IF
OP_CHECKSIG
OP_ELSE
<RemotePubKey> OP_SWAP OP_SIZE 32 OP_EQUAL
OP_NOTIF
OP_DROP <CLTVExpiry> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_CHECKSIG
OP_ELSE
OP_HASH160 <PaymentHashRIPEMD160> OP_EQUALVERIFY
2 OP_SWAP <LocalPubKey> 2 OP_CHECKMULTISIG
OP_ENDIF
OP_ENDIF
The HTLC-Timeout Transaction
When an offered HTLC times out (Bob didn't reveal the preimage), Alice broadcasts an HTLC-Timeout second-level transaction:
# HTLC-Timeout TX:
# Input: Offered HTLC output (from commitment TX)
# Output: to_local-style output with CSV delay
# Input witness:
0 # OP_CHECKMULTISIG dummy
<AliceSignature>
<BobSignature>
"" # Empty preimage (timeout path)
0 # OP_ELSE branch
<htlc_witnessScript>
# nLockTime: set to CLTVExpiry (satisfies the CLTV in the HTLC script)
# Input nSequence: 0 (allows nLockTime to be enforced)
# Output script (to_local with CSV):
OP_IF
<RevocationPubKey> OP_CHECKSIG
OP_ELSE
<csv_delay> OP_CSV OP_DROP
<AliceDelayedPubKey> OP_CHECKSIG
OP_ENDIF
Atomic Swaps Using HTLCs
HTLCs enable trustless cross-chain swaps between Bitcoin and other cryptocurrencies:
# Cross-chain atomic swap: Alice wants to trade BTC for LTC with Bob
# Both chains must support hash locks and timelocks
# Step 1: Bob generates preimage and hash
preimage = secrets.token_bytes(32)
H = hashlib.sha256(preimage).digest()
# Step 2: Alice creates Bitcoin HTLC (funds locked to H, 48-hour CLTV)
bitcoin_htlc = f"""
OP_IF
OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 {H.hex()} OP_EQUALVERIFY
OP_DUP OP_HASH160 {bob_btc_hash} OP_EQUALVERIFY OP_CHECKSIG
OP_ELSE
{bitcoin_cltv_expiry} OP_CLTV OP_DROP
OP_DUP OP_HASH160 {alice_btc_hash} OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF
"""
# Step 3: Bob creates Litecoin HTLC (same H, 24-hour CLTV — shorter than Bitcoin!)
litecoin_htlc = f"""
OP_IF
OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 {H.hex()} OP_EQUALVERIFY
OP_DUP OP_HASH160 {alice_ltc_hash} OP_EQUALVERIFY OP_CHECKSIG
OP_ELSE
{litecoin_cltv_expiry} OP_CLTV OP_DROP
OP_DUP OP_HASH160 {bob_ltc_hash} OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF
"""
# Step 4: Alice claims LTC by revealing preimage (on Litecoin blockchain)
# Step 5: Bob learns preimage from Alice's Litecoin claim
# Step 6: Bob claims BTC using the same preimage (on Bitcoin blockchain)
HTLC Security Properties
| Property | Guarantee | |
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: