1. 程式人生 > >區塊鏈快速入門(四)——BFT(拜占庭容錯)共識算法

區塊鏈快速入門(四)——BFT(拜占庭容錯)共識算法

亂序 間接 要求 back 保留 vpd 過程 能耗 所有

區塊鏈快速入門(四)——BFT(拜占庭容錯)共識算法

一、BFT簡介

1、拜占庭將軍問題簡介

拜占庭將軍問題(Byzantine Generals Problem)是Leslie Lamport(2013年的圖靈獎得主)用來為描述分布式系統一致性問題(Distributed Consensus)在論文中抽象出來一個著名的例子。
拜占庭將軍問題簡易的非正式描述如下:
拜占庭帝國想要進攻一個強大的敵人,為此派出了10支軍隊去包圍這個敵人。這個敵人雖不比拜占庭帝國,但也足以抵禦5支常規拜占庭軍隊的同時襲擊。基於一些原因,這10支軍隊不能集合在一起單點突破,必須在分開的包圍狀態下同時進攻。他們任一支軍隊單獨進攻都毫無勝算,除非有至少6支軍隊同時襲擊才能攻下敵國。他們分散在敵國的四周,依靠通信兵相互通信來協商進攻意向及進攻時間。困擾這些將軍的問題是,他們不確定他們中是否有叛徒,叛徒可能擅自變更進攻意向或者進攻時間。在這種狀態下,拜占庭將軍們能否找到一種分布式的協議來讓他們能夠遠程協商,從而贏取戰鬥?這就是著名的拜占庭將軍問題。

拜占庭將軍問題中並不去考慮通信兵是否會被截獲或無法傳達信息等問題,即消息傳遞的信道絕無問題。Lamport已經證明了在消息可能丟失的不可靠信道上試圖通過消息傳遞的方式達到一致性是不可能的。所以,在研究拜占庭將軍問題的時候,假定信道是沒有問題的,然後去做一致性和容錯性相關研究。

2、兩將軍問題

拜占庭問題前,就已經存在兩將軍問題(Two Generals Paradox):兩個將軍要通過信使來達成進攻還是撤退的約定,但信使可能迷路或被敵軍阻攔(消息丟失或偽造),如何達成一致?
根據FLP不可能原理,兩將軍問題無通用解。

3、BFT簡介

BFT(Byzantine Fault Tolerance),即拜占庭容錯,是分布式計算領域的容錯技術,拜占庭容錯來源於拜占庭將軍問題。拜占庭將軍問題是對現實世界的模型化,由於硬件錯誤、網絡擁塞或中斷以及遭到惡意***等原因,計算機和網絡可能出現不可預料的行為。拜占庭容錯技術被設計用來處理現實存在的異常行為,並滿足所要解決的問題的規範要求。

區塊鏈網絡環境符合拜占庭將軍問題模型,有運行正常的服務器(忠誠的拜占庭將軍),有故障的服務器,還有破壞者的服務器(叛變的拜占庭將軍)。共識算法的核心是在正常的節點間形成對網絡狀態的共識。
通常,發生故障的節點被稱為拜占庭節點,而正常的節點為非拜占庭節點。
拜占庭容錯系統是一個擁有n臺節點的系統,整個系統對於每一個請求,滿足以下條件:
  A、所有非拜占庭節點使用相同的輸入信息,產生同樣的結果;
  B、如果輸入的信息正確,那麽所有非拜占庭節點必須接收這個信息,並計算相應的結果。
拜占庭系統普遍采用的假設條件包括:
  A、拜占庭節點的行為可以是任意的,拜占庭節點之間可以共謀;
  B、節點之間的錯誤是不相關的;
  C、節點之間通過異步網絡連接,網絡中的消息可能丟失、亂序並延時到達,但大部分協議假設消息在有限的時間裏能傳達到目的地;
  D、服務器之間傳遞的信息,第三方可以嗅探到,但是不能篡改、偽造信息的內容和驗證信息的完整性。
