协议演进 / BIP/比特币改进提案 / BIP-22
BIP-22
给“聪明的”矿工与代理软件的 JSON-RPC 接口:节点不再只发一个待哈希的区块头,而是把整个区块模板发过去,由矿工自己组装,并用 submitblock 把成果交回来。本 BIP 目前处于已部署状态。
一、档案卡
| 编号 | BIP-22 |
|---|---|
| 标题 | getblocktemplate - Fundamentals |
| 作者 | Luke Dashjr <[email protected]> |
| 指定日期 | 2012-02-28 |
| 层级 | API/RPC(接口) |
| 类型 | Specification(规范类) |
| 状态 | Deployed(已部署) |
| 阅读版 | https://bips.dev/22 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki |
二、放在哪一族
挖矿接口(API/RPC)族的基础文档,与 BIP-23 是上下篇关系:
- BIP-22(本页):getblocktemplate 的基础——怎么请求模板、模板里有什么、怎么提交区块,外加可选的长轮询与模板微调;
- BIP-23:在基础之上为矿池挖矿加的全部可选扩展(区块提议、可变项、提交缩略、逻辑服务等),并明确其所有章节都是对本页的可选增补。
规范内部还牵到两处其他 BIP:模板的 version 字段要求客户端理解所用版本的含义,如版本 2 须遵守 BIP-34(coinbase 中写入区块高度;coinbaseaux 一节也重申高度不经模板下发、由 BIP-34 要求写入);Rationale 还专门说明,交易要下发 sigops 数据,是因为 BIP-16 改变了区块 sigop 的计数规则(要把 scriptCheck 里的也算进去),光看交易本身数不出来。
三、它要解决什么
原文 Motivation 给出两个背景:
其一,bitcoind 内置的 JSON-RPC 服务已经扛不住“生成可供有效挖矿的工作”所需的负载,专门生成工作的外部软件变得必要——挖矿软件与全节点开始分家。
其二,新的独立节点实现正在成熟,将来同样要能给矿工供活。
两边一分家,就必须有一套共同标准来传递“区块怎么构造”的全部细节,否则每种节点与每种工作生成软件之间都要单独适配。getblocktemplate 就是这个接口契约:全节点负责给出经它认可的区块材料,矿工与代理软件在此范围内组装、哈希、提交。
与更早的取活方式相比,关键变化写在摘要里:不再只发一个简单的区块头去哈希,而是把整个区块结构发过去,矿工可以(在允许范围内)自行定制与组装。
四、规则本身
4.1 请求模板:getblocktemplate
JSON-RPC 方法 getblocktemplate 只接受一个参数,且必须是请求参数对象。其中 mode 用于显式选择默认的 “template” 请求,或 BIP-23 定义的 “proposal”(区块提议);请求还可带 capabilities 数组,声明客户端支持的能力,如 “longpoll”、“coinbasetxn”、“coinbasevalue”、“proposal”、“serverlist”、“workid” 以及 BIP-23 的各项可变项。
4.2 模板必含的字段
返回必须是一个 JSON 对象,关键字段包括:
bits:十六进制的压缩难度;curtime:服务器眼中的当前时间(推荐作区块时间,须落在 mintime/maxtime 规则内,不一定等于系统时钟);height:要挖的区块高度;previousblockhash:前一区块哈希(大端十六进制);version:区块版本(当时为 1 或 2,客户端必须理解所用版本的含义);transactions:交易对象数组(不含 coinbase),原则上应提供;coinbasetxn或coinbasevalue:二选一——要么给出 coinbase 交易对象,要么给出 coinbase 可得的总额(单位聪);- 可选项:
sigoplimit、sizelimit(区块的 sigop 与字节上限)、coinbaseaux(应写进 coinbase scriptSig 的数据,只取其值、不取键;区块高度不在此列)、workid(服务器给出时,提交结果必须原样带回)。
4.3 交易对象格式
transactions 中每个对象只有 data(十六进制的完整交易数据)是必填;服务器知道时还应给出:depends(本交易依赖数组中哪几笔,1 起编号)、fee(输入输出差额,单位聪;coinbase 时为所收手续费总额的负数)、hash(小端十六进制)、required(为真则最终区块必须包含它)、sigops(为区块上限计数的签名操作数)。缺失 depends、fee 或 sigops 时,客户端不得假设它们不存在或为零。
4.4 提交区块:submitblock
第二个方法 submitblock 接受两个参数:第一个恒为十六进制编码的区块数据字符串,第二个是可选参数对象(服务器发过 workid 时必须带回该值)。返回规则:份额被接受返回 null;被拒返回简述理由的字符串;涉及合并挖矿时可返回按各链区分的对象。原文附录列了拒收理由词表,如 bad-diffbits(bits 被改)、bad-prevblk(父区块不对)、bad-txnmrklroot(默克尔根不符)、high-hash(哈希未低于目标)、stale-work(工作已过时)、time-too-new / time-too-old 等。
4.5 可选:长轮询(Long Polling)
服务器支持时在模板中给出唯一的 longpollid;矿工用同一授权、以该值发起一个长超时请求,服务器一直等到该替换当前工作时才完成响应。响应可带 longpolluri(长轮询专用地址,给了就必须用它)与 submitold(为 false 时矿工可丢弃先前工作的份额队列)。收到完整响应后,客户端应尽快转到新工作并立刻发起下一次长轮询;响应不完整或无效时须指数退避重试,超过一次失败后禁止无延迟立即重试;遇到 Forbidden(如 HTTP 403)则不得在无人介入时重试。
4.6 可选:模板微调(Template Tweaking)
请求可带 sigoplimit、sizelimit(数字或布尔;负数与零表示自服务器上限的偏移,true 用默认上限,false 表示不要上限)与 maxversion(支持的最高区块版本)。服务器应尽量尊重(SHOULD),但不强制;客户端应自行检查返回模板是否满足要求。
五、谁必须动
全节点(服务器端):按 4.2、4.3 给出完整模板材料与已知元数据;校验并接收 submitblock 提交,按词表给出拒收理由。
独立矿工与挖矿代理软件:理解模板字段的含义(尤其版本规则与 sigop 计数),在服务器允许的范围内组装区块;拿到 workid 必须在提交与提议时带回;支持长轮询的须遵守退避规则,不能失败就无延迟狂重试。
普通持币人:无任何直接关系。这套接口只在节点软件与挖矿软件之间说话。
共识层:不受影响。getblocktemplate 是接口约定,模板里装的仍是按现行共识规则构造的普通区块;接口本身不改变任何区块有效性规则。
六、现在算不算数,以及一个常见误读
状态为 Deployed(已部署):它与 BIP-23 一起构成挖矿软件与全节点之间的通行接口语言,参考实现在原文中列有 Eloipool(服务器)、libblkmaker(客户端)与 bitcoind 的最小服务器实现。
判断“一个实现支持到什么程度”时要分清层次:本页的非可选部分是基础;长轮询、模板微调是本页内的可选项;BIP-23 的全部内容更是在其上的可选扩展。所以“支持 getblocktemplate”不自动等于支持全部扩展,BIP-23 甚至为矿池扩展单独划了 Level 1 / Level 2 两档。
常见误读:
“getblocktemplate 就是节点把拼好的区块头丢给矿工,矿工只管算哈希。”
恰好反了。原文摘要明确说:发过去的是整个区块结构,组装与(在允许范围内的)定制留给矿工。只发区块头的老式取活方式正是它要替代的对象——也正因为矿工能看见并能动区块内容,才需要有 BIP-23 的提议校验与可变项清单来划清边界。
七、延伸
- 阅读版:https://bips.dev/22
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki
- 相关:BIP-23 getblocktemplate——矿池挖矿(扩展篇)、BIP-34 区块 v2 与 coinbase 高度、BIP-16 P2SH(sigop 计数背景)
- 仓库总目录:https://github.com/bitcoin/bips
