限制和计量initcode

该EIP提议为以太坊的initcode(合约创建代码)引入最大尺寸限制(49152字节)和新的Gas费用(每32字节2个Gas),以更公平地计量合约创建过程中跳跃目标分析(jumpdest-analysis)的成本。此举旨在提高EVM的效率和安全性,并简化客户端实现。

摘要

我们通过引入 initcode 的最大大小限制(MAX_INITCODE_SIZE = 2 * MAX_CODE_SIZE = 49152)来扩展 EIP-170

此外,我们对每 32 字节的 initcode 块收取 2 gas 的费用,以代表 jumpdest-analysis 的成本。

最后,大小限制带来了 EVM 代码大小、代码偏移量(PC)和跳转偏移量适合 16 位值的实用特性。

动机

在合约创建期间,客户端必须在执行前对 initcode 执行 jumpdest-analysis。所执行的工作量与 initcode 的大小呈线性关系。这项工作目前既未被计量,也没有协议强制规定其大小上限。

目前有三种费用:

  1. calldata(即 initcode)的费用:零值字节为 4 gas,其他为 16 gas。
  2. 生成的部署代码的费用:每字节 200 gas。
  3. 仅在 CREATE2 情况下,地址计算(代码哈希)的费用:每字 6 gas。

只有第一项费用适用于 initcode,但仅限于合约创建交易。对于 CREATE/CREATE2 的情况,没有此类费用,并且可以相对廉价地以编程方式生成 initcode 的变体。过去,由于 geth 1.6.5 在 2017 年修复的一个漏洞,有可能制造恶意的 initcode

此外,缺乏限制导致了一些 EVM 提案的漫长讨论,影响了设计,甚至导致某个功能的延迟或取消。

我们的动机有三个原因:

  1. 确保 initcode 公平收费(最重要的是成本与 initcode 的长度成比例),以最大程度地降低未来的风险。
  2. 拥有一个未来可扩展的成本系统。
  3. 通过明确的限制(代码大小、代码偏移量(PC)和跳转偏移量适合 16 位)来简化 EVM 引擎。

规范

参数

常量
INITCODE_WORD_COST 2
MAX_INITCODE_SIZE 2 * MAX_CODE_SIZE

其中 MAX_CODE_SIZEEIP-170 定义为 24576

我们将 initcode_cost(initcode) 定义为等于 INITCODE_WORD_COST * ceil(len(initcode) / 32)

规则

  1. 如果创建交易中的交易数据(initcode)长度超过 MAX_INITCODE_SIZE,则交易无效。(注意:这类似于因不满足固有 gas 成本要求而被视为无效的交易。)
  2. 对于创建交易,扩展交易数据成本公式以包含 initcode_cost(initcode)。(注意:这包含在交易固有成本中,即 gas 不足以支付 initcode 成本的交易无效。)
  3. 如果 CREATECREATE2 指令的 initcode 长度超过 MAX_INITCODE_SIZE,则指令执行异常中止(如同 gas 耗尽)。
  4. 对于 CREATECREATE2 指令,额外收取等于 initcode_cost(initcode) 的 gas 费用。此费用在计算生成的合约地址和执行 initcode 之前扣除。(注意:这意味着在 CREATE2 中应用哈希成本之前或同时。)

原理

Gas 成本常数

INITCODE_WORD_COST 的值是根据不同实现的最坏情况性能基准选择的。基准是 geth 1.10.9 中 KECCAK256 哈希的性能,它在 4.0 GHz x86_64 CPU 上符合 70 Mgas/s 的 gas 限制目标。

EVM 版本 MB/s B/CPUcycle CPUcycle/B 1 B 的成本 32 B 的成本
geth/KECCAK256 1.10.9 357 1.8 0.6 0.2 6.0
geth 1.10.9 1091 5.5 0.2 0.1 2.0
evmone/Baseline 0.8.2 727 3.7 0.3 0.1 2.9
evmone/Advanced 0.8.2 155 0.8 1.3 0.4 13.8

每字(32 字节块)的 Gas 成本

我们选择每字 2 gas 的成本是基于 Geth 的实现并与 KECCAK256 性能进行比较。这意味着每字节成本为 0.0625。虽然 EVM 不允许分数 gas 成本,但我们可以通过按字收费来近似。

此外,按字计算 gas 与 EIP-1014CREATE2哈希成本 计算兼容。因此,CREATECREATE2 可以使用相同的实现,但成本常数不同:激活前 CREATE0CREATE26;激活后 CREATE2CREATE26 + 2

initcode 大小限制的原因

在有上限的情况下,估计和创建最坏情况场景更容易,因为搜索的一个参数大大减少了。这允许选择更乐观的每字节 gas。

如果不存在上限,则成本需要更高,以应对未知因素。鉴于大多数 initcode待办:在此处说明主网上看到的导致部署的最大 initcode 大小)不超过建议的限制,通过过于保守的成本来惩罚合约似乎没有必要。

initcode 大小限制的影响

在大多数(如果不是所有)新合约创建的情况下,生成的运行时代码是从 initcode 本身复制的。对于基本情况,2 * MAX_CODE_SIZE 限制允许 MAX_CODE_SIZE 用于运行时代码,另一个 MAX_CODE_SIZE 用于合约构造函数代码。然而,对于在一个创建交易中部署多个合约的情况,该限制可能具有实际影响。

创建交易的 Initcode 成本

创建交易数据(每字节 0.0625 gas)的 initcode 成本与交易数据成本(每字节 4 或 16 gas)相比可忽略不计。尽管如此,我们决定将其包含在规范中以保持一致性,更重要的是为了向前兼容。

如何报告 initcode 限制违规?

我们规定 CREATE/CREATE2 的 initcode 大小限制违规会导致执行异常中止。这将其归入早期 out-of-gas 检查的组,包括:堆栈下溢、内存扩展、静态调用违规、initcode 哈希成本以及本 EIP 引入的 initcode 成本。它们先于后面的“轻量级”检查:调用深度和余额。这种选择为检查顺序提供了一致性,并降低了实现复杂性(out-of-gas 检查可以按任何顺序执行)。

向后兼容性

此 EIP 需要“网络升级”,因为它修改了共识规则。

已部署的合约不应受影响,但某些交易(initcode 超出建议限制的交易)仍可包含在区块中,但会导致异常中止。

测试用例

测试应包含以下情况:

  • 具有足够 gas 限制以覆盖 initcode 成本的创建交易
  • 具有足够 gas 限制但不足以覆盖 initcode 成本的固有成本的创建交易
  • CREATE/CREATE2/创建交易,其中 len(initcode) 等于 MAX_INITCODE_SIZE
  • CREATE/CREATE2/创建交易,其中 len(initcode) 等于 MAX_INITCODE_SIZE+1

安全考虑

对于客户端实现,此 EIP 使基于 jumpdest-analysis 的攻击问题减少,因此应提高客户端的鲁棒性

对于 Layer 2,此 EIP 引入了以前不存在的失败模式。可能存在部署多层合约层次结构的工厂合约,使得多个合约的代码包含在第一个合约的 initcode 中。本 EIP 的作者不了解任何此类合约。

目前,在 London 升级后,如果 gas 限制为 30M,则可能触发总计 ~1.3GB initcode 的 jumpdest-analysis。通过此 EIP,此类攻击的成本将增加约 80M gas。

版权

版权及相关权利通过 CC0 放弃。

  • 原文链接: github.com/nerolation/EI...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Nerolation
Nerolation
江湖只有他的大名,没有他的介绍。