來源 | ethresear.ch
作者 | Vitalik Buterin
這是對信標鏈提議的一個替代設計方案,信標鏈可以在比較遠的未來切換到這個模型 (替代現在計劃的 CBC),它試圖提供以下一些關鍵特性:
➤ 在正常情況下,提供有意義的單個 slot 的經濟確定性 (即類似于 Tendermint 的特性)
- 使得即使大多數驗證者參與合謀進行單個 slot 的重組,執行的成本也比現在高得多,從而減少共識可提取價值 (consensus-extractable value, CEV)
➤ 擺脫對 LMD GHOST 分叉選擇的高度依賴,避免那些已知的缺陷,并需要引入復雜的混合分叉選擇規則,以修補這些缺陷,
➤ 有可能會使更低的最低存款額度 (deposit size) 和更高的驗證者數變得可能
➤ 保留經濟確定性 (economic finality) 最終接近于一個非常大的數值 (數百萬個 ETH) 這一特性
預備知識
讓 CONSENSUS 成為一種異步安全的共識算法 (例如,Tendermint、Casper FFG 等),我們假設共識算法的設計是涉及 slot 和 view (查看視圖) 的,即它在每個固定時間段嘗試達成共識時,我們還假設它把加權的驗證者集 (現有的拜占庭容錯共識算法要增加這一特性是很容易的) 作為輸入,
在下面的設計里,我們修改 CONSENSUS,使得在每次的查看中,要求做最終敲定的驗證者集都是不一樣的。也就是說,是把 CONSENSUS 而不是驗證者集作為函數 get_validator_set(view_number: int) -> Map[Validator, int] (其中 int 代表驗證者余額) 的輸入,該函數可以生成驗證者集的新查看視圖,get_validator_set 應該具有這樣的特性,驗證者集從一個視圖到下一個視圖最多變化 1/r,其中 r (r=65536 ) 是復原周期長度。更形式化來說,我們希望是這樣:
其中,|x|返回的是 x 值的絕對值之和,而 diff 返回的是每個鍵值相減后的值 (例如,diff({a: 0.1, b:0.2}, {b:0.1, c:0.3}) = {a: 0.1, b: 0.1, c: -0.3})。
在實踐中,相鄰的兩個驗證者集間的差值會包括現有驗證者被扣除的余額,而新加入的驗證者的比率與被扣除余額的比率相等,
請注意,只有在之前的驗證者還未做最后敲定時,1/r 的最大驗證者集差值函數才可用,如果之前的驗證者集已經最終敲定了,CONSENSUS 的實例會改變,因此 get_validator_set 函數的內部隨機性會也會完全改變;在這種情況里,兩個相鄰的驗證者集會變得完全不一樣,
請注意,這意味著,如果兩個最終敲定視圖上的數值相差足夠大,CONSENSUS 函數現在是可能兩個一起敲定的,且不會發生罰沒;這是故意如此設計的,而協議的處理方法就與今天 Casper FFG 處理怠工懲罰一樣,
機制
我們使用兩級分叉選擇:
➤ S選擇 LATEST_FINALIZED_BLOCK (最新被敲定的區塊)
➤ 從 LATEST_FINALIZED_BLOCK 開始,使用其他的分叉選擇 (例如 LMD GHOST) 來選擇區塊頭
在每個 slot 都能查看一次 CONSENSUS 算法,將基于 get_post_state(LATEST_FINALIZED_BLOCK) 產生的數據的驗證者集生成函數作為一項輸入,一個有效的提議必須包含一個 LATEST_FINALIZED_BLOCK 的有效子孫區塊,只有當該部分在分叉選擇中勝出,成為區塊鏈的一部分時,驗證者才會準備并給區塊提議投票,
如果 CONSENSUS 在某個視圖中勝出了,那么該視圖中被提議的區塊就會成為新的 LATEST_FINALIZED_BLOCK,改變未來幾輪的驗證者集。如果它失敗了,它需要在下一個 slot 或 view 里進行下一次嘗試。
注意:slot 應該總是等于當前的視圖編號加上之前每個成功最終敲定的驗證者集的視圖編號之和,
我們有以下的懲罰:
➤ 由共識算法決定的常規罰沒懲罰
➤ 怠工懲罰:如果區塊鏈無法做最終敲定,每個沒有參與最終敲定的驗證者都會受到懲罰。這個懲罰是在 r/2 個 slot 后將余額減半。
FFG 替代方案:單個- slot-epoch 的 Casper FFG
上述設計的一個替代方案是使用 Casper FFG,但要讓 epoch 的長度等同于 slot,Casper FFG 的工作機制是不一樣的,因為它不試圖防止同一個委員會對一個區塊及其子孫區塊做最終敲定。為了適應這種差異,我們需要執行 (i) 1/4 的安全閾值而不是 1/3,(ii) 這樣一條規則:如果一個 slot 做最終敲定,驗證者集最多替換 1/4 而不是完全替換。
請注意,在這樣的設計中,實現一個 slot (但不超過一個 slot) 的重組在理論上是無成本的,另外,在圖表最后“直到最大最終確定性的 slot” 數需要增加 4 倍。
特性
如果一個區塊被最終敲定了,其競爭區塊如果要被最終敲定的話,需要發生以下其中一種情況:
➤ 某個委員會 (committee) 出現問題了,≥1/3 的驗證者因為雙重最終敲定另一個區塊而被罰沒
➤ 最新近的委員會離線了,在經過 r/3 個 slot 后,委員會經過充分混洗能夠最終敲定另一個區塊而不會被罰沒。但是,這帶來了嚴重的怠工懲罰 (≥1/3 的攻擊者余額)
在任何一種情況下,即使要回滾一個被最終敲定的區塊也需要至少有 DEPOSIT_SIZE * COMMITTEE_SIZE / 3 (存款額*委員會人數/3) 個 ETH 被燒毀。如果我們設置 COMMITTEE_SIZE = 131,072 (Eth2 委員會每個 slot 的驗證者數,理論上最大值為 400 萬),那么這個數值就是 1,398,101 個 ETH。
方案里的一些其他重要特性包括:
➤ 無論有多少驗證者存款了,在處理每個 slot 的 COMMITTEE_SIZE(委員會大小)交易時驗證者的負載都很穩定
➤ 驗證者的負載會變得更低,因為當他們沒有被要求加入委員會時,它們可以休眠
➤ 休眠中的驗證者可以快速退出和提款,而不會犧牲安全性。
擴展:用小型委員會進行鏈確認
如果為了提高效率,我們不得不縮小 COMMITTEE_SIZE ,我們可以作出下列調整:
➤ 我們把“finalization (最終敲定)” 更名為“confirmation (確認)”,以反映單個確認不再代表真正的最終確定性
➤ 不同于選擇最新的被確認區塊,我們選擇的是被確認區塊最長鏈鏈頭的被確認區塊 (但拒絕回滾由 COMMITTEE_LOOKAHEAD 確認以外的區塊,因此 COMMITTEE_LOOKAHEAD 的確認就代表真正的最終確定性)
➤ get_validator_set 應該只能使用狀態的資訊,而不是 COMMITTEE_LOOKAHEAD 確認之前的資訊
➤ view 的編號應該就是 slot 的編號 (這使得同一個驗證者集試圖在不同鏈上達成共識的情況變得更易于被推導出來,這種情況只有在打破一些確認的時候才可能發生)
這個方案保留了以上所有的特性,但它也引入了一個新特性:如果一個區塊獲得多個確認 (例如,該區塊被最終敲定了,且一條鏈的子孫區塊又獲得 k-1 個確認,因為共連續獲得 k 個確認會影響該區塊),那么回滾該區塊就需要在多個委員會違反共識保證,這會使得來自多個委員會的安全水平得以堆積起來:回滾 k 個確認需要 COMMITTEE_SIZE * DEPOSIT_SIZE * k / 3 個 ETH,要達到 k = COMMITTEE_LOOKAHEAD,委員會才會出現分歧,
還要注意的是,無論如何,為了 p2p 子網的安全,前瞻機制 (lookahead mechanism) 是值得使用的,因此用它來設計是個好主意,而且如果有需要的話,可以留給客戶端來決定他們要如何處理確認回滾問題。
具體數值的例子
請注意,“打破最終確定性所需的 ETH” 數假設了攻擊者控制的驗證者數相當于控制了超過總質押的 ETH 的一半 (即數百萬個 ETH);這個數字是攻擊者將失去的 ETH 。但這不等于任何擁有 2,730, 174,762 個 ETH 的人都可以通過隨便燒毀這些 ETH 就能回滾單個 slot 的確認。