diff --git a/src/engine/cancun.md b/src/engine/cancun.md new file mode 100644 index 00000000..8abd2612 --- /dev/null +++ b/src/engine/cancun.md @@ -0,0 +1,172 @@ +# Engine API -- Cancun + +Engine API changes introduced in Cancun. + +This specificaiton is based on and extends [Engine API - Shanghai](./shanghai.md) specification. + +## Table of contents + + + + +- [Structures](#structures) + - [ExecutionPayloadV3](#executionpayloadv3) + - [BlobsBundleV1](#blobsbundlev1) + - [PayloadAttributesV3](#payloadattributesv3) +- [Methods](#methods) + - [engine_newPayloadV3](#engine_newpayloadv3) + - [Request](#request) + - [Response](#response) + - [Specification](#specification) + - [engine_forkchoiceUpdatedV3](#engine_forkchoiceupdatedv3) + - [Request](#request-1) + - [Response](#response-1) + - [Specification](#specification-1) + - [engine_getPayloadV3](#engine_getpayloadv3) + - [Request](#request-2) + - [Response](#response-2) + - [Specification](#specification-2) + - [Deprecate `engine_exchangeTransitionConfigurationV1`](#deprecate-engine_exchangetransitionconfigurationv1) + + + +## Structures + +### ExecutionPayloadV3 + +This structure has the syntax of [`ExecutionPayloadV2`](./shanghai.md#executionpayloadv2) and appends the new fields: `dataGasUsed` and `excessDataGas`. + +- `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 +- `transactions`: `Array of DATA` - Array of transaction objects, each object is a byte list (`DATA`) representing `TransactionType || TransactionPayload` or `LegacyTransaction` as defined in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) +- `withdrawals`: `Array of WithdrawalV1` - Array of withdrawals, each object is an `OBJECT` containing the fields of a `WithdrawalV1` structure. +- `dataGasUsed`: `QUANTITY`, 64 bits +- `excessDataGas`: `QUANTITY`, 64 Bits + +### BlobsBundleV1 + +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` as defined in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), 48 bytes each (`DATA`). +- `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) + +All of the above three arrays **MUST** be of same length. + +### PayloadAttributesV3 + +This structure has the syntax of [`PayloadAttributesV2`](./shanghai.md#payloadattributesv2) and appends a single field: `parentBeaconBlockRoot`. + +- `timestamp`: `QUANTITY`, 64 Bits - value for the `timestamp` field of the new payload +- `prevRandao`: `DATA`, 32 Bytes - value for the `prevRandao` field of the new payload +- `suggestedFeeRecipient`: `DATA`, 20 Bytes - suggested value for the `feeRecipient` field of the new payload +- `withdrawals`: `Array of WithdrawalV1` - Array of withdrawals, each object is an `OBJECT` containing the fields of a `WithdrawalV1` structure. +- `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. + +## Methods + +### engine_newPayloadV3 + +#### Request + +* method: `engine_newPayloadV3` +* params: + 1. `executionPayload`: [`ExecutionPayloadV3`](#ExecutionPayloadV3). + 2. `expectedBlobVersionedHashes`: `Array of DATA`, 32 Bytes - Array of expected blob versioned hashes to validate. + 3. `parentBeaconBlockRoot`: `DATA`, 32 Bytes - Root of the parent beacon block. + +Client software **MUST** return `-32602: Invalid params` error unless all parameters and their fields are provided with non-`null` values. + +#### Response + +Refer to the response for [`engine_newPayloadV2`](./shanghai.md#engine_newpayloadv2). + +#### Specification + +This method follows the same specification as [`engine_newPayloadV2`](./shanghai.md#engine_newpayloadv2) with the addition of the following: + +1. Given the expected array of blob versioned hashes client software **MUST** run its validation by taking the following steps: + 1. Obtain the actual array by concatenating blob versioned hashes lists (`tx.blob_versioned_hashes`) of each [blob transaction](https://eips.ethereum.org/EIPS/eip-4844#new-transaction-type) included in the payload, respecting the order of inclusion. If the payload has no blob transactions the expected array **MUST** be `[]`. + 2. Return `{status: INVALID, latestValidHash: null, validationError: errorMessage | null}` if the expected and the actual arrays don't match. + + This validation **MUST** be instantly run in all cases even during active sync process. + +2. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the payload is less than the Cancun activation timestamp. + +### engine_forkchoiceUpdatedV3 + +#### Request + +* method: `engine_forkchoiceUpdatedV3` +* params: + 1. `forkchoiceState`: [`ForkchoiceStateV1`](./paris.md#ForkchoiceStateV1). + 2. `payloadAttributes`: `Object|null` - Instance of [`PayloadAttributesV3`](#payloadattributesv3) or `null`. +* timeout: 8s + +Client software **MUST** return `-32602: Invalid params` error unless: +* every field of `forkchoiceState` is provided with non-`null` value, +* every field of `payloadAttributes` is provided with non-`null` values when `payloadAttributes` is not `null`. + +#### Response + +Refer to the response for [`engine_forkchoiceUpdatedV2`](./shanghai.md#engine_forkchoiceupdatedv2). + +#### Specification + +This method follows the same specification as [`engine_forkchoiceUpdatedV2`](./shanghai.md#engine_forkchoiceupdatedv2) with addition of the following: + +1. Client software **MUST** return `-38005: Unsupported fork` error if the `payloadAttributes.timestamp` is less than the Cancun activation timestamp. + +### engine_getPayloadV3 + +The response of this method is extended with [`BlobsBundleV1`](#blobsbundlev1) containing the blobs, their respective KZG commitments +and proofs corresponding to the `versioned_hashes` included in the blob transactions of the execution payload. + +#### Request + +* method: `engine_getPayloadV3` +* params: + 1. `payloadId`: `DATA`, 8 Bytes - Identifier of the payload build process +* timeout: 1s + +#### Response + +* result: `object` + - `executionPayload`: [`ExecutionPayloadV3`](#ExecutionPayloadV3) + - `blockValue` : `QUANTITY`, 256 Bits - The expected value to be received by the `feeRecipient` in wei + - `blobsBundle`: [`BlobsBundleV1`](#BlobsBundleV1) - Bundle with data corresponding to blob transactions included into `executionPayload` +* error: code and message set in case an exception happens while getting the payload. + +#### Specification + +Refer to the specification for [`engine_getPayloadV2`](./shanghai.md#engine_getpayloadv2) with addition of the following: + +1. The call **MUST** return `blobsBundle` with empty `blobs`, `commitments` and `proofs` if the payload doesn't contain any blob transactions. + +2. The call **MUST** return `commitments` matching the versioned hashes of the transactions list of the execution payload, in the same order, + i.e. `assert verify_kzg_commitments_against_transactions(payload.transactions, blobsBundle.commitments)` (see EIP-4844 consensus-specs). + +3. The call **MUST** return `blobs` and `proofs` that match the `commitments` list, i.e. `assert len(blobsBundle.commitments) == len(blobsBundle.blobs) == len(blobsBundle.proofs)` and `assert verify_blob_kzg_proof_batch(blobsBundle.blobs, blobsBundle.commitments, blobsBundle.proofs)`. + +4. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the built payload is less than the Cancun activation timestamp. + +### Deprecate `engine_exchangeTransitionConfigurationV1` + +This document introduces deprecation of [`engine_exchangeTransitionConfigurationV1`](./paris.md#engine_exchangetransitionconfigurationv1). The deprecation is specified as follows: + +1. Consensus layer clients **MUST NOT** call this method. + +2. Execution layer clients **MUST NOT** surface an error message to the user if this method is not called. + +3. Consensus and execution layer clients **MAY** remove support of this method after Cancun. If no longer supported, this method **MUST** be removed from the [`engine_exchangeCapabilities`](./common.md#engine_exchangecapabilities) request or response list depending on whether it is consensus or execution layer client. diff --git a/src/engine/openrpc/methods/forkchoice.yaml b/src/engine/openrpc/methods/forkchoice.yaml index 83fa19bf..e54c44d5 100644 --- a/src/engine/openrpc/methods/forkchoice.yaml +++ b/src/engine/openrpc/methods/forkchoice.yaml @@ -44,3 +44,30 @@ message: Invalid forkchoice state - code: -38003 message: Invalid payload attributes +- name: engine_forkchoiceUpdatedV3 + summary: Updates the forkchoice state + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_forkchoiceupdatedv3 + params: + - name: Forkchoice state + required: true + schema: + $ref: '#/components/schemas/ForkchoiceStateV1' + - name: Payload attributes + required: false + schema: + $ref: '#/components/schemas/PayloadAttributesV3' + result: + name: Response object + schema: + $ref: '#/components/schemas/ForkchoiceUpdatedResponseV1' + errors: + - code: -38002 + message: Invalid forkchoice state + - code: -38003 + message: Invalid payload attributes + - code: -32602 + message: Invalid params + - code: -38005 + message: Unsupported fork diff --git a/src/engine/openrpc/methods/payload.yaml b/src/engine/openrpc/methods/payload.yaml index 1cd3f50c..b2d84fd4 100644 --- a/src/engine/openrpc/methods/payload.yaml +++ b/src/engine/openrpc/methods/payload.yaml @@ -31,6 +31,35 @@ errors: - code: -32602 message: Invalid params +- name: engine_newPayloadV3 + summary: Runs execution payload validation + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_newpayloadv3 + params: + - name: Execution payload + required: true + schema: + $ref: '#/components/schemas/ExecutionPayloadV3' + - name: Expected blob versioned hashes + required: true + schema: + type: array + items: + $ref: '#/components/schemas/hash32' + - name: Root of the parent beacon block + required: true + schema: + $ref: '#/components/schemas/hash32' + result: + name: Payload status + schema: + $ref: '#/components/schemas/PayloadStatusNoInvalidBlockHash' + errors: + - code: -32602 + message: Invalid params + - code: -38005 + message: Unsupported fork - name: engine_getPayloadV1 summary: Obtains execution payload from payload build process externalDocs: @@ -77,6 +106,39 @@ errors: - code: -38001 message: Unknown payload +- name: engine_getPayloadV3 + summary: Obtains execution payload from payload build process + externalDocs: + description: Method specification + url: https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_getpayloadv3 + params: + - name: Payload id + required: true + schema: + $ref: '#/components/schemas/bytes8' + result: + name: Response object + schema: + type: object + required: + - executionPayload + - blockValue + - blobsBundle + properties: + executionPayload: + title: Execution payload + $ref: '#/components/schemas/ExecutionPayloadV3' + blockValue: + title: Expected fee value + $ref: '#/components/schemas/uint256' + blobsBundle: + title: Blobs bundle + $ref: '#/components/schemas/BlobsBundleV1' + errors: + - code: -38001 + message: Unknown payload + - code: -38005 + message: Unsupported fork - name: engine_getPayloadBodiesByHashV1 summary: Given block hashes returns bodies of the corresponding execution payloads externalDocs: diff --git a/src/engine/openrpc/schemas/forkchoice.yaml b/src/engine/openrpc/schemas/forkchoice.yaml index da871188..c398de23 100644 --- a/src/engine/openrpc/schemas/forkchoice.yaml +++ b/src/engine/openrpc/schemas/forkchoice.yaml @@ -64,3 +64,24 @@ PayloadAttributesV2: type: array items: $ref: '#/components/schemas/WithdrawalV1' +PayloadAttributesV3: + title: Payload attributes object V3 + type: object + required: + - timestamp + - prevRandao + - suggestedFeeRecipient + - withdrawals + - parentBeaconBlockRoot + properties: + timestamp: + $ref: '#/components/schemas/PayloadAttributesV2/properties/timestamp' + prevRandao: + $ref: '#/components/schemas/PayloadAttributesV2/properties/prevRandao' + suggestedFeeRecipient: + $ref: '#/components/schemas/PayloadAttributesV2/properties/suggestedFeeRecipient' + withdrawals: + $ref: '#/components/schemas/PayloadAttributesV2/properties/withdrawals' + parentBeaconBlockRoot: + title: Parent beacon block root + $ref: '#/components/schemas/hash32' diff --git a/src/engine/openrpc/schemas/payload.yaml b/src/engine/openrpc/schemas/payload.yaml index f4333fb4..4681408d 100644 --- a/src/engine/openrpc/schemas/payload.yaml +++ b/src/engine/openrpc/schemas/payload.yaml @@ -185,6 +185,64 @@ ExecutionPayloadV2: type: array items: $ref: '#/components/schemas/WithdrawalV1' +ExecutionPayloadV3: + title: Execution payload object V3 + type: object + required: + - parentHash + - feeRecipient + - stateRoot + - receiptsRoot + - logsBloom + - prevRandao + - blockNumber + - gasLimit + - gasUsed + - timestamp + - extraData + - baseFeePerGas + - blockHash + - transactions + - withdrawals + - dataGasUsed + - excessDataGas + properties: + parentHash: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/parentHash' + feeRecipient: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/feeRecipient' + stateRoot: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/stateRoot' + receiptsRoot: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/receiptsRoot' + logsBloom: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/logsBloom' + prevRandao: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/prevRandao' + blockNumber: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/blockNumber' + gasLimit: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/gasLimit' + gasUsed: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/gasUsed' + timestamp: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/timestamp' + extraData: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/extraData' + baseFeePerGas: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/baseFeePerGas' + blockHash: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/blockHash' + transactions: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/transactions' + withdrawals: + $ref: '#/components/schemas/ExecutionPayloadV2/properties/withdrawals' + dataGasUsed: + title: Data gas used + $ref: '#/components/schemas/uint64' + excessDataGas: + title: Excess data gas + $ref: '#/components/schemas/uint64' ExecutionPayloadBodyV1: title: Execution payload body object V1 type: object @@ -200,3 +258,26 @@ ExecutionPayloadBodyV1: - 'null' items: $ref: '#/components/schemas/WithdrawalV1' +BlobsBundleV1: + title: Blobs bundle object V1 + type: object + required: + - commitments + - proofs + - blobs + properties: + commitments: + title: Commitments + type: array + items: + $ref: '#/components/schemas/bytes48' + proofs: + title: Proofs + type: array + items: + $ref: '#/components/schemas/bytes48' + blobs: + title: Blobs + type: array + items: + $ref: '#/components/schemas/bytes' diff --git a/src/schemas/base-types.yaml b/src/schemas/base-types.yaml index 71f8984f..f9ff48ca 100644 --- a/src/schemas/base-types.yaml +++ b/src/schemas/base-types.yaml @@ -27,6 +27,10 @@ bytes32: title: 32 hex encoded bytes type: string pattern: ^0x[0-9a-f]{64}$ +bytes48: + title: 48 hex encoded bytes + type: string + pattern: ^0x[0-9a-f]{96}$ bytes256: title: 256 hex encoded bytes type: string