原始的拜占庭容錯系統由於需要展示其理論上的可行性而缺乏實用性。另外,還需要額外的時鐘同步機制支持,算法的復雜度也是隨節點增加而指數級增加。

二、PBFT算法

1、PBFT算法簡介

PBFT(Practical Byzantine Fault Tolerance),即實用拜占庭容錯算法,由Miguel Castro和Barbara Liskov在1999年發表的論文《Practical Byzantine Fault Tolerance and Proactive Recovery》中提出。PBFT算法可以工作在異步環境中,並且通過優化解決了原始拜占庭容錯算法效率不高的問題,將算法復雜度由指數級降低到多項式級,使得拜占庭容錯算法在實際系統應用中變得可行,目前已得到廣泛應用。PBFT算法可以在失效節點不超過總數1/3的情況下同時保證Safety和Liveness。
PBFT 算法采用密碼學相關技術(RSA 簽名算法、消息驗證編碼和摘要)確保消息傳遞過程無法被篡改和破壞。

2、PBFT算法原理

PBFT是一種狀態機副本復制算法,即服務作為狀態機進行建模,狀態機在分布式系統的不同節點進行副本復制。每個狀態機的副本都保存了服務的狀態,同時也實現了服務的操作。將所有的副本組成的集合使用大寫字母R表示,使用0到|R|-1的整數表示每一個副本。為了描述方便,通常假設故障節點數為f個,整個服務節點數為|R|=3f+1個,f是有可能失效的副本的最大個數。盡管可以存在多於3f+1個副本,但額外的副本除了降低性能外不能提高可靠性。
所有的副本在一個被稱為視圖(View)的輪換過程中運作。在某個視圖中,一個副本作為主節點(primary),其它的副本節點作為備份節點(backups)。視圖是連續編號的整數。主節點由公式p = v mod |R|計算得到,v是視圖編號,p是副本編號,|R|是副本集合的個數。當主節點失效的時候就需要啟動視圖輪換過程。
PBFT算法實現流程如下:
技術分享圖片
(1)REQUEST
客戶端C向主節點p發送


<REQUEST, o, t, c>

請求。
o:請求的具體操作
t:請求時客戶端追加的時間戳
c:客戶端標識。
REQUEST: 包含消息內容m,以及消息摘要d(m)。
客戶端對請求進行簽名。
(2)PRE-PREPARE
主節點收到客戶端的請求,需要對客戶端請求消息簽名是否正確進行校驗。
非法請求則丟棄。正確請求,分配一個編號n,編號n主要用於對客戶端的請求進行排序。然後廣播一條


<<PRE-PREPARE, v, n, d>,? m>

消息給其它副本節點。
v:視圖編號
d客戶端消息摘要
m:消息內容


<PRE-PREPARE, v, n, d>

進行主節點簽名。
n是要在某一個範圍區間內的[h, H]。
(3)PREPARE
副本節點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中,用於視圖輪換過程中恢復未完成的請求操作。
PREPARE階段如果發生視圖輪換會導致丟棄PREPARE階段的請求。
(4)COMMIT
主節點和副本節點收到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消息到日誌中,用於視圖輪換過程中恢復未完成的請求操作。記錄其它副本節點發送的PREPARE消息到log中。
COMMIT階段用來確保網絡中大多數節點都已經收到足夠多的信息來達成共識,如果COMMIT階段發生視圖輪換,會保存原來COMMIT階段的請求,不會達不成共識,也不會丟失請求編號。

(5)REPLY
主節點和副本節點收到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中。
### 3、PBFT算法的垃圾回收
為了確保在視圖輪換的過程中,能夠恢復先前的請求,每一個副本節點都記錄一些消息到本地的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發生變化,再繼續前進。

4、PBFT算法的視圖輪換

如果主節點作惡,可能會給不同的請求編上相同的序號,或者不去分配序號,或者讓相鄰的序號不連續。備份節點應當有職責來主動檢查這些序號的合法性。如果主節點掉線或者作惡不廣播客戶端的請求,客戶端設置超時機制,超時的話,向所有副本節點廣播請求消息。副本節點檢測出主節點作惡或者下線,發起視圖輪換協議。
副本節點向其它節點廣播


