權益證明機制 PoS - 一種使用網絡共識來處理容錯的算法
工作量證明機制 PoW - 一種使用計算力來處理容錯的算法
拜占庭錯誤 BF - 節點可用,但由于其行為不可靠造成的失敗
改進的拜占庭容錯機制 DBFT - 在 NEO 區塊鏈內部實現的保證容錯的共識算法
視圖 v - NEO DBFT 共識行為中使用的數據集
2 - 角色
在 NEO 共識算法中,共識節點由 NEO 持有者選出并對交易合法性進行投票,同時它們也被稱作“賬本”。但在下文中,它們將被統稱為共識節點。

共識節點 - 參與共識行為的節點。在共識行為中,共識節點輪流扮演以下兩個角色:

發言人(一個)- 發言人負責向系統發送區塊提案。

議員(多個) - 議員負責達成交易共識。
3 - 簡介
區塊鏈之間的一個根本差異就是如何在有缺陷和不誠實行為的網絡中保證容錯。
使用 PoW 這種傳統的實現方法可以保證容錯,只要網絡中的大部分計算力都是誠實的。然而,因為這種方案對于計算的依賴,使得其效率非常低(計算力耗費能源并且對硬件有一定要求)。這使得 PoW 網絡受到很多限制,最主要的就是擴展成本。
DBFT 在 NEO 中的實現利用了一些類似 PoS 的特點(NEO 持有者投票產生共識節點),這能保護網絡不受拜占庭錯誤干擾并將消耗的資源最小化,同時也能去其糟粕(指 PoS 實現中的問題,譯者注)。這個方案在沒有對容錯機制造成顯著影響的情況下,妥善處理了當下區塊鏈實現中性能與擴展之間的問題。
4 - 理論
拜占庭將軍問題是分布式計算中的一個經典問題。這個問題中定義多個議員必須在發言人的命令下達成共識,在整個系統中,發言人或某些議員可能會是叛徒,因此我們要小心行事。最糟糕的情況下,非誠實節點可能會向每個接收者發送不同的信息。該問題的解決辦法要求議員們組團鑒定發言人是否誠實并且鑒別出真實的命令。
為了說明 DBFT 的工作機制,我們將在本部分著重論述為何要在第五部分用 66.6% 的共識率。要記住,非誠實節點并不總是會做出惡意行為,它也可能只是簡單地失效了而已。
為了便于討論,我們設想一些場景,在這些簡單的例子中,我們假定每個節點都按照發言人的信息發送響應。這種機制也被用在 DBFT 中,并在系統中嚴格執行。我們只描述正常系統與失效系統之間的區別,若想獲取更多內容,請查看參考文獻。
誠實的發言人

圖 1: 一個 n = 3 的例子,其中包含一個不誠實的議員.
在圖 1中,我們只有一個誠實的議員(50%),每個議員都會從誠實的發言人那里獲取到相同的信息。然而,因為其中一個議員是不誠實的,誠實的議員只能判斷出存在一個不誠實的節點,但是并不能鑒別該不誠實節點是區塊核心(即發言人)還是議員。因此,議員必須放棄投票,放棄改變視圖。

圖 2: 一個 n = 4 的例子,其中包含一個不誠實的議員.
在圖 2中,我們有兩個誠實的議員(66%),每個議員都會從誠實的發言人那里獲取到相同的信息,并根據該信息向其它每個議員發送驗證信息。基于兩個誠實的議員達到的共識,我們能夠判斷出系統中的不誠實節點到底是發言人還是議員。
不誠實的發言人

圖 3: 一個 n = 3 的例子,其中包含一個不誠實的發言人.
在圖 3的例子中,由于存在這個不誠實的發言人,我們會得到跟圖 1相同的結論,所有的議員都無法判斷哪個節點是不誠實的。

圖 4: 一個 n = 4 的例子,其中包含一個不誠實的發言人.
在圖 4的例子中,區塊從中間節點和右節點接收到了該驗證不合法的結果,這將會使得它們首先創建一個新的視圖來選擇一個新的發言人,因為它們占 66% 的比例,屬于多數。這個例子中,如果不誠實的發言人向其中兩個議員發送了誠實的數據,區塊將通過驗證而不需更改視圖。
5 - 具體實現
NEO 中 DBFT 的具體實現用使用了一種迭代共識的方法來保證達到共識,這個算法的性能取決于誠實節點在系統中的比例。圖 5中將預期迭代描述為不誠實節點所占比例的一個函數。
需要注意的是,圖 5中共識節點的誠實度并沒有低于 66.66%。當共識節點誠實度在 66% 和 33% 之間時,這種情況被稱為無法達到共識的“無主之地”(No-Man's Land)。如果共識節點的誠實度低于 33.33%,不誠實節點(假設它們能夠取得共識)就能夠達到共識并成為系統中新的事實。

圖 5: DBFT 算法的 Monto-Carlo 模擬圖,描繪了達到共識所需的迭代次數,其中有 100 個節點,100,000 個模擬區塊和隨機選擇的誠實節點。
5.1 - 定義
在本算法中,我們有如下定義:
t
: 區塊生成的時間,以秒計。
這個值可大致近似于單個視圖迭代的時間,因為共識行為和通信事件對于該時間常量是非常迅速的。
n
: 活躍的共識節點數目。
f
: 系統中錯誤共識節點的最小閾值。
h
: 共識行為中當前區塊的高度
i
: 共識節點索引。
v
: 共識節點視圖。視圖包含了在一次共識回合中節點接受到的所有信息,包括所有議員發起的投票(prepareResponse
或者 ChangeView
)。
k
: 視圖 v
的索引。一次共識行為可能會需要多個共識回合,共識失敗時,k
會遞增并開始一個新的共識回合。
p
: 被選為發言人的共識節點的索引。該索引的計算機制在共識節點中輪流執行,以防止某個節點在系統中產生獨裁行為。
s
: 安全共識閾值。低于這個閾值,網絡將會出現錯誤。
5.2 - 要求
在 NEO 內部,有三個主要的共識容錯要求:
s
個議員必須在區塊被提交之前對某個交易達成共識。
不誠實的共識節點必須不能說服誠實的共識節點接受一個錯誤的交易。
至少有 s
個具有相同(h
, k
)狀態的議員才能開始一個共識行為
5.3 - 算法
算法流程如下:
一個共識節點在全網范圍內廣播一個被發送方簽名過的交易。

圖 6: 一個共識節點接收到了一個交易并向全網進行廣播
其它共識節點在內存中記錄交易信息。
共識行為的第一個視圖 v
被初始化。
確定發言人。

等待 t
秒
發言人廣播提案:

圖 8:發言人建立一個區塊提案并由議員審查
議員收到提案并進行驗證:
圖 9:議員審查區塊鏈提案并響應
在收到 s
個 'prepareResponse' 廣播后,該議員就達成共識并發布一個區塊。
該議員對區塊進行簽名。

圖 10:達成共識,批準該交易的議員對區塊簽名,并將其綁定到區塊鏈上
當一個共識節點接收到整個區塊的時候,當前視圖的數據將被清除并開始新一輪的共識。
注意:
如果在 (
) 秒之后,沒有就該視圖達成共識:
6 - 參考文獻
A Byzantine Fault Tolerance Algorithm for Blockchain
Practical Byzantine Fault Tolerance
The Byzantine Generals Problem