newsence

FOCIL 與原生帳戶抽象化

Ethereum Magicians·20 天前

本文探討 FOCIL 如何透過定義符合條件的框架交易子集,並實施受限的驗證程序來支援原生帳戶抽象化,在不增加過度運算負擔的情況下確保抗審查特性。

作者:Thomas Thiery

感謝 Jihoon Song Julian Ma Toni Wahrstätter 以及 Vitalik Buterin 提供的反饋與建議。

摘要: FOCIL 透過廉價的 Nonce/餘額代理(proxy)對照後置狀態(post-state),來檢查被遺漏的包含列表(Inclusion List, IL)交易。這對 EOA 有效,但對原生帳戶抽象(AA)無效,因為 AA 交易的有效性需要執行 VERIFY 框架。本文定義了一個適用於公共內存池(mempool)的 FrameTx 子集,並採用更嚴格的遺漏檢查:針對後置狀態執行有界的 VERIFY,並為每個 IL 設定 VERIFY-gas 預算以限制證明者(attester)的工作量。

背景

在執行區塊後,FOCIL (EIP-7805) 會檢查每個未被包含的 IL 交易:如果該交易符合剩餘 Gas 且通過針對後置狀態的 Nonce/餘額檢查,則該區塊違反 IL 條件,證明者將不會為其投票。

這種代理方式成本極低(每筆排除的交易只需一次帳戶查詢,無需執行),且非常適合 EOA 和 EIP-7702,因為遺漏衝突會透過發送者的 Nonce 和餘額顯現出來。

本提案不會改變 FOCIL 對 EOA 或 EIP-7702 交易的行為。以下內容僅適用於下文定義的合規子集中的 Frame 交易 (EIP-8141)。

合規的 FrameTxs

本說明在兩類 FrameTx 之間劃分了嚴格的界限。

「合規的 FrameTxs」是同時被視為適用於公共內存池且受 FOCIL 強制執行的子集。合規子集在設計上源自公共內存池合規集合:任何不安全、不適合廣泛傳播的 FrameTx 同樣不適合 FOCIL 強制執行,但反之則不然。所有其他 FrameTx 仍可在選擇性加入(opt-in)的替代內存池或私有訂單流通道中廣播;它們的遺漏永遠是被允許的。

這反映了更廣泛的 AA 生態系統。ERC-4337 使用替代內存池;ERC-7562 定義了更嚴格的共享內存池規則以及獨立的替代內存池規則。同樣的原則也適用於此:FOCIL 強制執行僅涵蓋已獲准進行廣泛公共傳播的 FrameTx。

為什麼原生 AA 會破壞代理機制

與 EOA 不同,Frame 交易的有效性無法僅憑發送者狀態來確定。VERIFY 框架必須針對狀態執行並調用 APPROVE:支付者(payer)只能在執行過程中被發現,且可能與發送者不同。這意味著 Nonce 和餘額檢查可能通過,但 VERIFY 卻失敗。目前沒有廉價的代理機制:證明者必須重放驗證前綴,以確定被排除的合規 FrameTx 是否本應被包含。

透過共享基礎設施產生的衝突

AA 還引入了僅從交易字節無法察覺的衝突。考慮 TX_A 和 TX_B 都針對同一個贊助者(sponsor)進行驗證:

// 偽代碼;APPROVE 是 EVM 操作碼(根據 EIP-8141 為 0xaa)
function validateSponsorship() {
    require(address(this).balance >= MIN_RESERVE)
    APPROVE(payment)
}

如果 TX_A 被包含並收取了費用,贊助者的餘額可能會降至 MIN_RESERVE 以下,導致 TX_B 在後置狀態下失效。這在後置狀態規則下會自然解決:任何在最終後置狀態下無效的交易都會被豁免。構建者(builder)也可能透過耗盡贊助者餘額來發動審查攻擊,從而一次性豁免多個遺漏;這會消耗區塊資源,且是任何後置狀態機制固有的特性。下方的有界狀態訪問規則(約束 5)限制了這種攻擊面。

更廣泛地說,共享合約存儲可能允許單個已包含的交易使多個被排除的 FrameTx 在後置狀態下失效,從而創造系統性的集體遺漏藉口;約束 5 排除了解決了這一點。

合規性約束

合規的 FrameTx 是滿足以下約束 1-5 的 FrameTx。約束 1-4 是在第一階段(Tier 1)評估的靜態檢查;約束 5 是在第三階段(Tier 3)執行期間評估的運行時檢查。FrameTx 只有通過全部五項檢查才算合規。

約束分為兩類:

靜態檢查:可從框架列表(frame list)中檢查,無需任何狀態訪問或執行。這些在第一階段強制執行。

