份额难度与额外随机数:矿机的工作空间从哪来 图 1
份额难度与额外随机数:矿机的工作空间从哪来 · 图 1

网络难度太高,矿机够不着

比特币网络的难度阈值意味着:一个算力不算大的设备,可能连续几年都撞不出一个合规区块头。如果让矿机直接以网络难度为目标盲跑,它既无法证明自己”在干活”,也几乎不可能产出任何可提交的结果。矿池的做法是设一个门槛低得多的过滤器——份额难度(share difficulty)。矿机照常穷举随机数,凡是哈希值低于份额难度阈值的结果就提交给池子记为一份份额;池子定期用set difficulty之类的消息按你的算力调整这个阈值:机器快就调高,慢就调低,让提交频率保持在一个既能证明工作量、又不会把池子网络刷爆的舒适区间。份额哈希通常达不到网络出块标准,但它以可验证的方式摊平了”你干了这么多活”这一事实。

getwork时代:4字节随机数的天花板

早期矿机通过getwork接口拿一个现成的区块头去算。区块头里可自由遍历的字段只有4字节的nonce,翻一轮不过约43亿次哈希,即大约4GH的工作量。GPU时代这已经捉襟见肘,面对2012年底呼之欲出的ASIC,一个头根本喂不饱一台机器——矿机每秒要算上千亿次,只能不停换头。协议后来加了rollntime扩展,也只是把每头4GH提升到每秒4GH的量级,仍然远低于新一代硬件的吞吐。

换思路:把区块本身变成一个巨大的旋钮

解法是不再限定”同一个头”,而是让每一次哈希都用不同的区块内容。getblocktemplate协议(BIP22与BIP23)把建块权交还给矿机一侧:矿机自己组织交易、自己搭默克尔树,需要多少工作空间就造多少个不同的区块头。Stratum协议选择了更省流量的折中:池子不把整棵默克尔树发下来,只发coinbase交易和默克尔分支。矿机在coinbase的额外随机数字段(extra nonce,由池子分配的一段空间加矿机自己的计数)里做文章——coinbase哈希一变,整棵默克尔树的根就变,区块头随之全变。于是单个任务就内含了几乎无限多个可遍历的区块头,配合池子随时的job推送,一台现代矿机可以在一条TCP连接上吃满自己的算力。

这套机制的日常代价

工作空间变大的另一面是新的边角问题:矿机重启后如果没有及时取回原来的extra nonce取值区间,可能重复合成已经算过的区块头,白白浪费算力;池子换任务时旧任务上的慢结果会变成”过期份额”被拒收;而份额难度报错了,轻则大量误拒,重则池子记账失真。理解”份额只是过滤器、真正值钱的哈希极其稀有”这件事,也能帮普通读者识别一类话术:凡是把提交份额的数量说成挖到了多少比特币的,都是把记账凭证和币混为一谈。

从一次完整提交的视角串一遍

把镜头拉远看一个工作周期:矿机开机,向池子注册账户,池子按账户历史算力下发一个初始份额难度和第一批任务;矿机在coinbase额外随机数与时间戳、随机数组成的空间里高速扫描,每撞到一个低于份额阈值的哈希,就带着任务编号、随机数和时间戳提交一次;池子校验收纳为份额,可能顺手把份额难度往上调一档。每隔几十秒到半分钟,一旦全网有人出块或池子重组交易集合,一条新任务推送下来,旧任务即刻作废。这个循环里没有任何一步需要”碰运气中大奖”——大奖是池子层级极小概率的副产品,由那个恰好让哈希值低于网络目标的随机数触发,随后进入前面讲的结算程序。也正因为工作单元如此廉价,协议才必须用份额难度做闸门:闸门太松,海量无效提交挤爆网络与记账;闸门太紧,低算力设备几分钟凑不出一份凭证,被系统性地排除在结算之外。闸门调得好不好,本身就是矿池工程能力的体现。