Skip to content

Commit 4982ae8

Browse files
authored
Update EIP-6493: Define receipt format
Merged by EIP-Bot.
1 parent 5af1bdd commit 4982ae8

2 files changed

Lines changed: 65 additions & 11 deletions

File tree

EIPS/eip-6493.md

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ For each transaction, two perpetual hashes are derived.
2525

2626
For existing [EIP-2718](./eip-2718.md) Recursive-Length Prefix (RLP) transactions, these hashes are based on a linear keccak256 hash across their serialization.
2727

28-
For [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md) transaction types, a similar signature scheme is required and defined in this EIP.
28+
For [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md) transaction types, an alternative signature scheme based on SHA256 hash tree is defined in this EIP.
2929

30-
Furthermore, existing RLP transactions should be convertable to SSZ for a consistent transaction representation.
30+
Furthermore, the EIP defines a conversion mechanism to achieve a consistent representation across both RLP and SSZ transactions and receipts.
3131

3232
## Specification
3333

@@ -69,6 +69,7 @@ Definitions from existing specifications that are used throughout this document
6969
| - | - |
7070
| [`MAX_BYTES_PER_TRANSACTION`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#execution) | `uint64(2**30)` (= 1,073,741,824) |
7171
| [`MAX_TRANSACTIONS_PER_PAYLOAD`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#execution) | `uint64(2**20)` (= 1,048,576) |
72+
| [`BYTES_PER_LOGS_BLOOM`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#execution) | `uint64(2**8)` (= 256) |
7273
| [`MAX_BLOB_COMMITMENTS_PER_BLOCK`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/beacon-chain.md#execution) | `uint64(2**12)` (= 4,096) |
7374

7475
### SSZ `SignedTransaction` container
@@ -154,7 +155,7 @@ Such changes [do not affect](./eip-7495.md) how existing transactions serialize,
154155

155156
### Transaction signature scheme
156157

157-
When an SSZ transaction is signed, additional information is mixed into the signed hash to uniquely identify the underlying SSZ schema as well as the operating network. This prevents hash collisions when different networks extend their corresponding `SignedTransaction` SSZ definition in incompatible ways.
158+
When an SSZ transaction is signed, additional information is mixed into the `sig_hash` to uniquely identify the underlying SSZ schema as well as the operating network. This prevents hash collisions when different networks extend their corresponding `SignedTransaction` SSZ definition in incompatible ways.
158159

159160
| Name | SSZ equivalent | Description |
160161
| - | - | - |
@@ -192,26 +193,73 @@ def compute_ssz_tx_hash(tx: SignedTransaction) -> Hash32:
192193
return Hash32(tx.hash_tree_root())
193194
```
194195

196+
### SSZ `Receipt` container
197+
198+
All SSZ receipts are represented as a single, normalized SSZ container. The definition uses the `PartialContainer[T, N]` SSZ type and `Optional[E]` as defined in [EIP-7495](./eip-7495.md).
199+
200+
| Name | Value | Description |
201+
| - | - | - |
202+
| `MAX_TOPICS_PER_LOG` | `4` | `LOG0` through `LOG4` opcodes allow 0-4 topics per log |
203+
| `MAX_LOG_DATA_SIZE` | `uint64(2**24)` (= 16,777,216) | Maximum `data` byte length for a log |
204+
| `MAX_LOGS_PER_RECEIPT` | `uint64(2**21)` (= 2,097,152) | Maximum number of entries within `logs` |
205+
| `MAX_RECEIPT_FIELDS` | `uint64(2**5)` (= 32) | Maximum number of fields to which `Receipt` can ever grow in the future |
206+
207+
```python
208+
class Log(Container):
209+
address: ExecutionAddress
210+
topics: List[Bytes32, MAX_TOPICS_PER_LOG]
211+
data: ByteVector[MAX_LOG_DATA_SIZE]
212+
213+
@dataclass
214+
class ReceiptPayload:
215+
root: Optional[Hash32]
216+
gas_used: uint64
217+
contract_address: Optional[ExecutionAddress]
218+
logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
219+
logs: List[Log, MAX_LOGS_PER_RECEIPT]
220+
221+
# EIP-658
222+
status: Optional[bool]
223+
224+
class Receipt(PartialContainer[ReceiptPayload, MAX_RECEIPT_FIELDS]):
225+
pass
226+
```
227+
228+
Future specifications MAY:
229+
230+
- Add fields to the end of `Receipt`
231+
- Convert existing fields to `Optional`
232+
233+
Such changes [do not affect](./eip-7495.md) how existing receipts serialize, merkleize, or validate.
234+
235+
![Receipt merkleization](../assets/eip-6493/receipt.png)
236+
195237
## Rationale
196238

197239
### Why SSZ transactions?
198240

199241
1. **Transaction inclusion proofs:** Currently, there is no commitment to the transaction hash stored on chain. Therefore, proving inclusion of a certain transaction within a block requires sending the entire transaction body, and proving a list of all transaction hashes within a block requires sending _all_ transaction bodies. With SSZ, a transaction can be ["summarized"](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md#summaries-and-expansions) by it's [`hash_tree_root`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/simple-serialize.md#merkleization), unlocking transaction root proofs without sending all transaction bodies, and compact transaction inclusion proofs by root.
200242

201-
2. **Better for light clients:** With SSZ, individual fields of a transaction can be proven. This allows light clients to obtain only fields relevant to them. Furthermore, common fields fields always merkleize at the same [generalized indices](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/merkle-proofs.md), allowing existing verification logic to continue working even when future updates introduce additional transaction fields.
243+
2. **Better for light clients:** With SSZ, individual fields of a transaction or receipt can be proven. This allows light clients to obtain only fields relevant to them. Furthermore, common fields fields always merkleize at the same [generalized indices](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/ssz/merkle-proofs.md), allowing existing verification logic to continue working even when future updates introduce additional transaction or receipt fields.
202244

203-
3. **Better for smart contracts:** Smart contracts that validate transactions benefit from the ability to prove individual chunks of a transaction. Gas fees may be lower, and it becomes possible to process transactions that do not fully fit into calldata.
245+
3. **Better for smart contracts:** Smart contracts that validate transactions or receipts benefit from the ability to prove individual chunks of a transaction. Gas fees may be lower, and it becomes possible to process transactions and receipts that do not fully fit into calldata.
204246

205-
4. **Smaller data size:** SSZ objects are typically compressed using Snappy framed compression. Transaction `input` and `access_list` fields typically contain a lot of zero bytes and benefit from this compression. Snappy framed compression allows sending sequences of transactions without having to recompress, and is designed to be computationally inexpensive.
247+
4. **Smaller data size:** SSZ objects are typically compressed using Snappy framed compression. Transaction `input` and `access_list` fields and receipt `logs_bloom` and `logs` fields often contain a lot of zero bytes and benefit from this compression. Snappy framed compression allows sending sequences of transactions and receipts without having to recompress, and is designed to be computationally inexpensive.
206248

207-
### Why include the `from` address?
249+
### Why include the `from` address in transactions?
208250

209-
For transactions converted from RLP, the `sig_hash` is computed from its original RLP representation. To prevent requiring API clients to implement the original RLP encoding and keccak hashing, the `from` address is included as part of the `SignedTransaction`.
251+
For transactions converted from RLP, the `sig_hash` is computed from its original RLP representation. To avoid requiring API clients to implement the original RLP encoding and keccak hashing, the `from` address is included as part of the `SignedTransaction`.
210252

211253
Note that this also eliminates the need for secp256k1 public key recovery when serving JSON-RPC API requests, as the `from` address is already known.
212254

213255
Furthermore, this allows early rejecting transactions that do not pay enough gas, as the `from` account balance can be checked without the computationally expensive `ecrecover`.
214256

257+
### Why include the `contract_address` in receipts?
258+
259+
Computing the address of a newly created contract requires RLP encoding and keccak hashing. Adding a commitment on-chain avoids requiring API clients to implement those formats.
260+
261+
Even though the `contract_address` is statically determinable from the corresponding `SignedTransaction` alone, including it in the `Receipt` allows the mechanism by which it is computed to change in the future.
262+
215263
### Why the `TransactionDomainData`?
216264

217265
If other SSZ objects are being signed in the future, e.g., messages, it must be ensured that their hashes do not collide with transaction `sig_hash`. Mixing in a constant that indicates that `sig_hash` pertains to an SSZ transaction prevents such hash collisions.
@@ -224,12 +272,18 @@ All SSZ transactions (including future ones) share the single [EIP-2718](./eip-2
224272

225273
This also reduces combinatorial explosion; for example, the `access_list` property could be made optional for all SSZ transactions without having to double the number of defined transaction types.
226274

275+
### Why change from `cumulative_gas_used` to `gas_used` in receipts?
276+
277+
[EIP-658](./eip-658.md) replaced the intermediate post-state `root` from receipts with a boolean `status` code. Replacing `cumulative_gas_used` with `gas_used` likewise replaces the final stateful field with a stateless one, unlocking future optimization potential as transaction receipts operating on distinct state no longer depend on their order. Furthermore, API clients no longer need to fetch information from multiple receipts if they want to validate the `gas_used` of an individual transaction.
278+
227279
## Backwards Compatibility
228280

229-
The new signature scheme is solely used for new transaction types.
281+
The new signature scheme is solely used for new transactions.
230282

231283
Existing RLP transactions can be converted to SSZ transactions for a normalized representation. Their original representation can be fully recovered from their SSZ representation, allowing bidirectional lossless conversion.
232284

285+
Existing RLP receipts can be converted to SSZ receipts for a normalized representation. The full sequence of accompanying transactions must be known to fill-in the new `contract_address` field. Note that JSON-RPC already exposes the `contract_address`, so implementations are already required to know the transaction before queries for receipts can be served.
286+
233287
## Test Cases
234288

235289
TBD
@@ -242,9 +296,9 @@ TBD
242296

243297
SSZ signatures MUST NOT collide with existing RLP transaction and message hashes.
244298

245-
As RLP messages are hashed using keccak256, and SSZ objects are hashed using SHA256, and those two hash functions are both considered cryptographically secure and are based on fundamentally different approaches, there is no significant risk of hash collision between those two signature systems.
299+
As RLP messages are hashed using keccak256, and all SSZ objects are hashed using SHA256. These two hashing algorithms are both considered cryptographically secure and are based on fundamentally different approaches, minimizing the risk of hash collision between those two hashing algorithms.
246300

247-
Furthermore, RLP messages are hashed linearly across their serialization, while SSZ objects are hashed using a recursive Merkle tree. Having a different mechanism further reduce the probability of hash collisions.
301+
Furthermore, RLP messages are hashed linearly across their serialization, while SSZ objects are hashed using a recursive Merkle tree. Having a different mechanism further reduce the risk of hash collisions.
248302

249303
## Copyright
250304

assets/eip-6493/receipt.png

197 KB
Loading

0 commit comments

Comments
 (0)