主页 > imtoken如何转账 > Ethereum Account Abstraction (EIP-2938) 智能合约钱包@Ethereum Fang Enthusiast

Ethereum Account Abstraction (EIP-2938) 智能合约钱包@Ethereum Fang Enthusiast

imtoken如何转账 2023-05-25 07:26:10

翻译校对:敏敏、阿健

历史和动机

账户抽象的概念最早在2017年编写的EIP-86中提出,其目的是实现“交易来源和签名的抽象”。 不过其动机和想法可以追溯到2016年初vitalik提交的一个issue,文章建议“与其将ECDSA签名算法和默认的nonce机制写入协议作为‘标准’账户安全机制,不如最好先建立一个(统一的),以后所有的账户都变成合约,合约可以支付gas,用户可以自由定义自己的安全模型。”

实现最初的提议非常具有挑战性,因为不仅要对协议进行实质性修改,而且还需要满足系统的安全保证。

最近,Vitalik 等人。 提议的 EIP-2938 草案,它概述了一个更简单的实现。 此实现对协议/共识进行了最小的更改,并通过设置节点的内存池规则来满足所需的安全保证。 Vitalik 的 Ethereum Engineering Group Meetup 演讲和 Sam Wilson 和 Ansgar Dietrichs(EIP 的另外 2 位作者)的 ETH Online 演讲(以及两篇随附的文章:1 和 2)是对该主题的出色介绍。 本文将重点介绍这些材料的关键要素。

动机:

账户抽象背后的动机很简单,但它会带来根本性的改变:目前,以太坊交易在功能上是可编程的(通过调用智能合约),但交易的验证方式是固定的。 只有持有有效的 ECDSA 签名、有效的 nonce 值和足够的账户余额,交易才有效。 账户抽象引入了一种新的交易类型——抽象账户交易(AA Transaction)。 此类交易总是由一个特殊地址生成,协议不检查其签名、随机数和余额。 通过引入这种交易,账户抽象实现了固定验证方式向可编程验证方式的转变。 抽象账户交易的有效性由其目标字段指定的智能合约验证。 验证通过后,合约可自行支付交易手续费。

那么为什么账户抽象如此有用呢? 我们将以以太坊钱包为例来说明它带来的好处。

智能合约钱包:

今天大多数以太坊钱包都是外部账户钱包,它们的安全性受到种子短语生成的私钥的保护。 (遵循BIP-39标准的一串助记词由从2048个单词中依次选出的12-24个单词组成。助记词为PBKDF2函数提供了生成一串二进制种子所需的信息熵。基于BIP-32的钱包则使用此种子生成非对称密钥对。)为了以后在其他钱包中恢复密钥,用户应妥善保管助记词。 但是这种钱包很容易因为私钥被盗或者助记词丢失导致用户的资产丢失。

(顾名思义)智能合约钱包是通过智能合约在链上实现的。 该钱包可以提供可编程的风险迁移和友好的用户体验,例如多重签名安全、基于社交或时间的钱包恢复、转账金额限制、地址黑白名单、无燃料费的元交易和批量交易。

尽管智能合约由于代码质量差而面临安全风险,但可以通过钱包提供商的安全审计来降低这种风险。 外部账户钱包的风险完全由用户自行承担。 用户无法像智能合约那样获得可编程的安全保障,用户必须自行保管好助记词。

以太坊合约怎么做_sitezhishu.com 以太坊合约_以太坊合约地址查询

目前可用的智能合约钱包有 Argent、Authereum、Dapper、Dharma、Gnos is Safe、Monolith 和 MYKEY。 从下图中可以看出,这些钱包的使用率似乎在增加。

所有这些高级钱包功能都使用灵活的智能合约。 钱包用户要么通过外部账户发送交易,支付gas费调用钱包合约,要么依赖钱包提供商支持元交易功能,通过钱包提供商中继或Gas Station Network等第三方中继网络使用钱包。 前者通常是指通过KYC认证的用户依赖中心化交易所购买ETH(支付gas费); 后者将用户的负担转移到中继器上,由钱包提供商或用户链上或链下中继器补偿,从而提高用户体验。

但是,基于中继器的架构具有三个主要缺点:

他们可能面临中心化的批评并引起对交易审查的担忧; 由于中继器发送的交易需要额外支付 21,000 单位的基本 gas 费,为了获得利润,它必须收取更高的费用来覆盖这部分成本,这就导致了技术和经济上的低效率; 使用中继特定协议迫使应用程序依赖非以太坊基础设施,较小的用户群无法支持这些设施提供稳定可靠的服务。

