帳戶抽象化第 4 部分:聚合簽章
聚合簽章
我們目前的實作方式是分別驗證 bundle 中的每個 user op。這是思考驗證問題的一種直觀方式,但可能會造成浪費。驗證簽章在 gas 花費上可能偏高,因為這需要相當大量的加密演算運算。
如果我們能用一個簽章就同時驗證多個 op,而不是分別驗證每一個,豈不是更好?
要做到這點,需要用到密碼學中的一個概念——聚合簽章(aggregate signatures)。
一個支援聚合的簽章方案,能讓我們把多個由不同金鑰簽署的訊息,合併成一個簽章,使得驗證這個合併後的簽章即可證明所有原本的簽章都是有效的。
一個常見的支援聚合的簽章方案例子是 BLS。
這項優化對於實作 rollup 特別有用,因為 rollup 的主要目標就是資料壓縮,而簽章聚合能讓我們壓縮簽章的部分。
關於簽章聚合能節省多少空間,可參考 Vitalik 針對此議題發的推文。
介紹聚合器(aggregator)
我們馬上就能發現,並非 bundle 中所有的 user op 簽章都能聚合在一起。別忘了錢包可以使用任意邏輯來驗證給定的簽章,因此同一個 bundle 中可能會出現各種不同的簽章方案。
由於我們大概無法把不同方案的簽章聚合在一起,我們的 bundle 最終會由多組 op 組成,每一組使用各自獨立的聚合方案,或是完全不使用聚合方案。
由於鏈上需要有各種聚合方案各自的邏輯表示,我們會讓每個聚合方案都由一個合約來代表,我們稱之為聚合器(aggregator)。
一個聚合方案的定義,取決於它如何把多個簽章合併成一個,以及如何驗證這個合併後的簽章,因此聚合器會以方法的形式公開這兩個功能:

由於每個錢包都自行定義自己的簽章方案,因此要相容哪一個聚合器(如果有的話),是由各個錢包自行決定的。
如果一個錢包想要參與聚合,它會公開一個方法來選擇自己的聚合器:
透過這個新的 getAggregator 方法,bundler 就能把使用相同聚合器的 op 分在一組,並使用該聚合器的 aggregateSignatures 方法為它們計算出一個合併簽章。
一組可能長得像這樣:
💡 如果 bundler 對某個特定聚合器有鏈下的了解,它可以透過硬編碼一個原生版本的簽章聚合演算法來最佳化,而不必以 EVM code 的形式執行 aggregateSignatures。
接下來,我們需要更新入口點合約(entry point contract),讓它能使用這些新的聚合器。
回想一下,入口點有一個 handleOps 方法,接收一份 op 的清單。
我們會為它新增一個方法, handleAggregatedOps,功能相同,但接收的是依聚合器分組後的 op:
新方法 handleAggregatedOps 的運作方式大致和 handleOps 相同,唯一的差異在於驗證步驟。
handleOps 是透過呼叫每個錢包的 validateOp 方法來進行驗證,而 handleAggregatedOps 則會改為對每組合併後的簽章,使用該組所屬的聚合器呼叫其 validateSignatures 方法。

