016 | 漫談區塊鏈共識機制

Keegan小鋼發表於2019-02-02

原創文章,轉載請註明:轉載自Keegan小鋼

並標明原文連結:http://keeganlee.me/post/blockchain/20180425

微信訂閱號:keeganlee_me

寫於2018-04-25


專欄地址:xiaozhuanlan.com/fullstack


共識機制是區塊鏈的一個核心特徵,是保證區塊鏈系統在分散式架構下的一致性方案。目前主流的也有好多種共識演算法:POW、POS、DPOS、RCP、PBFT、DBFT 等等。網上已經充斥了很多對這些共識演算法的簡單介紹,但基本流於表面而缺少深入的講解,從而讀者們也很難理解到這些共識機制背後的核心原理。而本文將以深入淺出的方式講解區塊鏈共識機制,但由於篇幅有限,因此,只會講解最重要的兩種區塊鏈的共識機制,即比特幣和以太坊的共識機制。

比特幣共識機制

比特幣是區塊鏈的第一個應用,也是第一個實現了共識機制的,因此,要理解區塊鏈共識機制,自然也要先從比特幣共識機制開始。另外,雖然很多文章都提到比特幣的共識機制為 POW(Proof of Work,工作量證明),但實際上,POW 只是整個比特幣共識機制中的一部分,雖然是核心的那部分,但卻不是全部。其實,比特幣的分散式共識是由網路節點的 4 種獨立過程相互作用而達成的:

  • 每個全節點基於一份長長的判斷標準清單對每個交易進行獨立驗證
  • 每個挖礦節點獨立將多個交易打包進新區塊,通過完成 POW 演算法的驗算
  • 每個節點獨立驗證新區塊並組裝進區塊鏈
  • 每個節點獨立選擇最長鏈,即在 POW 機制下累計工作量最多的那條鏈

先說第一種過程,對交易的獨立驗證。每個節點收到每一個交易之後,都會先根據一份很長的判斷標準清單對該交易進行有效性校驗,包括但不限於校驗交易的語法和資料結構是否正確、輸入和輸出是否為空、輸入總額是否小於輸出總額、每一個輸入所引用的輸出是否已經被消費,等等。如果該交易通過所有驗證,則可以說明該交易是有效的,那麼,該節點就會將該交易放入本地的交易池(或稱記憶體池),並將該交易廣播給其他相臨的節點。如果沒通過驗證,則會廢棄該交易,也不會將其廣播出去。其他節點接收到該交易後,也各自做同樣的獨立校驗,校驗為交易有效之後,同樣也放入各節點自己的交易池,並繼續廣播給其他節點。所以,理論上來說,無效的交易一開始就會被廢棄,而有效的交易最終會到達整個網路所有節點,並被每個全節點所儲存,即全網達成了“該交易有效”的共識。

接著,再來聊聊第二種過程,瞭解有效的交易是如何被打包進區塊的。經過一段時間後,一般是 10 分鐘左右,每個節點的交易池裡會收集到很多有效但還未確認的交易,這些交易會組裝成一顆 Merkle Tree。關於 Merkle Tree 的結構,我們在之前的文章《014|從微觀到巨集觀理解區塊鏈》已經講過,這裡就不贅述了。不過,組裝進 Merkle Tree 的第一筆交易是比較特殊的,這是一筆創幣交易,也叫 Coinbase 交易,新的比特幣就是從該筆交易產生的。這筆交易是由節點自己建立的,並將挖礦獎勵支付到礦工自己的地址,挖礦獎勵包括新建立的比特幣和打包進該區塊所有交易的手續費總額。組裝好 Merkle Tree 之後,就得到 Merkle Root,再結合區塊頭的其他 5 個欄位——Version、Pre Block、Times、Difficulty、Nonce,總共 6 個欄位合在一起經過兩次 SHA256 計算得到區塊雜湊值。一個有效的區塊要求其雜湊值必須小於 Difficulty 難度值,寫作本文時的難度要求雜湊值至少已經有 18 個 0 開頭。挖礦其實就是通過修改引數的值而不斷計算區塊雜湊值,直到計算出符合難度要求的雜湊值。一般是通過修改 Nonce 值來計算區塊雜湊值,其他 5 個欄位基本是不變的。而由於雜湊函式的特性,難度值越大,理論上計算出符合要求的雜湊值所需的計算量就越大。舉個簡單例子,比如你扔三個骰子,如果難度要求總和小於18,那是非常容易達到的,基本扔個一兩次就能滿足要求了;而如果加大難度,要求總和小於9,那從概率上來說相對就沒那麼容易了,可能要扔個十幾次甚至幾十次才能達到;而如果要求總和等於 3,那隻能扔出三個 1 才行,這誰都知道要達到的概率是很低的,也許扔個一兩百次才可能出現。因此,從統計學來說,一定的難度值可以推算出概率上對應所需的計算次數,也就是“工作量”,所以,只要你達到了難度要求,也就間接證明你付出了對應的工作量,這就是工作量證明

