V神新文:以太坊內置ZK後,Layer2駛向何方?
出品- Odaily
編譯- Loopy Lu

今日,Vitalik Buterin 在以太坊社群發布了一篇名為《內置ZK-EVM 可能是什麼樣子的? 》的新文章。這篇文章探討了以太坊在未來的網絡升級中將如何內置自己的ZK-EVM。
眾所周知,在以太坊開發緩慢的背景下,目前幾乎主流Layer 2 都已經擁有了ZK-EVM,而當以太坊主網封裝了自己的ZK-EVM 之後,主網和Layer 2 又是否會產生角色定位的衝突呢? Layer 1 和Layer 2 又該如何有效的分工合作?
在本文中,Vitalik Buterin 強調了相容性、資料可用性和可審計性的重要性,並探索了實現高效和有狀態證明者的可能性。此外,文章還探討了為提高效率實現有狀態證明者的可能性,並討論了Layer 2 項目在提供快速預確認和MEV 緩解策略方面的作用。這篇文章反映了在保持以太坊網絡靈活性的同時,透過ZK-EVMs 推進其發展的平衡。
Odaily對原文進行了編譯,如下:
optimistic rollups 和ZK rollup 作為以太坊之上的Layer-2 EVM 協議,都依賴EVM 驗證。然而,這要求他們信任一個龐大的程式碼庫,如果這個程式碼庫中存在bug,那麼這些虛擬機器就有被駭客攻擊的風險。這也意味著,ZK-EVM 即使是希望與L1 EVM 保持完全等效,也需要某種形式的治理,以此來將L1 EVM 的改變複製到它們自己的EVM 實現中。
這種並不是一種理想的情況。因為這些項目正在將以太坊協議中已經存在的功能複製到自身中——以太坊治理已經負責進行升級和修復bug,ZK-EVM 基本上所做的工作只是驗證Layer 1 以太坊區塊。在未來幾年中,我們預計輕客戶端將變得越來越強大,很快就能夠使用ZK-SNARKs 來完全驗證L1 EVM 執行。到那時,以太坊網絡將實際上擁有一個封裝的ZK-EVM。因此,問題就出現了:為什麼不讓這個ZK-EVM 對於rollups 也是原生可用的呢?
這篇文章將描述「封裝ZK-EVM」的幾個版本,分析其權衡、設計挑戰以及不走某些特定方向的原因。實現一個協定功能的好處應該與讓生態系統處理事務並保持基礎協議簡單的好處相比較。
我們希望從封裝的ZK-EVM 中獲得哪些關鍵特性?
基本功能:驗證以太坊區塊。該協議功能(目前還未確定是操作碼、預編譯還是其他機制)應該至少能接受預狀態根、一個區塊和後狀態根作為輸入,並驗證後狀態根實際上是在預狀態根之上執行該區塊的結果。與以太坊的多客戶端相容。這意味著我們希望避免內置單一證明系統,而是允許不同的客戶端使用不同的證明系統。
這也意味著幾點:
數據可用性要求:對於任何使用封裝ZK-EVM 證明的EVM 執行,我們希望確保底層資料是可用的,這樣使用不同證明系統的證明者就可以重新證明執行,依賴該證明系統的客戶端就可以驗證這些新產生的證明。
證明位於EVM 和區塊資料結構之外:ZK-EVM 功能不會真的將SNARK 作為EVM 內部的輸入,因為不同的客戶端會期望不同類型的SNARK。相反,它可能類似於blob 驗證:交易可以包括需要證明的(預狀態、區塊體、後狀態)聲明,操作碼或預編譯可以訪問這些聲明的內容,客戶端共識規則會分別檢查資料可用性和區塊中所做聲明的證明。
可審計性:如果任何執行被證明,我們希望底層資料是可用的,這樣如果出現任何問題,使用者和開發者都可以檢查它。實際上,這增加了一個更多原因,為什麼數據可用性要求很重要。
可升級性:如果發現某個特定ZK-EVM 方案有bug,我們希望能夠快速修復它。這意味著不需要硬分叉就能修復問題。這又增加了一個原因,說明在EVM 和區塊資料結構之外的證明很重要。
支援“近似EVM”:L2s的一個吸引力在於能夠在執行層進行創新,並對EVM 進行擴展。如果某個L2的VM 只是稍微有點不同於EVM,那麼如果L2可以對與EVM 相同的部分使用原生的協定內ZK-EVM,並且只依賴自己的程式碼來處理不同的部分,這將是很好的。這可以透過設計ZK-EVM 功能來實現,使得呼叫者可以指定一個位元域或操作碼或地址列表,這些列表將由外部提供的表格而不是EVM 本身來處理。我們還可以使gas 成本在一定程度上可客製化。
“開放式”與“封閉式”多客戶端系統
「多客戶端思路」可能是這個清單中最有爭議的要求。一個選項是放棄多客戶端並專注於一個ZK-SNARK 方案,這將簡化設計。但代價是對以太坊進行更大的「哲學轉變」(因為這實際上是放棄了以太坊長期以來的多客戶端思維),並引入更大的風險。在長期的未來,例如當形式驗證技術變得更好時,走這條路可能會更好,但目前看來風險似乎太大。
另一種選擇是封閉的多客戶端系統,其中有一個固定的證明系統集合,該集合在協議內已知。例如,我們可能決定使用三個ZK-EVM:PSE ZK-EVM、Polygon ZK-EVM 和Kakarot。一個區塊需要至少來自這三個中的兩個的證明才有效。這比單一證明系統要好,但它使系統因為使用者必須為每個存在的證明系統維護驗證器,會有不可避免的治理過程來納入新的證明系統等原因而變得不那麼適應性強。
這促使我更傾向於一個開放的多客戶端系統,其中證明被放置在“區塊之外”,並由客戶端分別驗證。個別用戶會使用他們想要的任何客戶端來驗證區塊,只要有至少一個證明者為該證明系統創建證明,他們就能做到這一點。證明系統將透過說服用戶運行它們來獲得影響力,而不是透過說服協議治理過程。然而,這種方法確實有更多的複雜性成本,正如我們將看到的。
我們在ZK-EVM 實作中想要什麼關鍵特性?
除了基本的功能正確性和安全性保證之外,最重要的屬性是速度。雖然可以設計一個非同步的協議內置ZK-EVM 功能,每個聲明只在N 個slots 後返回結果,但如果我們能可靠地保證在幾秒鐘內就能產生一個證明,問題就會變得容易得多,這樣每個區塊中發生的事情就是自給自足的。
雖然今天為一個以太坊區塊產生一個證明需要花費幾分鐘或幾小時的時間,但我們知道沒有理論上的原因阻止大規模並行化:我們總是可以集結足夠的GPU 來分別證明區塊執行的不同部分,然後使用遞歸SNARK 將這些證明組合在一起。此外,透過FPGA 和ASIC 的硬件加速可以進一步優化證明過程。然而,實際達到這一點是一個不容小覷的工程挑戰。
協議內ZK-EVM 功能具體是什麼樣的?
類似於EIP-4844 blob 交易,我們引入了一種包含ZK-EVM 聲明的新交易類型:
class ZKEVMClaimTransaction(Container):
pre_state_root: bytes 32
post_state_root: bytes 32
transaction_and_witness_blob_pointers: List[VersionedHash]
...
與EIP-4844 一樣,在記憶體池中傳遞的物件是交易的修改版本:
class ZKEvmClaimNetworkTransaction(Container):
pre_state_root: bytes 32
post_state_root: bytes 32
proof: bytes
transaction_and_witness_blobs: List[Bytes[FIELD_ELEMENTS_PER_BLOB * 31 ]]
後者可以轉換為前者,但反之則不行。我們還擴展了區塊sidecar 物件(在EIP-4844 中引入),以包含區塊中聲明的證明清單。

