PPIO 是爲開發者打造的去中心化存儲與分發平臺,讓數據更便宜、更高速、更隱私。官方網站是
pp.io。
在以前的分享中,咱們有總體介紹過 Tendermint 實現跨鏈的整個流程,以及他的易使用,易理解,高性能的相關特色(可參考以前的文章《Tendermint 介紹及實戰分析》)。而且簡要的介紹了Tendermint 共識算法,狀態機複製及 ABCI 接口的相關知識。基於上次的分享,今天咱們從根本原理上,來着重剖析 Tendermint 業務邏輯中最複雜,也是最重要的環節——共識算法。算法
咱們知道分佈式一致性算法通常能夠分爲兩類:拜占庭容錯和非拜占庭容錯。非拜占庭容錯算法如 Paxos, Raft 等在當前的分佈式系統中已經普遍使用,而拜占庭容錯算法的實際應用範圍相對來講小不少(特別是在區塊鏈問世以前)。Tendermint 屬於拜占庭容錯算法,它針對傳統的PBFT算法作了優化,只須要有兩輪投票便可達成共識,目前 Tendermint 算法主要應用在區塊鏈系統中。
Round-based協議
首先咱們先說一下Round-based協議。在Tendermint中一共有三種類型的投票:prevote,precommit和commit。當一個block被全網絡commit的話,意味着這個block已經被全網超過2/3的Validator簽名並廣播了。
vote數據結構以下:
在鏈達到一個新的 Height 時候,系統會運行一個 round-based 協議來決定下一個block。round-based 協議由如下三個步驟構成:proposal,prevote,precommit。以及兩個特殊步驟:commit,NewHeight。其中 propose,prevote 和 precommit 會分別佔用整個 round 1/3時間。每一 round 的時間會比上一 round 的時間長一點,這是爲了讓網絡在部分同步的狀況下最終達成一致性共識。
round-based 協議運行過程以下:
round-based 協議是一個狀態機,主要有 NewHeigh -> Propose -> Prevote -> Precommit -> Commit 一共 5 個狀態。上述每一個狀態都被稱爲一個 Step。首尾的 NewHeigh 和 Commit ,這兩個 Steps 被稱爲特殊的 Step。而中間循環三個 Steps 則被稱爲一個 Round,是共識階段,也是算法的核心原理所在。一個塊的最終提交(Commit)可能須要多個 Round 過程,這是由於有許多緣由可能會致使當前 Round 不成功(好比出塊節點 Offline,提出的塊是無效塊,收到的 Prevote 或者 Precommit 票數不夠 +2/3 等等)。出現這些狀況的話,解決方案就是移步到下一輪,或者增長 timeout 時間。
當區塊鏈達到一個新的高度時進入 NewHeight 階段。接下來 Propose 階段會提交一個 proposal ,prevote 階段會對收到的 proposal 進行 prevote 投票。在 precommit 階段收集到+⅔ prevote 投票後,對 block 進行 precommit 投票。若是收集到+⅔ precommit 投票後則進入 commit 階段,若是沒有收集到+⅔ precommit 投票,會再次進入 propose 階段。在共識階段期間若是收到+⅔ commit 投票那麼直接進入 commit 階段。
以上就是算法運行的總體過程,接下來分階段來闡述各個階段。
Proposal
在每一輪開始前會經過 round-robin 方式選出一個 proposer,選出的 proposal 會提交這一輪的 proposal。proposer 的選擇規則請查看以前的一篇文章《
出塊節點選擇》
proposal 的數據結構以下:
Prevote
在 Prevote 開始階段,每一個 Validator 會判斷本身是否鎖定在上一輪的 proposed 區塊上,若是鎖定在以前的 proposal 區塊中,那麼在本輪中繼續爲以前鎖定的 proposal 區塊簽名並廣播 prevote 投票。不然爲當前輪中接收到的 proposal 區塊簽名並廣播prevote 投票。若是因爲某些緣由當前 Validator 並無收到任何 proposal 區塊,那麼簽名並廣播一個空的 prevote 投票。
Precommit
在 precommit 開始階段,每一個 Validator 會判斷,若是收集到了超過 2/3 prevote 投票,那麼爲這個區塊簽名並廣播 precommit 投票,而且當前 Validator 會鎖定在這個區塊上,同時釋放以前鎖定的區塊。。一個 Validator 一次只能鎖定在一個區塊上。若是一個 Validator 收集到超過2/3空區塊(nil)的 prevote 投票,那麼釋放以前鎖定的區塊。處於鎖定狀態的 Validator 會爲鎖定的區塊收集 prevote 投票,並把這些投票打成包放入 proof-of-lock 中,proof-of-lock 會在以後的propose階段用到。若是一個 Validator 沒有收集到超過2/3的 prevote 投票,那麼它不會鎖定在任何區塊上。這裏,介紹一個重要概念:PoLC,全稱爲 Proof of Lock Change,表示在某個特定的高度和輪數(height, round),對某個塊或 nil (空塊)超過總結點 2/3 的 Prevote 投票集合。簡單來講 PoLC 就是 Prevote 的投票集。
在 precommit 階段後期,若是 Validator 收集到超過2/3的 precommit 投票,那麼 Validator 進入到 commit 階段。不然進入下一輪的 propose 階段。
Commit
commit 階段分爲兩個並行的步驟:
-
Validator 收到了被全網 commit 的區塊,Validator 會爲這個區塊廣播一個commit 投票。
-
Validator 須要爲被全網絡precommit的區塊,收集到超過 ⅔ commit投票。
一旦兩個條件所有知足了,節點會將 commitTime 設置到當前時間上,而且會進入NewHeight 階段。
在整個共識過程的任何階段,一旦節點收到超過⅔ commit 投票,那麼它會馬上進入到commit 階段。
爲何不會分叉?
若是小於1/3節點是拜占庭節點(若是大於等於1/3,那麼共識就無法達成了)。當validator commit 了區塊 B,那麼表示有大於2/3的節點在R輪投了 precommit,這表示至少有大於1/3節點(大於1/3節點哪兒來的呢?就是大於2/3減去小於⅓。爲何是這麼算呢?
有人說不是有大於2/3的節點投了 precommit ,那麼這些人不都是誠實的節點嗎?固然不是了,拜占庭節點的意思它工做隨性,有時候正確有時候失敗。假設這個時候全部的拜占庭節點正確的工做了,因此都算在在+2/3節點內,因此這麼算了)被 lock在了 R‘>R。若是這個時候有針對同一區塊高度的投票,那麼因爲這+1/3節點被 lock在了 R’ 輪,因此不會有+2/3的節點投 prevote,也就不會在同一高度達成一個新的共識區塊,因此就不會分叉。
因此 Tendermint 不分叉是基於它是 BFT 共識,而後加上 PoLC 共同完成。
今天咱們帶你們一塊兒深刻學習了,Tendermint 中的共識算法部分。重點介紹了 round-based 協議運行過程,以及在運行過程當中 Propose 、 Prevote 、Precommit 和 Commit 環節的具體實現步驟。相信經過這兩期文章,你們應該對 Tendermint 技術有了更深刻的瞭解。
從此咱們還會和你們探討更多區塊鏈技術方面的知識,若是您想更進一步的和咱們一塊兒學習探索,就快來關注 PPIO 公衆號,加入 PPIO 開發者社區或 Discord 羣組,和咱們一塊兒創造精彩。
想了解更多有關 PPIO 的信息,能夠移步官網:pp.io
若是你想更進一步瞭解項目,歡迎加入咱們的微信討論羣,
後臺
回覆「
PPIO討論羣」 獲取入羣二維碼