- 區塊鏈原理、架構與應用
- 魏翼飛 李曉東 于非
- 14981字
- 2019-11-15 20:38:02
2.3 區塊鏈共識機制
前面說過,可以將區塊鏈看作網絡中每個節點都擁有的一個巨大賬本。在缺乏第三方監管機構的情況下,當網絡中的大部分人都擁有書寫賬本的權利時,區塊鏈該如何保持賬本內容的一致性和內容不被惡意篡改呢?共識機制就是區塊鏈中節點就區塊信息達成全網一致共識的機制,保證最新的區塊信息被準確添加至區塊鏈、節點存儲的區塊鏈信息一致并能夠抵御惡意攻擊。共識機制是區塊鏈這個分布式賬本能夠實現的靈魂所在。
隨著區塊鏈技術的不斷發展,不同的共識機制不斷涌現,現有的一部分共識機制和代表應用介紹如表2-2所示。需要特殊說明的是,IOTA采用的共識機制有向無環圖(drected acyclic graph)改變了區塊的鏈式存儲結構,實現了無區塊的概念。
表2-2 部分共識機制和應用舉例

2.3.1 實用拜占庭容錯算法
對于分布式系統首先需要解決的問題就是一致性的達成。一致性問題的定義是對于系統中的多個服務器節點,在給定一系列操作的情況下,在一致性協議的保障下,服務器節點對它們的處理結果相同,當然這里并不強制處理結果的正確性,所有節點都達成失敗狀態也是一種一致性的表現。
而在實際的計算機系統中達成一致性需要面臨的挑戰有很多,包括節點之間的網絡通信并不是永久可靠的,可能有任意時延和內容故障;節點的處理結果錯誤,甚至節點自身都有可能隨時宕機;以及同步調用使得系統不具備可擴展性。拜占庭問題與算法討論的場景是:有少數節點作惡場景下系統的一致性達成問題。
1. 拜占庭將軍問題
拜占庭將軍問題(Byzantine failures problem)是由萊斯利·蘭伯特(Leslie.Lamport)和其他兩人針對點對點通信在1982年提出的一個基本問題。
問題描述為:在古代東羅馬的首都,由于地域寬廣,守衛邊境的多個將軍(系統中的多個節點)需要通過信使來傳遞消息,達成某些一致的決定。但由于將軍中可能存在叛徒(系統中節點出錯),這些叛徒將努力向不同的將軍發送不同的消息,試圖干擾一致性的達成。拜占庭問題即為在此情況下,如何讓忠誠的將軍們能達成行動的一致。
例如,10個將軍共同去攻打一座城堡,只有一半以上也就是至少要6個將軍一起進攻,才可能攻破。但是,這中間有可能存在未知叛徒,有可能造成真正進攻的軍隊數量少于或等于5,致使進攻失敗而遭受滅亡。那么如何相互通信,才能確保有6個將軍的進攻命令,從而使軍隊一致進攻而成功,或者確保少于6個將軍的進攻命令,從而使軍隊一致不進攻避免被滅掉?也就是說,要么一半以上同意一起進攻而決定進攻,要么不到一半同意一起進攻而決定不進攻,但要避免說進攻但命令卻是不進攻,使那些進攻軍隊數少于或等于一半,造成進攻者的被滅。這種情況并不考慮進攻的命令是否準確有效,單純就各位將軍的命令在何種情況下能夠確保一致。
拜占庭將軍問題可以簡化為,所有忠誠的將軍能夠相互間知曉對方的真實意圖,并最終做出一致行動。而形式化的要求就是一致性和正確性。蘭伯特對拜占庭將軍問題的研究結論是,如果叛徒的數量大于或等于1/3,拜占庭問題不可解;如果叛徒個數小于將軍總數的1/3,在通信信道可靠的情況下,通過口頭協議,可以構造滿足一致性和正確性的解決方法,將軍們能夠做出正確決定。
口頭協議指的是將軍們通過口頭消息傳遞達到一致。隱藏條件是:每則消息都能夠被正確傳遞;信息接收方確定信息的發送方;缺少的信息部分已知。
如果一個節點的信息同時傳遞給其他兩個節點,這兩個節點接收到消息后也分別傳達給其他節點,這樣每個節點都是信息的接收方和傳遞方,直到每個節點最后都有所有節點發送的信息。在此過程中若出現叛徒或虛假消息導致信息不匹配,所有節點按照少數服從多數的原則,行動便能夠達成一致。缺點是如果出現信息不一致的情況,因為對于信息的傳送方未知,所以無法判斷叛徒。
為了解決無法追溯根源的問題,方案二是采用簽名信息。將軍們利用不可偽造的簽名技術表達自己的意見,其他人可以驗證簽名的有效性,如果簽名被除本人外的第三方篡改很容易被發現。但是這種方案需要解決如何實現真正可靠的簽名體系的問題。如果依賴第三方存儲簽名數據,那么這個網絡本身就不再是前提中所假設的節點間互不信任的分布式結構,其次是簽名造假的問題也無法避免,同時存在異步協商帶來的漫長的傳輸時間并不適合實際使用。
2. 拜占庭容錯(BFT)
拜占庭將軍問題是對現實中可能遇到問題的模型化,在分布式計算機領域中,由于硬件錯誤、網絡堵塞或中斷以及遭遇惡意攻擊等原因,網絡可能出現各種不可預測的異常行為。不同出錯類型對于系統造成的危害程度也不同。影響最小的出錯類型是“出錯-停止(failstop)”。此種類型的節點在出錯之后,就會立即停止工作,這樣,系統中的其他節點也會知道該節點出錯了。但是拜占庭錯誤節點在出錯后會繼續工作,做出任意行為,就像拜占庭將軍問題中的叛徒一樣,做出不響應、發出錯誤消息、復制多份信息、向不同節點發出不同的決策信息、與其他拜占庭節點合謀等擾亂行為,而系統中的節點無法自發識別拜占庭錯誤節點。被攻擊者控制、向系統發出攻擊的節點就是典型的拜占庭錯誤節點。如果一個系統中存在少量的拜占庭錯誤節點,仍能達成共識,那么系統就是拜占庭容錯的。
在蘭伯特提出拜占庭將軍問題時,就提出了一種在同步環境中解決問題的拜占庭容錯算法;1988年,也有學者提出了一種在大多數異步環境中工作的算法,但是對于實際應用的指導意義都不大。直到1999年由Miguel Castro(卡斯特羅)和Barbara Liskov(利斯科夫)提出了PBFT(實用拜占庭容錯算法)。解決了原始拜占庭容錯算法效率不高的問題,將算法由指數降低到多項式級,使得拜占庭容錯算法在實際系統中應用可行,但除了在專業領域以外并沒有引起足夠的重視。而2009年中本聰創建的比特幣,作為第一個開放式去中心化應用程序,對區塊鏈網絡的記賬問題和拜占庭將軍問題是類似的。每次參與記賬的節點就好比一位將軍,某些節點可能因為某些原因傳遞錯誤消息給其他節點,做出“背叛”行為。而對于不需要貨幣體系的聯盟鏈或者私有鏈來說,傳統共識算法比PoW和PoS更符合要求,傳統共識算法能夠提供絕對可信任的節點,滿足高效的需求。
傳統共識算法中較為典型的有Paxos、Raft算法,其中Paxos問題是指分布式系統中存在故障節點場景下的一致性問題,并不存在惡意節點;而Raft算法是Paxos算法的一種簡化實現。在一些互聯網的數據庫產品的防火墻內都使用了該類算法,使得有故障的機器出現時服務正常可用。
而在區塊鏈系統中,存在攻擊者,也有潛在可能存在拜占庭容錯節點。攻擊者可以延遲網絡中的通信、協調拜占庭錯誤節點發起攻擊、阻斷部分節點與其他節點的聯系。所以使用實用拜占庭容錯算法的更適合。
PBFT算法中各個節點由業務的參與方或監管方組成,安全性與穩定性由業務相關方保證,共識時延能夠達到商用實時處理的需求,共識效率高,能夠滿足高頻交易量的需求,因此被一些區塊鏈應用選作共識算法,在超級賬本(Hyperledger)Fabric的0.6版中就使用了經典的PBFT共識算法。
3. 實用拜占庭容錯算法(PBFT)
拜占庭將軍問題的核心是,如何使得將軍們需要收到正確的命令并做出正確的反應。而PBFT的解決思路是,每個節點都對周圍節點進行信息正確性的確認,用通信次數換取信用,每條命令的執行都需要兩兩驗證去檢驗消息。利用狀態機副本復制的方法,假設系統中共有3f+1個復制節點,其中最多f個節點為拜占庭錯誤節點,系統中每個節點都運行一個有限狀態機的副本,同時支持若干種操作,該算法在保證活性與安全性(liveness&safety)的前提下提供了(n-1)/3的容錯性。
客戶端會給各個復制節點(replicas)發送一系列請求來執行相應操作,需要保證所有節點執行相同順序的操作。因為所有復制節點的初始狀態是相同的,對于相同請求的響應也是相同的,根據狀態機原理,這些復制節點應該產生相同的結果狀態。但是狀態機原理的問題在于如何確保正常工作的復制節點能夠以相同的序列執行相同的操作,尤其是在面對拜占庭故障的時候。
R是所有復制節點的組合,用[0,|R|-1]的證書表示每一個復制節點。假設|R|=3f+1,f為可能失效復制節點的最大個數。所有復制節點在視圖(view)的輪換過程中運作,視圖是一個連續編號的整數,不同視圖的意義類似于不同的時間段。在每個視圖中使用不同的主節點(primary),其余復制節點均為備份節點(backups)。主節點編號由公式p=vmod|R|得到,其中v是視圖編號,p是節點的編號。
主節點負責接收客戶端的請求,并將請求排好序,按序組播給備份節點(全部復制節點構成的一個組,組播指的就是發送消息給組成員)。但是主節點可能會出錯,它可能會給不同的請求編上相同的號碼,或不分配編號,或將相鄰的序號編上不連續的號碼。備份節點需要主動檢查號碼的合法性,當出現異常情況的時候,啟發視圖更換(view change)過程重新選擇主節點。
一次共識過程包括請求(request)、預準備(pre-prepare)、準備(prepare)、確認(commit)和回復(reply)。其中,請求和回復過程為客戶端發起請求并收到最終答復,預準備、準備和確認過程為PBFT算法的主線,預準備和準備階段用來確保時序性,即同一個視圖中的請求的正確序列;而準備和確認過程為確保到達確認階段的請求即使在視圖轉換后在新的視圖中仍然保持原有順序不變,也就是不同視圖之間的確認請求的嚴格排序。比如說在視圖V0中,三個請求Req0、Req1、Req2依次進入了確認階段。如果節點不存在問題,那么節點需要依次執行三條請求并返回給客戶端,但是如果主節點出現異常,那么視圖更換過程啟動,視圖從V0更替為V1。在新的視圖里,原本的Req0、Req1、Req2三個請求的序列被保留,但是處于預準備和準備階段的請求在新的視圖中并不會進行保留。
復制節點的狀態中會保留服務的整體狀態,接收的信息會被保存在消息日志中,并且有一個整數表示當前所處的視圖編號,而在和客戶端的交互中,復制節點向客戶端發送的信息便包含當前的視圖編號,以便客戶端能夠跟蹤當前的視圖編號,從而推算出當前的主節點。
客戶端會給它認為的主節點發送請求,內容為<Request,o,t,c>,其中,o為operation,表示期待狀態機執行的操作;t為timestamp時間戳,用來保證客戶端的請求只會執行一次,因為客戶端發出請求的時間戳是全序排列的,后續發出的請求的時間戳會高于之前發出的請求。主節點接收請求后會自動將請求進行組播。
當主節點接收到客戶端的請求后,會給請求進行編號,然后主節點組播一條預準備消息給所有備份節點。預準備消息的格式是<<pre-prepare,v,n,d>,m>,其中,v為視圖編號,n為主節點給請求的編號,m為客戶端發送的請求消息,d是請求消息的摘要。請求本身不在預準備信息中,這樣能夠使得預準備消息足夠小。發送預準備消息的目的是為了確定該請求在視圖v中被賦予了編號,使得即使在視圖變更過程中序列仍是可追溯的。另外,將請求排序協議和請求傳輸協議進行解耦,有利于傳輸速率的優化。
備份節點并不是無條件接收主節點發送的所有預準備消息,需要滿足以下條件:請求和預準備消息的簽名正確,d和消息m的摘要一致;視圖編號與當前視圖相符;節點從未接收過同一視圖和同一序列編號的不同摘要的預準備信息;消息的序號必須在水線的上下限h和H之前,水線的意義在于防止一個失效節點故意用一個很大的序號消耗序號空間。
如果消息通過驗證,那么備份節點接收預準備信息,同時進入準備階段。在準備階段,備份節點組播準備信息<prepare,v,n,d,i>,并將預準備消息和準備消息都寫入消息日志中。在這個階段,該備份節點還會分別收到其他備份節點的準備消息,該備份節點會綜合所有準備消息做出自己對該消息的最終裁決,以防主節點為拜占庭錯誤節點。每個節點驗證預準備和準備信息的一致性主要檢查:視圖編號、消息序號和摘要。如果無誤,那么就稱請求在該節點的狀態是prepared,該節點就擁有了一個prepared certificate。
預準備階段和準備階段確保所有正常節點對同一個視圖中的請求序號達成一致。接下去是對這個結論的形式化證明:如果prepared(m,v,n,i)為真,則prepared(m',v,n,j)必不成立,這就意味著至少f+1個正常節點在視圖v的預準備或者準備階段發送了序號為n的消息m。因為系統中至多存在f個故障節點,所以此時消息必為真。
當條件為真時,節點i將<commit,v,n,D(m),i>向其他節點廣播,廣播信息代表節點i已經擁有一個prepared certificate,同時節點i也會收到其他節點發送的commit信息,如果它收到了2f+1條帶有相同視圖編號、序列編號和摘要的確認信息(包括節點自身所有的一條信息),那么就說該節點擁有了comminted certificate,請求在這個節點達到了committed狀態。
每個復制節點i在committed-local(m,v,n,i)為真之后執行m的請求,并且i的狀態反映了所有編號小于n的請求依次順序執行。這就確保了所有正常節點以同樣的順序執行所有請求,這樣就保證了算法的正確性。在完成請求的操作之后,每個副本節點都向客戶端發送回復。副本節點會把時間戳比已回復時間戳更小的請求丟棄,以保證請求只會被執行一次。
上述過程可簡要描述如下,假設C為請求客戶端,0、1、2、3為副本節點,其中0是主節點,3是失效節點,如圖2-7所示。
(1)請求(request):客戶端向主節點發送請求調用服務。
(2)預準備(pre-prepare):主節點0收到客戶端的請求后將其組播給其他副本,即0->123。
(3)準備(prepare):復制節點1、2、3收到請求后記錄,并再次組播給其他復制節點,即1->023、2->013,復制節點3因為宕機失效無法進行組播。

圖2-7 PBFT算法示意圖
(4)確認(commit):0、1、2、3節點在prepare階段,若收到超過一個數量的相同請求,則進入commit階段,組播commit請求,即0->123、1->023、2->013。
(5)回復(reply):0、1、2、3節點在commit階段,若收到超過一定數量的相同請求,則對客戶端進行反饋。客戶端需要等待f+1個不同復制節點發回相同的結果,作為整個操作的最終節點。
根據上述操作流程,當節點數n>3f+1時,系統的一致性能夠得到解決。以剛才的系統為例,如表2-3所示,拜占庭容錯能夠容納將近1/3的錯誤節點誤差。
表2-3 不同數目錯誤節點可能情況列舉

2.3.2 工作量證明
區塊鏈網絡作為一種分布式網絡,需要解決拜占庭將軍問題,達成工程上的相對一致。在比特幣區塊鏈中,通過工作量證明機制解決了這個互不信任的分布式網絡如何在各方利益都能得到確保的情況下達成一致共識的難題。
工作量證明(PoW)是一種對應服務與資源濫用或是阻斷服務攻擊的經濟對策。一般是要求用戶進行一些耗時適當的復雜運算,并且答案能被服務方快速驗算,以此耗用的時間、設備與能源作為擔保成本,以確保服務與資源是被真正的需求所使用。此概念最早由Cynthia Dwork和Moni Naor于1993年的學術論文提出,而工作量證明一詞則是在1999年由Markus Jakobsson與Ari Juels所發表。現在常說工作量證明機制指的是應用于區塊鏈技術中的一種主流共識機制。
工作量證明常用的技術原理是散列函數。在比特幣挖礦過程中使用的是SHA-256哈希函數,無論輸入值的大小,SHA-256函數的輸出的長度總是256位。算法的規則是,節點通過解決密碼學難題(即工作量證明)競爭獲得唯一記賬權;平均10分鐘內(具體時間會和密碼學問題的難度相互影響)只能有一個人可以記賬成功,其他節點驗證通過后復制這一記賬結果。
礦工首先根據存儲的交易池中的交易構造一個候選區塊,計算區塊頭信息的哈希值,觀察是否小于當前的目標值。如果小于目標值,那么在沒有其他節點廣播信息的時候,礦工成功爭奪記賬權;如果哈希值不小于目標值,那么礦工就會修改nonce值,然后再試一次。
具體目標值越小,找到小于其的哈希值就會越難。拿擲骰子舉例,兩個骰子的和小于12的概率遠大于兩個骰子的和小于5,相同的,哈希值前有多少位規定為0,隨著0位數的增加,難度越大。如果考慮的是256位空間。每次要求多一個0,那么哈希查找的空間縮減了一半。
礦工成功挖礦就代表得到了新區塊的工作量證明解,就會迅速在網絡中進行廣播,其他節點在接收并驗證后也會繼續傳播新區塊,每個節點都會把它當作新區塊添加到自身節點的區塊鏈副本中。當挖礦節點收到并驗證了這個新區塊后,便會放棄之前對構建這個相同高度區塊的計算,并立即開始計算區塊鏈中下一個區塊的工作。
在比特幣網絡中,實現所有節點的去中心化共識機制,不單單需要工作量證明,還有其他三個獨立的過程相互作用產生:每個全節點依據綜合標準對每個交易進行獨立驗證;通過完成工作量證明算法的驗算,挖礦節點將交易記錄獨立打包進新區塊;每個節點獨立地對新區塊進行校驗并組裝進區塊鏈;每個節點對區塊鏈進行獨立選擇,在工作量證明機制下選擇累計工作量最大的區塊鏈。
其中解決區塊鏈的分叉問題遵循了累計工作量最大的鏈條為網絡主鏈的原則。當有兩名礦工幾乎在同一時間算得新區塊的工作量證明解,在分別對各自區塊進行傳播的過程中,就會出現兩個版本不同的區塊鏈。解決方法就是,總有一方能夠搶先發現工作量證明解并傳播出去,所有節點會接收更長的鏈,這樣網絡就會重新達成共識。
2.3.3 權益證明
工作量證明算法的優勢明顯,但為了維持其正常運轉卻需要大量的資源投入,尤其是電力資源和購置礦機的成本消耗。Digiconomist調查顯示,僅僅比特幣,礦工就要使用54太千瓦時的電力。這些電量足夠支持美國500萬個家庭用電,甚至整個新西蘭或匈牙利的電力,但是實際耗電不僅止于此。權益證明機制試圖找到一個更為綠色環保的分布式共識機制。
2011年,QuantumMechanic在Bitcointalk論壇首次提出了權益證明,權益證明(PoS)是一類應用于公共區塊鏈的共識算法,不同于工作量證明中新區塊的挖掘完全取決于節點進行哈希碰撞的算力,在權益證明中,新區塊的創建是通過隨機、財富或幣齡的各種組合來進行選擇的,取決于節點在網絡中的經濟效益。它所蘊含的概念是:區塊鏈應該由具有經濟利益的人進行保障。系統通過選舉隨機選擇節點驗證下一個區塊,但要成為驗證者,節點需要在網絡中事先存入一定數量的貨幣作為權益,類似于保證金機制。權益證明的運作方式是,當創造一個新區塊的時候,節點需要創建一個coinstake交易,交易會按照一定比例將一些幣發送給節點本身。根據節點擁有幣的比例和時間,按照算法對難度目標進行調整,從而加快了節點找到符合難度目標隨機數的速度,極大地降低了系統達成共識所需要的時間。
權益證明并不單純考慮賬戶余額,因為如果將賬戶余額定義為下一個有效區塊的挖掘方式,那么單個最富有的節點將具有永久優勢,勢必會導致網絡的集中化。在不同的數字加密貨幣中,已經設計了幾種不同選擇方法的權益證明體系,本節將主要講述點點幣(Peercoin)和黑幣(Blackcoin)采用的權益證明機制。
1. PoS1.0——點點幣(Peercoin)
點點幣是從中本聰創造的比特幣衍生而來的數字貨幣,首次實現了PoS,由化名為Sunny King的網友于2012年提出并發布。但點點幣的共識機制是并不純粹的權益證明,而是采用了基于PoW和PoS的混合機制,前期采用工作量證明機制進行挖礦開采和分配貨幣,后期采用權益證明機制,保證網絡安全,因此從長遠來看,點點幣更節能而且具有成本優勢。
點點幣中采用的PoS是基于幣齡(coinage)的,同樣涉及與比特幣類似的散列運算,但是不像比特幣無范圍地盲目搜索,點點幣中的搜索空間被加以限制。Sunny King在《點點幣:一種點對點的權益證明電子密碼貨幣》(PPCoin:Peer-to-Peer Crypto-Currency with Proof-of-Stake)中對其進行了詳細的說明。
1)幣齡
幣齡的概念緣于中本聰的設計,被簡單定義為貨幣的持有時間,例如Alice收到了10個幣,并且持有10天,那Alice就有了10×10=100幣天(coinday)的幣齡,當Alice花費了這10個幣,那么認為這10個幣上的積累的幣齡被消耗。但在比特幣中,幣齡只用來給交易排序,并沒有起到很重要的作用。點點幣中加入了交易時間戳的概念,簡化了系統對于幣天的運算。
2)coinstake
coinstake依據比特幣中的coinbase交易命名,是Sunny King為實現PoS專門設計的一種特殊交易類型,如圖2-8所示。類似于比特幣中coinbase必須是區塊中的第一筆交易,點點幣中規定,如果一個區塊為PoS區塊,那么它的第二筆交易必須是coinstake,同時如果一個區塊的第二筆交易為coinstake,那么它是PoS區塊。coinstake的第一個輸入不能為空,即kernel(核心)字段永恒存在,合格區塊的判定只與kernel的幣齡有關。輸出的output0必須置零,output1輸出給區塊持有人指定的收益地址,包括輸入的本金和利息(stakeReward)。利息的計算公式為

