中国领先的IT技术网站
|
|

1.4.3 比特币的发行:挖矿

《白话区块链》第1章初识区块链,本章我们将从区块链的原理及分类、技术组成、技术特点等出发来初步介绍区块链的概念,并通过分析比特币的结构让大家对区块链有一个感性的认识。比特币作为区块链技术的第一个应用,它的原理设计影响深远。本节为大家介绍比特币的发行:挖矿。

作者:蒋勇/文延/嘉文来源:机械工业出版社|2017-11-24 11:44

开发者大赛路演 | 12月16日,技术创新,北京不见不散


1.4.3 比特币的发行:挖矿

很多朋友在第一次看到“挖矿”这个词时都很疑惑,包括本人。比特币不是一个软件吗?通过软件来挖矿是什么意思?从字面上来看,应当是通过投入某种工作,然后能得到一个“宝贝”,也就是矿。当然了,“挖矿”自然不是我们通常认为的那个挖矿,它只是一套算法,在介绍算法过程前,我们先来了解下挖矿在比特币软件中主要都有哪些用途:

抢夺区块打包权

验证交易事务

奖励发行新币

广播新区块

我们知道,比特币是一个对等网络,每个节点都可以独立维护自己的数据副本,那么问题就来了,怎么来保证彼此之间的数据一致呢?既然没有一个中心服务器,自然也就没有一个传统意义上的权威数据来源了。这就得有一个约定的规则,大家共同按照这个规则来进行竞争,谁竞争成功了谁就有数据的打包权,也就是记账权,打包完成后广播给别人,别人只要验证一下有无问题即可,没有问题就存入到自己的数据文件中。这个思路不错,等于就是大家来竞争临时中心服务器的资格,那么比特币中实行了一种什么样的规则呢?那就是被称为工作量证明(Proof of Work,PoW)的一种算法,其实就是类似于掷骰子的一种游戏。比如大家约定掷出一个10位长度的数字,前面6位要都是0,后面的4位数得小于某个值,看谁先掷出符合要求的数字出来,谁就抢得了打包权(记账权)。我们来看下比特币中具体是怎么来掷这个骰子的。

1.难度值

首先,既然是大家都在竞争掷骰子,那掷出来的数字必然是要符合一个难度的,这个难度就是一个门槛,在比特币软件中,规定一个256位的整数:

  1. x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 

作为难度1的目标值。在比特币诞生初期,当时的全网算力,大约需要10分钟左右的运算能得到一个符合这个难度1要求的值,这也是我们常常说比特币网络每隔大约10分钟出一个区块的来源。我们在查询创世区块(也就是0号区块)的信息时,可以看到当时的难度就是1。那么,所谓符合这个难度为1的要求的值是什么意思呢?就是说通过工作量证明算法,也就是比特币中的挖矿算法来计算出一个结果,这个结果要小于这个难度目标值,我们来看下0号区块的难度信息:

  1. "nonce": 2083236893,  
  2. "bits": "1d00ffff",  
  3. "difficulty": 1, 

这些信息可以通过比特币支持的JSON-RPC中的getblock命令方法获得,其中的difficulty就是指难度级别。0号区块的难度值是1,nonce是一个随机数,是挖矿计算得到的一个数字,这个等会儿再介绍,bits是用来存储难度的十六进制目标值的,这个难度目标值是存储在区块的头部的,在源码中被定义为一个4字节长度的字段,4字节也就是32位,要用来存储256位长度的难度目标值,因此这256位长度的值需要经过压缩处理后才能放到这个字段中。以这个难度1的目标值来说,我们查询区块信息后,看到的值是1d00ffff,那么,这个值是怎么压缩而来的呢?规则其实很简单,我们一共有4个字节来存储,这4个字节的最高位字节用来存储难度值的有效字节数。什么叫有效字节数?就是从第一个不全为0的字节开始的部分,比如难度1的值有效位是0x00FFFF……。等等,怎么前面有2个0呢?这是因为在压缩规则中,规定了如果难度值有效位的最高位为1(大于0x80),则需要在前面补上一个0x00,这里的最高位是F,也就是二进制的1111,因此是符合这个规则的。难度1的目标值中,有4个字节长度的0,减掉这些0的长度共32bit,剩余256-32=224,也就是28个字节,加上补的0x00,因此,有效位总计29个字节,29的十六进制是1D,另外3个字节中存储的是目标值有效位的最高3个字节,此时的目标值有效位前面已经加上了2个0,因此最高3个字节为0x00FFFF,合起来压缩后的值就是0x1D00FFFF。对于这样的一个压缩后的十六进制4字节难度目标值,前2位通常称为幂或者指数,后面6位称为系数。

