协议演进 / BIP/比特币改进提案 / BIP-113
BIP-113
把一笔时间锁定交易能否进块的判断端点,从本区块的时间戳改为过去 11 个区块时间戳的中位数,保证该值随每个区块单调递增,矿工无法靠谎报时间提前解锁。本 BIP 目前处于已激活状态。
一、档案卡
| 编号 | BIP-113 |
|---|---|
| 标题 | Median time-past as endpoint for lock-time calculations |
| 作者 | Thomas Kerin <[email protected]>;Mark Friedenbach <[email protected]> |
| 指定日期 | 2015-08-10 |
| 层级 | Consensus (soft fork)(共识(软分叉)) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已激活) |
| 阅读版 | https://bips.dev/113 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki |
二、放在哪一族
时间锁族的“计时基准”文档。它自己不发明任何时间锁,只回答一个基础问题:判断“锁到期没有”时,应当拿什么时间来比?
BIP-65:OP_CHECKLOCKTIMEVERIFY,绝对锁定——原文说,本提案旨在保证锁定时间计算有可靠行为,正是 BIP-65 所需要的
BIP-68:相对锁定时间(序列号)
BIP-112:CHECKSEQUENCEVERIFY,脚本相对锁定
BIP-113:给上述按时间计的锁定统一换上中位过去时间(median time-past)这一端点,并与 BIP-68、BIP-112 用同一机制同时部署
想法来源上,原文致谢称:最初的想法由 Gregory Maxwell 于 2013 年 7 月 16 日在 #bitcoin-wizards 频道提出;Mark Friedenbach 设计并编写了参考实现,Thomas Kerin 撰写了本文档。
三、它要解决什么
3.1 区块时间戳并不可靠
当时的规则是:若当前时间或区块高度小于等于交易 locktime 所指定的值,该交易就被排除、不得进块。问题是共识规则并不强制区块时间戳严格有序排列。
3.2 由此产生的歪激励
原文点名这一后果:矿工有动机谎报自己区块的时间,以便把按墙上时钟(wall clock)判断其实尚未到期的时间锁定交易提前收进块里,多赚手续费(collect more fees)。
也就是说,拿单个区块自己的时间戳当裁判,这个裁判恰好由利益相关方填写。BIP-113 要换掉的正是这个裁判。
四、规则本身
4.1 新的端点:过去 11 个区块的中位数
交易 locktime 的数值本身不变,变的只是判断一笔交易能否进块时的计算方式。不再用不可靠的单个时间戳,而是用如下函数得出“当前区块时间”:
enum { nMedianTimeSpan=11 };
int64_t GetMedianTimePast(const CBlockIndex* pindex)
{
...
for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
*(--pbegin) = pindex->GetBlockTime();
std::sort(pbegin, pend);
return pbegin[(pend - pbegin)/2];
}
即:沿链回取最近 11 个区块的时间戳,排序后取中位数。既有的共识规则保证这个值随每个区块单调前进(monotonically advance)——矿工再无法靠谎报自己这一个块的时间,把它往前拨。
4.2 落点:IsFinalTx()
锁定约束由共识方法 IsFinalTx() 检查,该方法把区块时间作为一个参数传入。本 BIP 规定:激活之后,共识代码中调用 IsFinalTx() 时,改传 GetMedianTimePast(pindexPrev) 的返回值,即以前一个区块为基准算出的中位过去时间。
4.3 适用范围
新规则适用于所有交易,包括 coinbase 交易。原文给出的参考实现见其引用的代码合并请求(bitcoin/bitcoin pull request 6566)。
4.4 部署
以 BIP-9(versionbits)的第 0 位部署,且须与 BIP-68、BIP-112 用同一机制同时部署:
- 主网:starttime 为 2016 年 5 月 1 日 00:00 UTC(Unix 时间戳 1462060800),timeout 为 2017 年 5 月 1 日 00:00 UTC(1493596800);
- 测试网:starttime 为 2016 年 3 月 1 日 00:00 UTC(1456790400),timeout 同为 2017 年 5 月 1 日 00:00 UTC。
4.5 兼容性代价
原文在兼容性一节写明:用基于时间的 locktime 生成的交易,其确认时间会比旧规则下预期的大约晚一个小时。原文称,这一变化未发现会给既有协议带来兼容性问题。
五、谁必须动
普通持币人:无直接操作。唯一的体感是:使用基于时间(而非高度)的锁定交易,到期被确认的时间会比旧规则下预计的晚约一小时,应在安排时留出余量。
钱包开发者:估算时间锁定何时可用时,应按中位过去时间而非单个区块时间戳或本地墙上时钟来计算,避免向用户报出过早的可用时刻。
全节点与矿工:升级节点在共识代码的 IsFinalTx() 检查中改用中位过去时间;矿工不能再指望靠时间戳把未到期的锁定交易提前打包——在升级节点眼里这样的块通不过终局性检查。
共识层:这是一次语义重定义:locktime 的数值与编码都不动,动的是与之比较的那个“现在”。它波及一切按时间判断的锁定,包括与 BIP-65、BIP-68、BIP-112 配合使用的情形。
六、现在算不算数,以及一个常见误读
档案状态写作 Deployed,站点状态为已激活:它与 BIP-68、BIP-112 同批部署,是今天仍在生效的共识规则。中位过去时间自此成为比特币里判断时间锁的统一基准——凡是需要“现在几点了”的共识判断,用的都是这个抗操纵的链上时间,而不是某个矿工写在区块头里的数字。
常见误读:
“BIP-113 新增了一种时间锁,或改了 locktime 的写法。”
不对。locktime 的取值与交易写法完全不变,脚本里也不增加任何新操作码。它只替换了判定端点:从“本块时间戳”换成“过去 11 个区块时间戳的中位数”。把它与 BIP-65、BIP-112 混为一谈,就会误以为它也定义了某种 CHECK 类操作码。
七、延伸
- 阅读版:https://bips.dev/113
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki
- 相关:BIP-9 version bits、BIP-65 OP_CHECKLOCKTIMEVERIFY、BIP-68 相对锁定时间、BIP-112 CHECKSEQUENCEVERIFY
- 仓库总目录:https://github.com/bitcoin/bips
