PBFT共識簡述

pbft協議

pbft算法是區塊鏈公鏈項目中的一種共識機制。特點是不僅容錯故障節點,同時容忍惡意節點的存在。
作惡節點不僅是,宕機引起的無法發送數據。甚至可能發送相反的回覆或者僞造數據。

算法概要

PBFT

  • 客戶端發送請求到primary節點,primary由公式p = V mod R決定,p是節點的編號,V是視圖號,R是整個系統中節點的個數。請求的消息格式爲<REQUEST,o,t,c>,其中o是請求的操作,t是客戶端的本地時間,c是客戶端;
  • Primary廣播請求消息到每一個backup節點;
  • 所有節點(primary和backups)執行請求,把結果返回到客戶端,返回的消息格式爲<REPLY,v,t,c,i,r>,v是節點維持的當前的視圖號,t是與請求消息中一樣的時間,i是節點的編號,r是執行請求的結果;
  • 如果客戶端收到f+1個來自不同節點且t相同、r也相同的應答,則接受此應答。如果客戶端一直沒有收到應答,則客戶端向每一個節點都發送此請求消息,如果此請求已經被執行,則直接把結果返回給客戶端(每個節點保存上一個發送給客戶端的應答);如果此請求還沒執行,那麼非primary節點把此請求轉發給primary。如果primary一直不廣播請求,backups收不到請求,則懷疑primary節點出錯,導致view change(詳見第四部分)。

角色

pbft共識機制中,集羣節點分爲 主節點(primary)和副本節點(replica).
主節點負責產塊等行爲,副本節點負責轉發消息和投票。
主節點和副本節點之間可以相互轉化,轉化的具體方式需要引入視圖(view)概念,後面詳解。

容忍惡意節點

在pbft共識機制中,允許的作惡節點個數爲(n-1)/3個(向下取整)。
即需要2/3個節點是善良節點

2/3善良節點比例的出處

說法1

https://learnblockchain.cn/2019/08/29/pbft/
設集羣中有n個節點,有惡意節點f個。那麼收到的數據中,有n-f個正常,但n-f個數據中,可能有f個是有惡意節點僞造的數據。
所有最終判別爲善良誠實的數據共有n-f-f個
而共識成功的標準是 n-f-f > f
明顯 f < n/3
故而有容忍1/3惡意節點

說法2

https://bitcoin.stackexchange.com/questions/58907/byzantine-fault-tolerant-consensus-why-33-threshold

設集羣中有n個節點,其中有誠實節點h個,惡意節點d個。設要求的pbft信任閾值(善良節點個數最小值)是t
有
h >= t >=  (h/2) + d
(3/2)h >= d
d < h/2
故而容忍1/3惡意節點

但仍然不理解這裏的(h/2) + d 個惡意節點是怎麼來的。
按照出處1中的說法應該是 t >= 2d

說法3

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

最壞的情況是:f個節點是有問題的,由於到達順序的問題,有可能f個有問題的節點比正常的f個節點先返回消息,又要保證收到的正常的節點比有問題的節點多,所以需要滿足N-f-f>f => N>3f,所以至少3f+1個節點

2/3善良節點的出處總結

正確的表述應該是這樣的。
有N個節點,f個故障節點(不知道是宕機還是惡意)
此時主節點需要收到N-f個msg才能完成共識
最壞的情況
這f個故障節點全是惡意節點。所以N不僅要剪掉故障的f個msg,還要減去其實是惡意節點僞造的f個msg。
故有N-f-f>f => N>3f

這裏還要考慮時間,最壞的情況就是f個惡意節點發出的msg比正常msg先到。
即 這一輪中 主節點收到的msg總數是N個,但主節點只處理前N-f個msg

View change

View-Change
View change確保即使當前的primary節點出錯,整個系統也能繼續運行。View change防止backup節點無限地等待請求的執行。
當一個backup節點收到一個請求(此請求由於客戶端一直沒有收到應答而把請求廣播到所有節點)時,啓動一個timer;如果此節點不需要等待請求,則timer停止;如果此節點需要執行其他請求,則timer重啓。如果timer超時(超市時間根據實際情況指定),則觸發view change。view change過程如下:

1.當一個backup節點(i)的timer超時,i停止接收消息(但仍然接收checkpoint、view change和new view(定義見下文)消息),並廣播一個view change消息,消息格式爲<VIEW-CHANGE,v+1,n,s,C,P,i>,n是節點i中上一個stable checkpoint(s) 對應的序號,C是s的證據,P是i中每一個序號大於n的請求對應的prepared的證據。

2.由於視圖號變爲v+1,所以產生了一個新的primary節點(原因是p=V mod R)。如果新的primary節點收到視圖號爲v+1的2f+1個來自不同節點(可能包含自己)的<VIEW-CHANGE,v+1,n,s,C,P,i>消息,我們把這個2f+1個消息作爲new view的證據。

3.如果primary得到new view的證據,那麼它廣播一個new view消息到其他節點。消息格式爲<NEW-VIEW,v+1,V,O,N>,V是new view的證據,O與N是某些pre-prepare消息的集合,O與N的計算過程如下:

(1)primary指定h的值爲V中上一個stable checkpoint對應的序號,指定H的值爲V中的prepared證據中的最大的序號;

(2)primary對每一個序號爲n(h<n<=H)的請求創建一個新的且視圖號爲v+1的pre-prepare消息。此時有兩種情況:(一)在V中,存在序號爲n的prepared的證據;(二)不存在這樣的prepared證據。對於(一),primary創建一個<PRE-PREPARE,v+1,n,m>消息,並把此消息記入O,m是(一)中序號爲n的請求;對於(二),primary創建一個<PRE-PREPARE,v+1,n,null>消息,null是“null”請求(此請求不做任何操作)的digest,並把此消息記入N。

Primary把O與N記入log。如果h大於上一個stable checkpoint的序號,那麼primary把序號爲h的checkpoint的證據記入log,並刪除第三章第3節中描述的log。如果h大於primary當前的state,那麼primary更新當前的state爲h。
此時,primary節點進入view爲v+1階段,並可以接收視圖號爲v+1的消息。

4.一個backup節點若能接收一個<NEW-VIEW,v+1,V,O,N>消息,需滿足以下兩個條件:

(1)此節點已經含有視圖號爲v+1的new-view的證據;
(2)此節點驗證O與N是正確的,驗證方法與primary創建O與N的方法一樣。

之後,此節點把O與N記入log。並且對O與N中的每一個消息都創建一個對應的prepare消息,並廣播這些prepare消息到每一個節點,並把這些消息記入log,進入v+1階段。
每一個節點對序號爲n,n在h與H之間的每個消息重做上述協議。

發佈了7 篇原創文章 · 獲贊 3 · 訪問量 599
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章