Alert Source Discuss
⚠️ Draft Standards Track: Core

EIP-6466: SSZ 回执

将 RLP 回执迁移到 SSZ

Authors Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Vitalik Buterin (@vbuterin)
Created 2023-02-08
Discussion Link https://ethereum-magicians.org/t/eip-6466-ssz-receipts/12884
Requires EIP-658, EIP-2718, EIP-6404, EIP-7702

摘要

本 EIP 定义了将 EIP-2718 递归长度前缀 (RLP) 回执迁移到 Simple Serialize (SSZ) 的过程。

动机

RLP 回执存在许多缺点:

  1. 有限的证明支持: 由于回执数据在线性哈希后作为 receipts_root Merkle-Patricia Trie (MPT) 的一部分,因此无法有效地证明回执的各个部分,例如日志。 需要提供完整的回执数据对于基于智能合约的应用程序(如 L2 欺诈证明或验证日志数据的客户端应用程序)来说可能代价过高。

  2. 不必要的有状态性: EIP-658 将回执中的中间后状态 root 替换为布尔值 status 代码。 但是,cumulativeGasUsed 同样是有状态的,不必要地复杂化了并行执行交易的工作。 此外,验证单个交易使用的有效 gas 需要多个回执。

  3. 不完整的数据: JSON-RPC 为回执提供 fromgasUsedcontractAddress 字段,但链上回执不包含验证它们所需的的信息。

  4. 低效的日志布隆: 由于其高误报率,日志布隆机制效率低下。它没有找到足够的实际用途来保证其高存储要求,应该删除。

本 EIP 定义了一种基于 SSZ 的通用回执格式,以解决这些问题。

规范

本文档中使用的关键词“必须(MUST)”、“禁止(MUST NOT)”、“必需(REQUIRED)”、“应(SHALL)”、“不应(SHALL NOT)”、“应该(SHOULD)”、“不应该(SHOULD NOT)”、“推荐(RECOMMENDED)”、“不推荐(NOT RECOMMENDED)”、“可以(MAY)”和“可选(OPTIONAL)”按照 RFC 2119 和 RFC 8174 中的描述进行解释。

现有定义

为了方便参考,此处复制了本文档中使用的现有规范中的定义。

名称
MAX_TRANSACTIONS_PER_PAYLOAD uint64(2**20) (= 1,048,576)
MAX_AUTHORIZATION_LIST_SIZE uint64(2**16) (= 65,536)
SSZ_TX_TYPE 0x1f
名称 SSZ 等效项
Root Bytes32
ExecutionAddress Bytes20
GasAmount uint64

Receipt 容器

所有回执都表示为单个标准化的 SSZ 容器。 该定义使用 EIP-7495 中定义的 StableContainer[N] SSZ 类型和 Optional[T]

名称 描述
MAX_TOPICS_PER_LOG 4 LOG0LOG4 操作码允许每个日志 0-4 个主题
MAX_LOG_DATA_SIZE uint64(2**24) (= 16,777,216) 日志的最大 data 字节长度
MAX_LOGS_PER_RECEIPT uint64(2**21) (= 2,097,152) logs 中的最大条目数
MAX_RECEIPT_FIELDS uint64(2**5) (= 32) Receipt 未来可能增长到的最大字段数
class Log(Container):
    address: ExecutionAddress
    topics: List[Bytes32, MAX_TOPICS_PER_LOG]
    data: ByteList[MAX_LOG_DATA_SIZE]

class StableReceipt(StableContainer[MAX_RECEIPT_FIELDS]):
    from_: Optional[ExecutionAddress]
    gas_used: Optional[GasAmount]
    contract_address: Optional[ExecutionAddress]
    logs: Optional[List[Log, MAX_LOGS_PER_RECEIPT]]

    # EIP-658
    status: Optional[boolean]

    # EIP-7702
    authorities: Optional[List[ExecutionAddress, MAX_AUTHORIZATION_LIST_SIZE]]

