如何利用零知識證明改造區塊鏈

買賣虛擬貨幣

編者按:本文來自:以太坊愛好者(ID:ethfans),作者:Ronald Mannak,翻譯 & 校對: 曾汨 & 阿劍,Odaily星球日報經授權轉載。

已經有許多技術部落格發表了關於零知識證明(ZKP)的文章。最近,我自己寫了一篇文章,比較了新的通用型 zk-SNARK。我注意到,用淺白的語言來解釋 ZKP 用例的文章還寥寥無幾。其實,ZKP 不僅僅可以用於保護隱私,由於其豐富多樣的功能,ZKP 甚至可以改變區塊鏈執行的方式。

首先:簡潔的區塊鏈,從 GB 到 KB

因為區塊鏈的資料規模會隨著新區塊的產生而不斷增長,所以其規模可能會變得很大。這是設計使然,我們已經開始接受這一現實。然而,最近上線的 Coda 測試網卻有些與眾不同。首先, Coda 的區塊鏈資料規模恆定,並不會增長。其次,它的整條區塊鏈大小隻有 22kb!這意味著哪怕你用一臺上世紀 80 年代的 Commodore 64 或者 ZX Spectrum 來跑節點也毫不費力。然而,相較於傳統的區塊鏈而言,Coda 的安全性有過之而無不及。還有越來越多的專案正在朝著這方面發展:Mir 和 Starling(我是 Starling 的一員) 將在不久後啟動與 Coda 相似但功能更加豐富的 “簡潔的區塊鏈”。那它們到底是怎麼做的呢?

任何一個執行過區塊鏈節點的人都經歷過這樣的痛苦:同步一個節點需要耗費幾個小時甚至數天。區塊鏈的資料量往往非常巨大,以至於絕大多數家庭的電腦硬碟和頻寬都達不到執行節點的要求。這就導致了中心化。即便是像以太坊這樣廣受歡迎的區塊鏈,全網也只有大約 10,000 個節點。其中大部分節點還是被託管在 AWS 上的,並且歸屬於少數實體。區塊鏈並沒有許多人認為的那樣去中心化。

為什麼同步一條區塊鏈要花這麼長的時間?有兩個原因。第一個原因顯而易見:下載數百 GB 甚至更多的資料需要耗費一段時間。其次,當節點下載完資料後,還需要對整條區塊鏈進行驗證,因為可能會有惡意的節點給你傳送錯誤的資料。

要想驗證一條區塊鏈,必須從創世區塊開始重放:執行第一筆交易,確認計算出的狀態與下載到的狀態一致。然後驗證下一筆交易,直到你驗證完整條區塊鏈中所有的交易。這樣做既耗時費力;而且在你之前,已經有成千上萬的節點執行過同樣的計算。

但這樣做是必要的,因為在傳統的計算模式中,知道計算是否正確的唯一方法就是重新再算一次。這對於小型計算來說還好,但對於比較大的計算量而言就不太友好了,比如重放區塊鏈。

利用 ZKP 改善效率及頻寬利用

事實證明,有一種技術可以在無需重新計算的前提下降低驗證計算結果的成本:零知識證明(ZKP),而 zk-SNARK 可能是所有零知識證明技術中最出名的。

所以到底怎麼結合呢?我們必須將區塊鏈的重放函式用 zk-SNARK 重寫一遍。zk-SNARK 將輸出兩樣結果:初始輸出(就像初始的重放函式會輸出的結果一樣)和一個小型的數學證明,用於證明該計算結果是正確的。這個證明可以小到只有 200 Bytes(是的,你沒看錯,不到 1KB)。

無需讓所有的(甚至多臺)計算機都執行重放函式。只需要有一臺計算機建立證明,其它所有計算機都可以按自己的需要驗證結果。驗證只需要花費幾毫秒,不論初始的計算花了多長時間(甚至是幾個小時、幾天或幾年,都無關緊要)。這些證明可以釋出到網路上、透過 U 盤傳播,甚至列印在 T 恤上。