我們幾乎完成了!
但這裡有個問題,相信大家現在已經很熟悉了。
bundler 想要模擬驗證過程,確認聚合器會驗證通過某一組 op,之後才把這些 op 放進 bundle 裡,因為如果驗證失敗,bundler 就得自己承擔 gas 費用。但一個邏輯任意的聚合器,很可能在模擬階段成功通過,卻在實際執行時失敗。
我們會用和 paymaster、factory 完全相同的方式來解決這個問題:限制聚合器能存取哪些 storage、能使用哪些 opcode,並且要求它在入口點中質押 ETH,除非它不存取 storage。
聚合簽章的部分到此結束!
總結
我們在這裡建立的內容,基本上就是 ERC-4337 的完整架構!雖然在一些細節上有所不同,例如某些方法的名稱和參數,但已經沒有任何我認為屬於架構層面的差異了。如果我做得夠好,你現在應該已經能夠閱讀真正的 ERC-4337,並理解其中的內容。
如果你讀到了這裡,非常感謝你閱讀我的說明!希望這篇文章對你的幫助,就像撰寫它對我的幫助一樣大。
附錄:與 ERC-4337 的差異
雖然我們已經掌握了帳戶抽象的整體架構,但 ERC-4337 背後的聰明人們,在一些地方想出了和我們上面描述略有不同的做法。
讓我們來看看其中幾個!
1. 驗證的時間範圍
在前面,我對錢包的 validateOp 和 paymaster 的 validatePaymasterOp 的回傳型別講得相當含糊。ERC-4337 找到了一個很好的方式來運用這一點。
錢包很希望能做到的一件事,是只讓某個 user op 在特定一段時間內有效。否則,一個心懷不軌的 bundler 可能會把這個操作壓著很長一段時間,然後在對自己有利的時機,才把它放進 bundle 裡。
錢包可能會想在驗證期間檢查 TIMESTAMP,確保它不會離現在太遙遠,藉此來防範這種情況,但它做不到,因為我們已經禁止在驗證期間使用 TIMESTAMP,以避免模擬結果不準確。這代表錢包需要另一種方式,來表示這個操作在什麼時間範圍內有效。
因此,ERC-4337 讓 validateOp** 擁有一個回傳值,讓錢包可以用來選擇一個時間範圍:**
這個回傳值以兩個前後相連的 8 位元組整數,來表示該操作有效的時間範圍。
ERC-4337 的另一個要點是:錢包在驗證失敗時,應該從 validateOp 回傳一個哨兵值(sentinel value),而不是 revert,這有助於 gas 估算,因為 eth_estimateGas 無法告訴你一筆會 revert 的交易實際用掉了多少 gas。
2. 錢包與 factory 的任意呼叫資料
我們之前說過,我們錢包的介面是:
在 ERC-4337 中,錢包實際上並沒有一個叫做 executeOp 的方法。
取而代之,user operation 有一個 callData 欄位:
這個欄位會以呼叫資料(call data)的形式傳遞給錢包。
對於一般的智慧合約來說,這份資料的前四個位元組會被解讀為函式選擇器(function selector),其餘部分則是函式引數。
這代表除了必要的 validateOp 方法之外,錢包可以自行定義自己的介面,而 user operation 可以用來呼叫錢包上任意的方法。
同樣地,在 ERC-4337 中,factory 合約實際上也沒有 deployContract 方法。它們同樣接收任意的呼叫資料,在這裡是來自 op 的 initCode 欄位。
3. paymaster 與 factory 的精簡資料
前面我們提到,user operation 包含用來指定 paymaster 以及要傳給它的資料的欄位:
在 ERC-4337 中,作為一種優化,這些欄位被合併成單一欄位,其中前 20 個位元組是 paymaster 的地址,其餘部分則是資料:
factory 以及傳給它的資料也是同樣的情況:我們原本使用 factory 和 factoryData 這兩個欄位,而 ERC-4337 將它們合併成單一欄位 initCode。
好了,你做到了!
希望你從中學到了不少關於帳戶抽象的知識。
你也能發明帳戶抽象
錯過這個四篇系列的開頭了嗎?回去從頭開始閱讀吧!
相關總覽
錢包2026年10月14日
什麼是 paymaster?
Paymaster 為 user operation 贊助 gas,或讓使用者用 ERC-20 代幣支付這筆費用。
錢包2026年9月2日
Agent 錢包:AI agent 的 session 與權限模型
AI agent 如何在不持有私鑰的情況下,取得範圍受限、可撤銷的錢包存取權限:session、委派簽署與即時撤銷。
錢包2026年7月29日
別再把私鑰貼到 Cursor:如何讓你的 coding agent 擁有錢包
讓你的 coding agent 擁有錢包,卻不用把私鑰交給它。了解 Alchemy CLI agent wallets 如何透過限定範圍的 sessions,讓 agent 不必在 .env 中存放私鑰也能交易。

打造區塊鏈魔法
Alchemy 結合最強大的 Web3 開發者產品與工具,並提供資源、社群與卓越的支援。