那么,有朋友问了,压缩是可以,那还原出来呢?我们看个公式:目标值= 系数*

2^(8*(指数-3))次方。

我们就以这个0x1D00FFFF为例来说明,系数是后面6位也就是00FFFF,指数是前面2位也就是1D,代入进去就是:0x00FFFF*2^(8*(0x1D-3)),计算后得到的值是:

  1. 0x00000000FFFF0000000000000000000000000000000000000000000000000000 

有朋友可能疑惑了,不对吧,这个跟规定的那个难度1的值不一样了啊,精度少了很多,确实是的,存储在bits中的值是一个精度截断的近似值。

我们以200 000号区块为例,查询一下难度值,得到如下:

  1. "nonce": 4158183488,  
  2. "bits": "1a05db8b",  
  3. "difficulty": 2864140.507810974, 

我们来看看这个difficulty的值是怎么来的,0号区块的难度是1,对应的目标值是0x1D00FFFF,200 000号区块的难度目标值是0x1A05DB8B,将两者的目标值按照上述公式进行转换后相除便能得到这个2864140.507810974的难度值,我们发现,200 000号区块的difficulty比0号区块的大许多,而bits的大小却比0号区块的小许多。这其实是表明了一个特点,随着全网算力越来越强,difficulty难度值就会越来越大,而bits表示的目标值会越来越小,这两者成反比,目标值越小就越难挖矿。

刚才也提到了,难度值并不是一成不变的,比特币差不多每两周会调整一下新的难度值,因为计算的算力是会变化的,为了维持差不多10分钟出一个区块的节奏,难度要跟随算力变化而调整,不得不说比特币的设计还是相当完整的。

新难度值的计算公式是这样的:新难度值= 当前难度值×(最近的2016个区块的实际出块时间 / 20 160 分钟)。2016个区块的意思是:假设按照理论的10分钟出一个块,2周也就是14天的时间,应该出2016个区块,可以看到实际上就是计算一下实际与理论上的时间差值,弥补上这个差值即可。

2.挖矿计算

我们了解了难度值的概念,现在来看看挖矿计算具体是怎样一个过程。首先,我们说了挖矿是要抢夺区块打包权,那就得收集需要打包进区块的那些交易事务,那这些数据从哪来呢?这里有个概念需要大家注意,打包就像是记账,是把发生的交易事务记录下来存档,但是无论什么时候打包、谁打包,在网络中发生的交易是持续不断的,就像企业仓库的进销存业务,无论记账员是一个月还是半个月记一次账,业务是持续进行的。在比特币系统中,每个人都会将通过钱包进行的转账交易数据广播到网络中,这些都是属于等待打包的未确认交易数据。这些数据都会放在一个内存池中,总之就是一个缓冲区,当然,这些数据都会被接受基本的验证,用以判断是否是不合法的或者是不符合格式的交易数据。

挖矿程序从内存池中获取用来打包区块的交易数据,接下来就要干活啦,我们来看一下挖矿的计算公式:

  1. SHA256(  
  2.         SHA256(version + prev_hash + merkle_root + ntime + nbits + nonce )  
  3.     ) < TARGET 

