十方创智(深圳)网络科技有限公司张翼梁华洪孝林
摘要:大家听到“挖矿”这个词应该是从第一批比特币淘金者那里听到的。比特币区块链是货币型的公链,挖取的是“数字黄金”。随着共识面得扩大,最初的矿工赚了大钱,后来的人们就像马蜂一样进入到这里面来。这种比特币挖矿潮很像当年的淘金热,当时的淘金热很多淘金者下海淘金,最终只有很少的人变得富有,很多人却失去了一切。中本聪设计的比特币网络初衷是去中心化和普适性,但是随着机器算力越来越集中,比特币挖矿呈现出再中心性化的趋势,出现“富者越富,贫者恒贫”的状况,大量的普通用户已经很难参与进来,这与现实社会里贵金属开采有着惊人的相识,其他类似的货币型公链也存在这种现象。区块链是人类社会用代码传递信任的重大变革,区块链3.0时代一定是应用的时代,大力发展应用型公链是必然趋势,应用型公链挖矿必须回归到普适性时代,让更多用户参与进来。本文用技术去解释”挖矿到底是一件什么样的事情”
挖矿到底是一件什么样的事情
如果你想成为比特币的矿工,你首先要加入到比特币的网络当中与其他矿工进行连接。在连接完成之后我们还有一些任务要完成:
1.监听交易广播: 在整个比特币网络中每个时间段都有一些交易的广播,然后需要验证矿工们的签名是正当有效的,交易没有被重复支付。
2.维护区块链的网络并且负责监听新的区块: 矿工的首要职责就是维护区块链,为了保证这一点,中本聪设计的非常完善,矿工在一开始就需要要求其他的矿工和节点把当时你还没有加入区块链之前的历史记录同步到本地。然后监听那些被广播到网络上的新区块,你的工作就是验证每个广播后你所收到的每一个区块,验证的目的是为了保证区块里的每笔交易都是有效的。而且每一个区块都包含了一个有效随机数【1】。
3.生成备选区块:如果你备份完毕了所有的区块数据,你就可以生成你自己的区块了。但是你想要做到这一点你就要把所监听到的数据进行打包并且放到新的区块当中,然后把这个区块排在整条链的最新区块的后面。但是你必须要保证里面的数据是真实有效的。
4.找到让你的区块变得有效的随机数。这个工作量是巨大的,也是最难的一部分,这里取决于你的机器算力与全网算力的比例值。随着全网算力的大幅提高,许多矿机被升级成算力更高的专业矿机,并且为了提高比例值,专业矿机并联形成大规模专业矿场。
5.让全网接受你的区块:即使你找到了一个随机数,也不能保证该区块会成为共识链的一部分。其实这是有一部分运气成分在里面的。接受你的区块并且从该区块继续传承下去,而不是从其他矿工那里获得的区块开始传承。
6.利润:如果其他的矿工都接受了你的区块,那你就可以获得相对应的比特币了【2】。在这里补充一点,除了新区块产生的奖励以外,还有一种费用是额外收入的。但是比较低,那就是交易手续费,这里大约是一个区块默认奖励的1%。
7寻找有效区块:
现在我来解释如何找到使区块变得有效的随机数。身为一名矿工,首先需要从你的交易池中选出一些有效的交易并且编译成梅克尔树。你可以任意选择编译的交易数量但是前提是不超过每个区块的随机数的交易上限。然后组装出一个新的区块【3】。你需要尝试不同的临时随机数直到该随机数能使整个区块的哈希值小于目标值。这个目标值一般用零开始的特定位数的数值来体现。也就是从0开始,每次增加数值1,直到该随机数能使区块有效为止。
在很多情况下,随机数试过所有的32位以后取的数值仍然不能产生一个有效的哈希值,这个时候就要做出更多的改变。但是当在整个梅克尔树上的数值发生变化的时候整个都会发生变化,最重要的是在梅克尔树上不会改变coinbase,因为coinbase会向上传递所以改变这个值会计算更多,所以只改变头部的随机数是一个很好的选择。在尝试2^32次以后还没有找到有效区块才会改变coinbase。当你找到这个数值以后就需要立刻宣布,你就有机会获得区块奖励。
8决定难度:
当矿工挖出每2016个区块,挖矿难度就会改变一次。这个难度的改变是根据前2016个区块的挖矿效率来决定的。我们的公式如下进行表示:
下一个区块的难度=上一个难度*2016*10min/产生上2016个区块所花费的时间
注:2016*10min=两周,这里的两周是没有意义的,只是权衡之下的产物而已。
中本聪为了要平衡这种动态值,因为他要把比特币作为数字黄金的存在。所以他决定把难度让市场决定。挖矿难度会受到有多少新的矿工加入而产生影响,因为新加入的矿工是因为受到了比特币价格的波动而加入的。
挖矿之所以那么难的核心问题是因为矿工要对SHA-256哈希函数进行运算,SHA-256是一个通用的密码学哈希函数,也是一个256位的状态机。这256个状态被分割成8个32位字段,这样可以很优化的运行在32位的硬件上。每一轮运算选择一定数量的字段,最终进行32位模加法运算,然后运算结果被一道状态最左的第一个字段,这样使得整个状态进行向右位置。一个完整的SHA-256运算要做64次这样的迭代运算,在每一轮运算中,会志勇稍微不同的常数,所以所有的迭代运算都不一样。矿工就是尽可能快的进行这种函数运算,矿工就是比运算速度。
CPU挖矿
在当初的时候,大家挖取比特币都是使用家庭普通电脑进行挖矿的,也就是CPU挖矿。按照现在比特币网络的情况还想指望CPU来进行挖比特币是根本不可能了,在过去几年里面还执着于用CPU挖类似比特币(货币型公链)之类的的矿工是根本不知道比特币的运作原理。应用型公链要回归到普适性时代,CPU挖矿是重要的第一步,CPU挖矿能让普通PC用户更加方便地参与进来。
GPU挖矿
第二代矿工用GPU挖矿的原因是因为GPU有高吞吐量和高并行处理功能,这两点是对于挖矿非常有利的条件。在2010年的时候OPENCL语言诞生了,这个语言可以让GPU进行非图像处理工作,这个语言让GPU挖矿成为了当时的主流。GPU可以进行超频,举个例子,如果超频让你的吞吐量变成1.5倍,运算成功率降为0.7,但是乘机为1.05.也就意味着你获得了5%的增幅。最后一条就是一个CPU可以带多个GPU,让每个GPU区分别负责不同的事情,大大缩短时间。
GPU挖矿也是优缺点的。GPU有大量的浮点运算单元,但是这些内置硬件并不完全被用在挖矿这件事情上,对于SHA-256的运算没有起到任何帮助性作用。同时,GPU没有很强大的散热功能,而且很耗电。随后出了几个月的FPGA挖矿,但是由于要一支超频使用就变得经常报错,导致人们不得已放弃这种挖矿方式。
GPU同时也是大型3D游戏、美工等家用及工作软件所必需硬件,应用型公链的普适性不排除GPU算力,但是应限制GPU的无限拓展。
ASIC挖矿
当今的挖矿市场主要被ASIC芯片所主导。这些芯片被设计出来就是为了货币型公链挖矿而存在的。制作这种芯片是需要非常专业的知识,开发周期也非常的长。但是最为奇妙的是,在这个行业里面芯片的开发速度居然打破了芯片行业的世界纪录。由于当时开发速度过快导致设计缺陷过多,造成了很多人的抱怨。
绝大部分早期的ASIC芯片寿命十分短暂,6个月就被淘汰了,这就导致了厂商的出货速度决定了用户的回报率,不然用户买回家的就是一对废铜烂铁。由于现在比特币的网络已经稳定下来了,所以现在的矿机还是有比较高的稳定性,但是在早期,矿机客户控诉厂商的事情还是发生的很普遍的。
反ASIC
大致上说,我们想抑制为了挖矿而特别定制的设备的优势。这也可以理解为,设计一个解谜程序,让现有的普通电脑成为最廉价和最有效率的解谜运算设备。但这在现实中不可能,毕竟所有的通用电脑的中央处理器里已经针对一些特殊目的进行了优化。并不是所有的电脑都有相同的优化配置,并且它们随着时代而变化。比如,过去的10年中,英特尔(Intel)和AMD在芯片里加入特殊指令(通常叫作“增加硬件支持”)来更加有效地计算高级加密标准(Advanced Encryption Standard,简称AES)的区块密码。所以有些电脑在挖矿这个事情上总是会比其他电脑更加低效。另外,很难想象设计一个挖矿解密程序,而这些程序是依赖普通个人电脑诸如音响或显示器这些特性的,所以去除了那些通用特性的具体特殊目的的设备,很可能会更有效率,并且成本更低。
更加实际地说,我们有一个适中的目标:设计一个解谜程序,尽可能地减少最有效率的定制运算设备与通用电脑之间的效率差距。ASIC还是会不可避免地成为更加有效的矿机,但是我们可以将其运算效能限制在一定范围内,让他的投入和损耗得不到合适的回报,从而限制ASIC矿机的发展,让普通用户使用他们已有的通用电脑来挖矿仍具备一定的经济效应。
1、刚性内存解谜
大多数被设计成反ASIC的解谜程序中,最普遍被应用的叫作刚性内存解谜(memory-hard puzzles)-----解谜需要大量的内存来计算,而不是靠大量的CPU时间。一个类似但又不一样的概念是内存限制解谜(memory-bound puzzles),花在读取内存上的时间,占据了这种程序大部分的计算时间。一个解谜可以是刚性内存类而不是内存限制类,或是内存限制类而不是刚性内存类,或是二者兼而有之。一个微妙但重要的区别在于,虽然CPU的速度是计算时间的瓶颈,但平行运算大量解谜的成本,还是被内存的成本所左右,或者反之亦然。通常对于运算类的解谜程序,我们要做到刚性内存和内存限制,就需要保证在运算过程中大量的内存被要求使用,使之成为一个限制性因素。
为什么刚性内存解谜或内存限制解谜可以反ASIC?因为用来计算哈希函数的逻辑运算只占了CPU里的一小部分,意思是在比特币的解谜计算里,ASIC不需要执行一些不必要的功能,而只需要执行计算哈希函数的相关功能,所以占了很大优势。另外一个相关因素是,不同的内存性能上的差异(和单位性能的成本)比不同处理器之间运算速度上的差异要小很多,所以,如果我们设计了一个刚性内存类的解谜,计算时需要相对简单的算力但需要大量的内存,这就意味着,解密成本的上升速率将会像内存成本提升速率那样,在一个相对低一些的水平。
SHA-256已经被认定为不是刚性内存解谜算法。它只需要一个小小的256位模块,可以很容易地被放进CPU的注册机里。但设计一个刚性内存类的工作量证明解谜不是一件太难的事。
2、Scrypt
现在最受欢迎的刚性内存解谜叫作Scrypt,被第二大加密数字货币莱特币以及其他加密数字货币所用。
Scrypt是一个刚性内存的哈希函数,最早是为了加密密码而不容易被暴力破解(比如,反复试错破解),所以挖矿解谜与比特币用的“不完全哈希函数原像解谜”是一样的,只不过用Scrypt取代了SHA-256。
Scrypt在比特币被发明出来之前就已经存在,而且它是用来加密个人密码,这一点让我们对它的安全性有一定信心。密码的哈希函数化其实与反ASIC有着相似的目的。出于安全性考虑,我们期待,一个有着定制化设备的攻击者不能够比使用一般电脑或者服务器的用户更快地计算密码的函数值【4】。
Scrypt基本上有两个步骤:第一个步骤是在用随机数据填充随机存取存储器(Random Acess Memory,简称RAM)里面的缓存空间;第二个步骤是从这块内存区域里虚拟随机地读取(或者更新)数据,同时要求整个缓存都存储在RAM里面【5】。
在时间和内存之间的权衡。如果没有一个较大的内存缓存,计算Scrypt会变得很慢,但是用较少的内存来增加相对较少的计算还是有可能的。假设我们使用一个大小约N/2的缓存(而不是N的大小),现在,我们只在j是偶数的情况储存V【j】的值,丢掉那些j是奇数的值。而在第二次循环里,一半的情况下j为奇数的值将会被选到,但这种情况还是很容易被计算的。我们只需要简单地计算SHA-256(V【j-1】),因为V【j-1】在我们的缓存里。在一半的时间内会产生这种情况,所以它增加了N/2个额外的SHA-256计算。
因此,对内存要求量的减半只会增加1/4的SHA-256计算量(从2N到5N/2)。总体来说,我们可储存缓存区域V里的每个k排数据,即使用N/k的内存和计算(k+3)N/2次的SHA-256迭代计算。在这个限制下,如果我们设定k=N,我们就回到先前运算时间为O(N的平方)的计算。这些数字不一定非常准确地适用于Scrypt算法本身,但是渐进预测的方式确实是适用的。
除此之外,还有其他的设计可以弱化用时间来换取内存地能力。举例来说,如果一个缓存持续地在第二次循环中被更新,它可以让时间与内存之间的互换不是那么有效,因为这些更新必须被储存在内存中。
Scrypt的检验成本
Scrypt的另一个局限性是,它需要用与计算所用的同样大小的内存来做校验。为了让内存刚性有意义,N需要变得比较大。这意味着一个Scrypt的计算要比一个SHA-256的迭代计算(在比特币里只需要一个SHA-256计算就可以校验)昂贵许多倍。
这会产生负面的结果,因为在网络里的每个用户必须重复这个计算来检查每一个新发现的区块是否有效。这会减缓新区块传播和被认可的速度,从而增加了分叉攻击的风险。它还要求每个客户端(即使是轻量级的SPV客户端)拥有足够的内存来有效地进行函数计算。这样一来,实际上在加密数字货币中能够被Scrypt用到的内存N是有限的。
一直到最近我们都不明确,是否有可能设计一个挖矿解谜程序在计算上是刚性内存类的,又可以很快地(不需要大量内存)进行校验。这个特性对密码进行哈希运算没有多大作用,在用于加密数字货币之前,这是Scrypt算法的主要用途。
在2014年,一个叫作杜鹃鸟周期的新解谜算法被约翰·特龙普(John Tromp)所提出(起这个名字是因为这个算法的特性与杜鹃鸟的特性类似,杜占雀巢)。杜鹃鸟周期算法,是从杜鹃鸟哈希表所衍生的一张图中寻找周期的难度而设定的,杜鹃鸟哈希表这种数据结构在2001年才被首次提出。除了建立起一个很大的哈希表之外,没有其他已知的方法来计算这个周期,结果却可以通过发现一个周期(相对小的)来简单地验证。
这个算法可能会让刚性内存或是内存限制类的证明工作在比特币共识里变得更加实用。可惜的是,这个函数无法再数学上证明,如果它不用内存的话就不能被有效地计算。通常,一个新的密码学算法看起来都是安全的,但是社区会对它持有保留意见,直到它存在了多年而没有被破解过。因为这个缘故,并且因为它也是最近才被发明的,当前杜鹃鸟周期算法还没有被任何加密数字货币所采用。
实际应用中的Scrypt
Scrypt被许多种加密数字货币所使用,包括莱特币在内的几种热门币,结果好坏参半【6】。针对莱特币Scrypt算法参数的ASIC已经存在(然后被其他几种另类币所复制)。令人惊讶的是,相较于大众电脑,这些ASIC在算力上的提高比起SHA-256相对普通电脑的提高,至少旗鼓相当甚至要更大!所以,Scrypt最终还是无法反ASIC,至少在莱特币上是如此。莱特币的设计者期初宣称反ASIC是莱特币的一大优势。但现在他们已经收回了这个说法。
这可能是莱特币所用的数值N(内存使用参数)比较低所造成的,它只要求128KB就可以进行计算(如果使用时间内存互换的模式,可能所需要的内存更低,这也被普遍用于GPU以获得更快地缓存)。低数值N使设计一个不需要复杂的内存存储总线的轻量级挖矿ASIC变得很容易,通常这种复杂的总线是读取十亿字节(Gigabytes)级别的随机存取存储起所需要的,而这些通用电脑都具备。莱特币的开发者没有选择一个比较高的内存参数(这会是ASIC更加难以设计),因为他们认为高内存参数所导致的高成本的校验过程是不太现实的。
3其他抵抗ASIC的方法
请回忆一下,我们的初衷是想让可以大幅度提升计算性能的ASIC的开发变得困难。刚性内存解谜只是其中一个方法,还有其他办法。
另外被提出但还没有被实施的一个办法是使用一个移动的目标值来作为挖矿解谜。也就是说,解谜算法本身就会变化,就像比特币里的难度会周期性地改变一样。在理想的状态下,为上一个解谜算法而被优化过的挖矿硬件,对下一个解谜算法不再适用。我们不是很清楚要多久改变一次解谜算法,才能达到我们需要的安全要求。如果这是由另类币的开发者所决定的,这可能就变成了一种不可接受的中心化来源。比如,开发者可以根据他们已经开发出来的一种硬件(或者只是优化过的FPGA),去设计一个相对应新的解谜算法,他们自然就有了针对这个新算法的早期优势。
或许这些解密算法的顺序能够被自动生成,但这看上去也很难。一个想法是选择一大堆哈希函数(比如24个没有被攻破的基于SHA-3的算法),然后每个用上6个月到一年,在这么短的周期里很难开发新的硬件。当然如果这个顺序安排被事先知道,相应的硬件设计就可以按照函数使用的时间表来进行。【7】
PC矿机从CPU挖矿过渡到CPU+GPU挖矿,同时限制GPU并行拓展及反ASIC芯片,在PC忙时和闲时用人工智能动态调节硬件及带宽资源,将让应用型公链的普适性大大提高,进入千家万户。
关键词:挖矿;应用型公链;ASIC;挖矿历程;反ASIC;挖矿原理;Scrypt算法
参考文献:
【1】
篇名:《区块链技术与应用前瞻综述》
作者:何蒲于戈张岩峰鲍玉斌
页码:P1—P7,15
页数:8页
期刊名称:《计算机科学》
【2】来源(学术期刊):
篇名:《比特币基因不会消亡》
作者:何佳艳
页码:P30—P32
页数:3页
【3】来源(学术期刊):
篇名:《区块链技术原理、应用及建议》
作者:张偲
参考文献:8篇
页码:P51—P54
页数:4页
期刊名称:《软件》
【4】来源(学术期刊)
篇名:《基于核函数的有监督哈希视频图像检索》
作者:唐珂方雪峰
页码:P49—P51
页数:3页
期刊名称:《江苏科技信息》
【5】来源(学位论文):
篇名:《基于AT89C51单片机开发的一款能实现MP3播放的Flash芯片测试开发板》
作者:雷镇海
学科专业:软件工程
【6】来源(学术期刊):
篇名:《莱特币与Scrypt算法》
作者:何洪亮
参考文献:1篇
页数:1页
期刊名称:《经贸实践》
【7】来源(学位论文):
篇名:《基于中间相遇的哈希函数原像攻击》
作者:钟锦敏
学科专业:计算机系统结构
备注:本文已被国家级期刊(国际刊ISSN:1673-5811,国内刊号CN:11-544/N)《中国科技投资杂志》收录,已于2018年11月(33期)出版。