Gate 广场创作者新春激励正式开启,发帖解锁 $60,000 豪华奖池
如何参与:
报名活动表单:https://www.gate.com/questionnaire/7315
使用广场任意发帖小工具,搭配文字发布内容即可
丰厚奖励一览:
发帖即可可瓜分 $25,000 奖池
10 位幸运用户:获得 1 GT + Gate 鸭舌帽
Top 发帖奖励:发帖与互动越多,排名越高,赢取 Gate 新年周边、Gate 双肩包等好礼
新手专属福利:首帖即得 $50 奖励,继续发帖还能瓜分 $10,000 新手奖池
活动时间:2026 年 1 月 8 日 16:00 – 1 月 26 日 24:00(UTC+8)
详情:https://www.gate.com/announcements/article/49112
研究报告:Aztec账户抽象介绍
作者:ChiHaoLu ( chihaolu.eth ) 来源:medium 翻译:善欧巴,金色财经
本文主要介绍Aztec Layer2解决方案中Account Abstraction(AA)的发展及相关内容。我引用了大量Aztec的官方资源,包括官方文档、博客和教程。请在文章末尾的参考文献部分找到这些优秀的资源!
背景
由于与 ZK-Rollups 中的其他 Native AA 实现相比,Aztec 的复杂性有所增加,读者可能会受益于拥有一定的背景,以便更好地理解本文。
介绍
快速浏览Aztec
Aztec 是一个开源第 2 层网络,旨在为以太坊提供可扩展性和隐私保护。Aztec 利用 zkSNARK 证明通过 ZK-Rollup 服务提供隐私保护和可扩展性。Aztec 的用户不需要任何受信任的第三方或额外的共识机制来访问隐私交易。
我们都知道,在传统的 ZK-Rollups 中,“ZK”并不一定意味着隐私;它意味着使用零知识证明(ZKP)来证明某些计算已在链下正确执行。然而,在 Aztec 中,除了可扩展性之外,ZK-Rollup 中还实现了隐私性。深究一下,在过去,每笔交易的细节在链上都是公开可见的,但在Aztec,每笔交易的输入和输出都是加密的。这些交易通过ZKP进行验证,以证明加密信息是准确的并且源自明文。只有构建这些私人交易的用户才知道实际的明文信息。
如何实现私密交易以及如何验证它们的基本原理是一个很大的话题,超出了本文的范围。简单来说,我们需要的是一个“用于零知识证明验证的附加层”来验证 ZKP 列表,每个 ZKP 都验证一个私人交易。这也是它们被称为“ZK-ZK-Rollups”的原因。
什么是Noir?
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的 AA 机制
什么是协议层,什么是应用层?
众所周知,EIP-4337旨在将整个交易流程移至应用层,实现开放中继系统,并通过智能合约的可编程特性抽象出签名(验证机制)和支付模型。然而,对于 Native Account Abstraction,无论是在 StarkNet、zkSync 时代,还是本文重点的 Aztec,都需要将某些元素蚀刻到 Layer2 的协议中才能正常运行。例如,在 Aztec 中,加密密钥和无效密钥需要在协议级别实现。
了解本机帐户抽象需要更深入地了解整个链的运作方式(假设它被称为“本机”,AA 的执行逻辑自然链接到特定 Layer2 的协议)。例如,在 zkSync 时代,需要理解系统合约,在 StarkNet 中,需要理解序列器如何运行,而在 Aztec 中,理解这些“密钥及其底层私有状态”的作用至关重要。
账户入口点和验证阶段
在 Aztec 中,与账户抽象的其他实现不同,没有严格定义的函数名称(函数签名)作为账户合约的入口点(例如,validateUserOp在 EIP-4337、validateTransactionzkSync Era 和__validate__StarkNet 中)。用户可以自由选择账户合约中的任意函数作为入口点,并发送带有相关参数的交易。
用户选择的函数(我们称之为entrypoint())必须是私有的(在用户的私有执行环境中执行)。只能从账户合约所有者的客户端(用户的钱包)调用。当用户的钱包entrypoint()在本地执行时,它同时生成零知识证明。该证明通知Aztec协议的验证阶段,链下执行已经发生并且已经成功。
验证阶段的限制
这也延伸到是否在验证阶段对可执行操作施加限制的问题。众所周知,由于验证交易没有成本限制(本质上,验证交易是调用函数view),攻击者可以对内存池执行拒绝服务(DOS)攻击,以破坏捆绑器(EIP-4337)或操作员/排序器(原生AA)。EIP-4337 定义了禁止哪些操作码以及如何限制存储访问。zkSync Era放宽了一些OpCode的使用,而StarkNet根本不允许外部合约调用。
由于 Aztec 协议涉及客户端对附加的零知识证明进行验证,而不是实际调用验证函数来确定结果为 或 ,因此trueAztecfalse与其他协议不同,在验证阶段不会施加任何限制。账户内的合约entrypoint可以自由调用其他合约、访问任何存储、执行任何计算。
交互流程
更详细地说,在 zkSync Era 和 StarkNet 中,只有“账户合约”才能发起交易,因为协议调用指定函数作为入口点,施加了这种限制。然而,在 Aztec 中,“所有合约”都可以发起交易,因为协议调用哪个函数作为入口点没有限制。这意味着在 Aztec 上,不再是用户将交易发送到特定角色(例如 EIP-4337 中的 EntryPoint 合约或 Native AA 中的定序器/操作符),然后调用目标合约的固定交互流程。用户可以通过钱包发送交易,直接让目标合约完成相关交互,大大增强了灵活性。
Aztec 帐户中的密钥
在 Aztec 中,每个帐户通常有两个主密钥:签名密钥和隐私主密钥。
签名密钥
签名密钥用于表示用户对使用私钥执行特定操作的授权。一个简单的例子是用户在帐户合约中记录从签名密钥派生的公钥。然后,通过使用此签名密钥对交易或消息进行签名,可以在合约内恢复生成的签名,以检查其是否与合约中记录的公钥(也称为所有者控制密钥,以密钥形式存储)相匹配。addressSolidity 钱包合约中的变量)。
关于数字签名椭圆曲线算法的选择,由用户决定。例如,以太坊使用secp256k1,而 Aztec 提供了使用 的示例schnorr。在账户合约中,该entrypoint()函数作为入口点(调用的来源),验证逻辑(is_valid_impl())使用 来检查 Schnorr 签名是否与记录的公钥匹配std::schnorr::verify_signature(…)。
签名密钥本质上和我们熟悉的智能合约钱包中的所有者控制密钥相同,所以应该比较容易理解。事实上,签名密钥并不是绝对必要的。如果帐户开发者实施了其他验证机制,则帐户可能没有签名密钥。
隐私主密钥
Aztec账户中的隐私主密钥是不可转让的;每个 Aztec 帐户都绑定到一个隐私主密钥。隐私主密钥衍生出公共主密钥,然后与合约代码进行哈希运算,生成账户合约的地址。
所以,尽管Aztec允许我们在账户合约中实现验证机制甚至一些恢复机制来增强账户安全性,但与隐私主密钥相关的机制却被印在协议中并与地址绑定。因此,它不可互换。
隐私主密钥还使用类似于 BIP-32 的过程导出加密密钥和无效密钥。用户可以在不同的应用程序或操作中使用不同的加密密钥和无效密钥,以确保隐私和安全。
加密密钥
加密密钥的公钥用于加密私人票据,而私钥用于解密它。例如,在代币转账场景中,如果我(代币发送者)想要将代币转账给我的朋友(代币接收者),我需要对私人票据进行加密(代币的转账,涉及到改变变量,本质上balance是使用我朋友的加密公钥更改私有状态变量 UTXO)并发送它。
从局外人的角度来看,如果不知道令牌接收者的加密私钥,他们就无法破译这个私人票据,也无法知道令牌接收者是谁。
无效符
每次使用私人注释时,都会生成从该私人注释派生的无效符(使用无效密钥加密)。该机制用于防止双花(避免其他人使用相同的方法确定纸币的位置或两次扣除资金),因为 Aztec 协议会检查无效符是否唯一。为了将该无效符与私人票据相匹配,需要无效私钥对其进行解密,因此只有其所有者才能建立两者之间的关系。
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 并完成交易。
基于客户端的 ZKP 代替 EVM 的类型执行环境
在 Aztec 中,我们不会简单地将所有信息输入到像 EVM 这样的图灵机中来生成更新的状态。相反,它依赖每个 Dapp 内的电路来确定隐私信息应如何工作。这意味着Dapp开发者需要有一种方法来证明合约变量的状态。例如,让我们考虑 ERC-20 代币合约中用户的余额。如果我们想转账 10 个 DAI 代币,合约可能有以下逻辑:
从外人的角度来看,他们只能看到新的无效符和注释出现,而且它们都是加密的。所以,每个人都知道发生了一笔新的交易,但里面到底发生了什么只有参与的参与者知道。
深入了解Aztec账户合约
钱包
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合约上定义的验证函数()来确定该操作是否得到账户所有者的授权,并通过 进行必要的调用以实现交易所需的操作ute_calls。
这意味着,如果您想引用此 Aztec AA 库,并且您的账户合约没有is_valid_impl使用相同的函数签名实现,则此步骤将失败。
另一个关键的实现细节是使用get_auth_witness()检索signature. 您可以参考下面参考资料中的介绍来了解见证人的详细工作原理。简单来说,见证人是“对用户想要执行的操作的授权”。
身份验证见证是一种在 Aztec 上验证操作的方案,因此用户可以允许第三方(例如协议或其他用户)代表他们执行操作。引自Aztec 官方文档。— 认证见证人
之所以称为“见证人”而不是简单地称为“签名”,是因为账户合约的验证方式并不一定涉及验证签名。
例如,假设有一个操作,将 1000 个代币从 Alice 的账户转移到 DeFi 平台。在这种情况下,代币合约需要查询Alice的账户合约,看看她是否批准这个“行动”。此“操作”需要在 Alice 的钱包(本地)中生成一个身份验证见证,然后可以通过她的帐户合约进行验证。如果账户合约验证成功,代币合约就能知道这个“动作”已经被授权。
结论
截至目前,Aztec还没有实现费用机制,他们的目标也是抽象化费用的支付。这意味着,要使一笔交易被视为有效,它必须证明它已经锁定了足够的资金来支付自己的费用。然而,它没有具体说明这些资金必须来自哪里,从而可以通过即时交换轻松实现付款或实物支付。