Alert Source Discuss
⚠️ Draft Standards Track: Core

EIP-7519: 原子存储操作 SCREDIT 和 SDEBIT

添加用于增加和减少存储槽的原子操作

Authors Danno Ferrin (@shemnon)
Created 2023-09-16
Discussion Link https://ethereum-magicians.org/t/eip-7519-atomic-storage-operations-scredit-and-sdebit/15818
Requires EIP-2200, EIP-2929

摘要

提出了两个新的操作码,用于原子性地改变智能合约存储: SCREDIT,它按指定值增加存储槽;以及 SDEBIT,它按指定值 减少存储槽。强制执行溢出和下溢错误,当无符号 256 位整数将溢出或 下溢时,会回退。

动机

在多条链上的并行 EVM 方面已经投入了大量的精力,但是 EVM 内部缺乏并行原语来支持 除乐观并发控制(OCC)之外的任何模型。通过添加并发的 增加和减少操作,可以在 Layer 2 网络中引入更高级的并行环境。

这也提供了服务于增加和减少的主要用例的机会:代币余额。我们可以在溢出和 下溢条件下引入失败,并提供一种在并行用例之外也有用的操作。

规范

将引入两个原子性地增加和减少存储的操作, 位于 0xTBD。每个操作都接受两个堆栈参数,并且没有立即数参数。Gas 消耗计划将与 SSTORE 相同。

助记符 Op 输入 输出
SCREDIT 0xTBD 2 0
SDEBIT 0xTBD+1 2 0

SCREDIT

SCREDIT: slot, value

描述

value 加到合约存储 slot 中存储的值。如果发生溢出, 则操作异常中止。

Gas 消耗

Gas 消耗与 SSTORE 完全相同,包括与热存储槽列表的交互。 未来对 SSTORE gas 消耗的任何修改也将适用于 SCREDIT。

执行

非有效的 python,还不适合 EELS

slot = evm_stack.pop()
value = evm_stack.pop()

storage_value = read_contract_storage(slot)
storage_value = storage_value + value

if storage_value >= 2**256 :
  raise Exception("scredit overflow")
 
write_contract_storage(storage_value)

SDEBIT

SDEBIT: slot, value

描述

从合约存储 slot 中存储的值中减去 value。如果发生 下溢,则操作异常中止。

Gas 消耗

Gas 消耗与 SSTORE 完全相同,包括与热存储槽列表的交互。 未来对 SSTORE gas 消耗的任何修改也将适用于 SDEBIT。

执行

非有效的 python,还不适合 EELS

slot = evm_stack.pop()
value = evm_stack.pop()

storage_value = read_contract_storage(slot)
storage_value = storage_value - value

if storage_value < 0 :
  raise Exception("sdebit underflow")
 
write_contract_storage(storage_value)

理由

在选择替代方案时,主要考虑因素是主要目标受众是代币合约和其他资产跟踪合约, 以及希望发布最少的必要更改以启用该用例。通用并发控制不是此 EIP 的目标。

强制执行溢出语义

当允许乱序执行时,需要一种机制来处理任何可能的执行顺序。 OCC 通过验证前置和后置条件来处理此问题,如果这些不变量不成立,则重新评估交易。 这种技术在写入余额和计数器时会失效。

具有回滚检查的递增/递减允许简单地处理余额和计数器,同时允许功能性读取支持, 确保存在足够的余额或计数,而无需依赖确切的值。这允许评估模型, 其中唯一检查的后置条件是验证存储槽是否可以处理所有可能的交易重新排序。

Gas 消耗计划

将操作的成本设置为与 SSTORE 完全相同的值的决定,部分是为了易于实现, 部分是为了激励编译器和开发人员。

这些语义今天可以在 EVM 中实现,但它也需要包括 SLOAD、DUP、LT、JUMPI 和 REVERT 指令。 然而,EVM 可以比通过操作码更有效地完成这些操作。首先,每个 SSTORE 总是会产生一个槽加载, 以便应用 EIP-2200 gas 计算规则。如果没有配对的 SLOAD,则此加载至关重要。 如果 256 位数字的数学库尚未存在,则可以很容易地使其对溢出和下溢敏感。 条件逻辑处理在操作逻辑中也更快,因为大多数开销将是操作解析和堆栈 管理(当解释时)。

对最昂贵的评估(ADD 和 LT 操作,高于普通 SSTORE 的成本)的最相关操作的净影响将是 4 gas,或当前 SSTORE 成本的 0.2%。最后,数据库访问成本在操作的实际成本中占主导地位。 0.2% 的开销可能会在 I/O 停顿中消失。

保持成本相同使得 gas 消耗的实现非常简单。

仅限存储槽

此 EIP 最重要的用例是资产余额,而不是通用并发控制。因此, 仅对存储槽启用 credit 和 debit 操作(这些操作在事务之间持续存在)。 事务内的并行执行以及更通用的工具(如锁和信号量)在此范围内用途非常有限。 事务内并行执行的缺乏也排除了针对瞬态存储使用此类原语(如 EIP-1153 中定义的那样)。

操作码而不是系统合约

一种替代方案,特别适用于 Layer 2 链,是将 SCREDIT 和 SDEBIT 实现为系统合约。 对其他操作使用系统合约的主要反对意见是构建调用的 gas 成本开销。 因为 SSTORE 总是大于调用的成本,所以可以内置折扣。但是,对于调用此类调用所需的代码大小, 无法进行此类调整。

向后兼容性

这些操作码不是 SLOAD-(ADD SUB)-SSTORE 序列的简单替代品,因为存在溢出/下溢检查。

此提案不会删除任何 EVM 功能。

测试用例

测试以下值以及之前和之后的值的溢出和非溢出:

1, 2^8, 2^16, 2^32, 2^64, 2^128 2^255, 2^256-1.

参考实现

/# TBD

安全考虑

使用 revert 来处理溢出/下溢表示一种新的停止条件,审核员在检查重入问题时需要考虑。

版权

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

Citation

Please cite this document as:

Danno Ferrin (@shemnon), "EIP-7519: 原子存储操作 SCREDIT 和 SDEBIT [DRAFT]," Ethereum Improvement Proposals, no. 7519, September 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7519.