在公有链中用的最多的是pow算法和pos算法,这些算法都是参与者的利益直接相关,通过利益来制约节点诚实的工作,解决分布式系统中的拜占庭问题。拜占庭容错算法是一种状态机副本复制算法,通过节点间的多轮消息传递,网络内的所有诚实节点就可以达成一致的共识。使用拜占庭容错算法不需要发行加密货币,但是只能用于私有链或者联盟链,需要对节点的加入进行权限控制;不能用于公有链,因为公有链中所有节点都可以随意加入退出,无法抵挡女巫攻击(sybil attack)。下面主要介绍Fabric的PBFT算法。

系统模型

该系统要达成的目的是:让所有正常的replicas节点执行相同的序列操作。

1、系统假设是异步分布式的,通过网络传播的消息可能丢失、延迟、重复或乱序,节点可能失效但节点失效是相互独立的。传递的消息都是通过签名的,恶意节点可以控制失效节点,但是不能够篡改正常节点的签名信息。

2、安全性:在R>=3f+1的前提下,系统能保持安全性和活性。R为总结点数,f为错误节点数。

3、角色分工:

replica(副本)所有参与的节点,总数为R

primary(主节点):负责将来自client的请求排好序,然后发给所有的备份节点。

backup(备份节点):接收并检查主节点的排序信息,如果主节点作恶可以进行换选。

其中主节点的选举方法是:p = v mod R ,其中v是系统的view编号,每次换选时发生view change,view编号+1。

4、quorums

quorums有两个重要的属性:

  • Intersection: 任意两个quorums至少有一个共同的并且正确的replica
  • Availability: 总是存在一个没有faulty replicas的quorum

如果一个replica把信息写给一个quorum,并让该quorum来存储信息,在收到每一个quorum中的成员的确认反馈后,那么我们可以认为该replica的信息已经被可靠的保存在了这个分布式系统中。这是强的约束,当然还有一个weak certificates:就是至少f+1个节点来共同存取信息,这样至少有一个正确的replica存到了这份信息。

算法流程

PBFT算法通过三阶段广播协议来使所有正常节点按相同的顺序执行请求,三阶段分别为pre-prepare、prepare和commit。执行流程如图所示。

prepare阶段和commit阶段用来确保那些已经达到commit状态的请求即使在发生view change后在新的view里依然保持原有的序列不变,比如一开始在view 0中,共有req 0, req 1, req2三个请求依次进入了commit阶段,假设没有坏节点,那么这四个replicas即将要依次执行者三条请求并返回给Client。但这时主节点问题导致view change的发生,view 0 变成 view 1,在新的view里,原本的req 0, req1, req2三条请求的序列被保留,作数。那些处于pre-prepare和prepare阶段的请求在view change发生后,在新的view里都将被遗弃,不作数。

假设replica 0为主节点,下面详细介绍三阶段:

pre-prepare阶段

主节点收到client发送的一条请求,给这条请求编号为n,然后想所有的备份节点发送pre-prepare消息,消息的格式为<<pre-prepare, v, n, d>, m>,其中v是视图view编号,m是请求的消息,d是请求消息的摘要。当满足一下条件时,备份节点会接受这条pre-prepare消息,进入prepare阶段。

1、请求和预准备消息的签名正确,并且d与m的摘要一致。
2、当前视图编号是v。
3、该备份节点从未在视图v中接受过序号为n但是摘要d不同的消息m。

4、预准备消息的序号n必须在水线(watermark)上下限h和H之间。

prepare阶段

备份节点i进入prepare阶段后,发送一条prepare消息给所有的副本节点,消息格式为<prepare, v, n, d, i>,同时接收其他节点发送的prepare消息。

所有副本节点在收到准备消息之后,对消息的签名是否正确,视图编号是否一致,以及消息序号是否满足水线限制这三个条件进行验证,如果都正确则接受。(这个阶段是防止主节点作恶)如果从2f个不同的副本收到的prepare消息与pre-prepare消息一致,即连同自己一共2f+1个确认,那么这个节点就处于prepared状态,同时拥有一个prepared certificate证书。然后进入commit阶段。

预准备阶段和准备阶段确保所有正常节点对同一个视图中的请求序号达成一致。

commit阶段

进入commit阶段的节点i会广播一条commit消息给其他所有节点,消息格式为<commit, v, n, D(m), i>,同时接收其他节点发送的commit消息,每个副本接受确认消息的条件是:
1)签名正确;
2)消息的视图编号与节点的当前视图编号一致;

3)消息的序号n满足水线条件,在h和H之间。

如果满足以上条件,则接受消息。如果从不同的节点收到2f+1(包括自己)条commit消息且都正确,那么这个节点进入committed状态,并拥有一个committd certificate。然后向客户端返回请求。