運行時檢查:無法靜態評估。這些在第三階段 VERIFY 執行期間作為「不合規條件」強制執行。觸發不合規條件的交易將被豁免。

VERIFY Gas 權重

verify_gas(tx) = Σ frame.gas_limit(適用於所有 frame.mode == VERIFY 的框架)

可從框架列表中計算,無需任何執行。

參數(初始值,可調)

  • MAX_VERIFY_GAS_PER_FRAMETX(例如:100,000)

  • MAX_VERIFY_GAS_PER_INCLUSION_LIST(例如:250,000)

註:根據這些參數,後量子(PQ)簽名驗證(Falcon, Dilithium)將超過 MAX_VERIFY_GAS_PER_FRAMETX,因此不具備 FOCIL 合規性。PQ FrameTxs 最初仍可透過替代渠道傳播,且其遺漏將始終被豁免。

靜態檢查 (Tier 1)

1. 驗證前綴排序。 VERIFY 框架必須排在所有 DEFAULT 和 SENDER 框架之前。唯一的例外是合約創建框架(to == null),它可以出現在 VERIFY 框架之前,以部署正在驗證的合約。這確保了證明者只需執行創建和 VERIFY 框架即可確定有效性,而無需執行常規執行框架。

2. 單筆交易 VERIFY Gas 有界。 verify_gas(tx) ≤ MAX_VERIFY_GAS_PER_FRAMETX。超過此上限的交易不受限制;遺漏它們是被允許的。

3. 每個包含列表的 VERIFY 預算。 對於每個 IL,按聲明順序掃描交易並構建預算子集:僅當加入候選 FrameTx 後,運行的 verify_gas 總和仍等於或低於 MAX_VERIFY_GAS_PER_INCLUSION_LIST 時,才將其納入。不在任何 IL 預算子集中的合規 FrameTx 將被豁免。

同一個 FrameTx 可能出現在多個 IL 的不同位置,並可能被某些 IL 納入預算而未被其他 IL 納入。證明者必須評估所有 IL,只要至少有一個 IL 將其納入預算,就將該 FrameTx 視為已納入預算。這提供了一種抗審查特性:只要有一位誠實的委員會成員將 FrameTx 列入預算,無論其他成員如何排序,該交易都是可強制執行的。

4. 基礎交易健全性。 Chain ID 匹配、max_priority_fee_per_gas ≤ max_fee_per_gasmax_fee_per_gas ≥ block.base_fee、解析有效、無 Blob(blob_versioned_hashes 為空,max_fee_per_blob_gas 為零)。

運行時檢查 (Tier 3 不合規條件)

5. 有界狀態訪問。 VERIFY 僅能讀取發送者和支付者的帳戶狀態(餘額、Nonce、代碼)及其前 N 個存儲插槽(Storage Slots),其中 N 的範圍為 2–4(確切值待基準測試)。超出此範圍的讀取將使交易不合規。

內存池節點在准入時重放 VERIFY,而不執行完整區塊。將讀取限制在帳戶狀態加上少量固定的存儲插槽,意味著每個節點都確切知道要獲取什麼:一個小型的、確定性的集合,而不會暴露於任意的按需存儲查詢。該約束存在於合規層,以便內存池准入和 FOCIL 強制執行在同一個合規集合上保持同步。

選擇 N 插槽限制是為了與 AA-VOPS 保持一致,AA-VOPS 透過讓節點為每個帳戶緩存少量存儲插槽來擴展 VOPS。大多數智能錢包將其 Nonce、所有者和守護者存儲在插槽 0–3 中,因此 N 個插槽足以覆蓋常見的驗證模式。當 AA-VOPS 完全規範化時,N 的確切值將被固定。

推薦的內存池策略(非共識)

單個發送者待處理上限: 每個發送者最多一個待處理的受限 FrameTx(或深度為 D 的有界 Nonce 鏈),這與 EIP-7702 類似。

單個支付者風險追蹤: 追蹤每個支付者的累計最壞情況費用風險(tx_gas_limit × max_fee_per_gas),當其超過 state[payer].balance × α(其中 α < 1 為安全係數)時,剔除優先級最低的交易。

確定性驗證環境: 拒絕其 VERIFY 訪問易變區塊環境操作碼(TIMESTAMPNUMBERCOINBASEBLOCKHASH 等)的 FrameTx。這是一項內存池准入規則,而非 FOCIL 合規性約束:證明者針對固定的後置狀態重放 VERIFY,在該狀態下這些操作碼是確定性的。內存池節點透過在准入時追蹤 VERIFY 來強制執行此規則,遵循 EIP-7562 的方法。

構建 (Building)

