consensus: BIP65 OP_CHECKLOCKTIMEVERIFY — activate at 1,055,555 #34
Labels
No labels
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
SubGeniusFinance/Offerings-to-Cthulhu#34
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Goal
Add OP_CHECKLOCKTIMEVERIFY (BIP65) at consensus level, repurposing the
OP_NOP2slot. Enables script-level timelocks for vault patterns, refund clauses, and any cooperative-spend pattern that wants "this output can't be reclaimed until block/time X."Flagged by @9019x on 2026-06-14 as part of the BIP66 family — paired because both are script-level soft forks that exchanges and modern wallets check together for "Bitcoin script compatibility."
Problem
OFF has
OP_NOP2 = 0xb1atsrc/script.h:199, currently a literal no-op (src/script.cpp:393, which catchesOP_NOP1throughOP_NOP5together). That's the script slot BIP65 redefines asOP_CHECKLOCKTIMEVERIFY. Without CLTV, the only timelock OFF supports is tx-levelnLockTime(src/main.cpp:570-576) — a coarse-grained "this entire transaction is invalid before time X" that can't be expressed as a conditional inside a script.Use cases CLTV unlocks for OFF:
None urgent; each is currently impossible at script level.
What BIP65 actually requires
From https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki:
When
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFYflag is set,OP_NOP2(0xb1) is redefined asOP_CHECKLOCKTIMEVERIFY. The opcode body:locktimeandtx.nLockTimerepresent different lock types (block-height vs unix-time, perLOCKTIME_THRESHOLD) → fail.locktime > tx.nLockTime→ fail.nSequence == 0xFFFFFFFF→ fail (would otherwise disablenLockTime).When the flag is NOT set,
OP_NOP2continues to behave as a no-op (i.e., scripts compiled against post-fork rules deploy fine on pre-fork nodes — the soft-fork property of NOP-redefinition).Constants
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFYSCRIPT_VERIFY_DERSIG(#33) so each can be enforced independently if needed.OP_CHECKLOCKTIMEVERIFYHARDFORK_CLTV_MAIN_OFFHARDFORK_CLTV_TESTNET_OFFWhy activate at 1,055,555 (post-freeze, bundled with #6)
Original draft placed activation at h=1,025,000 inside the OFFSIG window, on the "Conclave-only mining → zero split risk" rationale. Revised 2026-06-16 to honor the feature-freeze policy in #20, which prohibits merging consensus changes to
mainbetween h=998,000 and h=1,050,667. Activation moves to the post-freeze slot.Why 1,055,555 specifically:
Trade vs the original mid-OFFSIG activation: outsider miners can in principle produce blocks between h=1,050,667 and h=1,055,555 under the old rule. The freeze-end upgrade-coordination announcement closes that gap. A 3.4-day lead time is short but standard for post-freeze coordination on a small chain.
Files touched
src/script.h— addSCRIPT_VERIFY_CHECKLOCKTIMEVERIFYflag; aliasOP_CHECKLOCKTIMEVERIFYtoOP_NOP2.src/script.cpp— addOP_CHECKLOCKTIMEVERIFYhandler inEvalScript()around line 393 whereOP_NOP2is currently caught. ~30 LoC for the opcode body. Split the existingcase OP_NOP1: case OP_NOP2: ...group so CLTV gets its own arm when the flag is set.src/main.cpp— height-gated flag bit added toConnectBlockflags (line 2120-2121) andAcceptToMemoryPoolflags (line 968), same gate pattern as BIP66.src/pow.h—HARDFORK_CLTV_MAIN_OFF/_TESTNET_OFFconstants.Approx 50 LoC total.
Semantics
The new rule applies to any script verification at
nSpendHeight ≥ HARDFORK_CLTV_MAIN_OFF. Pre-fork:OP_NOP2is a no-op, scripts using it pass without doing anything. Post-fork: scripts that use the opcode get the actual CLTV semantics.This is forward-compatible: a script written for the post-fork CLTV semantics will also deploy on pre-fork nodes, because they treat
OP_NOP2as a no-op and don't enforce the timelock. That's the entire soft-fork property of NOP-redefinition. The reverse (a script that deliberately exploits the no-op nature ofOP_NOP2) would break — but no such scripts are known on the OFF chain.Test plan
qa/rpc-tests/with:<locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP <pubkey> OP_CHECKSIG. Pre-fork: spend succeeds at any height (CLTV is no-op). Post-fork: spend fails before<locktime>, succeeds at-or-after.locktime > tx.nLockTime,nSequence=0xFFFFFFFF.script_tests.jsonBIP65 cases.v2.0.x-rc-bipsoftat testnet h=100.Risks / mitigations
OP_NOP2no-op behaviorOP_NOP2(0xb1) in scriptPubKey. Expected count: zero. Document the result in the testnet announcement.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY). Each revertable independently if testnet exposes a problem.nSequencesemantics. Scope explicitly excludes them.OP_CLTVas no-op and pass the script through. Post-fork rules are strictly tighter, never looser.Process
Bundle into
v2.0.x-rc-bipsoftwith COINBASE_MATURITY (#32) and BIP66 DERSIG (#33). All three rules shareHARDFORK_*_MAIN_OFF = 1,055,555. Branch development onfeat/v2.0.x-rc-bipsoft; do not merge tomainuntil freeze-end (post h=1,050,667).Community chat for live discussion: https://23skidoo.info/discord
Activation milestone (to add to WHERE_WE_LEFT_OFF.md)
BIP65 CLTV: h=1,055,555 (bundled in v2.0.x-rc-bipsoft)References
src/script.h:199—OP_NOP2 = 0xb1slotsrc/script.cpp:393— currentOP_NOP2no-op handlingsrc/main.cpp:570-576— existing tx-levelnLockTimeenforcementLive on mainnet. Activated on schedule at h=1,055,555 (2026-07-23), block
00000000438cf73291060c7c2caeadd568b7e432c192f4f44b3d84eafb157c7c.OP_CHECKLOCKTIMEVERIFYis now consensus-enforced — OFF scripts can bind coins until an absolute height or time, enabling trustless timelock constructions (vaults, escrows, HTLC building blocks). ~5,800 blocks validated under the rule with zero incident; the mixed-version soak (v2.0.8.7 / v2.0.9 / v2.1.0-rc) remains fork-free at delta 0.Shipped in v2.0.9-Eldersign. Closing.