Skip to content

Commit

Permalink
Add genesis minimal spec test
Browse files Browse the repository at this point in the history
  • Loading branch information
twoeths committed May 27, 2021
1 parent 30f5512 commit cc659de
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 9 deletions.
21 changes: 18 additions & 3 deletions packages/beacon-state-transition/src/util/genesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {processDeposit as altairProcessDeposit} from "../naive/altair";
import {computeEpochAtSlot} from "./epoch";
import {getActiveValidatorIndices} from "./validator";
import {getTemporaryBlockHeader} from "./blockRoot";
import {getNextSyncCommittee} from "../altair/state_accessor";

// TODO: Refactor to work with non-phase0 genesis state

Expand Down Expand Up @@ -48,8 +49,15 @@ export function getGenesisBeaconState(
// MISC
state.slot = GENESIS_SLOT;
const version = config.getForkVersion(GENESIS_SLOT);
const forkName = config.getForkName(GENESIS_SLOT);
const allForkNames = Object.keys(config.forks) as ForkName[];
const forkIndex = allForkNames.findIndex((item) => item === forkName);
const previousForkIndex = Math.max(0, forkIndex - 1);
const previousForkName = allForkNames[previousForkIndex];
const previousFork = config.forks[previousForkName];
// the altair genesis spec test requires previous version to be phase0 although ALTAIR_FORK_EPOCH=0
state.fork = {
previousVersion: version,
previousVersion: previousFork.version,
currentVersion: version,
epoch: computeEpochAtSlot(config, GENESIS_SLOT),
} as phase0.Fork;
Expand All @@ -62,7 +70,6 @@ export function getGenesisBeaconState(
// Ethereum 1.0 chain data
state.eth1Data = genesisEth1Data;
state.randaoMixes = randaoMixes;

return state as TreeBacked<allForks.BeaconState>;
}

Expand Down Expand Up @@ -187,5 +194,13 @@ export function initializeBeaconStateFromEth1(
// Process deposits
applyDeposits(config, state, deposits);

return state;
if (config.getForkName(GENESIS_SLOT) === ForkName.altair) {
const syncCommittees = getNextSyncCommittee(config, state);
const altairState = state as TreeBacked<altair.BeaconState>;
altairState.currentSyncCommittee = syncCommittees;
altairState.nextSyncCommittee = syncCommittees;
return altairState as TreeBacked<allForks.BeaconState>;
} else {
return state;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {join} from "path";
import {expect} from "chai";
import {params} from "@chainsafe/lodestar-params/minimal";
import {IBeaconConfig, createIBeaconConfig} from "@chainsafe/lodestar-config";
import {altair, Uint64, Root} from "@chainsafe/lodestar-types";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
import {initializeBeaconStateFromEth1} from "@chainsafe/lodestar-beacon-state-transition";

import {SPEC_TEST_LOCATION} from "../../../../utils/specTestCases";

interface IGenesisInitSpecTest {
[k: string]: altair.Deposit | unknown | null | undefined;
eth1_block_hash: Root;
eth1_timestamp: Uint64;
meta: {
depositsCount: Uint64;
};
state: altair.BeaconState;
}

// eslint-disable-next-line @typescript-eslint/naming-convention
const config = createIBeaconConfig({...params, ALTAIR_FORK_EPOCH: 0});

describeDirectorySpecTest<IGenesisInitSpecTest, altair.BeaconState>(
"genesis initialization",
join(SPEC_TEST_LOCATION, "/tests/minimal/altair/genesis/initialization/pyspec_tests"),
(testcase) => {
const deposits: altair.Deposit[] = [];
for (let i = 0; i < Number(testcase.meta.depositsCount); i++) {
deposits.push(testcase[`deposits_${i}`] as altair.Deposit);
}
return initializeBeaconStateFromEth1(
config,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
config.types.Root.fromJson(testcase.eth1.eth1BlockHash),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
Number(testcase.eth1.eth1Timestamp),
deposits
) as altair.BeaconState;
},
{
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
inputTypes: {
meta: InputType.YAML,
eth1: InputType.YAML,
},
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
sszTypes: {
eth1_block_hash: config.types.Root,
state: config.types.altair.BeaconState,
...generateDepositSSZTypeMapping(192, config),
},
timeout: 60000,
getExpected: (testCase) => testCase.state,
expectFunc: (testCase, expected, actual) => {
expect(config.types.altair.BeaconState.equals(actual, expected)).to.be.true;
},
// shouldSkip: (_, __, index) => index !== 0,
}
);

function generateDepositSSZTypeMapping(
n: number,
config: IBeaconConfig
): Record<string, typeof config.types.phase0.Deposit> {
const depositMappings: Record<string, typeof config.types.phase0.Deposit> = {};
for (let i = 0; i < n; i++) {
depositMappings[`deposits_${i}`] = config.types.phase0.Deposit;
}
return depositMappings;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {join} from "path";

import {config} from "@chainsafe/lodestar-config/minimal";
import {phase0} from "@chainsafe/lodestar-types";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
import {isValidGenesisState} from "@chainsafe/lodestar-beacon-state-transition";
import {SPEC_TEST_LOCATION} from "../../../../utils/specTestCases";

interface IGenesisValidityTestCase {
is_valid: boolean;
genesis: phase0.BeaconState;
}

describeDirectorySpecTest<IGenesisValidityTestCase, boolean>(
"genesis validity",
join(SPEC_TEST_LOCATION, "tests/minimal/phase0/genesis/validity/pyspec_tests"),
(testcase) => {
return isValidGenesisState(config, testcase.genesis);
},
{
inputTypes: {
is_valid: InputType.YAML,
genesis: InputType.SSZ_SNAPPY,
},
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
sszTypes: {
genesis: config.types.phase0.BeaconState,
},
getExpected: (testCase) => testCase.is_valid,
}
);
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
/* eslint-disable @typescript-eslint/naming-convention */
import {join} from "path";

import {config} from "@chainsafe/lodestar-config/minimal";
import {phase0} from "@chainsafe/lodestar-types";
import {createIBeaconConfig} from "@chainsafe/lodestar-config";
import {params} from "@chainsafe/lodestar-params/minimal";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
import {isValidGenesisState} from "@chainsafe/lodestar-beacon-state-transition";
import {altair, isValidGenesisState} from "@chainsafe/lodestar-beacon-state-transition";
import {SPEC_TEST_LOCATION} from "../../../../utils/specTestCases";

interface IGenesisValidityTestCase {
is_valid: boolean;
genesis: phase0.BeaconState;
genesis: altair.BeaconState;
}

// eslint-disable-next-line @typescript-eslint/naming-convention
const config = createIBeaconConfig({...params, ALTAIR_FORK_EPOCH: 0});

describeDirectorySpecTest<IGenesisValidityTestCase, boolean>(
"genesis validity",
join(SPEC_TEST_LOCATION, "tests/minimal/phase0/genesis/validity/pyspec_tests"),
join(SPEC_TEST_LOCATION, "tests/minimal/altair/genesis/validity/pyspec_tests"),
(testcase) => {
return isValidGenesisState(config, testcase.genesis);
},
Expand All @@ -26,7 +29,7 @@ describeDirectorySpecTest<IGenesisValidityTestCase, boolean>(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
sszTypes: {
genesis: config.types.phase0.BeaconState,
genesis: config.types.altair.BeaconState,
},
getExpected: (testCase) => testCase.is_valid,
}
Expand Down

0 comments on commit cc659de

Please sign in to comment.