Examples:
4. OP_CHECKSEQUENCEVERIFY (CSV) — BIP 112 Explained
The Problem CLTV Couldn't Solve
CLTV enabled absolute timelocks — conditions anchored to a specific point in time or block. But many real-world scenarios require relative timelocks: "this output cannot be spent until X blocks have passed since this output was first confirmed." For example, in the Lightning Network, a channel participant needs to be able to claim funds if the other party disappears, but only after a reasonable timeout period — a period that begins when a particular transaction is confirmed, not at some predetermined future block.
BIP 112, authored by BtcDrak, Mark Friedenbach, and Eric Lombrozo, introduced OP_CHECKSEQUENCEVERIFY (CSV) to solve exactly this problem. It was activated alongside BIP 68 (which gave new meaning to the nSequence field) in the BIP 68/112/113 soft fork, activated at block 419,328 in July 2016.
What CSV Does
OP_CHECKSEQUENCEVERIFY (opcode 0xb2, previously OP_NOP3) checks that the relative locktime encoded in the spending transaction's nSequence field for the current input is at least as large as the value on top of the stack.
The relative locktime measures time or block count from when the output being spent was first confirmed in a block. This is fundamentally different from CLTV, which compares against an absolute chain height or timestamp.
BIP 68: Making nSequence Meaningful
CSV depends entirely on BIP 68, which redefined the nSequence field of transaction inputs. Historically, nSequence was used to implement Replace-by-Fee signaling, but most of its bit space was unused.
BIP 68 repurposed bits 0–15 and bit 22 of nSequence for relative locktime encoding:
nSequence field (32 bits):
Bit 31: Disable flag (if set, BIP 68 rules do NOT apply)
Bit 22: Type flag (0 = block count, 1 = 512-second intervals)
Bits 0-15: Value (block count or time intervals)
Examples:
nSequence = 0x00000001 → 1 block relative locktime
nSequence = 0x00000064 → 100 blocks relative locktime
nSequence = 0x00400001 → 1 × 512 seconds (~8.5 minutes) relative locktime
nSequence = 0x80000000 → BIP68 disabled for this input
nSequence = 0xFFFFFFFF → Legacy SEQUENCE_FINAL (disables nLockTime too)
CSV Failure Conditions
Similar to CLTV, CSV fails if:
1. Stack is empty.
2. Top stack item is negative.
3. Top stack item has the disable bit (bit 31) set.
4. The spending transaction's version is less than 2 (BIP 68 only applies to v2+ transactions).
5. The input's nSequence has bit 31 (disable flag) set — meaning relative locktime is disabled for this input.
6. The type flag (bit 22) in the script value and nSequence don't match (mixing block and time types).
7. The nSequence value (masked to bits 0–15) is less than the stack value (masked to bits 0–15 and type bit).
Encoding CSV Values
CSV values are Script integers, just like CLTV values. The encoding must match the nSequence encoding defined in BIP 68.
CSV_SEQUENCE_MASK = 0x0000FFFF # Bits 0-15
CSV_TYPE_FLAG = 1 << 22 # Bit 22: 0=blocks, 1=time
CSV_DISABLE_FLAG = 1 << 31 # Bit 31: disable BIP68
def make_csv_value(blocks=None, seconds=None):
"""
Create a CSV script integer.
blocks: number of blocks (1 to 65535)
seconds: time in seconds (rounded to 512-second units, 1 to 65535 units)
"""
if blocks is not None:
if not (1 <= blocks <= 65535):
raise ValueError("Block count out of range")
return blocks # No type flag needed for blocks
elif seconds is not None:
units = (seconds + 511) // 512 # Round up to 512-second intervals
if not (1 <= units <= 65535):
raise ValueError("Time units out of range")
return CSV_TYPE_FLAG | units # Set type flag for time-based
else:
raise ValueError("Specify either blocks or seconds")
# Examples:
csv_100_blocks = make_csv_value(blocks=100)
print(hex(csv_100_blocks)) # 0x64
csv_1_day = make_csv_value(seconds=86400)
print(hex(csv_1_day)) # 0x400069 (type flag + ~169 units of 512 seconds)
A Minimal CSV Script
# Funds locked for 144 blocks (~1 day) from confirmation
witnessScript:
144 OP_CHECKSEQUENCEVERIFY OP_DROP
OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
# Spending transaction must have:
# - version >= 2
# - this input's nSequence >= 144 (and bit 31 not set)
# - the output being spent must have at least 144 block confirmations
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: