Skip to content
Closed
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
20 changes: 14 additions & 6 deletions packages/beacon-node/src/execution/engine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -510,13 +510,21 @@ function prefixRequests(requestsBytes: Uint8Array, requestType: ExecutionRequest
return prefixedRequests;
}

function serializeDepositRequests(depositRequests: electra.DepositRequests): DepositRequestsRpc {
const requestsBytes = ssz.electra.DepositRequests.serialize(depositRequests);
function serializeDepositRequests(
fork: ForkName,
depositRequests: electra.DepositRequests | gloas.DepositRequests
): DepositRequestsRpc {
const requestsType = ForkSeq[fork] >= ForkSeq.gloas ? ssz.gloas.DepositRequests : ssz.electra.DepositRequests;
const requestsBytes = requestsType.serialize(depositRequests);
return bytesToData(prefixRequests(requestsBytes, DEPOSIT_REQUEST_TYPE));
}

function deserializeDepositRequests(serialized: DepositRequestsRpc): electra.DepositRequests {
return ssz.electra.DepositRequests.deserialize(dataToBytes(serialized, null));
function deserializeDepositRequests(
fork: ForkName,
serialized: DepositRequestsRpc
): electra.DepositRequests | gloas.DepositRequests {
const requestsType = ForkSeq[fork] >= ForkSeq.gloas ? ssz.gloas.DepositRequests : ssz.electra.DepositRequests;
return requestsType.deserialize(dataToBytes(serialized, null));
}

function serializeWithdrawalRequests(withdrawalRequests: electra.WithdrawalRequests): WithdrawalRequestsRpc {
Expand Down Expand Up @@ -571,7 +579,7 @@ export function serializeExecutionRequests(fork: ForkName, executionRequests: Ex
const result: ExecutionRequestsRpc = [];

if (deposits.length !== 0) {
result.push(serializeDepositRequests(deposits));
result.push(serializeDepositRequests(fork, deposits));
}

if (withdrawals.length !== 0) {
Expand Down Expand Up @@ -637,7 +645,7 @@ export function deserializeExecutionRequests(fork: ForkName, serialized: Executi

switch (currentRequestType) {
case DEPOSIT_REQUEST_TYPE: {
result.deposits = deserializeDepositRequests(requests);
result.deposits = deserializeDepositRequests(fork, requests);
break;
}
case WITHDRAWAL_REQUEST_TYPE: {
Expand Down
19 changes: 19 additions & 0 deletions packages/beacon-node/test/unit/execution/engine/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CONSOLIDATION_REQUEST_TYPE,
DEPOSIT_REQUEST_TYPE,
ForkName,
MAX_DEPOSIT_REQUESTS_PER_PAYLOAD,
WITHDRAWAL_REQUEST_TYPE,
} from "@lodestar/params";
import {ExecutionRequests, gloas, ssz} from "@lodestar/types";
Expand Down Expand Up @@ -91,6 +92,24 @@ describe("execution / engine / types", () => {
expect(Number(serialized[1].substring(0, 2))).toBe(BUILDER_EXIT_REQUEST_TYPE);
});

it("should serialize Gloas deposit requests beyond the Electra limit", () => {
const executionRequests: gloas.ExecutionRequests = {
deposits: Array.from({length: MAX_DEPOSIT_REQUESTS_PER_PAYLOAD + 1}, () =>
ssz.electra.DepositRequest.defaultValue()
),
withdrawals: [],
consolidations: [],
builderDeposits: [],
builderExits: [],
};

const serialized = serializeExecutionRequests(ForkName.gloas, executionRequests);
const deserialized = deserializeExecutionRequests(ForkName.gloas, serialized) as gloas.ExecutionRequests;

expect(serialized.length).toBe(1);
expect(deserialized.deposits.length).toBe(MAX_DEPOSIT_REQUESTS_PER_PAYLOAD + 1);
});

it("should skip builder requests pre-gloas", () => {
const executionRequests: gloas.ExecutionRequests = {
deposits: [],
Expand Down
8 changes: 7 additions & 1 deletion packages/types/src/gloas/sszTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ const {
EpochInf,
} = primitiveSsz;

// SSZ implementation bound for Gloas deposit requests; consensus-specs uses the
// same value for max-size helpers after removing the CL-side request count limit.
const GLOAS_DEPOSIT_REQUESTS_SSZ_LIMIT = 40_000;

export const Builder = new ContainerType(
{
pubkey: BLSPubkey,
Expand Down Expand Up @@ -95,6 +99,8 @@ export const BuilderDepositRequests = new ListCompositeType(
MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD
);

export const DepositRequests = new ListCompositeType(electraSsz.DepositRequest, GLOAS_DEPOSIT_REQUESTS_SSZ_LIMIT);

export const BuilderExitRequest = new ContainerType(
{
sourceAddress: ExecutionAddress,
Expand All @@ -108,7 +114,7 @@ export const BuilderExitRequests = new ListCompositeType(BuilderExitRequest, MAX
// New in GLOAS:EIP8282 — extends electra ExecutionRequests with builder deposits and exits
export const ExecutionRequests = new ContainerType(
{
deposits: electraSsz.DepositRequests,
deposits: DepositRequests,
withdrawals: electraSsz.WithdrawalRequests,
consolidations: electraSsz.ConsolidationRequests,
builderDeposits: BuilderDepositRequests,
Expand Down
1 change: 1 addition & 0 deletions packages/types/src/gloas/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type BuilderPendingWithdrawal = ValueOf<typeof ssz.BuilderPendingWithdraw
export type BuilderPendingPayment = ValueOf<typeof ssz.BuilderPendingPayment>;
export type BuilderDepositRequest = ValueOf<typeof ssz.BuilderDepositRequest>;
export type BuilderDepositRequests = ValueOf<typeof ssz.BuilderDepositRequests>;
export type DepositRequests = ValueOf<typeof ssz.DepositRequests>;
export type BuilderExitRequest = ValueOf<typeof ssz.BuilderExitRequest>;
export type BuilderExitRequests = ValueOf<typeof ssz.BuilderExitRequests>;
export type ExecutionRequests = ValueOf<typeof ssz.ExecutionRequests>;
Expand Down
12 changes: 12 additions & 0 deletions packages/types/test/unit/gloas/executionRequestsJson.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {describe, expect, it} from "vitest";
import {MAX_DEPOSIT_REQUESTS_PER_PAYLOAD} from "@lodestar/params";
import {ssz} from "../../../src/index.js";

// Ensures the gloas-extended ExecutionRequests (and the ExecutionPayloadEnvelope that carries it)
Expand Down Expand Up @@ -61,6 +62,17 @@ describe("gloas ExecutionRequests JSON shape", () => {
expect(ssz.gloas.ExecutionRequests.hashTreeRoot(back)).toEqual(ssz.gloas.ExecutionRequests.hashTreeRoot(value));
});

it("ExecutionRequests accepts deposits beyond the Electra request limit", () => {
const value = ssz.gloas.ExecutionRequests.defaultValue();
value.deposits = Array.from({length: MAX_DEPOSIT_REQUESTS_PER_PAYLOAD + 1}, () =>
ssz.electra.DepositRequest.defaultValue()
);

const back = ssz.gloas.ExecutionRequests.deserialize(ssz.gloas.ExecutionRequests.serialize(value));

expect(back.deposits.length).toBe(MAX_DEPOSIT_REQUESTS_PER_PAYLOAD + 1);
});

it("ExecutionPayloadEnvelope round-trips through JSON with builder requests populated", () => {
const envelope = ssz.gloas.ExecutionPayloadEnvelope.defaultValue();
envelope.executionRequests.builderDeposits.push({
Expand Down
Loading