請注意,在實踐中,我們可能希望將sidecar 拆分為兩個單獨的sidecar,一個用於blob,一個用於證明,並且為每種類型的證明設置一個單獨的子網(以及一個用於blob的附加子網路)。
在共識層,我們增加了一個驗證規則,即只有當客戶端看到區塊中每個聲明的有效證明時,才會接受區塊。證明必須是ZK-SNARK 證明的串聯,是一對的transaction_and_witness_blobs 序列化,並且pre_state_root 使用(i)有效,並且Witness (ii) 輸出正確的post_state_root. (Block, Witness) 潛在地,客戶可以選擇等待多種類型證明的M-of-N。
這裡的一個注意事項是,區塊執行本身可以簡單地被視為需要與ZKEVMClaimTransaction 對像中提供的三元組一起檢查的三元組( σpre,σpost, Proof)。
因此,使用者的ZK-EVM 實作可以取代其執行客戶端;執行客戶端仍將由(i) 證明者和區塊建構者使用,以及(ii) 關心索引和儲存資料以供本地使用的節點。
驗證和重新驗證
假設有兩個以太坊客戶端,其中一個使用PSE ZK-EVM,另一個使用Polygon ZK-EVM。假設此時,兩個實現都已經發展到可以在5 秒內證明以太坊區塊執行的程度,並且對於每個證明系統,都存在足夠多的獨立志願者運行硬件來產生證明。
不幸的是,由於獨立證明系統沒有被內置,因此它們不能在協議中得到激勵;然而,我們預計與研發成本相比,運行證明者的成本較低,因此我們可以簡單地使用通用機構為證明者提供公共產品資金。
假設有人發布了一個ZKEvmClaimNetworkTransaction ,只不過他們只發布了PSE ZK-EVM proof 的一個版本。 Polygon ZK-EVM 的證明節點看到了這一點,並使用Polygon ZK-EVM 的proof 計算並重新發布物件。

