BTC篇
什么是挖矿?
BTC节点通过网络收集未打包的交易,产生出candidate block(候选区块),其header包含如下字段:
- Version 表示当前使用的BTC协议的版本
- Previous Block Hash 前一个区块的hash值
- Merkleroot 打包到当前区块的交易组装的merkle tree的root hash
- Difficulty target 当前BTC网络的难度值,简单说就是要成为合法的区块,区块哈希前面要有多少个0
- Timestamp 时间戳
- Nonce 32bit的随机值,矿工可以通过搜寻合适的Nonce值,让区块哈希满足前面的Difficulty target
挖矿就是通过调整区块中的内容,主要是Nonce值,产生出一个符合当前网络难度的合法区块。
挖矿的目的
对于BTC网络来说:挖矿是产生合法区块的唯一途径,保持BTC网络安全持续的运转下去。
对于矿工个人来说:挖矿可以获得BTC奖励。
挖矿历史和演进
挖矿经历了CPU → GPU → FPGA → ASIC 等演进阶段。
BTC自身就带有挖矿程序,但是只支持CPU挖矿,所以最开始是CPU挖矿阶段。
很快大家就发现GPU在挖矿上比CPU效率高的多,于是果断抛弃官方的挖矿程序,开发了基于GPU的专用挖矿软件(比如cgminer)。
通过FPGA过渡之后,最终进入了ASIC(专用芯片)阶段。
相关历史可以参见 Category:History - Bitcoin Wiki
参与挖矿的两种方式
Solo mining 和 加入矿池。
Solo mining顾名思义,就是矿工独自挖矿。只要自己运行一个BTC节点,运行挖矿软件就可以了(现在比较难了,后面再展开)。
但是挖矿是个完全随机的过程,波动比较大。其大致遵循泊松分布,即使矿工的算力达到平均每天能挖到一个块,在具体的某天,也有高达37%的概率挖不到块。这对于每天都要吃饭和交电费的矿工来说风险太大了。
然后矿池模式就诞生了。矿池是将一批矿工的算力聚集到一起挖矿,然后将挖矿收益根据每个矿工的贡献比例进行分配。类似于多人合伙买彩票,中奖之后按出资比例分配奖金。
这样可以降低收益的波动,矿工每天可以有比较稳定的收益,降低了风险。矿池模式很快成为挖矿的主流。
但是矿池模式也是有问题的。从前面的分析可知,矿池聚集的算力越多,收益波动越小。因此矿工会倾向于加入算力更大的矿池,导致矿池的头部效应,全网算力很快就集中到了几个头部的矿池。这导致了网络的中心化和潜在的51%攻击的风险。
矿池运营方只会运行一个全节点和一个矿池服务端。矿工的挖矿设备依然自己管理,通过网络与矿池交互,从矿池那里获取任务,然后只负责尝试计算区块哈希,然后向矿池上报任务完成情况。
此模式下,矿工并不运行节点,挖矿收益是直接进入矿池的账户,然后矿池收取一定比例的手续费后,根据各个矿工的贡献度进行收益分配。
矿池统计矿工贡献度的方式叫share。前面提到过,只有区块哈希前面的0足够多,才是一个合法的区块,才会有挖矿奖励。share就是一个不够格的区块,其哈希前面的0不够多。矿池通过统计矿工提交的share数量来评判其贡献度。类似于我们日常的每日工作汇报,不一定要完成工作之后才去向领导汇报,每天都汇报一下工作进展(完成了一个步骤或者其中一个小任务),这样领导知道你每天都在干活,才会给你记工。
结算模式也有不同的方式,参见 https://f2pool.zendesk.com/hc/zh-tw/articles/360061042332-收益結算模式-PPS-PPLNS-FPPS-PPS
矿机与矿池之间的网络通信逐渐形成了一套矿池协议(这个等下再展开),先回过头来说solo mining。因为矿池模式是挖矿的主流,因此在ASIC时代,矿机厂商直接就在矿机的固件里集成了挖矿协议。
更具体来说矿机的固件其实就是一个挖矿软件,从比特大陆很早之前开源的固件代码来看,其实就是cgminer。对挖矿协议的支持也在cgminer代码里面。Antminer_firmware/sources/meta-antminer/recipes-bitmianer/cgminer/cgminer-1.0/cgminer-3.12.0_bak/util.c at master · bitmaintech/Antminer_firmware · GitHub
因此矿工买到ASIC矿机之后,只要开机之后设置一下连接矿池的配置,马上就可以开始参与挖矿。反而自己挖矿变的困难了,因为矿机默认就是连矿池的,而不能连自己运行的节点了。
当然方法也是有的,就是自己跑一个矿池服务端,相当于一个私有化部署的矿池。但是因为矿池和矿机涉及巨大的经济利益,一般都是不开源的,网上也很少有相关的技术资料。BTC原来有一个开源的BTCPool,但是已经废弃,很多年没有更新了。现在有一个 GitHub - benjamin-wilson/public-pool 可以用,算是给solo ming保留了一丝火种。
矿池协议演进
Getwork。
BTC节点最早为挖矿提供了一个Getwork的RPC接口,但是这个接口并不是返回candidate block(候选块)的完整区块头,而是会将区块头预处理成一段data,矿工拿到之后只是不停的尝试不同的Nonce值并计算哈希。
前面讲过,一个区块是否有效看的是整个区块头的哈希前面是否有足够的0,所以调整区块头的任何一个值都可以。但是Getwrok模式下,矿工只能修改Nonce值,而无法修改区块头的其他内容,而BTC的Nonce字段只有32位。
当矿工的算力达到4.3Ghash/s的时候,1秒就可以遍历所有可能的Nonce。剩下的时间就只能干等着节点给新的任务。如果矿池连接了多个矿工,就更惨了,多个矿工的任务完全是重复的,严重浪费了算力。
GBT(Getblocktemplate)
BTC节点提供了新的RPC接口——Getblocktemplate——返回更多的区块信息,让矿工可以调整的东西更多(比如timestamp和coinbase交易中的无关内容),从而增加了矿工的搜索空间。
大名鼎鼎的Stratum (V1)协议
Stratum与GBT方案差不多时间提出,但是Stratum协议是由首个BTC矿池运营商提出的,他们明显更懂挖矿,而且在吸收了GBT方案的基础上进行了一些改进,因此最终成为了挖矿的事实标准。
现在只要说起挖矿协议,默认指的就是Stratum (V1)协议。
Stratum (V1)协议非常的简单,直接基于TCP连接,内容是以换行隔开的,一行一个json字符串。非常简单易懂,且易于调试,速度快,资源占用小。
最主要的是针对矿池模式进行了很多优化。比如它引入了 extranonce 的概念。前面我们提到过,一个矿池可以接入很多矿工。如果矿池给所有矿工下发同样的任务,让他们随机寻找Nonce,那多个矿工之间可能就会重复搜寻,浪费算力。extranonce 就像hash分桶一样,给每个矿工分配了一个不同的前缀值,这样不同的矿工就在不同的桶力搜索,避免了重复劳动。
更详细的协议内容大家可以看参考资料或者实际的交互例子 Ethereum stratum mining protocol v1.0.0 - 简书
当然这个协议也有一些缺点:
- 安全风险。因为是明文协议,很容易被攻击。
- 隐私。矿工的信息完全暴露给矿池,没有任何隐私可言。
- 鉴权不完善。非常简单的用户名密码机制,而且还明文传输,容易遭受中间人攻击。
- 带宽消耗大。json格式的消息不够有效。
- 中心化风险。到目前为止的三个演进阶段,都是为了解决搜索空间,或者挖矿效率的问题。对于矿池模式娘胎力带来的中心化风险没有任何改善。矿工完全就是机器上的齿轮,所有的权力都被矿池掌控。
Stratum (V2)协议。
Stratum (V2)改进了V1的很多缺点:
- 消息换成了二进制格式,更加紧凑,带宽消耗大大减少。
- 完善了鉴权和加密,使用公私钥方案,更加安全。
- 解决了中心化风险。通过复杂的架构,让矿工可以提交自己的区块,包括自己的coinbase,也就是收益可以直接到矿工账户上。实现了solo和矿池两种模式的无缝切换。
- 效率提升。矿池给矿机下发的各项信息,其变动的周期其实差别很大。比如Previous Block Hash,这个在一个出块周期内都不会变。而transaction相关的信息,一旦有新的交易打包进来,就会变化,变化更频繁。V1协议是每次都全量下发,对变动不频繁的有些浪费,对变动频繁的则不够及时。V2把任务内容进一步拆分,可以以不同的频率下发不同信息,更有效率,更及时。而且如果当前区块被本矿池挖到,那么直接把当前区块的哈希作为Previous Block Hash下发,就可以在下一个块有一些先发优势。
V2协议对BTC节点的RPC也提出了新要求(需要修改BTC节点)。它提出了一个新的概念,templateProvider。不同于原来那些get方法,是在BTC节点中新增加一个服务,采用push的方式主动推送,可以更及时的通知交易池重组,同步区块等信息。参见 doc: explain Stratum v2 design, testing and usage · bitcoin/bitcoin@72b8f59 · GitHub
但是它至今还很少有落地实现。虽然官方做了参考实现( GitHub - stratum-mining/stratum: stratum ),并且提供了兼容和升级方案。
但是跟历史上很多升级换代的技术一样,因为老的技术太成熟,生态太庞大了,新的技术很难冒头。
目前绝大部分矿机的固件和商业矿池都还是V1协议。只有 Braiins OS 提供了部分BTC矿机的V2固件,他们家的Braiins Pool 支持V2协议。
矿机与矿池
这两个对于挖矿来说很重要的东西,在区块链生态里面显得非常神秘。跟区块链生态其他部分各种开源,宣讲,有点进展恨不得满世界宣传,相比之下矿机和矿池是闷声发大财的代表。
因为相互之间有博弈关系,所以大家都非常小心翼翼,好像不太想暴露太多技术细节,但是又相互依赖,需要尽量兼容。矿机要兼容尽量多的矿池,矿池也要兼容尽量多的矿机。
Stratum (V1)协议其实没有特别明确的标准文档,但是大家通过这种相互摸索,逐渐形成了一种类似行业默契的事实标准。
这种默契是Stratum (V2)很难打破的。所以估计在之后很长一段时间,Stratum (V1)协议的地位都很难被动摇。