协议演进 / BIP/比特币改进提案 / BIP-135
BIP-135
把 BIP-9 的 version bits 信号机制推广为通用版:每一位可自设阈值、统计窗口与锁定宽限期,且信号对象从软分叉扩展到任意共识变更。本 BIP 目前处于已关闭状态。
一、档案卡
| 编号 | BIP-135 |
|---|---|
| 标题 | Generalized version bits voting |
| 作者 | Sancho Panza <[email protected]> |
| 指定日期 | 2017-03-29 |
| 类型 | Informational(信息类) |
| 状态 | Closed(已关闭) |
| 取代文档 | Replaces: BIP-9 |
| 阅读版 | https://bips.dev/135 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0135.mediawiki |
二、放在哪一族
升级部署与矿工信号族,源头是 BIP-9(version bits 状态机)。BIP-135 在档案关系上直接写明 Replaces: BIP-9,意图不是另起炉灶,而是把 BIP-9 的框架一般化。
它在这一族里的特殊之处有两点:
- 信号对象放宽:BIP-9 只管向后兼容的软分叉信号,BIP-135 把信号位的语义扩展到任意共识变更,统称 forks(分叉),软、硬都在内;
- 参数改为逐位可配:BIP-9 对一条链上所有部署共用固定阈值与不可配的锁定期,BIP-135 让每一位有自己的阈值、窗口与宽限期。
仍用同一段 version bits、仍保留 BIP-9 状态机的状态与原始参数(name、bit、starttime、timeout),只是在状态转移条件上追加参数。设计目标之一就是用合适的参数配置,能严格地向后兼容既有 BIP-9 部署。
三、它要解决什么
原文动机先肯定 BIP-9 服务过往部署有功,再列三条短板:
- 只适用于向后兼容的变更,硬分叉等变更不在其内;
- 固定的 95% 阈值不够灵活,无法表达一条“争议程度光谱”——不同变更本应可以用不同门槛;
- 小少数可以否决拟议变更,可能导致不希望看到的停滞。
协议需要一套灵活的、就协议变更达成共识的方案,才能适应市场需要。通用化修订的目标,就是在保持对既有 BIP-9 部署向后兼容的同时,给激活策略更多选择自由。
原文同时给出配套的使用建议,例如:阈值应尽可能高以确保平稳激活,且强烈建议 threshold 不低于 windowsize 的一半向上取整,以保证只有多数支持才激活;timeout 建议设为 starttime 之后一年;尝试失败后应留一段休耕期(fallow period,惯例建议三个月)以便发现有缺陷的客户端,并给成功分叉留出警告与升级时间。
四、规则本身
4.1 信号位
信号位是区块头 nVersion 字段的最低 29 位,编号 0 到 28。nVersion 最高 3 位必须置为 001,即取值落在 0x20000000 到 0x3FFFFFFF;若某区块 nVersion 最高 3 位不是 001,它的所有信号位一律按 0 处理。
某一位为 1 表示支持对应的分叉并计入统计,为 0 表示不支持、不计入。统计在活跃链链头每次变化时进行,包括重组之后。
与 BIP-9 一致,某区块的部署状态永不取决于它自己的 nVersion,只取决于其祖先。
4.2 五个状态
每个分叉部署在每个区块上处于下列状态之一:
- DEFINED:起始状态,创世块对每个部署按定义处于此状态;
- STARTED:已过 starttime;
- LOCKED_IN:进入 STARTED 后,在高度可被 windowsize 整除处测量,至少 threshold 个(共 windowsize 个)区块置位;
- ACTIVE:宽限期条件满足后的全部区块;
- FAILED:已过 timeout 且仍未锁定。
ACTIVE 与 FAILED 都是终局状态,到达后不再改变。部署状态沿区块链分支分别维护,重组时需要重算。分叉的新共识规则,只对处于 ACTIVE 状态的区块强制执行。
4.3 逐位可配的部署参数
每个分叉部署按链(主网、测试网等分开)配置下列参数:
- name:简短标识,单个 BIP 描述的部署建议用 “bipN”;
- bit:用 nVersion 中的哪一位,取 0 到 28;
- starttime / timeout:以中位时间过去(MTP)计的起止时刻;
- windowsize:统计锁定时回看的区块数;
- threshold:windowsize 中必须置位的区块数,取值 1 到 windowsize,在高度可被 windowsize 整除时测量;windowsize 取 2016 时与难度重定向间隔重合;
- minlockedblocks:进入 ACTIVE 前必须在锁定状态至少停留的区块数;
- minlockedtime:进入 ACTIVE 前必须经过的最短宽限时间,以锁定区块的 MTP 为基准。
从 LOCKED_IN 到 ACTIVE,除高度同步条件外,minlockedblocks 与 minlockedtime 两个宽限条件必须同时满足;两者都设为 0 时,高度一到 windowsize 的倍数即直接转 ACTIVE。
4.4 与 BIP-9 的兼容配置
原文给出把参数调回 BIP-9 行为的对照:主网取 windowsize 2016、threshold 1916(即 95%)、minlockedblocks 2016、minlockedtime 0;测试网取 threshold 1512(即 75%),其余同主网。规范还要求:本规范必须能通过参数实现与既有 BIP-9 部署的严格向后兼容,妨碍完全兼容之处视为错误、应予修正。
此外原文还有可选的运行者通知建议(如状态转移时通知、支持率跟踪、对未知特征信号的警告),以及信号指南(如已 ACTIVE 或已 FAILED 时应发 0、不建议对未定义位发 1、矿工可推翻配置选择发 0 或 1 等)。getblocktemplate 的 BIP-9 相关功能原样保留、不作修改。
4.5 理据中的两个细节
超时进入 FAILED 的设计目的,是让一次尝试失败后信号位日后可以被复用,而不是永久占位。
复用也不是立刻进行:原文在理据与指南中都强调休耕期与参数选择之间的配合。
另一个约束来自既有部署:受 BIP-34、BIP-66、BIP-65 的限制,可用的 nVersion 取值本就有限。
把最高 3 位固定为 001 后剩下的 29 位,就是本规范信号位的全部空间;另两个高位模式(010、011)在原文中被留给将来的其他机制。
五、谁必须动
普通持币人:不必直接操作。信号与状态机是矿工与节点软件之间的事,持币人受影响的方式只是某项变更最终是否按某套参数激活。
钱包开发者:一般不必实现状态机,但要读得懂部署处于哪个状态,以免在未 ACTIVE 时就按新规则构造交易。
全节点与矿工:这是主要实现方。节点要按链维护逐位参数与状态、做统计与重组重算;矿工要在 nVersion 中按自己的选择置位,并可覆盖软件配置决定发 0 还是 1。
共识层:本 BIP 本身按原文“不是共识相关”的信息类文档处理,如同 BIP-9 一样推出时不需要占用一个 BIP-9 分叉位;被它信号的那个分叉,其新规则只在 ACTIVE 后才成为共识。
六、现在算不算数,以及一个常见误读
状态为 Closed(已关闭),且档案上标为 Replaces: BIP-9 的拟议通用化版本。它没有取代现行实践成为通行的激活框架;今天读它,价值在于看清 BIP-9 状态机可以被拆成哪些可调参数,以及“阈值写死 95%”在当时引发了哪些争议。
原文的参考实现以拉取请求形式给出,并保留了既有单元与回归测试,用以演示默认设置与 BIP-9 的向后兼容。
常见误读:
“BIP-135 把激活阈值降了,所以它主张少数人就能强推分叉。”
不对。原文只是让阈值逐位可配,并明确建议阈值应尽可能高、强烈建议不低于窗口的一半,以确保多数支持才激活。它批评的是“一刀切 95% 加小少数否决”这套固定参数,不是主张把门槛普遍调低。
七、延伸
- 阅读版:https://bips.dev/135
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0135.mediawiki
- 相关:BIP-9 version bits 状态机
- 仓库总目录:https://github.com/bitcoin/bips
