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

fix: fix electra genesis spec test #6764

Merged
merged 5 commits into from
May 14, 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
8 changes: 7 additions & 1 deletion packages/beacon-node/src/chain/genesis/genesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,13 @@ export class GenesisBuilder implements IGenesisBuilder {
};
});

const {activatedValidatorCount} = applyDeposits(this.config, this.state, newDeposits, this.depositTree);
const {activatedValidatorCount} = applyDeposits(
this.config.getForkSeq(this.state.slot),
this.config,
this.state,
newDeposits,
this.depositTree
);
this.activatedValidatorCount += activatedValidatorCount;

// TODO: If necessary persist deposits here to this.db.depositData, this.db.depositDataRoot
Expand Down
29 changes: 22 additions & 7 deletions packages/state-transition/src/util/genesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ import {
EFFECTIVE_BALANCE_INCREMENT,
EPOCHS_PER_HISTORICAL_VECTOR,
ForkName,
ForkSeq,
GENESIS_EPOCH,
GENESIS_SLOT,
MAX_EFFECTIVE_BALANCE,
UNSET_DEPOSIT_RECEIPTS_START_INDEX,
} from "@lodestar/params";
import {Bytes32, phase0, Root, ssz, TimeSeconds} from "@lodestar/types";

import {CachedBeaconStateAllForks, BeaconStateAllForks} from "../types.js";
import {CachedBeaconStateAllForks, BeaconStateAllForks, CachedBeaconStateElectra} from "../types.js";
import {createCachedBeaconState} from "../cache/stateCache.js";
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 {getTemporaryBlockHeader} from "./blockRoot.js";
Expand Down Expand Up @@ -127,6 +129,7 @@ export function applyTimestamp(config: ChainForkConfig, state: CachedBeaconState
* @returns active validator indices
*/
export function applyDeposits(
fork: ForkSeq,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a lot of our code has new "fork" param and it caused a lot of files changed, we can just get the config from state and determine the fork based on state.slot
the good thing is we don't have to keep computing fork in different functions if we pass fork param
I think we can store fork inside the CachedBeaconState so that we don't have to pass fork param around or keep recomputing it in different functions

config: ChainForkConfig,
state: CachedBeaconStateAllForks,
newDeposits: phase0.Deposit[],
Expand Down Expand Up @@ -164,6 +167,16 @@ export function applyDeposits(
processDeposit(fork, state, deposit);
}

// Process deposit balance updates
if (fork >= ForkSeq.electra) {
const stateElectra = state as CachedBeaconStateElectra;
stateElectra.commit();
for (const {index: validatorIndex, amount} of stateElectra.pendingBalanceDeposits.getAllReadonly()) {
increaseBalance(state, validatorIndex, Number(amount));
}
stateElectra.pendingBalanceDeposits = ssz.electra.PendingBalanceDeposits.defaultViewDU();
}

// Process activations
const {epochCtx} = state;
const balancesArr = state.balances.getAll();
Expand Down Expand Up @@ -226,6 +239,8 @@ export function initializeBeaconStateFromEth1(
getTemporaryBlockHeader(config, config.getForkTypes(GENESIS_SLOT).BeaconBlock.defaultValue())
);

const fork = config.getForkSeq(GENESIS_SLOT);

// We need a CachedBeaconState to run processDeposit() which uses various caches.
// However at this point the state's syncCommittees are not known.
// This function can be called by:
Expand All @@ -240,13 +255,13 @@ export function initializeBeaconStateFromEth1(
applyEth1BlockHash(state, eth1BlockHash);

// Process deposits
applyDeposits(config, state, deposits, fullDepositDataRootList);
applyDeposits(fork, config, state, deposits, fullDepositDataRootList);

// Commit before reading all validators in `getActiveValidatorIndices()`
state.commit();
const activeValidatorIndices = getActiveValidatorIndices(state, computeEpochAtSlot(GENESIS_SLOT));

if (GENESIS_SLOT >= config.ALTAIR_FORK_EPOCH) {
if (fork >= ForkSeq.altair) {
const {syncCommittee} = getNextSyncCommittee(
state,
activeValidatorIndices,
Expand All @@ -259,7 +274,7 @@ export function initializeBeaconStateFromEth1(
stateAltair.nextSyncCommittee = ssz.altair.SyncCommittee.toViewDU(syncCommittee);
}

if (GENESIS_SLOT >= config.BELLATRIX_FORK_EPOCH) {
if (fork >= ForkSeq.bellatrix) {
const stateBellatrix = state as CompositeViewDU<typeof ssz.bellatrix.BeaconState>;
stateBellatrix.fork.previousVersion = config.BELLATRIX_FORK_VERSION;
stateBellatrix.fork.currentVersion = config.BELLATRIX_FORK_VERSION;
Expand All @@ -268,7 +283,7 @@ export function initializeBeaconStateFromEth1(
ssz.bellatrix.ExecutionPayloadHeader.defaultViewDU();
}

if (GENESIS_SLOT >= config.CAPELLA_FORK_EPOCH) {
if (fork >= ForkSeq.capella) {
const stateCapella = state as CompositeViewDU<typeof ssz.capella.BeaconState>;
stateCapella.fork.previousVersion = config.CAPELLA_FORK_VERSION;
stateCapella.fork.currentVersion = config.CAPELLA_FORK_VERSION;
Expand All @@ -277,7 +292,7 @@ export function initializeBeaconStateFromEth1(
ssz.capella.ExecutionPayloadHeader.defaultViewDU();
}

if (GENESIS_SLOT >= config.DENEB_FORK_EPOCH) {
if (fork >= ForkSeq.deneb) {
const stateDeneb = state as CompositeViewDU<typeof ssz.deneb.BeaconState>;
stateDeneb.fork.previousVersion = config.DENEB_FORK_VERSION;
stateDeneb.fork.currentVersion = config.DENEB_FORK_VERSION;
Expand All @@ -286,7 +301,7 @@ export function initializeBeaconStateFromEth1(
ssz.deneb.ExecutionPayloadHeader.defaultViewDU();
}

if (GENESIS_SLOT >= config.ELECTRA_FORK_EPOCH) {
if (fork >= ForkSeq.electra) {
const stateElectra = state as CompositeViewDU<typeof ssz.electra.BeaconState>;
stateElectra.fork.previousVersion = config.ELECTRA_FORK_VERSION;
stateElectra.fork.currentVersion = config.ELECTRA_FORK_VERSION;
Expand Down
7 changes: 6 additions & 1 deletion packages/types/src/electra/sszTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,11 @@ export const PendingBalanceDeposit = new ContainerType(
{typeName: "PendingBalanceDeposit", jsonCase: "eth2"}
);

export const PendingBalanceDeposits = new ListCompositeType(
PendingBalanceDeposit,
Number(PENDING_BALANCE_DEPOSITS_LIMIT)
);

export const PartialWithdrawal = new ContainerType(
{
index: ValidatorIndex,
Expand Down Expand Up @@ -341,7 +346,7 @@ export const BeaconState = new ContainerType(
earliestExitEpoch: Epoch, // New in Electra:EIP7251
consolidationBalanceToConsume: Gwei, // New in Electra:EIP7251
earliestConsolidationEpoch: Epoch, // New in Electra:EIP7251
pendingBalanceDeposits: new ListCompositeType(PendingBalanceDeposit, Number(PENDING_BALANCE_DEPOSITS_LIMIT)), // new in electra:eip7251
pendingBalanceDeposits: PendingBalanceDeposits, // new in electra:eip7251
pendingPartialWithdrawals: new ListCompositeType(PartialWithdrawal, Number(PENDING_PARTIAL_WITHDRAWALS_LIMIT)), // New in Electra:EIP7251
pendingConsolidations: new ListCompositeType(PendingConsolidation, Number(PENDING_CONSOLIDATIONS_LIMIT)), // new in electra:eip7251
},
Expand Down