所有語言
分享
作者:ChiHaoLu ( chihaolu.eth ) 來源:medium 翻譯:善歐巴,金色財經
本文主要介紹Aztec Layer2解決方案中Account Abstraction(AA)的發展及相關內容。我引用了大量Aztec的官方資源,包括官方文檔、博客和教程。請在文章末尾的參考文獻部分找到這些優秀的資源!
由於與 ZK-Rollups 中的其他 Native AA 實現相比,Aztec 的複雜性有所增加,讀者可能會受益於擁有一定的背景,以便更好地理解本文。
熟悉智能合約錢包及其功能
熟悉 EIP-4337
熟悉 ZK-Rollups 中的本機帳戶抽象
UTXO基本概念
ZK-Rollups 的基本概念
零知識證明程序的基本概念
Aztec 是一個開源第 2 層網絡,旨在為以太坊提供可擴展性和隱私保護。Aztec 利用 zkSNARK 證明通過 ZK-Rollup 服務提供隱私保護和可擴展性。Aztec 的用戶不需要任何受信任的第三方或額外的共識機制來訪問隱私交易。
我們都知道,在傳統的 ZK-Rollups 中,“ZK”並不一定意味着隱私;它意味着使用零知識證明(ZKP)來證明某些計算已在鏈下正確執行。然而,在 Aztec 中,除了可擴展性之外,ZK-Rollup 中還實現了隱私性。深究一下,在過去,每筆交易的細節在鏈上都是公開可見的,但在Aztec,每筆交易的輸入和輸出都是加密的。這些交易通過ZKP進行驗證,以證明加密信息是準確的並且源自明文。只有構建這些私人交易的用戶才知道實際的明文信息。
即使是 ZK-Rollup 中的重要角色,例如 Sequencer 和 Prover,也無法確定明文內容。有關交易的所有信息,包括髮送者、接收者、交易數據和轉移的價值,都是隱藏的。雖然只有用戶自己知道交易細節,但他們仍然可以相信交易的正確性。這種信心源於這樣一個事實:只有合法的交易才能生成有效的零知識證明來證明其準確性。
如何實現私密交易以及如何驗證它們的基本原理是一個很大的話題,超出了本文的範圍。簡單來說,我們需要的是一個“用於零知識證明驗證的附加層”來驗證 ZKP 列表,每個 ZKP 都驗證一個私人交易。這也是它們被稱為“ZK-ZK-Rollups”的原因。
在 Aztec 中,使用本機帳戶抽象,這意味着外部擁有的帳戶 (EOA) 和合約帳戶之間沒有區別。所有賬戶都是智能合約。因此,我們將簡要介紹 Aztec 的合約開發生態系統,因為了解合約開發至關重要。但是,如果您不打算親自開發賬戶合約,那麼閱讀和理解本文並不需要您打開計算機並編寫合約。您只需要了解帳戶合約代碼中的邏輯即可。您可以自行決定探索該主題的深度!
Noir是一種用於編寫 SNARK 程序的語言,類似於 Circcom 和 ZoKrates。它不僅允許您在電路創建后自動生成 Solidity Verifier 合約,還可以用於編寫您自己的協議甚至區塊鏈。由於 Noir 並不完全依賴於 Aztec(它不會編譯成特定的證明系統),因此只要為證明系統實現後端服務器和智能合約接口,您就可以實現您的目標。
在 Aztec,Noir 用於編寫智能合約,其中變量(狀態)和函數可以受到隱私保護。
根據我們對公共區塊鏈的理解,通常所有狀態都是公共的。在Aztec語中,掌握私有狀態的概念以及如何管理它(添加、修改、刪除)至關重要。私有狀態被加密並由其持有者擁有。例如,如果我是合約的所有者,則該合約中的特定變量可以是加密和隱藏的私有狀態。只有我作為這個私有狀態的所有者,才能解密密文以獲得明文。
私有狀態通過僅附加數據庫樹存儲。這樣做是因為直接更改狀態值可能會從事務圖中泄漏大量信息。然而,該數據庫並不直接存儲私有狀態的值。相反,它以加密形式將它們記錄為私人筆記(例如,,x=0 -> x=1
)addr=0x00 -> addr=0x01
。所以,實際上,這些私有變量雖然看起來是變量,但實際上是由一堆不可變的私有票據組成的。這是變量的抽象概念。如果還不清楚,讓我們繼續前進。
當您需要刪除私有狀態時,您可以將與該私有狀態相關的無效符添加到另一個無效符數據庫中以使其無效。當您需要更改私有狀態時,首先將其無效,然後向其添加新的私有註釋。
我們很快就會介紹無效器的概念。您可以將其視為將私人註釋鏈接到其無效符所需的密鑰。只有無效密鑰的所有者才能識別並使用與其關聯的私人註釋。
此時,精明的讀者可能已經注意到,這種結構非常類似於 UTXO(未花費的交易輸出),我們可以遍歷 UTXO 來確定私有狀態的當前狀態(儘管重要的是要記住是用戶簽署交易,而不是 UTXO;我們稍後會解釋這一點)。
什麼是私人筆記?一個UTXO被稱為Note,我們通過遍歷這個Note Tree來獲取相關私有狀態的信息。當我們想要改變私有狀態時,步驟如下:
用戶從筆記數據庫中檢索與該私有狀態相關的所有私有筆記。
用戶(實際上是用戶運行的 Aztec 節點)在本地證明每個檢索到的註釋在此 DB 樹中的存在。
用戶添加一個無效符以防止其他人再次讀取同一片恭弘=叶 恭弘子。
用戶插入一個新的恭弘=叶 恭弘子(一個新的註釋)來更新這個私有狀態的值。
眾所周知,EIP-4337旨在將整個交易流程移至應用層,實現開放中繼系統,並通過智能合約的可編程特性抽象出簽名(驗證機制)和支付模型。然而,對於 Native Account Abstraction,無論是在 StarkNet、zkSync 時代,還是本文重點的 Aztec,都需要將某些元素蝕刻到 Layer2 的協議中才能正常運行。例如,在 Aztec 中,加密密鑰和無效密鑰需要在協議級別實現。
了解本機帳戶抽象需要更深入地了解整個鏈的運作方式(假設它被稱為“本機”,AA 的執行邏輯自然鏈接到特定 Layer2 的協議)。例如,在 zkSync 時代,需要理解系統合約,在 StarkNet 中,需要理解序列器如何運行,而在 Aztec 中,理解這些“密鑰及其底層私有狀態”的作用至關重要。
在 Aztec 中,與賬戶抽象的其他實現不同,沒有嚴格定義的函數名稱(函數簽名)作為賬戶合約的入口點(例如,validateUserOp
在 EIP-4337、validateTransaction
zkSync Era 和__validate__
StarkNet 中)。用戶可以自由選擇賬戶合約中的任意函數作為入口點,併發送帶有相關參數的交易。
用戶選擇的函數(我們稱之為entrypoint()
)必須是私有的(在用戶的私有執行環境中執行)。只能從賬戶合約所有者的客戶端(用戶的錢包)調用。當用戶的錢包entrypoint()
在本地執行時,它同時生成零知識證明。該證明通知Aztec協議的驗證階段,鏈下執行已經發生並且已經成功。
這也延伸到是否在驗證階段對可執行操作施加限制的問題。眾所周知,由於驗證交易沒有成本限制(本質上,驗證交易是調用函數view
),攻擊者可以對內存池執行拒絕服務(DOS)攻擊,以破壞捆綁器(EIP-4337)或操作員/排序器(原生AA)。EIP-4337 定義了禁止哪些操作碼以及如何限制存儲訪問。zkSync Era放寬了一些OpCode的使用,而StarkNet根本不允許外部合約調用。
由於 Aztec 協議涉及客戶端對附加的零知識證明進行驗證,而不是實際調用驗證函數來確定結果為 或 ,因此true
Aztecfalse
與其他協議不同,在驗證階段不會施加任何限制。賬戶內的合約entrypoint
可以自由調用其他合約、訪問任何存儲、執行任何計算。
更詳細地說,在 zkSync Era 和 StarkNet 中,只有“賬戶合約”才能發起交易,因為協議調用指定函數作為入口點,施加了這種限制。然而,在 Aztec 中,“所有合約”都可以發起交易,因為協議調用哪個函數作為入口點沒有限制。這意味着在 Aztec 上,不再是用戶將交易發送到特定角色(例如 EIP-4337 中的 EntryPoint 合約或 Native AA 中的定序器/操作符),然後調用目標合約的固定交互流程。用戶可以通過錢包發送交易,直接讓目標合約完成相關交互,大大增強了靈活性。
如果您熟悉EIP-2938(AA 的另一種實現),您會發現 Aztec 更類似於其中的多租戶方法。然而,這是一個更深層次的話題,你可以自己探索。
在 Aztec 中,每個帳戶通常有兩個主密鑰:簽名密鑰和隱私主密鑰。
簽名密鑰用於表示用戶對使用私鑰執行特定操作的授權。一個簡單的例子是用戶在帳戶合約中記錄從簽名密鑰派生的公鑰。然後,通過使用此簽名密鑰對交易或消息進行簽名,可以在合約內恢復生成的簽名,以檢查其是否與合約中記錄的公鑰(也稱為所有者控制密鑰,以密鑰形式存儲)相匹配。address
Solidity 錢包合約中的變量)。
關於数字簽名橢圓曲線算法的選擇,由用戶決定。例如,以太坊使用secp256k1
,而 Aztec 提供了使用 的示例schnorr
。在賬戶合約中,該entrypoint()
函數作為入口點(調用的來源),驗證邏輯(is_valid_impl()
)使用 來檢查 Schnorr 簽名是否與記錄的公鑰匹配std::schnorr::verify_signature(...)
。
簽名密鑰本質上和我們熟悉的智能合約錢包中的所有者控制密鑰相同,所以應該比較容易理解。事實上,簽名密鑰並不是絕對必要的。如果帳戶開發者實施了其他驗證機制,則帳戶可能沒有簽名密鑰。
Aztec賬戶中的隱私主密鑰是不可轉讓的;每個 Aztec 帳戶都綁定到一個隱私主密鑰。隱私主密鑰衍生出公共主密鑰,然後與合約代碼進行哈希運算,生成賬戶合約的地址。
我們將用戶的
account_address
、partial_address
、 和統稱public_master_key
為帳戶的完整地址。在處理私有狀態時,用戶需要提供這三項信息,以便任何人都可以驗證公鑰是否對應於預期的地址。但是,如果它是一個不打算處理私有狀態並且缺少 的應用程序(例如 DeFi)
public_master_key
,您可以簡單地填寫該public_master_key
字段0
以表明它不希望收到私有票據。
所以,儘管Aztec允許我們在賬戶合約中實現驗證機制甚至一些恢復機制來增強賬戶安全性,但與隱私主密鑰相關的機制卻被印在協議中並與地址綁定。因此,它不可互換。
這裏的含義是,該密鑰與以太坊中 EOA(外部擁有帳戶)的私鑰一樣重要,使其成為帳戶的單點故障(SPoF)。如果用戶丟失或賬戶的隱私主密鑰被盜,毫無疑問該賬戶將無法恢復。
隱私主密鑰還使用類似於 BIP-32 的過程導出加密密鑰和無效密鑰。用戶可以在不同的應用程序或操作中使用不同的加密密鑰和無效密鑰,以確保隱私和安全。
加密密鑰的公鑰用於加密私人票據,而私鑰用於解密它。例如,在代幣轉賬場景中,如果我(代幣發送者)想要將代幣轉賬給我的朋友(代幣接收者),我需要對私人票據進行加密(代幣的轉賬,涉及到改變變量,本質上balance
是使用我朋友的加密公鑰更改私有狀態變量 UTXO)併發送它。
從局外人的角度來看,如果不知道令牌接收者的加密私鑰,他們就無法破譯這個私人票據,也無法知道令牌接收者是誰。
每次使用私人註釋時,都會生成從該私人註釋派生的無效符(使用無效密鑰加密)。該機制用於防止雙花(避免其他人使用相同的方法確定紙幣的位置或兩次扣除資金),因為 Aztec 協議會檢查無效符是否唯一。為了將該無效符與私人票據相匹配,需要無效私鑰對其進行解密,因此只有其所有者才能建立兩者之間的關係。
描述 Aztec 中交易的概念可能具有挑戰性,因為它很容易與 UTXO(私人票據)混淆,而且 EVM 和 Aztec 中交易的執行模式完全不同。
在Aztec中,每筆交易都以零知識證明的形式廣播(顯然是出於隱私原因)。用戶必須在其節點(錢包應用程序或客戶端)本地執行計算,以生成與交易相對應的證明,而不是像我們過去那樣通過 RPC API 簡單地將交易對象發送到礦工的內存池或任何第 2 層操作員。
當用戶在本地創建交易時,有兩個重要要素:
發件人地址:這代表處理交易的賬戶合約的地址。在這個賬戶合約裏面,有我們前面提到的入口點,它作為外部各方驗證這個行為(交易)是否得到賬戶所有者授權的驗證功能。
有效負載數據:這包括有關交易的信息,例如簽名、目標合約地址、價值、數據等。
在 Aztec 的協議級別,每個有效交易的哈希值被用作防止同一交易被多次執行的手段。賬戶合約開發者可以決定賬戶合約中是否應該有nonce以及相關邏輯。例如,他們可以設置諸如確保交易中的nonce字段嚴格增加或交易可以按任何順序處理等要求。
由於協議層面沒有嚴格的隨機數要求,Aztec 無法通過提交具有相同隨機數和更高 Gas 費用的新交易來取消待處理的交易。
正如前面提到的,用戶可以根據不同情況指定賬戶合約中的任意函數作為入口點,而 Aztec 中的操作並不是由一個簡單的交易對象來控制的。實際上,告訴合約賬戶做什麼的是一個稱為“執行請求”的對象。該對象代表用戶的行為,例如“使用0x1234
以下參數調用合約上的傳輸函數”。
用戶在錢包本地發起交易,其中sender_address
是賬戶合約的地址,包含payload
調用目標合約中函數的相關編碼數據transfer()
,以及賬戶合約可以驗證的簽名。錢包將這兩個元素轉換為執行請求。
然後,錢包將私人票據、加密密鑰或無效秘密輸入到本地虛擬機以模擬此執行請求。模擬過程中會產生執行軌跡,交給證明者生成零知識證明。這個證明表明這些計算(私有函數的執行)確實是由用戶在本地完成的。
通過這個過程,我們獲得兩條信息:proof
和private_data
(本次交易的私有內核電路的輸出)。然後錢包將包含這兩條信息的交易對象發送到 Aztec 的 Sequencer mempool 並完成交易。
在 Aztec 中,我們不會簡單地將所有信息輸入到像 EVM 這樣的圖靈機中來生成更新的狀態。相反,它依賴每個 Dapp 內的電路來確定隱私信息應如何工作。這意味着Dapp開發者需要有一種方法來證明合約變量的狀態。例如,讓我們考慮 ERC-20 代幣合約中用戶的餘額。如果我們想轉賬 10 個 DAI 代幣,合約可能有以下邏輯:
檢查發送者的餘額是否大於 10 DAI(即> 10 DAI
)。
如果發送者有足夠的餘額,則創建一個無效符來表示發送者的 10 DAI 的銷毀(該無效符可以抵消發送者對 10 DAI 私人票據的佔有)。
為收件人創建新的私人註釋。
廣播並加密包含 10 DAI 傳輸的所有消息。
從外人的角度來看,他們只能看到新的無效符和註釋出現,而且它們都是加密的。所以,每個人都知道發生了一筆新的交易,但裏面到底發生了什麼只有參与的參与者知道。
Aztec 中的錢包是管理用戶與區塊鏈及其私人數據交互的重要組成部分。以下是 Aztec 錢包必須處理的任務的摘要:
創建賬戶:錢包應該允許用戶創建新的賬戶合約,這本質上意味着在區塊鏈上部署新的賬戶合約。
私鑰管理:錢包負責管理用戶種子短語和私鑰,其中包括隱私主密鑰和簽名密鑰(取決於賬戶合約的設計)。這種管理還可以擴展到硬件錢包集成。
查看帳戶:用戶應該能夠查看他們的帳戶和相關狀態,包括餘額和其他私人狀態。這意味着錢包需要維護一個本地數據庫,其中包含所有與用戶相關的私人筆記。
與 Dapp 交互:錢包需要促進用戶和 Dapp 之間的交互。當用戶與 Dapp 交互時,Dapp 可能會請求從用戶帳戶發送交易。
用戶同意: Dapp 可能需要用戶同意才能显示某些合約狀態,例如代幣合約中的餘額。要公開這些狀態,錢包必須能夠接收用戶請求(因為公開餘額需要用戶密鑰同意)。
生成證明:要代表用戶發送交易,錢包必須能夠在本地生成證明。這涉及創建和處理交易有效性的零知識證明。
需要注意的一個關鍵點是,錢包需要掃描從創世區塊開始的所有區塊,使用用戶的密鑰來發現和解密相關的私人筆記,然後將其存儲在本地數據庫中以供將來使用。這對於促進用戶交互並確保私有狀態數據能夠得到有效管理至關重要。
您提到了 Aztec 的另一個重要方面,即需要用戶廣播完整的地址。當錢包為目標交易的接收者創建加密票據時,它還需要能夠獲取接收者的完整地址。這可以通過手動輸入或維護收件人地址的本地數據庫來實現。關於這方面的更多細節,可以參考Aztec官方文檔。
在 Aztec 中,賬戶合約的主要任務是驗證簽名(確認交易是由賬戶所有者授權的,因此更廣泛的是授權,而不一定是“通過特定的数字簽名算法進行驗證”)、管理 Gas 消耗、並調用其他合約。
這是使用 Schnorr 簽名算法的 Aztec 帳戶合約的官方示例。所有事務的入口點是entrypoint()
函數(您可以自由選擇函數或名稱作為起點,但在本例中entrypoint()
使用)。
當我們調用entrypoint()
帶有附件的帳戶時payload
,帳戶合約entrypoint()
將調用Aztec AA 帳戶庫entrypoint()
中的。
Aztec不需要我們的賬戶合約導入EntrypointPayload和Aztec AA賬戶庫;你可以自由設計自己的賬戶合約邏輯。
是context一個在 中的每個函數中都可用的對象Aztec.nr。包含context應用程序執行所需的所有內核信息。引自Aztec 官方文檔。- 背景是什麼
以上是Aztec AA賬戶庫的代碼entrypoint()。它負責根據賬戶is_valid_impl合約上定義的驗證函數()來確定該操作是否得到賬戶所有者的授權,並通過 進行必要的調用以實現交易所需的操作execute_calls。
這意味着,如果您想引用此 Aztec AA 庫,並且您的賬戶合約沒有is_valid_impl使用相同的函數簽名實現,則此步驟將失敗。
另一個關鍵的實現細節是使用get_auth_witness()檢索signature. 您可以參考下面參考資料中的介紹來了解見證人的詳細工作原理。簡單來說,見證人是“對用戶想要執行的操作的授權”。
身份驗證見證是一種在 Aztec 上驗證操作的方案,因此用戶可以允許第三方(例如協議或其他用戶)代表他們執行操作。引自Aztec 官方文檔。— 認證見證人
之所以稱為“見證人”而不是簡單地稱為“簽名”,是因為賬戶合約的驗證方式並不一定涉及驗證簽名。
例如,假設有一個操作,將 1000 個代幣從 Alice 的賬戶轉移到 DeFi 平台。在這種情況下,代幣合約需要查詢Alice的賬戶合約,看看她是否批准這個“行動”。此“操作”需要在 Alice 的錢包(本地)中生成一個身份驗證見證,然後可以通過她的帳戶合約進行驗證。如果賬戶合約驗證成功,代幣合約就能知道這個“動作”已經被授權。
截至目前,Aztec還沒有實現費用機制,他們的目標也是抽象化費用的支付。這意味着,要使一筆交易被視為有效,它必須證明它已經鎖定了足夠的資金來支付自己的費用。然而,它沒有具體說明這些資金必須來自哪裡,從而可以通過即時交換輕鬆實現付款或實物支付。