SHA256是一种哈希算法,可以通过对一段数据进行计算后输出一个长度为256位的摘要信息。SHA256在比特币中使用很广泛,不但用于挖矿计算,也用于计算区块的哈希值和交易事务的哈希值,比特币对SHA256算法是情有独钟啊,我们看到在这个公式中,是对参数进行两次SHA256计算,如果计算出来的值小于那个TARGET(也就是难度目标值),那就算是挖矿成功了。那么,这些参数都是由哪些组成的呢?请看下表:

这些数据字段其实也是区块头的组成部分,将这些参数连接起来,参与SHA256的挖矿计算。在这些参数中,版本号是固定的值,前一个区块的哈希值也是固定的值,当前难度也是一个固定的值,那么要想改变这个公式的计算结果,能改动的参数就只有梅克尔根、区块时间戳和那个随机数了。

1)梅克尔根是通过交易事务计算出来的,挖矿程序从内存池中获取待打包的交易事务,然后计算出梅克尔根,获取交易事务本身也是有一些优先级规则的,比如根据手续费大小之类,这些细节就不赘述了。

2)区块时间戳是指UNIX时间戳,用于记录区块的产生时间,我们知道比特币系统是分布式的网络,没有固定的时间服务器,因此每个节点获得的时间戳都可能是不一样的,由此,比特币系统中设置了规则:①新产生区块的时间戳要大于之前11个区块的平均时间戳;②不超过当前网络时间2个小时。所以,后一个区块的时间戳比前一个区块的时间戳反而小也是可能的。

3)随机数是一个可自由取值的数值,取值范围是0~2的32次方。

我们可以看到,要通过这样的参数来计算出符合条件的值,基本上也就只能靠暴力计算匹配了,这种不断执行SHA256计算的过程很消耗算力,因此这个过程被形象地称为“挖矿”。简单地说,挖矿就是重复计算区块头的哈希值,不断修改该参数,直到与难度目标值匹配的一个过程。

一旦匹配成功,就可以广播一个新的区块,其他客户端会验证接收到的新区块是否合法,如果验证通过,就会写入到自己的区块链账本数据中。那么,挖矿的奖励在哪儿呢,不是说矿工成功出一个区块就能得到比特币作为奖励的吗?那么这里奖励在哪呢?这个奖励其实是作为一条交易事务包含在区块的交易事务中的,相当于系统给矿工转账了一笔比特币,这种交易事务由于特殊性,通常称为coinbase交易,这个交易一般是位于区块中的第一条,比特币系统也正是通过这种挖矿奖励的方式发行新的比特币,就像央行发行新钞一样。

这个奖励不是无限的,从2009年1月创建出第一个区块,每个区块奖励50个比特币,然后每21万个区块(大约4年)产量减半,到2012年11月减半为每个区块奖励25个比特币,然后在2016年7月减半为每个新区块奖励12.5个比特币。基于这个公式,比特币挖矿奖励逐步减少,直到2140年,所有的比特币(20 999 999.98)将全部发行完毕,到那个时候挖矿就只能收入一些交易手续费了。彼时,比特币网络是否还能保持运行,我们目前也只能持保留意见了。矿工在没有明显的激励情况下,是否还愿意通过挖矿承担区块打包的责任,现在也很难说。

比特币中的挖矿计算基本就是这个过程了,其实还是很简单的,本质上就是利用了SHA256计算,有朋友可能有疑问,那第一个区块也就是创世区块是怎么挖出来的?很简单,创世区块是硬编码直接写进去的,在比特币的源码中,通过CreateGenesisBlock这个方法写入,并且还留下了一句话:The Times 03/Jan/2009 Chancellor on brink of second bailout for banks。当时正是英国的财政大臣达林被迫考虑第二次出手缓解银行危机的时刻,这句话是泰晤士报当天的头版文章标题。

3.区块广播

矿工挖出区块后,就进行网络广播,传递给相邻的节点,节点接收到新的区块后会进行一系列的验证,比如区块数据格式是否正确;区块头的哈希值小于目标难度;区块时间戳是否在允许范围之内;区块中第一个交易(且只有第一个)是coinbase交易;区块中的交易事务是否有效等,总之就是一连串的检测,全部校验通过就把新的区块数据纳入到自己的区块链账本中。如果是挖矿节点接收到信息,就会立即停止当前的挖矿计算,转而进行下一区块的竞争。

