為什麼說“小表模式”zkEVM更為高效?

前言:以太坊虛擬機是建立在以太坊區塊鏈上的代碼運行環境,合約代碼可對外完全隔離並在EVM內部運行,其主要作用是處理以太坊系統內的智能合約。之所以說以太坊是圖靈完備,是因為開發者可以使用Solidity語言創建運行於EVM上的應用程序,一切可計算的問題都能計算。但僅是圖靈完備還不夠,人們還試圖將EVM封裝在ZK證明系統裡,但問題是封裝時會產生大量冗餘。 Fox所發明的“小表模式”zkEVM,在保證原生的Solidity以太坊開發者能無縫遷移至zkEVM的同時,還將大幅削減封裝EVM到ZK證明系統時產生的冗餘成本。

EVM自2015年問世以來正在經歷一場史詩級的ZK改造。這場大改造主要有兩個方向。

第一個方向就是所謂的zkVM賽道,該賽道項目致力於將Application的性能提升到最優,而與以太坊虛擬機的兼容性並不是首要考慮的問題。這裡有兩個子方向,其一是做自己的DSL (Domain Specific Language),比如StarkWare正致力於推廣Cairo語言,推廣難度並不小。其二是目標兼容現有的比較成熟的語言,比如RISC Zero致力於讓zkVM兼容C++/Rust。該賽道的難點在於因為引入了指令集ISA,導致最終輸出的約束更複雜

第二個方向就是所謂的zkEVM賽道,該賽道項目致力於EVM Bytecode的兼容,即Bytecode級別及其以上的EVM代碼都通過ZkEVM產生對應的零知識證明,這樣以來原生的Solidity以太坊開發者會可以無成本遷移至zkEVM。該賽道選手主要有Polygon zkEVM、Scroll、Taiko和Fox。該賽道的難點在於兼容EVM這樣一個並不適合封裝在ZK證明系統時產生的冗餘成本。 Fox經歷長時間的思考與論證,終於找到了從根本上消減第一代zkEVM巨大冗餘的那把鑰匙:“小表模式”zkEVM。

數據和證明電路是zkEVM生成證明的兩大核心要素。一方面,在zkEVM中,證明者需要所有交易涉及的數據以證明交易帶來的狀態轉移是正確的,而EVM中的數據量大且結構複雜。因此,如何整理和組織證明所需的數據便是構建一個高效的zkEVM需要仔細考慮的問題。另一方面,怎麼通過一系列的電路約束高效地證明(或檢驗)計算執行的有效性與正確性,則是保證zkEVM安全性的基礎。

我們首先談第二個問題,因為這是所有設計zkEVM的團隊都需要考慮的問題,這個問題的本質其實就是“我們到底要證明什麼?”而目前大家對這個問題的思路都是相似的,由於一個交易(或其涉及的op-code)可能是多種多樣的,直接按順序證明每一步的操作帶來的狀態改變都是正確的顯得不現實,因此我們需要分類證明。

圖1:大表、小表兩代zkEVM解決方案

例如,我們將每次stack中元素的變化都放在一塊,專門編寫一個stack電路證明,為單純的算術操作專門編寫一套的算術電路等等。如此一來,每個電路需要考慮的情況就變得相對簡單。這些不同功能的電路在不同zkEVM中有不同的名字,有人直接稱其為電路,也有人稱其為(子)狀態機,但是這個思想的本質都是一樣的。

為了更清楚的解釋這麼做的意義,我們舉一個例子,假設現在要證明加法操作(將stack的上2個元素取出來,並將他們的和放回stack頂端):

假設原先的stack是[1,3,5,4,2]

則如果不分類拆分的話,我們需要設法證明進行完上述操作後stack變為[1,3,5,6]

而如果進行了分類拆分的話我們只需要分別證明以下幾件事:

  • stack電路:

    • C1:證明[1,3,5,4,2] pop出2和4後變為[1,3,5]

    • C2:證明[1,3,5] push(6) 後變為[1,3,5,6]

  • 算術電路:

    • C3:a=2,b=4,c=6,證明a+b=c

