2.3 使用區塊鏈達成沒有身份的共識

在這一節裡,我們將探討比特幣共識算法的技術細節。回憶一下,我們在前面曾說過,比特幣中的每個節點並沒有一個穩定的、長期的身份,這一點也是與傳統分佈式共識算法的不同之處。身份缺失的原因是,在一個點對點網絡中,沒有一個中央權威機構來發放身份,並保證它們沒有製造節點。用技術術語來說,亂造節點就是所謂的「女巫攻擊」(sybil attack)現象。女巫就是惡意黑客製造的不同節點,這些節點看起來像是對應不同的身份的人,其實是由一個人在幕後控制。另一個原因是化名制(pseudonymity),也是比特幣想達到的一個目標,所以即使可以替所有節點建立唯一真實身份,我們也不想那樣做。雖然比特幣還是不能保證真正的匿名,一個用戶用不同身份做的不同交易還是有辦法被最終追蹤到,但比特幣的特性畢竟沒有強迫大家用真實身份來加入。這是比特幣的重要特性,也是比特幣系統的核心理念。

如果所有節點都有真實身份的話,那麼設計上會更加容易。有了真實身份,我們就能夠以這樣的方式發出協議指令,比如「編號最小的節點開始做某些動作」,在沒有真實身份前提下,系統能設計的指令就受到很多限制,但設計真實身份最主要的考慮是安全上的便利。如果節點的身份可以被識別,就不能隨便地製造新的節點身份出來。那樣的話,我們就可以假設有惡意節點的數量,然後部署安全措施來防範。基於以上原因,缺少真實身份給比特幣的共識協議帶來很多難點。

我們可以做一個較弱的理論假設來彌補這個先天的不足。假設我們可以在系統裡隨意選一個節點,一個比較好的比喻是——就如同在彩票站,或是在任何一個難以辨別每個人身份的系統中,我們給每一位顧客發出彩票或是一個識別牌,之後我們就可以開始抽獎,與獎號對應的人就會中獎。現在我們想像一下在比特幣的世界裡,我們假設也可以做到這一點。我們再假設,這個彩票的印製過程與發放辦法是足夠聰明的,如果一個黑客想製造出許多女巫節點來,最後所有這些節點也只能拿到一張彩票。也就是說,這個黑客無法通過製造假的節點來增強他的力量。如果你覺得我們做的假設太多了,請不要擔心,我們在以後會消除這些假設,並在後文會詳細說明,在比特幣系統中,與這些假設相對應的性質是如何實現的。

隱性共識

對隨意節點選擇的假設可以讓「隱性共識」(inplicit consensus)成為可能。我們的共識協議有多個回合,每個回合都對應著區塊鏈裡的一個塊。在每一個回合裡,一個隨機節點會被選中,然後這個節點可以提議這個鏈的下一個區塊。這時沒有共識算法,也沒有任何投票過程來決定哪個區塊會被選中,隨機被選中的節點會直接決定區塊鏈的下一個區塊,但萬一這個節點是惡意的呢?針對這個問題,還是有應對辦法的,解決方法就是隱性共識。其他節點可以通過隱性地接受或是拒絕前面這個被隨機選擇出來的節點。如果接受,它們會在這個塊之後接龍下去;如果拒絕,它們忽略這個新的區塊,而是選擇前一曾經接受的區塊,來繼續接龍下去。大家還記得,每一塊都記錄著前一塊的哈希值。這就是節點選擇在哪一塊來繼續接龍的技術處理方式:比特幣共識算法(簡化版)。

這個算法的簡化假設是,可以隨意選擇一個節點,這些節點都不會受到女巫攻擊的影響。

1.新的交易被廣播到所有節點上。

2.每個節點都將新的交易放進一個區塊。

3.在每個回合,一個隨機的節點可以廣播它的區塊。

4.其他節點可以選擇接受這個區塊,前提是如果區塊裡的交易都是正當的(有真的簽名)。

5.節點們可以把以上區塊的哈希值放進自己的區塊裡,以此來表示它們對那個新區塊的認可。

我們現在一起來研究一下為什麼這樣一個共識算法是有效的。為此,我們假設有一個叫愛麗絲的黑客,她想要破壞這個共識過程。

竊取比特幣

愛麗絲能夠竊取屬於另一個用戶,不受她控制的地址裡的比特幣嗎?答案是否定的。即使這一輪是由愛麗絲提議區塊鏈上的下一個區塊,她也不可能竊取別人的比特幣。這麼做的話,愛麗絲需要發起一筆有效的交易來花掉這個比特幣。這就要求愛麗絲偽造比特幣擁有者的簽名,然而如果數字簽名機制是安全的,她是無法辦到的。只要背後的密碼學基礎是牢靠的,她就無法輕易竊取比特幣。

