TeachMeBitcoin

Alice watches the Bitcoin blockchain

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

4. Fully Annotated Atomic Swap Script

An atomic swap allows two parties to exchange coins on different blockchains trustlessly. Either both exchanges succeed or both fail — there is no scenario where one party gets the coins and the other doesn't.

The Classic Hash-Locked Atomic Swap

Setup:

- Alice has BTC, wants LTC

- Bob has LTC, wants BTC

- Alice generates secret S and computes H = HASH160(S)

- Alice shares H with Bob (but NOT S)

Bitcoin HTLC (Alice creates on Bitcoin chain):
"Bob can claim 1 BTC by revealing S before block 700,100
 OR Alice can reclaim after block 700,100"

Litecoin HTLC (Bob creates on Litecoin chain):
"Alice can claim 100 LTC by revealing S before block 3,500,000
 OR Bob can reclaim after block 3,500,000"

Alice's HTLC expires LATER than Bob's — this is critical for safety.

Bitcoin HTLC Script (Alice creates)

scriptPubKey:
OP_IF
    OP_SHA256 <hash_of_secret_S> OP_EQUALVERIFY
    <bob_pubkey> OP_CHECKSIG
OP_ELSE
    <locktime_block_700100> OP_CHECKLOCKTIMEVERIFY OP_DROP
    <alice_pubkey> OP_CHECKSIG
OP_ENDIF

Execution: Bob Claims BTC (reveals secret)

ScriptSig: <bob_signature> <secret_S> OP_1

Step 1: Push

Stack: []

Step 2: Push

Stack: [, ]

Step 3: OP_1 (push TRUE for IF branch)

Stack: [, , 1]

Step 4: OP_IF evaluates 1 → TRUE → take IF branch

Stack: [, ]

Step 5: OP_SHA256

Stack: [, SHA256()]

Step 6: Push

Stack: [, SHA256(), ]

Step 7: OP_EQUALVERIFY

SHA256(<secret_S>) == <expected_hash>? → YES → continue

Stack: []

Step 8: Push

Stack: [, ]

Step 9: OP_CHECKSIG

Verify bob_sig is valid for bob_pubkey → 1 (TRUE)

Stack: [1]

Result: Bob claimed the BTC. Secret S is now on the Bitcoin blockchain.

How Alice Claims LTC After Seeing S On-Chain

# Alice watches the Bitcoin blockchain
# When Bob's claiming transaction is confirmed, she extracts S:

def extract_preimage_from_transaction(tx):
    """Extract the secret S from Bob's claiming transaction."""
    for vin in tx.vin:
        script_ops = parse_script(vin.scriptSig)
        # In a typical atomic swap claim, S is the second push item
        # after the signature
        if len(script_ops) >= 3:
            potential_secret = script_ops[1]  # Second item
            if len(potential_secret) == 32:  # S is 32 bytes
                return potential_secret
    return None

# Alice then uses S to claim LTC:
# scriptSig for Alice claiming LTC: <alice_sig> <secret_S> OP_1

The Timelock Safety Mechanism

Why Alice's timelock must be longer than Bob's:

Timeline:
Block 3,500,000 → Bob's LTC timelock expires (Bob can reclaim LTC)
Block 700,100   → Alice's BTC timelock expires (Alice can reclaim BTC)

Dangerous scenario if Alice's timelock were SHORTER:

1. Alice claims LTC (reveals S)

2. Alice's BTC timelock expires before Bob sees the tx

3. Bob reclaims BTC

4. Bob ends up with both BTC and LTC ← catastrophic

Safe ordering ensures:

- If Bob claims BTC (reveals S), Alice has time to see S and claim LTC

- If Bob never claims, both timelocks expire and everyone gets refunds

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!