DCIPs/EIPS/eip-6466.md

8.2 KiB

eip title description author discussions-to status type category created requires
6466 SSZ Receipts Root Migration of receipts MPT commitment to SSZ Etan Kissling (@etan-status), Vitalik Buterin (@vbuterin) https://ethereum-magicians.org/t/eip-6466-ssz-receipts-root/12884 Draft Standards Track Core 2023-02-08 155, 658, 1559, 2718, 2930, 4844, 6404, 6475

Abstract

This EIP defines a migration process of existing Merkle-Patricia Trie (MPT) commitments for receipts to Simple Serialize (SSZ)

Motivation

While the consensus ExecutionPayloadHeader and the execution block header map to each other conceptually, they are encoded differently. This EIP aims to align the encoding of the receipts_root, taking advantage of the more modern SSZ format. This brings several advantages:

  1. Better for light clients: Light clients no longer need to obtain and decode entire receipts to verify receipt related fields provided by the execution JSON-RPC API.

  2. Better for smart contracts: The SSZ format is optimized for production and verification of merkle proofs. It allows proving specific fields of containers and allows chunked processing, e.g., to support handling receipts with lots of logs.

  3. Reducing complexity: The proposed design reduces the number of use cases that require support for Merkle-Patricia Trie (MPT).

Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Existing definitions

Definitions from existing specifications that are used throughout this document are replicated here for reference.

Name SSZ equivalent
ExecutionAddress Bytes20
TransactionType uint8
Name Value
BYTES_PER_LOGS_BLOOM uint64(2**8) (= 256)
MAX_TRANSACTIONS_PER_PAYLOAD uint64(2**20) (= 1,048,576)

Normalized Receipt representation

A Receipt SSZ container is introduced to represent receipts. The definition uses the Optional[T] SSZ type as defined in EIP-6475.

Name SSZ equivalent
Topic Bytes32
Name Value Notes
MAX_TOPICS_PER_LOG uint64(2**2) (= 4) LOG0 through LOG4 opcodes allow 0-4 topics per log
MAX_LOG_DATA_SIZE uint64(2**24) (= 16,777,216) Recommended devp2p soft limit for entire receipt: 2 MiB
MAX_LOGS_PER_RECEIPT uint64(2**20) (= 1,048,576) Same scaling factor as MAX_TRANSACTIONS_PER_PAYLOAD
class ReceiptLog(Container):
    address: ExecutionAddress
    topics: List[Topic, MAX_TOPICS_PER_LOG]
    data: ByteVector[MAX_LOG_DATA_SIZE]

class Receipt(Container):
    status: uint256  # EIP-658
    cumulative_gas_used: uint64
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    logs: List[ReceiptLog, MAX_LOGS_PER_RECEIPT]
    tx_type: TransactionType
    cumulative_data_gas_used: Optional[uint64]

Consensus ExecutionPayload building

When building a consensus ExecutionPayload, the receipts_root is now based on the normalized Receipt SSZ container. Implementations that currently produce receipts in the EIP-2718 format can convert them using the normalize_receipt helper function.

Consensus ExecutionPayload changes

The consensus ExecutionPayload's receipts_root now refers to an SSZ Root instead of an MPT Hash32.

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

To compute the receipts_root, the list of individual Receipt containers is represented as an SSZ List.

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

payload.receipts_root = receipts.hash_tree_root()

Consensus ExecutionPayloadHeader changes

The consensus ExecutionPayloadHeader is updated for the new ExecutionPayload.receipts_root definition.

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

Execution block header changes

The execution block header's receipts-root is updated to match the consensus ExecutionPayloadHeader.receipts_root.

Networking

The recover_encoded_receipt helper function recovers a receipt's original representation for exchange through the devp2p Receipts message.

Rationale

Should computed transaction fields be included?

The EIP-6404 Transaction SSZ container defines computed fields that are derived from a transaction's original representation. Namely, the tx_hash and tx_from fields, and also tx_to for DESTINATION_TYPE_CREATE. Arguments could be made to move them to the Receipt SSZ container.

While moving the fields would simplify consensus ExecutionPayload a bit, those fields do not fit the semantics of a receipt describing a transaction's outcome after being applied to a state. The fields can be computed without access to a state. Furthermore, for SSZ transactions, the tx_hash and sig_hash are implicitly available as part of their original representation. Having those hashes in the transaction representation further suggests that they should not be copied into the receipt.

What about ReceiptLog data?

ReceiptLog data is formatted according to the Ethereum contract ABI. Merkleizing log data according to its original structure would be more useful than merkleizing it as a ByteVector. However, the data structure is determined by the log event signature, of which only the hash is known. As the hash preimages are erased from emitted EVM logs, it is not reliably possible to recover the original log event signature. Therefore, log data is provided as a ByteVector for now, with the option for a future EIP to extend it.

Backwards Compatibility

Applications that solely rely on the TypedReceipt RLP encoding but do not rely on the receipts_root commitment in the block header can still be used through a re-encoding proxy.

Applications that rely on the replaced MPT receipts_root in the block header can no longer find that information. Analysis is required whether affected applications have a migration path available to use the SSZ receipts_root instead.

Test Cases

TBD

Reference Implementation

TBD

Security Considerations

None

Copyright and related rights waived via CC0.