這增加了最早的誠實節點接受一個區塊和最新的誠實節點接受相同的區塊δ之間的總最大延遲: 2 δ+Tprove(假設Tprove<5 s )。
然而,好消息是,如果我們採用單槽(slot)最終性(finality),我們幾乎可以肯定地可以將這種額外的延遲與SSF 固有的多輪共識延遲一起「管道化」。例如,在4 子插槽提案中,「頭部投票」步驟可能只需要檢查基本區塊的有效性,但隨後「凍結並確認」步驟將需要存在證明。
擴充:支援“近似EVM”
ZK-EVM 特性的一個理想目標是支援「近似EVM」:即內置了一些額外功能的EVM。這可能包括新的預編譯、新的操作碼,甚至是合約可以在EVM 或完全不同的虛擬機器(例如,像Arbitrum Stylus 中的)中編寫的選項,或者甚至是具有同步交叉通訊的多個並行EVM。
一些修改可以以簡單的方式支援:我們可以定義一種語言,允許ZKEVMClaimTransaction 傳遞修改後的EVM 規則的完整描述。這可以做到:
自訂gas 表(使用者無法減少gas 成本,但可以增加)
停用某些操作碼
設置區塊編號(這將根據硬分叉而隱含不同規則)
設置一個標誌,用於啟動一整套EVM 更改,這些更改已針對L2 使用而非L1 使用進行標準化,或其他更簡單的更改
為了讓使用者以更開放的方式新增功能,透過引入新的預編譯(或操作碼),我們可以在ZKEVMClaimNetworkTransaction 的blob 中加入一個預編譯輸入/輸出記錄:
class PrecompileInputOutputTranscript(Container):
used_precompile_addresses: List[Address]
inputs_commitments: List[VersionedHash]
outputs: List[Bytes]
EVM 執行將以以下方式修改。初始化一個空的輸入數組。每當used_precompile_addresses 中的地址被呼叫時,我們向inputs 新增一個InputsRecord(callee_address, gas, input_calldata)對象,並將呼叫的RETURNDATA 設為outputs[i]。最後,我們檢查used_precompile_addresses 是否總共被呼叫了len(outputs)次,並且inputs_commitments 是否與對輸入的SSZ 序列化產生blob 承諾的結果相符。暴露inputs_commitments 的目的是為了讓外部的SNARK 更容易證明輸入和輸出之間的關係。
請注意輸入和輸出之間的不對稱性,輸入儲存在哈希中,而輸出儲存在必須提供的字節中。這是因為執行需要由只看到輸入並理解EVM 的客戶端來完成。 EVM 執行已經為他們產生了輸入,所以他們只需要檢查生成的輸入是否與聲稱的輸入匹配,這只需要一個哈希檢查。然而,輸出必須完整地提供給他們,因此必須是可用的數據。
另一個有用的功能可能是允許“特權交易”,這些交易可以從任意發送者帳戶發起呼叫。這些交易可以在兩個其他交易之間運行,或者在調用預編譯時,作為另一個(可能也是特權的)交易的一部分運行。這可以用來允許非EVM 機制回呼到EVM 中。
這種設計可以修改以支援新的或修改後的操作碼,除了新的或修改後的預編譯。即使只有預編譯,這種設計也相當強大。例如:
通過將used_precompile_addresses 設置為包括狀態中帶有某些標誌的普通賬戶地址列表,並製作一個SNARK 來證明它是正確構建的,你可以支持Arbitrum Stylus 風格的功能,其中合同可以用EVM 或WASM(或另一個VM)寫。特權交易可以用來允許WASM 賬戶回調到EVM 中。
透過新增一個外部檢查,以確保多個EVM 執行的輸入/輸出記錄和特權交易以正確的方式匹配,你可以證明一個透過同步通道相互交談的多個EVM 的平行系統。
一種4 型ZK-EVM 可以透過擁有多個實現來操作:一個直接將Solidity 或另一種高階語言轉換為對SNARK 友善的VM,另一個將其編譯為EVM 代碼並在內置的ZK-EVM中執行。第二種(不可避免地更慢的)實現只能在故障證明者發送一個斷言存在bug 的交易的情況下運行,如果他們能提供兩者處理不同的交易,則收集賞金。
一種純非同步VM 可以通過使所有呼叫返回零並將呼叫映射到添加到區塊末尾的特權交易來實現。
擴展:支援有狀態的證明器
上述設計的一個挑戰是它完全無狀態,這使得它在數據上效率低。在理想的資料壓縮情況下,與僅有狀態壓縮相比,使用有狀態壓縮的ERC 20 發送可以高達3 倍的空間效率。

