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

Don't manipualte spec tests casing #3715

Merged
merged 5 commits into from
Feb 7, 2022
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
3 changes: 3 additions & 0 deletions packages/lodestar/test/spec/allForks/epochProcessing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {IBaseSpecTest} from "../type";

export type EpochProcessFn = (state: CachedBeaconStateAllForks, epochProcess: allForks.IEpochProcess) => void;

/**
* https://github.com/ethereum/consensus-specs/blob/dev/tests/formats/epoch_processing/README.md
*/
type EpochProcessingStateTestCase = IBaseSpecTest & {
pre: allForks.BeaconState;
post: allForks.BeaconState;
Expand Down
21 changes: 15 additions & 6 deletions packages/lodestar/test/spec/allForks/finality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import {join} from "node:path";
import {TreeBacked} from "@chainsafe/ssz";
import {CachedBeaconStateAllForks, allForks, altair} from "@chainsafe/lodestar-beacon-state-transition";
import {describeDirectorySpecTest} from "@chainsafe/lodestar-spec-test-util";
import {bellatrix, ssz, Uint64} from "@chainsafe/lodestar-types";
import {bellatrix, ssz} from "@chainsafe/lodestar-types";
import {ACTIVE_PRESET, ForkName} from "@chainsafe/lodestar-params";
import {SPEC_TEST_LOCATION} from "../specTestVersioning";
import {IBaseSpecTest} from "../type";
import {IBaseSpecTest, shouldVerify} from "../type";
import {expectEqualBeaconState, inputTypeSszTreeBacked} from "../util";
import {getConfig} from "./util";
import {generateBlocksSZZTypeMapping} from "./sanity";

/* eslint-disable @typescript-eslint/naming-convention */

export function finality(fork: ForkName): void {
describeDirectorySpecTest<IFinalityTestCase, allForks.BeaconState>(
`${ACTIVE_PRESET}/${fork}/finality/finality`,
Expand All @@ -19,8 +21,8 @@ export function finality(fork: ForkName): void {
getConfig(fork),
testcase.pre as TreeBacked<allForks.BeaconState>
) as CachedBeaconStateAllForks;
const verify = testcase.meta !== undefined && testcase.meta.blsSetting === BigInt(1);
for (let i = 0; i < Number(testcase.meta.blocksCount); i++) {
const verify = shouldVerify(testcase);
for (let i = 0; i < testcase.meta.blocks_count; i++) {
const signedBlock = testcase[`blocks_${i}`] as bellatrix.SignedBeaconBlock;

wrappedState = allForks.stateTransition(
Expand Down Expand Up @@ -52,11 +54,18 @@ export function finality(fork: ForkName): void {
);
}

/**
* `meta.yaml`
* ```
* {blocks_count: 16}
* ```
* https://github.com/ethereum/consensus-specs/blob/dev/tests/formats/finality/README.md
*/
interface IFinalityTestCase extends IBaseSpecTest {
[k: string]: altair.SignedBeaconBlock | unknown | null | undefined;
meta: {
blocksCount: Uint64;
blsSetting: BigInt;
blocks_count: number;
bls_setting: bigint;
};
pre: altair.BeaconState;
post?: altair.BeaconState;
Expand Down
62 changes: 29 additions & 33 deletions packages/lodestar/test/spec/allForks/forkChoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ import {ChainEventEmitter} from "@chainsafe/lodestar/lib/chain/emitter";
import {toHexString} from "@chainsafe/ssz";
import {CheckpointWithHex, IForkChoice} from "@chainsafe/lodestar-fork-choice";
import {ssz, RootHex} from "@chainsafe/lodestar-types";
import {bnToNum} from "@chainsafe/lodestar-utils";
import {ACTIVE_PRESET, SLOTS_PER_EPOCH, ForkName} from "@chainsafe/lodestar-params";
import {SPEC_TEST_LOCATION} from "../specTestVersioning";
import {IBaseSpecTest} from "../type";
import {getConfig} from "./util";

/* eslint-disable @typescript-eslint/naming-convention */

const ANCHOR_STATE_FILE_NAME = "anchor_state";
const ANCHOR_BLOCK_FILE_NAME = "anchor_block";
const BLOCK_FILE_NAME = "^(block)_([0-9a-zA-Z]+)$";
Expand Down Expand Up @@ -57,7 +59,7 @@ export function forkChoiceTest(fork: ForkName): void {

for (const [i, step] of steps.entries()) {
if (isTick(step)) {
tickTime = Number(step.tick);
tickTime = bnToNum(step.tick);
forkchoice.updateTime(Math.floor(tickTime / config.SECONDS_PER_SLOT));
}

Expand All @@ -84,52 +86,43 @@ export function forkChoiceTest(fork: ForkName): void {

// checks step
else if (isCheck(step)) {
const {
head: expectedHead,
time: expectedTime,
justifiedCheckpoint,
finalizedCheckpoint,
bestJustifiedCheckpoint,
proposerBoostRoot: expectedProposerBoostRoot,
} = step.checks;

// Forkchoice head is computed lazily only on request
const head = forkchoice.updateHead();
const proposerBootRoot = forkchoice.getProposerBoostRoot();

if (expectedHead !== undefined) {
expect(head.slot).to.be.equal(Number(expectedHead.slot), `Invalid head slot at step ${i}`);
expect(head.blockRoot).to.be.equal(expectedHead.root, `Invalid head root at step ${i}`);
if (step.checks.head !== undefined) {
expect(head.slot).to.be.equal(bnToNum(step.checks.head.slot), `Invalid head slot at step ${i}`);
expect(head.blockRoot).to.be.equal(step.checks.head.root, `Invalid head root at step ${i}`);
}
if (expectedProposerBoostRoot !== undefined) {
if (step.checks.proposer_boost_root !== undefined) {
expect(proposerBootRoot).to.be.equal(
expectedProposerBoostRoot,
step.checks.proposer_boost_root,
`Invalid proposer boost root at step ${i}`
);
}
// time in spec mapped to Slot in our forkchoice implementation.
// Compare in slots because proposer boost steps doesn't always come on
// slot boundary.
if (expectedTime !== undefined && expectedTime > 0)
if (step.checks.time !== undefined && step.checks.time > 0)
expect(forkchoice.getTime()).to.be.equal(
Math.floor(Number(expectedTime) / config.SECONDS_PER_SLOT),
Math.floor(bnToNum(step.checks.time) / config.SECONDS_PER_SLOT),
`Invalid forkchoice time at step ${i}`
);
if (justifiedCheckpoint) {
if (step.checks.justified_checkpoint) {
expect(toSpecTestCheckpoint(forkchoice.getJustifiedCheckpoint())).to.be.deep.equal(
justifiedCheckpoint,
step.checks.justified_checkpoint,
`Invalid justified checkpoint at step ${i}`
);
}
if (finalizedCheckpoint) {
if (step.checks.finalized_checkpoint) {
expect(toSpecTestCheckpoint(forkchoice.getFinalizedCheckpoint())).to.be.deep.equal(
finalizedCheckpoint,
step.checks.finalized_checkpoint,
`Invalid finalized checkpoint at step ${i}`
);
}
if (bestJustifiedCheckpoint) {
if (step.checks.best_justified_checkpoint) {
expect(toSpecTestCheckpoint(forkchoice.getBestJustifiedCheckpoint())).to.be.deep.equal(
bestJustifiedCheckpoint,
step.checks.best_justified_checkpoint,
`Invalid best justified checkpoint at step ${i}`
);
}
Expand Down Expand Up @@ -277,7 +270,7 @@ type SpecTestCheckpoint = {epoch: BigInt; root: string};

type OnTick = {
/** to execute `on_tick(store, time)` */
tick: number;
tick: bigint;
/** optional, default to `true`. */
valid?: number;
};
Expand All @@ -297,19 +290,22 @@ type OnBlock = {
type Checks = {
/** Value in the ForkChoice store to verify it's correct after being mutated by another step */
checks: {
head: {slot: number; root: string};
time?: number;
justifiedCheckpoint?: SpecTestCheckpoint;
finalizedCheckpoint?: SpecTestCheckpoint;
bestJustifiedCheckpoint?: SpecTestCheckpoint;
proposerBoostRoot?: RootHex;
head?: {
slot: bigint;
root: string;
};
time?: bigint;
justified_checkpoint?: SpecTestCheckpoint;
finalized_checkpoint?: SpecTestCheckpoint;
best_justified_checkpoint?: SpecTestCheckpoint;
proposer_boost_root?: RootHex;
};
};

interface IForkChoiceTestCase extends IBaseSpecTest {
interface IForkChoiceTestCase {
meta?: {
description?: string;
blsSetting: BigInt;
bls_setting: BigInt;
};
anchorState: allForks.BeaconState;
anchorBlock: allForks.BeaconBlock;
Expand Down
13 changes: 7 additions & 6 deletions packages/lodestar/test/spec/allForks/genesis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {phase0, Uint64, Root, ssz, allForks, bellatrix} from "@chainsafe/lodesta
import {TreeBacked} from "@chainsafe/ssz";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
import {initializeBeaconStateFromEth1, isValidGenesisState} from "@chainsafe/lodestar-beacon-state-transition";
import {bnToNum} from "@chainsafe/lodestar-utils";
import {ACTIVE_PRESET, ForkName} from "@chainsafe/lodestar-params";
import {SPEC_TEST_LOCATION} from "../specTestVersioning";
import {expectEqualBeaconState} from "../util";
Expand All @@ -18,7 +19,7 @@ export function genesis(fork: ForkName): void {
join(SPEC_TEST_LOCATION, `/tests/${ACTIVE_PRESET}/${fork}/genesis/initialization/pyspec_tests`),
(testcase) => {
const deposits: phase0.Deposit[] = [];
for (let i = 0; i < Number(testcase.meta.depositsCount); i++) {
for (let i = 0; i < testcase.meta.deposits_count; i++) {
deposits.push(testcase[`deposits_${i}`] as phase0.Deposit);
}
let executionPayloadHeader: TreeBacked<bellatrix.ExecutionPayloadHeader> | undefined = undefined;
Expand All @@ -29,8 +30,8 @@ export function genesis(fork: ForkName): void {
}
return initializeBeaconStateFromEth1(
getConfig(fork),
ssz.Root.fromJson((testcase.eth1 as IGenesisInitCase).eth1BlockHash),
Number((testcase.eth1 as IGenesisInitCase).eth1Timestamp),
ssz.Root.fromJson((testcase.eth1 as IGenesisInitCase).eth1_block_hash),
bnToNum((testcase.eth1 as IGenesisInitCase).eth1_timestamp),
deposits,
undefined,
executionPayloadHeader
Expand Down Expand Up @@ -90,15 +91,15 @@ interface IGenesisInitSpecTest {
eth1_block_hash: Root;
eth1_timestamp: Uint64;
meta: {
depositsCount: Uint64;
deposits_count: number;
};
execution_payload_header?: bellatrix.ExecutionPayloadHeader;
state: phase0.BeaconState;
}

interface IGenesisInitCase {
eth1BlockHash: any;
eth1Timestamp: any;
eth1_block_hash: string;
eth1_timestamp: bigint;
}

interface IGenesisValidityTestCase extends IBaseSpecTest {
Expand Down
13 changes: 8 additions & 5 deletions packages/lodestar/test/spec/allForks/merkle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {IBaseSpecTest} from "../type";
import {verifyMerkleBranch} from "@chainsafe/lodestar-utils";
import {expect} from "chai";

/* eslint-disable @typescript-eslint/naming-convention */

export function merkle(fork: ForkName): void {
describeDirectorySpecTest<IMerkleTestCase, IProof>(
`${ACTIVE_PRESET}/${fork}/transition`,
Expand All @@ -19,16 +21,17 @@ export function merkle(fork: ForkName): void {
const stateRoot = stateTB.hashTreeRoot();
const leaf = fromHexString(specTestProof.leaf);
const branch = specTestProof.branch.map((item) => fromHexString(item));
const depth = Math.floor(Math.log2(Number(specTestProof.leafIndex)));
const verified = verifyMerkleBranch(leaf, branch, depth, Number(specTestProof.leafIndex) % 2 ** depth, stateRoot);
const leafIndex = Number(specTestProof.leaf_index);
const depth = Math.floor(Math.log2(leafIndex));
const verified = verifyMerkleBranch(leaf, branch, depth, leafIndex % 2 ** depth, stateRoot);
expect(verified, "cannot verify merkle branch").to.be.true;
const lodestarProof = stateTB.tree.getProof({
gindex: specTestProof.leafIndex,
gindex: specTestProof.leaf_index,
type: ProofType.single,
}) as SingleProof;
return {
leaf: toHexString(lodestarProof.leaf),
leafIndex: lodestarProof.gindex,
leaf_index: lodestarProof.gindex,
branch: lodestarProof.witnesses.map(toHexString),
};
},
Expand Down Expand Up @@ -57,7 +60,7 @@ export function merkle(fork: ForkName): void {

interface IProof {
leaf: string;
leafIndex: bigint;
leaf_index: bigint;
branch: string[];
}
}
2 changes: 1 addition & 1 deletion packages/lodestar/test/spec/allForks/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type BlockProcessFn<BeaconState extends allForks.BeaconState> = (
export type OperationsTestCase<BeaconState extends allForks.BeaconState> = IBaseSpecTest & {
pre: BeaconState;
post: BeaconState;
execution: {executionValid: boolean};
execution: {execution_valid: boolean};
};

export function operations<BeaconState extends allForks.BeaconState>(
Expand Down
19 changes: 11 additions & 8 deletions packages/lodestar/test/spec/allForks/sanity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import {join} from "node:path";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
import {allForks} from "@chainsafe/lodestar-beacon-state-transition";
import {TreeBacked} from "@chainsafe/ssz";
import {bellatrix, ssz, Uint64} from "@chainsafe/lodestar-types";
import {bellatrix, ssz} from "@chainsafe/lodestar-types";
import {ACTIVE_PRESET, ForkName} from "@chainsafe/lodestar-params";
import {bnToNum} from "@chainsafe/lodestar-utils";
import {expectEqualBeaconState, inputTypeSszTreeBacked} from "../util";
import {SPEC_TEST_LOCATION} from "../specTestVersioning";
import {IBaseSpecTest} from "../type";
import {IBaseSpecTest, shouldVerify} from "../type";
import {getConfig} from "./util";

/* eslint-disable @typescript-eslint/naming-convention */

export function sanity(fork: ForkName): void {
sanitySlot(fork);
sanityBlock(fork, `/tests/${ACTIVE_PRESET}/${fork}/sanity/blocks/pyspec_tests`);
Expand All @@ -21,7 +24,7 @@ export function sanitySlot(fork: ForkName): void {
(testcase) => {
const stateTB = (testcase.pre as TreeBacked<allForks.BeaconState>).clone();
const state = allForks.createCachedBeaconState(getConfig(fork), stateTB);
const postState = allForks.processSlots(state, state.slot + Number(testcase.slots));
const postState = allForks.processSlots(state, state.slot + bnToNum(testcase.slots));
return postState.type.createTreeBacked(postState.tree);
},
{
Expand All @@ -47,8 +50,8 @@ export function sanityBlock(fork: ForkName, testPath: string): void {
(testcase) => {
const stateTB = testcase.pre as TreeBacked<allForks.BeaconState>;
let wrappedState = allForks.createCachedBeaconState(getConfig(fork), stateTB);
const verify = testcase.meta !== undefined && testcase.meta.blsSetting === BigInt(1);
for (let i = 0; i < Number(testcase.meta.blocksCount); i++) {
const verify = shouldVerify(testcase);
for (let i = 0; i < testcase.meta.blocks_count; i++) {
const signedBlock = testcase[`blocks_${i}`] as bellatrix.SignedBeaconBlock;
wrappedState = allForks.stateTransition(
wrappedState,
Expand Down Expand Up @@ -92,8 +95,8 @@ export function generateBlocksSZZTypeMapping(fork: ForkName, n: number): BlocksS
interface IBlockSanityTestCase extends IBaseSpecTest {
[k: string]: allForks.SignedBeaconBlock | unknown | null | undefined;
meta: {
blocksCount: Uint64;
blsSetting: BigInt;
blocks_count: number;
bls_setting: bigint;
};
pre: allForks.BeaconState;
post: allForks.BeaconState;
Expand All @@ -102,5 +105,5 @@ interface IBlockSanityTestCase extends IBaseSpecTest {
interface IProcessSlotsTestCase extends IBaseSpecTest {
pre: allForks.BeaconState;
post?: allForks.BeaconState;
slots: Uint64;
slots: bigint;
}
Loading