對於合規的 FrameTx,Nonce/餘額代理被替換為針對後置狀態 S 的 EIP-8141 驗證前綴的有界重放。如果被排除的合規 FrameTx 在 S 下有效且符合 gas_left,則該區塊不滿足 IL 條件。

在構建有效載荷後,構建者迭代地追加剩餘的合規 IL FrameTx:

  • 嘗試追加每個剩餘的合規 IL FrameTx。
  • 如果有任何追加成功,則使用更新後的狀態從步驟 1 重複。
  • 當完整的一輪中沒有任何追加時停止。

這在被排除的合規 IL FrameTx 數量上是 O(k²)。來自同一發送者的連續 Nonce 會被自然處理:TX_A(Nonce N)首先被追加,然後 TX_B(Nonce N+1)在後續輪次中匹配。

該循環保證了一個不動點(fixed point):在最終後置狀態下,沒有任何被遺漏的合規 FrameTx 是有效的。這是正確的目標;不需要貪婪的最大化打包,不動點特性足以實現完全的抗審查性。

這不是強制性的算法。構建者可以使用任何能達到相同結果的策略。

引擎 API。 EIP-7805 已經提議對 newPayloadforkchoiceUpdated 進行與 IL 相關的更改。配合 FrameTx 感知檢查,執行層(EL)還需要完整的、有序的、非等義的 IL 視圖來運行 Tier 1–3 邏輯。這是對現有依賴關係的細化,需要兩個 EIP 之間的明確協調。

構建優化(非規範性)。 按 Nonce 預先排序同一發送者的 FrameTx。將共享支付者的 FrameTx 分組並根據該支付者的預算進行選擇,從而在典型條件下將循環減少到少量次數。

驗證 (Verification)

在整個驗證過程中,有兩個屬性是被獨立追蹤的。*合規性(Eligibility)*由約束 1-5 決定:違反任何約束的 FrameTx 無論是否能成功執行都會被豁免。*有效性(Validity)*由 EIP-8141 執行語義決定:如果沒有觸發無效條件,則 FrameTx 在給定狀態下有效。FrameTx 必須同時具備合規性且在後置狀態 S 下有效,並滿足 Tier 2 檢查,才構成 FOCIL 違規。

每一層都在前一層的輸出基礎上運行。Tier 1 獲取所有 IL 中的所有交易,並生成通過靜態檢查的被排除 FrameTx 候選集 C。Tier 2 獲取 C 並過濾出滿足 Nonce 和 Gas 容納條件的交易。Tier 3 獲取該過濾後的集合,應用運行時檢查,並識別出其遺漏違反了 IL 條件的交易。

後置狀態下有效後置狀態下無效
合規若被遺漏則構成 FOCIL 違規(假設 Tier 2 通過)。例如:格式正確的 VERIFY,調用了 APPROVE,支付者有償付能力。豁免。例如:執行了 VERIFY 但未調用 APPROVE,或支付者餘額不足。
不合規豁免。例如:VERIFY 讀取了超出 N 插槽限制的第三方存儲插槽(約束 5),但除此之外會成功。豁免。例如:違反約束 5 且未調用 APPROVE。

Tier 2(Nonce 和 Gas 容納)是合規+有效單元格的進一步條件;在那裡失敗也會被豁免。

證明者掃描所有 IL 交易(不僅是被排除的交易),以確定哪些 FrameTx 在 Tier 1 滿足靜態檢查。只有 C 中被排除的 FrameTx 會進入 Tier 2 和 Tier 3。

Tier 1:靜態檢查(無狀態訪問,無執行)

對於所有 IL 中的每筆交易 T:

  • 如果 T 已包含在區塊中:跳過。
  • 如果 T 不是 FrameTx:應用標準 Nonce/餘額代理並跳過。
  • 如果 T 未通過約束 1-4:豁免。
  • 否則:將 T 加入候選集 C。

C 是 Tier 2 的輸入。

約束 1-4 回顧:

  • 滿足 VERIFY 優先排序。
  • verify_gas(tx) ≤ MAX_VERIFY_GAS_PER_FRAMETX
  • 交易至少在一個 IL 的預算子集中。
  • 交易健全性通過(包括無 Blob)。

Tier 2:Nonce + Gas 容納(僅讀取後置狀態)

  • tx.nonce == S[tx.sender].nonce
  • tx_gas_limit ≤ gas_left

其中:

  • gas_left = block_gas_limit − total_gas_used(包括已追加的 IL FrameTxs)
  • tx_gas_limit = FRAME_TX_INTRINSIC_COST + calldata_cost + Σ frame.gas_limit

若任一檢查失敗:豁免。否則進入 Tier 3。

Tier 3:有界驗證前綴重放(後置狀態)

