作者:chirpyl

来源:恒生LIGHT云社区

在写Pow算法之前,我们先思考一个问题,怎么解决大规模网络节点下的共识问题?我们知道几个节点之间的共识可以用BFT算法或Raft等解决,但当节点数量达到上万甚至更多,怎么解决这个问题呢?采用BFT等投票的方式肯定是不可行的了,那怎么办呢?比特币节点数量非常庞大,他是怎么解决这个问题的呢?就是Pow共识算法,这里我们就浅谈一下其实现原理。为了更好的说明PoW的原理,我们再把哈希算法及相关概念描述一下:

哈希函数相关概念

  • 哈希函数——是一类数学函数,可以在有限合理的时间内,将任意长度的消息压缩为固定长度的二进制串,其输出值称为哈希值。
  • 碰撞定义——是指两个不同的消息在同一哈希函数作用下,具有相同的哈希值。
  • 哈希函数的安全性——是指在现有的计算资源(包括时间、空间、资金等)下,找到一个碰撞是不可行的。
  • 抗弱碰撞性——对于给定的消息$M_1$,要发现另一个消息$M_2$,满足$H(M_1)=H(M_2)$在计算上是不可行的。
  • 抗强碰撞性——找任意一对不同的消息$M_1$,$M_2$,使$H(M_1)=H(M_2)$在计算上是不可行的。
  • 雪崩效应——当一个输入位发生变化时,输出中的每一位均有50%的概率发生变化。

哈希算法就是以哈希函数为基础构造的,常用于实现数据完整性和实体认证。一个优秀的 hash 算法,将能实现:

  • 正向快速:给定明文和 hash 算法,在有限时间和有限资源内能计算出 hash 值。
  • 逆向困难:给定(若干) hash 值,在有限时间内很难(基本不可能)逆推出明文。
  • 输入敏感:原始输入信息修改一点信息,产生的 hash 值看起来应该都有很大不同。
  • 冲突避免:很难找到两段内容不同的明文,使得它们的 hash 值一致(发生冲突)。

哈希函数的性质

抗碰撞性

哈希函数的抗碰撞性是指寻找两个能够产生碰撞的消息在计算上是不可行的。但找到两个碰撞的消息在计算上不可行,并不意味着不存在两个碰撞的消息。哈希函数是把大空间上的消息压缩到小空间上,碰撞肯定存在。只是计算上是不可行的。例如,如果哈希值的长度固定为256位,显然如果顺序取$ 1,2,\cdots,2^{256}+1这 $$ 2^{256}+1$个输入值,计算它们的哈希值,肯定能够找到两个输入值,使得它们的哈希值相同。

原像不可逆

原像不可逆,指的是知道输入值,很容易通过哈希函数计算出哈希值;但知道哈希值,没有办法计算出原来的输入值。

难题友好性

难题友好性指的是没有便捷的方法去产生一满足特殊要求的哈希值。

一个哈希函数$H$称为难题友好的,如果对于每个$n$位的输出$y$,若$k$是从一个具有较高不可预测性(高小熵)分布中选取的,不可能以小于$ 2^n$的时间找到一个$x$,使$H(k||x)=y$。

为了引申出工作量证明PoW的原理,考虑一个由哈希函数构成的解谜问题:已知哈希函数$H$,一个高小熵分布的值$value$以及目标范围$Y$,寻找$x$,使得$H(value||x) \in Y$。

这个问题等价于需要找到一个输入值,使得输出值落在目标范围$Y$内,而$Y$往往是所有的输出值的一个子集。实际上,如果一个哈希函数$H$的输出位$n$位,那么输出值可以是任何一个$ [0 , 2^n]$ 范围内的值。预定义的目标范围 $ Y$ 的大小决定了这个问题的求解难度。如果$Y$包含所有$n$比特的串,那么问题就简单了,但如果$Y$只包含一个元素,那么这个求解是最难的,相当于给定一个哈希值,找出其中一个原像,原像不可逆的性质说明了这个难度。事实上,由于$value$具有高小熵分布,这确保了除了随机尝试$x$值以完成搜寻那个很大的空间外,没有其他有效的途径了。

哈希函数的难题友好性构成了基于工作量证明的共识算法的基础。通过哈希运算得出的符合特定要求的哈希值,可以作为共识算法中的工作量证明。这里比特币的安全保证依赖于哈希函数的安全性,如果哈希函数被攻破,可以想象Pow共识算法就失效了,不用算力达到$ 51\%$就可以了。

小熵(min-entropy)是信息理论中衡量某个结果的可预测性的一个指标。高小熵值的是变量呈均匀分布(随机分布)。如果我们从对分布的值进行随机抽样,不会经常抽到一个固定的值。例如,如果在一个128位的数中随机选一个固定的数$n$,那么选到该数的几率是$ 1/2^{128}$。

PoW共识算法

理解了难题友好性,就基本理解了PoW的原理。结合比特币去理解PoW。比特币PoW的过程,就是将不同的nonce值作为输入,尝试进行SHA256哈希运算,找出满足给定数量前导0的哈希值的过程。要求的前导0的个数越多,代表难度越大。比特币节点求解工作量证明问题的步骤归纳如下:

1)生成铸币交易,并与其他所有准备打包进区块的交易组成交易列表,通过Merkle树算法生成Merkle根哈希;
2)把Merkle根哈希及其他相关字段组装成区块头,将区块头的80字节数据作为工作量证明的输入;
3)不停地变更区块头中的随机数nonce,并对每次变更后的区块头做双重SHA256运算,将结果值与当前网络的目标难度做比对,如果满足难度条件,则解题成功,工作量证明完成。该矿工获得记账权,生成新区块并广播到全网。

对Pow共识算法与传统共识算法的思考

如果你熟悉Raft共识算法,可以与Pow做一个类比,Pow计算难题竞争记账权的过程可以认为是Raft中leader选举的过程,一切是leader说了算,不同的是Pow中竞争记账权胜出的有可能是恶意节点,即Raft是在节点全部是非拜占庭节点的情况下才是正确的,而Pow允许有拜占庭节点,这部分是靠工作量证明保证正确性的,即正确性的保证是依靠系统诚实节点占大多数的情况下(更准确的说是诚实节点算力占优的情况下),即使恶意节点胜出,它的区块也不能被诚实节点接受,最终诚实节点的链长超过恶意节点的链,恶意节点的链因工作量少而被丢弃。节点计算难题胜出获取记账权后,其他节点经过验证通过后认可该结果,加入到本地链中,达成一致。这一过程有点像Raft中的日志复制过程。

最后,如果你熟悉传统共识算法比如Paxos、Raft等,可以对比思考一下为什么比特币要采用工作量证明的方式达成共识?比特币区块链实质上就是一个状态复制机,不过相对于一般分布式系统几个副本间达成共识,比特币可以认为是数千数万个“副本”达成共识,如果采用节点间协商投票等方式,在节点数量巨大且节点网络一直动态变化的情况下基本是不可行的。而Pow共识算法,共识的过程节点只需自己计算难题就都可以了,不需要与其他节点进行协商交互,因此对节点的数量不敏感,甚至节点数量越多系统越安全,无论是一个节点还是数万个节点,能够达成共识。