diff --git a/packages/beacon-node/src/api/impl/config/constants.ts b/packages/beacon-node/src/api/impl/config/constants.ts index 6b390727cec..48ca02bf117 100644 --- a/packages/beacon-node/src/api/impl/config/constants.ts +++ b/packages/beacon-node/src/api/impl/config/constants.ts @@ -4,7 +4,9 @@ import { BLOB_TX_TYPE, BLS_WITHDRAWAL_PREFIX, COMPOUNDING_WITHDRAWAL_PREFIX, + CONSOLIDATION_REQUEST_TYPE, DEPOSIT_CONTRACT_TREE_DEPTH, + DEPOSIT_REQUEST_TYPE, DOMAIN_AGGREGATE_AND_PROOF, DOMAIN_APPLICATION_BUILDER, DOMAIN_APPLICATION_MASK, @@ -40,6 +42,7 @@ import { UNSET_DEPOSIT_REQUESTS_START_INDEX, VERSIONED_HASH_VERSION_KZG, WEIGHT_DENOMINATOR, + WITHDRAWAL_REQUEST_TYPE, } from "@lodestar/params"; /** @@ -108,4 +111,7 @@ export const specConstants = { // electra UNSET_DEPOSIT_REQUESTS_START_INDEX, FULL_EXIT_REQUEST_AMOUNT, + DEPOSIT_REQUEST_TYPE, + WITHDRAWAL_REQUEST_TYPE, + CONSOLIDATION_REQUEST_TYPE, }; diff --git a/packages/beacon-node/src/execution/engine/interface.ts b/packages/beacon-node/src/execution/engine/interface.ts index f62bf50d807..40ca06c4d2c 100644 --- a/packages/beacon-node/src/execution/engine/interface.ts +++ b/packages/beacon-node/src/execution/engine/interface.ts @@ -1,4 +1,4 @@ -import {ForkName} from "@lodestar/params"; +import {CONSOLIDATION_REQUEST_TYPE, DEPOSIT_REQUEST_TYPE, ForkName, WITHDRAWAL_REQUEST_TYPE} from "@lodestar/params"; import {ExecutionPayload, ExecutionRequests, Root, RootHex, Wei, capella} from "@lodestar/types"; import {Blob, BlobAndProof, KZGCommitment, KZGProof} from "@lodestar/types/deneb"; @@ -58,11 +58,13 @@ export enum ClientCode { XX = "XX", // unknown } -// Represents request type in ExecutionRequests defined in EIP-7685 -export enum RequestType { - DEPOSIT_REQUEST_TYPE = 0, // 0x00 - WITHDRAWAL_REQUEST_TYPE = 1, // 0x01 - CONSOLIDATION_REQUEST_TYPE = 2, // 0x02 +export type ExecutionRequestType = + | typeof DEPOSIT_REQUEST_TYPE + | typeof WITHDRAWAL_REQUEST_TYPE + | typeof CONSOLIDATION_REQUEST_TYPE; + +export function isExecutionRequestType(type: number): type is ExecutionRequestType { + return type === DEPOSIT_REQUEST_TYPE || type === WITHDRAWAL_REQUEST_TYPE || type === CONSOLIDATION_REQUEST_TYPE; } export type ExecutePayloadResponse = diff --git a/packages/beacon-node/src/execution/engine/types.ts b/packages/beacon-node/src/execution/engine/types.ts index def5831b760..76130dc3ec4 100644 --- a/packages/beacon-node/src/execution/engine/types.ts +++ b/packages/beacon-node/src/execution/engine/types.ts @@ -1,9 +1,12 @@ import { BYTES_PER_FIELD_ELEMENT, BYTES_PER_LOGS_BLOOM, + CONSOLIDATION_REQUEST_TYPE, + DEPOSIT_REQUEST_TYPE, FIELD_ELEMENTS_PER_BLOB, ForkName, ForkSeq, + WITHDRAWAL_REQUEST_TYPE, } from "@lodestar/params"; import {ExecutionPayload, ExecutionRequests, Root, Wei, bellatrix, capella, deneb, electra, ssz} from "@lodestar/types"; import {BlobAndProof} from "@lodestar/types/deneb"; @@ -17,7 +20,14 @@ import { quantityToBigint, quantityToNum, } from "../../eth1/provider/utils.js"; -import {BlobsBundle, ExecutionPayloadStatus, PayloadAttributes, RequestType, VersionedHashes} from "./interface.js"; +import { + BlobsBundle, + ExecutionPayloadStatus, + ExecutionRequestType, + PayloadAttributes, + VersionedHashes, + isExecutionRequestType, +} from "./interface.js"; import {WithdrawalV1} from "./payloadIdCache.js"; export type EngineApiRpcParamTypes = { @@ -407,7 +417,7 @@ export function deserializeWithdrawal(serialized: WithdrawalRpc): capella.Withdr /** * Prepend a single-byte requestType to requestsBytes */ -function prefixRequests(requestsBytes: Uint8Array, requestType: RequestType): Uint8Array { +function prefixRequests(requestsBytes: Uint8Array, requestType: ExecutionRequestType): Uint8Array { const prefixedRequests = new Uint8Array(1 + requestsBytes.length); prefixedRequests[0] = requestType; prefixedRequests.set(requestsBytes, 1); @@ -417,7 +427,7 @@ function prefixRequests(requestsBytes: Uint8Array, requestType: RequestType): Ui function serializeDepositRequests(depositRequests: electra.DepositRequests): DepositRequestsRpc { const requestsBytes = ssz.electra.DepositRequests.serialize(depositRequests); - return bytesToData(prefixRequests(requestsBytes, RequestType.DEPOSIT_REQUEST_TYPE)); + return bytesToData(prefixRequests(requestsBytes, DEPOSIT_REQUEST_TYPE)); } function deserializeDepositRequests(serialized: DepositRequestsRpc): electra.DepositRequests { @@ -426,7 +436,7 @@ function deserializeDepositRequests(serialized: DepositRequestsRpc): electra.Dep function serializeWithdrawalRequests(withdrawalRequests: electra.WithdrawalRequests): WithdrawalRequestsRpc { const requestsBytes = ssz.electra.WithdrawalRequests.serialize(withdrawalRequests); - return bytesToData(prefixRequests(requestsBytes, RequestType.WITHDRAWAL_REQUEST_TYPE)); + return bytesToData(prefixRequests(requestsBytes, WITHDRAWAL_REQUEST_TYPE)); } function deserializeWithdrawalRequests(serialized: WithdrawalRequestsRpc): electra.WithdrawalRequests { @@ -437,7 +447,7 @@ function serializeConsolidationRequests( consolidationRequests: electra.ConsolidationRequests ): ConsolidationRequestsRpc { const requestsBytes = ssz.electra.ConsolidationRequests.serialize(consolidationRequests); - return bytesToData(prefixRequests(requestsBytes, RequestType.CONSOLIDATION_REQUEST_TYPE)); + return bytesToData(prefixRequests(requestsBytes, CONSOLIDATION_REQUEST_TYPE)); } function deserializeConsolidationRequests(serialized: ConsolidationRequestsRpc): electra.ConsolidationRequests { @@ -478,11 +488,21 @@ export function deserializeExecutionRequests(serialized: ExecutionRequestsRpc): return result; } - let prevRequestType: RequestType | undefined; + let prevRequestType: ExecutionRequestType | undefined; + + for (let prefixedRequests of serialized) { + // Slice out 0x so it is easier to extract request type + if (prefixedRequests.startsWith("0x")) { + prefixedRequests = prefixedRequests.slice(2); + } + + const currentRequestType = Number(prefixedRequests.substring(0, 2)); + + if (!isExecutionRequestType(currentRequestType)) { + throw Error(`Invalid request type currentRequestType=${prefixedRequests.substring(0, 2)}`); + } - for (const prefixedRequests of serialized) { - const currentRequestType = RequestType[prefixedRequests[0] as keyof typeof RequestType]; - const requests = prefixedRequests.slice(1); + const requests = prefixedRequests.slice(2); if (prevRequestType !== undefined && prevRequestType >= currentRequestType) { throw Error( @@ -491,15 +511,15 @@ export function deserializeExecutionRequests(serialized: ExecutionRequestsRpc): } switch (currentRequestType) { - case RequestType.DEPOSIT_REQUEST_TYPE: { + case DEPOSIT_REQUEST_TYPE: { result.deposits = deserializeDepositRequests(requests); break; } - case RequestType.WITHDRAWAL_REQUEST_TYPE: { + case WITHDRAWAL_REQUEST_TYPE: { result.withdrawals = deserializeWithdrawalRequests(requests); break; } - case RequestType.CONSOLIDATION_REQUEST_TYPE: { + case CONSOLIDATION_REQUEST_TYPE: { result.consolidations = deserializeConsolidationRequests(requests); break; } diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index 64d3b64dbd6..1fb875801ba 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -270,3 +270,6 @@ export const FINALIZED_ROOT_INDEX_ELECTRA = 41; export const NEXT_SYNC_COMMITTEE_GINDEX_ELECTRA = 87; export const NEXT_SYNC_COMMITTEE_DEPTH_ELECTRA = 6; export const NEXT_SYNC_COMMITTEE_INDEX_ELECTRA = 23; +export const DEPOSIT_REQUEST_TYPE = 0x00; +export const WITHDRAWAL_REQUEST_TYPE = 0x01; +export const CONSOLIDATION_REQUEST_TYPE = 0x02;