Skip to content

Commit 6b3e816

Browse files
authored
Update EIP-6493: Define PooledTransaction wrapper for gossip
Merged by EIP-Bot.
1 parent 6a23776 commit 6b3e816

1 file changed

Lines changed: 67 additions & 8 deletions

File tree

EIPS/eip-6493.md

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ status: Draft
88
type: Standards Track
99
category: Core
1010
created: 2023-02-24
11-
requires: 155, 191, 1559, 2718, 2930, 4844, 7495
11+
requires: 155, 191, 1559, 2718, 2930, 4844, 5793, 7495
1212
---
1313

1414
## Abstract
@@ -46,8 +46,8 @@ The values `0x00` and `0x04` are marked as reserved [EIP-2718](./eip-2718.md) tr
4646

4747
| Name | Value | Description |
4848
| - | - | - |
49-
| (n/a) | `None` | Untyped [`LegacyTransaction`](./eip-2718.md#transactions) |
50-
| `TRANSACTION_TYPE_LEGACY` | `TransactionType(0x00)` | Untyped [`LegacyTransaction`](./eip-2718.md#transactions) with [chain ID](./eip-155.md) |
49+
| (n/a) | `None` | Untyped [`LegacyTransaction`](./eip-2718.md#transactions) ('Homestead' scheme) |
50+
| `TRANSACTION_TYPE_LEGACY` | `TransactionType(0x00)` | Untyped [`LegacyTransaction`](./eip-2718.md#transactions) ([EIP-155 scheme](./eip-155.md)) |
5151
| `TRANSACTION_TYPE_EIP2930` | `TransactionType(0x01)` | [EIP-2930](./eip-2930.md#definitions) transaction |
5252
| `TRANSACTION_TYPE_EIP1559` | `TransactionType(0x02)` | [EIP-1559](./eip-1559.md#specification) transaction |
5353
| `TRANSACTION_TYPE_EIP4844` | `TransactionType(0x03)` | [EIP-4844](./eip-4844.md#parameters) transaction |
@@ -63,11 +63,16 @@ Definitions from existing specifications that are used throughout this document
6363
| - | - |
6464
| [`Hash32`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/phase0/beacon-chain.md#custom-types) | `Bytes32` |
6565
| [`ExecutionAddress`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#custom-types) | `Bytes20` |
66+
| [`KZGCommitment`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/polynomial-commitments.md#custom-types) | `Bytes48` |
67+
| [`KZGProof`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/polynomial-commitments.md#custom-types) | `Bytes48` |
68+
| [`Blob`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/polynomial-commitments.md#custom-types) | `ByteVector[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB]` |
6669
| [`VersionedHash`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/beacon-chain.md#custom-types) | `Bytes32` |
6770

6871
| Name | Value |
6972
| - | - |
7073
| [`BYTES_PER_LOGS_BLOOM`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/bellatrix/beacon-chain.md#execution) | `uint64(2**8)` (= 256) |
74+
| [`BYTES_PER_FIELD_ELEMENT`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/polynomial-commitments.md#constants) | `uint64(32)` |
75+
| [`FIELD_ELEMENTS_PER_BLOB`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/polynomial-commitments.md#blob) | `uint64(4096)` |
7176
| [`MAX_BLOB_COMMITMENTS_PER_BLOCK`](https://github.com/ethereum/consensus-specs/blob/ef434e87165e9a4c82a99f54ffd4974ae113f732/specs/deneb/beacon-chain.md#execution) | `uint64(2**12)` (= 4,096) |
7277

7378
### SSZ `SignedTransaction` container
@@ -193,7 +198,7 @@ def compute_ssz_tx_hash(tx: SignedTransaction) -> Hash32:
193198

194199
### Transaction validation
195200

196-
As part of validating a `SignedTransaction`, the `from` address MUST be checked for consistency with the `ecdsa_signature`.
201+
As part of `SignedTransaction` validation, the `from` address MUST be checked for consistency with the `ecdsa_signature`.
197202

198203
```python
199204
def ecdsa_pack_signature(y_parity: bool,
@@ -235,6 +240,31 @@ def validate_transaction(tx: SignedTransaction,
235240

236241
See [EIP assets](../assets/eip-6493/tx_hashes.py) for a definition of `compute_sig_hash` that takes the various transaction types into account.
237242

243+
### SSZ `PooledTransaction` container
244+
245+
During transaction gossip responses ([`PooledTransactions`](https://github.com/ethereum/devp2p/blob/6b259a7003b4bfb18365ba690f4b00ba8a26393b/caps/eth.md#pooledtransactions-0x0a)), each `SignedTransaction` is wrapped into a `PooledTransaction`. The definition uses the `PartialContainer[T, N]` SSZ type and `Optional[E]` as defined in [EIP-7495](./eip-7495.md).
246+
247+
| Name | Value | Description |
248+
| - | - | - |
249+
| `MAX_POOLED_TRANSACTION_FIELDS` | `uint64(2**3)` (= 8) | Maximum number of fields to which `PooledTransaction` can ever grow in the future |
250+
251+
```python
252+
class BlobPayload(Container):
253+
blob: Blob
254+
kzg_commitment: KZGCommitment
255+
kzg_proof: KZGProof
256+
257+
@dataclass
258+
class PooledTransactionPayload:
259+
tx: SignedTransaction
260+
blob_payloads: Optional[List[BlobPayload, MAX_BLOB_COMMITMENTS_PER_BLOCK]]
261+
262+
class PooledTransaction(PartialContainer[PooledTransactionPayload, MAX_POOLED_TRANSACTION_FIELDS]):
263+
pass
264+
```
265+
266+
The same additional validation constraints as defined in [EIP-4844](./eip-4844.md) apply to transactions that define `tx.payload.blob_versioned_hashes` or `blob_payloads`.
267+
238268
### SSZ `Receipt` container
239269

240270
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).
@@ -276,6 +306,29 @@ Such changes [do not affect](./eip-7495.md) how existing receipts serialize, mer
276306

277307
![Receipt merkleization](../assets/eip-6493/receipt.png)
278308

309+
### Networking
310+
311+
When exchanging transactions and receipts via the [Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/6b259a7003b4bfb18365ba690f4b00ba8a26393b/caps/eth.md), the following [EIP-2718](./eip-2718.md) compatible envelopes are used:
312+
313+
- `SignedTransaction`: `TRANSACTION_TYPE_SSZ || snappyFramed(ssz(SignedTransaction))`
314+
- `PooledTransaction`: `TRANSACTION_TYPE_SSZ || snappyFramed(ssz(PooledTransaction))`
315+
- `Receipt`: `TRANSACTION_TYPE_SSZ || snappyFramed(ssz(Receipt))`
316+
317+
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](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 emited; 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.
318+
319+
Implementations SHALL continue to support accepting RLP transactions into their transaction pool. However, such transactions MUST be converted to SSZ for inclusion into an `ExecutionPayload`. See [EIP assets](../assets/eip-6493/convert.py) for a reference implementation to convert from RLP to SSZ, as well as corresponding [test cases](../assets/eip-6493/convert_tests.py). The original `sig_hash` and `tx_hash` are retained throughout the conversion process.
320+
321+
### Transaction gossip announcements
322+
323+
The semantics of the [`types` element](./eip-5793.md) in transaction gossip announcements ([`NewPooledTransactionHashes`](https://github.com/ethereum/devp2p/blob/6b259a7003b4bfb18365ba690f4b00ba8a26393b/caps/eth.md#newpooledtransactionhashes-0x08)) is changed to match `ssz(PooledTransaction.active_fields())`:
324+
325+
| `types` | Description |
326+
| - | - |
327+
| `0x00` | Untyped [`LegacyTransaction`](./eip-2718.md#transactions) ('Homestead' scheme, or [EIP-155 scheme](./eip-155.md)) |
328+
| `0x01` | [EIP-2930](./eip-2930.md) transaction, or basic SSZ `PooledTransaction` without any additional auxiliary payloads |
329+
| `0x02` | [EIP-1559](./eip-1559.md) transaction |
330+
| `0x03` | [EIP-4844](./eip-4844.md) transaction, or SSZ `PooledTransaction` with `blob_payloads` |
331+
279332
## Rationale
280333

281334
### Why SSZ transactions?
@@ -286,15 +339,15 @@ Such changes [do not affect](./eip-7495.md) how existing receipts serialize, mer
286339

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

289-
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.
342+
4. **Smaller data size:** SSZ objects are typically compressed using Snappy framed compression. Transaction `input` and `access_list` fields as well as 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.
290343

291344
### Why include the `from` address in transactions?
292345

293346
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`.
294347

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

297-
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`.
350+
Furthermore, this allows early rejecting transactions with sender accounts that do not have sufficient balance, as the `from` account balance can be checked without the computationally expensive `ecrecover`.
298351

299352
### Why include the `contract_address` in receipts?
300353

@@ -314,6 +367,14 @@ All SSZ transactions (including future ones) share the single [EIP-2718](./eip-2
314367

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

370+
### Why redefine `types` for `NewPooledTransactionHashes`?
371+
372+
The `types` element as introduced in eth/68 via [EIP-5793](./eip-5793.md) allows the receiving node better control over the data it fetches from the peer and allows throttling the download of specific types.
373+
374+
Current implementations primarily use `types` to distinguish type `0x03` blob transactions from basic type `0x00`, `0x01` and `0x02` transactions. However, all SSZ `SignedTransaction` use type `0x04` (`TRANSACTION_TYPE_SSZ`), eliminating this optimization potential.
375+
376+
To restore the optimization potential, `types` is redefined to indicate instead what auxiliary payloads are present in the `PooledTransaction`: SSZ blob transactions will share type `0x03` with RLP blob transactions, while basic SSZ transactions will be assigned type `0x01`, which is currently also used for a basic RLP transaction type. Therefore, implementations will not require changes to distinguish blob transactions from basic transactions.
377+
317378
### Why change from `cumulative_gas_used` to `gas_used` in receipts?
318379

319380
[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.
@@ -326,8 +387,6 @@ Existing RLP transactions can be converted to SSZ transactions. Their original `
326387

327388
Existing RLP receipts can be converted to SSZ receipts. The full sequence of accompanying transactions must be known to fill-in the new `contract_address` field. Note that because JSON-RPC exposes the `contract_address`, implementations are already required to know the transaction before queries for receipts can be served.
328389

329-
See [EIP assets](../assets/eip-6493/convert.py) for a reference implementation to convert from RLP to SSZ, as well as corresponding [test cases](../assets/eip-6493/convert_tests.py).
330-
331390
## Test Cases
332391

333392
TBD

0 commit comments

Comments
 (0)