HomeEIPsNewsletter
EIPsEIP-6466
EIP-6466

SSZ receipts

Migration of RLP receipts to SSZ
DraftStandards Track: Core
Created: 2023-02-08
Requires: EIP-658, EIP-2718, EIP-6404, EIP-7702
Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Vitalik Buterin (@vbuterin)
Discussions ForumOriginal Proposal LinkEdit
1 min read

EIP-6466 proposes a migration process of existing Merkle-Patricia Trie (MPT) commitments for receipts to Simple Serialize (SSZ) in Ethereum. This aligns the encoding of the receipts_root, taking advantage of the more modern SSZ format, which brings several benefits such as better support for light clients and smart contracts, and reducing complexity. ReceiptLog data is formatted according to the Ethereum contract ABI, and log data is provided as a ByteVector for now, with the option for a future EIP to extend it. The proposal includes information on backwards compatibility, test cases, and a reference implementation.

Video
Anyone may contribute to propose contents.
Go propose
Original

Abstract

This EIP defines a migration process of EIP-2718 Recursive-Length Prefix (RLP) receipts to Simple Serialize (SSZ)

Motivation

RLP receipts have a number of shortcomings:

  1. Limited proving support: Due to receipt data being linearly hashed as part of the receipts_root Merkle-Patricia Trie (MPT), it is not possible to efficiently proof individual parts of receipts, such as logs. Requiring the full receipt data to be present can be prohibitive for smart contract based applications such as L2 fraud proofs or client applications verifying log data.

  2. Unnecessary statefulness: EIP-658 replaced the intermediate post-state root from receipts with a boolean status code. However, cumulativeGasUsed is similarly stateful, unnecessarily complicating efforts to execute transactions in parallel. Furthermore, multiple receipts are required to verify the effective gas used by an individual transaction.

  3. Incomplete data: JSON-RPC provides from, gasUsed, and contractAddress fields for receipts, but the on-chain receipt does not contain the required information to verify them.

  4. Inefficient logs bloom: The logs bloom mechanism is inefficient due to its high false positive rate. It does not find enough practical use to warrant its high storage requirement, and should be removed.

This EIP defines a universal receipt format based on SSZ to address these concerns.

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.

NameValue
MAX_TRANSACTIONS_PER_PAYLOADuint64(2**20) (= 1,048,576)
MAX_AUTHORIZATION_LIST_SIZEuint64(2**16) (= 65,536)
SSZ_TX_TYPE0x1f
NameSSZ equivalent
RootBytes32
ExecutionAddressBytes20
GasAmountuint64

Receipt container

All receipts are represented as a single, normalized SSZ container. The definition uses the StableContainer[N] SSZ type and Optional[T] as defined in EIP-7495.

NameValueDescription
MAX_TOPICS_PER_LOG4LOG0 through LOG4 opcodes allow 0-4 topics per log
MAX_LOG_DATA_SIZEuint64(2**24) (= 16,777,216)Maximum data byte length for a log
MAX_LOGS_PER_RECEIPTuint64(2**21) (= 2,097,152)Maximum number of entries within logs
MAX_RECEIPT_FIELDSuint64(2**5) (= 32)Maximum number of fields to which Receipt can ever grow in the future
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 construction

Receipts are constructed as follows.

FieldDescription
fromThe transaction sender's address
gas_usedHow much gas this individual transaction used. Replaces cumulative_gas_used
contract_addressFor transactions deploying a contract, the new contract address
logsLogs emitted during transaction execution
statusEIP-658 transaction status code
authoritiesFor transactions with an authorization list, the list of EIP-7702 authority addresses. Non-successful authorizations are represented with an all-zero address

The logs_bloom and intermediate state root (Homestead scheme) are not present in SSZ receipts.

Execution block header changes

The execution block header's receipts-root is transitioned from MPT to 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

Transaction receipt objects in the context of the JSON-RPC API are extended to include:

  • authorities: Array of DATA|null - 0 through MAX_AUTHORIZATION_LIST_SIZE DATA entries each containing 20 Bytes, corresponding to the receipt's authorities field

The logsBloom field is no longer returned for new receipts. It continues to be returned for historical receipts conforming to earlier schemes.

from, gasUsed, and contractAddress are already provided via JSON-RPC and are left unchanged.

Consensus ExecutionPayload changes

When building a consensus ExecutionPayload, the receipts_root is now based on the Receipt type, changing the type of receipts_root from an MPT Hash32 to an SSZ Root.

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

Networking

When exchanging SSZ receipts via the Ethereum Wire Protocol, the following EIP-2718 compatible envelope is used:

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

Objects are encoded using SSZ and compressed using the Snappy framing format, matching the encoding of consensus objects as defined in the consensus networking specification. As part of the encoding, the uncompressed object length is emitted; the RECOMMENDED limit to enforce per object is MAX_CHUNK_SIZE bytes.

Rationale

Switching to a single, unified and forward compatible receipt format within execution blocks reduces implementation complexity for client applications and smart contracts. Individual chunks of receipt data can now be verified, simplifying implementation of bridges.

Light clients can now efficiently verify a receipt's from, gas_used, and authorities, which previously required obtaining the corresponding transaction data and additional receipts. Execution layer implementations no longer have to compute signer addresses using the expensive ecrecover mechanism when backfilling / serving historical receipt data.

Removal of logs_bloom reduces storage cost for receipts by 259 bytes per receipt.

Backwards Compatibility

Applications that rely on the replaced MPT receipts_root in the block header require migration to the SSZ receipts_root.

Applications using verified cumulativeGasUsed values have to compute the value from prior receipts.

Applications relying on the logsBloom will have to swap to an out-of-protocol mechanism for filtering logs, or fall back to processing the complete set of receipts. As the logsBloom mechanism was prohibitively inefficient for light clients, its removal is unlikely to have a significant impact.

Security Considerations

None

Copyright and related rights waived via CC0.

Further reading
Anyone may contribute to propose contents.
Go propose

Not miss a beat of EIPs' update?

Subscribe EIPs Fun to receive the latest updates of EIPs Good for Buidlers to follow up.

View all
Serve Ethereum Builders, Scale the Community.
Resources
GitHub
Supported by