在讲什么是算力时咱们说到:挖矿是做算法运算的过程,从计算机和代码的角度来讲,是反复执行Hash函数并检测执行结果的具体过程。挖矿的原理和流程请回顾:区块链100讲:知乎千赞回答讲清挖矿过程node
而在区块链100讲:不作码农作矿工,该怎么和爹妈解释一文中,你们已经很是清楚挖矿是由最开始的CPU挖矿,过分到GPU挖矿,最终演化到当前的ASIC(专业矿机)挖矿时代,本讲继续聊“挖矿”。挖矿的演进是硬件的演进过程,同时也是软件的演进过程,尤为是软硬件对接协议的改进过程,本文重点经过与挖矿有关的几个核心协议解析其中的逻辑设计和技术实现。算法
Setgenerate协议接口表明了CPU挖矿时代。后端
中本聪在论文里描述了“1 CPU 1 Vote”的理想数字民主理念,在最第一版本客户端就附带了挖矿功能,客户端挖矿很是简单,固然,须要同步数据结束才能够挖矿。如今有不少算力很低的山寨币仍是直接使用客户端挖矿,有两种方式能够启动挖矿:安全
在配置文件设置gen=1,而后启动客户端,节点将自行启动挖矿。网络
客户端启动后,利用RPC接口setgenerate控制挖矿。数据结构
若是使用经典QT客户端,点击“帮助”菜单,打开“调试窗口”,在“控制台”输入以下命令:setgenerate true 2,而后回车,客户端就开始挖矿,后面的数字表明挖矿线程数,若是想关闭挖矿,在控制台使用以下命令:setgenerate false,可使用getmininginfo命令查看挖矿状况。函数
节点挖矿过程也很是简单:性能
构造区块,初始化区块头各个字段,计算Hash并验证区块,不合格则nNonce自增,再计算并验证,如此往复。在CPU挖矿时代,nNonce提供的4字节搜索空间彻底够用(4字节即4G种可能,单核CPU运算SHA256D算力通常是2M左右),其实nNonce只遍历完两个字节就返回去重构块。区块链
getwork协议表明了GPU挖矿时代,需求主要源于挖矿程序与节点客户端分离,区块链数据与挖矿部件分离。优化
使用客户端节点直接挖矿,须要同步完整区块链,数据和程序紧密结合,也就是说,若是有多台电脑进行挖矿,须要每台电脑都单独同步一份区块链数据。这其实没有必要,对于矿工来讲,最少只须要一个完整节点就能够。而以此同时,GPU挖矿时代的到来,也须要一个协议与客户端节点交互。
getwork核心设计思路是:
由节点客户端构造区块,而后将区块头数据交给外部挖矿程序,挖矿程序遍历nNonce进行挖矿,验证合格后交付回给节点客户端,节点客户端验证合格后广播到全网。
如前所述,区块头共80个字节,因为没有区块链数据和待确认交易池,nVersion,hashPrevBlock,nBits和hashMerkleRoot这4个字段共72个字节必须由节点客户端提供。挖矿程序主要是递增遍历nNonce,必要时候能够微调nTime字段。
对于显卡GPU来讲,其实不用担忧nNonce的4字节搜索空间不足,并且挖矿程序从节点客户端那里拿到一份数据后,不该该埋头工做过久,否则颇有可能这个块已经被其余人挖到,继续挖只能作无用功,对于比特币来讲,虽然设计为每10分钟一个区块,良好的策略也应该在秒级内从新向节点申请新的挖矿数据。对于显卡来讲,运行SHA256D算力通常介于200M~1G,nNonce提供4G搜索空间,也就是说再好的显卡也能支撑4秒左右,调整一次nTime,又能够再挖4秒,这个时间绰绰有余。
节点提供RPC接口getwork,该接口有一个可选参数,若是不带参数,就是申请挖矿数据,若是带一个参数,就是提交挖到的块数据。
不带参数调用getwork,返回数据以下:
Data字段
共128字节(80区块头字节 + 48补全字节),由于SHA256将输入数据切分红固定长度的分片处理,每一个切片64字节,输入总长度必须是64字节的整数倍,输入长度通常不符合要求,则根据必定规则在元数据末端补全数据。其实对于挖矿来讲,补全数据是固定不变的,这里不必提供,外部挖矿软件能够自行补齐。甚至连nNonce字段都不须要提供,data最少只须要提供前面的76字节就够了。nTime字段也是必不可少的,外部挖矿程序须要参照节点提供的区块时间来调节nTime。
Target字段
即当前区块难度目标值,采用小头字节序,须要翻转才能使用。
其实对于外部挖矿程序来讲,有data 和 target这两个字段就能够正常挖矿了,不过getwork协议充分考虑各类状况,尽可能帮助外部挖矿程序作力所能及的事,提供了两个额外字段,data字段返回完整补全数据也是出于此理念。
Midstate字段
如上所述,SHA256对输入数据分片处理,矿工拿到data数据后,第一个分片(头64字节)是固定不变的,midstate就是第一个分片的计算结果,节点帮忙计算出来了。
所以,在midstate字段辅助下,外部挖矿程序甚至只须要44字节数据就能够正常挖矿:32字节midstate + 第一个切片余下的12(76-64)字节数据。
Hash1字段
比特币挖矿每次都须要连续执行两次SHA256,第一次执行结果32字节,须要再补充32字节数据凑足64字节做为第二次执行SHA256的输入。hash1就是补全数据,同理,hash1也是固定不变的。
外部挖矿程序挖到合格区块后再次调用getwork接口将修改过的data字段提交给节点客户端。节点客户端要求返回的数据也必须是128字节。
每次有外部无参调用一次getwork时,节点客户端构造一个新区块,在返回数据前,都要把新区块完整保存在内存,并用hashMerkleRoot做为惟一标识符,节点使用一个Map来存放全部构造的区块,当下一个块已经被其余人挖到时,当即清空Map。
getwork收到一个参数后,首先从参数提取hashMerkleRoot,在Map中找出以前保存的区块,接着从参数中提取nNonce和nTime填充到区块的对应字段,就能够验证区块了,若是难度符合要求,说明挖到了一个块,节点将其广播到全网。
getwork协议是最先版本挖矿协议,实现了节点和挖矿分离,经典的GPU挖矿驱动cgminer和sgminer,以及cpuminer都是使用getwork协议进行挖矿。getwork + cgminer一直是很是经典的配合,曾经不少新算法推出时,都快速被移植到cgminer。即使如今,除了BTC和LTC,其余众多竞争币都还在使用getwork协议进行挖矿。矿机出现以后,挖矿速度获得极大提升,当前比特币矿机算力已经达到10T/秒级别。而getwork只给外部挖矿程序提供32字节共4G的搜索空间,若是继续使用getwork协议,矿机须要频繁调用RPC接口,这显然不可行。现在BTC和LTC节点都已经禁用getwork协议,转向更新更高效的getblocktemplate协议。
getblocktemplate协议诞生于2012年中叶,此时矿池已经出现。矿池采用getblocktemplate协议与节点客户端交互,采用stratum协议与矿工交互,这是最典型的矿池搭建模式。
与getwork相比,**getblocktemplate协议最大的不一样点是:getblocktemplate协议让矿工自行构造区块。**如此一来,节点和挖矿彻底分离。对于getwork来讲,区块链是黑暗的,getwork对区块链一无所知,他只知道修改data字段的4个字节。对于getblocktemplate来讲,整个区块链是透明的,getblocktemplate掌握区块链上与挖矿有关的全部信息,包括待确认交易池,getblocktemplate能够本身选择包含进区块的交易。
getblocktemplate 在被开发出来后并不是一成不变,在随后发行的各个版本客户端都有所升级改动,主要是增添一些字段,不过核心理念和核心字段不变。目前比特币客户端返回数据以下,考虑到篇幅限制,交易字段(transactions)只保留了一笔交易数据,其实根据当前实际状况,待确认交易池实时有上万笔交易,目前区块基本都是塞满的(1M容量限制),加上额外信息,所以每次调用getblocktemplate基本都有1.5M左右返回数据,相对于getwork的几百个字节而言,不可同日而语。
来简单分析一下其中几个核心字段, Version,Previousblockhash,Bits这三个字段分别指区块版本号,前一个区块Hash,难度,矿工能够直接将数值填充区块头对应字段。
Transactions,交易集合,不但给了每一笔交易的16进制数据,同时给了hash,交易费等信息。 Coinbaseaux,若是有想要写入区块链的信息,放在这个字段,相似中本聪的创世块宣言。
Coinbasevalue,挖下一个块的最大收益值,包括发行新币和交易手续费,若是矿工包含Transactions字段的全部交易,能够直接使用该值做为coinbase输出。
** Target**,区块难度目标值。
Mintime,指下一个区块时间戳最小值,Curtime指当前时间,这两个时间做为矿工调节nTime字段参考。
Height,下一个区块难度,目前协议规定要将这个值写入coinbase的指定位置。
矿工拿到这些数据以后,挖矿步骤以下:
构建coinbase交易,涉及到字段包括Coinbaseaux,Coinbasevalue,Transactions,Height等,固然最重要的是要指定一个收益地址。
构建hashMerkleRoot,将coinbase放在transactions字段包含的交易列表以前,而后对相邻交易两两进行SHA256D运算,最终能够构造交易的Merkle树。因为coinbase有不少字节可供矿工随意发挥,此外交易列表也可随意调换顺序或者增删,于是hashMerkleRoot值空间几乎能够认为是无限的。其实getblocktemplate协议设计的主要目标就是让矿工得到这个巨大的搜索空间。
构建区块头,利用Version,Previousblockhash,Bits以及Curtime分别填充区块头对应字段,nNonce字段可默认置0。
挖矿,矿工可在由nNonce,nTime,hashMerkleRoot提供的搜索空间里设计本身的挖矿策略。
上交数据,当矿工挖到一个块后当当即使用submitblock接口将区块完整数据提交给节点客户端,由节点客户端验证并广播。
**须要注意的是:**与上文提到的GPU采用getwork挖矿同样,虽然getblocktemplate给矿工提供了巨大搜索空间,但矿工不该对一份请求数据挖矿过久,而应循环适时向节点索要最新区块和最新交易信息,以提升挖矿收益。
**挖矿有两种方式,一种叫SOLO挖矿,另外一种是去矿池挖矿。**前文所述的在节点客户端直接启动CPU挖矿,以及依靠getwork+cgminer驱动显卡直接链接节点客户端挖矿,都是SOLO挖矿,SOLO比如本身独资买彩票,不轻易中奖,中奖则收益所有归本身全部。去矿池挖矿比如合买彩票,你们一块儿出钱,能买一堆彩票,中奖后按出资比率分配收益。
理论上,矿机能够借助getblocktemplate协议连接节点客户端SOLO挖矿,但其实早已没有矿工会那么作,在写这篇文章时,比特币全网算力1600P+,而当前最早进的矿机算力10T左右,如此算来,单台矿机SOLO挖到一个块的几率不到16万分之一,矿工(人)投入真金白银购买矿机、交付电费,不会作风险那么高的投资,显然投入矿池抱团挖矿以下降风险,得到稳定收益更加适合。所以矿池的出现是必然,也不可消除,不管是否破坏系统的去中心化原则。
矿池的核心工做是给矿工分配任务,统计工做量并分发收益。矿池将区块难度分红不少难度更小的任务下发给矿工计算,矿工完成一个任务后将工做量提交给矿池,叫提交一个share。假如全网区块难度要求Hash运算结果的前70个比特位都是0,那么矿池给矿工分配的任务可能只要求前30位是0(根据矿工算力调节),矿工完成指定难度任务后上交share,矿池再检测在知足前30位为0的基础上,看看是否碰巧前70位都是0。
矿池会根据每一个矿工的算力状况分配不一样难度的任务,矿池是如何判断矿工算力大小以分配合适的任务难度呢?调节思路和比特币区块难度同样,矿池须要借助矿工的share率,矿池但愿给每一个矿工分配的任务都足够让矿工运算必定时间,好比说1秒,若是矿工在一秒以内完成了几回任务,说明矿池当前给到的难度低了,须要调高,反之。如此下来,通过一段时间调节,矿池能给矿工分配合理难度,并计算出矿工的算力。
矿池一直都是一个矛盾的存在,毫无疑问,矿池是中心化的,如上图所示,全网算力集中在几个矿池手里,网络虽然几千个节点同时在线,但只有矿池连接的几个点击拥有投票权,其余节点都只能行使监督权。矿池再一次将矿工至于“黑暗”之中,矿工对于区块链再次变得一无所知,他们只知道完成矿池分配的任务。
关于矿池,还有一个小插曲,在矿池刚出现时,反对声特别强烈,不少人悲观的认为矿池最终会致使算力集中,危及系统安全,甚至置比特币于死地。因而有人设计并实现了P2P矿池,力图将“抱团挖矿”去中心化,代码也都是开源的,但因为效率远不如中心化的矿池没能吸引太多算力,所谓理想很丰满,现实很骨感。
推荐几个比较成熟的开源矿池项目,有兴趣的读者可自行研究:
PHP-MPOS,早期很是经典的矿池,很稳定,被使用最多,尤为山寨币矿池,后端使用Stratum Ming协议,源码地址
node-open-mining-portal,支持多币种挖矿,源码地址
Powerpool,支持混合挖矿,源码地址
运行一个矿池须要考虑的问题不少,好比为了获得最及时的全网信息,矿池通常对接几个网络节点,并且最好分布在地球的几大洲。另外提升出块率,下降孤块率,下降空块率等都是矿池的核心技术问题,本文不能一一展开讨论,接下来只详细讨论一个问题,即矿池与矿工的具体配合工做方式——stratum协议。
矿池经过getblocktemplate协议与网络节点交互,以得到区块链的最新信息,经过stratum协议与矿工交互。此外,为了让以前用getwork协议挖矿的软件也能够链接到矿池挖矿,矿池通常也支持getwork协议,经过阶层挖矿代理机制实现(Stratum mining proxy)。须知在矿池刚出现时,显卡挖矿仍是主力,getwork用起来很是方便,另外早期的FPGA矿机有些是用getwork实现的,stratum与矿池采用TCP方式通讯,数据使用JSON封装格式。
先来讲一下getblocktemplate遗留下来的几个问题:
**矿工驱动:**在getblocktemplate协议里,依然是由矿工主动经过HTTP方式调用RPC接口向节点申请挖矿数据,这就意味着,网络最新区块的变更没法及时告知矿工,形成算力损失。
数据负载:如上所述,现在正常的一次getblocktemplate调用节点都会反馈回1.5M左右的数据,其中主要数据是交易列表,矿工与矿池需频繁交互数据,显然不能每次分配工做都要给矿工附带那么多信息。再者巨大的内存需求将大大影响矿机性能,增长成本。
Stratum协议完全解决了以上问题。
Stratum协议采用主动分配任务的方式,也就是说,矿池任什么时候候均可以给矿工指派新任务,对于矿工来讲,若是收到矿池指派的新任务,应当即无条件转向新任务;矿工也能够主动跟矿池申请新任务。
如今最核心的问题是如何让矿工得到更大的搜索空间,若是参照getwork协议,仅仅给矿工能够改变nNonce和nTime字段,则交互的数据量不多,但这点搜索空间确定是不够的。想增长搜索空间,只能在hashMerkleroot下功夫,若是让矿工本身构造coinbase,那么搜索空间的问题将迎刃而解,但代价是必要要把区块包含的全部交易都交给矿工,矿工才能构造交易列表的Merkleroot,这对于矿工来讲压力更大,对于矿池带宽要求也更高。
Stratum协议巧妙解决了这个问题,成功实现既能够给矿工增长足够的搜索空间,又只须要交互不多的数据量,这也是Stratum协议最具创新的地方。
再来回顾一下区块头的6个字段80字节,这个很关键,nVersion,nBits,hashPrevBlock这3个字段是固定的,nNonce,nTime这两个字段是矿工如今就能够改变的。增长搜索空间只能从hashMerkleroot下手,这个绕不过去。Stratum协议让矿工本身构造coinbase交易,coinbase的scriptSig字段有不少字节可让矿工自由填充,而coinbase的改动意味着hashMerkleroot的改变。从coinbase构造hashMerkleroot无需所有交易,如上图所示,假如区块将包含13笔交易,矿池先对这13笔交易进行处理,最后只要把图中的4个黑点(Hash值)交付给矿工,同时将构造coinbase须要的信息交付给矿工,矿工就能够本身构造hashMerkleroot(图中的绿点都是矿工自行计算得到,两两合并Hash时,规定下一个黑点表明的hash值老是放在右边)。按照这种方式,假如区块包含N笔交易,矿池能够浓缩成log2(N)个hash值交付给矿工,这大大下降了矿池和矿工交互的数据量。
Stratum协议严格规定了矿工和矿池交互的接口数据结构和交互逻辑,具体以下:
1. 矿工订阅任务
启动挖矿机器,使用mining.subscribe方法连接矿池
返回数据很重要,矿工需本地记录,在整个挖矿过程当中都用到,其中: b4b6693b72a50c7116db18d6497cac52:给矿工指定初始难度, ae6812eb4cd7735a302a8a9dd95cf71f:订阅号ID 08000002:学名Extranonce1 ,用于构造coinbase交易 4:学名Extranonce2_size ,即Extranonce2的长度,这里指定4个字节Extranonce1,和 Extranonce2对于挖矿很重要,增长的搜索空间就在这里,如今,咱们至少有了8个字节的搜索空间,即nNonce的4个字节,以及 Extranonce2的4个字节。
2. 矿池受权
在矿池注册一个帐号 ,添加矿工,矿池容许每一个帐号任意添加矿工数,并取不一样名字以区分。矿工使用mining.authorize 方法申请受权,只有被矿池受权的矿工才能收到矿池指派任务。
3. 矿池分配任务
以上每一个字段信息都是必不可少,其中: bf:任务号ID,每一次任务都有惟一标识符
前一个区块hash值,hashPrevBlock:
4d16b6f85af6e2198f44ae2a6de67f78487ae5611b77c6c0440b921e00000000:
学名coinb1 ,构造coinbase的第一部分序列数据:
01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff20020862062f503253482f04b8864e5008
学名coinb2 ,构造coinbase的第二部分序列数据:
072f736c7573682f000000000100f2052a010000001976a914d23fcdf86f7e756a64a7a9688ef9903327048ed988ac00000000
学名merkle_branch,交易列表的压缩表示方式,即上图的黑点:
["76cffd68bba7ea661512b68ec6414438191b08aaeaec23608de26ac87820cbd02016","e5a796c0b88fe695949a3e7b0b7b1948a327b2f28c5dbe8f36f0a18f96b2ffef2016"]
00000002:区块版本号,nVersion 1c2ac4af:区块难度nBits 504e86b9:当前时间戳,nTime 有了以上信息,再加上以前拿到的Extranonce1 和Extranonce2_size,就能够挖矿了。
4. 挖矿
构造coinbase交易
用到的信息包括Coinb1, Extranonce1, Extranonce2_size 以及Coinb2,构造很简单:
Coinbase=Coinb1 + Extranonce1 + Extranonce2 + Coinb2
为啥能够这样,由于矿池帮矿工作了不少工做,矿池已经构建了coinbase交易,系列化后在指定位置分割成coinb1和coinb2,coinb1和coinb2包含指定信息,好比coinb1包含区块高度,coinb2包含了矿工的收益地址和收益额等信息,可是这些信息对于矿工来讲可有可无,矿工挖矿的地方只是Extranonce2 的4个字节。另外Extranonce1是矿池写入区块的指定信息,通常来讲,每一个矿池会写入本身矿池的信息,好比矿池名字或者域名,咱们就是根据这个信息统计每一个矿池在全网的算力比重。
构建Merkleroot
利用coinbase和merkle_branch,按照上图方式构造hashMerkleroot字段。
构建区块头
填充余下的5个字段,如今,矿池能够在nNonce和Extranonce2 里搜索进行挖矿,若是嫌搜索空间还不够,只要增长Extranonce2_size为多几个字节就可垂手可得解决。
5. 矿工提交工做量 当矿工找到一个符合难度的shares时,提交给矿池,提交的信息量不多,都是必不可少的字段:
slush.miner1:矿工名字,矿池用以识别谁提交的工做量 bf:任务号ID,矿池在分配任务以前,构造了Coinbase等信息,用这个任务号惟一标识 00000001:
Extranonce2 504e86ed:nTime字段 b2957c02:nNonce字段
矿池拿到以上5个字段后,首先根据任务号ID找出以前分配任务前存储的信息(主要是构建的coinbase交易以及包含的交易列表等),而后重构区块,再验证shares难度,对于符合难度要求的shares,再检测是否符合全网难度。
6. 矿池给矿工调节难度
矿池记录每一个矿工的难度,并根据shares率不断调节以指定合适难度。矿池能够随时经过mining.set_difficulty方法给矿工发消息另其改变难度。
如上,Stratum协议核心理念基本解析清楚,在getblocktemplate协议和Stratum协议的配合下,矿池终于能够大声的对矿工说,让算力来的更猛烈些吧。
在挖矿的发展历史上,还出现了一个天马行空的事情,即混合挖矿(Merge Mining)。域名币(Namecoin)最早使用混合挖矿模式,挂靠在比特币链条上,矿工挖比特币时,能够同时挖域名币,后来狗狗币(Dogecoin)也支持混合挖矿,挂靠在莱特币(Litecoin)链条上。混合挖矿使用Auxiliary Proof-of-Work (AuxPOW)协议实现,虽然混合挖矿不怎么流行,可是协议设计的很精巧,最初看到协议时我不由感叹社区的力量之伟大,这种都能想出来。
以域名币的混合挖矿举例,比特币做为父链(Parent Blockchain),域名币做为辅链(Auxiliary Blockchain),AuxPOW协议的实现无需改动父链(比特币固然不会为了域名币作任何改动),但辅链须要作针对性设计,好比狗狗币改成支持混合挖矿时就进行了硬分叉。
AuxPOW的实现得益于比特币Coinbase的输入字段,中本聪当初不知有意无心,在此处只规定了长度限制,留了一片未定义区域。这片区域后来对比特币的发展产生深远影响,不少升级和优化都盯上这片区域,好比上文讲的Stratum协议。中本聪相似的有意无心状况还有不少,好比交易的nSequence字段,也是由于没有明肯定义,被黑客盯上引起的“延展性”问题成了“门头沟”倒闭的替罪羊。再好比说nNonce,若是一开始定义的字节大一些,你比方说32字节,挖矿的演进就不须要以上讨论的那么多协议。
AuxPOW协议核心理念不一样的地方在于:
对于经典的POW区块,规定只有难度符合要求才算一个合格的区块,AuxPOW协议对区块难度没有要求,但附加两个条件:
辅链区块的hash值必须内置于父链区块的Coinbase里。
该父链区块的难度必须符合辅链的难度要求。
将辅链区块的hash值内置于父链的Coinbase,实际上是利用父链做存在证实。这样就能够实现间接依靠父链的算力来维护辅链安全。通常来讲,父链的算力比辅链大,于是知足父链难度要求的区块必定同时知足辅链难度要求,反之则不成立。这样一来,不少原本在父链达不到难度要求的区块,却达到辅链难度要求,矿工g=广播到辅链网络,在辅链得到收益,何乐而不为。
AuxPOW协议对两条链都有一些数据结构方面的规定,对于父链,要求必须在区块的coinbase的scriptSig字段中插入以下格式的44字节数据:
对于辅链,对原区块结构改动比较大,在nNonce字段和txn_count之间插入了5个字段,这种区块取名AuxPOW区块。
**混合挖矿要求父链和辅链的算法一致,是否支持混合挖矿是矿池的决定,矿工不知道是否在混合挖矿。**矿池若是支持混合挖矿,须要对接全部辅链的节点。
将辅链区块hash值内置在父链的Coinbase,意味着矿工在构造父链Coinbase以前,必先构造辅链的AuxPOW 区块并计算hash值。若是只挖一条辅链,状况较为简单,若是同时挖多条辅链,则先对全部辅链在挖区块构造Merkleroot。矿池能够将特定的44字节信息内置于上文Stratum协议中提到的Coinb1中,交给矿工挖矿。对矿工返回的shares重构父链区块和全部辅链区块,并检测难度,若是符合辅链难度要求,则将整个AuxPOW区块广播到辅链。
辅链节点验证AuxPOW区块逻辑过程以下:
依靠父链区块头(parent_block)和区块Hash值(block_hash,本字段其实不必,由于节点能够自行计算),验证父链区块头是否符合辅链难度要求。
依靠Coinbase交易(coinbase_txn)、其所在的分支(coinbase_branch)以及父链区块头(parent_block),验证Coinbase交易是否真的被包含在父链区块中。
依靠辅链分支(blockchain_branch),以及Coinbase中放Hash值的地方(aux_block_hash),验证辅链区块Hash是否内置于父链区块的Coinbase交易中。
经过以上3点验证,则视为合格的辅链区块。
中本聪最初设计比特币时但愿全部节点都采用CPU挖矿,通常认为只有这样才能充分保证区块链的去中心化特征,比特币在CPU时代安全度过了萌芽阶段。getwork和cgminer将挖矿带入GPU时代,国内显卡曾经一度脱销,全网算力迅速提高了一个档次,CPU挖矿惨遭淘汰。随着愈来愈多人参与挖矿,全网算力不断上升,催生了抱团挖矿(矿池)。然而GPU时代的繁荣历史也没能持续多久就被getblocktemplate,stratum以及矿机带入了ASIC时代。
getwork实现了数据与挖矿分离,getblocktemplate给外部挖矿程序提供了最大自由度,完全解决了外部挖矿程序与节点交互的可扩展性问题(scalability problems),主要用于矿池与网络节点对接。stratum不但解决了搜索空间不足的问题,同时也解决了矿池与矿机交互数据量大的问题。getblocktemplate和stratum这两个协议使大型矿池,大规模矿场,大算力矿机成为可能,今后挖矿产业进入一个全新阶段,此后挖矿的演进主要集中于几个方向:矿池的设计优化与稳定运行,矿场的科学部署,以及矿机工艺升级,提高算力,下降功耗等。
内容来源:区块链兄弟
活动推荐
主题:Blockathon,挑战区块链开发,敢不敢来!(点击了解详情)
5月25-27日,Blockathon2018北京站,招募100名开发者一块儿挑战区块链开发。
开发者免费,报名需审核。识别下图二维码或点击“阅读原文”便可报名参加。
点击“阅读原文”便可报名。