OP_CHECKLOCKTIMEVERIFY 怎么用?比特币绝对时间锁的脚本与陷阱 图 1
OP_CHECKLOCKTIMEVERIFY 怎么用?比特币绝对时间锁的脚本与陷阱 · 图 1

时间锁要解决什么问题

普通的比特币输出只要签名正确随时可花。但有些场景需要“不到某个时点谁也花不了”:两个陌生人做原子交换,退款分支要等对方超时后才能动用;一个非托管退款路径要给自己留后路;个人资产规划希望某笔输出在若干年后才可动用。BIP65 引入的操作码 OP_CHECKLOCKTIMEVERIFY(常缩写为 CLTV)就是为此设计的,它作为软分叉在区块高度 388381 处生效,今天所有全节点都强制执行这条共识规则。

验证逻辑其实很简单

CLTV 把交易的 nLockTime 字段和脚本里预先写入的一个“门槛值”做比较:如果当前链上已允许的时间(区块高度或 Unix 时间戳)还没有达到门槛,脚本直接失败,无论签名多好。这里要和常见误解区分开:nLockTime 单独使用时只是限制“这笔交易最早何时能被打包”,而 UTXO 一旦被确认就可以被正常花掉;CLTV 把锁的条件写进了输出脚本本身,锁的是这笔输出本身,任何想要花费它的交易都必须满足条件,详见 比特币 UTXO 是什么?和账户模型区别。锁定的坐标有两种写法:小于 5 亿整数按区块高度解释,大于等于 5 亿按 Unix 秒解释,脚本里选哪种就锁哪种,不能混用。

花费一侧必须做什么

构造花费交易时,交易的 nLockTime 必须填一个不小于门槛、且不超过当前链上中位时间的值。这里藏着本文最重要的一个坑:nLockTime 非零的交易如果不把输入的 nSequence 显式设成最大值,会被节点按照 BIP125 判定为“可选择替代”(RBF)交易。对退款路径来说,这通常不是你想要的——你的退款交易可能还没等到时间窗就被自己的另一版本挤掉。稳妥做法是:构造 CLTV 退款分支的花费交易时,把时间锁需要的 nLockTime 填对的同时,评估是否需要显式设置序列号,必要时配合钱包的 opt-in 全替代信号规则核对,具体取舍见 比特币RBF和CPFP怎么选?

脚本长什么样

一段典型脚本的逻辑顺序是:先把门槛值压栈,执行 OP_CHECKLOCKTIMEVERIFY,再 OP_DROP,然后才进入正常签名验证。注意 CLTV 验证完不会替你把值弹出,脚本作者必须自己处理栈,早期实现常在这里出错。地址形态上,CLTV 脚本被哈希后放进 P2SH,或者放进隔离见证见证脚本,地址类型本身不决定有没有时间锁,见 比特币地址类型是什么?

与相对时间锁的分工

CLTV 是绝对坐标:锁到“高度 900000 或 2027 年 1 月之后”。如果你的需求是“输出确认之后再等 N 个块”,那属于相对时间锁,由 OP_CHECKSEQUENCEVERIFY 负责,两者在闪电网络里配合使用,本文不展开,见 OP_CHECKSEQUENCEVERIFY 相对时间锁:延迟从何时起算。构造和签名流程如果不联网完成,需要走 PSBT 离线签名,见 比特币离线签名流程是什么?不联网怎么完成一次转账

小结与风险提示

CLTV 给了比特币输出一个硬性到期日:主路径到期前不动,退款路径到期后兜底。它的风险主要在构造环节——门槛单位选错、花费交易 nLockTime 填错、时间锁意外带来 RBF 信号——上线任何依赖时间锁的流程前,务必在测试网完整演练两条支出路径。涉及资产锁定的操作存在脚本构造与执行风险,本文不构成投资建议。

实操前的一次完整演练清单

上线任何带时间锁的流程之前,建议至少完成以下动作:第一,在测试网络分别走通“主路径提前花费”和“退款路径到期花费”两条分支,确认前者被拒绝、后者被接受;第二,用离线工具核对脚本哈希与收款地址一致,防止脚本写错却把钱锁进了无法识别的模板;第三,把门槛值换算成日历时间写进运行手册,区块高度与时间戳两种单位混用是事故高发区;第四,若退款路径依赖你未来主动发起,评估届时钱包版本、费率与替代信号是否仍然可用。时间锁的本质是把信任从“对手方守约”转移到“链的规则”,而链只认字节,不认你的意图——脚本里写错一个字节,锁住的可能是你自己的退路。