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

Add more tests #207

Merged
merged 10 commits into from
Oct 12, 2021
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
37 changes: 34 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,38 @@ jobs:
run: yarn lint
- name: Tests
run: yarn test

# Download spec tests with cache
- name: Restore spec tests cache
uses: actions/cache@master
with:
path: packages/ssz/spec-tests
key: spec-test-data-${{ hashFiles('packages/ssz/test/specTestVersioning.ts') }}
- name: Download spec tests
run: lerna run download-spec-tests
- name: Spec tests
run: lerna run test:spec
run: yarn download-spec-tests
working-directory: packages/ssz

# Run them in different steps to quickly identifying which command failed
# Otherwise just doing `yarn test:spec` you can't tell which specific suite failed
# many of the suites have identical names for minimal and mainnet
- name: Spec tests general
run: ../../node_modules/.bin/mocha test/spec/generic/index.test.ts
working-directory: packages/ssz
- name: Spec tests phase0-minimal
run: LODESTAR_PRESET=minimal LODESTAR_FORK=phase0 ../../node_modules/.bin/mocha test/spec/ssz_static.test.ts
working-directory: packages/ssz
- name: Spec tests phase0-mainnet
run: LODESTAR_PRESET=mainnet LODESTAR_FORK=phase0 ../../node_modules/.bin/mocha test/spec/ssz_static.test.ts
working-directory: packages/ssz
- name: Spec tests altair-minimal
run: LODESTAR_PRESET=minimal LODESTAR_FORK=altair ../../node_modules/.bin/mocha test/spec/ssz_static.test.ts
working-directory: packages/ssz
- name: Spec tests altair-mainnet
run: LODESTAR_PRESET=mainnet LODESTAR_FORK=altair ../../node_modules/.bin/mocha test/spec/ssz_static.test.ts
working-directory: packages/ssz
- name: Spec tests merge-minimal
run: LODESTAR_PRESET=minimal LODESTAR_FORK=merge ../../node_modules/.bin/mocha test/spec/ssz_static.test.ts
working-directory: packages/ssz
- name: Spec tests merge-mainnet
run: LODESTAR_PRESET=mainnet LODESTAR_FORK=merge ../../node_modules/.bin/mocha test/spec/ssz_static.test.ts
working-directory: packages/ssz
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ yarn-error.log
.nyc_output/
.idea/
.vscode

packages/ssz/spec-tests
2 changes: 1 addition & 1 deletion packages/ssz/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ node_modules/
.vscode
yarn-error.log

