Skip to content

Commit

Permalink
Update EIP-6404: Add from, authorities, and drop logs_bloom
Browse files Browse the repository at this point in the history
Merged by EIP-Bot.
  • Loading branch information
etan-status authored Oct 18, 2024
1 parent d439cbe commit 935a22d
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 49 deletions.
21 changes: 11 additions & 10 deletions EIPS/eip-6404.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
eip: 6404
title: SSZ Transactions
description: Migration of RLP transactions to SSZ
author: Etan Kissling (@etan-status), Vitalik Buterin (@vbuterin)
author: Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Vitalik Buterin (@vbuterin)
discussions-to: https://ethereum-magicians.org/t/eip-6404-ssz-transactions/12783
status: Draft
type: Standards Track
category: Core
created: 2023-01-30
requires: 155, 1559, 2718, 2930, 4844, 5793, 7495
requires: 155, 1559, 2718, 2930, 4844, 5793, 7495, 7702
---

## Abstract
Expand Down Expand Up @@ -109,14 +109,15 @@ All transactions are represented as a single, normalized SSZ container. The defi
| `MAX_ACCESS_LIST_STORAGE_KEYS` | `uint64(2**19)` (= 524,288) | Maximum number of storage keys within an access tuple |
| `MAX_ACCESS_LIST_SIZE` | `uint64(2**19)` (= 524,288) | Maximum number of access tuples within an `access_list` |
| `MAX_AUTHORIZATION_PAYLOAD_FIELDS` | `uint64(2**4)` (= 16) | Maximum number of fields to which `AuthorizationPayload` can ever grow in the future |
| `MAX_AUTHORIZATION_LIST_SIZE` | `uint64(2**16)` (= 65,536) | Maximum number of authorization tuples within an `access_list` |
| `MAX_AUTHORIZATION_LIST_SIZE` | `uint64(2**16)` (= 65,536) | Maximum number of authorizations within an `authorization_list` |
| `MAX_TRANSACTION_PAYLOAD_FIELDS` | `uint64(2**5)` (= 32) | Maximum number of fields to which `TransactionPayload` can ever grow in the future |

| Name | SSZ equivalent | Description |
| - | - | - |
| `TransactionType` | `uint8` | [EIP-2718](./eip-2718.md) transaction type, range `[0x00, 0x7F]` |
| `ChainId` | `uint64` | [EIP-155](./eip-155.md) chain ID |
| `FeePerGas` | `uint256` | Fee per unit of gas |
| `GasAmount` | `uint64` | Amount in units of gas |

