From 6e6c3d51049f63dc9cd6617ff205112bb5645486 Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Mon, 17 Jun 2024 15:30:09 +0300 Subject: [PATCH 01/10] Update spec test version --- packages/beacon-node/test/spec/presets/operations.test.ts | 5 +++++ packages/beacon-node/test/spec/specTestVersioning.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/beacon-node/test/spec/presets/operations.test.ts b/packages/beacon-node/test/spec/presets/operations.test.ts index 55b8c57e1638..f5d5aa52f5a6 100644 --- a/packages/beacon-node/test/spec/presets/operations.test.ts +++ b/packages/beacon-node/test/spec/presets/operations.test.ts @@ -96,6 +96,10 @@ const operationFns: Record> = blockFns.processWithdrawalRequest(ForkSeq.electra, state as CachedBeaconStateElectra, testCase.withdrawal_request); }, + deposit_request: (state, testCase: {deposit_request: electra.DepositRequest}) => { + blockFns.processDepositRequest(ForkSeq.electra, state as CachedBeaconStateElectra, testCase.deposit_request); + }, + consolidation_request: (state, testCase: {consolidation_request: electra.ConsolidationRequest}) => { blockFns.processConsolidationRequest(state as CachedBeaconStateElectra, testCase.consolidation_request); }, @@ -151,6 +155,7 @@ const operations: TestRunnerFn = (fork, address_change: ssz.capella.SignedBLSToExecutionChange, // Electra withdrawal_request: ssz.electra.WithdrawalRequest, + deposit_request: ssz.electra.DepositRequest, consolidation_request: ssz.electra.ConsolidationRequest, }, shouldError: (testCase) => testCase.post === undefined, diff --git a/packages/beacon-node/test/spec/specTestVersioning.ts b/packages/beacon-node/test/spec/specTestVersioning.ts index 9195532379a0..e97770e8146c 100644 --- a/packages/beacon-node/test/spec/specTestVersioning.ts +++ b/packages/beacon-node/test/spec/specTestVersioning.ts @@ -15,7 +15,7 @@ import {DownloadTestsOptions} from "@lodestar/spec-test-util/downloadTests"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); export const ethereumConsensusSpecsTests: DownloadTestsOptions = { - specVersion: "v1.5.0-alpha.2", + specVersion: "v1.5.0-alpha.3", // Target directory is the host package root: 'packages/*/spec-tests' outputDir: path.join(__dirname, "../../spec-tests"), specTestsRepoUrl: "https://github.com/ethereum/consensus-spec-tests", From 9f6f735b03efec9579ee51b9ee25f8bcc361a91d Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Mon, 17 Jun 2024 15:32:06 +0300 Subject: [PATCH 02/10] Use new max effective balance --- .../state-transition/src/cache/epochCache.ts | 7 ++++--- packages/state-transition/src/epoch/index.ts | 2 +- .../src/epoch/processSyncCommitteeUpdates.ts | 5 +++-- .../src/slot/upgradeStateToAltair.ts | 1 + packages/state-transition/src/util/genesis.ts | 5 +++-- packages/state-transition/src/util/seed.ts | 16 +++++++++++----- .../state-transition/src/util/syncCommittee.ts | 4 +++- 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index b03576a653ec..207689bf9d4a 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -394,7 +394,7 @@ export class EpochCache { // Allow to create CachedBeaconState for empty states, or no active validators const proposers = currentShuffling.activeIndices.length > 0 - ? computeProposers(currentProposerSeed, currentShuffling, effectiveBalanceIncrements) + ? computeProposers(currentProposerSeed, currentShuffling, effectiveBalanceIncrements, currentEpoch >= config.ELECTRA_FORK_EPOCH) : []; const proposersNextEpoch: ProposersDeferred = { @@ -571,7 +571,7 @@ export class EpochCache { this.proposersPrevEpoch = this.proposers; const currentProposerSeed = getSeed(state, this.currentShuffling.epoch, DOMAIN_BEACON_PROPOSER); - this.proposers = computeProposers(currentProposerSeed, this.currentShuffling, this.effectiveBalanceIncrements); + this.proposers = computeProposers(currentProposerSeed, this.currentShuffling, this.effectiveBalanceIncrements, currEpoch >= this.config.ELECTRA_FORK_EPOCH); // Only pre-compute the seed since it's very cheap. Do the expensive computeProposers() call only on demand. this.proposersNextEpoch = {computed: false, seed: getSeed(state, this.nextShuffling.epoch, DOMAIN_BEACON_PROPOSER)}; @@ -770,7 +770,8 @@ export class EpochCache { const indexes = computeProposers( this.proposersNextEpoch.seed, this.nextShuffling, - this.effectiveBalanceIncrements + this.effectiveBalanceIncrements, + this.epoch + 1 >= this.config.ELECTRA_FORK_EPOCH, ); this.proposersNextEpoch = {computed: true, indexes}; } diff --git a/packages/state-transition/src/epoch/index.ts b/packages/state-transition/src/epoch/index.ts index 6e736fdae2cc..21455521897b 100644 --- a/packages/state-transition/src/epoch/index.ts +++ b/packages/state-transition/src/epoch/index.ts @@ -178,7 +178,7 @@ export function processEpoch( const timer = metrics?.epochTransitionStepTime.startTimer({ step: EpochTransitionStep.processSyncCommitteeUpdates, }); - processSyncCommitteeUpdates(state as CachedBeaconStateAltair); + processSyncCommitteeUpdates(fork, state as CachedBeaconStateAltair); timer?.(); } } diff --git a/packages/state-transition/src/epoch/processSyncCommitteeUpdates.ts b/packages/state-transition/src/epoch/processSyncCommitteeUpdates.ts index dc1f39274399..1c48eced5830 100644 --- a/packages/state-transition/src/epoch/processSyncCommitteeUpdates.ts +++ b/packages/state-transition/src/epoch/processSyncCommitteeUpdates.ts @@ -1,5 +1,5 @@ import bls from "@chainsafe/bls"; -import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD} from "@lodestar/params"; +import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD, ForkSeq} from "@lodestar/params"; import {ssz} from "@lodestar/types"; import {getNextSyncCommitteeIndices} from "../util/seed.js"; import {CachedBeaconStateAltair} from "../types.js"; @@ -10,7 +10,7 @@ import {CachedBeaconStateAltair} from "../types.js"; * PERF: Once every `EPOCHS_PER_SYNC_COMMITTEE_PERIOD`, do an expensive operation to compute the next committee. * Calculating the next sync committee has a proportional cost to $VALIDATOR_COUNT */ -export function processSyncCommitteeUpdates(state: CachedBeaconStateAltair): void { +export function processSyncCommitteeUpdates(fork: ForkSeq, state: CachedBeaconStateAltair): void { const nextEpoch = state.epochCtx.epoch + 1; if (nextEpoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD === 0) { @@ -18,6 +18,7 @@ export function processSyncCommitteeUpdates(state: CachedBeaconStateAltair): voi const {effectiveBalanceIncrements} = state.epochCtx; const nextSyncCommitteeIndices = getNextSyncCommitteeIndices( + fork, state, activeValidatorIndices, effectiveBalanceIncrements diff --git a/packages/state-transition/src/slot/upgradeStateToAltair.ts b/packages/state-transition/src/slot/upgradeStateToAltair.ts index 0afa43930ef0..fa7e6fbeba8e 100644 --- a/packages/state-transition/src/slot/upgradeStateToAltair.ts +++ b/packages/state-transition/src/slot/upgradeStateToAltair.ts @@ -70,6 +70,7 @@ export function upgradeStateToAltair(statePhase0: CachedBeaconStatePhase0): Cach stateAltair.inactivityScores = ssz.altair.InactivityScores.toViewDU(newZeroedArray(validatorCount)); const {syncCommittee, indices} = getNextSyncCommittee( + ForkSeq.altair, stateAltair, stateAltair.epochCtx.nextShuffling.activeIndices, stateAltair.epochCtx.effectiveBalanceIncrements diff --git a/packages/state-transition/src/util/genesis.ts b/packages/state-transition/src/util/genesis.ts index ca894fd5b4e5..ed7886f95838 100644 --- a/packages/state-transition/src/util/genesis.ts +++ b/packages/state-transition/src/util/genesis.ts @@ -18,7 +18,7 @@ import {EpochCacheImmutableData} from "../cache/epochCache.js"; import {processDeposit} from "../block/processDeposit.js"; import {increaseBalance} from "../index.js"; import {computeEpochAtSlot} from "./epoch.js"; -import {getActiveValidatorIndices} from "./validator.js"; +import {getActiveValidatorIndices, getValidatorMaxEffectiveBalance} from "./validator.js"; import {getTemporaryBlockHeader} from "./blockRoot.js"; import {newFilledArray} from "./array.js"; import {getNextSyncCommittee} from "./syncCommittee.js"; @@ -193,7 +193,7 @@ export function applyDeposits( } const balance = balancesArr[i]; - const effectiveBalance = Math.min(balance - (balance % EFFECTIVE_BALANCE_INCREMENT), MAX_EFFECTIVE_BALANCE); + const effectiveBalance = Math.min(balance - (balance % EFFECTIVE_BALANCE_INCREMENT), getValidatorMaxEffectiveBalance(validator.withdrawalCredentials)); validator.effectiveBalance = effectiveBalance; epochCtx.effectiveBalanceIncrementsSet(i, effectiveBalance); @@ -263,6 +263,7 @@ export function initializeBeaconStateFromEth1( if (fork >= ForkSeq.altair) { const {syncCommittee} = getNextSyncCommittee( + fork, state, activeValidatorIndices, state.epochCtx.effectiveBalanceIncrements diff --git a/packages/state-transition/src/util/seed.ts b/packages/state-transition/src/util/seed.ts index cf48fda8bec4..f851179e68a3 100644 --- a/packages/state-transition/src/util/seed.ts +++ b/packages/state-transition/src/util/seed.ts @@ -5,7 +5,9 @@ import { DOMAIN_SYNC_COMMITTEE, EFFECTIVE_BALANCE_INCREMENT, EPOCHS_PER_HISTORICAL_VECTOR, + ForkSeq, MAX_EFFECTIVE_BALANCE, + MAX_EFFECTIVE_BALANCE_ELECTRA, MIN_SEED_LOOKAHEAD, SHUFFLE_ROUND_COUNT, SLOTS_PER_EPOCH, @@ -22,7 +24,8 @@ import {computeEpochAtSlot} from "./epoch.js"; export function computeProposers( epochSeed: Uint8Array, shuffling: {epoch: Epoch; activeIndices: ArrayLike}, - effectiveBalanceIncrements: EffectiveBalanceIncrements + effectiveBalanceIncrements: EffectiveBalanceIncrements, + isAfterElectra: boolean, ): number[] { const startSlot = computeStartSlotAtEpoch(shuffling.epoch); const proposers = []; @@ -31,7 +34,8 @@ export function computeProposers( computeProposerIndex( effectiveBalanceIncrements, shuffling.activeIndices, - digest(Buffer.concat([epochSeed, intToBytes(slot, 8)])) + digest(Buffer.concat([epochSeed, intToBytes(slot, 8)])), + isAfterElectra, ) ); } @@ -46,7 +50,8 @@ export function computeProposers( export function computeProposerIndex( effectiveBalanceIncrements: EffectiveBalanceIncrements, indices: ArrayLike, - seed: Uint8Array + seed: Uint8Array, + isAfterElectra: boolean, ): ValidatorIndex { if (indices.length === 0) { throw Error("Validator indices must not be empty"); @@ -54,7 +59,7 @@ export function computeProposerIndex( // TODO: Inline outside this function const MAX_RANDOM_BYTE = 2 ** 8 - 1; - const MAX_EFFECTIVE_BALANCE_INCREMENT = MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; + const MAX_EFFECTIVE_BALANCE_INCREMENT = isAfterElectra ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; let i = 0; /* eslint-disable-next-line no-constant-condition */ @@ -90,13 +95,14 @@ export function computeProposerIndex( * SLOW CODE - 🐢 */ export function getNextSyncCommitteeIndices( + fork: ForkSeq, state: BeaconStateAllForks, activeValidatorIndices: ArrayLike, effectiveBalanceIncrements: EffectiveBalanceIncrements ): ValidatorIndex[] { // TODO: Bechmark if it's necessary to inline outside of this function const MAX_RANDOM_BYTE = 2 ** 8 - 1; - const MAX_EFFECTIVE_BALANCE_INCREMENT = MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; + const MAX_EFFECTIVE_BALANCE_INCREMENT = fork >= ForkSeq.electra ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; const epoch = computeEpochAtSlot(state.slot) + 1; diff --git a/packages/state-transition/src/util/syncCommittee.ts b/packages/state-transition/src/util/syncCommittee.ts index 89c476b69c04..99c3611ae104 100644 --- a/packages/state-transition/src/util/syncCommittee.ts +++ b/packages/state-transition/src/util/syncCommittee.ts @@ -2,6 +2,7 @@ import bls from "@chainsafe/bls"; import { BASE_REWARD_FACTOR, EFFECTIVE_BALANCE_INCREMENT, + ForkSeq, SLOTS_PER_EPOCH, SYNC_COMMITTEE_SIZE, SYNC_REWARD_WEIGHT, @@ -19,11 +20,12 @@ import {getNextSyncCommitteeIndices} from "./seed.js"; * SLOW CODE - 🐢 */ export function getNextSyncCommittee( + fork: ForkSeq, state: BeaconStateAllForks, activeValidatorIndices: ArrayLike, effectiveBalanceIncrements: EffectiveBalanceIncrements ): {indices: ValidatorIndex[]; syncCommittee: altair.SyncCommittee} { - const indices = getNextSyncCommitteeIndices(state, activeValidatorIndices, effectiveBalanceIncrements); + const indices = getNextSyncCommitteeIndices(fork, state, activeValidatorIndices, effectiveBalanceIncrements); // Using the index2pubkey cache is slower because it needs the serialized pubkey. const pubkeys = indices.map((index) => state.validators.getReadonly(index).pubkey); From 17a429edcefa0f560b46853fffe531cf5207dc00 Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Mon, 17 Jun 2024 15:32:42 +0300 Subject: [PATCH 03/10] Relax loop breaking condition for `computeProposerIndex` --- packages/state-transition/src/util/seed.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/state-transition/src/util/seed.ts b/packages/state-transition/src/util/seed.ts index f851179e68a3..772737741c05 100644 --- a/packages/state-transition/src/util/seed.ts +++ b/packages/state-transition/src/util/seed.ts @@ -78,7 +78,9 @@ export function computeProposerIndex( return candidateIndex; } i += 1; - if (i === indices.length) { + // TODO Electra: Spec does not have this condition to end infinite loop. Spec test won't pass if we + // only loop the validator indices once + if (i === indices.length * 2) { return -1; } } From 3e02a2e628962461a216a9a532393f4abbeafa2b Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Mon, 17 Jun 2024 16:56:49 +0300 Subject: [PATCH 04/10] fix remaining --- .../spec/presets/epoch_processing.test.ts | 6 ++++- .../src/block/processConsolidationRequest.ts | 2 +- .../state-transition/src/cache/epochCache.ts | 16 ++++++++++--- .../state-transition/src/util/execution.ts | 2 ++ packages/state-transition/src/util/genesis.ts | 5 +++- packages/state-transition/src/util/seed.ts | 24 ++++++++++++------- 6 files changed, 41 insertions(+), 14 deletions(-) diff --git a/packages/beacon-node/test/spec/presets/epoch_processing.test.ts b/packages/beacon-node/test/spec/presets/epoch_processing.test.ts index f159612e416c..604243400aa0 100644 --- a/packages/beacon-node/test/spec/presets/epoch_processing.test.ts +++ b/packages/beacon-node/test/spec/presets/epoch_processing.test.ts @@ -5,6 +5,7 @@ import { EpochTransitionCache, BeaconStateAllForks, beforeProcessEpoch, + CachedBeaconStateAltair, } from "@lodestar/state-transition"; import * as epochFns from "@lodestar/state-transition/epoch"; import {ssz} from "@lodestar/types"; @@ -40,7 +41,10 @@ const epochTransitionFns: Record = { rewards_and_penalties: epochFns.processRewardsAndPenalties, slashings: epochFns.processSlashings, slashings_reset: epochFns.processSlashingsReset, - sync_committee_updates: epochFns.processSyncCommitteeUpdates as EpochTransitionFn, + sync_committee_updates: (state, _) => { + const fork = state.config.getForkSeq(state.slot); + epochFns.processSyncCommitteeUpdates(fork, state as CachedBeaconStateAltair); + }, historical_summaries_update: epochFns.processHistoricalSummariesUpdate as EpochTransitionFn, pending_balance_deposits: epochFns.processPendingBalanceDeposits as EpochTransitionFn, pending_consolidations: epochFns.processPendingConsolidations as EpochTransitionFn, diff --git a/packages/state-transition/src/block/processConsolidationRequest.ts b/packages/state-transition/src/block/processConsolidationRequest.ts index 4b6a65e036ad..44d6aa33fb8c 100644 --- a/packages/state-transition/src/block/processConsolidationRequest.ts +++ b/packages/state-transition/src/block/processConsolidationRequest.ts @@ -34,7 +34,7 @@ export function processConsolidationRequest( return; } - const sourceValidator = state.validators.getReadonly(sourceIndex); + const sourceValidator = state.validators.get(sourceIndex); const targetValidator = state.validators.getReadonly(targetIndex); const sourceWithdrawalAddress = sourceValidator.withdrawalCredentials.subarray(12); const currentEpoch = state.epochCtx.epoch; diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index 207689bf9d4a..06c8d666d279 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -394,7 +394,12 @@ export class EpochCache { // Allow to create CachedBeaconState for empty states, or no active validators const proposers = currentShuffling.activeIndices.length > 0 - ? computeProposers(currentProposerSeed, currentShuffling, effectiveBalanceIncrements, currentEpoch >= config.ELECTRA_FORK_EPOCH) + ? computeProposers( + currentProposerSeed, + currentShuffling, + effectiveBalanceIncrements, + currentEpoch >= config.ELECTRA_FORK_EPOCH + ) : []; const proposersNextEpoch: ProposersDeferred = { @@ -571,7 +576,12 @@ export class EpochCache { this.proposersPrevEpoch = this.proposers; const currentProposerSeed = getSeed(state, this.currentShuffling.epoch, DOMAIN_BEACON_PROPOSER); - this.proposers = computeProposers(currentProposerSeed, this.currentShuffling, this.effectiveBalanceIncrements, currEpoch >= this.config.ELECTRA_FORK_EPOCH); + this.proposers = computeProposers( + currentProposerSeed, + this.currentShuffling, + this.effectiveBalanceIncrements, + currEpoch >= this.config.ELECTRA_FORK_EPOCH + ); // Only pre-compute the seed since it's very cheap. Do the expensive computeProposers() call only on demand. this.proposersNextEpoch = {computed: false, seed: getSeed(state, this.nextShuffling.epoch, DOMAIN_BEACON_PROPOSER)}; @@ -771,7 +781,7 @@ export class EpochCache { this.proposersNextEpoch.seed, this.nextShuffling, this.effectiveBalanceIncrements, - this.epoch + 1 >= this.config.ELECTRA_FORK_EPOCH, + this.epoch + 1 >= this.config.ELECTRA_FORK_EPOCH ); this.proposersNextEpoch = {computed: true, indexes}; } diff --git a/packages/state-transition/src/util/execution.ts b/packages/state-transition/src/util/execution.ts index 0f949a3b3b61..95181dc63d70 100644 --- a/packages/state-transition/src/util/execution.ts +++ b/packages/state-transition/src/util/execution.ts @@ -175,6 +175,8 @@ export function executionPayloadToPayloadHeader( ssz.electra.DepositRequests.hashTreeRoot((payload as electra.ExecutionPayload).depositRequests); (bellatrixPayloadFields as electra.ExecutionPayloadHeader).withdrawalRequestsRoot = ssz.electra.WithdrawalRequests.hashTreeRoot((payload as electra.ExecutionPayload).withdrawalRequests); + (bellatrixPayloadFields as electra.ExecutionPayloadHeader).consolidationRequestsRoot = + ssz.electra.ConsolidationRequests.hashTreeRoot((payload as electra.ExecutionPayload).consolidationRequests); } return bellatrixPayloadFields; diff --git a/packages/state-transition/src/util/genesis.ts b/packages/state-transition/src/util/genesis.ts index ed7886f95838..d1f09a9796e1 100644 --- a/packages/state-transition/src/util/genesis.ts +++ b/packages/state-transition/src/util/genesis.ts @@ -193,7 +193,10 @@ export function applyDeposits( } const balance = balancesArr[i]; - const effectiveBalance = Math.min(balance - (balance % EFFECTIVE_BALANCE_INCREMENT), getValidatorMaxEffectiveBalance(validator.withdrawalCredentials)); + const effectiveBalance = Math.min( + balance - (balance % EFFECTIVE_BALANCE_INCREMENT), + getValidatorMaxEffectiveBalance(validator.withdrawalCredentials) + ); validator.effectiveBalance = effectiveBalance; epochCtx.effectiveBalanceIncrementsSet(i, effectiveBalance); diff --git a/packages/state-transition/src/util/seed.ts b/packages/state-transition/src/util/seed.ts index 772737741c05..126d7df00c74 100644 --- a/packages/state-transition/src/util/seed.ts +++ b/packages/state-transition/src/util/seed.ts @@ -18,6 +18,9 @@ import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js import {computeStartSlotAtEpoch} from "./epoch.js"; import {computeEpochAtSlot} from "./epoch.js"; +// Max number of iterations over validator set when computing proposer index +const MAX_ITERATION_OVER_VALIDATORS = 10; + /** * Compute proposer indices for an epoch */ @@ -25,7 +28,7 @@ export function computeProposers( epochSeed: Uint8Array, shuffling: {epoch: Epoch; activeIndices: ArrayLike}, effectiveBalanceIncrements: EffectiveBalanceIncrements, - isAfterElectra: boolean, + isAfterElectra: boolean ): number[] { const startSlot = computeStartSlotAtEpoch(shuffling.epoch); const proposers = []; @@ -35,7 +38,7 @@ export function computeProposers( effectiveBalanceIncrements, shuffling.activeIndices, digest(Buffer.concat([epochSeed, intToBytes(slot, 8)])), - isAfterElectra, + isAfterElectra ) ); } @@ -51,7 +54,7 @@ export function computeProposerIndex( effectiveBalanceIncrements: EffectiveBalanceIncrements, indices: ArrayLike, seed: Uint8Array, - isAfterElectra: boolean, + isAfterElectra: boolean ): ValidatorIndex { if (indices.length === 0) { throw Error("Validator indices must not be empty"); @@ -59,7 +62,9 @@ export function computeProposerIndex( // TODO: Inline outside this function const MAX_RANDOM_BYTE = 2 ** 8 - 1; - const MAX_EFFECTIVE_BALANCE_INCREMENT = isAfterElectra ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; + const MAX_EFFECTIVE_BALANCE_INCREMENT = isAfterElectra + ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT + : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; let i = 0; /* eslint-disable-next-line no-constant-condition */ @@ -78,9 +83,9 @@ export function computeProposerIndex( return candidateIndex; } i += 1; - // TODO Electra: Spec does not have this condition to end infinite loop. Spec test won't pass if we - // only loop the validator indices once - if (i === indices.length * 2) { + // Spec does not have this condition to end infinite loop. Spec test won't pass if we + // only loop the validator indices once. Electra spec test requires MAX_ITERATION_OVER_VALIDATORS >= 6 + if (i === indices.length * MAX_ITERATION_OVER_VALIDATORS) { return -1; } } @@ -104,7 +109,10 @@ export function getNextSyncCommitteeIndices( ): ValidatorIndex[] { // TODO: Bechmark if it's necessary to inline outside of this function const MAX_RANDOM_BYTE = 2 ** 8 - 1; - const MAX_EFFECTIVE_BALANCE_INCREMENT = fork >= ForkSeq.electra ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; + const MAX_EFFECTIVE_BALANCE_INCREMENT = + fork >= ForkSeq.electra + ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT + : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; const epoch = computeEpochAtSlot(state.slot) + 1; From eafcc55499549ed8c0624c51197fa91944a67665 Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Mon, 17 Jun 2024 17:08:36 +0300 Subject: [PATCH 05/10] check-types & lint --- .../test/perf/epoch/epochAltair.test.ts | 2 +- .../perf/epoch/processSyncCommitteeUpdates.test.ts | 4 ++-- packages/state-transition/test/perf/util.ts | 8 +++++++- .../test/perf/util/shufflings.test.ts | 12 ++++++++++-- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/state-transition/test/perf/epoch/epochAltair.test.ts b/packages/state-transition/test/perf/epoch/epochAltair.test.ts index 6c43151cc137..39e0a1b4c5c3 100644 --- a/packages/state-transition/test/perf/epoch/epochAltair.test.ts +++ b/packages/state-transition/test/perf/epoch/epochAltair.test.ts @@ -172,7 +172,7 @@ function benchmarkAltairEpochSteps(stateOg: LazyValue id: `${stateId} - altair processSyncCommitteeUpdates`, convergeFactor: 1 / 100, // Very unstable make it converge faster beforeEach: () => stateOg.value.clone() as CachedBeaconStateAltair, - fn: (state) => processSyncCommitteeUpdates(state), + fn: (state) => processSyncCommitteeUpdates(ForkSeq.altair, state), }); itBench({ diff --git a/packages/state-transition/test/perf/epoch/processSyncCommitteeUpdates.test.ts b/packages/state-transition/test/perf/epoch/processSyncCommitteeUpdates.test.ts index ffde30e1302c..4497dc16be0c 100644 --- a/packages/state-transition/test/perf/epoch/processSyncCommitteeUpdates.test.ts +++ b/packages/state-transition/test/perf/epoch/processSyncCommitteeUpdates.test.ts @@ -1,5 +1,5 @@ import {itBench} from "@dapplion/benchmark"; -import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD} from "@lodestar/params"; +import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD, ForkSeq} from "@lodestar/params"; import {processSyncCommitteeUpdates} from "../../../src/epoch/processSyncCommitteeUpdates.js"; import {StateAltair} from "../types.js"; import {generatePerfTestCachedStateAltair, numValidators} from "../util.js"; @@ -21,7 +21,7 @@ describe("altair processSyncCommitteeUpdates", () => { }, fn: (state) => { const nextSyncCommitteeBefore = state.nextSyncCommittee; - processSyncCommitteeUpdates(state); + processSyncCommitteeUpdates(ForkSeq.altair, state); if (state.nextSyncCommittee === nextSyncCommitteeBefore) { throw Error("nextSyncCommittee instance has not changed"); } diff --git a/packages/state-transition/test/perf/util.ts b/packages/state-transition/test/perf/util.ts index 4df6746ea938..4cc984786778 100644 --- a/packages/state-transition/test/perf/util.ts +++ b/packages/state-transition/test/perf/util.ts @@ -7,6 +7,7 @@ import {createBeaconConfig, createChainForkConfig} from "@lodestar/config"; import { EPOCHS_PER_ETH1_VOTING_PERIOD, EPOCHS_PER_HISTORICAL_VECTOR, + ForkSeq, MAX_ATTESTATIONS, MAX_EFFECTIVE_BALANCE, SLOTS_PER_EPOCH, @@ -273,7 +274,12 @@ export function generatePerformanceStateAltair(pubkeysArg?: Uint8Array[]): Beaco const activeValidatorIndices = getActiveValidatorIndices(altairState, epoch); const effectiveBalanceIncrements = getEffectiveBalanceIncrements(altairState); - const {syncCommittee} = getNextSyncCommittee(altairState, activeValidatorIndices, effectiveBalanceIncrements); + const {syncCommittee} = getNextSyncCommittee( + ForkSeq.altair, + altairState, + activeValidatorIndices, + effectiveBalanceIncrements + ); state.currentSyncCommittee = syncCommittee; state.nextSyncCommittee = syncCommittee; diff --git a/packages/state-transition/test/perf/util/shufflings.test.ts b/packages/state-transition/test/perf/util/shufflings.test.ts index e04dd405d960..670ae1c95c4b 100644 --- a/packages/state-transition/test/perf/util/shufflings.test.ts +++ b/packages/state-transition/test/perf/util/shufflings.test.ts @@ -1,6 +1,6 @@ import {itBench} from "@dapplion/benchmark"; import {Epoch} from "@lodestar/types"; -import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params"; +import {DOMAIN_BEACON_PROPOSER, ForkSeq} from "@lodestar/params"; import { computeEpochAtSlot, CachedBeaconStateAllForks, @@ -28,7 +28,13 @@ describe("epoch shufflings", () => { id: `computeProposers - vc ${numValidators}`, fn: () => { const epochSeed = getSeed(state, state.epochCtx.nextShuffling.epoch, DOMAIN_BEACON_PROPOSER); - computeProposers(epochSeed, state.epochCtx.nextShuffling, state.epochCtx.effectiveBalanceIncrements); + const fork = state.config.getForkSeq(state.slot); + computeProposers( + epochSeed, + state.epochCtx.nextShuffling, + state.epochCtx.effectiveBalanceIncrements, + fork >= ForkSeq.electra + ); }, }); @@ -42,7 +48,9 @@ describe("epoch shufflings", () => { itBench({ id: `getNextSyncCommittee - vc ${numValidators}`, fn: () => { + const fork = state.config.getForkSeq(state.slot); getNextSyncCommittee( + fork, state, state.epochCtx.nextShuffling.activeIndices, state.epochCtx.effectiveBalanceIncrements From 2ba9ab84b2e1ae1a1668ca6f56d27b961c837e8a Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Tue, 18 Jun 2024 16:29:01 +0300 Subject: [PATCH 06/10] Skip invalid test --- packages/beacon-node/test/spec/utils/specTestIterator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/beacon-node/test/spec/utils/specTestIterator.ts b/packages/beacon-node/test/spec/utils/specTestIterator.ts index 63fe0cc10442..b1930f0f8f30 100644 --- a/packages/beacon-node/test/spec/utils/specTestIterator.ts +++ b/packages/beacon-node/test/spec/utils/specTestIterator.ts @@ -66,7 +66,7 @@ export const defaultSkipOpts: SkipOpts = { /^capella\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, /^deneb\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, ], - skippedTests: [], + skippedTests: [/incorrect_not_enough_consolidation_churn_available/], skippedRunners: ["merkle_proof", "networking"], }; From 5bc9d94edd0d42b5953892d340dfcc1e574eac43 Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Fri, 21 Jun 2024 19:47:17 +0300 Subject: [PATCH 07/10] Fix rebase + lint --- .../beacon-node/src/chain/produceBlock/produceBlockBody.ts | 1 - packages/beacon-node/test/spec/presets/operations.test.ts | 1 - .../src/block/processConsolidationRequest.ts | 5 ++--- packages/state-transition/src/block/processOperations.ts | 2 +- .../src/epoch/processPendingBalanceDeposits.ts | 2 +- packages/state-transition/src/signatureSets/index.ts | 4 ++-- 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts index 0e3a55e31e1c..988e3ca135e1 100644 --- a/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts +++ b/packages/beacon-node/src/chain/produceBlock/produceBlockBody.ts @@ -11,7 +11,6 @@ import { capella, deneb, Wei, - electra, } from "@lodestar/types"; import { CachedBeaconStateAllForks, diff --git a/packages/beacon-node/test/spec/presets/operations.test.ts b/packages/beacon-node/test/spec/presets/operations.test.ts index f5d5aa52f5a6..0e8a105e5cde 100644 --- a/packages/beacon-node/test/spec/presets/operations.test.ts +++ b/packages/beacon-node/test/spec/presets/operations.test.ts @@ -103,7 +103,6 @@ const operationFns: Record> = consolidation_request: (state, testCase: {consolidation_request: electra.ConsolidationRequest}) => { blockFns.processConsolidationRequest(state as CachedBeaconStateElectra, testCase.consolidation_request); }, - }; export type BlockProcessFn = (state: T, testCase: any) => void; diff --git a/packages/state-transition/src/block/processConsolidationRequest.ts b/packages/state-transition/src/block/processConsolidationRequest.ts index 44d6aa33fb8c..2f12065fde41 100644 --- a/packages/state-transition/src/block/processConsolidationRequest.ts +++ b/packages/state-transition/src/block/processConsolidationRequest.ts @@ -10,7 +10,6 @@ export function processConsolidationRequest( state: CachedBeaconStateElectra, consolidationRequest: electra.ConsolidationRequest ): void { - // If the pending consolidations queue is full, consolidation requests are ignored if (state.pendingConsolidations.length >= PENDING_CONSOLIDATIONS_LIMIT) { return; @@ -30,7 +29,7 @@ export function processConsolidationRequest( } // Verify that source != target, so a consolidation cannot be used as an exit. - if (sourceIndex === targetIndex){ + if (sourceIndex === targetIndex) { return; } @@ -71,4 +70,4 @@ export function processConsolidationRequest( targetIndex, }); state.pendingConsolidations.push(pendingConsolidation); -} \ No newline at end of file +} diff --git a/packages/state-transition/src/block/processOperations.ts b/packages/state-transition/src/block/processOperations.ts index 810ce202bb8f..732db8598058 100644 --- a/packages/state-transition/src/block/processOperations.ts +++ b/packages/state-transition/src/block/processOperations.ts @@ -67,7 +67,7 @@ export function processOperations( const stateElectra = state as CachedBeaconStateElectra; const bodyElectra = body as electra.BeaconBlockBody; - for (const depositRequest of bodyElectra.executionPayload.depositReceipts) { + for (const depositRequest of bodyElectra.executionPayload.depositRequests) { processDepositRequest(fork, stateElectra, depositRequest); } diff --git a/packages/state-transition/src/epoch/processPendingBalanceDeposits.ts b/packages/state-transition/src/epoch/processPendingBalanceDeposits.ts index 112832c920d7..e6e43bbaa089 100644 --- a/packages/state-transition/src/epoch/processPendingBalanceDeposits.ts +++ b/packages/state-transition/src/epoch/processPendingBalanceDeposits.ts @@ -10,7 +10,7 @@ import {getCurrentEpoch} from "../util/epoch.js"; * For each eligible `deposit`, call `increaseBalance()`. * Remove the processed deposits from `state.pendingBalanceDeposits`. * Update `state.depositBalanceToConsume` for the next epoch - * + * * TODO Electra: Update ssz library to support batch push to `pendingBalanceDeposits` */ export function processPendingBalanceDeposits(state: CachedBeaconStateElectra): void { diff --git a/packages/state-transition/src/signatureSets/index.ts b/packages/state-transition/src/signatureSets/index.ts index 4a84f3afc83e..b1336223eb5a 100644 --- a/packages/state-transition/src/signatureSets/index.ts +++ b/packages/state-transition/src/signatureSets/index.ts @@ -1,7 +1,7 @@ import {ForkSeq} from "@lodestar/params"; -import {allForks, altair, capella, electra} from "@lodestar/types"; +import {allForks, altair, capella} from "@lodestar/types"; import {ISignatureSet} from "../util/index.js"; -import {CachedBeaconStateAllForks, CachedBeaconStateAltair, CachedBeaconStateElectra} from "../types.js"; +import {CachedBeaconStateAllForks, CachedBeaconStateAltair} from "../types.js"; import {getSyncCommitteeSignatureSet} from "../block/processSyncCommittee.js"; import {getProposerSlashingsSignatureSets} from "./proposerSlashings.js"; import {getAttesterSlashingsSignatureSets} from "./attesterSlashings.js"; From 18c54da067a224db996f96a565e4580f5a84f633 Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Fri, 21 Jun 2024 19:59:29 +0300 Subject: [PATCH 08/10] Remove early return statement in `computeProposers` --- packages/state-transition/src/util/seed.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/state-transition/src/util/seed.ts b/packages/state-transition/src/util/seed.ts index 126d7df00c74..a1f65c814dcf 100644 --- a/packages/state-transition/src/util/seed.ts +++ b/packages/state-transition/src/util/seed.ts @@ -18,9 +18,6 @@ import {EffectiveBalanceIncrements} from "../cache/effectiveBalanceIncrements.js import {computeStartSlotAtEpoch} from "./epoch.js"; import {computeEpochAtSlot} from "./epoch.js"; -// Max number of iterations over validator set when computing proposer index -const MAX_ITERATION_OVER_VALIDATORS = 10; - /** * Compute proposer indices for an epoch */ @@ -83,11 +80,6 @@ export function computeProposerIndex( return candidateIndex; } i += 1; - // Spec does not have this condition to end infinite loop. Spec test won't pass if we - // only loop the validator indices once. Electra spec test requires MAX_ITERATION_OVER_VALIDATORS >= 6 - if (i === indices.length * MAX_ITERATION_OVER_VALIDATORS) { - return -1; - } } } From 8797fe63c1e14729d516cf21d5d357eff29c684a Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Mon, 24 Jun 2024 13:08:55 +0300 Subject: [PATCH 09/10] Address comment --- packages/config/src/forkConfig/index.ts | 8 +++++++- packages/config/src/forkConfig/types.ts | 5 ++++- .../state-transition/src/cache/epochCache.ts | 12 ++++++------ packages/state-transition/src/util/seed.ts | 19 ++++++++++--------- .../test/perf/util/shufflings.test.ts | 9 ++------- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/packages/config/src/forkConfig/index.ts b/packages/config/src/forkConfig/index.ts index efb27ca1505f..266c138b6842 100644 --- a/packages/config/src/forkConfig/index.ts +++ b/packages/config/src/forkConfig/index.ts @@ -7,7 +7,7 @@ import { isForkExecution, isForkBlobs, } from "@lodestar/params"; -import {Slot, allForks, Version, ssz} from "@lodestar/types"; +import {Slot, allForks, Version, ssz, Epoch} from "@lodestar/types"; import {ChainConfig} from "../chainConfig/index.js"; import {ForkConfig, ForkInfo} from "./types.js"; @@ -80,6 +80,9 @@ export function createForkConfig(config: ChainConfig): ForkConfig { // Fork convenience methods getForkInfo(slot: Slot): ForkInfo { const epoch = Math.floor(Math.max(slot, 0) / SLOTS_PER_EPOCH); + return this.getForkInfoFromEpoch(epoch); + }, + getForkInfoFromEpoch(epoch: Epoch): ForkInfo { // NOTE: forks must be sorted by descending epoch, latest fork first for (const fork of forksDescendingEpochOrder) { if (epoch >= fork.epoch) return fork; @@ -92,6 +95,9 @@ export function createForkConfig(config: ChainConfig): ForkConfig { getForkSeq(slot: Slot): ForkSeq { return this.getForkInfo(slot).seq; }, + getForkSeqFromEpoch(epoch: Epoch): ForkSeq { + return this.getForkInfoFromEpoch(epoch).seq; + }, getForkVersion(slot: Slot): Version { return this.getForkInfo(slot).version; }, diff --git a/packages/config/src/forkConfig/types.ts b/packages/config/src/forkConfig/types.ts index b61752bf3698..4ca1bd6a186d 100644 --- a/packages/config/src/forkConfig/types.ts +++ b/packages/config/src/forkConfig/types.ts @@ -21,11 +21,14 @@ export type ForkConfig = { /** Get the hard-fork info for the active fork at `slot` */ getForkInfo(slot: Slot): ForkInfo; - + /** Get the hard-fork info for the active fork at `epoch` */ + getForkInfoFromEpoch(epoch: Epoch): ForkInfo; /** Get the hard-fork name at a given slot */ getForkName(slot: Slot): ForkName; /** Get the hard-fork sequence number at a given slot */ getForkSeq(slot: Slot): ForkSeq; + /** Get the hard-fork sequence number at a given epoch */ + getForkSeqFromEpoch(epoch: Epoch): ForkSeq; /** Get the hard-fork version at a given slot */ getForkVersion(slot: Slot): Version; /** Get SSZ types by hard-fork */ diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index 06c8d666d279..1dd471ea76ab 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -395,10 +395,10 @@ export class EpochCache { const proposers = currentShuffling.activeIndices.length > 0 ? computeProposers( + config.getForkSeqFromEpoch(currentEpoch), currentProposerSeed, currentShuffling, - effectiveBalanceIncrements, - currentEpoch >= config.ELECTRA_FORK_EPOCH + effectiveBalanceIncrements ) : []; @@ -577,10 +577,10 @@ export class EpochCache { const currentProposerSeed = getSeed(state, this.currentShuffling.epoch, DOMAIN_BEACON_PROPOSER); this.proposers = computeProposers( + this.config.getForkSeqFromEpoch(currEpoch), currentProposerSeed, this.currentShuffling, - this.effectiveBalanceIncrements, - currEpoch >= this.config.ELECTRA_FORK_EPOCH + this.effectiveBalanceIncrements ); // Only pre-compute the seed since it's very cheap. Do the expensive computeProposers() call only on demand. @@ -778,10 +778,10 @@ export class EpochCache { getBeaconProposersNextEpoch(): ValidatorIndex[] { if (!this.proposersNextEpoch.computed) { const indexes = computeProposers( + this.config.getForkSeqFromEpoch(this.epoch + 1), this.proposersNextEpoch.seed, this.nextShuffling, - this.effectiveBalanceIncrements, - this.epoch + 1 >= this.config.ELECTRA_FORK_EPOCH + this.effectiveBalanceIncrements ); this.proposersNextEpoch = {computed: true, indexes}; } diff --git a/packages/state-transition/src/util/seed.ts b/packages/state-transition/src/util/seed.ts index a1f65c814dcf..a5a0028d6c17 100644 --- a/packages/state-transition/src/util/seed.ts +++ b/packages/state-transition/src/util/seed.ts @@ -22,20 +22,20 @@ import {computeEpochAtSlot} from "./epoch.js"; * Compute proposer indices for an epoch */ export function computeProposers( + fork: ForkSeq, epochSeed: Uint8Array, shuffling: {epoch: Epoch; activeIndices: ArrayLike}, - effectiveBalanceIncrements: EffectiveBalanceIncrements, - isAfterElectra: boolean + effectiveBalanceIncrements: EffectiveBalanceIncrements ): number[] { const startSlot = computeStartSlotAtEpoch(shuffling.epoch); const proposers = []; for (let slot = startSlot; slot < startSlot + SLOTS_PER_EPOCH; slot++) { proposers.push( computeProposerIndex( + fork, effectiveBalanceIncrements, shuffling.activeIndices, - digest(Buffer.concat([epochSeed, intToBytes(slot, 8)])), - isAfterElectra + digest(Buffer.concat([epochSeed, intToBytes(slot, 8)])) ) ); } @@ -48,10 +48,10 @@ export function computeProposers( * SLOW CODE - 🐢 */ export function computeProposerIndex( + fork: ForkSeq, effectiveBalanceIncrements: EffectiveBalanceIncrements, indices: ArrayLike, - seed: Uint8Array, - isAfterElectra: boolean + seed: Uint8Array ): ValidatorIndex { if (indices.length === 0) { throw Error("Validator indices must not be empty"); @@ -59,9 +59,10 @@ export function computeProposerIndex( // TODO: Inline outside this function const MAX_RANDOM_BYTE = 2 ** 8 - 1; - const MAX_EFFECTIVE_BALANCE_INCREMENT = isAfterElectra - ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT - : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; + const MAX_EFFECTIVE_BALANCE_INCREMENT = + fork >= ForkSeq.electra + ? MAX_EFFECTIVE_BALANCE_ELECTRA / EFFECTIVE_BALANCE_INCREMENT + : MAX_EFFECTIVE_BALANCE / EFFECTIVE_BALANCE_INCREMENT; let i = 0; /* eslint-disable-next-line no-constant-condition */ diff --git a/packages/state-transition/test/perf/util/shufflings.test.ts b/packages/state-transition/test/perf/util/shufflings.test.ts index 670ae1c95c4b..2730db434e47 100644 --- a/packages/state-transition/test/perf/util/shufflings.test.ts +++ b/packages/state-transition/test/perf/util/shufflings.test.ts @@ -1,6 +1,6 @@ import {itBench} from "@dapplion/benchmark"; import {Epoch} from "@lodestar/types"; -import {DOMAIN_BEACON_PROPOSER, ForkSeq} from "@lodestar/params"; +import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params"; import { computeEpochAtSlot, CachedBeaconStateAllForks, @@ -29,12 +29,7 @@ describe("epoch shufflings", () => { fn: () => { const epochSeed = getSeed(state, state.epochCtx.nextShuffling.epoch, DOMAIN_BEACON_PROPOSER); const fork = state.config.getForkSeq(state.slot); - computeProposers( - epochSeed, - state.epochCtx.nextShuffling, - state.epochCtx.effectiveBalanceIncrements, - fork >= ForkSeq.electra - ); + computeProposers(fork, epochSeed, state.epochCtx.nextShuffling, state.epochCtx.effectiveBalanceIncrements); }, }); From 375a760767876335b3ec7ec3d74c3f31a890d1af Mon Sep 17 00:00:00 2001 From: Navie Chan Date: Mon, 24 Jun 2024 13:10:59 +0300 Subject: [PATCH 10/10] Address comment --- packages/beacon-node/test/spec/utils/specTestIterator.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/beacon-node/test/spec/utils/specTestIterator.ts b/packages/beacon-node/test/spec/utils/specTestIterator.ts index b1930f0f8f30..ac0d70307d33 100644 --- a/packages/beacon-node/test/spec/utils/specTestIterator.ts +++ b/packages/beacon-node/test/spec/utils/specTestIterator.ts @@ -66,6 +66,7 @@ export const defaultSkipOpts: SkipOpts = { /^capella\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, /^deneb\/light_client\/single_merkle_proof\/BeaconBlockBody.*/, ], + // TODO Electra: Review this test in the next spec test release skippedTests: [/incorrect_not_enough_consolidation_churn_available/], skippedRunners: ["merkle_proof", "networking"], };