refactor: restructure to tests and CI workflow to reduce CI time (#5951)

* Enable debug logging for e2e tests

* Reduce the duration of lightclient test

* Run all e2e tests with minimal preset

* Fix the few e2e tests

* Fix test job names

* Fix the task script

* Add yarn cache to node actions

* Update few e2e tests after code review

* Fix the type export to use with transpilation

* Remove unused file

* Revert changes to an e2e test file

* Reduce the genesis delay

* Refactor workflow jobs

* Add .git-data to build cache

* Fix spec tests option

* Upgrade the github action version

* Add a package dev dependency

* Add artifact name

* Update the workflow to add env variables

* Update the workflow to add env variables

* Add tsnode option

* Parallelize the spec tests

* Add the ts-node configuration

* Update tsconfig for the e2e tests

* Update the tsconfig for the project

* Fix the types issue

* Remove unused file
This commit is contained in:
Nazar Hussain
2023-09-22 12:05:46 +02:00
committed by GitHub
parent 9dae25f817
commit 4fd3d4d302
90 changed files with 621 additions and 525 deletions

View File

@@ -34,6 +34,7 @@ jobs:
with:
node-version: 20
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT

View File

@@ -16,6 +16,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 20
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT

View File

@@ -15,6 +15,7 @@ jobs:
with:
node-version: 20
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT

View File

@@ -23,6 +23,7 @@ jobs:
node-version: 20
registry-url: "https://registry.npmjs.org"
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT

View File

@@ -56,6 +56,7 @@ jobs:
with:
node-version: 20
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT

View File

@@ -62,6 +62,7 @@ jobs:
with:
node-version: 20
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT

View File

@@ -1,64 +0,0 @@
name: Browser tests
concurrency:
# If PR, cancel prev commits. head_ref = source branch name on pull_request, null if push
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
push:
# We intentionally don't run push on feature branches. See PR for rational.
branches: [unstable, stable]
pull_request:
workflow_dispatch:
jobs:
tests-main:
name: Tests
runs-on: buildjet-4vcpu-ubuntu-2204
strategy:
fail-fast: false
matrix:
node: [20]
steps:
# <common-build> - Uses YAML anchors in the future
- uses: actions/checkout@v3
- uses: browser-actions/setup-firefox@latest
with:
firefox-version: "latest"
- uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
check-latest: true
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT
- name: Restore dependencies
uses: actions/cache@master
id: cache-deps
with:
path: |
node_modules
packages/*/node_modules
key: ${{ runner.os }}-${{ steps.node.outputs.v8CppApiVersion }}-${{ hashFiles('**/yarn.lock', '**/package.json') }}
- name: Install & build
if: steps.cache-deps.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile && yarn build
- name: Build
run: yarn build
if: steps.cache-deps.outputs.cache-hit == 'true'
# </common-build>
# Misc sanity checks
- name: Test root binary exists
run: ./lodestar --version
- name: Reject yarn.lock changes
run: .github/workflows/scripts/reject_yarn_lock_changes.sh
# Run only on forks
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
- name: Browser tests
run: |
export DISPLAY=':99.0'
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
yarn test:browsers

View File

@@ -1,78 +0,0 @@
name: E2E tests
concurrency:
# If PR, cancel prev commits. head_ref = source branch name on pull_request, null if push
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
push:
# We intentionally don't run push on feature branches. See PR for rational.
branches: [unstable, stable]
pull_request:
workflow_dispatch:
env:
GOERLI_RPC_DEFAULT_URL: https://goerli.infura.io/v3/84842078b09946638c03157f83405213
GETH_DOCKER_IMAGE: ethereum/client-go:v1.11.6
NETHERMIND_DOCKER_IMAGE: nethermind/nethermind:1.18.0
jobs:
tests-main:
name: Tests
runs-on: buildjet-4vcpu-ubuntu-2204
strategy:
fail-fast: false
matrix:
node: [20]
steps:
# <common-build> - Uses YAML anchors in the future
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
check-latest: true
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT
- name: Restore dependencies
uses: actions/cache@master
id: cache-deps
with:
path: |
node_modules
packages/*/node_modules
key: ${{ runner.os }}-${{ steps.node.outputs.v8CppApiVersion }}-${{ hashFiles('**/yarn.lock', '**/package.json') }}
- name: Install & build
if: steps.cache-deps.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile && yarn build
- name: Build
run: yarn build
if: steps.cache-deps.outputs.cache-hit == 'true'
# </common-build>
# Misc sanity checks
- name: Test root binary exists
run: ./lodestar --version
- name: Reject yarn.lock changes
run: .github/workflows/scripts/reject_yarn_lock_changes.sh
# Run only on forks
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
- name: Run the e2e test environment
run: scripts/run_e2e_env.sh start
- name: E2E tests
run: yarn test:e2e
env:
GOERLI_RPC_URL: ${{ secrets.GOERLI_RPC_URL!=0 && secrets.GOERLI_RPC_URL || env.GOERLI_RPC_DEFAULT_URL }}
- name: Stop the e2e test environment
run: scripts/run_e2e_env.sh stop
- name: Upload debug log test for test env
if: ${{ always() }}
uses: actions/upload-artifact@v2
with:
name: debug-e2e-test-logs
path: test-logs/e2e-test-env

View File

@@ -32,6 +32,7 @@ jobs:
with:
node-version: 20
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT
@@ -91,7 +92,7 @@ jobs:
- name: Upload debug log test files
if: ${{ always() }}
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: debug-test-logs
path: packages/beacon-node/test-logs
@@ -143,7 +144,7 @@ jobs:
- name: Upload debug log test files
if: ${{ always() }}
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: debug-test-logs
path: packages/beacon-node/test-logs

View File

@@ -33,6 +33,7 @@ jobs:
with:
node-version: 20
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT

View File

@@ -1,69 +0,0 @@
name: Spec tests
concurrency:
# If PR, cancel prev commits. head_ref = source branch name on pull_request, null if push
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
push:
# We intentionally don't run push on feature branches. See PR for rational.
branches: [unstable, stable]
pull_request:
workflow_dispatch:
jobs:
tests-spec:
name: Spec tests
runs-on: buildjet-4vcpu-ubuntu-2204
steps:
# As of October 2020, runner has +8GB of free space w/out this script (takes 1m30s to run)
# - run: ./scripts/free-disk-space.sh
# <common-build> - Uses YAML anchors in the future
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20
check-latest: true
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT
- name: Restore dependencies
uses: actions/cache@master
id: cache-deps
with:
path: |
node_modules
packages/*/node_modules
key: ${{ runner.os }}-${{ steps.node.outputs.v8CppApiVersion }}-${{ hashFiles('**/yarn.lock', '**/package.json') }}
- name: Install & build
if: steps.cache-deps.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile && yarn build
- name: Build
run: yarn build
if: steps.cache-deps.outputs.cache-hit == 'true'
# </common-build>
# Download spec tests with cache
- name: Restore spec tests cache
uses: actions/cache@master
with:
path: packages/beacon-node/spec-tests
key: spec-test-data-${{ hashFiles('packages/beacon-node/test/spec/specTestVersioning.ts') }}
- name: Download spec tests
run: yarn download-spec-tests
working-directory: packages/beacon-node
# 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 bls-general
run: yarn test:spec-bls-general
working-directory: packages/beacon-node
- name: Spec tests minimal
run: yarn test:spec-minimal
working-directory: packages/beacon-node
- name: Spec tests mainnet
run: NODE_OPTIONS='--max-old-space-size=4096' yarn test:spec-mainnet
working-directory: packages/beacon-node

View File

@@ -11,10 +11,14 @@ on:
branches: [unstable, stable]
pull_request:
workflow_dispatch:
env:
GETH_DOCKER_IMAGE: ethereum/client-go:v1.11.6
NETHERMIND_DOCKER_IMAGE: nethermind/nethermind:1.18.0
jobs:
tests-main:
name: Tests
build:
name: Build
runs-on: buildjet-4vcpu-ubuntu-2204
strategy:
fail-fast: false
@@ -27,25 +31,135 @@ jobs:
with:
node-version: ${{matrix.node}}
check-latest: true
cache: yarn
- name: Node.js version
id: node
run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT
- name: Restore dependencies
uses: actions/cache@master
id: cache-deps
- name: Restore build
uses: actions/cache/restore@v3
id: cache-build-restore
with:
path: |
node_modules
packages/*/node_modules
key: ${{ runner.os }}-${{ steps.node.outputs.v8CppApiVersion }}-${{ hashFiles('**/yarn.lock', '**/package.json') }}
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-${{ matrix.node }}-${{ github.event.pull_request.head.sha }}
- name: Install & build
if: steps.cache-deps.outputs.cache-hit != 'true'
if: steps.cache-build-restore.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile && yarn build
- name: Build
run: yarn build
if: steps.cache-deps.outputs.cache-hit == 'true'
# </common-build>
if: steps.cache-build-restore.outputs.cache-hit == 'true'
- name: Check Build
run: yarn check-build
- name: Test root binary exists
run: ./lodestar --version
- name: Reject yarn.lock changes
run: .github/workflows/scripts/reject_yarn_lock_changes.sh
# Run only on forks
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
- name: Cache build artifacts
uses: actions/cache@master
id: cache-build
with:
path: |
node_modules
packages/*/node_modules
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-${{ matrix.node }}-${{ github.event.pull_request.head.sha }}
lint:
name: Lint
needs: build
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20
check-latest: true
cache: yarn
- name: Restore build cache
id: cache-primes-restore
uses: actions/cache/restore@v3
with:
path: |
node_modules
packages/*/node_modules
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-20-${{ github.event.pull_request.head.sha }}
- name: Assert yarn prints no warnings
run: scripts/assert_no_yarn_warnings.sh
- name: Lint Code
run: yarn lint
- name: Lint Grafana dashboards
run: scripts/validate-grafana-dashboards.sh
- name: Assert ESM module exports
run: node scripts/assert_exports.mjs
- name: Assert eslintrc rules sorted
run: scripts/assert_eslintrc_sorted.mjs
type-checks:
name: Type Checks
needs: build
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20
check-latest: true
cache: yarn
- name: Restore build cache
id: cache-primes-restore
uses: actions/cache/restore@v3
with:
path: |
node_modules
packages/*/node_modules
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-20-${{ github.event.pull_request.head.sha }}
- name: Check Types
run: yarn check-types
- name: README check
run: yarn check-readme
unit-tests:
name: Unit Tests
needs: type-checks
runs-on: buildjet-4vcpu-ubuntu-2204
strategy:
fail-fast: false
matrix:
node: [20]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
check-latest: true
cache: yarn
- name: Restore build cache
id: cache-primes-restore
uses: actions/cache/restore@v3
with:
path: |
node_modules
packages/*/node_modules
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-${{ matrix.node }}-${{ github.event.pull_request.head.sha }}
# Cache validator slashing protection data tests
- name: Restore spec tests cache
uses: actions/cache@master
@@ -53,34 +167,135 @@ jobs:
path: packages/validator/spec-tests
key: spec-test-data-${{ hashFiles('packages/validator/test/spec/params.ts') }}
- name: Assert yarn prints no warnings
run: scripts/assert_no_yarn_warnings.sh
# Misc sanity checks
- name: Lint Grafana dashboards
run: scripts/validate-grafana-dashboards.sh
- name: Test root binary exists
run: ./lodestar --version
- name: Reject yarn.lock changes
run: .github/workflows/scripts/reject_yarn_lock_changes.sh
# Run only on forks
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }}
- name: Assert ESM module exports
run: node scripts/assert_exports.mjs
- name: Assert eslintrc rules sorted
run: scripts/assert_eslintrc_sorted.mjs
- name: Check Types
run: yarn check-types
- name: README check
run: yarn check-readme
- name: Lint
run: yarn lint
- name: Check Build
run: yarn check-build
- name: Unit tests
run: yarn test:unit
- name: Upload coverage data
run: yarn coverage
e2e-tests:
name: E2E Tests
runs-on: buildjet-4vcpu-ubuntu-2204
needs: build
strategy:
fail-fast: false
matrix:
node: [20]
steps:
# <common-build> - Uses YAML anchors in the future
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
check-latest: true
cache: yarn
- name: Restore build cache
id: cache-primes-restore
uses: actions/cache/restore@v3
with:
path: |
node_modules
packages/*/node_modules
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-${{ matrix.node }}-${{ github.event.pull_request.head.sha }}
- name: Run the e2e test environment
run: scripts/run_e2e_env.sh start
- name: E2E tests
run: yarn test:e2e
env:
GOERLI_RPC_URL: ${{ secrets.GOERLI_RPC_URL!=0 && secrets.GOERLI_RPC_URL || env.GOERLI_RPC_DEFAULT_URL }}
- name: Stop the e2e test environment
run: scripts/run_e2e_env.sh stop
- name: Upload debug log test for test env
if: ${{ always() }}
uses: actions/upload-artifact@v3
with:
name: debug-e2e-test-logs-node-${{matrix.node}}
path: test-logs/e2e-test-env
browser-tests:
name: Browser Tests
runs-on: buildjet-4vcpu-ubuntu-2204
needs: build
strategy:
fail-fast: false
matrix:
node: [20]
steps:
# <common-build> - Uses YAML anchors in the future
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
check-latest: true
cache: yarn
- name: Restore build cache
id: cache-primes-restore
uses: actions/cache/restore@v3
with:
path: |
node_modules
packages/*/node_modules
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-${{ matrix.node }}-${{ github.event.pull_request.head.sha }}
- name: Browser tests
run: |
export DISPLAY=':99.0'
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
yarn test:browsers
spec-tests:
name: Spec tests
needs: build
runs-on: buildjet-4vcpu-ubuntu-2204
strategy:
fail-fast: false
matrix:
node: [20]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: ${{matrix.node}}
check-latest: true
cache: yarn
- name: Restore build cache
id: cache-primes-restore
uses: actions/cache/restore@v3
with:
path: |
node_modules
packages/*/node_modules
lib/
packages/*/lib
packages/*/.git-data.json
key: ${{ runner.os }}-${{ matrix.node }}-${{ github.event.pull_request.head.sha }}
# Download spec tests with cache
- name: Restore spec tests cache
uses: actions/cache@master
with:
path: packages/beacon-node/spec-tests
key: spec-test-data-${{ hashFiles('packages/beacon-node/test/spec/specTestVersioning.ts') }}
- name: Download spec tests
run: yarn download-spec-tests
working-directory: packages/beacon-node
# 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 bls-general
run: yarn test:spec-bls-general
working-directory: packages/beacon-node
- name: Spec tests minimal
run: yarn test:spec-minimal
working-directory: packages/beacon-node
- name: Spec tests mainnet
run: NODE_OPTIONS='--max-old-space-size=4096' yarn test:spec-mainnet
working-directory: packages/beacon-node

View File

@@ -93,7 +93,8 @@
"ts-node": "^10.9.1",
"typescript": "^5.1.6",
"typescript-docs-verifier": "^2.5.0",
"webpack": "^5.88.1"
"webpack": "^5.88.1",
"wait-port": "^1.0.4"
},
"resolutions": {
"dns-over-http-resolver": "^2.1.1"

View File

@@ -1,4 +1,4 @@
import {Api} from "./routes/index.js";
import type {Api} from "./routes/index.js";
// NOTE: Don't export server here so it's not bundled to all consumers

View File

@@ -15,10 +15,11 @@ import * as state from "./state.js";
export * as block from "./block.js";
export * as pool from "./pool.js";
export * as state from "./state.js";
export {BlockId, BlockHeaderResponse, BroadcastValidation} from "./block.js";
export {AttestationFilters} from "./pool.js";
export {BroadcastValidation} from "./block.js";
export type {BlockId, BlockHeaderResponse} from "./block.js";
export type {AttestationFilters} from "./pool.js";
// TODO: Review if re-exporting all these types is necessary
export {
export type {
StateId,
ValidatorId,
ValidatorStatus,

View File

@@ -17,7 +17,7 @@ import * as validator from "./validator.js";
export {ApiError};
// Re-export for convenience
export {RouteConfig};
export type {RouteConfig};
export function registerRoutes(
server: ServerInstance,

View File

@@ -5,7 +5,7 @@ import * as builder from "./client.js";
// NOTE: Don't export server here so it's not bundled to all consumers
export {Api};
export type {Api};
// Note: build API does not have namespaces as routes are declared at the "root" namespace

View File

@@ -5,7 +5,7 @@ import {
ServerRoutes,
getGenericJsonServer,
registerRoute,
RouteConfig,
type RouteConfig,
} from "../../utils/server/index.js";
import {Api, ReqTypes, routesData, getReturnTypes, getReqSerializers} from "../routes.js";

View File

@@ -1,19 +1,10 @@
// Re-exporting beacon only for backwards compatibility
export * from "./beacon/index.js";
export * from "./interfaces.js";
export {HttpStatusCode, HttpErrorCodes, HttpSuccessCodes} from "./utils/client/httpStatusCode.js";
export {
HttpClient,
IHttpClient,
HttpClientOptions,
HttpClientModules,
HttpError,
ApiError,
Metrics,
FetchError,
isFetchError,
fetch,
} from "./utils/client/index.js";
export {HttpStatusCode} from "./utils/client/httpStatusCode.js";
export type {HttpErrorCodes, HttpSuccessCodes} from "./utils/client/httpStatusCode.js";
export {HttpClient, HttpError, ApiError, FetchError, isFetchError, fetch} from "./utils/client/index.js";
export type {IHttpClient, HttpClientOptions, HttpClientModules, Metrics} from "./utils/client/index.js";
export * from "./utils/routes.js";
// NOTE: Don't export server here so it's not bundled to all consumers

View File

@@ -6,18 +6,8 @@ import * as keymanager from "./client.js";
// NOTE: Don't export server here so it's not bundled to all consumers
export {
ImportStatus,
DeletionStatus,
ImportRemoteKeyStatus,
DeleteRemoteKeyStatus,
ResponseStatus,
SignerDefinition,
KeystoreStr,
SlashingProtectionData,
PubkeyHex,
Api,
} from "./routes.js";
export {ImportStatus, DeletionStatus, ImportRemoteKeyStatus, DeleteRemoteKeyStatus} from "./routes.js";
export type {ResponseStatus, SignerDefinition, KeystoreStr, SlashingProtectionData, PubkeyHex, Api} from "./routes.js";
type ClientModules = HttpClientModules & {
config: ChainForkConfig;

View File

@@ -5,7 +5,7 @@ import {
ServerRoutes,
getGenericJsonServer,
registerRoute,
RouteConfig,
type RouteConfig,
} from "../../utils/server/index.js";
import {Api, ReqTypes, routesData, getReturnTypes, getReqSerializers} from "../routes.js";

View File

@@ -3,7 +3,7 @@ import {ReqGeneric, RouteDef} from "../index.js";
import {ApiClientResponse, ApiClientSuccessResponse} from "../../interfaces.js";
import {fetch, isFetchError} from "./fetch.js";
import {stringifyQuery, urlJoin} from "./format.js";
import {Metrics} from "./metrics.js";
import type {Metrics} from "./metrics.js";
import {HttpStatusCode} from "./httpStatusCode.js";
/** A higher default timeout, validator will sets its own shorter timeoutMs */

