(四川省區(qū)塊未來科技有限責任公司 ,四川 成都 610000)
摘 要:介紹區(qū)塊鏈共識機制的基本功能,闡述工作量證明(Proof-of-Work,POW)和權益證明(Proof-of-Stake,POS)的基本原理,對比分析兩種共識機制的優(yōu)缺點——POW機制簡單、安全,但浪費能源;POS機制環(huán)保、共識快,但其安全性缺乏嚴格的數(shù)學證明。
關鍵詞:區(qū)塊鏈;共識機制;POW;POS
一般而言,在介紹區(qū)塊鏈時都會提到兩個核心要點:一是分布式賬本,二是拜占庭將軍問題(Byzantine Generals Problem)。使用分布式賬本目的是讓每個節(jié)點都能夠驗證交易,而拜占庭將軍問題與賬本的一致性有關,即本文要討論的共識機制(consensus)。
區(qū)塊鏈上的共識機制主要解決由誰來記賬,以及如何維護賬本統(tǒng)一的問題,該問題的理論基礎是拜占庭容錯(Byzantine Fault Tolerant,BFT)。拜占庭容錯從20世紀80年代開始被研究,目前已經(jīng)是一個被研究得比較透徹的理論,存在解的前提條件及具體實現(xiàn)都有現(xiàn)成算法。本文不打算從BFT說起,因為要分析的是區(qū)塊鏈共識機制的演進之路,而中本聰并沒有采用BFT,其實在筆者研究比特幣伊始,即便在理解了POW(Proof-of-Work,工作量證明方式)機制之后的很長一段時間,并不了解拜占庭將軍問題。下文在分析 HyperLedger Fabric的PBFT(Practical Byzantine Fault Tolerant)算法以及小蟻項目的DBFT算法時再全面闡述拜占庭將軍問題及傳統(tǒng)分布式一致性算法(PAXOS、RAFT)。
POW
其實“共識機制”一詞在這一兩年才被頻繁使用,以前一般叫證明方式(Proof),因為比特幣采用工作量證明方式(POW)。隨著大家對分布式賬本一致性問題的不斷探索,很多算法被提出來,尤其近期有很多項目回歸了對傳統(tǒng)BFT算法的改進,在算法思路上已經(jīng)跳出了“證明”的語義,進一步高度概括為共識機制。筆者記得第一次碰到POW這一概念時感到很費解,對這種表述方式很頭疼,掌握了POW機理后才真正明白其本意為“通過工作以獲得指定成果,用成果來證明曾經(jīng)付出的努力”。其實我們?nèi)粘9ぷ魃钪薪?jīng)常使用POW,比如學生考試成績、畢業(yè)證、駕照等,這種證明方式的一個顯著特征是往往需要很大的工作量才能拿到指定成果,且這個成果很容易驗證。之所以如此是因為我們一般很難去實時監(jiān)督一個人是否真的付出了這些工作量。
再回到比特幣的設計思路,中本聰已經(jīng)使用非對稱密碼解決了電子貨幣的所有權問題,用區(qū)塊時間戳解決了交易的存在性問題,用分布式賬本解決了剔除第三方結構后交易的驗證問題,剩下需要解決的問題是雙重支付,這要求所有節(jié)點賬本統(tǒng)一,而真正的平等又必須賦予人人都有記賬的權利,記賬是一件簡單的事情,每個人都可以做,顯然最終會存在眾多大同小異的賬本,而其實我們只需要其中的一個賬本就夠了。
中本聰想到給記賬加入成本,總賬本由各個分頁按照時間先后排序,給每個賬本分頁設立一個評判標準,以區(qū)分賬本分頁是否合格,這給記賬增加了難度,同時給每個賬本分頁加入一個隨機元素,用以調(diào)節(jié)記賬難度以保證一定時間段內(nèi)只有一個人生成合格的賬本分頁。增加的成本就是工作量,合格的賬本分頁就是工作量證明。對于比特幣而言,所謂的賬本分頁就是一個區(qū)塊,區(qū)塊通過巧妙設計形成區(qū)塊鏈,合格的區(qū)塊可以表述為
F(Nonce) < Target
其中Nonce是隨機元素,Target是合格區(qū)塊的量化,每個記賬節(jié)點的Target一致。Target根據(jù)過往一段時間內(nèi)的平均區(qū)塊間距時間與預期間距時間的差異來自動調(diào)節(jié)。此外POW的成功運行還需要配合如下兩條約定。
(1)Best chain原則:將最長的鏈條視為正確的鏈條。
(2)激勵原則:找到合格的區(qū)塊有獎勵收益。
第(1)條約定為硬性規(guī)則,所有人必須無條件遵守,畢竟大家共同的目標是找到一致性賬本,而最長的鏈條代表最大的工作量。如果沒有這條約定,每個人都只會構造自己的區(qū)塊鏈,無法統(tǒng)一。第(2)條為工作量激勵,既然記賬有成本,那唯有收益才能驅動大家都去記賬,參與記賬構造區(qū)塊變成投資行為,其成本和收益風險在第(1)條約束下形成博弈,驅動所有節(jié)點按約定規(guī)則老老實實地夠造區(qū)塊,最終達到納什均衡。
具體實現(xiàn)方式是比特幣采用哈希(Hash)算法。邏輯上比特幣是對整個區(qū)塊進行哈希運算,但真正實現(xiàn)并非將整個區(qū)塊數(shù)據(jù)作為哈希函數(shù)的參數(shù),區(qū)塊數(shù)據(jù)大體可以分為區(qū)塊頭和交易列表兩部分,如圖1所示。交易列表通過構造成Merkle樹最終濃縮成Merkleroot內(nèi)置于區(qū)塊頭,區(qū)塊頭只有6個字段,共80字節(jié)。如此設計的好處是方便哈希運算,每次運算只需要80字節(jié)的參數(shù)輸入,而不是整個區(qū)塊輸入。
比特幣采用SHA256哈希運算,且每次都是連續(xù)進行兩次SHA256運算才能作為最終結果,前一次運算的結果作為后一次運算的輸入,即Double SHA256,一般簡稱SHA256D,擴展上面的公式,比特幣合格區(qū)塊判斷依據(jù)如上:
公式(1)的各項參數(shù)釋義如下。
nVersion:版本號,4字節(jié)。
hashPrevBlock:前一個區(qū)塊hash值,32字節(jié)。
hashMerkleRoot:包含進本區(qū)塊的所有交易構造的Merkle樹根,32字節(jié)。
nTime:Unix時間戳,4字節(jié)。
nBits:記錄本區(qū)塊難度,4字節(jié)。
nNonce:隨機數(shù),4字節(jié)。
MAXTARGET:最大目標值,常量。
Diff:當前區(qū)塊難度,全網(wǎng)難度一致。
MAXTARGET/Diff即通常所說的當前目標值,可見難度Diff越大,當前目標值越小,找到一個合格區(qū)塊的概率就越小。
很顯然,POW的核心要義為算力越大,挖到塊的概率越大,維護區(qū)塊鏈安全的權重越大。相對其他共識機制而言,POW邏輯簡單,容易實現(xiàn),容錯達50%,其安全有嚴格的數(shù)學論證。
POS
POW缺點也很明顯,其中被指責最多的主要有兩點,一是浪費能源,二是風險和收益博弈必然導致聯(lián)合挖礦,而大算力礦池可能會對系統(tǒng)的去中心化構成威脅。
于是在2011年,一個名為Quantum Mechanic的數(shù)字貨幣愛好者在Bitcointalk論壇提出Proof-of-Stake(POS)證明機制,該機制被充分討論之后證明具有可行性。如果說POW主要比拼算力,算力越大,挖到一個塊的概率越大,POS則是比拼余額,通俗說就是自己的手里的幣越多,挖到一個塊的概率越大。POS合格區(qū)塊的評判標準可以表述為
F(Timestamp) < Target × Balance (2)
與POW相比,公式(2)左邊的搜索空間由Nonce變?yōu)門imestamp,Nonce本質(zhì)是無限的,而Timestamp極其有限,一個合格區(qū)塊的區(qū)塊時間必須在前一個區(qū)塊時間的規(guī)定范圍之內(nèi),時間太早或者太超前的區(qū)塊都不會被其他節(jié)點接納。公式(2)右邊的目標值引入一個乘積因子余額,可見余額越大,整體目標值(Target × Balance)越大,找到一個合格區(qū)塊的概率就越大。因為Timestamp有限,POS鍛造區(qū)塊成功率主要與Balance有關。
POS只是代表一種共識機制理念,具體有多種實現(xiàn)方式,下面重點解析兩種比較經(jīng)典的實現(xiàn)思路。
Peercoin
Peercoin(點點幣,PPC)于2012年8月發(fā)布,最大創(chuàng)新是其采礦方式混合了POW及POS兩種方式,其中POW主要用于發(fā)行代幣,未來預計隨著挖礦難度上升,產(chǎn)量降低,系統(tǒng)安全主要由POS維護。目前區(qū)塊鏈中存在兩種類型的區(qū)塊,POW區(qū)塊和POS區(qū)塊。PPC的作者為同樣不愿意公開身份的密碼貨幣極客Sunny King,同時也是Primecoin的研發(fā)者。
要掌握Peercoin的POS機制,需要重點理解Sunny King專門為PPC設計的幾個核心概念:Coinstake,Kernel,Stake Modifier,Modifier Interval,StakeReward,Coinage等。
Coinstake
為了實現(xiàn)POS,Sunny King專門設計了一種特殊類型交易,叫Coinstake,Coinstake的設計借鑒于中本聰?shù)腃oinbase設計。本質(zhì)上Coinbase和Coinsake都是一筆交易,只是對他們的輸入、輸出做了一些硬性限制,這樣才不會擾亂系統(tǒng)原有的POW機制。
(1)Coinbase結構要求:
(1)輸入數(shù)量必須等于1,且輸入的Prevout字段(指定前一筆交易的輸出)必須置空值。
(2)輸出數(shù)量必須大于等于1。
(2)Coinstake結構要求(如圖2所示)。
(1)輸入數(shù)量大于等于1,且第一個輸入的Prevout字段不能為空,即要求Kernel必須存在。
(2)輸出數(shù)量大于等于2,且第一個輸出必須置空值。
這兩種特殊交易在區(qū)塊鏈中存放的位置也有特殊要求,中本聰規(guī)定每個區(qū)塊的第一筆交易必須放置Coinbase,反之,Coinbase不能出現(xiàn)在區(qū)塊的其他位置。Sunny King顯然不想破壞這個規(guī)則,他增加了一條規(guī)則,對于POS區(qū)塊,第二筆交易必須放置Coinstake,反之,Coinstake不能出現(xiàn)在其他地方。換言之,只要第二筆交易是Coinstake,那么這個區(qū)塊就當POS區(qū)塊來處理。
Coinbase和Coinstake都不應該被單獨廣播,而只存在于區(qū)塊中,因此客戶端節(jié)點一般都不允許進入內(nèi)存池,當花費這兩種交易時,都需要檢測是否已經(jīng)成熟。
Kernel Protocal
Coinstake的第一個輸入(Input 0)叫Kernel,Kernel在POS機制里確實起到核心作用,合格區(qū)塊的判定與之息息相關。合格區(qū)塊表述為
SHA256D(nStakeModifier + txPrev.block.-nTime + txPrev.offset + txPrev.nTime + txPrev.vout.n + nTime)< bnTarget × nCoinDayWeight (3)
公式(3)中的每一個參數(shù)都有明確的設計目的。
nStakeModifier:專門為POS設計的調(diào)節(jié)器,按照以上公式,如果沒有參數(shù)nStakeModifier,當一個人收到一筆幣之后,他立即就能提前計算得知自己在未來何時可以鍛造區(qū)塊,這顯然不符合設計目標,Sunny King希望POS礦工和POW礦工一樣做盲目探索,以實時在線維護區(qū)塊鏈,nStakeModifier的設計就是為了防止POS礦工提前計算。nStakeModifier可以理解為POS區(qū)塊的一個屬性,每一個區(qū)塊對應一個nStakeModifier值,但nStakeModifier并不是每個區(qū)塊都變動,不過協(xié)議規(guī)定每隔一定時間(modifier interval)必須重新計算一次,取值與前一個nStakeModifier以及最新區(qū)塊哈希值有關,因此POS礦工無法提前計算,因為他不知道未來的區(qū)塊哈希值。
也就是說,在PPC系統(tǒng)中,除了存在區(qū)塊鏈、幣鏈(幣的交易簽名歷史),還隱藏著一個很少被提及的鏈條——權益調(diào)節(jié)器鏈條。
值得一提的是,Sunny King是在PPC后來的版本才加入這個調(diào)節(jié)器的,一開始他使用nBits。
txPrev:Kernel對應的前一筆交易。
txPrev.block.nTime:txPrev所在區(qū)塊的時間戳,一筆交易被納入?yún)^(qū)塊的時間是交易發(fā)起者不能確定的,節(jié)點有可能通過提前計算預估到未來對自己有利的時間戳,這個參數(shù)就是為了防止節(jié)點利用這種預估優(yōu)勢提前生成大批交易。
txPrev.offset:txPrev在區(qū)塊中的偏移量,用以降低網(wǎng)路節(jié)點同時生成Coinstake的概率。
txPrev.nTime:txPrev構造時間,設計目標如txPrev.offset。
txPrev.vout.n:Kernel在txPrev中的輸出下標,設計目標如txPrev.offset。
bnTarget:全網(wǎng)當前目標難度基準值,類似POW中的當前難度值,由nbits記錄。
nCoinDayWeight:Kernel消耗的幣齡,加入了一個時間權重。
從以上公式可以看出,Sunny King一方面希望能給所有POS礦工足夠的隨機性,另一方面,搜索空間始終控制在只局限于Coinstake的時間戳Time,影響找到合格區(qū)塊鏈最大的因素是Kernel消耗的幣齡。
節(jié)點在鍛造區(qū)塊時,首先從自己所有的UTXO中選定一個作為Kernel,構造Coinstake,計算hash,如果不合格,重新構造Coinstake,此時Time已經(jīng)改變,也可以改變Kernel,以得到不同的Coinstake,如此往復,直到找到合格區(qū)塊。
Coinage
上面提到了幣齡,也叫幣天,假如1.5個幣存在于區(qū)塊鏈中10天,幣齡數(shù)值為
Coinage = 1.5×10 = 15
PPC采用幣齡,而不是直接采用余額(Balance)來計算。
stakeReward
權益激勵,俗稱獲得利息,計算公式為
stakeReward = Coinage × 33 / (365 ×33 + 8) ×0.01 ×COIN
公式(4)可簡化為
stakeReward = (0.01 ×Coinage / 365) × COIN
其中,Coinage即上文說的幣齡,COIN可理解為“幣”,1 COIN即通常所說的1個幣,本質(zhì)是一個常量,中本聰在比特幣系統(tǒng)里定義為100 000 000,如此設計主要是為了避免浮點數(shù)運算,比特幣支持8位小數(shù)源于此。
由公式(4)、(5)可知,收益按輸入幣齡總和的1%年利率計算。
POS一并解決了POW浪費能源和算力集中兩個痛點,理論上還能縮短了共識時間,但同時也丟棄了POW的某些優(yōu)勢,因此更容易分叉,一筆交易需要等待更多確認才能確保安全,而POS最大的問題是其安全性和容錯性還沒有得到嚴格的數(shù)學論證。
(編輯: 彭遠紅 )
專欄作者簡介:周鄴飛,男,幣創(chuàng)網(wǎng)聯(lián)合創(chuàng)始人,技術副總裁,中國科學院智能控制博士生,DACA區(qū)塊鏈協(xié)會講師,小企鏈(icochain)研發(fā)者,參與《區(qū)塊鏈講義》一書撰寫,最早一批熱衷區(qū)塊鏈的技術極客,對比特幣、區(qū)塊鏈及智能合約有深入研究,zhouyefei@bichuang.com。