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: add engine_getPayloadBodiesByHash and ByRange V2 #6852

Merged
merged 3 commits into from
Jun 8, 2024
Merged
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
2 changes: 1 addition & 1 deletion packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ export class BeaconChain implements IBeaconChain {
// Will resolve this later
// if (cpEpoch >= (this.config.ELECTRA_FORK_EPOCH ?? Infinity)) {
// // finalizedState can be safely casted to Electra state since cp is already post-Electra
// if (finalizedState.eth1DepositIndex >= (finalizedState as CachedBeaconStateElectra).depositReceiptsStartIndex) {
// if (finalizedState.eth1DepositIndex >= (finalizedState as CachedBeaconStateElectra).depositRequestsStartIndex) {
// // Signal eth1 to stop polling eth1Data
// this.eth1.stopPollingEth1Data();
// }
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/eth1/eth1DepositDataTracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ export class Eth1DepositDataTracker {
async getEth1DataAndDeposits(state: CachedBeaconStateAllForks): Promise<Eth1DataAndDeposits> {
if (
state.epochCtx.isAfterElectra() &&
state.eth1DepositIndex >= (state as CachedBeaconStateElectra).depositReceiptsStartIndex
state.eth1DepositIndex >= (state as CachedBeaconStateElectra).depositRequestsStartIndex
) {
// No need to poll eth1Data since Electra deprecates the mechanism after depositReceiptsStartIndex is reached
// No need to poll eth1Data since Electra deprecates the mechanism after depositRequestsStartIndex is reached
return {eth1Data: state.eth1Data, deposits: []};
}
const eth1Data = this.forcedEth1DataVote ?? (await this.getEth1Data(state));
Expand Down
9 changes: 6 additions & 3 deletions packages/beacon-node/src/execution/engine/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,8 +396,9 @@ export class ExecutionEngineHttp implements IExecutionEngine {
this.payloadIdCache.prune();
}

async getPayloadBodiesByHash(blockHashes: RootHex[]): Promise<(ExecutionPayloadBody | null)[]> {
const method = "engine_getPayloadBodiesByHashV1";
async getPayloadBodiesByHash(fork: ForkName, blockHashes: RootHex[]): Promise<(ExecutionPayloadBody | null)[]> {
const method =
ForkSeq[fork] >= ForkSeq.electra ? "engine_getPayloadBodiesByHashV2" : "engine_getPayloadBodiesByHashV1";
assertReqSizeLimit(blockHashes.length, 32);
const response = await this.rpc.fetchWithRetries<
EngineApiRpcReturnTypes[typeof method],
Expand All @@ -407,10 +408,12 @@ export class ExecutionEngineHttp implements IExecutionEngine {
}

async getPayloadBodiesByRange(
fork: ForkName,
startBlockNumber: number,
blockCount: number
): Promise<(ExecutionPayloadBody | null)[]> {
const method = "engine_getPayloadBodiesByRangeV1";
const method =
ForkSeq[fork] >= ForkSeq.electra ? "engine_getPayloadBodiesByRangeV2" : "engine_getPayloadBodiesByRangeV1";
assertReqSizeLimit(blockCount, 32);
const start = numToQuantity(startBlockNumber);
const count = numToQuantity(blockCount);
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/src/execution/engine/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ export interface IExecutionEngine {
shouldOverrideBuilder?: boolean;
}>;

getPayloadBodiesByHash(blockHash: DATA[]): Promise<(ExecutionPayloadBody | null)[]>;
getPayloadBodiesByHash(fork: ForkName, blockHash: DATA[]): Promise<(ExecutionPayloadBody | null)[]>;

getPayloadBodiesByRange(start: number, count: number): Promise<(ExecutionPayloadBody | null)[]>;
getPayloadBodiesByRange(fork: ForkName, start: number, count: number): Promise<(ExecutionPayloadBody | null)[]>;

getState(): ExecutionEngineState;
}
2 changes: 2 additions & 0 deletions packages/beacon-node/src/execution/engine/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ export class ExecutionEngineMockBackend implements JsonRpcBackend {
engine_getPayloadV3: this.getPayload.bind(this),
engine_getPayloadV4: this.getPayload.bind(this),
engine_getPayloadBodiesByHashV1: this.getPayloadBodiesByHash.bind(this),
engine_getPayloadBodiesByHashV2: this.getPayloadBodiesByHash.bind(this),
engine_getPayloadBodiesByRangeV1: this.getPayloadBodiesByRange.bind(this),
engine_getPayloadBodiesByRangeV2: this.getPayloadBodiesByRange.bind(this),
};
}

Expand Down
10 changes: 7 additions & 3 deletions packages/beacon-node/src/execution/engine/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ export type EngineApiRpcParamTypes = {
* 1. Array of DATA - Array of block_hash field values of the ExecutionPayload structure
* */
engine_getPayloadBodiesByHashV1: DATA[][];
engine_getPayloadBodiesByHashV2: DATA[][];

/**
* 1. start: QUANTITY, 64 bits - Starting block number
* 2. count: QUANTITY, 64 bits - Number of blocks to return
*/
engine_getPayloadBodiesByRangeV1: [start: QUANTITY, count: QUANTITY];
engine_getPayloadBodiesByRangeV2: [start: QUANTITY, count: QUANTITY];
};

export type PayloadStatus = {
Expand Down Expand Up @@ -102,8 +104,10 @@ export type EngineApiRpcReturnTypes = {
engine_getPayloadV4: ExecutionPayloadResponse;

engine_getPayloadBodiesByHashV1: (ExecutionPayloadBodyRpc | null)[];
engine_getPayloadBodiesByHashV2: (ExecutionPayloadBodyRpc | null)[];

engine_getPayloadBodiesByRangeV1: (ExecutionPayloadBodyRpc | null)[];
engine_getPayloadBodiesByRangeV2: (ExecutionPayloadBodyRpc | null)[];
};

type ExecutionPayloadRpcWithValue = {
Expand Down Expand Up @@ -217,8 +221,8 @@ export function serializeExecutionPayload(fork: ForkName, data: allForks.Executi

// ELECTRA adds depositRequests/depositRequests to the ExecutionPayload
if (ForkSeq[fork] >= ForkSeq.electra) {
const {depositReceipts, withdrawalRequests} = data as electra.ExecutionPayload;
payload.depositRequests = depositReceipts.map(serializeDepositRequest);
const {depositRequests, withdrawalRequests} = data as electra.ExecutionPayload;
payload.depositRequests = depositRequests.map(serializeDepositRequest);
payload.withdrawalRequests = withdrawalRequests.map(serializeExecutionLayerWithdrawalRequest);
}

Expand Down Expand Up @@ -316,7 +320,7 @@ export function parseExecutionPayload(
`depositRequests missing for ${fork} >= electra executionPayload number=${executionPayload.blockNumber} hash=${data.blockHash}`
);
}
(executionPayload as electra.ExecutionPayload).depositReceipts = depositRequests.map(deserializeDepositRequest);
(executionPayload as electra.ExecutionPayload).depositRequests = depositRequests.map(deserializeDepositRequest);

if (withdrawalRequests == null) {
throw Error(
Expand Down
10 changes: 5 additions & 5 deletions packages/beacon-node/test/sim/electra-interop.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@ describe("executionEngine / ExecutionEngineHttp", function () {
}
}

if (payload.depositReceipts.length !== 1) {
throw Error(`Number of depositRequests mismatched. Expected: 1, actual: ${payload.depositReceipts.length}`);
if (payload.depositRequests.length !== 1) {
throw Error(`Number of depositRequests mismatched. Expected: 1, actual: ${payload.depositRequests.length}`);
}

const actualDepositRequest = payload.depositReceipts[0];
const actualDepositRequest = payload.depositRequests[0];
assert.deepStrictEqual(
actualDepositRequest,
depositRequestB,
Expand Down Expand Up @@ -431,8 +431,8 @@ describe("executionEngine / ExecutionEngineHttp", function () {
throw Error("Historical validator length for epoch 1 or 2 is not dropped properly");
}

if (headState.depositReceiptsStartIndex === UNSET_DEPOSIT_RECEIPTS_START_INDEX) {
throw Error("state.depositReceiptsStartIndex is not set upon processing new deposit receipt");
if (headState.depositRequestsStartIndex === UNSET_DEPOSIT_RECEIPTS_START_INDEX) {
throw Error("state.depositRequestsStartIndex is not set upon processing new deposit receipt");
}

// wait for 1 slot to print current epoch stats
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ const operations: TestRunnerFn<OperationsTestCase, BeaconStateAllForks> = (fork,
block: ssz[fork].BeaconBlock,
body: ssz[fork].BeaconBlockBody,
deposit: ssz.phase0.Deposit,
deposit_receipt: ssz.electra.DepositReceipt,
deposit_receipt: ssz.electra.DepositRequest,
proposer_slashing: ssz.phase0.ProposerSlashing,
voluntary_exit: ssz.phase0.SignedVoluntaryExit,
// Altair
Expand Down
4 changes: 2 additions & 2 deletions packages/beacon-node/test/unit/executionEngine/http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ describe("ExecutionEngine / http", () => {

returnValue = response;

const res = await executionEngine.getPayloadBodiesByHash(reqBlockHashes);
const res = await executionEngine.getPayloadBodiesByHash(ForkName.bellatrix, reqBlockHashes);

expect(reqJsonRpcPayload).toEqual(request);
expect(res.map(serializeExecutionPayloadBody)).toEqual(response.result);
Expand Down Expand Up @@ -271,7 +271,7 @@ describe("ExecutionEngine / http", () => {

returnValue = response;

const res = await executionEngine.getPayloadBodiesByRange(startBlockNumber, blockCount);
const res = await executionEngine.getPayloadBodiesByRange(ForkName.bellatrix, startBlockNumber, blockCount);

expect(reqJsonRpcPayload).toEqual(request);
expect(res.map(serializeExecutionPayloadBody)).toEqual(response.result);
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/test/utils/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export function generateState(

if (forkSeq >= ForkSeq.electra) {
const stateElectra = state as electra.BeaconState;
stateElectra.depositReceiptsStartIndex = 2023n;
stateElectra.depositRequestsStartIndex = 2023n;
stateElectra.latestExecutionPayloadHeader = ssz.electra.ExecutionPayloadHeader.defaultValue();
}

Expand Down
6 changes: 3 additions & 3 deletions packages/light-client/src/spec/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ export function upgradeLightClientHeader(

// eslint-disable-next-line no-fallthrough
case ForkName.electra:
(upgradedHeader as electra.LightClientHeader).execution.depositReceiptsRoot =
ssz.electra.LightClientHeader.fields.execution.fields.depositReceiptsRoot.defaultValue();
(upgradedHeader as electra.LightClientHeader).execution.depositRequestsRoot =
ssz.electra.LightClientHeader.fields.execution.fields.depositRequestsRoot.defaultValue();
(upgradedHeader as electra.LightClientHeader).execution.withdrawalRequestsRoot =
ssz.electra.LightClientHeader.fields.execution.fields.withdrawalRequestsRoot.defaultValue();

Expand Down Expand Up @@ -148,7 +148,7 @@ export function isValidLightClientHeader(config: ChainForkConfig, header: allFor

if (epoch < config.ELECTRA_FORK_EPOCH) {
if (
(header as electra.LightClientHeader).execution.depositReceiptsRoot !== undefined ||
(header as electra.LightClientHeader).execution.depositRequestsRoot !== undefined ||
(header as electra.LightClientHeader).execution.withdrawalRequestsRoot !== undefined
) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export function processDepositRequest(
state: CachedBeaconStateElectra,
depositRequest: electra.DepositRequest
): void {
if (state.depositReceiptsStartIndex === UNSET_DEPOSIT_RECEIPTS_START_INDEX) {
state.depositReceiptsStartIndex = BigInt(depositRequest.index);
if (state.depositRequestsStartIndex === UNSET_DEPOSIT_RECEIPTS_START_INDEX) {
state.depositRequestsStartIndex = BigInt(depositRequest.index);
}

applyDeposit(fork, state, depositRequest);
Expand Down
2 changes: 1 addition & 1 deletion packages/state-transition/src/block/processOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function processOperations(
processExecutionLayerWithdrawalRequest(fork, state as CachedBeaconStateElectra, elWithdrawalRequest);
}

for (const depositRequest of bodyElectra.executionPayload.depositReceipts) {
for (const depositRequest of bodyElectra.executionPayload.depositRequests) {
processDepositRequest(fork, stateElectra, depositRequest);
}

Expand Down
14 changes: 7 additions & 7 deletions packages/state-transition/src/slot/upgradeStateToElectra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,16 @@ export function upgradeStateToElectra(stateDeneb: CachedBeaconStateDeneb): Cache
stateElectraView.nextSyncCommittee = stateElectraCloned.nextSyncCommittee;
stateElectraView.latestExecutionPayloadHeader = ssz.electra.BeaconState.fields.latestExecutionPayloadHeader.toViewDU({
...stateElectraCloned.latestExecutionPayloadHeader.toValue(),
depositReceiptsRoot: ssz.Root.defaultValue(),
depositRequestsRoot: ssz.Root.defaultValue(),
withdrawalRequestsRoot: ssz.Root.defaultValue(),
});
stateElectraView.nextWithdrawalIndex = stateDeneb.nextWithdrawalIndex;
stateElectraView.nextWithdrawalValidatorIndex = stateDeneb.nextWithdrawalValidatorIndex;
stateElectraView.historicalSummaries = stateElectraCloned.historicalSummaries;

// latestExecutionPayloadHeader's depositReceiptsRoot and withdrawalRequestsRoot set to zeros by default
// default value of depositReceiptsStartIndex is UNSET_DEPOSIT_RECEIPTS_START_INDEX
stateElectraView.depositReceiptsStartIndex = UNSET_DEPOSIT_RECEIPTS_START_INDEX;
// latestExecutionPayloadHeader's depositRequestsRoot and withdrawalRequestsRoot set to zeros by default
// default value of depositRequestsStartIndex is UNSET_DEPOSIT_RECEIPTS_START_INDEX
stateElectraView.depositRequestsStartIndex = UNSET_DEPOSIT_RECEIPTS_START_INDEX;
stateElectraView.depositBalanceToConsume = BigInt(0);
stateElectraView.exitBalanceToConsume = BigInt(0);

Expand Down Expand Up @@ -136,9 +136,9 @@ export function upgradeStateToElectraOriginal(stateDeneb: CachedBeaconStateDeneb
epoch: stateDeneb.epochCtx.epoch,
});

// latestExecutionPayloadHeader's depositReceiptsRoot and withdrawalRequestsRoot set to zeros by default
// default value of depositReceiptsStartIndex is UNSET_DEPOSIT_RECEIPTS_START_INDEX
stateElectra.depositReceiptsStartIndex = UNSET_DEPOSIT_RECEIPTS_START_INDEX;
// latestExecutionPayloadHeader's depositRequestsRoot and withdrawalRequestsRoot set to zeros by default
// default value of depositRequestsStartIndex is UNSET_DEPOSIT_RECEIPTS_START_INDEX
stateElectra.depositRequestsStartIndex = UNSET_DEPOSIT_RECEIPTS_START_INDEX;

const validatorsArr = stateElectra.validators.getAllReadonly();

Expand Down
4 changes: 2 additions & 2 deletions packages/state-transition/src/util/deposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export function getEth1DepositCount(state: CachedBeaconStateAllForks, eth1Data?:
// eth1DataIndexLimit = min(UintNum64, UintBn64) can be safely casted as UintNum64
// since the result lies within upper and lower bound of UintNum64
const eth1DataIndexLimit: UintNum64 =
eth1DataToUse.depositCount < electraState.depositReceiptsStartIndex
eth1DataToUse.depositCount < electraState.depositRequestsStartIndex
? eth1DataToUse.depositCount
: Number(electraState.depositReceiptsStartIndex);
: Number(electraState.depositRequestsStartIndex);

if (state.eth1DepositIndex < eth1DataIndexLimit) {
return Math.min(MAX_DEPOSITS, eth1DataIndexLimit - state.eth1DepositIndex);
Expand Down
4 changes: 2 additions & 2 deletions packages/state-transition/src/util/execution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ export function executionPayloadToPayloadHeader(
}

if (fork >= ForkSeq.electra) {
(bellatrixPayloadFields as electra.ExecutionPayloadHeader).depositReceiptsRoot =
ssz.electra.DepositReceipts.hashTreeRoot((payload as electra.ExecutionPayload).depositReceipts);
(bellatrixPayloadFields as electra.ExecutionPayloadHeader).depositRequestsRoot =
ssz.electra.DepositRequests.hashTreeRoot((payload as electra.ExecutionPayload).depositRequests);
(bellatrixPayloadFields as electra.ExecutionPayloadHeader).withdrawalRequestsRoot =
ssz.electra.ExecutionLayerWithdrawalRequests.hashTreeRoot(
(payload as electra.ExecutionPayload).withdrawalRequests
Expand Down
2 changes: 1 addition & 1 deletion packages/state-transition/src/util/genesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ export function initializeBeaconStateFromEth1(
stateElectra.latestExecutionPayloadHeader =
(executionPayloadHeader as CompositeViewDU<typeof ssz.electra.ExecutionPayloadHeader>) ??
ssz.electra.ExecutionPayloadHeader.defaultViewDU();
stateElectra.depositReceiptsStartIndex = UNSET_DEPOSIT_RECEIPTS_START_INDEX;
stateElectra.depositRequestsStartIndex = UNSET_DEPOSIT_RECEIPTS_START_INDEX;
}

state.commit();
Expand Down
4 changes: 2 additions & 2 deletions packages/state-transition/test/unit/util/deposit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("getEth1DepositCount", () => {
throw Error("Not a post-Electra state");
}

postElectraState.depositReceiptsStartIndex = 1000n;
postElectraState.depositRequestsStartIndex = 1000n;
postElectraState.eth1Data.depositCount = 995;

// 1. Should get less than MAX_DEPOSIT
Expand Down Expand Up @@ -77,7 +77,7 @@ describe("getEth1DepositCount", () => {
throw Error("Not a post-Electra state");
}

postElectraState.depositReceiptsStartIndex = 1000n;
postElectraState.depositRequestsStartIndex = 1000n;
postElectraState.eth1Data.depositCount = 1005;

// Before eth1DepositIndex reaching the start index
Expand Down
12 changes: 6 additions & 6 deletions packages/types/src/electra/sszTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,18 @@ export const SignedAggregateAndProof = new ContainerType(
{typeName: "SignedAggregateAndProof", jsonCase: "eth2"}
);

export const DepositReceipt = new ContainerType(
export const DepositRequest = new ContainerType(
{
pubkey: BLSPubkey,
withdrawalCredentials: Bytes32,
amount: UintNum64,
signature: BLSSignature,
index: DepositIndex,
},
{typeName: "DepositReceipt", jsonCase: "eth2"}
{typeName: "DepositRequest", jsonCase: "eth2"}
);

export const DepositReceipts = new ListCompositeType(DepositReceipt, MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD);
export const DepositRequests = new ListCompositeType(DepositRequest, MAX_DEPOSIT_RECEIPTS_PER_PAYLOAD);

export const ExecutionLayerWithdrawalRequest = new ContainerType(
{
Expand All @@ -141,7 +141,7 @@ export const ExecutionLayerWithdrawalRequests = new ListCompositeType(
export const ExecutionPayload = new ContainerType(
{
...denebSsz.ExecutionPayload.fields,
depositReceipts: DepositReceipts, // New in ELECTRA
depositRequests: DepositRequests, // New in ELECTRA
withdrawalRequests: ExecutionLayerWithdrawalRequests, // New in ELECTRA
},
{typeName: "ExecutionPayload", jsonCase: "eth2"}
Expand All @@ -150,7 +150,7 @@ export const ExecutionPayload = new ContainerType(
export const ExecutionPayloadHeader = new ContainerType(
{
...denebSsz.ExecutionPayloadHeader.fields,
depositReceiptsRoot: Root, // New in ELECTRA
depositRequestsRoot: Root, // New in ELECTRA
withdrawalRequestsRoot: Root, // New in ELECTRA
},
{typeName: "ExecutionPayloadHeader", jsonCase: "eth2"}
Expand Down Expand Up @@ -340,7 +340,7 @@ export const BeaconState = new ContainerType(
nextWithdrawalValidatorIndex: capellaSsz.BeaconState.fields.nextWithdrawalValidatorIndex,
// Deep history valid from Capella onwards
historicalSummaries: capellaSsz.BeaconState.fields.historicalSummaries,
depositReceiptsStartIndex: UintBn64, // New in ELECTRA:EIP6110
depositRequestsStartIndex: UintBn64, // New in ELECTRA:EIP6110
depositBalanceToConsume: Gwei, // New in Electra:EIP7251
exitBalanceToConsume: Gwei, // New in Electra:EIP7251
earliestExitEpoch: Epoch, // New in Electra:EIP7251
Expand Down
4 changes: 2 additions & 2 deletions packages/types/src/electra/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export type AttesterSlashing = ValueOf<typeof ssz.AttesterSlashing>;
export type AggregateAndProof = ValueOf<typeof ssz.AggregateAndProof>;
export type SignedAggregateAndProof = ValueOf<typeof ssz.SignedAggregateAndProof>;

export type DepositRequest = ValueOf<typeof ssz.DepositReceipt>;
export type DepositRequests = ValueOf<typeof ssz.DepositReceipts>;
export type DepositRequest = ValueOf<typeof ssz.DepositRequest>;
export type DepositRequests = ValueOf<typeof ssz.DepositRequests>;

export type ExecutionLayerWithdrawalRequest = ValueOf<typeof ssz.ExecutionLayerWithdrawalRequest>;
export type ExecutionLayerWithdrawalRequests = ValueOf<typeof ssz.ExecutionLayerWithdrawalRequests>;
Expand Down
Loading