协议演进 / 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 用同一机制同时部署:

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 类操作码。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。