在之前我們提到的那些原生帳戶的問題中,其實都在於我們的「交易」被綁在以太坊的原生 Protocol 上,因此抽象帳戶是一種將交易驗證與執行過程,從底層拉到合約層的設計。
所以這個新的帳戶不只是一個「新形式的帳戶」而已,而是連驗證交易、執行交易的過程都和過往不同了。
Quick Look the Core Questions
這篇文章接續前文的帳戶介紹,由淺入深繼續介紹:
- 什麼是抽象帳戶
- 抽象帳戶為何重要:與原生合約帳戶的差別
- 未來帳戶:使用和開發體驗
這邊的抽象帳戶介紹基本上都以 EIP-4337 的提案為主,不過附註的 Reference 與延伸閱讀可能會有一些 EIP-2938 的內容,兩者都是抽象帳戶的提案,只是設計上略有不同,大家有興趣可以再自行深入探討。
什麼是抽象帳戶?
深入的說,過去節點會負責驗證交易、收取手續費、使用 ECDSA 驗證簽章,抽象帳戶把這些東西拉到智能合約中變成合約程式碼的一部分,就能夠對其進行編程。
所以,實作抽象帳戶有個目標:「有一個完善的,能正確驗證交易,且將用戶交易打包上鏈的智能合約系統設計」。聽起來是不是非常拗口,我們可以繼續看下去。
抽象帳戶下的交易如何運作
1. 用戶會簽核完一筆 Signed Message(這裡我們將 EOA 簽送一筆交易的行為改稱為 UserOperation),這個簽完的交易(UserOperation)裡面可能有數個 Calls,每個 Call 都是一個我們過往認識的交易行為(e.g. 與合約函式互動、匯款給別人等)。
重點一:簽完的交易叫做 UserOperation,裡面可能有多個 Calls,在 EOA 的時候這些 Call 都必須是一筆一筆的交易,但現在他們可以被包裝在一個交易(UserOperation)裡面。
2. 用戶把這個簽完的交易(UserOperation)送到 UserOperation mempool 之中,它類似當今的 Tx mempool。進入 mempool 的 UserOperation 就是在 Pending 的狀態。
重點二:用戶可以選擇他要把自己的交易(UserOperation)送到誰運作的 memPool,有可能是錢包商或礦工自己有的公開網路 memPool。這個部分會與現在的 mem pool 並存。
3. Bundler 會從 mempool 中挑選它喜歡的 UserOperation 們,綑綁成一筆 Bundle Transaction(這就是我們現在就在使用的 Ethereum 交易)。這個 Bundle Transaction 會去觸發 Entry Point Smart Contract 的函式 handleOps
。
重點三:Bundler 有可能是礦工,或是能作為 User 和 Miner 之間的中介人。他負責監聽 mempool 中新加入的 UserOperation,因為只要綑綁(Bundle)這些交易就可以從中收取手續費,因此他們有動機去替我們綑綁送給 Entry Point Smart Contract(以下都稱 EntryPoint)。
4. EntryPoint 會確認每個用戶都有他們的 Wallet Contract ,如果沒有就幫用戶佈署一個,作為用戶在這裡將要使用的 Wallet Contract。這個 Wallet Contract 負責針對該用戶送上來的 UserOperation 驗證交易、支付手續費、執行交易。
重點四:EntryPoint 是一個早就被佈署的合約,它將在未來被相關的 AA Transaction 呼叫使用,作為 AA 交易的統一進入點。
過往的交易中,節點會去檢驗 nonce 的合法性,確認簽章合法,並還原出簽章地址之後查看是否有足夠的 balance 以及 gas fees。在 AA 中這些交易驗證都需要移動到 Wallet Contract 裡。
5. EntryPoint 會呼叫 Wallet Contract 上的函式,依序為:
- 驗證(
__validate__()
):EntryPoint 呼叫了此函式之後,Wallet Contract 會檢查交易是否合法,包含 nonce 是否正確,以及任何這個 Account(Wallet Contract)想要做的檢查(e.g. 多簽、不同的 Sig. Algorithms 等)。 - 在確認驗證通過之後會向 Wallet 收取手續費(直接匯款,Wallet Contract 會檢驗調用者是 EntryPoint)。
- 執行(
__execute__()
):EntryPoint 呼叫了此函式之後,Wallet 就真的去執行這筆 UserOperation 要執行的內容(Calls 們),這些 Call 可能會是與合約互動等行為或匯款等。
抽象帳戶為何重要:與原生合約帳戶的差別
如果要說抽象帳戶與原生合約帳戶哪裡有差別,不如說抽象帳戶能夠繼承所有原生合約帳戶的特性於優點,卻又能克服他的缺點,同時再優化更多交易形式的彈性。
既然大家已經知道什麼是 AA 了,我們就可以先回過頭看當初列出的六大問題表格作為 Overview,並同時加上 AA 抽象帳戶的新欄位:
首先是 「問題(1)- 私鑰保管問題」 與 「問題(4)- 多簽授權交易」:AA 依然具有 Contract Account 的特性,能夠將多簽或 Social Recovery 等 Features 實作,有機會緩解私鑰保存問題。
私鑰安全是一個很大的議題,這些 Features 非萬能解也非唯一解,就是作為舉例而已。
問題(2)- 可使用其他簽章演算法
我們在上一個小節講述 AA 運作流程的時候,就有提到執行交易驗證的地方是 EntryPoint 佈署的 Wallet 中的 驗證(__validate__()
)函式。
在 AA 中,這裡的驗證機制就可以使用其他演算法來驗證交易簽章,例如: Multisig verification、Schnorr sigs、BLS sigs、Quantum-resistant sigs (e.g. Lamport, Winternitz) 等。
這個部份端看佈署 EntryPoint 的服務商希望用戶送上來的交易是以何種方式被驗證的。
問題(3)- 可以其他方式支付交易手續費
更深入一點探討以太坊原本的交易 Protocol,在交易被處理跟驗證之前,我們就必須先隨著附上一定數量的 ether 作為 Gas Fee。所以才會說我們有一個空的新帳戶,它沒辦法做任何事情,必須先被注入 ether 才能動作(與合約互動)。
但現在在 AA 的情況,我們可以透過 Paymaster 的設計來以其他方式支付手續費。例如中心化的 Paymaster 可以收取信用卡,去中心化的 Paymaster 能夠在合約中收取 ERC-20 代幣作為收費手段。最後 Paymaster 會替我們支付 Ether 給 EntryPoint 去真正執行交易。
在 EntryPoint 呼叫 Wallet Contract 上的函式時,能夠插入一個角色叫做 Paymasters,Paymaster 可以接收用戶資產後,使用 Ether 代替 Wallet Contract 支付手續費(驗證與執行仍然是 Wallet 做)。
舉例來說用戶已經使用信用卡或 ERC20 等方式向 Paymaster 服務商支付手續費了,Paymaster 的合約中就會記上相對應的紀錄;且同時用戶在送上 UserOperation 時會在交易中附帶一些特別的參數,白話的說就是告訴 EntryPoint :「這筆交易的手續費請你跟某某某 Paymaster 拿,不是跟 Wallet Contract 拿。」。
待 EntryPoint 呼叫 Wallet Contract 的驗證,確認此 UserOperation 合法後,就會去跟 Paymaster 討 Ether 作為手續費,拿到錢之後才接著做執行的相關動作。
問題(5)- 可作為交易發起者
問題(3)- 以其他方式支付交易手續費的另外一個例子是 Tornado Cash(TC),我拉到第五點:「Contract Account 無法作為交易發起者,但 AA 可以」來講。
AA 不僅可以收取其他形式的費用,還可以從我們提款的費用扣掉一部分成為手續費。並且交易成立關鍵在於 EntryPoint 收取 UserOperation 的時候,只需要用戶送上「已簽的交易物件(UserOperation)」,而非當今的送出一筆交易(Transaction)給節點驗證打包。這樣的設計使得 AA 能夠作為交易發起者。
在 TC 的運作中,存款者向 TC Contract 存入資金,而提款者(去戳合約函式示意我要提款的那個人)則須要先持有一定 Ether 來支付提款這個行為的交易手續費,才能將錢提出來。
問題就在於,我們如果用任何一個 Funded Account 注入提款者帳戶,都會在鏈上被串聯起關係,隱私也就蕩然無存了。現行的解決方法是有一個第三方的 Relayer 來接收 Off-Chain Message ,並且進行驗證,成功後提交交易物件給 TC Contract(Relayer 同時獲得 Gas refund 和 fee),最後 TC Contract 會匯出款項。
在 AA 的設計下:我們能夠將 Bundler 當作 relayer 使用(不需要特別跑一個 TC relayer 或 relayer 網路):Bundler 打包我們提領 TC 的 UserOperation,UserOperation 裡直接使用提領的 ether 或代幣來支付手續費給 Bundler。因此我們的提款者就不需要事先被注入資金,就能夠呼叫合約函式。
以上詳情可見:EIP-2938 簡介 的 Example 2 — Privacy Solution: Tornado.Cash。
問題(6)- 一筆交易可包含多個呼叫
用戶們送給 Bundler 打包的交易物件以 UserOperation 的形式組成,UserOperation 作為以多個 Calls 綑綁而成的一個物件,在此可以將一連串的 operations(不同的 calls 們)包裝成一個不可分割的(atomic)交易行為。
未來帳戶:使用和開發體驗
More Features
除了以上提到的原生帳戶問題優化之外,AA 還可以做到更多特性:
- 交易排序的自由度:執行交易的順序檢查由被佈署的 Wallet Contract 自己決定,可以比只檢查依序遞增的 nonce 有更多樣的解決方法。
- Application-Specific:不同的 Dapp 能夠針對他們的需求設計交易的驗證和取款方式。
- Privacy Solution:如我們上述提到的 Tornado Cash 以及其他解決隱私方面問題的 Dapp(e.g. PSE: ZKP Dapp),都有機會因為 AA 的設計達到更高的私密性。
以上的特性能夠被實作,原因都是來自於「交易驗證」這件事情被拉到合約層做而不是單純綁在以太坊的原生協議上。
普通用戶視角
當我們的交易真的能夠透過 AA 運作時,其實用戶並不會感受到太大的差別,就像往日大多數在使用區塊鏈服務的人們,可能都不會在自己的電腦裡面生成交易物件跟簽章,而是使用錢包的服務(e.g. imToken, MetaMask)以及 Dapp 提供的前端(e.g. Uniswap Interface)。
在 AA 的情況下:每個帳戶都是 Contract Account,而從簽核交易物件、送出交易物件、綑綁交易物件、驗證交易、扣除手續費到最後的執行交易,一切過程都會是錢包商負責處理。
所以從用戶的視角中,日常操作基本上是沒有差別的,只會感受到錢包多了許多新穎的功能,某些情況下也會更值得信賴(與傳統 CA 錢包商比較下,AA 錢包商不需要依賴 Relayer)。
錢包商 / 開發者視角
在面對 AA 這樣新型態的交易模式時,第一個要解決的問題就是過度 Application-Specific,目前並沒有一個絕對的 Protocol 決定一個合約錢包該長怎樣,每一個 Dapp 也可能會有不同的交易驗證方式。所以開發者就需要針對不同的服務,去注意不同的 Operations。
另外一個問題是,隨著合約錢包的功能不斷增加,驗證過程越趨複雜,安全漏洞出現的機率也就隨之提升。這可能會造成開發團隊不小的負擔,也要花更多人力在處理審計問題。
原本交易的驗證這件事情只在底層被處理,普通的開發者只要寫出安全的合約,交易驗證交給礦工跟 Ethereum Native Protocol 開發者去煩惱就好。但現在交易過程都拉到合約層運作時,除了寫出原本提供服務的智能合約,還要多處理與合約錢包配合的契合度與安全性。
更進一步的說,原本做 EOA 錢包的開發商為了應對 Dapp 開始實作 AA 型態的交易模式,就也需要開始負擔智能合約錢包的部分,這部分得要非常熟悉 AA 的運作。
可想而知 AA 與過往的交易型態是非常不同的,與既有的 EOA 錢包甚至合約錢包的工作流程都完全不同,因此大部分錢包商針對 AA 的開發動力可能會嚴重不足。
Summary
最後,抽象帳戶做為近期風靡社群的存在,勢必有它吸引人的地方,乍看之下他也好像能解決許多問題。但許多地方實際上都沒有想像中美好(e.g. 實作麻煩、Gas Fee 高等),一切都還需要開發者與提案者們更多的深入討論,才有機會真正將 AA 帶入應用場景。
希望大家到這裡能夠對抽象帳戶有一定的了解了!最後如果對實作 AA 以及系統設計的 Protocol 細節有興趣,歡迎閱讀我之前寫過的兩篇文章:
Special thanks to NIC Lin, Chang-Wu Chen and imToken colleagues for reviewing this post.