1999年Miguel Castro等学者提出了PBFT(Practical Byzantine Fault Tolerance)算法,该算法的主要过程如图2-3所示。
图2-3 PBFT过程
算法中将节点划分为两类:主节点和其他节点。每一次请求要经历五个步骤:发起(Request)、预准备(Pre-prepare)、准备(Prepare)、确认(Commit)和响应(Reply)。对这些步骤简述如下。
首先,从全网节点选举出一个主节点(Leader),新区块由主节点负责生成。主节点的选择方法是类轮询的方式。假设Node0是主节点,当客户端向它发起请求后,就从发起阶段进入了预准备阶段。
在预准备阶段,主节点把该请求广播到所有节点。为了确保请求的时间顺序不错乱,主节点会给当前的请求分配一个编号 p 。所有节点收到这个请求信息后,都会各自对该消息进行校验,当确认时序正确、校验信息无误后,该节点会进入下一阶段。
在准备阶段,每个节点将收到的请求信息存入消息队列,在请求信息中嵌入其自身编号 i ,并继续向所有其他节点广播处理后的请求信息(即Prepare消息),完成后进入下一阶段。
在确认阶段,如果某个节点收到了来自其他2 f 个节点( f 代表PBFT最大容错节点数量,算法中假设 f 不大于总节点数的1/3)的Prepare消息,并确认这些消息和自己之前收到的一致,就可以执行Commit操作,即向所有其他节点发送一条Commit确认消息,这条消息中包含消息编号 n 和节点编号 i 。
最后是响应阶段。在该阶段中,如果一个节点收到来自2 f +1个不同节点的Commit消息,则确认成功,并向最初发起请求的客户端发送响应信息。请求的发起者会等待,直到收到 f +1个响应,才接受这个结论。至此,整个算法流程结束。
简而言之,PBFT算法通过两种手段实现拜占庭容错:以类似轮询的方式选择主节点;每一次请求都要在主节点和其他节点之间互相验证,只有足够多的节点确认后才达成共识。PBFT比经典拜占庭协议的复杂度低,应用性更强。