當某個節點計算出符合難度要求的區塊雜湊時,即說明該礦工挖礦成功了,該節點就會將此區塊組裝到本地的區塊鏈,同時也將此區塊廣播給其他節點。然後,就進入第三種過程了。當其他節點收到此區塊時,也會各自獨立驗證該區塊是否有效。和獨立驗證交易一樣,也存在一份驗證標準清單,包括但不限於校驗引用的上一個區塊是否是否正確、難度值是否符合標準、區塊雜湊是否真的符合難度要求、Coinbase 交易中的挖礦獎勵是否多於應得的、整個區塊的每筆交易是否都是有效的,等等。其中,難度值是有標準的計算公式的,每個節點都會根據標準公式獨立計算實際的難度值,所以,礦工如果不按照標準而自己設定一個較低的難度,在其他節點是無法通過的。同樣,挖礦獎勵也是有標準公式的,所以,如果礦工給自己獎勵過多的比特幣,在其他節點也是同樣無法通過的。每個節點驗證該區塊為有效之後,也會各自將該區塊組裝進它們本地的區塊鏈,並繼續將該區塊廣播給其他節點。

由於所有節點同時在挖同一個區塊,就有可能會出現多個節點同時挖出了同個區塊,並都將各自挖到的區塊廣播到其他節點。假設有兩個節點同時挖出了新區塊,分別為區塊 N1 和 N2,它們的上一個區塊都是 P。有些節點會先收到 N1,它們會將 N1 先組裝進它們本地的區塊鏈,也稱為主鏈。但之後不久,這些節點也會收到 N2,這時候,它們會將 N2 放入備選鏈。而其他節點則先收到 N2 再收到 N1,則 N2 在它們的主鏈上,而 N1 在它們的備選鏈上。這時候,整個區塊鏈暫時就分成了兩個分叉,而要打破這種局面,就要看下一個生成的區塊是基於 N1 還是 N2 了。如果下一個區塊是基於 N1,自然,N1 的這條鏈就變成了最長鏈,也是累計工作量最多的鏈。那麼,那些將 N2 鏈設為主鏈的節點就會根據實際情況自己選擇將 N1 鏈改為主鏈,而 N2 將成為孤塊而被廢棄。

以上就是比特幣共識機制的核心內容了,說白了其實就是根據一些所有節點都認可的標準對每個交易和區塊的建立和校驗進行獨立驗證,當大多數節點都認可並寫入自己的區塊鏈的時候,就自動形成了分散式共識。所有區塊鏈基本都是這個邏輯,不同區塊鏈主要在於制定的標準不同,比特幣主要就是基於 POW 機制,這種機制實現簡單,但它會造成大量的能源浪費,由於所有節點同時競爭挖礦同一個區塊,而基本只有一個節點能勝出,那其他未勝出的節點所消耗的算力能源就白費了。另外,每次交易確認(即出塊時間)大概 10 分鐘,一筆交易一般要有 6 次確認才算安全,那基本就要 1 個小時了,這共識達成的時間太長了。

以太坊共識機制

以太坊的共識機制也是基於 POW 的,但與比特幣相比,主要有兩點不同:一是挖礦時間控制在 10 ~ 19 秒之間,出塊時間比比特幣快了很多;二是對於孤塊也有挖礦獎勵。在比特幣中,孤塊(即上文的 N2 區塊)是會被丟棄的,挖出了孤塊的礦工是得不到任何獎勵的。但在以太坊中,孤塊是能被打包進區塊裡的,如果後續的區塊將前面產生的孤塊也打包進區塊裡,那這個孤塊就變成了叔塊,那麼,挖到這個叔塊的礦工就能得到獎勵,而將叔塊打包進區塊的礦工也能得到額外的獎勵,但每個區塊最多隻能包含兩個叔塊,而且也不能包含太久的孤塊,最多隻支援到 7 層的祖先孤塊。由於以太坊的出塊時間短很多,那自然更容易出現臨時分叉而產生孤塊,而且這麼短的時間內,每個區塊也很難能夠在全網充分傳播,那對於網速慢的礦工來說,就非常吃虧了。所以,為了平衡各方利益,以太坊才設計了叔塊機制。寫作本文時,叔塊率在 16.9% 左右。

不過,以太坊正在計劃從 POW 機制切換為 **POS(Proof of Stack,權益證明)**機制,其新的共識機制名為 Casper,其存在兩個不同實現的版本,分別是:

  • Casper the Friendly Finality Gadget(FFG)
  • Casper the Friendly GHOST: Correct-by-Construction(CBC)