```python
class FeesPerGas(StableContainer[MAX_FEES_PER_GAS_FIELDS]):
Expand Down Expand Up @@ -148,7 +149,7 @@ class TransactionPayload(StableContainer[MAX_TRANSACTION_PAYLOAD_FIELDS]):

nonce: Optional[uint64]
max_fees_per_gas: Optional[FeesPerGas]
gas: Optional[uint64]
gas: Optional[GasAmount]
to: Optional[ExecutionAddress]
value: Optional[uint256]
input_: Optional[ByteList[MAX_CALLDATA_SIZE]]
Expand Down Expand Up @@ -187,7 +188,7 @@ class RlpLegacyTransactionPayload(Profile[TransactionPayload]):
chain_id: Optional[ChainId]
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: Optional[ExecutionAddress]
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -201,7 +202,7 @@ class RlpAccessListTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: Optional[ExecutionAddress]
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -216,7 +217,7 @@ class RlpFeeMarketTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: Optional[ExecutionAddress]
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -232,7 +233,7 @@ class RlpBlobTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BlobFeesPerGas
gas: uint64
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -259,7 +260,7 @@ class RlpSetCodeTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand Down Expand Up @@ -293,7 +294,7 @@ def identify_authorization_profile(auth: Authorization) -> Type[Profile]:
def identify_transaction_profile(tx: Transaction) -> Type[Profile]:
if tx.payload.type_ == SET_CODE_TX_TYPE:
for auth in tx.payload.authorization_list or []:
auth = identify_authorization_profile(auth)(backing=auth.get_backing())
auth = identify_authorization_profile(auth).from_base(auth)
if not isinstance(auth, RlpSetCodeAuthorization):
raise Exception(f'Unsupported authorization in Set Code RLP transaction: {tx}')
return RlpSetCodeTransaction
Expand Down
75 changes: 51 additions & 24 deletions EIPS/eip-6466.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
eip: 6466
title: SSZ Receipts
description: Migration of RLP receipts to SSZ
author: Etan Kissling (@etan-status), Vitalik Buterin (@vbuterin)
author: Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Vitalik Buterin (@vbuterin)
discussions-to: https://ethereum-magicians.org/t/eip-6466-ssz-receipts/12884
status: Draft
type: Standards Track
category: Core
created: 2023-02-08
requires: 658, 6404
requires: 658, 2718, 6404, 7702
---

## Abstract
Expand All @@ -23,7 +23,9 @@ RLP receipts have a number of shortcomings:

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

Expand All @@ -38,12 +40,14 @@ Definitions from existing specifications that are used throughout this document
| 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) |
| [`MAX_AUTHORIZATION_LIST_SIZE`](./eip-6404.md#transaction-container) | `uint64(2**16)` (= 65,536) |
| [`SSZ_TX_TYPE`](./eip-6404.md#networking) | `0x1f` |

| Name | SSZ equivalent |
| - | - |
| [`Root`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/beacon-chain.md#custom-types) | `Bytes32` |
| [`ExecutionAddress`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#custom-types) | `Bytes20` |
| [`GasAmount`](./eip-6404.md#transaction-container) | `uint64` |

### `Receipt` container

Expand All @@ -62,38 +66,45 @@ class Log(Container):
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]
class StableReceipt(StableContainer[MAX_RECEIPT_FIELDS]):
from_: Optional[ExecutionAddress]
gas_used: Optional[GasAmount]
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]
# EIP-7702
authorities: Optional[List[ExecutionAddress, MAX_AUTHORIZATION_LIST_SIZE]]

class BasicReceipt(Profile[Receipt]):
gas_used: uint64
class Receipt(Profile[StableReceipt]):
from_: ExecutionAddress
gas_used: GasAmount
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
# EIP-658
status: boolean

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

![Receipt merkleization](../assets/eip-6466/receipt.png)
### `Receipt` construction

Receipts are constructed as follows.

| Field | Description |
| - | - |
| `from` | The transaction sender's address |
| `gas_used` | How much gas this individual transaction used. Replaces `cumulative_gas_used` |
| `contract_address` | For transactions deploying a contract, the new contract address |
| `logs` | Logs emitted during transaction execution |
| `status` | [EIP-658](./eip-658.md) transaction status code |
| `authorities` | For transactions with an authorization list, the list of [EIP-7702](./eip-7702.md) `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

