
框架交易與隱私保護的三道門檻
AI 生成摘要
本文分析了 EIP-8141 框架交易如何消除隱私協議中的中繼者,並探討了當前內存池規則、FOCIL 強制執行與無狀態路線圖之間在支持隱私交易方面存在的技術衝突。
本文將 EIP-8141 視為既定前提,而非爭論其優劣。目標是展示 Frame 交易如何改進隱私協議,以及公共內存池(mempool)規則和包含列表(inclusion list)強制執行需要做出哪些改變,才能使其真正發揮作用。
Frame 交易(EIP-8141)有望將中繼者(relayers)從隱私協議中移除。然而,管理公共內存池准入、FOCIL 強制執行以及無狀態(statelessness)路線圖的規則,各自對其支持的交易劃定了不同的界限。本文分析了這些界限在何處交匯,以及在何處產生衝突,特別是針對保護隱私的交易。
Frame 交易如何消除中繼者
像 Tornado Cash 和 Railgun 這樣的隱私協議使用 zk-SNARKs 斷開存款者與取款者之間的鏈上聯繫。取款操作證明了對 Merkle 樹中某個有效承諾(commitment)的知曉,而不洩露是哪一個。問題在於:取款者的地址是全新的,沒有 ETH 來支付 Gas。目前,中繼者(中心化、可被審查的第三方,且常在需要時離線)通過資助取款交易來彌補這一缺口。
EIP-8141 改變了這種經濟模式。Frame 交易的 VERIFY 框架作為 STATICCALL 運行:唯讀,無狀態變更。如果 VERIFY 在付款核准前恢復(revert),則該交易在協議層級無效,永遠不會進入區塊,且不會向任何人收取 Gas。隱私取款流程變為:
-
VERIFY 框架(設置
tx.sender = pool,因此框架針對資金池自身的存儲):從SENDER框架的 calldata 中讀取publicInputs,根據資金池存儲的歷史記錄驗證 Merkle 根(SLOAD),確認作廢符(nullifier)未被使用(SLOAD),並針對這些publicInputs執行 Groth16 配對檢查。如果一切通過,則調用APPROVE。 -
SENDER 框架:將作廢符標記為已使用,將淨額轉移給接收者,並將手續費計入資金池內的資助者(sponsor)帳下。
至關重要的是,手續費不再需要來自外部資助者。取款本身就可以支付執行費用:SENDER 框架可以撥出一部分取款資金來覆蓋 Gas,從而消除了對預先注資的發送者或第三方中繼者的需求。資助者的份額作為內部信用留在資金池中,稍後可以領取,因此取款只會產生一筆對外轉帳而非兩筆。
| 模式 | 子類 | 目標 | 調用者 | 標誌 | 數據 | 角色 |
|---|---|---|---|---|---|---|
| 0 | VERIFY | only_verify | pool (null → tx.sender) | ENTRY_POINT | APPROVE_EXECUTION | SNARK 證明 |
| 1 | VERIFY | pay | sponsor | ENTRY_POINT | APPROVE_PAYMENT | (空 / 資助者策略數據) |
| 2 | SENDER | user_op | pool (null → tx.sender) | pool (tx.sender) | APPROVE_SCOPE_NONE | withdraw(publicInputs) |
對於無效證明,資助者的風險為零(VERIFY 恢復,交易丟棄);對於重放證明,風險也為零(作廢符已標記,VERIFY 恢復)。無需信任,無需中繼者基礎設施,也沒有額外的審查空間。
進入包含列表的三道門檻
以隱私為中心的 Frame 交易通往抗審查的道路需經過三道獨立的門檻,每道門檻都有其自身的約束:
第一道門檻:公共內存池准入
EIP-8141 的內存池規則借鑑自 ERC-7562,但完全剔除了質押和聲譽機制,定義了哪些內容可以通過公共 P2P 網絡傳播:
- 驗證前綴必須匹配公認的模式(
self_verify或only_verify + pay,可選前置deploy) SLOAD僅限於讀取tx.sender的存儲- 總
VERIFYGas 限制在MAX_VERIFY_GAS(100,000) 以內 - 禁用操作碼:
TIMESTAMP,NUMBER,BLOCKHASH,BALANCE,SELFBALANCE,SSTORE,TLOAD,TSTORE等 - 規範付款人(Canonical paymaster)通過精確的運行時代碼哈希識別,具有時間鎖取款和節點端待處理餘額追蹤
- 非規範付款人限制為每個僅能有
MAX_PENDING_TXS_USING_NON_CANONICAL_PAYMASTER(1) 筆待處理交易
任何違反這些規則的交易都會被公共內存池拒絕,但仍可通過替代內存池(alt-mempools)或私有渠道到達構建者(builders)。
第二道門檻:FOCIL 強制執行
FOCIL 保證交易包含:每個時隙(slot)由 16 名 IL 委員會成員根據其觀察到的待處理交易構建包含列表。證明者(Attesters)只為包含 IL 交易(或證明其在後狀態下無效)的區塊投票。
對於 EOA,FOCIL 的遺漏檢查是對後狀態進行廉價的 nonce/餘額查詢。對於 FrameTxs,遺漏檢查需要重放 VERIFY 前綴。沒有廉價的替代方案,因為交易有效性取決於執行,而不僅僅是發送者狀態。FOCIL-frame-txs 提案通過五個約束定義了資格:
- 驗證前綴順序:
VERIFY框架必須排在DEFAULT/SENDER框架之前 - 單筆交易 VERIFY Gas 限制:
verify_gas(tx) <= MAX_VERIFY_GAS_PER_FRAMETX(100,000) - 單個 IL 的 VERIFY 預算:整個 IL 的累計
VERIFYGas 上限為MAX_VERIFY_GAS_PER_INCLUSION_LIST(250,000) - 基本交易健全性:
chain_id、費用、無 blobs - 受限的狀態訪問:
VERIFY僅能讀取tx.sender和付款人帳戶狀態(餘額、nonce、代碼)及其前 N 個存儲槽(N = 2-4),與 AA-VOPS 快取一致。讀取任何其他合約的存儲都會使交易失去資格。
違反任何約束的 FrameTxs 將被免除 FOCIL 強制執行:構建者遺漏這些交易不會受到懲罰。
第三道門檻:節點驗證能力
術語說明:
PS = 部分無狀態(Partial Statelessness):持有部分狀態,而非全部
VOPS = 僅有效性 PS(Validity-Only PS):持有足夠狀態以驗證來自 EOA 的交易
AA-VOPS = VOPS + 每個帳戶少數幾個存儲槽
在 ZKEVM 之後,節點將不需要持有完整狀態。例如,VOPS 節點僅存儲約 8.4 GB(每個帳戶的 nonce、餘額、codeHash)。AA-VOPS 通過在 trie 中維護每個帳戶的前 N 個存儲槽來擴展此功能(因此某些 tx.sender 和付款人存儲槽可用於本地 VERIFY 重放)。部分無狀態(PS)節點還會額外追蹤選定合約的存儲。節點類型決定了它可以本地重放哪些 VERIFY 框架,進而決定了它可以准入哪些交易類別到其內存池並源入類 FOCIL 的包含列表:
| 能力 | 全節點 | PS 節點 | AA-VOPS | VOPS |
|---|---|---|---|---|
| EOA nonce/餘額檢查 | 是 | 是 | 是 | 是 |
| AA 錢包 VERIFY (tx.sender 存儲) | 是 | 若有追蹤 | N 個槽位子集 | 否 |
| 規範付款人准入 (代碼哈希匹配 + 餘額預留) | 是 | 是 | 是 | 是 |
| 規範付款人 VERIFY 軌跡重放 | 是 | 若有追蹤 | 否 | 否 |
| 隱私池存儲 (roots, nullifiers) | 是 | 若有追蹤 | 否 | 否 |
無法驗證某種交易類型的節點無法在其內存池中維護該交易,也不應將其包含在 IL 中。該類別的抗審查性會隨著具備能力的驗證者比例下降而惡化。
參見 從無狀態視角看 Frame 交易 以獲取關於哪些節點類型支持哪些 EIP-8141 內存池策略的詳細分析。
為什麼隱私交易無法通過這三道門檻
在默認參數下,隱私取款無法通過所有三道門檻:
第一道門檻(公共內存池):設置 tx.sender = pool 後,VERIFY 框架對資金池 Merkle 根歷史和 nullifierHashes 映射的 SLOAD 雖然滿足了僅限 tx.sender 存儲的限制,但 Groth16 配對檢查超過了 EIP-8141 驗證軌跡規則中定義的 100k MAX_VERIFY_GAS 上限。被拒絕。
第二道門檻(FOCIL 資格):Groth16 配對檢查超過了單筆交易 100k 的 VERIFY Gas 預算。即使 tx.sender = pool 使資金池存儲符合受限狀態訪問規則,僅 Gas 上限一項就使交易失去資格。被免除強制執行。
第三道門檻(節點能力):VOPS 和 AA-VOPS 節點不持有資金池合約存儲。只有追蹤該資金池的 PS 節點或全節點才能驗證。
| 交易類型 | 公共內存池 | FOCIL 合格 | VOPS | AA-VOPS | PS (追蹤資金池) |
|---|---|---|---|---|---|
| EOA frame tx (ECDSA/P256) | 是 | 是 | 是 | 是 | 是 |
| 智能錢包 (tx.sender 存儲, <= N 槽) | 是 | 是 | 否 | 是 | 是 |
| 規範付款人資助 | 是 | 是 | 否 | 否 | 若有追蹤 |
| 隱私取款 | 否 | 否 | 否 | 否 | 若有追蹤 |
因此,隱私交易被排除在每一條通往抗審查的默認路徑之外。最需要抗審查的交易,恰恰是當前設計無法保護的交易。
這並非不可避免。差距源於 FOCIL 如何強制執行 FrameTxs 的包含,而 FOCIL-frame-txs 提案提供了兩種具有截然不同影響的方法。兩者之間的選擇決定了隱私相關的 FrameTxs 是否有通往抗審查的道路。
FOCIL 強制執行:兩種方法
兩種方法都解決同一個問題:構建者如何證明他們沒有審查合格的 IL FrameTxs,以及證明者如何驗證這些聲明。
追加循環法(Append-loop approach)
默認方法是讓構建者迭代地將被排除的合格 IL FrameTxs 追加到區塊中,直到在最終後狀態下沒有被遺漏的 FrameTx 是有效的。成本相對於被排除的 FrameTxs 數量是 O(k²)。這種二次方的構建者成本迫使參數趨於保守:MAX_VERIFY_GAS_PER_FRAMETX 為 100,000,MAX_VERIFY_GAS_PER_INCLUSION_LIST 為 250,000。
假設有 25% 的對抗性 IL 委員會(16 名成員中有 4 名,這在 1% 質押份額下大約每月發生一次)且交易約為 100 字節:每個 IL 可以在 MAX_BYTES_PER_INCLUSION_LIST (8 KiB) 內容納約 81 筆交易,但每個 IL 的 VERIFY Gas 預算僅允許 2 筆達到 MAX_VERIFY_GAS_PER_FRAMETX 上限的 FrameTxs(2 * 100k = 200k <= 250k)。4 個惡意 IL 會產生 k=8 個無效 FrameTxs。追加循環運行 k(k+1)/2 = 36 次 VERIFY 重放:3.6M Gas(約佔區塊的 6%)。證明者工作量:4 * 250k = 1M Gas(約 1.7%)。開銷雖然適中,但這些參數使得 FOCIL 對 FrameTxs 幾乎形同虛設:100k 的 MAX_VERIFY_GAS_PER_FRAMETX 排除了 Groth16 證明、後量子(PQ)簽名和任何非平凡的驗證邏輯,而 250k 的 MAX_VERIFY_GAS_PER_INCLUSION_LIST 將每個 IL 限制在僅 2 筆滿額 Gas 的 FrameTxs。一個空間僅夠容納 2 筆可強制執行 FrameTxs 的 IL,幾乎無法強制執行帳戶抽象。
驗證索引法(Validation-index approach)
後續方案消除了追加循環。取而代之的是,構建者通過發布一個 (tx_hash, claimed_index) 對來為每筆被排除的交易辯解,聲明該交易在區塊的哪個索引處變得無效。證明者使用區塊訪問列表(EIP-7928)在 claimed_index 處重建狀態並重放 VERIFY 前綴。如果 VERIFY 成功,則構建者撒謊,區塊違反 IL 條件。構建者成本從 O(k²) 降至 O(k)。權衡之處在於增加了協議複雜性:索引聲明是額外的網絡工件,engine_newPayload 需要將其與 IL 交易一起接受,且執行層(EL)需要相應地驗證它們。
由於構建者成本不再是瓶頸,MAX_VERIFY_GAS_PER_INCLUSION_LIST 可以提高到 2^20(~1M Gas),且單筆交易上限變得不那麼關鍵,因為每筆被排除的交易是在其聲明的索引處驗證一次,而非迭代驗證。每個 IL 2^20 的預算足以讓來自隱私協議的交易從 FOCIL 的抗審查保證中受益。
同樣是 25% 對抗場景:每個 IL 現在可以預算多達 10 筆每筆 100k 的 FrameTxs(10 * 100k = 1M <= 2^20)。四個惡意 IL * 10 = 40 筆被排除的 FrameTxs。構建者成本是線性的:40 * 100k = 4M Gas(約區塊的 6.7%)。證明者成本:4 * 2^20 ≈ 4.2M Gas(約 7%)。所有 16 個 IL 的最壞情況:16 * 2^20 = 2^24 ≈ 16.8M Gas(約 28%)。每個 IL 預算約 4 倍的增長完全消除了二次方的構建者成本爆炸。
節點能力作為限制因素
索引法開啟了公共內存池規則與 FOCIL 強制執行之間的分離。公共內存池規則必須嚴格,因為交易可能在每個區塊後都需要重新驗證,因此狀態依賴必須小且具確定性。驗證索引法下的 FOCIL 在固定的 claimed_index 處僅重放一次 VERIFY。沒有持續的維護成本,這使得它可以負擔更廣泛的狀態訪問和更高的 Gas 預算。反之:FOCIL 驗證處於證明者的關鍵路徑上(在 t=4s 的證明截止時間內),而內存池驗證是異步運行的。更高的 MAX_VERIFY_GAS_PER_INCLUSION_LIST 會直接消耗證明者的時間預算。
這意味著 IL 委員會成員可以從替代內存池(包括以隱私為中心的內存池)獲取交易並將其包含在 IL 中,即使默認的公共內存池不攜帶這些交易。但要讓隱私交易發揮作用,受限狀態訪問規則(僅限讀取 tx.sender 和付款人帳戶)需要放寬。而且強制執行的節點需要狀態來實際驗證這些交易。
AA-VOPS 無法彌補這一差距。它為每個帳戶快取 N 個存儲槽,這對於簡單的錢包驗證(所有者密鑰、nonce)足夠,但對於隱私協議則不然。隱私交易相關的 VERIFY 框架讀取資金池合約存儲(根環形緩衝區、作廢符映射),而非發送者存儲。調整 N 的值也無濟於事:讀取目標完全是另一個合約。即使 AA-VOPS 為每個合約快取 N 個槽位也沒用:作廢符映射是通過哈希鍵控的,因此訪問的槽位是不可預測的,且分佈在整個存儲 trie 中。
規範隱私池(A Canonical Privacy Pool)
最務實的解決方案是規範池模式,類似於規範付款人。一個通過代碼哈希識別的規範合約可以作為多個隱私協議的共享註冊表:以統一、可審計的佈局存儲每個池的僅追加(append-only)Merkle 根和作廢符集。設計得當,這樣的池對於公共內存池和 FOCIL 強制執行都是安全的:針對此合約的 VERIFY 框架精確讀取兩個存儲槽:acceptedRoots[R] 和 nullifierHashes[h],兩者都位於可從 calldata 推導的鍵處。訪問模式是受限、可預測且單調的:VERIFY 讀取的每個槽位只會發生 false → true 的轉變。規範註冊表不需要節點追蹤 N 個獨立的資金池合約,而是將問題簡化為一個具有已知存儲佈局的知名地址,從而以極低的成本使隱私的部分無狀態化變得可行。
單調狀態是使設計具備抗大規模失效(mass-invalidation-resistant)能力的關鍵。當今的隱私協議使用近期 Merkle 根的滾動環形緩衝區,在每次存款時剔除最舊的條目。在 EIP-8141 下,這種剔除是一個大規模失效向量:單次存款(或攻擊者垃圾郵件)可以輪換掉數十個待處理資助取款所依賴的根,從而同時將它們全部從內存池中剔除。將環形緩衝區替換為僅追加的 acceptedRoots 映射可以完全消除該向量。針對任何歷史根生成的取款證明將永遠有效;作廢符集已經防止了雙重支出,因此接受舊根在加密學上是安全的。唯一能使待處理取款失效的狀態更改是寫入其特定的 nullifierHashes[h] 槽位,這需要持有該票據(note)的秘密。這是針對單筆交易且精確定位的,絕不會發生大規模失效。
一個實現細節:當今隱私協議中常用的 Merkle 根環形緩衝區必須替換為僅追加映射,以避免大規模失效。就大小而言,這並無大礙:例如,最常用的 Tornado Cash 合約(1-ETH 池)有 81,881 筆存款。這大約是 10.5 MB 的原始鍵值數據(
acceptedRoots和nullifierHashes各 81,881 個條目,每個條目約 64 字節),存儲在狀態 trie 中後約為 25–40 MB。追蹤此池的 PS 節點承擔的額外狀態遠低於 50 MB,與 ~8.4 GB 的 VOPS 基準相比微不足道。
每個時隙有 16 名 IL 委員會成員,FOCIL 只需要 1/16 的誠實成員即可保證包含。但這裡的「誠實」也意味著「有能力」:一個想要包含隱私交易但運行 VOPS 或 AA-VOPS 節點的成員根本無法驗證它。1/16 誠實假設變成了 1/16 能力假設。PS 節點解決了這個問題。它們不需要完整狀態,只需要它們關心的合約。追蹤一個規範隱私池的 PS 節點最多增加幾 MB。基礎設施成本微乎其微;問題在於是否有足夠的驗證者選擇這樣做。
規範化隱私池的一個替代方案是讓交易發送者隨交易附帶所需的狀態(存儲)以及針對最新狀態根的 Merkle 證明。這種方法存在缺陷,原因有很多,最重要的是這些證明在每個區塊後都會失效,必須不斷重新計算。
建議的變更
-
將規範合約例外擴展到隱私池。 EIP-8141 已經通過運行時代碼哈希匹配准入規範付款人,免除其受嚴格公共內存池規則的限制,因為它們的狀態依賴性已知是安全的。
-
提高規範合約框架的單筆交易 VERIFY Gas 上限。
MAX_VERIFY_GAS = 100,000不足以支持 Groth16(~250k)。規範合約具有固定的驗證路徑,因此其最壞情況下的VERIFY成本是代碼哈希的一個靜態屬性。無效證明與有效證明燃燒相同的 Gas 並被丟棄,沒有放大效應。對通用框架保持 100k;對規範合約框架允許例如 ~400k,留出足夠空間,並限制它們在內存池中的數量。 -
採用驗證索引 FOCIL 強制執行,接受增加的協議複雜性(
(tx_hash, claimed_index)映射),以消除迫使 FrameTx 採用保守 Gas 預算的二次方構建者開銷。 -
將 MAX_VERIFY_GAS_PER_INCLUSION_LIST 提高到 2^20 (=1M),讓具有更高
VERIFYGas 的單個交易(Groth16、PQ 簽名)能納入每個 IL 的預算。 -
放寬規範隱私池合約的受限狀態訪問規則,允許 IL 委員會成員從替代內存池獲取這些交易,並使運行追蹤這些合約的 PS 節點的證明者能夠強制執行其包含。
這些措施共同為隱私 FrameTxs 提供了一條可行的抗審查路徑:在規範合約例外下進行公共內存池傳播,由具備 PS 能力的 IL 成員包含,並通過驗證索引法進行 FOCIL 強制執行,同時不削弱非規範 FrameTxs 的抗 DoS 能力。
類似的論點也適用於後量子交易。PQ 簽名體積大且驗證昂貴,100k 的
VERIFYGas 不足以覆蓋。與隱私協議一樣,PQ 交易需要豁免統一上限,方法可以是規範化驗證合約,或添加規範預編譯(precompiles)。
當前 FrameTxs 的公共內存池規則、VOPS 和 AA-VOPS 對於隱私協議來說過於僵化。規範化隱私池改變了這一點。通過代碼哈希識別它們讓公共內存池能安全地驗證其 VERIFY 框架,而追蹤一組少量高價值合約(隱私池、規範付款人)的 PS 節點可以為其構建包含列表。這換來的是對那些最需要它的交易的抗審查性。
附錄
為什麼替代內存池會失敗
-
碎片化無法組合:每種需要更重度驗證的交易(隱私、PQ 等)可能都必須產生自己的替代內存池。節點運營商會挑選贏家,支持這些池的節點數量會變稀疏,而最弱的替代內存池會成為其所依賴內容的審查向量。在沒有內置激勵的情況下,替代內存池只能通過要求志願者利他地運行來擴展,甚至可能要求他們購買更強大、更昂貴的硬件。
-
匿名集崩潰:匿名集從「所有以太坊節點」退化為「支持隱私內存池的節點」,且對等連接會在網絡層洩漏。
-
在網絡層極易被審查:單一用途替代內存池的引導節點(Bootstrap nodes)、DNS 記錄和對等列表是 ISP 或國家可以通過一條規則封鎖的關鍵點。公共內存池難以審查,因為它是整個網絡的支柱;替代內存池則不然。隱私流量最終會落在結構上比它所取代的中繼者更容易被下線的基礎設施上。
-
FOCIL 的 1/16 假設破裂:只有當至少一名 IL 委員會成員與替代內存池建立對等連接且能驗證交易時,及時包含才成立。「1/16 誠實」假設變成了「1/16 誠實、已訂閱且有能力」,這比 EIP-7805 承諾的保證要弱得多。如果 IL 構建者被宣傳為低硬件節點,這尤其成問題。
-
中繼者並未消失,只是轉移了:替代內存池交易仍需到達構建者。跨邊界轉發的橋接節點正是 Frame 交易本應消除的信任和審查表面,只是在堆棧中下移了一層。
Frame 交易 <> 公共內存池決策樹:
規範隱私池示例
有關規範隱私協議實現示例(使用偽代碼),請查看此處。
相關文章
其他收藏 · 0
收藏夾