工作量证明:
上一文中我们介绍了区块链基础模型的实现,但是一个最大的问题就是我们向其中添加区块的操作是非常容易的。实际应用中,向区块链中添加区块需要完成一个非常复杂的数学计算,区块的添加需要经过所有包含区块数据的节点的验证通过,其数学求解的过程也称为挖矿,其数学解称之为工作量证明。所有参与求解的人称之为矿工,第一个得到正解的矿工挖矿成功,获得挖矿奖励。正是由于挖矿需要非常大的算力,才保证区块链的安全性和一致性。
做为奖励,区块链机制给予第一个得到解的人记账的权利(即向区块链添加新的区块的权利),该区块的第一笔交易记录给予矿工的奖励,由系统发放(区块中交易记录了用户之间的数字货币或资产的转移,来源指向一个用户地址。唯独第一笔交易来源为空,即由系统发放)。在一个矿工完成挖矿后,其他参与者会对该用户的求解进行验证,只有通过验证的区块才会被其他矿工计入区块链。
区块链的计算求解到解的验证过程称之为工作量证明。这一过程是需要耗费极大计算机算力,即使性能很好的计算机也不能很快得到结果。此外,挖矿难度随着整体算力实时进行改变已保证每个小时产出区块大概6个。对于比特币来讲,挖矿的目的实际是通过不断改变参数,进行哈希计算,为区块找出找出符合一定条件的哈希值。在比特币中,这个哈希就是工作量的证明。它表明矿工进行了大量的计算。那么什么是哈希呢?
哈希:
哈希是为特定数据求解哈希值的过程,不同的数据经过哈希后具有自己独一无二的值。哈希具有以下特征:
1.原始数据不能通过哈希值反推,因此哈希不是加密。
2.特定数据具有唯一的哈希,该哈希对于这些数据是独一无二的。
3.即使数据由一点的改变,其哈希也会完全不同。
i love goland > 2c9ea2ac5ce8ed7f7afb42255d1578b6c4e661177580203e15350ed2803e17af
i love goland. > e92dd79674e6fd93c84f80967b7281c25b05487b2919b1fe733b051394c88f4f
哈希被广泛用来验证数据的一致性。在区块链中,哈希是为了保证区块数据的一致性。由于一个区块中用于哈希计算的数据包含了上一个区块的哈希值,因此对区块链进行修改是非常困难的。要想更改一个区块的数据,必须同时修改其后的所有区块数据,这需要进行大量的工作量。
hashcash:
hashcash是一种哈希算法的系统,该技术最先用来进行邮件过滤。该算法主要分为以下几个步骤:
1.取出一些公开的数据data。
2.在这些数据上添加技术count,从0开始。
3.计算data+count的哈希。
4.验证哈希值是否满足一定条件:
1.满足,
2.不满足,count+1,重复3-4.
这一过程是很粗暴的,你必须不断增加count直到找到满足条件的值。这也是为什么挖矿如此耗费计算机算力。
比特币中该条件为哈希值的前20位必须为0,同时该条件实时变化以保证出块速度保持稳定。不管矿工人数增加或计算机算力增加,比特币每2016个区块后调整一次计算难度。
代码实现:
首先我们定义挖矿难度:
const targetBits = 24 //目标在内存比256bit少24bit
在比特币中,挖矿难度保存在区块头中,实时变化。我们先假定区块难度不变。
在NewProofOfWork中我们使用bigint,因为我们将区块hash转为bigint与target进行比较,hash条件为hash值小于target。我们定义的target16进制表示为:
0x10000000000000000000000000000000000000000000000000000000000
target可以认为是hash的上边界值,任何小于target的hash计算都是有效的。若我们减小上边界,即增大计算难度。
为了计算hash,我们必须首先准备数据:
这里我们简单的将这些数据组合在一起进行哈希计算。工作量证明的计算过程:
在上图中,hashInt是哈希的int表示,hash是循环计算的哈希值,nonce为count,不断增加直到找到符合条件的哈希。在循环中我们分为几步:
1.准备数据
2.计算哈希
3.与目标值进行比较:
1.满足条件,跳出循环
2.不满足条件,nonce增加,继续循环
现在我们将nonce加入区块头,删除上一文中的SetHash函数,并修改NewBlock函数。
我们将nonce作为区块的一个基本参数,以用来对区块进行验证。
为了计算速度,我将targetBits设置为12,可以看到新的区块哈希都满足前3位为0。
总结:
现在我们离真实的区块链模型更加接近,添加区块需要进行大量计算。但是要实现真实的区块链,我们还需要增加一些主要功能:区块持久化、钱包、转账、地址、共识机制等。继续努力。