比特币的挖矿过程说到这里,不知道有没有朋友会有个疑惑,那就是挖矿算法虽然能够提供工作量证明,表明矿工确实是投入了相当的算力的,但是却不能保证只能是一个矿工能挖到啊,如果在同一时间内多个矿工都计算出了符合条件的值,都拥有了打包权,那以谁的为准呢?比特币中的解决方案,竟然是那么简单,人家没用什么复杂的算法,就是让节点自己选择,最终传播最广、处于最长链中的区块将被保留,因此到底谁的区块会被保留下来,可能还真得看看运气了。

这里实际上隐含着FLP原理,先看下定义:在网络可靠,存在节点失效(即使只有一个)的最小化异步模型系统中,不存在一个可以解决一致性问题的确定性算法。这个其实也很好理解,来看个例子:三个人在不同房间投票,虽然三个人彼此之间是可以通电话沟通的,但是经常会有人时不时地睡着。比如,A投票0,B投票1,C收到了然后睡着了(类比节点失效了),则A和B永远无法在有限时间内和C共同获得最终的结果。看到这里,我们也就明白了挖矿的作用了,除了发行新的比特币外,主要就是维持网络共识,让每个节点对区块链的数据保持最终一致性。

4.挖矿方式

比特币的挖矿过程我们已经了解了,现在给大家介绍下挖矿方式。挖矿算法在执行过程中,为了抢夺区块打包权,就得拼命去算出那个符合难度目标的值,大家都在不断升级自己的算力,难度也就越来越大,挖矿程序本身不复杂,关键是这个过程非常依赖计算机的算力资源,可以说得算力者得天下,也因为这个原因,挖矿的方式在多年来不断进化,一切都围绕着为了得到更高的算力来进化。

我们先从硬件类型来说,早期的时候,还没多少人挖矿,难度值也还不大,使用普通的个人电脑就能进行挖矿了,这个时期的硬件设施主要是普通CPU挖矿。随着有更多的矿工加入,难度越来越大,使用普通CPU的算力,效率开始不够用,于是出现了GPU挖矿,利用显卡来进行挖矿计算,GPU对于SHA256的计算性能更高。曾经一段时间,市面上的显卡销量猛增,就是被买去搭建显卡挖矿的,2017年上半年,另外一种数字加密货币以太坊价格暴涨,也一度引发了市面上的“一卡难求”,显卡尤其是高端显卡的GPU计算在一些挖矿算法上的性能表现确实相当不错,然而,对于算力的追求是无止境的,接着又出现了配置FPGA(Field-Programmable Gate Array,现场可编程门阵列)和ASIC(Application Specific Integrated Circuit,特定应用集成电路)的挖矿装备。这两类是属于集成电路的装备了,尤其是ASIC,基本是目前顶级性能的矿机了,专门为了挖矿而设计,只为挖矿而生!

说完了挖矿的装备,我们再来说说挖矿节点的类型,最简单的挖矿节点类型就是solo挖矿,也就是个体矿工,自己搞个挖矿装备然后默默开挖,守株待兔般等待着挖矿成功。如今,在挖矿难度大幅度提升的时代,个人挖矿几乎是一点机会都没有,那么现在流行的挖矿节点是什么类型?那就是矿池,矿池通过挖矿协议协调众多的矿工,相当于大家联合起来,每个人都贡献自己的算力,形成一个整体,大大增强整个挖矿节点网络的算力,个人矿工也可以加入到矿池,他们的挖矿设备在挖矿时保持和矿池服务器的连接,和其他矿工共同分享挖矿任务,之后分享奖励。


喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢
24H热文
一周话题
本月最赞

读 书 +更多

数据库加密——最后的防线

本书是关于如何使用已有的密码技术和算法对数据库中存储的信息进行保护的书,书中所关注的内容主要是如何设计、建立(或者挑选、集成)一套...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊
× 51CTO学院双十二活动