本文介绍了在以太坊虚拟机(EVM)中引入三条新的指令 SWAPN
、DUPN
和 EXCHANGE
以提升栈操作的灵活性,这三条指令允许访问深达256个项的栈,简化了编译器的设计,并支持更复杂的函数调用。文章详细阐述了这些新指令的规范、执行规则、兼容性及安全性考虑。
目前,SWAP*
和 DUP*
指令的堆栈深度限制为 16。引入三条新指令,SWAPN
、DUPN
和 EXCHANGE
,以消除此限制并允许在更高的深度访问堆栈。
虽然堆栈深度为 1024 项,但只能轻松访问顶部 16 项。通过手动将更多局部变量保留在内存中或通过编译器的“堆栈到内存提升”功能,可以支持更多局部变量。这可能导致复杂且低效的代码。
此外,在 EVM 上实现更高级的构造(例如函数)将导致输入和输出参数列表,以及返回的指令偏移量。
这些参数(或堆栈项)的数量可能轻易超过 16,因此可能需要编译器额外小心以确保它们都能被访问。
最后,交换堆栈中除第一个和第 N 项以外的项对实施堆栈调度算法的编译器非常重要(堆栈机器的寄存器分配类比),该算法在给定变量和使用分析的情况下试图最小化堆栈流量。
引入 SWAPN
、DUPN
和 EXCHANGE
将为编译器提供简化访问深层堆栈项的选项。
我们引入三条新指令:
DUPN
(0xe6
)SWAPN
(0xe7
)EXCHANGE
(0xe8
)如果代码是遗留字节码,这些指令中的任何一条都会导致 异常中止。 (注意:这意味着行为不变。)
如果代码是有效的 EOF1,适用以下规则:
imm
,其值可以为 0 到 255。
DUPN
和 SWAPN
的情况下,引入变量 n
等于 imm + 1
。EXCHANGE
的情况下,引入变量 n
等于 imm >> 4 + 1
,以及变量 m
等于 imm & 0x0F + 1
(即 imm
的前两个半字节,转换为一索引)。RJUMP
/RJUMPI
/RJUMPV
) 指向 DUPN
、SWAPN
或 EXCHANGE
的立即数值。DUPN
前,如果当前堆栈高度小于 n
,则代码无效。在 DUPN
后,堆栈高度增加。SWAPN
前,如果当前堆栈高度小于 n + 1
,则代码无效。在 SWAPN
后,堆栈高度不变。EXCHANGE
前,如果当前堆栈高度小于 n + m + 1
,则代码无效。在 EXCHANGE
后,堆栈高度不变。DUPN
:第 n
项堆栈项被复制到堆栈顶部。(注意:这里使用的是 1 基索引。)SWAPN
:第 n + 1
项堆栈项与堆栈顶部交换。EXCHANGE
:第 n + 1
项堆栈项与第 n + m + 1
项堆栈项交换。所有三条指令的 gas 成本设定为 3。
允许动态选择要交换、复制或交换的参数可能会阻止对堆栈内容的静态分析。由于静态分析是安全审计人员的重要工具,我们希望尽可能简化他们的工作。因此,操作数需要一个不是动态性质的立即数参数。
由于该指令依赖于立即数参数编码,因此只能在 EOF 内启用。在遗留字节码中,该编码可能会与跳转目标分析相矛盾。
对于 DUPN
和 SWAPN
,考虑使用 16 位大小以适应堆栈空间的 1024 项,但是:
n < 1024
)。对 EXCHANGE
同样,提议的方案允许寻址 32 项。
这些操作的 gas 成本与现有的 DUP*
和 SWAP*
指令相同,因为它们仅作为指针交换实现。
EXCHANGE
与 SWAPN
如前所述,EXCHANGE
对实现堆栈调度算法的编译器非常重要。具体而言,在堆栈项计划在堆栈更深处被消耗的情况下(例如,堆栈中的第 3 项需要移至第 2 个位置以供下一个操作使用),目前需要三条指令 SWAP2 SWAP3 SWAP2
。然而,在 EVM 实现中,该实现仅是一个指针交换,因此可以在没有额外运行时成本的情况下以一条指令实现。
这对向后兼容性没有影响,因为操作码之前未被分配,并且该功能仅在 EOF 中启用。
给定 stack[]
是一个以 0 为基础的数据结构,n
、m
和 imm
根据规范定义:
DUPN imm
在 stack_height < n
的情况下验证失败。SWAPN imm
在 stack_height < n + 1
的情况下验证失败。EXCHANGE imm
在 stack_height < n + m + 1
的情况下验证失败。DUPN imm
应增加函数的最大堆栈高度。如果最大堆栈高度超过 1023 的限制,则验证失败。DUPN imm
、SWAPN imm
和 EXCHANGE imm
在运行时如果可用的 gas 少于 3 则失败。DUPN imm
应复制 stack[n - 1]
项并将其推送到堆栈SWAPN imm
应交换 stack[n]
与 stack[stack.top()]
EXCHANGE imm
应交换 stack[n]
与 stack[n + m]
。作者未发现此处引入的任何附加风险。EVM 堆栈固定为 1024 项,大多数实现始终将其保存在内存中。这一变化将增加通过单一指令可访问的堆栈项数量。
由于 CC0,版权和相关权利已放弃。
- 原文链接: github.com/ethereum/EIPs...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!