账户抽象将使智能合约能够在不依赖中继网络的情况下接受来自用户的无 gas 元交易并为他们支付 gas 费用。 因此,这种底层能力可以在不牺牲去中心化的情况下极大地改善这些智能合约钱包的用户体验。

Tornodo Cash:另一个相关应用程序(将受益于帐户抽象)是交易混淆器,例如 tornado.cash。 Tornado 使用智能合约切断地址之间的链上连接,以提高交易的隐私性。 该合约允许用户通过另一个地址存入 ETH 和提取资金。 用户在存款时提供一个秘密值的哈希值,随后在提款时提供 zkSnark 证明。 这个证明可以在不泄露秘密值和存款信息的情况下证明它知道秘密值。 这将存款和取款分离。

但是在提款方面存在鸡与蛋的问题。 为了在新生成的地址上进行取款交易,用户需要向该地址存入一些ETH来支付gas费。 但是这些 ETH 的来源(通常是交易所)本身会破坏使用 Tornado 所带来的隐私。 首选的替代方案是再次使用中继网络,它具有上述缺点。

账户抽象可以解决这个问题。 Tornado 合约可以接受用户的提现抽象账户交易,验证 zkSnark,扣除 gas 费(从保证金中),然后将剩余资金转移到提现地址。

帐户抽象

EIP-2938 中提出的账户抽象接受合约作为顶级账户,这样它就可以支付交易费用并开始交易的执行过程。 实现账户抽象需要更改协议以添加新的抽象账户交易类型、修改内存池规则并引入扩展以支持高级使用。 抽象账户交易需要添加两个新的操作码:NONCE和PAYGAS。 账户类型保持现有的两种(外部账户和合约账户),所有变化都向后兼容以支持当前的交易、智能合约和协议。

账户抽象应用可以分为两类: 1)单租户应用,如智能合约钱包,为每个用户创建一个新合约; 2) 多租户应用程序,例如 tornado.cash 或 Uniswap,其中多个用户和同一组智能合约交互。

以太坊合约怎么做_以太坊合约地址查询_sitezhishu.com 以太坊合约

目前还不能支持多租户应用,需要更多的研究工作,以期在未来尽快实现。 因此,本文将重点关注单租户账户的抽象。

协议变更

协议的唯一变化是引入了一种新的交易类型,以及相关的两个操作码 NONCE 和 PAYGAS。

抽象账户交易:协议引入了一种新的交易类型:AA_TX_TYPE。 它的二进制数据(payload)将被解析为 RLP([nonce, target, data]) 而不是 RLP([nonce, gas_price, gas_limit, to, value, data, v, r, s]) for existing transactions 。

Nonce校验类似于现有交易,需要满足tx.nonce == tx.target.nonce。 如果检查失败,则交易无效,如果检查通过,tx.target.nonce 将递增,交易继续进行。

抽象账户交易的基本气体消耗将从 21000 减少到 15000(以反映去除内置 ECDSA 签名所节省的成本)。 此外以太坊合约怎么做,抽象账户交易没有内置的气体限制。 交易执行时,只需将gas limit设置为当前区块剩余的gas limit即可。

NONCE操作码:NONCE操作码(0x48)将被调用者的nonce值——即抽象账户交易的目标字段指定的合约——压入EVM堆栈。 这样,nonce值暴露给了EVM,因此抽象账户合约可以使用交易的任何字段(包括nonce)作为签名验证逻辑的一部分。

PAYGAS 操作码:PAYGAS 操作码 (0x49) 从栈中弹出 2 个参数:(栈顶)version_number,(二级栈顶)memory_start。

Version_number 允许未来通过新的实现更改操作码的语义。 目前,操作码的语义如下:

检查 version_number == 0(否则抛出异常)读取 gas_price = bytes_to_int(vm.memory[memory_start: memory_start + 32]) 读取 gas_limit = bytes_to_int(vm.memory[memory_start + 32: memory_start + 64]) 检查合约。 balance >= gas_price * gas_limit(否则抛异常) 检查globals.transaction_fee_paid == False(否则抛异常) 检查AA执行框架==顶层框架,即当前EVM执行是否退出或回滚,整个交易EVM暂停执行(否则抛出异常) Set contract.balance -= gas_price * gas_limit Set globals.transaction_fee_paid = True Set globals.gas_price = gas_price, globals.gas_limit = gas_limit set remaining_gas = gas_limit 本次执行context - 已经消耗了 gas

