diff --git a/packages/api/src/beacon/routes/validator.ts b/packages/api/src/beacon/routes/validator.ts index bcb4f08eab2b..190f5413c96a 100644 --- a/packages/api/src/beacon/routes/validator.ts +++ b/packages/api/src/beacon/routes/validator.ts @@ -12,8 +12,6 @@ import { Slot, ssz, ValidatorIndex, - Wei, - Gwei, ProducedBlockSource, stringType, } from "@lodestar/types"; @@ -21,6 +19,7 @@ import {AnyPostEndpoint, Endpoint, ResponseCodec, RouteDefinitions, Schema} from import {fromGraffitiHex, toForkName, toGraffitiHex} from "../../utils/serdes.js"; import { ArrayOf, + BlockValuesMeta, EmptyMeta, EmptyMetaCodec, EmptyResponseCodec, @@ -31,6 +30,7 @@ import { ExecutionOptimisticMeta, VersionCodec, VersionMeta, + WithBlockValues, WithMeta, WithVersion, } from "../../utils/codecs.js"; @@ -52,12 +52,10 @@ export type ExtraProduceBlockOps = { blindedLocal?: boolean; }; -export type ProduceBlockV3Meta = { - version: ForkName; +export type ProduceBlockMeta = VersionMeta & BlockValuesMeta; +export type ProduceBlockV3Meta = ProduceBlockMeta & { executionPayloadBlinded: boolean; executionPayloadSource: ProducedBlockSource; - executionPayloadValue: Wei; - consensusBlockValue: Gwei; }; // See /packages/api/src/routes/index.ts for reasoning and instructions to add new routes @@ -312,7 +310,7 @@ export type Endpoints = { }; }, allForks.BeaconBlockOrContents, - VersionMeta + ProduceBlockMeta >; /** @@ -356,7 +354,7 @@ export type Endpoints = { }, {params: {slot: number}; query: {randao_reveal: string; graffiti: string}}, allForks.BlindedBeaconBlock, - VersionMeta + ProduceBlockMeta >; /** @@ -673,7 +671,7 @@ export const definitions: RouteDefinitions = { (fork) => (isForkBlobs(fork) ? BlockContentsType : ssz[fork].BeaconBlock) as Type ), - meta: VersionCodec, + meta: WithBlockValues(VersionCodec), }, }, produceBlockV3: { @@ -733,13 +731,11 @@ export const definitions: RouteDefinitions = { ? BlockContentsType : ssz[version].BeaconBlock) as Type ), - meta: { + meta: WithBlockValues({ toJson: (meta) => ({ version: meta.version, execution_payload_blinded: meta.executionPayloadBlinded, execution_payload_source: meta.executionPayloadSource, - execution_payload_value: meta.executionPayloadValue, - consensus_block_value: meta.consensusBlockValue, }), fromJson: (val) => { const executionPayloadBlinded = (val as {execution_payload_blinded: boolean}).execution_payload_blinded; @@ -753,17 +749,12 @@ export const definitions: RouteDefinitions = { version: toForkName((val as {version: string}).version), executionPayloadBlinded, executionPayloadSource, - // For cross client usage where beacon or validator are of separate clients, executionPayloadValue could be missing - executionPayloadValue: BigInt((val as {execution_payload_value: string}).execution_payload_value ?? "0"), - consensusBlockValue: BigInt((val as {consensus_block_value: string}).consensus_block_value ?? "0"), }; }, toHeadersObject: (meta) => ({ "Eth-Consensus-Version": meta.version, "Eth-Execution-Payload-Blinded": String(meta.executionPayloadBlinded), "Eth-Execution-Payload-Source": String(meta.executionPayloadSource), - "Eth-Execution-Payload-Value": String(meta.executionPayloadValue), - "Eth-Consensus-Block-Value": String(meta.consensusBlockValue), }), fromHeaders: (headers) => { const executionPayloadBlinded = Boolean(headers.get("Eth-Execution-Payload-Blinded")!); @@ -777,12 +768,9 @@ export const definitions: RouteDefinitions = { version: toForkName(headers.get("Eth-Consensus-Version")!), executionPayloadBlinded, executionPayloadSource, - // For cross client usage where beacon or validator are of separate clients, executionPayloadValue could be missing - executionPayloadValue: BigInt(headers.get("Eth-Execution-Payload-Value") ?? "0"), - consensusBlockValue: BigInt(headers.get("Eth-Consensus-Block-Value") ?? "0"), }; }, - }, + }), }, }, produceBlindedBlock: { @@ -808,7 +796,7 @@ export const definitions: RouteDefinitions = { }, resp: { data: WithVersion((fork) => ssz.allForksBlinded[isForkExecution(fork) ? fork : ForkName.bellatrix].BeaconBlock), - meta: VersionCodec, + meta: WithBlockValues(VersionCodec), }, }, produceAttestationData: { diff --git a/packages/api/src/utils/codecs.ts b/packages/api/src/utils/codecs.ts index 04a963932993..43ad3f503c27 100644 --- a/packages/api/src/utils/codecs.ts +++ b/packages/api/src/utils/codecs.ts @@ -2,7 +2,7 @@ import {ArrayType, ListBasicType, ListCompositeType, Type, isBasicType, isCompositeType} from "@chainsafe/ssz"; import {ForkName} from "@lodestar/params"; -import {Root} from "@lodestar/types"; +import {Gwei, Root, Wei} from "@lodestar/types"; import {fromHex, toHex} from "@lodestar/utils"; import {ExecutionOptimistic} from "../beacon/routes/beacon/block.js"; import { @@ -29,6 +29,7 @@ export type ExecutionOptimisticMeta = {executionOptimistic: ExecutionOptimistic} export type VersionMeta = {version: ForkName}; export type ExecutionOptimisticAndVersionMeta = ExecutionOptimisticMeta & VersionMeta; export type ExecutionOptimisticAndDependentRootMeta = {executionOptimistic: ExecutionOptimistic; dependentRoot: Root}; +export type BlockValuesMeta = {executionPayloadValue: Wei; consensusBlockValue: Gwei}; /** Shortcut for routes that have no params, query */ export const EmptyGetRequestCodec: GetRequestCodec = { @@ -156,6 +157,35 @@ export const ExecutionOptimisticAndDependentRootCodec: ResponseMetadataCodec>( + meta: ResponseMetadataCodec> +): ResponseMetadataCodec { + return { + toJson: (val) => ({ + ...(meta.toJson(val) as Record), + execution_payload_value: val.executionPayloadValue.toString(), + consensus_block_value: val.consensusBlockValue.toString(), + }), + fromJson: (val) => ({ + ...(meta.fromJson(val) as M), + // For cross client usage where beacon or validator are of separate clients, executionPayloadValue could be missing + executionPayloadValue: BigInt((val as {execution_payload_value: string}).execution_payload_value ?? "0"), + consensusBlockValue: BigInt((val as {consensus_block_value: string}).consensus_block_value ?? "0"), + }), + toHeadersObject: (val) => ({ + ...meta.toHeadersObject(val), + "Eth-Execution-Payload-Value": val.executionPayloadValue.toString(), + "Eth-Consensus-Block-Value": val.consensusBlockValue.toString(), + }), + fromHeaders: (val) => ({ + ...(meta.fromHeaders(val) as M), + // For cross client usage where beacon or validator are of separate clients, executionPayloadValue could be missing + executionPayloadValue: BigInt(val.get("Eth-Execution-Payload-Value") ?? "0"), + consensusBlockValue: BigInt(val.get("Eth-Consensus-Block-Value") ?? "0"), + }), + }; +} + export const EmptyResponseCodec: ResponseCodec = { data: EmptyResponseDataCodec, meta: EmptyMetaCodec,