Part V · Special Transactions Chapter 15

Timelocks: Programming in Time

"This BIP describes a new opcode (OP_CHECKLOCKTIMEVERIFY) for the Bitcoin scripting system that allows a transaction output to be made unspendable until some point in the future."—Peter Todd, BIP 65 (2014)

Every transaction we have studied so far answers the question who can spend. Signatures prove ownership; scripts encode spending conditions; multisig requires agreement among parties. But none of these mechanisms answers an equally important question: when can the funds be spent?

🔧 Interactive: Timelock Decoder

Bitcoin's timelock system answers this question through four complementary mechanisms, organized along two axes:

31
dis
30–24
unused
22
type
21–16
unused
15–0
value (blocks or 512s intervals)
Bit 31=0: BIP 68 active Bit 22=0: blocks · Bit 22=1: 512s intervals

Absolute timelocks say "not before block \(X\)" or "not before time \(T\)." Relative timelocks say "not until \(n\) blocks (or \(t\) seconds) after the input was confirmed." Transaction-level locks are enforced by nodes checking header fields. Script-level locks are enforced by the Script interpreter during execution.

This chapter examines each mechanism in detail, building from the simplest (nLockTime, present since the Genesis block) to the most sophisticated (OP_CSV, which enables Lightning Network payment channels).

15.1nLockTime: The Original Timelock

Every transaction has a 4-byte nLockTime field—the very last field in the transaction, in both legacy and SegWit serialization. We have encountered it in every specimen, always as 00 00 00 00—except in Chapter 12, where our Taproot specimen had:

ff d3 0a 00_nLockTime = 709,631 (little-endian)

This meant the transaction could not be included in any block with height \(<709,631\).

15.1.1The Dual Interpretation

The nLockTime field has a dual interpretation based on its value:

ValueInterpretationMeaning
\(0\)DisabledTransaction valid immediately
\(1\)–\(499,999,999\)Block heightNot valid until block \(\geq\) nLockTime
\(\geq 500,000,000\)UNIX timestampNot valid until time \(\geq\) nLockTime

The threshold 500,000,000 corresponds to November 5, 1985—well before Bitcoin's creation, ensuring no ambiguity between heights and timestamps for any real transaction.

15.1.2How nLockTime Works

When a node receives a transaction with \(\texttt{nLockTime} > 0\):

  1. If nLockTime \(< 500,000,000\): compare against the current block height. The transaction is invalid if the next block's height would be less than nLockTime.
  2. If nLockTime \(\geq 500,000,000\): compare against the block's median time past (MTP—the median of the last 11 block timestamps, per BIP 113). The transaction is invalid if MTP \(<\) nLockTime.
nLockTime Requires Cooperation

nLockTime alone provides weak guarantees. A transaction with \(\texttt{nLockTime} = 800,000\) cannot be mined before block 800,000—but nothing prevents the sender from creating a second transaction spending the same inputs with \(\texttt{nLockTime} = 0\), broadcasting it immediately, and invalidating the time-locked version. nLockTime constrains when a transaction can be mined, not when the underlying funds can be spent. For enforceable timelocks, you need script-level locks (CLTV or CSV).

15.1.3The nSequence Interaction

There is a critical exception: nLockTime is only enforced if at least one input has \(\texttt{nSequence} < \texttt{0xFFFFFFFF}\). If every input's sequence number is 0xFFFFFFFF (the maximum), nLockTime is ignored entirely and the transaction is valid at any time.

This was Satoshi's original design: nSequence was intended for transaction "replacement"—parties could update a transaction by incrementing the sequence number, with the highest-sequence version being final. Once all sequences reached the maximum, no more updates were possible, and nLockTime became irrelevant.

In practice, this replacement mechanism was never used (it was a denial-of-service vector). But the nSequence/nLockTime interaction remains in consensus and has been repurposed by BIP 68 (relative timelocks) and BIP 125 (Replace-by-Fee).

15.1.4Anti-Fee-Sniping

