『壹』 什麼是神經網路共識演算法
BP(Back Propagation)網路是1986年由Rumelhart和McCelland為首的科學家小組提出,是一種按誤差逆傳播演算法訓練的多層前饋網路,是目前應用最廣泛的神經網路模型之一。BP網路能學習和存貯大量的輸入-輸出模式映射關系,而無需事前揭示描述這種映射關系的數學方程。它的學習規則是使用最速下降法,通過反向傳播來不斷調整網路的權值和閾值,使網路的誤差平方和最小。BP神經網路模型拓撲結構包括輸入層(input)、隱層(hide layer)和輸出層(output layer)。
『貳』 深入了解區塊鏈的共識機制及演算法原理
所謂「共識機制」,是通過特殊節點的投票,在很短的時間內完成對交易的驗證和確認;對一筆交易,如果利益不相乾的若干個節點能夠達成共識,我們就可以認為全網對此也能夠達成共識。再通俗一點來講,如果中國一名微博大V、美國一名虛擬幣玩家、一名非洲留學生和一名歐洲旅行者互不相識,但他們都一致認為你是個好人,那麼基本上就可以斷定你這人還不壞。
要想整個區塊鏈網路節點維持一份相同的數據,同時保證每個參與者的公平性,整個體系的所有參與者必須要有統一的協議,也就是我們這里要將的共識演算法。比特幣所有的節點都遵循統一的協議規范。協議規范(共識演算法)由相關的共識規則組成,這些規則可以分為兩個大的核心:工作量證明與最長鏈機制。所有規則(共識)的最終體現就是比特幣的最長鏈。共識演算法的目的就是保證比特幣不停地在最長鏈條上運轉,從而保證整個記賬系統的一致性和可靠性。
區塊鏈中的用戶進行交易時不需要考慮對方的信用、不需要信任對方,也無需一個可信的中介機構或中央機構,只需要依據區塊鏈協議即可實現交易。這種不需要可信第三方中介就可以順利交易的前提是區塊鏈的共識機制,即在互不了解、信任的市場環境中,參與交易的各節點出於對自身利益考慮,沒有任何違規作弊的動機、行為,因此各節點會主動自覺遵守預先設定的規則,來判斷每一筆交易的真實性和可靠性,並將檢驗通過的記錄寫入到區塊鏈中。各節點的利益各不相同,邏輯上將它們沒有合謀欺騙作弊的動機產生,而當網路中有的節點擁有公共信譽時,這一點尤為明顯。區塊鏈技術運用基於數學原理的共識演算法,在節點之間建立「信任」網路,利用技術手段從而實現一種創新式的信用網路。
目前區款連行業內主流的共識演算法機制包含:工作量證明機制、權益證明機制、股份授權證明機制和Pool驗證池這四大類。
工作量證明機制即對於工作量的證明,是生成要加入到區塊鏈中的一筆新的交易信息(即新區塊)時必須滿足的要求。在基於工作量證明機制構建的區塊鏈網路中,節點通過計算隨機哈希散列的數值解爭奪記賬權,求得正確的數值解以生成區塊的能力是節點算力的具體表現。工作量證明機制具有完全去中心化的優點,在以工作量證明機制為共識的區塊鏈中,節點可以自由進出。大家所熟知的比特幣網路就應用工作量證明機制來生產新的貨幣。然而,由於工作量證明機制在比特幣網路中的應用已經吸引了全球計算機大部分的算力,其他想嘗試使用該機制的區塊鏈應用很難獲得同樣規模的算力來維持自身的安全。同時,基於工作量證明機制的挖礦行為還造成了大量的資源浪費,達成共識所需要的周期也較長,因此該機制並不適合商業應用。
2012年,化名Sunny King的網友推出了Peercoin,該加密電子貨幣採用工作量證明機制發行新幣,採用權益證明機制維護網路安全,這是權益證明機制在加密電子貨幣中的首次應用。與要求證明人執行一定量的計算工作不同,權益證明要求證明人提供一定數量加密貨幣的所有權即可。權益證明機制的運作方式是,當創造一個新區塊時,礦工需要創建一個「幣權」交易,交易會按照預先設定的比例把一些幣發送給礦工本身。權益證明機制根據每個節點擁有代幣的比例和時間,依據演算法等比例地降低節點的挖礦難度,從而加快了尋找隨機數的速度。這種共識機制可以縮短達成共識所需的時間,但本質上仍然需要網路中的節點進行挖礦運算。因此,PoS機制並沒有從根本上解決PoW機制難以應用於商業領域的問題。
股份授權證明機制是一種新的保障網路安全的共識機制。它在嘗試解決傳統的PoW機制和PoS機制問題的同時,還能通過實施科技式的民主抵消中心化所帶來的負面效應。
股份授權證明機制與董事會投票類似,該機制擁有一個內置的實時股權人投票系統,就像系統隨時都在召開一個永不散場的股東大會,所有股東都在這里投票決定公司決策。基於DPoS機制建立的區塊鏈的去中心化依賴於一定數量的代表,而非全體用戶。在這樣的區塊鏈中,全體節點投票選舉出一定數量的節點代表,由他們來代理全體節點確認區塊、維持系統有序運行。同時,區塊鏈中的全體節點具有隨時罷免和任命代表的權力。如果必要,全體節點可以通過投票讓現任節點代表失去代表資格,重新選舉新的代表,實現實時的民主。
股份授權證明機制可以大大縮小參與驗證和記賬節點的數量,從而達到秒級的共識驗證。然而,該共識機制仍然不能完美解決區塊鏈在商業中的應用問題,因為該共識機制無法擺脫對於代幣的依賴,而在很多商業應用中並不需要代幣的存在。
Pool驗證池基於傳統的分布式一致性技術建立,並輔之以數據驗證機制,是目前區塊鏈中廣泛使用的一種共識機制。
Pool驗證池不需要依賴代幣就可以工作,在成熟的分布式一致性演算法(Pasox、Raft)基礎之上,可以實現秒級共識驗證,更適合有多方參與的多中心商業模式。不過,Pool驗證池也存在一些不足,例如該共識機制能夠實現的分布式程度不如PoW機制等
這里主要講解區塊鏈工作量證明機制的一些演算法原理以及比特幣網路是如何證明自己的工作量的,希望大家能夠對共識演算法有一個基本的認識。
工作量證明系統的主要特徵是客戶端要做一定難度的工作來得到一個結果,驗證方則很容易通過結果來檢查客戶端是不是做了相應的工作。這種方案的一個核心特徵是不對稱性:工作對於請求方是適中中的,對於驗證方是易於驗證的。它與驗證碼不同,驗證碼是易於被人類解決而不是易於被計算機解決。
下圖所示的為工作量證明流程。
舉個例子,給個一個基本的字元創「hello,world!」,我們給出的工作量要求是,可以在這個字元創後面添加一個叫做nonce(隨機數)的整數值,對變更後(添加nonce)的字元創進行SHA-256運算,如果得到的結果(一十六進制的形式表示)以「0000」開頭的,則驗證通過。為了達到這個工作量證明的目標,需要不停地遞增nonce值,對得到的字元創進行SHA-256哈希運算。按照這個規則,需要經過4251次運算,才能找到前導為4個0的哈希散列。
通過這個示例我們對工作量證明機制有了一個初步的理解。有人或許認為如果工作量證明只是這樣一個過程,那是不是只要記住nonce為4521使計算能通過驗證就行了,當然不是了,這只是一個例子。
下面我們將輸入簡單的變更為」Hello,World!+整數值」,整數值取1~1000,也就是說將輸入變成一個1~1000的數組:Hello,World!1;Hello,World!2;...;Hello,World!1000。然後對數組中的每一個輸入依次進行上面的工作量證明—找到前導為4個0的哈希散列。
由於哈希值偽隨機的特性,根據概率論的相關知識容易計算出,預計要進行2的16次方次數的嘗試,才能得到前導為4個0的哈希散列。而統計一下剛剛進行的1000次計算的實際結果會發現,進行計算的平均次數為66958次,十分接近2的16次方(65536)。在這個例子中,數學期望的計算次數實際就是要求的「工作量」,重復進行多次的工作量證明會是一個符合統計學規律的概率事件。
統計輸入的字元創與得到對應目標結果實際使用的計算次數如下:
對於比特幣網路中的任何節點,如果想生成一個新的區塊加入到區塊鏈中,則必須解決出比特幣網路出的這道謎題。這道題的關鍵要素是工作量證明函數、區塊及難度值。工作量證明函數是這道題的計算方法,區塊是這道題的輸入數據,難度值決定了解這道題的所需要的計算量。
比特幣網路中使用的工作量證明函數正是上文提及的SHA-256。區塊其實就是在工作量證明環節產生的。曠工通過不停地構造區塊數據,檢驗每次計算出的結果是否滿足要求的工作量,從而判斷該區塊是不是符合網路難度。區塊頭即比特幣工作量證明函數的輸入數據。
難度值是礦工們挖掘的重要參考指標,它決定了曠工需要經過多少次哈希運算才能產生一個合法的區塊。比特幣網路大約每10分鍾生成一個區塊,如果在不同的全網算力條件下,新區塊的產生基本都保持這個速度,難度值必須根據全網算力的變化進行調整。總的原則即為無論挖礦能力如何,使得網路始終保持10分鍾產生一個新區塊。
難度值的調整是在每個完整節點中獨立自動發生的。每隔2016個區塊,所有節點都會按照統一的格式自動調整難度值,這個公式是由最新產生的2016個區塊的花費時長與期望時長(按每10分鍾產生一個取款,則期望時長為20160分鍾)比較得出來的,根據實際時長一期望時長的比值進行調整。也就是說,如果區塊產生的速度比10分鍾快,則增加難度值;反正,則降低難度值。用公式來表達如下:
新難度值=舊難度值*(20160分鍾/過去2016個區塊花費時長)。
工作量證明需要有一個目標值。比特幣工作量證明的目標值(Target)的計算公式如下:
目標值=最大目標值/難度值,其中最大目標值為一個恆定值
目標值的大小與難度值成反比,比特幣工作量證明的達成就是礦中計算出來的區塊哈希值必須小於目標值。
我們也可以將比特幣工作量的過程簡單的理解成,通過不停變更區塊頭(即嘗試不同nonce值)並將其作為輸入,進行SHA-256哈希運算,找出一個有特定格式哈希值的過程(即要求有一定數量的前導0),而要求的前導0個數越多,難度越大。
可以把比特幣將這道工作量證明謎題的步驟大致歸納如下:
該過程可以用下圖表示:
比特幣的工作量證明,就是我們俗稱「挖礦」所做的主要工作。理解工作量證明機制,將為我們進一步理解比特幣區塊鏈的共識機制奠定基礎。
『叄』 常見的共識演算法介紹
在非同步系統中,需要主機之間進行狀態復制,以保證每個主機達成一致的狀態共識。而在非同步系統中,主機之間可能出現故障,因此需要在默認不可靠的非同步網路中定義容錯協議,以確保各個主機達到安全可靠的狀態共識。
共識演算法其實就是一組規則,設置一組條件,篩選出具有代表性的節點。在區塊鏈系統中,存在很多這樣的篩選方案,如在公有鏈中的POW、Pos、DPOS等,而在不需要貨幣體系的許可鏈或私有鏈中,絕對信任的節點、高效的需求是公有鏈共識演算法不能提供的,對於這樣的區塊鏈,傳統的一致性共識演算法成為首選,如PBFT、PAXOS、RAFT等。
目錄
一、BFT(拜占庭容錯技術)
二、PBFT(實用拜占庭容錯演算法)
三、PAXOS
四、Raft
五、POW(工作量證明)
六、POS(權益證明)
七、DPOS(委任權益證明)
八、Ripple
拜占庭弄錯技術是一類分布式計算領域的容錯技術。拜占庭假設是由於硬體錯誤、網路擁塞或中斷以及遭到惡意攻擊的原因,計算機和網路出現不可預測的行為。拜占庭容錯用來處理這種異常行為,並滿足所要解決問題的規范。
拜占庭容錯系統是一個擁有n台節點的系統,整個系統對於每一個請求,滿足以下條件:
1)所有非拜占庭節點使用相同的輸入信息,產生同樣的結果;
2)如果輸入的信息正確,那麼所有非拜占庭節點必須接收這個信息,並計算相應的結果。
拜占庭系統普遍採用的假設條件包括:
1)拜占庭節點的行為可以是任意的,拜占庭節點之間可以共謀;
2)節點之間的錯誤是不相關的;
3)節點之間通過非同步網路連接,網路中的消息可能丟失、亂序並延時到達,但大部分協議假設消息在有限的時間里能傳達到目的地;
4)伺服器之間傳遞的信息,第三方可以嗅探到,但是不能篡改、偽造信息的內容和驗證信息的完整性。
拜占庭容錯由於其理論上的可行性而缺乏實用性,另外還需要額外的時鍾同步機制支持,演算法的復雜度也是隨節點的增加而指數級增加。
實用拜占庭容錯降低了拜占庭協議的運行復雜度,從指數級別降低到多項式級別。
PBFT是一種狀態機副本復制演算法,即服務作為狀態機進行建模,狀態機在分布式系統的不同節點進行副本復制。PBFT要求共同維護一個狀態。需要運行三類基本協議,包括一致性協議、檢查點協議和視圖更換協議。
一致性協議。一致性協議至少包含若干個階段:請求(request)、序號分配(pre-prepare)和響應(reply),可能包含相互交互(prepare),序號確認(commit)等階段。
PBFT通信模式中,每個客戶端的請求需要經過5個階段。由於客戶端不能從伺服器端獲得任何伺服器運行狀態的信息,PBFT中主節點是否發生錯誤只能由伺服器監測。如果伺服器在一段時間內都不能完成客戶端的請求,則會觸發視圖更換協議。
整個協議的基本過程如下:
1)客戶端發送請求,激活主節點的服務操作。
2)當主節點接收請求後,啟動三階段的協議以向各從節點廣播請求。
[2.1]序號分配階段,主節點給請求賦值一個序列號n,廣播序號分配消息和客戶端的請求消息m,並將構造PRE-PREPARE消息給各從節點;
[2.2]交互階段,從節點接收PRE-PREPARE消息,向其他服務節點廣播PREPARE消息;
[2.3]序號確認階段,各節點對視圖內的請求和次序進行驗證後,廣播COMMIT消息,執行收到的客戶端的請求並給客戶端以響應。
3)客戶端等待來自不同節點的響應,若有m+1個響應相同,則該響應即為運算的結果。
PBFT一般適合有對強一致性有要求的私有鏈和聯盟鏈,例如,在IBM主導的區塊鏈超級賬本項目中,PBFT是一個可選的共識協議。在Hyperledger的Fabric項目中,共識模塊被設計成可插拔的模塊,支持像PBFT、Raft等共識演算法。
在有些分布式場景下,其假設條件不需要考慮拜占庭故障,而只是處理一般的死機故障。在這種情況下,採用Paxos等協議會更加高效。。PAXOS是一種基於消息傳遞且具有高度容錯特性的一致性演算法。
PAXOS中有三類角色Proposer、Acceptor及Learner,主要交互過程在Proposer和Acceptor之間。演算法流程分為兩個階段:
phase 1
a) proposer向網路內超過半數的acceptor發送prepare消息
b) acceptor正常情況下回復promise消息
phase 2
a) 在有足夠多acceptor回復promise消息時,proposer發送accept消息
b) 正常情況下acceptor回復accepted消息
流程圖如圖所示:
PAXOS協議用於微信PaxosStore中,每分鍾調用Paxos協議過程數十億次量級。
Paxos是Lamport設計的保持分布式系統一致性的協議。但由於Paxos非常復雜,比較難以理解,因此後來出現了各種不同的實現和變種。Raft是由Stanford提出的一種更易理解的一致性演算法,意在取代目前廣為使用的Paxos演算法。
Raft最初是一個用於管理復制日誌的共識演算法,它是在非拜占庭故障下達成共識的強一致協議。Raft實現共識過程如下:首先選舉一個leader,leader從客戶端接收記賬請求、完成記賬操作、生成區塊,並復制到其他記賬節點。leader有完全的管理記賬權利,例如,leader能夠決定是否接受新的交易記錄項而無需考慮其他的記賬節點,leader可能失效或與其他節點失去聯系,這時,重新選出新的leader。
在Raft中,每個節點會處於以下三種狀態中的一種:
(1)follower:所有結點都以follower的狀態開始。如果沒收到leader消息則會變成candidate狀態;
(2)candidate:會向其他結點「拉選票」,如果得到大部分的票則成為leader。這個過程就叫做Leader選舉(Leader Election);
(3)leader:所有對系統的修改都會先經過leader。每個修改都會寫一條日誌(log entry)。leader收到修改請求後的過程如下:此過程叫做日誌復制(Log Replication)
1)復制日誌到所有follower結點
2)大部分結點響應時才提交日誌
3)通知所有follower結點日誌已提交
4)所有follower也提交日誌
5)現在整個系統處於一致的狀態
Raft階段主要分為兩個,首先是leader選舉過程,然後在選舉出來的leader基礎上進行正常操作,比如日誌復制、記賬等。
(1)leader選舉
當follower在選舉時間內未收到leader的消息,則轉換為candidate狀態。在Raft系統中:
1)任何一個伺服器都可以成為候選者candidate,只要它向其他伺服器follower發出選舉自己的請求。
2)如果其他伺服器同意了,發出OK。如果在這個過程中,有一個follower宕機,沒有收到請求選舉的要求,此時候選者可以自己選自己,只要達到N/2+1的大多數票,候選人還是可以成為leader的。
3)這樣這個候選者就成為了leader領導人,它可以向選民也就是follower發出指令,比如進行記賬。
4)以後通過心跳消息進行記賬的通知。
5)一旦這個leader崩潰了,那麼follower中有一個成為候選者,並發出邀票選舉。
6)follower同意後,其成為leader,繼續承擔記賬等指導工作。
(2)日誌復制
記賬步驟如下所示:
1)假設leader已經選出,這時客戶端發出增加一個日誌的要求;
2)leader要求follower遵從他的指令,將這個新的日誌內容追加到各自日誌中;
3)大多數follower伺服器將交易記錄寫入賬本後,確認追加成功,發出確認成功信息;
4)在下一個心跳消息中,leader會通知所有follower更新確認的項目。
對於每個新的交易記錄,重復上述過程。
在這一過程中,若發生網路通信故障,使得leader不能訪問大多數follower了,那麼leader只能正常更新它能訪問的那些follower伺服器。而大多數的伺服器follower因為沒有了leader,他們將重新選舉一個候選者作為leader,然後這個leader作為代表與外界打交道,如果外界要求其添加新的交易記錄,這個新的leader就按上述步驟通知大多數follower。當網路通信恢復,原先的leader就變成follower,在失聯階段,這個老leader的任何更新都不能算確認,必須全部回滾,接收新的leader的新的更新。
在去中心賬本系統中,每個加入這個系統的節點都要保存一份完整的賬本,但每個節點卻不能同時記賬,因為節點處於不同的環境,接收不同的信息,如果同時記賬,必然導致賬本的不一致。因此通過同時來決定那個節點擁有記賬權。
在比特幣系統中,大約每10分鍾進行一輪算力競賽,競賽的勝利者,就獲得一次記賬的權力,並向其他節點同步新增賬本信息。
PoW系統的主要特徵是計算的不對稱性。工作端要做一定難度的工作才能得出一個結果,而驗證方卻很容易通過結果來檢查工作端是不是做了相應的工作。該工作量的要求是,在某個字元串後面連接一個稱為nonce的整數值串,對連接後的字元串進行SHA256哈希運算,如果得到的哈希結果(以十六進制的形式表示)是以若干個0開頭的,則驗證通過。
比特幣網路中任何一個節點,如果想生成一個新的區塊並寫入區塊鏈,必須解出比特幣網路出的PoW問題。關鍵的3個要素是 工作量證明函數、區塊及難度值 。工作量證明函數是這道題的計算方法,區塊決定了這道題的輸入數據,難度值決定了這道題所需要的計算量。
(1)工作量證明函數就是<u style="box-sizing: border-box;"> SHA256 </u>
比特幣的區塊由區塊頭及該區塊所包含的交易列表組成。擁有80位元組固定長度的區塊頭,就是用於比特幣工作量證明的輸入字元串。
(2)難度的調整是在每個完整節點中獨立自動發生的。每2016個區塊,所有節點都會按統一的公式自動調整難度。如果區塊產生的速率比10分鍾快則增加難度,比10分鍾慢則降低難度。
公式可以總結為:新難度值=舊難度值×(過去2016個區塊花費時長/20160分鍾)
工作量證明需要有一個目標值。比特幣工作量證明的目標值(Target)的計算公式:目標值=最大目標值/難度值
其中最大目標值為一個恆定值:
目標值的大小與難度值成反比。比特幣工作量證明的達成就是礦工計算出來的 區塊哈希值必須小於目標值 。
(3)PoW能否解決拜占庭將軍問題
比特幣的PoW共識演算法是一種概率性的拜占庭協議(Probabilistic BA)
當不誠實的算力小於網路總算力的50%時,同時挖礦難度比較高(在大約10分鍾出一個區塊情況下)比特幣網路達到一致性的概念會隨確認區塊的數目增多而呈指數型增加。但當不誠實算力具一定規模,甚至不用接近50%的時候,比特幣的共識演算法並不能保證正確性,也就是,不能保證大多數的區塊由誠實節點來提供。
比特幣的共識演算法不適合於私有鏈和聯盟鏈。其原因首先是它是一個最終一致性共識演算法,不是一個強一致性共識演算法。第二個原因是其共識效率低。
擴展知識: 一致性
嚴格一致性,是在系統不發生任何故障,而且所有節點之間的通信無需任何時間這種理想的條件下,才能達到。這個時候整個系統就等價於一台機器了。在現實中,是不可能達到的。
強一致性,當分布式系統中更新操作完成之後,任何多個進程或線程,訪問系統都會獲得最新的值。
弱一致性,是指系統並不保證後續進程或線程的訪問都會返回最新的更新的值。系統在數據成功寫入之後,不承諾立即可以讀到最新寫入的值,也不會具體承諾多久讀到。但是會盡可能保證在某個時間級別(秒級)之後。可以讓數據達到一致性狀態。
最終一致性是弱一致性的特定形式。系統保證在沒有後續更新的前提下,系統最終返回上一次更新操作的值。也就是說,如果經過一段時間後要求能訪問到更新後的數據,則是最終一致性。
在股權證明PoS模式下,有一個名詞叫幣齡,每個幣每天產生1幣齡,比如你持有100個幣,總共持有了30天,那麼,此時你的幣齡就為3000,這個時候,如果你發現了一個PoS區塊,你的幣齡就會被清空為0。你每被清空365幣齡,你將會從區塊中獲得0.05個幣的利息(假定利息可理解為年利率5%),那麼在這個案例中,利息 = 3000 * 5% / 365 = 0.41個幣,這下就很有意思了,持幣有利息。
點點幣(Peercoin)是首先採用權益證明的貨幣。,點點幣的權益證明機制結合了隨機化與幣齡的概念,未使用至少30天的幣可以參與競爭下一區塊,越久和越大的幣集有更大的可能去簽名下一區塊。一旦幣的權益被用於簽名一個區塊,則幣齡將清為零,這樣必須等待至少30日才能簽署另一區塊。
PoS機制雖然考慮到了PoW的不足,但依據權益結余來選擇,會導致首富賬戶的權力更大,有可能支配記賬權。股份授權證明機制(Delegated Proof of Stake,DPoS)的出現正是基於解決PoW機制和PoS機制的這類不足。
比特股(Bitshare)是一類採用DPoS機制的密碼貨幣。它的原理是,讓每一個持有比特股的人進行投票,由此產生101位代表 , 我們可以將其理解為101個超級節點或者礦池,而這101個超級節點彼此的權利是完全相等的。如果代表不能履行他們的職責(當輪到他們時,沒能生成區塊),他們會被除名,網路會選出新的超級節點來取代他們。
比特股引入了見證人這個概念,見證人可以生成區塊,每一個持有比特股的人都可以投票選舉見證人。得到總同意票數中的前N個(N通常定義為101)候選者可以當選為見證人,當選見證人的個數(N)需滿足:至少一半的參與投票者相信N已經充分地去中心化。
見證人的候選名單每個維護周期(1天)更新一次。見證人然後隨機排列,每個見證人按序有2秒的許可權時間生成區塊,若見證人在給定的時間片不能生成區塊,區塊生成許可權交給下一個時間片對應的見證人。
比特股還設計了另外一類競選,代表競選。選出的代表擁有提出改變網路參數的特權,包括交易費用、區塊大小、見證人費用和區塊區間。若大多數代表同意所提出的改變,持股人有兩周的審查期,這期間可以罷免代表並廢止所提出的改變。這一設計確保代表技術上沒有直接修改參數的權利以及所有的網路參數的改變最終需得到持股人的同意。
Ripple(瑞波)是一種基於互聯網的開源支付協議,在Ripple的網路中,交易由客戶端(應用)發起,經過追蹤節點(tracking node)或驗證節點(validating node)把交易廣播到整個網路中。
追蹤節點的主要功能是分發交易信息以及響應客戶端的賬本請求。驗證節點除包含追蹤節點的所有功能外,還能夠通過共識協議,在賬本中增加新的賬本實例數據。
Ripple的共識達成發生在驗證節點之間,每個驗證節點都預先配置了一份可信任節點名單,稱為UNL(Unique Node List)。在名單上的節點可對交易達成進行投票。每隔幾秒,Ripple網路將進行如下共識過程:
1)每個驗證節點會不斷收到從網路發送過來的交易,通過與本地賬本數據驗證後,不合法的交易直接丟棄,合法的交易將匯總成交易候選集(candidate set)。交易候選集裡面還包括之前共識過程無法確認而遺留下來的交易。
2)每個驗證節點把自己的交易候選集作為提案發送給其他驗證節點。
3)驗證節點在收到其他節點發來的提案後,如果不是來自UNL上的節點,則忽略該提案;如果是來自UNL上的節點,就會對比提案中的交易和本地的交易候選集,如果有相同的交易,該交易就獲得一票。在一定時間內,當交易獲得超過50%的票數時,則該交易進入下一輪。沒有超過50%的交易,將留待下一次共識過程去確認。
4)驗證節點把超過50%票數的交易作為提案發給其他節點,同時提高所需票數的閾值到60%,重復步驟3)、步驟4),直到閾值達到80%。
5)驗證節點把經過80%UNL節點確認的交易正式寫入本地的賬本數據中,稱為最後關閉賬本(Last Closed Ledger),即賬本最後(最新)的狀態。
在Ripple的共識演算法中,參與投票節點的身份是事先知道的。該共識演算法只適合於許可權鏈(Permissioned chain)的場景。Ripple共識演算法的拜占庭容錯(BFT)能力為(n-1)/5,即可以容忍整個網路中20%的節點出現拜占庭錯誤而不影響正確的共識。
在區塊鏈網路中,由於應用場景的不同,所設計的目標各異,不同的區塊鏈系統採用了不同的共識演算法。一般來說,在私有鏈和聯盟鏈情況下,對一致性、正確性有很強的要求。一般來說要採用強一致性的共識演算法。而在公有鏈情況下,對一致性和正確性通常沒法做到百分之百,通常採用最終一致性(Eventual Consistency)的共識演算法。
共識演算法的選擇與應用場景高度相關,可信環境使用paxos 或者raft,帶許可的聯盟可使用pbft ,非許可鏈可以是pow,pos,ripple共識等,根據對手方信任度分級,自由選擇共識機制。
『肆』 共識演算法:Raft
上篇講到了「拜占庭將軍問題」:多個拜占庭將軍要如何在可能有叛徒、信使可能被策反或者暗殺的情況下達成是否要進攻的一致性決定?還不了解的先看看上一篇 《拜占庭將軍問題》 。這篇主要是介紹簡化版拜占庭將軍問題的解決方案:Raft 共識演算法。
所以將拜占庭將軍問題根據常見的工作上的問題進行簡化: 假設將軍中沒有叛軍,信使的信息可靠但有可能被暗殺的情況下,將軍們如何達成一致性決定?
對於這個簡化後的問題,有許多解決方案,第一個被證明的共識演算法是 Paxos,由拜占庭將軍問題的作者 Leslie Lamport 在1990年提出,最初以論文難懂而出名,後來這哥們在2001重新發了一篇簡單版的論文 Paxos Made Simple ,然而還是挺難懂的。
因為 Paxos 難懂,難實現,所以斯坦福大學的教授在2014年發表了新的分布式協議 Raft。與 Paxos 相比,Raft 有著基本相同運行效率,但是更容易理解,也更容易被用在系統開發上。
我們還是用拜占庭將軍的例子來幫助理解 Raft。
Raft 的解決方案大概可以理解成 先在所有將軍中選出一個大將軍,所有的決定由大將軍來做。 選舉環節 :比如說現在一共有3個將軍 A, B, C,每個將軍都有一個 隨機時間 的倒計時器,倒計時一結束,這個將軍就會把自己當成大將軍候選人,然後派信使去問其他幾個將軍,能不能選我為總將軍?假設現在將軍A倒計時結束了,他派信使傳遞選舉投票的信息給將軍B和C,如果將軍B和C還沒把自己當成候選人(倒計時還沒有結束),並且沒有把選舉票投給其他,他們把票投給將軍A,信使在回到將軍A時,將軍A知道自己收到了足夠的票數,成為了大將軍。在這之後,是否要進攻就由大將軍決定,然後派信使去通知另外兩個將軍,如果在一段時間後還沒有收到回復(可能信使被暗殺),那就再重派一個信使,直到收到回復。
故事先講到這里,希望不做技術方面的朋友可以大概能理解 Raft 的原理,下面從比較技術的角度講講 Raft 的原理。
從拜占庭將軍的故事映射到分布式系統上,每個將軍相當於一個分布式網路節點,每個節點有 三種狀態:Follower,Candidate,Leader ,狀態之間是互相轉換的,可以參考下圖,具體的後面說。
每個節點上都有一個倒計時器 (Election Timeout),時間隨機在 150ms 到 300ms 之間。有幾種情況會重設 Timeout:
在 Raft 運行過程中,最主要進行兩個活動:
假設現在有如圖5個節點,5個節點一開始的狀態都是 Follower。
在一個節點倒計時結束 (Timeout) 後,這個節點的狀態變成 Candidate 開始選舉,它給其他幾個節點發送選舉請求 (RequestVote)
其他四個節點都返回成功,這個節點的狀態由 Candidate 變成了 Leader,並在每個一小段時間後,就給所有的 Follower 發送一個 Heartbeat 以保持所有節點的狀態,Follower 收到 Leader 的 Heartbeat 後重設 Timeout。
這是最簡單的選主情況, 只要有超過一半的節點投支持票了,Candidate 才會被選舉為 Leader ,5個節點的情況下,3個節點 (包括 Candidate 本身) 投了支持就行。
一開始已經有一個 Leader,所有節點正常運行。
Leader 出故障掛掉了,其他四個 Follower 將進行重新選主。
4個節點的選主過程和5個節點的類似,在選出一個新的 Leader 後,原來的 Leader 恢復了又重新加入了,這個時候怎麼處理?在 Raft 里,第幾輪選舉是有記錄的,重新加入的 Leader 是第一輪選舉 (Term 1) 選出來的,而現在的 Leader 則是 Term 2,所有原來的 Leader 會自覺降級為 Follower
假設一開始有4個節點,都還是 Follower。
有兩個 Follower 同時 Timeout,都變成了 Candidate 開始選舉,分別給一個 Follower 發送了投票請求。
兩個 Follower 分別返回了ok,這時兩個 Candidate 都只有2票,要3票才能被選成 Leader。
兩個 Candidate 會分別給另外一個還沒有給自己投票的 Follower 發送投票請求。
但是因為 Follower 在這一輪選舉中,都已經投完票了,所以都拒絕了他們的請求。所以在 Term 2 沒有 Leader 被選出來。
這時,兩個節點的狀態是 Candidate,兩個是 Follower,但是他們的倒計時器仍然在運行,最先 Timeout 的那個節點會進行發起新一輪 Term 3 的投票。
兩個 Follower 在 Term 3 還沒投過票,所以返回 OK,這時 Candidate 一共有三票,被選為了 Leader。
如果 Leader Heartbeat 的時間晚於另外一個 Candidate timeout 的時間,另外一個 Candidate 仍然會發送選舉請求。
兩個 Follower 已經投完票了,拒絕了這個 Candidate 的投票請求。
Leader 進行 Heartbeat, Candidate 收到後狀態自動轉為 Follower,完成選主。
以上是 Raft 最重要活動之一選主的介紹,以及在不同情況下如何進行選主。
Raft 在實際應用場景中的一致性更多的是體現在不同節點之間的數據一致性,客戶端發送請求到任何一個節點都能收到一致的返回,當一個節點出故障後,其他節點仍然能以已有的數據正常進行。在選主之後的復制日誌就是為了達到這個目的。
一開始,Leader 和 兩個 Follower 都沒有任何數據。
客戶端發送請求給 Leader,儲存數據 「sally」,Leader 先將數據寫在本地日誌,這時候數據還是 Uncommitted (還沒最終確認,紅色表示)
Leader 給兩個 Follower 發送 AppendEntries 請求,數據在 Follower 上沒有沖突,則將數據暫時寫在本地日誌,Follower 的數據也還是 Uncommitted。
Follower 將數據寫到本地後,返回 OK。Leader 收到後成功返回, 只要收到的成功的返回數量超過半數 (包含Leader) ,Leader 將數據 「sally」 的狀態改成 Committed。( 這個時候 Leader 就可以返回給客戶端了)
Leader 再次給 Follower 發送 AppendEntries 請求,收到請求後,Follower 將本地日誌里 Uncommitted 數據改成 Committed。這樣就完成了一整個復制日誌的過程,三個節點的數據是一致的,
在 Network Partition 的情況下,部分節點之間沒辦法互相通信,Raft 也能保證在這種情況下數據的一致性。
一開始有 5 個節點處於同一網路狀態下。
Network Partition 將節點分成兩邊,一邊有兩個節點,一邊三個節點。
兩個節點這邊已經有 Leader 了,來自客戶端的數據 「bob」 通過 Leader 同步到 Follower。
因為只有兩個節點,少於3個節點,所以 「bob」 的狀態仍是 Uncommitted。所以在這里, 伺服器會返回錯誤給客戶端
另外一個 Partition 有三個節點,進行重新選主。客戶端數據 「tom」 發到新的 Leader,通過和上節網路狀態下相似的過程,同步到另外兩個 Follower。
因為這個 Partition 有3個節點,超過半數,所以數據 「tom」 都 Commit 了。
網路狀態恢復,5個節點再次處於同一個網路狀態下。但是這里出現了數據沖突 「bob" 和 「tom"
三個節點的 Leader 廣播 AppendEntries
兩個節點 Partition 的 Leader 自動降級為 Follower,因為這個 Partition 的數據 「bob」 沒有 Commit,返回給客戶端的是錯誤,客戶端知道請求沒有成功,所以 Follower 在收到 AppendEntries 請求時,可以把 「bob「 刪除,然後同步 」tom」,通過這么一個過程,就完成了在 Network Partition 情況下的復制日誌,保證了數據的一致性。
Raft 是能夠實現分布式系統強一致性的演算法,每個系統節點有三種狀態 Follower,Candidate,Leader。實現 Raft 演算法兩個最重要的事是:選主和復制日誌
參考鏈接:
Raft 官網: https://raft.github.io/
Raft 原理動畫 (推薦看看): http://thesecretlivesofdata.com/raft/
(本來不想一個個圖片粘,但是在國內時候訪問不了這個鏈接,乾脆就復述了一遍整個過程。)
『伍』 鄭州北大青鳥分享區塊鏈技術中的共識演算法
關於區塊鏈技術的一些講解和知識點分析我們已經給大家分享過很多次了。
今天,鄭州java課程http://www.kmbdqn.cn/就再來了解一下,區塊鏈技術中的共識演算法的一些基本定義與特點。
簡單過一下區塊鏈我們一般意識形態中的鏈是鐵鏈,由鐵鑄成,一環扣一環。
形象地,區塊鏈的也可以這么理解,只不過它不是由鐵鑄成,而是由擁有一定數據結構的塊連接而成,這是一個簡單的雛形通俗講解共識所謂共識,通俗來說,就是我們大家對某種事物的理解達成一致的意思。
比如說日常的開會討論問題,又比如判斷一個動物是不是貓,我們肉眼看了後覺得像貓,其滿足貓的特徵,那麼我們認為它是貓。
共識,是一種規則。
繼續我們的會議例子。
參與會議的人,通過開會的方式來達到談論解決問題。
對比區塊鏈中,參與挖礦的礦工通過某種共識方式(演算法)來解決讓自己的賬本跟其他節點的賬本保持一致。
讓賬本保持一致的深入一層意思就是,讓鏈中區塊信息保持一致。
為什麼需要共識,不需要可不可以?當然不可以,生活中沒了共識的規則,一切亂套。
區塊鏈沒了共識的規則,各個節點各干各的,失去一致的意義。
這兩個例子的對應的關系如下:會議的人=挖礦的礦工開會=共識方式(演算法)談論解決問題=讓自己的賬本跟其他節點的賬本保持一致如果你對節點的概念意思不懂,請先理解為礦工,一個節點內部包含很多角色,礦工是其中之一。
共識演算法目前常見的在區塊鏈中,節點們讓自己的賬本跟其他節點的賬本保持一致的共識方式(演算法)有如下幾種:PoW,代表者是比特幣(BTC)弊端:礦池的出現,一定程度上違背了去中心化的初衷,同時也使得51%攻擊成為可能,影響其安全性。
存在巨大的算力浪費,看看礦池消耗大量的電力資源,隨著難度增加,挖出的不夠付電費PoS,代表者是以太坊(ETH),從PoW過度到PoS弊端:破壞者對網路的攻擊成本很低,擁有代幣就能競爭另外擁有代幣數量大的節點獲得記賬權的概率會更大,會使得網路共識受少數富裕賬戶支配,從而失去公正性。
『陸』 簡評三個基於VRF的共識演算法
上交所技術公司 朱立
Algorand、Dfinity和Ouroboros Praos三個共識演算法(Dfinity雖然是項目名,這里用來稱呼其共識演算法也應無不妥)近期較受關注,而且都是基於VRF(Verifiable Random Function) 設計,可以對照學習。Algorand的版本很多,以下單指 1607.01341v9 ,暫稱其為Algorand'(筆者手中另有Algorand的 最新版本 ,其中已對下文提及的幾處問題完成了修正,可與本文參看)。
一、VRF的共性
VRF的意義很好理解——用以完成出塊人(群)的隨機選擇。為此,VRF的返回值應盡力難以預測。先看Algorand'和Dfinity的套路是怎麼做的:大體上是先將前一個隨機數(最初的隨機數卻是協議給定的)和某種代表高度、輪次的變數進行組合,用某種私鑰對之進行簽名(或者是先簽名再組合),最後哈希一下得出最新的隨機數。這樣產生的隨機數旁人很容易驗證其合乎演算法,"V"就這樣得到了;而哈希返回值又是隨機分布的,「R」也因此得到保證。在此過程中,為降低操縱結果的可能性,有兩個注意事項: A) 簽名演算法應當具有唯一性,也就是用同一把私鑰對同樣的信息進行簽名,只有一個合法簽名可以通過驗證——普通的非對稱加解密演算法一般不具備這個屬性,如SM2。如果用的簽名演算法沒有這種uniqueness屬性,那在生成新隨機數的時候就存在通過反復多次嘗試簽名以挑出最有利者的餘地,會降低安全性。 B) 避免在生成新隨機數時將當前塊的數據作為隨機性來源之一,比如引用本塊交易列表的merkle root值等等,因為這樣做會給出塊人嘗試變更打包交易順序、嘗試打包不同交易以產生最有利的新隨機數的餘地。在設計和檢視新的共識演算法時,以上兩個注意事項是要特別留意的。
考察一下VRF的返回結果應該如何運用。目前所見用法中,VRF的返回結果可以用來公開完成節點或節點群體的選擇,也可以私密地完成選擇。以Dfinity為例,它是利用mod操作來唯一、公開地確定一個Group。Algorand'、Ouroboros Praos是私密選擇的範例,大致套路是對VRF的最新返回值,配上輪次等變數後用私鑰進行簽名並哈希,如果哈希值小於某個閾值,節點就可以私密地知道自己被選中。這種方法很可能在網路節點數較多時的表現會更穩定,否則幸運兒個數上下波動會較大,進而影響協議表現,包括空塊和分叉。
二、簡評強同步假設版本的Algorand'
私密選擇提供了較強的抗擊定點攻擊的能力,但由於幸運兒的總數對於任何一個幸運兒都是不能預知的,也因此給後續共識演算法的設計和區塊鏈的優化帶來了困難。Algorand『採用了很強的同步網路假設(同步網路假設下的共識演算法當然容易做一些),要求預先知道網路消息傳播時間的上限:在固定時間內完成對固定比例的用戶的網路傳播。比如要知道,1KB消息,在1秒鍾內完成全網95%的傳播,而1MB消息需要1.5分鍾完成全網95%的傳播。但這個傳輸上限應該如何選擇? 通過一段時間的統計結果再乘以一個系數這種經驗統計?只能說「感覺上可以」,但如果要嚴謹和安全,Algorand『演算法應該補充證明即使在遭遇DDOS或互聯網擁堵的情況下消息傳播嚴重超限後演算法仍然能夠保證安全——然而這個證明是缺失的。作為對照,Ouroboros Praos公開承認之前在同步網路假設下設計的Ouroboros協議在非同步網路條件下會出錯,所以才又做了Ouroboros Praos;新版本的Algorand承認在弱同步網路時會在不同的塊上達成共識(後續網路恢復強同步時分叉可以得到解決)雲雲,這些都可資參考。
即使我們暫且認可Algorand'演算法可以通過設定一個很大的傳播時間上限來回應上述問題,但隨之而來的是此時可以看出此演算法缺乏一個非常好的特性:Responsiveness。這個特性指的是:若一個協議被設計為在一個較大的傳播時間上限DELTA下工作,但若實際傳播時間是較小的delta,則協議的實際推進步調將只和delta有關,這種協議被稱為Responsive的。具有Responsive特性的共識演算法再配以同步網路假設會非常理想——出於安全,上限可以設置很大,然而協議執行速度只和當時網路條件有關。Algorand'並不具有這種特性。平均而言,Algorand'完成共識所需的消息傳送次數是11輪,每輪如果要確保安全,完成共識的時間就會很長,單個分區的吞吐量就不會太高。當然,架構設計涉及很多取捨,最終評價一個演算法好還是不好還是要回到初心——准備拿來實現的目標是什麼。上述分析只是嘗試客觀地指出Algorand'演算法的幾個少為人知的固有特徵,供讀者自行評估。
三、簡評Dfinity的可擴展性問題
私密選擇並且立即上任的做法,也給系統分片帶來了極大挑戰。Dfinity是明確要做分片(Sharding)的,所以必須直面挑戰。可擴展性問題非常復雜,完整解決這個問題需要通盤考慮網路、存儲、計算三方面的可擴展性——時下大多數區塊鏈3.0項目只注意到計算的分片和可擴展性,忽略了其餘二者,從而不可能真正實現理想的擴展。由於公鏈節點網路帶寬的制約,計算合約所需的數據通常很難迅速地從一個節點拷貝到另一節點,所以就算用VRF實現了飄忽來去的出塊節點選擇,存儲節點是沒法同樣飄逸如風的。明顯的選擇有那麼幾個:全部節點存儲全部數據,不同節點靜態地分配用來存儲不同分區。前者的可擴展性很差,對於後者而言,如果出塊節點漂浮不定且出塊節點還需要完成合約運算,就意味著基於P2P網路來回遠程訪問存儲,性能多半急劇下降;動態決定的出塊節點只完成排序共識,計算能力和存儲捆綁,通過靜態分區提供可擴展性,可能是合理的應對。然而,最可恨的就是「然而」二字——即使如此,系統還存在一處對存儲和網路構成壓力的所在:最終用戶提交的待打包交易。普通公鏈(先不考慮EOS那種)的帶寬有限,如果用戶提交的待打包交易必須粗放型地全網泛濫傳播,那現有網路帶寬可以提供多少TPS?如果出塊節點是靜態分區或者至少提前一段時間公開知曉,事情尚有迴旋餘地;如果出塊節點是如此飄忽不定,而且直到最後一刻也只有這些節點自己知道,那無論是用戶還是出塊節點候選人看起來最直接的應對之道就是全網泛濫傳播全部待打包交易、保存全部待打包交易,這樣帶寬和存儲仍然成為系統瓶頸。
所以這里碰到的,本質上還是安全、可擴展性、去中心化的不可能三角。
四、簡評Ouroboros Praos
BM懟 Ouroboros的文字已經流傳廣泛。BM的話當然有些明顯是不對的,比如Ouroboros的DPOS是指"Dynamic [stake distribution] POS"而不是BM的Delegate POS,但其關於Pareto分布的評論則值得玩味。如果我們仔細瀏覽後出的Ouroboros Praos,可以發現協議的安全假設和安全證明完全沒有考慮經濟博弈因素,因此洋洋灑灑的證明很可能會不得要領而錯過真正需要防護的方向——畢竟一直以來POS/DPOS這些協議的血管裡面流淌的就是基於經濟博弈和人性進行設計的血液。最明顯的例子是在forward secure signature的實現方法上,協議目前的設計是要求每個好的節點自覺主動地安全刪除用過的私鑰,而完全沒有考慮近乎零的私鑰保存成本如何面對bribe attack的誘惑,然而這卻是值得考慮的。除了形式化證明之外,Ouroboros Praos本身並沒有太多值得關注的協議特徵,總體上就是用VRF抽簽結合POS演算法並針對某些安全假設進行了形式化證明,其做事的態度是非常值得贊賞的。
五、總結
這幾個演算法本身頗有創意,也很值得學習。與此同時,在看過以太坊CASPER目前披露的分區技術後,筆者的體會是:區塊鏈3.0的競爭才剛剛開始,從以太坊團隊的技術路線看,他們的技術考量和選擇要比很多宣稱要超越以太坊的團隊來得深刻和全面。如果當真要超越以太坊,還是應該先從理解以太坊開始。
順便感謝趣鏈邱煒偉博士對本文的貢獻!
『柒』 區塊鏈 --- 共識演算法
PoW演算法是一種防止分布式服務資源被濫用、拒絕服務攻擊的機制。它要求節點進行適量消耗時間和資源的復雜運算,並且其運算結果能被其他節點快速驗算,以耗用時間、能源做擔保,以確保服務與資源被真正的需求所使用。
PoW演算法中最基本的技術原理是使用哈希演算法。假設求哈希值Hash(r),若原始數據為r(raw),則運算結果為R(Result)。
R = Hash(r)
哈希函數Hash()的特性是,對於任意輸入值r,得出結果R,並且無法從R反推回r。當輸入的原始數據r變動1比特時,其結果R值完全改變。在比特幣的PoW演算法中,引入演算法難度d和隨機值n,得到以下公式:
Rd = Hash(r+n)
該公式要求在填入隨機值n的情況下,計算結果Rd的前d位元組必須為0。由於哈希函數結果的未知性,每個礦工都要做大量運算之後,才能得出正確結果,而算出結果廣播給全網之後,其他節點只需要進行一次哈希運算即可校驗。PoW演算法就是採用這種方式讓計算消耗資源,而校驗僅需一次。
PoS演算法要求節點驗證者必須質押一定的資金才有挖礦打包資格,並且區域鏈系統在選定打包節點時使用隨機的方式,當節點質押的資金越多時,其被選定打包區塊的概率越大。
POS模式下,每個幣每天產生1幣齡,比如你持有100個幣,總共持有了30天,那麼,此時你的幣齡就為3000。這個時候,如果你驗證了一個POS區塊,你的幣齡就會被清空為0,同時從區塊中獲得相對應的數字貨幣利息。
節點通過PoS演算法出塊的過程如下:普通的節點要成為出塊節點,首先要進行資產的質押,當輪到自己出塊時,打包區塊,然後向全網廣播,其他驗證節點將會校驗區塊的合法性。
DPoS演算法和PoS演算法相似,也採用股份和權益質押。
但不同的是,DPoS演算法採用委託質押的方式,類似於用全民選舉代表的方式選出N個超級節點記賬出塊。
選民把自己的選票投給某個節點,如果某個節點當選記賬節點,那麼該記賬節點往往在獲取出塊獎勵後,可以採用任意方式來回報自己的選民。
這N個記賬節點將輪流出塊,並且節點之間相互監督,如果其作惡,那麼會被扣除質押金。
通過信任少量的誠信節點,可以去除區塊簽名過程中不必要的步驟,提高了交易的速度。
拜占庭問題:
拜占庭是古代東羅馬帝國的首都,為了防禦在每塊封地都駐扎一支由單個將軍帶領的軍隊,將軍之間只能靠信差傳遞消息。在戰爭時,所有將軍必須達成共識,決定是否共同開戰。
但是,在軍隊內可能有叛徒,這些人將影響將軍們達成共識。拜占庭將軍問題是指在已知有將軍是叛徒的情況下,剩餘的將軍如何達成一致決策的問題。
BFT:
BFT即拜占庭容錯,拜占庭容錯技術是一類分布式計算領域的容錯技術。拜占庭假設是對現實世界的模型化,由於硬體錯誤、網路擁塞或中斷以及遭到惡意攻擊等原因,計算機和網路可能出現不可預料的行為。拜占庭容錯技術被設計用來處理這些異常行為,並滿足所要解決的問題的規范要求。
拜占庭容錯系統 :
發生故障的節點被稱為 拜占庭節點 ,而正常的節點即為 非拜占庭節點 。
假設分布式系統擁有n台節點,並假設整個系統拜占庭節點不超過m台(n ≥ 3m + 1),拜占庭容錯系統需要滿足如下兩個條件:
另外,拜占庭容錯系統需要達成如下兩個指標:
PBFT即實用拜占庭容錯演算法,解決了原始拜占庭容錯演算法效率不高的問題,演算法的時間復雜度是O(n^2),使得在實際系統應用中可以解決拜占庭容錯問題
PBFT是一種狀態機副本復制演算法,所有的副本在一個視圖(view)輪換的過程中操作,主節點通過視圖編號以及節點數集合來確定,即:主節點 p = v mod |R|。v:視圖編號,|R|節點個數,p:主節點編號。
PBFT演算法的共識過程如下:客戶端(Client)發起消息請求(request),並廣播轉發至每一個副本節點(Replica),由其中一個主節點(Leader)發起提案消息pre-prepare,並廣播。其他節點獲取原始消息,在校驗完成後發送prepare消息。每個節點收到2f+1個prepare消息,即認為已經准備完畢,並發送commit消息。當節點收到2f+1個commit消息,客戶端收到f+1個相同的reply消息時,說明客戶端發起的請求已經達成全網共識。
具體流程如下 :
客戶端c向主節點p發送<REQUEST, o, t, c>請求。o: 請求的具體操作,t: 請求時客戶端追加的時間戳,c:客戶端標識。REQUEST: 包含消息內容m,以及消息摘要d(m)。客戶端對請求進行簽名。
主節點收到客戶端的請求,需要進行以下交驗:
a. 客戶端請求消息簽名是否正確。
非法請求丟棄。正確請求,分配一個編號n,編號n主要用於對客戶端的請求進行排序。然後廣播一條<<PRE-PREPARE, v, n, d>, m>消息給其他副本節點。v:視圖編號,d客戶端消息摘要,m消息內容。<PRE-PREPARE, v, n, d>進行主節點簽名。n是要在某一個范圍區間內的[h, H],具體原因參見 垃圾回收 章節。
副本節點i收到主節點的PRE-PREPARE消息,需要進行以下交驗:
a. 主節點PRE-PREPARE消息簽名是否正確。
b. 當前副本節點是否已經收到了一條在同一v下並且編號也是n,但是簽名不同的PRE-PREPARE信息。
c. d與m的摘要是否一致。
d. n是否在區間[h, H]內。
非法請求丟棄。正確請求,副本節點i向其他節點包括主節點發送一條<PREPARE, v, n, d, i>消息, v, n, d, m與上述PRE-PREPARE消息內容相同,i是當前副本節點編號。<PREPARE, v, n, d, i>進行副本節點i的簽名。記錄PRE-PREPARE和PREPARE消息到log中,用於View Change過程中恢復未完成的請求操作。
主節點和副本節點收到PREPARE消息,需要進行以下交驗:
a. 副本節點PREPARE消息簽名是否正確。
b. 當前副本節點是否已經收到了同一視圖v下的n。
c. n是否在區間[h, H]內。
d. d是否和當前已收到PRE-PPREPARE中的d相同
非法請求丟棄。如果副本節點i收到了2f+1個驗證通過的PREPARE消息,則向其他節點包括主節點發送一條<COMMIT, v, n, d, i>消息,v, n, d, i與上述PREPARE消息內容相同。<COMMIT, v, n, d, i>進行副本節點i的簽名。記錄COMMIT消息到日誌中,用於View Change過程中恢復未完成的請求操作。記錄其他副本節點發送的PREPARE消息到log中。
主節點和副本節點收到COMMIT消息,需要進行以下交驗:
a. 副本節點COMMIT消息簽名是否正確。
b. 當前副本節點是否已經收到了同一視圖v下的n。
c. d與m的摘要是否一致。
d. n是否在區間[h, H]內。
非法請求丟棄。如果副本節點i收到了2f+1個驗證通過的COMMIT消息,說明當前網路中的大部分節點已經達成共識,運行客戶端的請求操作o,並返回<REPLY, v, t, c, i, r>給客戶端,r:是請求操作結果,客戶端如果收到f+1個相同的REPLY消息,說明客戶端發起的請求已經達成全網共識,否則客戶端需要判斷是否重新發送請求給主節點。記錄其他副本節點發送的COMMIT消息到log中。
如果主節點作惡,它可能會給不同的請求編上相同的序號,或者不去分配序號,或者讓相鄰的序號不連續。備份節點應當有職責來主動檢查這些序號的合法性。
如果主節點掉線或者作惡不廣播客戶端的請求,客戶端設置超時機制,超時的話,向所有副本節點廣播請求消息。副本節點檢測出主節點作惡或者下線,發起View Change協議。
View Change協議 :
副本節點向其他節點廣播<VIEW-CHANGE, v+1, n, C , P , i>消息。n是最新的stable checkpoint的編號, C 是 2f+1驗證過的CheckPoint消息集合, P 是當前副本節點未完成的請求的PRE-PREPARE和PREPARE消息集合。
當主節點p = v + 1 mod |R|收到 2f 個有效的VIEW-CHANGE消息後,向其他節點廣播<NEW-VIEW, v+1, V , O >消息。 V 是有效的VIEW-CHANGE消息集合。 O 是主節點重新發起的未經完成的PRE-PREPARE消息集合。PRE-PREPARE消息集合的選取規則:
副本節點收到主節點的NEW-VIEW消息,驗證有效性,有效的話,進入v+1狀態,並且開始 O 中的PRE-PREPARE消息處理流程。
在上述演算法流程中,為了確保在View Change的過程中,能夠恢復先前的請求,每一個副本節點都記錄一些消息到本地的log中,當執行請求後副本節點需要把之前該請求的記錄消息清除掉。
最簡單的做法是在Reply消息後,再執行一次當前狀態的共識同步,這樣做的成本比較高,因此可以在執行完多條請求K(例如:100條)後執行一次狀態同步。這個狀態同步消息就是CheckPoint消息。
副本節點i發送<CheckPoint, n, d, i>給其他節點,n是當前節點所保留的最後一個視圖請求編號,d是對當前狀態的一個摘要,該CheckPoint消息記錄到log中。如果副本節點i收到了2f+1個驗證過的CheckPoint消息,則清除先前日誌中的消息,並以n作為當前一個stable checkpoint。
這是理想情況,實際上當副本節點i向其他節點發出CheckPoint消息後,其他節點還沒有完成K條請求,所以不會立即對i的請求作出響應,它還會按照自己的節奏,向前行進,但此時發出的CheckPoint並未形成stable。
為了防止i的處理請求過快,設置一個上文提到的 高低水位區間[h, H] 來解決這個問題。低水位h等於上一個stable checkpoint的編號,高水位H = h + L,其中L是我們指定的數值,等於checkpoint周期處理請求數K的整數倍,可以設置為L = 2K。當副本節點i處理請求超過高水位H時,此時就會停止腳步,等待stable checkpoint發生變化,再繼續前進。
在區塊鏈場景中,一般適合於對強一致性有要求的私有鏈和聯盟鏈場景。例如,在IBM主導的區塊鏈超級賬本項目中,PBFT是一個可選的共識協議。在Hyperledger的Fabric項目中,共識模塊被設計成可插拔的模塊,支持像PBFT、Raft等共識演算法。
Raft基於領導者驅動的共識模型,其中將選舉一位傑出的領導者(Leader),而該Leader將完全負責管理集群,Leader負責管理Raft集群的所有節點之間的復制日誌。
下圖中,將在啟動過程中選擇集群的Leader(S1),並為來自客戶端的所有命令/請求提供服務。 Raft集群中的所有節點都維護一個分布式日誌(復制日誌)以存儲和提交由客戶端發出的命令(日誌條目)。 Leader接受來自客戶端的日誌條目,並在Raft集群中的所有關注者(S2,S3,S4,S5)之間復制它們。
在Raft集群中,需要滿足最少數量的節點才能提供預期的級別共識保證, 這也稱為法定人數。 在Raft集群中執行操作所需的最少投票數為 (N / 2 +1) ,其中N是組中成員總數,即 投票至少超過一半 ,這也就是為什麼集群節點通常為奇數的原因。 因此,在上面的示例中,我們至少需要3個節點才能具有共識保證。
如果法定仲裁節點由於任何原因不可用,也就是投票沒有超過半數,則此次協商沒有達成一致,並且無法提交新日誌。
數據存儲:Tidb/TiKV
日誌:阿里巴巴的 DLedger
服務發現:Consul& etcd
集群調度:HashiCorp Nomad
只能容納故障節點(CFT),不容納作惡節點
順序投票,只能串列apply,因此高並發場景下性能差
Raft通過解決圍繞Leader選舉的三個主要子問題,管理分布式日誌和演算法的安全性功能來解決分布式共識問題。
當我們啟動一個新的Raft集群或某個領導者不可用時,將通過集群中所有成員節點之間協商來選舉一個新的領導者。 因此,在給定的實例中,Raft集群的節點可以處於以下任何狀態: 追隨者(Follower),候選人(Candidate)或領導者(Leader)。
系統剛開始啟動的時候,所有節點都是follower,在一段時間內如果它們沒有收到Leader的心跳信號,follower就會轉化為Candidate;
如果某個Candidate節點收到大多數節點的票,則這個Candidate就可以轉化為Leader,其餘的Candidate節點都會回到Follower狀態;
一旦一個Leader發現系統中存在一個Leader節點比自己擁有更高的任期(Term),它就會轉換為Follower。
Raft使用基於心跳的RPC機制來檢測何時開始新的選舉。 在正常期間, Leader 會定期向所有可用的 Follower 發送心跳消息(實際中可能把日誌和心跳一起發過去)。 因此,其他節點以 Follower 狀態啟動,只要它從當前 Leader 那裡收到周期性的心跳,就一直保持在 Follower 狀態。
當 Follower 達到其超時時間時,它將通過以下方式啟動選舉程序:
根據 Candidate 從集群中其他節點收到的響應,可以得出選舉的三個結果。
共識演算法的實現一般是基於復制狀態機(Replicated state machines),何為 復制狀態機 :
簡單來說: 相同的初識狀態 + 相同的輸入 = 相同的結束狀態 。不同節點要以相同且確定性的函數來處理輸入,而不要引入一下不確定的值,比如本地時間等。使用replicated log是一個很不錯的注意,log具有持久化、保序的特點,是大多數分布式系統的基石。
有了Leader之後,客戶端所有並發的請求可以在Leader這邊形成一個有序的日誌(狀態)序列,以此來表示這些請求的先後處理順序。Leader然後將自己的日誌序列發送Follower,保持整個系統的全局一致性。注意並不是強一致性,而是 最終一致性 。
日誌由有序編號(log index)的日誌條目組成。每個日誌條目包含它被創建時的任期號(term),和日誌中包含的數據組成,日誌包含的數據可以為任何類型,從簡單類型到區塊鏈的區塊。每個日誌條目可以用[ term, index, data]序列對表示,其中term表示任期, index表示索引號,data表示日誌數據。
Leader 嘗試在集群中的大多數節點上執行復制命令。 如果復製成功,則將命令提交給集群,並將響應發送回客戶端。類似兩階段提交(2PC),不過與2PC的區別在於,leader只需要超過一半節點同意(處於工作狀態)即可。
leader 、 follower 都可能crash,那麼 follower 維護的日誌與 leader 相比可能出現以下情況
當出現了leader與follower不一致的情況,leader強制follower復制自己的log, Leader會從後往前試 ,每次AppendEntries失敗後嘗試前一個日誌條目(遞減nextIndex值), 直到成功找到每個Follower的日誌一致位置點(基於上述的兩條保證),然後向後逐條覆蓋Followers在該位置之後的條目 。所以丟失的或者多出來的條目可能會持續多個任期。
要求候選人的日誌至少與其他節點一樣最新。如果不是,則跟隨者節點將不投票給候選者。
意味著每個提交的條目都必須存在於這些伺服器中的至少一個中。如果候選人的日誌至少與該多數日誌中的其他日誌一樣最新,則它將保存所有已提交的條目,避免了日誌回滾事件的發生。
即任一任期內最多一個leader被選出。這一點非常重要,在一個復制集中任何時刻只能有一個leader。系統中同時有多餘一個leader,被稱之為腦裂(brain split),這是非常嚴重的問題,會導致數據的覆蓋丟失。在raft中,兩點保證了這個屬性:
因此, 某一任期內一定只有一個leader 。
當集群中節點的狀態發生變化(集群配置發生變化)時,系統容易受到系統故障。 因此,為防止這種情況,Raft使用了一種稱為兩階段的方法來更改集群成員身份。 因此,在這種方法中,集群在實現新的成員身份配置之前首先更改為中間狀態(稱為聯合共識)。 聯合共識使系統即使在配置之間進行轉換時也可用於響應客戶端請求,它的主要目的是提升分布式系統的可用性。
『捌』 共識演算法4 (BFT)
拜占庭將軍問題(Byzantine Generals Problem),由Leslie Lamport、Robert Shostak和Marshall Pease,在其同名論文中提出(1982年)。拜占庭將軍問題現在主要指分布式對等網路節點間的通信容錯問題。在分布式網路中,不同的計節點通過交換信息達成共識。但有時候,系統中的成員節點可能出錯而發送錯誤的信息,用於傳遞信息的通訊網路也可能導致信息損壞,也可能存在惡意節點或被黑客攻破的節點故意發送錯誤的信息,從而導致系統無法達成共識或者達成錯誤的共識。(參考: BFT Wikipedia )
拜占庭將軍問題提出後,有很多的演算法被提出用於解決這個問題。這類演算法統稱拜占庭容錯演算法(BFT: Byzantine Fault Tolerance)。BFT從上世紀80年代開始被研究,目前已經是一個被研究得比較透徹的理論,具體實現都已經有現成的演算法。
BFT演算法中最典型的是PBFT(Practical BFT)。PBFT是由Miguel Castro和Barbara Liskov於1999年提出。PBFT演算法解決了之前拜占庭容錯演算法效率不高的問題,將演算法復雜度由指數級降低到多項式級,使得拜占庭容錯演算法在實際系統應用中變得可行。PBFT在保證安全性和可用性的前提下,提供了 (n-1)/3 的容錯性。(細節請參考: PBFT )
PBFT之後,很多進一步提升性能或魯棒性的BFT演算法先後被提出,例如Zyzzyva、ABsTRACTs、Aardvark、RBFT等等。近幾年,由於區塊鏈的熱度,無數針對區塊鏈應用場景優化過的BFT演算法也不斷涌現出來。雖然目前PBFT已經不能說是最好的,或最適合區塊鏈的BFT演算法。但是PBFT已經足夠好了,而且在實際應用中已經非常成熟。
在BFT共識機制中,網路中節點的數量和身份必須是提前確定好的。BFT共識機制無法做到PoW共識機制中實現的任何人都可以隨時加入挖礦。另外,BFT演算法無法應用到大量的節點,業內普遍認為100個節點是BFT演算法的上限。所以BFT演算法無法直接用於公有鏈,BFT演算法適合的場景是私有鏈和聯盟鏈。業內大名鼎鼎的聯盟鏈Hyperledger fabric v0.6採用的是PBFT,v1.0又推出PBFT的改進版本SBFT。這里再順便提一句,在可信環境下共識演算法一般使用傳統的分布式一致演算法PAXOS或者RAFT。
公有鏈使用BFT的一個例外是NEO,NEO使用了DBFT(delegated BFT)共識機制。DBFT共識機制下投票選出7個共識節點。這些代理節點是通過靜態選出的,並完全由項目方部署。這也是NEO被外界質疑過於中心化的原因。(參考: 早期公有鏈明星項目-NEO )
BFT演算法和公有鏈合適的結合點在於基於BFT的PoS共識演算法(BFT based PoS)。基於BFT的PoS共識演算法要點有:一,網路節點通過鎖定虛擬資產申請成為區塊鏈系統的驗證者(或礦工)。系統驗證者的數量是動態變化的。二,系統從當前驗證者中隨機選擇一個人作為區塊提案人。三,系統驗證者對區塊提案進行投票表決,投票可能要進行多輪才能達成共識。每個人的投票比重與鎖定的虛擬資產成比例。
基於BFT的PoS的典型例子是tendermint(Cosmos採用了tendermint作為共識核心)。
『玖』 共識演算法系列之一:私鏈的raft演算法和聯盟鏈的 pbft 演算法
對數據順序達成一致共識是很多共識演算法要解決的本質問題
Fabic的pbft演算法實現
現階段的共識演算法主要可以分成三大類:公鏈,聯盟鏈和私鏈
私鏈,所有節點可信
聯盟鏈,存在對等的不信任節點
私鏈:私鏈的共識演算法即區塊鏈這個概念還沒普及時的傳統分布式系統里的共識演算法,比如 zookeeper 的 zab 協議,就是類 paxos 演算法的一種。私鏈的適用環境一般是不考慮集群中存在作惡節點,只考慮因為系統或者網路原因導致的故障節點。
聯盟鏈:聯盟鏈中,經典的代表項目是 Hyperledger 組織下的 Fabric 項目, Fabric0.6 版本使用的就是 pbft 演算法。聯盟鏈的適用環境除了需要考慮集群中存在故障節點,還需要考慮集群中存在作惡節點。對於聯盟鏈,每個新加入的節點都是需要驗證和審核的。
公鏈:公鏈不僅需要考慮網路中存在故障節點,還需要考慮作惡節點,這一點和聯盟鏈是類似的。和聯盟鏈最大的區別就是,公鏈中的節點可以很自由的加入或者退出,不需要嚴格的驗證和審核。
在公有鏈中用的最多的是pow演算法和pos演算法,這些演算法都是參與者的利益直接相關,通過利益來制約節點誠實的工作,解決分布式系統中的拜占庭問題。拜占庭容錯演算法是一種狀態機副本復制演算法,通過節點間的多輪消息傳遞,網路內的所有誠實節點就可以達成一致的共識。
使用拜占庭容錯演算法不需要發行加密貨幣,但是只能用於私有鏈或者聯盟鏈,需要對節點的加入進行許可權控制;不能用於公有鏈,因為公有鏈中所有節點都可以隨意加入退出,無法抵擋女巫攻擊(sybil attack)
raft 演算法包含三種角色,分別是:跟隨者( follower ),候選人(candidate )和領導者( leader )。集群中的一個節點在某一時刻只能是這三種狀態的其中一種,這三種角色是可以隨著時間和條件的變化而互相轉換的。
raft 演算法主要有兩個過程:一個過程是領導者選舉,另一個過程是日誌復制,其中日誌復制過程會分記錄日誌和提交數據兩個階段。raft 演算法支持最大的容錯故障節點是(N-1)/2,其中 N 為 集群中總的節點數量。
國外有一個動畫介紹raft演算法介紹的很透徹,鏈接地址為: http://thesecretlivesofdata.com/raft/ 。這個動畫主要包含三部分內容,第一部分介紹簡單版的領導者選舉和日誌復制的過程,第二部分內容介紹詳細版的領導者選舉和日誌復制的過程,第三部分內容介紹的是如果遇到網路分區(腦裂),raft 演算法是如何恢復網路一致的。
pbft 演算法的提出主要是為了解決拜占庭將軍問題
要讓這個問題有解,有一個 十分重要的前提 ,那就是 信道必須是可靠的 。如果信道不能保證可靠,那麼拜占庭問題無解。關於信道可靠問題,會引出兩軍問題。兩軍問題的結論是,在一個不可靠的通信鏈路上試圖通過通信以達成一致是基本不可能或者十分困難的。
拜占庭將軍問題最早是由 Leslie Lamport 與另外兩人在 1982 年發表的論文《The Byzantine Generals Problem 》提出的, 他證明了在將軍總數大於 3f ,背叛者為f 或者更少時,忠誠的將軍可以達成命令上的一致,即 3f+1<=n 。演算法復雜度為 o(n^(f+1)) 。而 Miguel Castro (卡斯特羅)和 Barbara Liskov (利斯科夫)在1999年發表的論文《 Practical Byzantine Fault Tolerance 》中首次提出 pbft 演算法,該演算法容錯數量也滿足 3f+1<=n ,演算法復雜度為 o(n^2)。
首先我們先來思考一個問題,為什麼 pbft 演算法的最大容錯節點數量是(n-1)/3,而 raft 演算法的最大容錯節點數量是(n-1)/2 ?
對於raft演算法,raft演算法的的容錯只支持容錯故障節點,不支持容錯作惡節點。什麼是故障節點呢?就是節點因為系統繁忙、宕機或者網路問題等其它異常情況導致的無響應,出現這種情況的節點就是故障節點。那什麼是作惡節點呢?作惡節點除了可以故意對集群的其它節點的請求無響應之外,還可以故意發送錯誤的數據,或者給不同的其它節點發送不同的數據,使整個集群的節點最終無法達成共識,這種節點就是作惡節點。
raft 演算法只支持容錯故障節點,假設集群總節點數為n,故障節點為 f ,根據小數服從多數的原則,集群里正常節點只需要比 f 個節點再多一個節點,即 f+1 個節點,正確節點的數量就會比故障節點數量多,那麼集群就能達成共識。因此 raft 演算法支持的最大容錯節點數量是(n-1)/2。
對於 pbft 演算法,因為 pbft 演算法的除了需要支持容錯故障節點之外,還需要支持容錯作惡節點。假設集群節點數為 N,有問題的節點為 f。有問題的節點中,可以既是故障節點,也可以是作惡節點,或者只是故障節點或者只是作惡節點。那麼會產生以下兩種極端情況:
第一種情況,f 個有問題節點既是故障節點,又是作惡節點,那麼根據小數服從多數的原則,集群里正常節點只需要比f個節點再多一個節點,即 f+1 個節點,確節點的數量就會比故障節點數量多,那麼集群就能達成共識。也就是說這種情況支持的最大容錯節點數量是 (n-1)/2。
第二種情況,故障節點和作惡節點都是不同的節點。那麼就會有 f 個問題節點和 f 個故障節點,當發現節點是問題節點後,會被集群排除在外,剩下 f 個故障節點,那麼根據小數服從多數的原則,集群里正常節點只需要比f個節點再多一個節點,即 f+1 個節點,確節點的數量就會比故障節點數量多,那麼集群就能達成共識。所以,所有類型的節點數量加起來就是 f+1 個正確節點,f個故障節點和f個問題節點,即 3f+1=n。
結合上述兩種情況,因此 pbft 演算法支持的最大容錯節點數量是(n-1)/3
pbft 演算法的基本流程主要有以下四步:
客戶端發送請求給主節點
主節點廣播請求給其它節點,節點執行 pbft 演算法的三階段共識流程。
節點處理完三階段流程後,返回消息給客戶端。
客戶端收到來自 f+1 個節點的相同消息後,代表共識已經正確完成。
為什麼收到 f+1 個節點的相同消息後就代表共識已經正確完成?從上一小節的推導里可知,無論是最好的情況還是最壞的情況,如果客戶端收到 f+1 個節點的相同消息,那麼就代表有足夠多的正確節點已全部達成共識並處理完畢了。
3.演算法核心三階段流程
演算法的核心三個階段分別是 pre-prepare 階段(預准備階段),prepare 階段(准備階段), commit 階段(提交階段)
流程的對比上,對於 leader 選舉這塊, raft 演算法本質是誰快誰當選,而 pbft 演算法是按編號依次輪流做主節點。對於共識過程和重選 leader 機制這塊,為了更形象的描述這兩個演算法,接下來會把 raft 和 pbft 的共識過程比喻成一個團隊是如何執行命令的過程,從這個角度去理解 raft 演算法和 pbft 的區別。
一個團隊一定會有一個老大和普通成員。對於 raft 演算法,共識過程就是:只要老大還沒掛,老大說什麼,我們(團隊普通成員)就做什麼,堅決執行。那什麼時候重新老大呢?只有當老大掛了才重選老大,不然生是老大的人,死是老大的鬼。
對於 pbft 演算法,共識過程就是:老大向我發送命令時,當我認為老大的命令是有問題時,我會拒絕執行。就算我認為老大的命令是對的,我還會問下團隊的其它成員老大的命令是否是對的,只有大多數人 (2f+1) 都認為老大的命令是對的時候,我才會去執行命令。那什麼時候重選老大呢?老大掛了當然要重選,如果大多數人都認為老大不稱職或者有問題時,我們也會重新選擇老大。
四、結語
raft 演算法和 pbft 演算法是私鏈和聯盟鏈中經典的共識演算法,本文主要介紹了 raft 和 pbft 演算法的流程和區別。 raft 和 pbft 演算法有兩點根本區別:
raft 演算法從節點不會拒絕主節點的請求,而 pbft 演算法從節點在某些情況下會拒絕主節點的請求 ;
raft 演算法只能容錯故障節點,並且最大容錯節點數為 (n-1)/2 ,而 pbft 演算法能容錯故障節點和作惡節點,最大容錯節點數為 (n-1)/3 。
pbft演算法是通過投票來達成共識,可以很好的解決包括分叉等問題的同時提升效率。但僅僅比較適合於聯盟鏈私有鏈,因為兩兩節點之間通信量是O(n^2)(通過優化可以減少通信量),一般來說不能應用於超過100個節點。
pbft有解的前提是 信道必須是可靠的 ,存在的問題是 可擴展性(scalability)差
部分來自: https://blog.csdn.net/kojhliang/article/details/80270223
區塊鏈在設計上就是為了BFT