<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消息集合的選取規則如下:
A、選取V中最小的stable checkpoint編號min-s,選取V中prepare消息的最大編號max-s。
B、在min-s和max-s之間,如果存在P消息集合,則創建


<<PRE-PREPARE, v+1, n, d>, m>

消息。否則創建一個空的PRE-PREPARE消息,即:


<<PRE-PREPARE, v+1, n, d(null)>, m(null)>

, m(null)為空消息,d(null)為空消息摘要。
副本節點收到主節點的NEW-VIEW消息,驗證有效性,有效的話,進入v+1狀態,並且開始O中的PRE-PREPARE消息處理流程。

5、PBFT算法的優缺點

PBFT算法的優點:
PBFT算法具有高交易通量和吞吐量,高可用性,易於理解。
PBFT算法的缺點:
A、計算效率依賴於參與協議的節點數量,由於每個副本節點都需要和其它節點進行P2P的共識同步,因此隨著節點的增多,性能會下降的很快,但在較少節點的情況下可以有不錯的性能,並且分叉的幾率很低,不適用於節點數量過大的區塊鏈,擴展性差。
B、系統節點是固定的,無法應對公有鏈的開放環境,只適用於聯盟鏈或私
有鏈環境。
C、PBFT算法要求總節點數n>=3f+1(其中,f代表作惡節點數)。系統的失效節點數量不得超過全網節點的1/3,容錯率相對較低。

6、PBFT算法的應用場景

PBFT算法的節點數量是固定的,節點身份提前確定,無法動態添加或刪除,只能適用於節點數目固定的聯盟鏈或私有鏈場景中。
PBFT在很多場景都有應用,在區塊鏈場景中,一般適合於對強一致性有要求的私有鏈和聯盟鏈場景,但如果能夠結合DPOS節點代表選舉規則,也可以應用於公有鏈,並且可以在一個不可信的網絡裏解決拜占庭容錯問題。在Hyperledger Fabric項目中,共識模塊被設計成可插拔的模塊,支持像PBFT、Raft等共識算法。

三、POW算法

1、POW算法簡介

POW(Proof of Work),即工作量證明,也稱挖礦。工作量證明通過計算來猜測一個數值(nonce),使得拼湊上交易數據後內容的Hash值滿足規定的上限。由於Hash難題在目前計算模型下需要大量的計算,可以保證在一段時間內,系統中只能出現少數合法提案。如果能夠提出合法提案,證明提案者確實已經付出了一定的工作量。
哈希現金是一種工作量證明機制,是Adam Back在1997年發明的,用於抵抗郵件的拒絕服務***及垃圾郵件網關濫用。

2、POW算法原理

工作量證明的主要特征是客戶端需要做一定難度的工作得出一個結果,驗證方卻很容易通過結果來檢查出客戶端是不是做了相應的工作。工作量證明方案的一個核心特征是不對稱性:工作對於請求方是適中的,對於驗證方則是易於驗證的。
技術分享圖片
給定一個基本字符串,在基本字符串後面添加一個叫做nonce的整數值,對變更後(添加nonce)的字符串進行SHA256哈希運算,如果得到的哈希結果(以16進制的形式表示)是以某個字符串(如"0000")開頭的,則驗證通過。為了達到工作量證明的目標,需要不停的遞增nonce值,對得到的新字符串進行SHA256哈希運算。
由於給定的基本字符串在不同的場合並不確定,對於不同的基本字符串和nonce的組合,要使用SHA256計算得到某個字符串開頭Hash值的計算次數並不確定,但會是一個符合統計學規律的概率事件。
按照規則,預期大概要進行2^16 次嘗試(哈希值的偽隨機特性可以做概率估算),才能得到4個前導0的哈希散列。

3、比特幣的POW實現

