TeachMeBitcoin

Watchtower monitoring logic for vault:

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

5. Fully Annotated Timelock Vault Script

A timelock vault uses Bitcoin's timelock opcodes to create a two-tier security system: a "hot" key for normal spending with a delay, and a "cold" emergency key for immediate cancellation.

Vault Design

Goal: Protect against key theft

- If attacker steals hot key, they must wait 144 blocks (~24 hours)
  during which the owner can cancel using cold key

- Owner can cancel instantly using cold key at any time

- After 144 blocks, hot key spend is final

Vault structure:
IF
    <cold_key> CHECKSIG          ← Immediate spend (emergency)
ELSE
    <144> CHECKSEQUENCEVERIFY    ← Must wait 144 blocks relative
    DROP
    <hot_key> CHECKSIG           ← Then hot key can spend
ENDIF

Full Vault Script

scriptPubKey (as P2WSH, hash of this goes on-chain):

OP_IF
    <cold_pubkey_33bytes> OP_CHECKSIG
OP_ELSE
    <0x9000> OP_CHECKSEQUENCEVERIFY
    OP_DROP
    <hot_pubkey_33bytes> OP_CHECKSIG
OP_ENDIF

Where 0x9000 = 144 blocks in CSV encoding:

- 0x0090 in little-endian = 144

- CSV flag bit not set (blocks, not time)

Execution Path 1: Cold Key Emergency Spend

Witness: [<cold_sig>, 0x01]
(for P2WSH: scriptWitness = [cold_sig, "1", vault_script])

Step 1: Push

Stack: []

Step 2: Push 0x01 (TRUE)

Stack: [, 1]

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

Stack: []

Step 4: Push

Stack: [, ]

Step 5: OP_CHECKSIG

Valid cold_sig? → [1]

Result: Immediate withdrawal using cold key. No waiting.

Used in: Emergency situations, key rotation, suspicious activity noticed.

Execution Path 2: Hot Key Delayed Spend

Witness: [<hot_sig>, 0x00]
Input must have nSequence >= 144 (0x00000090)

Step 1: Push

Stack: []

Step 2: Push 0x00 (FALSE)

Stack: [, 0]

Step 3: OP_IF evaluates 0 → FALSE → take ELSE branch

Stack: []

Step 4: Push 144 (CSV argument)

Stack: [, 144]

Step 5: OP_CHECKSEQUENCEVERIFY

Check: input's nSequence >= 144?
  If YES (144+ blocks since vault output confirmed): continue
  If NO (too soon): SCRIPT FAILS

Step 6: OP_DROP

Remove CSV argument from stack

Stack: []

Step 7: Push

Stack: [, ]

Step 8: OP_CHECKSIG

Valid hot_sig AND input is 144+ blocks old? → [1]

Result: Delayed withdrawal using hot key.

The 144-Block Window and Watchtower

# Watchtower monitoring logic for vault:
def watch_vault_utxo(vault_txid, vault_vout, cold_key):
    """
    Watch for unauthorized hot-key spend attempts.
    If detected within 144 blocks, broadcast cold-key cancellation.
    """
    while True:
        # Check mempool and recent blocks
        spending_tx = find_spending_tx(vault_txid, vault_vout)

        if spending_tx:
            # Check if it's a hot-key spend (ELSE branch)
            if uses_hot_key_path(spending_tx):
                # We have 144 blocks to react
                cancellation_tx = build_cold_key_spend(
                    vault_txid, vault_vout, cold_key,
                    destination=cold_storage_address
                )
                broadcast(cancellation_tx)
                log("Vault breach attempt cancelled!")
                break

        sleep(60)  # Check every minute

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!