本文介绍了四条在EOF1引入的新指令:DATALOAD
、DATALOADN
、DATASIZE
和DATACOPY
,旨在对EOF容器的数据部分进行读取。新的指令设计遵循现有数据读取指令的模式,并在保持向后兼容的情况下,优化了数据的访问和复制方式。
引入了四条新指令,允许读取 EOF container 的数据部分:DATALOAD
将 32 字节字加载到栈中,DATALOADN
将 32 字节字加载到栈中,其中字由静态立即数参数地址指定,DATASIZE
加载数据部分大小,DATACOPY
将数据部分的一段复制到内存中。
代码与数据的清晰分离是 EOF1 的主要特性之一。数据部分可以包含任何内容,例如编译器的元数据,但为了使其对智能合约有用,EVM 必须具有允许从数据部分读取的指令。之前存在的用于字节码检查的指令(CODECOPY
、CODESIZE
等)在 EOF1 中已被弃用,无法用于该目的。
DATALOAD
、DATASIZE
、DATACOPY
指令模式遵循现有的读取其他类型数据的指令(即 returndata 和 calldata)的设计。
DATALOADN
是 DATALOAD
的优化版本,其中读取的数据偏移在编译时设置,因此不需要在运行时进行验证,这使得指令更便宜。
我们在相同的区块号上引入四条新指令:EIP-3540 已激活:
DATALOAD
(0xd0)DATALOADN
(0xd1)DATASIZE
(0xd2)DATACOPY
(0xd3)如果代码是传统字节码,则所有这些指令将导致 异常停止。(注:这意味着行为没有变化。)
如果代码是有效的 EOF1,则适用以下执行规则:
DATALOAD
offset
。[offset:offset+32]
段,并将其作为 32 字节值推入栈中。offset + 32
大于数据部分的大小,将数据部分末尾之后的字节设置为 0。DATALOADN
offset
,编码为 16 位无符号大端值。[offset:offset+32]
段,并将其作为 32 字节值推入栈中。[offset:offset+32]
通过 代码验证 保证在数据边界范围内。
DATASIZE
DATACOPY
mem_offset
、offset
、size
。mem_offset + size
的内存扩展,并扣除内存扩展费用。3 + 3 * ((size + 31) // 32)
瓦特以进行复制。[offset:offset+size]
段,将其写入从 mem_offset
开始的内存中。offset + size
大于数据部分大小,数据部分末尾之后的字节将复制为 0 字节。我们扩展代码部分验证规则(如 EIP-3670 中定义)。
DATALOADN
的立即数参数 offset
使得 offset + 32
大于数据部分大小,则代码部分无效,这在部署前通过容器头指示。RJUMP
、RJUMPI
和 RJUMPV
立即数参数值(跳转目标相对偏移)验证:如果偏移指向 DATALOADN
指令后紧接着的两个字节中的一个,代码部分无效。现有用于读取其他类型数据的指令在超出边界访问时会隐式填充零值,唯一的例外是返回数据复制。
避免超出边界访问导致的异常失败是有利的,因为编译器可以使用优化来删除复制数据的代码,但从不访问此拷贝,而这种优化只有在指令没有其它副作用(例如异常中止)时才可能。
EXTDATACOPY
EXTCODECOPY
指令在 EOF 合约中被弃用和拒绝,并且在对传统合约的调用中,不会复制合约代码。当考虑到替代指令 EXTDATACOPY
时,决定不采用,以减少变更范围。
以前依赖 EXTCODECOPY
的仅数据合约因此受到抑制,但如果有强烈需求,可以通过在未来升级中引入 EXTDATACOPY
来轻松恢复对它们的支持。
此更改对向后兼容性没有风险,因为它仅为 EOF1 合约引入,而不允许部署未定义的指令,因此没有现有合约使用这些指令。新指令不针对传统字节码(未按 EOF 格式化的代码)引入。
待补充
版权和相关权利通过 CC0 放弃。
- 原文链接: github.com/ethereum/EIPs...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!