协议演进 / BIP/比特币改进提案 / BIP-310

BIP-310 Stratum 协议扩展

为 Stratum 挖矿协议定义通用的扩展协商机制 mining.configure,并首先规范 version rolling:让矿工与矿池协商可改写的 nVersion 位。本 BIP 目前处于草案状态。

一、档案卡

档案卡
编号BIP-310
标题Stratum protocol extensions
作者Pavel Moravec <[email protected]>、Jan Čapek <[email protected]>
指定日期2018-03-10
层级Applications(应用)
类型Informational(信息类)
状态Draft(草案)
阅读版https://bips.dev/310
官方原文https://github.com/bitcoin/bips/blob/master/bip-0310.mediawiki

二、放在哪一族

挖矿协议族。Stratum 是矿工(矿机)与矿池服务器之间通信的协议;比特币早期的挖矿协议文档还有 BIP-40、BIP-41(Stratum 线路协议与挖矿协议,仅分配编号)与 BIP-22、BIP-23(getblocktemplate,节点与矿池之间取区块模板的接口)。

BIP-310 不重写 Stratum,而是给它加一层“扩展协商”:以后再加新功能,不必再逐个发明新消息。它规范的第一个、也是最重要的扩展 version rolling,与区块头 nVersion 位的用途直接相关,因此常与下面两篇一起读:

BIP-320:把 nVersion 的 16 位预留为通用用途

BIP-323:把预留扩大到 24 位

三、它要解决什么

3.1 矿工想改 nVersion,却没法告诉矿池

最初的动机是 version rolling:矿工改写区块头第一个字段 nVersion 的值。区块头里可供矿工滚动的空间有限,多滚一些位能减少向矿机分发新任务的频率;其中 AsicBoost 等技术也要用到 nVersion 的位。

但在原始 Stratum 协议里,这件事做不成:矿工无法把不同的区块版本值传达给服务器,服务器也无法把“哪些位可以安全滚动”告诉矿工。这是一个与旧协议不兼容的改动,矿工与矿池两侧都必须实现某种协议扩展才能支持。

3.2 乱发未知消息不安全

原文指出一个现实约束:通常矿工若向服务器发送未知消息,服务器会直接关闭连接(并非所有实现都这样,但有些会)。因此试探性地发送未知消息并不安全。

3.3 借一次不兼容改动,做成通用机制

作者的取舍是:既然不得不做一次不兼容改动,就把它做成通用的——引入一条新消息 mining.configure,统一处理特性的初始配置与协商。此后添加新特性不必再增加新消息;矿工既能宣告自己的能力,也能向服务器请求所需特性。原文要求同一协商机制也能服务于尚未知晓的未来特性,且在挖矿软件中应当易于实现。每个扩展有一个唯一字符串名,称扩展代码(extension code)。

四、规则本身

4.1 mining.configure 消息

这是矿工在与服务器建立连接后应当发送的第一条消息(JSON-RPC 请求)。它带两个必填参数:

返回值为一张映射:extensions 列表中的每个代码都必须有明确返回值——true 表示该特性被支持、配置被理解并应用;false 表示不支持或未知;字符串则表示出错信息。某些扩展还借返回映射把附加信息(如最终掩码)送回矿工。

原文在规范部分列出的扩展有三个:version-rolling、minimum-difficulty、subscribe-extranonce;正文另行定义了 info 扩展。

4.2 扩展一:version-rolling

矿工发送一个掩码,说明自己能改写哪些位(1 为可改、0 为不可改,称 miner_mask),并给出高效滚动所需的最少位数(version-rolling.min-bit-count,必填)。服务器通常只允许改写其中一部分位(server_mask),其余位须固定——例如区块要保持有效、或某些位正用于信号。服务器的回应掩码是两者的交集:

response = server_mask & miner_mask

参数与返回值要点:

协商成功后,服务器可随时用通知 mining.set_version_mask 下发新掩码,新掩码立即生效、不等下一个任务;矿工提交结果的 mining.submit 消息则须多带一个参数 version_bits(排在 worker_name、job_id、extranonce2、ntime、nonce 之后的第 6 个参数)。矿工只能置位最后收到掩码中为 1 的位(须满足 version_bits & ~last_mask == 0),服务器按下式算出最终 nVersion:

nVersion = (job_version & ~last_mask) | (version_bits & last_mask)

4.3 其余扩展

4.4 与旧机制的不兼容

原文专门说明:Stratum 里原有一个类似的特性 mining.capabilities,本意也是承载各种协议扩展;但 mining.configure 与之不兼容,因为 configure 要求服务器对每个被接受、被协商的扩展逐一回复确认,而 mining.capabilities 的请求没有关联响应,无从确认协商结果。

五、谁必须动

普通持币人:完全无感。这份 BIP 只涉及矿机与矿池之间的通信,不涉及钱包与交易。

矿工与矿机固件开发者:要在连接建立后先发 mining.configure,宣告扩展并给出参数;实现 version rolling 的,还须遵守掩码纪律——只改服务器放行的位,提交时带上 version_bits,并处理运行中掩码被更新的情况。

矿池运营者:要实现 mining.configure 的应答语义:对每个请求的扩展明确回 true、false 或错误信息;计算并下发掩码交集;接受带 version_bits 的 mining.submit 并按下式合成 nVersion;超出位数请求时让矿工降级运行而非断开连接。

全节点与共识层:无需改动。本 BIP 是信息类文档,不改变比特币共识规则;它影响的是区块头 nVersion 在矿工侧如何被滚动,而区块是否有效仍由既有规则判定。

六、现在算不算数,以及一个常见误读

状态为 Draft(草案),类型为 Informational(信息类)。信息类 BIP 的作用是描述与说明,不提出必须采用的强制规范;因此它的“算不算数”不在主网共识,而在矿工与矿池的实际实现是否按同一套扩展名与协商格式对接。原文给出的机制与扩展定义可供实现者直接参照,但草案状态意味着文本仍可能变动,引用时应以仓库原文为准。

常见误读:

“BIP-310 规定了矿工可以随便改 nVersion 的哪些位。”

不对。它只规定“怎么协商”:矿工报自己能改的位,矿池报自己放行的位,实际可改的是两者交集,且矿池可以随时下发新掩码收紧。哪些位在比特币规则层面适合通用滚动,是 BIP-320、BIP-323 讨论的事,不是本 BIP 单方面定的。

七、延伸

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