From 0c34c20249f361cdfb7bdbc1aa12f5ccaddefc55 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:45:02 +0700 Subject: [PATCH 1/2] Initial commit --- .../blocks/verifyBlocksExecutionPayloads.ts | 5 ++++- .../src/chain/produceBlock/produceBlockBody.ts | 5 +++++ .../beacon-node/src/execution/engine/http.ts | 17 +++++++++++++---- .../src/execution/engine/interface.ts | 5 ++++- .../beacon-node/src/execution/engine/mock.ts | 1 + .../beacon-node/src/execution/engine/types.ts | 18 +++++++++++++++++- packages/types/src/electra/sszTypes.ts | 5 +++-- 7 files changed, 47 insertions(+), 9 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts index e37442bfde8f..fb839f85902e 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts @@ -304,6 +304,8 @@ export async function verifyBlockExecutionPayload( const parentBlockRoot = ForkSeq[fork] >= ForkSeq.deneb ? block.message.parentRoot : undefined; const executionRequests = ForkSeq[fork] >= ForkSeq.electra ? (block.message.body as electra.BeaconBlockBody).executionRequests : undefined; + const targetBlobsPerBlock = + ForkSeq[fork] >= ForkSeq.electra ? 0 : undefined; const logCtx = {slot: block.message.slot, executionBlock: executionPayloadEnabled.blockNumber}; chain.logger.debug("Call engine api newPayload", logCtx); @@ -312,7 +314,8 @@ export async function verifyBlockExecutionPayload( executionPayloadEnabled, versionedHashes, parentBlockRoot, - executionRequests + executionRequests, + targetBlobsPerBlock, ); chain.logger.debug("Receive engine api newPayload result", {...logCtx, status: execResult.status}); diff --git a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts index d26703050070..21a5fc9758ea 100644 --- a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts +++ b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts @@ -586,6 +586,11 @@ function preparePayloadAttributes( (payloadAttributes as deneb.SSEPayloadAttributes["payloadAttributes"]).parentBeaconBlockRoot = parentBlockRoot; } + if (ForkSeq[fork] >= ForkSeq.electra) { + (payloadAttributes as electra.SSEPayloadAttributes["payloadAttributes"]).targetBlobsPerBlock = 0; + (payloadAttributes as electra.SSEPayloadAttributes["payloadAttributes"]).maxBlobsPerBlock = 0; + } + return payloadAttributes; } diff --git a/packages/beacon-node/src/execution/engine/http.ts b/packages/beacon-node/src/execution/engine/http.ts index ea064d2fe816..1a109ce485fb 100644 --- a/packages/beacon-node/src/execution/engine/http.ts +++ b/packages/beacon-node/src/execution/engine/http.ts @@ -201,7 +201,8 @@ export class ExecutionEngineHttp implements IExecutionEngine { executionPayload: ExecutionPayload, versionedHashes?: VersionedHashes, parentBlockRoot?: Root, - executionRequests?: ExecutionRequests + executionRequests?: ExecutionRequests, + maxBlobsPerBlock?: number, ): Promise { const method = ForkSeq[fork] >= ForkSeq.electra @@ -230,7 +231,11 @@ export class ExecutionEngineHttp implements IExecutionEngine { if (executionRequests === undefined) { throw Error(`executionRequests required in notifyNewPayload for fork=${fork}`); } + if (maxBlobsPerBlock === undefined) { + throw Error(`maxBlobsPerBlock required in notifyNewPayload for fork=${fork}`); + } const serializedExecutionRequests = serializeExecutionRequests(executionRequests); + engineRequest = { method: "engine_newPayloadV4", params: [ @@ -238,6 +243,7 @@ export class ExecutionEngineHttp implements IExecutionEngine { serializedVersionedHashes, parentBeaconBlockRoot, serializedExecutionRequests, + numToQuantity(maxBlobsPerBlock), ], methodOpts: notifyNewPayloadOpts, }; @@ -341,11 +347,14 @@ export class ExecutionEngineHttp implements IExecutionEngine { // Once on capella, should this need to be permanently switched to v2 when payload attrs // not provided const method = - ForkSeq[fork] >= ForkSeq.deneb + ForkSeq[fork] >= ForkSeq.electra + ? "engine_forkchoiceUpdatedV4" + : + ForkSeq[fork] >= ForkSeq.deneb ? "engine_forkchoiceUpdatedV3" - : ForkSeq[fork] >= ForkSeq.capella + : ForkSeq[fork] >= ForkSeq.capella ? "engine_forkchoiceUpdatedV2" - : "engine_forkchoiceUpdatedV1"; + : "engine_forkchoiceUpdatedV1"; const payloadAttributesRpc = payloadAttributes ? serializePayloadAttributes(payloadAttributes) : undefined; // If we are just fcUing and not asking execution for payload, retry is not required // and we can move on, as the next fcU will be issued soon on the new slot diff --git a/packages/beacon-node/src/execution/engine/interface.ts b/packages/beacon-node/src/execution/engine/interface.ts index c32cc1bc7215..0022415e9a4e 100644 --- a/packages/beacon-node/src/execution/engine/interface.ts +++ b/packages/beacon-node/src/execution/engine/interface.ts @@ -88,6 +88,8 @@ export type PayloadAttributes = { suggestedFeeRecipient: string; withdrawals?: capella.Withdrawal[]; parentBeaconBlockRoot?: Uint8Array; + targetBlobsPerBlock?: number; + maxBlobsperBlock?: number; }; export type BlobsBundle = { @@ -135,7 +137,8 @@ export interface IExecutionEngine { executionPayload: ExecutionPayload, versionedHashes?: VersionedHashes, parentBeaconBlockRoot?: Root, - executionRequests?: ExecutionRequests + executionRequests?: ExecutionRequests, + targetBlobsPerBlock?: number, ): Promise; /** diff --git a/packages/beacon-node/src/execution/engine/mock.ts b/packages/beacon-node/src/execution/engine/mock.ts index 8a84d2b0148e..dc2945cf1255 100644 --- a/packages/beacon-node/src/execution/engine/mock.ts +++ b/packages/beacon-node/src/execution/engine/mock.ts @@ -92,6 +92,7 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend { engine_forkchoiceUpdatedV1: this.notifyForkchoiceUpdate.bind(this), engine_forkchoiceUpdatedV2: this.notifyForkchoiceUpdate.bind(this), engine_forkchoiceUpdatedV3: this.notifyForkchoiceUpdate.bind(this), + engine_forkchoiceUpdatedV4: this.notifyForkchoiceUpdate.bind(this), engine_getPayloadV1: this.getPayload.bind(this), engine_getPayloadV2: this.getPayload.bind(this), engine_getPayloadV3: this.getPayload.bind(this), diff --git a/packages/beacon-node/src/execution/engine/types.ts b/packages/beacon-node/src/execution/engine/types.ts index f35a63aa3d96..497dbef58ce2 100644 --- a/packages/beacon-node/src/execution/engine/types.ts +++ b/packages/beacon-node/src/execution/engine/types.ts @@ -27,7 +27,7 @@ export type EngineApiRpcParamTypes = { engine_newPayloadV1: [ExecutionPayloadRpc]; engine_newPayloadV2: [ExecutionPayloadRpc]; engine_newPayloadV3: [ExecutionPayloadRpc, VersionedHashesRpc, DATA]; - engine_newPayloadV4: [ExecutionPayloadRpc, VersionedHashesRpc, DATA, ExecutionRequestsRpc]; + engine_newPayloadV4: [ExecutionPayloadRpc, VersionedHashesRpc, DATA, ExecutionRequestsRpc, QUANTITY]; /** * 1. Object - Payload validity status with respect to the consensus rules: * - blockHash: DATA, 32 Bytes - block hash value of the payload @@ -45,6 +45,10 @@ export type EngineApiRpcParamTypes = { forkChoiceData: {headBlockHash: DATA; safeBlockHash: DATA; finalizedBlockHash: DATA}, payloadAttributes?: PayloadAttributesRpc, ]; + engine_forkchoiceUpdatedV4: [ + forkChoiceData: {headBlockHash: DATA; safeBlockHash: DATA; finalizedBlockHash: DATA}, + payloadAttributes?: PayloadAttributesRpc, + ]; /** * 1. payloadId: QUANTITY, 64 Bits - Identifier of the payload building process */ @@ -99,6 +103,10 @@ export type EngineApiRpcReturnTypes = { payloadStatus: PayloadStatus; payloadId: QUANTITY | null; }; + engine_forkchoiceUpdatedV4: { + payloadStatus: PayloadStatus; + payloadId: QUANTITY | null; + }; /** * payloadId | Error: QUANTITY, 64 Bits - Identifier of the payload building process */ @@ -155,6 +163,7 @@ export type ExecutionPayloadRpc = { blobGasUsed?: QUANTITY; // DENEB excessBlobGas?: QUANTITY; // DENEB parentBeaconBlockRoot?: QUANTITY; // DENEB + targetBlobsPerBlock?: QUANTITY; // ELECTRA }; export type WithdrawalRpc = { @@ -193,6 +202,9 @@ export type PayloadAttributesRpc = { withdrawals?: WithdrawalRpc[]; /** DATA, 32 Bytes - value for the parentBeaconBlockRoot to be used for building block */ parentBeaconBlockRoot?: DATA; + // TODO + targetBlobsPerBlock?: QUANTITY; + maxBlobsPerBlock?: QUANTITY; }; export type ClientVersionRpc = { @@ -348,6 +360,8 @@ export function serializePayloadAttributes(data: PayloadAttributes): PayloadAttr suggestedFeeRecipient: data.suggestedFeeRecipient, withdrawals: data.withdrawals?.map(serializeWithdrawal), parentBeaconBlockRoot: data.parentBeaconBlockRoot ? bytesToData(data.parentBeaconBlockRoot) : undefined, + targetBlobsPerBlock: data.targetBlobsPerBlock ? numToQuantity(data.targetBlobsPerBlock) : undefined, + maxBlobsPerBlock: data.maxBlobsperBlock ? numToQuantity(data.maxBlobsperBlock) : undefined, }; } @@ -364,6 +378,8 @@ export function deserializePayloadAttributes(data: PayloadAttributesRpc): Payloa suggestedFeeRecipient: data.suggestedFeeRecipient, withdrawals: data.withdrawals?.map((withdrawal) => deserializeWithdrawal(withdrawal)), parentBeaconBlockRoot: data.parentBeaconBlockRoot ? dataToBytes(data.parentBeaconBlockRoot, 32) : undefined, + targetBlobsPerBlock: data.targetBlobsPerBlock ? quantityToNum(data.targetBlobsPerBlock) : undefined, + maxBlobsperBlock: data.maxBlobsPerBlock ? quantityToNum(data.maxBlobsPerBlock) : undefined, }; } diff --git a/packages/types/src/electra/sszTypes.ts b/packages/types/src/electra/sszTypes.ts index f6b6c745803e..ece45a2e9322 100644 --- a/packages/types/src/electra/sszTypes.ts +++ b/packages/types/src/electra/sszTypes.ts @@ -392,8 +392,9 @@ export const LightClientStore = new ContainerType( // PayloadAttributes primarily for SSE event export const PayloadAttributes = new ContainerType( { - ...capellaSsz.PayloadAttributes.fields, - parentBeaconBlockRoot: Root, + ...denebSsz.PayloadAttributes.fields, + targetBlobsPerBlock: UintNum64, + maxBlobsPerBlock: UintNum64, }, {typeName: "PayloadAttributes", jsonCase: "eth2"} ); From 26b6bc6e02a4a36fb22baae2398d301183c1ca28 Mon Sep 17 00:00:00 2001 From: NC <17676176+ensi321@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:31:42 +0700 Subject: [PATCH 2/2] Add flags --- .../blocks/verifyBlocksExecutionPayloads.ts | 5 ++--- packages/beacon-node/src/chain/options.ts | 4 ++++ .../chain/produceBlock/produceBlockBody.ts | 10 ++++++++-- .../beacon-node/src/execution/engine/http.ts | 9 ++++----- .../src/execution/engine/interface.ts | 2 +- .../src/options/beaconNodeOptions/chain.ts | 20 +++++++++++++++++++ 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts index fb839f85902e..ab20af511def 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts @@ -304,8 +304,7 @@ export async function verifyBlockExecutionPayload( const parentBlockRoot = ForkSeq[fork] >= ForkSeq.deneb ? block.message.parentRoot : undefined; const executionRequests = ForkSeq[fork] >= ForkSeq.electra ? (block.message.body as electra.BeaconBlockBody).executionRequests : undefined; - const targetBlobsPerBlock = - ForkSeq[fork] >= ForkSeq.electra ? 0 : undefined; + const targetBlobsPerBlock = ForkSeq[fork] >= ForkSeq.electra ? 0 : undefined; const logCtx = {slot: block.message.slot, executionBlock: executionPayloadEnabled.blockNumber}; chain.logger.debug("Call engine api newPayload", logCtx); @@ -315,7 +314,7 @@ export async function verifyBlockExecutionPayload( versionedHashes, parentBlockRoot, executionRequests, - targetBlobsPerBlock, + targetBlobsPerBlock ); chain.logger.debug("Receive engine api newPayload result", {...logCtx, status: execResult.status}); diff --git a/packages/beacon-node/src/chain/options.ts b/packages/beacon-node/src/chain/options.ts index f87fffd7b363..c7a8ba779494 100644 --- a/packages/beacon-node/src/chain/options.ts +++ b/packages/beacon-node/src/chain/options.ts @@ -41,6 +41,8 @@ export type IChainOptions = BlockProcessOpts & archiveBlobEpochs?: number; nHistoricalStates?: boolean; nHistoricalStatesFileDataStore?: boolean; + targetBlobsPerBlock?: number; + maxBlobsPerBlock?: number; }; export type BlockProcessOpts = { @@ -119,4 +121,6 @@ export const defaultChainOptions: IChainOptions = { nHistoricalStatesFileDataStore: false, maxBlockStates: DEFAULT_MAX_BLOCK_STATES, maxCPStateEpochsInMemory: DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY, + targetBlobsPerBlock: 4, // This is arbitrary as we have not agreed on an appropriate value yet + maxBlobsPerBlock: 8, // This is arbitrary as we have not agreed on an appropriate value yet }; diff --git a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts index 21a5fc9758ea..500f8438bb51 100644 --- a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts +++ b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts @@ -40,6 +40,7 @@ import {numToQuantity} from "../../eth1/provider/utils.js"; import {IExecutionBuilder, IExecutionEngine, PayloadAttributes, PayloadId} from "../../execution/index.js"; import type {BeaconChain} from "../chain.js"; import {CommonBlockBody} from "../interface.js"; +import {IChainOptions} from "../options.js"; import {validateBlobsAndKzgCommitments} from "./validateBlobsAndKzgCommitments.js"; // Time to provide the EL to generate a payload from new payload id @@ -375,6 +376,7 @@ export async function prepareExecutionPayload( eth1: IEth1ForBlockProduction; executionEngine: IExecutionEngine; config: ChainForkConfig; + opts: IChainOptions; }, logger: Logger, fork: ForkExecution, @@ -516,6 +518,7 @@ export async function getPayloadAttributesForSSE( chain: { eth1: IEth1ForBlockProduction; config: ChainForkConfig; + opts: IChainOptions; }, { prepareState, @@ -553,6 +556,7 @@ function preparePayloadAttributes( fork: ForkExecution, chain: { config: ChainForkConfig; + opts: IChainOptions; }, { prepareState, @@ -587,8 +591,10 @@ function preparePayloadAttributes( } if (ForkSeq[fork] >= ForkSeq.electra) { - (payloadAttributes as electra.SSEPayloadAttributes["payloadAttributes"]).targetBlobsPerBlock = 0; - (payloadAttributes as electra.SSEPayloadAttributes["payloadAttributes"]).maxBlobsPerBlock = 0; + (payloadAttributes as electra.SSEPayloadAttributes["payloadAttributes"]).targetBlobsPerBlock = + chain.opts.targetBlobsPerBlock ?? 4; + (payloadAttributes as electra.SSEPayloadAttributes["payloadAttributes"]).maxBlobsPerBlock = + chain.opts.maxBlobsPerBlock ?? 8; } return payloadAttributes; diff --git a/packages/beacon-node/src/execution/engine/http.ts b/packages/beacon-node/src/execution/engine/http.ts index 1a109ce485fb..50cfb045e3d2 100644 --- a/packages/beacon-node/src/execution/engine/http.ts +++ b/packages/beacon-node/src/execution/engine/http.ts @@ -202,7 +202,7 @@ export class ExecutionEngineHttp implements IExecutionEngine { versionedHashes?: VersionedHashes, parentBlockRoot?: Root, executionRequests?: ExecutionRequests, - maxBlobsPerBlock?: number, + maxBlobsPerBlock?: number ): Promise { const method = ForkSeq[fork] >= ForkSeq.electra @@ -349,11 +349,10 @@ export class ExecutionEngineHttp implements IExecutionEngine { const method = ForkSeq[fork] >= ForkSeq.electra ? "engine_forkchoiceUpdatedV4" - : - ForkSeq[fork] >= ForkSeq.deneb - ? "engine_forkchoiceUpdatedV3" + : ForkSeq[fork] >= ForkSeq.deneb + ? "engine_forkchoiceUpdatedV3" : ForkSeq[fork] >= ForkSeq.capella - ? "engine_forkchoiceUpdatedV2" + ? "engine_forkchoiceUpdatedV2" : "engine_forkchoiceUpdatedV1"; const payloadAttributesRpc = payloadAttributes ? serializePayloadAttributes(payloadAttributes) : undefined; // If we are just fcUing and not asking execution for payload, retry is not required diff --git a/packages/beacon-node/src/execution/engine/interface.ts b/packages/beacon-node/src/execution/engine/interface.ts index 0022415e9a4e..b6ce0394fa78 100644 --- a/packages/beacon-node/src/execution/engine/interface.ts +++ b/packages/beacon-node/src/execution/engine/interface.ts @@ -138,7 +138,7 @@ export interface IExecutionEngine { versionedHashes?: VersionedHashes, parentBeaconBlockRoot?: Root, executionRequests?: ExecutionRequests, - targetBlobsPerBlock?: number, + targetBlobsPerBlock?: number ): Promise; /** diff --git a/packages/cli/src/options/beaconNodeOptions/chain.ts b/packages/cli/src/options/beaconNodeOptions/chain.ts index 21c05545c43d..057bcb477673 100644 --- a/packages/cli/src/options/beaconNodeOptions/chain.ts +++ b/packages/cli/src/options/beaconNodeOptions/chain.ts @@ -33,6 +33,8 @@ export type ChainArgs = { "chain.nHistoricalStatesFileDataStore"?: boolean; "chain.maxBlockStates"?: number; "chain.maxCPStateEpochsInMemory"?: number; + "chain.targetBlobsPerBlock"?: number; + "chain.maxBlobsPerBlock"?: number; }; export function parseArgs(args: ChainArgs): IBeaconNodeOptions["chain"] { @@ -68,6 +70,8 @@ export function parseArgs(args: ChainArgs): IBeaconNodeOptions["chain"] { args["chain.nHistoricalStatesFileDataStore"] ?? defaultOptions.chain.nHistoricalStatesFileDataStore, maxBlockStates: args["chain.maxBlockStates"] ?? defaultOptions.chain.maxBlockStates, maxCPStateEpochsInMemory: args["chain.maxCPStateEpochsInMemory"] ?? defaultOptions.chain.maxCPStateEpochsInMemory, + targetBlobsPerBlock: args["chain.targetBlobsPerBlock"] ?? defaultOptions.chain.targetBlobsPerBlock, + maxBlobsPerBlock: args["chain.maxBlobsPerBlock"] ?? defaultOptions.chain.maxBlobsPerBlock, }; } @@ -284,4 +288,20 @@ Will double processing times. Use only for debugging purposes.", default: defaultOptions.chain.maxCPStateEpochsInMemory, group: "chain", }, + + "chain.targetBlobsPerBlock": { + hidden: true, + description: "Target blobs per block per EIP-7742", + type: "number", + default: defaultOptions.chain.targetBlobsPerBlock, + group: "chain", + }, + + "chain.maxBlobsPerBlock": { + hidden: true, + description: "Max blobs per block per EIP-7742", + type: "number", + default: defaultOptions.chain.maxBlobsPerBlock, + group: "chain", + }, };