class Receipt(Profile[StableReceipt]):
    from_: ExecutionAddress
    gas_used: GasAmount
    contract_address: Optional[ExecutionAddress]
    logs: List[Log, MAX_LOGS_PER_RECEIPT]

    # EIP-658
    status: boolean

    # EIP-7702
    authorities: Optional[List[ExecutionAddress, MAX_AUTHORIZATION_LIST_SIZE]]

Receipt 构造

回执的构造方式如下。

字段 描述
from 交易发送者的地址
gas_used 此单个交易使用的 gas 量。 替换 cumulative_gas_used
contract_address 对于部署合约的交易,新的合约地址
logs 交易执行期间发出的日志
status EIP-658 交易状态代码
authorities 对于具有授权列表的交易,EIP-7702 authority 地址的列表。 不成功的授权用全零地址表示

SSZ 回执中不存在 logs_bloom 和中间状态 root(Homestead 方案)。

执行区块头部的变更

执行区块头部的 receipts-root 从 MPT 转换为 SSZ。

receipts = List[Receipt, MAX_TRANSACTIONS_PER_PAYLOAD](
    receipt_0, receipt_1, receipt_2, ...)

block_header.receipts_root = receipts.hash_tree_root()

JSON-RPC API

JSON-RPC API 上下文中的交易回执对象已扩展为包括:

  • authorities: Array of DATA|null - 0 到 MAX_AUTHORIZATION_LIST_SIZEDATA 条目,每个条目包含 20 字节,对应于回执的 authorities 字段

logsBloom 字段不再为新回执返回。 它继续为符合早期方案的历史回执返回。

fromgasUsedcontractAddress 已经通过 JSON-RPC 提供,并且保持不变。

共识 ExecutionPayload 变更

构建共识 ExecutionPayload 时,receipts_root 现在基于 Receipt 类型,从而将 receipts_root 的类型从 MPT Hash32 更改为 SSZ Root

class ExecutionPayload(Container):
    ...
    receipts_root: Root
    ...

class ExecutionPayloadHeader(Container):
    ...
    receipts_root: Root
    ...
payload_header.receipts_root = payload.receipts_root

网络

当通过 Ethereum Wire Protocol 交换 SSZ 回执时,使用以下 EIP-2718 兼容信封:

  • Receipt: SSZ_TX_TYPE || snappyFramed(ssz(Receipt))

对象使用 SSZ 进行编码,并使用 Snappy 帧格式进行压缩,这与 共识网络规范 中定义的共识对象的编码匹配。 作为编码的一部分,会发出未压缩的对象长度; 建议对每个对象强制执行的限制是 MAX_CHUNK_SIZE 字节。

理由

在执行区块中切换到单一、统一且向前兼容的回执格式降低了客户端应用程序和智能合约的实现复杂性。 现在可以验证回执数据的各个块,从而简化桥的实现。

轻客户端现在可以有效地验证回执的 fromgas_usedauthorities,这以前需要获取相应的交易数据和其他回执。 在回填/提供历史回执数据时,执行层实现不再需要使用昂贵的 ecrecover 机制来计算签名者地址。

删除 logs_bloom 减少了每个回执 259 字节的存储成本。

向后兼容性

依赖于区块头中已替换的 MPT receipts_root 的应用程序需要迁移到 SSZ receipts_root

使用已验证的 cumulativeGasUsed 值的应用程序必须从先前的回执中计算该值。

依赖于 logsBloom 的应用程序将不得不转换为协议外的机制来过滤日志,或者退回到处理完整的回执集。 由于 logsBloom 机制对于轻客户端来说效率极低,因此其删除不太可能产生重大影响。

安全注意事项

版权

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

Citation

Please cite this document as:

Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Vitalik Buterin (@vbuterin), "EIP-6466: SSZ 回执 [DRAFT]," Ethereum Improvement Proposals, no. 6466, February 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6466.