一. 背景介绍
1. 区块链为什么要使用共识算法
区块链作为分布式网络,大部分节点都拥有记账的权限,因此需要保护网络的一致性,防止恶意节点对内容的恶意篡改,保证最新的区块信息可以被准确的添加至区块链,共识问题源于拜占庭将军问题。
2. 拜占庭将军问题
拜占庭将军问题的场景为:在一个边境上,有n为将军,将军间需要通过信使传递消息,但是每个将军都可能是一个叛徒,在这种情况下如何保证将军间的信息都可以达成一致?将场景拓展到系统,将失效节点或是恶意节点标记为拜占庭错误节点,当一个系统中即使存在少量拜占庭错误节点,系统也可以正常运行,那么就称该系统是拜占庭容错的。在区块链系统中,不可能所有的节点都是正常节点,因此会在区块链网络中使用拜占庭容错算法(BFT)。
二. 常用算法
1. 实用拜占庭容错算法(PBFT)
主要应用场景:Hyperledger0.6,数字货币
解决思路:用通信次数换取更高的信用,最多允许3f+1节点组成网络(f为拜占庭错误节点的数量)
算法流程:
所有的节点称为复制节点R,复制节点在视图v的轮换下运作
当试图v轮换时,选择一个复制节点作为主节点p,p = v mod |R|
主节点p接受客户端请求,将请求排序后组播给其他复制节点,复制节点接受到消息后检查收到消息的合法性,如果发现异常情况,启动视图更换,重新选择主节点p
进入预准备(pre-prepare)阶段,此阶段保证在进行视图切换后请求的顺序保持不变。例如在v0下的请求序列r1,r2,r3当触发了视图转换后,从v0切换到v1,请求序列依旧保持不变
客户端给主节点p发送的消息可记为<req , o ,t, c>,分别代表请求内容及摘要,操作,时间戳 ,客户端标识
主节点异常:不组播-触发视图轮换,乱编号-后续commit阶段无法确认,修改req-与消息摘要不符,副本节点不接受
主节点正常:组播预准备消息给所有副本节点,内容可表示为<<pre-prepare, v, n, d>, m>分别为<<预准备标记,视图编号,主节点请求编号,消息摘要>,请求消息>,当复制节点检查d,m一致时,v主=v复,且收到消息唯一时,接受预准备消息
如果一切正常,进入准备阶段(prepare),复制节点将预准备消息与准备消息写入日志,组播准备信息<prepare, v, n, d, i>,i为当前副本节点编号
当别的副本节点接受到其他副本节点的prepare消息时,对消息进行检查,检查v,n,d,若无误,则验证通过,组播<commit, v, n, D(m), i>称i节点在n节点处有一个prepare commit,即通过了认证
当客户端收到f+1个节点返回相同的结果时,操作结束
图摘自:https://zhuanlan.zhihu.com/p/217827966 图中3为拜占庭错误节点
2. 工作量证明Pow
主要应用场景:比特币,以太坊等
解决思路:使用一些计算复杂,验证简单的hash去解决问题
算法流程:
矿工开始构造候选区块,构造完成后计算区块头信息的hash,如果小于当前目标值,可在别人广播之前广播区块,争夺记账权,如果不小于,就修改nonce,再试一次
当其他矿工验证了新区块,就接着往下挖
当有两个人都发现了新区块,区块链会产生分叉,但随着矿工继续挖,最后会选择长链作为主链,重新达成共识
Pow机制操作简单,可以解决共识问题,但是维持工作量需要消耗大量资源成本,包括电力,算力等
3. 权益证明Pos
主要应用场景:点点币,黑币
解决思路:引入保证金机制,选具有经济效益(有钱)的节点来生产区块,但是生产之前要存入保证金,创建区块完成后通过固定的coinstake还给你
算法流程:
点点币Pos1.0
引入币龄的概念,也就是这个币在你手中持有了多久,例如你有10个币,拿了10天没花,你就有10*10=100币龄,你如果花掉了,那就没有了
当一个区块被Pos机制创建,它的第二笔交易必须是coinstake交易,这笔交易需要输出给存保证金的人(即创建区块的人)本金和利息,
利息stakeReward = coinage * 33/(365*33+8)*coin_number
想要拿到这个利息,就需要存入一定的保证金,同时coinstake的第一个输入需要输入一个proofhash,使得proofhash<CoinDayWeight * Target
其中CoinDayWeight = coin_number * days , 30<=days<=90
proofhash = hash(nStakeModifier + txPrev.block.nTime + txPrev.offset + txPrev.nTime + nTime)
创建区块n的难度Target(n) = Target(n-1) * (1007 * 10 * 60 + 2 * block_interval) / (1009 * 10 * 60)其中block_interval为区块n和n-1的时间间隔
在10分钟以内难度增加,在10分钟后难度减小
在Pos1.0中,判断主链的标准为区块所有交易的币龄总和,总和高的将被认证为主链
Pos1.0存在的问题是:可以攒着钱不动来积攒币龄,然后狠狠地赚利息,由于选取主链是按照币龄花费算的,也有可能造成双花问题
Pos2.0
调整proofhash < coin_number * Target,取消了用币龄作为proofhash的空间
同时调整了nStakeModifier权重修正因子会经常改变,防止提前进行计算
Pos机制的安全问题:
N@S无利害攻击:
因为在Pos网络中,新的区块只能由特定节点产生,若当区块产生分叉,这个权益人(区块产生者)可能为了利益最大化,在每条链上都创建区块以保证至少能拿到利益。还有就是由于产生价值是通过 利息激励机制,可能会导致中心化出现(有钱的越来越有钱),因此,很多网络采用Pow+Pos的机制(Pow不存在上述两个问题)
其余的常用算法,例如委任权益DPos,瑞波共识RPCA,授权拜占庭dBFT等,等待补档。。。