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

BIP-22 getblocktemplate——基础

给“聪明的”矿工与代理软件的 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:模板的 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 对象,关键字段包括:

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 的提议校验与可变项清单来划清边界。

七、延伸

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