關于共識機制的討論已經有許多,但這些分析大多不全。在碳鏈價值舉辦的「碳話」線下沙龍第一期活動中,Conflux研究總監楊光博士用一萬三千余字,全面分析了POW與POS共識機制的原理、運行時遇到的問題,以及兩者的優劣比較。
首先給大家簡單介紹一下我們的 Conflux 團隊:我們團隊的核心是姚班的幾個同學以及師弟,并且有幸請到姚期智先生擔任我們的首席科學家和顧問。我們之所以投入到區塊鏈這個行業中來,是因為這個行業里邊有很多非常重要也很有意義的新問題——以我最熟悉的密碼學和博弈論為例,區塊鏈面對的和要解決的很多問題已經是學術界最前沿的研究方向了。這些問題不是單靠工程師就可以解決的,而是需要更多學術界的力量參與進來,大家一起合作才能推動整個區塊鏈行業往前發展得更好。
1. 女巫攻擊與區塊鏈共識協議
今天我來講一下 PoW 和 PoS 的對比。我們先來回顧一下最典型的區塊鏈共識協議:大家把交易打包成塊,通過哈希引用把塊連接成一條鏈,就得到了一個共享的賬本。但是直接這樣用一個賬本肯定是很不安全的,因為壞人也可以造一個賬本,然后把兩個賬本同時擺在你面前,哪個是真的哪個是假的,我們應該相信哪一個,這就成了一個問題。
如果是中心化的,當然這個問題非常好解決——我用支付寶,支付寶說我賬戶有多少錢,那就是多少錢。如果和事實不一致的話,我有不同意見可以去法院告他。但如果是去中心化的,這件事就很難說了。去中心化的時候,大家沒有一個這樣一錘定音的機構,需要通過其他方式達成共識,才能有一個公正的賬本。那么在去中心化的環境下,應該怎樣做共識呢?一個很容易想到的辦法就是我們投票,大家共同投票,投出來一個賬本,然后都相信這個就行。
但是,既然說到投票,那么首先就有一個投票的公平性問題:投票權要怎么分配?比如今天我們大家一起投票,然后我手里有一百票,在坐的各位每人一票,我們這個不叫投票,我有一百票,基本上我說什么想投什么,結果就是什么樣的。如果我們真的想達到一個共識,就不可能用這種特別不公平的方式去投票。所以投票權的分配是共識協議里面最核心最重要的部分之一。在線下投票權分配的問題其實比較容易解決:我們就簡單的一人一票即可。大家都有身份證,然后投票的時候登記一下就行了。但是線上的話,要想實現一人一票就非常困難。
首先,你在線上的環境中,特別是去中心化的環境中,如何定義「什么叫做一個人」,這就是一個很大的問題。你是把一個賬戶當一個人還是一個ip當一個人,還是說你用別的什么方法去確定?在網上的話,大家都是以匿名的方式存在的,你在聊天的時候,你甚至都無法判斷網絡另一邊跟你聊天的到底是一個摳腳大漢還是一條狗。因此,我們就需要一個抗女巫攻擊的機制。
我們先簡單講一下什么是女巫攻擊:它是說攻擊者可以低成本地制造很多賬戶,然后控制這些賬戶一塊兒去行動,讓別人看上去以為人多勢眾的樣子。 比如說在論壇上大家會見到有水軍引導輿論,再比如電影評分的網站也會有人專門去組織去在上面刷評論刷分。如果說有很多這種水軍馬甲的賬號在攻擊的話,你最后投票得到的結果就不是真實的。有可能某個人通過這種方式投出非常多的票,最后投票的結果就是完全受這一個人控制的。在傳統的互聯網環境下,我們有很多對抗女巫攻擊的方式,比如增加每個賬戶的注冊成本。大家在網上要注冊一個賬號的時候,常常需要輸入一個驗證碼,這件事就是計算機實現起來比較麻煩,即使能寫程序做也比較困難,但人去做的話就很簡單;還有的網站注冊的時候要求綁定一個手機號,或者檢測ip地址,這都是比較常見的抗女巫攻擊的方式。但是在去中心化的環境下,以上那些方式就不好用了。因為去中心化的環境下,誰去發布這個驗證碼,誰去判斷驗證碼填得對不對?然后誰去驗證手機號?即使用ip地址的話,其實也是一個非常不公平的方式。因為我們知道并不是每個人都平等地享有一個靜態的ip地址的。
所以在區塊鏈中,我們實際上用到的解決方案最常見的就是一個工作量證明(PoW),一個是權益證明(PoS),后者包括代理的權益證明(DPoS)。還有一些其他的證明方式,比如說證明你擁有多少空間,或者證明你燃燒了多少貨幣,還有別的一些方法,但是目前最主要最常見的還是 PoW 和 PoS 這兩種。這里我還要稍微強調一下,無論 PoW 還是 PoS 或者別的什么 PoX,都是抗女巫攻擊的機制,是共識算法(協議)里邊一個重要的組成部分,但它們本身不等價于共識算法。
2. 工作量證明
接下來我先講一下大家都比較熟悉的工作量證明。
工作量證明的基本思想就是算力決定出塊權。如果你能解出一個 PoW 計算難題,你就可以出塊。粗糙地概括下,可以理解為一個CPU一票,或者一個GPU、一臺礦機一票,大概是這么個意思。它的好處首先是這個系統是無許可的。參與者不需要任何人許可,只要有機器有算力就可以參與——理論上甚至都不一定需要機器。如果說你可以手動算出一個區塊的哈希,并及時把這個上傳上去,別人也會承認這是一個合法的區塊。還有一個是PoW投票行為本身成本是比較高的,不管用CPU、GPU還是用礦機,機器的成本和電力的成本,都是要實打實地花出去的。這就跟我們之前說的驗證碼,其實形式上有一點像,對吧?有一些驗證碼,人看了以后還是要花一點時間去識別里邊的數字或者字母到底是什么,然后才能打上去通過驗證。工作量證明一個最大的優點,我認為就是所投的票和投票權是綁定的:一旦投票成功以后,即使是投票者本人也修改不了投票的內容。
按照工作量證明的一般邏輯,投票的時候需要先打包出一個塊,然后再對這個塊做工作量證明,如果做出來證明就相當于投出去一票,但是這個時候打包的塊已經沒有辦法修改了。例如我的礦機跑一天可以投出很多票,但是如果我想把之前一天的算力集中到新的一個塊上,這是辦不到的;另一方面,如果我想要回滾掉自己出的塊,我也必須付出和回滾別人的塊時候所需的同等的算力。這是PoW一個特別好的特點。
當然基于PoW機制去做共識算法也有一些缺點。首先這個缺點就是延遲比較高,因為我們把交易打包到區塊以后,這個區塊不是馬上就成為一個有效的候選區塊的,至少還要完成一個工作量證明這個區塊才能稱為候選區塊。這里工作量證明的時間不能設得特別短,等一下我會講為什么不能太短。于是,至少從打包好區塊到做完區塊的工作量證明這一段時間內,你這個交易是不可能被人確認的。所以說即便比特幣不是等六個塊確認,而是看到一個塊就確認,確認一筆交易平均也要等十分鐘時間。PoW機制另一個被人詬病的點就是能耗特別高、不環保。對于這一點,工作量證明的能耗是否必要,我覺得是見仁見智的,可以持保留意見。但是我們既然是在談工作量證明,那么這個工作量怎么也是沒辦法省掉的,如果省掉的話它就叫別的名了。
我們看一下如何解決基于PoW的共識的主要問題。
第一個是說確認速度慢。以比特幣為例,出一個塊平均要十分鐘,確認的話還要再等六個塊,就平均要一個小時。第二個是吞吐量比較低,大家都很清楚,比特幣在這點上已經被人批評好幾年了。然后第三點就是能耗高不環保。但是第三點,既然我們要用PoW,這點能耗是避免不了的,所以我們也就不想著去解決這個問題了。
對前面兩個問題,確認速度慢和吞吐量低。其實這兩個問題看上去都有一個很簡單的解決方法——降低PoW問題的目標難度,提高出塊速度。實際上萊特幣就是這么做的。它把目標難度從比特幣的10分鐘降到2.5分鐘,然后一下子出塊速度就比特幣快四倍。還有一個提高吞吐量的方法就是增大塊容量,比如BCH就把每個塊從1M先擴大到8M,然后又擴大到32M,甚至后來還有提議說要改到128M。很直觀地,同樣的出塊速度下,塊越大吞吐量也就越大。
是不是這么簡單就可以解決比特幣確認速度慢和存儲量低的問題呢?當然不會。要真這么簡單的話,比特幣也不會現在是十分鐘1M的設定了。為什么剛才說的方法不能解決問題呢?因為當我們出塊速度快了以后,區塊鏈就會很頻繁地出現分叉,特別是當你出塊的速度超過廣播速度的時候,分叉的情況就會特別嚴重。
如果我們降低PoW問題的難度,提高出塊速度,然后增大區塊容量,實際上在網絡條件一定的情況下,肯定是會降低廣播速度的。因為區塊越大,廣播得就越慢。然后如果說你出塊速度快但是廣播速度慢,也就是說我在收到別人新出的一個塊之前,自己也能挖到一個塊,這樣的話就會出現分叉。然后如果說這個差距比較大的話,分叉就會特別多。
分叉多了以后有什么不好?最大的不好就是會降低安全性。在比特幣里邊我們常說壞人攻擊需要51%的算力。 這個前提是說好人都集中在一條主鏈上。這樣的話,好人有49%集中在上面,壞人有51%才能攻擊。但如果真的出現這種頻繁分叉的情況,比如說我在分叉A上有30%的算力,在分叉B上有40%的算力。這個時候壞人想把分叉B給回滾改到分叉A,它不需要很多,它只需要11%算力就可以。只要比全世界的誠實的算力最多的兩個分叉之間的差稍微多一點,攻擊者就可以讓最長鏈在這兩個上面分支上跳來跳去。所以如果真的簡單粗暴地去改比特幣的參數,最后安全性肯定會降低。
但是我認為這個安全性降低其實不能怪PoW。PoW在這里邊只是一個抗女巫攻擊的機制,而且它的難度是可以調的。這里安全性降低的罪魁禍首這個鍋得讓“最長鏈”而不是PoW去背。為什么會分叉多安全性低?其實是因為比特幣采用了最長鏈共識。在最長鏈機制下,如果出現分叉,誠實的算力很可能會跟著分叉,也就意味著誠實的人投票就會分叉,這樣的話壞人就更容易操縱最后的結果。
然后下一個問題:基于PoW的最長鏈共識為什么會分叉?是不是說如果大家都是好人,就不會分叉?
這個也不是的。我們用圖里邊每條線表示是一個節點,向右的這個箭頭表示的是時間。當這個節點產生一個區塊的時候,它需要把區塊廣播出去,但是廣播出去要消耗時間,所以會形成一個“事件光錐”。距離產生區塊的節點越遠,收到廣播過去的區塊所花的時間也越久,相應的要等到更晚的時間以后才能看到剛才生成的新區塊。也就是說只有在這個黃色區域及以后其他的節點才能看到你這邊產生的一個區塊。既然有光錐,相應的也就有光錐外的區域,也就是圖上綠色的部分。當一個節點處在這個光錐外區域的時候,他是不可能知道你這邊剛剛產生了一個區塊的,因為還沒有廣播過來。也就是說,如果網絡里產生的下一個區塊是在后邊黃色的這部分,那么當然很安全,因為這個時候所有的節點都看到最新的區塊了,然后他們再生產區塊都會跟在后面就不會出現分叉——如果大家都是好人的話。
但是如果說出塊的速度比較快,我在綠色的光錐外區域就產生區塊,那就必然會出現分叉,然后最后會出現孤塊,對吧?因為這兩個區塊互相都是不可能引用的。所以簡單的來估計一下,孤塊率大致是等于光錐外這個區域的面積除以期望的出塊間隔的總面積。因為出塊的事件在期望的區塊間隔內是以相等的概率隨機出現的。另一方面,綠色的光錐外區域面積所占的比例越小,就表示出現孤塊的可能性就越低。
但實際中我們肯定不會只有四個節點,我們節點會非常多,而節點多了以后,廣播的時間自然就會變長。廣播的時間變長,就意味著光錐外的區域面積會變大,我們的出塊間隔也需要變長,這樣才能保證孤塊會被控制在一個比較小的范圍以內。因為其實孤塊本身也是對安全性有影響的,比如有20%的孤塊率的話,只需要41%而不是51%的算力就可以完成攻擊了。因此,為了提高安全性,為了降低孤塊,我們必須拉長出塊的間隔。比如比特幣就定在了十分鐘。這個十分鐘當然不是完全不能改的,只是改過以后安全性肯定會受到一點影響。
拉長出塊間隔以后,整個系統的效率都會降低,特別是對吞吐量造成的影響很大。我們在這兒看一下整個系統的帶寬,其實可以把它分成三部分:一部分帶寬(藍色部分)是大家在傳輸最終會加到共識里邊的交易;還有一部分帶寬(紅色部分)是大家在傳輸一些不加入共識的數據,包括整個協議的開銷,還有一些可能是最終沒有被加入共識的作廢的塊和交易;最后一部分(白色),就是沒有被用到浪費掉的帶寬。如果說我們用 PoW 做抗女巫攻擊機制,再用最長鏈的協議去計算最后的共識的話,我們對帶寬的利用率其實是非常低的。
以比特幣為例,我們600秒產生1MB有效的區塊,期望600秒才有1MB有效的這一塊,就算我這一個區塊再擴大幾次,整個網絡里面600秒的時間,我有效利用的存儲的信息量可能還不到20MB吧?但現在網絡的平均速度已經是600秒傳幾個GB了。所以它對整個網絡帶寬的利用率也就在1%左右,浪費還是非常嚴重的。如果說我們用一些技術把廣播的速度變快,比如說用致密區塊的技術,那么綠色的光錐外的區域這段時間就會變短。這樣我們也就可以等比例地把出塊間隔也縮短,在保持和之前相同的安全性的同時把帶寬的利用提高一點。但是即使是這么提高,只要我們是用最長鏈并且要控制孤塊率,帶寬的利用率依然高不到哪兒去。一般來說,一個公鏈網絡可能會有幾千甚至上萬個節點,如果要廣播的話,平均可能要十次甚至更多次轉發。以需要十次轉發為例,從出塊的這個節點開始,發送給下一個節點,然后這個節點接受到區塊并且驗證過以后再發送給下一個節點,就這種過程要重復十次。在這十次轉發的全過程以內,如果我要降低孤塊率,就需要全網別的節點不要在這段時間內產生第二個區塊,或者說只有很低的概率產生第二個區塊。也就是說,這么長的時間,大家其實只在廣播一個區塊。第一個人傳給第二個人以后,第二個人傳給第三個人的時候,第一個人就處于一個閑著的狀態了,對吧?所以最終的帶寬利用率自然不高。可能會比之前有一個常數倍的改進,但也是遠遠不可能把整個帶寬用滿的,能用到1/10就已經算很不錯了。
既然這樣的話,如果說我們想避免分叉,不可避免的帶寬就用不滿,帶寬用不滿的話,TPS就不可能高到哪去。因為你一共同步的數據就那么多,那它里邊能放的交易就是有一個上限的——如果交易的尺寸不變的話(交易尺寸縮小也是可以提高TPS的,但是其他所有區塊鏈也可以用同樣的技術,相對的劣勢依然不變)。
其實剛才要解決的問題,就是說出現分叉以后誠實算力不集中,會降低安全性。但這個解決方案并不是說只有降低分叉概率這一種方案去解決。比如我們也可以用基于 DAG 的有向無環圖去解決。
以太坊選擇分叉的時候用的不是最長鏈而是 GHOST 協議。其實以太坊用的是一個稍微修改過的版本,這個協議核心思想是遇到分叉時候選擇擁有最重子樹的分支而不是有最長子鏈的。這樣的話就不管你有沒有分叉,有多少分叉,安全性的問題都不大。因為即使是分叉的誠實的礦工,依然會對之前的選擇貢獻安全性。比如說礦工在靠后的一個區塊分叉,但是對于分叉之前的某個地方的分支應該如何選擇,礦工依然是貢獻安全性的。它會在應該選擇的分支的子樹上貢獻一個重量。
但是 GHOST 協議有一個缺點:雖然說它可以把帶寬用得比較充分,但同時浪費也很嚴重。 因為那些最終沒有被確定在最重子樹那條鏈上的區塊,它們里面的交易都是不算數的。大家挖到了一些區塊,但是最后都沒有加入共識,這些區塊的吞吐量就被浪費掉了。而我們的Conflux 其實和 GHOST 用了比較相似的方式去確定一條樞軸鏈,等確定好以后,我們再把所有的區塊排一個順序,這樣所有區塊里邊的交易都會對整個系統的吞吐量作出貢獻。當然排過順序以后,還需要把里邊有沖突的或者重復的交易去做一些處理,沖突的交易肯定不能都執行。如果我們從帶寬的角度去解釋的話, GHOST 這個協議可以把帶寬利用得非常好,但它整個系統的開銷比較大,因為傳輸過很多沒有被加入共識的區塊,會浪費掉一些帶寬。
Conflux 雖然說也會有一些重復的交易,但是因為它對整個帶寬的利用比較充分,而且在這個前提下,有效的帶寬利用率也遠比 GHOST 更高,所以就可以把整個系統的吞吐量提高。如果做對比的話,由于比特幣的總帶寬利用率特別低(~1%),所以即使它再怎么降低協議開銷,吞吐量上跟 Conflux 的差距依然非常明顯。
這些是關于PoW的一些簡單的介紹,下面我們再看一下權益證明。
3. 權益證明(PoS)
權益證明基本的思想是:當你持有幣(有時人們也管這個叫 stake),你就有記賬權,然后有投票權。你的投票權和你持幣的數量是成正比的,這就是一個幣一票。簡單來說,就是錢越多,投票的權力就越大。
PoS 協議的基本框架是按所有的參與者的持幣量,去分配打包權和投票權。在PoS的系統里邊打包和投票兩件事是分開的,它也可以分開——PoW 系統里這兩個其實是一回事兒。分配完打包權以后,拿到打包權的人就有資格出一個候選區塊。這個區塊里面包含要處理的交易,并且有他自己的簽名。候選區塊并不意味著就會被加入共識,在廣播候選區塊以后還需要由那些有投票權的人去投票。
投票的形式可以就是在被投票的區塊上做個簽名。在投票后得到比較多票支持,候選區塊才會最終被加入共識,變成一個有效的區塊。當然投票的過程我們可以用很多方式執行,比較常見的就是可以用一個少數服從多數的共識算法去做。因為現在我們知道一共有多少人有資格投票、一共有多少票,所以用這個共識算法我們很容易算出來多數,比如超過1/2或者2/3。這一點跟 PoW 非常不一樣,因為在 PoW 系統里你根本不知道全網的算力有多少,只能靠估計,而且一般還估計不準。所以 PoW 系統里不可能說用一個確定的閾值去判斷什么是多數。
在去中心化機制中,我們需要選舉誰負責打包,誰負責投票。有時候為了效率,大家會先選舉一個比較小的委員會,然后由他們負責投票。如果不是用代理權益證明的 DPoS 機制的話,這樣的委員會通常是隨機選取的,而且為了公平性還要經常輪換。
在 PoS 系統中,如果檢測到有的參與者違反了 PoS 共識的協議,就可以對他們做出一些懲罰。比如有的人把自己的一票投給很多個塊,或者說他有票,但是就是不投,這些會對系統的安全性造成影響的行為都可以懲罰。
我們再來看一下權益證明的優點是什么。
第一個優點:礦工和持幣者的動機是一致的。PoS 的礦工都必須持幣,在整個的生態環境里減少了一個不持幣但靠機器來挖礦的角色。在 PoW 的社區中,經常會出現有錢人、開發者、以及礦工三方的利益不是完全一致的情況,然后就會吵,以至于最后很多事很難辦成。到了PoS 中,現在至少礦工和資本家的利益會更為一致,一定程度上減少了沖突和分歧。
第二個優點:PoS 的延遲可以做得非常低,確認可以非常快。在 PoS 系統里,拿到一個交易就可以馬上打包,打包以后就可以廣播,這個時間是不需要等待的,不像 PoW,必須等至少做一個 PoW 問題的時間。實際上,PoS 共識的延遲主要是受限于網絡和參與投票的人數。因為你投票的人越多,肯定要等的時間也就越久。
第三個優點:PoS 比較環保,因為它不需要做工作量證明。投票實際上就是做個簽名,最多再做一些簡單的運算,比求解 PoW 難題容易多了。
但它的缺點也是跟上面相對的,PoW 系統的一些優點它失去了。
第一,與無許可的 PoW 系統相比,PoS 的系統在匿名性和許可性上稍微差一些。因為我作為一個人,我要加入一個 PoS 的系統,想進去投票,我首先要持有幣。這個幣我是不可能通過其他方式得到的,我必須跟已經有幣的那些人去做交易,他們把幣給我以后我才有權利。這就不像 PoW,只要拿一臺機器接入系統,就可以直接挖到幣。
第二,投票行為本身成本非常低,只需要做個簽名就可以生成一個有效的投票。這樣的話在安全性上會有一些問題。比如 PoS 系統常見的無利害攻擊問題。
另外,投票權可以復用,可以轉讓,這也是不好的。如果我把自己的私鑰賣給別人,那么我以前投出的那些票,在歷史上每個分支做出的選擇,這時候拿到我私鑰的人,他都可以再去投一遍。可以重復使用以前的投票權會在安全性上帶來一些問題。等一會兒我們講到長程攻擊的時候再詳細討論。
還有就是投票機制帶來的一些問題。剛剛我們說了 PoS 共識的優勢是確認快,可以做到不分叉,但這個不分叉的前提是需要假設大多數節點是誠實的。這里說的有2/3以上的節點誠實,實際上嚴格來說是要求2/3以上的幣和投票權都在誠實的人手里,壞人只有不到1/3的投票權。——這樣對于一個得到2/3以上投票的塊來說,就算是有一些壞人可以給不同的塊投票,他們聯合上剩下還沒簽名的好人,全加在一塊也不會超過2/3。這樣的話只要有足夠多的節點簽名,且整個系統里大部分節點都誠實的話,這個系統就完全不會分叉,又可以做得非常快,大家確認得也會很快。例如 EOS 現在就實現了出塊很快,確認很快。
但是 PoS 共識的話也有一些新的問題。
第一個就是通訊復雜度跟投票的人數相關,而且通常是平方的關系。參與投票的人數越多,通訊越復雜,然后大家要等的就越久。就像是如果說我們要一人一票選一下美國總統,整個投票的過程就非常復雜非常慢;而政治局里邊投票決定一件事就快得多,因為他們人少。
還有一個PoS的共識的比較本質的問題,就是投票權的決定時間是早于生成候選區塊的。在有這個區塊以前,我就知道誰有投票權、誰沒有投票權了。因為投票權的決定方式,所以實際上決定投票權和行使這個權利的動作是分離的,沒有綁定在一起的。我拿到投票權的時候,別人誰也沒有辦法說,就規定我這個票必須投給誰。所以拿到投票權以后,我可以隨便地去投,而不會因為我投票的行為決定我有沒有投票權。但這樣的話投票權使用是更靈活了,也意味著我可以選擇的策略空間更大,整個博弈會變得更復雜。通常來說,策略空間大對于安全性是不好的,因為給攻擊者留出了更大的操作空間。一個誠實的人通常只會按照規則去,他每一次就確定了做一個動作,但是攻擊者如果操作空間大,能干的事兒就很多了,想保證安全性也會變得更難。結果就是在 PoS 系統里面會有更多的攻擊方式,比如無利害攻擊、長程攻擊等。
那么為什么在 PoS 系統里,我們不能像在 PoW 系統里那樣,先生成區塊,然后再決定投票權呢?因為我們需要確保對投票權大家是有共識的。不管投票者把票投給哪個候選區塊,對于誰有權投票,是必須確保所有人都知道的。不然的話就會有可能退化成類似于 PoW 的情況——這個在 PoS 系統里邊叫 stake grinding,就是說每次嘗試產生很多新的區塊,然后從這些區塊里挑選對自己最有利的一個廣播出去,然后由這個區塊去決定后邊的投票權。如果真的先出區塊,后決定投票權,我們就可能會看到一個分叉分出去若干個分支,然后每一個分支的區塊后邊都跟著一個親友團一樣的委員會,親友團里邊多數人都說這個區塊是對的。但是因為每個區塊后邊跟著親友團都不一樣,他們再怎么投票也還是達不到整個系統的共識。
還有一個 PoS 共識的問題,就是需要假設大部分節點是誠實的。“誠實”這件事兒一般是在密碼學里邊提得多一些。但是在博弈論和經濟學里面,很少會說一個人是誠實的,更多是說一個人是理性的——如果說謊可以多賺錢,很多人會選擇說謊。所以說,如果假設這些節點都是誠實的,實際上是一個非常強的假設。意味著他們即使能夠通過說謊、通過做惡多賺錢,也依然會選擇遵守協議。這點還需要看具體協議,對誠實要求到什么程度,才能知道它是不是一個合理的假設。
下面我來講講如何解決 PoS 共識帶來的這些新的問題。
第一個是說通訊復雜度很高的問題,這個其實是最容易解決的。大家可以隨機選取出一個比較小的委員會,由這些人作為代表負責投票,或者也可以用代理投票,就是我把我的票先投票去選一個代表,例如 EOS 里邊的超級節點,然后這些選上的代表再代替我去投票。這樣的好處就是實際參與出塊共識投票的人數比較少,可以降低投票的復雜度。現實中的人民代表大會、國外的議會或者陪審團,都是用到了類似的邏輯。
然后如何對抗攻擊呢?一個方式是我們假設大多數人都是誠實的,再假設網絡有非常好的同步性——即廣播出去一個區塊以后,在一段確定的時間內,比如說一分鐘或者30秒內,整個網絡絕大部分節點都可以收到。在這個前提下就非常容易做到共識。但是這樣的假設實際上是非常強的,現實中并不容易保證。如果說我們要解決某一個攻擊的問題的時候,直接假設這個攻擊不存在,然后問題解決了,這肯定不是一個讓人信服的方法。
我們再來討論一下幾種比較常見的針對 PoS 系統的攻擊方式。
第一個是無利害攻擊,其實也就是一票多投。如果說在一個 PoW 的系統里邊,礦工看到有兩個區塊這樣的分叉,他的算力只能跟在一個后面去挖,不可能同時在兩個后面。當然真要同時挖兩個塊的話也不是不行,只是那樣就意味著分配到每個塊上的算力肯定是要減少的,兩邊挖礦的算力加在一起是一個定值,所以一般不會有人這么干。在PoS的系統里邊就不一樣了:我看見左邊有一個分叉,好,我給他投一票;看見右邊有一個分叉,我又投一票。這樣不管哪個分叉稱為共識,我都可以分到投票的獎勵。這樣的話壞人就很開心。壞人說反正我做一個分叉,你們這些理性的礦工也都會給我投票,那么我只要比剩下那些“不那么理性的好人”掌握的投票權多一點就可以把之前的主鏈給回滾掉。這樣的話就很不安全。
對于無利害攻擊,常見的對抗方式是說一旦檢測到這種一票多投的行為,就對這種人做出一個懲罰。你如果真的一票多投,別人可以拿到你投票的信息,然后提交到鏈上,說“這個人一票多投了,扣他錢”。但是這種方法實際上也可能會遇到一些問題,就是有可能會出現我在兩邊一票多投了,但是最后只在一邊會被扣錢,但在另一邊有可能會得到更大的收益。
還有一個是賄賂攻擊。投票的時候,大部分參與者實際上都更接近理性人。比如說你持有一百塊錢,每次投票的收益是一塊錢,然后我跟你說只要你把票投給我的這個區塊,我就給你兩塊錢。可能很多人都會接受我的提議。這樣的話,壞人可以用非常低的成本,去買到更多的票支持自己的分支,比如說用兩塊錢買到相當于一百塊錢資產的投票權。這肯定會對安全性造成影響。現在對賄賂的問題已經有一些解決方案了,雖然還不是特別完美,但是已經比較讓人信服了。比如像 Algorand 提出解決的方案,就是投票權的分配是通過私有的隨機數去算的。在投票者把這個投票權的證明公開出來以前,大家都不知道到底哪些人有投票權。這樣的話,至少在投票之前不會有人知道我有投票權,他們也沒辦法來賄賂我。公開投票以后,因為 Algorand 的方式是每完成一輪投票就把委員會所有的人全都換一遍,然后重新選一批人去投票,所以在別人知道我有投票權的時候我的票已經投出去了,沒辦法再去賄賂去修改了。這里對共識參與者的誠實性有一個比較高的假設:不能說我有投票權以后就跑到網上到處問,我有哪些輪次的投票權,有沒有人要出錢買。現實中如果真的有人大規模的去問這件事,其實很容易被社區發現,大家就會知道有人在做這種攻擊了,也就比較容易做出應對。所以這至少是一個降低被攻擊風險的方法。
還有一個是關于長程攻擊的安全性。這個說的是什么呢?就是說A在創世區塊有20%的幣或者20%的股權,他就可以在正常的區塊上出塊去投票。然而,A可以在某個時間把他在鏈上的幣全都賣掉,也就是套現跑路。現在他在鏈上沒有任何錢,以后別人不可能在鏈上懲罰他。這時候他把自己的私鑰賣給攻擊者。攻擊者可以去收購A的,B的、C的、很多人的很多私鑰。收購到那些私鑰以后,這些私鑰在創世塊里面控制的權利可能是超過50%的,甚至超過80%都有可能。然后攻擊者拿到這些私鑰以后再做出一個惡意區塊,代替A,B,C 他們各投一票支持惡意區塊。
在第三方看來,這個區塊和真正的主鏈區塊看上去都是同樣合法的,因為都有很多人去投票。如果壞人的這條鏈足夠長,以后新加入的人會發現現在有兩條鏈,每一條都是有很多人投票投出來的,我該信哪一個?這時候共識已經出現問題了。所以怎么應對這種攻擊呢?一種方法是說要保證一個弱活躍性,即要求每一個誠實的礦工至少隔一段時間就上去看看,同步一下最新的狀態。如果有人告訴你說你那個狀態不對,應該從一年前的某一個狀態分叉過來,通常來說你不應該接受這樣的一個建議,因為回滾的時間太久了。
還有一個方式就是鎖定押金,然后再加上回滾的長度限制。以太坊的 Casper PoS 協議里邊就是這么設置的。如果你非要把用于投票的錢賣掉,可以,但你必須要等一段時間。這個時間足夠久,久到等其他的人再看到你用之前的投票權去投票的時候已經不會承認了。因為別的人已經跟著合法的鏈往后走很遠了。這個是以太坊的解決方案。
Algorand 在這一點上解決的方案是,既然你們是誠實的,作為一個誠實的人,你每一輪投票以后,你應該把當輪投票用的私鑰刪掉,在你刪掉了以后,就不會有人再拿這個私鑰去干壞事。這個解決方案說得沒錯,但是它對參與者的道德水平提出了比較高的要求。
基于 PoS 的共識系統還有一些其他問題。通常我們如果選擇一個小的委員會,如果不用 DPoS 的話,在 PoS 系統里我們需要隨機地去選。PoW 投票里的隨機性主要是由大家分布式并行挖礦時候的運氣帶來的,因為求解 PoW 問題本身有內在的隨機性。但如果說我們要用隨機性去選擇一個投票委員會的話,就又要解決一個新的問題:怎么樣去產生一個公平的隨機數?
如何產生公平的隨機數在密碼學上也是一個討論了很多年的問題,目前也有相對比較好的方案去解決。這個方案雖說不能產生絕對均勻的完美的隨機數,但偏差可以控制到一個范圍以內。另一方面,產生完全均勻的完美的隨機數是很難辦到的。因為我們知道,如果有 2/3 以上的幣攻擊者就可以完全控制整條鏈,產生的隨機數也可以隨便挑。所以你如果有 67% 的幣就可以控制百分之百的隨機數,那么有10%的幣能控制個 11% 的隨機數聽起來也不是特別不可接受。其實基于 PoW 的比特幣也有類似的性質:比如說有 51% 的算力就可以控制鏈上百分之百的收益;少一些的話,實際上有百分之二十幾算力就可以通過自私挖礦,獲得比實際算力所占的百分比高一點的收益。這是一個非線性的關系,但是只要它不是偏離得太多,大家一般還是勉強可以接受。
PoS 共識的安全性假設是比 PoW 要強的。PoW 我們要求是要有51%以上的誠實算力,PoS的 Algorand 他們對 Staker 的要求是 80% 以上的錢控制在誠實的人手里,而且這些人需要非常誠實:他們不會提前告訴別人自己有投票權;投票以后要把當輪的私鑰刪掉,不能賣給別人;而且他們還必須定期上線去同步一下狀態,算一下接下來的一段時間內自己是不是有投票權,如果有的話還要按時上線投票。如果像我們現在很多人那樣,錢存在銀行后就不管了,不到花錢的時候就不會去登錄系統,那么壞人只要在最后實際投票的活躍的人里邊超過一定的比例就可以了。不活躍不投票的人實際上不對安全性產生任何貢獻。當然即使一般的 PoS 至少也會要求 2/3 以上的多數錢是掌握在的誠實的人手里,而且還要有一定的對于活躍性的假設或者說要求。至少誠實的人要經常上線去看一下,去投個票什么的。
另外,基于 PoS 共識的系統在啟動的時候會有一些問題。因為一個項目往往剛開始啟動的時候,是它的資產分布的最不去中心化的時候。就像比特幣剛開始的時候,中本聰會有很多的幣。如果是 PoS 的系統,他一個人就可以完全控制整個系統。其他項目的開發團隊以及早期的幾個大的投資機構,可能就已經拿到大部分的幣了,他們對 PoS 的話語權會變得非常非常大。所以如何啟動一個 PoS 的公鏈也是一個比較大的問題。EOS 啟動前也是花了很久時間才做得比較好的。所以對于這一點,我們團隊認為至少在項目啟動的時候,用 PoW 是比 PoS 要方便很多的。PoW 方式才能做到無許可,然后一開始的幣在發行的時候也會比較公平。
最后,雖然 PoS 可以檢查一些違規行為,然后在鏈上對這些人做懲罰,但是有可能攻擊者的利益并不全在鏈上,他在鏈下還有其他的收益。比如說我在以太坊上發起攻擊,在上面被懲罰損失很多以太幣;但是同時幣價也很可能會降低,如果我在另外的市場做空以太幣,就可以通過做空得到更高的收益。這樣的話,鏈外的動機會導致一些在鏈上有很多錢的人依然有動力去攻擊這條鏈。這也是 PoS 比較難解決的一個問題。
4. PoW VS. PoS
我們最后簡單看一下基于 PoW 和 PoS 機制的共識的比較。
一個是準入機制。即它到底是不是有許可的?投票是不是匿名的?參與的人數有沒有限制?投票的形式是并行還是要通過廣播的方式?還有一個投票結果確認的方式?投票的邊際成本?
一個是安全性。我覺得最大的兩個區別就是先有投票權,還是先有候選區塊?投票行為和投票權利是不是綁定的?從這些角度上看,PoW 在安全性方面做得比較好。
但是,PoW 的投票結果需要等一個分支上累積的優勢足夠大才能確認,所以其實不是等一個塊,他還要再等誠實的算力集中在這一塊后面工作一段時間以后才能確認。因此 PoW 系統只能說通過一些優化把確認速度盡可能加快,但是很難做到像有的 PoS 那樣秒級確認。
說到投票的邊際成本,因為要有機器和電費,PoW 是沒辦法避免的。但其他的方面做得都比較好。相對的,PoS 在性能方面做得比較好,主要差在安全性上。就是因為它先決定了投票權,所以大家拿著這個投票權可以隨便投。而且你投過一次票以后還可以拿著這個權利再投。至于 PoS 其他的一些問題,實際上我們用委員會或者用代理的權益證明都可以把那些問題減輕或者解決掉,只有投票權的問題很難解決。投票權和投票行為不綁定的問題是 PoS 的一個本質難題。
PoW 的缺點是確認慢,吞吐量一般會相對比較低一點。PoS 主要缺點是要考慮如何應對賄賂攻擊、長程攻擊、無利害攻擊等各種攻擊手段。為了應對這些攻擊,PoS 的協議就要處理很多情況,于是就會變得比較復雜。眾所周知,越復雜的系統的安全性也越難保證,一方面是分析證明起來會更困難,另一方面是攻擊者也更容易在復雜的系統找到漏洞。
還有一種現在可能用的還不是很多的方式是 PoW 和 PoS 混合在一起做共識。因為 PoW 的優點主要就是安全可靠,而 PoS 的優點是效率高,特別是確認快,而且能耗比較低。如果能把這兩個的優點結合在一起,就有可能設計出一個更理想的共識協議。同時大家還可以考慮用 DAG 的方式而不是鏈的方式組織區塊。因為 DAG 的方式不怕分叉,不需要過分限制出塊速度,所以大家可以出塊出得比較快,只要帶寬能同步就可以。
當吞吐量做到帶寬和網絡容量的上限以后,如果要進一步的擴容,就需要從其他方面動腦筋了。一個比較簡單的思路是采用第二層的擴容方案:每筆交易不要傳到全網去驗證,比如像sharding,一個交易只在 shard 內部局部地驗證,這樣的話就可以節省全網的帶寬,提高整個系統吞吐量。閃電網絡也用到了類似的邏輯。另外一種比較難的方式要用到一些“黑科技”,比如可驗證計算、簡短的零知識證明、概率可驗證證明等等,這里不展開講了。
但設計 PoW 和 PoS 混合的系統最難的一點是怎么樣把兩者的優勢結合在一起,而不是把它們的劣勢結合在一起。我聽說過有一些設計是先用 PoW 的方式挖到一個票,然后用這個票去對候選區塊進行投票。在我看來這種方式就不是很好,因為它放棄了 PoW 投票和投票權綁定的優勢,安全性更接近于 PoS 系統。
如果能把 PoW 和 PoS 的優勢結合起來,就有可能做到一個安全性又高,確認又快,吞吐量大,而且能耗還比較合理的系統。目前為止我還沒有看到特別好的解決方案,期待以后能出現這樣一個完美的解決方案。