其中watermark的作用是:

我们想象一种情况,主节点是坏的,它在给请求编号时故意选择了一个很大的编号,以至于超出了序号的范围,所以我们需要设置一个低水位(low water mark)h和高水位(high water mark)H,让主节点分配的编号在h和H之间,不能肆意分配。

三阶段到此结束,客户端等待f+1个相同的副本结果作为最后结果。

垃圾回收

节点在一次三阶段协议中收到的pre-prepre,prepare,commit等消息是非常多的,这小消息都要记录在本地的日志中,为了节省存储空间,可以把已经确认无误的消息给清除掉。只有当至少f+1个节点执行了请求的消息的时候,才能将相应的日志删除。

于是,当一个节点执行完某条请求后,可以广播一条消息,当全网有2f+1个节点都执行完这条请求后就可以删除它的日志了。但是每条消息都进行广播来确认是否删除是低效的,所以可以k条消息放一起确认,每当k条请求执行完后,就广播一条消息,当2f+1个节点都执行完这个请求后,就可以将这k条请求的日志删除了。这就是建立检查点checkpoint,当节点i执行完k条请求后,就生成一个checkpoint,并广播checkpoint消息:<CHECKPOINT, n, d, i>,n是最近一个影响状态的请求序号,d是状态的摘要。当有2f+1个检查点消息时,就证明这个检查点是正确的,形成一个stable checkpoint。具有这个stable checkpoint的节点就可以将所有序号小于等于n的pre-prepare,prepare,commit消息,以及之前的检查点和检查点消息删除。

但是由于节点的执行速度不同,要使不同的节点的检查点维持在一个范围内,最快的几点与最慢的节点之间最多差L个检查点。这里又用到了水线watermark,用检查点协议来更新水线的高低值(h和H),这两个高低值限定了可以被接受的消息。水线的低值h与最近稳定检查点的序列号相同,而水线的高值H=h+L,L需要足够大才能使副本不至于为了等待稳定检查点而停顿。

视图变更

(以下内容直接从这篇文章中摘取过来,原文讲的很明白,若不同意马上删除)

当主节点挂掉后就触发了view change协议。我们需要确保在新的view中如何来延续上一个view最终的状态,比如给这时来的新请求的编号,还有如何处理上一个view还没来得及完全处理好的请求。

Data Structures

所以我们需要记录上一个view里发生什么。 
有两个集合P和Q,replica i 的P存着 i 在上一 view 中达到prepared状态的请求的一些信息,有了P,在新的view中,replica i就会明白接下来处于prepared状态的请求不能与上一个view中处于prepared状态的请求的编号相同。Q是记录在上一个view里到达pre-prepared状态的请求的一些信息。

View-Change Messages

我们来看一下Fig 2, 当备份节点 i 怀疑 view v中的主节点出问题(比如是坏节点)后,它会进入 view v+1,并广播一条VIEW-CHANGE信息给所有的replicas,其中包含该replica i最新的stable checkpoint的编号,还有 replica i上存的每一个checkpoint的编号和digest的集合,还有上面所说的该replica的P和Q两个集合。

View-Change-Ack Messages

replicas 会收集VIEW-CHANGE信息并发送ACK确认给 view v+1 中的主节点 
。新的主节点收集了VIEW-CHANGE和VIEW-CHANGE-ACK(包含自己的信息),它会将VIEW-CHANGE存在一个集合S中。主节点需要选出一个checkpoint作为新view处理请求的起始状态。它会从checkpoint的集合中选出编号最大(假设编号为h)的checkpoint。接下来,主节点会从h开始依次选取h到h+L(L就是normal case阶段我们提到的设置值)之间的编号n对应的请求在新的view中进行pre-prepare,如果一条请求在上一个view中到达了committed状态,主节点就选取这个请求开始在新的view中进行三阶段。之所以选取committed的请求,是因为上面我们提到增加COMMIT阶段为了across view来考虑的,处于committed状态的请求的编号在新的view中是有效的,可以继续使用。但是如果选取的请求在上一view中并没有被一个quorum给prepare,那它的编号n有可能是不被一个quorum给同意的,我们选择在新的view中作废这样的请求。

参考文章:

https://blog.csdn.net/bluecloudmatrix/article/details/51898105?utm_source=tuicool&utm_medium=referral#commentBox

https://www.jianshu.com/p/fb5edf031afd

