Alert Source Discuss
Standards Track: Core

EIP-2930: 可选访问列表

Authors Vitalik Buterin (@vbuterin), Martin Swende (@holiman)
Created 2020-08-29
Requires EIP-2718, EIP-2929

简单总结

添加一种包含访问列表的交易类型,该列表包含交易计划访问的地址和存储键的列表。列表之外的访问是可能的,但会变得更加昂贵。

摘要

我们引入了一种新的 EIP-2718 交易类型,格式为 0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])

accessList 指定了一个地址和存储键的列表;这些地址和存储键被添加到 accessed_addressesaccessed_storage_keys 全局集合中(在 EIP-2929 中引入)。会收取一定的 gas 费用,但相对于在列表之外访问的成本而言,会有折扣。

动机

这个 EIP 有两个作用:

  1. 缓解了 EIP-2929 引入的合约破坏风险,因为交易可以预先指定和预先支付交易计划访问的账户和存储槽;因此,在实际执行中,SLOADEXT* 操作码只会花费 100 gas:这已经足够低,不仅可以防止由于该 EIP 造成的破坏,还可以“解除”由于 EIP 1884 而卡住的任何合约。
  2. 引入访问列表格式和处理该格式的逻辑。这种逻辑以后可以用于许多其他目的,包括全区块见证、在 ReGenesis 中使用、随着时间的推移转向静态状态访问等等。

规范

定义

TransactionType 1。参考 EIP-2718

ChainId 交易仅在具有此 chainID 的网络上有效。

YParity secp256k1 签名 y 值的奇偶校验(偶数为 0,奇数为 1)。

参数

常量
FORK_BLOCK 12244000
ACCESS_LIST_STORAGE_KEY_COST 1900
ACCESS_LIST_ADDRESS_COST 2400

FORK_BLOCK_NUMBER 开始,引入了一个新的 EIP-2718 交易,其 TransactionType1

此交易的 EIP-2718 TransactionPayloadrlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])

此交易的 signatureYParity, signatureR, signatureS 元素表示对 keccak256(0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList])) 的 secp256k1 签名。

此交易的 EIP-2718 ReceiptPayloadrlp([status, cumulativeGasUsed, logsBloom, logs])

为了使交易有效,accessList 必须是 [[{20 bytes}, [{32 bytes}...]]...] 类型,其中 ... 表示“左侧事物的零个或多个”。例如,以下是一个有效的访问列表(所有十六进制字符串实际上都是字节表示):

[
    [
        "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
        [
            "0x0000000000000000000000000000000000000000000000000000000000000003",
            "0x0000000000000000000000000000000000000000000000000000000000000007"
        ]
    ],
    [
        "0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
        []
    ]
]

在执行开始时(即,与根据 EIP-2028 规则收取 21000 + 4 * zeroes + 16 * nonzeroes 启动 gas 的同时),我们会为访问列表收取额外的 gas:每个地址 ACCESS_LIST_ADDRESS_COST gas 和每个存储键 ACCESS_LIST_STORAGE_KEY_COST gas。例如,上面的示例将被收取 ACCESS_LIST_ADDRESS_COST * 2 + ACCESS_LIST_STORAGE_KEY_COST * 2 gas。

请注意,不允许非唯一地址和存储键,尽管它们将被多次收费,并且除了更高的 gas 成本外,多次包含一个值与推荐的单次包含在执行流程或结果上没有其他区别。

地址和存储键将立即加载到 accessed_addressesaccessed_storage_keys 全局集合中;这可以使用以下逻辑完成(该逻辑兼作 RLP 解码访问列表的规范代码):

def process_access_list(access_list) -> Tuple[List[Set[Address], Set[Pair[Address, Bytes32]]], int]:
    accessed_addresses = set()
    accessed_storage_keys = set()
    gas_cost = 0
    assert isinstance(access_list, list)
    for item in access_list:
        assert isinstance(item, list) and len(item) == 2
        # 验证并添加地址
        address = item[0]
        assert isinstance(address, bytes) and len(address) == 20
        accessed_addresses.add(address)
        gas_cost += ACCESS_LIST_ADDRESS_COST
        # 验证并添加存储键
        assert isinstance(item[1], list)
        for key in item[1]:
            assert isinstance(key, bytes) and len(key) == 32
            accessed_storage_keys.add((address, key))
            gas_cost += ACCESS_LIST_STORAGE_KEY_COST
    return (
        accessed_addresses,
        accessed_storage_keys,
        gas_cost
    )

访问列表不收取像交易数据那样的每字节费用;上面描述的每项成本旨在涵盖访问列表数据的带宽成本,以及评估交易时访问这些帐户和存储键的成本。

理由

为访问列表中访问收取较少的费用

这样做是为了鼓励交易尽可能多地使用访问列表,并且当交易的存储读取是可预测时,处理交易更容易(因为客户端可以从数据库预加载数据和/或在收到交易时请求见证,或者至少在收到区块时并行加载数据)。

允许重复

这样做是因为它最大限度地提高了简单性,避免了诸如针对什么来防止重复的问题:仅仅是访问列表中的两个地址/键之间,访问列表和交易发送者/接收者/新创建的合约之间,其他限制?由于 gas 是按项目收费的,因此在访问列表中包含两次值没有收益,只有成本,因此这在实践中不应导致额外的链膨胀。

签名对交易类型以及交易数据进行签名

这样做是为了确保交易不能被“重新解释”为不同类型的交易。

向后兼容性

这个 EIP 确实使执行“意外”的 SLOAD 和帐户访问的 gas 成本更高。因为 gas 是预付的,所以不会影响固定 gas 的本地调用,所以它不会像以前的 gas 成本增加那样破坏合约。但是,它确实使严重依赖存储访问的应用程序在经济上变得不太可行。

安全考虑

访问列表生成

在许多情况下,访问列表很难实时构建,并且在交易生成和签名之间存在较高的时间延迟或者交易生成器的简单性受到高度重视的环境中,这种情况会更加严重(例如,两者都可能适用于硬件钱包)。

但是,此 EIP 仅建议对访问列表进行 10% 的初始折扣,因此不费心生成访问列表而仅进行简单的交易几乎没有成本。随着工具的开发和访问列表生成变得更加成熟,预计将来硬分叉中访问列表之外的状态的成本会随着时间的推移而逐步提高。

交易规模膨胀

由于访问列表的使用,平均区块大小将会增加。但是,存储键的每字节访问列表成本为 1900 / 32 = 59.375,地址的每字节访问列表成本为 2400 / 20 = 120,使其比 calldata 贵得多;因此,最坏情况下的区块大小不会增加。此外,平均区块大小的增加将部分地通过在接收交易时预取存储和/或在接收区块时并行加载存储的能力来弥补。

版权

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

Citation

Please cite this document as:

Vitalik Buterin (@vbuterin), Martin Swende (@holiman), "EIP-2930: 可选访问列表," Ethereum Improvement Proposals, no. 2930, August 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2930.