從『抓出說謊者』到『證明你說了實話』
在上一篇你認識了 樂觀 Rollup:一種 第二層,由定序器貼出新的狀態根,然後僅僅「宣稱」它是對的。接下來大約七天內,任何人都能在 挑戰期 提交 詐欺證明 來推翻它。想像一位裁判:除非有人在一週內正式提出抗議,否則每個進球都算數。這行得通——但你的錢在被證明造假之前都先當作清白,而且你得等上一週才能提款回 L1。
ZK-Rollup 則把舉證責任整個翻轉。它不採「先假定有效,再寄望有人抓出詐欺」,而是為每個批次附上一張數學收據——一份 有效性證明——擔保這個批次確實被正確執行。L1 合約會在「接受新狀態之前」就先「驗過這張收據」。在證明通過之前,沒有任何一球算數;也因此沒有長達一週的抗議窗口,因為根本沒什麼好抗議的。定序器無法貼出一個錯誤狀態再嗆你來抓:一個假命題根本就生不出有效的證明。
這筆交易:用一個小證明,擔保一場大運算
整個把戲建立在一種不對稱上。「生成」證明很「昂貴」:證明者會把整個批次放進一個 證明電路 裡重跑一遍,並做大量密碼學運算。但「驗證」它卻又便宜又快——而且關鍵是,驗證成本幾乎是「常數,無論這個批次裝了多少筆交易」。一份涵蓋 50 筆轉帳的證明,和一份涵蓋 50,000 筆的證明,驗起來耗的 gas 大致一樣少。這個常數成本的檢查,就是整套擴容引擎:成千上萬筆 L2 交易,被攤平成 L1 上一次便宜的證明驗證。
用真實數字會更具體。一份 Groth16 SNARK 在以太坊上驗證大約只要 200,000~300,000 gas,長度也只有區區數百位元組——不管這個批次搬動了 50 筆還是 50,000 筆交易。證明者真正擔保的,是這一句話:「從舊狀態根 S_old 出發,依協定規則套用這個批次,會得到新狀態根 S_new。」這份證明具備「健全性(soundness)」——如果定序器想偷渡一筆無效交易(花用它根本沒有的錢、或餘額算錯一位),那個假命題就生不出有效證明,L1 驗證者便會拒絕它。你不再去信任定序器,而是改去信任數學。
L1 驗證者:整套機制最終落腳之處
在 L1 上,一個 ZK-Rollup 最終濃縮成一份合約:它保存著當前的狀態根,並持有一個 證明驗證器。每個批次的成敗,全繫於一道 `require` 檢查。以下就是它的核心,去蕪存菁到最精簡:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IVerifier {
// Returns true iff `proof` attests that applying the batch
// takes the rollup from `oldRoot` to `newRoot`, and that the
// batch the proof covers hashes to `batchDataHash`.
function verifyProof(
bytes calldata proof,
bytes32 oldRoot,
bytes32 newRoot,
bytes32 batchDataHash
) external view returns (bool);
}
contract ZkRollup {
bytes32 public stateRoot; // the rollup's current state commitment
IVerifier public immutable verifier;
event BatchSettled(bytes32 oldRoot, bytes32 newRoot);
constructor(IVerifier _verifier, bytes32 genesisRoot) {
verifier = _verifier;
stateRoot = genesisRoot;
}
/// Settle one batch. Reverts unless the validity proof checks out.
function submitBatch(
bytes calldata batchData, // the L2 txs, posted for data availability
bytes32 newRoot,
bytes calldata proof
) external {
bytes32 oldRoot = stateRoot;
bytes32 dataHash = keccak256(batchData);
// The ENTIRE security of the rollup is this one line.
require(
verifier.verifyProof(proof, oldRoot, newRoot, dataHash),
"invalid validity proof"
);
stateRoot = newRoot; // final immediately - no challenge window
emit BatchSettled(oldRoot, newRoot);
}
}有兩點值得留意。其一,`submitBatch` 是在「驗證證明的同一筆交易」裡就更新 `stateRoot`——沒有挑戰窗口,因此這個 L2 狀態在以太坊納入該批次的當下就已定案(只受 L1 自身 最終性 約束)。其二,`batchData` 仍然得貼上鏈。證明只擔保了狀態轉換「正確」,本身並不會讓資料「可得」:任何想重建這條 L2 的人——要跑節點、要證明所有權、要強制退出——都還是需要原始交易資料。這就是 資料可得性 問題,也正是下一篇的主題。如果你只貼證明、卻把資料藏起來,那你做的就是另一種東西,叫做「validium」——它用「鏈上資料可得性的保證」去換取更低的成本。
一個批次的一生,從頭到尾
- 使用者簽署 L2 交易並送給 定序器,由它排好順序,幾乎即時回傳一個軟性的預確認。
- 定序器以當前狀態為基底,在鏈下執行這個批次,算出新的狀態根 S_new。這一步很便宜——它不過是普通的執行,還沒動到任何密碼學。
- 一個證明者——通常是另一台、吃重 GPU 的機器——把批次放進證明電路裡重跑一遍,生成有效性證明。這是昂貴又緩慢的一步:耗時數秒到數分鐘,並吃掉大量硬體資源。
- 定序器把三樣東西貼上 L1:批次的交易資料(供資料可得性)、新的狀態根,以及那份證明。
- L1 驗證者合約檢查這份證明。通過的話,S_new 即刻被接受並定案;不通過的話,整筆提交回滾,L1 上什麼都不會改變。
- 因為狀態在被證明的瞬間就已定案,一筆回 L1 的提款,只要它所在的批次被證明並驗證通過,就能立即兌現——不像樂觀 Rollup 那樣要等上七天。
兩種證明風味:SNARK、STARK,以及你究竟在信任什麼
有兩大證明家族當道。zk-SNARK(Groth16、PLONK)給出最小的證明與最便宜的驗證,但其中許多需要 可信設定:一場一次性的儀式,產生公開參數,而其中的祕密隨機性——所謂「有毒廢料(toxic waste)」——必須被銷毀。令人安心的是它的「N 取 1」信任模型:只要 powers-of-tau 儀式 裡哪怕只有一位參與者誠實地刪掉自己那份,整個設定就是安全的;唯有「全部人」串通並留著它,他們才偽造得出證明。PLONK 系的系統用一次通用設定就能跨電路重用;Groth16 則每個電路都得重做一次設定。
zk-STARK(StarkWare 的 Cairo)則完全不需要可信設定——它們是「透明的」,只用雜湊函式構築,這也讓它們可望抗量子。代價是證明較大、在 L1 上驗證要花更多 gas(數百萬 gas,相對於 SNARK 的區區數十萬)。一個流行的折衷,是把 STARK 包進 SNARK 裡:你既得到 STARK 那種透明、快速的證明生成,最後又能在鏈上享有便宜的 SNARK 驗證。天下沒有白吃的午餐——每個選擇都是在證明大小、證明速度、驗證 gas 與信任假設之間互相權衡。
zkEVM 這道難題,以及該怎麼選
通用型 ZK-Rollup 真正的難關,在於證明「EVM 本身」。早期的有效性 Rollup 靠「應用專屬」來迴避這點:Loopring 與 zkSync Lite 只證明一份固定菜單上的付款操作;StarkEx 則為 dYdX v3、Immutable X 與 Sorare 證明交易與 NFT。要在「任意」智慧合約之下,去證明一整個 以太坊 式 世界狀態 的更新,那難得多——每個操作碼、每次儲存寫入、每一回 keccak,都得在電路裡表達出來。一個能對一般 Solidity 做到這件事的 zkEVM 是聖杯,而通用型 zkEVM 直到 2023 年起才陸續上主網(Polygon zkEVM、zkSync Era、Scroll、Linea;Starknet 則經由 Cairo)。
Vitalik 的「Type 1~4 zkEVM」分類,正好點出核心的權衡:EVM 等價性,對上證明速度。「Type 1」zkEVM 證明的是分毫不差的以太坊執行,完美等價,卻是最慢、最昂貴的證明對象。「Type 2」(如 Scroll、Polygon zkEVM)在位元組碼層級與 EVM 等價,僅做少許內部微調。「Type 4」則把高階 Solidity 編譯到一個對 ZK 友善的虛擬機(Starknet 的 Cairo、zkSync Era 的路線)——證明最快,但位元組碼相容性最低,因此部分工具鏈與邊角合約行為會有出入。你坐得離原生以太坊愈近,就得跑愈吃重的證明者。
把它擺到上一篇的樂觀 Rollup 旁邊,權衡就一目了然。「提款」——ZK:證明完成後數分鐘到數小時;樂觀:約 7 天。「安全性」——ZK:純密碼學,不需要一位時刻盯場的誠實方,但帶著電路與可信設定的風險;樂觀:至少需要一位誠實的觀察者在窗口內提出挑戰,外加一條抗審查的 L1,好讓詐欺證明能上得了鏈。「成本與成熟度」——ZK:證明吃重、EVM 相容較難、較新;樂觀:便宜、簡單、更早經過實戰。還有一個常被忽略的重點:「兩者都仍得把資料貼上 L1」——誰也逃不過 資料可得性,而那正是兩者共同的、真正的瓶頸,也是下一篇要處理的。