增加访问列表成本

该EIP提案旨在通过对访问列表(Access List)的数据足迹进行收费,以防止绕过EIP-7623设定的数据地板价。此举通过将访问列表数据计入总数据Token和地板价计算,确保了所有交易数据来源定价的一致性,有效降低了最坏情况下的区块大小约21%。

markdown

摘要

此 EIP 根据数据占用量向访问列表收费,防止规避 EIP-7623 的最低定价。通过对用户影响最小化,这有效地将最坏情况下的区块大小减少约21%。

动机

访问列表只为存储付费,而不为其数据付费。

此外,访问列表可以通过贡献 EVM gas 来规避 EIP-7623 的最低定价,同时仍然留下不可忽略的数据占用。这使得通过以一定比例结合访问列表和 calldata 来实现最大可能的区块大小成为可能。

规范

Parameter Value Source
ACCESS_LIST_ADDRESS_COST 2400 EIP-2930
ACCESS_LIST_STORAGE_KEY_COST 1900 EIP-2930
TOTAL_COST_FLOOR_PER_TOKEN 10 EIP-7623

$access\_list\_nonzero\_bytes$$access\_list\_zero\_bytes$ 分别为访问列表中包含的地址(每个20字节)和存储键(每个32字节)中的非零字节和零字节的数量。

$tokens\_in\_access\_list = access\_list\_zero\_bytes + access\_list\_nonzero\_bytes * 4$

访问列表的成本公式从 EIP-2930 更改为包含数据成本:

access_list_cost = (
    ACCESS_LIST_ADDRESS_COST * access_list_addresses
    + ACCESS_LIST_STORAGE_KEY_COST * access_list_storage_keys
    + TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_access_list
)

EIP-7623 的最低计算方式被修改为包含访问列表的 token:

tokens_in_calldata = zero_bytes_in_calldata + nonzero_bytes_in_calldata * 4
total_data_tokens = tokens_in_calldata + tokens_in_access_list

data_floor_gas_cost = TX_BASE_COST + TOTAL_COST_FLOOR_PER_TOKEN * total_data_tokens

使用的 gas 计算变为:

tx.gasUsed = (
    21000
    +
    max(
        STANDARD_TOKEN_COST * tokens_in_calldata
        + execution_gas_used
        + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata))
        + access_list_cost,
        TOTAL_COST_FLOOR_PER_TOKEN * total_data_tokens
    )
)

任何 gas 限制低于 $21000 + TOTAL\_COST\_FLOOR\_PER\_TOKEN * total\_data\_tokens$ 或低于其 $intrinsic\_gas\_cost$ 的交易都将被视为无效。

原理

访问列表数据总是按最低费率收费(加入到 $access\_list\_cost$ 中),并且访问列表 token 被包含在最低计算中。这确保了:

  • 访问列表数据无论执行级别如何,都始终支付最低费率
  • 访问列表不能用于绕过 calldata 的最低定价
  • 所有交易数据源的定价保持一致

向后兼容性

这是一个向后不兼容的 gas 重新定价,需要进行计划的网络升级。

需要更新钱包和节点中的 gas 估算。正常使用模式基本不受影响。

参考实现

def calculate_access_list_tokens(access_list: Tuple[Access, ...]) -> Uint:
    """计算访问列表地址和存储键中的数据 token。"""
    zero_bytes = Uint(0)
    nonzero_bytes = Uint(0)

    for access in access_list:
        for byte in access.account:
            if byte == 0:
                zero_bytes += Uint(1)
            else:
                nonzero_bytes += Uint(1)
        for slot in access.slots:
            for byte in slot:
                if byte == 0:
                    zero_bytes += Uint(1)
                else:
                    nonzero_bytes += Uint(1)

    return zero_bytes + nonzero_bytes * Uint(4)

def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
    """
    计算固有 gas 成本和最低 gas 成本。
    返回 (intrinsic_gas, floor_gas)。
    """
    # Calldata token
    calldata_zero_bytes = Uint(0)
    for byte in tx.data:
        if byte == 0:
            calldata_zero_bytes += Uint(1)
    tokens_in_calldata = (
        calldata_zero_bytes + (ulen(tx.data) - calldata_zero_bytes) * Uint(4)
    )

    # 访问列表 token 和成本
    tokens_in_access_list = Uint(0)
    access_list_cost = Uint(0)
    if has_access_list(tx):
        tokens_in_access_list = calculate_access_list_tokens(tx.access_list)
        for access in tx.access_list:
            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
            access_list_cost += ulen(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST
        # EIP-7981: 始终收取数据成本
        access_list_cost += tokens_in_access_list * TOTAL_COST_FLOOR_PER_TOKEN

    # EIP-7981: 最低成本包含所有数据 token
    total_data_tokens = tokens_in_calldata + tokens_in_access_list
    floor_gas = TX_BASE_COST + total_data_tokens * TOTAL_COST_FLOOR_PER_TOKEN

    # 固有 gas
    calldata_cost = tokens_in_calldata * STANDARD_TOKEN_COST
    create_cost = TX_CREATE_COST + init_code_cost(tx.data) if is_create(tx) else Uint(0)

    intrinsic_gas = TX_BASE_COST + calldata_cost + create_cost + access_list_cost

    return intrinsic_gas, floor_gas

安全考虑

此 EIP 堵塞了一个允许规避 EIP-7623 最低定价的漏洞。如果没有此修复,攻击者可以通过将访问列表与 calldata 结合起来实现超出预期的更大区块。现在所有交易数据源都一致地参与最低计算。

版权

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

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

0 条评论

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