針對後置狀態 S 執行 EIP-8141 驗證前綴(有序的 VERIFY 框架序列),重放精確的框架語義,包括 ORIGIN 行為和批准狀態。應用運行時檢查(約束 5);若不合規:豁免。

驗證前綴完成後,如果識別出支付者,則檢查償付能力:

required_balance = tx_gas_limit × min(tx.max_fee_per_gas, block.base_fee + tx.max_priority_fee_per_gas)

若無償付能力:豁免。若在後置狀態下有效且符合 gas_left:區塊不滿足 IL 條件。

Tier 3 的 FrameTx 合規性與有效性條件

如果 FrameTx 未觸發任何無效條件,則在給定狀態下有效。非 VERIFY 框架的回退(revert)不會使交易失效;但 VERIFY 框架在未調用 APPROVE 的情況下終止則會失效。

  • tx.chain_id == block.chain_id
  • tx.max_priority_fee_per_gas ≤ tx.max_fee_per_gas
  • tx.max_fee_per_gas ≥ block.base_fee
  • tx.nonce == state[tx.sender].nonce
  • 所有 VERIFY 框架均以 APPROVE 終止;回退、Gas 不足或未調用 APPROVE 終止:無效。
  • 必須在設置 payer_approved 之前建立 sender_approved;所有 VERIFY 框架完成後,payer_approved 必須為 true。

不合規條件(約束 5)會豁免該交易,無論其餘有效性條件是否本應得到滿足。

安全考量

抗 DoS 能力

  • 單筆交易: 根據設計,verify_gas(tx) ≤ MAX_VERIFY_GAS_PER_FRAMETX
  • 每個 IL: 每個 IL 最多貢獻 MAX_VERIFY_GAS_PER_INCLUSION_LIST 的 Tier 3 工作量。證明者按交易哈希在 IL 之間進行去重,每個唯一交易僅執行一次驗證前綴。
  • 每個時隙(Slot): 在擁有 16 名成員的 IL 委員會的最壞情況下,工作量為 16 × MAX_VERIFY_GAS_PER_INCLUSION_LIST。根據建議參數:每個時隙 4,000,000 VERIFY-gas。控制 m 個時隙的攻擊者最多強制執行 m × MAX_VERIFY_GAS_PER_INCLUSION_LIST

這些數字僅限制了證明者的工作量。構建者端的重放成本更高;參見「開放問題」中的構建者複雜性。

集體失效

約束 5 排除了解決了基於存儲的共享驗證依賴,這涵蓋了主要的集體失效向量。共享支付者餘額仍可能被耗盡以使多個 FrameTx 失效,但這受限於區塊資源成本。

抗審查性

在後置狀態 S 下有效且符合 gas_left 的合規 FrameTx 必須被包含。構建者沒有任何機制可以為此類交易聲明豁免。

替代方案:基於索引的驗證

如果追加循環被證明不切實際,構建者可以透過證明交易在聲明的索引處無效來豁免排除。構建者提供交易哈希和聲明的索引;證明者使用 BAL (EIP-7928) 或類似的區塊級訪問數據重建該索引處的狀態,並重新執行驗證前綴。無論如何,VERIFY Gas 限制仍然是必需的。

這消除了 O(k²) 的追加循環,但引入了新的網絡對象(構建者的索引聲明),並將舉證責任轉移給構建者,構建者對聲明哪個索引擁有完全控制權。

開放問題

構建者複雜性。 迭代重試對 EL 客戶端在實踐中的成本如何?它會增加多少時隙延遲?作為參考:在 16 個 IL 委員會成員中有 4 個是惡意的情況下,構建者面臨高達 1,000,000 VERIFY-gas 的重放工作,約佔 60M 區塊 Gas 限制的 1.7%。

AA-VOPS 緩存大小。 約束 5 中的前 N 個存儲插槽限制需要根據 AA-VOPS 緩存設計進行校準。N 的精確值 (2–4) 需針對真實智能錢包驗證模式進行基準測試。

擴展讀取的見證數據(Witnesses)。 除了 AA-VOPS 緩存之外,如果受限 FrameTx 可以附加見證數據(值 + Merkle 證明)用於額外的驗證讀取,那麼適用什麼樣的新鮮度和根規則?當區塊頭變化時由誰來更新證明?

參數變動。 MAX_VERIFY_GAS_PER_FRAMETXMAX_VERIFY_GAS_PER_INCLUSION_LIST 需要進行基準測試。

引擎 API 細節。 為了將有序 IL 集合傳遞給 EL,對 newPayload / forkchoiceUpdated 的精確更改需要具體的規範。


1 則貼文 - 1 位參與者

閱讀完整話題

https://ethereum-magicians.org/t/focil-native-account-abstraction/27999