在前一節,我們籠統地討論了去中心化和中心化。現在我們從一個更為技術性的層面看一下比特幣的去中心化。接下來,我們會遇到一個被稱作「共識」(consensus)的重要概念,特別地,還有「分佈式共識」(distributed consensus)。建立一個分佈式的電子現金系統的關鍵技術問題,就在於要達成分佈式共識。直觀地說,你可以想像我們的目標就是要將第1章提到的財奴幣去中心化。
分佈式共識有各種應用,計算機界對其也研究了多年,傳統具有啟髮式的應用就是提高分佈式系統的可靠性。設想你在管理一個社交網絡公司的後端平台,比如微信,像這樣龐大的系統通常有幾千台甚至幾萬台服務器,這些服務器組成了一個巨大的分佈式數據庫,數據庫中記錄了這個系統裡發生的各種活動,而每條信息都會被記錄在後端的若干個節點上,對於整個系統的狀態,這些節點必須要做到同步。
分佈式共識協議的意義遠遠超出了傳統意義的範疇。一旦具備了這樣的體系,我們就可以建立一個龐大的分佈式鍵值(key-value)存儲庫,該類存儲庫可以將任意數據如身高、名字等對應一個相應的開啟鍵,基於此,許多應用得以實現。例如,我們可以建立一個分佈式域名系統,將人腦易於理解的域名與IP地址進行配對,我們也可以建立一個公鑰目錄,這個目錄可以把公鑰與電郵地址(或者其他真實世界中的身份證明)對應起來。
以上討論在直覺上說明了分佈式共識的大概含義。對於分佈式共識,我們還是要給出一個技術定義,以此我們可以判別一個協定是否符合分佈式共識的要求。
分佈式共識協議 在一個有n個節點的系統中,每一個節點都有一個輸入值,其中一些節點具有故障,甚至是惡意的。一個分佈式共識協議有以下兩個屬性:
● 輸入值的中止須經所有誠實節點來確定。
● 這個輸入值必須由誠實節點來生成。
那麼以上概念在比特幣裡又是什麼含義呢?想要理解分佈式共識在比特幣中的用途,我們需要記住比特幣是個點對點的系統。當愛麗絲向鮑勃付款的時候,她其實是在向構成比特幣網絡上的所有節點廣播其交易行為,見圖2.1。
圖2.1 廣播交易
註:為了向鮑勃付款,愛麗絲需要向整個比特幣點對點網絡進行廣播。
順便提一下,你可能注意到,當愛麗絲向整個比特幣點對點系統廣播時,鮑勃的計算機並不一定在圖2.1的網絡中。當然鮑勃也有可能在這個網絡上運行著一個節點,如果鮑勃想在愛麗絲轉幣給他時及時被系統通知,運行一個節點當然是個好主意,但其實這並不重要,鮑勃是否運行節點並不影響他收到愛麗絲轉給他的比特幣。
在比特幣網絡裡,節點到底要達成什麼樣的共識呢?網絡裡有各種各樣的用戶在向網絡廣播交易,節點必須對哪些交易可以進行廣播和交易發生的次序達成共識,以此系統將形成一個唯一的全球交易總賬。回想我們在第1章1.5節中曾提到的財奴幣將交易打包成塊,對信息進行優化處理。類似地,在比特幣體系裡,我們也將每個區塊進行共識處理。
在任何時點,所有在點對點網絡上的節點都有包含一系列區塊的總賬本,每個區塊中都包含了已經被所有節點達成共識的交易清單。除此之外,每個節點還有一堆沒有被打包進入區塊的交易,就是那些網絡節點已經被通知、交易已經發生,但還沒有被寫進區塊的交易。網絡節點對於這些交易還沒有達成共識,所以每個節點都有一個略有差異、尚待確認的交易池。在實際中,點對點網絡是不完美的,所以有些節點聽到了交易,而有些節點卻沒有聽到。
那麼,所有的節點是如何對一個區塊達成共識的呢?一個方法是,在一個時間段裡,比如說每隔十分鐘,每個節點都提議,自己的未被認可的交易成為已經達成共識的區塊鏈後面的下一個區塊,然後那些節點會執行一些共識協議,每個節點把自己提議的區塊作為輸入。但不可避免地,有些節點可能是惡意的,存心要把不當交易放進區塊裡,其他節點則是誠實的。如果共識協議能夠順利完成,一個正當有效的區塊會被選作輸出值。儘管有些被選出的區塊是由一個節點提交,但只要這個區塊是正當有效的,輸出就是正當有效的。這時候可能有人會指出,這個被選出的區塊可能未包含所有的正當有效的交易,但這並沒有關係,如果有些正當有效的交易沒被放進區塊,它們可以等待下一次機會。
前面所談到的這個辦法與比特幣系統有些相似之處了,但實質還是不完全一樣。以上做法有幾個技術上的問題:第一,達成共識一般是個難題,因為有些節點會死機或是根本就是惡意節點;第二,就比特幣而言,點對點網絡是不完美的,並非所有對應的節點是兩兩相連的,互聯網鏈接的不良可能會造成網絡問題,要執行一個所有節點都參與的共識協議好像並不現實;第三,由於交易信息是分佈在整個互聯網上,信息傳遞會有嚴重延遲。
延遲與全球時間
比特幣協議達成共識時必須直面兩大障礙:其一是不完美網絡,例如信息延遲和節點死機,其二是某些故意搞破壞的節點。
嚴重網絡延遲導致的一個後果是,節點之間沒有一個統一的全球時間概念。意思是,並非所有節點都能根據每個交易的時間戳來達成交易時間共識,因此,共識協議不能執行以下指令:「在第一步裡發了第一個消息的節點必須在第二步裡執行X。」這一做法根本無法執行,因為所有的節點對於誰在第一步中發出第一個信息有不同的看法。
不可能性結論
在全球時間上的不統一,給共識協議算法帶來了很多限制。事實上,由於這些限制,許多關於分佈式共識的文獻都對是否能達成共識持悲觀態度,有許多達成共識具備不可能性的結論已經被證實。一個經典案例就是「拜占庭將軍問題」(Byzantine Generals Problem),這個經典難題是這樣闡述的:拜占庭是東羅馬帝國的首都,它的軍隊分成多個師,每個師都由一個將軍統領。這些將軍通過信使進行交流,來達成一個共同作戰方案,有些將軍可能是叛徒,想故意破壞這個過程,這會造成那些忠誠的將軍也無法達成一個統一的作戰計劃。解決這個難題的辦法就是讓那些忠誠的將軍在這樣的情況下達成統一作戰方案,而避免那些叛徒對作戰方案的誤導。事實證明,如果叛徒數量超過1/3時,這個難題將無法克服,那些忠臣的計劃終會被叛徒們破壞。
還有一個更為微妙的關於不可能性的結論,這就是著名的「Fischer-Lynch-Paterson不可能結果」[1],該名稱以最初的作者而命名。該結果指出,在一定的條件下(包括節點行為具有確定性特徵),甚至在只有一個缺陷的過程中,達成共識都是不可能的。
儘管有這些「不可能性結論」,還是有文獻談到了一些共識協議。比較著名的就是Paxos算法協議。Paxos算法做了一些妥協,一方面,Paxos算法能做到不產生不一致的結果;另一方面,Paxos算法所做的妥協是,在一定條件下(雖然是不常見的情形),該協議會死機卡住,從而無法繼續運行。
打破傳統上的假設
但好消息是,這些所謂的「不可能性結論」都是在一些特定的模式下才成立,這些結論是針對分佈式數據庫的研究,這些模型不能完全套用到比特幣身上來,比特幣本身就打破了很多原來分佈式數據庫所做的假設。這些結論其實從某一方面讓我們更明白了那些特定模式,由此或許可以真正對分佈式共識給出解決方案。
具有諷刺意義的是,就目前對共識的研究來說,比特幣實際運行情況下遠比理論上告訴我們的要好得多,這就是比特幣讓專家們跌破眼鏡之處。我們看到分佈式共識在比特幣裡運行良好,但我們還沒有建立理論來充分解釋為什麼會這樣,但無論如何,完善理論對將來的發展還是十分重要的,理論結果可以使我們預測,甚至預防未來可能的攻擊和問題。我們一旦具備了較強的理論依據,來解釋比特幣分佈式共識的良好運作機制,我們才能真正地對比特幣的安全性和穩定性做出保證。
比特幣到底打破了經典模型裡的哪些假設呢?第一,比特幣引進了獎勵的理念,這對分佈式共識協議來說是一個全新的理念,這也只有在比特幣裡才可能實現,因為比特幣也是個貨幣,所以人們自然而然地會為了金錢獎勵而變得誠實起來。所以,比特幣並沒有真正解決分佈式共識問題,它只是在特定貨幣系統下解決了這個問題而已。
第二,比特幣體系包含隨機性這個概念。在後面兩節裡我們將會看到,比特幣的共識算法很大程度上依賴於隨機性。此外,它也不再糾結於規定共識的起點與終點。相反,共識是通過一段較長的時間而達成的,在實際系統中,達成共識大約需要一個小時左右。但即使在一個小時以後,節點們也無法確定哪一個交易塊應該進入總賬本。但隨著時間的流逝,我們對某一個塊的認識與最終總體共識相吻合的概率將越來越大,觀點出現分歧的概率按指數級下降。比特幣在以上方面的不同,讓它能夠逾越傳統理論關於分佈式共識不可達成這一鴻溝。
[1] Fischer-Lynch-Paterson不可能結果,是Michael J. Fischer、Nancy A. Lynch和Michael S. Paterson在論文Impossibility of distributed consensus with one faulty process中證明的一個結論,稱得上是分佈式理論中最為深刻的結論,大致表述如下:「在一個多進程異步系統中,只要有一個進程不可靠,那麼就不存在一個協議,此協議能保證有限時間內使所有進程達成一致。」——譯者注