Casper FFG 是由 Vitalik 主導的,側重於通過逐步迭代實現,慢慢過渡到 POS 機制。而 Casper CBC 則是由 Vlad Zamfir 主導的,不同於傳統的協議設計方式,即先定義完整的協議,CBC 協議在開始階段只是部分確定的,其餘部分協議以證明能夠滿足所需/必需屬性的方式得到。不過,也只是兩種不同的方法,關於 POS 的核心理念還是一致的。相對來說,FFG 比較容易理解,也很大可能是即將第一個部署到以太坊的 Casper 版本,所以下面的篇幅主要講解 FFG。

FFG 版本的 Casper 是一種混合 POW / POS 的共識機制,該機制下的每次出塊依然還是採用 POW 挖礦機制,但每 100 個區塊會增加一個 POS 檢查點(checkpoint),通過驗證人(validator)來評估區塊的最終有效性。創世區塊是一個檢查點,區塊高度為 100 的倍數的區塊也是檢查點,將這些檢查點連起來就組成了一條檢查點鏈(checkpoint chain)。檢查點一般會有兩種狀態:justifiedfinalizedfinalized 則表示已經確定為最終有效的,該狀態的檢查點至少已經存在一個子檢查點,justified 則表示該檢查點是已經被證明合理的,finalized 的檢查點一定是 justified 的,但反過來則不一定。而一個檢查點是否有效,是通過多個驗證人投票得出的結果。下面,我們就來簡單聊聊這個過程。

首先,要成為驗證人,是需要投入保證金的,即抵押一定量的以太幣作為權益證明,才有資格成為驗證人。投入保證金是通過廣播一條 deposit 訊息進行操作的,只要這條訊息是有效的並被打包進區塊中,那就能加入驗證人集合(validator set),成為其中一個驗證人。另外,如果要退出驗證人集合,則可以再廣播一條 withdraw 訊息。不過,需要注意,一旦退出後,該驗證人的公鑰將被永久禁止再次加入驗證人集合。

接著,成為驗證人之後,就可以開始投票選舉檢查點了,通過廣播一條 vote 訊息到網路中。vote 訊息主要包含五個資訊:兩個檢查點 st,以及這兩個檢查點的高度 h(s)h(t),以及驗證人的公鑰 ν。要求 s 必須是 t 的祖先,一般來說,t 就是最新的檢查點,而 s 是上一個已經確定為最終有效的檢查點。另外,還要求驗證人的公鑰 v 必須在驗證人集合中找得到,否則都認為該投票是無效的。當超過 2/3 的驗證人(實際上是 2/3 的總保證金)都投給了 (s, t) 這對檢查點時,那 s 就是 finalized 的,t 則是 justified 的。而且,那些投注了 (s, t) 的驗證人還會得到貨幣獎勵,得到的獎勵是和抵押的保證金成比例的,就是說抵押的保證金越多,得到的獎勵越多。這個獎勵也可以理解為抵押保證金的利息。

另外,Casper 設定了兩條戒律:

  1. 驗證人不能釋出兩個 h(t) 相同的投票,即如果存在兩個投票:<ν, s1, t1, h(s1), h(t1)> 和 <ν,s2,t2,h(s2),h(t2)>,那麼 h(t1) = h(t2) 是不允許的;
  2. 如果 h(s1) < h(s2) < h(t2) < h(t1),則第一個投票的跨度已經涵蓋了第二個投票,這也是不允許的。

如果驗證人違反了上面的戒律,則會對驗證人進行懲罰,沒收他抵押的保證金。

最後,Casper 對分叉鏈的選擇不同於 POW 機制下選擇累計工作量最多的那條鏈,Casper 對分叉鏈選擇的規則就是選擇 justified 檢查點高度最大的鏈,原文是:

  • FOLLOW THE CHAIN CONTAINING THE JUSTIFIED CHECKPOINT OF THE GREATEST HEIGHT.

很明顯,以太坊的共識機制和比特幣相比複雜得多,主要在於兩點引起的:一是大大縮短了出塊時間,二是引入了 POS 機制。在 POW 機制下將出塊時間縮短到十幾秒,雖然加快了效能,但其實減低了安全性,因為會引入很多其他問題,比如新區塊難以在這麼短的時間內擴散到全網,比如分叉鏈出現的概率更大,為了解決這些問題,就需要設計更多共識協議來提高安全性。引入 POS 機制變成 POW + POS 的混合機制,那這種複雜度不是 1 + 1 = 2 這麼簡單的。

思考和實踐

EOS 的共識機制是怎樣的?其安全性和效能又如何呢?


掃描以下二維碼即可關注訂閱號。

016 | 漫談區塊鏈共識機制

相關文章