可簡化為

式中,coin_number代表擁有幣的數量。

圖2-8 coinstake示意圖
這樣,點點幣便通過coinstake交易定義了除過PoW以外的一種新型的鑄幣方式。PoS將根據coinstake交易中所消耗的幣齡產生利息,0.01代表每一個幣一年將產生1分的利息。這就使得點點幣有一個與通貨緊縮的比特幣完全不同的特征,點點幣沒有固定的數量,點點幣也是第一種引入無限量代幣供應的數字貨幣。
3)權益證明
權益證明通過選舉的方式,選擇節點進行下一個區塊的驗證,將這樣的節點稱為驗證者(validator),新區塊不再是礦工挖掘產生的,而是通過鑄造(mint/forge)生成。要成為驗證者,節點需要在網絡中存入一定數量的貨幣作為權益,類似于保證金機制。
PPC中加入了幣齡的考量。在coinstake交易中,區塊持有人可以消耗他的幣齡獲得利息,同時獲得為網絡產生一個區塊和用PoS鑄幣的優先權。coinstake的第一個輸入kernel需要滿足某一哈希的目標協議,這使得區塊的產生具有了隨機性,具體公式為
proofhash<CoinDayWeight×Target
CoinDayWeight=coin_number×days,days∈[30,90]
proofhash=hash(nStakeModifier+txPrev.block.nTime+txPrev.offset+txPrev.nTime+txPrev.voutn+nTime)
proofhash對應一組數據的哈希值,CoinDayWeight即幣齡,用戶持有的貨幣數量乘以持有該筆貨幣的時間,天數存在取值區間,用戶只有將該筆貨幣儲存在錢包中至少30天才能夠參與創建新區塊,最大值為90天。從公式能明顯看出,隨著持幣天數的增加,能夠搜索的目標空間就會增大。Target為目標值,用于衡量PoS機制下鑄造新區塊的難度,具體計算公式為