区块链之PBFT算法相关推荐

  1. 区块链共识算法:Paxos、Raft以及实用拜占庭容错机制PBFT

    详情参见个人博客: http://brainware360.cn/%E5%8C%BA%E5%9D%97%E9%93%BE%E5%85%B1%E8%AF%86%E7%AE%97%E6%B3%95%EF% ...

  2. 拜占庭将军问题与区块链共识算法PBFT

    概述 1.两军问题 两军问题中信道是不可靠的,并且其中没有叛徒之说. 解决方式:Tcp的三次握手可以提供相对可靠地信道通信. 2.拜占庭将军问题 概述 拜占庭将军问题中并不去考虑通信兵是否会被截获或无 ...

  3. 区块链之智能合约详解

    链客,专为开发者而生,有问必答! 此文章来自区块链技术社区,未经允许拒绝转载. 什么是智能合约? 智能合约又称智能合同,是由事件驱动的.具有状态的.获得多方承认的.运行在区块链之上的.且能够根据预设条 ...

  4. BC之CM:区块链之共识机制——深入浅出以及国内外当下主流区块链平台共识机制纵向、横向比较相关配图

    BC之CM:区块链之共识机制--深入浅出以及国内外当下主流区块链平台共识机制纵向.横向比较相关配图 目录 区块链共识机制的深入浅出 国内外当下主流区块链平台共识机制纵向.横向比较 区块链共识机制的深入 ...

  5. Fabric学习笔记-PBFT算法

    本文介绍了实用拜占庭容错算法(PBFT). Fabric在v0.6中采用的是PBFT算法,在v1.0.0-preview中是SBFT算法,在v1.0.0-release中文档上说PBFT还在开发中,项 ...

  6. BlockChain:区块链入门课程 -- 区块链之类型 、应用程序、技术挑战和潜力

    BlockChain:区块链 类型 .应用程序.面临挑战和潜力 区块链的类型 不同类型的区块链协议概述.我们将深入探讨共识方法,了解公共区块,财团区块和私有区块链之间的差异; 他们的用途和价值主张. ...

  7. 【区块链之菜鸟入门】区块链发展史:从拜占庭将军问题到智慧契约

    在"[区块链之菜鸟入门]亲,你淘的区块链到了!"这篇文章中,我们了解到了区块链技术的出现其实是为了去除银行类等中心机构的信用背书.从原本信任足够信用度的单独个体(中心)到信任一堆个 ...

  8. 【区块链之技术进阶】Attention please!区块链技术的风险!

    不知不觉咱们在[区块链之技术进阶]部分已经分享了七篇文章了,通过之前的七篇文章大家对于区块链技术的理解是不是上升了一个高度呢?这七篇文章,告诉我们区块链是互联网时代的通往第二纪元--信任纪元的革命,这 ...

  9. 深入理解区块链共识算法

    区块链的概念: 区块链是一种去中心化.不可篡改.可追溯的分布式数据库系统[3].区块链系统中底层网络采用对等式网络(P2P 网络)组织各个独立的网络节点.P2P网络是扁平式的拓扑结构, 网络中的每个节 ...

最新文章

  1. 凑微分公式_武忠祥真题班归纳(更新至多元函数微分学)
  2. 关于Thinkphp3.2版本的分页问题
  3. 第九篇:Spring Boot整合Spring Data JPA_入门试炼03
  4. 信号量sem 的用法
  5. cstringw转lpctstr_CString 和 LPCTSTR 之间的转换 及 LPSTR、LPWSTR、LPCSTR、LPCWSTR、LPTSTR、LPCTSTR的区分与转化...
  6. 用于语音识别的数据增强
  7. 20165223 week2测试补交与总结
  8. Django 路由系统
  9. 获取字符串中的汉字拼音首字母
  10. 深度学习算法:AlphaGo 算法
  11. C#实现Word批量转换Pdf
  12. hdu 5510 Bazinga (尺取法)
  13. VC++课程设计常见问题解答
  14. 离散数学与组合数学-03函数
  15. centos安装mysql_centos如何安装mysql
  16. 股票入门:什么是股票指数,什么是大盘指数
  17. NGUI中UITable下文本内容过多无法自适应
  18. 【解决方案】智慧工地AI视频远程集中监控解决方案是如何通过EasyCVR视频平台实现的?
  19. PyQt5学习(17):实现与matplotlib的结合,以及类似的pyqtgraph
  20. 英文简历如何美言自己的性格

热门文章

  1. python定义定长数组_python 初始化一个定长的数组实例
  2. Keepalived常用配置及脚本
  3. 中国石油大学(北京)-《 完井工程》第一阶段在线作业
  4. 基于百度智能云的人脸识别系统
  5. 北航计算机科学与技术专业考研方向,北京航空航天大学2017年计算机科学与技术专业介绍_北航考研网...
  6. Android-Apk的安装流程分析(二)
  7. AirDisk产品怎么恢复出厂设置?
  8. 网页中打开qq聊天框
  9. Pomelo 使用教程
  10. 【OpenCV】OpenCV基础教程(9)—— 傅里叶变换