Watchtower monitoring logic for vault:
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: [
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: [
Step 3: OP_IF evaluates 0 → FALSE → take ELSE branch
Stack: [
Step 4: Push 144 (CSV argument)
Stack: [
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.
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: