Skip to content

Commit

Permalink
Update EIP-6404: Split RLP conversions and Receipt from EIP-6493
Browse files Browse the repository at this point in the history
EIP-6493 mixes the introduction of SSZ transactions converted from RLP
with native SSZ transactions, implying that the corresponding Receipt
definition and engine API changes also must be part of EIP-6493.

Splitting the RLP converted transactions into the other SSZ transaction
EIP-6404 achieves a clearer balance, and is also closer to practical
implementation order where an EL initially may choose to support only
RLP converted transactions before adding the native SSZ profiles.
  • Loading branch information
etan-status committed Sep 8, 2024
1 parent 226b17b commit b34f4d9
Show file tree
Hide file tree
Showing 12 changed files with 937 additions and 1,233 deletions.
366 changes: 339 additions & 27 deletions EIPS/eip-6404.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions EIPS/eip-6465.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ title: SSZ Withdrawals Root
description: Migration of withdrawals MPT commitment to SSZ
author: Etan Kissling (@etan-status), Mikhail Kalinin (@mkalinin)
discussions-to: https://ethereum-magicians.org/t/eip-6465-ssz-withdrawals-root/12883
status: Stagnant
status: Draft
type: Standards Track
category: Core
created: 2023-02-08
requires: 2718, 4895, 6493
requires: 2718, 4895, 6404
---

## Abstract
Expand Down Expand Up @@ -41,7 +41,7 @@ Definitions from existing specifications that are used throughout this document
| Name | Value |
| - | - |
| [`MAX_WITHDRAWALS_PER_PAYLOAD`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/capella/beacon-chain.md#execution) | `uint64(2**4)` (= 16) |
| [`TRANSACTION_TYPE_SSZ`](./eip-6493.md#eip-2718-transaction-types) | `0x04` |
| [`SSZ_TX_TYPE`](./eip-6404.md#networking) | `0x04` |

### SSZ `Withdrawal` container

Expand Down Expand Up @@ -95,7 +95,7 @@ typed-withdrawal = withdrawal-type || withdrawal-data

When exchanging SSZ withdrawals via the [Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/6b259a7003b4bfb18365ba690f4b00ba8a26393b/caps/eth.md), the following withdrawal envelope is used:

- `Withdrawal`: `TRANSACTION_TYPE_SSZ || snappyFramed(ssz(Withdrawal))`
- `Withdrawal`: `SSZ_TX_TYPE || snappyFramed(ssz(Withdrawal))`

Objects are encoded using [SSZ](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md) and compressed using the Snappy framing format, matching the encoding of consensus objects as defined in the [consensus networking specification](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/p2p-interface.md#ssz-snappy-encoding-strategy). As part of the encoding, the uncompressed object length is emitted; the RECOMMENDED limit to enforce per object is `8 + 8 + 20 + 8` (= 44) bytes.

Expand Down
116 changes: 91 additions & 25 deletions EIPS/eip-6466.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,121 @@
---
eip: 6466
title: SSZ Receipts Root
description: Migration of receipts MPT commitment to SSZ
title: SSZ Receipts
description: Migration of RLP receipts to SSZ
author: Etan Kissling (@etan-status), Vitalik Buterin (@vbuterin)
discussions-to: https://ethereum-magicians.org/t/eip-6466-ssz-receipts-root/12884
status: Stagnant
discussions-to: https://ethereum-magicians.org/t/eip-6466-ssz-receipts/12884
status: Draft
type: Standards Track
category: Core
created: 2023-02-08
requires: 6404, 6493
requires: 658, 6404
---

## Abstract

This EIP defines a migration process of existing Merkle-Patricia Trie (MPT) commitments for receipts to [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md)
This EIP defines a migration process of [EIP-2718](./eip-2718.md) Recursive-Length Prefix (RLP) receipts to [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md)

## Motivation

[EIP-6404](./eip-6404.md) introduces the more modern SSZ format to the `transactions_root` of the consensus `ExecutionPayloadHeader` and the execution block header. This EIP defines the equivalent transition for `receipts_root` to add support for [EIP-6493 `Receipt`](./eip-6493.md).
RLP receipts have a number of shortcomings:

Note that in contrast to the `transactions_root` which refers to a Merkle Patricia Trie (MPT) root in execution but to an SSZ root in consensus, the `receipts_root` is already consistent and refers to the same MPT root. With this EIP, it will be changed to consistently refer to the same SSZ root.
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](./eip-658.md) 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 `contractAddress` in the receipt for a transaction creating a new contract, but the receipt does not contain the required information to verify it. Workarounds that rely on also fetching the transaction data may not be future-proof.

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.

### Consensus `ExecutionPayload` changes
### Existing definitions

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

| Name | Value |
| - | - |
| [`MAX_TRANSACTIONS_PER_PAYLOAD`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#execution) | `uint64(2**20)` (= 1,048,576) |
| [`BYTES_PER_LOGS_BLOOM`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#execution) | `uint64(2**8)` (= 256) |
| [`SSZ_TX_TYPE`](./eip-6404.md#networking) | `0x04` |

| Name | SSZ equivalent |
| - | - |
| [`Root`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/beacon-chain.md#custom-types) | `Bytes32` |

### `Receipt` container

When building a consensus `ExecutionPayload`, the [`receipts_root`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/capella/beacon-chain.md#executionpayload) is now based on the [`Receipt`](./eip-6493.md) SSZ container. [EIP-6493](./eip-6493.md) defines how RLP receipts can be converted to SSZ.
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](./eip-7495.md).

This changes the type of `receipts_root` from an MPT [`Hash32`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/beacon-chain.md#custom-types) to an SSZ [`Root`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/beacon-chain.md#custom-types).
| Name | Value | Description |
| - | - | - |
| `MAX_TOPICS_PER_LOG` | `4` | `LOG0` through `LOG4` opcodes allow 0-4 topics per log |
| `MAX_LOG_DATA_SIZE` | `uint64(2**24)` (= 16,777,216) | Maximum `data` byte length for a log |
| `MAX_LOGS_PER_RECEIPT` | `uint64(2**21)` (= 2,097,152) | Maximum number of entries within `logs` |
| `MAX_RECEIPT_FIELDS` | `uint64(2**5)` (= 32) | Maximum number of fields to which `Receipt` can ever grow in the future |

```python
class ExecutionPayload(Container):
...
receipts_root: Root
...
class Log(Container):
address: ExecutionAddress
topics: List[Bytes32, MAX_TOPICS_PER_LOG]
data: ByteList[MAX_LOG_DATA_SIZE]

class Receipt(StableContainer[MAX_RECEIPT_FIELDS]):
root: Optional[Hash32]
gas_used: Optional[uint64]
contract_address: Optional[ExecutionAddress]
logs_bloom: Optional[ByteVector[BYTES_PER_LOGS_BLOOM]]
logs: Optional[List[Log, MAX_LOGS_PER_RECEIPT]]

# EIP-658
status: Optional[boolean]

class HomesteadReceipt(Profile[Receipt]):
root: Hash32
gas_used: uint64
contract_address: Optional[ExecutionAddress]
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
logs: List[Log, MAX_LOGS_PER_RECEIPT]

class BasicReceipt(Profile[Receipt]):
gas_used: uint64
contract_address: Optional[ExecutionAddress]
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
logs: List[Log, MAX_LOGS_PER_RECEIPT]
status: boolean

def select_receipt_profile(value: Receipt) -> Type[Profile]:
if value.status is not None:
return BasicReceipt

return HomesteadReceipt
```

To compute the `receipts_root`, the list of individual `Receipt` containers is represented as an SSZ `List`.
![Receipt merkleization](../assets/eip-6466/receipt.png)

| Name | Value |
| - | - |
| [`MAX_TRANSACTIONS_PER_PAYLOAD`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#execution) | `uint64(2**20)` (= 1,048,576) |
### Execution block header changes

The [execution block header's `receipts-root`](https://github.com/ethereum/devp2p/blob/6b259a7003b4bfb18365ba690f4b00ba8a26393b/caps/eth.md#block-encoding-and-validity) is transitioned from MPT to SSZ.

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

payload.receipts_root = receipts.hash_tree_root()
block_header.receipts_root = receipts.hash_tree_root()
```

### Consensus `ExecutionPayloadHeader` changes
### Consensus `ExecutionPayload` changes

The [consensus `ExecutionPayloadHeader`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/capella/beacon-chain.md#executionpayloadheader) is updated to match the new `ExecutionPayload.receipts_root` definition.
When building a consensus `ExecutionPayload`, the [`receipts_root`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/beacon-chain.md#executionpayload) is now based on the `Receipt` type, changing the type of `receipts_root` from an MPT [`Hash32`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/beacon-chain.md#custom-types) to an SSZ [`Root`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/beacon-chain.md#custom-types).

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

class ExecutionPayloadHeader(Container):
...
receipts_root: Root
Expand All @@ -66,18 +126,24 @@ class ExecutionPayloadHeader(Container):
payload_header.receipts_root = payload.receipts_root
```

### Execution block header changes
### Networking

The [execution block header's `receipts-root`](https://github.com/ethereum/devp2p/blob/6b259a7003b4bfb18365ba690f4b00ba8a26393b/caps/eth.md#block-encoding-and-validity) is updated to match the consensus `ExecutionPayloadHeader.receipts_root`.
When exchanging SSZ receipts via the [Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/6b259a7003b4bfb18365ba690f4b00ba8a26393b/caps/eth.md), the following [EIP-2718](./eip-2718.md) compatible envelope is used:

- `Receipt`: `SSZ_TX_TYPE || snappyFramed(ssz(Receipt))`

Objects are encoded using [SSZ](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md) and compressed using the Snappy framing format, matching the encoding of consensus objects as defined in the [consensus networking specification](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/p2p-interface.md#ssz-snappy-encoding-strategy). As part of the encoding, the uncompressed object length is emitted; the RECOMMENDED limit to enforce per object is [`MAX_CHUNK_SIZE`](https://github.com/ethereum/consensus-specs/blob/e3a939e439d6c05356c9c29c5cd347384180bc01/specs/phase0/p2p-interface.md#configuration) bytes.

## Rationale

This change enables the use of SSZ transactions as defined in [EIP-6493](./eip-6493.md).
SSZ merkleization allows verification of individual chunks of receipt data, reducing complexity for client applications and smart contracts. Additionally, SSZ [`StableContainer`](./eip-7495.md) enables unification of the receipt format across all [EIP-2718](./eip-2718.md) transaction types and provides forward compatibility.

## 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.

## Security Considerations

None
Expand Down
Loading

0 comments on commit b34f4d9

Please sign in to comment.