本文爲萬向區塊鏈技術中心研究組撰寫,文章嘗試對PBFT算法的正確性證實以及算法優化等內容做一個介紹。算法
本部分介紹PBFT算法的正確性證實。安全
PBFT算法提供的安全性(safety)的具體含義是,對於全部本地確認(commit locally)的客戶端請求來講,系統中全部正常副本節點都會就這些請求的消息序號達成一致。併發
上述的「達成一致」,其含義又分爲兩種:性能
同一視圖中的消息序號一致:對於全部在同一視圖中本地確認的客戶端請求來講,各正常副本節點就其消息序號會達成一致。
新舊視圖中的消息序號一致:對於在新舊視圖中本地確認的客戶端請求來講,各正常副本節點就其消息序號會達成一致。區塊鏈
接下來分別證實上述兩種「一致」是成立的。優化
1. 在同一視圖中,任何一個請求 m ,若是其已經本地確認過,也就是說,至少對於某一個正常副本節點 i 來講,prepared(m, v, n, i) 爲 true , 以前已經證實過,此時,對於任意的正常副本節點 j (j也能夠是 i) 來講,prepared(m’, v, n, j) 都爲 false 。這裏 m’ 是不一樣於 m 的另外一個請求,也就是說 D(m’) 不等於 D(m) 。這就意味着對於全部在同一視圖中本地確認的客戶端請求來講,各正常副本節點就其消息序號會達成一致,第一個性質成立。spa
2. 如今考慮存在視圖變動的狀況。首先,在視圖 v 中,對於任意一個請求 m 來講,若是其在 某個正常副本節點 i 完成了本地確認,假設其消息序號爲 n 。那麼,就有 committed(m, v, n) 爲 true 。 這也意味着存在一個節點集合R1, 其中至少含有 f+1 個正常副本節點,而且對於其中每個節點 i ,prepared(m, v, n, i) 爲 true。.net
而後,考慮系統最終變動視圖到 v' 的狀況。在從視圖 v 變動到 v' 的過程當中,此時變動沒有完成,正常副本節點在接收到 new-view 消息以前,不會接受視圖 v' 上的預準備消息。
可是,對於視圖 v 變動到 v'的任意一個有效的 new-view 消息來講,其中包含 2f+1 個有效的view-change 消息。這些消息來自不一樣的副本節點,記它們組成的集合爲R2。R1和R2至少有一個相同的元素,也就是相同的節點。否則的話,它們總的節點個數將爲(f+1) + (2f+1) = 3f+2,這與咱們假定的系統總節點個數 3f+1 不符。blog
所以,假設這個共同的正常副本節點爲 k 。對於請求 m 來講,只有可能存在下面兩種狀況:new-view 消息中,存在 view-change 消息,其中包含的最新穩定檢查點對應的消息序號大於 m 的序號 n 。new-view 消息中全部的 view-change 消息中包含的最新穩定檢查點對應的消息序號不大於m的序號n。get
對於第一種狀況,根據視圖變動協議,新視圖 v' 中,全部正常副本節點不會接受序號爲n或小於n的消息。
對於第二種狀況,m 將會被傳播到新視圖 v'中,由於根據視圖變動協議,min-s≤n。視圖變動完成後,在 v' 中,算法將針對編號爲 n 的請求 m 從新運行三階段協議。這就使得全部正常副本節點會達成一致,而不會出現下面這種狀況:
另外一個不一樣於 m 的請求 m' , 其在視圖 v 中分配的序號爲 n ,且在新視圖中 v' 完成本地確認。
綜合上面 1 和 2 的證實,就證實了算法在同一視圖和視圖變動過程當中,都會保證本地確認的請求的序號在全部正常副本節點中會達成一致,從而保證了算法的安全性(safety)。
對於PBFT算法來講,爲了保證系統的活性(liveness),當節點沒法執行客戶端請求時,須要變動到新的視圖。同時,視圖變動也須要進行合理控制,只在須要時才進行,不然頻繁的視圖變動會影響到系統的活性。這就須要保證如下兩點:
系統中至少 2f+1 個正常副本節點處於同一視圖中時,這種狀態儘量長時間地保持;
每次視圖變動時,上述時間間隔須要快速增加,好比以指數形式增加。
PBFT算法經過以下三種方法來保證上述兩點:
1. 爲了防止視圖變動太快開始,當一個節點發送 view-change 消息後,在等待接收 2f+1 個 view-change消息時,會同時啓動定時器,其超時時間設置爲 T。若是視圖變動沒有在 T 時間內完成,或者在新視圖中請求沒有在該時間間隔內完成,則會觸發新的視圖變動。此時,算法會調整超時時間,將其設置爲原來的兩倍,即 2T 。
2. 除了上述的定時器超時觸發節點發送 view-change 消息外,當其接收到來自 f+1 個不一樣節點的有效view-change 消息,而且變動的目標視圖大於節點當前視圖時,也會觸發節點發送 view-change 消息。這能夠防止節點過晚啓動視圖變動。
3. 基於上述第二點的規則,失效節點沒法經過故意發送 view-change 消息來觸發頻繁的視圖變動從而干擾系統的運行。由於失效節點最多隻能發送 f 條消息,達不到 f+1 的觸發條件。失效節點是主節點時,可能會觸發視圖變動,可是連續的視圖變動最多隻會是 f 個,以後主節點就是正常節點。所以,基於以上的規則,系統能夠保證活性。
本部分介紹PBFT算法的優化。這些優化方式應用於算法的正常操做中,能夠提高算法的性能,同時能夠保持系統的安全性和活性。
能夠採用三種方法減小系統通訊量:
1. 向客戶端發送回覆的消息摘要,而不是回覆的原始內容客戶端指定一個特定的副本節點,從該節點接收完整的回覆內容,而只從其餘全部節點處接收回復的摘要。經過判讀摘要與回覆的一致性以及對回覆計數,能夠確保接收到正確的回覆。若是客戶端接收不到正確結果,就會按正常流程從新請求系統,並接收不一樣節點的完整回覆。
2. 請求在副本節點prepared後,節點即試探性地執行請求,併發送結果。客戶端只要收到 2f+1 個匹配的結果,就能夠確保該結果的正確性。也就是說,該請求最終會確認(至少f+1 個正常副本節點的本地確認)。若是客戶端沒法獲得正確結果,就從新發送請求,系統執行正常流程。一個被試探性執行的請求,有可能在視圖變動過程當中被中斷,並被替換爲一個空請求。此時,已經執行過請求的節點能夠經過 new-view 消息中的最新的穩定檢查點或本地的檢查點來更新狀態(取決於哪一個序號更大)。
3. 針對只讀操做,客戶端將請求廣播到每個副本節點。各節點判斷請求確實爲只讀且知足條件後,直接執行請求,併發送回復到客戶端。客戶端收到 2f+1 個相同的回覆,即爲正確結果;不然客戶端以前設置的重發請求定時器將觸發超時,使得客
戶端重發請求,系統執行正常流程。
這種優化的前提條件是,副本節點在執行請求以前,需確保以前全部請求都已確認,而且被執行。
使用公鑰簽名的方式驗證消息存在以下不足:
相似於RSA這樣的簽名算法,簽名速度比較慢;
其餘公鑰密碼系統,如橢圓曲線公鑰密碼系統,雖然簽名更快,可是驗籤更慢。
PBFT算法實際上在正常流程中採用 MAC(Message Authentication Code,消息驗證碼) 認證消息,由於它具備以下優勢,使得算法相對於以前的算法性能提高了一個數量級以上:
MAC 計算速度快;
經過適當優化,能夠減小其長度;
經過對authenticator(vector of MAC)的使用,可使驗證時間爲常量,而生成時間只隨着節點數量線性增加。
具體來講,PBFT算法中使用 MAC 和公鑰簽名的具體場景是:
全部正常操做流程中使用 MAC 驗證消息;
視圖變動中的消息:view-change, new-view,以及出現錯誤時,使用公鑰簽名。這些場景的出現頻率相對較低,從而對算法的性能影響較小。
關聯閱讀: