-
Notifications
You must be signed in to change notification settings - Fork 494
EIP-8025 #735
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
EIP-8025 #735
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,184 @@ | ||
| # Engine API -- EIP-8025 | ||
|
|
||
| Engine API methods for stateless validation using execution proofs. | ||
|
|
||
| This specification is based on and extends [Engine API - Osaka](./osaka.md) specification. | ||
|
|
||
| ## Table of contents | ||
|
|
||
| <!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
| <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
|
||
| - [Structures](#structures) | ||
| - [PublicInputV1](#publicinputv1) | ||
| - [ExecutionProofV1](#executionproofv1) | ||
| - [ProofAttributesV1](#proofAttributesv1) | ||
| - [ExecutionPayloadHeaderV1](#executionpayloadheaderv1) | ||
| - [NewPayloadRequestHeaderV1](#newpayloadrequestheaderv1) | ||
| - [ProofStatusV1](#proofstatusv1) | ||
| - [Methods](#methods) | ||
| - [engine_verifyExecutionProofV1](#engine_verifyexecutionproofv1) | ||
| - [engine_verifyNewPayloadRequestHeaderV1](#engine_verifynewpayloadrequestheaderv1) | ||
| - [engine_requestProofsV1](#engine_requestproofsv1) | ||
| - [Errors](#errors) | ||
|
|
||
| <!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
|
||
| ## Configuration | ||
|
|
||
| *Note*: The configuration values are not definitive. | ||
|
|
||
| | Name | Value | Description | | ||
| |--------------------------------|-------|-------------| | ||
| | `MIN_REQUIRED_EXECUTION_PROOFS` | `1` | Minimum number of valid execution proofs required to satisfy proof requirements | | ||
|
|
||
| ## Structures | ||
|
|
||
| ### PublicInputV1 | ||
|
|
||
| The fields are encoded as follows: | ||
|
|
||
| - `newPayloadRequestRoot`: `DATA`, 32 Bytes - The hash tree root of the `NewPayloadRequest`. | ||
|
|
||
| ### ExecutionProofV1 | ||
|
|
||
| The fields are encoded as follows: | ||
|
|
||
| - `proofData`: `DATA` - Variable length proof data, maximum 300 KiB. | ||
| - `proofType`: `QUANTITY`, 64 Bits - Type identifier for the proof system. | ||
| - `publicInput`: `Object` - A [`PublicInputV1`](#publicinputv1) object. | ||
|
|
||
| ### ProofAttributesV1 | ||
|
|
||
| The fields are encoded as follows: | ||
|
|
||
| - `proofTypes`: `Array of QUANTITY` - Array of proof type identifiers to request. | ||
|
|
||
| ### ExecutionPayloadHeaderV1 | ||
|
|
||
| This structure maps on the [`ExecutionPayloadHeader`] structure of the beacon chain spec. | ||
| The fields are encoded as follows: | ||
|
|
||
| - `parentHash`: `DATA`, 32 Bytes | ||
| - `feeRecipient`: `DATA`, 20 Bytes | ||
| - `stateRoot`: `DATA`, 32 Bytes | ||
| - `receiptsRoot`: `DATA`, 32 Bytes | ||
| - `logsBloom`: `DATA`, 256 Bytes | ||
| - `prevRandao`: `DATA`, 32 Bytes | ||
| - `blockNumber`: `QUANTITY`, 64 Bits | ||
| - `gasLimit`: `QUANTITY`, 64 Bits | ||
| - `gasUsed`: `QUANTITY`, 64 Bits | ||
| - `timestamp`: `QUANTITY`, 64 Bits | ||
| - `extraData`: `DATA`, 0 to 32 Bytes | ||
| - `baseFeePerGas`: `QUANTITY`, 256 Bits | ||
| - `blockHash`: `DATA`, 32 Bytes | ||
| - `transactionsRoot`: `DATA`, 32 Bytes - The hash tree root of the transactions included in the payload. | ||
| - `withdrawalsRoot`: `DATA`, 32 Bytes - The hash tree root of the withdrawals included in the payload. | ||
| - `blobGasUsed`: `QUANTITY`, 64 Bits | ||
| - `excessBlobGas`: `QUANTITY`, 64 Bits | ||
|
|
||
| ### NewPayloadRequestHeaderV1 | ||
|
|
||
| The fields are encoded as follows: | ||
|
|
||
| - `executionPayloadHeader`: `Object` - An [`ExecutionPayloadHeaderV1`](#executionpayloadheaderv1) object. | ||
| - `versionedHashes`: `Array of DATA`, 32 Bytes each - Array of blob versioned hashes. | ||
| - `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. | ||
| - `executionRequests`: `Array of DATA` - Execution layer triggered requests. | ||
|
|
||
| ### ProofStatusV1 | ||
|
|
||
| The fields are encoded as follows: | ||
|
|
||
| - `status`: `String` - The verification status. One of: | ||
| - `"VALID"` - The proof/header verification succeeded. | ||
| - `"INVALID"` - The proof/header verification failed. | ||
| - `"SYNCING"` - Less than `MIN_REQUIRED_EXECUTION_PROOFS` valid proofs have been verified for the given header. | ||
| - `"NOT_SUPPORTED"` - The proof type is not supported by this client. | ||
| - `error`: `String` - Optional error message if status is not `"VALID"`. | ||
|
|
||
| ## Methods | ||
|
|
||
| *Note*: The timeouts are not definitive. | ||
|
|
||
| ### engine_verifyExecutionProofV1 | ||
|
|
||
| #### Request | ||
|
|
||
| * method: `engine_verifyExecutionProofV1` | ||
| * params: | ||
| 1. `executionProof`: [`ExecutionProofV1`](#executionproofv1) - The execution proof to verify. | ||
| * timeout: 1s | ||
|
|
||
| #### Response | ||
|
|
||
| * result: [`ProofStatusV1`](#proofstatusv1) - The verification result. | ||
| * error: code and message set in case an exception happens while verifying the proof. | ||
|
|
||
| #### Specification | ||
|
|
||
| 1. Client software **MUST** validate the `executionProof` parameter: | ||
| - `proofData` **MUST** be non-empty and not exceed 300 KiB. | ||
| - `proofType` **MUST** be a supported proof type. | ||
| - `publicInput.newPayloadRequestRoot` **MUST** be a valid 32-byte hash. | ||
|
|
||
| 2. Client software **MUST** verify the execution proof using the appropriate proof verification algorithm based on `proofType`. | ||
|
|
||
| 3. Client software **MUST** respond with `{status: "VALID"}` if the proof is valid, `{status: "INVALID", error: "..."}` if the proof is invalid, or `{status: "NOT_SUPPORTED", error: "..."}` if the proof type is not supported. | ||
|
|
||
| ### engine_verifyNewPayloadRequestHeaderV1 | ||
|
|
||
| #### Request | ||
|
|
||
| * method: `engine_verifyNewPayloadRequestHeaderV1` | ||
| * params: | ||
| 1. `newPayloadRequestHeader`: [`NewPayloadRequestHeaderV1`](#newpayloadrequestheaderv1) - The header to verify. | ||
| * timeout: 1s | ||
|
|
||
| #### Response | ||
|
|
||
| * result: [`ProofStatusV1`](#proofstatusv1) - The verification result. | ||
| * error: code and message set in case an exception happens while verifying. | ||
|
|
||
| #### Specification | ||
|
|
||
| 1. Client software **MUST** validate the `newPayloadRequestHeader` parameter structure. | ||
|
|
||
| 2. Client software **MUST** respond with `{status: "VALID"}` if at least `MIN_REQUIRED_EXECUTION_PROOFS` proofs have been verified for this `NewPayloadRequestHeader`, or `{status: "SYNCING "}` if not. | ||
|
|
||
| ### engine_requestProofsV1 | ||
|
|
||
| #### Request | ||
|
|
||
| * method: `engine_requestProofsV1` | ||
| * params: | ||
| 1. `executionPayload`: [`ExecutionPayloadV3`](./cancun.md#executionpayloadv3) - The execution payload to generate proofs for. | ||
| 2. `versionedHashes`: `Array of DATA`, 32 Bytes each - Array of blob versioned hashes. | ||
| 3. `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. | ||
| 4. `executionRequests`: `Array of DATA` - List of execution layer triggered requests. | ||
| 5. `proofAttributes`: [`ProofAttributesV1`](#proofAttributesv1) - Attributes specifying which proofs to generate. | ||
| * timeout: 1s | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this TBD?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, I added a note - |
||
|
|
||
| #### Response | ||
|
|
||
| * result: `DATA`, 8 Bytes - A `ProofGenId` to track the proof generation request. | ||
| * error: code and message set in case an exception happens while initiating proof generation. | ||
|
|
||
| #### Specification | ||
|
|
||
| 1. Client software **MUST** validate all parameters. | ||
|
|
||
| 2. Client software **MUST** initiate asynchronous proof generation for the given payload and return a `ProofGenId` immediately. | ||
|
|
||
| 3. Generated proofs are delivered asynchronously via the beacon API endpoint `POST /eth/v1/prover/execution_proofs`. The client **MUST NOT** block waiting for proof generation to complete. | ||
|
|
||
| 4. If proof generation is unavailable (e.g., no prover configured), client software **MUST** return error code `-39004`. | ||
|
|
||
| ## Errors | ||
|
|
||
| | Code | Message | Meaning | | ||
| |------|---------|---------| | ||
| | -39001 | Invalid proof format | The execution proof structure is malformed | | ||
| | -39002 | Invalid header format | The new payload request header structure is malformed | | ||
| | -39003 | Invalid payload | The execution payload is invalid | | ||
| | -39004 | Proof generation unavailable | The client cannot generate proofs | | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| - name: engine_verifyExecutionProofV1 | ||
| summary: Verifies an execution proof | ||
| externalDocs: | ||
| description: Method specification | ||
| url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8025.md#engine_verifyexecutionproofv1 | ||
| params: | ||
| - name: Execution proof | ||
| required: true | ||
| schema: | ||
| $ref: '#/components/schemas/ExecutionProofV1' | ||
| result: | ||
| name: Proof status | ||
| schema: | ||
| $ref: '#/components/schemas/ProofStatusV1' | ||
| errors: | ||
| - code: -39001 | ||
| message: Invalid proof format | ||
| examples: | ||
| - name: engine_verifyExecutionProofV1 example | ||
| params: | ||
| - name: Execution proof | ||
| value: | ||
| proofData: '0x0000000000000000000000000000000000000000000000000000000000000000' | ||
| proofType: '0x1' | ||
| publicInput: | ||
| newPayloadRequestRoot: '0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858' | ||
| result: | ||
| name: Proof status | ||
| value: | ||
| valid: true | ||
|
|
||
| - name: engine_verifyNewPayloadRequestHeaderV1 | ||
| summary: Verifies a new payload request header has sufficient proof coverage | ||
| externalDocs: | ||
| description: Method specification | ||
| url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8025.md#engine_verifynewpayloadrequestheaderv1 | ||
| params: | ||
| - name: New payload request header | ||
| required: true | ||
| schema: | ||
| $ref: '#/components/schemas/NewPayloadRequestHeaderV1' | ||
| result: | ||
| name: Verification status | ||
| schema: | ||
| $ref: '#/components/schemas/ProofStatusV1' | ||
| errors: | ||
| - code: -39002 | ||
| message: Invalid header format | ||
| examples: | ||
| - name: engine_verifyNewPayloadRequestHeaderV1 example | ||
| params: | ||
| - name: New payload request header | ||
| value: | ||
| executionPayloadHeader: | ||
| parentHash: '0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a' | ||
| feeRecipient: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b' | ||
| stateRoot: '0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45' | ||
| receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' | ||
| logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' | ||
| prevRandao: '0x0000000000000000000000000000000000000000000000000000000000000000' | ||
| blockNumber: '0x1' | ||
| gasLimit: '0x1c9c380' | ||
| gasUsed: '0x0' | ||
| timestamp: '0x5' | ||
| extraData: '0x' | ||
| baseFeePerGas: '0x7' | ||
| blockHash: '0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858' | ||
| transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' | ||
| withdrawalsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' | ||
| blobGasUsed: '0x0' | ||
| excessBlobGas: '0x0' | ||
| versionedHashes: [] | ||
| parentBeaconBlockRoot: '0x0000000000000000000000000000000000000000000000000000000000000000' | ||
| executionRequests: [] | ||
| result: | ||
| name: Verification status | ||
| value: | ||
| valid: true | ||
|
|
||
| - name: engine_requestProofsV1 | ||
| summary: Requests proof generation for a new payload request | ||
|
Comment on lines
+80
to
+81
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checking, do we still need this if the proofs are pushed to the CL versus the CL requesting proofs from the proof engine?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it makes sense to keep it. The CL should instruct the proof engine what blocks to generate proofs for. It requires consensus layer context to determine when a proof is required by that nodes builder. I think the flow is pretty clean if you look at the first diagram in this PR (prover replaced by builder in the future) ethereum/consensus-specs#4828. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see, I think I merged some of the prover related responsibilities into zkboost -- but perhaps it doesn't matter |
||
| externalDocs: | ||
| description: Method specification | ||
| url: https://github.com/ethereum/execution-apis/blob/main/src/engine/eip8025.md#engine_requestproofsv1 | ||
| params: | ||
| - name: Execution payload | ||
| required: true | ||
| schema: | ||
| $ref: '#/components/schemas/ExecutionPayloadV3' | ||
| - name: Versioned hashes | ||
| required: true | ||
| schema: | ||
| type: array | ||
| items: | ||
| $ref: '#/components/schemas/hash32' | ||
| - name: Parent beacon block root | ||
| required: true | ||
| schema: | ||
| $ref: '#/components/schemas/hash32' | ||
| - name: Proof attributes | ||
| required: true | ||
| schema: | ||
| $ref: '#/components/schemas/ProofAttributesV1' | ||
| result: | ||
| name: Proof generation ID | ||
| schema: | ||
| $ref: '#/components/schemas/bytes8' | ||
| errors: | ||
| - code: -39003 | ||
| message: Invalid payload | ||
| - code: -39004 | ||
| message: Proof generation unavailable | ||
| examples: | ||
| - name: engine_requestProofsV1 example | ||
| params: | ||
| - name: Execution payload | ||
| value: | ||
| parentHash: '0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a' | ||
| feeRecipient: '0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b' | ||
| stateRoot: '0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45' | ||
| receiptsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421' | ||
| logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' | ||
| prevRandao: '0x0000000000000000000000000000000000000000000000000000000000000000' | ||
| blockNumber: '0x1' | ||
| gasLimit: '0x1c9c380' | ||
| gasUsed: '0x0' | ||
| timestamp: '0x5' | ||
| extraData: '0x' | ||
| baseFeePerGas: '0x7' | ||
| blockHash: '0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858' | ||
| transactions: [] | ||
| withdrawals: [] | ||
| blobGasUsed: '0x0' | ||
| excessBlobGas: '0x0' | ||
| - name: Versioned hashes | ||
| value: [] | ||
| - name: Parent beacon block root | ||
| value: '0x0000000000000000000000000000000000000000000000000000000000000000' | ||
| - name: Proof attributes | ||
| value: | ||
| proofTypes: | ||
| - '0x1' | ||
| result: | ||
| name: Proof generation ID | ||
| value: '0x0000000000000001' | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a nit, but for this
engine_verifyNewPayloadRequestHeaderV1we should technically name the return typeProofsStatusV1instead ofProofStatusV1?Since technically we are checking a proofs policy, no?
Not sure it is worth changing tbh -- just surfacing thought.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is fine to use the same return type
ProofStatusV1for bothengine_verifyNewPayloadRequestHeaderV1andengine_verifyExecutionProofV1and have slightly different interpretations. This is analogous to howPayloadStatusV*is used as the return type for bothengine_newPayload*andengine_forkchoiceUpdated*.