要想整个 P2P 网络维持一份相同的数据,保证每个参与者的公平性,整个体系的所有参与者必须要有统一的协议(共识算法)。
这些协议规则可以划分为两个大的核心:
- 工作量证明
- 最长链机制
共识算法的目的就是保证比特币不停地在最长链条上运转,从而保证整个记账系统的一致性和可靠性。
1. 工作量证明
工作量证明(POW)可简单地理解为一份证明,用来确认你做过一定量的工作。
监测工作的整个过程是极为低效的,而对工作的结果进行认证来证明完成了相应的工作量,是一种非常高效的方式。
比如现实生活中的毕业证、驾驶证等,是通过检验结果的方式(通过相关的考试)取得证明。
1.1 起源
工作量证明系统,是一种应对服务攻击和其他服务滥用的经济对策。它要求发起者进行一定量的运算,消耗计算机一定的时间。
哈希现金是一种工作量证明机制,
Hashcash 在防治垃圾邮件中的应用:在电子邮件的消息头中,增加一个 Hashcash 戳记(Hashcash Stamp)散列值。该散列中包含收件人地址,发送时间,salt,该散列值特别之处在于它至少前20位必须是0才是一个合法的Hashcash 戳记。为了得到合法的散列值,发送者必须经过许多次尝试(改变 salt 值)才能获得。一旦生成戳记,不希望每一个给我发送邮件的垃圾邮件制造者都能重复使用它。所以,Hashcash 戳记要带一个日期。这样可以指定时间更早的戳记是非法的。另外 Hashcash 的接收端要实现一个 Double-spending 数据库,用来记录戳记的历史信息。
1.2 工作量证明的基本原理
工作量证明指客户端需要做一定难度的工作得出一个结果,验证方很容易通过验证结果来检查客户端是不是做了相应的工作。
这种方案的一个核心特征是不对称性:工作对于请求方是适中的,对于验证方则是易于验证的。
它与验证码的不同:验证码的设计出发点是易于被人类解决而不易被计算机解决。
例子:给定一个基本的字符串“Hello, world! ”。工作量要求是:可以在这个字符串后面添加一个叫作 nonce(随机数)的整数值,对添加 nonce 后的字符串进行 SHA-256 哈希运算,如果得到的哈希结果(以十六进制的形式表示)以 0000 开头的,则验证通过。为了达到这个工作量证明的目标。计算机需要不停地递增 nonce 值,对得到的新字符串进行 SHA-256 哈希运算。按照这个规则,需要经过 4251 次计算,才能找到恰好前 4 位为 0 的哈希散列。为了增加复杂性:验证方可以要求请求方对多个字符串进行 SHA-256 运算。
比特币里的工作量证明机制类似,但是更复杂。
1.3 比特币中的工作量证明
一个节点若生成一个新的区块并写入区块链,须解出比特币网络给出的工作量证明迷题。
这道题的3个关键要素是工作量证明函数,区块,难度值。
- 工作量证明函数是这道题的计算方法
- 区块决定了这道题的输入数据
- 难度值决定了解这道题所需要的计算量。
工作量证明函数是 SHA-256。区块是在工作量证明环节产生的。矿工不停地构造区块数据,检验每次计算出的结果是否满足工作量,从而判断该区块是否符合网络难度。区块头即为比特币的工作量证明的输入数据。
难度值是矿工们挖矿的重要参考指标,它决定了矿工大约需要经过多少次哈希运算才能产生一个合法的区块。
比特币的区块大约每 10 分钟生成一个,为了使新区块的产生都基本保持这个速率,难度值必须根据全网算力的变化进行调整。
每隔 2016 个区块,所有节点都会按统一的公式自动调整难度值。
公式:新难度值 = 旧难度值*(过去2016个区块花费时长 / 20160 分钟)
这个公式是由产生最新 2016 个区块的花费时长与期望时长(期望时长为 20160 分钟,即两周,是按每 10 分钟一个区块的产生速率计算出的总时长)比较得出的,根据实际时长与期望时长的比值,进行相应调整。
工作量证明需要有一个目标值。比特币工作量证明的目标值(Target)的计算公式如下:
目标值= 最大目标值/难度值
最大目标值为一个恒定值:0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
比特币工作量证明的达成就是矿工计算出来的区块哈希值小于目标值。
比特币工作量证明的过程简单理解成,通过不停地变换区块头(即尝试不同的nonce 值)并将其作为输入,进行 SHA-256 哈希运算,找出一个有特定格式的哈希值的过程(即要求有一定数量的前导 0 )。而要求的前导0的个数越多,难度越大。
可以把比特币矿工解这道工作量证明迷题的步骤大致归纳如下:
- 生成 coinbase 交易,并与其他所有准备打包进区块的交易组成交易列表,通过 Merkle Tree 算法生成 Merkle Root Hash。
- 把 Merkle Root Hash 及其他相关字段组装成区块头,将区块头的 80 字节数据作为工作量证明的输入。
- 不停地变更区块头中的随机数(即 nonce 的数值),并对每次变更后的区块头做双重 SHA-256 运算(即 SHA256(SHA 256(Block_Header))),将结果值哈希反转并与当前网络的目标值对应的十进制字符串做对比,如果小于目标值,则解题成功,工作量证明完成。
![img](file:///storage/emulated/0/Note/images/1526699332810.png)