Skip to content
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

feat: exclude empty requests in execution requests list #7196

Draft
wants to merge 1 commit into
base: unstable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/beacon-node/src/execution/engine/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +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 ExecutePayloadResponse =
| {
status: ExecutionPayloadStatus.SYNCING | ExecutionPayloadStatus.ACCEPTED;
Expand Down
93 changes: 75 additions & 18 deletions packages/beacon-node/src/execution/engine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import {
DATA,
QUANTITY,
quantityToBigint,
numberToHex,
} from "../../eth1/provider/utils.js";
import {ExecutionPayloadStatus, BlobsBundle, PayloadAttributes, VersionedHashes} from "./interface.js";
import {ExecutionPayloadStatus, BlobsBundle, PayloadAttributes, VersionedHashes, RequestType} from "./interface.js";
import {WithdrawalV1} from "./payloadIdCache.js";
import {fromHexString} from "@chainsafe/ssz";

export type EngineApiRpcParamTypes = {
/**
Expand Down Expand Up @@ -160,12 +162,12 @@ export type WithdrawalRpc = {
};

/**
* ExecutionRequestsRpc only holds 3 elements in the following order:
* ExecutionRequestsRpc only holds at most 3 elements and no repeated type:
* - ssz'ed DepositRequests
* - ssz'ed WithdrawalRequests
* - ssz'ed ConsolidationRequests
*/
export type ExecutionRequestsRpc = [DepositRequestsRpc, WithdrawalRequestsRpc, ConsolidationRequestsRpc];
export type ExecutionRequestsRpc = (DepositRequestsRpc | WithdrawalRequestsRpc | ConsolidationRequestsRpc)[];

export type DepositRequestsRpc = DATA;
export type WithdrawalRequestsRpc = DATA;
Expand Down Expand Up @@ -394,26 +396,39 @@ export function deserializeWithdrawal(serialized: WithdrawalRpc): capella.Withdr
} as capella.Withdrawal;
}

function prefixRequests(requestsBytes: Uint8Array, requestType: RequestType): Uint8Array {
const prefix = fromHexString(numberToHex(requestType));

const prefixedRequests = new Uint8Array(prefix.length + requestsBytes.length);
prefixedRequests.set(prefix, 0);
prefixedRequests.set(requestsBytes, prefix.length);

return prefixedRequests;
}

function serializeDepositRequests(depositRequests: electra.DepositRequests): DepositRequestsRpc {
return bytesToData(ssz.electra.DepositRequests.serialize(depositRequests));
const requestsBytes = ssz.electra.DepositRequests.serialize(depositRequests);
return bytesToData(prefixRequests(requestsBytes, RequestType.DEPOSIT_REQUEST_TYPE));
}

function deserializeDepositRequests(serialized: DepositRequestsRpc): electra.DepositRequests {
return ssz.electra.DepositRequests.deserialize(dataToBytes(serialized, null));
}

function serializeWithdrawalRequests(withdrawalRequests: electra.WithdrawalRequests): WithdrawalRequestsRpc {
return bytesToData(ssz.electra.WithdrawalRequests.serialize(withdrawalRequests));
const requestsBytes = ssz.electra.WithdrawalRequests.serialize(withdrawalRequests);
return bytesToData(prefixRequests(requestsBytes, RequestType.WITHDRAWAL_REQUEST_TYPE));
}

function deserializeWithdrawalRequest(serialized: WithdrawalRequestsRpc): electra.WithdrawalRequests {
function deserializeWithdrawalRequests(serialized: WithdrawalRequestsRpc): electra.WithdrawalRequests {
return ssz.electra.WithdrawalRequests.deserialize(dataToBytes(serialized, null));
}

function serializeConsolidationRequests(
consolidationRequests: electra.ConsolidationRequests
): ConsolidationRequestsRpc {
return bytesToData(ssz.electra.ConsolidationRequests.serialize(consolidationRequests));
const requestsBytes = ssz.electra.ConsolidationRequests.serialize(consolidationRequests);
return bytesToData(prefixRequests(requestsBytes, RequestType.CONSOLIDATION_REQUEST_TYPE));
}

function deserializeConsolidationRequests(serialized: ConsolidationRequestsRpc): electra.ConsolidationRequests {
Expand All @@ -426,22 +441,64 @@ function deserializeConsolidationRequests(serialized: ConsolidationRequestsRpc):
*/
export function serializeExecutionRequests(executionRequests: ExecutionRequests): ExecutionRequestsRpc {
const {deposits, withdrawals, consolidations} = executionRequests;
const result = [];

return [
serializeDepositRequests(deposits),
serializeWithdrawalRequests(withdrawals),
serializeConsolidationRequests(consolidations),
];
if (deposits.length !== 0) {
result.push(serializeDepositRequests(deposits));
}

if (withdrawals.length !== 0) {
result.push(serializeWithdrawalRequests(withdrawals));
}

if (consolidations.length !== 0) {
result.push(serializeConsolidationRequests(consolidations));
}

return result;
}

export function deserializeExecutionRequests(serialized: ExecutionRequestsRpc): ExecutionRequests {
const [deposits, withdrawals, consolidations] = serialized;

return {
deposits: deserializeDepositRequests(deposits),
withdrawals: deserializeWithdrawalRequest(withdrawals),
consolidations: deserializeConsolidationRequests(consolidations),
const result: ExecutionRequests = {
deposits: [],
withdrawals: [],
consolidations: [],
};

if (serialized.length === 0) {
return result;
}

let prevRequestType: RequestType | undefined;

for (const prefixedRequests of serialized) {
const currentRequestType = RequestType[prefixedRequests[0] as keyof typeof RequestType];
const requests = prefixedRequests.slice(1);

if (prevRequestType !== undefined && prevRequestType >= currentRequestType) {
throw Error(
`Current request type must be larger than previous request type prevRequestType=${prevRequestType} currentRequestType=${currentRequestType}`
);
}

switch (currentRequestType) {
case RequestType.DEPOSIT_REQUEST_TYPE: {
result.deposits = deserializeDepositRequests(requests);
break;
}
case RequestType.WITHDRAWAL_REQUEST_TYPE: {
result.withdrawals = deserializeWithdrawalRequests(requests);
break;
}
case RequestType.CONSOLIDATION_REQUEST_TYPE: {
result.consolidations = deserializeConsolidationRequests(requests);
break;
}
}
prevRequestType = currentRequestType;
}

return result;
}

export function deserializeExecutionPayloadBody(data: ExecutionPayloadBodyRpc | null): ExecutionPayloadBody | null {
Expand Down
Loading