拒絕服務攻擊

讓我們來考慮另一種攻擊。假設愛麗絲不喜歡叫鮑勃的某個用戶,愛麗絲可以決定她不把鮑勃發起的任何交易放進她所提議的區塊裡。換言之,她拒絕提供服務給鮑勃。儘管這是愛麗絲可以開展的有效的攻擊,但幸好這不過是個小問題。如果鮑勃的交易沒有被放進愛麗絲所提議的下一個區塊,鮑勃只要等到下一個誠實節點發起區塊的時候,他的交易記錄就會被放進這個區塊裡。所以這其實也不算是一個有效的攻擊。

雙重支付攻擊

愛麗絲也可能會發起一個雙重支付攻擊。要理解愛麗絲如何發起這種攻擊,我們可以假設愛麗絲是鮑勃開的網店或網站的一名顧客。鮑勃提供一些比特幣付費的在線服務,比如軟件下載。雙重支付攻擊是這樣的:愛麗絲在鮑勃的網站選中一件商品並加入購物車中,此時服務器要求付款。然後,愛麗絲在她的地址上向鮑勃的地址發起了一筆比特幣交易,並向整個網絡廣播這筆交易。我們假設由某個誠實節點來製造下一個區塊,並把這筆交易放進這個區塊中。因此,現在就有了一個由誠實節點發起,包含代表愛麗絲向商家鮑勃支付這筆交易在內的區塊了。

我們還記得一個交易就是一個數據結構,裡面有愛麗絲的數字簽名,一個付給鮑勃的公鑰(地址)的指令和一個哈希值。這個哈希值代表了一個指針,指向先前的一筆交易的輸出,即愛麗絲之前收到並於現在消費比特幣。這個指針必須指向一個已被共識鏈上的某個之前的區塊所認可的交易。

順便說一下,有兩種容易混淆的不同類型的哈希指針。一種是在區塊內用來表示接在之前哪個區塊後面的哈希指針;另一種是在交易裡的一個或多個,用來指向之前交易裡說明比特幣來源的哈希指針。

我們回到愛麗絲如何發起雙重支付攻擊這個問題。最新的一個區塊由一個誠實節點產生,其中包含愛麗絲下載軟件向鮑勃付費的交易記錄。當看到這筆交易被放入區塊鏈後,鮑勃認為愛麗絲已經向他付款,便允許愛麗絲下載軟件。假設在下一個回合被隨機選中的節點恰巧被愛麗絲所控制。現在因為愛麗絲可以提議下一個區塊,她可以選擇忽略掉前面那個包含她支付給鮑勃的那筆交易的區塊,而產生一個包含指向之前區塊指針的區塊。不僅這樣,在這個區塊裡,愛麗絲可以放進一筆交易,把她付給鮑勃的幣轉到一個被她所控制地址裡去。這就是一個經典的雙重支付攻擊。因為這兩個交易用的是同一個幣,只有一個交易可以被放進區塊鏈。所以如果愛麗絲成功地把幣轉到她控制的地址,那個她付幣給鮑勃的交易記錄將變得無效,因為它將不會被放進區塊鏈裡。這一過程詳見圖2.2。

圖2.2 雙重支付攻擊

註:愛麗絲創建了兩筆交易:一筆是她付給鮑勃比特幣的交易,另一筆是她將這筆比特幣重複支付到她控制的另一個地址。因為這兩筆交易用相同的比特幣支付,所以只有一筆會被放進區塊鏈。圖中的箭頭表示一個區塊鏈接到前一個區塊的指針,通過在前一個區塊自己的內容中包含了一個哈希值進行了擴展。CA代表愛麗絲擁有的幣。

那我們如何知道這個雙重支付攻擊是否能成功呢?這取決於最後哪個區塊會被納入長期的共識鏈,是愛麗絲轉給鮑勃的區塊,還是愛麗絲轉給愛麗絲自己的區塊。是什麼決定了哪一個區塊被納入呢?誠實節點會遵守在最長有效分支後面延展這一規則,那到底在哪個分支後面延展呢?並沒有明確的答案!目前來看,這兩條分支長度一樣,它們的區別是僅在於最後一個區塊,並且這兩個區塊都是有效的。選擇下一個區塊的節點可以決定建立在其中一個區塊上。這個選擇就決定了雙重支付攻擊的成功與否。

微妙之處在於:從道德角度考慮,這兩個分支截然不同,一個是包含付給鮑勃交易的區塊,一個是包含愛麗絲把這些幣雙重支付給她自己地址交易的區塊。但這個區別僅僅建立在我們知道愛麗絲先支付給鮑勃再試圖雙重支付這個故事的基礎上。但從技術角度來看,這兩筆交易完全一致,且都有效。節點沒有辦法分辨出哪一個是道義上合理合法的交易。