抽象账户交易执行结束时,(globals.limit - remaining_gas) * globals.gas_price 的手续费会转给矿工,remaining_gas * globals.gas_price 的数量会返还给抽象账户合约.

以太坊合约怎么做_以太坊合约地址查询_sitezhishu.com 以太坊合约

PAYGAS 操作码充当 EVM 执行期间的检查点。 任何回滚只会返回到之前的检查点。 此时合约不会收到退款,globals.gas_limit * globals.gas_price 的金额会转给矿工。

这种新的交易类型和这两种新的操作码构成了协议/共识层面的彻底改变,其语义相对直观易懂。

内存池规则

“Mempool指的是以太坊节点内部存储在内存中的数据结构,它存储了可供挖矿的候选交易。Geth称之为‘交易池’;Parity称之为‘交易队列’(transaction queue)’。不管它是什么called,它是一个数据池,里面存放着将要被打包进区块的交易,我们可以把它看成是待打包区块的“候车厅”。

抽象账户交易的可编程验证引入了额外的复杂性。 抽象账户交易不预付gas费,而是依赖目标字段指定的抽象账户合约(通过PAYGAS opcode)支付gas费。 理论上,抽象账户交易分两个阶段进行处理:较短的验证阶段(执行 PAYGAS 操作码之前)和较长的执行阶段(执行 PAYGAS 操作码后)。如果验证阶段失败(或抛出异常),则交易无效(就像签名无效的非抽象账户交易),交易不会被包含在区块中,矿工也不会得到交易费

因此,矿工和节点需要一种可预测的机制来避免挂起的抽象账户交易的有效性取决于内存池中其他挂起的交易。 否则,一次交易执行失败可能导致很多甚至所有抽象账户交易无效,从而构成拒绝服务攻击。 为了避免这种情况发生,我们建议内存池对抽象账户交易执行两条规则(由矿工和节点执行,但不修改协议本身)。

操作码限制

为了防止抽象账户交易的有效性取决于抽象账户合约以外的任何状态,以下操作码在验证阶段(即执行 PAYGAS 操作码之前)被视为无效: 执行环境操作码(BLOCKHASH、COINBASE、TIMESTAMP、NUMBER , DIFFICULTY, GASLIMIT), BALANCE(对于任何账户,包括目标合约地址),任何外部调用/创建操作码(CALL,CALLCODE,STATICCALL,CREATE,CREATE2)除了目标合约或预编译合约,对于任何外部状态的读取操作码除了目标合约(EXTCODESIZE、EXTCODEHASH、ETXCODECOPY、DELEGATECALL)。

如果抽象账户交易的目标字段指向的抽象账户合约违反了该操作码限制规则,节点将丢弃该交易。 这样,只要抽象合约的状态不发生变化,内存池中有效的抽象账户交易就会持续有效。

字节码前缀限制

如果非抽象账户交易可以影响抽象账户合约的状态,它可以影响内存池中抽象账户交易的有效性。 为了防止这种情况发生,抽象账户交易应该只接受字节码前缀为 AA_PREFIX 的目标合约。 AA_PREFIX 对 msg.sender 进行检查以确保它是一个特殊的 ENTRY_POINT 地址。 这有效地防止了非抽象账户交易与抽象账户交易的交互。

以太坊合约怎么做_sitezhishu.com 以太坊合约_以太坊合约地址查询

如果节点检查抽象账户交易指定的合约没有这个AA_PREFIX作为字节码前缀(即不是抽象合约),则应该删除该交易。

抽象账户合约的这两个限制保证了:(1)只有抽象账户合约的内部状态才能影响抽象账户交易的验证逻辑; (2) 只有与目标具有相同抽象账户合约的抽象账户交易才能修改合约的状态。

因此以太坊合约怎么做,只有当区块包含另一个针对同一抽象账户合约的抽象账户交易时,才有可能使待处理的抽象账户交易无效。 然而,由于这不是协议/共识层的变化,矿工在打包交易时可以自由地违反这些规则。

扩张

上述协议变更和内存池规则足以安全地实现智能合约钱包等单租户应用程序。 其他高级用法需要放宽上述规则或需要实现多租户应用,这就需要账户抽象支持以下形式的扩展:

SET_INDESTRUCTIBLE 操作码,它禁用 SELFDESTRUCT 并允许抽象账户合约在验证阶段通过 DELEGATECALL 安全地调用库函数。