test/spec-tests-data
spec-tests
10 changes: 7 additions & 3 deletions packages/ssz/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@
"benchmark:local": "yarn benchmark --local",
"test:perf": "mocha \"test/perf/**/*.test.ts\"",
"test:unit": "nyc -e .ts mocha \"test/unit/**/*.test.ts\"",
"test:spec": "mocha \"test/spec/**/*.test.ts\"",
"test:spec": "yarn test:spec-generic && yarn test:spec-static",
"test:spec-generic": "mocha \"test/spec/generic/**/*.test.ts\"",
"test:spec-static": "yarn test:spec-static-minimal && yarn test:spec-static-mainnet",
"test:spec-static-minimal": "LODESTAR_PRESET=minimal mocha test/spec/ssz_static.test.ts",
"test:spec-static-mainnet": "LODESTAR_PRESET=mainnet mocha test/spec/ssz_static.test.ts",
"download-spec-tests": "node -r ts-node/register test/spec/downloadTests.ts"
},
"types": "lib/index.d.ts",
Expand All @@ -37,8 +41,8 @@
"case": "^1.6.3"
},
"devDependencies": {
"@chainsafe/lodestar-params": "^0.28.1",
"@chainsafe/lodestar-spec-test-util": "^0.28.1"
"@chainsafe/lodestar-params": "^0.31.0",
"@chainsafe/lodestar-spec-test-util": "^0.31.0"
},
"keywords": [
"ethereum",
Expand Down
4 changes: 2 additions & 2 deletions packages/ssz/src/types/composite/abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ export abstract class CompositeType<T extends CompositeValue> extends Type<T> {
return this.tree_serializeToBytes(tree, output, 0);
}

bytes_validate(data: Uint8Array, start: number, end: number): void {
bytes_validate(data: Uint8Array, start: number, end: number, emptyOk?: boolean): void {
if (!data) {
throw new Error("Data is null or undefined");
}
if (data.length === 0) {
if (data.length === 0 && !emptyOk) {
throw new Error("Data is empty");
}
if (start < 0) {
Expand Down
8 changes: 4 additions & 4 deletions packages/ssz/src/types/composite/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ export abstract class BasicArrayType<T extends ArrayLike<unknown>> extends Compo
return newValue;
}

struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T {
this.bytes_validate(data, start, end);
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number, emptyOk?: boolean): T {
this.bytes_validate(data, start, end, emptyOk);
const elementSize = this.elementType.struct_getSerializedLength();
return Array.from({length: (end - start) / elementSize}, (_, i) =>
this.elementType.struct_deserializeFromBytes(data, start + i * elementSize)
Expand Down Expand Up @@ -387,8 +387,8 @@ export abstract class CompositeArrayType<T extends ArrayLike<unknown>> extends C
return newValue;
}

struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T {
this.bytes_validate(data, start, end);
struct_deserializeFromBytes(data: Uint8Array, start: number, end: number, emptyOk?: boolean): T {
this.bytes_validate(data, start, end, emptyOk);
if (start === end) {
return [] as unknown as T;
}
Expand Down
8 changes: 4 additions & 4 deletions packages/ssz/src/types/composite/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ export class BasicListType<T extends List<unknown> = List<unknown>> extends Basi
}

bytes_validate(data: Uint8Array, start: number, end: number): void {
super.bytes_validate(data, start, end);
super.bytes_validate(data, start, end, true);
if (end - start > this.getMaxSerializedLength()) {
throw new Error("Deserialized list length greater than limit");
}
}

struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T {
this.bytes_validate(data, start, end);
return super.struct_deserializeFromBytes(data, start, end);
return super.struct_deserializeFromBytes(data, start, end, true);
}

struct_getChunkCount(value: T): number {
Expand Down Expand Up @@ -379,8 +379,8 @@ export class CompositeListType<T extends List<unknown> = List<unknown>> extends
}

struct_deserializeFromBytes(data: Uint8Array, start: number, end: number): T {
this.bytes_validate(data, start, end);
const value = super.struct_deserializeFromBytes(data, start, end);
this.bytes_validate(data, start, end, true);
const value = super.struct_deserializeFromBytes(data, start, end, true);
if (value.length > this.limit) {
throw new Error(`Deserialized list length greater than limit: ${value.length} ${this.limit}`);
}
Expand Down
41 changes: 41 additions & 0 deletions packages/ssz/test/copyTypes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/bash

####################################################
# Copy all Lodestar eth2.0 types to SSZ's test files
#
# Why?
# - To leverage consensus spec tests before release
# - To ensure Lodestar's types definitions are compatible before releasing
# - To benchmark usage a real eth2.0 types in SSZ for fast development
####################################################

# Allow the script to be run from any folder and not break paths
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
LODESTAR_EXECUTABLE=${SCRIPT_DIR}/../../packages/cli/bin/lodestar

# Assumes your directory structure is:
# i.e. you have cloned both the lodestar and ssz monorepo in the same parent directory
# .
# ├── lodestar
# │ └── packages
# │ └── types
# └── ssz
# └── packages
# └── ssz
#

LODESTAR_TYPES_SRC=${SCRIPT_DIR}/../../../../lodestar/packages/types/src
TYPES_SSZ_LOCATION=${SCRIPT_DIR}/lodestarTypes

# Clean up existing directory
rm -rf $TYPES_SSZ_LOCATION
mkdir -p $TYPES_SSZ_LOCATION

# Copy from lodestar types the entire source
cp -R $LODESTAR_TYPES_SRC/. $TYPES_SSZ_LOCATION

# Replace imports
find $TYPES_SSZ_LOCATION \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i 's/@chainsafe\/ssz/\.\.\/\.\.\/\.\.\/src/g'



2 changes: 2 additions & 0 deletions packages/ssz/test/lodestarTypes/allForks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * as ts from "./types";
export * as ssz from "./sszTypes";
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
import {ForkName} from "@chainsafe/lodestar-params";

import {AllForksSSZTypes} from "./types";
import * as phase0 from "../phase0/sszTypes";
import * as altair from "../altair/sszTypes";
import {ssz as phase0} from "../phase0";
import {ssz as altair} from "../altair";
import {ssz as merge} from "../merge";

/**
* Index the ssz types that differ by fork
Expand All @@ -24,4 +25,11 @@ export const allForks: {[K in ForkName]: AllForksSSZTypes} = {
BeaconState: altair.BeaconState as AllForksSSZTypes["BeaconState"],
Metadata: altair.Metadata as AllForksSSZTypes["Metadata"],
},
merge: {
BeaconBlockBody: merge.BeaconBlockBody as AllForksSSZTypes["BeaconBlockBody"],
BeaconBlock: merge.BeaconBlock as AllForksSSZTypes["BeaconBlock"],
SignedBeaconBlock: merge.SignedBeaconBlock as AllForksSSZTypes["SignedBeaconBlock"],
BeaconState: merge.BeaconState as AllForksSSZTypes["BeaconState"],
Metadata: altair.Metadata as AllForksSSZTypes["Metadata"],
},
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {ContainerType} from "../../../src";

import * as phase0 from "../phase0/types";
import * as altair from "../altair/types";
import {ts as phase0} from "../phase0";
import {ts as altair} from "../altair";
import {ts as merge} from "../merge";

// Re-export union types for types that are _known_ to differ

export type BeaconBlockBody = phase0.BeaconBlockBody | altair.BeaconBlockBody;
export type BeaconBlock = phase0.BeaconBlock | altair.BeaconBlock;
export type SignedBeaconBlock = phase0.SignedBeaconBlock | altair.SignedBeaconBlock;
export type BeaconState = phase0.BeaconState | altair.BeaconState;
export type BeaconBlockBody = phase0.BeaconBlockBody | altair.BeaconBlockBody | merge.BeaconBlockBody;
export type BeaconBlock = phase0.BeaconBlock | altair.BeaconBlock | merge.BeaconBlock;
export type SignedBeaconBlock = phase0.SignedBeaconBlock | altair.SignedBeaconBlock | merge.SignedBeaconBlock;
export type BeaconState = phase0.BeaconState | altair.BeaconState | merge.BeaconState;
export type Metadata = phase0.Metadata | altair.Metadata;

/**
Expand Down
2 changes: 2 additions & 0 deletions packages/ssz/test/lodestarTypes/altair/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * as ts from "./types";
export * as ssz from "./sszTypes";
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {BitVectorType, ContainerType, VectorType, ListType, RootType, Vector} from "../../../src";
import {
JUSTIFICATION_BITS_LENGTH,
FINALIZED_ROOT_INDEX_FLOORLOG2,
Expand All @@ -6,19 +7,16 @@ import {
SYNC_COMMITTEE_SIZE,
SLOTS_PER_HISTORICAL_ROOT,
HISTORICAL_ROOTS_LIMIT,
EPOCHS_PER_ETH1_VOTING_PERIOD,
SLOTS_PER_EPOCH,
VALIDATOR_REGISTRY_LIMIT,
EPOCHS_PER_HISTORICAL_VECTOR,
EPOCHS_PER_SLASHINGS_VECTOR,
EPOCHS_PER_SYNC_COMMITTEE_PERIOD,
} from "@chainsafe/lodestar-params";
import {BitVectorType, ContainerType, VectorType, ListType, RootType, Vector} from "../../../src";
import * as phase0Ssz from "../phase0/sszTypes";
import * as primitiveSsz from "../primitive/sszTypes";
import * as phase0 from "../phase0/types";
import {Root} from "../primitive/types";
import {LazyVariable} from "../lazyVar";
import {ssz as phase0Ssz, ts as phase0Types} from "../phase0";
import {ssz as primitiveSsz} from "../primitive";
import {LazyVariable} from "../utils/lazyVar";
import * as altair from "./types";

const {
Expand Down Expand Up @@ -124,7 +122,7 @@ export const HistoricalStateRoots = new VectorType<Vector<Root>>({
length: SLOTS_PER_HISTORICAL_ROOT,
});

export const HistoricalBatch = new ContainerType<phase0.HistoricalBatch>({
export const HistoricalBatch = new ContainerType<phase0Types.HistoricalBatch>({
fields: {
blockRoots: HistoricalBlockRoots,
stateRoots: HistoricalStateRoots,
Expand Down Expand Up @@ -156,8 +154,11 @@ export const SignedBeaconBlock = new ContainerType<altair.SignedBeaconBlock>({
},
});

//we don't reuse phase0.BeaconState fields since we need to replace some keys
//and we cannot keep order doing that
export const EpochParticipation = new ListType({elementType: ParticipationFlags, limit: VALIDATOR_REGISTRY_LIMIT});
export const InactivityScores = new ListType({elementType: Number64, limit: VALIDATOR_REGISTRY_LIMIT});

// we don't reuse phase0.BeaconState fields since we need to replace some keys
// and we cannot keep order doing that
export const BeaconState = new ContainerType<altair.BeaconState>({
fields: {
genesisTime: Number64,
Expand All @@ -174,33 +175,24 @@ export const BeaconState = new ContainerType<altair.BeaconState>({
}),
// Eth1
eth1Data: phase0Ssz.Eth1Data,
eth1DataVotes: new ListType({
elementType: phase0Ssz.Eth1Data,
limit: EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH,
}),
eth1DataVotes: phase0Ssz.Eth1DataVotes,
eth1DepositIndex: Number64,
// Registry
validators: new ListType({elementType: phase0Ssz.Validator, limit: VALIDATOR_REGISTRY_LIMIT}),
balances: new ListType({elementType: Gwei, limit: VALIDATOR_REGISTRY_LIMIT}),
balances: new ListType({elementType: Number64, limit: VALIDATOR_REGISTRY_LIMIT}),
randaoMixes: new VectorType({elementType: Bytes32, length: EPOCHS_PER_HISTORICAL_VECTOR}),
// Slashings
slashings: new VectorType({elementType: Gwei, length: EPOCHS_PER_SLASHINGS_VECTOR}),
// Participation
previousEpochParticipation: new ListType({
elementType: ParticipationFlags,
limit: VALIDATOR_REGISTRY_LIMIT,
}),
currentEpochParticipation: new ListType({
elementType: ParticipationFlags,
limit: VALIDATOR_REGISTRY_LIMIT,
}),
previousEpochParticipation: EpochParticipation,
currentEpochParticipation: EpochParticipation,
// Finality
justificationBits: new BitVectorType({length: JUSTIFICATION_BITS_LENGTH}),
previousJustifiedCheckpoint: phase0Ssz.Checkpoint,
currentJustifiedCheckpoint: phase0Ssz.Checkpoint,
finalizedCheckpoint: phase0Ssz.Checkpoint,
// Inactivity
inactivityScores: new ListType({elementType: Number64, limit: VALIDATOR_REGISTRY_LIMIT}),
inactivityScores: InactivityScores,
// Sync
currentSyncCommittee: SyncCommittee,
nextSyncCommittee: SyncCommittee,
Expand Down
Loading