Alert Source Discuss
⚠️ Review Standards Track: Core

EIP-7698: EOF - 创建交易

使用创建交易部署 EOF 合约

Authors Piotr Dobaczewski (@pdobacz), Andrei Maiboroda (@gumb0), Paweł Bylica (@chfast), Alex Beregszaszi (@axic)
Created 2024-04-24
Requires EIP-3540

摘要

创建交易(即 to 为空的交易)可以通过在交易的 data 中提供 EOF initcontainercalldata 的连接来部署 EOF 合约,用于 initcontainer 的执行。Initcontainer 的执行类似于在 EOFCREATE 指令期间的执行,以 RETURNCODE 指令结束。新账户地址的计算基于发送者的地址和 nonce。

动机

创建交易是除了传统 EVM 提供的创建指令之外的三种部署新代码的方式之一。鉴于传统创建指令(CREATECREATE2)不允许部署 EOF 代码,因此在创建交易中支持 EOF 是在链上获取第一个 EOF 的唯一方法。

initcontainer 提供构造函数参数的机制与部署传统代码的机制完全相同(只需将它们与 initcontainer 连接起来),因此现有的部署工具可以直接用于部署 EOF。

规范

在未明确列出的情况下,EOF 合约创建的规则应与传统创建交易的规则相同或类似。这包括但不限于:

  • accessed_addresses 上的行为和地址冲突 (EIP-684EIP-2929)
  • 为 initcode 创建的 EVM 执行帧 - 内存、账户上下文等。
  • 新创建合约账户的 nonce 增加 EIP-161
  • 创建捐赠的余额检查和转移

参数

Constant Value
EOF_MAGIC EIP-3540 中定义为 0xEF00
MAX_CODE_SIZE EIP-170 中定义为 24576

如果创建交易(to 为空的交易)的 dataEOF_MAGIC 开头,则 data 将被解释为 EOF initcontainercalldata 的串联。更具体地说:

  1. 应用 EIP-3860 中为创建交易定义的内在 gas 成本规则和限制。交易的整个 data 用于这些计算。
  2. 找到将 data 拆分为 initcontainercalldata 的位置:
    • 解析 EOF 头部
    • 通过从头部读取所有 section 大小并将它们与头部大小相加来找到 intcontainer 大小,以获得完整的容器大小。
  3. 递归地验证 initcontainer 及其所有子容器。
    • 与通用验证不同,initcontainer 还需要使其在头部中声明的 data_size 等于实际的 data_section 大小。
    • 验证包括检查 initcontainer 是否不包含 RETURNSTOP
  4. 如果 EOF 头部解析或完整容器验证失败,则交易被认为是有效但失败的。不消耗 initcode 执行的 Gas,仅收取内在创建交易成本。
  5. 交易 data 中位于 initcontainer 之后的 calldata 部分被视为传递到执行帧的 calldata。
  6. 执行容器并扣除执行所需的 gas。
    1. 计算 new_addresskeccak256(sender || sender_nonce)[12:]
    2. 成功的执行以 initcode 执行 RETURNCODE{deploy_container_index}(aux_data_offset, aux_data_size) 指令结束。之后:
      • 从执行 RETURNCODE 的容器中的 deploy_container_index 位置加载 EOF 子容器中的 deploy-contract,
      • 将数据段与 (aux_data_offset, aux_data_offset + aux_data_size) 内存段连接起来,并更新头部中的数据大小,
      • deployed_code_size 为更新后的 deploy 容器大小,
      • 如果 deployed_code_size > MAX_CODE_SIZE 指令异常中止,
      • state[new_address].code 设置为更新后的 deploy 容器(EIP-3541 的规则,禁止从创建交易部署以 EF 开头的 code,在这种情况下不适用)。
  7. 扣除 200 * deployed_code_size gas。

理由

用于部署 Creator Contract 的不规则状态更改

最初建议通过不规则状态更改来部署第一个 EOF 合约。此合约将执行 TXCREATE 指令,然后可以用作部署任何其他 EOF 代码的入口点。这也需要引入 InitcodeTransaction,这是 TXCREATE 所需的。考虑到减少更改范围,最终决定不采用这种方式。

initcontainer 外部与数据段中的构造函数参数

考虑了另一种为 initcontainer 执行提供构造函数参数的机制,其中它们与 initcontainer 的数据段连接,并通过 DATA* 指令而不是 CALLDATA* 访问。这样做的好处是不需要查找将 transaction.data 拆分为 initcontainercalldata 的步骤,因为整个 transaction.data 都是一个 EOF 容器。但是,由于以下原因,它被拒绝:

  • 如果不进行修改,则无法使用现有工具来部署 EOF。为了构造 EOF 创建交易,该工具将需要将构造函数参数附加到容器,并更新 EOF 头部中的数据段大小。编译器可以预测构造函数参数的大小以将预期的数据大小放在头部中,但是对于可变长度的构造函数参数是不可能的。
  • 如果在以后的升级中引入了专门的 EOF 创建交易(例如 InitcodeTransaction),它将具有用于 initcontainer 执行输入的专用字段(calldata),并且将在 initcode 中使用 CALLDATA* 指令访问它。最好避免编译器需要根据它将在哪个上下文中使用来以不同的方式生成 initcontainer 代码的情况。
  • 作为一个普遍的论点,数据段可以被视为包含执行认为已验证并与代码定义紧密耦合的数据,而 calldata 是来自外部的输入,可能是任意的且未经验证。

向后兼容性

部署传统代码的创建交易不受影响,因为任何以前以 EF 字节开头的此类交易都会因执行无效指令而失败。

安全考虑

待定

版权

CC0 下放弃版权及相关权利。

Citation

Please cite this document as:

Piotr Dobaczewski (@pdobacz), Andrei Maiboroda (@gumb0), Paweł Bylica (@chfast), Alex Beregszaszi (@axic), "EIP-7698: EOF - 创建交易 [DRAFT]," Ethereum Improvement Proposals, no. 7698, April 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7698.