Modern wallets set nLockTime to the current block height as an anti-fee-sniping measure. Fee sniping is a theoretical attack where a miner re-mines a previous block to steal its fees. By setting nLockTime to the current height, the transaction cannot be included in any earlier block—making fee sniping slightly harder.

Our Chapter 12 specimen's \(\texttt{nLockTime} = 709,631\) is exactly this: the transaction was created when the chain tip was block 709,631, ensuring it could only be mined in block 709,632 or later. The corresponding \(\texttt{nSequence} = \texttt{0xFFFFFFFD}\) enables both nLockTime enforcement and RBF signaling.

15.2OP_CHECKLOCKTIMEVERIFY (BIP 65)

nLockTime constrains the transaction. But what if you want to constrain the output—ensuring that no transaction, regardless of who creates it, can spend the funds before a certain time? This requires a script-level lock.

BIP 65 introduced OP_CHECKLOCKTIMEVERIFY (CLTV, opcode 0xb1)—a Script opcode that verifies the spending transaction's nLockTime against a value on the stack.

15.2.1The CLTV Script Pattern

A CLTV-locked output uses this script:

CLTV Locking Script (scriptPubKey)

<expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey> OP_CHECKSIG

For example, to lock funds until block 900,000:

03 a0 bb 0d OP_CLTV OP_DROP <pubkey> OP_CHECKSIG

where 03 a0 bb 0d pushes the 3-byte little-endian encoding of 900,000 (\(= \texttt{0x0DBBA0}\)).

15.2.2How CLTV Works

When the Script interpreter encounters OP_CHECKLOCKTIMEVERIFY:

  1. Read the top stack value (the required lock time). The value is not popped—it stays on the stack.
  2. Verify that the spending transaction's nLockTime \(\geq\) the stack value.
  3. Verify that the lock-time type matches: both must be block heights (\(< 500,000,000\)) or both must be timestamps (\(\geq 500,000,000\)). Mixing types causes script failure.
  4. Verify that the spending input's nSequence \(\neq\) 0xFFFFFFFF (ensuring nLockTime is actually enforced).
  5. If all checks pass, execution continues. If any check fails, the script fails immediately.