此外,有狀態的EVM 不需要提供見證資料。在這兩種情況下,原則是相同的:當我們已經知道數據是可用的,因為它是在先前的EVM 執行中輸入或產生的,那麼要求數據是可用的就是一種浪費。
如果我們想讓ZK-EVM 特性有狀態,那麼我們有兩個選擇:
1)要求σpre 要麼為空,要麼是已宣告鍵和值的可用資料列表,要麼是某次之前執行的σpost 。
2)在( σpre, σpost, Proof ) 三元組中加入一個對區塊產生的收據R 的blob 承諾。任何先前生成或使用的blob 承諾,包括那些代表區塊、見證、收據甚至是普通的EIP-4844 blob 交易的承諾,可能有一些時間限制,可以在ZKEVMClaimTransaction 中引用,並在其執行期間訪問(可能通過一系列指令:「將承諾i 的字節N...N+k-1 插入到區塊+見證資料的位置j 」)。
選項一表示:與其內建無狀態EVM 驗證,不如內建EVM 子鏈。選項二本質上是創建一個最小的內置狀態壓縮算法,它使用先前使用或產生的blob 作為字典。這兩種方法都會給證明者節點帶來負擔,只有證明者節點需要儲存更多資訊;在情況二中,比起情況一更容易讓這種負擔有時間限制。
封閉式多證明器和鏈下資料的參數
一個封閉的多證明者係統,其中有一個固定數量的證明系統在一個M-of-N 結構中,避免了上面的許多複雜性。特別是,封閉的多證明者係統不需要擔心確保資料在鏈上。此外,一個封閉的多證明者係統將允許ZK-EVM 證明鏈下執行;這使其與EVM Plasma 解決方案相容。
然而,一個封閉的多證明者係統增加了治理複雜性並移除了可審計性,這些是高昂的成本,需要與這些好處相權衡。
如果我們將ZK-EVM 內置並使其成為協議特性,那麼「Layer 2 專案」的角色是什麼?
目前由Layer 2 團隊自己實作的EVM 驗證功能將由協定處理,但Layer 2 專案仍負責許多重要功能:
快速預確認:單一slot 的最終確定性可能會使Layer 1 的slot 變慢,而Layer 2 項目已經在為其用戶提供“預確認”,這些預確認由Layer 2 自身的安全性支持,延遲遠低於一個slot。這項服務將繼續完全由Layer 2 負責。
MEV(礦工可提取價值)緩解策略:這可能包括加密的mempool、基於聲譽的排序器選擇,以及Layer 1 不願意實現的其他功能。
對EVM 的擴展:Layer 2 專案可以為其使用者提供EVM 的重大擴充。這包括「近似EVM」和像Arbitrum Stylus 的WASM 支援以及對SNARK 友善的Cairo 語言這樣的根本不同的方法。
面向用戶和開發者的便利性:Layer 2 團隊在吸引用戶和項目到他們的生態系統並使他們感到受歡迎方面做了很多工作;他們通過在其網絡內捕獲MEV 和擁堵費用來獲得補償。這種關係將繼續存在。