實踐中,節點往往用延展它們在點對點網絡裡最早聽到的區塊這種啟髮式的方法。但這不是一個無懈可擊的法則。在一些情況下,因為網絡延遲,很可能它們先聽到的區塊實際上是後被創造出來的。所以下一個提議節點至少是有可能選擇在那個包含雙重支付的區塊上延展。愛麗絲甚至還可以賄賂下一個提議節點來加大這個可能性。不管出於什麼原因,如果下一個節點真的接受了這個雙重支付的區塊,那麼這條鏈將比包含支付給鮑勃交易的那條鏈更長。基於此,下一個誠實節點就有可能去延展這條鏈,因為它更長。隨著這個過程繼續,這條包含雙重支付的鏈會更有可能成為長期共識鏈的一部分。相反,那個包含愛麗絲支付給鮑勃交易區塊的鏈會被網絡完全遺忘,成為一個 孤塊(orphan block)。

我們現在從商家鮑勃的立場重新考慮整個情況。理解鮑勃如何保護自己不受雙重支付攻擊是理解比特幣安全措施的重要的一部分。當愛麗絲廣播她向鮑勃支付的交易時,鮑勃也在網上聽著,鮑勃在下一區塊被創建之前就能聽到這筆交易。如果鮑勃比我們前面描述的更加草率的話,他可以在網上完成檢查程序,並允許愛麗絲此時下載軟件。這叫作零驗證交易(zero confirmation transaction)。這將導致一個比前面所說的更加基礎的雙重支付攻擊。前面所述情況,為了實現雙重支付攻擊,我們需要假設一個惡意黑客控制了發起下一個區塊的節點。但如果鮑勃允許愛麗絲在沒有收到區塊鏈一條確認信息的情況下就下載軟件,那麼愛麗絲可以立刻廣播一條雙重支付交易,一個誠實節點就有可能把這個交易放進下一區塊,而不是支付給鮑勃的那筆交易。見圖2.3。

圖2.3 從鮑勃立場來看雙重支付

註:這是一個從商家鮑勃的立場來看愛麗絲做的雙重支付嘗試。為了保護自己免受雙重支付攻擊,鮑勃應當等愛麗絲向他支付的交易被區塊鏈包含進去,並且多等幾次確認。

另一方面,一個謹慎的商家甚至在看到交易被包含在一個區塊後仍然不會允許愛麗絲下載軟件,而是繼續等待。如果鮑勃看到愛麗絲成功發起了雙重支付的攻擊,他會意識到那個含有愛麗絲向他支付的交易的區塊有可能已經被丟棄。他應該放棄這個交易,不讓愛麗絲下載軟件。如果在嘗試雙重支付的情況下,恰巧下幾個節點還是建立在愛麗絲向鮑勃支付交易的區塊上,那鮑勃就相信這筆交易會被納入長期共識鏈。

總而言之,一個交易得到的確認越多,它被納入長期共識鏈的概率就越大。如前文所述,誠實節點總是選擇延展最長的共識鏈。因為長鏈增長更多,那條含有雙重支付的短鏈追上長鏈的概率會變得越來越小。在只有一小撮惡意節點的情況下,這個結論尤其正確。因為短鏈要想趕上,這些惡意節點需要被一直連續選中。

事實證明,雙重支付攻擊成功的概率將隨著確認的數目的增加而指數級降低。所以,如果你感興趣的交易已經收到k個確認,雙重支付攻擊交易被納入長期共識鏈的概率以關於k的一個函數指數級下降。在比特幣生態系統裡,最常見的方法是等6個確認。並不是6這個數字有什麼特殊意義,只不過,這樣在你等待的時間與確認你所感興趣的交易被納入長期共識鏈之間做了很好的平衡[1]。

總結起來,防止不正當交易完全是用密碼學的方法。但這些方法被共識所加強,意思是一個節點如果想放進一個密碼學上不正當的交易,這個交易不會被納入長期共識鏈的唯一原因是絕大多數的節點是誠實的,不會把一個不正當交易放進區塊鏈。另外,防止雙重支付攻擊完全依賴於共識,密碼學不起任何作用。從密碼角度來看,這兩個交易都是正當有效的。但共識可以能決定哪個被放進長期共識鏈。最後,你無法百分之百保證你感興趣的交易被放進了長期共識鏈。但指數級概率保證了不錯的結果,6筆交易過後,實質上你沒有犯錯的可能了。

[1] 如後文總結時所說,並沒有一個固定的數字,但6是個常用的數目。——譯者注

《區塊鏈:技術驅動金融》