The OP_DROP after CLTV removes the lock-time value from the stack (CLTV doesn't pop it), leaving the stack clean for OP_CHECKSIG.

CLTV Makes nLockTime Enforceable

CLTV solves nLockTime's fundamental weakness. Without CLTV, the sender can always bypass nLockTime by creating a competing transaction with \(\texttt{nLockTime} = 0\). With CLTV, the lock is embedded in the output script—the funds literally cannot be spent until the time has passed, regardless of who creates the spending transaction. The lock is on the coins, not the transaction.

15.2.3Use Cases

15.3nSequence: The Overloaded Field

The 4-byte nSequence field on each input is the most overloaded field in Bitcoin. It serves three distinct purposes depending on its value:

ValueMeaningBIP
0xFFFFFFFFFinal (disables nLockTime)Original
0xFFFFFFFEFinal (nLockTime enabled, no RBF)
\(<\) 0xFFFFFFFE, bit 31 setRBF signal onlyBIP 125
\(<\) 0xFFFFFFFE, bit 31 clearRelative timelock + RBFBIP 68

15.3.1BIP 68 Encoding

When bit 31 is clear (0), the nSequence value encodes a relative timelock per BIP 68:

BIP 68 nSequence Bit Layout
31
dis
30–24
unused
22
type
21–16
unused
15–0
value
Bit 31=0: BIP 68 active Bit 22=0: blocks · 1: 512s intervals
nSequenceEncodingMeaning
0x000000011 block, block-basedNot before 1 confirmation
0x00000090144 blocks, block-basedNot before 1 day
0x004000A9169 units \(\times\) 512s, time-basedNot before 24 hours
0xFFFFFFFFBIP 68 disabledNo relative timelock
0xFFFFFFFDBIP 68 disabled (bit 31 set)RBF signal only

The relative timelock is measured from the block in which the referenced output was confirmed. If the input spends an output confirmed in block 800,000, and nSequence encodes 144 blocks, the spending transaction cannot be mined before block 800,144.

15.4OP_CHECKSEQUENCEVERIFY (BIP 112)

Just as CLTV enforces nLockTime at the script level, OP_CHECKSEQUENCEVERIFY (CSV, opcode 0xb2) enforces BIP 68 relative timelocks at the script level.

BIP 112 allows a script to require that the spending input's nSequence meets a minimum relative delay.

15.4.1The CSV Script Pattern

CSV Locking Script

<delay> OP_CHECKSEQUENCEVERIFY OP_DROP <pubkey> OP_CHECKSIG

For example, to require 144 confirmations (\(\approx\)1 day):

Example: 144-Block Relative Delay

02 90 00 OP_CSV OP_DROP <pubkey> OP_CHECKSIG

where 02 90 00 pushes the 2-byte little-endian encoding of 144 (\(= \texttt{0x0090}\)).

15.4.2How CSV Works

When the Script interpreter encounters OP_CHECKSEQUENCEVERIFY:

  1. Read the top stack value (the required relative delay).
  2. Verify the spending input's nSequence satisfies BIP 68 (bit 31 clear).
  3. Verify the type flags match (both block-based or both time-based).
  4. Verify the input's nSequence value \(\geq\) the stack value.
  5. If all checks pass, continue. Otherwise, script failure.
CSV Enables Lightning Network

CSV is the critical building block for the Lightning Network. In a Lightning commitment transaction, the to_local output (the channel partner's own funds) is locked with a CSV delay—typically 144 blocks (1 day) to 2,016 blocks (2 weeks). This delay gives the counterparty time to detect a revoked commitment and broadcast a penalty transaction. Without CSV, Lightning's security model would not work.

15.5CLTV vs. CSV: Absolute vs. Relative

The distinction between absolute and relative timelocks is fundamental:

CLTV (Absolute)CSV (Relative)
Question"After what block/time?""How long after confirmation?"
ReferenceGlobal (block height or UTC)Local (confirmation of the input)
Script opcodeOP_CHECKLOCKTIMEVERIFY (0xb1)OP_CHECKSEQUENCEVERIFY (0xb2)
Tx fieldnLockTimenSequence
ActivationBlock 388,381 (Dec 2015)Block 419,328 (Jul 2016)
BIP6568, 112, 113
Use caseHODL, escrow timeoutLightning, vault recovery

CLTV answers: "These coins cannot be spent before January 1, 2030." CSV answers: "These coins cannot be spent until 144 blocks after they were confirmed." Both can appear in the same script—enabling complex conditions like "Alice can spend after 1,000 blocks from confirmation, OR Bob can spend after January 2030."

15.6Combining Timelocks: The HTLC

The most powerful timelock pattern combines hash locks with time locks, creating a Hash Time-Locked Contract (HTLC):

HTLC Script Pattern (simplified)

OP_IF

OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG

OP_ELSE

OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG

OP_ENDIF

This script has two spending paths:

HTLCs are the atomic building block of the Lightning Network (Chapter 18). They enable trustless multi-hop payments: each hop in a Lightning payment is secured by an HTLC that ensures either the payment completes across all hops, or every participant gets refunded.

15.7What We Learned

15.7.1Looking Ahead

Timelocks are about when funds can move. Chapter 17 explores how transactions compete: Replace-by-Fee (RBF) and Child-Pays-for-Parent (CPFP)—the tools for navigating Bitcoin's fee market. Both rely on nSequence, the same field we studied here.

*Exercises

Litmus (L)

  1. What is the dual interpretation of nLockTime? What value serves as the threshold?
  2. What happens if every input in a transaction has \(\texttt{nSequence} = \texttt{0xFFFFFFFF}\)?
  3. What opcode is CLTV? What opcode is CSV? Give the hex values.
  4. Why does OP_DROP always follow OP_CHECKLOCKTIMEVERIFY in practice?
  5. In a BIP 68 nSequence value, what does bit 22 control?

Hands-On (H)

  1. Encode block 900,000 as a 4-byte little-endian nLockTime. What are the hex bytes?
  2. Construct a BIP 68 nSequence value for a relative timelock of exactly 1,008 blocks (\(\approx\)1 week). Express it in hex.
  3. Construct a BIP 68 nSequence value for a time-based relative lock of approximately 48 hours. How many 512-second units is this?
  4. Our Chapter 12 specimen has \(\texttt{nLockTime} = 709,631\) and \(\texttt{nSequence} = \texttt{0xFFFFFFFD}\). Is BIP 68 relative timelock active? Is nLockTime enforced? Is RBF signaled?

Proofs and Reasoning (P)

  1. Explain why nLockTime alone is insufficient for enforceable timelocks. Construct a scenario where a sender bypasses an nLockTime constraint. Then explain how CLTV prevents this.
  2. Why must CLTV and nLockTime use the same type (both heights or both timestamps)? What would go wrong if a CLTV script specified a block height but the transaction used a timestamp nLockTime?
  3. A Lightning commitment transaction's to_local output uses CSV with a 144-block delay. Explain why this delay is necessary for security. What attack does it prevent?

Connections (C)

  1. HODL vault. Design a script that locks bitcoin until block 1,050,000 (the 5th halving). Write the complete locking script using CLTV. What must the spending transaction's nLockTime and nSequence be?
  2. Two-path escrow. Design a script with two spending paths: (1) Alice and Bob sign together (no timelock), or (2) Alice alone after block 900,000. Use OP_IF/OP_ELSE with CLTV.

Bridge (B)

  1. Chapter 17 covers RBF, which uses nSequence \(<\) 0xFFFFFFFE as a signal. How does RBF signaling interact with BIP 68 relative timelocks? Can a transaction signal RBF and enforce a relative timelock simultaneously?
  2. Chapter 18 covers Lightning Network. Explain at a high level how HTLCs use both CLTV (for the refund path) and hash preimages (for the claim path) to enable trustless multi-hop payments.

*Solutions

L1. nLockTime values \(< 500,000,000\) are interpreted as block heights: the transaction is invalid before that block. Values \(\geq 500,000,000\) are interpreted as UNIX timestamps: the transaction is invalid before that time. The threshold is \(500,000,000\) (corresponding to November 5, 1985—well before Bitcoin's creation).

L2. If every input has \(\texttt{nSequence} = \texttt{0xFFFFFFFF}\), nLockTime is disabled: the transaction is valid immediately regardless of the nLockTime value. This is the original behavior from Satoshi's design.

L3. OP_CHECKLOCKTIMEVERIFY (CLTV) = 0xb1. OP_CHECKSEQUENCEVERIFY (CSV) = 0xb2.

L4. Because CLTV does not pop the lock-time value from the stack—it only reads it. The value would remain on the stack and interfere with subsequent opcodes (like OP_CHECKSIG). OP_DROP removes it, leaving the stack clean.

L5. Bit 22 is the type flag: if clear (0), the value in bits 0–15 represents blocks; if set (1), the value represents time in 512-second units.

H1. \(900,000 = \texttt{0x0DBBA0}\). In 4-byte little-endian: a0 bb 0d 00.

H2. \(1,008\) blocks, block-based (bit 22 = 0): nSequence = \(1,008 = \texttt{0x03F0}\). Full 4-byte value: 0x000003F0. In little-endian bytes: f0 03 00 00. Bit 31 must be 0 (BIP 68 enabled).

H3. 48 hours = \(48 \times 3,600 = 172,800\) seconds. Each unit = 512 seconds: \(172,800 / 512 = 337.5\), round to 338 units. Time-based: set bit 22. nSequence = \((1 \ll 22) \,|\, 338 = \texttt{0x00400152}\). Verify: \(338 \times 512 = 173,056\) seconds \(= 48.07\) hours.

H4. \(\texttt{nSequence} = \texttt{0xFFFFFFFD}\):

Summary: nLockTime active, RBF active, no relative timelock.

P1. Suppose Alice creates a transaction paying Bob with \(\texttt{nLockTime} = 850,000\) (block 850,000 is one month away). Before block 850,000, Alice can create a new transaction spending the same inputs with \(\texttt{nLockTime} = 0\), broadcast it, and get it mined immediately. Bob's time-locked transaction becomes invalid (double-spend).

CLTV prevents this by embedding the lock in the output script. If Alice locks funds in a CLTV output, any spending transaction must have \(\texttt{nLockTime} \geq 850,000\). Alice cannot create a bypassing transaction because the script itself rejects it. The lock is on the coins, not the transaction.

P2. CLTV compares its stack value against nLockTime, and both must use the same type (heights or timestamps). If the script specifies block 900,000 (a height) but the transaction sets nLockTime to a UNIX timestamp, the comparison is meaningless—900,000 as a timestamp is January 11, 1970, which is always in the past. A malicious spender could bypass the intended lock by using the wrong type. BIP 65 prevents this: if the types don't match, the script fails immediately.

P3. In Lightning, each commitment transaction gives one party their funds immediately (the to_remote output) and the other party their funds after a CSV delay (the to_local output). The delay exists so that if a party broadcasts a revoked commitment (an old state that has been superseded), the counterparty has time to detect it and broadcast a penalty transaction that claims all funds. Without the delay, the cheating party could broadcast an old commitment and immediately spend their output, leaving no window for the penalty. The 144-block (1 day) delay is a security parameter: it must be long enough for the honest party's watchtower to detect the breach and respond.

C1. The 5th halving occurs at block 1,050,000. The CLTV locking script:

03 90 05 10 OP_CLTV OP_DROP <pubkey> OP_CHECKSIG

where 03 90 05 10 pushes the 3-byte little-endian encoding of 1,050,000 (\(= \texttt{0x100590}\)). The spending transaction must have \(\texttt{nLockTime} \geq 1,050,000\) and at least one input with \(\texttt{nSequence} < \texttt{0xFFFFFFFF}\) (to enable nLockTime enforcement).

C2. The two-path escrow script:

Two-Path Escrow

OP_IF

OP_2 OP_2 OP_CHECKMULTISIG

OP_ELSE

<900000> OP_CHECKLOCKTIMEVERIFY OP_DROP

OP_CHECKSIG

OP_ENDIF

Path 1 (cooperative): Alice and Bob both sign, supplying OP_TRUE to take the OP_IF branch. No timelock. Path 2 (timeout): After block 900,000, Alice provides her signature with OP_FALSE to take the OP_ELSE branch. The spending transaction must have \(\texttt{nLockTime} \geq 900,000\) and at least one input with \(\texttt{nSequence} < \texttt{0xFFFFFFFF}\). Note: CLTV uses absolute heights. For a relative delay (e.g., "30 days after the output is created"), use CSV instead.

B1. Yes, a transaction can signal RBF and enforce a BIP 68 relative timelock simultaneously. Any nSequence with bit 31 clear and value \(<\) 0xFFFFFFFE satisfies both: bit 31 = 0 activates BIP 68, and the sub-maximum value signals RBF per BIP 125. For example, \(\texttt{nSequence} = \texttt{0x00000090}\) (144-block relative lock) also signals RBF because \(\texttt{0x00000090} < \texttt{0xFFFFFFFE}\).

B2. In a Lightning multi-hop payment, each intermediate node creates an HTLC with two paths: (1) the recipient reveals a hash preimage to claim the funds (the "success" path), or (2) the sender reclaims the funds after a CLTV timeout (the "refund" path). The timeouts decrease along the route: if the payment is A B C, the HTLC from A to B might timeout at block \(n+20\), while B to C times out at block \(n+10\). This ensures that if C claims the preimage from B, B has time to claim from A before A's timeout. The hash preimage propagates backward (C B A), and the timelocks ensure every hop can claim or refund. The atomicity guarantee: either all hops complete (preimage revealed), or all hops refund (timeouts expire).

← Ch. 14 Ch. 16 →