比特幣區塊由區塊頭和該區塊所包含的交易列表組成。區塊頭大小為80字節,其構成包括:
   4字節:版本號
   32字節:上一個區塊的哈希值
   32字節:交易列表的Merkle根哈希值
   4字節:當前時間戳
   4字節:當前難度值
   4字節:隨機數Nonce值
   80字節長度的區塊頭,即為比特幣Pow算法的輸入字符串。
  交易列表附加在區塊頭之後,其中第一筆交易為礦工獲得獎勵和手續費的特殊交易。
工作量證明過程,即為不斷調整Nonce值,對區塊頭做雙重SHA256哈希運算,使得結果滿足給定數量前導0的哈希值的過程,其中前導0的個數,取決於挖礦難度,前導0的個數越多,挖礦難度越大。
每創建2016個塊後將計算新的難度,此後的2016個塊使用新的難度。計算步驟如下:
  A、找到前2016個塊的第一個塊,計算生成這2016個塊花費的時間。
即最後一個塊的時間與第一個塊的時間差。時間差不小於3.5天,不大於56天。
  B、計算前2016個塊的難度總和,即單個塊的難度x總時間。
  C、計算新的難度,即2016個塊的難度總和/14天的秒數,得到每秒的難度值。
  D、要求新的難度,難度不低於參數定義的最小難度。

4、POW算法的優缺點

POW算法的優點:
A、完全去中心化
B、節點自由進出
C、安全性高
POW算法的缺點:
A、記賬權向資本集中
B、挖礦造成大量的資源浪費。
C、網絡性能太低,需要等待多個確認,容易產生分叉,區塊的確認共識達成的周期較長,不適合商業應用。

5、POW算法的應用場景

POW共識機制用在了大部分挖礦的區塊鏈項目,比如BTC、ETH、LTC。

四、POS算法

1、POS算法簡介

POS(Proof of Stake),即權益證明,是POW的一種升級共識機制,根據每個節點所占代幣的比例和時間,等比例的降低挖礦難度,從而加快找隨機數的速度。
鑒於POW的缺陷,2012年Sunny King提出了POS,並基於POW和POS的混合機制發布了點點幣PPCoin。

2、POS算法原理

POS原理的核心概念為幣齡,即持有貨幣的時間。例如有10個幣、持有90天,即擁有900幣天的幣齡。
  使用幣即意味著幣齡的銷毀。
  在POS中有一種特殊的交易稱為利息幣,即持有人可以消耗幣齡獲得利息,同時獲得為網絡產生區塊以及POS造幣的優先權。
POW通過算力證明自己有資格寫區塊鏈,而PoS通過擁有的幣齡來證明自己有資格寫區塊鏈。

3、POS算法的優缺點

POS算法的優點:
A、不消耗大量算力挖礦,節省能耗。
B、在一定程度上縮短了共識達成的時間
C、防作弊。
POS算法的缺點:
A、本質仍然需要挖礦,未解決商業應用的痛點
B、極端的情況下會帶來中心化的結果

4、點點幣的POS實現

點點幣的POS證明計算公式為:
  proofhash < 幣齡x目標值
  展開如下:
  hash(nStakeModifier + txPrev.block.nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime) < bnTarget x bnCoinDayWeight
  其中proofhash,對應一組數據的哈希值,即hash(nStakeModifier + txPrev.block.nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime)。
  幣齡即bnCoinDayWeight,即幣天,即持有的幣數乘以持有幣的天數,此處天數最大值為90天。
  目標值,即bnTarget,用於衡量POS挖礦難度。目標值與難度成反比,目標值越大、難度越小;反之亦然。
  因此,持有的幣天越大,挖到區塊的機會越大。

五、DPOS算法

1、DPOS算法簡介