值得注意的是,證明的複雜程度和電路需要考慮的各種情況的數量有關係,如果不分類拆分的話,電路需要覆蓋的可能性將會非常巨大。

為什麼說“小表模式”zkEVM更為高效?

圖2: 第一代zkEVM採用的大表模式

而一旦分類拆分了,每一個部分的情況將會變得相對單純,從而證明的難度也會顯著減小。

但是分類拆分也會帶來其他問題,那便是不同類別電路的數據一致性問題,例如在上面的例子裡,我們實際上還需要證明以下兩件事:

  • C4:”C1中pop出來的數” = “C3中的a和b”

  • C5:“C2中push的數” = “C3中的c”

為了解決這個問題,我們回到了第一個問題,即我們要如何組織交易涉及的數據,下面我們接著探討這個議題:

一個直觀的方法是這樣的:通過trace,我們可以拆解出所有交易涉及的每個步驟,知道其涉及的數據,並通過向節點發送請求以獲得不在trace中的那部分數據,隨後,我們將其如下排列成一個大表格T:

“第一步操作” “第一步操作涉及的數據”

“第二步操作” “第二步操作涉及的數據”

“第n步操作” “第n步操作涉及的數據”

如此一來,在上面的例子中,我們就會有一行記錄著

“第k步:加法” “a=2, b=4, c=6”

而上面的C4便可以被如下證明:

  • C4(a):C1 pop 出的數和大表T中的第k步一致

  • C4(a):C3 的a和b和大表T中的第k步一致

C5也是類似的。這個操作(證明一些元素在一個表中出現過)被稱為lookup。 lookup的具體算法我們不在本文中詳細介紹,但是可以想像,lookup操作的複雜度與大表T的大小密切相關。因此,現在我們回到第一個問題:如何組織證明會用到的數據呢?

為什麼說“小表模式”zkEVM更為高效?

圖3: Fox所發明的“小表模式”zkEVM

我們考慮如下一系列的表格構造:

表格Ta:

“類型a的第一個操作” “類型a的第一個操作涉及的數據”

“類型a的第二個操作” “類型a的第二個操作涉及的數據”

“類型a的第m個操作” “類型a的第m個操作涉及的數據”

表格Tb:

“類型b的第一個操作” “類型b的第一個操作涉及的數據”

“類型b的第二個操作” “類型b的第二個操作涉及的數據”

“類型b的第m個操作” “類型b的第n個操作涉及的數據”

如此構造多個小表,這麼做的好處是當我們可以根據需要的數據所涉及的操作的類型,直接在對應的小表中進行lookup,如此一來,便能很大程度的提高效率。

一個簡單的例子(假設我們每次只能lookup一個元素)是如果我們要證明a~h這8個字母都存在[a,b,c,d,e,f,g,h]中,我們需要對大小為8的表進行8次的lookup,但是如果我們把表分為[a,b,c,d]和[e,f,g,h]的話,我們只需要對這兩個大小為4的表分別進行4次lookup就可以了!

在FOX這個layer2的zkEVM中便使用了這種小表的設計以提升效率,為了保證在各種情況下都能完備的證明,對於具體的小表拆分方式需要仔細的設計,而提升效率的關鍵則在於對錶的內容的分類與其大小的平衡。儘管將完整的zkEVM在這個框架中實現需要龐大的工作量,我們預期這樣的zkEVM將會在性能方面有突破性的進步。

結論:Fox所發明的“小表模式”zkEVM,在保證原生的Solidity以太坊開發者能無成本遷移至zkEVM的同時,大幅削減封裝EVM到ZK證明系統時產生的冗餘成本。這是zkEVM結構的一次重大變革,將對以太坊擴容方案產生深遠影響。

Total
0
Shares
Related Posts