EIP-7698: EOF - 创建交易
使用创建交易部署 EOF 合约
Authors | Piotr Dobaczewski (@pdobacz), Andrei Maiboroda (@gumb0), Paweł Bylica (@chfast), Alex Beregszaszi (@axic) |
---|---|
Created | 2024-04-24 |
Requires | EIP-3540 |
Table of Contents
摘要
创建交易(即 to
为空的交易)可以通过在交易的 data
中提供 EOF initcontainer
与 calldata
的连接来部署 EOF 合约,用于 initcontainer
的执行。Initcontainer
的执行类似于在 EOFCREATE
指令期间的执行,以 RETURNCODE
指令结束。新账户地址的计算基于发送者的地址和 nonce。
动机
创建交易是除了传统 EVM 提供的创建指令之外的三种部署新代码的方式之一。鉴于传统创建指令(CREATE
和 CREATE2
)不允许部署 EOF 代码,因此在创建交易中支持 EOF 是在链上获取第一个 EOF 的唯一方法。
为 initcontainer
提供构造函数参数的机制与部署传统代码的机制完全相同(只需将它们与 initcontainer
连接起来),因此现有的部署工具可以直接用于部署 EOF。
规范
在未明确列出的情况下,EOF 合约创建的规则应与传统创建交易的规则相同或类似。这包括但不限于:
accessed_addresses
上的行为和地址冲突 (EIP-684 和 EIP-2929)- 为 initcode 创建的 EVM 执行帧 - 内存、账户上下文等。
- 新创建合约账户的 nonce 增加 EIP-161
- 创建捐赠的余额检查和转移
参数
Constant | Value |
---|---|
EOF_MAGIC |
在 EIP-3540 中定义为 0xEF00 |
MAX_CODE_SIZE |
在 EIP-170 中定义为 24576 |
如果创建交易(to
为空的交易)的 data
以 EOF_MAGIC
开头,则 data
将被解释为 EOF initcontainer
和 calldata
的串联。更具体地说:
- 应用 EIP-3860 中为创建交易定义的内在 gas 成本规则和限制。交易的整个
data
用于这些计算。 - 找到将
data
拆分为initcontainer
和calldata
的位置:- 解析 EOF 头部
- 通过从头部读取所有 section 大小并将它们与头部大小相加来找到
intcontainer
大小,以获得完整的容器大小。
- 递归地验证
initcontainer
及其所有子容器。- 与通用验证不同,
initcontainer
还需要使其在头部中声明的data_size
等于实际的data_section
大小。 - 验证包括检查
initcontainer
是否不包含RETURN
或STOP
- 与通用验证不同,
- 如果 EOF 头部解析或完整容器验证失败,则交易被认为是有效但失败的。不消耗 initcode 执行的 Gas,仅收取内在创建交易成本。
- 交易
data
中位于initcontainer
之后的calldata
部分被视为传递到执行帧的 calldata。 - 执行容器并扣除执行所需的 gas。
- 计算
new_address
为keccak256(sender || sender_nonce)[12:]
- 成功的执行以 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
,在这种情况下不适用)。
- 从执行
- 计算
- 扣除
200 * deployed_code_size
gas。
理由
用于部署 Creator Contract 的不规则状态更改
最初建议通过不规则状态更改来部署第一个 EOF 合约。此合约将执行 TXCREATE
指令,然后可以用作部署任何其他 EOF 代码的入口点。这也需要引入 InitcodeTransaction
,这是 TXCREATE
所需的。考虑到减少更改范围,最终决定不采用这种方式。
initcontainer 外部与数据段中的构造函数参数
考虑了另一种为 initcontainer 执行提供构造函数参数的机制,其中它们与 initcontainer 的数据段连接,并通过 DATA*
指令而不是 CALLDATA*
访问。这样做的好处是不需要查找将 transaction.data
拆分为 initcontainer
和 calldata
的步骤,因为整个 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.