Polkadot系列(二)——混合共識詳解

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"本文作者"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"夏立偉,陶勇星 "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"來自趣鏈科技數據網格實驗室BitXHub團隊,主要負責區塊鏈賬本互操作技術相關研究工作。"}]},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"導讀"},{"type":"text","text":":此文是Polkadot系列文章第2篇,Polkadot的混合共識詳解。當說到Polkadot的共識時,很多人的第一反應是Polkadot有很多的共識算法,有很多新鮮的名詞,由於Polkadot共識算法的數量較多、功能各異,很多人對Polkadot採用的共識算法有很多疑問,其中最容易混淆的是多種不同的共識算法之間如何協作的問題,本文接下來擬針對Polkadot的共識進行深度剖析。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Polkadot共識主要有三種"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"NPOS, BABE, GRANDPA"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","text":"接下來我們對這三種共識進行逐一的解釋"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":22}},{"type":"strong"}],"text":"NPOS"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":16}},{"type":"strong"}],"text":"什麼是NPOS共識"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Polkadot 中,中繼鏈上的驗證者需要分配到各個平行鏈,爲它們提供區塊鏈驗證能力,是 Polkadot 共享安全性的一部分,因此中繼鏈的驗證者對於整個Polkadot多鏈系統的安全性至關重要。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何公平安全地選舉出中繼鏈上的驗證者也就成了保障整個系統共享安全性的第一步,是不可或缺的一步。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"NPOS( Nominated Proof of Stake)共識算法就是用來選舉出能讓系統更安全,更高效的驗證者集合的。和傳統意義上的POS共識相比,NPOS算法結合了Polkadot鏈自身架構的一些特點,進行相應的優化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面看看NPOS是如何進行工作的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在說明NPOS之前,我們需要先回顧一下Polkadot中重要的兩種角色。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"▲ 驗證人"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"中繼鏈的全節點,中繼鏈會在驗證人池中通過隨機分組把驗證人指定給不同的平行鏈。驗證人會接受來自收集人打包的區塊並進行有效性驗證,然後結合共識算法對收集人提交的區塊進行確認。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"▲ 提名人"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Polkadot中數字貨幣DOT的持有人,它會選擇自己所信任的驗證人進行DOT質押,然後分享驗證人的收益。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Polkadot的選舉模型"},{"type":"text","text":"是建立在這兩種角色基礎上的。要成爲驗證人,必須先成爲驗證人候選人蔘加選舉的過程,而這個選舉過程中的“選民”就是提名人。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Polkadot的設計中,提名人數量在理論是可以不設置上限的,如果能夠讓更多的提名者參與到投票階段,那麼參與到選舉的資金量也就越大,整個系統就更加的安全;而對於驗證者來說,爲了區塊鏈的性能,不能太多(所有節點都能作爲驗證者的話,那就是比特幣採用的模式了),驗證者的數量由系統確定的固定值,這一點來說和POS共識是一致的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":16}},{"type":"strong"}],"text":"選舉模型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了明確選舉問題,Polkadot中將選舉驗證者集合的問題抽象爲一個數學的選舉問題:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"▲ "},{"type":"text","marks":[{"type":"strong"}],"text":"問題:"},{"type":"text","text":"m 個選民對 n 個候選者的情況下,選出最終的 t 爲當選者"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"(注:提名人可以有任意個,驗證者是有限個)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"問題的描述很簡單,但是如何做到讓系統更安全,會有不同的策略。Polkadot的設計哲學中,認爲選舉策略需要滿足下面的“三大原則”:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Balance:"},{"type":"text","text":" 驗證者在出塊時候的比重相同,因此該策略在Stake分配需要儘量平均,保證網絡的安全;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Support: "},{"type":"text","text":"該策略需要讓儘可能多的 Stake 資金參與進來。因爲提名者只負責選投哪些候選者,但是對於的 Stake具體分配給多少到哪個驗證者是沒有決定權的,這部分是NPOS算法通過計算來決定的。這也是NPOS和普通的POS共識中很大的不同之處;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Fair representation: "},{"type":"text","text":"Stake 多的提名者選投的驗證人更可能出現在驗證者集合中。"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"輸入:給定,其中是Nominator集合,是Validator候選者集合,是邊的集合,表示提名者投了候選者一票。同時給定向量 ,表示各個提名者各自的Stake數量,是選出的最終驗證者集合的大小。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 輸出:給定解,其中是最終選定的Validator,大小爲, 是提名者分配多少 Stake 到最終的Validator。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"限制條件:"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Balance: 給定,能夠給出一個 ,使得最小"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Support: 給定,能夠給出一個 ,使得最大"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Fair representation: proportional justified representation(PJR)規則"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" 任意一個 ,都不會存在一個提名者的子集,導致出現下面的情況:"}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/62/62448720e97467a3327a77bfa0e9d495.jpeg","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用較爲通俗的話來說就是不允許出現:存在某些中的提名者的stake 超過了總的staking的的比重,並且他們支持的人選有交集的超過個,但是他們支持的Validator的數量入選卻沒有超過個。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上述的問題在數學上就是一個最優化問題,很可惜這個選舉在數學上已經被證明是 NP完全問題,並不能在多項式時間內給出最優解。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以Polkadot給出了自己的一套解決方案,來繞過這個難解問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":16}},{"type":"strong"}],"text":"NPOS流程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上述推導的數學模型中,由於是NP完全問題,也就是說給出最優解的計算時間複雜度是無法確定在多項式時間內的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Polkadot給出了一個相對來說可行的方案。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不追求最優解,達到相對最優即可NP完全問題中給出可行解是很困難的,但是驗證已有解是簡單的,能在多項式時間內完全。所以驗證可行解的部分放在鏈上進行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"▲ 完整的流程如下:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/34/343212490a6a25b60e059bc7974e2883.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在提名者給出自己的投票之後,每一個候選者都可以給出自己對於上述選舉問題的一個可行解。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在上述這些可行解的集合中,利用鏈上的方案比較方案,按照之前的“三大原則”來比較這些方案,選取其中最優的方案最爲最後驗證人選舉結果,這樣就完成了一輪選舉。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":22}},{"type":"strong"}],"text":"BABE"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BABE的全稱是Blind Assignment for Blockchain Extension,BABE是一個用來出塊的引擎,類似於Ourobros Praos,一種PoS的協議。BABE算法是基於slots的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在Polkadot中每一個slot差不多6秒長的時間。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每個slot時間段中BABE會選出一個leader來出塊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"BABE中leader的選舉是通過一個隨機函數(VRF)來實現的,在每個slot階段,每一個節點會通過運算VRF函數來獲得一個數值,如果這個數值小於網絡中預先規定好的閾值,那麼節點就會認爲自己就是這個時間段的leader,於是節點就開始出塊了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"值得注意的是在上述的過程中,由於VRF函數是隨機生成數字的,所以可能造成在某一slot中沒有leader或者有多個節點算出自己的VRF值小於閾值進而產生多個leader的情況。我們依次分析兩種情況:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當沒有leader產生時,Polkadot就規定按照順序來決定誰是leader,這個順序是預先確定好的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當出現多個leader的時候,Polkadot允許多個節點都提交區塊,而最終區塊的確認則由GRANDPA來決定。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":22}},{"type":"strong"}],"text":"GRANDPA"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"GRANDPA則是用來做區塊確認的,在文章的第二部分我們有提到BABE將會對Polkadot的交易進行出塊,那麼這些出塊最終就是由GRANDPA來確定的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"像其他PBFT的衍生算法一樣,GRANDPA的時間複雜度也是"},{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"O(n²)"},{"type":"text","text":"。但是Polkadot之所以採用GRANDPA是因爲GRANDPA並不是每次只確認一個區塊,它每一次都會確定好幾個區塊來做確認"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"Idle(24peers),best:#664257(0x706c…76b7),finalized#664253"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"(0xe4ab…4d2a)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"Imported#664258(0xee71…6321)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"Idle(24peers),best:#664258(0xee71…6321),finalized#664256"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"(0x809a…a5d8)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面是Polkadot測試網絡的一段日誌,可以看到一次確認區塊高度從664253到了664256,所以GRANDPA一次性確認了三個區塊。這樣的話跟一次性只確認一個相比,GRANDPA的效率要比其他PBFT的衍生算法要高出很多。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"▲ "},{"type":"text","text":"下面介紹一下"},{"type":"text","marks":[{"type":"strong"}],"text":"GRANDPA的具體流程"},{"type":"text","text":":"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1. 一個主節點廣播之前一輪確認後的區塊高度;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2. 等待網絡延遲以後,每個節點都廣播他們認爲的可以被確認的最高的區塊(pre-vote);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3. 每個節點對步驟2接受到的區塊集進行計算,算出他們認爲的能夠被確認的最高區塊,並且將結果廣播出去(pre-commit);"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"4. 當節點接收到足夠的pre-commit的消息能夠確認區塊後就會形成commit的消息,一般認爲大於2/3就可以被確認了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上述就是GRANDPA確認區塊的主要流程。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們需要擔心的是在步驟2的pre-vote過程中可能會有作惡的節點投票了兩個區塊並且廣播出去,這樣的話就有可能產生鏈的分叉行爲。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Polkadot爲了防止這種情況的發生使用了一個叫做"},{"type":"text","marks":[{"type":"strong"}],"text":"Account Safety"},{"type":"text","text":"的方式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果當網絡中出現了要分叉的commit信息時,Polkadot的節點會馬上採取Account Safety的機制。每個節點都會詢問其他節點他們所看到的pre-vote的情況,節點都會回覆他們收到的信息,這樣就很容易檢查到有哪些惡意節點投了兩個區塊。最後這些被抓到的作惡節點將會被踢出共識網絡,永遠不能進入。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讓我們回到BABE,通過結合BABE和GRANDPA我們可以看到在出塊的時候Polkadot採用BABE出塊,此時節點之間只要發送一次塊信息即可,這樣的話時間複雜度僅僅是"},{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"O(n)"},{"type":"text","text":",在出塊之後節點之間再採用GRANDPA進行塊確認,此時由於確認階段節點之間要通過二次確認來保證確認塊結果的一致性,時間複雜度是"},{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"O(n²)"},{"type":"text","text":",不過由於是多個塊一次性進行確認,所以兩者結合的混合共識是非常高效的,比普通的PBFT共識要高效很多。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":22}},{"type":"strong"}],"text":"結語"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面三種就是我們向大家介紹的Polkadot的共識算法,可以看到NPOS主要是爲了選取Polkadot的共識節點,BABE和GRANDPA通過混合來高效的進行區塊鏈的出塊和確認。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣的混合共識比傳統的PBFT共識速度更快,並且在速度更快的基礎上並沒有丟失掉安全性。將出塊和確認區塊兩個階段分開並且使用不同的算法是在區塊鏈共識中值得學習的地方。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過這三種算法,Polkadot可以說在一定程度上高效的實現了Polkadot上區塊鏈的共識算法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"參考文獻:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"[1] Ouroboros Praos: An adaptively-secure, semi-synchronous proof-of-stake blockchain Bernardo David , Peter Gaˇzi , Aggelos Kiayias November 14, 2017"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":"br"}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章