View File

@@ -3,6 +3,5 @@ module.exports = {
require: ["./test/setupPreset.ts", "./test/setup.ts"],
"node-option": ["loader=ts-node/esm"],
timeout: 60_000,
// Do not run tests through workers, it's not proven to be faster than with `jobs: 2`
parallel: false,
parallel: true
};

View File

@@ -80,7 +80,7 @@
"test:unit:minimal": "nyc --cache-dir .nyc_output/.cache -e .ts mocha 'test/unit/**/*.test.ts'",
"test:unit:mainnet": "LODESTAR_PRESET=mainnet nyc --cache-dir .nyc_output/.cache -e .ts mocha 'test/unit-mainnet/**/*.test.ts'",
"test:unit": "yarn test:unit:minimal && yarn test:unit:mainnet",
"test:e2e": "mocha 'test/e2e/**/*.test.ts'",
"test:e2e": "LODESTAR_PRESET=minimal mocha 'test/e2e/**/*.test.ts'",
"test:sim": "mocha 'test/sim/**/*.test.ts'",
"test:sim:merge-interop": "mocha 'test/sim/merge-interop.test.ts'",
"test:sim:mergemock": "mocha 'test/sim/mergemock.test.ts'",

View File

@@ -11,7 +11,7 @@ import {assertLinearChainSegment} from "./utils/chainSegment.js";
import {BlockInput, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
import {verifyBlocksSanityChecks} from "./verifyBlocksSanityChecks.js";
import {removeEagerlyPersistedBlockInputs} from "./writeBlockInputToDb.js";
export {ImportBlockOpts, AttestationImportOpt} from "./types.js";
export {type ImportBlockOpts, AttestationImportOpt} from "./types.js";
const QUEUE_MAX_LENGTH = 256;

View File

@@ -1,3 +1,4 @@
export {IBlsVerifier} from "./interface.js";
export {BlsMultiThreadWorkerPool, BlsMultiThreadWorkerPoolModules} from "./multithread/index.js";
export type {IBlsVerifier} from "./interface.js";
export type {BlsMultiThreadWorkerPoolModules} from "./multithread/index.js";
export {BlsMultiThreadWorkerPool} from "./multithread/index.js";
export {BlsSingleThreadVerifier} from "./singleThread.js";

View File

@@ -14,7 +14,7 @@ import {CachedBeaconStateAllForks} from "@lodestar/state-transition";
* - Fork Choice: the chain's fork choice is updated
* - Checkpointing: the chain processes epoch boundaries
*/
export const enum ChainEvent {
export enum ChainEvent {
/**
* This event signals that the chain has processed (or reprocessed) a checkpoint.
*

View File

@@ -21,7 +21,7 @@ import {ChainEventEmitter} from "../emitter.js";
import {ChainEvent} from "../emitter.js";
import {GENESIS_SLOT} from "../../constants/index.js";
export {ForkChoiceOpts};
export type {ForkChoiceOpts};
/**
* Fork Choice extended with a ChainEventEmitter

View File

@@ -37,8 +37,8 @@ import {IChainOptions} from "./options.js";
import {AssembledBlockType, BlockAttributes, BlockType} from "./produceBlock/produceBlockBody.js";
import {SeenAttestationDatas} from "./seenCache/seenAttestationData.js";
export {BlockType, AssembledBlockType};
export {ProposerPreparationData};
export {BlockType, type AssembledBlockType};
export {type ProposerPreparationData};
export type BlockHash = RootHex;
export type StateGetOpts = {

View File

@@ -1,2 +1,2 @@
export {IBeaconDb} from "./interface.js";
export type {IBeaconDb} from "./interface.js";
export {BeaconDb} from "./beacon.js";

View File

@@ -2,7 +2,8 @@ export {BlobSidecarsRepository} from "./blobSidecars.js";
export {BlobSidecarsArchiveRepository} from "./blobSidecarsArchive.js";
export {BlockRepository} from "./block.js";
export {BlockArchiveBatchPutBinaryItem, BlockArchiveRepository, BlockFilterOptions} from "./blockArchive.js";
export {BlockArchiveRepository} from "./blockArchive.js";
export type {BlockArchiveBatchPutBinaryItem, BlockFilterOptions} from "./blockArchive.js";
export {StateArchiveRepository} from "./stateArchive.js";
export {AttesterSlashingRepository} from "./attesterSlashing.js";

View File

@@ -6,7 +6,8 @@ import {Eth1DepositDataTracker, Eth1DepositDataTrackerModules} from "./eth1Depos
import {Eth1MergeBlockTracker, Eth1MergeBlockTrackerModules} from "./eth1MergeBlockTracker.js";
import {Eth1Options} from "./options.js";
import {Eth1Provider} from "./provider/eth1Provider.js";
export {IEth1ForBlockProduction, IEth1Provider, Eth1Provider};
export {Eth1Provider};
export type {IEth1ForBlockProduction, IEth1Provider};
// This module encapsulates all consumer functionality to the execution node (formerly eth1). The execution client
// has to:

View File

@@ -6,7 +6,7 @@ import {DATA, QUANTITY} from "../../eth1/provider/utils.js";
import {PayloadIdCache, PayloadId, WithdrawalV1} from "./payloadIdCache.js";
import {ExecutionPayloadBody} from "./types.js";
export {PayloadIdCache, PayloadId, WithdrawalV1};
export {PayloadIdCache, type PayloadId, type WithdrawalV1};
export enum ExecutionPayloadStatus {
/** given payload is valid */

View File

@@ -1,17 +1,23 @@
export {initStateFromAnchorState, initStateFromDb, initStateFromEth1} from "./chain/index.js";
export {BeaconDb, IBeaconDb} from "./db/index.js";
export {Eth1Provider, IEth1Provider} from "./eth1/index.js";
export {createNodeJsLibp2p, NodeJsLibp2pOpts} from "./network/index.js";
export {BeaconDb, type IBeaconDb} from "./db/index.js";
export {Eth1Provider, type IEth1Provider} from "./eth1/index.js";
export {createNodeJsLibp2p, type NodeJsLibp2pOpts} from "./network/index.js";
export * from "./node/index.js";
// Export metrics utilities to de-duplicate validator metrics
export {RegistryMetricCreator, collectNodeJSMetrics, HttpMetricsServer, getHttpMetricsServer} from "./metrics/index.js";
export {
RegistryMetricCreator,
collectNodeJSMetrics,
type HttpMetricsServer,
getHttpMetricsServer,
} from "./metrics/index.js";
// Export monitoring service to make it usable by validator
export {MonitoringService} from "./monitoring/index.js";
// Export generic RestApi server for CLI
export {RestApiServer, RestApiServerOpts, RestApiServerModules, RestApiServerMetrics} from "./api/rest/base.js";
export {RestApiServer} from "./api/rest/base.js";
export type {RestApiServerOpts, RestApiServerModules, RestApiServerMetrics} from "./api/rest/base.js";
// Export type util for CLI - TEMP move to lodestar-types eventually
export {getStateTypeFromBytes} from "./util/multifork.js";

View File

@@ -35,7 +35,7 @@ import * as protocols from "./protocols.js";
import {collectExactOneTyped} from "./utils/collect.js";
export {getReqRespHandlers} from "./handlers/index.js";
export {ReqRespMethod, RequestTypedContainer} from "./types.js";
export {ReqRespMethod, type RequestTypedContainer} from "./types.js";
export interface ReqRespBeaconNodeModules {
libp2p: Libp2p;

View File

@@ -8,7 +8,7 @@ import {IBeaconChain} from "../chain/index.js";
import {Metrics} from "../metrics/index.js";
import {IBeaconDb} from "../db/index.js";
import {SyncChainDebugState} from "./range/chain.js";
export {SyncChainDebugState};
export type {SyncChainDebugState};
export type SyncingStatus = routes.node.SyncingStatus;

View File

@@ -6,7 +6,7 @@ import {ErrorAborted} from "@lodestar/utils";
import {computeEpochAtSlot, computeTimeAtSlot, getCurrentSlot} from "@lodestar/state-transition";
import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../constants/constants.js";
export const enum ClockEvent {
export enum ClockEvent {
/**
* This event signals the start of a new slot, and that subsequent calls to `clock.currentSlot` will equal `slot`.
* This event is guaranteed to be emitted every `SECONDS_PER_SLOT` seconds.

View File

@@ -17,8 +17,6 @@ const CONSTANT_NAMES_SKIP_LIST = new Set([
]);
describe("api / impl / config", function () {
this.timeout(60 * 1000);
it("Ensure all constants are exposed", async () => {
const constantNames = await downloadRemoteConstants(ethereumConsensusSpecsTests.specVersion);

View File

@@ -1,35 +0,0 @@
import {expect} from "chai";
import {config} from "@lodestar/config/default";
import {ssz} from "@lodestar/types";
import {GENESIS_SLOT} from "@lodestar/params";
import {setupApiImplTestServer, ApiImplTestModules} from "../../../unit/api/impl/index.test.js";
import {zeroProtoBlock} from "../../../utils/mocks/chain.js";
describe("getBlobSideCar", function () {
let server: ApiImplTestModules;
before(function () {
server = setupApiImplTestServer();
});
// TODO: Write actual tests against the real BeaconChain class, this test is useless
it.skip("getBlobSideCar From BlobSidecars", async () => {
const block = config.getForkTypes(GENESIS_SLOT).SignedBeaconBlock.defaultValue();
const blobSidecars = ssz.deneb.BlobSidecars.defaultValue();
const wrappedBlobSidecars = {
blockRoot: ssz.Root.defaultValue(),
slot: block.message.slot,
blobSidecars,
};
server.forkChoiceStub.getFinalizedBlock.returns(zeroProtoBlock);
server.dbStub.blockArchive.get.resolves(block);
server.dbStub.blobSidecars.get.resolves(wrappedBlobSidecars);
const returnedBlobSideCars = await server.blockApi.getBlobSidecars("genesis");
expect(returnedBlobSideCars.data).to.equal(blobSidecars);
});
});

View File

@@ -38,8 +38,7 @@ describe("api / impl / validator", function () {
const genesisValidatorsRoot = Buffer.alloc(32, 0xaa);
const config = createBeaconConfig(chainConfig, genesisValidatorsRoot);
const testLoggerOpts: TestLoggerOpts = {level: LogLevel.info};
const loggerNodeA = testLogger("Node-A", testLoggerOpts);
const loggerNodeA = testLogger("Node-A");
const bn = await getDevBeaconNode({
params: testParams,

View File

@@ -78,6 +78,7 @@ describe("chain / bls / multithread queue", function () {
expect(isValid).to.deep.equal([true, true, true], `sig set ${i} returned invalid`);
}
}
await pool.close();
}
for (const priority of [true, false]) {
@@ -122,6 +123,7 @@ describe("chain / bls / multithread queue", function () {
for (const [i, isValid] of isValidArr.entries()) {
expect(isValid).to.equal(true, `sig set ${i} returned invalid`);
}
await pool.close();
});
}
});

View File

@@ -23,7 +23,8 @@ describe("chain / lightclient", function () {
const maxLcHeadTrackingDiffSlots = 4;
const validatorCount = 8;
const validatorClientCount = 4;
const targetSyncCommittee = 3;
// Reduced from 3 to 1, so test can complete in 10 epoch vs 27 epoch
const targetSyncCommittee = 1;
/** N sync committee periods + 1 epoch of margin */
const finalizedEpochToReach = targetSyncCommittee * EPOCHS_PER_SYNC_COMMITTEE_PERIOD + 1;
/** Given 100% participation the fastest epoch to reach finalization is +2 epochs. -1 for margin */
@@ -53,7 +54,7 @@ describe("chain / lightclient", function () {
// delay a bit so regular sync sees it's up to date and sync is completed from the beginning
// also delay to allow bls workers to be transpiled/initialized
const genesisSlotsDelay = 16;
const genesisSlotsDelay = 7;
const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT;
const testLoggerOpts: TestLoggerOpts = {

View File

@@ -21,6 +21,7 @@ import {BeaconNode} from "../../../src/node/index.js";
//
// Attempting to do both 1. and 2. in this e2e test more expensive than necessary.
// Unit tests in the validator cover 2., so some test in lodestar package should cover 1.
// https://github.com/ChainSafe/lodestar/issues/5967
describe.skip("doppelganger / doppelganger test", function () {
const afterEachCallbacks: (() => Promise<unknown> | void)[] = [];
afterEach(async () => {

View File

@@ -27,6 +27,7 @@ const pyrmontDepositsDataRoot = [
"0x61cef7d8a3f7c590a2dc066ae1c95def5ce769b3e9471fdb34f36f7a7246965e",
];
// https://github.com/ChainSafe/lodestar/issues/5967
describe.skip("eth1 / Eth1Provider", function () {
this.timeout("2 min");

View File

@@ -15,6 +15,7 @@ import {getGoerliRpcUrl} from "../../testParams.js";
// This test is constantly failing. We must unblock PR so this issue is a TODO to debug it and re-enable latter.
// It's OKAY to disable temporarily since this functionality is tested indirectly by the sim merge tests.
// See https://github.com/ChainSafe/lodestar/issues/4197
// https://github.com/ChainSafe/lodestar/issues/5967
describe.skip("eth1 / Eth1MergeBlockTracker", function () {
this.timeout("2 min");

View File

@@ -8,6 +8,7 @@ import {Eth1Provider, parseEth1Block} from "../../../src/eth1/provider/eth1Provi
import {Eth1Block} from "../../../src/eth1/interface.js";
import {getGoerliRpcUrl} from "../../testParams.js";
// https://github.com/ChainSafe/lodestar/issues/5967
describe.skip("eth1 / Eth1Provider", function () {
this.timeout("2 min");

View File

@@ -6,6 +6,7 @@ import {Eth1Provider} from "../../../src/eth1/provider/eth1Provider.js";
import {getGoerliRpcUrl} from "../../testParams.js";
import {Eth1Options} from "../../../src/eth1/options.js";
// https://github.com/ChainSafe/lodestar/issues/5967
describe.skip("Eth1 streams", function () {
this.timeout("2 min");

View File

@@ -19,7 +19,7 @@ describe("gossipsub / worker", function () {
function runTests(this: Mocha.Suite, {useWorker}: {useWorker: boolean}): void {
if (this.timeout() < 20 * 1000) this.timeout(150 * 1000);
this.retries(0); // This test fail sometimes, with a 5% rate.
this.retries(2); // This test fail sometimes, with a 5% rate.
const afterEachCallbacks: (() => Promise<void> | void)[] = [];
afterEach(async () => {

View File

@@ -24,6 +24,7 @@ import {memoOnce} from "../../utils/cache.js";
let port = 9000;
const mu = "/ip4/127.0.0.1/tcp/0";
// https://github.com/ChainSafe/lodestar/issues/5967
// eslint-disable-next-line mocha/no-skipped-tests
describe.skip("mdns", function () {
this.timeout(50000);

View File

@@ -47,7 +47,7 @@ describe("sync / unknown block sync", function () {
this.timeout("10 min");
// the node needs time to transpile/initialize bls worker threads
const genesisSlotsDelay = 16;
const genesisSlotsDelay = 7;
const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT;
const testLoggerOpts: TestLoggerOpts = {
level: LogLevel.info,

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {expect} from "chai";
import {
CachedBeaconStateAllForks,
@@ -7,11 +8,14 @@ import {
} from "@lodestar/state-transition";
import * as epochFns from "@lodestar/state-transition/epoch";
import {ssz} from "@lodestar/types";
import {ACTIVE_PRESET} from "@lodestar/params";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {expectEqualBeaconState, inputTypeSszTreeViewDU} from "../utils/expectEqualBeaconState.js";
import {getConfig} from "../../utils/config.js";
import {TestRunnerFn} from "../utils/types.js";
import {RunnerType, TestRunnerFn} from "../utils/types.js";
import {assertCorrectProgressiveBalances} from "../config.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
export type EpochTransitionFn = (state: CachedBeaconStateAllForks, epochTransitionCache: EpochTransitionCache) => void;
@@ -47,7 +51,7 @@ type EpochTransitionCacheingTestCase = {
* @param fork
* @param epochTransitionFns Describe with which function to run each directory of tests
*/
export const epochProcessing =
const epochProcessing =
(skipTestNames?: string[]): TestRunnerFn<EpochTransitionCacheingTestCase, BeaconStateAllForks> =>
(fork, testName) => {
const config = getConfig(fork);
@@ -92,3 +96,15 @@ export const epochProcessing =
},
};
};
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
epoch_processing: {
type: RunnerType.default,
fn: epochProcessing([
// TODO: invalid_large_withdrawable_epoch asserts an overflow on a u64 for its exit epoch.
// Currently unable to reproduce in Lodestar, skipping for now
// https://github.com/ethereum/consensus-specs/blob/3212c419f6335e80ed825b4855a071f76bef70c3/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_registry_updates.py#L349
"invalid_large_withdrawable_epoch",
]),
},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {
BeaconStateAllForks,
DataAvailableStatus,
@@ -5,16 +6,18 @@ import {
stateTransition,
} from "@lodestar/state-transition";
import {altair, bellatrix, ssz} from "@lodestar/types";
import {ForkName} from "@lodestar/params";
import {ACTIVE_PRESET, ForkName} from "@lodestar/params";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {expectEqualBeaconState, inputTypeSszTreeViewDU} from "../utils/expectEqualBeaconState.js";
import {shouldVerify, TestRunnerFn} from "../utils/types.js";
import {RunnerType, shouldVerify, TestRunnerFn} from "../utils/types.js";
import {getConfig} from "../../utils/config.js";
import {assertCorrectProgressiveBalances} from "../config.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
/* eslint-disable @typescript-eslint/naming-convention */
export const finality: TestRunnerFn<FinalityTestCase, BeaconStateAllForks> = (fork) => {
const finality: TestRunnerFn<FinalityTestCase, BeaconStateAllForks> = (fork) => {
return {
testFunction: (testcase) => {
let state = createCachedBeaconStateTest(testcase.pre, getConfig(fork));
@@ -80,3 +83,7 @@ type FinalityTestCase = {
pre: BeaconStateAllForks;
post?: BeaconStateAllForks;
};
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
finality: {type: RunnerType.default, fn: finality},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {
BeaconStateAllForks,
CachedBeaconStateBellatrix,
@@ -7,13 +8,15 @@ import {
} from "@lodestar/state-transition";
import * as slotFns from "@lodestar/state-transition/slot";
import {phase0, ssz} from "@lodestar/types";
import {ForkName} from "@lodestar/params";
import {ACTIVE_PRESET, ForkName} from "@lodestar/params";
import {createChainForkConfig, ChainForkConfig} from "@lodestar/config";
import {expectEqualBeaconState, inputTypeSszTreeViewDU} from "../utils/expectEqualBeaconState.js";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {TestRunnerFn} from "../utils/types.js";
import {RunnerType, TestRunnerFn} from "../utils/types.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
export const fork: TestRunnerFn<ForkStateCase, BeaconStateAllForks> = (forkNext) => {
const fork: TestRunnerFn<ForkStateCase, BeaconStateAllForks> = (forkNext) => {
const config = createChainForkConfig({});
const forkPrev = getPreviousFork(config, forkNext);
@@ -66,3 +69,7 @@ export function getPreviousFork(config: ChainForkConfig, fork: ForkName): ForkNa
}
return config.forksAscendingEpochOrder[forkIndex - 1].name;
}
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
fork: {type: RunnerType.default, fn: fork},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {expect} from "chai";
import {toHexString} from "@chainsafe/ssz";
import {BeaconStateAllForks, isExecutionStateType} from "@lodestar/state-transition";
@@ -6,13 +7,13 @@ import {CheckpointWithHex, ForkChoice} from "@lodestar/fork-choice";
import {phase0, allForks, bellatrix, ssz, RootHex} from "@lodestar/types";
import {bnToNum} from "@lodestar/utils";
import {createBeaconConfig} from "@lodestar/config";
import {ForkSeq, isForkBlobs} from "@lodestar/params";
import {ACTIVE_PRESET, ForkSeq, isForkBlobs} from "@lodestar/params";
import {BeaconChain} from "../../../src/chain/index.js";
import {ClockEvent} from "../../../src/util/clock.js";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {testLogger} from "../../utils/logger.js";
import {getConfig} from "../../utils/config.js";
import {TestRunnerFn} from "../utils/types.js";
import {RunnerType, TestRunnerFn} from "../utils/types.js";
import {Eth1ForBlockProductionDisabled} from "../../../src/eth1/index.js";
import {getExecutionEngineFromBackend} from "../../../src/execution/index.js";
import {ExecutionPayloadStatus} from "../../../src/execution/engine/interface.js";
@@ -25,6 +26,8 @@ import {ZERO_HASH_HEX} from "../../../src/constants/constants.js";
import {PowMergeBlock} from "../../../src/eth1/interface.js";
import {assertCorrectProgressiveBalances} from "../config.js";
import {initCKZG, loadEthereumTrustedSetup} from "../../../src/util/kzg.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
/* eslint-disable @typescript-eslint/naming-convention */
@@ -37,7 +40,7 @@ const ATTESTER_SLASHING_FILE_NAME = "^(attester_slashing)_([0-9a-zA-Z])+$";
const logger = testLogger("spec-test");
export const forkChoiceTest =
const forkChoiceTest =
(opts: {onlyPredefinedResponses: boolean}): TestRunnerFn<ForkChoiceTestCase, void> =>
(fork) => {
return {
@@ -460,3 +463,8 @@ class Eth1ForBlockProductionMock extends Eth1ForBlockProductionDisabled {
});
}
}
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
fork_choice: {type: RunnerType.default, fn: forkChoiceTest({onlyPredefinedResponses: false})},
sync: {type: RunnerType.default, fn: forkChoiceTest({onlyPredefinedResponses: true})},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {expect} from "chai";
import {phase0, Root, ssz, TimeSeconds, allForks, deneb} from "@lodestar/types";
import {InputType} from "@lodestar/spec-test-util";
@@ -10,15 +11,20 @@ import {
import {bnToNum} from "@lodestar/utils";
import {ForkName} from "@lodestar/params";
import {ACTIVE_PRESET} from "@lodestar/params";
import {expectEqualBeaconState} from "../utils/expectEqualBeaconState.js";
import {TestRunnerFn} from "../utils/types.js";
import {getConfig} from "../../utils/config.js";
import {RunnerType} from "../utils/types.js";
import {specTestIterator} from "../utils/specTestIterator.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
// The aim of the genesis tests is to provide a baseline to test genesis-state initialization and test if the
// proposed genesis-validity conditions are working.
/* eslint-disable @typescript-eslint/naming-convention */
export const genesis: TestRunnerFn<any, any> = (fork, testName, testSuite) => {
const genesis: TestRunnerFn<any, any> = (fork, testName, testSuite) => {
const testFn = genesisTestFns[testName];
if (testFn === undefined) {
throw Error(`Unknown genesis test ${testName}`);
@@ -145,3 +151,7 @@ type GenesisInitCase = {
};
type ExecutionFork = Exclude<ForkName, ForkName.phase0 | ForkName.altair>;
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
genesis: {type: RunnerType.default, fn: genesis},
});

View File

@@ -1,79 +0,0 @@
import path from "node:path";
import {ACTIVE_PRESET} from "@lodestar/params";
import {RunnerType} from "../utils/types.js";
import {SkipOpts, specTestIterator} from "../utils/specTestIterator.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {epochProcessing} from "./epoch_processing.js";
import {finality} from "./finality.js";
import {fork} from "./fork.js";
import {forkChoiceTest} from "./fork_choice.js";
import {genesis} from "./genesis.js";
import {lightClient} from "./light_client/index.js";
import {merkle} from "./merkle.js";
import {operations} from "./operations.js";
import {rewards} from "./rewards.js";
import {sanity, sanityBlocks} from "./sanity.js";
import {shuffling} from "./shuffling.js";
import {sszStatic} from "./ssz_static.js";
import {transition} from "./transition.js";
// NOTE: You MUST always provide a detailed reason of why a spec test is skipped plus link
// to an issue marking it as pending to re-enable and an aproximate timeline of when it will
// be fixed.
// NOTE: Comment the minimum set of test necessary to unblock PRs: For example, instead of
// skipping all `bls_to_execution_change` tests, just skip for a fork setting:
// ```
// skippedPrefixes: [
// // Skipped since this only test that withdrawals are de-activated
// "eip4844/operations/bls_to_execution_change",
// ],
// ```
const skipOpts: SkipOpts = {
skippedForks: ["eip6110"],
// TODO: capella
// BeaconBlockBody proof in lightclient is the new addition in v1.3.0-rc.2-hotfix
// Skip them for now to enable subsequently
skippedPrefixes: [
"capella/light_client/single_merkle_proof/BeaconBlockBody",
"deneb/light_client/single_merkle_proof/BeaconBlockBody",
],
};
/* eslint-disable @typescript-eslint/naming-convention */
specTestIterator(
path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET),
{
epoch_processing: {
type: RunnerType.default,
fn: epochProcessing([
// TODO: invalid_large_withdrawable_epoch asserts an overflow on a u64 for its exit epoch.
// Currently unable to reproduce in Lodestar, skipping for now
// https://github.com/ethereum/consensus-specs/blob/3212c419f6335e80ed825b4855a071f76bef70c3/tests/core/pyspec/eth2spec/test/phase0/epoch_processing/test_process_registry_updates.py#L349
"invalid_large_withdrawable_epoch",
]),
},
finality: {type: RunnerType.default, fn: finality},
fork: {type: RunnerType.default, fn: fork},
fork_choice: {type: RunnerType.default, fn: forkChoiceTest({onlyPredefinedResponses: false})},
genesis: {type: RunnerType.default, fn: genesis},
light_client: {type: RunnerType.default, fn: lightClient},
merkle: {type: RunnerType.default, fn: merkle},
operations: {type: RunnerType.default, fn: operations},
random: {type: RunnerType.default, fn: sanityBlocks},
rewards: {type: RunnerType.default, fn: rewards},
sanity: {type: RunnerType.default, fn: sanity},
shuffling: {type: RunnerType.default, fn: shuffling},
ssz_static: {
type: RunnerType.custom,
fn: sszStatic(),
},
sync: {type: RunnerType.default, fn: forkChoiceTest({onlyPredefinedResponses: true})},
transition: {
type: RunnerType.default,
fn: transition(),
},
},
skipOpts
);

View File

@@ -1,11 +1,15 @@
import {TestRunnerFn} from "../../utils/types.js";
import path from "node:path";
import {ACTIVE_PRESET} from "@lodestar/params";
import {ethereumConsensusSpecsTests} from "../../specTestVersioning.js";
import {specTestIterator} from "../../utils/specTestIterator.js";
import {RunnerType, TestRunnerFn} from "../../utils/types.js";
import {singleMerkleProof} from "./single_merkle_proof.js";
import {sync} from "./sync.js";
import {updateRanking} from "./update_ranking.js";
/* eslint-disable @typescript-eslint/naming-convention */
export const lightClient: TestRunnerFn<any, any> = (fork, testName, testSuite) => {
const lightClient: TestRunnerFn<any, any> = (fork, testName, testSuite) => {
const testFn = lightclientTestFns[testName];
if (testFn === undefined) {
throw Error(`Unknown lightclient test ${testName}`);
@@ -19,3 +23,7 @@ const lightclientTestFns: Record<string, TestRunnerFn<any, any>> = {
sync: sync,
update_ranking: updateRanking,
};
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
light_client: {type: RunnerType.default, fn: lightClient},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {expect} from "chai";
import {ProofType, SingleProof, Tree} from "@chainsafe/persistent-merkle-tree";
import {fromHexString, toHexString} from "@chainsafe/ssz";
@@ -5,11 +6,14 @@ import {ssz} from "@lodestar/types";
import {BeaconStateAllForks} from "@lodestar/state-transition";
import {InputType} from "@lodestar/spec-test-util";
import {verifyMerkleBranch} from "@lodestar/utils";
import {TestRunnerFn} from "../utils/types.js";
import {ACTIVE_PRESET} from "@lodestar/params";
import {RunnerType, TestRunnerFn} from "../utils/types.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
/* eslint-disable @typescript-eslint/naming-convention */
export const merkle: TestRunnerFn<MerkleTestCase, IProof> = (fork) => {
const merkle: TestRunnerFn<MerkleTestCase, IProof> = (fork) => {
return {
testFunction: (testcase) => {
const {proof: specTestProof, state} = testcase;
@@ -62,3 +66,7 @@ interface IProof {
leaf_index: bigint;
branch: string[];
}
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
merkle: {type: RunnerType.default, fn: merkle},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {
BeaconStateAllForks,
CachedBeaconStateAllForks,
@@ -10,12 +11,14 @@ import {
import * as blockFns from "@lodestar/state-transition/block";
import {ssz, phase0, altair, bellatrix, capella} from "@lodestar/types";
import {InputType} from "@lodestar/spec-test-util";
import {ForkName} from "@lodestar/params";
import {ACTIVE_PRESET, ForkName} from "@lodestar/params";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {expectEqualBeaconState, inputTypeSszTreeViewDU} from "../utils/expectEqualBeaconState.js";
import {getConfig} from "../../utils/config.js";
import {BaseSpecTest, shouldVerify, TestRunnerFn} from "../utils/types.js";
import {BaseSpecTest, RunnerType, shouldVerify, TestRunnerFn} from "../utils/types.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
/* eslint-disable @typescript-eslint/naming-convention */
@@ -95,7 +98,7 @@ export type OperationsTestCase = {
execution: {execution_valid: boolean};
};
export const operations: TestRunnerFn<OperationsTestCase, BeaconStateAllForks> = (fork, testName) => {
const operations: TestRunnerFn<OperationsTestCase, BeaconStateAllForks> = (fork, testName) => {
const operationFn = operationFns[testName];
if (operationFn === undefined) {
throw Error(`No operationFn for ${testName}`);
@@ -144,3 +147,7 @@ export const operations: TestRunnerFn<OperationsTestCase, BeaconStateAllForks> =
};
type ExecutionFork = Exclude<ForkName, ForkName.phase0 | ForkName.altair>;
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
operations: {type: RunnerType.default, fn: operations},
});

View File

@@ -1,19 +1,23 @@
import path from "node:path";
import {expect} from "chai";
import {VectorCompositeType} from "@chainsafe/ssz";
import {BeaconStateAllForks, beforeProcessEpoch} from "@lodestar/state-transition";
import {getRewardsAndPenalties} from "@lodestar/state-transition/epoch";
import {ssz} from "@lodestar/types";
import {ACTIVE_PRESET} from "@lodestar/params";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {inputTypeSszTreeViewDU} from "../utils/expectEqualBeaconState.js";
import {getConfig} from "../../utils/config.js";
import {TestRunnerFn} from "../utils/types.js";
import {RunnerType, TestRunnerFn} from "../utils/types.js";
import {assertCorrectProgressiveBalances} from "../config.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
/* eslint-disable @typescript-eslint/naming-convention */
const deltasType = new VectorCompositeType(ssz.phase0.Balances, 2);
export const rewards: TestRunnerFn<RewardTestCase, Deltas> = (fork) => {
const rewards: TestRunnerFn<RewardTestCase, Deltas> = (fork) => {
return {
testFunction: (testcase) => {
const config = getConfig(fork);
@@ -85,3 +89,7 @@ function sumDeltas(deltasArr: Deltas[]): Deltas {
}
return totalDeltas;
}
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
rewards: {type: RunnerType.default, fn: rewards},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {InputType} from "@lodestar/spec-test-util";
import {
BeaconStateAllForks,
@@ -7,17 +8,19 @@ import {
stateTransition,
} from "@lodestar/state-transition";
import {allForks, deneb, ssz} from "@lodestar/types";
import {ForkName} from "@lodestar/params";
import {ACTIVE_PRESET, ForkName} from "@lodestar/params";
import {bnToNum} from "@lodestar/utils";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {expectEqualBeaconState, inputTypeSszTreeViewDU} from "../utils/expectEqualBeaconState.js";
import {shouldVerify, TestRunnerFn} from "../utils/types.js";
import {RunnerType, shouldVerify, TestRunnerFn} from "../utils/types.js";
import {getConfig} from "../../utils/config.js";
import {assertCorrectProgressiveBalances} from "../config.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
/* eslint-disable @typescript-eslint/naming-convention */
export const sanity: TestRunnerFn<any, BeaconStateAllForks> = (fork, testName, testSuite) => {
const sanity: TestRunnerFn<any, BeaconStateAllForks> = (fork, testName, testSuite) => {
switch (testName) {
case "slots":
return sanitySlots(fork, testName, testSuite);
@@ -55,7 +58,7 @@ const sanitySlots: TestRunnerFn<SanitySlotsTestCase, BeaconStateAllForks> = (for
};
};
export const sanityBlocks: TestRunnerFn<SanityBlocksTestCase, BeaconStateAllForks> = (fork) => {
const sanityBlocks: TestRunnerFn<SanityBlocksTestCase, BeaconStateAllForks> = (fork) => {
return {
testFunction: (testcase) => {
const stateTB = testcase.pre;
@@ -119,3 +122,8 @@ type SanitySlotsTestCase = {
post?: BeaconStateAllForks;
slots: bigint;
};
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
sanity: {type: RunnerType.default, fn: sanity},
random: {type: RunnerType.default, fn: sanityBlocks},
});

View File

@@ -1,9 +1,13 @@
import path from "node:path";
import {unshuffleList} from "@lodestar/state-transition";
import {InputType} from "@lodestar/spec-test-util";
import {bnToNum, fromHex} from "@lodestar/utils";
import {TestRunnerFn} from "../utils/types.js";
import {ACTIVE_PRESET} from "@lodestar/params";
import {RunnerType, TestRunnerFn} from "../utils/types.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
export const shuffling: TestRunnerFn<ShufflingTestCase, number[]> = () => {
const shuffling: TestRunnerFn<ShufflingTestCase, number[]> = () => {
return {
testFunction: (testcase) => {
const seed = fromHex(testcase.mapping.seed);
@@ -28,3 +32,7 @@ type ShufflingTestCase = {
mapping: bigint[];
};
};
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
shuffling: {type: RunnerType.default, fn: shuffling},
});

View File

@@ -6,6 +6,9 @@ import {ACTIVE_PRESET, ForkName, ForkLightClient} from "@lodestar/params";
import {replaceUintTypeWithUintBigintType} from "../utils/replaceUintTypeWithUintBigintType.js";
import {parseSszStaticTestcase} from "../utils/sszTestCaseParser.js";
import {runValidSszTest} from "../utils/runValidSszTest.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
import {RunnerType} from "../utils/types.js";
// ssz_static
// | Attestation
@@ -26,7 +29,7 @@ type Types = Record<string, Type<any>>;
// tests / mainnet / altair / ssz_static / Validator / ssz_random / case_0/roots.yaml
//
export const sszStatic =
const sszStatic =
(skippedTypes?: string[]) =>
(fork: ForkName, typeName: string, testSuite: string, testSuiteDirpath: string): void => {
// Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts
@@ -63,3 +66,11 @@ export const sszStatic =
});
}
};
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
// eslint-disable-next-line @typescript-eslint/naming-convention
ssz_static: {
type: RunnerType.custom,
fn: sszStatic(),
},
});

View File

@@ -1,3 +1,4 @@
import path from "node:path";
import {
BeaconStateAllForks,
DataAvailableStatus,
@@ -6,16 +7,18 @@ import {
} from "@lodestar/state-transition";
import {allForks, ssz} from "@lodestar/types";
import {createChainForkConfig, ChainConfig} from "@lodestar/config";
import {ForkName} from "@lodestar/params";
import {ACTIVE_PRESET, ForkName} from "@lodestar/params";
import {bnToNum} from "@lodestar/utils";
import {config} from "@lodestar/config/default";
import {expectEqualBeaconState, inputTypeSszTreeViewDU} from "../utils/expectEqualBeaconState.js";
import {createCachedBeaconStateTest} from "../../utils/cachedBeaconState.js";
import {TestRunnerFn} from "../utils/types.js";
import {RunnerType, TestRunnerFn} from "../utils/types.js";
import {assertCorrectProgressiveBalances} from "../config.js";
import {getPreviousFork} from "./fork.js";
import {ethereumConsensusSpecsTests} from "../specTestVersioning.js";
import {specTestIterator} from "../utils/specTestIterator.js";
import {getPreviousFork} from "./fork.test.js";
export const transition =
const transition =
(skipTestNames?: string[]): TestRunnerFn<TransitionTestCase, BeaconStateAllForks> =>
(forkNext) => {
if (forkNext === ForkName.phase0) {
@@ -116,3 +119,10 @@ type TransitionTestCase = {
pre: BeaconStateAllForks;
post: BeaconStateAllForks;
};
specTestIterator(path.join(ethereumConsensusSpecsTests.outputDir, "tests", ACTIVE_PRESET), {
transition: {
type: RunnerType.default,
fn: transition(),
},
});

View File

@@ -19,6 +19,53 @@ export interface SkipOpts {
skippedHandlers?: string[];
}
/**
* Because we want to execute the spec tests in parallel so one or two runners will be executed
* in isolation at a time and would not be available how many runners are there in total.
* This list is curated manually and should be updated when new runners are added.
* It will make sure if specs introduce new runner, we should cover in our spec tests.
*/
const coveredTestRunners = [
"light_client",
"epoch_processing",
"finality",
"fork",
"fork_choice",
"sync",
"fork",
"genesis",
"merkle",
"operations",
"rewards",
"sanity",
"random",
"shuffling",
"ssz_static",
"transition",
];
// NOTE: You MUST always provide a detailed reason of why a spec test is skipped plus link
// to an issue marking it as pending to re-enable and an aproximate timeline of when it will
// be fixed.
// NOTE: Comment the minimum set of test necessary to unblock PRs: For example, instead of
// skipping all `bls_to_execution_change` tests, just skip for a fork setting:
// ```
// skippedPrefixes: [
// // Skipped since this only test that withdrawals are de-activated
// "eip4844/operations/bls_to_execution_change",
// ],
// ```
export const defaultSkipOpts: SkipOpts = {
skippedForks: ["eip6110"],
// TODO: capella
// BeaconBlockBody proof in lightclient is the new addition in v1.3.0-rc.2-hotfix
// Skip them for now to enable subsequently
skippedPrefixes: [
"capella/light_client/single_merkle_proof/BeaconBlockBody",
"deneb/light_client/single_merkle_proof/BeaconBlockBody",
],
};
/**
* This helper ensures that strictly all tests are run. There's no hardcoded value beyond "config".
* Any additional unknown fork, testRunner, testHandler, or testSuite will result in an error.
@@ -48,7 +95,7 @@ export interface SkipOpts {
export function specTestIterator(
configDirpath: string,
testRunners: Record<string, TestRunner>,
opts?: SkipOpts
opts: SkipOpts = defaultSkipOpts
): void {
for (const forkStr of readdirSyncSpec(configDirpath)) {
if (opts?.skippedForks?.includes(forkStr)) {
@@ -65,6 +112,17 @@ export function specTestIterator(
const testRunnerDirpath = path.join(forkDirpath, testRunnerName);
const testRunner = testRunners[testRunnerName];
if (testRunner === undefined && coveredTestRunners.includes(testRunnerName)) {
// That runner is not part of the current call to specTestIterator
continue;
}
if (testRunner === undefined && !coveredTestRunners.includes(testRunnerName)) {
throw new Error(
`No test runner for ${testRunnerName}. Please make sure it is covered in "coveredTestRunners" if you added new runner.`
);
}
for (const testHandler of readdirSyncSpec(testRunnerDirpath)) {
if (opts?.skippedHandlers?.includes(testHandler)) {
continue;
@@ -78,8 +136,6 @@ export function specTestIterator(
displaySkipTest(testId);
} else if (fork === undefined) {
displayFailTest(testId, `Unknown fork ${forkStr}`);
} else if (testRunner === undefined) {
displayFailTest(testId, `No test runner for ${testRunnerName}`);
} else {
const testSuiteDirpath = path.join(testHandlerDirpath, testSuite);
// Specific logic for ssz_static since it has one extra level of directories

View File

@@ -32,7 +32,7 @@
"lint:fix": "yarn run lint --fix",
"pretest": "yarn run check-types",
"test:unit": "nyc --cache-dir .nyc_output/.cache -e .ts mocha 'test/unit/**/*.test.ts'",
"test:e2e": "mocha --timeout 30000 'test/e2e/**/*.test.ts'",
"test:e2e": "LODESTAR_PRESET=minimal mocha --timeout 30000 'test/e2e/**/*.test.ts'",
"test:sim:multifork": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/multi_fork.test.ts",
"test:sim:mixedclient": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/mixed_client.test.ts",
"test:sim:endpoints": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/endpoints.test.ts",

View File

@@ -3,7 +3,7 @@ import {ForkName, SLOTS_PER_EPOCH, DOMAIN_VOLUNTARY_EXIT} from "@lodestar/params
import {DomainType, ForkDigest, phase0, Root, Slot, ssz, Version} from "@lodestar/types";
import {ChainForkConfig} from "../beaconConfig.js";
import {ForkDigestHex, CachedGenesis} from "./types.js";
export {ForkDigestContext} from "./types.js";
export type {ForkDigestContext} from "./types.js";
export function createCachedGenesis(chainForkConfig: ChainForkConfig, genesisValidatorsRoot: Root): CachedGenesis {
const domainCache = new Map<ForkName, Map<DomainType, Uint8Array>>();

View File

@@ -1,3 +1,3 @@
export {Db, DbReqOpts, DatabaseController, FilterOptions, KeyValue} from "./interface.js";
export type {Db, DbReqOpts, DatabaseController, FilterOptions, KeyValue} from "./interface.js";
export {LevelDbController} from "./level.js";
export {LevelDbControllerMetrics} from "./metrics.js";
export type {LevelDbControllerMetrics} from "./metrics.js";

View File

@@ -1,28 +1,33 @@
export {ProtoArray} from "./protoArray/protoArray.js";
export {
export type {
ProtoBlock,
ProtoNode,
ExecutionStatus,
MaybeValidExecutionStatus,
BlockExecution,
LVHValidResponse,
LVHInvalidResponse,
} from "./protoArray/interface.js";
export {ExecutionStatus} from "./protoArray/interface.js";
export {ForkChoice, ForkChoiceOpts, assertValidTerminalPowBlock} from "./forkChoice/forkChoice.js";
export {ForkChoice, type ForkChoiceOpts, assertValidTerminalPowBlock} from "./forkChoice/forkChoice.js";
export {
IForkChoice,
PowBlockHex,
type IForkChoice,
type PowBlockHex,
EpochDifference,
AncestorResult,
type AncestorResult,
AncestorStatus,
ForkChoiceMetrics,
type ForkChoiceMetrics,
} from "./forkChoice/interface.js";
export {ForkChoiceStore, IForkChoiceStore, CheckpointWithHex, JustifiedBalancesGetter} from "./forkChoice/store.js";
export {
InvalidAttestation,
ForkChoiceStore,
type IForkChoiceStore,
type CheckpointWithHex,
type JustifiedBalancesGetter,
} from "./forkChoice/store.js";
export {
type InvalidAttestation,
InvalidAttestationCode,
InvalidBlock,
type InvalidBlock,
InvalidBlockCode,
ForkChoiceError,
ForkChoiceErrorCode,

View File

@@ -18,7 +18,7 @@ import {LightClientTransport} from "./transport/interface.js";
// Re-export types
export {LightclientEvent} from "./events.js";
export {SyncCommitteeFast} from "./types.js";
export type {SyncCommitteeFast} from "./types.js";
export {upgradeLightClientFinalityUpdate, upgradeLightClientOptimisticUpdate} from "./spec/utils.js";
export type GenesisData = {

View File

@@ -6,7 +6,8 @@ import {getSyncCommitteeAtPeriod, processLightClientUpdate, ProcessUpdateOpts} f
import {ILightClientStore, LightClientStore, LightClientStoreEvents} from "./store.js";
import {ZERO_FINALITY_BRANCH, ZERO_HEADER, ZERO_NEXT_SYNC_COMMITTEE_BRANCH, ZERO_SYNC_COMMITTEE} from "./utils.js";
export {isBetterUpdate, toLightClientUpdateSummary, LightClientUpdateSummary} from "./isBetterUpdate.js";
export {isBetterUpdate, toLightClientUpdateSummary} from "./isBetterUpdate.js";
export type {LightClientUpdateSummary} from "./isBetterUpdate.js";
export {upgradeLightClientHeader} from "./utils.js";
export class LightclientSpec {

View File

@@ -58,7 +58,7 @@
"pretest": "yarn run check-types",
"test:unit": "mocha 'test/unit/**/*.test.ts'",
"test:browsers": "yarn karma start karma.config.cjs",
"test:e2e": "mocha 'test/e2e/**/*.test.ts'",
"test:e2e": "LODESTAR_PRESET=minimal mocha 'test/e2e/**/*.test.ts'",
"check-readme": "typescript-docs-verifier"
},
"types": "lib/index.d.ts",

View File

@@ -2,7 +2,8 @@
import {LEVEL, MESSAGE} from "triple-beam";
import {LogLevel, Logger, LogHandler, LogData} from "@lodestar/utils";
export {LogLevel, Logger, LogHandler, LogData, LEVEL, MESSAGE};
export {LogLevel, LEVEL, MESSAGE};
export type {Logger, LogHandler, LogData};
export const logLevelNum: {[K in LogLevel]: number} = {
[LogLevel.error]: 0,

View File

@@ -55,7 +55,7 @@
"test": "yarn run check-types",
"test:unit": "mocha 'test/unit/**/*.test.ts'",
"test:browsers": "yarn karma start karma.config.cjs",
"test:e2e": "mocha 'test/e2e/**/*.test.ts'",
"test:e2e": "LODESTAR_PRESET=minimal mocha 'test/e2e/**/*.test.ts'",
"check-readme": "typescript-docs-verifier"
},
"repository": {

View File

@@ -5,18 +5,9 @@ import {gnosisPreset} from "./presets/gnosis.js";
import {presetStatus} from "./presetStatus.js";
import {userSelectedPreset, userOverrides} from "./setPreset.js";
export {BeaconPreset} from "./types.js";
export {
ForkName,
ForkSeq,
ForkLightClient,
ForkExecution,
ForkBlobs,
isForkExecution,
isForkWithdrawals,
isForkBlobs,
isForkLightClient,
} from "./forkName.js";
export type {BeaconPreset} from "./types.js";
export type {ForkLightClient, ForkExecution, ForkBlobs} from "./forkName.js";
export {ForkName, ForkSeq, isForkExecution, isForkWithdrawals, isForkBlobs, isForkLightClient} from "./forkName.js";
export {presetToJson} from "./json.js";
export {PresetName};

View File

@@ -24,6 +24,9 @@ describe("Override preset", function () {
this.timeout(30_000);
it("Should correctly override preset", async () => {
// These commands can not run with minimal preset
if (process.env.LODESTAR_PRESET === "minimal") delete process.env.LODESTAR_PRESET;
await exec(`node --loader ts-node/esm ${path.join(__dirname, scriptNames.ok)}`);
});

View File

@@ -24,6 +24,9 @@ describe("setPreset", function () {
this.timeout(30_000);
it("Should correctly set preset", async () => {
// These commands can not run with minimal preset
if (process.env.LODESTAR_PRESET === "minimal") delete process.env.LODESTAR_PRESET;
await exec(`node --loader ts-node/esm ${path.join(__dirname, scriptNames.ok)}`);
});

View File

@@ -5,7 +5,7 @@ import {ProofProvider} from "./proof_provider/proof_provider.js";
import {JsonRpcRequest, JsonRpcRequestOrBatch, JsonRpcResponse, JsonRpcResponseOrBatch} from "./types.js";
import {ELRpc} from "./utils/rpc.js";
export {NetworkName} from "@lodestar/config/networks";
export type {NetworkName} from "@lodestar/config/networks";
export enum LCTransport {
Rest = "Rest",
P2P = "P2P",

View File

@@ -49,7 +49,7 @@
"lint": "eslint --color --ext .ts src/ test/",
"lint:fix": "yarn run lint --fix",
"pretest": "yarn run check-types",
"test": "yarn test:unit && yarn test:e2e",
"test": "yarn test:unit",
"test:unit": "nyc --cache-dir .nyc_output/.cache -e .ts mocha 'test/unit/**/*.test.ts'",
"check-readme": "typescript-docs-verifier"
},

View File

@@ -1,5 +1,7 @@
export {ReqResp, ReqRespOpts} from "./ReqResp.js";
export {getMetrics, Metrics, MetricsRegister} from "./metrics.js";
export {ReqResp} from "./ReqResp.js";
export type {ReqRespOpts} from "./ReqResp.js";
export {getMetrics} from "./metrics.js";
export type {Metrics, MetricsRegister} from "./metrics.js";
export {Encoding as ReqRespEncoding} from "./types.js"; // Expose enums renamed
export * from "./types.js";
export * from "./interface.js";

View File

@@ -2,9 +2,9 @@ export * from "./stateTransition.js";
export * from "./constants/index.js";
export * from "./util/index.js";
export * from "./signatureSets/index.js";
export {BeaconStateTransitionMetrics} from "./metrics.js";
export type {BeaconStateTransitionMetrics} from "./metrics.js";
export {
export type {
CachedBeaconStatePhase0,
CachedBeaconStateAltair,
CachedBeaconStateBellatrix,
@@ -25,25 +25,25 @@ export {
// Main state caches
export {
createCachedBeaconState,
BeaconStateCache,
type BeaconStateCache,
isCachedBeaconState,
isStateBalancesNodesPopulated,
isStateValidatorsNodesPopulated,
} from "./cache/stateCache.js";
export {
EpochCache,
EpochCacheImmutableData,
type EpochCacheImmutableData,
createEmptyEpochCacheImmutableData,
EpochCacheError,
EpochCacheErrorCode,
} from "./cache/epochCache.js";
export {EpochTransitionCache, beforeProcessEpoch} from "./cache/epochTransitionCache.js";
export {type EpochTransitionCache, beforeProcessEpoch} from "./cache/epochTransitionCache.js";
// Aux data-structures
export {PubkeyIndexMap, Index2PubkeyCache} from "./cache/pubkeyCache.js";
export {PubkeyIndexMap, type Index2PubkeyCache} from "./cache/pubkeyCache.js";
export {
EffectiveBalanceIncrements,
type EffectiveBalanceIncrements,
getEffectiveBalanceIncrementsZeroed,
getEffectiveBalanceIncrementsWithLen,
} from "./cache/effectiveBalanceIncrements.js";
@@ -53,7 +53,7 @@ export {isValidVoluntaryExit} from "./block/processVoluntaryExit.js";
export {isValidBlsToExecutionChange} from "./block/processBlsToExecutionChange.js";
export {assertValidProposerSlashing} from "./block/processProposerSlashing.js";
export {assertValidAttesterSlashing} from "./block/processAttesterSlashing.js";
export {ExecutionPayloadStatus, DataAvailableStatus, BlockExternalData} from "./block/externalData.js";
export {ExecutionPayloadStatus, DataAvailableStatus, type BlockExternalData} from "./block/externalData.js";
// BeaconChain, to prepare new blocks
export {becomesNewEth1Data} from "./block/processEth1Data.js";

View File

@@ -1,7 +1,7 @@
export {EpochCache} from "./cache/epochCache.js";
export {EpochTransitionCache} from "./cache/epochTransitionCache.js";
export type {EpochTransitionCache} from "./cache/epochTransitionCache.js";
export {
export type {
CachedBeaconStateAllForks,
CachedBeaconStateExecutions,
CachedBeaconStatePhase0,
@@ -11,7 +11,7 @@ export {
CachedBeaconStateDeneb,
} from "./cache/stateCache.js";
export {
export type {
BeaconStateAllForks,
BeaconStateExecutions,
BeaconStatePhase0,

View File

@@ -1,7 +1,7 @@
import type {Suite} from "mocha";
import {Logger} from "@lodestar/utils";
import {TestContext} from "./interfaces.js";
export {TestContext} from "./interfaces.js";
export type {TestContext} from "./interfaces.js";
/**
* Create a Mocha context object that can be used to register callbacks that will be executed

View File

@@ -9,12 +9,12 @@ export * from "./logger.js";
export * from "./map.js";
export * from "./math.js";
export * from "./objects.js";
export {retry, RetryOptions} from "./retry.js";
export {retry, type RetryOptions} from "./retry.js";
export * from "./notNullish.js";
export * from "./sleep.js";
export * from "./sort.js";
export * from "./timeout.js";
export {RecursivePartial, bnToNum} from "./types.js";
export {type RecursivePartial, bnToNum} from "./types.js";
export * from "./validation.js";
export * from "./verifyMerkleBranch.js";
export * from "./promise.js";

View File

@@ -32,7 +32,7 @@
"test": "yarn test:unit",
"test:e2e:only": "mocha 'test/e2e/**/*.test.ts'",
"test:spec": "mocha 'test/spec/**/*.test.ts'",
"test:e2e": "yarn run download-spec-tests && yarn test:spec && yarn test:e2e:only",
"test:e2e": "LODESTAR_PRESET=minimal yarn run download-spec-tests && yarn test:spec && yarn test:e2e:only",
"download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts",
"coverage": "codecov -F lodestar-validator",
"check-readme": "typescript-docs-verifier"

View File

@@ -1,17 +1,14 @@
export {Validator, ValidatorOptions} from "./validator.js";
export {
ValidatorStore,
SignerType,
export {Validator, type ValidatorOptions} from "./validator.js";
export {ValidatorStore, SignerType, defaultOptions, BuilderSelection} from "./services/validatorStore.js";
export type {
Signer,
SignerLocal,
SignerRemote,
ValidatorProposerConfig,
defaultOptions,
ProposerConfig,
BuilderSelection,
} from "./services/validatorStore.js";
export {waitForGenesis} from "./genesis.js";
export {getMetrics, Metrics, MetricsRegister} from "./metrics.js";
export {getMetrics, type Metrics, type MetricsRegister} from "./metrics.js";
// Remote signer client
export {
@@ -21,7 +18,7 @@ export {
} from "./util/externalSignerClient.js";
// Types
export {ProcessShutdownCallback} from "./types.js";
export type {ProcessShutdownCallback} from "./types.js";
export * from "./slashingProtection/index.js";
export * from "./repositories/index.js";

View File

@@ -22,8 +22,9 @@ import {SlashingProtectionBlock, SlashingProtectionAttestation} from "./types.js
export {InvalidAttestationError, InvalidAttestationErrorCode} from "./attestation/index.js";
export {InvalidBlockError, InvalidBlockErrorCode} from "./block/index.js";
export {InterchangeError, InterchangeErrorErrorCode, Interchange, InterchangeFormat} from "./interchange/index.js";
export {ISlashingProtection, InterchangeFormatVersion, SlashingProtectionBlock, SlashingProtectionAttestation};
export {InterchangeError, InterchangeErrorErrorCode} from "./interchange/index.js";
export type {Interchange, InterchangeFormat} from "./interchange/index.js";
export type {ISlashingProtection, InterchangeFormatVersion, SlashingProtectionBlock, SlashingProtectionAttestation};
/**
* Handles slashing protection for validator proposer and attester duties as well as slashing protection
* during a validator interchange import/export process.

View File

@@ -24,5 +24,8 @@
"declarationMap": true,
"incremental": true,
"preserveWatchOutput": true
},
"ts-node": {
"transpileOnly": true
}
}

View File

@@ -7,6 +7,14 @@
"typeRoots": ["node_modules/@types", "./types"],
"noEmit": true,
// To be used in the test fixtures
"resolveJsonModule": true
"resolveJsonModule": true,
// We want to speed up the CI run for all tests, which require us to use the
// `transpileOnly` mode for the `ts-node`. This change requires to treat types for each module
// independently, which is done by setting the `isolatedModules` flag to `true`.
"isolatedModules": true,
},
"ts-node": {
"transpileOnly": true
}
}

View File

@@ -5019,6 +5019,11 @@ commander@^2.20.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commander@^9.3.0:
version "9.5.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30"
integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==
commander@~2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
@@ -13801,6 +13806,15 @@ void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==
wait-port@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/wait-port/-/wait-port-1.0.4.tgz#6f9474645ddbf7701ac100ab6762438edf6e5689"
integrity sha512-w8Ftna3h6XSFWWc2JC5gZEgp64nz8bnaTp5cvzbJSZ53j+omktWTDdwXxEF0jM8YveviLgFWvNGrSvRHnkyHyw==
dependencies:
chalk "^4.1.2"
commander "^9.3.0"
debug "^4.3.4"
walk-up-path@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e"