Expand All @@ -106,6 +117,16 @@ receipts = List[Receipt, MAX_TRANSACTIONS_PER_PAYLOAD](
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`](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).
Expand Down Expand Up @@ -136,14 +157,20 @@ Objects are encoded using [SSZ](https://github.com/ethereum/consensus-specs/blob

## Rationale

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.
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
Expand Down
6 changes: 3 additions & 3 deletions EIPS/eip-6493.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
eip: 6493
title: SSZ Transaction Signature Scheme
description: Signature scheme for native SSZ transactions
author: Etan Kissling (@etan-status), Matt Garnett (@lightclient), Vitalik Buterin (@vbuterin)
author: Etan Kissling (@etan-status), Gajinder Singh (@g11tech), Matt Garnett (@lightclient), Vitalik Buterin (@vbuterin)
discussions-to: https://ethereum-magicians.org/t/eip-6493-ssz-transaction-signature-scheme/13050
status: Draft
type: Standards Track
Expand Down Expand Up @@ -69,7 +69,7 @@ class BasicTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: Optional[ExecutionAddress]
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -84,7 +84,7 @@ class BlobTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BlobFeesPerGas
gas: uint64
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand Down
4 changes: 2 additions & 2 deletions assets/eip-6404/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def upgrade_rlp_transaction_to_ssz(tx_bytes: bytes):
max_priority_fees_per_gas=BasicFeesPerGas(
regular=tx.max_priority_fee_per_gas,
),
authorization_list=[Authorization(backing=RlpSetCodeAuthorization(
authorization_list=[RlpSetCodeAuthorization(
payload=RlpSetCodeAuthorizationPayload(
magic=SET_CODE_TX_MAGIC,
chain_id=auth.chain_id if auth.chain_id != 0 else None,
Expand All @@ -36,7 +36,7 @@ def upgrade_rlp_transaction_to_ssz(tx_bytes: bytes):
signature=Secp256k1ExecutionSignature(
secp256k1=secp256k1_pack(auth.r, auth.s, auth.y_parity),
),
).get_backing()) for auth in tx.authorization_list],
).to_base(Authorization) for auth in tx.authorization_list],
),
signature=Secp256k1ExecutionSignature(
secp256k1=secp256k1_pack(tx.r, tx.s, tx.y_parity),
Expand Down
8 changes: 5 additions & 3 deletions assets/eip-6404/convert_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class Test:
for test in tests:
tx = upgrade_rlp_transaction_to_ssz(test.rlp_tx_bytes)

stable_tx = Transaction(backing=tx.get_backing())
stable_tx = tx.to_base(Transaction)
assert identify_transaction_profile(stable_tx) is test.tx_profile
assert stable_tx.encode_bytes() == test.ssz_tx_bytes

Expand All @@ -113,7 +113,9 @@ class Test:

assert secp256k1_recover_signer(tx.signature.secp256k1, test.sig_hash) == test.from_
assert [
secp256k1_recover_signer(auth.signature.secp256k1, compute_auth_hash(
identify_authorization_profile(auth)(backing=auth.get_backing())))
secp256k1_recover_signer(
auth.signature.secp256k1,
compute_auth_hash(identify_authorization_profile(auth).from_base(auth)),
)
for auth in getattr(tx.payload, 'authorization_list', [])
] == test.authorities
17 changes: 10 additions & 7 deletions assets/eip-6404/ssz_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class TransactionType(uint8):
class ChainId(uint64):
pass

class GasAmount(uint64):
pass

class FeePerGas(uint256):
pass

Expand Down Expand Up @@ -95,7 +98,7 @@ class TransactionPayload(StableContainer[MAX_TRANSACTION_PAYLOAD_FIELDS]):

nonce: Optional[uint64]
max_fees_per_gas: Optional[FeesPerGas]
gas: Optional[uint64]
gas: Optional[GasAmount]
to: Optional[ExecutionAddress]
value: Optional[uint256]
input_: Optional[ByteList[MAX_CALLDATA_SIZE]]
Expand Down Expand Up @@ -128,7 +131,7 @@ class RlpLegacyTransactionPayload(Profile[TransactionPayload]):
chain_id: Optional[ChainId]
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: Optional[ExecutionAddress]
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -142,7 +145,7 @@ class RlpAccessListTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: Optional[ExecutionAddress]
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -157,7 +160,7 @@ class RlpFeeMarketTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: Optional[ExecutionAddress]
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -173,7 +176,7 @@ class RlpBlobTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BlobFeesPerGas
gas: uint64
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand All @@ -200,7 +203,7 @@ class RlpSetCodeTransactionPayload(Profile[TransactionPayload]):
chain_id: ChainId
nonce: uint64
max_fees_per_gas: BasicFeesPerGas
gas: uint64
gas: GasAmount
to: ExecutionAddress
value: uint256
input_: ByteList[MAX_CALLDATA_SIZE]
Expand Down Expand Up @@ -230,7 +233,7 @@ def identify_authorization_profile(auth: Authorization) -> Type[Profile]:
def identify_transaction_profile(tx: Transaction) -> Type[Profile]:
if tx.payload.type_ == SET_CODE_TX_TYPE:
for auth in tx.payload.authorization_list or []:
auth = identify_authorization_profile(auth)(backing=auth.get_backing())
auth = identify_authorization_profile(auth).from_base(auth)
if not isinstance(auth, RlpSetCodeAuthorization):
raise Exception(f'Unsupported authorization in Set Code RLP transaction: {tx}')
return RlpSetCodeTransaction
Expand Down
Binary file removed assets/eip-6466/receipt.png
Binary file not shown.

0 comments on commit 935a22d

Please sign in to comment.