Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EIP-7594 (PeerDAS) related changes #630

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/engine/openrpc/methods/blob.yaml

Large diffs are not rendered by default.

23 changes: 19 additions & 4 deletions src/engine/openrpc/schemas/blob.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,25 @@ BlobAndProofV1:
- blob
- proof
properties:
blob:
blob:
title: Blob
$ref: '#/components/schemas/bytes'
$ref: "#/components/schemas/bytes"
proof:
title: proof
$ref: '#/components/schemas/bytes48'

$ref: "#/components/schemas/bytes48"

BlobAndProofV2:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name? It has proofs plural

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this to be a V2 it has to keep the original name...

title: Blob and proof object V2
type: object
required:
- blob
- proofs
properties:
blob:
title: Blob
$ref: "#/components/schemas/bytes"
proofs:
title: Cell Proofs
type: array
items:
$ref: "#/components/schemas/bytes48"
109 changes: 109 additions & 0 deletions src/engine/osaka.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Engine API -- Osaka

Engine API changes introduced in Osaka.

This specification is based on and extends [Engine API - Prague](./prague.md) specification.

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**

- [Structures](#structures)
- [BlobsBundleV2](#blobsbundlev2)
- [BlobAndProofV2](#blobandproofv2)
- [Methods](#methods)
- [engine_getPayloadV5](#engine_getpayloadv5)
- [Request](#request)
- [Response](#response)
- [Specification](#specification)
- [engine_getBlobsV2](#engine_getblobsv2)
- [Request](#request-1)
- [Response](#response-1)
- [Specification](#specification-1)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Structures

### BlobsBundleV2

The fields are encoded as follows:

- `commitments`: `Array of DATA` - Array of `KZGCommitment` as defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), 48 bytes each (`DATA`).
- `proofs`: `Array of DATA` - Array of `KZGProof` (48 bytes each, type defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), semantics defined in [EIP-7594](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7594.md)).
- `blobs`: `Array of DATA` - Array of blobs, each blob is `FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT = 4096 * 32 = 131072` bytes (`DATA`) representing a SSZ-encoded `Blob` as defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844)

`blobs` and `commitments` arrays **MUST** be of same length and `proofs` **MUST** contain exactly `CELLS_PER_EXT_BLOB` * `len(blobs)` cell proofs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this is the only way BlobsBundleV2 differs from https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.4/src/engine/cancun.md#blobsbundlev1?


### BlobAndProofV2

The fields are encoded as follows:

- `blob`: `DATA` - `FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT = 4096 * 32 = 131072` bytes (`DATA`) representing a SSZ-encoded `Blob` as defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844).
- `proofs`: `Array of DATA` - Array of `KZGProof` as defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), 48 bytes each (`DATA`).

`proofs` **MUST** contain exactly `CELLS_PER_EXT_BLOB` cell proofs.

## Methods

### engine_getPayloadV5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much effort is it to make these endpoints return in SSZ encoding? I'd imagine JSON serialisation and deserialisation would take much longer with much higher blob count.

Given that engine has SSZ encoding capability (blob is already SSZ encoded), is it possible to support SSZ encoding the entire endpoint responses?

Copy link
Contributor

@jimmygchen jimmygchen Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh never mind - i think SSZ encoding the blobs already provide most of the savings on blobs.

actually, no, this is still hex encoded for JSON wrapped in a string, so it's still slow and expensive.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Peter mentioned it before here:
https://x.com/peter_szilagyi/status/1841424117733478650

We should seriously consider doing this to support high blob count.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should seriously consider doing this to support high blob count.

the way the current engine-api is designed makes it almost impossible to add ssz as a wire format, yesterday the geth team mentioned they are working on a rest api following the beacon-api design, I think this is the right step forward, not only for blobs but also if we wanna bump up the gas limit

Copy link
Contributor

@etan-status etan-status Apr 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EIP-7919 would solve this as a side effect... it essentially makes everything SSZ (except the execution state).


This method is updated in a backward incompatible way. Instead of returning `BlobBundleV1`, it returns `BlobsBundleV2`.

#### Request

* method: `engine_getPayloadV5`
* params:
1. `payloadId`: `DATA`, 8 Bytes - Identifier of the payload build process
* timeout: 1s

#### Response

* result: `object`
- `executionPayload`: [`ExecutionPayloadV3`](./cancun.md#executionpayloadv3)
- `blockValue` : `QUANTITY`, 256 Bits - The expected value to be received by the `feeRecipient` in wei
- `blobsBundle`: [`BlobsBundleV2`](#BlobsBundleV2) - Bundle with data corresponding to blob transactions included into `executionPayload`
- `shouldOverrideBuilder` : `BOOLEAN` - Suggestion from the execution layer to use this `executionPayload` instead of an externally provided one
- `executionRequests`: `Array of DATA` - Execution layer triggered requests obtained from the `executionPayload` transaction execution.
* error: code and message set in case an exception happens while getting the payload.

#### Specification

This method follows the same specification as [`engine_getPayloadV4`](./prague.md#engine_getpayloadv4) with changes of the following:

1. The call **MUST** return `BlobsBundleV2` with empty `blobs`, `commitments` and `proofs` if the payload doesn't contain any blob transactions.

2. The call **MUST** return `blobs` and `proofs` that match the `commitments` list, i.e.
1. `assert len(blobsBundle.commitments) == len(blobsBundle.blobs)` and
2. `assert len(blobsBundle.proofs) == len(blobsBundle.blobs) * CELLS_PER_EXT_BLOB` and
3. `assert verify_cell_kzg_proof_batch(commitments, cell_indices, cells, blobsBundle.proofs)` (see [EIP-7594 consensus-specs](https://github.com/ethereum/consensus-specs/blob/36d80adb44c21c66379c6207a9578f9b1dcc8a2d/specs/fulu/polynomial-commitments-sampling.md#verify_cell_kzg_proof_batch))
1. `commitments` should list each commitment `CELLS_PER_EXT_BLOB` times, repeating it for every cell. In python, `[blobsBundle.commitments[i] for i in range(len(blobsBundle.blobs)) for _ in range(CELLS_PER_EXT_BLOB)]`
2. `cell_indices` should be `[0, ..., CELLS_PER_EXT_BLOB, 0, ..., CELLS_PER_EXT_BLOB, ...]`. In python, `list(range(CELLS_PER_EXT_BLOB)) * len(blobsBundle.blobs)`
3. `cells` is the list of cells for an extended blob. In python, `[cell for blob in blobsBundle.blobs for cell in compute_cells(blob)]` (see [compute_cells](https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.3/specs/fulu/polynomial-commitments-sampling.md#compute_cells) in consensus-specs)
4. All of the inputs to `verify_cell_kzg_proof_batch` have the same length, `CELLS_PER_EXT_BLOB * len(blobsBundle.blobs)`

### engine_getBlobsV2

Consensus layer clients **MAY** use this method to fetch blobs from the execution layer blob pool.

#### Request

* method: `engine_getBlobsV2`
* params:
1. `Array of DATA`, 32 Bytes - Array of blob versioned hashes.
* timeout: 1s

#### Response

* result: `Array of BlobAndProofV2` - Array of [`BlobAndProofV2`](#BlobAndProofV2), items of which may be `null`.
* error: code and message set in case an error occurs during processing of the request.

#### Specification

Refer to the specification for [`engine_getBlobsV1`](./cancun.md#engine_getblobsv1) with changes of the following:

1. Given an array of blob versioned hashes client software **MUST** respond with an array of `BlobAndProofV2` objects with matching versioned hashes, respecting the order of versioned hashes in the input array.
2. Client software **MUST** place responses in the order given in the request, using `null` for any missing blobs. For instance, if the request is `[A_versioned_hash, B_versioned_hash, C_versioned_hash]` and client software has data for blobs `A` and `C`, but doesn't have data for `B`, the response **MUST** be `[A, null, C]`.
3. Client software **MUST** support request sizes of at least 128 blob versioned hashes. The client **MUST** return `-38004: Too large request` error if the number of requested blobs is too large.
4. Client software **MAY** return an array of all `null` entries if syncing or otherwise unable to serve blob pool data.
5. Callers **MUST** consider that execution layer clients may prune old blobs from their pool, and will respond with `null` if a blob has been pruned.
10 changes: 10 additions & 0 deletions src/eth/submit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@
[EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) transactions, the raw
form must be the network form. This means it includes the blobs, KZG
commitments, and KZG proofs.
For [EIP-7594](https://eips.ethereum.org/EIPS/eip-7594) transactions, the raw format
must be the network form. This means it includes the blobs, KZG commitments, and cell proofs.
The logic for handling the new transaction during fork boundaries are
1. When receiving an encoded transaction with cell proofs before the PeerDAS fork activates, we reject it. Only blob proofs are accepted into the pool.
2. At the time of fork activation, the implementer could (not mandatory)
- Drop all old-format transactions
- Convert old proofs to new format (computationally expensive)
- Convert only when including in a locally produced block
3. After the fork has activated, only txs with cell proofs are accepted via p2p relay.
4. On RPC (eth_sendRawTransaction), txs with blob proofs may still be accepted and will be auto-converted by the node. At implementer discretion, this facility can be deprecated later when users have switched to new client libraries that can create cell proofs.
params:
- name: Transaction
required: true
Expand Down