block_interval為前兩個區塊的時間間隔,由公式可見,兩個區塊的目標時間間隔是10分鐘。目標與難度成反比,難度越高,目標值越小,鑄造難度越大。如果前兩個區塊的時間間隔大于10分鐘,目標值會提高,當前區塊的難度會降低;與此相反,如果前兩個區塊的時間間隔小于10分鐘,目標值會降低,當前難度就會提高。與比特幣中難度目標約兩周調整一次不同,點點幣中目標值持續調整,主要目的是避免鑄造新區塊的突然波動。
proofhash由一些固定字段通過哈希運算得到。nStakeModifier是專門為PoS設計的調節器,每個區塊對應一個nStakeModifier值,但并不是每個區塊的值都會進行變化,協議規定每隔一段時間必須重新計算一次,取值與前一個nStakeModifier和最新區塊哈希值有關。如果沒有nStakeModifier字段,當用戶收到一筆幣后,能夠提前計算得知自己在未來什么時間段構造區塊,這并不符合Sunny King的初衷,系統需要用戶進行哈希值的盲目探索,以確保區塊鏈網絡的安全性。txPrev為kernel對應的與一筆交易;txPrev.block.nTime為上一筆交易所在區塊的時間戳;txPrev.offset是上一筆交易在區塊中的偏移量;txPrev.nTime為上一筆交易的構造時間,也就是上一筆交易的時間戳;txPrev.voutn為kernel在txPrev的輸出下標,也就是kernel是txPrev的第幾個輸出。
而判斷主鏈的標準轉變為對區塊累計消耗幣齡的判斷,每個區塊的交易都會將消耗的幣齡提交給該區塊,獲得最高消耗幣齡的區塊將被選為主鏈。
2. PoS2.0——黑幣(Blackcoin)
點點幣采用的基于幣齡的PoS機制存在一些潛在的安全問題,例如一些節點會積攢幣齡,平時保持離線狀態,只有在積累了一定的幣齡之后才重新上線獲取利息,網絡中不夠數量的節點保持活躍狀態就會影響網絡中安全性能。另外,幣齡可能會被惡意節點濫用以獲得更高的網絡權重以實現雙花。
黑幣(Blackcoin,BLK)誕生于2014年2月24日,作者是Paul Vasin。在黑幣的白皮書《黑幣POS協議2.0》(BlackCoin's Proof-of-Stake Protocol v2)中,他闡述了現有PoS協議的不足,除了上述的幣齡的問題,還包括權益證明的組件是可以充分預測的,節點能夠對將來的權益證明進行提前計算。在黑幣中提出了PoS2.0機制,對之前權益證明的不足之處進行了修改完善。
黑幣中PoS證明的計算公式為
proofhash<coin_number×Target
安全的PoS系統需要保證可能多的節點保持在線狀態,越多的節點進行在線的權益累積,系統遭遇攻擊的可能性就越低,同時交易得到確認的速度也就越快。因此在新的等式中去掉幣齡,使得積攢幣齡的方法在新系統中無法使用,進行權益累計就需要節點盡可能保持在線狀態。proofhash的具體表達式為
proofhash=hash(nStakeModifier+txPrev.block.nTime+txPrev.nTime+
txPrev.vout.hash+txPrev.voutn+nTime)
為了降低節點進行預算計算的可能性,nStakeModifier權重修正因子在每次修正因子間歇時都會進行改變,以便對將要用來進行下一個權益證明的時間戳的計算結果進行更好的模糊處理。
同時,黑幣對區塊的時間戳也進行了適當的改變,使得在PoS機制下能進行更有效的工作,理想預計區塊的生成時間為64s。每生成一個區塊,不包括驗證交易產生的交易費,系統給予驗證者的獎勵為1.5BLK,可大致估算出每年生成的區塊獎勵為×24×365×1.5=739 125BLK。根據黑幣官網介紹,截至目前,739 125是黑幣總供應量的0.972%。這0.972%僅分配給參與網絡權益證明的用戶,獎勵率高于1%。
黑幣是首創快速挖礦+低股息的發行模式,發行前7天采用Scrypt算法挖礦,第8天開始進入純粹PoS階段,是歷史上第一個使用PoW創建周期然后過渡到完整的PoS的數字貨幣。隨著時間的推移,黑幣的核心協議已經進入了PoS3.0階段,PoS3.0主要對交易中多重簽名的部分進行了補充。
3. PoS機制存在的問題
區塊鏈應用的最核心問題是如何在去中心化的環境中達成共識,比特幣最核心的突破是在沒有中心組織的情況下,讓全網對交易的有效性達成了一致。比特幣通過引入外部算力資源來確保共識的安全性,也就是工作量證明,另外通過每個新區塊產生一定量的比特幣激勵網絡參與者,這也幾乎是所有采用工作量證明的系統采用的方法。但是這種激勵必須保證足夠的吸引力,才能吸引足夠的參與者持續參與新區塊的挖掘,以維持網絡的運行,一旦激勵的吸引力下降,網絡的安全性就會很容易被破壞。同時引入外部資源也使得網絡暗含著被外部資源攻擊的危險,只要有足夠的資金那么就能夠買到足以破壞現有共識的設備和算力。
正是因為比特幣存在的這些問題,出現了權益證明。權益證明放棄通過外部資源而選擇通過網絡用戶幣種的權益維持網絡的穩定,此時用戶的權益就類似工作量證明中的算力。但因為沒有引入外部資源,采用權益證明的系統不需要消耗大量能源,也不用擔心外部的算力攻擊。
但是PoS系統出現了新的問題——內部的Nothing-at-Stake(無利害關系,N@S)攻擊。在早期的基于區塊鏈的權益證明算法中,只為創造區塊提供激勵,沒有懲罰措施,這就造成了當網絡出現分叉,多條鏈相互競爭的情況下,對于幣種的持有者,最佳策略就是在每條鏈上都創造區塊,以確保自己能獲得最終獎勵,如圖2-9所示。
這樣,無論哪條鏈最終勝出,幣種持有者的利益都不會有任何損失。這就導致一旦出現分叉,只要系統中有一定量“貪心”的驗證者,即使沒有外部攻擊,全網也不會達成共識。工作量證明機制中則不需要考慮這種攻擊存在,因為礦工獲得激勵的可能性會隨著算力分配的區塊數目增加而降低,有損于礦工自身利益,如圖2-10所示。
第二個問題是重寫歷史攻擊。從理論上來說,攻擊者可以通過購買原始持有幣種的賬戶從頭發起攻擊,重新分叉一個區塊鏈。因為持有原始幣種的賬戶可以將貨幣轉移到任意賬戶而不受懲罰,因此存在重寫歷史攻擊的可能性。

圖2-9 N@S攻擊示意圖

圖2-10 工作量證明機制下攻擊情況示意圖
前面說過,想要維持一個區塊鏈網絡的穩定性,必須要有足夠的激勵機制吸引參與者盡可能多地參與新區塊的挖掘或者鑄造。但是一般的PoS系統是沒有新幣產生的,礦工只能賺交易費,如果交易費不高,那么對于礦工的激勵就十分有限。因此有些PoS系統中,通過持續產生新幣,也就是coinstake交易產生的利息,來激勵驗證者,但這就會導致通貨膨脹。假設利息為1%,那么就是每年1%的通貨膨脹率,通貨膨脹率會使得小戶、散戶的貨幣貶值,只有大戶才能對貨幣進行保值,最終會導致中心化的現象出現。
為了解決上述問題,改進的PoS機制加入了十分嚴苛的懲罰制度來保障系統的安全。驗證者將權益通過保證金的形式存入,一旦對系統有惡意攻擊,得到的懲罰比獎勵要大得多,攻擊得不償失,但是對于如何判定惡意攻擊依然是一個備受爭議的問題。所以在這種情況下,很多應用選擇了PoW+PoS的模式,依據PoS機制通過降低PoW出塊的難度從而縮短了共識達成的時間,就連ETH也將采用這種模式,根據2018年1月2日Ethereum Team發布的第四季度總結,基于PoS的項目Casper測試網絡也已經發布了。
2.3.4 委任權益證明
委任權益證明(DPoS)由區塊鏈工程師丹尼爾·拉爾默(Daniel Larmer)提出,首先在比特股(Bitshares)上實現,之后的斯蒂姆幣(Steem)、柚子(EOS)等數字貨幣或應用上都使用了DPoS機制。
簡單來說,持幣者投票選出一定數量的節點,代替他們進行區塊驗證的記賬。用戶通過一個特別的加密貨幣社區,投票選擇網絡的代表。投票的影響是根據持有的貨幣數量來決定的,貨幣持有量越大,那么投票的影響力也就越大。這些代表需要負責區塊的產生,同時系統會給予他們一定收益。一旦被選擇出來的代表沒有履行應盡的職責,社區可以進行投票將其資格取消。有固定收益的激勵機制存在,有大量用戶愿意成為票選出的代表。類似于一個公司,公司中的員工都持有該公司數額不等的股份。每隔一段時間,員工可以把自己手中的票投向自己最認可的N個人來領導公司進行決策,每個員工的投票權和他手里持有的股份數等比例,投票結束后,得票最多的N個人成為公司的領導。如果領導做了不利于公司發展的事情,那么員工可以取消領導的資格,從而退出管理層。DPoS通過一定程度的中心化,實現了秒級的共識驗證速度,同時規避了純粹PoS機制可能導致的攻擊問題。
DPoS中投票選擇出來的代表根據任務不同,可分為兩類:證人(witnesses)和受托人(delegates),在比特股的白皮書中進行了仔細的解釋。
委托人的權利是提議更改網絡參數,包括交易費用、區塊大小、證人的獎勵金額大小、區塊間隔時間等所有內容,這些參數通過創世賬戶進行記錄更新,一旦大多數代表批準了擬定的變更后,貨幣持有人即利益相關者擁有兩周的審核期,在此期間他們可以將提案的代表罷免并使變更提案無效。此設計是為了確保委托人在技術上沒有直接權力,所有對網絡參數的更改最終都是得到利益相關方批準的。根據DPoS,真正實現了權力掌握在利益相關方手中。值得注意的是,委托人并不是有償職位。
證人的作用類似于現實社會中的公證人,公證人有時需要證明合同是在特定的時間由特定的人簽署的,證人需要驗證區塊中的交易及簽名的有效性。證人每產出一個區塊,系統會給予他們固定數目的獎勵,獎勵數額的大小由委托人決定。如果證人沒有按照規定產生新的區塊,他們不會獲得報酬,同時還會被票決出代表集體。證人的名單并不是固定的,系統會按照設定好的時間間隔進行名單的更新。同時,所有利益相關者都可以觀察證人的參與率來監督網絡的健康狀況,在任何時間一旦證人的參與率低于某個基準,用戶可以為交易的確認預留出更長的時間,同時對網絡的安全性保持警惕。此屬性使得比特股能夠在不到1min內提醒用戶潛在問題。

圖2-11 區塊產生示意圖
假設每個區塊的生成時間為3s,那么正常情況下,塊生產者需要每3s輪流生成區塊,一旦錯過自己的輪次,這個時間段不再有區塊產生,由規定的名單序列中的下一個證人生產新區塊。塊生產者在被調度輪次之外的任何時間段產出的塊都是無效的,如圖2-11所示。
在《DPoS Consensus Algorithm-The Missing White Paper(DPoS——缺失的白皮書)》中,將可能對共識產生威脅的情況做以列舉說明。
如果不超過1/3的節點故障或者惡意分叉,如圖2-12所示,依照每3s進行一次區塊產生者輪換,在這種情況下,少數節點只能每9s產生一個區塊,而多數節點可以產生兩個區塊。這樣,誠實的多數節點將永遠比少數節點產生的鏈條更長,網絡不會產生分叉。如果少數節點試圖在離線狀態下進行無限量的分叉實驗,也不會對網絡的共識產生影響。因為少數人在出塊速度上注定比多數節點的慢,他們產生的分叉也永遠比多數人的鏈條短。

圖2-12 少數節點分叉情況
如果多數節點出現故障或進行惡意分叉,在他們所屬的生產區塊的時間段可以產生無限數量的分叉,如圖2-13所示。每個分叉都有2/3以上的算力在創建區塊以延長分叉,最后在不可逆區塊時按照最長鏈法則進行主鏈的選擇,最長鏈就是為大多數節點批準承認的鏈條,這種情況下由少部分誠實節點決定。同時絕大多數節點進行惡意分叉或者故障的情況并不會維持很長時間,因為利益相關方很快會將這些代表節點票決替換。

圖2-13 多數節點惡意分叉情況
網絡有可能出現碎片化的情況,導致沒有任何一條分叉擁有占據網絡多數區塊生產者,如圖2-14所示。假設可能存在三條分叉,其中兩條的長度相同,因為投票選擇的證人總數永遠為奇數,但第三個生產者產生較小的分叉加入網絡中后,平局會被打破。網絡最長鏈會倒向最大的那個少數群體。當網絡的連通性恢復時,較小的少數群體會切換到最長鏈,網絡共識重新恢復。

圖2-14 網絡碎片化情況
實際在網絡中并不會出現這種情況,因為即使區塊生產者的數目相同,分叉也不會以相同的步長增加,因為每輪生產過后,都會經歷生產者的洗牌,重新安排出塊順序。這種隨機性確保順序相近的生產者不會總是相互忽略,在擁有相同生產者進行分叉的情況下,平局也總是會被打破的。

圖2-15 最后不可逆區塊
在網絡出現碎片化的情況下,多個分叉有可能會增長一段相當長的時間,雖然最終最長鏈會獲得勝利,但是觀察者需要一種更確切的手段判斷一個區塊是否屬于增長最快的那條鏈。這可以通過觀察來自2/3+1多數塊生產者進行判定。如圖2-15所示,區塊A已經被B和C確認,這代表了網絡中2/3+1的多數確認,在全部節點誠實的情況下,可以判定沒有其他鏈會比該鏈更長,將區塊B稱為不可逆區塊。
設想一種比較極端的情況,網絡中的大多數生產者不履行職責,只有少數代表堅持繼續出塊。在DPoS機制下,利益相關方可以在這些被少數區塊堅持生產的區塊中發起更改投票的交易,這些投票可以選擇一批新的生產者,將參與出塊的比率恢復到100%。這樣,該條鏈最終會超過其他以低于100%參與率運行的分叉鏈。很明顯的是,一條參與率低于67%的鏈最終的網絡狀態是不確定的,共識最終會在一個不同的分叉上建立起來。選擇在此條件下交易的用戶冒的風險與在比特幣網絡中選擇接受不到6個區塊確認的人是相似的。
在能夠設想的自然網絡分叉的情況下,DPoS都是強健的,甚至于在面對大量生產者作弊的場景也是安全的。同時不像其他共識機制,在大多數生產者不合格的情況中,DPoS機制也是可以繼續運行的。DPoS機制在高強度和多變化的失敗條件下仍然保持極高的強健性,在共識算法中后來居上,吸引了越來越多開發者的注意。
2.3.5 其他共識算法
隨著區塊鏈技術的不斷發展以及各種數字貨幣的涌現,新的共識機制也不斷地被創造出來。下面介紹兩種比較熱點的共識機制。
1. 瑞波共識機制(RPCA)
瑞波共識機制(Ripple protocol consensus algorithm,RPCA)使得節點通過基于特殊信任節點達成共識。在Ripple網絡中,交易由客戶端發起,經過追蹤節點(tracking node)或驗證節點(validating node)對交易進行廣播,追蹤節點能夠分發交易信息并響應客戶端需求,驗證節點除了包括追蹤節點的功能外,還要對需確認的交易達成共識,也就是說,Ripple網絡的共識只發生在驗證節點中。
每個驗證節點都會維護一份可信任節點列表,稱為UNL(unique node list),系統默認信任列表中的節點不會聯合作弊。在共識過程中,交易需要接收UNL中節點的投票,投票超過一定閾值后便達成共識。具體共識過程大致如下。
(1)驗證節點接收待驗證的交易,結合本地賬本數據內容,對交易內容進行驗證,不合格交易會被直接丟棄,合法交易將匯總為交易候選集,候選集中還包括之前無法被確認而遺留的交易。
(2)活躍的驗證節點將自己的交易候選集作為提案發送給其他驗證節點,需要注意的是,參與共識機制的節點必須處于活躍狀態,驗證節點和活躍節點之間存在報活機制。
(3)驗證節點檢查收到的提案是否來自UNL中的可信任節點。如果不是,該提案可以被忽略。如果是可信任節點,對提案內容進行本地存儲。
(4)驗證節點對比可信任節點的提案內容和本地候選集,尋找交集,如果有相同的交易,那么該交易獲得一票。如果UNL中可信任節點數目為M,本輪交易認可的閾值為N(百分比,如50%),則每一個超過M×N個信任節點認可的交易將被該驗證節點認可;驗證節點需要在系統設置的本輪交易驗證計數時間之內,將所有被認可的交易生成可交易列表。
(5)驗證節點持續接收來自可信任節點的提案內容,并更新可交易列表,如果賬本中每筆交易都獲得滿足條件閾值的信任節點列表的認可,則共識達成,交易驗證結束。
共識遵循可信任節點的認可,就類似俱樂部會員中的核心會員,外部人員對于共識沒有影響力,對比其他共識機制,RPCA更中心化。Stellar恒星幣的共識機制(Stellar consensus protocol,SCP)便是在RPCA的基礎上演化形成的。
2. 授權拜占庭容錯算法(dBFT)
授權拜占庭容錯算法(delegated Byzantine fault tolerance,dBFT)是根據權益選出記賬人,然后記賬人之間通過拜占庭容錯算法來達成共識。該算法由小蟻(NEO)團隊提出,對比PBFT,白皮書中進行的改進包括:
(1)將C/S架構的請求響應模式改進為適合P2P網絡的對等節點模式。
(2)將靜態的共識參與節點改進為可動態進入、退出的動態共識參與節點。
(3)為共識參與節點的產生設計了一套基于持有權益比例的投票機制,通過投票決定共識參與節點(記賬節點)。
(4)在區塊鏈中引入數字證書,解決了投票中對記賬節點真實身份的認證問題。
機制將網絡的參與者分為兩類:專業記賬的記賬節點和普通用戶。普通用戶基于持有權益的比例進行投票選擇記賬節點,當需要通過一項共識時,在記賬節點中選定一個發言人進行方案的擬定,其他記賬節點根據拜占庭容錯算法進行表態,如果超過指定比例的節點同意該方案,則方案達成,否則重新選擇發言人進行方案的擬定。
這種方法的優點是有專業化的記賬人;能夠容忍任何類型的錯誤;記賬由多人協同完成;每個區塊都有最終性,不會分叉;算法的可靠性有嚴格的數學證明。但在白皮書中也坦言了現有算法的缺陷:當有1/3或以上記賬人停止工作后,系統將無法提供服務;當有1/3或以上記賬人聯合作惡,且其他所有的記賬人被恰好分割為兩個網絡孤島時,惡意記賬人可以使系統出現分叉,但是會留下密碼學證據。綜上來說,dBFT機制最核心的一點,就是最大限度地確保系統的最終性,使區塊鏈能夠適用于真正的金融應用場景。
這符合NEO團隊的定位,用戶可以將實體世界的資產和權益進行數字化,通過點對點網絡進行登記發行、轉讓交易、清算交割等金融業務的去中心化網絡協議。目標市場不僅是數字貨幣圈,還包括主流互聯網金融。小蟻可以被用于股權眾籌、P2P網貸、數字資產管理、智能合約等。