Skip to content

Commit

Permalink
Add state upgrade to capella and enable spec tests (#4679)
Browse files Browse the repository at this point in the history
  • Loading branch information
g11tech authored Oct 21, 2022
1 parent 64f6334 commit 81c090f
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 14 deletions.
9 changes: 7 additions & 2 deletions packages/beacon-node/test/spec/presets/fork.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import {BeaconStateAllForks, CachedBeaconStateAltair, CachedBeaconStatePhase0} from "@lodestar/state-transition";
import {
BeaconStateAllForks,
CachedBeaconStateBellatrix,
CachedBeaconStateAltair,
CachedBeaconStatePhase0,
} from "@lodestar/state-transition";
import * as slotFns from "@lodestar/state-transition/slot";
import {phase0, ssz} from "@lodestar/types";
import {ForkName} from "@lodestar/params";
Expand All @@ -23,7 +28,7 @@ export const fork: TestRunnerFn<ForkStateCase, BeaconStateAllForks> = (forkNext)
case ForkName.bellatrix:
return slotFns.upgradeStateToBellatrix(preState as CachedBeaconStateAltair);
case ForkName.capella:
throw Error("capella upgrade not implemented yet");
return slotFns.upgradeStateToCapella(preState as CachedBeaconStateBellatrix);
}
},
options: {
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-node/test/spec/specTestVersioning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {IDownloadTestsOptions} from "@lodestar/spec-test-util";
const __dirname = path.dirname(fileURLToPath(import.meta.url));

export const ethereumConsensusSpecsTests: IDownloadTestsOptions = {
specVersion: "v1.2.0-rc.3",
specVersion: "v1.2.0",
// Target directory is the host package root: 'packages/*/spec-tests'
outputDir: path.join(__dirname, "../../spec-tests"),
specTestsRepoUrl: "https://github.com/ethereum/consensus-spec-tests",
Expand Down
6 changes: 1 addition & 5 deletions packages/beacon-node/test/spec/utils/specTestIterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ const ARTIFACT_FILENAMES = new Set([
*/
export function specTestIterator(configDirpath: string, testRunners: Record<string, TestRunner>): void {
for (const forkStr of readdirSyncSpec(configDirpath)) {
// TODO enable capella
if (forkStr === "capella") {
continue;
}
const fork = ForkName[forkStr as ForkName];
if (fork === undefined) {
throw Error(`Unknown fork ${forkStr}`);
Expand All @@ -52,7 +48,7 @@ export function specTestIterator(configDirpath: string, testRunners: Record<stri
const forkDirpath = path.join(configDirpath, fork);
for (const testRunnerName of readdirSyncSpec(forkDirpath)) {
// We don't have runner for light client yet
if (testRunnerName === "light_client") {
if (["light_client", "sync"].includes(testRunnerName)) {
continue;
}
const testRunnerDirpath = path.join(forkDirpath, testRunnerName);
Expand Down
2 changes: 1 addition & 1 deletion packages/params/src/presets/mainnet/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {altair} from "./altair.js";
import {bellatrix} from "./bellatrix.js";
import {capella} from "./capella.js";

export const commit = "v1.2.0-rc.3";
export const commit = "v1.2.0";

export const preset: BeaconPreset = {
...phase0,
Expand Down
2 changes: 1 addition & 1 deletion packages/params/src/presets/minimal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {altair} from "./altair.js";
import {bellatrix} from "./bellatrix.js";
import {capella} from "./capella.js";

export const commit = "v1.2.0-rc.3";
export const commit = "v1.2.0";

export const preset: BeaconPreset = {
...phase0,
Expand Down
3 changes: 2 additions & 1 deletion packages/state-transition/src/block/processDeposit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ export function processDeposit(fork: ForkSeq, state: CachedBeaconStateAllForks,
withdrawableEpoch: FAR_FUTURE_EPOCH,
effectiveBalance,
slashed: false,
fullyWithdrawnEpoch: FAR_FUTURE_EPOCH,
// This field is removed in the latest spec, but is present in 1.2.0 set to 0
fullyWithdrawnEpoch: 0,
})
);
}
Expand Down
1 change: 1 addition & 0 deletions packages/state-transition/src/slot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {ZERO_HASH} from "../constants/index.js";

export {upgradeStateToAltair} from "./upgradeStateToAltair.js";
export {upgradeStateToBellatrix} from "./upgradeStateToBellatrix.js";
export {upgradeStateToCapella} from "./upgradeStateToCapella.js";

/**
* Dial state to next slot. Common for all forks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function upgradeStateToBellatrix(stateAltair: CachedBeaconStateAltair): C
// An altair BeaconState tree can be safely casted to a bellatrix BeaconState tree because:
// - All new fields are appended at the end
//
// altair | op | altair
// altair | op | bellatrix
// ----------------------------- | --- | ------------
// genesis_time | - | genesis_time
// genesis_validators_root | - | genesis_validators_root
Expand Down
75 changes: 75 additions & 0 deletions packages/state-transition/src/slot/upgradeStateToCapella.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {ssz} from "@lodestar/types";
import {CachedBeaconStateBellatrix, CachedBeaconStateCapella} from "../types.js";
import {getCachedBeaconState} from "../cache/stateCache.js";

/**
* Upgrade a state from altair to bellatrix.
*/
export function upgradeStateToCapella(stateBellatrix: CachedBeaconStateBellatrix): CachedBeaconStateCapella {
const {config} = stateBellatrix;

// Get underlying node and cast bellatrix tree to capella tree
//
// An bellatrix BeaconState tree can be safely casted to a capella BeaconState tree because:
// - Deprecated fields are replaced by new fields at the exact same indexes
// - All new fields are appended at the end
//
// bellatrix | op | capella
// -------------------------------- | ---- | ------------
// genesis_time | - | genesis_time
// genesis_validators_root | - | genesis_validators_root
// slot | - | slot
// fork | - | fork
// latest_block_header | - | latest_block_header
// block_roots | - | block_roots
// state_roots | - | state_roots
// historical_roots | - | historical_roots
// eth1_data | - | eth1_data
// eth1_data_votes | - | eth1_data_votes
// eth1_deposit_index | - | eth1_deposit_index
// validators | diff | validators
// balances | - | balances
// randao_mixes | - | randao_mixes
// slashings | - | slashings
// previous_epoch_participation | - | previous_epoch_participation
// current_epoch_participation | - | current_epoch_participation
// justification_bits | - | justification_bits
// previous_justified_checkpoint | - | previous_justified_checkpoint
// current_justified_checkpoint | - | current_justified_checkpoint
// finalized_checkpoint | - | finalized_checkpoint
// inactivity_scores | - | inactivity_scores
// current_sync_committee | - | current_sync_committee
// next_sync_committee | - | next_sync_committee
// latest_execution_payload_header | diff | latest_execution_payload_header
// - | new | withdrawal_queue
// - | new | next_withdrawal_index
// - | new | next_partial_withdrawal_validator_index

const stateBellatrixNode = ssz.bellatrix.BeaconState.commitViewDU(stateBellatrix);
const stateCapellaView = ssz.capella.BeaconState.getViewDU(stateBellatrixNode);
// Attach existing BeaconStateCache from stateBellatrix to new stateCapellaView object
const stateCapella = getCachedBeaconState(stateCapellaView, stateBellatrix);

stateCapella.fork = ssz.phase0.Fork.toViewDU({
previousVersion: stateBellatrix.fork.currentVersion,
currentVersion: config.CAPELLA_FORK_VERSION,
epoch: stateBellatrix.epochCtx.epoch,
});

// Upgrade the validators, this validator change is not present in latest specs but in 1.2.0
// so just set it to 0 and cleanup later
for (let i = 0; i < stateCapella.validators.length; i++) {
const validator = stateCapella.validators.get(i);
validator.fullyWithdrawnEpoch = Infinity;
}
// Nothing to do for latestExecutionPayloadHeader as the root is set to 0 by default
stateCapella.withdrawalQueue = ssz.capella.WithdrawalQueue.defaultViewDU();
// nextWithdrawalIndex and nextPartialWithdrawalValidatorIndex are also set to 0 by default

// Commit new added fields ViewDU to the root node
stateCapella.commit();
// Clear cache to ensure the cache of bellatrix fields is not used by new capella fields
stateCapella["clearCache"]();

return stateCapella;
}
12 changes: 10 additions & 2 deletions packages/state-transition/src/stateTransition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import {SLOTS_PER_EPOCH} from "@lodestar/params";
import {toHexString} from "@chainsafe/ssz";
import {IBeaconStateTransitionMetrics} from "./metrics.js";
import {beforeProcessEpoch, EpochProcessOpts} from "./cache/epochProcess.js";
import {CachedBeaconStateAllForks, CachedBeaconStatePhase0, CachedBeaconStateAltair} from "./types.js";
import {
CachedBeaconStateAllForks,
CachedBeaconStatePhase0,
CachedBeaconStateAltair,
CachedBeaconStateBellatrix,
} from "./types.js";
import {computeEpochAtSlot} from "./util/index.js";
import {verifyProposerSignature} from "./signatureSets/index.js";
import {processSlot, upgradeStateToAltair, upgradeStateToBellatrix} from "./slot/index.js";
import {processSlot, upgradeStateToAltair, upgradeStateToBellatrix, upgradeStateToCapella} from "./slot/index.js";
import {processBlock} from "./block/index.js";
import {processEpoch} from "./epoch/index.js";

Expand Down Expand Up @@ -145,6 +150,9 @@ function processSlotsWithTransientCache(
if (stateSlot === config.BELLATRIX_FORK_EPOCH) {
postState = upgradeStateToBellatrix(postState as CachedBeaconStateAltair) as CachedBeaconStateAllForks;
}
if (stateSlot === config.CAPELLA_FORK_EPOCH) {
postState = upgradeStateToCapella(postState as CachedBeaconStateBellatrix) as CachedBeaconStateAllForks;
}
} else {
postState.slot++;
}
Expand Down

0 comments on commit 81c090f

Please sign in to comment.