如果有一個惡意的節點改動了餘額,那麼其證明就會和結果不匹配,所有驗證者都會拒絕該狀態。如果惡意的節點對 zk-SNARK 的程式碼動了手腳,其結果也會被其它節點拒絕。(系統中還存在第三個引數 —— 一個公開的共享字串,它將證明和 zk-SNARK 程式碼繫結在了一起。一旦程式碼被動了手腳,其證明就會和和共享字串匹配不上,於是驗證者就會拒絕該計算結果。)

我們已經擺脫了對重複進行昂貴計算的依賴,同時也不再需要下載整條區塊鏈了(因為我們已經有了數學證明來證明區塊鏈的存在及有效)。你只需要下載當前的狀態(例如最新的區塊)加上一個很小的證明,用於證明當前狀態是有效區塊鏈的一部分,然後花費幾毫秒來驗證計算結果。

遞迴組合(Recursive composition)

驗證證明的過程非常快,可建立證明的過程呢?事實證明,建立證明所耗費的時間並不是固定的,相較於傳統的計算而言,該過程在計算和記憶體方面要低效得多。事實上,儘管採用了 zk-SNARK 的重放函式聽上去很美好,但它實踐起來並不是一個優秀的解決方案。它會消耗巨大的記憶體,甚至比最初的非 zk-SNARK 重放函式還要慢。

但如今有了另一種優雅的解決方案。透過一些小技巧,我們可以使用遞迴的 zk-SNARK。透過遞迴,我們不再需要從頭開始驗證區塊鏈,而可以在上一個狀態的基礎上構建新的狀態。這要快得多。請注意,遞迴的 zk-SNARK 並沒有非遞迴的 zk-SNARK 效率高,但最近 zk-SNARK 構建已取得了巨大的進步。

遞迴的 zk-SNARK 程式使用上一個狀態、該狀態的證明以及新的交易作為輸入。它(使用提供的證明)驗證上一個狀態,並檢查新狀態中的交易是否有效。如果有效,它將輸出新狀態及其證明。

一旦新狀態和證明分發到了網路中,所有節點都可以直接拋棄舊的狀態,而不用擔心產生任何負面後果。新節點只需要下載最新的狀態及其證明就可以了。這就為什麼 Coda、Mir、和 Starlin 能實現資料規模恆定的區塊鏈。

在我們上一個例子中,只有一個節點會建立新的區塊及證明。很顯然,並非所有區塊都必然是同一個節點產生的。例如,可以從眾多節點中隨機選擇一個節點來建立區塊(如果採用了可驗證的隨機函式(Verifiable Random Function),節點們甚至可以在內部選出節點來出塊,且無法作惡)。我們甚至可以做的更好。我們可以將區塊生產的邏輯劃分為多個 zk-SNARK。

最終的結果就是區塊生產者不需要再儲存整條區塊鏈,而只需要儲存上一個狀態。這種解決方案可以小多少呢?一個常規的 Coda 節點只需要佔用 22KB 的空間用於儲存證明、當前狀態和指向一個餘額的默克爾路徑。透過 22KB 的儲存,節點可以驗證整條區塊鏈、查詢餘額、以及建立交易。但要想生產區塊,節點需要做更多的操作:它需要上一個狀態的全餘額默克爾樹。默克爾樹的大小取決於錢包的數量。即便 Coda 擁有的錢包數量和以太坊一樣多,一個 Coda 的區塊生產者仍然只需要 1GB 大小的儲存空間。而最小的以太坊全節點則需要 230GB(截止 2019 年 12 月)。這是一個巨大的差距。

透過這種方式,網路中會有更多活躍的節點,進而增加其去中心化程度,併為與區塊鏈互動的程式開闢了許多新的可能性,而不用再借助諸如 Infura 或 Metamask 等解決方案。考慮到 99% 的使用者在安裝 Metamask 之前就已經放棄了,這應該會帶來巨大的影響。

感謝 Daniel Lubarov (Mir)、Shane Vitarana、Stan van de Burgt、Taariq Lewis、和 Dmitriy Berenzon 對本文的校對。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;