DPOS(Delegated Proof of Stake),即股份授權證明算法,是在POW及POS基礎上誕生的一種新型共識算法,2014年4月由Bitshares的首席開發者Dan Larimer (現為EOS CTO)提出並應用。DPOS既能解決POW在挖礦過程中產生的DPOS大量能源過耗的問題,也能避免POS權益分配下可能產生的信任天平偏頗的問題。
DPOS是由被社區選舉的可信賬戶(超級節點,比如得票數前101位可以成為)來創建區塊。比如選出101個超級節點,即101個礦池,超級節點之間的權利是完全相等的。普通的持幣者可以隨時通過投票更換超級節點(礦池),DPOS的去中心化不是每個持幣者就有直接的股份權益,而是需要間接的投票權力,來保證被推選出來的超級節點不作惡,同時也可以自己拉選票成為超級節點或者備用超級節點。

2、DPOS算法原理

DPOS算法的基本原則:
A、持股人依據所持股份行使表決權,而不是依賴挖礦競爭記賬權。
B、最大化持股人的盈利。
C、最小化維護網絡安全的費用。
D、?最大化網絡的效能。
E、?最小化運行網絡的成本 (帶寬、CPU等),在不浪費大量電力的情況下實現網絡的安全穩定。
在DPOS共識算法中,區塊鏈的正常運轉依賴於超級節點,超級節點的職責主要有:
A、提供一臺服務器節點,保證節點的正常運行;
B、節點服務器收集網絡裏的交易;
C、節點驗證交易,把交易打包到區塊;
D、節點廣播區塊,其它節點驗證後把區塊添加到自己的數據庫;
E、帶領並促進區塊鏈項目的發展;
DPOS算法運行機制如下:
A、所有持幣者先選出超級節點負責簽署區塊
B、DPOS的規則是最長鏈勝出,每個超級節點必須按照生產排程,輪流產生區塊。假設排程排定A、B、C分別輪流生產區塊,在一定時間內產生的區塊如下:
技術分享圖片
C、如果惡意節點生產了分叉區塊,假設A、C都是誠實的節點,只有B節點是惡意的,由於B產生區塊的速度(每個周期生產一個區塊)慢於A、C合力產生區塊的速度(每個周期生產一個區塊),根據最長鏈勝出的規則,誠實的節點還是會勝出。
技術分享圖片
D、同一個節點要產生重復兩個區塊的速度也要慢於誠實節點合作產生區塊的速度,所以最長鏈勝出規則會保證誠實節點的鏈會勝出。
E、如果A,B,C三個超級節點的網絡出現碎片化,各自為政的情況。在短期內的確可能三鏈並行,但一旦網絡連接恢復,短鏈自然會向最長鏈回歸。超級節點數量為奇數,所以兩大派系勢均力敵僵持不下的情況不會維持太久,最終勢必會有其中一方的鏈更長。
技術分享圖片

3、DPOS對惡意節點的懲罰

註冊成為候選超級節點需要支付一筆保證金(約10 XTS),通常擔任超級節點約兩周後才可達到損益平衡,因此促進了受托人的穩定性,確保至少會挖滿兩周的礦。
DPOS對惡意節點的懲罰為:不按排程產生區塊的超級節點將在下一輪被投票剔除,被沒收繳納的保證金。
惡意節點在短期內是能夠作惡的,惡意的區塊只是短時間保留而已,很快超級節點之間會回歸誠實節點達成的共識,制造出最長鏈,向沒有作惡區塊的最長鏈回歸。

4、DPOS算法的優缺點

DPOS算法的優點:
A、能耗優勢,網絡運行成本低。
B、理論上更加去中心化。
C、較快的確認速度。出塊速度秒級,交易確認分鐘級。
DPOS算法的缺點:
A、壞節點不能被及時處理,只有經過選舉才能清除壞節點。
B、小散投票積極性不高。
C、依賴代幣

5、DPOS算法的應用場景

比特股(Bitshare)是一類采用DPOS機制的密碼貨幣,通過引入一個技術民主層來減少中心化的負面影響。
DPOS系統任然存在中心化,但中心化是受到控制的,超級節點由普通持幣者選舉產生。DPOS通過保留持幣者的控制權,從而使系統去中心化。

區塊鏈快速入門(四)——BFT(拜占庭容錯)共識算法