S_STATIC 操作码,如果当前上下文是静态的,则返回 true,并允许非抽象账户交易的调用者绕过之前的字节码前缀限制,并从抽象账户合约中安全地读取数据。

RESERVE_GAS 操作码,当一个非抽象账户交易试图将状态写入一个抽象账户合约时,设置一个gas消耗的下限。 这样做是为了迫使攻击者在试图使 mempool 的抽象账户交易无效时至少消耗一定量的 gas,从而抑制他们的攻击动机。

还有一些其他的扩展,比如存储多笔待处理的交易(译者注:内存池在同一个地址存储多笔待处理的抽象账户交易)、缓存验证结果、验证时的动态gas limit、安全交易等。 全部用于支持多租户应用程序和零知识证明。 这些超出了本文的范围。

下一步

目前,EIP-2938 on account abstraction 只是一个草案,正在以太坊研究论坛上进行讨论。 下一步是考虑将此 EIP 合并到即将到来的硬分叉中。 EIP 的作者显然瞄准了柏林之后的硬分叉(柏林暂定在 2021 年初的某个时间),尽管具体时间表尚不确定。 因此,EIP-2938 还处于早期阶段。

以太坊合约地址查询_sitezhishu.com 以太坊合约_以太坊合约怎么做

此外,尚不清楚是否有必要将 EIP-2938 添加到以太坊的第 1 层 (L1)。 鉴于第 2 层 (L2) 方法的灵活性(如我们之前的帖子所述),我们还可以在特定的 L2 上实现帐户抽象,这样就不需要升级整个 L1。 但是,在L1上统一支持账户抽象要比在不同的L2上分别实现账户抽象要好。 因此,在何处以及如何实施帐户抽象还有待观察。

“帐户抽象在某种程度上不太重要,因为无论 L1 是否支持,它都可以在 L2 实施。” - Vitalik 在谈到基础层的升级需求时表达了这一观点(这是他在以汇总为中心的以太坊路线图帖子中提到的写作)。

Status:Status钱包目前是一个外部账户钱包,其独门绝技是将聊天支付和Keycard(译者注:硬件钱包)整合为一个私人信使服务。 目前正在考虑添加一些智能合约钱包功能,例如多重签名和基于社交的钱包恢复。 如前所述,支持 EIP-2938 有助于消除对中心化和低效中继架构的依赖。

Status 还在评估 L2 解决方案,正如我们在之前的帖子中所说,该解决方案将支持钱包中的多个链并为多个用例提供所需的扩展。 例如,Keycard 正在探索一种支付网络,该网络需要以太坊网络目前无法提供的信用卡级可扩展性和近乎即时的终结性。 此外,还有许多其他程序,例如推荐程序、SNT 反应、Tribute-to-Talk 和 ENS 域。 所有这些计划都适合在 L2 上实施,因为它部署可行并且可以提供不错的用户体验。 如果一个可行的 L2 解决方案实现了账户抽象,那么在这个 L2 上的项目就可以享受账户抽象的好处,而不需要依赖 L1。

总结

以太坊协议的一个根本问题是,只有外部账户(EOS())可以支付 gas 费用并启动交易执行过程,而合约账户(CA())不能。账户抽象(AA( 提案允许具有特定结构的合约账户检查一种新型交易——抽象账户交易的有效性,并代为支付gas费,从而在不需要外部账户的情况下有效地启动交易的执行过程。

账户抽象可以显着改善钱包、交易混淆器、DApp 和 DeFi 的用户体验,而无需依赖中心化和低效的中继架构。 通过引入新的交易类型、两个操作码和两个内存池规则,账户抽象可以安全地支持基本的单租户场景,例如智能合约钱包。 如果要支持更高级的多租户应用,比如Tornodo Cash,就需要对协议和节点规则做更多的扩展。

本文说明了智能合约钱包中帐户抽象的必要性。 通过描述协议更改及其对节点的影响来突出帐户抽象的关键部分。 我们还谈到了一些高级使用的扩展建议,最后通过介绍以太坊 Status 项目的路线图和优先级,让读者对账户抽象有一个更清晰的定位。

减少 Web3 摩擦和提升用户体验是这个生态中所有项目的重中之重。 账户抽象在未来最终会以某种形式发挥重要作用。

(感谢 Hester Bruikman 审阅本文草稿并提供有用的反馈。感谢 Alex Howell 提供的深思熟虑的插图。)

(结束)

(本文链接较多,可点击左下方“阅读原文”从EthFans网站获取)

原文链接: