From 01d47b9a0901c9f03a01ef68c819f4e592cbfd8b Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 25 Jan 2024 02:00:48 -0800 Subject: [PATCH 01/71] chore: align test scripts (#6339) * chore: align yarn test scripts * fix: handle prover stratup failure * fix: lint * chore: improve test guide * chore: introduce top level download-spec-tests script * chore: remove pretest scripts --- CONTRIBUTING.md | 8 ++++++++ package.json | 1 + packages/api/package.json | 3 +-- packages/beacon-node/package.json | 1 - packages/cli/package.json | 1 - packages/config/package.json | 2 +- packages/db/package.json | 1 - packages/flare/package.json | 2 +- packages/fork-choice/package.json | 1 - packages/light-client/package.json | 3 +-- packages/logger/package.json | 2 +- packages/params/package.json | 2 +- packages/prover/package.json | 1 - packages/prover/test/e2e/cli/cmds/start.test.ts | 6 ++++-- packages/reqresp/package.json | 1 - packages/spec-test-util/package.json | 2 +- packages/state-transition/package.json | 1 + packages/test-utils/package.json | 1 - packages/types/package.json | 1 + packages/utils/package.json | 1 - packages/validator/package.json | 3 +-- 21 files changed, 23 insertions(+), 21 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4e67c4d226b..4074c47e88e8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,6 +32,14 @@ To run tests: - :test_tube: Run `yarn check-types` to check TypeScript types. - :test_tube: Run `yarn lint` to run the linter (ESLint). +Note that to run `test:e2e`, first ensure that the environment is correctly setup by running the `run_e2e_env.sh` script. + +```sh +GETH_DOCKER_IMAGE=ethereum/client-go:v1.11.6 NETHERMIND_DOCKER_IMAGE=nethermind/nethermind:1.18.0 ./scripts/run_e2e_env.sh start +``` + +Similarly, run `yarn download-spec-tests` before running `yarn test:spec`. + Contributing to tests: - Test must not depend on external live resources, such that running tests for a commit must be deterministic: diff --git a/package.json b/package.json index 93b364359a38..5d7a90f27e6f 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "test:browsers": "lerna run test:browsers", "test:e2e": "lerna run test:e2e --concurrency 1", "test:e2e:sim": "lerna run test:e2e:sim", + "download-spec-tests": "lerna run download-spec-tests", "test:spec": "lerna run test:spec", "test-coverage:unit": "c8 --config .c8rc.json --report-dir coverage/unit/ --all npm run test:unit", "test-coverage:browsers": "c8 --config .c8rc.json --report-dir coverage/browsers/ --all npm run test:browsers", diff --git a/packages/api/package.json b/packages/api/package.json index e1a52c47b489..0aa48470296d 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -63,8 +63,7 @@ "coverage": "codecov -F lodestar-api", "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": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 3ddde8540670..7b1bf0206011 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -75,7 +75,6 @@ "coverage": "codecov -F lodestar", "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:unit:minimal": "vitest --run --segfaultRetry 3 --dir test/unit/", "test:unit:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/unit-mainnet", diff --git a/packages/cli/package.json b/packages/cli/package.json index 243dee688417..368637c8983a 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -30,7 +30,6 @@ "docs:build": "node --loader ts-node/esm ./docsgen/index.ts", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", "test:unit": "vitest --run --dir test/unit/", "test:e2e": "vitest --run --config vitest.config.e2e.ts --dir test/e2e/", "test:sim:multifork": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/multi_fork.test.ts", diff --git a/packages/config/package.json b/packages/config/package.json index 3b0a649e78c5..12c16f383fa8 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -49,7 +49,7 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", + "test": "yarn test:unit", "test:unit": "yarn vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, diff --git a/packages/db/package.json b/packages/db/package.json index d99b21d80b9b..64d499bd7fc1 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -31,7 +31,6 @@ "coverage": "codecov -F lodestar-fork-choice", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/flare/package.json b/packages/flare/package.json index 7417cf93c63d..8106e2b85c7f 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -43,7 +43,7 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", + "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, diff --git a/packages/fork-choice/package.json b/packages/fork-choice/package.json index 495c67a8e80b..6436a4299ff5 100644 --- a/packages/fork-choice/package.json +++ b/packages/fork-choice/package.json @@ -32,7 +32,6 @@ "coverage": "codecov -F lodestar-fork-choice", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/light-client/package.json b/packages/light-client/package.json index dee231409730..f09f4fdaffb9 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -57,8 +57,7 @@ "coverage": "codecov -F lodestar-light-client", "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": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/logger/package.json b/packages/logger/package.json index 2f450ee5be12..f5efd6587bb4 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -55,7 +55,7 @@ "check-types": "tsc", "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:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/params/package.json b/packages/params/package.json index 2586c73566aa..ae2bb4d66cc2 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -52,7 +52,7 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "test": "yarn run check-types", + "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/prover/package.json b/packages/prover/package.json index 05f7c33579b4..15066cfd81ce 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -51,7 +51,6 @@ "coverage": "codecov -F lodestar-api", "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:unit": "vitest --run --dir test/unit/", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", diff --git a/packages/prover/test/e2e/cli/cmds/start.test.ts b/packages/prover/test/e2e/cli/cmds/start.test.ts index da0c9dceb405..8888b3ce84d5 100644 --- a/packages/prover/test/e2e/cli/cmds/start.test.ts +++ b/packages/prover/test/e2e/cli/cmds/start.test.ts @@ -43,7 +43,7 @@ describe("prover/start", () => { }); describe("when started", () => { - let proc: childProcess.ChildProcess; + let proc: childProcess.ChildProcess | null = null; const paramsFilePath = path.join("/tmp", "e2e-test-env", "params.json"); const web3: Web3 = new Web3(proxyUrl); @@ -74,7 +74,9 @@ describe("prover/start", () => { }, 50000); afterAll(async () => { - await stopChildProcess(proc); + if (proc) { + await stopChildProcess(proc); + } }); it("should respond to verified calls", async () => { diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index c19af565c397..9ac7472cd6cf 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -48,7 +48,6 @@ "coverage": "codecov -F lodestar-api", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index 899d6438d939..5e6461863947 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -46,7 +46,7 @@ "check-types": "tsc", "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:unit": "vitest --run --passWithNoTests --dir test/unit/", "test:e2e": "vitest --run --config vitest.config.e2e.ts --dir test/e2e/", "check-readme": "typescript-docs-verifier" diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index cbde9b062177..acba374e6e64 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -52,6 +52,7 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", + "test": "yarn test:unit", "test:unit": "vitest --run --dir test/unit/", "check-readme": "typescript-docs-verifier" }, diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index d4a1df589e8f..b1aaf3b16a33 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -44,7 +44,6 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/types/package.json b/packages/types/package.json index b51acbef6801..4497098c14f4 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -61,6 +61,7 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", + "test": "yarn test:unit", "test:constants:minimal": "LODESTAR_PRESET=minimal vitest --run --dir test/constants/", "test:constants:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/constants/", "test:unit": "wrapper() { yarn test:constants:minimal $@ && yarn test:constants:mainnet $@ && vitest --run --dir test/unit/ $@; }; wrapper", diff --git a/packages/utils/package.json b/packages/utils/package.json index fcc0f5ac36c1..db3ed9e06986 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -30,7 +30,6 @@ "check-types": "tsc && vitest --run --typecheck --dir test/types/", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", "test:unit": "vitest --run --dir test/unit", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/validator/package.json b/packages/validator/package.json index 92c3e92d04a1..9b8fc03c942d 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -27,9 +27,8 @@ "check-types": "tsc", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", - "pretest": "yarn run check-types", "test:unit": "vitest --run --dir test/unit/", - "test": "yarn test:unit", + "test": "yarn test:unit && yarn test:e2e", "test:spec": "vitest --run --config vitest.config.spec.ts --dir test/spec/", "test:e2e": "LODESTAR_PRESET=mainnet vitest --run --config vitest.config.e2e.ts --dir test/e2e", "download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts", From 347c95fb0da219b5a4d551b7ce014f2ceda7ae48 Mon Sep 17 00:00:00 2001 From: g11tech Date: Fri, 26 Jan 2024 22:28:28 +0530 Subject: [PATCH 02/71] feat: allow builder boost factor to be configured via proposer config file (#6357) * feat: allow builder boost factor to be configured via proposer config file * reuse parseBuilderBoostFactor fn * re-shuffle fns and add builder selection validation --- packages/cli/src/cmds/validator/handler.ts | 29 +------------- packages/cli/src/util/proposerConfig.ts | 38 ++++++++++++++++++- .../validator/parseProposerConfig.test.ts | 3 ++ .../validator/proposerConfigs/validData.yaml | 2 + 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/packages/cli/src/cmds/validator/handler.ts b/packages/cli/src/cmds/validator/handler.ts index 91789c99ee3b..a98eb0755ad0 100644 --- a/packages/cli/src/cmds/validator/handler.ts +++ b/packages/cli/src/cmds/validator/handler.ts @@ -22,6 +22,7 @@ import {GlobalArgs} from "../../options/index.js"; import {YargsError, cleanOldLogFiles, getDefaultGraffiti, mkdir, parseLoggerArgs} from "../../util/index.js"; import {onGracefulShutdown, parseFeeRecipient, parseProposerConfig} from "../../util/index.js"; import {getVersionData} from "../../util/version.js"; +import {parseBuilderSelection, parseBuilderBoostFactor} from "../../util/proposerConfig.js"; import {getAccountPaths, getValidatorPaths} from "./paths.js"; import {IValidatorCliArgs, validatorMetricsDefaultOptions, validatorMonitoringDefaultOptions} from "./options.js"; import {getSignersFromArgs} from "./signers/index.js"; @@ -254,24 +255,6 @@ function getProposerConfigFromArgs( return valProposerConfig; } -function parseBuilderSelection(builderSelection?: string): routes.validator.BuilderSelection | undefined { - if (builderSelection) { - switch (builderSelection) { - case "maxprofit": - break; - case "builderalways": - break; - case "builderonly": - break; - case "executiononly": - break; - default: - throw new YargsError("Invalid input for builder selection, check help"); - } - } - return builderSelection as routes.validator.BuilderSelection; -} - function parseBroadcastValidation(broadcastValidation?: string): routes.beacon.BroadcastValidation | undefined { if (broadcastValidation) { switch (broadcastValidation) { @@ -286,13 +269,3 @@ function parseBroadcastValidation(broadcastValidation?: string): routes.beacon.B return broadcastValidation as routes.beacon.BroadcastValidation; } - -function parseBuilderBoostFactor(boostFactor?: string): bigint | undefined { - if (boostFactor === undefined) return; - - if (!/^\d+$/.test(boostFactor)) { - throw new YargsError("Invalid input for builder boost factor, must be a valid number without decimals"); - } - - return BigInt(boostFactor); -} diff --git a/packages/cli/src/util/proposerConfig.ts b/packages/cli/src/util/proposerConfig.ts index 2f3c71236255..661c81ee63af 100644 --- a/packages/cli/src/util/proposerConfig.ts +++ b/packages/cli/src/util/proposerConfig.ts @@ -8,6 +8,7 @@ import {routes} from "@lodestar/api"; import {parseFeeRecipient} from "./feeRecipient.js"; import {readFile} from "./file.js"; +import {YargsError} from "./index.js"; type ProposerConfig = ValidatorProposerConfig["defaultConfig"]; @@ -20,6 +21,7 @@ type ProposerConfigFileSection = { // for js-yaml gas_limit?: number; selection?: routes.validator.BuilderSelection; + boost_factor?: bigint; }; }; @@ -57,7 +59,7 @@ function parseProposerConfigSection( overrideConfig?: ProposerConfig ): ProposerConfig { const {graffiti, strict_fee_recipient_check, fee_recipient, builder} = proposerFileSection; - const {gas_limit, selection: builderSelection} = builder || {}; + const {gas_limit, selection: builderSelection, boost_factor} = builder || {}; if (graffiti !== undefined && typeof graffiti !== "string") { throw Error("graffiti is not 'string"); @@ -79,6 +81,9 @@ function parseProposerConfigSection( throw Error("(Number.isNaN(Number(gas_limit)) 2"); } } + if (boost_factor !== undefined && typeof boost_factor !== "string") { + throw Error("boost_factor is not 'string"); + } return { graffiti: overrideConfig?.graffiti ?? graffiti, @@ -88,7 +93,8 @@ function parseProposerConfigSection( feeRecipient: overrideConfig?.feeRecipient ?? (fee_recipient ? parseFeeRecipient(fee_recipient) : undefined), builder: { gasLimit: overrideConfig?.builder?.gasLimit ?? (gas_limit !== undefined ? Number(gas_limit) : undefined), - selection: overrideConfig?.builder?.selection ?? builderSelection, + selection: overrideConfig?.builder?.selection ?? parseBuilderSelection(builderSelection), + boostFactor: overrideConfig?.builder?.boostFactor ?? parseBuilderBoostFactor(boost_factor), }, }; } @@ -98,3 +104,31 @@ export function readProposerConfigDir(filepath: string, filename: string): Propo const proposerConfigJSON = JSON.parse(proposerConfigStr) as ProposerConfigFileSection; return proposerConfigJSON; } + +export function parseBuilderSelection(builderSelection?: string): routes.validator.BuilderSelection | undefined { + if (builderSelection) { + switch (builderSelection) { + case "maxprofit": + break; + case "builderalways": + break; + case "builderonly": + break; + case "executiononly": + break; + default: + throw new YargsError("Invalid input for builder selection, check help"); + } + } + return builderSelection as routes.validator.BuilderSelection; +} + +export function parseBuilderBoostFactor(boostFactor?: string): bigint | undefined { + if (boostFactor === undefined) return; + + if (!/^\d+$/.test(boostFactor)) { + throw new YargsError("Invalid input for builder boost factor, must be a valid number without decimals"); + } + + return BigInt(boostFactor); +} diff --git a/packages/cli/test/unit/validator/parseProposerConfig.test.ts b/packages/cli/test/unit/validator/parseProposerConfig.test.ts index fcb6933f035b..993d9640e47c 100644 --- a/packages/cli/test/unit/validator/parseProposerConfig.test.ts +++ b/packages/cli/test/unit/validator/parseProposerConfig.test.ts @@ -17,6 +17,7 @@ const testValue = { builder: { gasLimit: 30000000, selection: undefined, + boostFactor: undefined, }, }, "0xa4855c83d868f772a579133d9f23818008417b743e8447e235d8eb78b1d8f8a9f63f98c551beb7de254400f89592314d": { @@ -26,6 +27,7 @@ const testValue = { builder: { gasLimit: 35000000, selection: routes.validator.BuilderSelection.MaxProfit, + boostFactor: BigInt(18446744073709551616), }, }, }, @@ -36,6 +38,7 @@ const testValue = { builder: { gasLimit: 30000000, selection: routes.validator.BuilderSelection.BuilderAlways, + boostFactor: BigInt(100), }, }, }; diff --git a/packages/cli/test/unit/validator/proposerConfigs/validData.yaml b/packages/cli/test/unit/validator/proposerConfigs/validData.yaml index 6b7e7074b118..5ea7e1bebea7 100644 --- a/packages/cli/test/unit/validator/proposerConfigs/validData.yaml +++ b/packages/cli/test/unit/validator/proposerConfigs/validData.yaml @@ -10,6 +10,7 @@ proposer_config: builder: gas_limit: "35000000" selection: "maxprofit" + boost_factor: "18446744073709551616" default_config: graffiti: 'default graffiti' strict_fee_recipient_check: "true" @@ -17,3 +18,4 @@ default_config: builder: gas_limit: "30000000" selection: "builderalways" + boost_factor: "100" From 6adbd27c85f6fbb3a2a17ef4552274e985319c02 Mon Sep 17 00:00:00 2001 From: g11tech Date: Sat, 27 Jan 2024 22:37:49 +0530 Subject: [PATCH 03/71] fix: ignore forkchoice invalidations if latestValidHash not found (#6361) * fix: ignore forkchoice invalidations if latestValidHash not found * rename for better understanding * update the lvh search start index * apply feedback --- .../blocks/verifyBlocksExecutionPayloads.ts | 4 +- .../fork-choice/src/protoArray/interface.ts | 2 +- .../fork-choice/src/protoArray/protoArray.ts | 45 ++++++++++--------- .../protoArray/executionStatusUpdates.test.ts | 10 ++--- 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts index 5dbe104c9541..91242d879f85 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts @@ -319,7 +319,7 @@ export async function verifyBlockExecutionPayload( const lvhResponse = { executionStatus, latestValidExecHash: execResult.latestValidHash, - invalidateFromBlockHash: toHexString(block.message.parentRoot), + invalidateFromParentBlockRoot: toHexString(block.message.parentRoot), }; const execError = new BlockError(block, { code: BlockErrorCode.EXECUTION_ENGINE_ERROR, @@ -416,7 +416,7 @@ function getSegmentErrorResponse( invalidSegmentLVH = { executionStatus: ExecutionStatus.Invalid, latestValidExecHash: lvhResponse.latestValidExecHash, - invalidateFromBlockHash: parentBlock.blockRoot, + invalidateFromParentBlockRoot: parentBlock.blockRoot, }; } } diff --git a/packages/fork-choice/src/protoArray/interface.ts b/packages/fork-choice/src/protoArray/interface.ts index 1910ad2b4206..003a3c8f9f1e 100644 --- a/packages/fork-choice/src/protoArray/interface.ts +++ b/packages/fork-choice/src/protoArray/interface.ts @@ -29,7 +29,7 @@ export type LVHValidResponse = { export type LVHInvalidResponse = { executionStatus: ExecutionStatus.Invalid; latestValidExecHash: RootHex | null; - invalidateFromBlockHash: RootHex; + invalidateFromParentBlockRoot: RootHex; }; export type LVHExecResponse = LVHValidResponse | LVHInvalidResponse; diff --git a/packages/fork-choice/src/protoArray/protoArray.ts b/packages/fork-choice/src/protoArray/protoArray.ts index 62f50b03771c..eaa86b2f0ee1 100644 --- a/packages/fork-choice/src/protoArray/protoArray.ts +++ b/packages/fork-choice/src/protoArray/protoArray.ts @@ -279,32 +279,33 @@ export class ProtoArray { // Mark chain ii) as Invalid if LVH is found and non null, else only invalidate invalid_payload // if its in fcU. // - const {invalidateFromBlockHash, latestValidExecHash} = execResponse; - const invalidateFromIndex = this.indices.get(invalidateFromBlockHash); - if (invalidateFromIndex === undefined) { - throw Error(`Unable to find invalidateFromBlockHash=${invalidateFromBlockHash} in forkChoice`); + const {invalidateFromParentBlockRoot, latestValidExecHash} = execResponse; + const invalidateFromParentIndex = this.indices.get(invalidateFromParentBlockRoot); + if (invalidateFromParentIndex === undefined) { + throw Error(`Unable to find invalidateFromParentBlockRoot=${invalidateFromParentBlockRoot} in forkChoice`); } const latestValidHashIndex = - latestValidExecHash !== null ? this.getNodeIndexFromLVH(latestValidExecHash, invalidateFromIndex) : null; + latestValidExecHash !== null ? this.getNodeIndexFromLVH(latestValidExecHash, invalidateFromParentIndex) : null; if (latestValidHashIndex === null) { /** - * If the LVH is null or not found, represented with latestValidHashIndex=undefined, - * then just invalidate the invalid_payload and bug out. + * The LVH (latest valid hash) is null or not found. * - * Ideally in not found scenario we should invalidate the entire chain upwards, but - * it is possible (and observed in the testnets) that the EL was + * The spec gives an allowance for the EL being able to return a nullish LVH if it could not + * "determine" one. There are two interpretations: * - * i) buggy: that the LVH was not really the parent of the invalid block, but on - * some side chain - * ii) lazy: that invalidation was result of simple check and the EL just - * responded with a bogus LVH + * - "the LVH is unknown" - simply throw and move on. We can't determine which chain to invalidate + * since we don't know which ancestor is valid. * - * So we will just invalidate the current payload and let future responses take care - * to be as robust as possible. + * - "the LVH doesn't exist" - this means that the entire ancestor chain is invalid, and should + * be marked as such. + * + * The more robust approach is to treat nullish LVH as "the LVH is unknown" rather than + * "the LVH doesn't exist". The alternative means that we will poison a valid chain when the + * EL is lazy (or buggy) with its LVH response. */ - this.invalidateNodeByIndex(invalidateFromIndex); + throw Error(`Unable to find latestValidExecHash=${latestValidExecHash} in the forkchoice`); } else { - this.propagateInValidExecutionStatusByIndex(invalidateFromIndex, latestValidHashIndex, currentSlot); + this.propagateInValidExecutionStatusByIndex(invalidateFromParentIndex, latestValidHashIndex, currentSlot); } } } @@ -333,12 +334,12 @@ export class ProtoArray { */ private propagateInValidExecutionStatusByIndex( - invalidateFromIndex: number, + invalidateFromParentIndex: number, latestValidHashIndex: number, currentSlot: Slot ): void { - // Pass 1: mark invalidateFromIndex and its parents invalid - let invalidateIndex: number | undefined = invalidateFromIndex; + // Pass 1: mark invalidateFromParentIndex and its parents invalid + let invalidateIndex: number | undefined = invalidateFromParentIndex; while (invalidateIndex !== undefined && invalidateIndex > latestValidHashIndex) { const invalidNode = this.invalidateNodeByIndex(invalidateIndex); invalidateIndex = invalidNode.parent; @@ -368,8 +369,8 @@ export class ProtoArray { }); } - private getNodeIndexFromLVH(latestValidExecHash: RootHex, ancestorOfIndex: number): number | null { - let nodeIndex = this.nodes[ancestorOfIndex].parent; + private getNodeIndexFromLVH(latestValidExecHash: RootHex, ancestorFromIndex: number): number | null { + let nodeIndex: number | undefined = ancestorFromIndex; while (nodeIndex !== undefined && nodeIndex >= 0) { const node = this.getNodeFromIndex(nodeIndex); if ( diff --git a/packages/fork-choice/test/unit/protoArray/executionStatusUpdates.test.ts b/packages/fork-choice/test/unit/protoArray/executionStatusUpdates.test.ts index 94e5cd3ac9a0..e6916f24800f 100644 --- a/packages/fork-choice/test/unit/protoArray/executionStatusUpdates.test.ts +++ b/packages/fork-choice/test/unit/protoArray/executionStatusUpdates.test.ts @@ -149,7 +149,7 @@ describe("executionStatus / normal updates", () => { { executionStatus: ExecutionStatus.Invalid, latestValidExecHash: "2C", - invalidateFromBlockHash: "3C", + invalidateFromParentBlockRoot: "3C", }, 3 ); @@ -212,7 +212,7 @@ describe("executionStatus / normal updates", () => { { executionStatus: ExecutionStatus.Invalid, latestValidExecHash: "1A", - invalidateFromBlockHash: "3A", + invalidateFromParentBlockRoot: "3A", }, 3 ); @@ -259,7 +259,7 @@ describe("executionStatus / invalidate all postmerge chain", () => { { executionStatus: ExecutionStatus.Invalid, latestValidExecHash: "0x0000000000000000000000000000000000000000000000000000000000000000", - invalidateFromBlockHash: "3B", + invalidateFromParentBlockRoot: "3B", }, 3 ); @@ -336,7 +336,7 @@ describe("executionStatus / poision forkchoice if we invalidate previous valid", { executionStatus: ExecutionStatus.Invalid, latestValidExecHash: "0x0000000000000000000000000000000000000000000000000000000000000000", - invalidateFromBlockHash: "3A", + invalidateFromParentBlockRoot: "3A", }, 3 ) @@ -373,7 +373,7 @@ describe("executionStatus / poision forkchoice if we validate previous invalid", { executionStatus: ExecutionStatus.Invalid, latestValidExecHash: "0x0000000000000000000000000000000000000000000000000000000000000000", - invalidateFromBlockHash: "3B", + invalidateFromParentBlockRoot: "3B", }, 3 ); From 291e17867becb3884fe502542bcede5bae1fc5b1 Mon Sep 17 00:00:00 2001 From: Matthew Keil Date: Mon, 29 Jan 2024 01:55:48 -0500 Subject: [PATCH 04/71] feat: add down-scoring for metadata ssz size error (#6366) --- packages/beacon-node/src/network/reqresp/score.ts | 1 + packages/reqresp/src/request/errors.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/beacon-node/src/network/reqresp/score.ts b/packages/beacon-node/src/network/reqresp/score.ts index 6aca573a9ca9..c74b645c9909 100644 --- a/packages/beacon-node/src/network/reqresp/score.ts +++ b/packages/beacon-node/src/network/reqresp/score.ts @@ -24,6 +24,7 @@ export function onOutgoingReqRespError(e: RequestError, method: ReqRespMethod): switch (e.type.code) { case RequestErrorCode.INVALID_REQUEST: case RequestErrorCode.INVALID_RESPONSE_SSZ: + case RequestErrorCode.SSZ_OVER_MAX_SIZE: return PeerAction.LowToleranceError; case RequestErrorCode.SERVER_ERROR: diff --git a/packages/reqresp/src/request/errors.ts b/packages/reqresp/src/request/errors.ts index ccc3c12f97a1..0078ad5d2ecf 100644 --- a/packages/reqresp/src/request/errors.ts +++ b/packages/reqresp/src/request/errors.ts @@ -31,6 +31,8 @@ export enum RequestErrorCode { RESP_TIMEOUT = "REQUEST_ERROR_RESP_TIMEOUT", /** Request rate limited */ REQUEST_RATE_LIMITED = "REQUEST_ERROR_RATE_LIMITED", + /** */ + SSZ_OVER_MAX_SIZE = "SSZ_SNAPPY_ERROR_OVER_SSZ_MAX_SIZE", } type RequestErrorType = @@ -47,7 +49,8 @@ type RequestErrorType = | {code: RequestErrorCode.EMPTY_RESPONSE} | {code: RequestErrorCode.TTFB_TIMEOUT} | {code: RequestErrorCode.RESP_TIMEOUT} - | {code: RequestErrorCode.REQUEST_RATE_LIMITED}; + | {code: RequestErrorCode.REQUEST_RATE_LIMITED} + | {code: RequestErrorCode.SSZ_OVER_MAX_SIZE}; export const REQUEST_ERROR_CLASS_NAME = "RequestError"; From cbf349c73d7730c11d7295c27a61fbf36225df52 Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 29 Jan 2024 00:53:35 -0800 Subject: [PATCH 05/71] feat: blob sidecars can be filtered by indices (#6337) * feat: blob sidecars can be filtered by indices * fix: properly filter blobs * fix: type indices as number * chore: remove use of set * fix: make stringify more robust * Update packages/beacon-node/src/api/impl/beacon/blocks/index.ts Co-authored-by: Nico Flaig * fix: cleanup * fix: remove useless types --------- Co-authored-by: Nico Flaig --- .../api/src/beacon/routes/beacon/block.ts | 19 ++++++++++++++++--- .../api/test/unit/beacon/oapiSpec.test.ts | 6 ------ .../api/test/unit/beacon/testData/beacon.ts | 2 +- packages/api/test/utils/checkAgainstSpec.ts | 15 ++++++++++++--- .../src/api/impl/beacon/blocks/index.ts | 5 +++-- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/packages/api/src/beacon/routes/beacon/block.ts b/packages/api/src/beacon/routes/beacon/block.ts index 95a32097028d..c1f1e723e358 100644 --- a/packages/api/src/beacon/routes/beacon/block.ts +++ b/packages/api/src/beacon/routes/beacon/block.ts @@ -229,8 +229,12 @@ export type Api = { * Retrieves BlobSidecar included in requested block. * @param blockId Block identifier. * Can be one of: "head" (canonical head in node's view), "genesis", "finalized", \, \. + * @param indices Array of indices for blob sidecars to request for in the specified block. Returns all blob sidecars in the block if not specified. */ - getBlobSidecars(blockId: BlockId): Promise< + getBlobSidecars( + blockId: BlockId, + indices?: number[] + ): Promise< ApiClientResponse<{ [HttpStatusCode.OK]: {executionOptimistic: ExecutionOptimistic; data: deneb.BlobSidecars}; }> @@ -270,7 +274,7 @@ export type ReqTypes = { publishBlockV2: {body: unknown; query: {broadcast_validation?: string}}; publishBlindedBlock: {body: unknown}; publishBlindedBlockV2: {body: unknown; query: {broadcast_validation?: string}}; - getBlobSidecars: BlockIdOnlyReq; + getBlobSidecars: {params: {block_id: string}; query: {indices?: number[]}}; }; export function getReqSerializers(config: ChainForkConfig): ReqSerializers { @@ -356,7 +360,16 @@ export function getReqSerializers(config: ChainForkConfig): ReqSerializers ({ + params: {block_id: String(block_id)}, + query: {indices}, + }), + parseReq: ({params, query}) => [params.block_id, query.indices], + schema: { + query: {indices: Schema.UintArray}, + }, + }, }; } diff --git a/packages/api/test/unit/beacon/oapiSpec.test.ts b/packages/api/test/unit/beacon/oapiSpec.test.ts index 15a10bfeb6f7..f7d6cb9a077c 100644 --- a/packages/api/test/unit/beacon/oapiSpec.test.ts +++ b/packages/api/test/unit/beacon/oapiSpec.test.ts @@ -130,12 +130,6 @@ const ignoredProperties: Record = { */ getHealth: {request: ["query.syncing_status"]}, - /** - * https://github.com/ChainSafe/lodestar/issues/6185 - * - must have required property 'query' - */ - getBlobSidecars: {request: ["query"]}, - /* https://github.com/ChainSafe/lodestar/issues/4638 /query - must have required property 'skip_randao_verification' diff --git a/packages/api/test/unit/beacon/testData/beacon.ts b/packages/api/test/unit/beacon/testData/beacon.ts index 7fa8368c590b..6d6bc6576f56 100644 --- a/packages/api/test/unit/beacon/testData/beacon.ts +++ b/packages/api/test/unit/beacon/testData/beacon.ts @@ -71,7 +71,7 @@ export const testData: GenericServerTestCases = { res: undefined, }, getBlobSidecars: { - args: ["head"], + args: ["head", [0]], res: {executionOptimistic: true, data: ssz.deneb.BlobSidecars.defaultValue()}, }, diff --git a/packages/api/test/utils/checkAgainstSpec.ts b/packages/api/test/utils/checkAgainstSpec.ts index ed65279bca22..c887f66e95e6 100644 --- a/packages/api/test/utils/checkAgainstSpec.ts +++ b/packages/api/test/utils/checkAgainstSpec.ts @@ -199,12 +199,21 @@ function prettyAjvErrors(errors: ErrorObject[] | null | undefined): string { return errors.map((e) => `${e.instancePath ?? "."} - ${e.message}`).join("\n"); } +type StringifiedProperty = string | StringifiedProperty[]; + +function stringifyProperty(value: unknown): StringifiedProperty { + if (typeof value === "number") { + return value.toString(10); + } else if (Array.isArray(value)) { + return value.map(stringifyProperty); + } + return String(value); +} + function stringifyProperties(obj: Record): Record { for (const key of Object.keys(obj)) { const value = obj[key]; - if (typeof value === "number") { - obj[key] = value.toString(10); - } + obj[key] = stringifyProperty(value); } return obj; diff --git a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts index f2e29f00fe57..6fde04bc737c 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts @@ -406,7 +406,7 @@ export function getBeaconBlockApi({ await publishBlock(signedBlockOrContents, opts); }, - async getBlobSidecars(blockId) { + async getBlobSidecars(blockId, indices) { const {block, executionOptimistic} = await resolveBlockId(chain, blockId); const blockRoot = config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message); @@ -418,9 +418,10 @@ export function getBeaconBlockApi({ if (!blobSidecars) { throw Error(`blobSidecars not found in db for slot=${block.message.slot} root=${toHexString(blockRoot)}`); } + return { executionOptimistic, - data: blobSidecars, + data: indices ? blobSidecars.filter(({index}) => indices.includes(index)) : blobSidecars, }; }, }; From 54c20699d2395ba0ac658616b8a227fc52ccc414 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 29 Jan 2024 18:15:27 +0100 Subject: [PATCH 06/71] fix: ignore stale keystore lockfiles (#6363) * fix: ignore stale keystore lockfiles * Update error message if lockfile is already acquired * Update keymanager lockfile e2e tests --- packages/cli/package.json | 4 +- packages/cli/src/util/lockfile.ts | 54 +++++++++++-------- .../test/e2e/importKeystoresFromApi.test.ts | 8 +-- .../decryptKeystoreDefinitions.test.ts | 13 +++-- packages/db/src/controller/level.ts | 2 +- yarn.lock | 19 +++---- 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index c16baf13c25f..8531db5b633f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -77,7 +77,6 @@ "@lodestar/utils": "^1.15.0", "@lodestar/validator": "^1.15.0", "@multiformats/multiaddr": "^12.1.3", - "@types/lockfile": "^1.0.2", "bip39": "^3.1.0", "deepmerge": "^4.3.1", "ethers": "^6.7.0", @@ -86,9 +85,9 @@ "got": "^11.8.6", "inquirer": "^9.1.5", "js-yaml": "^4.1.0", - "lockfile": "^1.0.4", "lodash": "^4.17.21", "prom-client": "^15.1.0", + "proper-lockfile": "^4.1.2", "rimraf": "^4.4.1", "source-map-support": "^0.5.21", "uint8arrays": "^4.0.9", @@ -102,6 +101,7 @@ "@types/got": "^9.6.12", "@types/inquirer": "^9.0.3", "@types/lodash": "^4.14.192", + "@types/proper-lockfile": "^4.1.4", "@types/yargs": "^17.0.24" } } diff --git a/packages/cli/src/util/lockfile.ts b/packages/cli/src/util/lockfile.ts index 65933e8f2897..f7a6ddf4d57d 100644 --- a/packages/cli/src/util/lockfile.ts +++ b/packages/cli/src/util/lockfile.ts @@ -1,29 +1,21 @@ -export type Lockfile = { - lockSync(path: string): void; - unlockSync(path: string): void; -}; - -const lockFile: Lockfile = (await import("lockfile")) as Lockfile; - -function getLockFilepath(filepath: string): string { - return `${filepath}.lock`; -} - -/** - * When lockfile is imported, it registers listeners to process - * Since it's only used by the validator client, require lazily to not pollute - * beacon_node client context - */ -function getLockFile(): Lockfile { - return lockFile; -} +import {lockSync, unlockSync} from "proper-lockfile"; /** * Creates a .lock file for `filepath`, argument passed must not be the lock path * @param filepath File to lock, i.e. `keystore_0001.json` */ export function lockFilepath(filepath: string): void { - getLockFile().lockSync(getLockFilepath(filepath)); + try { + lockSync(filepath, { + // Allows to lock files that do not exist + realpath: false, + }); + } catch (e) { + if (isLockfileError(e) && e.code === "ELOCKED") { + e.message = `${filepath} is already in use by another process`; + } + throw e; + } } /** @@ -31,7 +23,23 @@ export function lockFilepath(filepath: string): void { * @param filepath File to unlock, i.e. `keystore_0001.json` */ export function unlockFilepath(filepath: string): void { - // Does not throw if the lock file is already deleted - // https://github.com/npm/lockfile/blob/6590779867ee9bdc5dbebddc962640759892bb91/lockfile.js#L68 - getLockFile().unlockSync(getLockFilepath(filepath)); + try { + unlockSync(filepath, { + // Allows to unlock files that do not exist + realpath: false, + }); + } catch (e) { + if (isLockfileError(e) && e.code === "ENOTACQUIRED") { + // Do not throw if the lock file is already deleted + return; + } + throw e; + } +} + +// https://github.com/moxystudio/node-proper-lockfile/blob/9f8c303c91998e8404a911dc11c54029812bca69/lib/lockfile.js#L53 +export type LockfileError = Error & {code: "ELOCKED" | "ENOTACQUIRED"}; + +function isLockfileError(e: unknown): e is LockfileError { + return e instanceof Error && (e as LockfileError).code !== undefined; } diff --git a/packages/cli/test/e2e/importKeystoresFromApi.test.ts b/packages/cli/test/e2e/importKeystoresFromApi.test.ts index bb91d467b86a..1cf5f107e226 100644 --- a/packages/cli/test/e2e/importKeystoresFromApi.test.ts +++ b/packages/cli/test/e2e/importKeystoresFromApi.test.ts @@ -95,10 +95,10 @@ describe("import keystores from api", function () { validator.on("exit", (code) => { if (code !== null && code > 0) { // process should exit with code > 0, and an error related to locks. Sample error: - // vc 351591: ✖ Error: EEXIST: file already exists, open '/tmp/tmp-351554-dMctEAj7sJIz/import-keystores-test/keystores/0x8be678633e927aa0435addad5dcd5283fef6110d91362519cd6d43e61f6c017d724fa579cc4b2972134e050b6ba120c0/voting-keystore.json.lock' - // at Object.openSync (node:fs:585:3) - // at Module.exports.lockSync (/home/lion/Code/eth2.0/lodestar/node_modules/lockfile/lockfile.js:277:17) - if (/EEXIST.*voting-keystore\.json\.lock/.test(vcProc2Stderr.read())) { + // vc 351591: ✖ Error: /tmp/tmp-5080-lwNxdM5Ok9ya/import-keystores-test/keystores/0x8be678633e927aa0435addad5dcd5283fef6110d91362519cd6d43e61f6c017d724fa579cc4b2972134e050b6ba120c0/voting-keystore.json is already in use by another process + // at /home/runner/actions-runner/_work/lodestar/lodestar/node_modules/proper-lockfile/lib/lockfile.js:68:47 + // ... more stack trace + if (/Error.*voting-keystore\.json is already in use by another process/.test(vcProc2Stderr.read())) { resolve(); } else { reject(Error(`Second validator proc exited with unknown error. stderr:\n${vcProc2Stderr.read()}`)); diff --git a/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts b/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts index f24b83ae43a6..0f4173604405 100644 --- a/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts +++ b/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts @@ -7,6 +7,7 @@ import {cachedSeckeysHex} from "../../utils/cachedKeys.js"; import {testFilesDir} from "../../utils.js"; import {decryptKeystoreDefinitions} from "../../../src/cmds/validator/keymanager/decryptKeystoreDefinitions.js"; import {LocalKeystoreDefinition} from "../../../src/cmds/validator/keymanager/interface.js"; +import {LockfileError, unlockFilepath} from "../../../src/util/lockfile.js"; describe("decryptKeystoreDefinitions", () => { vi.setConfig({testTimeout: 100_000}); @@ -22,6 +23,10 @@ describe("decryptKeystoreDefinitions", () => { let definitions: LocalKeystoreDefinition[] = []; beforeEach(async () => { + // remove lockfiles from proper-lockfile cache + for (const {keystorePath} of definitions) { + unlockFilepath(keystorePath); + } rimraf.sync(dataDir); rimraf.sync(importFromDir); @@ -46,7 +51,9 @@ describe("decryptKeystoreDefinitions", () => { expect(fs.existsSync(cacheFilePath)).toBe(true); // remove lockfiles created during cache file preparation - rimraf.sync(path.join(importFromDir, "*.lock"), {glob: true}); + for (const {keystorePath} of definitions) { + unlockFilepath(keystorePath); + } }); testDecryptKeystoreDefinitions(cacheFilePath); @@ -75,14 +82,14 @@ describe("decryptKeystoreDefinitions", () => { await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath}); expect.fail("Second decrypt should fail due to failure to get lockfile"); } catch (e) { - expect((e as Error).message.startsWith("EEXIST: file already exists")).toBe(true); + expect((e as LockfileError).code).toBe("ELOCKED"); } }); it("decrypt keystores if lockfiles already exist if ignoreLockFile=true", async () => { await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath}); - // lockfiles should exist after the first run + await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath, ignoreLockFile: true}); }); } diff --git a/packages/db/src/controller/level.ts b/packages/db/src/controller/level.ts index 3eed75958e3e..2cea8681c95b 100644 --- a/packages/db/src/controller/level.ts +++ b/packages/db/src/controller/level.ts @@ -52,7 +52,7 @@ export class LevelDbController implements DatabaseController Date: Tue, 30 Jan 2024 00:17:23 +0700 Subject: [PATCH 07/71] fix: stabilize unknown block sync e2e test (#6364) fix: stabalize unknown block sync e2e test --- .../test/e2e/sync/unknownBlockSync.test.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts b/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts index a51beaf7b961..e64adfc94888 100644 --- a/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts +++ b/packages/beacon-node/test/e2e/sync/unknownBlockSync.test.ts @@ -12,7 +12,7 @@ import {waitForEvent} from "../../utils/events/resolver.js"; import {getAndInitDevValidators} from "../../utils/node/validator.js"; import {ChainEvent} from "../../../src/chain/index.js"; import {NetworkEvent} from "../../../src/network/index.js"; -import {connect} from "../../utils/network.js"; +import {connect, onPeerConnect} from "../../utils/network.js"; import {testLogger, LogLevel, TestLoggerOpts} from "../../utils/logger.js"; import {BlockError, BlockErrorCode} from "../../../src/chain/errors/index.js"; import {BlockSource, getBlockInput} from "../../../src/chain/blocks/types.js"; @@ -48,7 +48,7 @@ describe("sync / unknown block sync", function () { for (const {id, event} of testCases) { it(id, async function () { // the node needs time to transpile/initialize bls worker threads - const genesisSlotsDelay = 7; + const genesisSlotsDelay = 4; const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT; const testLoggerOpts: TestLoggerOpts = { level: LogLevel.info, @@ -71,6 +71,7 @@ describe("sync / unknown block sync", function () { chain: {blsVerifyAllMainThread: true}, }, validatorCount, + genesisTime, logger: loggerNodeA, }); @@ -100,7 +101,7 @@ describe("sync / unknown block sync", function () { chain: {blsVerifyAllMainThread: true}, }, validatorCount, - genesisTime: bn.chain.getHeadState().genesisTime, + genesisTime, logger: loggerNodeB, }); @@ -116,7 +117,11 @@ describe("sync / unknown block sync", function () { ({block}) => block === headSummary.blockRoot ); + const connected = Promise.all([onPeerConnect(bn2.network), onPeerConnect(bn.network)]); await connect(bn2.network, bn.network); + await connected; + loggerNodeA.info("Node A connected to Node B"); + const headInput = getBlockInput.preDeneb(config, head, BlockSource.gossip, null); switch (event) { @@ -147,4 +152,4 @@ describe("sync / unknown block sync", function () { await waitForSynced; }); } -}, {timeout: 30_000}); +}, {timeout: 40_000}); From ed43a988bf7acbe25fad9988434a1ade3ed6016e Mon Sep 17 00:00:00 2001 From: Julien Date: Mon, 29 Jan 2024 09:53:35 -0800 Subject: [PATCH 08/71] chore: align vitest config filenames (#6369) --- CONTRIBUTING.md | 2 +- packages/beacon-node/package.json | 10 +++++----- .../{vitest.config.e2e.ts => vitest.e2e.config.ts} | 0 .../{vitest.config.spec.ts => vitest.spec.config.ts} | 0 packages/cli/package.json | 2 +- .../cli/{vitest.config.e2e.ts => vitest.e2e.config.ts} | 0 packages/logger/package.json | 2 +- .../{vitest.config.e2e.ts => vitest.e2e.config.ts} | 0 packages/params/package.json | 2 +- .../{vitest.config.e2e.ts => vitest.e2e.config.ts} | 0 packages/prover/package.json | 2 +- .../{vitest.config.e2e.ts => vitest.e2e.config.ts} | 0 packages/spec-test-util/package.json | 2 +- .../{vitest.config.e2e.ts => vitest.e2e.config.ts} | 0 packages/validator/package.json | 4 ++-- .../{vitest.config.e2e.ts => vitest.e2e.config.ts} | 0 .../{vitest.config.spec.ts => vitest.spec.config.ts} | 0 17 files changed, 13 insertions(+), 13 deletions(-) rename packages/beacon-node/{vitest.config.e2e.ts => vitest.e2e.config.ts} (100%) rename packages/beacon-node/{vitest.config.spec.ts => vitest.spec.config.ts} (100%) rename packages/cli/{vitest.config.e2e.ts => vitest.e2e.config.ts} (100%) rename packages/logger/{vitest.config.e2e.ts => vitest.e2e.config.ts} (100%) rename packages/params/{vitest.config.e2e.ts => vitest.e2e.config.ts} (100%) rename packages/prover/{vitest.config.e2e.ts => vitest.e2e.config.ts} (100%) rename packages/spec-test-util/{vitest.config.e2e.ts => vitest.e2e.config.ts} (100%) rename packages/validator/{vitest.config.e2e.ts => vitest.e2e.config.ts} (100%) rename packages/validator/{vitest.config.spec.ts => vitest.spec.config.ts} (100%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4074c47e88e8..75fc18a95da9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,7 +65,7 @@ If you observe following error running any of the test files that means you are - To then run only that failed test you can run against a specific file as use vitest's filters to run only one case ```sh -LODESTAR_PRESET=minimal yarn vitest --run --config vitest.config.spec.ts test/spec/phase0/sanity.test.ts +LODESTAR_PRESET=minimal yarn vitest --run --config vitest.spec.config.ts test/spec/phase0/sanity.test.ts ``` ## Docker diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index aab75c458d56..174ed8cbb125 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -79,17 +79,17 @@ "test:unit:minimal": "vitest --run --segfaultRetry 3 --dir test/unit/", "test:unit:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/unit-mainnet", "test:unit": "wrapper() { yarn test:unit:minimal $@ && yarn test:unit:mainnet $@; }; wrapper", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --segfaultRetry 3 --config vitest.config.e2e.ts --dir test/e2e", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --segfaultRetry 3 --config vitest.e2e.config.ts --dir test/e2e", "test:sim": "vitest --run test/sim/**/*.test.ts", "test:sim:merge-interop": "vitest --run test/sim/merge-interop.test.ts", "test:sim:mergemock": "vitest --run test/sim/mergemock.test.ts", "test:sim:withdrawals": "vitest --run test/sim/withdrawal-interop.test.ts", "test:sim:blobs": "vitest --run test/sim/4844-interop.test.ts", "download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts", - "test:spec:bls": "vitest --run --config vitest.config.spec.ts --dir test/spec/bls/", - "test:spec:general": "vitest --run --config vitest.config.spec.ts --dir test/spec/general/", - "test:spec:minimal": "LODESTAR_PRESET=minimal vitest --run --config vitest.config.spec.ts --dir test/spec/presets/", - "test:spec:mainnet": "LODESTAR_PRESET=mainnet vitest --run --config vitest.config.spec.ts --dir test/spec/presets/", + "test:spec:bls": "vitest --run --config vitest.spec.config.ts --dir test/spec/bls/", + "test:spec:general": "vitest --run --config vitest.spec.config.ts --dir test/spec/general/", + "test:spec:minimal": "LODESTAR_PRESET=minimal vitest --run --config vitest.spec.config.ts --dir test/spec/presets/", + "test:spec:mainnet": "LODESTAR_PRESET=mainnet vitest --run --config vitest.spec.config.ts --dir test/spec/presets/", "test:spec": "yarn test:spec:bls && yarn test:spec:general && yarn test:spec:minimal && yarn test:spec:mainnet", "check-readme": "typescript-docs-verifier" }, diff --git a/packages/beacon-node/vitest.config.e2e.ts b/packages/beacon-node/vitest.e2e.config.ts similarity index 100% rename from packages/beacon-node/vitest.config.e2e.ts rename to packages/beacon-node/vitest.e2e.config.ts diff --git a/packages/beacon-node/vitest.config.spec.ts b/packages/beacon-node/vitest.spec.config.ts similarity index 100% rename from packages/beacon-node/vitest.config.spec.ts rename to packages/beacon-node/vitest.spec.config.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index 8531db5b633f..d21e523696ef 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -31,7 +31,7 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test:unit": "vitest --run --dir test/unit/", - "test:e2e": "vitest --run --config vitest.config.e2e.ts --dir test/e2e/", + "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e/", "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", diff --git a/packages/cli/vitest.config.e2e.ts b/packages/cli/vitest.e2e.config.ts similarity index 100% rename from packages/cli/vitest.config.e2e.ts rename to packages/cli/vitest.e2e.config.ts diff --git a/packages/logger/package.json b/packages/logger/package.json index fd82a7651b3f..e8d32622ae95 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -61,7 +61,7 @@ "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.config.e2e.ts --dir test/e2e", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.e2e.config.ts --dir test/e2e", "check-readme": "typescript-docs-verifier" }, "types": "lib/index.d.ts", diff --git a/packages/logger/vitest.config.e2e.ts b/packages/logger/vitest.e2e.config.ts similarity index 100% rename from packages/logger/vitest.config.e2e.ts rename to packages/logger/vitest.e2e.config.ts diff --git a/packages/params/package.json b/packages/params/package.json index ebd4116f16b1..bd5259c4712d 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -58,7 +58,7 @@ "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.config.e2e.ts --dir test/e2e/", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.e2e.config.ts --dir test/e2e/", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/params/vitest.config.e2e.ts b/packages/params/vitest.e2e.config.ts similarity index 100% rename from packages/params/vitest.config.e2e.ts rename to packages/params/vitest.e2e.config.ts diff --git a/packages/prover/package.json b/packages/prover/package.json index 36433fa8d567..b5c7eac31033 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -57,7 +57,7 @@ "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.config.e2e.ts --dir test/e2e", + "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.e2e.config.ts --dir test/e2e", "check-readme": "typescript-docs-verifier", "generate-fixtures": "node --loader ts-node/esm scripts/generate_fixtures.ts" }, diff --git a/packages/prover/vitest.config.e2e.ts b/packages/prover/vitest.e2e.config.ts similarity index 100% rename from packages/prover/vitest.config.e2e.ts rename to packages/prover/vitest.e2e.config.ts diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index c2c202a72614..7e9a82b16035 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -48,7 +48,7 @@ "lint:fix": "yarn run lint --fix", "test": "yarn test:unit && yarn test:e2e", "test:unit": "vitest --run --passWithNoTests --dir test/unit/", - "test:e2e": "vitest --run --config vitest.config.e2e.ts --dir test/e2e/", + "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e/", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/spec-test-util/vitest.config.e2e.ts b/packages/spec-test-util/vitest.e2e.config.ts similarity index 100% rename from packages/spec-test-util/vitest.config.e2e.ts rename to packages/spec-test-util/vitest.e2e.config.ts diff --git a/packages/validator/package.json b/packages/validator/package.json index 5a2dcb55c2ba..5b913ad84a63 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -29,8 +29,8 @@ "lint:fix": "yarn run lint --fix", "test:unit": "vitest --run --dir test/unit/", "test": "yarn test:unit && yarn test:e2e", - "test:spec": "vitest --run --config vitest.config.spec.ts --dir test/spec/", - "test:e2e": "LODESTAR_PRESET=mainnet vitest --run --config vitest.config.e2e.ts --dir test/e2e", + "test:spec": "vitest --run --config vitest.spec.config.ts --dir test/spec/", + "test:e2e": "LODESTAR_PRESET=mainnet vitest --run --config vitest.e2e.config.ts --dir test/e2e", "download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts", "coverage": "codecov -F lodestar-validator", "check-readme": "typescript-docs-verifier" diff --git a/packages/validator/vitest.config.e2e.ts b/packages/validator/vitest.e2e.config.ts similarity index 100% rename from packages/validator/vitest.config.e2e.ts rename to packages/validator/vitest.e2e.config.ts diff --git a/packages/validator/vitest.config.spec.ts b/packages/validator/vitest.spec.config.ts similarity index 100% rename from packages/validator/vitest.config.spec.ts rename to packages/validator/vitest.spec.config.ts From 8b354f2087cac8abea6f478b8bda6fe09ebdc528 Mon Sep 17 00:00:00 2001 From: Matthew Keil Date: Tue, 30 Jan 2024 16:17:20 +0700 Subject: [PATCH 09/71] docs: add comment to RequestErrorCode.SSZ_OVER_MAX_SIZE (#6373) --- packages/reqresp/src/request/errors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/reqresp/src/request/errors.ts b/packages/reqresp/src/request/errors.ts index 0078ad5d2ecf..ba3904e563ed 100644 --- a/packages/reqresp/src/request/errors.ts +++ b/packages/reqresp/src/request/errors.ts @@ -31,7 +31,7 @@ export enum RequestErrorCode { RESP_TIMEOUT = "REQUEST_ERROR_RESP_TIMEOUT", /** Request rate limited */ REQUEST_RATE_LIMITED = "REQUEST_ERROR_RATE_LIMITED", - /** */ + /** For malformed SSZ (metadata) responses */ SSZ_OVER_MAX_SIZE = "SSZ_SNAPPY_ERROR_OVER_SSZ_MAX_SIZE", } From 5064fab473641bb724425222db79646ac7016ae7 Mon Sep 17 00:00:00 2001 From: scott willeke Date: Tue, 30 Jan 2024 01:30:14 -0800 Subject: [PATCH 10/71] docs: update link to erigon jwt setup (#6375) --- docs/pages/getting-started/starting-a-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/getting-started/starting-a-node.md b/docs/pages/getting-started/starting-a-node.md index dd11381bde10..665a39b0df80 100644 --- a/docs/pages/getting-started/starting-a-node.md +++ b/docs/pages/getting-started/starting-a-node.md @@ -47,7 +47,7 @@ Use the `--JsonRpc.JwtSecretFile /data/jwtsecret` flag to configure the secret. Use the `--engine-jwt-secret=` flag to configure the secret. Use their documentation [here](https://besu.hyperledger.org/en/stable/Reference/CLI/CLI-Syntax/#engine-jwt-secret). **For Erigon:** -Use the `--authrpc.jwtsecret` flag to configure the secret. Use their documentation [here](https://github.com/ledgerwatch/erigon#authentication-api). +Use the `--authrpc.jwtsecret` flag to configure the secret. Use their documentation [here](https://github.com/ledgerwatch/erigon?tab=readme-ov-file#beacon-chain-consensus-layer). ## Run a beacon node From b5344bfe59cf8b0b7d13ae4722fed2f463506b7b Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 30 Jan 2024 13:47:50 +0100 Subject: [PATCH 11/71] fix: add block_id schema validation to getBlobSidecars (#6377) --- packages/api/src/beacon/routes/beacon/block.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/api/src/beacon/routes/beacon/block.ts b/packages/api/src/beacon/routes/beacon/block.ts index c1f1e723e358..ae150ca6b3e8 100644 --- a/packages/api/src/beacon/routes/beacon/block.ts +++ b/packages/api/src/beacon/routes/beacon/block.ts @@ -367,6 +367,7 @@ export function getReqSerializers(config: ChainForkConfig): ReqSerializers [params.block_id, query.indices], schema: { + params: {block_id: Schema.StringRequired}, query: {indices: Schema.UintArray}, }, }, From f2e352ff017341e098b8dcea8bd8bd204a93c425 Mon Sep 17 00:00:00 2001 From: tuyennhv Date: Wed, 31 Jan 2024 05:54:13 +0700 Subject: [PATCH 12/71] fix: skip useWorker mode for gossipsub e2e tests (#6368) --- packages/beacon-node/test/e2e/network/gossipsub.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/beacon-node/test/e2e/network/gossipsub.test.ts b/packages/beacon-node/test/e2e/network/gossipsub.test.ts index 0ffab720598c..c7b3dbefbe77 100644 --- a/packages/beacon-node/test/e2e/network/gossipsub.test.ts +++ b/packages/beacon-node/test/e2e/network/gossipsub.test.ts @@ -16,7 +16,12 @@ describe( {timeout: 3000} ); -describe( +/** + * This is nice to have to investigate networking issue in local environment. + * Since we use vitest to run tests in parallel, including this causes the test to be unstable. + * See https://github.com/ChainSafe/lodestar/issues/6358 + */ +describe.skip( "gossipsub / worker", function () { runTests({useWorker: true}); From 8e0078b828c57c1476a422e80d037306380ca512 Mon Sep 17 00:00:00 2001 From: Julien Date: Tue, 30 Jan 2024 14:54:37 -0800 Subject: [PATCH 13/71] docs: reflect vitest migration (#6247) * fix: reflect vitest migration * fix: incorrect spec example folder * chore: added filter examples --------- Co-authored-by: Cayman --- CONTRIBUTING.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 75fc18a95da9..7e567ab517fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,11 +61,12 @@ If you observe following error running any of the test files that means you are - To fix errors always focus on passing all minimal tests first without running mainnet tests. - Spec tests often compare full expected vs actual states in JSON format. -- A single logical error can cause many spec tests to fail. To focus on a single test at a time you can use vitest's option `--bail` to stop at the first failed test -- To then run only that failed test you can run against a specific file as use vitest's filters to run only one case +- A single logical error can cause many spec tests to fail. To focus on a single test at a time you can use vitest's option `--bail 1` to stop at the first failed test +- To then run only that failed test you can run against a specific file as use vitest's filters option `-t ` to run only one case ```sh -LODESTAR_PRESET=minimal yarn vitest --run --config vitest.spec.config.ts test/spec/phase0/sanity.test.ts +cd packages/beacon-node +LODESTAR_PRESET=minimal yarn vitest --run --bail 1 --config vitest.spec.config.ts test/spec/presets/sanity.test.ts -t attester_slashing ``` ## Docker From 6b732b0cf553e2b3b83b89307d761f2cdd84c201 Mon Sep 17 00:00:00 2001 From: Matthew Keil Date: Thu, 1 Feb 2024 15:34:56 +0700 Subject: [PATCH 14/71] fix: log errors setting agent version as debug (#6374) * feat: ignore NotFound error for setting agentVersion * fix: debug log instead of ignore peer not found for setting agentVersion * fix: remove NotFound check and only debug log error setting agentVersion Co-authored-by: Nico Flaig --------- Co-authored-by: Nico Flaig --- packages/beacon-node/src/network/peers/peerManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/beacon-node/src/network/peers/peerManager.ts b/packages/beacon-node/src/network/peers/peerManager.ts index 94af8f06ea03..2275178e13e3 100644 --- a/packages/beacon-node/src/network/peers/peerManager.ts +++ b/packages/beacon-node/src/network/peers/peerManager.ts @@ -620,7 +620,7 @@ export class PeerManager { }, {retries: 3, retryDelay: 1000} ).catch((err) => { - this.logger.error("Error setting agentVersion for the peer", {peerId: peerData.peerId.toString()}, err); + this.logger.debug("Error setting agentVersion for the peer", {peerId: peerData.peerId.toString()}, err); }); }; From 237439266adc69dbe30ea938cb4aca73160913e5 Mon Sep 17 00:00:00 2001 From: Cayman Date: Thu, 1 Feb 2024 10:52:44 -0500 Subject: [PATCH 15/71] chore: update chainsafe dependencies (#6380) --- packages/beacon-node/package.json | 10 +- packages/cli/package.json | 12 +- packages/flare/package.json | 2 +- packages/light-client/package.json | 4 +- packages/prover/package.json | 2 +- packages/state-transition/package.json | 2 +- packages/test-utils/package.json | 2 +- packages/utils/package.json | 2 +- yarn.lock | 1547 ++++++------------------ 9 files changed, 395 insertions(+), 1188 deletions(-) diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 174ed8cbb125..90f2026e1873 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -95,12 +95,12 @@ }, "dependencies": { "@chainsafe/as-chacha20poly1305": "^0.1.0", - "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/as-sha256": "^0.4.1", "@chainsafe/bls": "7.1.1", "@chainsafe/blst": "^0.2.9", - "@chainsafe/discv5": "^7.1.0", - "@chainsafe/enr": "^2.0.2", - "@chainsafe/libp2p-gossipsub": "^11.1.0", + "@chainsafe/discv5": "^9.0.0", + "@chainsafe/enr": "^3.0.0", + "@chainsafe/libp2p-gossipsub": "^11.2.0", "@chainsafe/libp2p-noise": "^14.1.0", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/prometheus-gc-stats": "^1.0.0", @@ -153,7 +153,7 @@ "systeminformation": "^5.17.12", "uint8-varint": "^2.0.2", "uint8arraylist": "^2.4.7", - "uint8arrays": "^4.0.9", + "uint8arrays": "^5.0.1", "xxhash-wasm": "1.0.2" }, "devDependencies": { diff --git a/packages/cli/package.json b/packages/cli/package.json index d21e523696ef..1b172087b180 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -52,13 +52,13 @@ "blockchain" ], "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/as-sha256": "^0.4.1", "@chainsafe/bls": "7.1.1", - "@chainsafe/bls-keygen": "^0.3.0", - "@chainsafe/bls-keystore": "^3.0.0", + "@chainsafe/bls-keygen": "^0.4.0", + "@chainsafe/bls-keystore": "^3.0.1", "@chainsafe/blst": "^0.2.9", - "@chainsafe/discv5": "^7.1.0", - "@chainsafe/enr": "^2.0.2", + "@chainsafe/discv5": "^9.0.0", + "@chainsafe/enr": "^3.0.0", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", "@chainsafe/threads": "^1.11.1", @@ -90,7 +90,7 @@ "proper-lockfile": "^4.1.2", "rimraf": "^4.4.1", "source-map-support": "^0.5.21", - "uint8arrays": "^4.0.9", + "uint8arrays": "^5.0.1", "uuidv4": "^6.2.13", "yargs": "^17.7.1" }, diff --git a/packages/flare/package.json b/packages/flare/package.json index a353598bcd77..6524562c9c82 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -59,7 +59,7 @@ ], "dependencies": { "@chainsafe/bls": "7.1.1", - "@chainsafe/bls-keygen": "^0.3.0", + "@chainsafe/bls-keygen": "^0.4.0", "@lodestar/api": "^1.15.0", "@lodestar/config": "^1.15.0", "@lodestar/params": "^1.15.0", diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 831498e2fff7..ef65e57fdef4 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -79,10 +79,10 @@ "strict-event-emitter-types": "^2.0.0" }, "devDependencies": { - "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/as-sha256": "^0.4.1", "@types/qs": "^6.9.7", "qs": "^6.11.1", - "uint8arrays": "^4.0.9" + "uint8arrays": "^5.0.1" }, "keywords": [ "ethereum", diff --git a/packages/prover/package.json b/packages/prover/package.json index b5c7eac31033..efeace5dfb65 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -78,7 +78,7 @@ "@lodestar/params": "^1.15.0", "@lodestar/types": "^1.15.0", "@lodestar/utils": "^1.15.0", - "ethereum-cryptography": "^1.2.0", + "ethereum-cryptography": "^2.0.0", "find-up": "^6.3.0", "http-proxy": "^1.18.1", "js-yaml": "^4.1.0", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index e3c97c127e08..4524edf43859 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -58,7 +58,7 @@ }, "types": "lib/index.d.ts", "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/as-sha256": "^0.4.1", "@chainsafe/bls": "7.1.1", "@chainsafe/blst": "^0.2.9", "@chainsafe/persistent-merkle-tree": "^0.6.1", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index ab3474370a28..cb742ad4ba56 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -58,7 +58,7 @@ ], "dependencies": { "@chainsafe/bls": "7.1.1", - "@chainsafe/bls-keystore": "^3.0.0", + "@chainsafe/bls-keystore": "^3.0.1", "@lodestar/params": "^1.15.0", "@lodestar/utils": "^1.15.0", "axios": "^1.3.4", diff --git a/packages/utils/package.json b/packages/utils/package.json index 751d6551ee48..7c94e4288b12 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -39,7 +39,7 @@ }, "types": "lib/index.d.ts", "dependencies": { - "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/as-sha256": "^0.4.1", "any-signal": "3.0.1", "bigint-buffer": "^1.1.5", "case": "^1.6.3", diff --git a/yarn.lock b/yarn.lock index ce67d0db390d..839c0dce5e90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -256,26 +256,11 @@ resolved "https://registry.yarnpkg.com/@chainsafe/as-chacha20poly1305/-/as-chacha20poly1305-0.1.0.tgz#7da6f8796f9b42dac6e830a086d964f1f9189e09" integrity sha512-BpNcL8/lji/GM3+vZ/bgRWqJ1q5kwvTFmGPk7pxm/QQZDbaMI98waOHjEymTjq2JmdD/INdNBFOVSyJofXg7ew== -"@chainsafe/as-sha256@^0.3.1": - version "0.3.1" - resolved "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz" - integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== - "@chainsafe/as-sha256@^0.4.1": version "0.4.1" resolved "https://registry.yarnpkg.com/@chainsafe/as-sha256/-/as-sha256-0.4.1.tgz#cfc0737e25f8c206767bdb6703e7943e5d44513e" integrity sha512-IqeeGwQihK6Y2EYLFofqs2eY2ep1I2MvQXHzOAI+5iQN51OZlUkrLgyAugu2x86xZewDk5xas7lNczkzFzF62w== -"@chainsafe/bls-hd-key@^0.2.0": - version "0.2.1" - resolved "https://registry.npmjs.org/@chainsafe/bls-hd-key/-/bls-hd-key-0.2.1.tgz" - integrity sha512-FGmRLcOd9KxfH9q7x+FT20lJy9ooQ/Xd5fFLFGpPaf9GW4AnE0oGPGakPuV5//g8db7OzZ3ZfVMKtB4M7qq/wA== - dependencies: - assert "^2.0.0" - bcrypto "^5.4.0" - bn.js "^5.1.1" - buffer "^5.4.3" - "@chainsafe/bls-hd-key@^0.3.0": version "0.3.0" resolved "https://registry.npmjs.org/@chainsafe/bls-hd-key/-/bls-hd-key-0.3.0.tgz" @@ -283,16 +268,6 @@ dependencies: "@noble/hashes" "^1.0.0" -"@chainsafe/bls-keygen@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@chainsafe/bls-keygen/-/bls-keygen-0.3.0.tgz#d7472a945f6f49b5cb357241bfba2f5c12a635c5" - integrity sha512-5Iq6E5E987hyio74G1fXPYI3t9iVeHxRX1tDMpnCV9T82rPz061yFsMz3W3aXE26+k6+fcz0bsYX3ijOizkx+A== - dependencies: - "@chainsafe/bls-hd-key" "^0.2.0" - bip39 "^3.0.2" - buffer "^5.4.3" - randombytes "^2.1.0" - "@chainsafe/bls-keygen@^0.4.0": version "0.4.0" resolved "https://registry.npmjs.org/@chainsafe/bls-keygen/-/bls-keygen-0.4.0.tgz" @@ -302,13 +277,13 @@ "@noble/hashes" "^1.0.0" "@scure/bip39" "^1.0.0" -"@chainsafe/bls-keystore@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@chainsafe/bls-keystore/-/bls-keystore-3.0.0.tgz#e28c979f7664417e4917fa0d4d32fa2b9416e9c6" - integrity sha512-vlRIIXnn555wq2emhqnSR7btno17M0sCcfdQ+Dhgr7IH6n0CMoTGw9qcrpnNYwM+9OPm3matSYeZc9mNlXf7fQ== +"@chainsafe/bls-keystore@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/bls-keystore/-/bls-keystore-3.0.1.tgz#1eaf1d89d3628b5fbab62fcd10f48703f2c428cc" + integrity sha512-U6m/tMgdEUq60RhcIj7xUD5n6zuavSbThR+szuAglmUa9gY8QfInxXpGAT4hyc2QjbLy9115vJVyhyu7TDl+DQ== dependencies: - ethereum-cryptography "^1.0.0" - uuid "8.3.2" + ethereum-cryptography "^2.0.0" + uuid "^9.0.0" "@chainsafe/bls@7.1.1": version "7.1.1" @@ -328,37 +303,36 @@ node-fetch "^2.6.1" node-gyp "^8.4.0" -"@chainsafe/discv5@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@chainsafe/discv5/-/discv5-7.1.0.tgz#c892075c84bdc75428774d4993e7346205ff8724" - integrity sha512-spO801KWe0C9XrXkVt4E1paXP1ZtfsgxOf+FSW6yCDQTWFVGRfcl/ww4B7JtdJOnZauqaHqXxAuNBpSafJoalw== +"@chainsafe/discv5@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/discv5/-/discv5-9.0.0.tgz#05d4d9d671894b41f0fafa8f32c48ae3ed761bd1" + integrity sha512-7s23ziqsHG/KRgkX79qB/w8kuqPrY8aJaF2aRDy9cScJocJ6ZaOnXhEc8Ku1AcSyrvfGp+tY8R4rDABcxRY+Wg== dependencies: - "@chainsafe/enr" "^2.0.2" - "@libp2p/crypto" "^3.0.4" + "@chainsafe/enr" "^3.0.0" + "@libp2p/crypto" "^4.0.1" "@libp2p/interface" "^1.1.1" "@multiformats/multiaddr" "^12.1.10" bcrypto "^5.4.0" bigint-buffer "^1.1.5" debug "^4.3.1" - err-code "^3.0.1" lru-cache "^10.1.0" rlp "^2.2.6" strict-event-emitter-types "^2.0.0" -"@chainsafe/enr@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@chainsafe/enr/-/enr-2.0.2.tgz#29814ae506a87d466640cddbac49369029334f09" - integrity sha512-90IEkHHb5ZHk2BuyX5QkLomaxH+HXF41wFOzDC2Hpla6c3ersxAJJms4kJSot7j20Uzfka4Xjxvkwjj8WfL77g== +"@chainsafe/enr@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/enr/-/enr-3.0.0.tgz#71c83d4381d703bbcd19245ce733eb7c779a30ed" + integrity sha512-D8M8sqnvOim0jWlTdr2IhLyVe0GSUgpk+QO6UaLY4pQVdW1myJP8REp7xdbv1193ULVEkJQFTJAZexTOtmu3jw== dependencies: - "@libp2p/crypto" "^3.0.4" + "@libp2p/crypto" "^4.0.1" "@libp2p/interface" "^1.1.1" "@libp2p/peer-id" "^4.0.4" "@multiformats/multiaddr" "^12.1.10" - base64url "^3.0.1" - bcrypto "^5.4.0" bigint-buffer "^1.1.5" + ethereum-cryptography "^2.1.3" rlp "^2.2.6" uint8-varint "^2.0.2" + uint8arrays "^5.0.1" "@chainsafe/eslint-plugin-node@^11.2.3": version "11.2.3" @@ -390,26 +364,26 @@ resolved "https://registry.yarnpkg.com/@chainsafe/is-ip/-/is-ip-2.0.2.tgz#7311e7403f11d8c5cfa48111f56fcecaac37c9f6" integrity sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA== -"@chainsafe/libp2p-gossipsub@^11.1.0": - version "11.1.0" - resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-11.1.0.tgz#e5ebd8dd08601845073f3b8c9601e047d7bdc279" - integrity sha512-6baEtpC9gu5D9bXv86zIdNIOekKgQPV3KRWvnsldtsKpiWtUv6K2mLsl3wsDi0nW/c3zxTAneaJMTLQoSXysJQ== - dependencies: - "@libp2p/crypto" "^3.0.1" - "@libp2p/interface" "^1.0.1" - "@libp2p/interface-internal" "^1.0.1" - "@libp2p/peer-id" "^4.0.1" - "@libp2p/pubsub" "^9.0.0" - "@multiformats/multiaddr" "^12.1.3" +"@chainsafe/libp2p-gossipsub@^11.2.0": + version "11.2.0" + resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-11.2.0.tgz#4134dc68d9e3e0c327474b48fbd6e1f76f97550b" + integrity sha512-VymXl4Z4qEIUxH4FjgbcVqyuapVHhzrJxADO4t84QOOWv9f8uQYV+c0cgwjneOW3XyTYBOHaZqyTHTngTrKjtQ== + dependencies: + "@libp2p/crypto" "^4.0.1" + "@libp2p/interface" "^1.1.2" + "@libp2p/interface-internal" "^1.0.7" + "@libp2p/peer-id" "^4.0.5" + "@libp2p/pubsub" "^9.0.8" + "@multiformats/multiaddr" "^12.1.14" abortable-iterator "^5.0.1" denque "^2.1.0" - it-length-prefixed "^9.0.1" + it-length-prefixed "^9.0.4" it-pipe "^3.0.1" - it-pushable "^3.2.0" - multiformats "^12.0.1" - protobufjs "^7.2.4" - uint8arraylist "^2.4.3" - uint8arrays "^4.0.4" + it-pushable "^3.2.3" + multiformats "^13.0.1" + protobufjs "^7.2.6" + uint8arraylist "^2.4.8" + uint8arrays "^5.0.1" "@chainsafe/libp2p-noise@^14.1.0": version "14.1.0" @@ -1456,7 +1430,7 @@ "@multiformats/mafmt" "^12.1.6" "@multiformats/multiaddr" "^12.1.10" -"@libp2p/crypto@^3.0.0", "@libp2p/crypto@^3.0.1", "@libp2p/crypto@^3.0.4": +"@libp2p/crypto@^3.0.0", "@libp2p/crypto@^3.0.4": version "3.0.4" resolved "https://registry.yarnpkg.com/@libp2p/crypto/-/crypto-3.0.4.tgz#8768b262c24a036774c6c5e290a1f0d76535a7d3" integrity sha512-FzSwBo+RJOUzdzEwug5ZL4dAGKwEBWTLzj+EmUTHHY6c87+oLh571DQk/w0oYObSD9hYbcKePgSBaZeBx0JaZg== @@ -1470,6 +1444,20 @@ uint8arraylist "^2.4.3" uint8arrays "^5.0.0" +"@libp2p/crypto@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@libp2p/crypto/-/crypto-4.0.1.tgz#350f3397c8fba18d30a74173c3791fe199821062" + integrity sha512-lKGbX8TvQt4JbqlttdexEz2VtYJnTwY31kVBDQviwt0pMF+6Uy2hzNnEQ1FHZBwnow8BIlyb6UevHfgyOFlnkw== + dependencies: + "@libp2p/interface" "^1.1.2" + "@noble/curves" "^1.1.0" + "@noble/hashes" "^1.3.3" + asn1js "^3.0.5" + multiformats "^13.0.0" + protons-runtime "^5.0.0" + uint8arraylist "^2.4.7" + uint8arrays "^5.0.0" + "@libp2p/identify@^1.0.9": version "1.0.9" resolved "https://registry.yarnpkg.com/@libp2p/identify/-/identify-1.0.9.tgz#6756d74919b7a171c7cdcdce45669b9f633fbb0f" @@ -1487,7 +1475,7 @@ uint8arrays "^5.0.0" wherearewe "^2.0.1" -"@libp2p/interface-internal@^1.0.1", "@libp2p/interface-internal@^1.0.5": +"@libp2p/interface-internal@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@libp2p/interface-internal/-/interface-internal-1.0.5.tgz#b7687e4c5cb765fd686fcd442d2cc4c49e8304d7" integrity sha512-qT4APD2nZKEGnkn4LfM2mzNbYv9bx/2FyvYaJ4exjzIIBPiRmjrek7hfWErKkazCDwO51+WuZ/DERdd32O9Fxg== @@ -1497,7 +1485,17 @@ "@multiformats/multiaddr" "^12.1.10" uint8arraylist "^2.4.3" -"@libp2p/interface@^1.0.0", "@libp2p/interface@^1.0.1", "@libp2p/interface@^1.1.1": +"@libp2p/interface-internal@^1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/interface-internal/-/interface-internal-1.0.7.tgz#e15ad52e148e31558972dd2f4800ad8be61ced88" + integrity sha512-r1nGpnGdkq0U7ow5i093OPWPBJXQP3BGwijino8cCZokYwF2P/CU+yeYvL8ncL8fPYLKuuUjLNGO4Z8Th5sqSQ== + dependencies: + "@libp2p/interface" "^1.1.2" + "@libp2p/peer-collections" "^5.1.5" + "@multiformats/multiaddr" "^12.1.10" + uint8arraylist "^2.4.7" + +"@libp2p/interface@^1.0.0", "@libp2p/interface@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-1.1.1.tgz#f37ea4930bd74e1299fbcafa49fdab39a28abba9" integrity sha512-g6xgF+q38ZDTRkjuJfuOByS4N0zGld+VPRiWPXYX8wA/9vS6lqJwKUoC6V33KUhP/zXHCkJaSD6z94fUbNM8vw== @@ -1509,6 +1507,18 @@ progress-events "^1.0.0" uint8arraylist "^2.4.3" +"@libp2p/interface@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-1.1.2.tgz#debfd9d1bd4b81929c9e30eb35c2801ca246ce2b" + integrity sha512-uC4hxtEJuWiDiZfokkSNEEbCzdyZrqb5kp67Wc5PjZsySZ2IoImdIfie003yQXlB1xBp/XUJzdC6kVu4M7LUmg== + dependencies: + "@multiformats/multiaddr" "^12.1.10" + it-pushable "^3.2.3" + it-stream-types "^2.0.1" + multiformats "^13.0.0" + progress-events "^1.0.0" + uint8arraylist "^2.4.7" + "@libp2p/logger@^4.0.1", "@libp2p/logger@^4.0.4": version "4.0.4" resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.4.tgz#98c5357e8b857d93a506f6818db6abe734d342ee" @@ -1520,6 +1530,17 @@ interface-datastore "^8.2.0" multiformats "^13.0.0" +"@libp2p/logger@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.5.tgz#6790776b4b2d587b75ccbdf85885c5d11533d19f" + integrity sha512-cXETMNZINnxeQBlfQ2S4di92FDDU89R7RHagrpebGrM7oLl5nf/Mw6myc23kGaM3/2YG3ko2rl9sYjemu0azTA== + dependencies: + "@libp2p/interface" "^1.1.2" + "@multiformats/multiaddr" "^12.1.10" + debug "^4.3.4" + interface-datastore "^8.2.0" + multiformats "^13.0.0" + "@libp2p/mdns@^10.0.10": version "10.0.10" resolved "https://registry.yarnpkg.com/@libp2p/mdns/-/mdns-10.0.10.tgz#02f08f1a485e3640ce575460af63a0b8c4171b64" @@ -1564,13 +1585,13 @@ uint8arraylist "^2.4.3" uint8arrays "^5.0.0" -"@libp2p/peer-collections@^5.0.0", "@libp2p/peer-collections@^5.1.3": - version "5.1.3" - resolved "https://registry.yarnpkg.com/@libp2p/peer-collections/-/peer-collections-5.1.3.tgz#52734a31fe52f01f2ff67132ed0eae28b3229ae4" - integrity sha512-qiQHO8s4neLaAZmjHHWvPc091Lp9nOEokjnTmrE2/YBNjKoiA1aPCf7gM/KasynuquFceTQBDVd/Y79Mfqxw4w== +"@libp2p/peer-collections@^5.1.3", "@libp2p/peer-collections@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@libp2p/peer-collections/-/peer-collections-5.1.5.tgz#8b241f129dd94f5b56a17fc0614b8e9b80687b44" + integrity sha512-/9VisdPC7+15n/0XntjGCzJ2Ky/zZnqdnuLNEwdu2LuTCbWTaqItG36ecgcVdO9L/V4mELwgY5XCjZKBDrYgjA== dependencies: - "@libp2p/interface" "^1.1.1" - "@libp2p/peer-id" "^4.0.4" + "@libp2p/interface" "^1.1.2" + "@libp2p/peer-id" "^4.0.5" "@libp2p/peer-id-factory@^4.0.3": version "4.0.3" @@ -1584,12 +1605,12 @@ uint8arraylist "^2.4.3" uint8arrays "^5.0.0" -"@libp2p/peer-id@^4.0.0", "@libp2p/peer-id@^4.0.1", "@libp2p/peer-id@^4.0.4": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@libp2p/peer-id/-/peer-id-4.0.4.tgz#3de8f012f2abdc1ab287ad652d24de587e653ca3" - integrity sha512-UHWpo0f34IOaAhlvMNtCMAFVVhv29Dy3IqNvfugFNwzv5p+Jo6TfPGd78H7RX2WIzyVzIgBYxVxmIIHHcqZQ5Q== +"@libp2p/peer-id@^4.0.0", "@libp2p/peer-id@^4.0.4", "@libp2p/peer-id@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@libp2p/peer-id/-/peer-id-4.0.5.tgz#ed8be246b4d7ba2b7806968b4bfa8d59b82a4b2a" + integrity sha512-/J9U6I/CWSOsYrTpFZpRQrhOhi+bp9WFp7+9Gc7kVt/oevIYTapUEjpxevjViem9ddR5RbdYeCj4ZLHA04QOoQ== dependencies: - "@libp2p/interface" "^1.1.1" + "@libp2p/interface" "^1.1.2" multiformats "^13.0.0" uint8arrays "^5.0.0" @@ -1637,24 +1658,24 @@ prom-client "^15.0.0" uint8arraylist "^2.4.3" -"@libp2p/pubsub@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@libp2p/pubsub/-/pubsub-9.0.0.tgz#e9d3869addd653868f87797849dbebfd23cd3a38" - integrity sha512-yvgKBNKtF09x4ahbxJrxj/OBTNvOoJibR28YaTlrlCIDU78wMMhIx89Ma14g2FAN1OsxagifyAgq188vGrsGfA== - dependencies: - "@libp2p/crypto" "^3.0.1" - "@libp2p/interface" "^1.0.1" - "@libp2p/interface-internal" "^1.0.1" - "@libp2p/peer-collections" "^5.0.0" - "@libp2p/peer-id" "^4.0.1" - "@libp2p/utils" "^5.0.2" +"@libp2p/pubsub@^9.0.8": + version "9.0.8" + resolved "https://registry.yarnpkg.com/@libp2p/pubsub/-/pubsub-9.0.8.tgz#4c222c94edb5a5b623ed10fa7555bb70a19ddc0d" + integrity sha512-p2UEfjQPMQgEJTXPdinWCMA6A1sLR7Hvfu8mtoOS1azgtTtqmMCNPtx+3acnNSnWItQFswl9w2HWjspfUcCF1w== + dependencies: + "@libp2p/crypto" "^4.0.1" + "@libp2p/interface" "^1.1.2" + "@libp2p/interface-internal" "^1.0.7" + "@libp2p/peer-collections" "^5.1.5" + "@libp2p/peer-id" "^4.0.5" + "@libp2p/utils" "^5.2.3" it-length-prefixed "^9.0.3" it-pipe "^3.0.1" - it-pushable "^3.2.1" - multiformats "^12.1.3" - p-queue "^7.4.1" - uint8arraylist "^2.4.3" - uint8arrays "^4.0.6" + it-pushable "^3.2.3" + multiformats "^13.0.0" + p-queue "^8.0.0" + uint8arraylist "^2.4.7" + uint8arrays "^5.0.0" "@libp2p/tcp@9.0.10": version "9.0.10" @@ -1668,25 +1689,26 @@ "@types/sinon" "^17.0.0" stream-to-it "^0.2.2" -"@libp2p/utils@^5.0.2", "@libp2p/utils@^5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@libp2p/utils/-/utils-5.2.0.tgz#896bcb9ceb5b90caea0b2a8a5bb353dc2116cc13" - integrity sha512-zAremC/0u7mhS32TS++WBlsjwmKKKonEB7dZMfTtKH0QfghII8vcBOgBCTEqhtm0AqwsT6vIlm6wAg9bbZKbQA== +"@libp2p/utils@^5.2.0", "@libp2p/utils@^5.2.3": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@libp2p/utils/-/utils-5.2.3.tgz#32c1dd68d661d7d93ed3428c7817da2e4b85817f" + integrity sha512-N+9pQHQ/XrxXP/RCiWUSUXnkFCWcyzMxlGXY+aQUfcfLi5M2eFtPSz2Tc5dWmYGVJeI9CNafok+72YUsPZHfOQ== dependencies: "@chainsafe/is-ip" "^2.0.2" - "@libp2p/interface" "^1.1.1" - "@libp2p/logger" "^4.0.4" + "@libp2p/interface" "^1.1.2" + "@libp2p/logger" "^4.0.5" "@multiformats/multiaddr" "^12.1.10" "@multiformats/multiaddr-matcher" "^1.1.0" + delay "^6.0.0" get-iterator "^2.0.1" is-loopback-addr "^2.0.1" - it-pushable "^3.2.2" + it-pushable "^3.2.3" it-stream-types "^2.0.1" + netmask "^2.0.2" p-defer "^4.0.0" - private-ip "^3.0.1" race-event "^1.1.0" - race-signal "^1.0.1" - uint8arraylist "^2.4.3" + race-signal "^1.0.2" + uint8arraylist "^2.4.7" "@lukeed/ms@^2.0.1": version "2.0.1" @@ -1709,15 +1731,15 @@ "@multiformats/multiaddr" "^12.0.0" multiformats "^12.0.1" -"@multiformats/multiaddr@^12.0.0", "@multiformats/multiaddr@^12.1.10", "@multiformats/multiaddr@^12.1.3": - version "12.1.12" - resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-12.1.12.tgz#d1609933dc5589d53f6b77fb88fe5e5ea787deae" - integrity sha512-hrY4uN/oeYhn410jBSpVXn37eenn4djKOj6Dh20Yh4xzGgqmS6u+/X08zQfHgWNjk7NJejPUcRfHEfs8e/MOcw== +"@multiformats/multiaddr@^12.0.0", "@multiformats/multiaddr@^12.1.10", "@multiformats/multiaddr@^12.1.14", "@multiformats/multiaddr@^12.1.3": + version "12.1.14" + resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-12.1.14.tgz#d021072667f4dfc566cdddcb45feee60fecc8cfd" + integrity sha512-1C0Mo73chzu7pTzTquuKs5vUtw70jhqg1i6pUNznGb0WV6RFa6vyB+D697Os5+cLx+DiItrAY6VzMtlGQsMzYg== dependencies: "@chainsafe/is-ip" "^2.0.1" "@chainsafe/netmask" "^2.0.0" "@libp2p/interface" "^1.0.0" - dns-over-http-resolver "3.0.0" + dns-over-http-resolver "^3.0.2" multiformats "^13.0.0" uint8-varint "^2.0.1" uint8arrays "^5.0.0" @@ -1792,46 +1814,29 @@ resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.4.0.tgz#e3f69e3ce935683dd8dadb636652a5cb5cd5958c" integrity sha512-xaUaUUDWbHIFSxaQ/pIe+33VG2mfJp6N/KxKLmZr5biWdNznCAmfu24QRhX10BbVAuqOahAoyp0S4M9md6GPDw== -"@noble/curves@1.0.0", "@noble/curves@~1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.0.0.tgz#e40be8c7daf088aaf291887cbc73f43464a92932" - integrity sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw== - dependencies: - "@noble/hashes" "1.3.0" - -"@noble/curves@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" - integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== +"@noble/curves@1.3.0", "@noble/curves@^1.1.0", "@noble/curves@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" + integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== dependencies: - "@noble/hashes" "1.3.1" + "@noble/hashes" "1.3.3" "@noble/hashes@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== -"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" - integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== - -"@noble/hashes@1.3.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.0", "@noble/hashes@~1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" - integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== - -"@noble/hashes@1.3.1", "@noble/hashes@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" - integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== +"@noble/hashes@1.3.3", "@noble/hashes@^1.0.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@~1.3.2": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" + integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== -"@noble/hashes@^1.0.0", "@noble/hashes@~1.0.0": +"@noble/hashes@~1.0.0": version "1.0.0" - resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.0.0.tgz#d5e38bfbdaba174805a4e649f13be9a9ed3351ae" integrity sha512-DZVbtY62kc3kkBtMHqwCOfXrT/hnoORy5BJ4+HU1IR59X0KWAOqsfzQPcUl/lQLlG7qXbe/fZ3r/emxtAl+sqg== -"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": +"@noble/secp256k1@1.7.1": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== @@ -2551,47 +2556,30 @@ "@scure/base@~1.0.0": version "1.0.0" - resolved "https://registry.npmjs.org/@scure/base/-/base-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.0.0.tgz#109fb595021de285f05a7db6806f2f48296fcee7" integrity sha512-gIVaYhUsy+9s58m/ETjSJVKHhKTBMmcRb9cEV5/5dwvfDlfORjKrFsDeDHWRrm6RjcPvCLZFwGJjAjLj1gg4HA== -"@scure/base@~1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" - integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== - -"@scure/bip32@1.1.5": +"@scure/base@~1.1.4": version "1.1.5" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" - integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== - dependencies: - "@noble/hashes" "~1.2.0" - "@noble/secp256k1" "~1.7.0" - "@scure/base" "~1.1.0" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" + integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== -"@scure/bip32@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.0.tgz#6c8d980ef3f290987736acd0ee2e0f0d50068d87" - integrity sha512-bcKpo1oj54hGholplGLpqPHRbIsnbixFtc06nwuNM5/dwSXOq/AAYoIBRsBmnZJSdfeNW5rnff7NTAz3ZCqR9Q== - dependencies: - "@noble/curves" "~1.0.0" - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" - -"@scure/bip39@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" - integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== +"@scure/bip32@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8" + integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ== dependencies: - "@noble/hashes" "~1.2.0" - "@scure/base" "~1.1.0" + "@noble/curves" "~1.3.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" -"@scure/bip39@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.0.tgz#a207e2ef96de354de7d0002292ba1503538fc77b" - integrity sha512-SX/uKq52cuxm4YFXWFaVByaSHJh2w3BnokVSeUJVCv6K7WulT9u2BuNRBhuFl8vAuYnzx9bEu9WgpcNYTrYieg== +"@scure/bip39@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527" + integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA== dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" "@scure/bip39@^1.0.0": version "1.0.0" @@ -2960,11 +2948,6 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.192.tgz#5790406361a2852d332d41635d927f1600811285" integrity sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A== -"@types/long@^4.0.1": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" - integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== - "@types/minimatch@^3.0.3": version "3.0.5" resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz" @@ -3011,11 +2994,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.5.tgz#4c6a79adf59a8e8193ac87a0e522605b16587258" integrity sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w== -"@types/node@11.11.6": - version "11.11.6" - resolved "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz" - integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== - "@types/node@18.15.13": version "18.15.13" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469" @@ -3859,11 +3837,6 @@ array-differ@^3.0.0: resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-3.0.0.tgz#3cbb3d0f316810eafcc47624734237d6aee4ae6b" integrity sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg== -array-filter@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz" - integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= - array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" @@ -3961,6 +3934,15 @@ asn1@^0.2.4: dependencies: safer-buffer "~2.1.0" +asn1js@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.5.tgz#5ea36820443dbefb51cc7f88a2ebb5b462114f38" + integrity sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ== + dependencies: + pvtsutils "^1.3.2" + pvutils "^1.1.3" + tslib "^2.4.0" + assert@^1.1.1: version "1.5.0" resolved "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz" @@ -4023,13 +4005,6 @@ atomic-sleep@^1.0.0: resolved "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== -available-typed-arrays@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz" - integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== - dependencies: - array-filter "^1.0.0" - available-typed-arrays@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" @@ -4091,11 +4066,6 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64url@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz" - integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== - basic-ftp@^5.0.2: version "5.0.3" resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.3.tgz#b14c0fe8111ce001ec913686434fe0c2fb461228" @@ -4173,16 +4143,6 @@ bintrees@1.0.1: resolved "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz" integrity sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ= -bip39@^3.0.2: - version "3.0.4" - resolved "https://registry.npmjs.org/bip39/-/bip39-3.0.4.tgz" - integrity sha512-YZKQlb752TrUWqHWj7XAwCSjYEgGAk+/Aas3V7NyjQeZYsztO8JnQUaCWhcnL4T+jL8nvB8typ2jRPzTlgugNw== - dependencies: - "@types/node" "11.11.6" - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - bip39@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" @@ -4391,7 +4351,7 @@ buffer@4.9.2, buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.2.1, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.7.1: +buffer@^5.2.1, buffer@^5.5.0, buffer@^5.7.1: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -4573,13 +4533,14 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" callsites@^3.0.0, callsites@^3.1.0: version "3.1.0" @@ -5304,14 +5265,7 @@ dateformat@^3.0.3: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1: - version "4.3.1" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" - integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== - dependencies: - ms "2.1.2" - -debug@4.3.4, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5417,10 +5371,10 @@ defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== -define-data-property@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.0.tgz#0db13540704e1d8d479a0656cf781267531b9451" - integrity sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g== +define-data-property@^1.0.1, define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== dependencies: get-intrinsic "^1.2.1" gopd "^1.0.1" @@ -5436,15 +5390,7 @@ define-lazy-prop@^3.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== -define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -define-properties@^1.2.0: +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -5462,6 +5408,11 @@ degenerator@^5.0.0: escodegen "^2.1.0" esprima "^4.0.1" +delay@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-6.0.0.tgz#43749aefdf6cabd9e17b0d00bd3904525137e607" + integrity sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -5564,7 +5515,7 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dns-over-http-resolver@3.0.0, dns-over-http-resolver@^2.1.1: +dns-over-http-resolver@^2.1.1, dns-over-http-resolver@^3.0.2: version "2.1.3" resolved "https://registry.yarnpkg.com/dns-over-http-resolver/-/dns-over-http-resolver-2.1.3.tgz#bb7f2e10cc18d960339a6e30e21b8c1d99be7b38" integrity sha512-zjRYFhq+CsxPAouQWzOsxNMvEN+SHisjzhX8EMxd2Y0EG3thvn6wXQgMJLnTDImkhe4jhLbOQpXtL10nALBOSA== @@ -5790,147 +5741,26 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.18.0-next.1: - version "1.18.0" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz" - integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.2" - is-callable "^1.2.3" - is-negative-zero "^2.0.1" - is-regex "^1.1.2" - is-string "^1.0.5" - object-inspect "^1.9.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.0" - -es-abstract@^1.18.0-next.2: - version "1.20.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.3.tgz#90b143ff7aedc8b3d189bcfac7f1e3e3f81e9da1" - integrity sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.6" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.2" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-abstract@^1.19.0, es-abstract@^1.19.5: - version "1.20.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" - integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - regexp.prototype.flags "^1.4.3" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-abstract@^1.20.4: - version "1.21.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" - integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== - dependencies: - array-buffer-byte-length "^1.0.0" - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.0" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.3" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - -es-abstract@^1.22.1: - version "1.22.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.2.tgz#90f7282d91d0ad577f505e423e52d4c1d93c1b8a" - integrity sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA== +es-abstract@^1.18.0-next.2, es-abstract@^1.20.4, es-abstract@^1.22.1: + version "1.22.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== dependencies: array-buffer-byte-length "^1.0.0" arraybuffer.prototype.slice "^1.0.2" available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + call-bind "^1.0.5" es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" function.prototype.name "^1.1.6" - get-intrinsic "^1.2.1" + get-intrinsic "^1.2.2" get-symbol-description "^1.0.0" globalthis "^1.0.3" gopd "^1.0.1" - has "^1.0.3" has-property-descriptors "^1.0.0" has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" internal-slot "^1.0.5" is-array-buffer "^3.0.2" is-callable "^1.2.7" @@ -5940,7 +5770,7 @@ es-abstract@^1.22.1: is-string "^1.0.7" is-typed-array "^1.1.12" is-weakref "^1.0.2" - object-inspect "^1.12.3" + object-inspect "^1.13.1" object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.5.1" @@ -5954,7 +5784,7 @@ es-abstract@^1.22.1: typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" - which-typed-array "^1.1.11" + which-typed-array "^1.1.13" es-set-tostringtag@^2.0.1: version "2.0.1" @@ -6157,17 +5987,7 @@ eslint-visitor-keys@^1.1.0: resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint-visitor-keys@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" - integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== - -eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -6220,16 +6040,7 @@ esm@^3.2.25: resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.0.tgz#80869754b1c6560f32e3b6929194a3fe07c5b82f" - integrity sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A== - dependencies: - acorn "^8.9.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" - -espree@^9.6.1: +espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== @@ -6279,25 +6090,15 @@ esutils@^2.0.2: resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -ethereum-cryptography@^1.0.0, ethereum-cryptography@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" - integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== - dependencies: - "@noble/hashes" "1.2.0" - "@noble/secp256k1" "1.7.1" - "@scure/bip32" "1.1.5" - "@scure/bip39" "1.1.1" - -ethereum-cryptography@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.0.0.tgz#e052b49fa81affae29402e977b8d3a31f88612b6" - integrity sha512-g25m4EtfQGjstWgVE1aIz7XYYjf3kH5kG17ULWVB5dH6uLahsoltOhACzSxyDV+fhn4gbR4xRrOXGe6r2uh4Bg== +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a" + integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA== dependencies: - "@noble/curves" "1.0.0" - "@noble/hashes" "1.3.0" - "@scure/bip32" "1.3.0" - "@scure/bip39" "1.2.0" + "@noble/curves" "1.3.0" + "@noble/hashes" "1.3.3" + "@scure/bip32" "1.3.3" + "@scure/bip39" "1.2.2" ethers@^5.7.1: version "5.7.2" @@ -6508,32 +6309,10 @@ fast-fifo@^1.1.0, fast-fifo@^1.2.0: resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" - integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-glob@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" - integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-glob@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== +fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -6619,17 +6398,10 @@ fastify@^4.19.0: semver "^7.5.0" tiny-lru "^11.0.1" -fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== - dependencies: - reusify "^1.0.4" - -fastq@^1.6.1: - version "1.11.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz" - integrity sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g== +fastq@^1.6.0, fastq@^1.6.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.0.tgz#ca5e1a90b5e68f97fc8b61330d5819b82f5fab03" + integrity sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w== dependencies: reusify "^1.0.4" @@ -6776,11 +6548,6 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= - foreground-child@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" @@ -6914,26 +6681,11 @@ fstream@^1.0.12: mkdirp ">=0.5 0" rimraf "2" -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function-bind@^1.1.2: +function-bind@^1.1.1, function-bind@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - function.prototype.name@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" @@ -6949,26 +6701,11 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2, functions-have-names@^1.2.3: +functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -gauge@^4.0.0: - version "4.0.2" - resolved "https://registry.npmjs.org/gauge/-/gauge-4.0.2.tgz" - integrity sha512-aSPRm2CvA9R8QyU5eXMFPd+cYkyxLsXHd2l5/FOH2V/eml//M04G6KZOmTap07O1PvEwNcl2NndyLfK8g3QrKA== - dependencies: - ansi-regex "^5.0.1" - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.3" - console-control-strings "^1.1.0" - has-unicode "^2.0.1" - signal-exit "^3.0.7" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.5" - gauge@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" @@ -7021,35 +6758,7 @@ get-func-name@^2.0.0, get-func-name@^2.0.2: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-intrinsic@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f" - integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-intrinsic@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - -get-intrinsic@^1.2.2: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== @@ -7064,12 +6773,7 @@ get-iterator@^1.0.2: resolved "https://registry.npmjs.org/get-iterator/-/get-iterator-1.0.2.tgz" integrity sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg== -get-iterator@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-2.0.0.tgz#c9ac9f8002e5d8d6b4dc9dae07c30945022a58c1" - integrity sha512-BDJawD5PU2gZv6Vlp8O28H4GnZcsr3h9gZUvnAP5xXP3WOy/QAoOsyMepSkw21jur+4t5Vppde72ChjhTIzxzg== - -get-iterator@^2.0.1: +get-iterator@^2.0.0, get-iterator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-2.0.1.tgz#a904829f61bace789e0d64bd1a504c511a015c3f" integrity sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg== @@ -7249,7 +6953,7 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.0: +glob@^8.0.0, glob@^8.0.1: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -7260,28 +6964,7 @@ glob@^8.0.0: minimatch "^5.0.1" once "^1.3.0" -glob@^8.0.1: - version "8.0.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" - integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - -glob@^9.2.0: - version "9.3.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.4.tgz#e75dee24891a80c25cc7ee1dd327e126b98679af" - integrity sha512-qaSc49hojMOv1EPM4EuyITjDSgSKI0rthoHnvE81tcOi1SCVndHko7auqxdQ14eiQG2NDBJBE86+2xIrbIvrbA== - dependencies: - fs.realpath "^1.0.0" - minimatch "^8.0.2" - minipass "^4.2.4" - path-scurry "^1.6.1" - -glob@^9.3.0, glob@^9.3.1: +glob@^9.2.0, glob@^9.3.1: version "9.3.5" resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== @@ -7370,21 +7053,11 @@ got@^12.6.1: p-cancelable "^3.0.0" responselike "^3.0.0" -graceful-fs@4.2.11, graceful-fs@^4.2.2: +graceful-fs@4.2.11, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== - -graceful-fs@^4.2.6: - version "4.2.9" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== - grapheme-splitter@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" @@ -7427,19 +7100,19 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== dependencies: - get-intrinsic "^1.1.1" + get-intrinsic "^1.2.2" has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== -has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -7706,20 +7379,10 @@ ignore-walk@^6.0.0: dependencies: minimatch "^7.4.2" -ignore@^5.0.4, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== - -ignore@^5.1.1: - version "5.1.8" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== - -ignore@^5.2.4: - version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +ignore@^5.0.4, ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" + integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -7841,28 +7504,18 @@ inquirer@^9.1.5: wrap-ansi "^8.1.0" interface-datastore@^8.0.0, interface-datastore@^8.2.0, interface-datastore@^8.2.7: - version "8.2.7" - resolved "https://registry.yarnpkg.com/interface-datastore/-/interface-datastore-8.2.7.tgz#6a1e168fd98a271a92b85223bae58fa30031fb9c" - integrity sha512-ot5B5+VogufRfjhedAXZHm5NuEKyYZkDyVpTjBYIrxYUpS5GIfF2soE/dsd/FiBVqubcxa4IEToMXL5ruMwhjw== + version "8.2.10" + resolved "https://registry.yarnpkg.com/interface-datastore/-/interface-datastore-8.2.10.tgz#2d7fc026c8185378c4d3433fe942d9d6838f95cb" + integrity sha512-D8RuxMdjOPB+j6WMDJ+I2aXTDzUT6DIVjgzo1E+ODL7w8WrSFl9FXD2SYmgj6vVzdb7Kb5qmAI9pEnDZJz7ifg== dependencies: interface-store "^5.0.0" - nanoid "^5.0.3" - uint8arrays "^4.0.2" + uint8arrays "^5.0.0" interface-store@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/interface-store/-/interface-store-5.1.0.tgz#1735cead844fe452d62c307fafbaaa1d261e6ff3" integrity sha512-mjUwX3XSoreoxCS3sXS3pSRsGnUjl9T06KBqt/T7AgE9Sgp4diH64ZyURJKnj2T5WmCvTbC0Dm+mwQV5hfLSBQ== -internal-slot@^1.0.3: - version "1.0.6" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" - integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== - dependencies: - get-intrinsic "^1.2.2" - hasown "^2.0.0" - side-channel "^1.0.4" - internal-slot@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" @@ -7882,7 +7535,7 @@ ip-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-5.0.0.tgz#cd313b2ae9c80c07bd3851e12bf4fa4dc5480632" integrity sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw== -ip@^1.1.5, ip@^1.1.8: +ip@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== @@ -7955,16 +7608,11 @@ is-buffer@^2.0.5: resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.3, is-callable@^1.2.6, is-callable@^1.2.7: +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - is-ci@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" @@ -7972,40 +7620,12 @@ is-ci@3.0.1: dependencies: ci-info "^3.2.0" -is-core-module@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.3.0, is-core-module@^2.5.0, is-core-module@^2.8.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: - has "^1.0.3" - -is-core-module@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== - dependencies: - has "^1.0.3" - -is-core-module@^2.3.0: - version "2.5.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz" - integrity sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg== - dependencies: - has "^1.0.3" - -is-core-module@^2.5.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" - integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== - dependencies: - has "^1.0.3" - -is-core-module@^2.8.1, is-core-module@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== - dependencies: - has "^1.0.3" + hasown "^2.0.0" is-date-object@^1.0.1: version "1.0.5" @@ -8044,14 +7664,7 @@ is-generator-function@^1.0.7: resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz" integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== -is-glob@^4.0.0, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -8109,7 +7722,7 @@ is-nan@^1.2.1: call-bind "^1.0.0" define-properties "^1.1.3" -is-negative-zero@^2.0.1, is-negative-zero@^2.0.2: +is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== @@ -8178,7 +7791,7 @@ is-property@^1.0.0, is-property@^1.0.2: resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g== -is-regex@^1.1.2, is-regex@^1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -8236,35 +7849,13 @@ is-text-path@^1.0.1: dependencies: text-extensions "^1.0.0" -is-typed-array@^1.1.10, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -is-typed-array@^1.1.12: +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.3, is-typed-array@^1.1.9: version "1.1.12" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: which-typed-array "^1.1.11" -is-typed-array@^1.1.3: - version "1.1.5" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz" - integrity sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug== - dependencies: - available-typed-arrays "^1.0.2" - call-bind "^1.0.2" - es-abstract "^1.18.0-next.2" - foreach "^2.0.5" - has-symbols "^1.0.1" - is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" @@ -8324,26 +7915,12 @@ isomorphic-ws@^5.0.0: resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== -istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== - -istanbul-lib-coverage@^3.2.2: +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-report@^3.0.1: +istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== @@ -8369,12 +7946,7 @@ istanbul-reports@^3.1.6: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -it-all@^3.0.0, it-all@^3.0.1, it-all@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/it-all/-/it-all-3.0.2.tgz#620b82c702c9c6d1c4caddb6407dba4a4baa970b" - integrity sha512-ujqWETXhsDbF6C+6X6fvRw5ohlowRoy/o/h9BC8D+R3JQ13oLQ153w9gSWkWupOY7omZFQbJiAL1aJo5Gwe2yw== - -it-all@^3.0.4: +it-all@^3.0.0, it-all@^3.0.1, it-all@^3.0.2, it-all@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/it-all/-/it-all-3.0.4.tgz#08f2e3eb3df04fa4525a343dcacfbdf91ffee162" integrity sha512-UMiy0i9DqCHBdWvMbzdYvVGa5/w4t1cc4nchpbnjdLhklglv8mQeEYnii0gvKESJuL1zV32Cqdb33R6/GPfxpQ== @@ -8388,15 +7960,10 @@ it-byte-stream@^1.0.0: it-stream-types "^2.0.1" uint8arraylist "^2.4.1" -it-drain@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/it-drain/-/it-drain-3.0.2.tgz#4fb2ab30119072268c68a895fa5b9f2037942c44" - integrity sha512-0hJvS/4Ktt9wT/bktmovjjMAY8r6FCsXqpL3zjqBBNwoL21VgQfguEnwbLSGuCip9Zq1vfU43cbHkmaRZdBfOg== - -it-drain@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/it-drain/-/it-drain-3.0.3.tgz#f80719d3d0d7e7d02dc298d86ca9d0e7f7bd666b" - integrity sha512-l4s+izxUpFAR2axprpFiCaq0EtxK1QMd0LWbEtau5b+OegiZ5xdRtz35iJyh6KZY9QtuwEiQxydiOfYJc7stoA== +it-drain@^3.0.1, it-drain@^3.0.3: + version "3.0.5" + resolved "https://registry.yarnpkg.com/it-drain/-/it-drain-3.0.5.tgz#d7aed18a16a12c157fa477653fb42c1b4f08491c" + integrity sha512-qYFe4SWdvs9oJGUY5bSjvmiLUMLzFEODNOQUdYdCIkuIgQF+AUB2INhM4yQ09buJ2rhHKDFxvTD/+yUq6qg0XA== it-filter@^3.0.0: version "3.0.2" @@ -8412,39 +7979,27 @@ it-foreach@^2.0.3: dependencies: it-peekable "^3.0.0" -it-length-prefixed-stream@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/it-length-prefixed-stream/-/it-length-prefixed-stream-1.0.2.tgz#dbcb291118fc9cf031c89ab4be3f99cdb452f548" - integrity sha512-gWevodoctgwWUaRJN9t+xEs1H1GQNYAjLCR7FO50fon9Ph4OJGgrxPKTc26QXKrC/cIQZLkHYClphUw0wl1k2A== +it-length-prefixed-stream@^1.0.0, it-length-prefixed-stream@^1.1.1: + version "1.1.6" + resolved "https://registry.yarnpkg.com/it-length-prefixed-stream/-/it-length-prefixed-stream-1.1.6.tgz#b757b96d352da6e97b66002dd2ead32893ba2337" + integrity sha512-MEby4r8n3XIYXjaWT3DweCuhBPQmFVT8RdI1BNjYQ5gelbFD3NLdjYpTI3TVmSEs/aJfgpfVFZzy6iP7OCxIgw== dependencies: it-byte-stream "^1.0.0" - it-length-prefixed "^9.0.1" it-stream-types "^2.0.1" uint8-varint "^2.0.1" uint8arraylist "^2.4.1" -it-length-prefixed-stream@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/it-length-prefixed-stream/-/it-length-prefixed-stream-1.1.4.tgz#5e5a73685e820366d9a9dd944decef55b46f09ef" - integrity sha512-6YcQ5jsaYnuXBqF+oSGjSdSY9jF7HWl7yh+dxYytXxbE2GcdiOpn6pLM7m6AlIID9MCzQqMY5nOzaiatQ8A3/A== - dependencies: - it-byte-stream "^1.0.0" - it-length-prefixed "^9.0.1" - it-stream-types "^2.0.1" - uint8-varint "^2.0.1" - uint8arraylist "^2.4.1" - -it-length-prefixed@^9.0.1, it-length-prefixed@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/it-length-prefixed/-/it-length-prefixed-9.0.3.tgz#73af16f786cab60a0a9bfc2997e88eb26d3a72ca" - integrity sha512-YAu424ceYpXctxtjcLOqn7vJq082CaoP8J646ZusYISfQc3bpzQErgTUqMFj81V262KG2W9/YMBHsy6A/4yvmg== +it-length-prefixed@^9.0.1, it-length-prefixed@^9.0.3, it-length-prefixed@^9.0.4: + version "9.0.4" + resolved "https://registry.yarnpkg.com/it-length-prefixed/-/it-length-prefixed-9.0.4.tgz#8096c3270420fe8abaa920c7b4d5e5895144008e" + integrity sha512-lz28fykbG0jq7s5XtvlzGxO5BeSOw6ikymkRllxjL21V5VKLcvB4pHr9wPvEnsAJ2et1xpOk3BRTMq9XrhgKsg== dependencies: err-code "^3.0.1" it-reader "^6.0.1" it-stream-types "^2.0.1" uint8-varint "^2.0.1" uint8arraylist "^2.0.0" - uint8arrays "^4.0.2" + uint8arrays "^5.0.1" it-map@^3.0.1: version "3.0.3" @@ -8453,14 +8008,7 @@ it-map@^3.0.1: dependencies: it-peekable "^3.0.0" -it-merge@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/it-merge/-/it-merge-3.0.1.tgz#20cc293593586e5afcbfed8ba88a94def5ccfcfa" - integrity sha512-I6hjU1ABO+k3xY1H6JtCSDXvUME88pxIXSgKeT4WI5rPYbQzpr98ldacVuG95WbjaJxKl6Qot6lUdxduLBQPHA== - dependencies: - it-pushable "^3.1.0" - -it-merge@^3.0.1: +it-merge@^3.0.0, it-merge@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/it-merge/-/it-merge-3.0.3.tgz#c7d407c8e0473accf7f9958ce2e0f60276002e84" integrity sha512-FYVU15KC5pb/GQX1Ims+lee8d4pdqGVCpWr0lkNj8o4xuNo7jY71k6GuEiWdP+T7W1bJqewSxX5yoTy5yZpRVA== @@ -8506,19 +8054,7 @@ it-protobuf-stream@^1.0.2: protons-runtime "^5.0.0" uint8arraylist "^2.4.1" -it-pushable@^3.0.0, it-pushable@^3.1.0, it-pushable@^3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/it-pushable/-/it-pushable-3.1.3.tgz#b6f4a1e0236502f12b5661b40468b629799baf0e" - integrity sha512-f50iQ85HISS6DaWCyrqf9QJ6G/kQtKIMf9xZkgZgyOvxEQDfn8OfYcLXXquCqgoLboxQtAW1ZFZyFIAsLHDtJw== - -it-pushable@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/it-pushable/-/it-pushable-3.2.1.tgz#72d7ccf7e7c0ccecf8cbaf74064f7be56e775c59" - integrity sha512-sLFz2Q0oyDCJpTciZog7ipP4vSftfPy3e6JnH6YyztRa1XqkpGQaafK3Jw/JlfEBtCXfnX9uVfcpu3xpSAqCVQ== - dependencies: - p-defer "^4.0.0" - -it-pushable@^3.2.1, it-pushable@^3.2.2: +it-pushable@^3.0.0, it-pushable@^3.1.2, it-pushable@^3.2.0, it-pushable@^3.2.1, it-pushable@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/it-pushable/-/it-pushable-3.2.3.tgz#e2b80aed90cfbcd54b620c0a0785e546d4e5f334" integrity sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg== @@ -9182,10 +8718,10 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== -lru-cache@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" - integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== +lru-cache@^10.1.0, "lru-cache@^9.1.1 || ^10.0.0": + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== lru-cache@^5.1.1: version "5.1.1" @@ -9201,26 +8737,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lru-cache@^7.14.1: +lru-cache@^7.14.1, lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: version "7.18.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -lru-cache@^7.4.4, lru-cache@^7.5.1: - version "7.14.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.0.tgz#21be64954a4680e303a09e9468f880b98a0b3c7f" - integrity sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ== - -lru-cache@^7.7.1: - version "7.10.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.10.1.tgz#db577f42a94c168f676b638d15da8fb073448cab" - integrity sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A== - -"lru-cache@^9.1.1 || ^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" - integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== - magic-string@^0.30.3, magic-string@^0.30.5: version "0.30.5" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" @@ -9252,13 +8773,6 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - make-error@^1.1.1: version "1.3.6" resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" @@ -9286,28 +8800,7 @@ make-fetch-happen@^10.0.3: socks-proxy-agent "^7.0.0" ssri "^9.0.0" -make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1: - version "11.1.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.1.0.tgz#f26b05e89317e960b75fd5e080e40d40f8d7b2a5" - integrity sha512-7ChuOzCb1LzdQZrTy0ky6RsCoMYeM+Fh4cY0+4zsJVhNcH5Q3OJojLY1mGkD0xAhWB29lskECVb6ZopofwjldA== - dependencies: - agentkeepalive "^4.2.1" - cacache "^17.0.0" - http-cache-semantics "^4.1.1" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^7.7.1" - minipass "^4.0.0" - minipass-fetch "^3.0.0" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.3" - promise-retry "^2.0.1" - socks-proxy-agent "^7.0.0" - ssri "^10.0.0" - -make-fetch-happen@^11.0.3, make-fetch-happen@^11.1.1: +make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1, make-fetch-happen@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz#85ceb98079584a9523d4bf71d32996e7e208549f" integrity sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w== @@ -9808,12 +9301,7 @@ multiformats@^12.0.1: resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-12.0.1.tgz#dd3e19dd44114c2672e4795a36888d263be30131" integrity sha512-s01wijBJoDUqESWSzePY0lvTw7J3PVO9x2Cc6ASI5AMZM2Gnhh7BC17+nlFhHKU7dDzaCaRfb+NiqNzOsgPUoQ== -multiformats@^12.1.3: - version "12.1.3" - resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-12.1.3.tgz#cbf7a9861e11e74f8228b21376088cb43ba8754e" - integrity sha512-eajQ/ZH7qXZQR2AgtfpmSMizQzmyYVmCql7pdhldPuYQi4atACekbJaQplk6dWyIi10jCaFnd6pqvcEFXjbaJw== - -multiformats@^13.0.0: +multiformats@^13.0.0, multiformats@^13.0.1: version "13.0.1" resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-13.0.1.tgz#c0622affa5171189eacd57c06f977195ca7acb08" integrity sha512-bt3R5iXe2O8xpp3wkmQhC73b/lC4S2ihU8Dndwcsysqbydqb8N+bpP116qMcClZ17g58iSIwtXUTcg2zT4sniA== @@ -9864,11 +9352,6 @@ nanoid@^4.0.0: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e" integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw== -nanoid@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.0.3.tgz#6c97f53d793a7a1de6a38ebb46f50f95bf9793c7" - integrity sha512-I7X2b22cxA4LIHXPSqbBCEQSL+1wv8TuoefejsX4HFWyC6jc5JG7CEaxOltiKjc1M+YCS2YkrZZcj4+dytw9GA== - napi-macros@~2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz" @@ -9919,15 +9402,17 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7: version "2.6.7" - resolved "https://registry.npmjs.org/@achingbrain/node-fetch/-/node-fetch-2.6.7.tgz" - integrity sha512-iTASGs+HTFK5E4ZqcMsHmeJ4zodyq8L38lZV33jwqcBJYoUt3HjN4+ot+O9/0b+ke8ddE7UgOtVuZN/OkV19/g== + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" -node-fetch@^2.6.12: - version "2.6.12" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" - integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== +node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -9966,32 +9451,16 @@ node-gyp@^8.4.0: tar "^6.1.2" which "^2.0.2" -node-gyp@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.0.0.tgz#e1da2067427f3eb5bb56820cb62bc6b1e4bd2089" - integrity sha512-Ma6p4s+XCTPxCuAMrOA/IJRmVy16R8Sdhtwl4PrCr7IBlj4cPawF0vg/l7nOT1jPbuNS7lIRJpBSvVsXwEZuzw== - dependencies: - env-paths "^2.2.0" - glob "^7.1.4" - graceful-fs "^4.2.6" - make-fetch-happen "^10.0.3" - nopt "^5.0.0" - npmlog "^6.0.0" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.2" - which "^2.0.2" - -node-gyp@^9.4.0: - version "9.4.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.0.tgz#2a7a91c7cba4eccfd95e949369f27c9ba704f369" - integrity sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg== +node-gyp@^9.0.0, node-gyp@^9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.1.tgz#8a1023e0d6766ecb52764cc3a734b36ff275e185" + integrity sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ== dependencies: env-paths "^2.2.0" exponential-backoff "^3.1.1" glob "^7.1.4" graceful-fs "^4.2.6" - make-fetch-happen "^11.0.3" + make-fetch-happen "^10.0.3" nopt "^6.0.0" npmlog "^6.0.0" rimraf "^3.0.2" @@ -10202,20 +9671,7 @@ npm-pick-manifest@^8.0.0: npm-package-arg "^10.0.0" semver "^7.3.5" -npm-registry-fetch@^14.0.0, npm-registry-fetch@^14.0.3: - version "14.0.4" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-14.0.4.tgz#43dfa55ce7c0d0c545d625c7a916bab5b95f7038" - integrity sha512-pMS2DRkwg+M44ct65zrN/Cr9IHK1+n6weuefAo6Er4lc+/8YBCU0Czq04H3ZiSigluh7pb2rMM5JpgcytctB+Q== - dependencies: - make-fetch-happen "^11.0.0" - minipass "^4.0.0" - minipass-fetch "^3.0.0" - minipass-json-stream "^1.0.1" - minizlib "^2.1.2" - npm-package-arg "^10.0.0" - proc-log "^3.0.0" - -npm-registry-fetch@^14.0.5: +npm-registry-fetch@^14.0.0, npm-registry-fetch@^14.0.3, npm-registry-fetch@^14.0.5: version "14.0.5" resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz#fe7169957ba4986a4853a650278ee02e568d115d" integrity sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA== @@ -10230,7 +9686,7 @@ npm-registry-fetch@^14.0.5: npm-run-all@^4.1.5: version "4.1.5" - resolved "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== dependencies: ansi-styles "^3.2.1" @@ -10257,17 +9713,7 @@ npm-run-path@^5.1.0: dependencies: path-key "^4.0.0" -npmlog@^6.0.0: - version "6.0.1" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz" - integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg== - dependencies: - are-we-there-yet "^3.0.0" - console-control-strings "^1.1.0" - gauge "^4.0.0" - set-blocking "^2.0.0" - -npmlog@^6.0.2: +npmlog@^6.0.0, npmlog@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== @@ -10345,20 +9791,10 @@ object-hash@^2.0.1: resolved "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz" integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== -object-inspect@^1.12.0: - version "1.12.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.1.tgz#28a661153bad7e470e4b01479ef1cb91ce511191" - integrity sha512-Y/jF6vnvEtOPGiKD1+q+X0CiUYRQtEHp89MLLUJ7TUivtH8Ugn2+3A7Rynqk7BRsAoqeOQWnFnjpDrKSxDgIGA== - -object-inspect@^1.12.2, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-inspect@^1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== +object-inspect@^1.13.1, object-inspect@^1.9.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== object-is@^1.0.1: version "1.1.5" @@ -10373,7 +9809,7 @@ object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.2, object.assign@^4.1.4: +object.assign@^4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== @@ -10651,13 +10087,13 @@ p-queue@^7.2.0: eventemitter3 "^4.0.7" p-timeout "^5.0.2" -p-queue@^7.4.1: - version "7.4.1" - resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-7.4.1.tgz#7f86f853048beca8272abdbb7cec1ed2afc0f265" - integrity sha512-vRpMXmIkYF2/1hLBKisKeVYJZ8S2tZ0zEAmIJgdVKP2nq0nh4qCdf8bgw+ZgKrkh71AOCaqzwbJJk1WtdcF3VA== +p-queue@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-8.0.1.tgz#718b7f83836922ef213ddec263ff4223ce70bef8" + integrity sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA== dependencies: eventemitter3 "^5.0.1" - p-timeout "^5.0.2" + p-timeout "^6.1.2" p-reduce@2.1.0, p-reduce@^2.0.0, p-reduce@^2.1.0: version "2.1.0" @@ -10676,10 +10112,10 @@ p-timeout@^5.0.2: resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-5.1.0.tgz#b3c691cf4415138ce2d9cfe071dba11f0fee085b" integrity sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew== -p-timeout@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-6.1.1.tgz#bcee5e37d730f5474d973b6ff226751a1a5e6ff1" - integrity sha512-yqz2Wi4fiFRpMmK0L2pGAU49naSUaP23fFIQL2Y6YT+qDGPoFwpvgQM/wzc6F8JoenUkIlAFa4Ql7NguXBxI7w== +p-timeout@^6.0.0, p-timeout@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-6.1.2.tgz#22b8d8a78abf5e103030211c5fc6dee1166a6aa5" + integrity sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ== p-try@^1.0.0: version "1.0.0" @@ -10857,7 +10293,7 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== -path-parse@^1.0.5, path-parse@^1.0.6, path-parse@^1.0.7: +path-parse@^1.0.5, path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -10892,7 +10328,7 @@ pathval@^1.1.1: resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pbkdf2@^3.0.3, pbkdf2@^3.0.9: +pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -10913,12 +10349,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4: - version "2.2.3" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz" - integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg== - -picomatch@^2.2.1, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -11076,15 +10507,7 @@ progress@2.0.3, progress@^2.0.3: resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -prom-client@^15.0.0: - version "15.0.0" - resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.0.0.tgz#067da874a2aa5d2e21bd5cdba9f24a8178bdab6a" - integrity sha512-UocpgIrKyA2TKLVZDSfm8rGkL13C19YrQBAiG3xo3aDFWcHedxRxI3z+cIcucoxpSO0h5lff5iv/SXoxyeopeA== - dependencies: - "@opentelemetry/api" "^1.4.0" - tdigest "^0.1.1" - -prom-client@^15.1.0: +prom-client@^15.0.0, prom-client@^15.1.0: version "15.1.0" resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.1.0.tgz#816a4a2128da169d0471093baeccc6d2f17a4613" integrity sha512-cCD7jLTqyPdjEPBo/Xk4Iu8jxjuZgZJ3e/oET3L+ZwOuap/7Cw3dH/TJSsZKs1TQLZ2IHpIlRAKw82ef06kmMw== @@ -11128,29 +10551,10 @@ properties-reader@^2.2.0: dependencies: mkdirp "^1.0.4" -protobufjs@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.0.0.tgz#8c678e1351fd926178fce5a4213913e8d990974f" - integrity sha512-ffNIEm+quOcYtQvHdW406v1NQmZSuqVklxsXk076BtuFnlYZfigLU+JOMrTD8TUOyqHYbRI/fSVNvgd25YeN3w== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.1" - "@types/node" ">=13.7.0" - long "^5.0.0" - -protobufjs@^7.2.4: - version "7.2.4" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.4.tgz#3fc1ec0cdc89dd91aef9ba6037ba07408485c3ae" - integrity sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ== +protobufjs@^7.0.0, protobufjs@^7.2.6: + version "7.2.6" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.2.6.tgz#4a0ccd79eb292717aacf07530a07e0ed20278215" + integrity sha512-dgJaEDDL6x8ASUZ1YqWciTRrdOuYNzoOf27oHNfdyvKqHr5i0FV7FSLU+aIeFjyFgVxrpTOtQUi0BLLBymZaBw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -11219,16 +10623,11 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -psl@^1.1.28: +psl@^1.1.28, psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== -psl@^1.1.33: - version "1.8.0" - resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" @@ -11251,20 +10650,15 @@ pump@^3.0.0: punycode@1.3.2: version "1.3.2" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== -punycode@^2.3.1: +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -11281,6 +10675,18 @@ puppeteer-core@^20.9.0: devtools-protocol "0.0.1147663" ws "8.13.0" +pvtsutils@^1.3.2: + version "1.3.5" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.5.tgz#b8705b437b7b134cd7fd858f025a23456f1ce910" + integrity sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA== + dependencies: + tslib "^2.6.1" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + qs@^6.11.0, qs@^6.11.1: version "6.11.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f" @@ -11338,7 +10744,7 @@ race-event@^1.1.0: resolved "https://registry.yarnpkg.com/race-event/-/race-event-1.1.0.tgz#69c2d855653acf11d8b23ea8f6fa50e1180a088b" integrity sha512-8BTiN6IAbov8mqkVEc3LiYbtUzanLfzFhwPF7kZV74ztYeQXdFPIgMCd/sy8xie6ZMtf2JPeMBedx78/RRNO3g== -race-signal@^1.0.1, race-signal@^1.0.2: +race-signal@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/race-signal/-/race-signal-1.0.2.tgz#e42379fba0cec4ee8dab7c9bbbd4aa6e0d14c25f" integrity sha512-o3xNv0iTcIDQCXFlF6fPAMEBRjFxssgGoRqLbg06m+AdzEXXLUmoNOoUHTVz2NoBI8hHwKFKoC6IqyNtWr2bww== @@ -11381,7 +10787,7 @@ read-package-json-fast@^3.0.0: json-parse-even-better-errors "^3.0.0" npm-normalize-package-bin "^3.0.0" -read-package-json@6.0.4: +read-package-json@6.0.4, read-package-json@^6.0.0: version "6.0.4" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-6.0.4.tgz#90318824ec456c287437ea79595f4c2854708836" integrity sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw== @@ -11391,16 +10797,6 @@ read-package-json@6.0.4: normalize-package-data "^5.0.0" npm-normalize-package-bin "^3.0.0" -read-package-json@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-6.0.1.tgz#566cb06bc05dbddefba4607e9096d5a9efbcd836" - integrity sha512-AaHqXxfAVa+fNL07x8iAghfKOds/XXsu7zoouIVsbm7PEbQ3nMWXlvjcbrNLjElnUHWQtAo4QEa0RXuvD4XlpA== - dependencies: - glob "^9.3.0" - json-parse-even-better-errors "^3.0.0" - normalize-package-data "^5.0.0" - npm-normalize-package-bin "^3.0.0" - read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" @@ -11444,7 +10840,7 @@ read@^2.0.0: dependencies: mute-stream "~1.0.0" -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@^2.3.7, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -11476,14 +10872,7 @@ readable-stream@^4.0.0: events "^3.3.0" process "^0.11.10" -readdir-glob@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.2.tgz#b185789b8e6a43491635b6953295c5c5e3fd224c" - integrity sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA== - dependencies: - minimatch "^5.1.0" - -readdir-glob@^1.1.2: +readdir-glob@^1.0.0, readdir-glob@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584" integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== @@ -11522,15 +10911,6 @@ regenerator-runtime@^0.11.0: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - regexp.prototype.flags@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" @@ -11587,23 +10967,7 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@^1.10.0, resolve@^1.22.1: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== - dependencies: - is-core-module "^2.9.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -resolve@^1.10.1: - version "1.16.1" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz" - integrity sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig== - dependencies: - path-parse "^1.0.6" - -resolve@^1.17.0: +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.17.0, resolve@^1.22.1: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -11796,24 +11160,10 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rxjs@^7.2.0: - version "7.3.0" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz" - integrity sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw== - dependencies: - tslib "~2.1.0" - -rxjs@^7.5.5: - version "7.5.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" - integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== - dependencies: - tslib "^2.1.0" - -rxjs@^7.8.0: - version "7.8.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" - integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== +rxjs@^7.2.0, rxjs@^7.5.5, rxjs@^7.8.0: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" @@ -11912,7 +11262,7 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.1: +semver@^6.1.0, semver@^6.2.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== @@ -11955,6 +11305,17 @@ set-cookie-parser@^2.4.1: resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz" integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== +set-function-length@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" + integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== + dependencies: + define-data-property "^1.1.1" + function-bind "^1.1.2" + get-intrinsic "^1.2.2" + gopd "^1.0.1" + has-property-descriptors "^1.0.1" + set-function-name@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" @@ -12130,15 +11491,7 @@ socks-proxy-agent@^8.0.1, socks-proxy-agent@^8.0.2: debug "^4.3.4" socks "^2.7.1" -socks@^2.6.1, socks@^2.6.2: - version "2.6.2" - resolved "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz" - integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== - dependencies: - ip "^1.1.5" - smart-buffer "^4.2.0" - -socks@^2.7.1: +socks@^2.6.1, socks@^2.6.2, socks@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== @@ -12396,15 +11749,6 @@ string.prototype.padend@^3.0.0: define-properties "^1.1.3" es-abstract "^1.18.0-next.2" -string.prototype.trim@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" - integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trim@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" @@ -12414,24 +11758,6 @@ string.prototype.trim@^1.2.8: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trimend@^1.0.4, string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimend@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" - integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trimend@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" @@ -12441,24 +11767,6 @@ string.prototype.trimend@^1.0.7: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trimstart@^1.0.4, string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimstart@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" - integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - string.prototype.trimstart@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" @@ -12496,14 +11804,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== - dependencies: - ansi-regex "^6.0.1" - -strip-ansi@^7.1.0: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -12892,16 +12193,7 @@ tough-cookie@^3.0.1: psl "^1.1.28" punycode "^2.1.1" -tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" - -tough-cookie@^4.1.3: +tough-cookie@^4.0.0, tough-cookie@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -12933,7 +12225,7 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -triple-beam@^1.2.0, triple-beam@^1.3.0: +triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== @@ -12991,7 +12283,7 @@ tsconfig@^7.0.0: strip-bom "^3.0.0" strip-json-comments "^2.0.0" -tslib@2.4.0, tslib@^2.3.0, tslib@^2.4.0: +tslib@2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== @@ -13001,31 +12293,11 @@ tslib@^1.10.0: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.2.0: - version "2.3.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz" - integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== - -tslib@^2.0.1: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.0, tslib@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tslib@^2.1.0: - version "2.2.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz" - integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== - -tslib@^2.5.0, tslib@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" - integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== - -tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== - tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz" @@ -13197,20 +12469,13 @@ uint8-varint@^2.0.0, uint8-varint@^2.0.1, uint8-varint@^2.0.2: uint8arraylist "^2.0.0" uint8arrays "^5.0.0" -uint8arraylist@^2.0.0, uint8arraylist@^2.4.1, uint8arraylist@^2.4.3, uint8arraylist@^2.4.7: +uint8arraylist@^2.0.0, uint8arraylist@^2.4.1, uint8arraylist@^2.4.3, uint8arraylist@^2.4.7, uint8arraylist@^2.4.8: version "2.4.8" resolved "https://registry.yarnpkg.com/uint8arraylist/-/uint8arraylist-2.4.8.tgz#5a4d17f4defd77799cb38e93fd5db0f0dceddc12" integrity sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ== dependencies: uint8arrays "^5.0.1" -uint8arrays@^4.0.2, uint8arrays@^4.0.4, uint8arrays@^4.0.6, uint8arrays@^4.0.9: - version "4.0.10" - resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-4.0.10.tgz#3ec5cde3348903c140e87532fc53f46b8f2e921f" - integrity sha512-AnJNUGGDJAgFw/eWu/Xb9zrVKEGlwJJCaeInlf3BkecE/zcTobk5YXYIPNQJO1q5Hh1QZrQQHf0JvcHqz2hqoA== - dependencies: - multiformats "^12.0.1" - uint8arrays@^5.0.0, uint8arrays@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-5.0.1.tgz#6016ef944379eabb6de605934ead4d7a698c9f07" @@ -13218,7 +12483,7 @@ uint8arrays@^5.0.0, uint8arrays@^5.0.1: dependencies: multiformats "^13.0.0" -unbox-primitive@^1.0.0, unbox-primitive@^1.0.2: +unbox-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== @@ -13281,7 +12546,7 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== -universalify@^0.1.0, universalify@^0.1.2: +universalify@^0.1.0: version "0.1.2" resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== @@ -13384,19 +12649,7 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@^0.12.0: - version "0.12.3" - resolved "https://registry.npmjs.org/util/-/util-0.12.3.tgz" - integrity sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -util@^0.12.4, util@^0.12.5: +util@^0.12.0, util@^0.12.4, util@^0.12.5: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== @@ -13894,41 +13147,16 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-typed-array@^1.1.11: - version "1.1.11" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" - integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -which-typed-array@^1.1.2: - version "1.1.4" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz" - integrity sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA== - dependencies: - available-typed-arrays "^1.0.2" - call-bind "^1.0.0" - es-abstract "^1.18.0-next.1" - foreach "^2.0.5" - function-bind "^1.1.1" - has-symbols "^1.0.1" - is-typed-array "^1.1.3" - -which-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" - integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== +which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.2: + version "1.1.13" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== dependencies: available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + call-bind "^1.0.4" for-each "^0.3.3" gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" which@^1.2.9: version "1.3.1" @@ -13983,18 +13211,10 @@ winston-daily-rotate-file@^4.7.1: triple-beam "^1.3.0" winston-transport "^4.4.0" -winston-transport@^4.4.0: - version "4.4.0" - resolved "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz" - integrity sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw== - dependencies: - readable-stream "^2.3.7" - triple-beam "^1.2.0" - -winston-transport@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" - integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== +winston-transport@^4.4.0, winston-transport@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.6.0.tgz#f1c1a665ad1b366df72199e27892721832a19e1b" + integrity sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg== dependencies: logform "^2.3.2" readable-stream "^3.6.0" @@ -14105,7 +13325,7 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@8.13.0, ws@^8.8.1: +ws@8.13.0: version "8.13.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== @@ -14115,10 +13335,10 @@ ws@8.5.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== -ws@^8.14.2, ws@^8.8.0: - version "8.14.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.14.2.tgz#6c249a806eb2db7a20d26d51e7709eab7b2e6c7f" - integrity sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g== +ws@^8.14.2, ws@^8.8.0, ws@^8.8.1: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== xml-name-validator@^5.0.0: version "5.0.0" @@ -14127,7 +13347,7 @@ xml-name-validator@^5.0.0: xml2js@0.4.19: version "0.4.19" - resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== dependencies: sax ">=0.6.0" @@ -14135,7 +13355,7 @@ xml2js@0.4.19: xml2js@^0.4.19: version "0.4.23" - resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== dependencies: sax ">=0.6.0" @@ -14224,7 +13444,7 @@ yargs@16.2.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@17.7.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.1: +yargs@17.7.1: version "17.7.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967" integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw== @@ -14237,7 +13457,7 @@ yargs@17.7.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.1: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@17.7.2: +yargs@17.7.2, yargs@^17.1.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -14250,19 +13470,6 @@ yargs@17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yargs@^17.1.1: - version "17.6.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" - integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" From b2c83ce79306e902f56614ec76d952bc338d82fe Mon Sep 17 00:00:00 2001 From: Phil Ngo <58080811+philknows@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:53:33 -0500 Subject: [PATCH 16/71] chore: update holesky.ts to include Lodestar bootnode (#6383) Update holesky.ts to include Lodestar bootnode --- packages/cli/src/networks/holesky.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cli/src/networks/holesky.ts b/packages/cli/src/networks/holesky.ts index 5c0f99ee53de..0f89cadaed33 100644 --- a/packages/cli/src/networks/holesky.ts +++ b/packages/cli/src/networks/holesky.ts @@ -13,4 +13,5 @@ export const bootEnrs = [ "enr:-Ly4QGbOw4xNel5EhmDsJJ-QhC9XycWtsetnWoZ0uRy381GHdHsNHJiCwDTOkb3S1Ade0SFQkWJX_pgb3g8Jfh93rvMBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpBpt9l0BAFwAAABAAAAAAAAgmlkgnY0gmlwhJK-DYCJc2VjcDI1NmsxoQOxKv9sv3zKF8GDewgFGGHKP5HCZZpPpTrwl9eXKAWGxIhzeW5jbmV0cwCDdGNwgiMog3VkcIIjKA", "enr:-LS4QG0uV4qvcpJ-HFDJRGBmnlD3TJo7yc4jwK8iP7iKaTlfQ5kZvIDspLMJhk7j9KapuL9yyHaZmwTEZqr10k9XumyCEcmHYXR0bmV0c4gAAAAABgAAAIRldGgykGm32XQEAXAAAAEAAAAAAACCaWSCdjSCaXCErK4j-YlzZWNwMjU2azGhAgfWRBEJlb7gAhXIB5ePmjj2b8io0UpEenq1Kl9cxStJg3RjcIIjKIN1ZHCCIyg", "enr:-Le4QLoE1wFHSlGcm48a9ZESb_MRLqPPu6G0vHqu4MaUcQNDHS69tsy-zkN0K6pglyzX8m24mkb-LtBcbjAYdP1uxm4BhGV0aDKQabfZdAQBcAAAAQAAAAAAAIJpZIJ2NIJpcIQ5gR6Wg2lwNpAgAUHQBwEQAAAAAAAAADR-iXNlY3AyNTZrMaEDPMSNdcL92uNIyCsS177Z6KTXlbZakQqxv3aQcWawNXeDdWRwgiMohHVkcDaCI4I", + "enr:-KG4QC9Wm32mtzB5Fbj2ri2TEKglHmIWgvwTQCvNHBopuwpNAi1X6qOsBg_Z1-Bee-kfSrhzUQZSgDUyfH5outUprtoBgmlkgnY0gmlwhHEel3eDaXA2kP6AAAAAAAAAAlBW__4Srr-Jc2VjcDI1NmsxoQO7KE63Z4eSI55S1Yn7q9_xFkJ1Wt-a3LgiXuKGs19s0YN1ZHCCIyiEdWRwNoIjKA", ]; From 863ee5f6252771ba3dc5024a1c385d0920402918 Mon Sep 17 00:00:00 2001 From: tuyennhv Date: Fri, 2 Feb 2024 02:51:07 +0700 Subject: [PATCH 17/71] fix: getAttestationsForBlock performance issue (#6367) * chore: enhance perf tests for getAttestationsForBlock * refactor: group attestations, cache forkchoice validation * fix: return only not seen indices for notSeenValidatorFn * fix: lint * chore: bring back finalizedSync.test.ts --- .../opPools/aggregatedAttestationPool.ts | 307 ++++++++++++------ .../test/e2e/sync/finalizedSync.test.ts | 124 +++++++ .../opPools/aggregatedAttestationPool.test.ts | 236 +++++++++++--- .../opPools/aggregatedAttestationPool.test.ts | 85 ++++- 4 files changed, 591 insertions(+), 161 deletions(-) create mode 100644 packages/beacon-node/test/e2e/sync/finalizedSync.test.ts diff --git a/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts b/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts index 00309d322a11..db7922758732 100644 --- a/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts +++ b/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts @@ -1,12 +1,6 @@ import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; -import { - ForkName, - MAX_ATTESTATIONS, - MIN_ATTESTATION_INCLUSION_DELAY, - SLOTS_PER_EPOCH, - TIMELY_SOURCE_FLAG_INDEX, -} from "@lodestar/params"; +import {ForkName, MAX_ATTESTATIONS, MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params"; import {phase0, Epoch, Slot, ssz, ValidatorIndex, RootHex} from "@lodestar/types"; import { CachedBeaconStateAllForks, @@ -24,9 +18,17 @@ import {InsertOutcome} from "./types.js"; type DataRootHex = string; +type CommitteeIndex = number; + type AttestationWithScore = {attestation: phase0.Attestation; score: number}; -type GetParticipationFn = (epoch: Epoch, committee: number[]) => Set | null; +/** + * This function returns not seen participation for a given epoch and committee. + * Return null if all validators are seen or no info to check. + */ +type GetNotSeenValidatorsFn = (epoch: Epoch, committee: number[]) => Set | null; + +type ValidateAttestationDataFn = (attData: phase0.AttestationData) => boolean; /** * Limit the max attestations with the same AttestationData. @@ -37,13 +39,13 @@ type GetParticipationFn = (epoch: Epoch, committee: number[]) => Set | n const MAX_RETAINED_ATTESTATIONS_PER_GROUP = 4; /** - * On mainnet, each slot has 64 committees, and each block has 128 attestations max so we don't - * want to store more than 2 per group. + * On mainnet, each slot has 64 committees, and each block has 128 attestations max so in average + * we get 2 attestation per groups. + * Starting from Jan 2024, we have a performance issue getting attestations for a block. Based on the + * fact that lot of groups will have only 1 attestation since it's full of participation increase this number + * a bit higher than average. This also help decrease number of slots to search for attestations. */ -const MAX_ATTESTATIONS_PER_GROUP = 2; - -/** Same to https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#has_flag */ -const TIMELY_SOURCE = 1 << TIMELY_SOURCE_FLAG_INDEX; +const MAX_ATTESTATIONS_PER_GROUP = 3; /** * Maintain a pool of aggregated attestations. Attestations can be retrieved for inclusion in a block @@ -52,19 +54,22 @@ const TIMELY_SOURCE = 1 << TIMELY_SOURCE_FLAG_INDEX; * Note that we want to remove attestations with attesters that were included in the chain. */ export class AggregatedAttestationPool { - private readonly attestationGroupByDataHashBySlot = new MapDef>( - () => new Map() - ); + private readonly attestationGroupByDataHashByIndexBySlot = new MapDef< + Slot, + Map> + >(() => new Map>()); private lowestPermissibleSlot = 0; /** For metrics to track size of the pool */ getAttestationCount(): {attestationCount: number; attestationDataCount: number} { let attestationCount = 0; let attestationDataCount = 0; - for (const attestationGroupByData of this.attestationGroupByDataHashBySlot.values()) { - attestationDataCount += attestationGroupByData.size; - for (const attestationGroup of attestationGroupByData.values()) { - attestationCount += attestationGroup.getAttestationCount(); + for (const attestationGroupByDataByIndex of this.attestationGroupByDataHashByIndexBySlot.values()) { + for (const attestationGroupByData of attestationGroupByDataByIndex.values()) { + attestationDataCount += attestationGroupByData.size; + for (const attestationGroup of attestationGroupByData.values()) { + attestationCount += attestationGroup.getAttestationCount(); + } } } return {attestationCount, attestationDataCount}; @@ -84,7 +89,12 @@ export class AggregatedAttestationPool { return InsertOutcome.Old; } - const attestationGroupByDataHash = this.attestationGroupByDataHashBySlot.getOrDefault(slot); + const attestationGroupByDataHashByIndex = this.attestationGroupByDataHashByIndexBySlot.getOrDefault(slot); + let attestationGroupByDataHash = attestationGroupByDataHashByIndex.get(attestation.data.index); + if (!attestationGroupByDataHash) { + attestationGroupByDataHash = new Map(); + attestationGroupByDataHashByIndex.set(attestation.data.index, attestationGroupByDataHash); + } let attestationGroup = attestationGroupByDataHash.get(dataRootHex); if (!attestationGroup) { attestationGroup = new MatchingDataAttestationGroup(committee, attestation.data); @@ -100,7 +110,7 @@ export class AggregatedAttestationPool { /** Remove attestations which are too old to be included in a block. */ prune(clockSlot: Slot): void { // Only retain SLOTS_PER_EPOCH slots - pruneBySlot(this.attestationGroupByDataHashBySlot, clockSlot, SLOTS_PER_EPOCH); + pruneBySlot(this.attestationGroupByDataHashByIndexBySlot, clockSlot, SLOTS_PER_EPOCH); this.lowestPermissibleSlot = Math.max(clockSlot - SLOTS_PER_EPOCH, 0); } @@ -112,15 +122,19 @@ export class AggregatedAttestationPool { const stateEpoch = state.epochCtx.epoch; const statePrevEpoch = stateEpoch - 1; - const getParticipation = getParticipationFn(state); + const notSeenValidatorsFn = getNotSeenValidatorsFn(state); + const validateAttestationDataFn = getValidateAttestationDataFn(forkChoice, state); const attestationsByScore: AttestationWithScore[] = []; - const slots = Array.from(this.attestationGroupByDataHashBySlot.keys()).sort((a, b) => b - a); + const slots = Array.from(this.attestationGroupByDataHashByIndexBySlot.keys()).sort((a, b) => b - a); + let minScore = Number.MAX_SAFE_INTEGER; + let slotCount = 0; slot: for (const slot of slots) { - const attestationGroupByDataHash = this.attestationGroupByDataHashBySlot.get(slot); + slotCount++; + const attestationGroupByDataHashByIndex = this.attestationGroupByDataHashByIndexBySlot.get(slot); // should not happen - if (!attestationGroupByDataHash) { + if (!attestationGroupByDataHashByIndex) { throw Error(`No aggregated attestation pool for slot=${slot}`); } @@ -134,34 +148,64 @@ export class AggregatedAttestationPool { continue; // Invalid attestations } - const attestationGroups = Array.from(attestationGroupByDataHash.values()); - for (const attestationGroup of attestationGroups) { - if (!isValidAttestationData(forkChoice, state, attestationGroup.data)) { + const slotDelta = stateSlot - slot; + const shuffling = state.epochCtx.getShufflingAtEpoch(epoch); + const slotCommittees = shuffling.committees[slot % SLOTS_PER_EPOCH]; + for (const [committeeIndex, attestationGroupByData] of attestationGroupByDataHashByIndex.entries()) { + // all attestations will be validated against the state in next step so we can get committee from the state + // this is an improvement to save the notSeenValidatorsFn call for the same slot/index instead of the same attestation data + if (committeeIndex > slotCommittees.length) { + // invalid index, should not happen continue; } - const participation = getParticipation(epoch, attestationGroup.committee); - if (participation === null) { + + const committee = slotCommittees[committeeIndex]; + const notSeenAttestingIndices = notSeenValidatorsFn(epoch, committee); + if (notSeenAttestingIndices === null || notSeenAttestingIndices.size === 0) { + continue; + } + + if ( + slotCount > 2 && + attestationsByScore.length >= MAX_ATTESTATIONS && + notSeenAttestingIndices.size / slotDelta < minScore + ) { + // after 2 slots, there are a good chance that we have 2 * MAX_ATTESTATIONS attestations and break the for loop early + // if not, we may have to scan all slots in the pool + // if we have enough attestations and the max possible score is lower than scores of `attestationsByScore`, we should skip + // otherwise it takes time to check attestation, add it and remove it later after the sort by score continue; } - // TODO: Is it necessary to validateAttestation for: - // - Attestation committee index not within current committee count - // - Attestation aggregation bits length does not match committee length - // - // These properties should not change after being validate in gossip - // IF they have to be validated, do it only with one attestation per group since same data - // The committeeCountPerSlot can be precomputed once per slot - - attestationsByScore.push( - ...attestationGroup.getAttestationsForBlock(participation).map((attestation) => ({ - attestation: attestation.attestation, - score: attestation.notSeenAttesterCount / (stateSlot - slot), - })) - ); - - // Stop accumulating attestations there are enough that may have good scoring - if (attestationsByScore.length > MAX_ATTESTATIONS * 2) { - break slot; + for (const attestationGroup of attestationGroupByData.values()) { + if (!validateAttestationDataFn(attestationGroup.data)) { + continue; + } + + // TODO: Is it necessary to validateAttestation for: + // - Attestation committee index not within current committee count + // - Attestation aggregation bits length does not match committee length + // + // These properties should not change after being validate in gossip + // IF they have to be validated, do it only with one attestation per group since same data + // The committeeCountPerSlot can be precomputed once per slot + for (const {attestation, notSeenAttesterCount} of attestationGroup.getAttestationsForBlock( + notSeenAttestingIndices + )) { + const score = notSeenAttesterCount / slotDelta; + if (score < minScore) { + minScore = score; + } + attestationsByScore.push({ + attestation, + score, + }); + } + + // Stop accumulating attestations there are enough that may have good scoring + if (attestationsByScore.length >= MAX_ATTESTATIONS * 2) { + break slot; + } } } } @@ -183,13 +227,15 @@ export class AggregatedAttestationPool { * @param bySlot slot to filter, `bySlot === attestation.data.slot` */ getAll(bySlot?: Slot): phase0.Attestation[] { - let attestationGroupsArr: Map[]; + let attestationGroupsArr: Map[]; if (bySlot === undefined) { - attestationGroupsArr = Array.from(this.attestationGroupByDataHashBySlot.values()); + attestationGroupsArr = Array.from(this.attestationGroupByDataHashByIndexBySlot.values()).flatMap((byIndex) => + Array.from(byIndex.values()) + ); } else { - const attestationGroups = this.attestationGroupByDataHashBySlot.get(bySlot); - if (!attestationGroups) throw Error(`No attestations for slot ${bySlot}`); - attestationGroupsArr = [attestationGroups]; + const attestationGroupsByIndex = this.attestationGroupByDataHashByIndexBySlot.get(bySlot); + if (!attestationGroupsByIndex) throw Error(`No attestations for slot ${bySlot}`); + attestationGroupsArr = Array.from(attestationGroupsByIndex.values()); } const attestations: phase0.Attestation[] = []; @@ -224,6 +270,7 @@ export class MatchingDataAttestationGroup { private readonly attestations: AttestationWithIndex[] = []; constructor( + // TODO: no need committee here readonly committee: ValidatorIndex[], readonly data: phase0.AttestationData ) {} @@ -284,24 +331,18 @@ export class MatchingDataAttestationGroup { return InsertOutcome.NewData; } - getAttestationsForBlock(seenAttestingIndices: Set): AttestationNonParticipant[] { + /** + * Get AttestationNonParticipant for this groups of same attestation data. + * @param notSeenAttestingIndices not seen attestting indices, i.e. indices in the same committee + * @returns an array of AttestationNonParticipant + */ + getAttestationsForBlock(notSeenAttestingIndices: Set): AttestationNonParticipant[] { const attestations: AttestationNonParticipant[] = []; - - const committeeLen = this.committee.length; - const committeeSeenAttesting = new Array(committeeLen); - - // Intersect committee with participation only once for all attestations - for (let i = 0; i < committeeLen; i++) { - committeeSeenAttesting[i] = seenAttestingIndices.has(this.committee[i]); - } - for (const {attestation} of this.attestations) { - const {aggregationBits} = attestation; let notSeenAttesterCount = 0; - - for (let i = 0; i < committeeLen; i++) { - // TODO: Optimize aggregationBits.get() in bulk for the entire BitArray - if (!committeeSeenAttesting[i] && aggregationBits.get(i)) { + const {aggregationBits} = attestation; + for (const notSeenIndex of notSeenAttestingIndices) { + if (aggregationBits.get(notSeenIndex)) { notSeenAttesterCount++; } } @@ -311,9 +352,13 @@ export class MatchingDataAttestationGroup { } } - return attestations - .sort((a, b) => b.notSeenAttesterCount - a.notSeenAttesterCount) - .slice(0, MAX_ATTESTATIONS_PER_GROUP); + if (attestations.length <= MAX_ATTESTATIONS_PER_GROUP) { + return attestations; + } else { + return attestations + .sort((a, b) => b.notSeenAttesterCount - a.notSeenAttesterCount) + .slice(0, MAX_ATTESTATIONS_PER_GROUP); + } } /** Get attestations for API. */ @@ -335,7 +380,7 @@ export function aggregateInto(attestation1: AttestationWithIndex, attestation2: * Pre-compute participation from a CachedBeaconStateAllForks, for use to check if an attestation's committee * has already attested or not. */ -export function getParticipationFn(state: CachedBeaconStateAllForks): GetParticipationFn { +export function getNotSeenValidatorsFn(state: CachedBeaconStateAllForks): GetNotSeenValidatorsFn { if (state.config.getForkName(state.slot) === ForkName.phase0) { // Get attestations to be included in a phase0 block. // As we are close to altair, this is not really important, it's mainly for e2e. @@ -344,18 +389,29 @@ export function getParticipationFn(state: CachedBeaconStateAllForks): GetPartici const phase0State = state as CachedBeaconStatePhase0; const stateEpoch = computeEpochAtSlot(state.slot); - const previousEpochParticipants = extractParticipation( + const previousEpochParticipants = extractParticipationPhase0( phase0State.previousEpochAttestations.getAllReadonly(), state ); - const currentEpochParticipants = extractParticipation(phase0State.currentEpochAttestations.getAllReadonly(), state); - - return (epoch: Epoch) => { - return epoch === stateEpoch - ? currentEpochParticipants - : epoch === stateEpoch - 1 - ? previousEpochParticipants - : null; + const currentEpochParticipants = extractParticipationPhase0( + phase0State.currentEpochAttestations.getAllReadonly(), + state + ); + + return (epoch: Epoch, committee: number[]) => { + const participants = + epoch === stateEpoch ? currentEpochParticipants : epoch === stateEpoch - 1 ? previousEpochParticipants : null; + if (participants === null) { + return null; + } + + const notSeenAttestingIndices = new Set(); + for (const [i, validatorIndex] of committee.entries()) { + if (!participants.has(validatorIndex)) { + notSeenAttestingIndices.add(i); + } + } + return notSeenAttestingIndices.size === 0 ? null : notSeenAttestingIndices; }; } @@ -374,20 +430,24 @@ export function getParticipationFn(state: CachedBeaconStateAllForks): GetPartici const participationStatus = epoch === stateEpoch ? currentParticipation : epoch === stateEpoch - 1 ? previousParticipation : null; - if (participationStatus === null) return null; + if (participationStatus === null) { + return null; + } - const seenValidatorIndices = new Set(); - for (const validatorIndex of committee) { - if (flagIsTimelySource(participationStatus[validatorIndex])) { - seenValidatorIndices.add(validatorIndex); + const notSeenAttestingIndices = new Set(); + for (const [i, validatorIndex] of committee.entries()) { + // no need to check flagIsTimelySource as if validator is not seen, it's participation status is 0 + if (participationStatus[validatorIndex] === 0) { + notSeenAttestingIndices.add(i); } } - return seenValidatorIndices; + // if all validators are seen then return null, we don't need to check for any attestations of same committee again + return notSeenAttestingIndices.size === 0 ? null : notSeenAttestingIndices; }; } } -export function extractParticipation( +export function extractParticipationPhase0( attestations: phase0.PendingAttestation[], state: CachedBeaconStateAllForks ): Set { @@ -408,7 +468,56 @@ export function extractParticipation( } /** - * Do those validations: + * This returns a function to validate if an attestation data is compatible to a state, + * it's an optimized version of isValidAttestationData(). + * Atttestation data is validated by: + * - Validate the source checkpoint + * - Validate shuffling using beacon block root and target epoch + * + * Here we always validate the source checkpoint, and cache beacon block root + target epoch + * to avoid running the same shuffling validation multiple times. + */ +export function getValidateAttestationDataFn( + forkChoice: IForkChoice, + state: CachedBeaconStateAllForks +): ValidateAttestationDataFn { + const cachedValidatedAttestationData = new Map(); + const {previousJustifiedCheckpoint, currentJustifiedCheckpoint} = state; + const stateEpoch = state.epochCtx.epoch; + return (attData: phase0.AttestationData) => { + const targetEpoch = attData.target.epoch; + let justifiedCheckpoint; + // simple check first + if (targetEpoch === stateEpoch) { + justifiedCheckpoint = currentJustifiedCheckpoint; + } else if (targetEpoch === stateEpoch - 1) { + justifiedCheckpoint = previousJustifiedCheckpoint; + } else { + return false; + } + + if (!ssz.phase0.Checkpoint.equals(attData.source, justifiedCheckpoint)) return false; + + // Shuffling can't have changed if we're in the first few epochs + // Also we can't look back 2 epochs if target epoch is 1 or less + if (stateEpoch < 2 || targetEpoch < 2) { + return true; + } + + // the isValidAttestationData does not depend on slot and index + const beaconBlockRootHex = toHex(attData.beaconBlockRoot); + const cacheKey = beaconBlockRootHex + targetEpoch; + let isValid = cachedValidatedAttestationData.get(cacheKey); + if (isValid === undefined) { + isValid = isValidShuffling(forkChoice, state, beaconBlockRootHex, targetEpoch); + cachedValidatedAttestationData.set(cacheKey, isValid); + } + return isValid; + }; +} + +/** + * A straight forward version to validate attestation data. We don't use it, but keep it here for reference. * - Validate the source checkpoint * - Since we validated attestation's signature in gossip validation function, * we only need to validate the shuffling of attestation @@ -441,6 +550,16 @@ export function isValidAttestationData( if (stateEpoch < 2 || targetEpoch < 2) { return true; } + const beaconBlockRootHex = toHex(data.beaconBlockRoot); + return isValidShuffling(forkChoice, state, beaconBlockRootHex, targetEpoch); +} + +function isValidShuffling( + forkChoice: IForkChoice, + state: CachedBeaconStateAllForks, + blockRootHex: RootHex, + targetEpoch: Epoch +): boolean { // Otherwise the shuffling is determined by the block at the end of the target epoch // minus the shuffling lookahead (usually 2). We call this the "pivot". const pivotSlot = computeStartSlotAtEpoch(targetEpoch - 1) - 1; @@ -450,7 +569,7 @@ export function isValidAttestationData( // pivot block is the same as the current state's pivot block. If it is, then the // attestation's shuffling is the same as the current state's. // To account for skipped slots, find the first block at *or before* the pivot slot. - const beaconBlockRootHex = toHex(data.beaconBlockRoot); + const beaconBlockRootHex = blockRootHex; const beaconBlock = forkChoice.getBlockHex(beaconBlockRootHex); if (!beaconBlock) { throw Error(`Attestation data.beaconBlockRoot ${beaconBlockRootHex} not found in forkchoice`); @@ -467,7 +586,3 @@ export function isValidAttestationData( } return attestationDependentRoot === stateDependentRoot; } - -function flagIsTimelySource(flag: number): boolean { - return (flag & TIMELY_SOURCE) === TIMELY_SOURCE; -} diff --git a/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts b/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts new file mode 100644 index 000000000000..d3d06f1fc070 --- /dev/null +++ b/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts @@ -0,0 +1,124 @@ +import {describe, it, afterEach} from "vitest"; +import {assert} from "chai"; +import {fromHexString} from "@chainsafe/ssz"; +import {ChainConfig} from "@lodestar/config"; +import {phase0} from "@lodestar/types"; +import {TimestampFormatCode} from "@lodestar/logger"; +import {SLOTS_PER_EPOCH} from "@lodestar/params"; +import {routes} from "@lodestar/api"; +import {EventData, EventType} from "@lodestar/api/lib/beacon/routes/events.js"; +import {getDevBeaconNode} from "../../utils/node/beacon.js"; +import {waitForEvent} from "../../utils/events/resolver.js"; +import {getAndInitDevValidators} from "../../utils/node/validator.js"; +import {ChainEvent} from "../../../src/chain/index.js"; +import {connect, onPeerConnect} from "../../utils/network.js"; +import {testLogger, LogLevel, TestLoggerOpts} from "../../utils/logger.js"; + +describe( + "sync / finalized sync", + function () { + const validatorCount = 8; + const testParams: Pick = { + // eslint-disable-next-line @typescript-eslint/naming-convention + SECONDS_PER_SLOT: 2, + }; + + const afterEachCallbacks: (() => Promise | void)[] = []; + afterEach(async () => { + while (afterEachCallbacks.length > 0) { + const callback = afterEachCallbacks.pop(); + if (callback) await callback(); + } + }); + + it("should do a finalized sync from another BN", async function () { + // single node at beginning, use main thread to verify bls + const genesisSlotsDelay = 4; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT; + + const testLoggerOpts: TestLoggerOpts = { + level: LogLevel.info, + timestampFormat: { + format: TimestampFormatCode.EpochSlot, + genesisTime, + slotsPerEpoch: SLOTS_PER_EPOCH, + secondsPerSlot: testParams.SECONDS_PER_SLOT, + }, + }; + + const loggerNodeA = testLogger("FinalizedSync-Node-A", testLoggerOpts); + const loggerNodeB = testLogger("FinalizedSync-Node-B", testLoggerOpts); + + const bn = await getDevBeaconNode({ + params: testParams, + options: { + sync: {isSingleNode: true}, + network: {allowPublishToZeroPeers: true, useWorker: false}, + chain: {blsVerifyAllMainThread: true}, + }, + validatorCount, + genesisTime, + logger: loggerNodeA, + }); + + afterEachCallbacks.push(() => bn.close()); + + const {validators} = await getAndInitDevValidators({ + node: bn, + logPrefix: "FinalizedSyncVc", + validatorsPerClient: validatorCount, + validatorClientCount: 1, + startIndex: 0, + useRestApi: false, + testLoggerOpts, + }); + + afterEachCallbacks.push(() => Promise.all(validators.map((validator) => validator.close()))); + + // stop beacon node after validators + afterEachCallbacks.push(() => bn.close()); + + await waitForEvent(bn.chain.emitter, ChainEvent.forkChoiceFinalized, 240000); + loggerNodeA.info("Node A emitted finalized checkpoint event"); + + const bn2 = await getDevBeaconNode({ + params: testParams, + options: { + api: {rest: {enabled: false}}, + network: {useWorker: false}, + chain: {blsVerifyAllMainThread: true}, + }, + validatorCount, + genesisTime, + logger: loggerNodeB, + }); + loggerNodeA.info("Node B created"); + + afterEachCallbacks.push(() => bn2.close()); + afterEachCallbacks.push(() => bn2.close()); + + const headSummary = bn.chain.forkChoice.getHead(); + const head = await bn.db.block.get(fromHexString(headSummary.blockRoot)); + if (!head) throw Error("First beacon node has no head block"); + const waitForSynced = waitForEvent( + bn2.chain.emitter, + routes.events.EventType.head, + 100000, + ({block}) => block === headSummary.blockRoot + ); + + await Promise.all([connect(bn2.network, bn.network), onPeerConnect(bn2.network), onPeerConnect(bn.network)]); + loggerNodeA.info("Node A connected to Node B"); + + try { + await waitForSynced; + loggerNodeB.info("Node B synced to Node A, received head block", {slot: head.message.slot}); + } catch (e) { + assert.fail("Failed to sync to other node in time"); + } + }); + }, + // chain is finalized at slot 32, plus 4 slots for genesis delay => ~72s it should sync pretty fast + {timeout: 90000} +); diff --git a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts index 5dd73bafa3f0..4ed8215ac85b 100644 --- a/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts +++ b/packages/beacon-node/test/perf/chain/opPools/aggregatedAttestationPool.test.ts @@ -1,13 +1,13 @@ import {itBench} from "@dapplion/benchmark"; -import {expect} from "chai"; import {BitArray, toHexString} from "@chainsafe/ssz"; import { CachedBeaconStateAltair, computeEpochAtSlot, computeStartSlotAtEpoch, getBlockRootAtSlot, + newFilledArray, } from "@lodestar/state-transition"; -import {HISTORICAL_ROOTS_LIMIT, SLOTS_PER_EPOCH, TIMELY_SOURCE_FLAG_INDEX} from "@lodestar/params"; +import {HISTORICAL_ROOTS_LIMIT, SLOTS_PER_EPOCH} from "@lodestar/params"; import {ExecutionStatus, ForkChoice, IForkChoiceStore, ProtoArray} from "@lodestar/fork-choice"; import {ssz} from "@lodestar/types"; // eslint-disable-next-line import/no-relative-packages @@ -15,33 +15,24 @@ import {generatePerfTestCachedStateAltair} from "../../../../../state-transition import {AggregatedAttestationPool} from "../../../../src/chain/opPools/aggregatedAttestationPool.js"; import {computeAnchorCheckpoint} from "../../../../src/chain/initState.js"; -/** Same to https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#has_flag */ -const TIMELY_SOURCE = 1 << TIMELY_SOURCE_FLAG_INDEX; -function flagIsTimelySource(flag: number): boolean { - return (flag & TIMELY_SOURCE) === TIMELY_SOURCE; -} +const vc = 1_500_000; -// Aug 11 2021 -// getAttestationsForBlock -// ✓ getAttestationsForBlock 4.410948 ops/s 226.7086 ms/op - 64 runs 51.8 s -describe("getAttestationsForBlock", () => { +/** + * Jan 2024 + * getAttestationsForBlock vc=1500000 + * ✔ notSeenSlots=1 numMissedVotes=1 numBadVotes=10 10.48105 ops/s 95.41024 ms/op - 12 runs 18.2 s + * ✔ notSeenSlots=1 numMissedVotes=0 numBadVotes=4 11.44517 ops/s 87.37307 ms/op - 13 runs 14.5 s + * ✔ notSeenSlots=2 numMissedVotes=1 numBadVotes=10 23.86144 ops/s 41.90862 ms/op - 18 runs 34.1 s + */ +describe(`getAttestationsForBlock vc=${vc}`, () => { let originalState: CachedBeaconStateAltair; let protoArray: ProtoArray; let forkchoice: ForkChoice; before(function () { - this.timeout(2 * 60 * 1000); // Generating the states for the first time is very slow - - originalState = generatePerfTestCachedStateAltair({goBackOneSlot: true}); - - const previousEpochParticipationArr = originalState.previousEpochParticipation.getAll(); - const currentEpochParticipationArr = originalState.currentEpochParticipation.getAll(); - - const numPreviousEpochParticipation = previousEpochParticipationArr.filter(flagIsTimelySource).length; - const numCurrentEpochParticipation = currentEpochParticipationArr.filter(flagIsTimelySource).length; + this.timeout(5 * 60 * 1000); // Generating the states for the first time is very slow - expect(numPreviousEpochParticipation).to.equal(250000, "Wrong numPreviousEpochParticipation"); - expect(numCurrentEpochParticipation).to.equal(250000, "Wrong numCurrentEpochParticipation"); + originalState = generatePerfTestCachedStateAltair({goBackOneSlot: true, vc}); const {blockHeader, checkpoint} = computeAnchorCheckpoint(originalState.config, originalState); // TODO figure out why getBlockRootAtSlot(originalState, justifiedSlot) is not the same to justifiedCheckpoint.root @@ -125,17 +116,115 @@ describe("getAttestationsForBlock", () => { forkchoice = new ForkChoice(originalState.config, fcStore, protoArray); }); + // notSeenSlots should be >=1 + for (const [notSeenSlots, numMissedVotes, numBadVotes] of [ + [1, 1, 10], + [1, 0, 4], + // notSeenSlots=2 means the previous block slot is missed + [2, 1, 10], + ]) { + itBench({ + id: `notSeenSlots=${notSeenSlots} numMissedVotes=${numMissedVotes} numBadVotes=${numBadVotes}`, + before: () => { + const state = originalState.clone(); + // by default make all validators have full participation + const previousParticipation = newFilledArray(vc, 0b111); + // origState is at slot 0 of epoch so there is no currentParticipation + const currentParticipation = newFilledArray(vc, 0); + const currentEpoch = computeEpochAtSlot(state.slot); + + for (let epochSlot = 0; epochSlot < SLOTS_PER_EPOCH; epochSlot++) { + const slot = state.slot - 1 - epochSlot; + const slotEpoch = computeEpochAtSlot(slot); + const committeeCount = state.epochCtx.getCommitteeCountPerSlot(slotEpoch); + for (let committeeIndex = 0; committeeIndex < committeeCount; committeeIndex++) { + const duties = state.epochCtx.getBeaconCommittee(slot, committeeIndex); + const participationArr = slotEpoch === currentEpoch ? currentParticipation : previousParticipation; + for (const [i, validatorIndex] of duties.entries()) { + // no attestation in previous slot is included yet as that's the spec + // for slot < previous slot, there is missed votes at every committee so the code need to keep looking for attestations because votes are not seen + if (slot >= state.slot - notSeenSlots || i < numMissedVotes) { + participationArr[validatorIndex] = 0; + } + } + } + } + state.previousEpochParticipation = ssz.altair.EpochParticipation.toViewDU(previousParticipation); + state.currentEpochParticipation = ssz.altair.EpochParticipation.toViewDU(currentParticipation); + state.commit(); + return state; + }, + beforeEach: (state) => { + const pool = getAggregatedAttestationPool(state, numMissedVotes, numBadVotes); + return {state, pool}; + }, + fn: ({state, pool}) => { + pool.getAttestationsForBlock(forkchoice, state); + }, + }); + } +}); + +/** + * Fir dev purpose to find the best way to get not seen validators. + */ +describe.skip("getAttestationsForBlock aggregationBits intersectValues vs get", () => { + const runsFactor = 1000; + // As of Jan 2004 + const committeeLen = 450; + const aggregationBits = BitArray.fromBoolArray(Array.from({length: committeeLen}, () => true)); + const notSeenValidatorIndices = Array.from({length: committeeLen}, (_, i) => i); + itBench({ - id: "getAttestationsForBlock", - beforeEach: () => getAggregatedAttestationPool(originalState), - fn: (pool) => { - // logger.info("Number of attestations in pool", pool.getAll().length); - pool.getAttestationsForBlock(forkchoice, originalState); + id: "aggregationBits.intersectValues()", + fn: () => { + for (let i = 0; i < runsFactor; i++) { + aggregationBits.intersectValues(notSeenValidatorIndices); + } }, + runsFactor, + }); + + itBench({ + id: "aggregationBits.get()", + fn: () => { + for (let i = 0; i < runsFactor; i++) { + for (let j = 0; j < committeeLen; j++) { + aggregationBits.get(j); + } + } + }, + runsFactor, + }); + + itBench({ + id: "aggregationBits.get() with push()", + fn: () => { + for (let i = 0; i < runsFactor; i++) { + const arr: number[] = []; + for (let j = 0; j < committeeLen; j++) { + if (aggregationBits.get(j)) { + arr.push(j); + } + } + } + }, + runsFactor, }); }); -function getAggregatedAttestationPool(state: CachedBeaconStateAltair): AggregatedAttestationPool { +/** + * Create the pool with the following properties: + * - state: at slot n + * - all attestations at slot n - 1 are included in block but they are not enough + * - numMissedVotes: number of missed attestations/votes at every committee + * - numBadVotes: number of bad attestations/votes at every committee, they are not included in block because they are seen in the state + */ +function getAggregatedAttestationPool( + state: CachedBeaconStateAltair, + numMissedVotes: number, + numBadVotes: number +): AggregatedAttestationPool { const pool = new AggregatedAttestationPool(); for (let epochSlot = 0; epochSlot < SLOTS_PER_EPOCH; epochSlot++) { const slot = state.slot - 1 - epochSlot; @@ -145,31 +234,82 @@ function getAggregatedAttestationPool(state: CachedBeaconStateAltair): Aggregate epoch: state.currentJustifiedCheckpoint.epoch, root: state.currentJustifiedCheckpoint.root, }; + for (let committeeIndex = 0; committeeIndex < committeeCount; committeeIndex++) { - const attestation = { - aggregationBits: BitArray.fromBitLen(64), - data: { - slot: slot, - index: committeeIndex, - beaconBlockRoot: getBlockRootAtSlot(state, slot), - source: sourceCheckpoint, - target: { - epoch, - root: getBlockRootAtSlot(state, computeStartSlotAtEpoch(epoch)), - }, + const goodAttData = { + slot: slot, + index: committeeIndex, + beaconBlockRoot: getBlockRootAtSlot(state, slot), + source: sourceCheckpoint, + target: { + epoch, + root: getBlockRootAtSlot(state, computeStartSlotAtEpoch(epoch)), }, - signature: Buffer.alloc(96), }; + // for each good att data group, there are 4 versions of aggregation bits const committee = state.epochCtx.getBeaconCommittee(slot, committeeIndex); - // all attestation has full participation so getAttestationsForBlock() has to do a lot of filter - // aggregate_and_proof messages - pool.add( - attestation, - toHexString(ssz.phase0.AttestationData.hashTreeRoot(attestation.data)), - committee.length, - committee - ); + const committeeLen = committee.length; + const goodVoteBits = BitArray.fromBoolArray(Array.from({length: committeeLen}, () => true)); + // n first validators are totally missed + for (let i = 0; i < numMissedVotes; i++) { + goodVoteBits.set(i, false); + } + // n next validators vote for different att data + for (let i = 0; i < numBadVotes; i++) { + goodVoteBits.set(i + numMissedVotes, false); + } + + // there are 4 different versions of the good vote + for (const endingBits of [0b1000, 0b0100, 0b0010, 0b0001]) { + const aggregationBits = goodVoteBits.clone(); + aggregationBits.set(committeeLen - 1, Boolean(endingBits & 0b0001)); + aggregationBits.set(committeeLen - 2, Boolean(endingBits & 0b0010)); + aggregationBits.set(committeeLen - 3, Boolean(endingBits & 0b0100)); + aggregationBits.set(committeeLen - 4, Boolean(endingBits & 0b1000)); + + const attestation = { + aggregationBits, + data: goodAttData, + signature: Buffer.alloc(96), + }; + // all attestation has full participation so getAttestationsForBlock() has to do a lot of filter + // aggregate_and_proof messages + pool.add( + attestation, + toHexString(ssz.phase0.AttestationData.hashTreeRoot(attestation.data)), + committee.length, + committee + ); + } + + if (epochSlot === 0) { + // epochSlot === 0: attestations will be included in block but it's not enough for block + // epochSlot >= 1: no attestation will be included in block but the code still need to scan through them + continue; + } + + const zeroAggregationBits = BitArray.fromBoolArray(Array.from({length: committeeLen}, () => false)); + + // n first validator votes for n different bad votes, that makes n different att data in the same slot/index + // these votes/attestations will NOT be included in block as they are seen in the state + for (let i = 0; i < numBadVotes; i++) { + const attData = ssz.phase0.AttestationData.clone(goodAttData); + attData.beaconBlockRoot = getBlockRootAtSlot(state, slot - i - 1); + const aggregationBits = zeroAggregationBits.clone(); + aggregationBits.set(i + numMissedVotes, true); + const attestation = { + aggregationBits, + data: attData, + signature: Buffer.alloc(96), + }; + pool.add( + attestation, + toHexString(ssz.phase0.AttestationData.hashTreeRoot(attestation.data)), + committee.length, + committee + ); + } } } return pool; diff --git a/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts b/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts index 48abfbc35675..00aa8a40168b 100644 --- a/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts +++ b/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts @@ -2,14 +2,15 @@ import type {SecretKey} from "@chainsafe/bls/types"; import bls from "@chainsafe/bls"; import {BitArray, fromHexString, toHexString} from "@chainsafe/ssz"; import {describe, it, expect, beforeEach, beforeAll, afterEach, vi} from "vitest"; -import {CachedBeaconStateAllForks} from "@lodestar/state-transition"; -import {SLOTS_PER_EPOCH} from "@lodestar/params"; +import {CachedBeaconStateAllForks, newFilledArray} from "@lodestar/state-transition"; +import {FAR_FUTURE_EPOCH, MAX_EFFECTIVE_BALANCE, SLOTS_PER_EPOCH} from "@lodestar/params"; import {ssz, phase0} from "@lodestar/types"; +import {CachedBeaconStateAltair} from "@lodestar/state-transition/src/types.js"; import {MockedForkChoice, getMockedForkChoice} from "../../../mocks/mockedBeaconChain.js"; import { AggregatedAttestationPool, aggregateInto, - getParticipationFn, + getNotSeenValidatorsFn, MatchingDataAttestationGroup, } from "../../../../src/chain/opPools/aggregatedAttestationPool.js"; import {InsertOutcome} from "../../../../src/chain/opPools/types.js"; @@ -18,6 +19,7 @@ import {generateCachedAltairState} from "../../../utils/state.js"; import {renderBitArray} from "../../../utils/render.js"; import {ZERO_HASH_HEX} from "../../../../src/constants/constants.js"; import {generateProtoBlock} from "../../../utils/typeGenerator.js"; +import {generateValidators} from "../../../utils/validator.js"; /** Valid signature of random data to prevent BLS errors */ const validSignature = fromHexString( @@ -29,15 +31,43 @@ describe("AggregatedAttestationPool", function () { const altairForkEpoch = 2020; const currentEpoch = altairForkEpoch + 10; const currentSlot = SLOTS_PER_EPOCH * currentEpoch; - const originalState = generateCachedAltairState({slot: currentSlot + 1}, altairForkEpoch); - let altairState: CachedBeaconStateAllForks; + const committeeIndex = 0; const attestation = ssz.phase0.Attestation.defaultValue(); attestation.data.slot = currentSlot; + attestation.data.index = committeeIndex; attestation.data.target.epoch = currentEpoch; const attDataRootHex = toHexString(ssz.phase0.AttestationData.hashTreeRoot(attestation.data)); - const committee = [0, 1, 2, 3]; + const validatorOpts = { + activationEpoch: 0, + effectiveBalance: MAX_EFFECTIVE_BALANCE, + withdrawableEpoch: FAR_FUTURE_EPOCH, + exitEpoch: FAR_FUTURE_EPOCH, + }; + // this makes a committee length of 4 + const vc = 64; + const committeeLength = 4; + const validators = generateValidators(vc, validatorOpts); + const originalState = generateCachedAltairState({slot: currentSlot + 1, validators}, altairForkEpoch); + const committee = originalState.epochCtx.getBeaconCommittee(currentSlot, committeeIndex); + expect(committee.length).toEqual(committeeLength); + // 0 and 1 in committee are fully participated + const epochParticipation = newFilledArray(vc, 0b111); + for (let i = 0; i < committeeLength; i++) { + if (i === 0 || i === 1) { + epochParticipation[committee[i]] = 0b111; + } else { + epochParticipation[committee[i]] = 0b000; + } + } + (originalState as CachedBeaconStateAltair).previousEpochParticipation = + ssz.altair.EpochParticipation.toViewDU(epochParticipation); + (originalState as CachedBeaconStateAltair).currentEpochParticipation = + ssz.altair.EpochParticipation.toViewDU(epochParticipation); + originalState.commit(); + let altairState: CachedBeaconStateAllForks; + let forkchoiceStub: MockedForkChoice; beforeEach(() => { @@ -53,9 +83,16 @@ describe("AggregatedAttestationPool", function () { it("getParticipationFn", () => { // previousEpochParticipation and currentEpochParticipation is created inside generateCachedState // 0 and 1 are fully participated - const participationFn = getParticipationFn(altairState); - const participation = participationFn(currentEpoch, committee); - expect(participation).toEqual(new Set([0, 1])); + const notSeenValidatorFn = getNotSeenValidatorsFn(altairState); + const participation = notSeenValidatorFn(currentEpoch, committee); + // seen attesting indices are 0, 1 => not seen are 2, 3 + expect(participation).toEqual( + // { + // validatorIndices: [null, null, committee[2], committee[3]], + // attestingIndices: new Set([2, 3]), + // } + new Set([2, 3]) + ); }); // previousEpochParticipation and currentEpochParticipation is created inside generateCachedState @@ -68,7 +105,7 @@ describe("AggregatedAttestationPool", function () { for (const {name, attestingBits, isReturned} of testCases) { it(name, function () { - const aggregationBits = new BitArray(new Uint8Array(attestingBits), 8); + const aggregationBits = new BitArray(new Uint8Array(attestingBits), committeeLength); pool.add( {...attestation, aggregationBits}, attDataRootHex, @@ -180,13 +217,14 @@ describe("MatchingDataAttestationGroup.add()", () => { describe("MatchingDataAttestationGroup.getAttestationsForBlock", () => { const testCases: { id: string; - seenAttestingBits: number[]; + notSeenAttestingBits: number[]; attestationsToAdd: {bits: number[]; notSeenAttesterCount: number}[]; }[] = [ // Note: attestationsToAdd MUST intersect in order to not be aggregated and distort the results { id: "All have attested", - seenAttestingBits: [0b11111111], + // same to seenAttestingBits: [0b11111111], + notSeenAttestingBits: [0b00000000], attestationsToAdd: [ {bits: [0b11111110], notSeenAttesterCount: 0}, {bits: [0b00000011], notSeenAttesterCount: 0}, @@ -194,7 +232,8 @@ describe("MatchingDataAttestationGroup.getAttestationsForBlock", () => { }, { id: "Some have attested", - seenAttestingBits: [0b11110001], // equals to indexes [ 0, 4, 5, 6, 7 ] + // same to seenAttestingBits: [0b11110001] + notSeenAttestingBits: [0b00001110], attestationsToAdd: [ {bits: [0b11111110], notSeenAttesterCount: 3}, {bits: [0b00000011], notSeenAttesterCount: 1}, @@ -202,7 +241,8 @@ describe("MatchingDataAttestationGroup.getAttestationsForBlock", () => { }, { id: "Non have attested", - seenAttestingBits: [0b00000000], + // same to seenAttestingBits: [0b00000000], + notSeenAttestingBits: [0b11111111], attestationsToAdd: [ {bits: [0b11111110], notSeenAttesterCount: 7}, {bits: [0b00000011], notSeenAttesterCount: 2}, @@ -213,7 +253,7 @@ describe("MatchingDataAttestationGroup.getAttestationsForBlock", () => { const attestationData = ssz.phase0.AttestationData.defaultValue(); const committee = linspace(0, 7); - for (const {id, seenAttestingBits, attestationsToAdd} of testCases) { + for (const {id, notSeenAttestingBits, attestationsToAdd} of testCases) { it(id, () => { const attestationGroup = new MatchingDataAttestationGroup(committee, attestationData); @@ -229,8 +269,19 @@ describe("MatchingDataAttestationGroup.getAttestationsForBlock", () => { attestationGroup.add({attestation, trueBitsCount: attestation.aggregationBits.getTrueBitIndexes().length}); } - const indices = new BitArray(new Uint8Array(seenAttestingBits), 8).intersectValues(committee); - const attestationsForBlock = attestationGroup.getAttestationsForBlock(new Set(indices)); + const notSeenAggBits = new BitArray(new Uint8Array(notSeenAttestingBits), 8); + // const notSeenValidatorIndices: (ValidatorIndex | null)[] = []; + const notSeenAttestingIndices = new Set(); + for (let i = 0; i < committee.length; i++) { + // notSeenValidatorIndices.push(notSeenAggBits.get(i) ? committee[i] : null); + if (notSeenAggBits.get(i)) { + notSeenAttestingIndices.add(i); + } + } + const attestationsForBlock = attestationGroup.getAttestationsForBlock( + // notSeenValidatorIndices, + notSeenAttestingIndices + ); for (const [i, {notSeenAttesterCount}] of attestationsToAdd.entries()) { const attestation = attestationsForBlock.find((a) => a.attestation === attestations[i]); From 0db50b929b97796f2e958c88054a271d849ff9f1 Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 1 Feb 2024 11:54:09 -0800 Subject: [PATCH 18/71] chore: improve browser support (#6384) * fix: remove unsupported syntax * fix: handle undefined process * chore: remove uneeded type --- packages/light-client/src/transport/rest.ts | 18 +++++++----------- packages/params/src/index.ts | 4 +++- packages/state-transition/src/util/sszBytes.ts | 4 ++-- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/light-client/src/transport/rest.ts b/packages/light-client/src/transport/rest.ts index ebbd8e52f691..2c63f2ea988a 100644 --- a/packages/light-client/src/transport/rest.ts +++ b/packages/light-client/src/transport/rest.ts @@ -1,25 +1,21 @@ import EventEmitter from "events"; -import StrictEventEmitter from "strict-event-emitter-types"; -import {allForks, SyncPeriod} from "@lodestar/types"; -import {Api, ApiError, routes} from "@lodestar/api"; -import {ForkName} from "@lodestar/params"; -import {LightClientTransport} from "./interface.js"; +import {type StrictEventEmitter} from "strict-event-emitter-types"; +import {type allForks, type SyncPeriod} from "@lodestar/types"; +import {type Api, ApiError, routes} from "@lodestar/api"; +import {type ForkName} from "@lodestar/params"; +import {type LightClientTransport} from "./interface.js"; export type LightClientRestEvents = { [routes.events.EventType.lightClientFinalityUpdate]: allForks.LightClientFinalityUpdate; [routes.events.EventType.lightClientOptimisticUpdate]: allForks.LightClientOptimisticUpdate; }; -type RestEvents = StrictEventEmitter; - -export class LightClientRestTransport extends (EventEmitter as {new (): RestEvents}) implements LightClientTransport { +export class LightClientRestTransport implements LightClientTransport { private controller = new AbortController(); private readonly eventEmitter: StrictEventEmitter = new EventEmitter(); private subscribedEventstream = false; - constructor(private readonly api: Api) { - super(); - } + constructor(private readonly api: Api) {} async getUpdates( startPeriod: SyncPeriod, diff --git a/packages/params/src/index.ts b/packages/params/src/index.ts index d111d090b8c3..6a95e3ca632e 100644 --- a/packages/params/src/index.ts +++ b/packages/params/src/index.ts @@ -28,7 +28,9 @@ presetStatus.frozen = true; * The active preset can be manually overridden with `setActivePreset` */ export const ACTIVE_PRESET = - userSelectedPreset ?? PresetName[process?.env?.LODESTAR_PRESET as PresetName] ?? PresetName.mainnet; + userSelectedPreset ?? + (typeof process !== "undefined" ? PresetName[process?.env?.LODESTAR_PRESET as PresetName] : undefined) ?? + PresetName.mainnet; export const activePreset = {...presets[ACTIVE_PRESET], ...userOverrides}; // These variables must be exported individually and explicitly diff --git a/packages/state-transition/src/util/sszBytes.ts b/packages/state-transition/src/util/sszBytes.ts index 25b65626a0dd..b5141e1673e5 100644 --- a/packages/state-transition/src/util/sszBytes.ts +++ b/packages/state-transition/src/util/sszBytes.ts @@ -37,14 +37,14 @@ export const VALIDATOR_BYTES_SIZE = 121; */ const SLOT_BYTES_POSITION_IN_STATE = 40; -export function getForkFromStateBytes(config: ChainForkConfig, bytes: Buffer | Uint8Array): ForkSeq { +export function getForkFromStateBytes(config: ChainForkConfig, bytes: Uint8Array): ForkSeq { const slot = bytesToInt(bytes.subarray(SLOT_BYTES_POSITION_IN_STATE, SLOT_BYTES_POSITION_IN_STATE + SLOT_BYTE_COUNT)); return config.getForkSeq(slot); } export function getStateTypeFromBytes( config: ChainForkConfig, - bytes: Buffer | Uint8Array + bytes: Uint8Array ): allForks.AllForksSSZTypes["BeaconState"] { const slot = getStateSlotFromBytes(bytes); return config.getForkTypes(slot).BeaconState; From 00dfa63413e9b2a57dbaea70ac7151ef134b0c05 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 1 Feb 2024 22:42:51 +0100 Subject: [PATCH 19/71] feat: add builder selection executionalways (#6370) --- docs/pages/validator-management/vc-configuration.md | 1 + packages/api/src/beacon/routes/validator.ts | 1 + packages/beacon-node/src/api/impl/validator/index.ts | 1 + .../test/unit/api/impl/validator/produceBlockV3.test.ts | 6 ++++++ packages/cli/src/cmds/validator/options.ts | 3 ++- packages/cli/src/util/proposerConfig.ts | 7 ++++--- packages/validator/src/services/validatorStore.ts | 1 + 7 files changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/pages/validator-management/vc-configuration.md b/docs/pages/validator-management/vc-configuration.md index a1077997cd77..f1fa720c7ee1 100644 --- a/docs/pages/validator-management/vc-configuration.md +++ b/docs/pages/validator-management/vc-configuration.md @@ -97,6 +97,7 @@ With produceBlockV3 (enabled automatically after the Deneb hard fork), the `--bu With Lodestar's `--builder.selection` validator options, you can select: - `maxprofit`: Default setting for Lodestar set at `--builder.boostFactor=100`. This default setting will always choose the more profitable block. Using this option, you may customize your `--builder.boostFactor` to your preference. Examples of its usage are below. +- `executionalways`: An alias of `--builder.boostFactor=0`, which will select the local execution block, unless it fails to produce due to an error or a delay in the response from the execution client. - `executiononly`: Beacon node will be requested to produce local execution block even if builder relays are configured. This option will always select the local execution block and will error if it couldn't produce one. - `builderalways`: An alias of `--builder.boostFactor=18446744073709551615` (2**64 - 1), which will select the builder block, unless the builder block fails to produce. The builder block may fail to produce if it's not available, not timely or there is an indication of censorship via `shouldOverrideBuilder` from the execution payload response. - `builderonly`: Generally used for distributed validators (DVs). No execution block production will be triggered. Therefore, if a builder block is not produced, the API will fail and _no block will be produced_. diff --git a/packages/api/src/beacon/routes/validator.ts b/packages/api/src/beacon/routes/validator.ts index 09fbd9de3162..5b6fa7797d88 100644 --- a/packages/api/src/beacon/routes/validator.ts +++ b/packages/api/src/beacon/routes/validator.ts @@ -43,6 +43,7 @@ import {ExecutionOptimistic} from "./beacon/block.js"; export enum BuilderSelection { BuilderAlways = "builderalways", + ExecutionAlways = "executionalways", MaxProfit = "maxprofit", /** Only activate builder flow for DVT block proposal protocols */ BuilderOnly = "builderonly", diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index e795d1c5afad..e6dac77b3a7c 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -612,6 +612,7 @@ export function getValidatorApi({ break; } + case routes.validator.BuilderSelection.ExecutionAlways: case routes.validator.BuilderSelection.ExecutionOnly: { executionPayloadSource = ProducedBlockSource.engine; break; diff --git a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts index 4484bcf03563..ba0267fc5810 100644 --- a/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts +++ b/packages/beacon-node/test/unit/api/impl/validator/produceBlockV3.test.ts @@ -49,6 +49,12 @@ describe("api/validator - produceBlockV3", function () { [routes.validator.BuilderSelection.BuilderAlways, 1, 1, 1, true, "engine"], [routes.validator.BuilderSelection.BuilderAlways, 1, null, 1, true, "builder"], + [routes.validator.BuilderSelection.ExecutionAlways, 2, 1, 0, false, "engine"], + [routes.validator.BuilderSelection.ExecutionAlways, 0, 1, 1, false, "engine"], + [routes.validator.BuilderSelection.ExecutionAlways, 0, null, 0, false, "builder"], + [routes.validator.BuilderSelection.ExecutionAlways, null, 0, 1, false, "engine"], + [routes.validator.BuilderSelection.ExecutionAlways, 1, 1, 1, true, "engine"], + [routes.validator.BuilderSelection.BuilderOnly, 0, 2, 0, false, "builder"], [routes.validator.BuilderSelection.ExecutionOnly, 2, 0, 1, false, "engine"], [routes.validator.BuilderSelection.BuilderOnly, 1, 1, 0, true, "builder"], diff --git a/packages/cli/src/cmds/validator/options.ts b/packages/cli/src/cmds/validator/options.ts index ecc8ad32ca87..20bfc106d258 100644 --- a/packages/cli/src/cmds/validator/options.ts +++ b/packages/cli/src/cmds/validator/options.ts @@ -242,7 +242,8 @@ export const validatorOptions: CliCommandOptions = { "builder.selection": { type: "string", - description: "Builder block selection strategy `maxprofit`, `builderalways`, `builderonly` or `executiononly`", + description: + "Builder block selection strategy `maxprofit`, `builderalways`, `builderonly`, `executionalways`, or `executiononly`", defaultDescription: `${defaultOptions.builderSelection}`, group: "builder", }, diff --git a/packages/cli/src/util/proposerConfig.ts b/packages/cli/src/util/proposerConfig.ts index 661c81ee63af..ae56cc45513a 100644 --- a/packages/cli/src/util/proposerConfig.ts +++ b/packages/cli/src/util/proposerConfig.ts @@ -8,7 +8,6 @@ import {routes} from "@lodestar/api"; import {parseFeeRecipient} from "./feeRecipient.js"; import {readFile} from "./file.js"; -import {YargsError} from "./index.js"; type ProposerConfig = ValidatorProposerConfig["defaultConfig"]; @@ -114,10 +113,12 @@ export function parseBuilderSelection(builderSelection?: string): routes.validat break; case "builderonly": break; + case "executionalways": + break; case "executiononly": break; default: - throw new YargsError("Invalid input for builder selection, check help"); + throw Error("Invalid input for builder selection, check help"); } } return builderSelection as routes.validator.BuilderSelection; @@ -127,7 +128,7 @@ export function parseBuilderBoostFactor(boostFactor?: string): bigint | undefine if (boostFactor === undefined) return; if (!/^\d+$/.test(boostFactor)) { - throw new YargsError("Invalid input for builder boost factor, must be a valid number without decimals"); + throw Error("Invalid input for builder boost factor, must be a valid number without decimals"); } return BigInt(boostFactor); diff --git a/packages/validator/src/services/validatorStore.ts b/packages/validator/src/services/validatorStore.ts index 03811062c2ad..d1474e7fdd28 100644 --- a/packages/validator/src/services/validatorStore.ts +++ b/packages/validator/src/services/validatorStore.ts @@ -277,6 +277,7 @@ export class ValidatorStore { boostFactor = MAX_BUILDER_BOOST_FACTOR; break; + case routes.validator.BuilderSelection.ExecutionAlways: case routes.validator.BuilderSelection.ExecutionOnly: boostFactor = BigInt(0); } From ac4e714ef38f663a5e7dcfe916ce3a027e1f3ff9 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Mon, 5 Feb 2024 15:52:15 +0100 Subject: [PATCH 20/71] refactor: update the block production race (#6241) * Update the promise race implementation * Update block production race * Fix spelling * Work on feedback * Update the test file name * Update the promise tests * Update util to switch * chore: add early return on censoring builder or 0 builder boost * Update the promise to extended promise * Update the builder flow * Fix the types * Fix lint errors * Simplify logging * Improve log messages for block values * Update the promise to be typesafe * Update the validator implementation * Restructure test file for better review * Fix lint errors * Fix lint error * Make the tyep more flexible * Fix flaky tests * Improve log message * Simplify implementation * Update log message function * chore: add review feedback * chore: fix linter error * chore: address PR comments * Update packages/beacon-node/src/api/impl/validator/index.ts Co-authored-by: Nico Flaig * chore: address PR comments * chore: clean up selectBlockProductionSource * Fix unit tests * Add support for routes.validator.BuilderSelection.ExecutionOnly * Fix unit tests * Increase the timeout for e2e env * Apply suggestions from code review Co-authored-by: Nico Flaig * Increase the timeout for e2e env * Revert e2e timeout --------- Co-authored-by: Cayman Co-authored-by: Nico Flaig --- .../src/api/impl/validator/index.ts | 346 +++++++++--------- .../src/api/impl/validator/utils.ts | 32 +- packages/utils/src/format.ts | 27 ++ packages/utils/src/promise.ts | 212 ++++++----- packages/utils/src/types.ts | 6 + packages/utils/test/unit/format.test.ts | 23 ++ packages/utils/test/unit/promise.test.ts | 73 ++++ packages/utils/test/unit/promiserace.test.ts | 84 ++--- packages/validator/src/services/block.ts | 3 +- packages/validator/src/util/format.ts | 9 - .../validator/test/unit/utils/format.test.ts | 21 -- 11 files changed, 479 insertions(+), 357 deletions(-) create mode 100644 packages/utils/test/unit/format.test.ts create mode 100644 packages/utils/test/unit/promise.test.ts delete mode 100644 packages/validator/test/unit/utils/format.test.ts diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index e6dac77b3a7c..0b45540c791e 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -35,7 +35,7 @@ import { phase0, } from "@lodestar/types"; import {ExecutionStatus} from "@lodestar/fork-choice"; -import {toHex, racePromisesWithCutoff, RaceEvent} from "@lodestar/utils"; +import {toHex, resolveOrRacePromises, prettyWeiToEth} from "@lodestar/utils"; import { AttestationError, AttestationErrorCode, @@ -57,7 +57,7 @@ import {getValidatorStatus} from "../beacon/state/utils.js"; import {validateGossipFnRetryUnknownRoot} from "../../../network/processor/gossipHandlers.js"; import {SCHEDULER_LOOKAHEAD_FACTOR} from "../../../chain/prepareNextSlot.js"; import {ChainEvent, CheckpointHex, CommonBlockBody} from "../../../chain/index.js"; -import {computeSubnetForCommitteesAtSlot, getPubkeysForIndices} from "./utils.js"; +import {computeSubnetForCommitteesAtSlot, getPubkeysForIndices, selectBlockProductionSource} from "./utils.js"; /** * If the node is within this many epochs from the head, we declare it to be synced regardless of @@ -177,6 +177,35 @@ export function getValidatorApi({ return computeEpochAtSlot(getCurrentSlot(config, chain.genesisTime - MAX_API_CLOCK_DISPARITY_SEC)); } + function getBlockValueLogInfo( + block: {executionPayloadValue: bigint; consensusBlockValue: bigint}, + source?: ProducedBlockSource + ): Record { + const executionValue = block.executionPayloadValue; + const consensusValue = block.consensusBlockValue; + const totalValue = executionValue + consensusValue; + + if (source == null) { + return { + executionPayloadValue: prettyWeiToEth(executionValue, true), + consensusBlockValue: prettyWeiToEth(consensusValue, true), + blockTotalValue: prettyWeiToEth(totalValue, true), + }; + } else if (source === ProducedBlockSource.builder) { + return { + builderExecutionPayloadValue: prettyWeiToEth(executionValue, true), + builderConsensusBlockValue: prettyWeiToEth(consensusValue, true), + builderBlockTotalValue: prettyWeiToEth(totalValue, true), + }; + } else { + return { + engineExecutionPayloadValue: prettyWeiToEth(executionValue, true), + engineConsensusBlockValue: prettyWeiToEth(consensusValue, true), + engineBlockTotalValue: prettyWeiToEth(totalValue, true), + }; + } + } + /** * This function is called 1s before next epoch, usually at that time PrepareNextSlotScheduler finishes * so we should have checkpoint state, otherwise wait for up to the slot 1 of epoch. @@ -472,11 +501,28 @@ export function getValidatorApi({ chain.executionBuilder !== undefined && builderSelection !== routes.validator.BuilderSelection.ExecutionOnly; + // At any point either the builder or execution or both flows should be active. + // + // Ideally such a scenario should be prevented on startup, but proposerSettingsFile or keymanager + // configurations could cause a validator pubkey to have builder disabled with builder selection builder only + // (TODO: independently make sure such an options update is not successful for a validator pubkey) + // + // So if builder is disabled ignore builder selection of builder only if caused by user mistake + // https://github.com/ChainSafe/lodestar/issues/6338 + const isEngineEnabled = !isBuilderEnabled || builderSelection !== routes.validator.BuilderSelection.BuilderOnly; + + if (!isEngineEnabled && !isBuilderEnabled) { + throw Error( + `Internal Error: Neither builder nor execution proposal flow activated isBuilderEnabled=${isBuilderEnabled} builderSelection=${builderSelection}` + ); + } + const loggerContext = { fork, builderSelection, slot, isBuilderEnabled, + isEngineEnabled, strictFeeRecipientCheck, // winston logger doesn't like bigint builderBoostFactor: `${builderBoostFactor}`, @@ -490,197 +536,151 @@ export function getValidatorApi({ }); logger.debug("Produced common block body", loggerContext); + logger.verbose("Block production race (builder vs execution) starting", { + ...loggerContext, + cutoffMs: BLOCK_PRODUCTION_RACE_CUTOFF_MS, + timeoutMs: BLOCK_PRODUCTION_RACE_TIMEOUT_MS, + }); + + // use abort controller to stop waiting for both block sources + const controller = new AbortController(); + // Start calls for building execution and builder blocks - const blindedBlockPromise = isBuilderEnabled - ? // can't do fee recipient checks as builder bid doesn't return feeRecipient as of now - produceBuilderBlindedBlock(slot, randaoReveal, graffiti, { + + const builderPromise = isBuilderEnabled + ? produceBuilderBlindedBlock(slot, randaoReveal, graffiti, { feeRecipient, + // can't do fee recipient checks as builder bid doesn't return feeRecipient as of now + strictFeeRecipientCheck: false, // skip checking and recomputing head in these individual produce calls skipHeadChecksAndUpdate: true, commonBlockBody, - }).catch((e) => { - logger.error("produceBuilderBlindedBlock failed to produce block", {slot}, e); - return null; }) - : null; - - const fullBlockPromise = - // At any point either the builder or execution or both flows should be active. - // - // Ideally such a scenario should be prevented on startup, but proposerSettingsFile or keymanager - // configurations could cause a validator pubkey to have builder disabled with builder selection builder only - // (TODO: independently make sure such an options update is not successful for a validator pubkey) - // - // So if builder is disabled ignore builder selection of builderonly if caused by user mistake - !isBuilderEnabled || builderSelection !== routes.validator.BuilderSelection.BuilderOnly - ? // TODO deneb: builderSelection needs to be figured out if to be done beacon side - // || builderSelection !== BuilderSelection.BuilderOnly - produceEngineFullBlockOrContents(slot, randaoReveal, graffiti, { - feeRecipient, - strictFeeRecipientCheck, - // skip checking and recomputing head in these individual produce calls - skipHeadChecksAndUpdate: true, - commonBlockBody, - }).catch((e) => { - logger.error("produceEngineFullBlockOrContents failed to produce block", {slot}, e); - return null; - }) - : null; - - let blindedBlock, fullBlock; - if (blindedBlockPromise !== null && fullBlockPromise !== null) { - // reference index of promises in the race - const promisesOrder = [ProducedBlockSource.builder, ProducedBlockSource.engine]; - [blindedBlock, fullBlock] = await racePromisesWithCutoff< - | ((routes.validator.ProduceBlockOrContentsRes | routes.validator.ProduceBlindedBlockRes) & { - shouldOverrideBuilder?: boolean; - }) - | null - >( - [blindedBlockPromise, fullBlockPromise], - BLOCK_PRODUCTION_RACE_CUTOFF_MS, - BLOCK_PRODUCTION_RACE_TIMEOUT_MS, - // Callback to log the race events for better debugging capability - (event: RaceEvent, delayMs: number, index?: number) => { - const eventRef = index !== undefined ? {source: promisesOrder[index]} : {}; - logger.verbose("Block production race (builder vs execution)", { - event, - ...eventRef, - delayMs, - cutoffMs: BLOCK_PRODUCTION_RACE_CUTOFF_MS, - timeoutMs: BLOCK_PRODUCTION_RACE_TIMEOUT_MS, - slot, - }); - } - ); - if (blindedBlock instanceof Error) { - // error here means race cutoff exceeded - logger.error("Failed to produce builder block", {slot}, blindedBlock); - blindedBlock = null; - } - if (fullBlock instanceof Error) { - logger.error("Failed to produce execution block", {slot}, fullBlock); - fullBlock = null; - } - } else if (blindedBlockPromise !== null && fullBlockPromise === null) { - blindedBlock = await blindedBlockPromise; - fullBlock = null; - } else if (blindedBlockPromise === null && fullBlockPromise !== null) { - blindedBlock = null; - fullBlock = await fullBlockPromise; - } else { - throw Error( - `Internal Error: Neither builder nor execution proposal flow activated isBuilderEnabled=${isBuilderEnabled} builderSelection=${builderSelection}` - ); - } + : Promise.reject(new Error("Builder disabled")); - const builderPayloadValue = blindedBlock?.executionPayloadValue ?? BigInt(0); - const enginePayloadValue = fullBlock?.executionPayloadValue ?? BigInt(0); - const consensusBlockValueBuilder = blindedBlock?.consensusBlockValue ?? BigInt(0); - const consensusBlockValueEngine = fullBlock?.consensusBlockValue ?? BigInt(0); - - const blockValueBuilder = builderPayloadValue + consensusBlockValueBuilder; // Total block value is in wei - const blockValueEngine = enginePayloadValue + consensusBlockValueEngine; // Total block value is in wei - - let executionPayloadSource: ProducedBlockSource | null = null; - const shouldOverrideBuilder = fullBlock?.shouldOverrideBuilder ?? false; - - // handle the builder override case separately - if (shouldOverrideBuilder === true) { - executionPayloadSource = ProducedBlockSource.engine; - logger.info("Selected engine block as censorship suspected in builder blocks", { - // winston logger doesn't like bigint - enginePayloadValue: `${enginePayloadValue}`, - consensusBlockValueEngine: `${consensusBlockValueEngine}`, - blockValueEngine: `${blockValueEngine}`, - shouldOverrideBuilder, - slot, - }); - } else if (fullBlock && blindedBlock) { - switch (builderSelection) { - case routes.validator.BuilderSelection.MaxProfit: { + const enginePromise = isEngineEnabled + ? produceEngineFullBlockOrContents(slot, randaoReveal, graffiti, { + feeRecipient, + strictFeeRecipientCheck, + // skip checking and recomputing head in these individual produce calls + skipHeadChecksAndUpdate: true, + commonBlockBody, + }).then((engineBlock) => { + // Once the engine returns a block, in the event of either: + // - suspected builder censorship + // - builder boost factor set to 0 or builder selection `executionalways` + // we don't need to wait for builder block as engine block will always be selected if ( - // explicitly handle the two special values mentioned in spec for builder preferred / engine preferred - builderBoostFactor !== MAX_BUILDER_BOOST_FACTOR && - (builderBoostFactor === BigInt(0) || - blockValueEngine >= (blockValueBuilder * builderBoostFactor) / BigInt(100)) + engineBlock.shouldOverrideBuilder || + builderBoostFactor === BigInt(0) || + builderSelection === routes.validator.BuilderSelection.ExecutionAlways ) { - executionPayloadSource = ProducedBlockSource.engine; - } else { - executionPayloadSource = ProducedBlockSource.builder; + controller.abort(); } - break; - } + return engineBlock; + }) + : Promise.reject(new Error("Engine disabled")); - case routes.validator.BuilderSelection.ExecutionAlways: - case routes.validator.BuilderSelection.ExecutionOnly: { - executionPayloadSource = ProducedBlockSource.engine; - break; - } + const [builder, engine] = await resolveOrRacePromises([builderPromise, enginePromise], { + resolveTimeoutMs: BLOCK_PRODUCTION_RACE_CUTOFF_MS, + raceTimeoutMs: BLOCK_PRODUCTION_RACE_TIMEOUT_MS, + signal: controller.signal, + }); - // For everything else just select the builder - default: { - executionPayloadSource = ProducedBlockSource.builder; - } - } - logger.info(`Selected executionPayloadSource=${executionPayloadSource} block`, { - builderSelection, - // winston logger doesn't like bigint - builderBoostFactor: `${builderBoostFactor}`, - enginePayloadValue: `${enginePayloadValue}`, - builderPayloadValue: `${builderPayloadValue}`, - consensusBlockValueEngine: `${consensusBlockValueEngine}`, - consensusBlockValueBuilder: `${consensusBlockValueBuilder}`, - blockValueEngine: `${blockValueEngine}`, - blockValueBuilder: `${blockValueBuilder}`, - shouldOverrideBuilder, - slot, - }); - } else if (fullBlock && !blindedBlock) { - executionPayloadSource = ProducedBlockSource.engine; - logger.info("Selected engine block: no builder block produced", { - // winston logger doesn't like bigint - enginePayloadValue: `${enginePayloadValue}`, - consensusBlockValueEngine: `${consensusBlockValueEngine}`, - blockValueEngine: `${blockValueEngine}`, - shouldOverrideBuilder, - slot, + if (builder.status === "pending" && engine.status === "pending") { + throw Error("Builder and engine both failed to produce the block within timeout"); + } + + if (builder.status === "rejected" && engine.status === "rejected") { + throw Error("Builder and engine both failed to produce the block"); + } + + if (engine.status === "rejected" && isEngineEnabled) { + logger.warn( + "Engine failed to produce the block", + { + ...loggerContext, + durationMs: engine.durationMs, + }, + engine.reason + ); + } + + if (builder.status === "rejected" && isBuilderEnabled) { + logger.warn( + "Builder failed to produce the block", + { + ...loggerContext, + durationMs: builder.durationMs, + }, + builder.reason + ); + } + + // handle shouldOverrideBuilder separately + if (engine.status === "fulfilled" && engine.value.shouldOverrideBuilder) { + logger.info("Selected engine block: censorship suspected in builder blocks", { + ...loggerContext, + durationMs: engine.durationMs, + shouldOverrideBuilder: engine.value.shouldOverrideBuilder, + ...getBlockValueLogInfo(engine.value), }); - } else if (blindedBlock && !fullBlock) { - executionPayloadSource = ProducedBlockSource.builder; + + return {...engine.value, executionPayloadBlinded: false, executionPayloadSource: ProducedBlockSource.engine}; + } + + if (builder.status === "fulfilled" && engine.status !== "fulfilled") { logger.info("Selected builder block: no engine block produced", { - // winston logger doesn't like bigint - builderPayloadValue: `${builderPayloadValue}`, - consensusBlockValueBuilder: `${consensusBlockValueBuilder}`, - blockValueBuilder: `${blockValueBuilder}`, - shouldOverrideBuilder, - slot, + ...loggerContext, + durationMs: builder.durationMs, + ...getBlockValueLogInfo(builder.value), }); + + return {...builder.value, executionPayloadBlinded: true, executionPayloadSource: ProducedBlockSource.builder}; } - if (executionPayloadSource === null) { - throw Error(`Failed to produce engine or builder block for slot=${slot}`); + if (engine.status === "fulfilled" && builder.status !== "fulfilled") { + logger.info("Selected engine block: no builder block produced", { + ...loggerContext, + durationMs: engine.durationMs, + ...getBlockValueLogInfo(engine.value), + }); + + return {...engine.value, executionPayloadBlinded: false, executionPayloadSource: ProducedBlockSource.engine}; } - if (executionPayloadSource === ProducedBlockSource.engine) { - return { - ...fullBlock, - executionPayloadBlinded: false, - executionPayloadSource, - } as routes.validator.ProduceBlockOrContentsRes & { - executionPayloadBlinded: false; - executionPayloadSource: ProducedBlockSource; - }; - } else { - return { - ...blindedBlock, - executionPayloadBlinded: true, - executionPayloadSource, - } as routes.validator.ProduceBlindedBlockRes & { - executionPayloadBlinded: true; - executionPayloadSource: ProducedBlockSource; - }; + if (engine.status === "fulfilled" && builder.status === "fulfilled") { + const executionPayloadSource = selectBlockProductionSource({ + builderBlockValue: builder.value.executionPayloadValue + builder.value.consensusBlockValue, + engineBlockValue: engine.value.executionPayloadValue + engine.value.consensusBlockValue, + builderBoostFactor, + builderSelection, + }); + + logger.info(`Selected ${executionPayloadSource} block`, { + ...loggerContext, + engineDurationMs: engine.durationMs, + ...getBlockValueLogInfo(engine.value, ProducedBlockSource.engine), + builderDurationMs: builder.durationMs, + ...getBlockValueLogInfo(builder.value, ProducedBlockSource.builder), + }); + + if (executionPayloadSource === ProducedBlockSource.engine) { + return { + ...engine.value, + executionPayloadBlinded: false, + executionPayloadSource, + }; + } else { + return { + ...builder.value, + executionPayloadBlinded: true, + executionPayloadSource, + }; + } } + + throw Error("Unreachable error occurred during the builder and execution block production"); }; const produceBlock: ServerApi["produceBlock"] = async function produceBlock( diff --git a/packages/beacon-node/src/api/impl/validator/utils.ts b/packages/beacon-node/src/api/impl/validator/utils.ts index 86ea223d59ab..8932f8951cf4 100644 --- a/packages/beacon-node/src/api/impl/validator/utils.ts +++ b/packages/beacon-node/src/api/impl/validator/utils.ts @@ -1,6 +1,8 @@ import {BeaconStateAllForks, computeSlotsSinceEpochStart} from "@lodestar/state-transition"; import {ATTESTATION_SUBNET_COUNT} from "@lodestar/params"; -import {BLSPubkey, CommitteeIndex, Slot, ValidatorIndex} from "@lodestar/types"; +import {routes} from "@lodestar/api"; +import {BLSPubkey, CommitteeIndex, ProducedBlockSource, Slot, ValidatorIndex} from "@lodestar/types"; +import {MAX_BUILDER_BOOST_FACTOR} from "@lodestar/validator"; export function computeSubnetForCommitteesAtSlot( slot: Slot, @@ -41,3 +43,31 @@ export function getPubkeysForIndices( return pubkeys; } + +export function selectBlockProductionSource({ + builderSelection, + engineBlockValue, + builderBlockValue, + builderBoostFactor, +}: { + builderSelection: routes.validator.BuilderSelection; + engineBlockValue: bigint; + builderBlockValue: bigint; + builderBoostFactor: bigint; +}): ProducedBlockSource { + switch (builderSelection) { + case routes.validator.BuilderSelection.ExecutionAlways: + case routes.validator.BuilderSelection.ExecutionOnly: + return ProducedBlockSource.engine; + + case routes.validator.BuilderSelection.MaxProfit: + return builderBoostFactor !== MAX_BUILDER_BOOST_FACTOR && + (builderBoostFactor === BigInt(0) || engineBlockValue >= (builderBlockValue * builderBoostFactor) / BigInt(100)) + ? ProducedBlockSource.engine + : ProducedBlockSource.builder; + + case routes.validator.BuilderSelection.BuilderAlways: + case routes.validator.BuilderSelection.BuilderOnly: + return ProducedBlockSource.builder; + } +} diff --git a/packages/utils/src/format.ts b/packages/utils/src/format.ts index 6a88ead41490..cf2352a4fbaa 100644 --- a/packages/utils/src/format.ts +++ b/packages/utils/src/format.ts @@ -1,4 +1,5 @@ import {toHexString} from "./bytes.js"; +import {ETH_TO_WEI} from "./ethConversion.js"; /** * Format bytes as `0x1234…1234` @@ -27,3 +28,29 @@ export function truncBytes(root: Uint8Array | string): string { const str = typeof root === "string" ? root : toHexString(root); return str.slice(0, 14); } + +/** + * Format a bigint value as a decimal string + */ +export function formatBigDecimal(numerator: bigint, denominator: bigint, maxDecimalFactor: bigint): string { + const full = numerator / denominator; + const fraction = ((numerator - full * denominator) * maxDecimalFactor) / denominator; + + // zeros to be added post decimal are number of zeros in maxDecimalFactor - number of digits in fraction + const zerosPostDecimal = String(maxDecimalFactor).length - 1 - String(fraction).length; + return `${full}.${"0".repeat(zerosPostDecimal)}${fraction}`; +} + +// display upto 5 decimal places +const MAX_DECIMAL_FACTOR = BigInt("100000"); + +/** + * Format wei as ETH, with up to 5 decimals + * + * if suffix is true, append ' ETH' + */ +export function prettyWeiToEth(wei: bigint, suffix = false): string { + let eth = formatBigDecimal(wei, ETH_TO_WEI, MAX_DECIMAL_FACTOR); + if (suffix) eth += " ETH"; + return eth; +} diff --git a/packages/utils/src/promise.ts b/packages/utils/src/promise.ts index 51e1cdbaf1e3..ba63854e9e85 100644 --- a/packages/utils/src/promise.ts +++ b/packages/utils/src/promise.ts @@ -1,4 +1,6 @@ +import {ErrorAborted, TimeoutError} from "./errors.js"; import {sleep} from "./sleep.js"; +import {ArrayToTuple, NonEmptyArray} from "./types.js"; /** * While promise t is not finished, call function `fn` per `interval` @@ -25,115 +27,129 @@ export async function callFnWhenAwait( return t; } -enum PromiseStatus { - resolved, - rejected, - pending, -} - -type PromiseState = - | {status: PromiseStatus.resolved; value: T} - | {status: PromiseStatus.rejected; value: Error} - | {status: PromiseStatus.pending; value: null}; - -function mapStatusesToResponses(promisesStates: PromiseState[]): (Error | T)[] { - return promisesStates.map((pmStatus) => { - switch (pmStatus.status) { - case PromiseStatus.resolved: - return pmStatus.value; - case PromiseStatus.rejected: - return pmStatus.value; - case PromiseStatus.pending: - return Error("pending"); +export type PromiseResult = { + promise: Promise; +} & ( + | { + status: "pending"; } - }); -} + | { + status: "fulfilled"; + value: T; + durationMs: number; + } + | { + status: "rejected"; + reason: Error; + durationMs: number; + } +); +export type PromiseFulfilledResult = PromiseResult & {status: "fulfilled"}; +export type PromiseRejectedResult = PromiseResult & {status: "rejected"}; -export enum RaceEvent { - /** all reject/resolve before cutoff */ - precutoff = "precutoff-return", - /** cutoff reached as some were pending till cutoff **/ - cutoff = "cutoff-reached", - /** atleast one resolved till cutoff so no race required */ - resolvedatcutoff = "resolved-at-cutoff", - /** if none reject/resolve before cutoff but one resolves or all reject before timeout */ - pretimeout = "pretimeout-return", - /** timeout reached as none resolved and some were pending till timeout*/ - timeout = "timeout-reached", +/** + * Wrap a promise to an object to track the status and value of the promise + */ +export function wrapPromise(promise: PromiseLike): PromiseResult { + const startedAt = Date.now(); + + const result = { + promise: promise.then( + (value) => { + result.status = "fulfilled"; + (result as PromiseFulfilledResult).value = value; + (result as PromiseFulfilledResult).durationMs = Date.now() - startedAt; + return value; + }, + (reason: unknown) => { + result.status = "rejected"; + (result as PromiseRejectedResult).reason = reason as Error; + (result as PromiseRejectedResult).durationMs = Date.now() - startedAt; + throw reason; + } + ), + status: "pending", + } as PromiseResult; - // events for the promises for better tracking - /** promise resolved */ - resolved = "resolved", - /** promise rejected */ - rejected = "rejected", + return result; } /** - * Wait for promises to resolve till cutoff and then race them beyond the cutoff with an overall timeout - * @return resolved values or rejections or still pending errors corresponding to input promises + * ArrayToTuple converts an `Array` to `[T, ...T]` + * + * eg: `[1, 2, 3]` from type `number[]` to `[number, number, number]` */ -export async function racePromisesWithCutoff( - promises: Promise[], - cutoffMs: number, - timeoutMs: number, - eventCb: (event: RaceEvent, delayMs: number, index?: number) => void -): Promise<(Error | T)[]> { - // start the cutoff and timeout timers - let cutoffObserved = false; - const cutoffPromise = sleep(cutoffMs).then(() => { - cutoffObserved = true; - }); - let timeoutObserved = false; - const timeoutPromise = sleep(timeoutMs).then(() => { - timeoutObserved = true; - }); - const startTime = Date.now(); +type ReturnPromiseWithTuple>> = { + [Index in keyof ArrayToTuple]: PromiseResult>; +}; - // Track promises status and resolved values/rejected errors - // Even if the promises reject with the following decoration promises will not throw - const promisesStates = [] as PromiseState[]; - promises.forEach((promise, index) => { - promisesStates[index] = {status: PromiseStatus.pending, value: null}; - promise - .then((value) => { - eventCb(RaceEvent.resolved, Date.now() - startTime, index); - promisesStates[index] = {status: PromiseStatus.resolved, value}; - }) - .catch((e: Error) => { - eventCb(RaceEvent.rejected, Date.now() - startTime, index); - promisesStates[index] = {status: PromiseStatus.rejected, value: e}; - }); - }); +/** + * Two phased approach for resolving promises: + * - first wait `resolveTimeoutMs` or until all promises settle + * - then wait `raceTimeoutMs - resolveTimeoutMs` or until at least a single promise resolves + * + * Returns a list of promise results, see `PromiseResult` + */ +export async function resolveOrRacePromises>>( + promises: T, + { + resolveTimeoutMs, + raceTimeoutMs, + signal, + }: { + resolveTimeoutMs: number; + raceTimeoutMs: number; + signal?: AbortSignal; + } +): Promise> | never { + if (raceTimeoutMs <= resolveTimeoutMs) { + throw new Error("Race time must be greater than resolve time"); + } + const resolveTimeoutError = new TimeoutError( + `Given promises can't be resolved within resolveTimeoutMs=${resolveTimeoutMs}` + ); + const raceTimeoutError = new TimeoutError( + `Not a any single promise be resolved in given raceTimeoutMs=${raceTimeoutMs}` + ); - // Wait till cutoff time unless all original promises resolve/reject early - await Promise.allSettled(promises.map((promise) => Promise.race([promise, cutoffPromise]))); - if (cutoffObserved) { - // If any is resolved, then just simply return as we are post cutoff - const anyResolved = promisesStates.reduce( - (acc, pmState) => acc || pmState.status === PromiseStatus.resolved, - false - ); - if (anyResolved) { - eventCb(RaceEvent.resolvedatcutoff, Date.now() - startTime); - return mapStatusesToResponses(promisesStates); - } else { - eventCb(RaceEvent.cutoff, Date.now() - startTime); + const promiseResults = promises.map((p) => wrapPromise(p)) as ReturnPromiseWithTuple; + promises = (promiseResults as PromiseResult[]).map((p) => p.promise) as unknown as T; + + try { + await Promise.race([ + Promise.allSettled(promises), + sleep(resolveTimeoutMs, signal).then(() => { + throw resolveTimeoutError; + }), + ]); + + return promiseResults; + } catch (err) { + if (err instanceof ErrorAborted) { + return promiseResults; + } + if (err !== resolveTimeoutError) { + throw err; } - } else { - eventCb(RaceEvent.precutoff, Date.now() - startTime); - return mapStatusesToResponses(promisesStates); } - // Post deadline resolve with any of the promise or all rejected before timeout - await Promise.any(promises.map((promise) => Promise.race([promise, timeoutPromise]))).catch( - // just ignore if all reject as we will returned mapped rejections - // eslint-disable-next-line @typescript-eslint/no-empty-function - (_e) => {} - ); - if (timeoutObserved) { - eventCb(RaceEvent.timeout, Date.now() - startTime); - } else { - eventCb(RaceEvent.pretimeout, Date.now() - startTime); + try { + await Promise.race([ + Promise.any(promises), + sleep(raceTimeoutMs - resolveTimeoutMs, signal).then(() => { + throw raceTimeoutError; + }), + ]); + + return promiseResults; + } catch (err) { + if (err instanceof ErrorAborted) { + return promiseResults; + } + if (err !== raceTimeoutError && !(err instanceof AggregateError)) { + throw err; + } } - return mapStatusesToResponses(promisesStates); + + return promiseResults; } diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index f302c9a4c80c..cf07331e4456 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -14,3 +14,9 @@ export type RecursivePartial = { export function bnToNum(bn: bigint): number { return Number(bn); } + +export type NonEmptyArray = [T, ...T[]]; + +export type ArrayToTuple> = { + [Index in keyof Tuple]: Tuple[Index]; +}; diff --git a/packages/utils/test/unit/format.test.ts b/packages/utils/test/unit/format.test.ts new file mode 100644 index 000000000000..11e8b89cb7a1 --- /dev/null +++ b/packages/utils/test/unit/format.test.ts @@ -0,0 +1,23 @@ +import {describe, it, expect} from "vitest"; +import {formatBigDecimal} from "../../src/format.js"; + +describe("format", () => { + describe("formatBigDecimal", () => { + const testCases: [bigint, bigint, bigint, string][] = [ + [BigInt("103797739275696858"), BigInt("1000000000000000000"), BigInt("100000"), "0.10379"], + [BigInt("103797739275696858"), BigInt("1000000000000000000"), BigInt("1000"), "0.103"], + [BigInt("10379773927569685"), BigInt("1000000000000000000"), BigInt("1000"), "0.010"], + [BigInt("1037977392756968"), BigInt("1000000000000000000"), BigInt("1000"), "0.001"], + [BigInt("1037977392756968"), BigInt("1000000000000000000"), BigInt("100000"), "0.00103"], + [BigInt("58200000000000000"), BigInt("1000000000000000000"), BigInt("100000"), "0.05820"], + [BigInt("111103797739275696858"), BigInt("1000000000000000000"), BigInt("100000"), "111.10379"], + [BigInt("111103797739275696858"), BigInt("1000000000000000000"), BigInt("1000"), "111.103"], + [BigInt("1037977392756"), BigInt("1000000000000000000"), BigInt("100000"), "0.00000"], + ]; + for (const [numerator, denominator, decimalFactor, expectedString] of testCases) { + it(`format ${numerator} / ${denominator} correctly to ${expectedString}`, () => { + expect(formatBigDecimal(numerator, denominator, decimalFactor)).toBe(expectedString); + }); + } + }); +}); diff --git a/packages/utils/test/unit/promise.test.ts b/packages/utils/test/unit/promise.test.ts new file mode 100644 index 000000000000..c76e72f70a22 --- /dev/null +++ b/packages/utils/test/unit/promise.test.ts @@ -0,0 +1,73 @@ +/* Causing this error on usage of expect.any(Number) */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +import {describe, it, expect} from "vitest"; +import {wrapPromise, PromiseRejectedResult, PromiseFulfilledResult} from "../../src/promise.js"; + +describe("promise", () => { + describe("wrapPromise", () => { + const timeoutMs = 100; + // TODO: Debug how promise is resolved quicker than the timeout + const promiseDurationMin = timeoutMs - 1; + // Add some margin for execution + const promiseDurationMax = timeoutMs + 20; + + it("should have initial status to pending", async () => { + const result = wrapPromise(Promise.resolve("my value")); + expect(result.status).toBe("pending"); + }); + + it("should resolve to value for a resolved promise", async () => { + const promise = Promise.resolve("my value"); + const result = wrapPromise(promise); + + await expect(promise).resolves.toBe("my value"); + expect(result).toEqual({ + value: "my value", + status: "fulfilled", + promise, + durationMs: expect.any(Number), + }); + }); + + it("should throw error for rejected promise", async () => { + const promise = Promise.reject("test error"); + const result = wrapPromise(promise); + + await expect(promise).rejects.toThrow("test error"); + await expect(result.promise).rejects.toThrow("test error"); + expect(result).toEqual({ + reason: "test error", + status: "rejected", + promise, + durationMs: expect.any(Number), + }); + }); + + it("should have correct durationMs attribute for promise which is resolved", async () => { + const promise = new Promise((resolve) => { + setTimeout(() => { + resolve("Resolved Value"); + }, timeoutMs); + }); + const result = wrapPromise(promise); + + await expect(promise).resolves.toBe("Resolved Value"); + expect((result as PromiseFulfilledResult).durationMs).toBeGreaterThanOrEqual(promiseDurationMin); + expect((result as PromiseFulfilledResult).durationMs).toBeLessThanOrEqual(promiseDurationMax); + }); + + it("should have correct durationMs attribute for promise which is rejected", async () => { + const promise = new Promise((_, reject) => { + setTimeout(() => { + reject("Rejected Error"); + }, timeoutMs); + }); + const result = wrapPromise(promise); + + await expect(promise).rejects.toThrow("Rejected Error"); + await expect(result.promise).rejects.toThrow("Rejected Error"); + expect((result as PromiseRejectedResult).durationMs).toBeGreaterThanOrEqual(promiseDurationMin); + expect((result as PromiseRejectedResult).durationMs).toBeLessThanOrEqual(promiseDurationMax); + }); + }); +}); diff --git a/packages/utils/test/unit/promiserace.test.ts b/packages/utils/test/unit/promiserace.test.ts index 5d0567553522..1f31a55014a4 100644 --- a/packages/utils/test/unit/promiserace.test.ts +++ b/packages/utils/test/unit/promiserace.test.ts @@ -1,7 +1,8 @@ import {describe, it, expect} from "vitest"; -import {racePromisesWithCutoff, RaceEvent} from "../../src/promise.js"; +import {resolveOrRacePromises, PromiseResult} from "../../src/promise.js"; +import {NonEmptyArray} from "../../src/types.js"; -describe("racePromisesWithCutoff", () => { +describe("resolveOrRacePromises", () => { const cutoffMs = 1000; const timeoutMs = 1500; @@ -9,96 +10,73 @@ describe("racePromisesWithCutoff", () => { new Promise((resolve) => { setTimeout(() => resolve(value), delay); }); + const rejectAfter = (value: string, delay: number): Promise => new Promise((_resolve, reject) => { setTimeout(() => reject(Error(value)), delay); }); - // For brevity in testcases - const precutoff = RaceEvent.precutoff; - const cutoff = RaceEvent.cutoff; - const resolvedatcutoff = RaceEvent.resolvedatcutoff; - const pretimeout = RaceEvent.pretimeout; - const timeout = RaceEvent.timeout; - const resolved = RaceEvent.resolved; - const rejected = RaceEvent.rejected; - - // Second item in testcase row i.e. array of numbers represent delay at which promise to be resolved - // or rejected (-ve number) - // Third item in testcase row is the expected value or error message in string - // Last item is expected events - const testcases: [string, number[], (string | Error)[], RaceEvent[]][] = [ - ["all resolve pre-cutoff", [100, 200], ["100", "200"], [resolved, resolved, precutoff]], - ["all resolve/reject pre-cutoff", [100, -200], ["100", "-200"], [resolved, rejected, precutoff]], - ["all reject pre-cutoff", [-100, -200], ["-100", "-200"], [rejected, rejected, precutoff]], - ["all reject pre-timeout", [-1100, -1200], ["-1100", "-1200"], [cutoff, rejected, rejected, pretimeout]], - ["race and resolve pre-timeout", [1100, 1200], ["1100", "pending"], [cutoff, resolved, pretimeout]], - [ - "race and resolve/reject pre-timeout", - [-1100, 1200, 1300], - ["-1100", "1200", "pending"], - [cutoff, rejected, resolved, pretimeout], - ], + const testCases: [string, number[], (string | Error)[]][] = [ + ["all resolve pre-cutoff", [100, 200], ["100", "200"]], + ["all resolve/reject pre-cutoff", [100, -200], ["100", "-200"]], + ["all reject pre-cutoff", [-100, -200], ["-100", "-200"]], + ["all reject pre-timeout", [-1100, -1200], ["-1100", "-1200"]], + ["race and resolve pre-timeout", [1100, 1200], ["1100", "pending"]], + ["race and resolve/reject pre-timeout", [-1100, 1200, 1300], ["-1100", "1200", "pending"]], [ "some resolve pre-cutoff with no race post cutoff", [100, -200, -1100, 1200], ["100", "-200", "pending", "pending"], - [resolved, rejected, resolvedatcutoff], ], [ "some reject pre-cutoff, with race resolution pre-timeout", [-100, -200, -1100, 1100, 1200], ["-100", "-200", "-1100", "1100", "pending"], - [rejected, rejected, cutoff, rejected, resolved, pretimeout], - ], - [ - "some reject pre-cutoff, rest reject pre-timeout", - [-100, -200, -1100, -1200], - ["-100", "-200", "-1100", "-1200"], - [rejected, rejected, cutoff, rejected, rejected, pretimeout], ], + ["some reject pre-cutoff, rest reject pre-timeout", [-100, -200, -1100, -1200], ["-100", "-200", "-1100", "-1200"]], [ "some resolve/reject pre-cutoff, some resolve/reject pre-timeout but no race beyond cutoff", [100, -200, -1100, 1100, 1700, -1700], ["100", "-200", "pending", "pending", "pending", "pending"], - [resolved, rejected, resolvedatcutoff], ], [ "none resolve/reject pre-cutoff with race resolution pre timeout", [-1100, 1200, 1700], ["-1100", "1200", "pending"], - [cutoff, rejected, resolved, pretimeout], - ], - [ - "none resolve pre-cutoff with race resolution pre timeout", - [1100, 1200, 1700], - ["1100", "pending", "pending"], - [cutoff, resolved, pretimeout], ], + ["none resolve pre-cutoff with race resolution pre timeout", [1100, 1200, 1700], ["1100", "pending", "pending"]], [ "some reject pre-cutoff, some reject pre-timeout, but no resolution till timeout", [-100, -1100, -1200, 1700, -1800], ["-100", "-1100", "-1200", "pending", "pending"], - [rejected, cutoff, rejected, rejected, timeout], ], - ["none resolve/reject pre timeout", [1600, -1700], ["pending", "pending"], [cutoff, timeout]], + ["none resolve/reject pre timeout", [1600, -1700], ["pending", "pending"]], ]; - for (const [name, promises, results, events] of testcases) { + for (const [name, timeouts, results] of testCases) { it(name, async () => { - const testPromises = promises.map((timeMs) => { + const testPromises = timeouts.map((timeMs) => { if (timeMs > 0) { return resolveAfter(`${timeMs}`, timeMs); } else { return rejectAfter(`${timeMs}`, -timeMs); } }); - const testEvents: RaceEvent[] = []; - const testResults = await racePromisesWithCutoff(testPromises, cutoffMs, timeoutMs, (event, _delayMs) => - testEvents.push(event) - ); - const testResultsCmp = testResults.map((res: string | Error) => (res instanceof Error ? res.message : res)); - expect({results: testResultsCmp, events: testEvents}).toEqual({results, events}); + const testResults = (await resolveOrRacePromises(testPromises as unknown as NonEmptyArray>, { + resolveTimeoutMs: cutoffMs, + raceTimeoutMs: timeoutMs, + })) as PromiseResult[]; + const testResultsCmp = testResults.map((r) => { + switch (r.status) { + case "fulfilled": + return r.value; + case "rejected": + return r.reason.message; + default: + return "pending"; + } + }); + expect(testResultsCmp).toEqual(results); }); } }); diff --git a/packages/validator/src/services/block.ts b/packages/validator/src/services/block.ts index dd7cea13c293..984550791384 100644 --- a/packages/validator/src/services/block.ts +++ b/packages/validator/src/services/block.ts @@ -11,12 +11,11 @@ import { } from "@lodestar/types"; import {ChainForkConfig} from "@lodestar/config"; import {ForkPreBlobs, ForkBlobs, ForkSeq, ForkExecution} from "@lodestar/params"; -import {ETH_TO_WEI, extendError, prettyBytes} from "@lodestar/utils"; +import {ETH_TO_WEI, extendError, formatBigDecimal, prettyBytes} from "@lodestar/utils"; import {Api, ApiError, routes} from "@lodestar/api"; import {IClock, LoggerVc} from "../util/index.js"; import {PubkeyHex} from "../types.js"; import {Metrics} from "../metrics.js"; -import {formatBigDecimal} from "../util/format.js"; import {ValidatorStore} from "./validatorStore.js"; import {BlockDutiesService, GENESIS_SLOT} from "./blockDuties.js"; diff --git a/packages/validator/src/util/format.ts b/packages/validator/src/util/format.ts index 6f4b61cf6826..a405383232c9 100644 --- a/packages/validator/src/util/format.ts +++ b/packages/validator/src/util/format.ts @@ -1,12 +1,3 @@ export function isValidatePubkeyHex(pubkeyHex: string): boolean { return /^0x[0-9a-fA-F]{96}$/.test(pubkeyHex); } - -export function formatBigDecimal(numerator: bigint, denominator: bigint, maxDecimalFactor: bigint): string { - const full = numerator / denominator; - const fraction = ((numerator - full * denominator) * maxDecimalFactor) / denominator; - - // zeros to be added post decimal are number of zeros in maxDecimalFactor - number of digits in fraction - const zerosPostDecimal = String(maxDecimalFactor).length - 1 - String(fraction).length; - return `${full}.${"0".repeat(zerosPostDecimal)}${fraction}`; -} diff --git a/packages/validator/test/unit/utils/format.test.ts b/packages/validator/test/unit/utils/format.test.ts deleted file mode 100644 index ab75c8fa1b72..000000000000 --- a/packages/validator/test/unit/utils/format.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {describe, it, expect} from "vitest"; -import {formatBigDecimal} from "../../../src/util/format.js"; - -describe("util / formatBigDecimal", function () { - const testCases: [bigint, bigint, bigint, string][] = [ - [BigInt("103797739275696858"), BigInt("1000000000000000000"), BigInt("100000"), "0.10379"], - [BigInt("103797739275696858"), BigInt("1000000000000000000"), BigInt("1000"), "0.103"], - [BigInt("10379773927569685"), BigInt("1000000000000000000"), BigInt("1000"), "0.010"], - [BigInt("1037977392756968"), BigInt("1000000000000000000"), BigInt("1000"), "0.001"], - [BigInt("1037977392756968"), BigInt("1000000000000000000"), BigInt("100000"), "0.00103"], - [BigInt("58200000000000000"), BigInt("1000000000000000000"), BigInt("100000"), "0.05820"], - [BigInt("111103797739275696858"), BigInt("1000000000000000000"), BigInt("100000"), "111.10379"], - [BigInt("111103797739275696858"), BigInt("1000000000000000000"), BigInt("1000"), "111.103"], - [BigInt("1037977392756"), BigInt("1000000000000000000"), BigInt("100000"), "0.00000"], - ]; - for (const [numerator, denominator, decimalFactor, expectedString] of testCases) { - it(`format ${numerator} / ${denominator} correctly to ${expectedString}`, () => { - expect(formatBigDecimal(numerator, denominator, decimalFactor)).toBe(expectedString); - }); - } -}); From b511d8394fe3ef5f609b45906245754390e7fcb8 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 5 Feb 2024 17:21:03 +0100 Subject: [PATCH 21/71] feat: allow to execute lodestar script inside docker container (#6392) --- lodestar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lodestar b/lodestar index 0b20ba4c9bcd..7cf5301e4de4 100755 --- a/lodestar +++ b/lodestar @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh # Convenience script to run the lodestar binary from built source # From 7995c97f46944446ff81caeb1db766ec165e6008 Mon Sep 17 00:00:00 2001 From: Phil Ngo <58080811+philknows@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:39:49 -0500 Subject: [PATCH 22/71] chore: update funding.yml link (#6385) Update funding.yml link --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 709ceff687ac..989f4bc9c0b5 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -custom: https://gitcoin.co/grants/6034/lodestar-typescript-eth-consensus-client-by-chains +custom: https://etherscan.io/address/0xb4da52336092db22fe8e036866d59c6488604f89 From c4bf38576e0cba5880697de3a5ca4956162ede5e Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 6 Feb 2024 09:37:14 +0100 Subject: [PATCH 23/71] chore: fix failing sim tests (#6389) * Disable /ipfs/id/push/1.0.0 * Fix the peer disconnect errors * Align genesis time for logging * Fix genesis state issue * Increase timeotu for keystore unit test * Remove unintended protocol * Fix the test timeout * Update stopChildProcess * Update the @chainsafe/libp2p-identify * Compute effective genesis delay * Update workflow file to make it consistent * Increase the genesis delay calculation --- .github/workflows/test-sim.yml | 20 +++++++-- packages/beacon-node/package.json | 1 + .../beacon-node/src/network/libp2p/index.ts | 3 +- .../cli/test/sim/backup_eth_provider.test.ts | 1 + packages/cli/test/sim/deneb.test.ts | 5 ++- packages/cli/test/sim/endpoints.test.ts | 1 + packages/cli/test/sim/mixed_client.test.ts | 1 + packages/cli/test/sim/multi_fork.test.ts | 1 + .../keymanager/keystoreCache.test.ts | 5 ++- .../cli/test/utils/simulation/utils/index.ts | 30 ++++++++++++- .../simulation/validator_clients/index.ts | 4 +- .../validator_clients/lighthouse.ts | 1 - .../simulation/validator_clients/lodestar.ts | 2 +- packages/test-utils/src/childProcess.ts | 26 +++++++++++- yarn.lock | 42 +++++++++++++++++++ 15 files changed, 127 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test-sim.yml b/.github/workflows/test-sim.yml index 65260fc38937..a90152d4ee3b 100644 --- a/.github/workflows/test-sim.yml +++ b/.github/workflows/test-sim.yml @@ -58,6 +58,12 @@ jobs: if: steps.cache-deps.outputs.cache-hit == 'true' # + - name: Download required docker images before running tests + run: | + docker pull ${{env.GETH_DOCKER_IMAGE}} + docker pull ${{env.LIGHTHOUSE_DOCKER_IMAGE}} + docker pull ${{env.NETHERMIND_DOCKER_IMAGE}} + - name: Sim tests multifork run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:multifork working-directory: packages/cli @@ -65,20 +71,28 @@ jobs: GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} - name: Sim tests endpoints - run: yarn test:sim:endpoints + run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:endpoints working-directory: packages/cli + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} - name: Sim tests deneb - run: yarn test:sim:deneb + run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:deneb working-directory: packages/cli + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} - name: Sim tests backup eth provider - run: yarn test:sim:backup_eth_provider + run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:backup_eth_provider working-directory: packages/cli + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} - name: Sim tests mixed client run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:mixedclient working-directory: packages/cli + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} - name: Upload debug log test files for "packages/cli" if: ${{ always() }} diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 90f2026e1873..f24963622d93 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -102,6 +102,7 @@ "@chainsafe/enr": "^3.0.0", "@chainsafe/libp2p-gossipsub": "^11.2.0", "@chainsafe/libp2p-noise": "^14.1.0", + "@chainsafe/libp2p-identify": "^1.0.0", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/prometheus-gc-stats": "^1.0.0", "@chainsafe/ssz": "^0.14.0", diff --git a/packages/beacon-node/src/network/libp2p/index.ts b/packages/beacon-node/src/network/libp2p/index.ts index ccbd07355c32..8a8cca38c167 100644 --- a/packages/beacon-node/src/network/libp2p/index.ts +++ b/packages/beacon-node/src/network/libp2p/index.ts @@ -1,7 +1,8 @@ import {PeerId} from "@libp2p/interface"; import {Registry} from "prom-client"; import {ENR} from "@chainsafe/enr"; -import {identify} from "@libp2p/identify"; +// TODO: We should use this fork until https://github.com/libp2p/js-libp2p/pull/2387 +import {identify} from "@chainsafe/libp2p-identify"; import {bootstrap} from "@libp2p/bootstrap"; import {mdns} from "@libp2p/mdns"; import {createLibp2p} from "libp2p"; diff --git a/packages/cli/test/sim/backup_eth_provider.test.ts b/packages/cli/test/sim/backup_eth_provider.test.ts index 40ad7d4661de..5a38a27dc8f0 100644 --- a/packages/cli/test/sim/backup_eth_provider.test.ts +++ b/packages/cli/test/sim/backup_eth_provider.test.ts @@ -16,6 +16,7 @@ const {estimatedTimeoutMs, forkConfig} = defineSimTestConfig({ ALTAIR_FORK_EPOCH: altairForkEpoch, BELLATRIX_FORK_EPOCH: bellatrixForkEpoch, runTillEpoch: runTillEpoch + syncWaitEpoch, + initialNodes: 3, }); const env = await SimulationEnvironment.initWithDefaults( diff --git a/packages/cli/test/sim/deneb.test.ts b/packages/cli/test/sim/deneb.test.ts index 5ed84d3d2792..b66252b06892 100644 --- a/packages/cli/test/sim/deneb.test.ts +++ b/packages/cli/test/sim/deneb.test.ts @@ -18,12 +18,13 @@ const {estimatedTimeoutMs, forkConfig} = defineSimTestConfig({ ALTAIR_FORK_EPOCH: altairForkEpoch, BELLATRIX_FORK_EPOCH: bellatrixForkEpoch, runTillEpoch: runTillEpoch + syncWaitEpoch, + initialNodes: 2, }); const env = await SimulationEnvironment.initWithDefaults( { - id: "multi-fork", - logsDir: path.join(logFilesDir, "multi-fork"), + id: "deneb", + logsDir: path.join(logFilesDir, "deneb"), forkConfig, }, [ diff --git a/packages/cli/test/sim/endpoints.test.ts b/packages/cli/test/sim/endpoints.test.ts index ea55b70e26c1..a31b561e0578 100644 --- a/packages/cli/test/sim/endpoints.test.ts +++ b/packages/cli/test/sim/endpoints.test.ts @@ -16,6 +16,7 @@ const {estimatedTimeoutMs, forkConfig} = defineSimTestConfig({ ALTAIR_FORK_EPOCH: altairForkEpoch, BELLATRIX_FORK_EPOCH: bellatrixForkEpoch, runTillEpoch: 2, + initialNodes: 1, }); const env = await SimulationEnvironment.initWithDefaults( diff --git a/packages/cli/test/sim/mixed_client.test.ts b/packages/cli/test/sim/mixed_client.test.ts index ad2095f8c378..80c20471ede5 100644 --- a/packages/cli/test/sim/mixed_client.test.ts +++ b/packages/cli/test/sim/mixed_client.test.ts @@ -17,6 +17,7 @@ const {estimatedTimeoutMs, forkConfig} = defineSimTestConfig({ BELLATRIX_FORK_EPOCH: bellatrixForkEpoch, CAPELLA_FORK_EPOCH: capellaForkEpoch, runTillEpoch: runTillEpoch + syncWaitEpoch, + initialNodes: 2, }); const env = await SimulationEnvironment.initWithDefaults( diff --git a/packages/cli/test/sim/multi_fork.test.ts b/packages/cli/test/sim/multi_fork.test.ts index 24f42498c638..70f119609454 100644 --- a/packages/cli/test/sim/multi_fork.test.ts +++ b/packages/cli/test/sim/multi_fork.test.ts @@ -27,6 +27,7 @@ const {estimatedTimeoutMs, forkConfig} = defineSimTestConfig({ BELLATRIX_FORK_EPOCH: bellatrixForkEpoch, CAPELLA_FORK_EPOCH: capellaForkEpoch, runTillEpoch: runTillEpoch + syncWaitEpoch, + initialNodes: 5, }); const env = await SimulationEnvironment.initWithDefaults( diff --git a/packages/cli/test/unit/cmds/validator/keymanager/keystoreCache.test.ts b/packages/cli/test/unit/cmds/validator/keymanager/keystoreCache.test.ts index ee0fedf301b6..40964a0a7b7d 100644 --- a/packages/cli/test/unit/cmds/validator/keymanager/keystoreCache.test.ts +++ b/packages/cli/test/unit/cmds/validator/keymanager/keystoreCache.test.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import {randomBytes} from "node:crypto"; -import {describe, it, expect, beforeEach} from "vitest"; +import {describe, it, expect, beforeEach, vi} from "vitest"; import tmp from "tmp"; import {Keystore} from "@chainsafe/bls-keystore"; import bls from "@chainsafe/bls"; @@ -12,6 +12,7 @@ import {LocalKeystoreDefinition} from "../../../../../src/cmds/validator/keymana const numberOfSigners = 10; describe("keystoreCache", () => { + vi.setConfig({testTimeout: 10000, hookTimeout: 50000}); let definitions: LocalKeystoreDefinition[]; let signers: SignerLocal[]; let secretKeys: Uint8Array[]; @@ -50,7 +51,7 @@ describe("keystoreCache", () => { passwords.push(password); secretKeys.push(secretKey.toBytes()); } - }, 50000); + }); describe("writeKeystoreCache", () => { it("should write a valid keystore cache file", async () => { diff --git a/packages/cli/test/utils/simulation/utils/index.ts b/packages/cli/test/utils/simulation/utils/index.ts index dfa66bed6580..bc0a4ee98d6f 100644 --- a/packages/cli/test/utils/simulation/utils/index.ts +++ b/packages/cli/test/utils/simulation/utils/index.ts @@ -17,18 +17,44 @@ export const avg = (arr: number[]): number => { return arr.length === 0 ? 0 : arr.reduce((p, c) => p + c, 0) / arr.length; }; +function getGenesisDelaySlots(initialNodes?: number): number { + if (process.env.GENESIS_DELAY_SLOTS) { + const genesisDelaySlots = parseInt(process.env.GENESIS_DELAY_SLOTS); + // If custom job is invoked and want to use default genesis delay then provider -1 as value + if (genesisDelaySlots >= 0) return genesisDelaySlots; + } + + if (initialNodes == null) return 40; + // Considering each node consists of EN, BN, VC and KM + // EN - Execution Node - 15s + const execution = 15; + // BN - Beacon Node - 15s + const beacon = 15; + // VC - Validator Client - 10s + const validator = 10; + // KM - Key Manager - 3s + const keyManager = 3; + // Initial script launch time - 10s + const initialLaunchScript = 10; + + return Math.ceil( + ((execution + beacon + validator + keyManager) * initialNodes + initialLaunchScript) / SIM_TESTS_SECONDS_PER_SLOT + ); +} + export function defineSimTestConfig( opts: Partial & { cliqueSealingPeriod?: number; additionalSlotsForTTD?: number; runTillEpoch: number; + // Used to calculate genesis delay + initialNodes?: number; } ): { estimatedTimeoutMs: number; forkConfig: ChainForkConfig; } { - const genesisDelaySeconds = - (process.env.GENESIS_DELAY_SLOTS ? parseInt(process.env.GENESIS_DELAY_SLOTS) : 40) * SIM_TESTS_SECONDS_PER_SLOT; + const genesisDelaySeconds = getGenesisDelaySlots(opts.initialNodes) * SIM_TESTS_SECONDS_PER_SLOT; const estimatedTimeoutMs = getEstimatedTimeInSecForRun({ diff --git a/packages/cli/test/utils/simulation/validator_clients/index.ts b/packages/cli/test/utils/simulation/validator_clients/index.ts index 1334382407e8..a75cbf6b1660 100644 --- a/packages/cli/test/utils/simulation/validator_clients/index.ts +++ b/packages/cli/test/utils/simulation/validator_clients/index.ts @@ -14,14 +14,14 @@ export async function createValidatorNode( "id" | "paths" | "forkConfig" | "nodeIndex" | "genesisTime" | "runner" | "beaconUrls" > ): Promise { - const {runner, forkConfig} = options; + const {runner} = options; const clId = `${options.id}-${client}`; const opts: ValidatorGeneratorOptions = { ...options, id: clId, keys: options.keys ?? {type: "no-keys"}, - genesisTime: options.genesisTime + forkConfig.GENESIS_DELAY, + genesisTime: options.genesisTime, clientOptions: options.clientOptions ?? {}, address: "127.0.0.1", }; diff --git a/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts b/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts index 27b2f485588d..a663fd0026c6 100644 --- a/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts +++ b/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts @@ -39,7 +39,6 @@ export const generateLighthouseValidatorNode: ValidatorNodeGenerator { + const pid = childProcess.pid; + + await new Promise((resolve, reject) => { childProcess.once("error", reject); - childProcess.once("close", resolve); + // We use `exit` instead of `close` as multiple processes can share same `stdio` + childProcess.once("exit", resolve); childProcess.kill(signal); }); + + if (pid != null && isPidRunning(pid)) { + // Wait for sometime and try to kill this time + await sleep(500); + await stopChildProcess(childProcess, "SIGKILL"); + } }; /** diff --git a/yarn.lock b/yarn.lock index 839c0dce5e90..0780e0bc2ef8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -385,6 +385,23 @@ uint8arraylist "^2.4.8" uint8arrays "^5.0.1" +"@chainsafe/libp2p-identify@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-identify/-/libp2p-identify-1.0.0.tgz#28191e619715a87c140d8b516ee85cb7d39e41e0" + integrity sha512-X+VWUC0xeCFIulE4BU5M8FmTxZ/OKzku+9/1UaX2EG1LcqQkCDrPi6CCODbE0SraqImG4aVHRbiCFWxKEfE8wQ== + dependencies: + "@libp2p/interface" "^1.1.2" + "@libp2p/interface-internal" "^1.0.7" + "@libp2p/peer-id" "^4.0.5" + "@libp2p/peer-record" "^7.0.7" + "@multiformats/multiaddr" "^12.1.10" + "@multiformats/multiaddr-matcher" "^1.1.0" + it-protobuf-stream "^1.1.1" + protons-runtime "^5.0.0" + uint8arraylist "^2.4.7" + uint8arrays "^5.0.0" + wherearewe "^2.0.1" + "@chainsafe/libp2p-noise@^14.1.0": version "14.1.0" resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-noise/-/libp2p-noise-14.1.0.tgz#4084a448cec73a941fddfc94751f6ce2e23c07cd" @@ -1629,6 +1646,21 @@ uint8arraylist "^2.4.3" uint8arrays "^5.0.0" +"@libp2p/peer-record@^7.0.7": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@libp2p/peer-record/-/peer-record-7.0.7.tgz#e55145b2509592696f42ff73c38f813efbbbc688" + integrity sha512-RsggFJVAWQBA2z+ZJsK5nKHDKLmSd89IhFiE5GyImedQFiMkJz/gDFROzfNF2NdOyEBNdRy5SmC9scNFRQQD9A== + dependencies: + "@libp2p/crypto" "^4.0.1" + "@libp2p/interface" "^1.1.2" + "@libp2p/peer-id" "^4.0.5" + "@libp2p/utils" "^5.2.3" + "@multiformats/multiaddr" "^12.1.10" + protons-runtime "^5.0.0" + uint8-varint "^2.0.2" + uint8arraylist "^2.4.7" + uint8arrays "^5.0.0" + "@libp2p/peer-store@^10.0.5": version "10.0.5" resolved "https://registry.yarnpkg.com/@libp2p/peer-store/-/peer-store-10.0.5.tgz#b969d1707f5dcbf4d110e099270de285b075aa02" @@ -8054,6 +8086,16 @@ it-protobuf-stream@^1.0.2: protons-runtime "^5.0.0" uint8arraylist "^2.4.1" +it-protobuf-stream@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/it-protobuf-stream/-/it-protobuf-stream-1.1.2.tgz#4444d78fcae0fce949b4cbea622bf1d92667e64f" + integrity sha512-epZBuG+7cPaTxCR/Lf3ApshBdA9qfflGPQLfLLrp9VQ0w67Z2xo4H+SLLetav57/29oPtAXwVaoyemg99JOWzA== + dependencies: + it-length-prefixed-stream "^1.0.0" + it-stream-types "^2.0.1" + protons-runtime "^5.0.0" + uint8arraylist "^2.4.1" + it-pushable@^3.0.0, it-pushable@^3.1.2, it-pushable@^3.2.0, it-pushable@^3.2.1, it-pushable@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/it-pushable/-/it-pushable-3.2.3.tgz#e2b80aed90cfbcd54b620c0a0785e546d4e5f334" From d8b500add9ac830dcf671341616e19586a752dd8 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 6 Feb 2024 15:18:33 +0100 Subject: [PATCH 24/71] chore: upgrade geth and nethermind for sim tests (#6395) Upgrade Geth and Nethermind --- .github/workflows/test-sim.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-sim.yml b/.github/workflows/test-sim.yml index a90152d4ee3b..20eee3d11e77 100644 --- a/.github/workflows/test-sim.yml +++ b/.github/workflows/test-sim.yml @@ -23,9 +23,9 @@ on: default: 40 env: - GETH_DOCKER_IMAGE: ethereum/client-go:v1.11.6 + GETH_DOCKER_IMAGE: ethereum/client-go:v1.13.11 LIGHTHOUSE_DOCKER_IMAGE: sigp/lighthouse:latest-amd64-modern-dev - NETHERMIND_DOCKER_IMAGE: nethermind/nethermind:1.18.0 + NETHERMIND_DOCKER_IMAGE: nethermind/nethermind:1.25.3 jobs: tests-sim: From cb754f61164fdf9399d027de6b1ba12b33f24e7e Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 6 Feb 2024 15:24:19 +0100 Subject: [PATCH 25/71] fix: increase e2e env startup timeout (#6396) Increase e2e timeout --- scripts/run_e2e_env.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run_e2e_env.sh b/scripts/run_e2e_env.sh index 08f1680b30c6..e22b44ae6c00 100755 --- a/scripts/run_e2e_env.sh +++ b/scripts/run_e2e_env.sh @@ -6,7 +6,7 @@ function start_app() { nohup node --loader ts-node/esm packages/cli/test/scripts/e2e_test_env.ts > test-logs/e2e-test-env/simulation.out 2>&1 & echo $! > test-logs/e2e-test-env/simulation.pid echo "Wait for the node to be ready" - npx wait-port -t 60000 0.0.0.0:5001 + npx wait-port -t 120000 0.0.0.0:5001 } function stop_app() { From 274871de3f990b2f2fbf0dbfc768ce057e9efd4b Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 6 Feb 2024 17:02:15 +0100 Subject: [PATCH 26/71] chore: improve the sim tests logs (#6394) * Improve the sim tests logs * Update packages/utils/src/format.ts --------- Co-authored-by: Nico Flaig --- .../cli/test/sim/backup_eth_provider.test.ts | 3 ++ packages/cli/test/sim/multi_fork.test.ts | 3 ++ .../utils/simulation/SimulationEnvironment.ts | 30 ++++++++++++++----- .../cli/test/utils/simulation/interfaces.ts | 14 ++++----- packages/test-utils/src/childProcess.ts | 18 ++++++----- packages/utils/src/format.ts | 8 +++++ 6 files changed, 55 insertions(+), 21 deletions(-) diff --git a/packages/cli/test/sim/backup_eth_provider.test.ts b/packages/cli/test/sim/backup_eth_provider.test.ts index 5a38a27dc8f0..52ad83a4f5f8 100644 --- a/packages/cli/test/sim/backup_eth_provider.test.ts +++ b/packages/cli/test/sim/backup_eth_provider.test.ts @@ -79,4 +79,7 @@ await waitForSlot(env.clock.getLastSlotOfEpoch(bellatrixForkEpoch) + activePrese env, }); +await node2.beacon.job.stop(); +await node3.beacon.job.stop(); + await env.stop(); diff --git a/packages/cli/test/sim/multi_fork.test.ts b/packages/cli/test/sim/multi_fork.test.ts index 70f119609454..e15f8b01fe90 100644 --- a/packages/cli/test/sim/multi_fork.test.ts +++ b/packages/cli/test/sim/multi_fork.test.ts @@ -259,4 +259,7 @@ await waitForHead(env, unknownBlockSync, { slot: headForUnknownBlockSync.response.data.message.slot, }); +await unknownBlockSync.beacon.job.stop(); +await unknownBlockSync.execution.job.stop(); + await env.stop(); diff --git a/packages/cli/test/utils/simulation/SimulationEnvironment.ts b/packages/cli/test/utils/simulation/SimulationEnvironment.ts index 5baec1b79048..3acd217e225e 100644 --- a/packages/cli/test/utils/simulation/SimulationEnvironment.ts +++ b/packages/cli/test/utils/simulation/SimulationEnvironment.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import {EventEmitter} from "node:events"; import fs from "node:fs"; import {mkdir, writeFile} from "node:fs/promises"; import path from "node:path"; @@ -9,6 +8,7 @@ import {nodeUtils} from "@lodestar/beacon-node"; import {ChainForkConfig} from "@lodestar/config"; import {activePreset} from "@lodestar/params"; import {BeaconStateAllForks, interopSecretKey} from "@lodestar/state-transition"; +import {prettyMsToTime} from "@lodestar/utils"; import {EpochClock, MS_IN_SEC} from "./EpochClock.js"; import {ExternalSignerServer} from "./ExternalSignerServer.js"; import {SimulationTracker} from "./SimulationTracker.js"; @@ -42,7 +42,6 @@ export class SimulationEnvironment { readonly nodes: NodePair[] = []; readonly clock: EpochClock; readonly tracker: SimulationTracker; - readonly emitter: EventEmitter; readonly runner: IRunner; readonly externalSigner: ExternalSignerServer; @@ -52,6 +51,7 @@ export class SimulationEnvironment { private keysCount = 0; private nodePairCount = 0; private genesisState?: BeaconStateAllForks; + private runTimeout?: NodeJS.Timeout; private constructor(forkConfig: ChainForkConfig, options: SimulationOptions) { this.forkConfig = forkConfig; @@ -64,7 +64,6 @@ export class SimulationEnvironment { signal: this.options.controller.signal, }); - this.emitter = new EventEmitter(); this.externalSigner = new ExternalSignerServer([]); this.runner = new Runner({logsDir: this.options.logsDir}); this.tracker = SimulationTracker.initWithDefaultAssertions({ @@ -96,8 +95,14 @@ export class SimulationEnvironment { async start(opts: StartOpts): Promise { const currentTime = Date.now(); + console.log( + `Starting simulation environment "${this.options.id}". currentTime=${new Date( + currentTime + ).toISOString()} simulationTimeout=${prettyMsToTime(opts.runTimeoutMs)}` + ); + if (opts.runTimeoutMs > 0) { - setTimeout(() => { + this.runTimeout = setTimeout(() => { const slots = this.clock.getSlotFor((currentTime + opts.runTimeoutMs) / MS_IN_SEC); const epoch = this.clock.getEpochForSlot(slots); const slot = this.clock.getSlotIndexInEpoch(slots); @@ -116,7 +121,7 @@ export class SimulationEnvironment { this.stop( 1, - `Start sequence not completed before genesis, in ${msToGenesis}ms (approx. ${epoch}/${slot}).` + `Start sequence not completed before genesis, in ${prettyMsToTime(msToGenesis)} (approx. ${epoch}/${slot}).` ).catch((e) => console.error("Error on stop", e)); }, msToGenesis); @@ -126,21 +131,27 @@ export class SimulationEnvironment { await mkdir(this.options.rootDir); } + console.log("Starting the simulation runner"); await this.runner.start(); + + console.log("Starting execution nodes"); await Promise.all(this.nodes.map((node) => node.execution.job.start())); + console.log("Initializing genesis state for beacon nodes"); await this.initGenesisState(); if (!this.genesisState) { throw new Error("The genesis state for CL clients is not defined."); } + console.log("Starting beacon nodes"); await Promise.all(this.nodes.map((node) => node.beacon.job.start())); + + console.log("Starting validators"); await Promise.all(this.nodes.map((node) => node.validator?.job.start())); if (this.nodes.some((node) => node.validator?.keys.type === "remote")) { - console.log("Starting external signer..."); + console.log("Starting external signer"); await this.externalSigner.start(); - console.log("Started external signer"); for (const node of this.nodes) { if (node.validator?.keys.type === "remote") { @@ -156,6 +167,7 @@ export class SimulationEnvironment { } } + console.log("Starting the simulation tracker"); await this.tracker.start(); await Promise.all(this.nodes.map((node) => this.tracker.track(node))); } catch (error) { @@ -179,6 +191,10 @@ export class SimulationEnvironment { await this.runner.stop(); this.options.controller.abort(); + if (this.runTimeout) { + clearTimeout(this.runTimeout); + } + if (this.tracker.getErrorCount() > 0) { this.tracker.reporter.summary(); process.exit(this.tracker.getErrorCount() > 0 ? 1 : code); diff --git a/packages/cli/test/utils/simulation/interfaces.ts b/packages/cli/test/utils/simulation/interfaces.ts index 41339b58a1e0..62b02ea25708 100644 --- a/packages/cli/test/utils/simulation/interfaces.ts +++ b/packages/cli/test/utils/simulation/interfaces.ts @@ -29,19 +29,19 @@ export type SimulationOptions = { }; export enum BeaconClient { - Lodestar = "beacon_lodestar", - Lighthouse = "beacon_lighthouse", + Lodestar = "beacon-lodestar", + Lighthouse = "beacon-lighthouse", } export enum ValidatorClient { - Lodestar = "validator_lodestar", - Lighthouse = "validator_lighthouse", + Lodestar = "validator-lodestar", + Lighthouse = "validator-lighthouse", } export enum ExecutionClient { - Mock = "execution_mock", - Geth = "execution_geth", - Nethermind = "execution_nethermind", + Mock = "execution-mock", + Geth = "execution-geth", + Nethermind = "execution-nethermind", } export enum ExecutionStartMode { diff --git a/packages/test-utils/src/childProcess.ts b/packages/test-utils/src/childProcess.ts index c3cacb9a1509..ae01d7ce0e86 100644 --- a/packages/test-utils/src/childProcess.ts +++ b/packages/test-utils/src/childProcess.ts @@ -3,7 +3,7 @@ import childProcess from "node:child_process"; import stream from "node:stream"; import fs from "node:fs"; import path from "node:path"; -import {sleep} from "@lodestar/utils"; +import {prettyMsToTime, sleep} from "@lodestar/utils"; import {TestContext} from "./interfaces.js"; /** @@ -328,13 +328,15 @@ export async function spawnChildProcess( const timeSinceHealthCheckStart = Date.now() - startHealthCheckMs; if (timeSinceHealthCheckStart > logHealthChecksAfterMs) { console.log( - `Health check unsuccessful. logPrefix=${logPrefix} pid=${proc.pid} timeSinceHealthCheckStart=${timeSinceHealthCheckStart}` + `Health check unsuccessful. logPrefix=${logPrefix} pid=${ + proc.pid + } timeSinceHealthCheckStart=${prettyMsToTime(timeSinceHealthCheckStart)}` ); } } }) .catch((e) => { - console.error("error on health check, health functions must never throw", e); + console.error("Error on health check, health functions must never throw", e); }); }, healthCheckIntervalMs); @@ -344,7 +346,9 @@ export async function spawnChildProcess( if (intervalId !== undefined) { reject( new Error( - `Health check timeout. logPrefix=${logPrefix} pid=${proc.pid} healthTimeoutMs=${healthTimeoutMs}` + `Health check timeout. logPrefix=${logPrefix} pid=${proc.pid} healthTimeout=${prettyMsToTime( + healthTimeoutMs ?? 0 + )}` ) ); } @@ -358,9 +362,9 @@ export async function spawnChildProcess( reject( new Error( - `process exited before healthy. logPrefix=${logPrefix} pid=${ - proc.pid - } healthTimeoutMs=${healthTimeoutMs} code=${code} command="${command} ${args.join(" ")}"` + `Process exited before healthy. logPrefix=${logPrefix} pid=${proc.pid} healthTimeout=${prettyMsToTime( + healthTimeoutMs ?? 0 + )} code=${code} command="${command} ${args.join(" ")}"` ) ); }); diff --git a/packages/utils/src/format.ts b/packages/utils/src/format.ts index cf2352a4fbaa..0e89748af8f8 100644 --- a/packages/utils/src/format.ts +++ b/packages/utils/src/format.ts @@ -54,3 +54,11 @@ export function prettyWeiToEth(wei: bigint, suffix = false): string { if (suffix) eth += " ETH"; return eth; } + +/** + * Format milliseconds to time format HH:MM:SS.ms + */ +export function prettyMsToTime(timeMs: number): string { + const date = new Date(0, 0, 0, 0, 0, 0, timeMs); + return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}.${date.getMilliseconds()}`; +} From 2a8342d819a46b0807c1fa56998f20bf31b9076f Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 6 Feb 2024 20:39:33 +0100 Subject: [PATCH 27/71] test: flaky unit tests (#6398) * Fix clock flaky tests * Fix api server flaky tests * Auto assign port for testing server * Update fake timer --- .../beacon/genericServerTest/config.test.ts | 4 +- .../beacon/genericServerTest/debug.test.ts | 28 ++++++++----- .../beacon/genericServerTest/events.test.ts | 23 ++++++++--- packages/api/test/utils/genericServerTest.ts | 40 +++++++++++++------ packages/api/test/utils/utils.ts | 20 +++------- packages/validator/src/util/clock.ts | 2 +- .../validator/test/unit/utils/clock.test.ts | 2 +- 7 files changed, 73 insertions(+), 46 deletions(-) diff --git a/packages/api/test/unit/beacon/genericServerTest/config.test.ts b/packages/api/test/unit/beacon/genericServerTest/config.test.ts index e11e4cbff6cb..3e9c001bffbf 100644 --- a/packages/api/test/unit/beacon/genericServerTest/config.test.ts +++ b/packages/api/test/unit/beacon/genericServerTest/config.test.ts @@ -9,9 +9,7 @@ import {testData} from "../testData/config.js"; /* eslint-disable @typescript-eslint/naming-convention */ describe("beacon / config", () => { - describe("Run generic server test", () => { - runGenericServerTest(config, getClient, getRoutes, testData); - }); + runGenericServerTest(config, getClient, getRoutes, testData); it("Serialize Partial Spec object", () => { const returnTypes = getReturnTypes(); diff --git a/packages/api/test/unit/beacon/genericServerTest/debug.test.ts b/packages/api/test/unit/beacon/genericServerTest/debug.test.ts index 6f7889677ec6..9a4c4bd71ef1 100644 --- a/packages/api/test/unit/beacon/genericServerTest/debug.test.ts +++ b/packages/api/test/unit/beacon/genericServerTest/debug.test.ts @@ -1,5 +1,6 @@ -import {describe, it, expect, MockInstance} from "vitest"; +import {describe, it, expect, MockInstance, beforeAll, afterAll} from "vitest"; import {toHexString} from "@chainsafe/ssz"; +import {FastifyInstance} from "fastify"; import {ssz} from "@lodestar/types"; import {config} from "@lodestar/config/default"; import {Api, ReqTypes, routesData} from "../../../../src/beacon/routes/debug.js"; @@ -13,19 +14,28 @@ import {testData} from "../testData/debug.js"; describe( "beacon / debug", - function () { - describe("Run generic server test", () => { - runGenericServerTest(config, getClient, getRoutes, testData); - }); + () => { + runGenericServerTest(config, getClient, getRoutes, testData); // Get state by SSZ describe("getState() in SSZ format", () => { - const {baseUrl, server} = getTestServer(); const mockApi = getMockApi(routesData); - for (const route of Object.values(getRoutes(config, mockApi))) { - registerRoute(server, route); - } + let baseUrl: string; + let server: FastifyInstance; + + beforeAll(async () => { + const res = getTestServer(); + server = res.server; + for (const route of Object.values(getRoutes(config, mockApi))) { + registerRoute(server, route); + } + baseUrl = await res.start(); + }); + + afterAll(async () => { + if (server !== undefined) await server.close(); + }); for (const method of ["getState" as const, "getStateV2" as const]) { it(method, async () => { diff --git a/packages/api/test/unit/beacon/genericServerTest/events.test.ts b/packages/api/test/unit/beacon/genericServerTest/events.test.ts index 3e1c02396710..2d6c9462c1fd 100644 --- a/packages/api/test/unit/beacon/genericServerTest/events.test.ts +++ b/packages/api/test/unit/beacon/genericServerTest/events.test.ts @@ -1,4 +1,5 @@ -import {describe, it, expect, beforeEach, afterEach} from "vitest"; +import {describe, it, expect, beforeEach, afterEach, beforeAll, afterAll} from "vitest"; +import {FastifyInstance} from "fastify"; import {sleep} from "@lodestar/utils"; import {Api, routesData, EventType, BeaconEvent} from "../../../../src/beacon/routes/events.js"; import {getClient} from "../../../../src/beacon/client/events.js"; @@ -8,11 +9,23 @@ import {getMockApi, getTestServer} from "../../../utils/utils.js"; import {eventTestData} from "../testData/events.js"; describe("beacon / events", () => { - const {baseUrl, server} = getTestServer(); const mockApi = getMockApi(routesData); - for (const route of Object.values(getRoutes(mockApi))) { - registerRoute(server, route); - } + let server: FastifyInstance; + let baseUrl: string; + + beforeAll(async () => { + const res = getTestServer(); + server = res.server; + for (const route of Object.values(getRoutes(mockApi))) { + registerRoute(server, route); + } + + baseUrl = await res.start(); + }); + + afterAll(async () => { + if (server !== undefined) await server.close(); + }); let controller: AbortController; beforeEach(() => { diff --git a/packages/api/test/utils/genericServerTest.ts b/packages/api/test/utils/genericServerTest.ts index f0f805b7469a..4cd0263aaea8 100644 --- a/packages/api/test/utils/genericServerTest.ts +++ b/packages/api/test/utils/genericServerTest.ts @@ -1,4 +1,5 @@ -import {it, expect, MockInstance} from "vitest"; +import {it, expect, MockInstance, describe, beforeAll, afterAll} from "vitest"; +import {FastifyInstance} from "fastify"; import {ChainForkConfig} from "@lodestar/config"; import {ReqGeneric, Resolves} from "../../src/utils/index.js"; import {FetchOpts, HttpClient, IHttpClient} from "../../src/utils/client/index.js"; @@ -28,26 +29,39 @@ export function runGenericServerTest< testCases: GenericServerTestCases ): void { const mockApi = getMockApi(testCases); - const {baseUrl, server} = getTestServer(); + let server: FastifyInstance; - const httpClient = new HttpClientSpy({baseUrl}); - const client = getClient(config, httpClient); + let client: Api; + let httpClient: HttpClientSpy; - for (const route of Object.values(getRoutes(config, mockApi))) { - registerRoute(server, route); - } + beforeAll(async () => { + const res = getTestServer(); + server = res.server; + + for (const route of Object.values(getRoutes(config, mockApi))) { + registerRoute(server, route); + } + + const baseUrl = await res.start(); + httpClient = new HttpClientSpy({baseUrl}); + client = getClient(config, httpClient); + }); - for (const key of Object.keys(testCases)) { - const routeId = key as keyof Api; - const testCase = testCases[routeId]; + afterAll(async () => { + if (server !== undefined) await server.close(); + }); + + describe("run generic server tests", () => { + it.each(Object.keys(testCases))("%s", async (key) => { + const routeId = key as keyof Api; + const testCase = testCases[routeId]; - it(routeId as string, async () => { // Register mock data for this route // TODO: Look for the type error (mockApi[routeId] as MockInstance).mockResolvedValue(testCases[routeId].res); // Do the call - const res = await (client[routeId] as APIClientHandler)(...(testCase.args as any[])); + const res = await client[routeId](...(testCase.args as any[])); // Use spy to assert argument serialization if (testCase.query) { @@ -64,7 +78,7 @@ export function runGenericServerTest< // Assert returned value is correct expect(res.response).toEqual(testCase.res); }); - } + }); } class HttpClientSpy extends HttpClient { diff --git a/packages/api/test/utils/utils.ts b/packages/api/test/utils/utils.ts index cca89c8e4fd5..b19899016117 100644 --- a/packages/api/test/utils/utils.ts +++ b/packages/api/test/utils/utils.ts @@ -1,13 +1,10 @@ -import {beforeAll, afterAll, MockedObject, vi} from "vitest"; +import {MockedObject, vi} from "vitest"; import qs from "qs"; import fastify, {FastifyInstance} from "fastify"; import {mapValues} from "@lodestar/utils"; import {ServerApi} from "../../src/interfaces.js"; -export function getTestServer(): {baseUrl: string; server: FastifyInstance} { - const port = Math.floor(Math.random() * (65535 - 49152)) + 49152; - const baseUrl = `http://localhost:${port}`; - +export function getTestServer(): {server: FastifyInstance; start: () => Promise} { const server = fastify({ ajv: {customOptions: {coerceTypes: "array"}}, querystringParser: (str) => qs.parse(str, {comma: true, parseArrays: false}), @@ -19,9 +16,9 @@ export function getTestServer(): {baseUrl: string; server: FastifyInstance} { done(); }); - beforeAll(async () => { - await new Promise((resolve, reject) => { - server.listen({port}, function (err, address) { + const start = (): Promise => + new Promise((resolve, reject) => { + server.listen({port: 0}, function (err, address) { if (err !== null && err != undefined) { reject(err); } else { @@ -29,13 +26,8 @@ export function getTestServer(): {baseUrl: string; server: FastifyInstance} { } }); }); - }); - - afterAll(async () => { - await server.close(); - }); - return {baseUrl, server}; + return {start, server}; } export function getMockApi>( diff --git a/packages/validator/src/util/clock.ts b/packages/validator/src/util/clock.ts index ca29eacd41c2..837fb82809bd 100644 --- a/packages/validator/src/util/clock.ts +++ b/packages/validator/src/util/clock.ts @@ -138,7 +138,7 @@ export class Clock implements IClock { */ export function getCurrentSlotAround(config: ChainForkConfig, genesisTime: TimeSeconds): Slot { const diffInSeconds = Date.now() / 1000 - genesisTime; - const slotsSinceGenesis = Math.round(diffInSeconds / config.SECONDS_PER_SLOT); + const slotsSinceGenesis = Math.floor(diffInSeconds / config.SECONDS_PER_SLOT); return GENESIS_SLOT + slotsSinceGenesis; } diff --git a/packages/validator/test/unit/utils/clock.test.ts b/packages/validator/test/unit/utils/clock.test.ts index 15f95ddbe2ee..dfa9d386e663 100644 --- a/packages/validator/test/unit/utils/clock.test.ts +++ b/packages/validator/test/unit/utils/clock.test.ts @@ -11,7 +11,7 @@ describe("util / Clock", function () { beforeEach(() => { controller = new AbortController(); - vi.useFakeTimers(); + vi.useFakeTimers({now: Date.now()}); }); afterEach(() => { From 3adf2c2eb233483b5bea2abf253a7cce68c36af9 Mon Sep 17 00:00:00 2001 From: Cayman Date: Tue, 6 Feb 2024 16:32:17 -0500 Subject: [PATCH 28/71] chore: bump gossipsub (#6399) --- packages/beacon-node/package.json | 2 +- yarn.lock | 19 +++++-------------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index f24963622d93..60955b4c2259 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -100,7 +100,7 @@ "@chainsafe/blst": "^0.2.9", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", - "@chainsafe/libp2p-gossipsub": "^11.2.0", + "@chainsafe/libp2p-gossipsub": "^11.2.1", "@chainsafe/libp2p-noise": "^14.1.0", "@chainsafe/libp2p-identify": "^1.0.0", "@chainsafe/persistent-merkle-tree": "^0.6.1", diff --git a/yarn.lock b/yarn.lock index 0780e0bc2ef8..e4059083f9e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -364,10 +364,10 @@ resolved "https://registry.yarnpkg.com/@chainsafe/is-ip/-/is-ip-2.0.2.tgz#7311e7403f11d8c5cfa48111f56fcecaac37c9f6" integrity sha512-ndGqEMG1W5WkGagaqOZHpPU172AGdxr+LD15sv3WIUvT5oCFUrG1Y0CW/v2Egwj4JXEvSibaIIIqImsm98y1nA== -"@chainsafe/libp2p-gossipsub@^11.2.0": - version "11.2.0" - resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-11.2.0.tgz#4134dc68d9e3e0c327474b48fbd6e1f76f97550b" - integrity sha512-VymXl4Z4qEIUxH4FjgbcVqyuapVHhzrJxADO4t84QOOWv9f8uQYV+c0cgwjneOW3XyTYBOHaZqyTHTngTrKjtQ== +"@chainsafe/libp2p-gossipsub@^11.2.1": + version "11.2.1" + resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-gossipsub/-/libp2p-gossipsub-11.2.1.tgz#80a993cca657084c861b78513ee0ff516bfb96f9" + integrity sha512-2NvlOY4Jfwn7U/sKF0kILl3+luHxq9hhEiBqZRqLTIV8LYmMQl9VpTMgMvRwKzgn/NDeZzsPb8olk2o00tkmZw== dependencies: "@libp2p/crypto" "^4.0.1" "@libp2p/interface" "^1.1.2" @@ -375,7 +375,6 @@ "@libp2p/peer-id" "^4.0.5" "@libp2p/pubsub" "^9.0.8" "@multiformats/multiaddr" "^12.1.14" - abortable-iterator "^5.0.1" denque "^2.1.0" it-length-prefixed "^9.0.4" it-pipe "^3.0.1" @@ -3533,14 +3532,6 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -abortable-iterator@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/abortable-iterator/-/abortable-iterator-5.0.1.tgz#5d93eba6fa8287a973a9ea090c64ca08b3777780" - integrity sha512-hlZ5Z8UwqrKsJcelVPEqDduZowJPBQJ9ZhBC2FXpja3lXy8X6MoI5uMzIgmrA8+3jcVnp8TF/tx+IBBqYJNUrg== - dependencies: - get-iterator "^2.0.0" - it-stream-types "^2.0.1" - abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" @@ -6805,7 +6796,7 @@ get-iterator@^1.0.2: resolved "https://registry.npmjs.org/get-iterator/-/get-iterator-1.0.2.tgz" integrity sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg== -get-iterator@^2.0.0, get-iterator@^2.0.1: +get-iterator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-2.0.1.tgz#a904829f61bace789e0d64bd1a504c511a015c3f" integrity sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg== From b6890adf2882b02960b8ffc5d685f3576dc6d0cc Mon Sep 17 00:00:00 2001 From: Julien Date: Tue, 6 Feb 2024 13:56:25 -0800 Subject: [PATCH 29/71] feat: add ERC-55 support to ExecutionAddress (#6355) * feat: add ERC-55 support to ExecutionAddress * chore: address PR comments * chore: address PR comments * fix: cleanup * fix: lower case * chore: address PR comments --- packages/types/package.json | 3 +- packages/types/src/bellatrix/sszTypes.ts | 2 +- packages/types/src/index.ts | 2 +- packages/types/src/primitive/sszTypes.ts | 3 +- packages/types/src/utils/executionAddress.ts | 48 +++++++++++++ .../utils/{StringType.ts => stringType.ts} | 0 .../types/test/unit/executionAddress.test.ts | 72 +++++++++++++++++++ 7 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 packages/types/src/utils/executionAddress.ts rename packages/types/src/utils/{StringType.ts => stringType.ts} (100%) create mode 100644 packages/types/test/unit/executionAddress.test.ts diff --git a/packages/types/package.json b/packages/types/package.json index e75266d9ed01..51baccc89314 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -74,7 +74,8 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/params": "^1.15.0" + "@lodestar/params": "^1.15.0", + "ethereum-cryptography": "^2.0.0" }, "keywords": [ "ethereum", diff --git a/packages/types/src/bellatrix/sszTypes.ts b/packages/types/src/bellatrix/sszTypes.ts index c6919d04b631..08f0378ef92a 100644 --- a/packages/types/src/bellatrix/sszTypes.ts +++ b/packages/types/src/bellatrix/sszTypes.ts @@ -9,7 +9,7 @@ import { import {ssz as primitiveSsz} from "../primitive/index.js"; import {ssz as phase0Ssz} from "../phase0/index.js"; import {ssz as altairSsz} from "../altair/index.js"; -import {stringType} from "../utils/StringType.js"; +import {stringType} from "../utils/stringType.js"; const { Bytes32, diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index d90b55909884..6931271aaa29 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -3,6 +3,6 @@ export * as ssz from "./sszTypes.js"; // Typeguards export * from "./utils/typeguards.js"; // String type -export {StringType, stringType} from "./utils/StringType.js"; +export {StringType, stringType} from "./utils/stringType.js"; // Container utils export * from "./utils/container.js"; diff --git a/packages/types/src/primitive/sszTypes.ts b/packages/types/src/primitive/sszTypes.ts index 65c81d1247b9..068a32e2cc17 100644 --- a/packages/types/src/primitive/sszTypes.ts +++ b/packages/types/src/primitive/sszTypes.ts @@ -1,4 +1,5 @@ import {ByteVectorType, UintNumberType, UintBigintType, BooleanType} from "@chainsafe/ssz"; +import {ExecutionAddressType} from "../utils/executionAddress.js"; export const Boolean = new BooleanType(); export const Byte = new UintNumberType(1); @@ -61,4 +62,4 @@ export const BLSPubkey = Bytes48; export const BLSSignature = Bytes96; export const Domain = Bytes32; export const ParticipationFlags = new UintNumberType(1, {setBitwiseOR: true}); -export const ExecutionAddress = Bytes20; +export const ExecutionAddress = new ExecutionAddressType(); diff --git a/packages/types/src/utils/executionAddress.ts b/packages/types/src/utils/executionAddress.ts new file mode 100644 index 000000000000..9d555c016f04 --- /dev/null +++ b/packages/types/src/utils/executionAddress.ts @@ -0,0 +1,48 @@ +import {keccak256} from "ethereum-cryptography/keccak.js"; +import {ByteVectorType} from "@chainsafe/ssz"; + +export type ByteVector = Uint8Array; + +export class ExecutionAddressType extends ByteVectorType { + constructor() { + super(20, {typeName: "ExecutionAddress"}); + } + toJson(value: ByteVector): unknown { + const str = super.toJson(value) as string; + return toChecksumAddress(str); + } +} + +function isAddressValid(address: string): boolean { + return /^(0x)?[0-9a-f]{40}$/i.test(address); +} + +/** + * Formats an address according to [ERC55](https://eips.ethereum.org/EIPS/eip-55) + */ +export function toChecksumAddress(address: string): string { + if (!isAddressValid(address)) { + throw Error(`Invalid address: ${address}`); + } + + const rawAddress = (address.startsWith("0x") ? address.slice(2) : address).toLowerCase(); + const chars = rawAddress.split(""); + + // Inspired by https://github.com/ethers-io/ethers.js/blob/cac1da1f912c2ae9ba20f25aa51a91766673cd76/src.ts/address/address.ts#L8 + const expanded = new Uint8Array(chars.length); + for (let i = 0; i < expanded.length; i++) { + expanded[i] = rawAddress[i].charCodeAt(0); + } + + const hashed = keccak256(expanded); + for (let i = 0; i < chars.length; i += 2) { + if (hashed[i >> 1] >> 4 >= 8) { + chars[i] = chars[i].toUpperCase(); + } + if ((hashed[i >> 1] & 0x0f) >= 8) { + chars[i + 1] = chars[i + 1].toUpperCase(); + } + } + + return "0x" + chars.join(""); +} diff --git a/packages/types/src/utils/StringType.ts b/packages/types/src/utils/stringType.ts similarity index 100% rename from packages/types/src/utils/StringType.ts rename to packages/types/src/utils/stringType.ts diff --git a/packages/types/test/unit/executionAddress.test.ts b/packages/types/test/unit/executionAddress.test.ts new file mode 100644 index 000000000000..841cd52468f5 --- /dev/null +++ b/packages/types/test/unit/executionAddress.test.ts @@ -0,0 +1,72 @@ +import {describe, it, expect} from "vitest"; +import {toChecksumAddress} from "../../src/utils/executionAddress.js"; + +describe("toChecksumAddress", () => { + it("should fail with invalid addresses", () => { + expect(() => toChecksumAddress("1234")).toThrowError("Invalid address: 1234"); + expect(() => toChecksumAddress("0x1234")).toThrowError("Invalid address: 0x1234"); + }); + + it("should format addresses as ERC55", () => { + type TestCase = { + address: string; + checksumAddress: string; + }; + + const testCases: TestCase[] = [ + // Input all caps + { + address: "0x52908400098527886E0F7030069857D2E4169EE7", + checksumAddress: "0x52908400098527886E0F7030069857D2E4169EE7", + }, + { + address: "0xDE709F2102306220921060314715629080E2FB77", + checksumAddress: "0xde709f2102306220921060314715629080e2fb77", + }, + // Without 0x prefix + { + address: "52908400098527886e0f7030069857d2e4169ee7", + checksumAddress: "0x52908400098527886E0F7030069857D2E4169EE7", + }, + // All caps + { + address: "0x52908400098527886e0f7030069857d2e4169ee7", + checksumAddress: "0x52908400098527886E0F7030069857D2E4169EE7", + }, + { + address: "0x8617e340b3d01fa5f11f306f4090fd50e238070d", + checksumAddress: "0x8617E340B3D01FA5F11F306F4090FD50E238070D", + }, + // All lower + { + address: "0xde709f2102306220921060314715629080e2fb77", + checksumAddress: "0xde709f2102306220921060314715629080e2fb77", + }, + { + address: "0x27b1fdb04752bbc536007a920d24acb045561c26", + checksumAddress: "0x27b1fdb04752bbc536007a920d24acb045561c26", + }, + // Normal + { + address: "0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed", + checksumAddress: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed", + }, + { + address: "0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359", + checksumAddress: "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359", + }, + { + address: "0xdbf03b407c01e7cd3cbea99509d93f8dddc8c6fb", + checksumAddress: "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", + }, + { + address: "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb", + checksumAddress: "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb", + }, + ]; + + for (const {address, checksumAddress} of testCases) { + expect(toChecksumAddress(address)).toBe(checksumAddress); + } + }); +}); From 924a6cd4957c75db1085e4551d744aba27afa7fb Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 7 Feb 2024 14:18:14 +0100 Subject: [PATCH 30/71] fix: parse --blindedLocal flag value as boolean (#6403) --- packages/cli/src/cmds/validator/options.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cmds/validator/options.ts b/packages/cli/src/cmds/validator/options.ts index 20bfc106d258..a5b4044f6867 100644 --- a/packages/cli/src/cmds/validator/options.ts +++ b/packages/cli/src/cmds/validator/options.ts @@ -268,7 +268,7 @@ export const validatorOptions: CliCommandOptions = { }, blindedLocal: { - type: "string", + type: "boolean", description: "Request fetching local block in blinded format for produceBlockV3", defaultDescription: `${defaultOptions.blindedLocal}`, }, From 3bc9673addd709892c52452bbcb268225ee0db98 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 7 Feb 2024 14:26:07 +0100 Subject: [PATCH 31/71] fix: correct error message if produceBlockV3 request fails (#6405) --- packages/validator/src/services/block.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/validator/src/services/block.ts b/packages/validator/src/services/block.ts index 984550791384..a28f7c019d0b 100644 --- a/packages/validator/src/services/block.ts +++ b/packages/validator/src/services/block.ts @@ -212,7 +212,7 @@ export class BlockProposingService { blindedLocal, builderBoostFactor, }); - ApiError.assert(res, "Failed to produce block: validator.produceBlockV2"); + ApiError.assert(res, "Failed to produce block: validator.produceBlockV3"); const {response} = res; const debugLogCtx = { From d1caa1f61730551908ab2b969b972c7978909e87 Mon Sep 17 00:00:00 2001 From: Cayman Date: Wed, 7 Feb 2024 14:13:45 -0500 Subject: [PATCH 32/71] fix: fix regression in getCurrentSlotAround (#6407) --- packages/validator/src/util/clock.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/validator/src/util/clock.ts b/packages/validator/src/util/clock.ts index 837fb82809bd..ca29eacd41c2 100644 --- a/packages/validator/src/util/clock.ts +++ b/packages/validator/src/util/clock.ts @@ -138,7 +138,7 @@ export class Clock implements IClock { */ export function getCurrentSlotAround(config: ChainForkConfig, genesisTime: TimeSeconds): Slot { const diffInSeconds = Date.now() / 1000 - genesisTime; - const slotsSinceGenesis = Math.floor(diffInSeconds / config.SECONDS_PER_SLOT); + const slotsSinceGenesis = Math.round(diffInSeconds / config.SECONDS_PER_SLOT); return GENESIS_SLOT + slotsSinceGenesis; } From cb99fc4041e08dfff407909d18e0b3c05ff8562c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:34:49 +0000 Subject: [PATCH 33/71] chore(deps): bump browserify-sign from 4.2.1 to 4.2.2 (#6071) Bumps [browserify-sign](https://github.com/crypto-browserify/browserify-sign) from 4.2.1 to 4.2.2. - [Changelog](https://github.com/browserify/browserify-sign/blob/main/CHANGELOG.md) - [Commits](https://github.com/crypto-browserify/browserify-sign/compare/v4.2.1...v4.2.2) --- updated-dependencies: - dependency-name: browserify-sign dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index e4059083f9e9..427db4fdc496 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4206,7 +4206,7 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.1, bn.js@^4.11.9: resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.0.0, bn.js@^5.1.1: +bn.js@^5.0.0: version "5.2.0" resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== @@ -4308,7 +4308,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: +browserify-rsa@^4.0.0, browserify-rsa@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== @@ -4317,19 +4317,19 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + version "4.2.2" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.2.tgz#e78d4b69816d6e3dd1c747e64e9947f9ad79bc7e" + integrity sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg== dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" + bn.js "^5.2.1" + browserify-rsa "^4.1.0" create-hash "^1.2.0" create-hmac "^1.1.7" - elliptic "^6.5.3" + elliptic "^6.5.4" inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" + parse-asn1 "^5.1.6" + readable-stream "^3.6.2" + safe-buffer "^5.2.1" browserify-zlib@^0.2.0: version "0.2.0" @@ -5675,7 +5675,7 @@ electron@^26.2.2: "@types/node" "^18.11.18" extract-zip "^2.0.1" -elliptic@6.5.4, elliptic@^6.5.3: +elliptic@6.5.4, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -10226,7 +10226,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: +parse-asn1@^5.0.0, parse-asn1@^5.1.6: version "5.1.6" resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== @@ -10895,6 +10895,15 @@ readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.1.1, readable string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.3.0.tgz#0914d0c72db03b316c9733bb3461d64a3cc50cba" @@ -11215,7 +11224,7 @@ safe-array-concat@^1.0.1: has-symbols "^1.0.3" isarray "^2.0.5" -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== From c98a48a4fbbd2a4fd970d327683bf62161a93344 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Thu, 8 Feb 2024 16:59:25 +0100 Subject: [PATCH 34/71] test: fix code coverage (#6410) * Fix ci coverage * Update the CI tasks to remove warning * Fix coverage path * Remove the coverage for spec-test-util * Update the ci tasks to clear warnings * Use latest codecov uploader * Add codecov token * Update the code coverage task * Add the badge * Remove a temp task * Split badges to two lines * Remove the token from the badge --- .codecov.yml | 6 ++ .github/actions/core-dump/action.yml | 2 +- .github/workflows/benchmark.yml | 4 +- .github/workflows/build-debug-node.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/docs-check.yml | 4 +- .github/workflows/docs.yml | 4 +- .github/workflows/publish-dev.yml | 6 +- .github/workflows/publish-rc.yml | 8 +-- .github/workflows/publish-stable.yml | 8 +-- .github/workflows/test-sim-merge.yml | 8 +-- .github/workflows/test-sim.yml | 6 +- .github/workflows/test.yml | 51 ++++++++-------- README.md | 2 + package.json | 2 - packages/api/package.json | 1 - packages/beacon-node/package.json | 1 - packages/cli/package.json | 1 - packages/db/package.json | 1 - packages/fork-choice/package.json | 1 - packages/light-client/package.json | 1 - packages/prover/package.json | 1 - packages/reqresp/package.json | 1 - packages/validator/package.json | 1 - yarn.lock | 82 ++++---------------------- 25 files changed, 74 insertions(+), 132 deletions(-) diff --git a/.codecov.yml b/.codecov.yml index 45b353124178..f9d25d52769e 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -34,3 +34,9 @@ ignore: - "supporting-docs" - "docker" - ".github" + +flags: + unit: + paths: + - ".*" + carryforward: true diff --git a/.github/actions/core-dump/action.yml b/.github/actions/core-dump/action.yml index eae37c2101b8..e2e0b1224912 100644 --- a/.github/actions/core-dump/action.yml +++ b/.github/actions/core-dump/action.yml @@ -10,7 +10,7 @@ runs: shell: sh - name: Backup core dump - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: core-dump path: /cores/* diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index b5fa586c7a8b..efb9e0231e20 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -30,8 +30,8 @@ jobs: steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 20 check-latest: true diff --git a/.github/workflows/build-debug-node.yml b/.github/workflows/build-debug-node.yml index 9e7c1ac66fab..da97e10d8e97 100644 --- a/.github/workflows/build-debug-node.yml +++ b/.github/workflows/build-debug-node.yml @@ -44,7 +44,7 @@ jobs: working-directory: 'nodejs' - name: Upload build to artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: nodejs-debug-build-${{ github.event.inputs.version }} path: nodejs-debug-build-${{ github.event.inputs.version }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 726199e68549..2d635afe2688 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,7 +47,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index 4dbbcdce5f5c..9b20732c2a56 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -12,8 +12,8 @@ jobs: runs-on: ubuntu-latest steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 20 cache: yarn diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a47f236b3470..123ec596f1a2 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,11 +25,11 @@ jobs: echo "Deploying ref: $DEPLOY_REF" # Checkout the correct ref being deployed - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ env.DEPLOY_REF }} - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 20 check-latest: true diff --git a/.github/workflows/publish-dev.yml b/.github/workflows/publish-dev.yml index 2e71cc86c33c..e38abd9e68dc 100644 --- a/.github/workflows/publish-dev.yml +++ b/.github/workflows/publish-dev.yml @@ -15,10 +15,10 @@ jobs: runs-on: buildjet-4vcpu-ubuntu-2204 steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 20 registry-url: "https://registry.npmjs.org" @@ -109,7 +109,7 @@ jobs: runs-on: buildjet-4vcpu-ubuntu-2204 needs: npm steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # https://github.com/docker/setup-qemu-action - name: Set up QEMU uses: docker/setup-qemu-action@v1 diff --git a/.github/workflows/publish-rc.yml b/.github/workflows/publish-rc.yml index c0dfe3b513dd..214c3497db1a 100644 --- a/.github/workflows/publish-rc.yml +++ b/.github/workflows/publish-rc.yml @@ -15,7 +15,7 @@ jobs: runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -49,10 +49,10 @@ jobs: if: needs.tag.outputs.is_rc == 'true' steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Needs full depth for changelog generation - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 20 check-latest: true @@ -132,7 +132,7 @@ jobs: needs: [tag, npm] if: needs.tag.outputs.is_rc == 'true' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: scripts/await-release.sh ${{ needs.tag.outputs.tag }} rc 900 # https://github.com/docker/setup-qemu-action - name: Set up QEMU diff --git a/.github/workflows/publish-stable.yml b/.github/workflows/publish-stable.yml index c0d046891bdf..933dc0b0ca4b 100644 --- a/.github/workflows/publish-stable.yml +++ b/.github/workflows/publish-stable.yml @@ -15,7 +15,7 @@ jobs: runs-on: buildjet-4vcpu-ubuntu-2204 steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 @@ -55,10 +55,10 @@ jobs: if: needs.tag.outputs.is_stable == 'true' steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Needs full depth for changelog generation - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 20 check-latest: true @@ -132,7 +132,7 @@ jobs: needs: [tag, npm] if: needs.tag.outputs.is_stable == 'true' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: scripts/await-release.sh ${{ needs.tag.outputs.tag }} latest 900 # https://github.com/docker/setup-qemu-action - name: Set up QEMU diff --git a/.github/workflows/test-sim-merge.yml b/.github/workflows/test-sim-merge.yml index 268df5620559..641d5ab2732e 100644 --- a/.github/workflows/test-sim-merge.yml +++ b/.github/workflows/test-sim-merge.yml @@ -27,8 +27,8 @@ jobs: runs-on: buildjet-4vcpu-ubuntu-2204 steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 20 check-latest: true @@ -92,7 +92,7 @@ jobs: - name: Upload debug log test files if: ${{ always() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: debug-test-logs path: packages/beacon-node/test-logs @@ -144,7 +144,7 @@ jobs: - name: Upload debug log test files if: ${{ always() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: debug-test-logs path: packages/beacon-node/test-logs diff --git a/.github/workflows/test-sim.yml b/.github/workflows/test-sim.yml index 20eee3d11e77..6adf60e98db1 100644 --- a/.github/workflows/test-sim.yml +++ b/.github/workflows/test-sim.yml @@ -33,8 +33,8 @@ jobs: runs-on: buildjet-4vcpu-ubuntu-2204 steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 20 check-latest: true @@ -96,7 +96,7 @@ jobs: - name: Upload debug log test files for "packages/cli" if: ${{ always() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: debug-test-logs-cli path: packages/cli/test-logs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d865045c4f3a..61be02b589be 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,8 +26,8 @@ jobs: node: [20] steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{matrix.node}} check-latest: true @@ -36,7 +36,7 @@ jobs: id: node run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT - name: Restore build - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 id: cache-build-restore with: path: | @@ -81,15 +81,15 @@ jobs: matrix: node: [20] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true cache: yarn - name: Restore build cache id: cache-primes-restore - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -119,15 +119,15 @@ jobs: matrix: node: [20] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true cache: yarn - name: Restore build cache id: cache-primes-restore - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -153,8 +153,8 @@ jobs: matrix: node: [20] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true @@ -165,7 +165,7 @@ jobs: - name: Restore build cache id: cache-primes-restore - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -194,7 +194,12 @@ jobs: # if: ${{ failure() && steps.unit_tests.conclusion == 'failure' }} - name: Upload coverage data - run: yarn coverage + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + verbose: true # optional (default = false) + flags: "unit" e2e-tests: name: E2E Tests @@ -206,15 +211,15 @@ jobs: node: [20] steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{matrix.node}} check-latest: true cache: yarn - name: Restore build cache id: cache-primes-restore - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -238,7 +243,7 @@ jobs: - name: Upload debug log test for test env if: ${{ always() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: debug-e2e-test-logs-node-${{matrix.node}} path: test-logs/e2e-test-env @@ -253,15 +258,15 @@ jobs: node: [20] steps: # - Uses YAML anchors in the future - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{matrix.node}} check-latest: true cache: yarn - name: Restore build cache id: cache-primes-restore - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | node_modules @@ -290,15 +295,15 @@ jobs: matrix: node: [20] steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{matrix.node}} check-latest: true cache: yarn - name: Restore build cache id: cache-primes-restore - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | node_modules diff --git a/README.md b/README.md index 52c671ae6f1d..6f682e6e87c8 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,10 @@ [![npm](https://img.shields.io/npm/v/@chainsafe/lodestar)](https://www.npmjs.com/package/@chainsafe/lodestar) [![Docker Image Version (latest by date)](https://img.shields.io/docker/v/chainsafe/lodestar?color=blue&label=Docker&sort=semver)](https://hub.docker.com/r/chainsafe/lodestar) [![Ethereum Consensus Spec v1.1.10](https://img.shields.io/badge/ETH%20consensus--spec-1.1.10-blue)](https://github.com/ethereum/consensus-specs/releases/tag/v1.1.10) +
![ES Version](https://img.shields.io/badge/ES-2021-yellow) ![Node Version](https://img.shields.io/badge/node-20.x-green) +[![codecov](https://codecov.io/gh/ChainSafe/lodestar/graph/badge.svg)](https://codecov.io/gh/ChainSafe/lodestar) [![gitpoap badge](https://public-api.gitpoap.io/v1/repo/ChainSafe/lodestar/badge)](https://www.gitpoap.io/gh/ChainSafe/lodestar) [Lodestar](https://lodestar.chainsafe.io) is a TypeScript implementation of the [Ethereum Consensus specification](https://github.com/ethereum/consensus-specs) developed by [ChainSafe Systems](https://chainsafe.io). diff --git a/package.json b/package.json index 5d7a90f27e6f..4aa463fb6084 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "check-readme": "lerna run check-readme", "check-types": "lerna run check-types", "check-spelling": "pyspelling -c .pyspelling.yml -v", - "coverage": "lerna run coverage", "docs:install": "pip install --user -r docs/requirements.txt", "docs:build": "lerna run check-readme && lerna run docs:build && ./scripts/prepare-docs.sh", "docs:lint": "prettier '**/*.md' --check", @@ -54,7 +53,6 @@ "@typescript-eslint/parser": "6.7.2", "@vitest/coverage-v8": "^1.2.1", "@vitest/browser": "^1.2.1", - "codecov": "^3.8.3", "crypto-browserify": "^3.12.0", "electron": "^26.2.2", "eslint": "^8.50.0", diff --git a/packages/api/package.json b/packages/api/package.json index a8b77bd662dd..8b5847c1a47e 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -60,7 +60,6 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "coverage": "codecov -F lodestar-api", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit", diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index ec17346bbc47..8a993a4e2f0f 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -72,7 +72,6 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "coverage": "codecov -F lodestar", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit && yarn test:e2e", diff --git a/packages/cli/package.json b/packages/cli/package.json index 187892b54553..cbd6dba233db 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -38,7 +38,6 @@ "test:sim:deneb": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/deneb.test.ts", "test:sim:backup_eth_provider": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/backup_eth_provider.test.ts", "test": "yarn test:unit && yarn test:e2e", - "coverage": "codecov -F lodestar", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/db/package.json b/packages/db/package.json index 6161ef625166..930a79a4333a 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -28,7 +28,6 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "coverage": "codecov -F lodestar-fork-choice", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit", diff --git a/packages/fork-choice/package.json b/packages/fork-choice/package.json index 56143dc46d37..ca1332b3ee14 100644 --- a/packages/fork-choice/package.json +++ b/packages/fork-choice/package.json @@ -29,7 +29,6 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "coverage": "codecov -F lodestar-fork-choice", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit", diff --git a/packages/light-client/package.json b/packages/light-client/package.json index b32d9ad6556f..8b87d714ab35 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -54,7 +54,6 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "coverage": "codecov -F lodestar-light-client", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit", diff --git a/packages/prover/package.json b/packages/prover/package.json index b88c42f4f01a..5c7d8ad8d691 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -48,7 +48,6 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "coverage": "codecov -F lodestar-api", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit && yarn test:e2e", diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index 9e2919a0c6d8..80fcb8d8b4f3 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -45,7 +45,6 @@ "build:release": "yarn clean && yarn run build", "check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"", "check-types": "tsc", - "coverage": "codecov -F lodestar-api", "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit", diff --git a/packages/validator/package.json b/packages/validator/package.json index 211627c6ace6..65e5d1547388 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -32,7 +32,6 @@ "test:spec": "vitest --run --config vitest.spec.config.ts --dir test/spec/", "test:e2e": "LODESTAR_PRESET=mainnet vitest --run --config vitest.e2e.config.ts --dir test/e2e", "download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts", - "coverage": "codecov -F lodestar-validator", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/yarn.lock b/yarn.lock index 427db4fdc496..f84e27c73d3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3835,11 +3835,6 @@ argparse@^2.0.1: resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -argv@0.0.2: - version "0.0.2" - resolved "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz" - integrity sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas= - aria-query@^5.0.0: version "5.3.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" @@ -4818,17 +4813,6 @@ cmd-shim@6.0.1: resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.1.tgz#a65878080548e1dca760b3aea1e21ed05194da9d" integrity sha512-S9iI9y0nKR4hwEQsVWpyxld/6kRfGepGfzff83FcaiEBpmvlbA2nnGe7Cylgrx2f/p1P5S5wpRm9oL8z1PbS3Q== -codecov@^3.8.3: - version "3.8.3" - resolved "https://registry.npmjs.org/codecov/-/codecov-3.8.3.tgz" - integrity sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA== - dependencies: - argv "0.0.2" - ignore-walk "3.0.4" - js-yaml "3.14.1" - teeny-request "7.1.1" - urlgrey "1.0.0" - color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -6387,13 +6371,6 @@ fast-uri@^2.0.0, fast-uri@^2.1.0: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.2.0.tgz#519a0f849bef714aad10e9753d69d8f758f7445a" integrity sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg== -fast-url-parser@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= - dependencies: - punycode "^1.3.2" - fastify-plugin@^4.0.0: version "4.5.0" resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-4.5.0.tgz#8b853923a0bba6ab6921bb8f35b81224e6988d91" @@ -7263,7 +7240,7 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" -http-proxy-agent@^4.0.0, http-proxy-agent@^4.0.1: +http-proxy-agent@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== @@ -7381,13 +7358,6 @@ ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore-walk@3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz" - integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== - dependencies: - minimatch "^3.0.4" - ignore-walk@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776" @@ -8173,14 +8143,6 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.14.1, js-yaml@^3.10.0: - version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" @@ -8188,6 +8150,14 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +js-yaml@^3.10.0: + version "3.14.1" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsdom@^23.0.1: version "23.0.1" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-23.0.1.tgz#ede7ff76e89ca035b11178d200710d8982ebfee0" @@ -10686,7 +10656,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== -punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: +punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== @@ -11716,13 +11686,6 @@ stream-browserify@^3.0.0: inherits "~2.0.4" readable-stream "^3.5.0" -stream-events@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz" - integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== - dependencies: - stubs "^3.0.0" - stream-http@^2.7.2: version "2.8.3" resolved "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz" @@ -11906,11 +11869,6 @@ strong-log-transformer@2.1.0, strong-log-transformer@^2.1.0: minimist "^1.2.0" through "^2.3.4" -stubs@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz" - integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls= - sumchecker@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" @@ -12061,17 +12019,6 @@ tdigest@^0.1.1: dependencies: bintrees "1.0.1" -teeny-request@7.1.1: - version "7.1.1" - resolved "https://registry.npmjs.org/teeny-request/-/teeny-request-7.1.1.tgz" - integrity sha512-iwY6rkW5DDGq8hE2YgNQlKbptYpY5Nn2xecjQiNjOXWbKzPGUfmeUBCSQbbr306d7Z7U2N0TPl+/SwYRfua1Dg== - dependencies: - http-proxy-agent "^4.0.0" - https-proxy-agent "^5.0.0" - node-fetch "^2.6.1" - stream-events "^1.0.5" - uuid "^8.0.0" - temp-dir@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -12660,13 +12607,6 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" -urlgrey@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/urlgrey/-/urlgrey-1.0.0.tgz" - integrity sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w== - dependencies: - fast-url-parser "^1.1.3" - userhome@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/userhome/-/userhome-1.0.0.tgz#b6491ff12d21a5e72671df9ccc8717e1c6688c0b" @@ -12707,7 +12647,7 @@ uuid@3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -uuid@8.3.2, uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.2: +uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== From 036fb39bcf6d3a5c6163692217ad2f50403a29aa Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 8 Feb 2024 08:43:11 -0800 Subject: [PATCH 35/71] feat: emit slashing events (#6391) * feat: emit slashing events * chore: added tests * chore: wording Co-authored-by: Nico Flaig --------- Co-authored-by: Nico Flaig --- packages/api/src/beacon/routes/events.ts | 10 +++ .../api/test/unit/beacon/testData/events.ts | 62 ++++++++++++++++++ .../src/chain/blocks/importBlock.ts | 10 +++ .../src/network/processor/gossipHandlers.ts | 4 ++ .../test/e2e/network/gossipsub.test.ts | 64 +++++++++++++++++++ 5 files changed, 150 insertions(+) diff --git a/packages/api/src/beacon/routes/events.ts b/packages/api/src/beacon/routes/events.ts index 41a8e2e9cad9..ddcc57104523 100644 --- a/packages/api/src/beacon/routes/events.ts +++ b/packages/api/src/beacon/routes/events.ts @@ -35,6 +35,10 @@ export enum EventType { attestation = "attestation", /** The node has received a valid voluntary exit (from P2P or API) */ voluntaryExit = "voluntary_exit", + /** The node has received a valid proposer slashing (from P2P or API) */ + proposerSlashing = "proposer_slashing", + /** The node has received a valid attester slashing (from P2P or API) */ + attesterSlashing = "attester_slashing", /** The node has received a valid blsToExecutionChange (from P2P or API) */ blsToExecutionChange = "bls_to_execution_change", /** Finalized checkpoint has been updated */ @@ -58,6 +62,8 @@ export const eventTypes: {[K in EventType]: K} = { [EventType.block]: EventType.block, [EventType.attestation]: EventType.attestation, [EventType.voluntaryExit]: EventType.voluntaryExit, + [EventType.proposerSlashing]: EventType.proposerSlashing, + [EventType.attesterSlashing]: EventType.attesterSlashing, [EventType.blsToExecutionChange]: EventType.blsToExecutionChange, [EventType.finalizedCheckpoint]: EventType.finalizedCheckpoint, [EventType.chainReorg]: EventType.chainReorg, @@ -85,6 +91,8 @@ export type EventData = { }; [EventType.attestation]: phase0.Attestation; [EventType.voluntaryExit]: phase0.SignedVoluntaryExit; + [EventType.proposerSlashing]: phase0.ProposerSlashing; + [EventType.attesterSlashing]: phase0.AttesterSlashing; [EventType.blsToExecutionChange]: capella.SignedBLSToExecutionChange; [EventType.finalizedCheckpoint]: { block: RootHex; @@ -174,6 +182,8 @@ export function getTypeByEvent(): {[K in EventType]: TypeJson} { [EventType.attestation]: ssz.phase0.Attestation, [EventType.voluntaryExit]: ssz.phase0.SignedVoluntaryExit, + [EventType.proposerSlashing]: ssz.phase0.ProposerSlashing, + [EventType.attesterSlashing]: ssz.phase0.AttesterSlashing, [EventType.blsToExecutionChange]: ssz.capella.SignedBLSToExecutionChange, [EventType.finalizedCheckpoint]: new ContainerType( diff --git a/packages/api/test/unit/beacon/testData/events.ts b/packages/api/test/unit/beacon/testData/events.ts index 7bfac9a59a88..08dd27e09d76 100644 --- a/packages/api/test/unit/beacon/testData/events.ts +++ b/packages/api/test/unit/beacon/testData/events.ts @@ -48,6 +48,68 @@ export const eventTestData: EventData = { signature: "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", }), + [EventType.proposerSlashing]: ssz.phase0.ProposerSlashing.fromJson({ + signed_header_1: { + message: { + slot: "0", + proposer_index: "0", + parent_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + state_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + body_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + signature: + "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, + signed_header_2: { + message: { + slot: "0", + proposer_index: "0", + parent_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + state_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + body_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + signature: + "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, + }), + [EventType.attesterSlashing]: ssz.phase0.AttesterSlashing.fromJson({ + attestation_1: { + attesting_indices: ["0", "1"], + data: { + slot: "0", + index: "0", + beacon_block_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + source: { + epoch: "0", + root: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + target: { + epoch: "0", + root: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + }, + signature: + "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, + attestation_2: { + attesting_indices: ["0", "1"], + data: { + slot: "0", + index: "0", + beacon_block_root: "0x0000000000000000000000000000000000000000000000000000000000000000", + source: { + epoch: "0", + root: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + target: { + epoch: "0", + root: "0x0000000000000000000000000000000000000000000000000000000000000000", + }, + }, + signature: + "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, + }), [EventType.blsToExecutionChange]: ssz.capella.SignedBLSToExecutionChange.fromJson({ message: { validator_index: "1", diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index 89ed52b66750..c8fc62eaa622 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -414,6 +414,16 @@ export async function importBlock( this.emitter.emit(routes.events.EventType.attestation, attestation); } } + if (this.emitter.listenerCount(routes.events.EventType.attesterSlashing)) { + for (const attesterSlashing of block.message.body.attesterSlashings) { + this.emitter.emit(routes.events.EventType.attesterSlashing, attesterSlashing); + } + } + if (this.emitter.listenerCount(routes.events.EventType.proposerSlashing)) { + for (const proposerSlashing of block.message.body.proposerSlashings) { + this.emitter.emit(routes.events.EventType.proposerSlashing, proposerSlashing); + } + } } // Register stat metrics about the block after importing it diff --git a/packages/beacon-node/src/network/processor/gossipHandlers.ts b/packages/beacon-node/src/network/processor/gossipHandlers.ts index 9073a204b785..bdd5f1917dc5 100644 --- a/packages/beacon-node/src/network/processor/gossipHandlers.ts +++ b/packages/beacon-node/src/network/processor/gossipHandlers.ts @@ -453,6 +453,8 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler } catch (e) { logger.error("Error adding attesterSlashing to pool", {}, e as Error); } + + chain.emitter.emit(routes.events.EventType.attesterSlashing, attesterSlashing); }, [GossipType.proposer_slashing]: async ({ @@ -470,6 +472,8 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler } catch (e) { logger.error("Error adding attesterSlashing to pool", {}, e as Error); } + + chain.emitter.emit(routes.events.EventType.proposerSlashing, proposerSlashing); }, [GossipType.voluntary_exit]: async ({gossipData, topic}: GossipHandlerParamGeneric) => { diff --git a/packages/beacon-node/test/e2e/network/gossipsub.test.ts b/packages/beacon-node/test/e2e/network/gossipsub.test.ts index c7b3dbefbe77..fd1794bf549d 100644 --- a/packages/beacon-node/test/e2e/network/gossipsub.test.ts +++ b/packages/beacon-node/test/e2e/network/gossipsub.test.ts @@ -138,6 +138,70 @@ function runTests({useWorker}: {useWorker: boolean}): void { ); }); + it("Publish and receive an attesterSlashing", async function () { + let onAttesterSlashingChange: (payload: Uint8Array) => void; + const onAttesterSlashingChangePromise = new Promise((resolve) => (onAttesterSlashingChange = resolve)); + + const {netA, netB} = await mockModules({ + [GossipType.attester_slashing]: async ({gossipData}: GossipHandlerParamGeneric) => { + onAttesterSlashingChange(gossipData.serializedData); + }, + }); + + await Promise.all([onPeerConnect(netA), onPeerConnect(netB), connect(netA, netB)]); + expect(netA.getConnectedPeerCount()).toBe(1); + expect(netB.getConnectedPeerCount()).toBe(1); + + await netA.subscribeGossipCoreTopics(); + await netB.subscribeGossipCoreTopics(); + + // Wait to have a peer connected to a topic + while (!netA.closed) { + await sleep(500); + if (await hasSomeMeshPeer(netA)) { + break; + } + } + + const attesterSlashing = ssz.phase0.AttesterSlashing.defaultValue(); + await netA.publishAttesterSlashing(attesterSlashing); + + const received = await onAttesterSlashingChangePromise; + expect(Buffer.from(received)).toEqual(Buffer.from(ssz.phase0.AttesterSlashing.serialize(attesterSlashing))); + }); + + it("Publish and receive a proposerSlashing", async function () { + let onProposerSlashingChange: (payload: Uint8Array) => void; + const onProposerSlashingChangePromise = new Promise((resolve) => (onProposerSlashingChange = resolve)); + + const {netA, netB} = await mockModules({ + [GossipType.proposer_slashing]: async ({gossipData}: GossipHandlerParamGeneric) => { + onProposerSlashingChange(gossipData.serializedData); + }, + }); + + await Promise.all([onPeerConnect(netA), onPeerConnect(netB), connect(netA, netB)]); + expect(netA.getConnectedPeerCount()).toBe(1); + expect(netB.getConnectedPeerCount()).toBe(1); + + await netA.subscribeGossipCoreTopics(); + await netB.subscribeGossipCoreTopics(); + + // Wait to have a peer connected to a topic + while (!netA.closed) { + await sleep(500); + if (await hasSomeMeshPeer(netA)) { + break; + } + } + + const proposerSlashing = ssz.phase0.ProposerSlashing.defaultValue(); + await netA.publishProposerSlashing(proposerSlashing); + + const received = await onProposerSlashingChangePromise; + expect(Buffer.from(received)).toEqual(Buffer.from(ssz.phase0.ProposerSlashing.serialize(proposerSlashing))); + }); + it("Publish and receive a LightClientOptimisticUpdate", async function () { let onLightClientOptimisticUpdate: (ou: Uint8Array) => void; const onLightClientOptimisticUpdatePromise = new Promise( From a9dc307b858737333326861496de4fa85cccd950 Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 8 Feb 2024 22:14:42 +0530 Subject: [PATCH 36/71] feat: schedule deneb on mainnet (#6411) --- packages/config/src/chainConfig/configs/mainnet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config/src/chainConfig/configs/mainnet.ts b/packages/config/src/chainConfig/configs/mainnet.ts index f9c17ce1cb8e..9d060330d201 100644 --- a/packages/config/src/chainConfig/configs/mainnet.ts +++ b/packages/config/src/chainConfig/configs/mainnet.ts @@ -47,7 +47,7 @@ export const chainConfig: ChainConfig = { // Deneb DENEB_FORK_VERSION: b("0x04000000"), - DENEB_FORK_EPOCH: Infinity, + DENEB_FORK_EPOCH: 269568, // March 13, 2024, 01:55:35pm UTC // Time parameters // --------------------------------------------------------------- From b1848ec145421a47df8efaff8c16872e391fc1fb Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 8 Feb 2024 20:27:50 +0100 Subject: [PATCH 37/71] chore: remove npm badge from README (#6412) --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 6f682e6e87c8..95efcc110db0 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,8 @@ # Lodestar Ethereum Consensus Implementation [![GitHub release (latest by date)](https://img.shields.io/github/v/release/chainsafe/lodestar?label=Github)](https://github.com/ChainSafe/lodestar/releases/latest) -[![npm](https://img.shields.io/npm/v/@chainsafe/lodestar)](https://www.npmjs.com/package/@chainsafe/lodestar) [![Docker Image Version (latest by date)](https://img.shields.io/docker/v/chainsafe/lodestar?color=blue&label=Docker&sort=semver)](https://hub.docker.com/r/chainsafe/lodestar) [![Ethereum Consensus Spec v1.1.10](https://img.shields.io/badge/ETH%20consensus--spec-1.1.10-blue)](https://github.com/ethereum/consensus-specs/releases/tag/v1.1.10) -
![ES Version](https://img.shields.io/badge/ES-2021-yellow) ![Node Version](https://img.shields.io/badge/node-20.x-green) [![codecov](https://codecov.io/gh/ChainSafe/lodestar/graph/badge.svg)](https://codecov.io/gh/ChainSafe/lodestar) From 10ac136b92cd2d72ebc4879d5bc1d6867dfc356e Mon Sep 17 00:00:00 2001 From: Cayman Date: Fri, 9 Feb 2024 23:08:06 -0500 Subject: [PATCH 38/71] feat: manually use identify protocol (#6400) --- packages/beacon-node/src/network/interface.ts | 3 ++- .../beacon-node/src/network/libp2p/index.ts | 1 + .../src/network/peers/peerManager.ts | 24 ++++++++----------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/packages/beacon-node/src/network/interface.ts b/packages/beacon-node/src/network/interface.ts index 573698c13ded..aeeb61f1feb2 100644 --- a/packages/beacon-node/src/network/interface.ts +++ b/packages/beacon-node/src/network/interface.ts @@ -15,6 +15,7 @@ import { } from "@libp2p/interface"; import type {AddressManager, ConnectionManager, Registrar, TransportManager} from "@libp2p/interface-internal"; import type {Datastore} from "interface-datastore"; +import {Identify} from "@chainsafe/libp2p-identify"; import {Slot, SlotRootHex, allForks, altair, capella, deneb, phase0} from "@lodestar/types"; import {PeerIdStr} from "../util/peerId.js"; import {INetworkEventBus} from "./events.js"; @@ -98,4 +99,4 @@ export type LodestarComponents = { metrics?: Metrics; }; -export type Libp2p = ILibp2p<{components: LodestarComponents}>; +export type Libp2p = ILibp2p<{components: LodestarComponents; identify: Identify}>; diff --git a/packages/beacon-node/src/network/libp2p/index.ts b/packages/beacon-node/src/network/libp2p/index.ts index 8a8cca38c167..a0d58033cf2f 100644 --- a/packages/beacon-node/src/network/libp2p/index.ts +++ b/packages/beacon-node/src/network/libp2p/index.ts @@ -112,6 +112,7 @@ export async function createNodeJsLibp2p( services: { identify: identify({ agentVersion: networkOpts.private ? "" : networkOpts.version ? `lodestar/${networkOpts.version}` : "lodestar", + runOnConnectionOpen: false, }), // individual components are specified because the components object is a Proxy // and passing it here directly causes problems downstream, not to mention is slowwww diff --git a/packages/beacon-node/src/network/peers/peerManager.ts b/packages/beacon-node/src/network/peers/peerManager.ts index 2275178e13e3..a5f330603593 100644 --- a/packages/beacon-node/src/network/peers/peerManager.ts +++ b/packages/beacon-node/src/network/peers/peerManager.ts @@ -3,7 +3,7 @@ import {BitArray} from "@chainsafe/ssz"; import {SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; import {BeaconConfig} from "@lodestar/config"; import {allForks, altair, phase0} from "@lodestar/types"; -import {retry, withTimeout} from "@lodestar/utils"; +import {withTimeout} from "@lodestar/utils"; import {LoggerNode} from "@lodestar/logger/node"; import {GoodByeReasonCode, GOODBYE_KNOWN_CODES, Libp2pEvent} from "../../constants/index.js"; import {IClock} from "../../util/clock.js"; @@ -606,22 +606,18 @@ export class PeerManager { void this.requestStatus(remotePeer, this.statusCache.get()); } - // AgentVersion was set in libp2p IdentifyService, 'peer:connect' event handler - // since it's not possible to handle it async, we have to wait for a while to set AgentVersion - // See https://github.com/libp2p/js-libp2p/pull/1168 - retry( - async () => { - const agentVersionBytes = (await this.libp2p.peerStore.get(peerData.peerId)).metadata.get("AgentVersion"); - if (agentVersionBytes) { - const agentVersion = new TextDecoder().decode(agentVersionBytes) || "N/A"; + this.libp2p.services.identify + .identify(evt.detail) + .then((result) => { + const agentVersion = result.agentVersion; + if (agentVersion) { peerData.agentVersion = agentVersion; peerData.agentClient = getKnownClientFromAgentVersion(agentVersion); } - }, - {retries: 3, retryDelay: 1000} - ).catch((err) => { - this.logger.debug("Error setting agentVersion for the peer", {peerId: peerData.peerId.toString()}, err); - }); + }) + .catch((err) => { + this.logger.debug("Error setting agentVersion for the peer", {peerId: peerData.peerId.toString()}, err); + }); }; /** From 54bedcbff7e9844ce464974b9fdc4349fe298217 Mon Sep 17 00:00:00 2001 From: Julien Date: Fri, 9 Feb 2024 20:08:49 -0800 Subject: [PATCH 39/71] chore: upgrade bls (#6413) --- packages/beacon-node/package.json | 2 +- packages/cli/package.json | 2 +- packages/flare/package.json | 2 +- packages/light-client/package.json | 2 +- packages/state-transition/package.json | 2 +- packages/test-utils/package.json | 2 +- packages/validator/package.json | 2 +- yarn.lock | 9 ++++----- 8 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 8a993a4e2f0f..49cbd1748646 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -95,7 +95,7 @@ "dependencies": { "@chainsafe/as-chacha20poly1305": "^0.1.0", "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/bls": "7.1.1", + "@chainsafe/bls": "7.1.3", "@chainsafe/blst": "^0.2.9", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index cbd6dba233db..ac72644244ec 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -52,7 +52,7 @@ ], "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/bls": "7.1.1", + "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keygen": "^0.4.0", "@chainsafe/bls-keystore": "^3.0.1", "@chainsafe/blst": "^0.2.9", diff --git a/packages/flare/package.json b/packages/flare/package.json index d7e2939c3df2..bc5f265f1f87 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -58,7 +58,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "7.1.1", + "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keygen": "^0.4.0", "@lodestar/api": "^1.15.1", "@lodestar/config": "^1.15.1", diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 8b87d714ab35..ae65958da8e4 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -65,7 +65,7 @@ "check-readme": "typescript-docs-verifier" }, "dependencies": { - "@chainsafe/bls": "7.1.1", + "@chainsafe/bls": "7.1.3", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", "@lodestar/api": "^1.15.1", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index ad6148b51984..f4a910d9f5c8 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -59,7 +59,7 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/bls": "7.1.1", + "@chainsafe/bls": "7.1.3", "@chainsafe/blst": "^0.2.9", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/persistent-ts": "^0.19.1", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 1d85e4cf4d6a..5cb3164b3cbc 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -57,7 +57,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "7.1.1", + "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keystore": "^3.0.1", "@lodestar/params": "^1.15.1", "@lodestar/utils": "^1.15.1", diff --git a/packages/validator/package.json b/packages/validator/package.json index 65e5d1547388..201591c2c272 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -45,7 +45,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "7.1.1", + "@chainsafe/bls": "7.1.3", "@chainsafe/ssz": "^0.14.0", "@lodestar/api": "^1.15.1", "@lodestar/config": "^1.15.1", diff --git a/yarn.lock b/yarn.lock index f84e27c73d3a..d6a1f10b071a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -285,14 +285,13 @@ ethereum-cryptography "^2.0.0" uuid "^9.0.0" -"@chainsafe/bls@7.1.1": - version "7.1.1" - resolved "https://registry.npmjs.org/@chainsafe/bls/-/bls-7.1.1.tgz" - integrity sha512-56hjFJujW0Z0Ntkr8y22xIAfT4SChYWQtCGM8dfUMkWWX8xLOXkhBFFSNTvPXA5cBlsFlo102CtBo+6A60II2w== +"@chainsafe/bls@7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@chainsafe/bls/-/bls-7.1.3.tgz#8d488357b187a511cfb94c96eddc7aa9f62644a9" + integrity sha512-d21eYdWxDSb63n7nB+viD+3U4yJW8huiKRibJyh8X7btPLoXkvtmDf7geYyHVbKfLDgbuHkc+b48pfPQkUTLxA== dependencies: "@chainsafe/bls-keygen" "^0.4.0" bls-eth-wasm "^0.4.8" - randombytes "^2.1.0" "@chainsafe/blst@^0.2.9": version "0.2.9" From 5c251851beb8434f2478c0e2c0fc7f9ab7983a73 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Sat, 10 Feb 2024 05:16:38 +0100 Subject: [PATCH 40/71] feat: add new panels to validator client dashboard (#6415) * Add url as label request to fallbacks and score metrics * Add url as label to request errors * Add connected beacon nodes panel * Add requests to fallback nodes panel * Add REST API request errors panel --- dashboards/lodestar_validator_client.json | 349 +++++++++++++++++- packages/api/src/utils/client/httpClient.ts | 6 +- packages/api/src/utils/client/metrics.ts | 6 +- .../src/metrics/metrics/lodestar.ts | 12 +- packages/validator/src/metrics.ts | 12 +- 5 files changed, 356 insertions(+), 29 deletions(-) diff --git a/dashboards/lodestar_validator_client.json b/dashboards/lodestar_validator_client.json index 7cc41cffdb34..8ec6a04437b1 100644 --- a/dashboards/lodestar_validator_client.json +++ b/dashboards/lodestar_validator_client.json @@ -506,21 +506,121 @@ "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "description": "A list of beacon nodes the validator client is connected to, with their last known health status. For fallback nodes, this status might be inaccurate as it is only updated if primary node is unhealthy.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [] + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "urlIndex" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "0": { + "index": 0, + "text": "Primary" + } + }, + "type": "value" + }, + { + "options": { + "from": 1, + "result": { + "index": 1, + "text": "Fallback" + }, + "to": 999 + }, + "type": "range" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "0": { + "color": "red", + "index": 2, + "text": "Unhealthy" + }, + "10": { + "color": "green", + "index": 0, + "text": "Healthy" + } + }, + "type": "value" + }, + { + "options": { + "from": 1, + "result": { + "color": "yellow", + "index": 1, + "text": "Degraded" + }, + "to": 9 + }, + "type": "range" + } + ] + }, + { + "id": "custom.cellOptions", + "value": { + "type": "color-text" + } + } + ] + } + ] + }, "gridPos": { "h": 4, "w": 12, "x": 12, "y": 5 }, - "id": 45, + "id": 44, "options": { - "code": { - "language": "plaintext", - "showLineNumbers": false, - "showMiniMap": false + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false }, - "content": "_Validator metrics =D_", - "mode": "markdown" + "showHeader": false }, "pluginVersion": "10.1.1", "targets": [ @@ -529,10 +629,66 @@ "type": "prometheus", "uid": "${DS_PROMETHEUS}" }, + "editorMode": "code", + "exemplar": false, + "expr": "vc_rest_api_client_urls_score", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, "refId": "A" } ], - "type": "text" + "title": "Connected beacon nodes", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "__name__": true, + "client_name": true, + "group": true, + "host_type": true, + "instance": true, + "job": true, + "network": true, + "scrape_location": true + }, + "indexByName": { + "Time": 3, + "Value": 2, + "__name__": 4, + "baseUrl": 0, + "client_name": 5, + "group": 6, + "host_type": 7, + "instance": 8, + "job": 9, + "network": 10, + "scrape_location": 11, + "urlIndex": 1 + }, + "renameByName": { + "Value": "Status", + "baseUrl": "URL", + "urlIndex": "Type" + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "Type" + } + ] + } + } + ], + "type": "table" }, { "datasource": { @@ -1100,7 +1256,7 @@ "unit": "s" } }, - "pluginVersion": "9.3.2", + "pluginVersion": "10.1.1", "reverseYBuckets": false, "targets": [ { @@ -1212,7 +1368,7 @@ "unit": "s" } }, - "pluginVersion": "9.3.2", + "pluginVersion": "10.1.1", "reverseYBuckets": false, "targets": [ { @@ -1269,6 +1425,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1349,6 +1506,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1429,6 +1587,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineStyle": { "fill": "solid" @@ -1535,6 +1694,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1615,6 +1775,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1750,7 +1911,7 @@ "unit": "s" } }, - "pluginVersion": "9.3.2", + "pluginVersion": "10.1.1", "reverseYBuckets": false, "targets": [ { @@ -1806,6 +1967,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1935,6 +2097,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -2013,6 +2176,170 @@ ], "title": "Duties reorgs / sec", "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-YlRd" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 73 + }, + "id": 46, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "60 * sum(rate(vc_rest_api_client_request_errors_total[$rate_interval])) by (baseUrl) > 0", + "instant": false, + "legendFormat": "{{baseUrl}}", + "range": true, + "refId": "A" + } + ], + "title": "REST API request errors (rate / min)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 73 + }, + "id": 45, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "60 * sum(rate(vc_rest_api_client_request_to_fallbacks_total[$rate_interval])) by (baseUrl) > 0", + "instant": false, + "legendFormat": "{{baseUrl}}", + "range": true, + "refId": "A" + } + ], + "title": "Requests to fallback nodes (rate / min)", + "type": "timeseries" } ], "refresh": "10s", diff --git a/packages/api/src/utils/client/httpClient.ts b/packages/api/src/utils/client/httpClient.ts index 674c6ddadbe8..c0fd2b8ad1aa 100644 --- a/packages/api/src/utils/client/httpClient.ts +++ b/packages/api/src/utils/client/httpClient.ts @@ -160,7 +160,7 @@ export class HttpClient implements IHttpClient { if (metrics) { metrics.urlsScore.addCollect(() => { for (let i = 0; i < this.urlsScore.length; i++) { - metrics.urlsScore.set({urlIndex: i}, this.urlsScore[i]); + metrics.urlsScore.set({urlIndex: i, baseUrl: this.urlsOpts[i].baseUrl}, this.urlsScore[i]); } }); } @@ -211,7 +211,7 @@ export class HttpClient implements IHttpClient { const routeId = opts.routeId ?? DEFAULT_ROUTE_ID; if (i > 0) { - this.metrics?.requestToFallbacks.inc({routeId}); + this.metrics?.requestToFallbacks.inc({routeId, baseUrl}); this.logger?.debug("Requesting fallback URL", {routeId, baseUrl, score: this.urlsScore[i]}); } @@ -319,7 +319,7 @@ export class HttpClient implements IHttpClient { this.logger?.debug("HttpClient response", {routeId}); return {status: res.status, body}; } catch (e) { - this.metrics?.requestErrors.inc({routeId}); + this.metrics?.requestErrors.inc({routeId, baseUrl}); if (isAbortedError(e as Error)) { if (signalGlobal?.aborted) { diff --git a/packages/api/src/utils/client/metrics.ts b/packages/api/src/utils/client/metrics.ts index 65089e92e7ec..b326bdf3abb3 100644 --- a/packages/api/src/utils/client/metrics.ts +++ b/packages/api/src/utils/client/metrics.ts @@ -3,7 +3,7 @@ import {Gauge, GaugeExtra, Histogram} from "@lodestar/utils"; export type Metrics = { requestTime: Histogram<{routeId: string}>; streamTime: Histogram<{routeId: string}>; - requestErrors: Gauge<{routeId: string}>; - requestToFallbacks: Gauge<{routeId: string}>; - urlsScore: GaugeExtra<{urlIndex: number}>; + requestErrors: Gauge<{routeId: string; baseUrl: string}>; + requestToFallbacks: Gauge<{routeId: string; baseUrl: string}>; + urlsScore: GaugeExtra<{urlIndex: number; baseUrl: string}>; }; diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 284f4e75c064..0f4940cd5d5c 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -1622,21 +1622,21 @@ export function createLodestarMetrics( // Provide max resolution on problematic values around 1 second buckets: [0.1, 0.5, 1, 2, 5, 15], }), - requestErrors: register.gauge<{routeId: string}>({ + requestErrors: register.gauge<{routeId: string; baseUrl: string}>({ name: "lodestar_builder_http_client_request_errors_total", help: "Total count of errors on builder http client requests by routeId", - labelNames: ["routeId"], + labelNames: ["routeId", "baseUrl"], }), - requestToFallbacks: register.gauge<{routeId: string}>({ + requestToFallbacks: register.gauge<{routeId: string; baseUrl: string}>({ name: "lodestar_builder_http_client_request_to_fallbacks_total", help: "Total count of requests to fallback URLs on builder http API by routeId", - labelNames: ["routeId"], + labelNames: ["routeId", "baseUrl"], }), - urlsScore: register.gauge<{urlIndex: number}>({ + urlsScore: register.gauge<{urlIndex: number; baseUrl: string}>({ name: "lodestar_builder_http_client_urls_score", help: "Current score of builder http URLs by url index", - labelNames: ["urlIndex"], + labelNames: ["urlIndex", "baseUrl"], }), }, diff --git a/packages/validator/src/metrics.ts b/packages/validator/src/metrics.ts index 4acf66955769..56d94318d12b 100644 --- a/packages/validator/src/metrics.ts +++ b/packages/validator/src/metrics.ts @@ -299,22 +299,22 @@ export function getMetrics(register: MetricsRegisterExtra, gitData: LodestarGitD buckets: [0.01, 0.1, 1, 2, 5], }), - requestErrors: register.gauge<{routeId: string}>({ + requestErrors: register.gauge<{routeId: string; baseUrl: string}>({ name: "vc_rest_api_client_request_errors_total", help: "Total count of errors on REST API client requests by routeId", - labelNames: ["routeId"], + labelNames: ["routeId", "baseUrl"], }), - requestToFallbacks: register.gauge<{routeId: string}>({ + requestToFallbacks: register.gauge<{routeId: string; baseUrl: string}>({ name: "vc_rest_api_client_request_to_fallbacks_total", help: "Total count of requests to fallback URLs on REST API by routeId", - labelNames: ["routeId"], + labelNames: ["routeId", "baseUrl"], }), - urlsScore: register.gauge<{urlIndex: number}>({ + urlsScore: register.gauge<{urlIndex: number; baseUrl: string}>({ name: "vc_rest_api_client_urls_score", help: "Current score of REST API URLs by url index", - labelNames: ["urlIndex"], + labelNames: ["urlIndex", "baseUrl"], }), }, From 1e6757944237305772290a913421b839bf90a9a4 Mon Sep 17 00:00:00 2001 From: Peter Straus <153843855+krauspt@users.noreply.github.com> Date: Sat, 10 Feb 2024 19:10:59 +0100 Subject: [PATCH 41/71] chore: update broken links to lodestar docs (#6417) * fix: update broken links to lodestar docs * fix: update messed links Co-authored-by: Nico Flaig --------- Co-authored-by: Nico Flaig --- README.md | 10 +++++----- packages/api/README.md | 2 +- packages/beacon-node/README.md | 2 +- packages/cli/README.md | 2 +- packages/reqresp/README.md | 2 +- packages/validator/README.md | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 95efcc110db0..867b8f5aaab2 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,12 @@ ## Getting started -- :gear: Follow the installation method for [source install](https://chainsafe.github.io/lodestar/install/source/), [NPM install](https://chainsafe.github.io/lodestar/install/npm/), or [Docker install](https://chainsafe.github.io/lodestar/install/docker/) to install Lodestar. Or use our [Lodestar Quickstart scripts](https://github.com/ChainSafe/lodestar-quickstart). -- :books: Use [Lodestar libraries](https://chainsafe.github.io/lodestar/libraries) in your next Ethereum Typescript project. -- :globe_with_meridians: Run a beacon node on [mainnet or a public testnet](https://chainsafe.github.io/lodestar/usage/beacon-management). -- :computer: Utilize the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/usage/local). +- :gear: Follow the installation method for [source install](https://chainsafe.github.io/lodestar/getting-started/installation/#build-from-source), [NPM install](https://chainsafe.github.io/lodestar/getting-started/installation/#install-from-npm-not-recommended), or [Docker install](https://chainsafe.github.io/lodestar/getting-started/installation/#docker-installation) to install Lodestar. Or use our [Lodestar Quickstart scripts](https://github.com/ChainSafe/lodestar-quickstart). +- :books: Use [Lodestar libraries](https://chainsafe.github.io/lodestar/supporting-libraries/libraries/) in your next Ethereum Typescript project. +- :globe_with_meridians: Run a beacon node on [mainnet or a public testnet](https://chainsafe.github.io/lodestar/getting-started/starting-a-node/). +- :computer: Utilize the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/advanced-topics/setting-up-a-testnet/). - :spiral_notepad: View the Lodestar [CLI commands and options](https://chainsafe.github.io/lodestar/reference/cli/). -- :nerd_face: View the [Package and dependency structure](https://chainsafe.github.io/lodestar/design/depgraph/). +- :nerd_face: View the [Package and dependency structure](https://chainsafe.github.io/lodestar/contribution/depgraph/). - :memo: Prospective contributors can read the [contributing section](./CONTRIBUTING.md) to understand how we develop and test on Lodestar. - :writing_hand: If you have questions [submit an issue](https://github.com/ChainSafe/lodestar/issues/new) or join us on [Discord](https://discord.gg/yjyvFRP)! [![Discord](https://img.shields.io/discord/593655374469660673.svg?label=Discord&logo=discord)](https://discord.gg/aMxzVcr) diff --git a/packages/api/README.md b/packages/api/README.md index 79658fda65f7..e8837961159b 100644 --- a/packages/api/README.md +++ b/packages/api/README.md @@ -45,7 +45,7 @@ You will need to go over the [specification](https://github.com/ethereum/beacon- ## Getting started - Follow the [installation guide](https://chainsafe.github.io/lodestar/) to install Lodestar. -- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/usage/local). +- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/advanced-topics/setting-up-a-testnet/). ## Contributors diff --git a/packages/beacon-node/README.md b/packages/beacon-node/README.md index 2459cd5699be..12d1aca05e95 100644 --- a/packages/beacon-node/README.md +++ b/packages/beacon-node/README.md @@ -18,7 +18,7 @@ You will need to go over the [specification](https://github.com/ethereum/consens ## Getting started - Follow the [installation guide](https://chainsafe.github.io/lodestar/) to install Lodestar. -- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/usage/local). +- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/advanced-topics/setting-up-a-testnet/). ## Contributors diff --git a/packages/cli/README.md b/packages/cli/README.md index ae379a9b5d8d..177cb18bc401 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -12,7 +12,7 @@ Command line tool for Lodestar ## Getting started - Follow the [installation guide](https://chainsafe.github.io/lodestar/) to install Lodestar. -- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/usage). +- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/advanced-topics/setting-up-a-testnet/). ### Lodestar diff --git a/packages/reqresp/README.md b/packages/reqresp/README.md index b384c2c178a2..6f8aea550ca6 100644 --- a/packages/reqresp/README.md +++ b/packages/reqresp/README.md @@ -53,7 +53,7 @@ You will need to go over the [specification](https://github.com/ethereum/beacon- ## Getting started - Follow the [installation guide](https://chainsafe.github.io/lodestar/) to install Lodestar. -- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/usage/local). +- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/advanced-topics/setting-up-a-testnet/). ## Contributors diff --git a/packages/validator/README.md b/packages/validator/README.md index 584f7ee3f559..b075c2f293f4 100644 --- a/packages/validator/README.md +++ b/packages/validator/README.md @@ -13,7 +13,7 @@ eth-consensus api compatible beacon nodes/databases/loggers. ## Getting started - Follow the [installation guide](https://chainsafe.github.io/lodestar/) to install Lodestar. -- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/usage/local). +- Quickly try out the whole stack by [starting a local testnet](https://chainsafe.github.io/lodestar/advanced-topics/setting-up-a-testnet/). ## License From da0bcc8f1933349320be546aeeee3970de04b610 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Mon, 12 Feb 2024 14:36:33 +0100 Subject: [PATCH 42/71] test: support .env.test to reuse env variables across the tests (#6408) * Variables using .env file * Add env variable support to normal tests * Fix the order of variables * Update the order of jobs * Export the varible using actions toolkit * Update the workflow tasks * Fix the sim workflow * Add .env.test file support to tests * Fix the lint * Update the task description * Move lodestar preset to env file * Fix the directory path * newline * Update debugging spec tests section * Update the env variable for preset * Fix the path for setup files * Update code as per feedback * Fix the e2e variables * Update doc * Fix the bash script * Fix sim geth runne * Update the env file * Fix e2e tests * Update the script tasks * Update the script tasks * Add minimal for e2e tests * Add minimal for e2e tests * Update comments in preset tests * Downgrade nethermind version * Load env file in e2e env * Add the issue link in env variable * Update bash script for failsafe current dir * Fix the mistaken genesis extension for el nodes * Add missing capella wait for one test * Downgrade the geth version * Update .env.test --------- Co-authored-by: Nico Flaig --- .env.test | 13 +++++++++ .github/actions/dotenv/action.yml | 5 ++++ .github/actions/dotenv/index.js | 29 +++++++++++++++++++ .github/workflows/test-sim.yml | 8 ++--- .github/workflows/test.yml | 7 ++--- CONTRIBUTING.md | 4 +-- .../contribution/testing/simulation-tests.md | 14 +++------ package.json | 4 ++- packages/beacon-node/package.json | 4 +-- packages/cli/package.json | 10 +++---- packages/cli/test/scripts/e2e_test_env.ts | 1 + .../simulation/execution_clients/geth.ts | 2 +- .../cli/test/utils/simulation/utils/paths.ts | 2 +- packages/logger/package.json | 2 +- packages/params/package.json | 2 +- .../params/test/e2e/overridePreset.test.ts | 4 +-- packages/params/test/e2e/setPreset.test.ts | 4 +-- .../test/e2e/web3_batch_request.test.ts | 6 ++-- packages/types/package.json | 2 +- packages/validator/package.json | 2 +- scripts/run_e2e_env.sh | 9 +++--- .../vitest/{ => setupFiles}/customMatchers.ts | 0 scripts/vitest/setupFiles/dotenv.ts | 8 +++++ vitest.base.browser.config.ts | 2 +- vitest.base.unit.config.ts | 5 +++- yarn.lock | 13 +++++++++ 26 files changed, 115 insertions(+), 47 deletions(-) create mode 100644 .env.test create mode 100644 .github/actions/dotenv/action.yml create mode 100644 .github/actions/dotenv/index.js rename scripts/vitest/{ => setupFiles}/customMatchers.ts (100%) create mode 100644 scripts/vitest/setupFiles/dotenv.ts diff --git a/.env.test b/.env.test new file mode 100644 index 000000000000..31222f7549cb --- /dev/null +++ b/.env.test @@ -0,0 +1,13 @@ +# We use these images during sim and e2e tests +# TODO: Upgrade Geth once the Nethermind issue is resolved else it's causing following error +# Rejected peer id=134e2c1a76745626 addr=192.168.0.3:9052 conn=staticdial err="useless peer" +GETH_DOCKER_IMAGE=ethereum/client-go:v1.11.6 +# Use either image or local binary for the testing +GETH_BINARY_DIR= +LIGHTHOUSE_DOCKER_IMAGE=sigp/lighthouse:v4.6.0-amd64-modern-dev +# We can't upgrade nethermind further due to genesis hash mismatch with the geth +# https://github.com/NethermindEth/nethermind/issues/6683 +NETHERMIND_DOCKER_IMAGE=nethermind/nethermind:1.18.2 +# We mostly use mainnet for unit testing +# Changing this value may impact the tests which are written with mainnet in mind +LODESTAR_PRESET=mainnet diff --git a/.github/actions/dotenv/action.yml b/.github/actions/dotenv/action.yml new file mode 100644 index 000000000000..88c0f80b02d3 --- /dev/null +++ b/.github/actions/dotenv/action.yml @@ -0,0 +1,5 @@ +name: "Setup env variables using .env file" +description: "Load .env file from root of repo and setup for CI runner" +runs: + using: "node20" + main: index.js diff --git a/.github/actions/dotenv/index.js b/.github/actions/dotenv/index.js new file mode 100644 index 000000000000..fd7ce8ec2527 --- /dev/null +++ b/.github/actions/dotenv/index.js @@ -0,0 +1,29 @@ +const fs = require("fs"); +const core = require("@actions/core"); +const dotEnv = require("dotenv"); +const envFile = ".env.test"; + +if (!fs.existsSync(envFile)) { + core.setFailed("File .env not found"); +} + +const result = dotEnv.config({path: envFile}); +if (result.error) { + core.setFailed(result.error.message); +} else { + core.setOutput("env", result.parsed); + core.info("Env file loaded"); + core.info("Populating env variables..."); + + for (const key in result.parsed) { + const value = result.parsed[key]; + core.info(`${key}=${value}`); + + // Export variable + core.exportVariable(key, value); + + // Set to output so it can be used in as the input for the next job/step + core.setOutput(key, value); + + } +} diff --git a/.github/workflows/test-sim.yml b/.github/workflows/test-sim.yml index 6adf60e98db1..9a4319aa84af 100644 --- a/.github/workflows/test-sim.yml +++ b/.github/workflows/test-sim.yml @@ -22,11 +22,6 @@ on: type: number default: 40 -env: - GETH_DOCKER_IMAGE: ethereum/client-go:v1.13.11 - LIGHTHOUSE_DOCKER_IMAGE: sigp/lighthouse:latest-amd64-modern-dev - NETHERMIND_DOCKER_IMAGE: nethermind/nethermind:1.25.3 - jobs: tests-sim: name: Sim tests @@ -58,6 +53,9 @@ jobs: if: steps.cache-deps.outputs.cache-hit == 'true' #
+ - name: Load env variables + uses: ./.github/actions/dotenv + - name: Download required docker images before running tests run: | docker pull ${{env.GETH_DOCKER_IMAGE}} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 61be02b589be..3838ef65aa13 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,10 +12,6 @@ on: pull_request: workflow_dispatch: -env: - GETH_DOCKER_IMAGE: ethereum/client-go:v1.11.6 - NETHERMIND_DOCKER_IMAGE: nethermind/nethermind:1.18.0 - jobs: build: name: Build @@ -230,6 +226,9 @@ jobs: key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} fail-on-cache-miss: true + - name: Load env variables + uses: ./.github/actions/dotenv + - name: Run the e2e test environment run: scripts/run_e2e_env.sh start diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7e567ab517fc..009eaa850367 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,7 +35,7 @@ To run tests: Note that to run `test:e2e`, first ensure that the environment is correctly setup by running the `run_e2e_env.sh` script. ```sh -GETH_DOCKER_IMAGE=ethereum/client-go:v1.11.6 NETHERMIND_DOCKER_IMAGE=nethermind/nethermind:1.18.0 ./scripts/run_e2e_env.sh start +./scripts/run_e2e_env.sh start ``` Similarly, run `yarn download-spec-tests` before running `yarn test:spec`. @@ -63,9 +63,9 @@ If you observe following error running any of the test files that means you are - Spec tests often compare full expected vs actual states in JSON format. - A single logical error can cause many spec tests to fail. To focus on a single test at a time you can use vitest's option `--bail 1` to stop at the first failed test - To then run only that failed test you can run against a specific file as use vitest's filters option `-t ` to run only one case +- Before running the tests, make sure to switch to the package directory (e.g. `packages/beacon-node`) to speed up test execution ```sh -cd packages/beacon-node LODESTAR_PRESET=minimal yarn vitest --run --bail 1 --config vitest.spec.config.ts test/spec/presets/sanity.test.ts -t attester_slashing ``` diff --git a/docs/pages/contribution/testing/simulation-tests.md b/docs/pages/contribution/testing/simulation-tests.md index c1059e5c4177..e8e26ad83468 100644 --- a/docs/pages/contribution/testing/simulation-tests.md +++ b/docs/pages/contribution/testing/simulation-tests.md @@ -12,7 +12,7 @@ There are a number of sim tests that are available and each has a slightly diffe ### Environment Variables -To see what typical values for these are check out the `test-sim.yaml` workflow file in the `.github/workflows` directory. +To see what typical values for these are check out the `.env.test` file in the root directory. - `GETH_DOCKER_IMAGE`: The geth docker image that will be used - `NETHERMIND_IMAGE`: The nethermind docker image that will be used @@ -23,10 +23,7 @@ To see what typical values for these are check out the `test-sim.yaml` workflow The multi-fork sim test checks most of the functionality Lodestar provides. Is verifies that Lodestar is capable of peering, moving through all of the forks and using various sync methods in a testnet environment. Lodestar is tested with both Geth and Nethermind as the execution client. It also checks a Lighthouse/Geth node for cross client compatibility. ```sh -GETH_DOCKER_IMAGE=ethereum/client-go:v1.11.6 \ - LIGHTHOUSE_DOCKER_IMAGE=sigp/lighthouse:latest-amd64-modern-dev \ - NETHERMIND_DOCKER_IMAGE=nethermind/nethermind:1.18.0 \ - yarn workspace @chainsafe/lodestar test:sim:multifork +yarn workspace @chainsafe/lodestar test:sim:multifork ``` ### `test:sim:endpoints` @@ -34,8 +31,7 @@ GETH_DOCKER_IMAGE=ethereum/client-go:v1.11.6 \ This tests that various endpoints of the beacon node and validator client are working as expected. ```sh -GETH_DOCKER_IMAGE=ethereum/client-go:v1.11.6 \ - yarn workspace @chainsafe/lodestar test:sim:endpoints +yarn workspace @chainsafe/lodestar test:sim:endpoints ``` ### `test:sim:deneb` @@ -47,9 +43,7 @@ This test is still included in our CI but is no longer as important as it once w Checks that Lodestar is compatible with other consensus validators and vice-versa. All tests use Geth as the EL. ```sh -GETH_DOCKER_IMAGE=ethereum/client-go:v1.11.6 \ - LIGHTHOUSE_DOCKER_IMAGE=sigp/lighthouse:latest-amd64-modern-dev \ - yarn workspace @chainsafe/lodestar test:sim:mixedclient +yarn workspace @chainsafe/lodestar test:sim:mixedclient ``` ## Sim Test Infrastructure diff --git a/package.json b/package.json index 4aa463fb6084..faf313bf775d 100644 --- a/package.json +++ b/package.json @@ -38,13 +38,14 @@ "test-coverage:e2e-sim": "c8 --config .c8rc.json --report-dir coverage/e2e-sim/ --all npm run test:e2e:sim", "test-coverage:spec": "c8 --config .c8rc.json --report-dir coverage/spec/ --all npm run test:spec", "benchmark": "yarn benchmark:files 'packages/*/test/perf/**/*.test.ts'", - "benchmark:files": "LODESTAR_PRESET=mainnet NODE_OPTIONS='--max-old-space-size=4096 --loader=ts-node/esm' benchmark --config .benchrc.yaml --defaultBranch unstable", + "benchmark:files": "NODE_OPTIONS='--max-old-space-size=4096 --loader=ts-node/esm' benchmark --config .benchrc.yaml --defaultBranch unstable", "release:create-rc": "node scripts/release/create_rc.mjs", "release:tag-rc": "node scripts/release/tag_rc.mjs", "release:tag-stable": "node scripts/release/tag_stable.mjs", "release:publish": "lerna publish from-package --yes --no-verify-access" }, "devDependencies": { + "@actions/core": "^1.10.1", "@chainsafe/eslint-plugin-node": "^11.2.3", "@dapplion/benchmark": "^0.2.4", "@types/mocha": "^10.0.6", @@ -54,6 +55,7 @@ "@vitest/coverage-v8": "^1.2.1", "@vitest/browser": "^1.2.1", "crypto-browserify": "^3.12.0", + "dotenv": "^16.4.1", "electron": "^26.2.2", "eslint": "^8.50.0", "eslint-import-resolver-typescript": "^3.6.1", diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 49cbd1748646..8413f9523652 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -75,8 +75,8 @@ "lint": "eslint --color --ext .ts src/ test/", "lint:fix": "yarn run lint --fix", "test": "yarn test:unit && yarn test:e2e", - "test:unit:minimal": "vitest --run --segfaultRetry 3 --dir test/unit/", - "test:unit:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/unit-mainnet", + "test:unit:minimal": "LODESTAR_PRESET=minimal vitest --run --segfaultRetry 3 --dir test/unit/", + "test:unit:mainnet": "LODESTAR_PRESET=mainnet vitest --run --segfaultRetry 3 --dir test/unit-mainnet", "test:unit": "wrapper() { yarn test:unit:minimal $@ && yarn test:unit:mainnet $@; }; wrapper", "test:e2e": "LODESTAR_PRESET=minimal vitest --run --segfaultRetry 3 --config vitest.e2e.config.ts --dir test/e2e", "test:sim": "vitest --run test/sim/**/*.test.ts", diff --git a/packages/cli/package.json b/packages/cli/package.json index ac72644244ec..0d56f85a7434 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -32,11 +32,11 @@ "lint:fix": "yarn run lint --fix", "test:unit": "vitest --run --dir test/unit/", "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e/", - "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", - "test:sim:deneb": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/deneb.test.ts", - "test:sim:backup_eth_provider": "LODESTAR_PRESET=minimal node --loader ts-node/esm test/sim/backup_eth_provider.test.ts", + "test:sim:multifork": "LODESTAR_PRESET=minimal DOTENV_CONFIG_PATH=../../.env.test node -r dotenv/config --loader ts-node/esm test/sim/multi_fork.test.ts", + "test:sim:mixedclient": "LODESTAR_PRESET=minimal DOTENV_CONFIG_PATH=../../.env.test node -r dotenv/config --loader ts-node/esm test/sim/mixed_client.test.ts", + "test:sim:endpoints": "LODESTAR_PRESET=minimal DOTENV_CONFIG_PATH=../../.env.test node -r dotenv/config --loader ts-node/esm test/sim/endpoints.test.ts", + "test:sim:deneb": "LODESTAR_PRESET=minimal DOTENV_CONFIG_PATH=../../.env.test node -r dotenv/config --loader ts-node/esm test/sim/deneb.test.ts", + "test:sim:backup_eth_provider": "LODESTAR_PRESET=minimal DOTENV_CONFIG_PATH=../../.env.test node -r dotenv/config --loader ts-node/esm test/sim/backup_eth_provider.test.ts", "test": "yarn test:unit && yarn test:e2e", "check-readme": "typescript-docs-verifier" }, diff --git a/packages/cli/test/scripts/e2e_test_env.ts b/packages/cli/test/scripts/e2e_test_env.ts index b35b3524d8cf..b5fa48260194 100644 --- a/packages/cli/test/scripts/e2e_test_env.ts +++ b/packages/cli/test/scripts/e2e_test_env.ts @@ -14,6 +14,7 @@ const {forkConfig} = defineSimTestConfig({ BELLATRIX_FORK_EPOCH: bellatrixForkEpoch, CAPELLA_FORK_EPOCH: capellaForkEpoch, runTillEpoch: Infinity, + initialNodes: 2, }); const env = await SimulationEnvironment.initWithDefaults( diff --git a/packages/cli/test/utils/simulation/execution_clients/geth.ts b/packages/cli/test/utils/simulation/execution_clients/geth.ts index bb17d1698330..2ed9a2a91e1c 100644 --- a/packages/cli/test/utils/simulation/execution_clients/geth.ts +++ b/packages/cli/test/utils/simulation/execution_clients/geth.ts @@ -21,7 +21,7 @@ export const generateGethNode: ExecutionNodeGenerator = (o const {id, mode, ttd, address, mining, clientOptions, nodeIndex} = opts; const ports = getNodePorts(nodeIndex); - const isDocker = process.env.GETH_DOCKER_IMAGE !== undefined; + const isDocker = !!process.env.GETH_DOCKER_IMAGE; const binaryPath = isDocker ? "" : `${process.env.GETH_BINARY_DIR}/geth`; const {rootDir, rootDirMounted, genesisFilePathMounted, logFilePath, jwtsecretFilePathMounted} = getNodeMountedPaths( opts.paths, diff --git a/packages/cli/test/utils/simulation/utils/paths.ts b/packages/cli/test/utils/simulation/utils/paths.ts index 0a7ffb716dd1..9f0628e34656 100644 --- a/packages/cli/test/utils/simulation/utils/paths.ts +++ b/packages/cli/test/utils/simulation/utils/paths.ts @@ -23,7 +23,7 @@ export function getNodePaths< return { rootDir: executionRootDir, dataDir: path.join(executionRootDir, "data"), - genesisFilePath: path.join(executionRootDir, "genesis.ssz"), + genesisFilePath: path.join(executionRootDir, "genesis.json"), jwtsecretFilePath: path.join(executionRootDir, "jwtsecret.txt"), logFilePath: path.join(logsDir, `${id}-${client}.log`), } as R; diff --git a/packages/logger/package.json b/packages/logger/package.json index 01ec8aec2444..29eec16d3bdd 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -61,7 +61,7 @@ "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.e2e.config.ts --dir test/e2e", + "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e", "check-readme": "typescript-docs-verifier" }, "types": "lib/index.d.ts", diff --git a/packages/params/package.json b/packages/params/package.json index 980363d1feb3..ced76e18b548 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -58,7 +58,7 @@ "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:electron": "echo 'Electron tests will be introduced back in the future as soon vitest supports electron.'", - "test:e2e": "LODESTAR_PRESET=minimal vitest --run --config vitest.e2e.config.ts --dir test/e2e/", + "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e/", "check-readme": "typescript-docs-verifier" }, "repository": { diff --git a/packages/params/test/e2e/overridePreset.test.ts b/packages/params/test/e2e/overridePreset.test.ts index 16f29f3c5c84..24995cbaa042 100644 --- a/packages/params/test/e2e/overridePreset.test.ts +++ b/packages/params/test/e2e/overridePreset.test.ts @@ -21,8 +21,8 @@ describe("Override preset", function () { vi.setConfig({testTimeout: 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; + // `LODESTAR_PRESET` must not be set to properly test preset override + if (process.env.LODESTAR_PRESET) delete process.env.LODESTAR_PRESET; await exec(`node --loader ts-node/esm ${path.join(__dirname, scriptNames.ok)}`); }); diff --git a/packages/params/test/e2e/setPreset.test.ts b/packages/params/test/e2e/setPreset.test.ts index aa1371fa2eea..844239d56bab 100644 --- a/packages/params/test/e2e/setPreset.test.ts +++ b/packages/params/test/e2e/setPreset.test.ts @@ -21,8 +21,8 @@ describe("setPreset", function () { vi.setConfig({testTimeout: 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; + // `LODESTAR_PRESET` must not be set to properly test setting preset + if (process.env.LODESTAR_PRESET) delete process.env.LODESTAR_PRESET; await exec(`node --loader ts-node/esm ${path.join(__dirname, scriptNames.ok)}`); }); diff --git a/packages/prover/test/e2e/web3_batch_request.test.ts b/packages/prover/test/e2e/web3_batch_request.test.ts index afb995d088a0..89ac4a711b31 100644 --- a/packages/prover/test/e2e/web3_batch_request.test.ts +++ b/packages/prover/test/e2e/web3_batch_request.test.ts @@ -3,14 +3,16 @@ import {describe, it, expect, beforeAll} from "vitest"; import Web3 from "web3"; import {LCTransport} from "../../src/interfaces.js"; import {createVerifiedExecutionProvider} from "../../src/web3_provider.js"; -import {rpcUrl, beaconUrl, config} from "../utils/e2e_env.js"; +import {rpcUrl, beaconUrl, config, waitForCapellaFork} from "../utils/e2e_env.js"; import {getVerificationFailedMessage} from "../../src/utils/json_rpc.js"; /* prettier-ignore */ describe("web3_batch_requests", function () { let web3: Web3; - beforeAll(() => { + beforeAll(async () => { + await waitForCapellaFork(); + const {provider} = createVerifiedExecutionProvider(new Web3.providers.HttpProvider(rpcUrl), { transport: LCTransport.Rest, urls: [beaconUrl], diff --git a/packages/types/package.json b/packages/types/package.json index b10063cb34d5..d84ebb33472d 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -64,7 +64,7 @@ "test": "yarn test:unit", "test:constants:minimal": "LODESTAR_PRESET=minimal vitest --run --dir test/constants/", "test:constants:mainnet": "LODESTAR_PRESET=mainnet vitest --run --dir test/constants/", - "test:unit": "wrapper() { yarn test:constants:minimal $@ && yarn test:constants:mainnet $@ && vitest --run --dir test/unit/ $@; }; wrapper", + "test:unit": "wrapper() { yarn test:constants:minimal $@ && yarn test:constants:mainnet $@ && LODESTAR_PRESET=mainnet vitest --run --dir test/unit/ $@; }; wrapper", "test:browsers": "yarn test:browsers:chrome && yarn test:browsers:firefox && yarn test:browsers:electron", "test:browsers:chrome": "vitest --run --browser chrome --config ./vitest.browser.config.ts --dir test/unit", "test:browsers:firefox": "vitest --run --browser firefox --config ./vitest.browser.config.ts --dir test/unit", diff --git a/packages/validator/package.json b/packages/validator/package.json index 201591c2c272..e7877ae458a0 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -30,7 +30,7 @@ "test:unit": "vitest --run --dir test/unit/", "test": "yarn test:unit && yarn test:e2e", "test:spec": "vitest --run --config vitest.spec.config.ts --dir test/spec/", - "test:e2e": "LODESTAR_PRESET=mainnet vitest --run --config vitest.e2e.config.ts --dir test/e2e", + "test:e2e": "vitest --run --config vitest.e2e.config.ts --dir test/e2e", "download-spec-tests": "node --loader=ts-node/esm test/spec/downloadTests.ts", "check-readme": "typescript-docs-verifier" }, diff --git a/scripts/run_e2e_env.sh b/scripts/run_e2e_env.sh index e22b44ae6c00..e81eb501f407 100755 --- a/scripts/run_e2e_env.sh +++ b/scripts/run_e2e_env.sh @@ -1,18 +1,19 @@ #!/bin/bash +DIR="$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + function start_app() { mkdir -p test-logs/e2e-test-env export LODESTAR_PRESET=minimal - nohup node --loader ts-node/esm packages/cli/test/scripts/e2e_test_env.ts > test-logs/e2e-test-env/simulation.out 2>&1 & + export DOTENV_CONFIG_PATH="$DIR/../.env.test" + nohup node -r dotenv/config --loader ts-node/esm packages/cli/test/scripts/e2e_test_env.ts > test-logs/e2e-test-env/simulation.out 2>&1 & echo $! > test-logs/e2e-test-env/simulation.pid echo "Wait for the node to be ready" npx wait-port -t 120000 0.0.0.0:5001 } function stop_app() { - kill -9 $(cat test-logs/e2e-test-env/simulation.pid) - # Incase the process pid file is not present - kill -9 $(lsof -t -i:5001) + kill -s TERM $(cat test-logs/e2e-test-env/simulation.pid) } diff --git a/scripts/vitest/customMatchers.ts b/scripts/vitest/setupFiles/customMatchers.ts similarity index 100% rename from scripts/vitest/customMatchers.ts rename to scripts/vitest/setupFiles/customMatchers.ts diff --git a/scripts/vitest/setupFiles/dotenv.ts b/scripts/vitest/setupFiles/dotenv.ts new file mode 100644 index 000000000000..71364c7426bc --- /dev/null +++ b/scripts/vitest/setupFiles/dotenv.ts @@ -0,0 +1,8 @@ +import path from "node:path"; +// It's a dev dependency +// eslint-disable-next-line import/no-extraneous-dependencies +import {config} from "dotenv"; +// eslint-disable-next-line @typescript-eslint/naming-convention +const __dirname = new URL(".", import.meta.url).pathname; + +config({path: path.join(__dirname, "../../../.env.test")}); diff --git a/vitest.base.browser.config.ts b/vitest.base.browser.config.ts index 5559e0f77b9c..a07f4d842b06 100644 --- a/vitest.base.browser.config.ts +++ b/vitest.base.browser.config.ts @@ -24,7 +24,7 @@ export default defineConfig({ "**/.{idea,git,cache,output,temp}/**", "**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*", ], - setupFiles: [path.join(__dirname, "./scripts/vitest/customMatchers.ts")], + setupFiles: [path.join(__dirname, "./scripts/vitest/setupFiles/customMatchers.ts")], reporters: ["default", "hanging-process"], coverage: { enabled: false, diff --git a/vitest.base.unit.config.ts b/vitest.base.unit.config.ts index b087466fec12..293b29214239 100644 --- a/vitest.base.unit.config.ts +++ b/vitest.base.unit.config.ts @@ -14,7 +14,10 @@ export default defineConfig({ "**/.{idea,git,cache,output,temp}/**", "**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build}.config.*", ], - setupFiles: [path.join(__dirname, "./scripts/vitest/customMatchers.ts")], + setupFiles: [ + path.join(__dirname, "./scripts/vitest/setupFiles/customMatchers.ts"), + path.join(__dirname, "./scripts/vitest/setupFiles/dotenv.ts"), + ], reporters: ["default", "hanging-process"], coverage: { enabled: process.env.CI === "true", diff --git a/yarn.lock b/yarn.lock index d6a1f10b071a..c4f6bd206eca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,6 +22,14 @@ semver "^6.1.0" uuid "^3.3.3" +"@actions/core@^1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.1.tgz#61108e7ac40acae95ee36da074fa5850ca4ced8a" + integrity sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g== + dependencies: + "@actions/http-client" "^2.0.1" + uuid "^8.3.2" + "@actions/core@^1.2.6": version "1.10.0" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.0.tgz#44551c3c71163949a2f06e94d9ca2157a0cfac4f" @@ -5600,6 +5608,11 @@ dotenv-expand@~10.0.0: resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== +dotenv@^16.4.1: + version "16.4.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.1.tgz#1d9931f1d3e5d2959350d1250efab299561f7f11" + integrity sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ== + dotenv@~16.3.1: version "16.3.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" From ae61683146ee8f935942ea91343aea92dc8e09b2 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Tue, 13 Feb 2024 17:19:24 +0100 Subject: [PATCH 43/71] chore: upgrade eslint and fix the warnings (#6420) * Update eslint packages * Fix elsint warnings * Update the code comment * Fix the build issue * Sort the eslint rules * Update name for an import * Update the import --- .eslintrc.js | 5 + package.json | 12 +- packages/api/src/utils/client/format.ts | 4 +- .../api/test/unit/client/httpClient.test.ts | 2 +- packages/api/test/utils/utils.ts | 2 +- packages/beacon-node/src/api/rest/base.ts | 8 +- packages/beacon-node/src/chain/emitter.ts | 2 +- .../src/eth1/provider/jsonRpcHttpClient.ts | 2 +- packages/beacon-node/src/eth1/provider/jwt.ts | 1 + packages/beacon-node/src/monitoring/system.ts | 4 + .../network/core/networkCoreWorkerHandler.ts | 6 +- .../beacon-node/src/network/discv5/index.ts | 2 +- packages/beacon-node/src/sync/range/range.ts | 2 +- packages/beacon-node/src/util/blobs.ts | 4 +- packages/beacon-node/src/util/clock.ts | 2 +- .../e2e/network/onWorker/workerEchoHandler.ts | 4 +- .../test/unit/monitoring/remoteService.ts | 2 +- packages/beacon-node/test/utils/db.ts | 4 +- .../utils/simulation/ExternalSignerServer.ts | 2 +- .../utils/simulation/SimulationTracker.ts | 4 +- packages/light-client/test/utils/server.ts | 8 +- packages/logger/src/node.ts | 2 + packages/logger/src/utils/format.ts | 6 +- packages/logger/src/winston.ts | 6 +- .../test/e2e/logger/workerLoggerHandler.ts | 4 +- .../prover/test/e2e/cli/cmds/start.test.ts | 2 +- .../test/e2e/web3_batch_request.test.ts | 2 +- .../prover/test/e2e/web3_provider.test.ts | 2 +- .../prover/test/unit/utils/assertion.test.ts | 2 +- .../verified_requests/eth_getBalance.test.ts | 6 +- .../eth_getBlockByHash.test.ts | 6 +- .../eth_getBlockByNumber.test.ts | 6 +- .../test/unit/web3_provider.node.test.ts | 2 +- packages/spec-test-util/src/downloadTests.ts | 4 +- packages/test-utils/src/externalSigner.ts | 4 +- packages/utils/src/promise.ts | 2 + packages/validator/src/services/emitter.ts | 2 +- yarn.lock | 520 +++++++----------- 38 files changed, 278 insertions(+), 382 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 8eeda9a0446f..c4f0d45fc42d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -64,6 +64,10 @@ module.exports = { }, //ignore rules on destructured params {selector: "variable", modifiers: ["destructured"], format: null}, + { + selector: "import", + format: ["camelCase", "PascalCase"], + }, ], "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-floating-promises": "error", @@ -94,6 +98,7 @@ module.exports = { "func-call-spacing": "off", // Force to add names to all functions to ease CPU profiling "func-names": ["error", "always"], + "import/namespace": "off", //if --fix is run it messes imports like /lib/presets/minimal & /lib/presets/mainnet "import/no-duplicates": "off", "import/no-extraneous-dependencies": [ diff --git a/package.json b/package.json index faf313bf775d..6dd34d2e9399 100644 --- a/package.json +++ b/package.json @@ -50,18 +50,18 @@ "@dapplion/benchmark": "^0.2.4", "@types/mocha": "^10.0.6", "@types/node": "^20.6.5", - "@typescript-eslint/eslint-plugin": "6.7.2", - "@typescript-eslint/parser": "6.7.2", + "@typescript-eslint/eslint-plugin": "6.21.0", + "@typescript-eslint/parser": "6.21.0", "@vitest/coverage-v8": "^1.2.1", "@vitest/browser": "^1.2.1", "crypto-browserify": "^3.12.0", "dotenv": "^16.4.1", "electron": "^26.2.2", - "eslint": "^8.50.0", + "eslint": "^8.56.0", "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-prettier": "^5.0.0", - "eslint-plugin-vitest": "^0.3.20", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-vitest": "^0.3.22", "https-browserify": "^1.0.0", "jsdom": "^23.0.1", "lerna": "^7.3.0", diff --git a/packages/api/src/utils/client/format.ts b/packages/api/src/utils/client/format.ts index 7f12631f6877..141be4139eb0 100644 --- a/packages/api/src/utils/client/format.ts +++ b/packages/api/src/utils/client/format.ts @@ -1,11 +1,11 @@ -import qs from "qs"; +import {stringify as queryStringStringify} from "qs"; /** * Ethereum Beacon API requires the query with format: * - arrayFormat: repeat `topic=topic1&topic=topic2` */ export function stringifyQuery(query: unknown): string { - return qs.stringify(query, {arrayFormat: "repeat"}); + return queryStringStringify(query, {arrayFormat: "repeat"}); } /** diff --git a/packages/api/test/unit/client/httpClient.test.ts b/packages/api/test/unit/client/httpClient.test.ts index b22727d6a22b..c82b879bdcf5 100644 --- a/packages/api/test/unit/client/httpClient.test.ts +++ b/packages/api/test/unit/client/httpClient.test.ts @@ -1,6 +1,6 @@ import {IncomingMessage} from "node:http"; import {describe, it, afterEach, expect} from "vitest"; -import fastify, {RouteOptions} from "fastify"; +import {RouteOptions, fastify} from "fastify"; import {ErrorAborted, TimeoutError, toBase64} from "@lodestar/utils"; import {HttpClient, HttpError} from "../../../src/utils/client/index.js"; import {HttpStatusCode} from "../../../src/utils/client/httpStatusCode.js"; diff --git a/packages/api/test/utils/utils.ts b/packages/api/test/utils/utils.ts index b19899016117..ced8cd5b7639 100644 --- a/packages/api/test/utils/utils.ts +++ b/packages/api/test/utils/utils.ts @@ -1,6 +1,6 @@ import {MockedObject, vi} from "vitest"; import qs from "qs"; -import fastify, {FastifyInstance} from "fastify"; +import {FastifyInstance, fastify} from "fastify"; import {mapValues} from "@lodestar/utils"; import {ServerApi} from "../../src/interfaces.js"; diff --git a/packages/beacon-node/src/api/rest/base.ts b/packages/beacon-node/src/api/rest/base.ts index 3ddb5354a897..f14937a49fa4 100644 --- a/packages/beacon-node/src/api/rest/base.ts +++ b/packages/beacon-node/src/api/rest/base.ts @@ -1,6 +1,6 @@ -import qs from "qs"; -import fastify, {FastifyInstance} from "fastify"; -import fastifyCors from "@fastify/cors"; +import {parse as parseQueryString} from "qs"; +import {FastifyInstance, fastify} from "fastify"; +import {fastifyCors} from "@fastify/cors"; import bearerAuthPlugin from "@fastify/bearer-auth"; import {RouteConfig} from "@lodestar/api/beacon/server"; import {ErrorAborted, Gauge, Histogram, Logger} from "@lodestar/utils"; @@ -48,7 +48,7 @@ export class RestApiServer { logger: false, ajv: {customOptions: {coerceTypes: "array"}}, querystringParser: (str) => - qs.parse(str, { + parseQueryString(str, { // Array as comma-separated values must be supported to be OpenAPI spec compliant comma: true, // Drop support for array query strings like `id[0]=1&id[1]=2&id[2]=3` as those are not required to diff --git a/packages/beacon-node/src/chain/emitter.ts b/packages/beacon-node/src/chain/emitter.ts index 8c02064b4a92..9c3ea4a9bf52 100644 --- a/packages/beacon-node/src/chain/emitter.ts +++ b/packages/beacon-node/src/chain/emitter.ts @@ -1,5 +1,5 @@ import {EventEmitter} from "events"; -import StrictEventEmitter from "strict-event-emitter-types"; +import {StrictEventEmitter} from "strict-event-emitter-types"; import {routes} from "@lodestar/api"; import {phase0} from "@lodestar/types"; diff --git a/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts b/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts index faa4e310e10a..17809e047944 100644 --- a/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts +++ b/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts @@ -1,5 +1,5 @@ import {EventEmitter} from "events"; -import StrictEventEmitter from "strict-event-emitter-types"; +import {StrictEventEmitter} from "strict-event-emitter-types"; import {fetch} from "@lodestar/api"; import {ErrorAborted, Gauge, Histogram, TimeoutError, isValidHttpUrl, retry} from "@lodestar/utils"; import {IJson, RpcPayload} from "../interface.js"; diff --git a/packages/beacon-node/src/eth1/provider/jwt.ts b/packages/beacon-node/src/eth1/provider/jwt.ts index 1e267120957f..da1fc1827cdd 100644 --- a/packages/beacon-node/src/eth1/provider/jwt.ts +++ b/packages/beacon-node/src/eth1/provider/jwt.ts @@ -2,6 +2,7 @@ import type {TAlgorithm} from "jwt-simple"; // TODO: fix jwt-simple types import jwt from "jwt-simple"; +// eslint-disable-next-line import/no-named-as-default-member const {encode, decode} = jwt; /** diff --git a/packages/beacon-node/src/monitoring/system.ts b/packages/beacon-node/src/monitoring/system.ts index ee85e9ae5088..a1a79b1bd277 100644 --- a/packages/beacon-node/src/monitoring/system.ts +++ b/packages/beacon-node/src/monitoring/system.ts @@ -1,5 +1,9 @@ +// We want to keep `system` export to be used as namespace +/* eslint-disable import/no-named-as-default-member */ import os from "node:os"; import path from "node:path"; +// We want to keep `system` export as it's more readable and easier to understand +// eslint-disable-next-line import/no-named-as-default import system from "systeminformation"; import {Logger} from "@lodestar/utils"; diff --git a/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts b/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts index 8370d3687635..2b6c85afa1f8 100644 --- a/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts +++ b/packages/beacon-node/src/network/core/networkCoreWorkerHandler.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import worker_threads from "node:worker_threads"; +import workerThreads from "node:worker_threads"; import {PeerScoreStatsDump} from "@chainsafe/libp2p-gossipsub/dist/src/score/peer-score.js"; import {PublishOpts} from "@chainsafe/libp2p-gossipsub/types"; import {ModuleThread, Thread, Worker, spawn} from "@chainsafe/threads"; @@ -78,14 +78,14 @@ export class WorkerNetworkCore implements INetworkCore { wireEventsOnMainThread( NetworkWorkerThreadEventType.networkEvent, modules.events, - modules.worker as unknown as worker_threads.Worker, + modules.worker as unknown as workerThreads.Worker, modules.metrics, networkEventDirection ); wireEventsOnMainThread( NetworkWorkerThreadEventType.reqRespBridgeEvents, this.reqRespBridgeEventBus, - modules.worker as unknown as worker_threads.Worker, + modules.worker as unknown as workerThreads.Worker, modules.metrics, reqRespBridgeEventDirection ); diff --git a/packages/beacon-node/src/network/discv5/index.ts b/packages/beacon-node/src/network/discv5/index.ts index 5a06545b98af..97d07ed774d5 100644 --- a/packages/beacon-node/src/network/discv5/index.ts +++ b/packages/beacon-node/src/network/discv5/index.ts @@ -1,6 +1,6 @@ import EventEmitter from "events"; import {PeerId} from "@libp2p/interface"; -import StrictEventEmitter from "strict-event-emitter-types"; +import {StrictEventEmitter} from "strict-event-emitter-types"; import {exportToProtobuf} from "@libp2p/peer-id-factory"; import {createPrivateKeyFromPeerId, ENR, ENRData, SignableENR} from "@chainsafe/enr"; import {spawn, Thread, Worker} from "@chainsafe/threads"; diff --git a/packages/beacon-node/src/sync/range/range.ts b/packages/beacon-node/src/sync/range/range.ts index 7739b6950ecb..d20e0c3690cd 100644 --- a/packages/beacon-node/src/sync/range/range.ts +++ b/packages/beacon-node/src/sync/range/range.ts @@ -1,5 +1,5 @@ import {EventEmitter} from "events"; -import StrictEventEmitter from "strict-event-emitter-types"; +import {StrictEventEmitter} from "strict-event-emitter-types"; import {computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {BeaconConfig} from "@lodestar/config"; import {Epoch, phase0} from "@lodestar/types"; diff --git a/packages/beacon-node/src/util/blobs.ts b/packages/beacon-node/src/util/blobs.ts index bbad27f684ed..13d935ba29da 100644 --- a/packages/beacon-node/src/util/blobs.ts +++ b/packages/beacon-node/src/util/blobs.ts @@ -1,4 +1,4 @@ -import SHA256 from "@chainsafe/as-sha256"; +import {digest as sha256Digest} from "@chainsafe/as-sha256"; import {Tree} from "@chainsafe/persistent-merkle-tree"; import {VERSIONED_HASH_VERSION_KZG, KZG_COMMITMENT_GINDEX0, ForkName} from "@lodestar/params"; import {deneb, ssz, allForks} from "@lodestar/types"; @@ -8,7 +8,7 @@ import {signedBlockToSignedHeader} from "@lodestar/state-transition"; type VersionHash = Uint8Array; export function kzgCommitmentToVersionedHash(kzgCommitment: deneb.KZGCommitment): VersionHash { - const hash = SHA256.digest(kzgCommitment); + const hash = sha256Digest(kzgCommitment); // Equivalent to `VERSIONED_HASH_VERSION_KZG + hash(kzg_commitment)[1:]` hash[0] = VERSIONED_HASH_VERSION_KZG; return hash; diff --git a/packages/beacon-node/src/util/clock.ts b/packages/beacon-node/src/util/clock.ts index 0be3b706a5ec..197d17f38281 100644 --- a/packages/beacon-node/src/util/clock.ts +++ b/packages/beacon-node/src/util/clock.ts @@ -1,5 +1,5 @@ import EventEmitter from "node:events"; -import type StrictEventEmitter from "strict-event-emitter-types"; +import type {StrictEventEmitter} from "strict-event-emitter-types"; import type {Epoch, Slot} from "@lodestar/types"; import {ChainForkConfig} from "@lodestar/config"; import {ErrorAborted} from "@lodestar/utils"; diff --git a/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts b/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts index 0b84ace618f1..cfd1629065a8 100644 --- a/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts +++ b/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts @@ -1,4 +1,4 @@ -import worker_threads from "node:worker_threads"; +import workerThreads from "node:worker_threads"; import {spawn, Worker} from "@chainsafe/threads"; export type EchoWorker = { @@ -8,7 +8,7 @@ export type EchoWorker = { export async function getEchoWorker(): Promise { const workerThreadjs = new Worker("./workerEcho.js"); - const worker = workerThreadjs as unknown as worker_threads.Worker; + const worker = workerThreadjs as unknown as workerThreads.Worker; // eslint-disable-next-line @typescript-eslint/no-explicit-any await spawn(workerThreadjs, { diff --git a/packages/beacon-node/test/unit/monitoring/remoteService.ts b/packages/beacon-node/test/unit/monitoring/remoteService.ts index 20afd99396b7..c5ce0e9ef0b3 100644 --- a/packages/beacon-node/test/unit/monitoring/remoteService.ts +++ b/packages/beacon-node/test/unit/monitoring/remoteService.ts @@ -1,4 +1,4 @@ -import fastify from "fastify"; +import {fastify} from "fastify"; import {afterAll, expect} from "vitest"; import {RemoteServiceError} from "../../../src/monitoring/service.js"; import {ProcessType} from "../../../src/monitoring/types.js"; diff --git a/packages/beacon-node/test/utils/db.ts b/packages/beacon-node/test/utils/db.ts index afb276b88c60..c44aa7f878dc 100644 --- a/packages/beacon-node/test/utils/db.ts +++ b/packages/beacon-node/test/utils/db.ts @@ -1,4 +1,4 @@ -import child_process from "node:child_process"; +import childProcess from "node:child_process"; import {FilterOptions, LevelDbController} from "@lodestar/db"; import {ChainForkConfig} from "@lodestar/config"; import {BeaconDb} from "../../src/index.js"; @@ -8,7 +8,7 @@ export const TEMP_DB_LOCATION = ".tmpdb"; export async function startTmpBeaconDb(config: ChainForkConfig): Promise { // Clean-up db first - child_process.execSync(`rm -rf ${TEMP_DB_LOCATION}`); + childProcess.execSync(`rm -rf ${TEMP_DB_LOCATION}`); return new BeaconDb(config, await LevelDbController.create({name: TEMP_DB_LOCATION}, {logger: testLogger()})); } diff --git a/packages/cli/test/utils/simulation/ExternalSignerServer.ts b/packages/cli/test/utils/simulation/ExternalSignerServer.ts index f6d258ddfa00..1a23c259023e 100644 --- a/packages/cli/test/utils/simulation/ExternalSignerServer.ts +++ b/packages/cli/test/utils/simulation/ExternalSignerServer.ts @@ -1,4 +1,4 @@ -import fastify from "fastify"; +import {fastify} from "fastify"; import {fromHexString} from "@chainsafe/ssz"; import type {SecretKey} from "@chainsafe/bls/types"; import {EXTERNAL_SIGNER_BASE_PORT} from "./constants.js"; diff --git a/packages/cli/test/utils/simulation/SimulationTracker.ts b/packages/cli/test/utils/simulation/SimulationTracker.ts index aa38a5c6dcec..f2159490c109 100644 --- a/packages/cli/test/utils/simulation/SimulationTracker.ts +++ b/packages/cli/test/utils/simulation/SimulationTracker.ts @@ -1,5 +1,5 @@ import EventEmitter from "node:events"; -import Debug from "debug"; +import createDebug from "debug"; import {routes} from "@lodestar/api/beacon"; import {ChainForkConfig} from "@lodestar/config"; import {Epoch, Slot} from "@lodestar/types"; @@ -20,7 +20,7 @@ import {defaultAssertions} from "./assertions/defaults/index.js"; import {TableReporter} from "./TableReporter.js"; import {fetchBlock} from "./utils/network.js"; -const debug = Debug("lodestar:sim:tracker"); +const debug = createDebug("lodestar:sim:tracker"); interface SimulationTrackerInitOptions { nodes: NodePair[]; diff --git a/packages/light-client/test/utils/server.ts b/packages/light-client/test/utils/server.ts index 3effdd06e658..2bbc7350b22a 100644 --- a/packages/light-client/test/utils/server.ts +++ b/packages/light-client/test/utils/server.ts @@ -1,6 +1,6 @@ -import qs from "qs"; -import fastify, {FastifyInstance} from "fastify"; -import fastifyCors from "@fastify/cors"; +import {parse as queryStringParse} from "qs"; +import {FastifyInstance, fastify} from "fastify"; +import {fastifyCors} from "@fastify/cors"; import {Api, ServerApi} from "@lodestar/api"; import {registerRoutes} from "@lodestar/api/beacon/server"; import {ChainForkConfig} from "@lodestar/config"; @@ -18,7 +18,7 @@ export async function startServer( const server = fastify({ logger: false, ajv: {customOptions: {coerceTypes: "array"}}, - querystringParser: (str) => qs.parse(str, {comma: true, parseArrays: false}), + querystringParser: (str) => queryStringParse(str, {comma: true, parseArrays: false}), }); registerRoutes(server, config, api, ["lightclient", "proof", "events"]); diff --git a/packages/logger/src/node.ts b/packages/logger/src/node.ts index ec2d57b85bbb..2740b37e3ca9 100644 --- a/packages/logger/src/node.ts +++ b/packages/logger/src/node.ts @@ -1,6 +1,8 @@ import path from "node:path"; import DailyRotateFile from "winston-daily-rotate-file"; import TransportStream from "winston-transport"; +// We want to keep `winston` export as it's more readable and easier to understand +// eslint-disable-next-line import/no-named-as-default-member import winston from "winston"; import type {Logger as Winston} from "winston"; import {Logger, LogLevel, TimestampFormat} from "./interface.js"; diff --git a/packages/logger/src/utils/format.ts b/packages/logger/src/utils/format.ts index 2340876a371e..edb2035c1957 100644 --- a/packages/logger/src/utils/format.ts +++ b/packages/logger/src/utils/format.ts @@ -1,11 +1,11 @@ -import winston from "winston"; +// We want to keep `winston` export as it's more readable and easier to understand +// eslint-disable-next-line import/no-named-as-default-member +import winston, {format} from "winston"; import {LodestarError, isEmptyObject} from "@lodestar/utils"; import {LoggerOptions, TimestampFormatCode} from "../interface.js"; import {logCtxToJson, logCtxToString, LogData} from "./json.js"; import {formatEpochSlotTime} from "./timeFormat.js"; -const {format} = winston; - type Format = ReturnType; // TODO: Find a more typesafe way of enforce this properties diff --git a/packages/logger/src/winston.ts b/packages/logger/src/winston.ts index db27970489ea..460706b1d081 100644 --- a/packages/logger/src/winston.ts +++ b/packages/logger/src/winston.ts @@ -1,4 +1,6 @@ -import winston from "winston"; +// We want to keep `winston` export as it's more readable and easier to understand +// eslint-disable-next-line import/no-named-as-default-member +import winston, {createLogger as winstonCreateLogger} from "winston"; import type {Logger as Winston} from "winston"; import {Logger, LoggerOptions, LogLevel, logLevelNum} from "./interface.js"; import {getFormat} from "./utils/format.js"; @@ -46,7 +48,7 @@ export class WinstonLogger implements Logger { static createWinstonInstance(options: Partial = {}, transports?: winston.transport[]): Winston { const defaultMeta: DefaultMeta = {module: options?.module || ""}; - return winston.createLogger({ + return winstonCreateLogger({ // Do not set level at the logger level. Always control by Transport, unless for testLogger level: options.level, defaultMeta, diff --git a/packages/logger/test/e2e/logger/workerLoggerHandler.ts b/packages/logger/test/e2e/logger/workerLoggerHandler.ts index b166ef15ff00..6d541a188796 100644 --- a/packages/logger/test/e2e/logger/workerLoggerHandler.ts +++ b/packages/logger/test/e2e/logger/workerLoggerHandler.ts @@ -1,4 +1,4 @@ -import worker_threads from "node:worker_threads"; +import workerThreads from "node:worker_threads"; import {spawn, Worker} from "@chainsafe/threads"; export type LoggerWorker = { @@ -12,7 +12,7 @@ export async function getLoggerWorker(opts: WorkerData): Promise { const workerThreadjs = new Worker("./workerLogger.js", { workerData: opts, }); - const worker = workerThreadjs as unknown as worker_threads.Worker; + const worker = workerThreadjs as unknown as workerThreads.Worker; // eslint-disable-next-line @typescript-eslint/no-explicit-any await spawn(workerThreadjs, { diff --git a/packages/prover/test/e2e/cli/cmds/start.test.ts b/packages/prover/test/e2e/cli/cmds/start.test.ts index 8888b3ce84d5..97790ce98c6e 100644 --- a/packages/prover/test/e2e/cli/cmds/start.test.ts +++ b/packages/prover/test/e2e/cli/cmds/start.test.ts @@ -2,7 +2,7 @@ import childProcess from "node:child_process"; import {writeFile, mkdir} from "node:fs/promises"; import path from "node:path"; import {describe, it, expect, beforeAll, afterAll} from "vitest"; -import Web3 from "web3"; +import {Web3} from "web3"; import {runCliCommand, spawnCliCommand, stopChildProcess} from "@lodestar/test-utils"; import {sleep} from "@lodestar/utils"; import {ChainConfig, chainConfigToJson} from "@lodestar/config"; diff --git a/packages/prover/test/e2e/web3_batch_request.test.ts b/packages/prover/test/e2e/web3_batch_request.test.ts index 89ac4a711b31..7792b796a3a9 100644 --- a/packages/prover/test/e2e/web3_batch_request.test.ts +++ b/packages/prover/test/e2e/web3_batch_request.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import {describe, it, expect, beforeAll} from "vitest"; -import Web3 from "web3"; +import {Web3} from "web3"; import {LCTransport} from "../../src/interfaces.js"; import {createVerifiedExecutionProvider} from "../../src/web3_provider.js"; import {rpcUrl, beaconUrl, config, waitForCapellaFork} from "../utils/e2e_env.js"; diff --git a/packages/prover/test/e2e/web3_provider.test.ts b/packages/prover/test/e2e/web3_provider.test.ts index 4de51dc94051..db5aba0faa7a 100644 --- a/packages/prover/test/e2e/web3_provider.test.ts +++ b/packages/prover/test/e2e/web3_provider.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ import {describe, it, expect, beforeAll} from "vitest"; -import Web3 from "web3"; +import {Web3} from "web3"; import {ethers} from "ethers"; import {LCTransport} from "../../src/interfaces.js"; import {createVerifiedExecutionProvider} from "../../src/web3_provider.js"; diff --git a/packages/prover/test/unit/utils/assertion.test.ts b/packages/prover/test/unit/utils/assertion.test.ts index 5cf481bacdf1..3ea712bab1f1 100644 --- a/packages/prover/test/unit/utils/assertion.test.ts +++ b/packages/prover/test/unit/utils/assertion.test.ts @@ -1,6 +1,6 @@ import {describe, it, expect} from "vitest"; import {ethers} from "ethers"; -import Web3 from "web3"; +import {Web3} from "web3"; import {isSendProvider, isWeb3jsProvider, isEthersProvider} from "../../../src/utils/assertion.js"; describe("utils/assertion", () => { diff --git a/packages/prover/test/unit/verified_requests/eth_getBalance.test.ts b/packages/prover/test/unit/verified_requests/eth_getBalance.test.ts index ea0c902750c8..4032f4c25f19 100644 --- a/packages/prover/test/unit/verified_requests/eth_getBalance.test.ts +++ b/packages/prover/test/unit/verified_requests/eth_getBalance.test.ts @@ -3,12 +3,12 @@ import {createForkConfig} from "@lodestar/config"; import {NetworkName, networksChainConfig} from "@lodestar/config/networks"; import {VERIFICATION_FAILED_RESPONSE_CODE} from "../../../src/constants.js"; import {eth_getBalance} from "../../../src/verified_requests/eth_getBalance.js"; -import eth_getBalance_eoa from "../../fixtures/sepolia/eth_getBalance_eoa.json" assert {type: "json"}; -import eth_getBalance_contract from "../../fixtures/sepolia/eth_getBalance_contract.json" assert {type: "json"}; +import ethGetBalanceEoa from "../../fixtures/sepolia/eth_getBalance_eoa.json" assert {type: "json"}; +import ethGetBalanceContract from "../../fixtures/sepolia/eth_getBalance_contract.json" assert {type: "json"}; import {cloneTestFixture, generateReqHandlerOptionsMock} from "../../mocks/request_handler.js"; import {getVerificationFailedMessage} from "../../../src/utils/json_rpc.js"; -const testCases = [eth_getBalance_eoa, eth_getBalance_contract]; +const testCases = [ethGetBalanceEoa, ethGetBalanceContract]; describe("verified_requests / eth_getBalance", () => { for (const testCase of testCases) { diff --git a/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts b/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts index 8052b290ff0d..fca484657c01 100644 --- a/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts +++ b/packages/prover/test/unit/verified_requests/eth_getBlockByHash.test.ts @@ -3,13 +3,13 @@ import {createForkConfig} from "@lodestar/config"; import {NetworkName, networksChainConfig} from "@lodestar/config/networks"; import {VERIFICATION_FAILED_RESPONSE_CODE} from "../../../src/constants.js"; import {eth_getBlockByHash} from "../../../src/verified_requests/eth_getBlockByHash.js"; -import eth_getBlock_with_contractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert {type: "json"}; -import eth_getBlock_with_no_accessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert {type: "json"}; +import ethGetBlockWithContractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert {type: "json"}; +import ethGetBlockWithNoAccessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert {type: "json"}; import {TestFixture, cloneTestFixture, generateReqHandlerOptionsMock} from "../../mocks/request_handler.js"; import {ELBlock} from "../../../src/types.js"; import {getVerificationFailedMessage} from "../../../src/utils/json_rpc.js"; -const testCases = [eth_getBlock_with_no_accessList, eth_getBlock_with_contractCreation] as [ +const testCases = [ethGetBlockWithNoAccessList, ethGetBlockWithContractCreation] as [ TestFixture, TestFixture, ]; diff --git a/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts b/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts index fa60be225d20..81f644a46024 100644 --- a/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts +++ b/packages/prover/test/unit/verified_requests/eth_getBlockByNumber.test.ts @@ -4,12 +4,12 @@ import {NetworkName, networksChainConfig} from "@lodestar/config/networks"; import {VERIFICATION_FAILED_RESPONSE_CODE} from "../../../src/constants.js"; import {ELBlock} from "../../../src/types.js"; import {eth_getBlockByNumber} from "../../../src/verified_requests/eth_getBlockByNumber.js"; -import eth_getBlock_with_contractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert {type: "json"}; -import eth_getBlock_with_no_accessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert {type: "json"}; +import ethGetBlockWithContractCreation from "../../fixtures/sepolia/eth_getBlock_with_contractCreation.json" assert {type: "json"}; +import ethGetBlockWithNoAccessList from "../../fixtures/sepolia/eth_getBlock_with_no_accessList.json" assert {type: "json"}; import {TestFixture, cloneTestFixture, generateReqHandlerOptionsMock} from "../../mocks/request_handler.js"; import {getVerificationFailedMessage} from "../../../src/utils/json_rpc.js"; -const testCases = [eth_getBlock_with_no_accessList, eth_getBlock_with_contractCreation] as [ +const testCases = [ethGetBlockWithNoAccessList, ethGetBlockWithContractCreation] as [ TestFixture, TestFixture, ]; diff --git a/packages/prover/test/unit/web3_provider.node.test.ts b/packages/prover/test/unit/web3_provider.node.test.ts index eed6c336483f..a83fbde4d858 100644 --- a/packages/prover/test/unit/web3_provider.node.test.ts +++ b/packages/prover/test/unit/web3_provider.node.test.ts @@ -1,5 +1,5 @@ import {describe, it, expect, afterEach, vi} from "vitest"; -import Web3 from "web3"; +import {Web3} from "web3"; import {ethers} from "ethers"; import {createVerifiedExecutionProvider, ProofProvider, LCTransport} from "@lodestar/prover/browser"; import {ELRpc} from "../../src/utils/rpc.js"; diff --git a/packages/spec-test-util/src/downloadTests.ts b/packages/spec-test-util/src/downloadTests.ts index d3da52c0306b..2fc61b99e5b8 100644 --- a/packages/spec-test-util/src/downloadTests.ts +++ b/packages/spec-test-util/src/downloadTests.ts @@ -5,7 +5,7 @@ import stream from "node:stream"; import {promisify} from "node:util"; import {rimraf} from "rimraf"; import axios from "axios"; -import tar from "tar"; +import {x as extractTar} from "tar"; import retry from "async-retry"; export const defaultSpecTestsRepoUrl = "https://github.com/ethereum/consensus-spec-tests"; @@ -81,7 +81,7 @@ export async function downloadGenericSpecTests( log(`Downloading ${url} - ${totalSize} bytes`); // extract tar into output directory - await promisify(stream.pipeline)(data, tar.x({cwd: outputDir})); + await promisify(stream.pipeline)(data, extractTar({cwd: outputDir})); log(`Downloaded ${url}`); }, diff --git a/packages/test-utils/src/externalSigner.ts b/packages/test-utils/src/externalSigner.ts index 20cf59cc26d0..96de139613b6 100644 --- a/packages/test-utils/src/externalSigner.ts +++ b/packages/test-utils/src/externalSigner.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import path from "node:path"; -import tmp from "tmp"; +import {dirSync as tmpDirSync} from "tmp"; import {GenericContainer, Wait, StartedTestContainer} from "testcontainers"; import {ForkSeq} from "@lodestar/params"; @@ -23,7 +23,7 @@ export async function startExternalSigner({ password: string; }): Promise { // path to store configuration - const tmpDir = tmp.dirSync({ + const tmpDir = tmpDirSync({ unsafeCleanup: true, // In Github runner NodeJS process probably runs as root, so web3signer doesn't have permissions to read config dir mode: 755, diff --git a/packages/utils/src/promise.ts b/packages/utils/src/promise.ts index ba63854e9e85..9a8574a57854 100644 --- a/packages/utils/src/promise.ts +++ b/packages/utils/src/promise.ts @@ -113,6 +113,8 @@ export async function resolveOrRacePromises wrapPromise(p)) as ReturnPromiseWithTuple; + // We intentionally want an array of promises here + // eslint-disable-next-line @typescript-eslint/no-floating-promises promises = (promiseResults as PromiseResult[]).map((p) => p.promise) as unknown as T; try { diff --git a/packages/validator/src/services/emitter.ts b/packages/validator/src/services/emitter.ts index dddf1583eb0a..19f9ac1de54a 100644 --- a/packages/validator/src/services/emitter.ts +++ b/packages/validator/src/services/emitter.ts @@ -1,5 +1,5 @@ import {EventEmitter} from "events"; -import StrictEventEmitter from "strict-event-emitter-types"; +import {StrictEventEmitter} from "strict-event-emitter-types"; import {Slot} from "@lodestar/types"; import {HeadEventData} from "./chainHeaderTracker.js"; diff --git a/yarn.lock b/yarn.lock index c4f6bd206eca..c858ef47ddf0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -656,10 +656,10 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.8.1.tgz#8c4bb756cc2aa7eaf13cfa5e69c83afb3260c20c" integrity sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ== -"@eslint/eslintrc@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" - integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -671,10 +671,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.50.0": - version "8.50.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.50.0.tgz#9e93b850f0f3fa35f5fa59adfd03adae8488e484" - integrity sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ== +"@eslint/js@8.56.0": + version "8.56.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" + integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== "@ethereumjs/block@^4.2.2": version "4.2.2" @@ -1252,13 +1252,13 @@ resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== -"@humanwhocodes/config-array@^0.11.11": - version "0.11.11" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.11.tgz#88a04c570dbbc7dd943e4712429c3df09bc32844" - integrity sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA== +"@humanwhocodes/config-array@^0.11.13": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": @@ -1266,10 +1266,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" + integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== "@hutson/parse-repository-url@^3.0.0": version "3.0.2" @@ -2413,17 +2413,10 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@pkgr/utils@^2.3.1": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" - integrity sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw== - dependencies: - cross-spawn "^7.0.3" - fast-glob "^3.3.0" - is-glob "^4.0.3" - open "^9.1.0" - picocolors "^1.0.0" - tslib "^2.6.0" +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== "@polka/url@^1.0.0-next.24": version "1.0.0-next.24" @@ -3223,16 +3216,16 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz#f18cc75c9cceac8080a9dc2e7d166008c5207b9f" - integrity sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q== +"@typescript-eslint/eslint-plugin@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3" + integrity sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.7.2" - "@typescript-eslint/type-utils" "6.7.2" - "@typescript-eslint/utils" "6.7.2" - "@typescript-eslint/visitor-keys" "6.7.2" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/type-utils" "6.21.0" + "@typescript-eslint/utils" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -3240,60 +3233,47 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/parser@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.2.tgz#e0ae93771441b9518e67d0660c79e3a105497af4" - integrity sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw== +"@typescript-eslint/parser@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" + integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== dependencies: - "@typescript-eslint/scope-manager" "6.7.2" - "@typescript-eslint/types" "6.7.2" - "@typescript-eslint/typescript-estree" "6.7.2" - "@typescript-eslint/visitor-keys" "6.7.2" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz#b6d2abb825b29ab70cb542d220e40c61c1678116" - integrity sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ== +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== dependencies: - "@typescript-eslint/types" "6.19.0" - "@typescript-eslint/visitor-keys" "6.19.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" -"@typescript-eslint/scope-manager@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz#cf59a2095d2f894770c94be489648ad1c78dc689" - integrity sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw== +"@typescript-eslint/type-utils@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz#6473281cfed4dacabe8004e8521cee0bd9d4c01e" + integrity sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag== dependencies: - "@typescript-eslint/types" "6.7.2" - "@typescript-eslint/visitor-keys" "6.7.2" - -"@typescript-eslint/type-utils@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz#ed921c9db87d72fa2939fee242d700561454f367" - integrity sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ== - dependencies: - "@typescript-eslint/typescript-estree" "6.7.2" - "@typescript-eslint/utils" "6.7.2" + "@typescript-eslint/typescript-estree" "6.21.0" + "@typescript-eslint/utils" "6.21.0" debug "^4.3.4" ts-api-utils "^1.0.1" -"@typescript-eslint/types@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.19.0.tgz#689b0498c436272a6a2059b09f44bcbd90de294a" - integrity sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A== +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== -"@typescript-eslint/types@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.2.tgz#75a615a6dbeca09cafd102fe7f465da1d8a3c066" - integrity sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg== - -"@typescript-eslint/typescript-estree@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz#0813ba364a409afb4d62348aec0202600cb468fa" - integrity sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ== +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== dependencies: - "@typescript-eslint/types" "6.19.0" - "@typescript-eslint/visitor-keys" "6.19.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -3301,60 +3281,31 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/typescript-estree@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz#ce5883c23b581a5caf878af641e49dd0349238c7" - integrity sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ== - dependencies: - "@typescript-eslint/types" "6.7.2" - "@typescript-eslint/visitor-keys" "6.7.2" - debug "^4.3.4" - globby "^11.1.0" - is-glob "^4.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" - -"@typescript-eslint/utils@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.2.tgz#b9ef0da6f04932167a9222cb4ac59cb187165ebf" - integrity sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ== - dependencies: - "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.7.2" - "@typescript-eslint/types" "6.7.2" - "@typescript-eslint/typescript-estree" "6.7.2" - semver "^7.5.4" - -"@typescript-eslint/utils@^6.15.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.19.0.tgz#557b72c3eeb4f73bef8037c85dae57b21beb1a4b" - integrity sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw== +"@typescript-eslint/utils@6.21.0", "@typescript-eslint/utils@^6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.19.0" - "@typescript-eslint/types" "6.19.0" - "@typescript-eslint/typescript-estree" "6.19.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" semver "^7.5.4" -"@typescript-eslint/visitor-keys@6.19.0": - version "6.19.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz#4565e0ecd63ca1f81b96f1dd76e49f746c6b2b49" - integrity sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ== +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== dependencies: - "@typescript-eslint/types" "6.19.0" + "@typescript-eslint/types" "6.21.0" eslint-visitor-keys "^3.4.1" -"@typescript-eslint/visitor-keys@6.7.2": - version "6.7.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz#4cb2bd786f1f459731b0ad1584c9f73e1c7a4d5c" - integrity sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ== - dependencies: - "@typescript-eslint/types" "6.7.2" - eslint-visitor-keys "^3.4.1" +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== "@vitest/browser@^1.2.1": version "1.2.1" @@ -3867,15 +3818,15 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== -array-includes@^3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" - integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== +array-includes@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" - get-intrinsic "^1.1.3" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" is-string "^1.0.7" array-union@^2.1.0: @@ -3883,35 +3834,46 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.findlastindex@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" - integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== +array.prototype.filter@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz#423771edeb417ff5914111fff4277ea0624c0d0e" + integrity sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw== dependencies: call-bind "^1.0.2" define-properties "^1.2.0" es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - get-intrinsic "^1.2.1" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" -array.prototype.flat@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" - integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== +array.prototype.findlastindex@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz#d1c50f0b3a9da191981ff8942a0aedd82794404f" + integrity sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" - integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" arraybuffer.prototype.slice@^1.0.2: @@ -4126,11 +4088,6 @@ big-integer@^1.6.17: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== -big-integer@^1.6.44: - version "1.6.51" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" - integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== - bigint-buffer@^1.1.5: version "1.1.5" resolved "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz" @@ -4223,13 +4180,6 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== -bplist-parser@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" - integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw== - dependencies: - big-integer "^1.6.44" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -4425,13 +4375,6 @@ builtins@^5.0.0: dependencies: semver "^7.0.0" -bundle-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bundle-name/-/bundle-name-3.0.0.tgz#ba59bcc9ac785fb67ccdbf104a2bf60c099f0e1a" - integrity sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw== - dependencies: - run-applescript "^5.0.0" - byline@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" @@ -5355,24 +5298,6 @@ deepmerge@^4.3.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -default-browser-id@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c" - integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA== - dependencies: - bplist-parser "^0.2.0" - untildify "^4.0.0" - -default-browser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/default-browser/-/default-browser-4.0.0.tgz#53c9894f8810bf86696de117a6ce9085a3cbc7da" - integrity sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA== - dependencies: - bundle-name "^3.0.0" - default-browser-id "^3.0.0" - execa "^7.1.1" - titleize "^3.0.0" - defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" @@ -5399,12 +5324,7 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-lazy-prop@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f" - integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg== - -define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -5760,7 +5680,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.18.0-next.2, es-abstract@^1.20.4, es-abstract@^1.22.1: +es-abstract@^1.18.0-next.2, es-abstract@^1.22.1, es-abstract@^1.22.3: version "1.22.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== @@ -5805,6 +5725,16 @@ es-abstract@^1.18.0-next.2, es-abstract@^1.20.4, es-abstract@^1.22.1: unbox-primitive "^1.0.2" which-typed-array "^1.1.13" +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-errors@^1.0.0, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-set-tostringtag@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" @@ -5821,6 +5751,13 @@ es-shim-unscopables@^1.0.0: dependencies: has "^1.0.3" +es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -5904,14 +5841,14 @@ escodegen@^2.1.0: optionalDependencies: source-map "~0.6.1" -eslint-import-resolver-node@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" - integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== dependencies: debug "^3.2.7" - is-core-module "^2.11.0" - resolve "^1.22.1" + is-core-module "^2.13.0" + resolve "^1.22.4" eslint-import-resolver-typescript@^3.6.1: version "3.6.1" @@ -5948,43 +5885,43 @@ eslint-plugin-es@^4.1.0: eslint-utils "^2.0.0" regexpp "^3.0.0" -eslint-plugin-import@^2.28.1: - version "2.28.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4" - integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A== +eslint-plugin-import@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== dependencies: - array-includes "^3.1.6" - array.prototype.findlastindex "^1.2.2" - array.prototype.flat "^1.3.1" - array.prototype.flatmap "^1.3.1" + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" debug "^3.2.7" doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.7" + eslint-import-resolver-node "^0.3.9" eslint-module-utils "^2.8.0" - has "^1.0.3" - is-core-module "^2.13.0" + hasown "^2.0.0" + is-core-module "^2.13.1" is-glob "^4.0.3" minimatch "^3.1.2" - object.fromentries "^2.0.6" - object.groupby "^1.0.0" - object.values "^1.1.6" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" semver "^6.3.1" - tsconfig-paths "^3.14.2" + tsconfig-paths "^3.15.0" -eslint-plugin-prettier@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz#6887780ed95f7708340ec79acfdf60c35b9be57a" - integrity sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w== +eslint-plugin-prettier@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" + integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw== dependencies: prettier-linter-helpers "^1.0.0" - synckit "^0.8.5" + synckit "^0.8.6" -eslint-plugin-vitest@^0.3.20: - version "0.3.20" - resolved "https://registry.yarnpkg.com/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.20.tgz#9c4e02dd0252ad359b1e02dbcfbe4cf7ad8d091a" - integrity sha512-O05k4j9TGMOkkghj9dRgpeLDyOSiVIxQWgNDPfhYPm5ioJsehcYV/zkRLekQs+c8+RBCVXucSED3fYOyy2EoWA== +eslint-plugin-vitest@^0.3.22: + version "0.3.22" + resolved "https://registry.yarnpkg.com/eslint-plugin-vitest/-/eslint-plugin-vitest-0.3.22.tgz#207eb4630768f6400cd91a6df23688e8a1fd0898" + integrity sha512-atkFGQ7aVgcuSeSMDqnyevIyUpfBPMnosksgEPrKE7Y8xQlqG/5z2IQ6UDau05zXaaFv7Iz8uzqvIuKshjZ0Zw== dependencies: - "@typescript-eslint/utils" "^6.15.0" + "@typescript-eslint/utils" "^6.21.0" eslint-scope@^7.2.2: version "7.2.2" @@ -6011,18 +5948,19 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.50.0: - version "8.50.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.50.0.tgz#2ae6015fee0240fcd3f83e1e25df0287f487d6b2" - integrity sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg== +eslint@^8.56.0: + version "8.56.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" + integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.2" - "@eslint/js" "8.50.0" - "@humanwhocodes/config-array" "^0.11.11" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.56.0" + "@humanwhocodes/config-array" "^0.11.13" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -6236,21 +6174,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" - integrity sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.1" - human-signals "^4.3.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^3.0.7" - strip-final-newline "^3.0.0" - execa@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" @@ -6328,7 +6251,7 @@ fast-fifo@^1.1.0, fast-fifo@^1.2.0: resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1: +fast-glob@^3.2.9, fast-glob@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -7329,11 +7252,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -human-signals@^4.3.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" - integrity sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ== - human-signals@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" @@ -7625,7 +7543,7 @@ is-ci@3.0.1: dependencies: ci-info "^3.2.0" -is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.3.0, is-core-module@^2.5.0, is-core-module@^2.8.1: +is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.3.0, is-core-module@^2.5.0, is-core-module@^2.8.1: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== @@ -7644,11 +7562,6 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-docker@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-3.0.0.tgz#90093aa3106277d8a77a5910dbae71747e15a200" - integrity sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ== - is-electron@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/is-electron/-/is-electron-2.2.0.tgz" @@ -7676,13 +7589,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-inside-container@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-inside-container/-/is-inside-container-1.0.0.tgz#e81fba699662eb31dbdaf26766a61d4814717ea4" - integrity sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA== - dependencies: - is-docker "^3.0.0" - is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" @@ -9834,7 +9740,7 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.fromentries@^2.0.6: +object.fromentries@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== @@ -9843,24 +9749,25 @@ object.fromentries@^2.0.6: define-properties "^1.2.0" es-abstract "^1.22.1" -object.groupby@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" - integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== +object.groupby@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.2.tgz#494800ff5bab78fd0eff2835ec859066e00192ec" + integrity sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" + array.prototype.filter "^1.0.3" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.0.0" -object.values@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" - integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== +object.values@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" obliterator@^2.0.1: version "2.0.4" @@ -9919,16 +9826,6 @@ open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -open@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/open/-/open-9.1.0.tgz#684934359c90ad25742f5a26151970ff8c6c80b6" - integrity sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg== - dependencies: - default-browser "^4.0.0" - define-lazy-prop "^3.0.0" - is-inside-container "^1.0.0" - is-wsl "^2.2.0" - openapi-types@^12.0.0, openapi-types@^12.0.2: version "12.1.3" resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.3.tgz#471995eb26c4b97b7bd356aacf7b91b73e777dd3" @@ -10991,7 +10888,7 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.17.0, resolve@^1.22.1: +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.17.0, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -11153,13 +11050,6 @@ rrweb-cssom@^0.6.0: resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" integrity sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw== -run-applescript@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/run-applescript/-/run-applescript-5.0.0.tgz#e11e1c932e055d5c6b40d98374e0268d9b11899c" - integrity sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg== - dependencies: - execa "^5.0.0" - run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -11943,13 +11833,13 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -synckit@^0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.5.tgz#b7f4358f9bb559437f9f167eb6bc46b3c9818fa3" - integrity sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q== +synckit@^0.8.6: + version "0.8.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" + integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== dependencies: - "@pkgr/utils" "^2.3.1" - tslib "^2.5.0" + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" systeminformation@^5.17.12: version "5.21.7" @@ -12139,11 +12029,6 @@ tinyspy@^2.2.0: resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.0.tgz#9dc04b072746520b432f77ea2c2d17933de5d6ce" integrity sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg== -titleize@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/titleize/-/titleize-3.0.0.tgz#71c12eb7fdd2558aa8a44b0be83b8a76694acd53" - integrity sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ== - tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -12255,10 +12140,10 @@ ts-node@^10.8.1, ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tsconfig-paths@^3.14.2: - version "3.14.2" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" - integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: "@types/json5" "^0.0.29" json5 "^1.0.2" @@ -12294,7 +12179,7 @@ tslib@^1.10.0: resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.0, tslib@^2.6.1: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== @@ -12562,11 +12447,6 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -untildify@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" - integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== - unzipper@^0.10.14: version "0.10.14" resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.14.tgz#d2b33c977714da0fbc0f82774ad35470a7c962b1" From cd7421e46bb1782f8a5ecf2aec4c98134c3328f2 Mon Sep 17 00:00:00 2001 From: Julien Date: Wed, 14 Feb 2024 03:43:46 -0800 Subject: [PATCH 44/71] chore: fixed incorrect link (#6427) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 867b8f5aaab2..b5accf7a2c61 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ yarn build | Package | Version | License | Docs | Description | | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | -| [`@lodestar/beacon-node`](./packages/beacon-node) | [![npm](https://img.shields.io/npm/v/@chainsafe/lodestar)](https://www.npmjs.com/package/@chainsafe/lodestar) | [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) | [![documentation](https://img.shields.io/badge/readme-blue)](./packages/beacon-node) | :rotating_light: Beacon-chain client | +| [`@lodestar/beacon-node`](./packages/beacon-node) | [![npm](https://img.shields.io/npm/v/@lodestar/beacon-node)](https://www.npmjs.com/package/@lodestar/beacon-node) | [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) | [![documentation](https://img.shields.io/badge/readme-blue)](./packages/beacon-node) | :rotating_light: Beacon-chain client | | [`@lodestar/validator`](./packages/validator) | [![npm](https://img.shields.io/npm/v/@lodestar/validator)](https://www.npmjs.com/package/@lodestar/validator) | [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) | [![documentation](https://img.shields.io/badge/readme-blue)](./packages/validator) | :bank: Validator client | | [`@lodestar/light-client`](./packages/light-client) | [![npm](https://img.shields.io/npm/v/@lodestar/light-client)](https://www.npmjs.com/package/@lodestar/light-client) | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) | [![documentation](https://img.shields.io/badge/readme-blue)](./packages/light-client) | :bird: Ethereum Light client | | [`@lodestar/api`](./packages/api) | [![npm](https://img.shields.io/npm/v/@lodestar/api)](https://www.npmjs.com/package/@lodestar/api) | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) | [![documentation](https://img.shields.io/badge/readme-blue)](./packages/api) | :clipboard: REST Client for the Ethereum Beacon API | From 81576426fbb3989f5a13055ef059091afc5e81eb Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 14 Feb 2024 17:25:09 +0100 Subject: [PATCH 45/71] feat: schedule deneb on gnosis (#6423) --- packages/config/src/chainConfig/networks/gnosis.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config/src/chainConfig/networks/gnosis.ts b/packages/config/src/chainConfig/networks/gnosis.ts index 7bafaa0225b1..8034e478fd28 100644 --- a/packages/config/src/chainConfig/networks/gnosis.ts +++ b/packages/config/src/chainConfig/networks/gnosis.ts @@ -51,5 +51,5 @@ export const gnosisChainConfig: ChainConfig = { CAPELLA_FORK_EPOCH: 648704, // 2023-08-01T11:34:20.000Z // Deneb DENEB_FORK_VERSION: b("0x04000064"), - DENEB_FORK_EPOCH: Infinity, + DENEB_FORK_EPOCH: 889856, // 2024-03-11T18:30:20.000Z }; From 0087c8ad32308e4ee3f948e485e5230843bd7af3 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 14 Feb 2024 17:27:44 +0100 Subject: [PATCH 46/71] docs: pin dependencies, update icons, and formatting fixes (#6425) * Pin versions of docs dependencies * Update icons of socials * Fix formatting of array default values * Fix syntax highlighting of code blocks * Add sh syntax highlighting to cli examples * Revive dev cli command * defaultDescription of arrays should match description help output * Remove duplicate brackets from array default values --- docs/mkdocs.yml | 7 ++++--- docs/pages/advanced-topics/setting-up-a-testnet.md | 4 ++-- docs/pages/beacon-management/networking.md | 2 +- docs/pages/getting-started/starting-a-node.md | 14 +++++++------- .../logging-and-metrics/prometheus-grafana.md | 4 ++-- docs/pages/reference/cli.md | 1 + .../pages/validator-management/vc-configuration.md | 2 +- docs/requirements.txt | 12 ++++++------ packages/cli/docsgen/markdown.ts | 6 ++++-- 9 files changed, 28 insertions(+), 24 deletions(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index c26b849e98b9..1a14241e07bb 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -60,9 +60,9 @@ extra_css: # Socials extra: social: - - icon: fontawesome/brands/github-alt + - icon: fontawesome/brands/github link: https://github.com/ChainSafe/lodestar - - icon: fontawesome/brands/twitter + - icon: fontawesome/brands/x-twitter link: https://twitter.com/lodestar_eth - icon: fontawesome/brands/discord link: https://discord.gg/yjyvFRP @@ -122,6 +122,7 @@ nav: # - Bug Reports: contribution/bug-reports.md - Dependency Graph: contribution/depgraph.md # - Repo: contribution/repo.md + - Dev CLI Reference: contribution/dev-cli.md - Testing: - Overview: contribution/testing/index.md # - Unit Tests: contribution/testing/unit-tests.md @@ -142,4 +143,4 @@ nav: # - Block Exploration: advanced-topics/block-exploration.md # - Slashing Protection: advanced-topics/slashing-protection.md - Setting Up a Testnet: advanced-topics/setting-up-a-testnet.md - # - Doppelganger Detection: advanced-topics/doppelganger-detection.md \ No newline at end of file + # - Doppelganger Detection: advanced-topics/doppelganger-detection.md diff --git a/docs/pages/advanced-topics/setting-up-a-testnet.md b/docs/pages/advanced-topics/setting-up-a-testnet.md index a6350b3a03de..4a57f6db423e 100644 --- a/docs/pages/advanced-topics/setting-up-a-testnet.md +++ b/docs/pages/advanced-topics/setting-up-a-testnet.md @@ -58,7 +58,7 @@ The exact ENR of node to connect to is then supplied via the `--bootnodes` flag. Once the second node starts, you should see an output similar to the following in either of the terminals: -``` +```txt Eph 167991/6 6.007 [] info: Searching peers - peers: 1 - slot: 5375718 (skipped 5375718) - head: 0 0xcc67…3345 - finalized: 0x0000…0000:0 ``` @@ -70,7 +70,7 @@ For example, making the request on the first node via the following command: will give a result similar to the following: -``` +```json { "data": [ { diff --git a/docs/pages/beacon-management/networking.md b/docs/pages/beacon-management/networking.md index 1afd80c9cea3..579fbdef8fe0 100644 --- a/docs/pages/beacon-management/networking.md +++ b/docs/pages/beacon-management/networking.md @@ -44,7 +44,7 @@ Note that bootnodes are announced via ENR. Lodestar prints out its own ENR on startup, the logs will show something similar to the following -``` +```txt info: discv5 worker started peerId=16Uiu...t9LQ3, initialENR=enr:-Iu4QGE...WRwgiMo, bindAddr4=/ip4/0.0.0.0/udp/9000 ``` diff --git a/docs/pages/getting-started/starting-a-node.md b/docs/pages/getting-started/starting-a-node.md index 665a39b0df80..1641cd7d9115 100644 --- a/docs/pages/getting-started/starting-a-node.md +++ b/docs/pages/getting-started/starting-a-node.md @@ -68,7 +68,7 @@ In case execution-layer clients are available at different locations, use `--exe Immediately you should see confirmation that the node has started -```bash +```txt pr-20 15:12:45.274[] info: Lodestar network=mainnet, version=v1.7.2, commit= Apr-20 15:12:45.327[] info: Connected to LevelDB database path=/data/mt1/chain-db Apr-20 15:12:57.747[] info: Initializing beacon from a valid db state slot=6264480, epoch=195765, stateRoot=0x8133cd4d0be59c3e94405f902fe0ad68ffaa5013b525dddb6285b91ad79716f6, isWithinWeakSubjectivityPeriod=true @@ -136,35 +136,35 @@ Lodestar beacon sync log aims to provide information of utmost importance about See the following example of different kinds of sync log: -``` +```txt Apr-20 15:24:08.034[] info: Searching peers - peers: 0 - slot: 6265018 - head: 6264018 0xed93…7b0a - exec-block: syncing(17088476 0x9649…) - finalized: 0xbf30…7e7c:195777 Apr-20 15:24:17.000[] info: Searching peers - peers: 0 - slot: 6265019 - head: 6264018 0xed93…7b0a - exec-block: syncing(17088476 0x9649…) - finalized: 0xbf30…7e7c:195777 ``` -``` +```txt Apr-20 15:13:41.298[] info: Syncing - 2.5 minutes left - 2.78 slots/s - slot: 6264966 - head: 6262966 0x5cec…f5b8 - exec-block: valid(17088105 0x6f74…) - finalized: 0x5cc0…3874:195764 - peers: 1 Apr-20 15:13:41.298[] info: Syncing - 2 minutes left - 2.78 slots/s - slot: 6264967 - head: 6263965 0x5cec…f5b8 - exec-block: valid(17088105 0x6f74…) - finalized: 0x5cc0…3874:195764 - peers: 1 ``` -``` +```txt Apr-20 15:13:53.151[] info: Syncing - 1.6 minutes left - 3.82 slots/s - slot: 6264967 - head: (slot -360) 0xe0cf…9f3c - exec-block: valid(17088167 0x2d6a…) - finalized: 0x8f3f…2f81:195766 - peers: 5 Apr-20 15:14:05.425[] info: Syncing - 1.1 minutes left - 4.33 slots/s - slot: 6264968 - head: (slot -297) 0x3655…1658 - exec-block: valid(17088231 0xdafd…) - finalized: 0x9475…425a:195769 - peers: 2 Apr-20 15:14:53.001[] info: Syncing - 9 seconds left - 5.00 slots/s - slot: 6264972 - head: (slot -45) 0x44e4…20a4 - exec-block: valid(17088475 0xca61…) - finalized: 0x9cbd…ba83:195776 - peers: 8 ``` -``` +```txt Apr-20 15:15:01.443[network] info: Subscribed gossip core topics Apr-20 15:15:01.446[sync] info: Subscribed gossip core topics Apr-20 15:15:05.000[] info: Synced - slot: 6264973 - head: 0x90ea…c655 - exec-block: valid(17088521 0xca9b…) - finalized: 0x6981…682f:195778 - peers: 6 Apr-20 15:15:17.003[] info: Synced - slot: 6264974 - head: 0x4f7e…0e3a - exec-block: valid(17088522 0x08b1…) - finalized: 0x6981…682f:195778 - peers: 6 ``` -``` +```txt Apr-20 15:15:41.001[] info: Synced - slot: 6264976 - head: (slot -1) 0x17c6…71a7 - exec-block: valid(17088524 0x5bc1…) - finalized: 0x6981…682f:195778 - peers: 8 Apr-20 15:15:53.001[] info: Synced - slot: 6264977 - head: (slot -2) 0x17c6…71a7 - exec-block: valid(17088524 0x5bc1…) - finalized: 0x6981…682f:195778 - peers: 8 ``` -``` +```txt Apr-20 15:16:05.000[] info: Synced - slot: 6264978 - head: 0xc9fd…28c5 - exec-block: valid(17088526 0xb5bf…) - finalized: 0x6981…682f:195778 - peers: 8 Apr-20 15:16:17.017[] info: Synced - slot: 6264979 - head: 0xde91…d4cb - exec-block: valid(17088527 0xa488…) - finalized: 0x6981…682f:195778 - peers: 7 ``` diff --git a/docs/pages/logging-and-metrics/prometheus-grafana.md b/docs/pages/logging-and-metrics/prometheus-grafana.md index 681e15d91ede..44f4fb6bd3c1 100644 --- a/docs/pages/logging-and-metrics/prometheus-grafana.md +++ b/docs/pages/logging-and-metrics/prometheus-grafana.md @@ -7,7 +7,7 @@ Prometheus is an open-source monitoring system with efficient time series databa To start, download Prometheus from https://prometheus.io/download/. Unzip the downloaded .zip file and run Prometheus from its installed location with the lodestar `prometheus.yml` passed in as the configuration file -``` +```sh ./prometheus --config.file=$dataDir/prometheus.yml ``` @@ -18,7 +18,7 @@ Unzip the downloaded .zip file and run Prometheus from its installed location wi Then run the Lodestar beacon node with -``` +```sh lodestar --metrics=true --metrics.port=8008 ``` diff --git a/docs/pages/reference/cli.md b/docs/pages/reference/cli.md index 1b57913b99fc..9bfd266aa51b 100644 --- a/docs/pages/reference/cli.md +++ b/docs/pages/reference/cli.md @@ -6,3 +6,4 @@ _**Welcome! This page has been moved. Please checkout our new docs layout from t - [Validator CLI](../validator-management/validator-cli.md) - [Bootnode CLI](../bootnode/bootnode-cli.md) - [Light Client CLI](../lightclient-prover/lightclient-cli.md) +- [Dev CLI](../contribution/dev-cli.md) diff --git a/docs/pages/validator-management/vc-configuration.md b/docs/pages/validator-management/vc-configuration.md index f1fa720c7ee1..4853bca5bfa6 100644 --- a/docs/pages/validator-management/vc-configuration.md +++ b/docs/pages/validator-management/vc-configuration.md @@ -132,7 +132,7 @@ To start a Lodestar validator run the command: You should see confirmation that modules have started. -``` +```txt Nov-29 10:47:13.647[] info: Lodestar network=sepolia, version=v1.2.2/f093b46, commit=f093b468ec3ab0dbbe8e2d2c8175f52ad88aa35f Nov-29 10:47:13.649[] info: Connecting to LevelDB database path=/home/user/.local/share/lodestar/sepolia/validator-db Nov-29 10:47:51.732[] info: 3 local keystores diff --git a/docs/requirements.txt b/docs/requirements.txt index 18befdfcbe5e..755759c0ace3 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ -mkdocs>=1.2 -mkdocs-material>=7.0 -Pygments>=2.4 -markdown>=3.2 -pymdown-extensions>=7.0 -mkdocs-mermaid2-plugin>=0.4 \ No newline at end of file +mkdocs==1.5.3 +mkdocs-material==9.5.9 +Pygments==2.17.2 +markdown==3.5.2 +pymdown-extensions==10.7 +mkdocs-mermaid2-plugin==1.1.1 diff --git a/packages/cli/docsgen/markdown.ts b/packages/cli/docsgen/markdown.ts index c05c7ad8c90f..e7fbcab7ad4b 100644 --- a/packages/cli/docsgen/markdown.ts +++ b/packages/cli/docsgen/markdown.ts @@ -6,7 +6,7 @@ const LINE_BREAK = "\n\n
"; function renderExampleBody(example: CliExample, lodestarCommand?: string): string { const cliExample = [ - `\`\`\` + `\`\`\`sh ${lodestarCommand ? `${lodestarCommand} ` : ""}${example.command} \`\`\``, ]; @@ -113,7 +113,9 @@ function renderOption(optionName: string, option: CliOptionDefinition): string | if (!defaultValue.includes(`"`)) { defaultValue = `"${defaultValue}"`; } - defaultValue = `[ ${defaultValue} ]`; + if (!defaultValue.startsWith("[")) { + defaultValue = `[ ${defaultValue} ]`; + } } commandOption.push(`default: \`${defaultValue}\``); } From d384213054bad3d3e421a4f1c885b07965d9e6a8 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 14 Feb 2024 17:29:35 +0100 Subject: [PATCH 47/71] refactor: reuse utils added in block production race refactor (#6422) --- .../src/api/impl/validator/index.ts | 18 +++++++++--------- packages/utils/src/format.ts | 10 +++------- packages/utils/src/metrics.ts | 4 +++- packages/utils/src/promise.ts | 5 ----- packages/utils/src/types.ts | 5 +++++ packages/validator/src/services/block.ts | 16 ++++------------ 6 files changed, 24 insertions(+), 34 deletions(-) diff --git a/packages/beacon-node/src/api/impl/validator/index.ts b/packages/beacon-node/src/api/impl/validator/index.ts index 0b45540c791e..553146a6cc58 100644 --- a/packages/beacon-node/src/api/impl/validator/index.ts +++ b/packages/beacon-node/src/api/impl/validator/index.ts @@ -187,21 +187,21 @@ export function getValidatorApi({ if (source == null) { return { - executionPayloadValue: prettyWeiToEth(executionValue, true), - consensusBlockValue: prettyWeiToEth(consensusValue, true), - blockTotalValue: prettyWeiToEth(totalValue, true), + executionPayloadValue: prettyWeiToEth(executionValue), + consensusBlockValue: prettyWeiToEth(consensusValue), + blockTotalValue: prettyWeiToEth(totalValue), }; } else if (source === ProducedBlockSource.builder) { return { - builderExecutionPayloadValue: prettyWeiToEth(executionValue, true), - builderConsensusBlockValue: prettyWeiToEth(consensusValue, true), - builderBlockTotalValue: prettyWeiToEth(totalValue, true), + builderExecutionPayloadValue: prettyWeiToEth(executionValue), + builderConsensusBlockValue: prettyWeiToEth(consensusValue), + builderBlockTotalValue: prettyWeiToEth(totalValue), }; } else { return { - engineExecutionPayloadValue: prettyWeiToEth(executionValue, true), - engineConsensusBlockValue: prettyWeiToEth(consensusValue, true), - engineBlockTotalValue: prettyWeiToEth(totalValue, true), + engineExecutionPayloadValue: prettyWeiToEth(executionValue), + engineConsensusBlockValue: prettyWeiToEth(consensusValue), + engineBlockTotalValue: prettyWeiToEth(totalValue), }; } } diff --git a/packages/utils/src/format.ts b/packages/utils/src/format.ts index 0e89748af8f8..8bd8a40273f1 100644 --- a/packages/utils/src/format.ts +++ b/packages/utils/src/format.ts @@ -45,14 +45,10 @@ export function formatBigDecimal(numerator: bigint, denominator: bigint, maxDeci const MAX_DECIMAL_FACTOR = BigInt("100000"); /** - * Format wei as ETH, with up to 5 decimals - * - * if suffix is true, append ' ETH' + * Format wei as ETH, with up to 5 decimals and append ' ETH' */ -export function prettyWeiToEth(wei: bigint, suffix = false): string { - let eth = formatBigDecimal(wei, ETH_TO_WEI, MAX_DECIMAL_FACTOR); - if (suffix) eth += " ETH"; - return eth; +export function prettyWeiToEth(wei: bigint): string { + return `${formatBigDecimal(wei, ETH_TO_WEI, MAX_DECIMAL_FACTOR)} ETH`; } /** diff --git a/packages/utils/src/metrics.ts b/packages/utils/src/metrics.ts index a25518280ee1..f8a965f2800a 100644 --- a/packages/utils/src/metrics.ts +++ b/packages/utils/src/metrics.ts @@ -1,3 +1,5 @@ +import {NonEmptyArray} from "./types.js"; + export type NoLabels = Record; export type LabelsGeneric = Record; export type LabelKeys = Extract; @@ -39,7 +41,7 @@ export interface Counter { export type GaugeConfig = { name: string; help: string; -} & (NoLabels extends Labels ? {labelNames?: never} : {labelNames: [LabelKeys, ...LabelKeys[]]}); +} & (NoLabels extends Labels ? {labelNames?: never} : {labelNames: NonEmptyArray>}); export type HistogramConfig = GaugeConfig & { buckets?: number[]; diff --git a/packages/utils/src/promise.ts b/packages/utils/src/promise.ts index 9a8574a57854..2be7467bfff4 100644 --- a/packages/utils/src/promise.ts +++ b/packages/utils/src/promise.ts @@ -74,11 +74,6 @@ export function wrapPromise(promise: PromiseLike): PromiseResult { return result; } -/** - * ArrayToTuple converts an `Array` to `[T, ...T]` - * - * eg: `[1, 2, 3]` from type `number[]` to `[number, number, number]` - */ type ReturnPromiseWithTuple>> = { [Index in keyof ArrayToTuple]: PromiseResult>; }; diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index cf07331e4456..5b46d65053ef 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -17,6 +17,11 @@ export function bnToNum(bn: bigint): number { export type NonEmptyArray = [T, ...T[]]; +/** + * ArrayToTuple converts an `Array` to `[T, ...T]` + * + * eg: `[1, 2, 3]` from type `number[]` to `[number, number, number]` + */ export type ArrayToTuple> = { [Index in keyof Tuple]: Tuple[Index]; }; diff --git a/packages/validator/src/services/block.ts b/packages/validator/src/services/block.ts index a28f7c019d0b..faec8d9e04ee 100644 --- a/packages/validator/src/services/block.ts +++ b/packages/validator/src/services/block.ts @@ -11,7 +11,7 @@ import { } from "@lodestar/types"; import {ChainForkConfig} from "@lodestar/config"; import {ForkPreBlobs, ForkBlobs, ForkSeq, ForkExecution} from "@lodestar/params"; -import {ETH_TO_WEI, extendError, formatBigDecimal, prettyBytes} from "@lodestar/utils"; +import {extendError, prettyBytes, prettyWeiToEth} from "@lodestar/utils"; import {Api, ApiError, routes} from "@lodestar/api"; import {IClock, LoggerVc} from "../util/index.js"; import {PubkeyHex} from "../types.js"; @@ -19,9 +19,6 @@ import {Metrics} from "../metrics.js"; import {ValidatorStore} from "./validatorStore.js"; import {BlockDutiesService, GENESIS_SLOT} from "./blockDuties.js"; -// display upto 5 decimal places -const MAX_DECIMAL_FACTOR = BigInt("100000"); - // The following combination of blocks and blobs can be produced // i) a full block pre deneb // ii) a full block and full blobs post deneb @@ -218,14 +215,9 @@ export class BlockProposingService { const debugLogCtx = { executionPayloadSource: response.executionPayloadSource, executionPayloadBlinded: response.executionPayloadBlinded, - // winston logger doesn't like bigint - executionPayloadValue: `${formatBigDecimal(response.executionPayloadValue, ETH_TO_WEI, MAX_DECIMAL_FACTOR)} ETH`, - consensusBlockValue: `${formatBigDecimal(response.consensusBlockValue, ETH_TO_WEI, MAX_DECIMAL_FACTOR)} ETH`, - totalBlockValue: `${formatBigDecimal( - response.executionPayloadValue + response.consensusBlockValue, - ETH_TO_WEI, - MAX_DECIMAL_FACTOR - )} ETH`, + executionPayloadValue: prettyWeiToEth(response.executionPayloadValue), + consensusBlockValue: prettyWeiToEth(response.consensusBlockValue), + totalBlockValue: prettyWeiToEth(response.executionPayloadValue + response.consensusBlockValue), // TODO PR: should be used in api call instead of adding in log strictFeeRecipientCheck, builderSelection, From 42e883586f3bbea1867b8b9c2458ed4b97216480 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 14 Feb 2024 17:31:47 +0100 Subject: [PATCH 48/71] ci: lint yarn lockfiles to analyze and detect security issues (#6424) --- .github/workflows/test.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3838ef65aa13..3e87dcd1ab3d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -97,6 +97,8 @@ jobs: fail-on-cache-miss: true - name: Assert yarn prints no warnings run: scripts/assert_no_yarn_warnings.sh + - name: Lint yarn lockfile + run: npx lockfile-lint --path yarn.lock --allowed-hosts npm yarn --validate-https - name: Lint Code run: yarn lint - name: Lint Grafana dashboards @@ -149,12 +151,12 @@ jobs: matrix: node: [20] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} check-latest: true - cache: yarn + cache: yarn # # Remove when finished debugging core dumps # - uses: './.github/actions/setup-debug-node' @@ -184,7 +186,7 @@ jobs: # Rever to "yarn test:unit" when finished debugging core dumps # run: sudo sh -c "ulimit -c unlimited && /usr/bin/node-with-debug $(which yarn) test:unit" run: yarn test:unit - + # # Remove when finished debugging core dumps # - uses: './.github/actions/core-dump' # if: ${{ failure() && steps.unit_tests.conclusion == 'failure' }} @@ -276,7 +278,7 @@ jobs: key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} fail-on-cache-miss: true - name: Install Chrome browser - run: npx @puppeteer/browsers install chromedriver@latest --path /tmp + run: npx @puppeteer/browsers install chromedriver@latest --path /tmp - name: Install Firefox browser run: npx @puppeteer/browsers install firefox@latest --path /tmp - name: Browser tests @@ -330,7 +332,7 @@ jobs: working-directory: packages/beacon-node - name: Spec tests bls run: yarn test:spec:bls - working-directory: packages/beacon-node + working-directory: packages/beacon-node - name: Spec tests minimal run: yarn test:spec:minimal working-directory: packages/beacon-node From c52c7bd6614c622f77913e85ec435bf0f50e2558 Mon Sep 17 00:00:00 2001 From: Phil Ngo <58080811+philknows@users.noreply.github.com> Date: Thu, 15 Feb 2024 02:38:37 -0500 Subject: [PATCH 49/71] docs: initialize FAQs page with Kubernetes unknown args error (#6416) * init commit with faq docs * Enable collapsable blocks and reorder nav * init faqs with kubernetes env arg errors * update wordlist * Explain root cause and resolution of issue * Add newline to the end of mkdocs file * Remove redundancies * Wording * Env variables are added becasue of Service name --------- Co-authored-by: Nico Flaig --- .wordlist.txt | 1 + docs/mkdocs.yml | 2 ++ docs/pages/faqs.md | 23 +++++++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 docs/pages/faqs.md diff --git a/.wordlist.txt b/.wordlist.txt index 9e9b2773bd66..f56de5f92c82 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -48,6 +48,7 @@ JSON JSObjects JWT KDE +Kubernetes LGPL LGPLv LMD diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1a14241e07bb..21a56df6c160 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -42,6 +42,7 @@ markdown_extensions: - codehilite: guess_lang: false - admonition + - pymdownx.details - toc: permalink: true - pymdownx.superfences: @@ -144,3 +145,4 @@ nav: # - Slashing Protection: advanced-topics/slashing-protection.md - Setting Up a Testnet: advanced-topics/setting-up-a-testnet.md # - Doppelganger Detection: advanced-topics/doppelganger-detection.md + - Frequently Asked Questions: faqs.md diff --git a/docs/pages/faqs.md b/docs/pages/faqs.md new file mode 100644 index 000000000000..65d719251bba --- /dev/null +++ b/docs/pages/faqs.md @@ -0,0 +1,23 @@ +# Frequently Asked Questions + +This section of the documentation will cover common questions and encounters often asked by users and developers. + +## Troubleshooting Lodestar + +### Using Kubernetes + + +???+ note "Unknown arguments error" + Lodestar reads all environment variables prefixed with `LODESTAR` and will try to parse + them similar to command line arguments, meaning any unknown argument will cause an error. + ``` + ✖ Unknown arguments: servicePort, servicePortEthConsensusP2p, + port9000Tcp, port9000TcpPort, port9000TcpProto, port9000TcpAddr, serviceHost + ``` + The extra arguments are present because Kubernetes automatically + [adds environment variables](https://kubernetes.io/docs/concepts/services-networking/service/#environment-variables) + to the Pod based on the name (`metadata.name`) defined in the associated `Service`. + To resolve the issue, this name has to be changed to something that does not start with `lodestar`. + + Reference Issue: [#6045](https://github.com/ChainSafe/lodestar/issues/6045) + From 83d7d701728ac70ad01cd80074b8537632ac0a23 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Thu, 15 Feb 2024 12:07:25 +0100 Subject: [PATCH 50/71] test: add support to dump raw simulation data for debugging (#6429) * Add logs support for file dump * Add logger to runner * Add feature to dump raw data for debugging * Add dump support to few assertions * Update log level for errors * Fix head assertion csv data * Revert "Fix head assertion csv data" This reverts commit 91abfc2c78ae4bc1a7b4025c843accd5d8c1ef50. * Fix head assertion csv data --- .../utils/simulation/SimulationEnvironment.ts | 43 +++++++++------ .../utils/simulation/SimulationTracker.ts | 53 ++++++++++++++++-- .../test/utils/simulation/TableRenderer.ts | 55 +++++++++---------- .../test/utils/simulation/TableReporter.ts | 36 ++++++------ .../defaults/attestationCountAssertion.ts | 15 +++++ .../assertions/defaults/headAssertion.ts | 15 +++++ .../defaults/inclusionDelayAssertion.ts | 15 +++++ .../syncCommitteeParticipationAssertion.ts | 18 +++++- .../cli/test/utils/simulation/interfaces.ts | 11 ++++ .../cli/test/utils/simulation/runner/index.ts | 14 +++-- 10 files changed, 198 insertions(+), 77 deletions(-) diff --git a/packages/cli/test/utils/simulation/SimulationEnvironment.ts b/packages/cli/test/utils/simulation/SimulationEnvironment.ts index 3acd217e225e..cb53f384f2ee 100644 --- a/packages/cli/test/utils/simulation/SimulationEnvironment.ts +++ b/packages/cli/test/utils/simulation/SimulationEnvironment.ts @@ -9,6 +9,8 @@ import {ChainForkConfig} from "@lodestar/config"; import {activePreset} from "@lodestar/params"; import {BeaconStateAllForks, interopSecretKey} from "@lodestar/state-transition"; import {prettyMsToTime} from "@lodestar/utils"; +import {LogLevel, TimestampFormatCode} from "@lodestar/logger"; +import {getNodeLogger, LoggerNode} from "@lodestar/logger/node"; import {EpochClock, MS_IN_SEC} from "./EpochClock.js"; import {ExternalSignerServer} from "./ExternalSignerServer.js"; import {SimulationTracker} from "./SimulationTracker.js"; @@ -36,14 +38,13 @@ interface StartOpts { runTimeoutMs: number; } -/* eslint-disable no-console */ - export class SimulationEnvironment { readonly nodes: NodePair[] = []; readonly clock: EpochClock; readonly tracker: SimulationTracker; readonly runner: IRunner; readonly externalSigner: ExternalSignerServer; + readonly logger: LoggerNode; readonly forkConfig: ChainForkConfig; readonly options: SimulationOptions; @@ -57,6 +58,14 @@ export class SimulationEnvironment { this.forkConfig = forkConfig; this.options = options; + this.logger = getNodeLogger({ + level: LogLevel.debug, + module: `sim-${this.options.id}`, + timestampFormat: { + format: TimestampFormatCode.DateRegular, + }, + file: {level: LogLevel.debug, filepath: path.join(options.logsDir, `simulation-${this.options.id}.log`)}, + }); this.clock = new EpochClock({ genesisTime: this.options.genesisTime + this.forkConfig.GENESIS_DELAY, secondsPerSlot: this.forkConfig.SECONDS_PER_SLOT, @@ -65,8 +74,10 @@ export class SimulationEnvironment { }); this.externalSigner = new ExternalSignerServer([]); - this.runner = new Runner({logsDir: this.options.logsDir}); + this.runner = new Runner({logsDir: this.options.logsDir, logger: this.logger.child({module: "runner"})}); this.tracker = SimulationTracker.initWithDefaultAssertions({ + logsDir: options.logsDir, + logger: this.logger, nodes: [], config: this.forkConfig, clock: this.clock, @@ -95,7 +106,7 @@ export class SimulationEnvironment { async start(opts: StartOpts): Promise { const currentTime = Date.now(); - console.log( + this.logger.info( `Starting simulation environment "${this.options.id}". currentTime=${new Date( currentTime ).toISOString()} simulationTimeout=${prettyMsToTime(opts.runTimeoutMs)}` @@ -108,7 +119,7 @@ export class SimulationEnvironment { const slot = this.clock.getSlotIndexInEpoch(slots); this.stop(1, `Sim run timeout in ${opts.runTimeoutMs}ms (approx. ${epoch}/${slot}).`).catch((e) => - console.error("Error on stop", e) + this.logger.error("Error on stop", e) ); }, opts.runTimeoutMs); } @@ -122,7 +133,7 @@ export class SimulationEnvironment { this.stop( 1, `Start sequence not completed before genesis, in ${prettyMsToTime(msToGenesis)} (approx. ${epoch}/${slot}).` - ).catch((e) => console.error("Error on stop", e)); + ).catch((e) => this.logger.error("Error on stop", e)); }, msToGenesis); try { @@ -131,26 +142,26 @@ export class SimulationEnvironment { await mkdir(this.options.rootDir); } - console.log("Starting the simulation runner"); + this.logger.info("Starting the simulation runner"); await this.runner.start(); - console.log("Starting execution nodes"); + this.logger.info("Starting execution nodes"); await Promise.all(this.nodes.map((node) => node.execution.job.start())); - console.log("Initializing genesis state for beacon nodes"); + this.logger.info("Initializing genesis state for beacon nodes"); await this.initGenesisState(); if (!this.genesisState) { throw new Error("The genesis state for CL clients is not defined."); } - console.log("Starting beacon nodes"); + this.logger.info("Starting beacon nodes"); await Promise.all(this.nodes.map((node) => node.beacon.job.start())); - console.log("Starting validators"); + this.logger.info("Starting validators"); await Promise.all(this.nodes.map((node) => node.validator?.job.start())); if (this.nodes.some((node) => node.validator?.keys.type === "remote")) { - console.log("Starting external signer"); + this.logger.info("Starting external signer"); await this.externalSigner.start(); for (const node of this.nodes) { @@ -162,12 +173,12 @@ export class SimulationEnvironment { url: this.externalSigner.url, })) ); - console.log(`Imported remote keys for node ${node.id}`); + this.logger.info(`Imported remote keys for node ${node.id}`); } } } - console.log("Starting the simulation tracker"); + this.logger.info("Starting the simulation tracker"); await this.tracker.start(); await Promise.all(this.nodes.map((node) => this.tracker.track(node))); } catch (error) { @@ -182,8 +193,8 @@ export class SimulationEnvironment { process.removeAllListeners("uncaughtException"); process.removeAllListeners("SIGTERM"); process.removeAllListeners("SIGINT"); - console.log(`Simulation environment "${this.options.id}" is stopping: ${message}`); - await this.tracker.stop(); + this.logger.info(`Simulation environment "${this.options.id}" is stopping: ${message}`); + await this.tracker.stop({dumpStores: true}); await Promise.all(this.nodes.map((node) => node.validator?.job.stop())); await Promise.all(this.nodes.map((node) => node.beacon.job.stop())); await Promise.all(this.nodes.map((node) => node.execution.job.stop())); diff --git a/packages/cli/test/utils/simulation/SimulationTracker.ts b/packages/cli/test/utils/simulation/SimulationTracker.ts index f2159490c109..3c2365ef9979 100644 --- a/packages/cli/test/utils/simulation/SimulationTracker.ts +++ b/packages/cli/test/utils/simulation/SimulationTracker.ts @@ -1,8 +1,11 @@ import EventEmitter from "node:events"; +import path from "node:path"; +import fs from "node:fs/promises"; import createDebug from "debug"; import {routes} from "@lodestar/api/beacon"; import {ChainForkConfig} from "@lodestar/config"; import {Epoch, Slot} from "@lodestar/types"; +import {LoggerNode} from "@lodestar/logger/node"; import {isNullish} from "../../utils.js"; import {EpochClock} from "./EpochClock.js"; import { @@ -27,6 +30,8 @@ interface SimulationTrackerInitOptions { config: ChainForkConfig; clock: EpochClock; signal: AbortSignal; + logger: LoggerNode; + logsDir: string; } export enum SimulationTrackerEvent { @@ -62,10 +67,20 @@ export function getStoresForAssertions( return filterStores as StoreTypes; } -/* eslint-disable no-console */ +async function pathExists(filePath: string): Promise { + try { + await fs.access(filePath); + return true; + } catch { + return false; + } +} + export class SimulationTracker { readonly emitter = new EventEmitter(); readonly reporter: SimulationReporter>; + readonly logger: LoggerNode; + readonly logsDir: string; private lastSeenSlot: Map = new Map(); private slotCapture: Map = new Map(); @@ -73,21 +88,24 @@ export class SimulationTracker { private nodes: NodePair[]; private clock: EpochClock; private forkConfig: ChainForkConfig; - private running: boolean = false; + private running = false; private errors: SimulationAssertionError[] = []; private stores: Stores; private assertions: SimulationAssertion[]; private assertionIdsMap: Record = {}; - private constructor({signal, nodes, clock, config}: SimulationTrackerInitOptions) { + private constructor({signal, nodes, clock, config, logger, logsDir}: SimulationTrackerInitOptions) { this.signal = signal; this.nodes = nodes; this.clock = clock; this.forkConfig = config; + this.logsDir = logsDir; + this.logger = logger.child({module: "tracker"}); this.stores = {} as StoreTypes & StoreType; this.assertions = [] as SimulationAssertion[]; this.reporter = new TableReporter({ + logger: this.logger.child({module: "reporter"}), clock: this.clock, forkConfig: this.forkConfig, nodes: this.nodes, @@ -162,19 +180,42 @@ export class SimulationTracker { // Start clock loop on current slot or genesis this.clockLoop(Math.max(this.clock.currentSlot, 0)).catch((e) => { - console.error("error on clockLoop", e); + this.logger.error("error on clockLoop", e); }); } - async stop(): Promise { + async stop(opts: {dumpStores: boolean}): Promise { this.running = false; + + if (opts.dumpStores) { + if (!(await pathExists(path.join(this.logsDir, "data")))) + await fs.mkdir(path.join(this.logsDir, "data"), {recursive: true}); + + for (const assertion of this.assertions) { + if (!assertion.dump) continue; + + const data = await assertion.dump({ + fork: this.forkConfig.getForkName(this.clock.currentSlot), + forkConfig: this.forkConfig, + clock: this.clock, + epoch: this.clock.currentEpoch, + store: this.stores[assertion.id], + slot: this.clock.currentSlot, + nodes: this.nodes, + }); + + for (const filename of Object.keys(data)) { + await fs.writeFile(path.join(this.logsDir, "data", filename), data[filename]); + } + } + } } async clockLoop(slot: number): Promise { while (this.running && !this.signal.aborted) { // Wait for 2/3 of the slot to consider it missed await this.clock.waitForStartOfSlot(slot + 2 / 3, slot > 0).catch((e) => { - console.error("error on waitForStartOfSlot", e); + this.logger.error("error on waitForStartOfSlot", e); }); this.reporter.progress(slot); slot++; diff --git a/packages/cli/test/utils/simulation/TableRenderer.ts b/packages/cli/test/utils/simulation/TableRenderer.ts index 5ceab13a8918..3ebeeff485fb 100644 --- a/packages/cli/test/utils/simulation/TableRenderer.ts +++ b/packages/cli/test/utils/simulation/TableRenderer.ts @@ -1,12 +1,19 @@ +import {Logger} from "@lodestar/logger"; import {strFixedSize} from "./utils/index.js"; +const V_SEP_M = " │ "; +const V_SEP_S = "│ "; +const V_SEP_E = " │"; + export class TableRenderer { + readonly logger: Logger; private columnsSizes: Record; private columns: Columns[]; private rows: Record[]; private totalWidth: number; - constructor(columnWithSizes: Record) { + constructor(columnWithSizes: Record, {logger}: {logger: Logger}) { + this.logger = logger; this.columnsSizes = columnWithSizes; this.columns = Object.keys(columnWithSizes) as Columns[]; this.rows = []; @@ -20,54 +27,42 @@ export class TableRenderer { } addEmptyRow(text: string): void { - this.printHSeparator(true); - this.printVSeparator("start"); - process.stdout.write(strFixedSize(text, this.totalWidth - 4)); - this.printVSeparator("end"); - this.printHSeparator(true); + this.printHSeparator(); + this.logger.info(`${V_SEP_S}${strFixedSize(text, this.totalWidth - 4)}${V_SEP_E}`); + this.printHSeparator(); } printHeader(): void { - this.printHSeparator(true); - this.printVSeparator("start"); + this.printHSeparator(); + const output = [V_SEP_S]; for (const [index, column] of this.columns.entries()) { - process.stdout.write(strFixedSize(column, this.columnsSizes[column])); + output.push(strFixedSize(column, this.columnsSizes[column])); if (index === this.columns.length - 1) { - this.printVSeparator("end"); + output.push(V_SEP_E); } else { - this.printVSeparator(); + output.push(V_SEP_M); } } - this.printHSeparator(true); + this.logger.info(output.join("")); + this.printHSeparator(); } printRow(rowIndex: number): void { const row = this.rows[rowIndex]; - - this.printVSeparator("start"); + const output = [V_SEP_S]; for (const [index, column] of this.columns.entries()) { const value = String(row[column]); - process.stdout.write(value.padEnd(this.columnsSizes[column])); + output.push(value.padEnd(this.columnsSizes[column])); if (index === this.columns.length - 1) { - this.printVSeparator("end"); + output.push(V_SEP_E); } else { - this.printVSeparator(); + output.push(V_SEP_M); } } + this.logger.info(output.join("")); } - private printHSeparator(lineBreak: boolean): void { - process.stdout.write(`┼${"─".repeat(this.totalWidth - 2)}┼`); - if (lineBreak) process.stdout.write("\n"); - } - - private printVSeparator(mode?: "start" | "end"): void { - if (!mode) { - process.stdout.write(" │ "); - } else if (mode === "start") { - process.stdout.write("│ "); - } else if (mode === "end") { - process.stdout.write(" │\n"); - } + private printHSeparator(): void { + this.logger.info(`┼${"─".repeat(this.totalWidth - 2)}┼`); } } diff --git a/packages/cli/test/utils/simulation/TableReporter.ts b/packages/cli/test/utils/simulation/TableReporter.ts index 1101c926269c..4a49470cc15b 100644 --- a/packages/cli/test/utils/simulation/TableReporter.ts +++ b/packages/cli/test/utils/simulation/TableReporter.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import {Slot} from "@lodestar/types"; import {isNullish} from "../../utils.js"; import {HeadSummary} from "./assertions/defaults/headAssertion.js"; @@ -10,18 +9,21 @@ import {arrayGroupBy, avg, isSingletonArray} from "./utils/index.js"; export class TableReporter extends SimulationReporter { private lastPrintedSlot = -1; - private table = new TableRenderer({ - time: 14, - fork: 10, - eph: 5, - slot: 4, - head: 10, - finzed: 8, - peers: 8, - attCount: 8, - incDelay: 8, - errors: 10, - }); + private table = new TableRenderer( + { + time: 14, + fork: 10, + eph: 5, + slot: 4, + head: 10, + finzed: 8, + peers: 8, + attCount: 8, + incDelay: 8, + errors: 10, + }, + {logger: this.options.logger} + ); bootstrap(): void { this.table.printHeader(); @@ -132,19 +134,19 @@ export class TableReporter extends SimulationReporter summary(): void { const {errors} = this.options; - console.info(`├${"─".repeat(10)} Errors (${errors.length}) ${"─".repeat(10)}┤`); + this.options.logger.error(`├${"─".repeat(10)} Errors (${errors.length}) ${"─".repeat(10)}┤`); const groupBySlot = arrayGroupBy(errors, (e) => String(e.slot as number)); for (const [slot, slotErrors] of Object.entries(groupBySlot)) { - if (slotErrors.length > 0) console.info(`├─ Slot: ${slot}`); + if (slotErrors.length > 0) this.options.logger.info(`├─ Slot: ${slot}`); const groupByAssertion = arrayGroupBy(slotErrors, (e) => e.assertionId); for (const [assertionId, assertionErrors] of Object.entries(groupByAssertion)) { - if (assertionErrors.length > 0) console.info(`├── Assertion: ${assertionId}`); + if (assertionErrors.length > 0) this.options.logger.info(`├── Assertion: ${assertionId}`); for (const error of assertionErrors) { - console.info( + this.options.logger.error( `├──── ${error.nodeId}: ${error.message} ${Object.entries(error.data ?? {}) .map(([k, v]) => `${k}=${v as string}`) .join(" ")}` diff --git a/packages/cli/test/utils/simulation/assertions/defaults/attestationCountAssertion.ts b/packages/cli/test/utils/simulation/assertions/defaults/attestationCountAssertion.ts index ed9f9bfc64e4..9c01a6bdc3ac 100644 --- a/packages/cli/test/utils/simulation/assertions/defaults/attestationCountAssertion.ts +++ b/packages/cli/test/utils/simulation/assertions/defaults/attestationCountAssertion.ts @@ -66,4 +66,19 @@ export const attestationsCountAssertion: SimulationAssertion< return errors; }, + + async dump({store, slot, nodes}) { + /* + * | Slot | Node 1 | Node 2 | Node 3 | + * |------|--------|--------|--------| + * | 1 | 10 | 10 | 10 | + * | 2 | 10 | 10 | 10 | + * | 3 | 10 | 10 | 10 | + */ + const result = [`Slot,${nodes.map((n) => n.beacon.id).join(", ")}`]; + for (let s = 1; s <= slot; s++) { + result.push(`${s}, ${nodes.map((n) => store[n.beacon.id][s] ?? "-").join(",")}`); + } + return {"attestationsCountAssertion.csv": result.join("\n")}; + }, }; diff --git a/packages/cli/test/utils/simulation/assertions/defaults/headAssertion.ts b/packages/cli/test/utils/simulation/assertions/defaults/headAssertion.ts index 74021abfc310..8d493637d228 100644 --- a/packages/cli/test/utils/simulation/assertions/defaults/headAssertion.ts +++ b/packages/cli/test/utils/simulation/assertions/defaults/headAssertion.ts @@ -37,4 +37,19 @@ export const headAssertion: SimulationAssertion<"head", HeadSummary> = { return errors; }, + + async dump({store, slot, nodes}) { + /* + * | Slot | Node 1 | Node 2 | + * |------|--------|--------| + * | 1 | 0x49d3 | 0x49d3 | + * | 2 | 0x49d3 | 0x49d3 | + * | 3 | 0x49d3 | 0x49d3 | + */ + const result = [`Slot,${nodes.map((n) => n.beacon.id).join(", ")}`]; + for (let s = 1; s <= slot; s++) { + result.push(`${s}, ${nodes.map((n) => store[n.beacon.id][s].blockRoot ?? "-").join(",")}`); + } + return {"headAssertion.csv": result.join("\n")}; + }, }; diff --git a/packages/cli/test/utils/simulation/assertions/defaults/inclusionDelayAssertion.ts b/packages/cli/test/utils/simulation/assertions/defaults/inclusionDelayAssertion.ts index 8db86fbb15aa..554df0e31ca9 100644 --- a/packages/cli/test/utils/simulation/assertions/defaults/inclusionDelayAssertion.ts +++ b/packages/cli/test/utils/simulation/assertions/defaults/inclusionDelayAssertion.ts @@ -30,4 +30,19 @@ export const inclusionDelayAssertion: SimulationAssertion<"inclusionDelay", numb return errors; }, + + async dump({store, slot, nodes}) { + /* + * | Slot | Node 1 | Node 2 | + * |------|--------|--------| + * | 1 | 1.0 | 1.0 | + * | 2 | 0.8 | 0.8 | + * | 3 | 0.5 | 0.95 | + */ + const result = [`Slot,${nodes.map((n) => n.beacon.id).join(", ")}`]; + for (let s = 1; s <= slot; s++) { + result.push(`${s}, ${nodes.map((n) => store[n.beacon.id][s] ?? "-").join(",")}`); + } + return {"inclusionDelayAssertion.csv": result.join("\n")}; + }, }; diff --git a/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts b/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts index 64d4039fb4a7..5858a0e151ca 100644 --- a/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts +++ b/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts @@ -7,9 +7,8 @@ export const expectedMinSyncParticipationRate = 0.9; export const syncCommitteeParticipationAssertion: SimulationAssertion<"syncCommitteeParticipation", number> = { id: "syncCommitteeParticipation", - match: ({slot, clock, epoch, forkConfig, fork}) => { + match: ({slot, clock, fork}) => { if (fork === ForkName.phase0) return AssertionMatch.None; - if (epoch < forkConfig.ALTAIR_FORK_EPOCH) return AssertionMatch.Capture; return clock.isLastSlotOfEpoch(slot) ? AssertionMatch.Capture | AssertionMatch.Assert : AssertionMatch.Capture; }, @@ -49,4 +48,19 @@ export const syncCommitteeParticipationAssertion: SimulationAssertion<"syncCommi return errors; }, + + async dump({store, slot, nodes}) { + /* + * | Slot | Node 1 | Node 2 | + * |------|--------|--------| + * | 1 | 16 | 18 | + * | 2 | 12 | 12 | + * | 3 | 14 | 14 | + */ + const result = [`Slot,${nodes.map((n) => n.beacon.id).join(", ")}`]; + for (let s = 1; s <= slot; s++) { + result.push(`${s}, ${nodes.map((n) => store[n.beacon.id][s] ?? "-").join(",")}`); + } + return {"syncCommitteeParticipationAssertion.csv": result.join("\n")}; + }, }; diff --git a/packages/cli/test/utils/simulation/interfaces.ts b/packages/cli/test/utils/simulation/interfaces.ts index 62b02ea25708..050782877608 100644 --- a/packages/cli/test/utils/simulation/interfaces.ts +++ b/packages/cli/test/utils/simulation/interfaces.ts @@ -6,6 +6,7 @@ import {Api as KeyManagerApi} from "@lodestar/api/keymanager"; import {ChainForkConfig} from "@lodestar/config"; import {ForkName} from "@lodestar/params"; import {Slot, allForks, Epoch} from "@lodestar/types"; +import {Logger} from "@lodestar/logger"; import {BeaconArgs} from "../../../src/cmds/beacon/options.js"; import {IValidatorCliArgs} from "../../../src/cmds/validator/options.js"; import {GlobalArgs} from "../../../src/options/index.js"; @@ -326,6 +327,11 @@ export interface SimulationAssertionInput = dependantStores: D; } +export interface SimulationDumpInput extends Omit { + nodes: NodePair[]; + store: Record>; +} + export type SimulationMatcherInput = AssertionInput; /** @@ -371,6 +377,10 @@ export interface SimulationAssertion< input: SimulationAssertionInput & StoreType> ): Promise; dependencies?: Dependencies; + // Use to dump the data to CSV files, as each assertion implementation knows + // how to make the dump more readable, so we define it in assertion + // Return object as key-value pair for file name as dump data + dump?(input: SimulationDumpInput): Promise>; } export type AssertionResult = string | [string, Record]; @@ -401,6 +411,7 @@ export abstract class SimulationReporter { stores: StoreTypes; nodes: NodePair[]; errors: SimulationAssertionError[]; + logger: Logger; } ) {} abstract bootstrap(): void; diff --git a/packages/cli/test/utils/simulation/runner/index.ts b/packages/cli/test/utils/simulation/runner/index.ts index 9bdca30562b4..cedd5c34e6a5 100644 --- a/packages/cli/test/utils/simulation/runner/index.ts +++ b/packages/cli/test/utils/simulation/runner/index.ts @@ -1,15 +1,17 @@ -/* eslint-disable no-console */ import {EventEmitter} from "node:events"; import path from "node:path"; +import {Logger} from "@lodestar/logger"; import {IRunner, Job, JobOptions, RunnerEvent, RunnerType} from "../interfaces.js"; import {ChildProcessRunner} from "./ChildProcessRunner.js"; import {DockerRunner} from "./DockerRunner.js"; export class Runner implements IRunner { + readonly logger: Logger; private emitter = new EventEmitter({captureRejections: true}); private runners: {[RunnerType.ChildProcess]: ChildProcessRunner; [RunnerType.Docker]: DockerRunner}; - constructor({logsDir}: {logsDir: string}) { + constructor({logsDir, logger}: {logsDir: string; logger: Logger}) { + this.logger = logger; this.runners = { [RunnerType.ChildProcess]: new ChildProcessRunner(), [RunnerType.Docker]: new DockerRunner(path.join(logsDir, "docker_runner.log")), @@ -51,25 +53,25 @@ export class Runner implements IRunner { startSequence.push(async () => { this.emitter.emit("starting", jobOption.id); - console.log(`Starting "${jobOption.id}"...`); + this.logger.info(`Starting "${jobOption.id}"...`); if (jobOption.bootstrap) await jobOption.bootstrap(); await job.start(); this.emitter.emit("started", jobOption.id); - console.log(`Started "${jobOption.id}" logFile=${jobOption.logs.stdoutFilePath}...`); + this.logger.info(`Started "${jobOption.id}" logFile=${jobOption.logs.stdoutFilePath}...`); if (childrenJob) await childrenJob.start(); }); stopSequence.push(async () => { this.emitter.emit("stopping", jobOption.id); - console.log(`Stopping "${jobOption.id}"...`); + this.logger.info(`Stopping "${jobOption.id}"...`); if (jobOption.teardown) await jobOption.teardown(); if (childrenJob) await childrenJob.stop(); await job.stop(); this.emitter.emit("stopped", jobOption.id); - console.log(`Stopped "${jobOption.id}"...`); + this.logger.info(`Stopped "${jobOption.id}"...`); }); } From e0b6e285c375c2823f31c87e5cc69bbd7308ea4c Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 15 Feb 2024 18:43:08 +0530 Subject: [PATCH 51/71] fix: publish blobs sooner than later (#6431) --- packages/beacon-node/src/api/impl/beacon/blocks/index.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts index 6fde04bc737c..d4aa2337fe3f 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts @@ -179,6 +179,13 @@ export function getBeaconBlockApi({ const publishPromises = [ // Send the block, regardless of whether or not it is valid. The API // specification is very clear that this is the desired behaviour. + // + // i) Publish blobs and block before importing so that network can see them asap + // ii) publish blobs first because + // a) by the times nodes see block, they might decide to pull blobs + // b) they might require more hops to reach recipients in peerDAS kind of setup where + // blobs might need to hop between nodes because of partial subnet subscription + ...blobSidecars.map((blobSidecar) => () => network.publishBlobSidecar(blobSidecar)), () => network.publishBeaconBlock(signedBlock) as Promise, () => // there is no rush to persist block since we published it to gossip anyway @@ -191,7 +198,6 @@ export function getBeaconBlockApi({ } throw e; }), - ...blobSidecars.map((blobSidecar) => () => network.publishBlobSidecar(blobSidecar)), ]; await promiseAllMaybeAsync(publishPromises); }; From 48871ebfffaccf686fe68b7936acbd9dd393e239 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 15 Feb 2024 16:15:15 +0100 Subject: [PATCH 52/71] fix: reduce verbosity of gossip block errors (#6430) * Log gossip block errors as warnings * Only log to debug if blobs are unavailable * Always prune cache and track error in metrics * Adapt log level (verbosity) based on error * Do not initialize log level to ensure each case is handled explicitly * Update comments * Update comment --- .../src/network/processor/gossipHandlers.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/beacon-node/src/network/processor/gossipHandlers.ts b/packages/beacon-node/src/network/processor/gossipHandlers.ts index bdd5f1917dc5..2bf9178a0567 100644 --- a/packages/beacon-node/src/network/processor/gossipHandlers.ts +++ b/packages/beacon-node/src/network/processor/gossipHandlers.ts @@ -1,6 +1,6 @@ import {toHexString} from "@chainsafe/ssz"; import {BeaconConfig} from "@lodestar/config"; -import {Logger, prettyBytes} from "@lodestar/utils"; +import {LogLevel, Logger, prettyBytes} from "@lodestar/utils"; import {Root, Slot, ssz, allForks, deneb} from "@lodestar/types"; import {ForkName, ForkSeq} from "@lodestar/params"; import {routes} from "@lodestar/api"; @@ -255,6 +255,9 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler chain.seenGossipBlockInput.prune(); }) .catch((e) => { + // Adjust verbosity based on error type + let logLevel: LogLevel; + if (e instanceof BlockError) { switch (e.type.code) { case BlockErrorCode.DATA_UNAVAILABLE: { @@ -264,6 +267,9 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler const rootHex = toHexString(forkTypes.BeaconBlock.hashTreeRoot(signedBlock.message)); events.emit(NetworkEvent.unknownBlock, {rootHex, peer: peerIdStr}); + + // Error is quite frequent and not critical + logLevel = LogLevel.debug; break; } // ALREADY_KNOWN should not happen with ignoreIfKnown=true above @@ -272,14 +278,21 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler case BlockErrorCode.PARENT_UNKNOWN: case BlockErrorCode.PRESTATE_MISSING: case BlockErrorCode.EXECUTION_ENGINE_ERROR: + // Errors might indicate an issue with our node or the connected EL client + logLevel = LogLevel.error; break; default: // TODO: Should it use PeerId or string? core.reportPeer(peerIdStr, PeerAction.LowToleranceError, "BadGossipBlock"); + // Misbehaving peer, but could highlight an issue in another client + logLevel = LogLevel.warn; } + } else { + // Any unexpected error + logLevel = LogLevel.error; } metrics?.gossipBlock.processBlockErrors.inc({error: e instanceof BlockError ? e.type.code : "NOT_BLOCK_ERROR"}); - logger.error("Error receiving block", {slot: signedBlock.message.slot, peer: peerIdStr}, e as Error); + logger[logLevel]("Error receiving block", {slot: signedBlock.message.slot, peer: peerIdStr}, e as Error); chain.seenGossipBlockInput.prune(); }); } From 5047410270ed7d74f686d6fab3e9d0217a6bcf6a Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Fri, 16 Feb 2024 10:11:39 +0100 Subject: [PATCH 53/71] test: temporarily reduce the sync committee participation limit for sim tests (#6433) Fix sync comittee test --- .../defaults/syncCommitteeParticipationAssertion.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts b/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts index 5858a0e151ca..5cce7554d737 100644 --- a/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts +++ b/packages/cli/test/utils/simulation/assertions/defaults/syncCommitteeParticipationAssertion.ts @@ -3,7 +3,9 @@ import {altair} from "@lodestar/types"; import {AssertionMatch, AssertionResult, SimulationAssertion} from "../../interfaces.js"; import {avg} from "../../utils/index.js"; -export const expectedMinSyncParticipationRate = 0.9; +// Until we identity and fix the following issue, reducing the expected sync committee participation rate from 0.9 to 0.75 +// https://github.com/ChainSafe/lodestar/issues/6432 +export const expectedMinSyncParticipationRate = 0.75; export const syncCommitteeParticipationAssertion: SimulationAssertion<"syncCommitteeParticipation", number> = { id: "syncCommitteeParticipation", From a02ea757fd0e613187ddf8cad54ad74b66a10375 Mon Sep 17 00:00:00 2001 From: Julien Date: Fri, 16 Feb 2024 01:52:50 -0800 Subject: [PATCH 54/71] feat: rename prover CLI start command as proxy and make it default (#6428) * feat: make start command default for prover CLI --- packages/prover/README.md | 2 +- packages/prover/src/cli/cli.ts | 5 ++++- packages/prover/src/cli/cmds/index.ts | 1 + packages/prover/src/cli/cmds/start/index.ts | 2 +- packages/prover/test/e2e/cli/cmds/start.test.ts | 12 ++++++------ 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/prover/README.md b/packages/prover/README.md index 290766219e79..0489756a066a 100644 --- a/packages/prover/README.md +++ b/packages/prover/README.md @@ -39,7 +39,7 @@ You can also invoke the package as binary. ```bash npm -i g @lodestar/prover -lodestar-prover start \ +lodestar-prover proxy \ --network sepolia \ --execution-rpc https://lodestar-sepoliarpc.chainsafe.io \ --mode rest \ diff --git a/packages/prover/src/cli/cli.ts b/packages/prover/src/cli/cli.ts index 8ef53e781a40..2d1475f3d39d 100644 --- a/packages/prover/src/cli/cli.ts +++ b/packages/prover/src/cli/cli.ts @@ -3,7 +3,7 @@ import yargs from "yargs"; import {hideBin} from "yargs/helpers"; import {registerCommandToYargs} from "../utils/command.js"; import {getVersionData} from "../utils/version.js"; -import {cmds} from "./cmds/index.js"; +import {cmds, proverProxyStartCommand} from "./cmds/index.js"; import {globalOptions} from "./options.js"; const {version} = getVersionData(); @@ -48,6 +48,9 @@ export function getLodestarProverCli(): yargs.Argv { registerCommandToYargs(prover, cmd); } + // Register the proxy command as the default one + registerCommandToYargs(prover, {...proverProxyStartCommand, command: "*"}); + // throw an error if we see an unrecognized cmd prover.recommendCommands().strict(); diff --git a/packages/prover/src/cli/cmds/index.ts b/packages/prover/src/cli/cmds/index.ts index 3b888ab41d83..ecd2dae1da99 100644 --- a/packages/prover/src/cli/cmds/index.ts +++ b/packages/prover/src/cli/cmds/index.ts @@ -1,5 +1,6 @@ import {CliCommand} from "../../utils/command.js"; import {GlobalArgs} from "../options.js"; import {proverProxyStartCommand} from "./start/index.js"; +export {proverProxyStartCommand} from "./start/index.js"; export const cmds: Required>>["subcommands"] = [proverProxyStartCommand]; diff --git a/packages/prover/src/cli/cmds/start/index.ts b/packages/prover/src/cli/cmds/start/index.ts index 76ad1bb3f260..2b49a6466a61 100644 --- a/packages/prover/src/cli/cmds/start/index.ts +++ b/packages/prover/src/cli/cmds/start/index.ts @@ -4,7 +4,7 @@ import {proverProxyStartHandler} from "./handler.js"; import {StartArgs, startOptions} from "./options.js"; export const proverProxyStartCommand: CliCommand = { - command: "start", + command: "proxy", describe: "Start proxy server", examples: [ { diff --git a/packages/prover/test/e2e/cli/cmds/start.test.ts b/packages/prover/test/e2e/cli/cmds/start.test.ts index 97790ce98c6e..a5ac299612e7 100644 --- a/packages/prover/test/e2e/cli/cmds/start.test.ts +++ b/packages/prover/test/e2e/cli/cmds/start.test.ts @@ -11,15 +11,15 @@ import {rpcUrl, beaconUrl, proxyPort, proxyUrl, chainId, waitForCapellaFork, con const cli = getLodestarProverCli(); -describe("prover/start", () => { +describe("prover/proxy", () => { it("should show help", async () => { - const output = await runCliCommand(cli, ["start", "--help"]); + const output = await runCliCommand(cli, ["proxy", "--help"]); expect(output).toEqual(expect.stringContaining("Show help")); }); it("should fail when --executionRpcUrl is missing", async () => { - await expect(runCliCommand(cli, ["start", "--port", "8088"])).rejects.toThrow( + await expect(runCliCommand(cli, ["proxy", "--port", "8088"])).rejects.toThrow( "Missing required argument: executionRpcUrl" ); }); @@ -27,7 +27,7 @@ describe("prover/start", () => { it("should fail when --beaconUrls and --beaconBootnodes are provided together", async () => { await expect( runCliCommand(cli, [ - "start", + "proxy", "--beaconUrls", "http://localhost:4000", "--beaconBootnodes", @@ -38,7 +38,7 @@ describe("prover/start", () => { it("should fail when both of --beaconUrls and --beaconBootnodes are not provided", async () => { await expect( - runCliCommand(cli, ["start", "--port", "8088", "--executionRpcUrl", "http://localhost:3000"]) + runCliCommand(cli, ["proxy", "--port", "8088", "--executionRpcUrl", "http://localhost:3000"]) ).rejects.toThrow("Either --beaconUrls or --beaconBootnodes must be provided"); }); @@ -55,7 +55,7 @@ describe("prover/start", () => { proc = await spawnCliCommand( "packages/prover/bin/lodestar-prover.js", [ - "start", + "proxy", "--port", String(proxyPort as number), "--executionRpcUrl", From 0cee060713e2b220799ad45ed8f14bd391170d74 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Fri, 16 Feb 2024 11:31:08 +0100 Subject: [PATCH 55/71] chore: improve type safety of CLI args (#6438) --- packages/cli/src/cmds/beacon/options.ts | 2 +- packages/cli/src/util/command.ts | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/cmds/beacon/options.ts b/packages/cli/src/cmds/beacon/options.ts index c9918b5d2e41..64a759615f7e 100644 --- a/packages/cli/src/cmds/beacon/options.ts +++ b/packages/cli/src/cmds/beacon/options.ts @@ -143,7 +143,7 @@ type ENRArgs = { nat?: boolean; }; -const enrOptions: Record = { +const enrOptions: CliCommandOptions = { "enr.ip": { description: "Override ENR IP entry", type: "string", diff --git a/packages/cli/src/util/command.ts b/packages/cli/src/util/command.ts index 0dd2fd82bc9f..760a1e2521a2 100644 --- a/packages/cli/src/util/command.ts +++ b/packages/cli/src/util/command.ts @@ -6,15 +6,26 @@ export interface CliExample { description?: string; } -export interface CliOptionDefinition extends Options { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export interface CliOptionDefinition extends Options { example?: Omit; + // Ensure `type` property matches type of `T` + type: T extends string + ? "string" + : T extends number + ? "number" + : T extends boolean + ? "boolean" + : T extends Array + ? "array" + : never; } export type CliCommandOptions = Required<{ [K in keyof OwnArgs]: undefined extends OwnArgs[K] - ? CliOptionDefinition + ? CliOptionDefinition : // If arg cannot be undefined it must specify a default value - CliOptionDefinition & Required>; + CliOptionDefinition & Required>; }>; // eslint-disable-next-line @typescript-eslint/no-explicit-any From d01c5425cdb25991074594113e73783b21dc2b0a Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Fri, 16 Feb 2024 11:39:04 +0100 Subject: [PATCH 56/71] test: add a work around for range sync issue during sim tests (#6436) * Fix a work around for range sync * Update packages/cli/test/sim/multi_fork.test.ts Co-authored-by: Nico Flaig --------- Co-authored-by: Nico Flaig --- packages/cli/test/sim/multi_fork.test.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/cli/test/sim/multi_fork.test.ts b/packages/cli/test/sim/multi_fork.test.ts index e15f8b01fe90..1302ad98bc82 100644 --- a/packages/cli/test/sim/multi_fork.test.ts +++ b/packages/cli/test/sim/multi_fork.test.ts @@ -7,6 +7,8 @@ import {SimulationEnvironment} from "../utils/simulation/SimulationEnvironment.j import {defineSimTestConfig, logFilesDir} from "../utils/simulation/utils/index.js"; import { connectAllNodes, + connectNewCLNode, + connectNewELNode, connectNewNode, waitForHead, waitForNodeSync, @@ -172,9 +174,27 @@ const checkpointSync = await env.createNodePair({ keysCount: 0, }); +// TODO: A workaround for this issue for sim tests only +// 1. Start the execution node and let it connect to network +// 2. Wait for few seconds +// 3. And later start the beacon node and connect to network +// 4. With this delay the execution node would be synced before the beacon node starts +// https://github.com/ChainSafe/lodestar/issues/6435 +// Revert to following code once the issue is fixed +// await rangeSync.execution.job.start(); +// await rangeSync.beacon.job.start(); +// await connectNewNode(rangeSync, env.nodes); await rangeSync.execution.job.start(); +await connectNewELNode( + rangeSync.execution, + env.nodes.map((node) => node.execution) +); +await sleep(4000); await rangeSync.beacon.job.start(); -await connectNewNode(rangeSync, env.nodes); +await connectNewCLNode( + rangeSync.beacon, + env.nodes.map((node) => node.beacon) +); await checkpointSync.execution.job.start(); await checkpointSync.beacon.job.start(); From 17b4fdea19e99dc438173c9a99a8210050582bde Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Fri, 16 Feb 2024 14:10:31 +0100 Subject: [PATCH 57/71] test: split sim tests to multiple jobs (#6437) * Reuse build actions * Split sim tests to multiple jobs * Improve sim test build time with cache * Lint edited files --------- Co-authored-by: Nico Flaig --- .github/actions/setup-and-build/action.yml | 58 ++++++++ .github/workflows/test-sim.yml | 157 +++++++++++++++----- .github/workflows/test.yml | 165 ++++----------------- 3 files changed, 202 insertions(+), 178 deletions(-) create mode 100644 .github/actions/setup-and-build/action.yml diff --git a/.github/actions/setup-and-build/action.yml b/.github/actions/setup-and-build/action.yml new file mode 100644 index 000000000000..f2575ea04565 --- /dev/null +++ b/.github/actions/setup-and-build/action.yml @@ -0,0 +1,58 @@ +name: "Setup and build the repo" +description: "A task to reuse setup steps during multiple jobs" +inputs: + node: + description: Node version + required: true + +runs: + using: "composite" + steps: + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: ${{inputs.node}} + check-latest: true + cache: yarn + + - name: Node.js version + id: node + shell: bash + run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT + + - name: Restore build + uses: actions/cache/restore@v4 + id: cache-build-restore + with: + path: | + node_modules + packages/*/node_modules + lib/ + packages/*/lib + packages/*/.git-data.json + key: ${{ runner.os }}-node-${{ inputs.node }}-${{ github.sha }} + + - name: Install & build + if: steps.cache-build-restore.outputs.cache-hit != 'true' + shell: bash + run: yarn install --frozen-lockfile && yarn build + + - name: Build + if: steps.cache-build-restore.outputs.cache-hit == 'true' + shell: bash + run: yarn build + + - name: Check Build + shell: bash + run: yarn check-build + + - name: Cache build artifacts + uses: actions/cache@master + with: + path: | + node_modules + packages/*/node_modules + lib/ + packages/*/lib + packages/*/.git-data.json + key: ${{ runner.os }}-node-${{ inputs.node }}-${{ github.sha }} diff --git a/.github/workflows/test-sim.yml b/.github/workflows/test-sim.yml index 9a4319aa84af..6895c74c016e 100644 --- a/.github/workflows/test-sim.yml +++ b/.github/workflows/test-sim.yml @@ -17,84 +17,163 @@ on: required: false default: "" genesisDelaySlots: - description: 'Number of slots delay before genesis' + description: "Number of slots delay before genesis" required: true type: number default: 40 jobs: - tests-sim: - name: Sim tests + build: + name: Build runs-on: buildjet-4vcpu-ubuntu-2204 steps: # - Uses YAML anchors in the future - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: "./.github/actions/setup-and-build" 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 - - 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' - # + node: 20 - - name: Load env variables + sim-test-multifork: + name: Multifork sim test + needs: build + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + # - Uses YAML anchors in the future + - uses: actions/checkout@v4 + - uses: "./.github/actions/setup-and-build" + with: + node: 20 + - name: Load env variables uses: ./.github/actions/dotenv - - name: Download required docker images before running tests run: | docker pull ${{env.GETH_DOCKER_IMAGE}} docker pull ${{env.LIGHTHOUSE_DOCKER_IMAGE}} docker pull ${{env.NETHERMIND_DOCKER_IMAGE}} - - name: Sim tests multifork run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:multifork working-directory: packages/cli - env: + env: GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} + - name: Upload debug log test files for "packages/cli" + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: sim-test-multifork-logs + path: packages/cli/test-logs + sim-test-endpoints: + name: Endpoint sim tests + needs: build + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + # - Uses YAML anchors in the future + - uses: actions/checkout@v4 + - uses: "./.github/actions/setup-and-build" + with: + node: 20 + - name: Load env variables + uses: ./.github/actions/dotenv + - name: Download required docker images before running tests + run: | + docker pull ${{env.GETH_DOCKER_IMAGE}} + docker pull ${{env.LIGHTHOUSE_DOCKER_IMAGE}} + docker pull ${{env.NETHERMIND_DOCKER_IMAGE}} - name: Sim tests endpoints run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:endpoints working-directory: packages/cli - env: - GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} + - name: Upload debug log test files for "packages/cli" + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: sim-test-endpoints-logs + path: packages/cli/test-logs + sim-test-deneb: + name: Deneb sim tests + needs: build + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + # - Uses YAML anchors in the future + - uses: actions/checkout@v4 + - uses: "./.github/actions/setup-and-build" + with: + node: 20 + - name: Load env variables + uses: ./.github/actions/dotenv + - name: Download required docker images before running tests + run: | + docker pull ${{env.GETH_DOCKER_IMAGE}} + docker pull ${{env.LIGHTHOUSE_DOCKER_IMAGE}} + docker pull ${{env.NETHERMIND_DOCKER_IMAGE}} - name: Sim tests deneb run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:deneb working-directory: packages/cli - env: - GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} + - name: Upload debug log test files for "packages/cli" + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: sim-test-deneb-logs + path: packages/cli/test-logs + sim-test-eth-backup-provider: + name: Eth backup provider sim tests + needs: build + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + # - Uses YAML anchors in the future + - uses: actions/checkout@v4 + - uses: "./.github/actions/setup-and-build" + with: + node: 20 + - name: Load env variables + uses: ./.github/actions/dotenv + - name: Download required docker images before running tests + run: | + docker pull ${{env.GETH_DOCKER_IMAGE}} + docker pull ${{env.LIGHTHOUSE_DOCKER_IMAGE}} + docker pull ${{env.NETHERMIND_DOCKER_IMAGE}} - name: Sim tests backup eth provider run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:backup_eth_provider working-directory: packages/cli - env: - GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} + - name: Upload debug log test files for "packages/cli" + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: sim-test-eth-backup-provider-logs + path: packages/cli/test-logs + sim-test-mixed-clients: + name: Mixed clients sim tests + needs: build + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + # - Uses YAML anchors in the future + - uses: actions/checkout@v4 + - uses: "./.github/actions/setup-and-build" + with: + node: 20 + - name: Load env variables + uses: ./.github/actions/dotenv + - name: Download required docker images before running tests + run: | + docker pull ${{env.GETH_DOCKER_IMAGE}} + docker pull ${{env.LIGHTHOUSE_DOCKER_IMAGE}} + docker pull ${{env.NETHERMIND_DOCKER_IMAGE}} - name: Sim tests mixed client run: DEBUG='${{github.event.inputs.debug}}' yarn test:sim:mixedclient working-directory: packages/cli - env: - GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} - + env: + GENESIS_DELAY_SLOTS: ${{github.event.inputs.genesisDelaySlots}} - name: Upload debug log test files for "packages/cli" if: ${{ always() }} uses: actions/upload-artifact@v4 with: - name: debug-test-logs-cli + name: sim-test-mixed-clients-logs path: packages/cli/test-logs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3e87dcd1ab3d..046cbe1f3cce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,50 +23,17 @@ jobs: steps: # - Uses YAML anchors in the future - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: "./.github/actions/setup-and-build" 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 build - uses: actions/cache/restore@v4 - id: cache-build-restore - with: - path: | - node_modules - packages/*/node_modules - lib/ - packages/*/lib - packages/*/.git-data.json - key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} - - name: Install & build - if: steps.cache-build-restore.outputs.cache-hit != 'true' - run: yarn install --frozen-lockfile && yarn build - - name: Build - if: steps.cache-build-restore.outputs.cache-hit == 'true' - run: yarn build - - name: Check Build - run: yarn check-build + node: ${{ matrix.node }} + - 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 }}-node-${{ matrix.node }}-${{ github.sha }} lint: name: Lint @@ -78,33 +45,25 @@ jobs: node: [20] steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node }} - check-latest: true - cache: yarn - - name: Restore build cache - id: cache-primes-restore - uses: actions/cache/restore@v4 + - uses: "./.github/actions/setup-and-build" with: - path: | - node_modules - packages/*/node_modules - lib/ - packages/*/lib - packages/*/.git-data.json - key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} - fail-on-cache-miss: true + node: ${{ matrix.node }} + - name: Assert yarn prints no warnings run: scripts/assert_no_yarn_warnings.sh + - name: Lint yarn lockfile run: npx lockfile-lint --path yarn.lock --allowed-hosts npm yarn --validate-https + - 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 @@ -118,23 +77,10 @@ jobs: node: [20] steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node }} - check-latest: true - cache: yarn - - name: Restore build cache - id: cache-primes-restore - uses: actions/cache/restore@v4 + + - uses: "./.github/actions/setup-and-build" with: - path: | - node_modules - packages/*/node_modules - lib/ - packages/*/lib - packages/*/.git-data.json - key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} - fail-on-cache-miss: true + node: ${{ matrix.node }} - name: Check Types run: yarn check-types @@ -152,27 +98,9 @@ jobs: node: [20] steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node }} - check-latest: true - cache: yarn - - # # Remove when finished debugging core dumps - # - uses: './.github/actions/setup-debug-node' - - - name: Restore build cache - id: cache-primes-restore - uses: actions/cache/restore@v4 + - uses: "./.github/actions/setup-and-build" with: - path: | - node_modules - packages/*/node_modules - lib/ - packages/*/lib - packages/*/.git-data.json - key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} - fail-on-cache-miss: true + node: ${{ matrix.node }} # Cache validator slashing protection data tests - name: Restore spec tests cache @@ -210,27 +138,14 @@ jobs: steps: # - Uses YAML anchors in the future - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{matrix.node}} - check-latest: true - cache: yarn - - name: Restore build cache - id: cache-primes-restore - uses: actions/cache/restore@v4 + + - uses: "./.github/actions/setup-and-build" with: - path: | - node_modules - packages/*/node_modules - lib/ - packages/*/lib - packages/*/.git-data.json - key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} - fail-on-cache-miss: true + node: ${{ matrix.node }} - - name: Load env variables + - name: Load env variables uses: ./.github/actions/dotenv - + - name: Run the e2e test environment run: scripts/run_e2e_env.sh start @@ -260,23 +175,9 @@ jobs: steps: # - Uses YAML anchors in the future - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: "./.github/actions/setup-and-build" with: - node-version: ${{matrix.node}} - check-latest: true - cache: yarn - - name: Restore build cache - id: cache-primes-restore - uses: actions/cache/restore@v4 - with: - path: | - node_modules - packages/*/node_modules - lib/ - packages/*/lib - packages/*/.git-data.json - key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} - fail-on-cache-miss: true + node: ${{ matrix.node }} - name: Install Chrome browser run: npx @puppeteer/browsers install chromedriver@latest --path /tmp - name: Install Firefox browser @@ -297,23 +198,9 @@ jobs: node: [20] steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: ${{matrix.node}} - check-latest: true - cache: yarn - - name: Restore build cache - id: cache-primes-restore - uses: actions/cache/restore@v4 + - uses: "./.github/actions/setup-and-build" with: - path: | - node_modules - packages/*/node_modules - lib/ - packages/*/lib - packages/*/.git-data.json - key: ${{ runner.os }}-node-${{ matrix.node }}-${{ github.sha }} - fail-on-cache-miss: true + node: ${{ matrix.node }} # Download spec tests with cache - name: Restore spec tests cache From 0e01efded7c607e8f0f9ec213340b2bf21740bb5 Mon Sep 17 00:00:00 2001 From: Julien Date: Fri, 16 Feb 2024 05:37:03 -0800 Subject: [PATCH 58/71] chore: fix prover README typos (#6426) * chore: fix prover README typos * chore: fix typos * chore: address comments * chore: restore beaconBootnodes description --- packages/prover/README.md | 9 ++++----- packages/prover/src/cli/cmds/start/options.ts | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/prover/README.md b/packages/prover/README.md index 0489756a066a..21f167fc43de 100644 --- a/packages/prover/README.md +++ b/packages/prover/README.md @@ -7,7 +7,7 @@ > This package is part of [ChainSafe's Lodestar](https://lodestar.chainsafe.io) project -Typescript REST client for the [Ethereum Consensus API spec](https://github.com/ethereum/beacon-apis) +A set of tools allowing to verify EL client JSON-RPC calls. ## Usage @@ -37,13 +37,12 @@ console.log({balance, address}); You can also invoke the package as binary. ```bash -npm -i g @lodestar/prover +npm i -g @lodestar/prover lodestar-prover proxy \ --network sepolia \ - --execution-rpc https://lodestar-sepoliarpc.chainsafe.io \ - --mode rest \ - --beacon-rpc https://lodestar-sepolia.chainsafe.io \ + --executionRpcUrl https://lodestar-sepoliarpc.chainsafe.io \ + --beaconUrls https://lodestar-sepolia.chainsafe.io \ --port 8080 ``` diff --git a/packages/prover/src/cli/cmds/start/options.ts b/packages/prover/src/cli/cmds/start/options.ts index ac51aac3f17c..af26f6c5ff3d 100644 --- a/packages/prover/src/cli/cmds/start/options.ts +++ b/packages/prover/src/cli/cmds/start/options.ts @@ -53,7 +53,7 @@ export const startOptions: CliCommandOptions = { }, beaconUrls: { - description: "The beacon node PRC urls for 'rest' mode.", + description: "Urls of the beacon nodes to connect to.", type: "string", array: true, conflicts: ["beaconBootnodes"], From 6a68b1e25a296b6cf0c465253a225413e6571077 Mon Sep 17 00:00:00 2001 From: g11tech Date: Fri, 16 Feb 2024 20:37:15 +0530 Subject: [PATCH 59/71] feat: allow blob archival for bigger time periods (#6393) * feat: allow blob archival for bigger time periods * fix spellcheck and spellings * change cli flag and desc --- .../src/chain/archiver/archiveBlocks.ts | 31 ++++++++++++------- .../beacon-node/src/chain/archiver/index.ts | 6 +++- packages/beacon-node/src/chain/options.ts | 1 + .../src/options/beaconNodeOptions/chain.ts | 8 +++++ .../unit/options/beaconNodeOptions.test.ts | 2 ++ 5 files changed, 35 insertions(+), 13 deletions(-) diff --git a/packages/beacon-node/src/chain/archiver/archiveBlocks.ts b/packages/beacon-node/src/chain/archiver/archiveBlocks.ts index 27934a6bae1f..71fa9fb61b2e 100644 --- a/packages/beacon-node/src/chain/archiver/archiveBlocks.ts +++ b/packages/beacon-node/src/chain/archiver/archiveBlocks.ts @@ -35,7 +35,8 @@ export async function archiveBlocks( lightclientServer: LightClientServer, logger: Logger, finalizedCheckpoint: CheckpointHex, - currentEpoch: Epoch + currentEpoch: Epoch, + archiveBlobEpochs?: number ): Promise { // Use fork choice to determine the blocks to archive and delete // getAllAncestorBlocks response includes the finalized block, so it's also moved to the cold db @@ -81,19 +82,25 @@ export async function archiveBlocks( } // Delete expired blobs - // Keep only `[max(GENESIS_EPOCH, current_epoch - MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS), current_epoch]` + // Keep only `[current_epoch - max(MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS, archiveBlobEpochs)] + // if archiveBlobEpochs set to Infinity do not prune` if (finalizedPostDeneb) { - const blobSidecarsMinEpoch = currentEpoch - config.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS; - if (blobSidecarsMinEpoch >= config.DENEB_FORK_EPOCH) { - const slotsToDelete = await db.blobSidecarsArchive.keys({lt: computeStartSlotAtEpoch(blobSidecarsMinEpoch)}); - if (slotsToDelete.length > 0) { - await db.blobSidecarsArchive.batchDelete(slotsToDelete); - logger.verbose( - `blobSidecars prune: batchDelete range ${slotsToDelete[0]}..${slotsToDelete[slotsToDelete.length - 1]}` - ); - } else { - logger.verbose(`blobSidecars prune: no entries before epoch ${blobSidecarsMinEpoch}`); + if (archiveBlobEpochs !== Infinity) { + const blobsArchiveWindow = Math.max(config.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS, archiveBlobEpochs ?? 0); + const blobSidecarsMinEpoch = currentEpoch - blobsArchiveWindow; + if (blobSidecarsMinEpoch >= config.DENEB_FORK_EPOCH) { + const slotsToDelete = await db.blobSidecarsArchive.keys({lt: computeStartSlotAtEpoch(blobSidecarsMinEpoch)}); + if (slotsToDelete.length > 0) { + await db.blobSidecarsArchive.batchDelete(slotsToDelete); + logger.verbose( + `blobSidecars prune: batchDelete range ${slotsToDelete[0]}..${slotsToDelete[slotsToDelete.length - 1]}` + ); + } else { + logger.verbose(`blobSidecars prune: no entries before epoch ${blobSidecarsMinEpoch}`); + } } + } else { + logger.verbose("blobSidecars pruning skipped: archiveBlobEpochs set to Infinity"); } } diff --git a/packages/beacon-node/src/chain/archiver/index.ts b/packages/beacon-node/src/chain/archiver/index.ts index 9c0290bfd8c4..ee0711e05e4b 100644 --- a/packages/beacon-node/src/chain/archiver/index.ts +++ b/packages/beacon-node/src/chain/archiver/index.ts @@ -11,6 +11,7 @@ const PROCESS_FINALIZED_CHECKPOINT_QUEUE_LEN = 256; export type ArchiverOpts = StatesArchiverOpts & { disableArchiveOnCheckpoint?: boolean; + archiveBlobEpochs?: number; }; type ProposalStats = { @@ -37,6 +38,7 @@ export class Archiver { private prevFinalized: CheckpointWithHex; private readonly statesArchiver: StatesArchiver; + private archiveBlobEpochs?: number; constructor( private readonly db: IBeaconDb, @@ -45,6 +47,7 @@ export class Archiver { signal: AbortSignal, opts: ArchiverOpts ) { + this.archiveBlobEpochs = opts.archiveBlobEpochs; this.statesArchiver = new StatesArchiver(chain.regen, db, logger, opts); this.prevFinalized = chain.forkChoice.getFinalizedCheckpoint(); this.jobQueue = new JobItemQueue<[CheckpointWithHex], void>(this.processFinalizedCheckpoint, { @@ -96,7 +99,8 @@ export class Archiver { this.chain.lightClientServer, this.logger, finalized, - this.chain.clock.currentEpoch + this.chain.clock.currentEpoch, + this.archiveBlobEpochs ); this.prevFinalized = finalized; diff --git a/packages/beacon-node/src/chain/options.ts b/packages/beacon-node/src/chain/options.ts index cc7795ade0a1..e687099a0cb4 100644 --- a/packages/beacon-node/src/chain/options.ts +++ b/packages/beacon-node/src/chain/options.ts @@ -30,6 +30,7 @@ export type IChainOptions = BlockProcessOpts & trustedSetup?: string; broadcastValidationStrictness?: string; minSameMessageSignatureSetsToBatch: number; + archiveBlobEpochs?: number; }; export type BlockProcessOpts = { diff --git a/packages/cli/src/options/beaconNodeOptions/chain.ts b/packages/cli/src/options/beaconNodeOptions/chain.ts index 0c9280f5330c..a324e3060e1f 100644 --- a/packages/cli/src/options/beaconNodeOptions/chain.ts +++ b/packages/cli/src/options/beaconNodeOptions/chain.ts @@ -26,6 +26,7 @@ export type ChainArgs = { broadcastValidationStrictness?: string; "chain.minSameMessageSignatureSetsToBatch"?: number; "chain.maxShufflingCacheEpochs"?: number; + "chain.archiveBlobEpochs"?: number; }; export function parseArgs(args: ChainArgs): IBeaconNodeOptions["chain"] { @@ -53,6 +54,7 @@ export function parseArgs(args: ChainArgs): IBeaconNodeOptions["chain"] { minSameMessageSignatureSetsToBatch: args["chain.minSameMessageSignatureSetsToBatch"] ?? defaultOptions.chain.minSameMessageSignatureSetsToBatch, maxShufflingCacheEpochs: args["chain.maxShufflingCacheEpochs"] ?? defaultOptions.chain.maxShufflingCacheEpochs, + archiveBlobEpochs: args["chain.archiveBlobEpochs"], }; } @@ -212,4 +214,10 @@ Will double processing times. Use only for debugging purposes.", default: defaultOptions.chain.maxShufflingCacheEpochs, group: "chain", }, + + "chain.archiveBlobEpochs": { + description: "Number of epochs to retain finalized blobs (minimum of MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS)", + type: "number", + group: "chain", + }, }; diff --git a/packages/cli/test/unit/options/beaconNodeOptions.test.ts b/packages/cli/test/unit/options/beaconNodeOptions.test.ts index 8a9ccff5a917..22faea094314 100644 --- a/packages/cli/test/unit/options/beaconNodeOptions.test.ts +++ b/packages/cli/test/unit/options/beaconNodeOptions.test.ts @@ -36,6 +36,7 @@ describe("options / beaconNodeOptions", () => { "chain.trustedSetup": "", "chain.minSameMessageSignatureSetsToBatch": 32, "chain.maxShufflingCacheEpochs": 100, + "chain.archiveBlobEpochs": 10000, emitPayloadAttributes: false, eth1: true, @@ -139,6 +140,7 @@ describe("options / beaconNodeOptions", () => { trustedSetup: "", minSameMessageSignatureSetsToBatch: 32, maxShufflingCacheEpochs: 100, + archiveBlobEpochs: 10000, }, eth1: { enabled: true, From 227930cdf61d266d25df466ea08a53a955114a5b Mon Sep 17 00:00:00 2001 From: Julien Date: Fri, 16 Feb 2024 07:21:42 -0800 Subject: [PATCH 60/71] chore: remove not yet relevant prover options (#6440) --- packages/prover/src/cli/cmds/start/handler.ts | 12 ++-------- packages/prover/src/cli/cmds/start/options.ts | 20 +++-------------- .../prover/test/e2e/cli/cmds/start.test.ts | 22 ++----------------- 3 files changed, 7 insertions(+), 47 deletions(-) diff --git a/packages/prover/src/cli/cmds/start/handler.ts b/packages/prover/src/cli/cmds/start/handler.ts index 5f13db0cfcb6..92922f1a45a4 100644 --- a/packages/prover/src/cli/cmds/start/handler.ts +++ b/packages/prover/src/cli/cmds/start/handler.ts @@ -1,5 +1,4 @@ import {ChainConfig, chainConfigFromJson} from "@lodestar/config"; -import {LCTransport} from "../../../interfaces.js"; import {readFile} from "../../../utils/file.js"; import {createVerifiedExecutionProxy, VerifiedProxyOptions} from "../../../web3_proxy.js"; import {GlobalArgs, parseGlobalArgs} from "../../options.js"; @@ -11,25 +10,18 @@ import {parseStartArgs, StartArgs} from "./options.js"; export async function proverProxyStartHandler(args: StartArgs & GlobalArgs): Promise { const {network, logLevel, paramsFile} = parseGlobalArgs(args); const opts = parseStartArgs(args); - const {executionRpcUrl, port, wsCheckpoint} = opts; const config: Partial = paramsFile ? chainConfigFromJson(readFile(paramsFile)) : {}; const options: VerifiedProxyOptions = { + ...opts, logLevel, - executionRpcUrl, - wsCheckpoint, - unverifiedWhitelist: opts.unverifiedWhitelist, - requestTimeout: opts.requestTimeout, ...(network ? {network} : {config}), - ...(opts.transport === LCTransport.Rest - ? {transport: LCTransport.Rest, urls: opts.urls} - : {transport: LCTransport.P2P, bootnodes: opts.bootnodes}), }; const {server, proofProvider} = createVerifiedExecutionProxy(options); - server.listen(port); + server.listen(opts.port); await proofProvider.waitToBeReady(); } diff --git a/packages/prover/src/cli/cmds/start/options.ts b/packages/prover/src/cli/cmds/start/options.ts index af26f6c5ff3d..53ff5957765b 100644 --- a/packages/prover/src/cli/cmds/start/options.ts +++ b/packages/prover/src/cli/cmds/start/options.ts @@ -7,7 +7,6 @@ export type StartArgs = { port: number; executionRpcUrl: string; beaconUrls?: string[]; - beaconBootnodes?: string[]; wsCheckpoint?: string; unverifiedWhitelist?: string[]; requestTimeout: number; @@ -19,7 +18,7 @@ export type StartOptions = { wsCheckpoint?: string; unverifiedWhitelist?: string[]; requestTimeout: number; -} & ({transport: LCTransport.Rest; urls: string[]} | {transport: LCTransport.P2P; bootnodes: string[]}); +} & {transport: LCTransport.Rest; urls: string[]}; export const startOptions: CliCommandOptions = { port: { @@ -55,16 +54,8 @@ export const startOptions: CliCommandOptions = { beaconUrls: { description: "Urls of the beacon nodes to connect to.", type: "string", + demandOption: true, array: true, - conflicts: ["beaconBootnodes"], - group: "beacon", - }, - - beaconBootnodes: { - description: "The beacon node PRC urls for 'p2p' mode.", - type: "string", - array: true, - conflicts: ["beaconUrls"], group: "beacon", }, @@ -78,17 +69,12 @@ export const startOptions: CliCommandOptions = { }; export function parseStartArgs(args: StartArgs): StartOptions { - if (!args.beaconUrls && !args.beaconBootnodes) { - throw new Error("Either --beaconUrls or --beaconBootnodes must be provided"); - } - // Remove undefined values to allow deepmerge to inject default values downstream return { port: args.port, executionRpcUrl: args.executionRpcUrl, - transport: args.beaconUrls ? LCTransport.Rest : LCTransport.P2P, + transport: LCTransport.Rest, urls: args.beaconUrls ?? [], - bootnodes: args.beaconBootnodes ?? [], wsCheckpoint: args.wsCheckpoint, unverifiedWhitelist: args.unverifiedWhitelist, requestTimeout: args.requestTimeout ?? DEFAULT_PROXY_REQUEST_TIMEOUT, diff --git a/packages/prover/test/e2e/cli/cmds/start.test.ts b/packages/prover/test/e2e/cli/cmds/start.test.ts index a5ac299612e7..8ac71e1a1797 100644 --- a/packages/prover/test/e2e/cli/cmds/start.test.ts +++ b/packages/prover/test/e2e/cli/cmds/start.test.ts @@ -18,30 +18,12 @@ describe("prover/proxy", () => { expect(output).toEqual(expect.stringContaining("Show help")); }); - it("should fail when --executionRpcUrl is missing", async () => { + it("should fail when --executionRpcUrl and --beaconUrls are missing", async () => { await expect(runCliCommand(cli, ["proxy", "--port", "8088"])).rejects.toThrow( - "Missing required argument: executionRpcUrl" + "Missing required arguments: executionRpcUrl, beaconUrls" ); }); - it("should fail when --beaconUrls and --beaconBootnodes are provided together", async () => { - await expect( - runCliCommand(cli, [ - "proxy", - "--beaconUrls", - "http://localhost:4000", - "--beaconBootnodes", - "http://localhost:0000", - ]) - ).rejects.toThrow("Arguments beaconBootnodes and beaconUrls are mutually exclusive"); - }); - - it("should fail when both of --beaconUrls and --beaconBootnodes are not provided", async () => { - await expect( - runCliCommand(cli, ["proxy", "--port", "8088", "--executionRpcUrl", "http://localhost:3000"]) - ).rejects.toThrow("Either --beaconUrls or --beaconBootnodes must be provided"); - }); - describe("when started", () => { let proc: childProcess.ChildProcess | null = null; const paramsFilePath = path.join("/tmp", "e2e-test-env", "params.json"); From 194334626e5a43350ea710c336aa65bcb7104989 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Sat, 17 Feb 2024 15:22:36 +0100 Subject: [PATCH 61/71] chore: remove unused eslint disable directives (#6444) * Remove unused eslint disable directives * Update yarn lint to report unused eslint disable directives --- package.json | 2 +- packages/api/src/utils/server/types.ts | 2 -- packages/api/test/unit/beacon/testData/events.ts | 2 +- packages/api/test/utils/utils.ts | 4 ++-- packages/beacon-node/src/network/core/networkCoreWorker.ts | 1 - packages/beacon-node/src/network/peers/score/score.ts | 2 -- .../beacon-node/src/network/reqresp/ReqRespBeaconNode.ts | 1 - packages/beacon-node/src/util/kzg.ts | 4 ++-- .../test/e2e/network/onWorker/workerEchoHandler.ts | 1 - .../beacon-node/test/e2e/network/peers/peerManager.test.ts | 1 - packages/beacon-node/test/e2e/network/reqresp.test.ts | 6 +----- packages/beacon-node/test/e2e/network/reqrespEncode.test.ts | 2 +- packages/beacon-node/test/e2e/sync/finalizedSync.test.ts | 1 - packages/beacon-node/test/mocks/mockedBeaconDb.ts | 1 - .../test/perf/chain/produceBlock/produceBlockBody.test.ts | 1 - .../test/perf/chain/validation/attestation.test.ts | 1 - .../beacon-node/test/perf/chain/verifyImportBlocks.test.ts | 1 - packages/beacon-node/test/sim/4844-interop.test.ts | 1 - packages/beacon-node/test/sim/merge-interop.test.ts | 3 --- packages/beacon-node/test/sim/mergemock.test.ts | 1 - packages/beacon-node/test/sim/withdrawal-interop.test.ts | 2 -- packages/beacon-node/test/spec/presets/fork_choice.test.ts | 2 -- packages/beacon-node/test/spec/presets/light_client/sync.ts | 1 - .../test/spec/presets/light_client/update_ranking.ts | 1 - packages/beacon-node/test/spec/presets/ssz_static.test.ts | 1 - .../beacon-node/test/unit/api/impl/beacon/beacon.test.ts | 1 - .../validateGossipAttestationsSameAttData.test.ts | 1 - .../chain/validation/lightClientOptimisticUpdate.test.ts | 1 - packages/beacon-node/test/unit/network/reqresp/utils.ts | 3 --- packages/beacon-node/test/unit/sync/range/chain.test.ts | 2 -- packages/beacon-node/test/utils/api.ts | 1 - packages/beacon-node/test/utils/networkWithMockDb.ts | 1 - packages/beacon-node/test/utils/node/beacon.ts | 1 - packages/beacon-node/test/utils/node/validator.ts | 1 - packages/cli/src/applyPreset.ts | 4 ++-- packages/cli/src/util/command.ts | 1 - packages/cli/test/utils/simulation/SimulationEnvironment.ts | 1 - .../cli/test/utils/simulation/beacon_clients/lighthouse.ts | 1 - packages/cli/test/utils/simulation/interfaces.ts | 1 - packages/cli/test/utils/simulation/runner/DockerRunner.ts | 1 - .../test/utils/simulation/validator_clients/lighthouse.ts | 1 - packages/flare/src/util/command.ts | 1 - packages/light-client/src/spec/utils.ts | 1 - packages/light-client/src/utils/logger.ts | 1 - packages/light-client/test/utils/server.ts | 4 ++-- packages/logger/src/node.ts | 2 +- packages/logger/src/utils/format.ts | 2 -- packages/logger/src/winston.ts | 6 +++--- packages/logger/test/e2e/logger/workerLoggerHandler.ts | 1 - packages/logger/test/unit/utils/json.test.ts | 4 ---- packages/prover/src/utils/command.ts | 1 - packages/prover/test/e2e/web3_batch_request.test.ts | 1 - packages/prover/test/e2e/web3_provider.test.ts | 1 - packages/reqresp/src/ReqResp.ts | 2 -- packages/reqresp/test/fixtures/messages.ts | 1 - packages/reqresp/test/unit/encoders/responseDecode.test.ts | 2 -- packages/reqresp/test/utils/index.ts | 3 --- packages/reqresp/test/utils/response.ts | 6 +----- packages/spec-test-util/src/downloadTests.ts | 3 +-- packages/utils/src/sleep.ts | 1 - packages/utils/test/unit/err.test.ts | 3 --- packages/validator/test/utils/clock.ts | 1 - 62 files changed, 18 insertions(+), 96 deletions(-) diff --git a/package.json b/package.json index 6dd34d2e9399..38c78a7456f7 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "build": "lerna run build", "build:watch": "lerna exec --parallel -- 'yarn run build:watch'", "build:ifchanged": "lerna exec -- ../../scripts/build_if_changed.sh", - "lint": "eslint --color --ext .ts packages/*/src packages/*/test", + "lint": "eslint --report-unused-disable-directives --color --ext .ts packages/*/src packages/*/test", "lint:fix": "yarn lint --fix", "lint-dashboards": "node scripts/lint-grafana-dashboards.mjs ./dashboards", "check-build": "lerna run check-build", diff --git a/packages/api/src/utils/server/types.ts b/packages/api/src/utils/server/types.ts index 0e2d5201f51c..ba5f54cc96a3 100644 --- a/packages/api/src/utils/server/types.ts +++ b/packages/api/src/utils/server/types.ts @@ -1,6 +1,4 @@ -// eslint-disable-next-line import/no-extraneous-dependencies import type {FastifyInstance, FastifyContextConfig} from "fastify"; -// eslint-disable-next-line import/no-extraneous-dependencies import type * as fastify from "fastify"; import {ReqGeneric} from "../types.js"; diff --git a/packages/api/test/unit/beacon/testData/events.ts b/packages/api/test/unit/beacon/testData/events.ts index 08dd27e09d76..f4962bc1827a 100644 --- a/packages/api/test/unit/beacon/testData/events.ts +++ b/packages/api/test/unit/beacon/testData/events.ts @@ -5,7 +5,7 @@ import {GenericServerTestCases} from "../../../utils/genericServerTest.js"; const abortController = new AbortController(); -/* eslint-disable @typescript-eslint/no-empty-function, @typescript-eslint/naming-convention */ +/* eslint-disable @typescript-eslint/naming-convention */ export const testData: GenericServerTestCases = { eventstream: { diff --git a/packages/api/test/utils/utils.ts b/packages/api/test/utils/utils.ts index ced8cd5b7639..b261ae54920f 100644 --- a/packages/api/test/utils/utils.ts +++ b/packages/api/test/utils/utils.ts @@ -1,5 +1,5 @@ import {MockedObject, vi} from "vitest"; -import qs from "qs"; +import {parse as parseQueryString} from "qs"; import {FastifyInstance, fastify} from "fastify"; import {mapValues} from "@lodestar/utils"; import {ServerApi} from "../../src/interfaces.js"; @@ -7,7 +7,7 @@ import {ServerApi} from "../../src/interfaces.js"; export function getTestServer(): {server: FastifyInstance; start: () => Promise} { const server = fastify({ ajv: {customOptions: {coerceTypes: "array"}}, - querystringParser: (str) => qs.parse(str, {comma: true, parseArrays: false}), + querystringParser: (str) => parseQueryString(str, {comma: true, parseArrays: false}), }); server.addHook("onError", (request, reply, error, done) => { diff --git a/packages/beacon-node/src/network/core/networkCoreWorker.ts b/packages/beacon-node/src/network/core/networkCoreWorker.ts index 2cbef57a16a2..1df348335582 100644 --- a/packages/beacon-node/src/network/core/networkCoreWorker.ts +++ b/packages/beacon-node/src/network/core/networkCoreWorker.ts @@ -30,7 +30,6 @@ const workerData = worker.workerData as NetworkWorkerData; const parentPort = worker.parentPort; // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!workerData) throw Error("workerData must be defined"); -// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!parentPort) throw Error("parentPort must be defined"); const config = createBeaconConfig(chainConfigFromJson(workerData.chainConfigJson), workerData.genesisValidatorsRoot); diff --git a/packages/beacon-node/src/network/peers/score/score.ts b/packages/beacon-node/src/network/peers/score/score.ts index a5617ab9fea5..a949bf5d43d1 100644 --- a/packages/beacon-node/src/network/peers/score/score.ts +++ b/packages/beacon-node/src/network/peers/score/score.ts @@ -139,14 +139,12 @@ export class MaxScore implements IPeerScore { return DEFAULT_SCORE; } - // eslint-disable-next-line @typescript-eslint/no-empty-function add(): void {} update(): number { return MAX_SCORE; } - // eslint-disable-next-line @typescript-eslint/no-empty-function updateGossipsubScore(): void {} getStat(): PeerScoreStat { diff --git a/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts b/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts index 5aea63fb9fe3..2a20a3f1f7fd 100644 --- a/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts +++ b/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts @@ -212,7 +212,6 @@ export class ReqRespBeaconNode extends ReqResp { * Any protocol not in this list must be un-subscribed. */ private getProtocolsAtFork(fork: ForkName): [ProtocolNoHandler, ProtocolHandler][] { - // eslint-disable-next-line @typescript-eslint/no-explicit-any const protocolsAtFork: [ProtocolNoHandler, ProtocolHandler][] = [ [protocols.Ping(this.config), this.onPing.bind(this)], [protocols.Status(this.config), this.onStatus.bind(this)], diff --git a/packages/beacon-node/src/util/kzg.ts b/packages/beacon-node/src/util/kzg.ts index d366a00ccc3a..e20a379d62ff 100644 --- a/packages/beacon-node/src/util/kzg.ts +++ b/packages/beacon-node/src/util/kzg.ts @@ -43,10 +43,10 @@ const G2POINT_COUNT = 65; const TOTAL_SIZE = 2 * POINT_COUNT_BYTES + G1POINT_BYTES * G1POINT_COUNT + G2POINT_BYTES * G2POINT_COUNT; export async function initCKZG(): Promise { - /* eslint-disable import/no-extraneous-dependencies, @typescript-eslint/ban-ts-comment */ + /* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-ignore ckzg = (await import("c-kzg")).default as typeof ckzg; - /* eslint-enable import/no-extraneous-dependencies, @typescript-eslint/ban-ts-comment */ + /* eslint-enable @typescript-eslint/ban-ts-comment */ } export enum TrustedFileMode { diff --git a/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts b/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts index cfd1629065a8..b2c0f6b56aa0 100644 --- a/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts +++ b/packages/beacon-node/test/e2e/network/onWorker/workerEchoHandler.ts @@ -10,7 +10,6 @@ export async function getEchoWorker(): Promise { const workerThreadjs = new Worker("./workerEcho.js"); const worker = workerThreadjs as unknown as workerThreads.Worker; - // eslint-disable-next-line @typescript-eslint/no-explicit-any await spawn(workerThreadjs, { // A Lodestar Node may do very expensive task at start blocking the event loop and causing // the initialization to timeout. The number below is big enough to almost disable the timeout diff --git a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts index 8eb0ecdd1ba4..795a4bf67ecc 100644 --- a/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts +++ b/packages/beacon-node/test/e2e/network/peers/peerManager.test.ts @@ -58,7 +58,6 @@ describe("network / peers / PeerManager", function () { const reqResp = new ReqRespFake(); const peerRpcScores = new PeerRpcScoreStore(); const networkEventBus = new NetworkEventBus(); - /* eslint-disable @typescript-eslint/no-empty-function */ const mockSubnetsService: IAttnetsService = { getActiveSubnets: () => [], shouldProcess: () => true, diff --git a/packages/beacon-node/test/e2e/network/reqresp.test.ts b/packages/beacon-node/test/e2e/network/reqresp.test.ts index 855dc7046203..38b5cda4db5f 100644 --- a/packages/beacon-node/test/e2e/network/reqresp.test.ts +++ b/packages/beacon-node/test/e2e/network/reqresp.test.ts @@ -13,11 +13,7 @@ import {arrToSource} from "../../unit/network/reqresp/utils.js"; import {GetReqRespHandlerFn, ReqRespMethod} from "../../../src/network/reqresp/types.js"; import {PeerIdStr} from "../../../src/util/peerId.js"; -/* eslint-disable - require-yield, - @typescript-eslint/naming-convention, - @typescript-eslint/explicit-function-return-type -*/ +/* eslint-disable require-yield, @typescript-eslint/naming-convention */ describe( "network / reqresp / main thread", diff --git a/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts b/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts index 74ad3533479b..d96f405eae7c 100644 --- a/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts +++ b/packages/beacon-node/test/e2e/network/reqrespEncode.test.ts @@ -22,7 +22,7 @@ import {testLogger} from "../../utils/logger.js"; import {GetReqRespHandlerFn} from "../../../src/network/reqresp/types.js"; import {LocalStatusCache} from "../../../src/network/statusCache.js"; -/* eslint-disable require-yield, @typescript-eslint/naming-convention */ +/* eslint-disable require-yield */ describe("reqresp encoder", () => { let port = 60000; diff --git a/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts b/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts index d3d06f1fc070..fcfe3b5156dc 100644 --- a/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts +++ b/packages/beacon-node/test/e2e/sync/finalizedSync.test.ts @@ -34,7 +34,6 @@ describe( it("should do a finalized sync from another BN", async function () { // single node at beginning, use main thread to verify bls const genesisSlotsDelay = 4; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const genesisTime = Math.floor(Date.now() / 1000) + genesisSlotsDelay * testParams.SECONDS_PER_SLOT; const testLoggerOpts: TestLoggerOpts = { diff --git a/packages/beacon-node/test/mocks/mockedBeaconDb.ts b/packages/beacon-node/test/mocks/mockedBeaconDb.ts index 4f5f494a0f40..8b99c85d2345 100644 --- a/packages/beacon-node/test/mocks/mockedBeaconDb.ts +++ b/packages/beacon-node/test/mocks/mockedBeaconDb.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ import {vi, Mocked} from "vitest"; import {config as minimalConfig} from "@lodestar/config/default"; import { diff --git a/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts b/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts index dbe86c2c5868..96dda3acaece 100644 --- a/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts +++ b/packages/beacon-node/test/perf/chain/produceBlock/produceBlockBody.test.ts @@ -41,7 +41,6 @@ describe("produceBlockBody", () => { config: state.config, db, logger, - // eslint-disable-next-line @typescript-eslint/no-empty-function processShutdownCallback: () => {}, metrics: null, anchorState: state, diff --git a/packages/beacon-node/test/perf/chain/validation/attestation.test.ts b/packages/beacon-node/test/perf/chain/validation/attestation.test.ts index ed5c17ed890b..5fce9a342509 100644 --- a/packages/beacon-node/test/perf/chain/validation/attestation.test.ts +++ b/packages/beacon-node/test/perf/chain/validation/attestation.test.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/no-relative-packages import {itBench, setBenchOpts} from "@dapplion/benchmark"; import {expect} from "chai"; import {ssz} from "@lodestar/types"; diff --git a/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts b/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts index 923436d6f96d..41d8aa76865b 100644 --- a/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts +++ b/packages/beacon-node/test/perf/chain/verifyImportBlocks.test.ts @@ -97,7 +97,6 @@ describe.skip("verify+import blocks - range sync perf test", () => { config: state.config, db, logger, - // eslint-disable-next-line @typescript-eslint/no-empty-function processShutdownCallback: () => {}, metrics: null, anchorState: state, diff --git a/packages/beacon-node/test/sim/4844-interop.test.ts b/packages/beacon-node/test/sim/4844-interop.test.ts index d6de49e32eff..23a01bf1bb33 100644 --- a/packages/beacon-node/test/sim/4844-interop.test.ts +++ b/packages/beacon-node/test/sim/4844-interop.test.ts @@ -65,7 +65,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { } }); - // eslint-disable-next-line vitest/expect-expect it("Post-merge, run for a few blocks", async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( diff --git a/packages/beacon-node/test/sim/merge-interop.test.ts b/packages/beacon-node/test/sim/merge-interop.test.ts index 9467c53831c8..59bb28879b12 100644 --- a/packages/beacon-node/test/sim/merge-interop.test.ts +++ b/packages/beacon-node/test/sim/merge-interop.test.ts @@ -86,7 +86,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { } }); - // eslint-disable-next-line vitest/expect-expect it("Send stub payloads to EL", async () => { const {elClient, tearDownCallBack} = await runEL( {...elSetupConfig, mode: ELStartMode.PostMerge}, @@ -203,7 +202,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { */ }); - // eslint-disable-next-line vitest/expect-expect it("Post-merge, run for a few blocks", async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( @@ -220,7 +218,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { }); }); - // eslint-disable-next-line vitest/expect-expect it("Pre-merge, run for a few blocks", async function () { console.log("\n\nPre-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( diff --git a/packages/beacon-node/test/sim/mergemock.test.ts b/packages/beacon-node/test/sim/mergemock.test.ts index 97a9d9f2aaf7..4cce95967c55 100644 --- a/packages/beacon-node/test/sim/mergemock.test.ts +++ b/packages/beacon-node/test/sim/mergemock.test.ts @@ -64,7 +64,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { }); for (const useProduceBlockV3 of [false, true]) { - // eslint-disable-next-line vitest/expect-expect it(`Test builder with useProduceBlockV3=${useProduceBlockV3}`, async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( diff --git a/packages/beacon-node/test/sim/withdrawal-interop.test.ts b/packages/beacon-node/test/sim/withdrawal-interop.test.ts index 6fdd4fd5a0ce..4f8efa71dce3 100644 --- a/packages/beacon-node/test/sim/withdrawal-interop.test.ts +++ b/packages/beacon-node/test/sim/withdrawal-interop.test.ts @@ -70,7 +70,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { } }); - // eslint-disable-next-line vitest/expect-expect it("Send stub payloads to EL", async () => { const {elClient, tearDownCallBack} = await runEL( {...elSetupConfig, mode: ELStartMode.PostMerge, genesisTemplate: "genesisPostWithdraw.tmpl"}, @@ -185,7 +184,6 @@ describe("executionEngine / ExecutionEngineHttp", function () { ); }); - // eslint-disable-next-line vitest/expect-expect it("Post-merge, run for a few blocks", async function () { console.log("\n\nPost-merge, run for a few blocks\n\n"); const {elClient, tearDownCallBack} = await runEL( diff --git a/packages/beacon-node/test/spec/presets/fork_choice.test.ts b/packages/beacon-node/test/spec/presets/fork_choice.test.ts index b0ad63a68205..49d78cc42f6a 100644 --- a/packages/beacon-node/test/spec/presets/fork_choice.test.ts +++ b/packages/beacon-node/test/spec/presets/fork_choice.test.ts @@ -101,7 +101,6 @@ const forkChoiceTest = config: createBeaconConfig(config, state.genesisValidatorsRoot), db: getMockedBeaconDb(), logger, - // eslint-disable-next-line @typescript-eslint/no-empty-function processShutdownCallback: () => {}, clock, metrics: null, @@ -367,7 +366,6 @@ const forkChoiceTest = }; }, timeout: 10000, - // eslint-disable-next-line @typescript-eslint/no-empty-function expectFunc: () => {}, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts // EXCEPTION : this test skipped here because prefix match can't be don't for this particular test diff --git a/packages/beacon-node/test/spec/presets/light_client/sync.ts b/packages/beacon-node/test/spec/presets/light_client/sync.ts index e48bb0f361a3..84ab2c28b467 100644 --- a/packages/beacon-node/test/spec/presets/light_client/sync.ts +++ b/packages/beacon-node/test/spec/presets/light_client/sync.ts @@ -191,7 +191,6 @@ export const sync: TestRunnerFn = (fork) => { } as SyncTestCase; }, timeout: 10000, - // eslint-disable-next-line @typescript-eslint/no-empty-function expectFunc: () => {}, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts }, diff --git a/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts b/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts index c4b5b7623d85..9a38ddf36c8c 100644 --- a/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts +++ b/packages/beacon-node/test/spec/presets/light_client/update_ranking.ts @@ -57,7 +57,6 @@ newUpdate = ${renderUpdate(newUpdate)} ? ssz.allForksLightClient[fork].LightClientUpdate : ssz.altair.LightClientUpdate, }, - // eslint-disable-next-line @typescript-eslint/no-empty-function expectFunc: () => {}, // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts }, diff --git a/packages/beacon-node/test/spec/presets/ssz_static.test.ts b/packages/beacon-node/test/spec/presets/ssz_static.test.ts index b721fced69a9..bcab25acde4c 100644 --- a/packages/beacon-node/test/spec/presets/ssz_static.test.ts +++ b/packages/beacon-node/test/spec/presets/ssz_static.test.ts @@ -60,7 +60,6 @@ const sszStatic = for (const testCase of fs.readdirSync(testSuiteDirpath)) { // Do not manually skip tests here, do it in packages/beacon-node/test/spec/presets/index.test.ts - // eslint-disable-next-line vitest/consistent-test-it it(testCase, function () { // Mainnet must deal with big full states and hash each one multiple times if (ACTIVE_PRESET === "mainnet") { diff --git a/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts b/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts index 28c8fe652e8a..28df366a0cde 100644 --- a/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts +++ b/packages/beacon-node/test/unit/api/impl/beacon/beacon.test.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ import {describe, it, expect, beforeAll} from "vitest"; import {ApiTestModules, getApiTestModules} from "../../../../utils/api.js"; import {getBeaconApi} from "../../../../../src/api/impl/beacon/index.js"; diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts index 29b9ba3e1912..cc6dc26f1a36 100644 --- a/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts @@ -4,7 +4,6 @@ import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; import {ForkName} from "@lodestar/params"; import {SignatureSetType} from "@lodestar/state-transition"; import {ssz} from "@lodestar/types"; -// eslint-disable-next-line import/no-relative-packages import {BlsSingleThreadVerifier} from "../../../../../src/chain/bls/singleThread.js"; import {AttestationError, AttestationErrorCode, GossipAction} from "../../../../../src/chain/errors/index.js"; import {IBeaconChain} from "../../../../../src/chain/index.js"; diff --git a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts index 304db1365fb1..386a08641273 100644 --- a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts @@ -9,7 +9,6 @@ import {getMockedBeaconChain} from "../../../mocks/mockedBeaconChain.js"; describe("Light Client Optimistic Update validation", function () { const afterEachCallbacks: (() => Promise | void)[] = []; - // eslint-disable-next-line @typescript-eslint/naming-convention const config = createChainForkConfig({ ...defaultChainConfig, /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/packages/beacon-node/test/unit/network/reqresp/utils.ts b/packages/beacon-node/test/unit/network/reqresp/utils.ts index a1a1a6c69bd2..231bd0cc42fb 100644 --- a/packages/beacon-node/test/unit/network/reqresp/utils.ts +++ b/packages/beacon-node/test/unit/network/reqresp/utils.ts @@ -56,11 +56,8 @@ export class MockLibP2pStream implements Stream { this.resultChunks.push(chunk.subarray()); } }; - // eslint-disable-next-line @typescript-eslint/no-empty-function close: Stream["close"] = async () => {}; - // eslint-disable-next-line @typescript-eslint/no-empty-function closeRead = async (): Promise => {}; - // eslint-disable-next-line @typescript-eslint/no-empty-function closeWrite = async (): Promise => {}; abort: Stream["abort"] = () => this.close(); } diff --git a/packages/beacon-node/test/unit/sync/range/chain.test.ts b/packages/beacon-node/test/unit/sync/range/chain.test.ts index a4cc54b21d11..5af96f0f1729 100644 --- a/packages/beacon-node/test/unit/sync/range/chain.test.ts +++ b/packages/beacon-node/test/unit/sync/range/chain.test.ts @@ -57,7 +57,6 @@ describe("sync / range / chain", () => { const zeroBlockBody = ssz.phase0.BeaconBlockBody.defaultValue(); const interval: NodeJS.Timeout | null = null; - // eslint-disable-next-line @typescript-eslint/no-empty-function const reportPeer: SyncChainFns["reportPeer"] = () => {}; afterEach(() => { @@ -124,7 +123,6 @@ describe("sync / range / chain", () => { const targetEpoch = 16; const peers = [peer]; - // eslint-disable-next-line @typescript-eslint/no-empty-function const processChainSegment: SyncChainFns["processChainSegment"] = async () => {}; const downloadBeaconBlocksByRange: SyncChainFns["downloadBeaconBlocksByRange"] = async (peer, request) => { const blocks: BlockInput[] = []; diff --git a/packages/beacon-node/test/utils/api.ts b/packages/beacon-node/test/utils/api.ts index 41face1ae737..7429ac79189e 100644 --- a/packages/beacon-node/test/utils/api.ts +++ b/packages/beacon-node/test/utils/api.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import {Mocked} from "vitest"; import {config} from "@lodestar/config/default"; import {ForkChoice} from "@lodestar/fork-choice"; diff --git a/packages/beacon-node/test/utils/networkWithMockDb.ts b/packages/beacon-node/test/utils/networkWithMockDb.ts index 3eea47892a0f..f8a4a6181d2f 100644 --- a/packages/beacon-node/test/utils/networkWithMockDb.ts +++ b/packages/beacon-node/test/utils/networkWithMockDb.ts @@ -59,7 +59,6 @@ export async function getNetworkForTest( config: beaconConfig, db, logger, - // eslint-disable-next-line @typescript-eslint/no-empty-function processShutdownCallback: () => {}, // set genesis time so that we are at ALTAIR_FORK_EPOCH // mock timer does not work on worker thread diff --git a/packages/beacon-node/test/utils/node/beacon.ts b/packages/beacon-node/test/utils/node/beacon.ts index 8c1ae9503b7c..0163fa148102 100644 --- a/packages/beacon-node/test/utils/node/beacon.ts +++ b/packages/beacon-node/test/utils/node/beacon.ts @@ -92,7 +92,6 @@ export async function getDevBeaconNode( config: beaconConfig, db, logger, - // eslint-disable-next-line @typescript-eslint/no-empty-function processShutdownCallback: () => {}, peerId, peerStoreDir, diff --git a/packages/beacon-node/test/utils/node/validator.ts b/packages/beacon-node/test/utils/node/validator.ts index dfa627383306..ce81fc6d18ca 100644 --- a/packages/beacon-node/test/utils/node/validator.ts +++ b/packages/beacon-node/test/utils/node/validator.ts @@ -70,7 +70,6 @@ export async function getAndInitDevValidators({ api: useRestApi ? getNodeApiUrl(node) : getApiFromServerHandlers(node.api), slashingProtection, logger, - // eslint-disable-next-line @typescript-eslint/no-empty-function processShutdownCallback: () => {}, abortController, signers, diff --git a/packages/cli/src/applyPreset.ts b/packages/cli/src/applyPreset.ts index 760c18dbbcd7..25f78b7d32ac 100644 --- a/packages/cli/src/applyPreset.ts +++ b/packages/cli/src/applyPreset.ts @@ -1,8 +1,8 @@ // MUST import this file first before anything and not import any Lodestar code. -// eslint-disable-next-line no-restricted-imports, import/no-extraneous-dependencies +// eslint-disable-next-line no-restricted-imports import {hasher} from "@chainsafe/persistent-merkle-tree/lib/hasher/as-sha256.js"; -// eslint-disable-next-line no-restricted-imports, import/no-extraneous-dependencies +// eslint-disable-next-line no-restricted-imports import {setHasher} from "@chainsafe/persistent-merkle-tree/lib/hasher/index.js"; // without setting this first, persistent-merkle-tree will use noble instead diff --git a/packages/cli/src/util/command.ts b/packages/cli/src/util/command.ts index 760a1e2521a2..ccc8f47e71a9 100644 --- a/packages/cli/src/util/command.ts +++ b/packages/cli/src/util/command.ts @@ -68,7 +68,6 @@ export function registerCommandToYargs(yargs: Argv, cliCommand: CliCommand & { - // eslint-disable-next-line @typescript-eslint/naming-convention lighthouse: { getPeers(): Promise<{ status: number; diff --git a/packages/cli/test/utils/simulation/runner/DockerRunner.ts b/packages/cli/test/utils/simulation/runner/DockerRunner.ts index 7658e198a738..999f970c05a4 100644 --- a/packages/cli/test/utils/simulation/runner/DockerRunner.ts +++ b/packages/cli/test/utils/simulation/runner/DockerRunner.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ import {ChildProcess} from "node:child_process"; import {sleep} from "@lodestar/utils"; import { diff --git a/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts b/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts index a663fd0026c6..8df15a3ec85b 100644 --- a/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts +++ b/packages/cli/test/utils/simulation/validator_clients/lighthouse.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/naming-convention */ import path from "node:path"; import {writeFile} from "node:fs/promises"; import got, {RequestError} from "got"; diff --git a/packages/flare/src/util/command.ts b/packages/flare/src/util/command.ts index 81a3993f3c43..f01d9f7ab17b 100644 --- a/packages/flare/src/util/command.ts +++ b/packages/flare/src/util/command.ts @@ -47,7 +47,6 @@ export function registerCommandToYargs(yargs: Argv, cliCommand: CliCommand {}, }; } diff --git a/packages/light-client/test/utils/server.ts b/packages/light-client/test/utils/server.ts index 2bbc7350b22a..5fe1dd623ccb 100644 --- a/packages/light-client/test/utils/server.ts +++ b/packages/light-client/test/utils/server.ts @@ -1,4 +1,4 @@ -import {parse as queryStringParse} from "qs"; +import {parse as parseQueryString} from "qs"; import {FastifyInstance, fastify} from "fastify"; import {fastifyCors} from "@fastify/cors"; import {Api, ServerApi} from "@lodestar/api"; @@ -18,7 +18,7 @@ export async function startServer( const server = fastify({ logger: false, ajv: {customOptions: {coerceTypes: "array"}}, - querystringParser: (str) => queryStringParse(str, {comma: true, parseArrays: false}), + querystringParser: (str) => parseQueryString(str, {comma: true, parseArrays: false}), }); registerRoutes(server, config, api, ["lightclient", "proof", "events"]); diff --git a/packages/logger/src/node.ts b/packages/logger/src/node.ts index 2740b37e3ca9..60ca87e0367c 100644 --- a/packages/logger/src/node.ts +++ b/packages/logger/src/node.ts @@ -2,7 +2,7 @@ import path from "node:path"; import DailyRotateFile from "winston-daily-rotate-file"; import TransportStream from "winston-transport"; // We want to keep `winston` export as it's more readable and easier to understand -// eslint-disable-next-line import/no-named-as-default-member +/* eslint-disable import/no-named-as-default-member */ import winston from "winston"; import type {Logger as Winston} from "winston"; import {Logger, LogLevel, TimestampFormat} from "./interface.js"; diff --git a/packages/logger/src/utils/format.ts b/packages/logger/src/utils/format.ts index edb2035c1957..651dc56ce687 100644 --- a/packages/logger/src/utils/format.ts +++ b/packages/logger/src/utils/format.ts @@ -1,5 +1,3 @@ -// We want to keep `winston` export as it's more readable and easier to understand -// eslint-disable-next-line import/no-named-as-default-member import winston, {format} from "winston"; import {LodestarError, isEmptyObject} from "@lodestar/utils"; import {LoggerOptions, TimestampFormatCode} from "../interface.js"; diff --git a/packages/logger/src/winston.ts b/packages/logger/src/winston.ts index 460706b1d081..4e6fbbecd6b2 100644 --- a/packages/logger/src/winston.ts +++ b/packages/logger/src/winston.ts @@ -1,6 +1,6 @@ // We want to keep `winston` export as it's more readable and easier to understand -// eslint-disable-next-line import/no-named-as-default-member -import winston, {createLogger as winstonCreateLogger} from "winston"; +/* eslint-disable import/no-named-as-default-member */ +import winston from "winston"; import type {Logger as Winston} from "winston"; import {Logger, LoggerOptions, LogLevel, logLevelNum} from "./interface.js"; import {getFormat} from "./utils/format.js"; @@ -48,7 +48,7 @@ export class WinstonLogger implements Logger { static createWinstonInstance(options: Partial = {}, transports?: winston.transport[]): Winston { const defaultMeta: DefaultMeta = {module: options?.module || ""}; - return winstonCreateLogger({ + return winston.createLogger({ // Do not set level at the logger level. Always control by Transport, unless for testLogger level: options.level, defaultMeta, diff --git a/packages/logger/test/e2e/logger/workerLoggerHandler.ts b/packages/logger/test/e2e/logger/workerLoggerHandler.ts index 6d541a188796..ab2097171af0 100644 --- a/packages/logger/test/e2e/logger/workerLoggerHandler.ts +++ b/packages/logger/test/e2e/logger/workerLoggerHandler.ts @@ -14,7 +14,6 @@ export async function getLoggerWorker(opts: WorkerData): Promise { }); const worker = workerThreadjs as unknown as workerThreads.Worker; - // eslint-disable-next-line @typescript-eslint/no-explicit-any await spawn(workerThreadjs, { // A Lodestar Node may do very expensive task at start blocking the event loop and causing // the initialization to timeout. The number below is big enough to almost disable the timeout diff --git a/packages/logger/test/unit/utils/json.test.ts b/packages/logger/test/unit/utils/json.test.ts index 02a6c95e1ed9..912f15fa958b 100644 --- a/packages/logger/test/unit/utils/json.test.ts +++ b/packages/logger/test/unit/utils/json.test.ts @@ -24,13 +24,9 @@ describe("Json helper", () => { {id: "symbol", arg: Symbol("foo"), json: "Symbol(foo)"}, // Functions - // eslint-disable-next-line @typescript-eslint/no-empty-function {id: "function", arg: function () {}, json: "function() {\n }"}, - // eslint-disable-next-line @typescript-eslint/no-empty-function {id: "arrow function", arg: () => {}, json: "() => {\n }"}, - // eslint-disable-next-line @typescript-eslint/no-empty-function {id: "async function", arg: async function () {}, json: "async function() {\n }"}, - // eslint-disable-next-line @typescript-eslint/no-empty-function {id: "async arrow function", arg: async () => {}, json: "async () => {\n }"}, // Arrays diff --git a/packages/prover/src/utils/command.ts b/packages/prover/src/utils/command.ts index 81a3993f3c43..f01d9f7ab17b 100644 --- a/packages/prover/src/utils/command.ts +++ b/packages/prover/src/utils/command.ts @@ -47,7 +47,6 @@ export function registerCommandToYargs(yargs: Argv, cliCommand: CliCommand(); private readonly dialOnlyProtocols = new Map(); @@ -251,7 +250,6 @@ export class ReqResp { // Override } - // eslint-disable-next-line @typescript-eslint/no-explicit-any protected onIncomingRequestError(_protocol: ProtocolDescriptor, _error: RequestError): void { // Override } diff --git a/packages/reqresp/test/fixtures/messages.ts b/packages/reqresp/test/fixtures/messages.ts index 7c5eedaeb3d4..5558e7c3e13a 100644 --- a/packages/reqresp/test/fixtures/messages.ts +++ b/packages/reqresp/test/fixtures/messages.ts @@ -181,5 +181,4 @@ const ALTAIR_FORK_EPOCH = Math.floor(slotBlockAltair / SLOTS_PER_EPOCH); // eslint-disable-next-line @typescript-eslint/naming-convention export const beaconConfig = createBeaconConfig({...chainConfig, ALTAIR_FORK_EPOCH}, ZERO_HASH); -// eslint-disable-next-line @typescript-eslint/no-empty-function export const getEmptyHandler = () => async function* emptyHandler(): AsyncGenerator {}; diff --git a/packages/reqresp/test/unit/encoders/responseDecode.test.ts b/packages/reqresp/test/unit/encoders/responseDecode.test.ts index 6e73fbbba315..8fc919c46313 100644 --- a/packages/reqresp/test/unit/encoders/responseDecode.test.ts +++ b/packages/reqresp/test/unit/encoders/responseDecode.test.ts @@ -13,7 +13,6 @@ describe("encoders / responseDecode", () => { it.each(responseEncodersTestCases)("$id", async ({protocol, responseChunks, chunks}) => { const responses = (await pipe( arrToSource(chunks), - // eslint-disable-next-line @typescript-eslint/no-empty-function responseDecode(protocol, {onFirstHeader: () => {}, onFirstResponseChunk: () => {}}), all )) as ResponseIncoming[]; @@ -32,7 +31,6 @@ describe("encoders / responseDecode", () => { await expectRejectedWithLodestarError( pipe( arrToSource(chunks as Uint8Array[]), - // eslint-disable-next-line @typescript-eslint/no-empty-function responseDecode(protocol, {onFirstHeader: () => {}, onFirstResponseChunk: () => {}}), all ), diff --git a/packages/reqresp/test/utils/index.ts b/packages/reqresp/test/utils/index.ts index c3c133352186..afddace8328d 100644 --- a/packages/reqresp/test/utils/index.ts +++ b/packages/reqresp/test/utils/index.ts @@ -73,11 +73,8 @@ export class MockLibP2pStream implements Stream { } }; - // eslint-disable-next-line @typescript-eslint/no-empty-function close: Stream["close"] = async () => {}; - // eslint-disable-next-line @typescript-eslint/no-empty-function closeRead = async (): Promise => {}; - // eslint-disable-next-line @typescript-eslint/no-empty-function closeWrite = async (): Promise => {}; abort: Stream["abort"] = () => this.close(); } diff --git a/packages/reqresp/test/utils/response.ts b/packages/reqresp/test/utils/response.ts index b231a3cfb275..b6da1b40bd0e 100644 --- a/packages/reqresp/test/utils/response.ts +++ b/packages/reqresp/test/utils/response.ts @@ -8,11 +8,7 @@ import {arrToSource} from "../utils/index.js"; export async function* responseEncode(responseChunks: ResponseChunk[], protocol: Protocol): AsyncIterable { for (const chunk of responseChunks) { if (chunk.status === RespStatus.SUCCESS) { - yield* pipe( - arrToSource([chunk.payload]), - // eslint-disable-next-line @typescript-eslint/no-empty-function - responseEncodeSuccess(protocol, {onChunk: () => {}}) - ); + yield* pipe(arrToSource([chunk.payload]), responseEncodeSuccess(protocol, {onChunk: () => {}})); } else { yield* responseEncodeError(protocol, chunk.status, chunk.errorMessage); } diff --git a/packages/spec-test-util/src/downloadTests.ts b/packages/spec-test-util/src/downloadTests.ts index 2fc61b99e5b8..9e90d5825bdf 100644 --- a/packages/spec-test-util/src/downloadTests.ts +++ b/packages/spec-test-util/src/downloadTests.ts @@ -1,4 +1,4 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ import fs from "node:fs"; import path from "node:path"; import stream from "node:stream"; @@ -10,7 +10,6 @@ import retry from "async-retry"; export const defaultSpecTestsRepoUrl = "https://github.com/ethereum/consensus-spec-tests"; -// eslint-disable-next-line @typescript-eslint/no-empty-function const logEmpty = (): void => {}; export type DownloadTestsOptions = { diff --git a/packages/utils/src/sleep.ts b/packages/utils/src/sleep.ts index 9f46f12074af..c31a9daffd32 100644 --- a/packages/utils/src/sleep.ts +++ b/packages/utils/src/sleep.ts @@ -12,7 +12,6 @@ export async function sleep(ms: number, signal?: AbortSignal): Promise { return new Promise((resolve, reject) => { if (signal && signal.aborted) return reject(new ErrorAborted()); - // eslint-disable-next-line @typescript-eslint/no-empty-function let onDone: () => void = () => {}; const timeout = setTimeout(() => { diff --git a/packages/utils/test/unit/err.test.ts b/packages/utils/test/unit/err.test.ts index 54908c50ccd3..94cebe3ed1a1 100644 --- a/packages/utils/test/unit/err.test.ts +++ b/packages/utils/test/unit/err.test.ts @@ -1,8 +1,6 @@ import {describe, it, expect} from "vitest"; import {Err, isErr, mapOkResults, mapOkResultsAsync, Result} from "../../src/err.js"; -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ - describe("Result Err", () => { describe("isErr works with any type", () => { const values: any[] = [ @@ -15,7 +13,6 @@ describe("Result Err", () => { null, [1, 2], new Uint8Array(1), - // eslint-disable-next-line @typescript-eslint/no-empty-function function test() {}, {a: 1}, new AbortController(), diff --git a/packages/validator/test/utils/clock.ts b/packages/validator/test/utils/clock.ts index b5a161e7efea..da9406ecfc35 100644 --- a/packages/validator/test/utils/clock.ts +++ b/packages/validator/test/utils/clock.ts @@ -11,7 +11,6 @@ export class ClockMock implements IClock { private readonly everySlot: RunEveryFn[] = []; private readonly everyEpoch: RunEveryFn[] = []; - // eslint-disable-next-line @typescript-eslint/no-empty-function start = (): void => {}; runEverySlot = (fn: RunEveryFn): number => this.everySlot.push(fn); runEveryEpoch = (fn: RunEveryFn): number => this.everyEpoch.push(fn); From 4c09412ed2c8a94b585d5dba1fe94bc9e2d56a35 Mon Sep 17 00:00:00 2001 From: tuyennhv Date: Sat, 17 Feb 2024 21:44:38 +0700 Subject: [PATCH 62/71] fix: earliest permissable slot for beacon_attestation topic post deneb (#6198) --- .../src/network/processor/index.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/beacon-node/src/network/processor/index.ts b/packages/beacon-node/src/network/processor/index.ts index ba84c9b12a60..420360920518 100644 --- a/packages/beacon-node/src/network/processor/index.ts +++ b/packages/beacon-node/src/network/processor/index.ts @@ -2,6 +2,8 @@ import {Logger, MapDef, mapValues, sleep} from "@lodestar/utils"; import {RootHex, Slot, SlotRootHex} from "@lodestar/types"; import {routes} from "@lodestar/api"; import {pruneSetToMax} from "@lodestar/utils"; +import {ForkSeq} from "@lodestar/params"; +import {computeStartSlotAtEpoch} from "@lodestar/state-transition"; import {IBeaconChain} from "../../chain/interface.js"; import {GossipErrorCode} from "../../chain/errors/gossipValidation.js"; import {Metrics} from "../../metrics/metrics.js"; @@ -47,10 +49,10 @@ const MAX_UNKNOWN_ROOTS_SLOT_CACHE_SIZE = 3; /** * This is respective to gossipsub seenTTL (which is 550 * 0.7 = 385s), also it's respective * to beacon_attestation ATTESTATION_PROPAGATION_SLOT_RANGE (32 slots). - * If message slots are withint this window, it'll likely to be filtered by gossipsub seenCache. + * If message slots are within this window, it'll likely to be filtered by gossipsub seenCache. * This is mainly for DOS protection, see https://github.com/ChainSafe/lodestar/issues/5393 */ -const EARLIEST_PERMISSIBLE_SLOT_DISTANCE = 32; +const DEFAULT_EARLIEST_PERMISSIBLE_SLOT_DISTANCE = 32; type WorkOpts = { bypassQueue?: boolean; @@ -250,7 +252,14 @@ export class NetworkProcessor { if (slotRoot) { // DOS protection: avoid processing messages that are too old const {slot, root} = slotRoot; - if (slot < this.chain.clock.currentSlot - EARLIEST_PERMISSIBLE_SLOT_DISTANCE) { + const clockSlot = this.chain.clock.currentSlot; + const {fork} = message.topic; + let earliestPermissableSlot = clockSlot - DEFAULT_EARLIEST_PERMISSIBLE_SLOT_DISTANCE; + if (ForkSeq[fork] >= ForkSeq.deneb && topicType === GossipType.beacon_attestation) { + // post deneb, the attestations could be in current or previous epoch + earliestPermissableSlot = computeStartSlotAtEpoch(this.chain.clock.currentEpoch - 1); + } + if (slot < earliestPermissableSlot) { // TODO: Should report the dropped job to gossip? It will be eventually pruned from the mcache this.metrics?.networkProcessor.gossipValidationError.inc({ topic: topicType, @@ -258,10 +267,7 @@ export class NetworkProcessor { }); return; } - if ( - slot === this.chain.clock.currentSlot && - (topicType === GossipType.beacon_block || topicType === GossipType.blob_sidecar) - ) { + if (slot === clockSlot && (topicType === GossipType.beacon_block || topicType === GossipType.blob_sidecar)) { // in the worse case if the current slot block is not valid, this will be reset in the next slot this.isProcessingCurrentSlotBlock = true; } From 290c301dcf40fef40150dd484341436bb71981fd Mon Sep 17 00:00:00 2001 From: g11tech Date: Sat, 17 Feb 2024 23:11:36 +0530 Subject: [PATCH 63/71] feat: add retry functionality in the api for builder publish (#6387) * feat: add retry functionality in the api for builder publish * update retry delay * retry logic when retires mentioned --- packages/api/src/beacon/client/beacon.ts | 2 +- packages/api/src/builder/client.ts | 4 +- packages/api/src/builder/index.ts | 13 +++++-- packages/api/src/utils/client/client.ts | 37 +++++++++++++++---- packages/api/src/utils/client/httpClient.ts | 19 +++++++++- .../beacon-node/src/execution/builder/http.ts | 2 +- 6 files changed, 61 insertions(+), 16 deletions(-) diff --git a/packages/api/src/beacon/client/beacon.ts b/packages/api/src/beacon/client/beacon.ts index 7a92afe15c6f..ef1e1983577d 100644 --- a/packages/api/src/beacon/client/beacon.ts +++ b/packages/api/src/beacon/client/beacon.ts @@ -11,7 +11,7 @@ export function getClient(config: ChainForkConfig, httpClient: IHttpClient): Api const reqSerializers = getReqSerializers(config); const returnTypes = getReturnTypes(); // Some routes return JSON, use a client auto-generator - const client = generateGenericJsonClient(routesData, reqSerializers, returnTypes, httpClient); + const client = generateGenericJsonClient(routesData, reqSerializers, returnTypes, httpClient) as Api; const fetchOptsSerializer = getFetchOptsSerializers(routesData, reqSerializers); return { diff --git a/packages/api/src/builder/client.ts b/packages/api/src/builder/client.ts index ed344b9c0e7f..381732b81433 100644 --- a/packages/api/src/builder/client.ts +++ b/packages/api/src/builder/client.ts @@ -1,11 +1,11 @@ import {ChainForkConfig} from "@lodestar/config"; -import {IHttpClient, generateGenericJsonClient} from "../utils/client/index.js"; +import {IHttpClient, generateGenericJsonClient, ApiWithExtraOpts} from "../utils/client/index.js"; import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "./routes.js"; /** * REST HTTP client for builder routes */ -export function getClient(config: ChainForkConfig, httpClient: IHttpClient): Api { +export function getClient(config: ChainForkConfig, httpClient: IHttpClient): ApiWithExtraOpts { const reqSerializers = getReqSerializers(config); const returnTypes = getReturnTypes(); // All routes return JSON, use a client auto-generator diff --git a/packages/api/src/builder/index.ts b/packages/api/src/builder/index.ts index 76100fba2057..531ceac1b624 100644 --- a/packages/api/src/builder/index.ts +++ b/packages/api/src/builder/index.ts @@ -1,14 +1,19 @@ import {ChainForkConfig} from "@lodestar/config"; -import {HttpClient, HttpClientModules, HttpClientOptions, IHttpClient} from "../utils/client/httpClient.js"; -import {Api} from "./routes.js"; +import { + HttpClient, + HttpClientModules, + HttpClientOptions, + IHttpClient, + ApiWithExtraOpts, +} from "../utils/client/index.js"; +import {Api as BuilderApi} from "../builder/routes.js"; import * as builder from "./client.js"; // NOTE: Don't export server here so it's not bundled to all consumers -export type {Api}; - // Note: build API does not have namespaces as routes are declared at the "root" namespace +export type Api = ApiWithExtraOpts; type ClientModules = HttpClientModules & { config: ChainForkConfig; httpClient?: IHttpClient; diff --git a/packages/api/src/utils/client/client.ts b/packages/api/src/utils/client/client.ts index a88b68553898..1782ceea57fd 100644 --- a/packages/api/src/utils/client/client.ts +++ b/packages/api/src/utils/client/client.ts @@ -5,10 +5,17 @@ import {APIClientHandler} from "../../interfaces.js"; import {FetchOpts, HttpError, IHttpClient} from "./httpClient.js"; import {HttpStatusCode} from "./httpStatusCode.js"; -// See /packages/api/src/routes/index.ts for reasoning - /* eslint-disable @typescript-eslint/no-explicit-any */ +type ExtraOpts = {retryAttempts?: number}; +type ParamatersWithOptionalExtaOpts any> = [...Parameters, ExtraOpts] | Parameters; + +export type ApiWithExtraOpts> = { + [K in keyof T]: (...args: ParamatersWithOptionalExtaOpts) => ReturnType; +}; + +// See /packages/api/src/routes/index.ts for reasoning + /** * Format FetchFn opts from Fn arguments given a route definition and request serializer. * For routes that return only JSOn use @see getGenericJsonClient @@ -58,22 +65,38 @@ export function generateGenericJsonClient< reqSerializers: ReqSerializers, returnTypes: ReturnTypes, fetchFn: IHttpClient -): Api { +): ApiWithExtraOpts { return mapValues(routesData, (routeDef, routeId) => { const fetchOptsSerializer = getFetchOptsSerializer(routeDef, reqSerializers[routeId], routeId as string); const returnType = returnTypes[routeId as keyof ReturnTypes] as TypeJson | null; - return async function request(...args: Parameters): Promise> { + return async function request( + ...args: ParamatersWithOptionalExtaOpts + ): Promise> { try { + // extract the extraOpts if provided + // + const argLen = (args as any[])?.length ?? 0; + const lastArg = (args as any[])[argLen] as ExtraOpts | undefined; + const retryAttempts = lastArg?.retryAttempts; + const extraOpts = {retryAttempts}; + if (returnType) { - const res = await fetchFn.json(fetchOptsSerializer(...args)); + // open extraOpts first if some serializer wants to add some overriding param + const res = await fetchFn.json({ + ...extraOpts, + ...fetchOptsSerializer(...(args as Parameters)), + }); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/return-await return {ok: true, response: returnType.fromJson(res.body), status: res.status} as ReturnType; } else { // We need to avoid parsing the response as the servers might just // response status 200 and close the request instead of writing an // empty json response. We return the status code. - const res = await fetchFn.request(fetchOptsSerializer(...args)); + const res = await fetchFn.request({ + ...extraOpts, + ...fetchOptsSerializer(...(args as Parameters)), + }); // eslint-disable-next-line @typescript-eslint/return-await return {ok: true, response: undefined, status: res.status} as ReturnType; @@ -98,5 +121,5 @@ export function generateGenericJsonClient< throw err; } }; - }) as unknown as Api; + }) as unknown as ApiWithExtraOpts; } diff --git a/packages/api/src/utils/client/httpClient.ts b/packages/api/src/utils/client/httpClient.ts index c0fd2b8ad1aa..57214c1ae04a 100644 --- a/packages/api/src/utils/client/httpClient.ts +++ b/packages/api/src/utils/client/httpClient.ts @@ -1,4 +1,4 @@ -import {ErrorAborted, Logger, TimeoutError, isValidHttpUrl, toBase64} from "@lodestar/utils"; +import {ErrorAborted, Logger, TimeoutError, isValidHttpUrl, toBase64, retry} from "@lodestar/utils"; import {ReqGeneric, RouteDef} from "../index.js"; import {ApiClientResponse, ApiClientSuccessResponse} from "../../interfaces.js"; import {fetch, isFetchError} from "./fetch.js"; @@ -70,6 +70,7 @@ export type FetchOpts = { /** Optional, for metrics */ routeId?: string; timeoutMs?: number; + retryAttempts?: number; }; export interface IHttpClient { @@ -181,6 +182,22 @@ export class HttpClient implements IHttpClient { private async requestWithBodyWithRetries( opts: FetchOpts, getBody: (res: Response) => Promise + ): Promise<{status: HttpStatusCode; body: T}> { + if (opts.retryAttempts !== undefined) { + return retry( + async (_attempt) => { + return this.requestWithBodyWithFallbacks(opts, getBody); + }, + {retries: opts.retryAttempts, retryDelay: 200} + ); + } else { + return this.requestWithBodyWithFallbacks(opts, getBody); + } + } + + private async requestWithBodyWithFallbacks( + opts: FetchOpts, + getBody: (res: Response) => Promise ): Promise<{status: HttpStatusCode; body: T}> { // Early return when no fallback URLs are setup if (this.urlsOpts.length === 1) { diff --git a/packages/beacon-node/src/execution/builder/http.ts b/packages/beacon-node/src/execution/builder/http.ts index c47e8471f199..b4013c384f81 100644 --- a/packages/beacon-node/src/execution/builder/http.ts +++ b/packages/beacon-node/src/execution/builder/http.ts @@ -118,7 +118,7 @@ export class ExecutionBuilderHttp implements IExecutionBuilder { async submitBlindedBlock( signedBlindedBlock: allForks.SignedBlindedBeaconBlock ): Promise { - const res = await this.api.submitBlindedBlock(signedBlindedBlock); + const res = await this.api.submitBlindedBlock(signedBlindedBlock, {retryAttempts: 3}); ApiError.assert(res, "execution.builder.submitBlindedBlock"); const {data} = res.response; From c7c99412c3bbe9a550811db7b812f5e6fc741357 Mon Sep 17 00:00:00 2001 From: g11tech Date: Sat, 17 Feb 2024 23:29:25 +0530 Subject: [PATCH 64/71] feat: track timings of various stages of block import (#6439) * feat: minutely track timings of various stages of block import * remove recvToValLatency metrics --- .../src/chain/blocks/importBlock.ts | 11 ++- .../blocks/verifyBlocksExecutionPayloads.ts | 15 ++- .../chain/blocks/verifyBlocksSignatures.ts | 16 ++- .../blocks/verifyBlocksStateTransitionOnly.ts | 11 ++- .../src/metrics/metrics/lodestar.ts | 97 +++++++++++++------ .../src/network/processor/gossipHandlers.ts | 65 ++++++++----- 6 files changed, 150 insertions(+), 65 deletions(-) diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index c8fc62eaa622..0f1f2a7890d9 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -67,6 +67,7 @@ export async function importBlock( const parentEpoch = computeEpochAtSlot(parentBlockSlot); const prevFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch; const blockDelaySec = (fullyVerifiedBlock.seenTimestampSec - postState.genesisTime) % this.config.SECONDS_PER_SLOT; + const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000); // 1. Persist block to hot DB (pre-emptively) // If eagerPersistBlock = true we do that in verifyBlocksInEpoch to batch all I/O operations to save block time to head @@ -447,9 +448,13 @@ export async function importBlock( }, 0); if (opts.seenTimestampSec !== undefined) { - const recvToImportedBlock = Date.now() / 1000 - opts.seenTimestampSec; - this.metrics?.gossipBlock.receivedToBlockImport.observe(recvToImportedBlock); - this.logger.verbose("Imported block", {slot: blockSlot, recvToImportedBlock}); + const recvToValidation = Date.now() / 1000 - opts.seenTimestampSec; + const validationTime = recvToValidation - recvToValLatency; + + this.metrics?.gossipBlock.blockImport.recvToValidation.observe(recvToValidation); + this.metrics?.gossipBlock.blockImport.validationTime.observe(validationTime); + + this.logger.debug("Imported block", {slot: blockSlot, recvToValLatency, recvToValidation, validationTime}); } this.logger.verbose("Block processed", { diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts index 91242d879f85..8f386ef191d2 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksExecutionPayloads.ts @@ -75,6 +75,7 @@ export async function verifyBlocksExecutionPayload( ): Promise { const executionStatuses: MaybeValidExecutionStatus[] = []; let mergeBlockFound: bellatrix.BeaconBlock | null = null; + const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000); // Error in the same way as verifyBlocksSanityChecks if empty blocks if (blocks.length === 0) { @@ -246,11 +247,17 @@ export async function verifyBlocksExecutionPayload( const executionTime = Date.now(); if (blocks.length === 1 && opts.seenTimestampSec !== undefined && executionStatuses[0] === ExecutionStatus.Valid) { - const recvToVerifiedExecPayload = executionTime / 1000 - opts.seenTimestampSec; - chain.metrics?.gossipBlock.receivedToExecutionPayloadVerification.observe(recvToVerifiedExecPayload); - chain.logger.verbose("Verified execution payload", { + const recvToValidation = executionTime / 1000 - opts.seenTimestampSec; + const validationTime = recvToValidation - recvToValLatency; + + chain.metrics?.gossipBlock.executionPayload.recvToValidation.observe(recvToValidation); + chain.metrics?.gossipBlock.executionPayload.validationTime.observe(validationTime); + + chain.logger.debug("Verified execution payload", { slot: blocks[0].message.slot, - recvToVerifiedExecPayload, + recvToValLatency, + recvToValidation, + validationTime, }); } diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksSignatures.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksSignatures.ts index 14ad46a35c1e..ff0b19ee3edc 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksSignatures.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksSignatures.ts @@ -22,6 +22,7 @@ export async function verifyBlocksSignatures( opts: ImportBlockOpts ): Promise<{verifySignaturesTime: number}> { const isValidPromises: Promise[] = []; + const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000); // Verifies signatures after running state transition, so all SyncCommittee signed roots are known at this point. // We must ensure block.slot <= state.slot before running getAllBlockSignatureSets(). @@ -54,9 +55,18 @@ export async function verifyBlocksSignatures( const verifySignaturesTime = Date.now(); if (blocks.length === 1 && opts.seenTimestampSec !== undefined) { - const recvToSigVer = verifySignaturesTime / 1000 - opts.seenTimestampSec; - metrics?.gossipBlock.receivedToSignaturesVerification.observe(recvToSigVer); - logger.verbose("Verified block signatures", {slot: blocks[0].message.slot, recvToSigVer}); + const recvToValidation = verifySignaturesTime / 1000 - opts.seenTimestampSec; + const validationTime = recvToValidation - recvToValLatency; + + metrics?.gossipBlock.signatureVerification.recvToValidation.observe(recvToValidation); + metrics?.gossipBlock.signatureVerification.validationTime.observe(validationTime); + + logger.debug("Verified block signatures", { + slot: blocks[0].message.slot, + recvToValLatency, + recvToValidation, + validationTime, + }); } return {verifySignaturesTime}; diff --git a/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts b/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts index 7d15d4e4f6ce..62d5f6802533 100644 --- a/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +++ b/packages/beacon-node/src/chain/blocks/verifyBlocksStateTransitionOnly.ts @@ -31,6 +31,7 @@ export async function verifyBlocksStateTransitionOnly( ): Promise<{postStates: CachedBeaconStateAllForks[]; proposerBalanceDeltas: number[]; verifyStateTime: number}> { const postStates: CachedBeaconStateAllForks[] = []; const proposerBalanceDeltas: number[] = []; + const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000); for (let i = 0; i < blocks.length; i++) { const {validProposerSignature, validSignatures} = opts; @@ -96,9 +97,13 @@ export async function verifyBlocksStateTransitionOnly( const verifyStateTime = Date.now(); if (blocks.length === 1 && opts.seenTimestampSec !== undefined) { const slot = blocks[0].block.message.slot; - const recvToTransition = verifyStateTime / 1000 - opts.seenTimestampSec; - metrics?.gossipBlock.receivedToStateTransition.observe(recvToTransition); - logger.verbose("Verified block state transition", {slot, recvToTransition}); + const recvToValidation = verifyStateTime / 1000 - opts.seenTimestampSec; + const validationTime = recvToValidation - recvToValLatency; + + metrics?.gossipBlock.stateTransition.recvToValidation.observe(recvToValidation); + metrics?.gossipBlock.stateTransition.validationTime.observe(validationTime); + + logger.debug("Verified block state transition", {slot, recvToValLatency, recvToValidation, validationTime}); } return {postStates, proposerBalanceDeltas, verifyStateTime}; diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 0f4940cd5d5c..c42dc4a747b3 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -668,26 +668,68 @@ export function createLodestarMetrics( help: "Time elapsed between block slot time and the time block processed", buckets: [0.5, 1, 2, 4, 6, 12], }), - receivedToGossipValidate: register.histogram({ - name: "lodestar_gossip_block_received_to_gossip_validate", - help: "Time elapsed between block received and block validated", - buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], - }), - receivedToStateTransition: register.histogram({ - name: "lodestar_gossip_block_received_to_state_transition", - help: "Time elapsed between block received and block state transition", - buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], - }), - receivedToSignaturesVerification: register.histogram({ - name: "lodestar_gossip_block_received_to_signatures_verification", - help: "Time elapsed between block received and block signatures verification", - buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], - }), - receivedToExecutionPayloadVerification: register.histogram({ - name: "lodestar_gossip_block_received_to_execution_payload_verification", - help: "Time elapsed between block received and execution payload verification", - buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], - }), + + gossipValidation: { + recvToValidation: register.histogram({ + name: "lodestar_gossip_block_received_to_gossip_validate", + help: "Time elapsed between block received and block validated", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + validationTime: register.histogram({ + name: "lodestar_gossip_block_gossip_validate_time", + help: "Time to apply gossip validations", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + }, + stateTransition: { + recvToValidation: register.histogram({ + name: "lodestar_gossip_block_received_to_state_transition", + help: "Time elapsed between block received and block state transition", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + validationTime: register.histogram({ + name: "lodestar_gossip_block_state_transition_time", + help: "Time to validate block state transition", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + }, + signatureVerification: { + recvToValidation: register.histogram({ + name: "lodestar_gossip_block_received_to_signatures_verification", + help: "Time elapsed between block received and block signatures verification", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + validationTime: register.histogram({ + name: "lodestar_gossip_block_signatures_verification_time", + help: "Time elapsed for block signatures verification", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + }, + executionPayload: { + recvToValidation: register.histogram({ + name: "lodestar_gossip_block_received_to_execution_payload_verification", + help: "Time elapsed between block received and execution payload verification", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + validationTime: register.histogram({ + name: "lodestar_gossip_execution_payload_verification_time", + help: "Time elapsed for execution payload verification", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + }, + blockImport: { + recvToValidation: register.histogram({ + name: "lodestar_gossip_block_received_to_block_import", + help: "Time elapsed between block received and block import", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + validationTime: register.histogram({ + name: "lodestar_gossip_block_block_import_time", + help: "Time elapsed for block import", + buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], + }), + }, + receivedToBlobsAvailabilityTime: register.histogram<{numBlobs: number}>({ name: "lodestar_gossip_block_received_to_blobs_availability_time", help: "Time elapsed between block received and blobs became available", @@ -705,11 +747,7 @@ export function createLodestarMetrics( buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], labelNames: ["numBlobs"], }), - receivedToBlockImport: register.histogram({ - name: "lodestar_gossip_block_received_to_block_import", - help: "Time elapsed between block received and block import", - buckets: [0.05, 0.1, 0.3, 0.5, 0.7, 1, 1.3, 1.6, 2, 2.5, 3, 3.5, 4], - }), + processBlockErrors: register.gauge<{error: BlockErrorCode | "NOT_BLOCK_ERROR"}>({ name: "lodestar_gossip_block_process_block_errors", help: "Count of errors, by error type, while processing blocks", @@ -717,9 +755,14 @@ export function createLodestarMetrics( }), }, gossipBlob: { - receivedToGossipValidate: register.histogram({ + recvToValidation: register.histogram({ name: "lodestar_gossip_blob_received_to_gossip_validate", - help: "Time elapsed between blob received and blob validated", + help: "Time elapsed between blob received and blob validation", + buckets: [0.05, 0.1, 0.2, 0.5, 1, 1.5, 2, 4], + }), + validationTime: register.histogram({ + name: "lodestar_gossip_blob_gossip_validate_time", + help: "Time elapsed for blob validation", buckets: [0.05, 0.1, 0.2, 0.5, 1, 1.5, 2, 4], }), }, diff --git a/packages/beacon-node/src/network/processor/gossipHandlers.ts b/packages/beacon-node/src/network/processor/gossipHandlers.ts index 2bf9178a0567..60186f8fb79f 100644 --- a/packages/beacon-node/src/network/processor/gossipHandlers.ts +++ b/packages/beacon-node/src/network/processor/gossipHandlers.ts @@ -115,7 +115,7 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler const forkTypes = config.getForkTypes(slot); const blockHex = prettyBytes(forkTypes.BeaconBlock.hashTreeRoot(signedBlock.message)); const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec); - const recvToVal = Date.now() / 1000 - seenTimestampSec; + const recvToValLatency = Date.now() / 1000 - seenTimestampSec; // always set block to seen cache for all forks so that we don't need to download it const blockInputRes = chain.seenGossipBlockInput.getGossipBlockInput(config, { @@ -133,19 +133,27 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler const blockInputMeta = config.getForkSeq(signedBlock.message.slot) >= ForkSeq.deneb ? blockInputRes.blockInputMeta : {}; - metrics?.gossipBlock.receivedToGossipValidate.observe(recvToVal); - logger.verbose("Received gossip block", { - slot: slot, - root: blockHex, - curentSlot: chain.clock.currentSlot, - peerId: peerIdStr, - delaySec, - recvToVal, - ...blockInputMeta, - }); - try { await validateGossipBlock(config, chain, signedBlock, fork); + + const recvToValidation = Date.now() / 1000 - seenTimestampSec; + const validationTime = recvToValidation - recvToValLatency; + + metrics?.gossipBlock.gossipValidation.recvToValidation.observe(recvToValidation); + metrics?.gossipBlock.gossipValidation.validationTime.observe(validationTime); + + logger.debug("Received gossip block", { + slot: slot, + root: blockHex, + curentSlot: chain.clock.currentSlot, + peerId: peerIdStr, + delaySec, + ...blockInputMeta, + recvToValLatency, + recvToValidation, + validationTime, + }); + return blockInput; } catch (e) { if (e instanceof BlockGossipError) { @@ -177,7 +185,7 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler const blockHex = prettyBytes(blockRoot); const delaySec = chain.clock.secFromSlot(slot, seenTimestampSec); - const recvToVal = Date.now() / 1000 - seenTimestampSec; + const recvToValLatency = Date.now() / 1000 - seenTimestampSec; const {blockInput, blockInputMeta} = chain.seenGossipBlockInput.getGossipBlockInput(config, { type: GossipedInputType.blob, @@ -185,20 +193,27 @@ function getDefaultHandlers(modules: ValidatorFnsModules, options: GossipHandler blobBytes, }); - metrics?.gossipBlob.receivedToGossipValidate.observe(recvToVal); - logger.verbose("Received gossip blob", { - slot: slot, - root: blockHex, - curentSlot: chain.clock.currentSlot, - peerId: peerIdStr, - delaySec, - recvToVal, - gossipIndex, - ...blockInputMeta, - }); - try { await validateGossipBlobSidecar(chain, blobSidecar, gossipIndex); + const recvToValidation = Date.now() / 1000 - seenTimestampSec; + const validationTime = recvToValidation - recvToValLatency; + + metrics?.gossipBlob.recvToValidation.observe(recvToValidation); + metrics?.gossipBlob.validationTime.observe(validationTime); + + logger.debug("Received gossip blob", { + slot: slot, + root: blockHex, + curentSlot: chain.clock.currentSlot, + peerId: peerIdStr, + delaySec, + gossipIndex, + ...blockInputMeta, + recvToValLatency, + recvToValidation, + validationTime, + }); + return blockInput; } catch (e) { if (e instanceof BlobSidecarGossipError) { From efb684a918fffe0efcc04b9a77d5c05caa9cbc6c Mon Sep 17 00:00:00 2001 From: g11tech Date: Tue, 20 Feb 2024 01:09:59 +0530 Subject: [PATCH 65/71] feat: add cli flag to ignore the wss check failure on checkpoint sync (#6453) * feat: add cli flag to ignore the wss check failure on checkpoint sync * minor fixes --- .../cli/src/cmds/beacon/initBeaconState.ts | 43 +++++++++++++------ packages/cli/src/cmds/beacon/options.ts | 9 ++++ packages/cli/src/util/errors.ts | 7 +++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/packages/cli/src/cmds/beacon/initBeaconState.ts b/packages/cli/src/cmds/beacon/initBeaconState.ts index 0185406db443..c8c444778991 100644 --- a/packages/cli/src/cmds/beacon/initBeaconState.ts +++ b/packages/cli/src/cmds/beacon/initBeaconState.ts @@ -15,7 +15,7 @@ import { } from "@lodestar/beacon-node"; import {Checkpoint} from "@lodestar/types/phase0"; -import {downloadOrLoadFile} from "../../util/index.js"; +import {downloadOrLoadFile, wrapFnError} from "../../util/index.js"; import {defaultNetwork, GlobalArgs} from "../../options/globalOptions.js"; import { fetchWeakSubjectivityState, @@ -31,7 +31,8 @@ async function initAndVerifyWeakSubjectivityState( logger: Logger, store: BeaconStateAllForks, wsState: BeaconStateAllForks, - wsCheckpoint: Checkpoint + wsCheckpoint: Checkpoint, + opts: {ignoreWeakSubjectivityCheck?: boolean} = {} ): Promise<{anchorState: BeaconStateAllForks; wsCheckpoint: Checkpoint}> { // Check if the store's state and wsState are compatible if ( @@ -56,12 +57,16 @@ async function initAndVerifyWeakSubjectivityState( ); } - // Instead of warning user of wss check failure, we throw because user explicity wants to use - // the checkpoint sync - ensureWithinWeakSubjectivityPeriod(config, anchorState, anchorCheckpoint); + // Throw error unless user explicitly asked not to, in testnets can happen that wss period is too small + // that even some epochs of non finalization can cause finalized checkpoint to be out of valid range + const wssCheck = wrapFnError(() => ensureWithinWeakSubjectivityPeriod(config, anchorState, anchorCheckpoint)); + const isWithinWeakSubjectivityPeriod = wssCheck.err === null; + if (!isWithinWeakSubjectivityPeriod && !opts.ignoreWeakSubjectivityCheck) { + throw wssCheck.err; + } anchorState = await initStateFromAnchorState(config, db, logger, anchorState, { - isWithinWeakSubjectivityPeriod: true, + isWithinWeakSubjectivityPeriod, isCheckpointState, }); @@ -123,7 +128,11 @@ export async function initBeaconState( if (args.checkpointState) { return readWSState( lastDbState, - {checkpointState: args.checkpointState, wssCheckpoint: args.wssCheckpoint}, + { + checkpointState: args.checkpointState, + wssCheckpoint: args.wssCheckpoint, + ignoreWeakSubjectivityCheck: args.ignoreWeakSubjectivityCheck, + }, chainForkConfig, db, logger @@ -131,7 +140,11 @@ export async function initBeaconState( } else if (args.checkpointSyncUrl) { return fetchWSStateFromBeaconApi( lastDbState, - {checkpointSyncUrl: args.checkpointSyncUrl, wssCheckpoint: args.wssCheckpoint}, + { + checkpointSyncUrl: args.checkpointSyncUrl, + wssCheckpoint: args.wssCheckpoint, + ignoreWeakSubjectivityCheck: args.ignoreWeakSubjectivityCheck, + }, chainForkConfig, db, logger @@ -158,7 +171,7 @@ export async function initBeaconState( async function readWSState( lastDbState: BeaconStateAllForks | null, - wssOpts: {checkpointState: string; wssCheckpoint?: string}, + wssOpts: {checkpointState: string; wssCheckpoint?: string; ignoreWeakSubjectivityCheck?: boolean}, chainForkConfig: ChainForkConfig, db: IBeaconDb, logger: Logger @@ -166,19 +179,21 @@ async function readWSState( // weak subjectivity sync from a provided state file: // if a weak subjectivity checkpoint has been provided, it is used for additional verification // otherwise, the state itself is used for verification (not bad, because the trusted state has been explicitly provided) - const {checkpointState, wssCheckpoint} = wssOpts; + const {checkpointState, wssCheckpoint, ignoreWeakSubjectivityCheck} = wssOpts; const stateBytes = await downloadOrLoadFile(checkpointState); const wsState = getStateTypeFromBytes(chainForkConfig, stateBytes).deserializeToViewDU(stateBytes); const config = createBeaconConfig(chainForkConfig, wsState.genesisValidatorsRoot); const store = lastDbState ?? wsState; const checkpoint = wssCheckpoint ? getCheckpointFromArg(wssCheckpoint) : getCheckpointFromState(wsState); - return initAndVerifyWeakSubjectivityState(config, db, logger, store, wsState, checkpoint); + return initAndVerifyWeakSubjectivityState(config, db, logger, store, wsState, checkpoint, { + ignoreWeakSubjectivityCheck, + }); } async function fetchWSStateFromBeaconApi( lastDbState: BeaconStateAllForks | null, - wssOpts: {checkpointSyncUrl: string; wssCheckpoint?: string}, + wssOpts: {checkpointSyncUrl: string; wssCheckpoint?: string; ignoreWeakSubjectivityCheck?: boolean}, chainForkConfig: ChainForkConfig, db: IBeaconDb, logger: Logger @@ -201,5 +216,7 @@ async function fetchWSStateFromBeaconApi( const {wsState, wsCheckpoint} = await fetchWeakSubjectivityState(chainForkConfig, logger, wssOpts); const config = createBeaconConfig(chainForkConfig, wsState.genesisValidatorsRoot); const store = lastDbState ?? wsState; - return initAndVerifyWeakSubjectivityState(config, db, logger, store, wsState, wsCheckpoint); + return initAndVerifyWeakSubjectivityState(config, db, logger, store, wsState, wsCheckpoint, { + ignoreWeakSubjectivityCheck: wssOpts.ignoreWeakSubjectivityCheck, + }); } diff --git a/packages/cli/src/cmds/beacon/options.ts b/packages/cli/src/cmds/beacon/options.ts index 64a759615f7e..a1d5b35fe5de 100644 --- a/packages/cli/src/cmds/beacon/options.ts +++ b/packages/cli/src/cmds/beacon/options.ts @@ -12,6 +12,7 @@ type BeaconExtraArgs = { checkpointState?: string; wssCheckpoint?: string; forceCheckpointSync?: boolean; + ignoreWeakSubjectivityCheck?: boolean; beaconDir?: string; dbDir?: string; persistInvalidSszObjectsDir?: string; @@ -75,6 +76,14 @@ export const beaconExtraOptions: CliCommandOptions = { group: "weak subjectivity", }, + ignoreWeakSubjectivityCheck: { + description: + "Ignore the checkpoint sync state failing the weak subjectivity check. This is relevant in testnets where the weak subjectivity period is too small for even few epochs of non finalization causing last finalized to be out of range. This flag is not recommended for mainnet use.", + hidden: true, + type: "boolean", + group: "weak subjectivity", + }, + beaconDir: { description: "Beacon root directory", defaultDescription: defaultBeaconPaths.beaconDir, diff --git a/packages/cli/src/util/errors.ts b/packages/cli/src/util/errors.ts index 3b462b4d68e3..62e05ef02710 100644 --- a/packages/cli/src/util/errors.ts +++ b/packages/cli/src/util/errors.ts @@ -11,3 +11,10 @@ export async function wrapError(promise: Promise): Promise> { return {err: err as Error}; } } +export function wrapFnError(fn: () => T): Result { + try { + return {err: null, result: fn()}; + } catch (err) { + return {err: err as Error}; + } +} From 0e9fc495a442da9759ebe21e82d49d4c00eb0e2d Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 20 Feb 2024 10:12:49 +0100 Subject: [PATCH 66/71] fix: improve error if lockfile exists but not a directory (#6450) --- packages/cli/src/util/lockfile.ts | 6 +++--- packages/cli/test/e2e/importKeystoresFromApi.test.ts | 4 ++-- packages/db/src/controller/level.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/util/lockfile.ts b/packages/cli/src/util/lockfile.ts index f7a6ddf4d57d..d28504507c7c 100644 --- a/packages/cli/src/util/lockfile.ts +++ b/packages/cli/src/util/lockfile.ts @@ -11,8 +11,8 @@ export function lockFilepath(filepath: string): void { realpath: false, }); } catch (e) { - if (isLockfileError(e) && e.code === "ELOCKED") { - e.message = `${filepath} is already in use by another process`; + if (isLockfileError(e) && (e.code === "ELOCKED" || e.code === "ENOTDIR")) { + e.message = `'${filepath}' already in use by another process`; } throw e; } @@ -38,7 +38,7 @@ export function unlockFilepath(filepath: string): void { } // https://github.com/moxystudio/node-proper-lockfile/blob/9f8c303c91998e8404a911dc11c54029812bca69/lib/lockfile.js#L53 -export type LockfileError = Error & {code: "ELOCKED" | "ENOTACQUIRED"}; +export type LockfileError = Error & {code: "ELOCKED" | "ENOTACQUIRED" | "ENOTDIR"}; function isLockfileError(e: unknown): e is LockfileError { return e instanceof Error && (e as LockfileError).code !== undefined; diff --git a/packages/cli/test/e2e/importKeystoresFromApi.test.ts b/packages/cli/test/e2e/importKeystoresFromApi.test.ts index 1cf5f107e226..8733d6cd5c48 100644 --- a/packages/cli/test/e2e/importKeystoresFromApi.test.ts +++ b/packages/cli/test/e2e/importKeystoresFromApi.test.ts @@ -95,10 +95,10 @@ describe("import keystores from api", function () { validator.on("exit", (code) => { if (code !== null && code > 0) { // process should exit with code > 0, and an error related to locks. Sample error: - // vc 351591: ✖ Error: /tmp/tmp-5080-lwNxdM5Ok9ya/import-keystores-test/keystores/0x8be678633e927aa0435addad5dcd5283fef6110d91362519cd6d43e61f6c017d724fa579cc4b2972134e050b6ba120c0/voting-keystore.json is already in use by another process + // vc 351591: ✖ Error: '/tmp/tmp-5080-lwNxdM5Ok9ya/import-keystores-test/keystores/0x8be678633e927aa0435addad5dcd5283fef6110d91362519cd6d43e61f6c017d724fa579cc4b2972134e050b6ba120c0/voting-keystore.json' already in use by another process // at /home/runner/actions-runner/_work/lodestar/lodestar/node_modules/proper-lockfile/lib/lockfile.js:68:47 // ... more stack trace - if (/Error.*voting-keystore\.json is already in use by another process/.test(vcProc2Stderr.read())) { + if (/Error.*voting-keystore\.json' already in use by another process/.test(vcProc2Stderr.read())) { resolve(); } else { reject(Error(`Second validator proc exited with unknown error. stderr:\n${vcProc2Stderr.read()}`)); diff --git a/packages/db/src/controller/level.ts b/packages/db/src/controller/level.ts index 2cea8681c95b..1a8f75ed875c 100644 --- a/packages/db/src/controller/level.ts +++ b/packages/db/src/controller/level.ts @@ -52,7 +52,7 @@ export class LevelDbController implements DatabaseController Date: Tue, 20 Feb 2024 11:14:50 +0100 Subject: [PATCH 67/71] fix: do not register libp2p handler twice for same protocol (#6455) --- packages/reqresp/src/ReqResp.ts | 21 ++++++++++----------- packages/reqresp/test/unit/ReqResp.test.ts | 8 ++++++++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/reqresp/src/ReqResp.ts b/packages/reqresp/src/ReqResp.ts index 1e42debba4e2..dc1459d87497 100644 --- a/packages/reqresp/src/ReqResp.ts +++ b/packages/reqresp/src/ReqResp.ts @@ -57,8 +57,6 @@ export class ReqResp { private readonly protocolPrefix: string; /** `${protocolPrefix}/${method}/${version}/${encoding}` */ - // Use any to avoid TS error on registering protocol - // Type 'unknown' is not assignable to type 'Resp' private readonly registeredProtocols = new Map(); private readonly dialOnlyProtocols = new Map(); @@ -79,28 +77,29 @@ export class ReqResp { * * Made it explicit method to avoid any developer mistake */ - registerDialOnlyProtocol(protocol: DialOnlyProtocol, opts?: ReqRespRegisterOpts): void { + registerDialOnlyProtocol(protocol: DialOnlyProtocol): void { const protocolID = this.formatProtocolID(protocol); - // libp2p will throw on error on duplicates, allow to overwrite behavior - if (opts?.ignoreIfDuplicate && this.registeredProtocols.has(protocolID)) { - return; - } - this.registeredProtocols.set(protocolID, protocol); this.dialOnlyProtocols.set(protocolID, true); } /** * Register protocol as supported and to libp2p. - * async because libp2p registar persists the new protocol list in the peer-store. + * async because libp2p registrar persists the new protocol list in the peer-store. * Throws if the same protocol is registered twice. * Can be called at any time, no concept of started / stopped */ async registerProtocol(protocol: Protocol, opts?: ReqRespRegisterOpts): Promise { const protocolID = this.formatProtocolID(protocol); + + // libp2p will throw if handler for protocol is already registered, allow to overwrite behavior + if (opts?.ignoreIfDuplicate && this.registeredProtocols.has(protocolID)) { + return; + } + const {handler: _handler, inboundRateLimits, ...rest} = protocol; - this.registerDialOnlyProtocol(rest, opts); + this.registerDialOnlyProtocol(rest); this.dialOnlyProtocols.set(protocolID, false); if (inboundRateLimits) { @@ -112,7 +111,7 @@ export class ReqResp { /** * Remove protocol as supported and from libp2p. - * async because libp2p registar persists the new protocol list in the peer-store. + * async because libp2p registrar persists the new protocol list in the peer-store. * Does NOT throw if the protocolID is unknown. * Can be called at any time, no concept of started / stopped */ diff --git a/packages/reqresp/test/unit/ReqResp.test.ts b/packages/reqresp/test/unit/ReqResp.test.ts index b62b1883cce1..8d78a46f292f 100644 --- a/packages/reqresp/test/unit/ReqResp.test.ts +++ b/packages/reqresp/test/unit/ReqResp.test.ts @@ -63,5 +63,13 @@ describe("ResResp", () => { expect(reqresp.getRegisteredProtocols()).toEqual(["/eth2/beacon_chain/req/number_to_string/1/ssz_snappy"]); expect(libp2p.handle).toHaveBeenCalledOnce(); }); + + it("should not register handler twice for same protocol if ignoreIfDuplicate=true", async () => { + await reqresp.registerProtocol(numberToStringProtocol, {ignoreIfDuplicate: true}); + expect(libp2p.handle).toHaveBeenCalledOnce(); + + await reqresp.registerProtocol(numberToStringProtocol, {ignoreIfDuplicate: true}); + expect(libp2p.handle).toHaveBeenCalledOnce(); + }); }); }); From 6b01690f47b358a4d589d7b62933b0b8e7dd8245 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 20 Feb 2024 11:50:14 +0100 Subject: [PATCH 68/71] fix: ignore known blocks during publishing (#6457) --- packages/beacon-node/src/api/impl/beacon/blocks/index.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts index d4aa2337fe3f..79e258960b2c 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts @@ -8,7 +8,7 @@ import {BlockSource, getBlockInput, ImportBlockOpts, BlockInput} from "../../../ import {promiseAllMaybeAsync} from "../../../../util/promises.js"; import {isOptimisticBlock} from "../../../../util/forkChoice.js"; import {computeBlobSidecars} from "../../../../util/blobs.js"; -import {BlockError, BlockErrorCode} from "../../../../chain/errors/index.js"; +import {BlockError, BlockErrorCode, BlockGossipError} from "../../../../chain/errors/index.js"; import {OpSource} from "../../../../metrics/validatorMonitor.js"; import {NetworkEvent} from "../../../../network/index.js"; import {ApiModules} from "../../types.js"; @@ -83,6 +83,13 @@ export function getBeaconBlockApi({ try { await validateGossipBlock(config, chain, signedBlock, fork); } catch (error) { + if (error instanceof BlockGossipError && error.type.code === BlockErrorCode.ALREADY_KNOWN) { + chain.logger.debug("Ignoring known block during publishing", valLogMeta); + // Blocks might already be published by another node as part of a fallback setup or DVT cluster + // and can reach our node by gossip before the api. The error can be ignored and should not result in a 500 response. + return; + } + chain.logger.error("Gossip validations failed while publishing the block", valLogMeta, error as Error); chain.persistInvalidSszValue( chain.config.getForkTypes(slot).SignedBeaconBlock, From 0a12b1bdb1423274f770d834656027394e3d2cab Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 20 Feb 2024 16:27:03 +0100 Subject: [PATCH 69/71] chore: fix typos in un-/subscribing attnets logs (#6454) --- packages/beacon-node/src/network/subnets/attnetsService.ts | 4 ++-- packages/beacon-node/src/network/subnets/dllAttnetsService.ts | 4 ++-- packages/beacon-node/src/network/subnets/syncnetsService.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/beacon-node/src/network/subnets/attnetsService.ts b/packages/beacon-node/src/network/subnets/attnetsService.ts index 7eabc2e4114c..ab24714e5da9 100644 --- a/packages/beacon-node/src/network/subnets/attnetsService.ts +++ b/packages/beacon-node/src/network/subnets/attnetsService.ts @@ -147,7 +147,7 @@ export class AttnetsService implements IAttnetsService { /** Call ONLY ONCE: Two epoch before the fork, re-subscribe all existing random subscriptions to the new fork */ subscribeSubnetsToNextFork(nextFork: ForkName): void { - this.logger.info("Suscribing to random attnets to next fork", {nextFork}); + this.logger.info("Subscribing to random attnets to next fork", {nextFork}); for (const subnet of this.subscriptionsRandom.getAll()) { this.gossip.subscribeTopic({type: gossipType, fork: nextFork, subnet}); } @@ -155,7 +155,7 @@ export class AttnetsService implements IAttnetsService { /** Call ONLY ONCE: Two epochs after the fork, un-subscribe all subnets from the old fork */ unsubscribeSubnetsFromPrevFork(prevFork: ForkName): void { - this.logger.info("Unsuscribing to random attnets from prev fork", {prevFork}); + this.logger.info("Unsubscribing to random attnets from prev fork", {prevFork}); for (let subnet = 0; subnet < ATTESTATION_SUBNET_COUNT; subnet++) { if (!this.opts.subscribeAllSubnets) { this.gossip.unsubscribeTopic({type: gossipType, fork: prevFork, subnet}); diff --git a/packages/beacon-node/src/network/subnets/dllAttnetsService.ts b/packages/beacon-node/src/network/subnets/dllAttnetsService.ts index 7236695cb11a..9de0bef68357 100644 --- a/packages/beacon-node/src/network/subnets/dllAttnetsService.ts +++ b/packages/beacon-node/src/network/subnets/dllAttnetsService.ts @@ -138,7 +138,7 @@ export class DLLAttnetsService implements IAttnetsService { * Call ONLY ONCE: Two epoch before the fork, re-subscribe all existing random subscriptions to the new fork **/ subscribeSubnetsToNextFork(nextFork: ForkName): void { - this.logger.info("Suscribing to long lived attnets to next fork", { + this.logger.info("Subscribing to long lived attnets to next fork", { nextFork, subnets: Array.from(this.longLivedSubscriptions).join(","), }); @@ -152,7 +152,7 @@ export class DLLAttnetsService implements IAttnetsService { * Call ONLY ONCE: Two epochs after the fork, un-subscribe all subnets from the old fork **/ unsubscribeSubnetsFromPrevFork(prevFork: ForkName): void { - this.logger.info("Unsuscribing to long lived attnets from prev fork", {prevFork}); + this.logger.info("Unsubscribing to long lived attnets from prev fork", {prevFork}); for (let subnet = 0; subnet < ATTESTATION_SUBNET_COUNT; subnet++) { if (!this.opts.subscribeAllSubnets) { this.gossip.unsubscribeTopic({type: gossipType, fork: prevFork, subnet}); diff --git a/packages/beacon-node/src/network/subnets/syncnetsService.ts b/packages/beacon-node/src/network/subnets/syncnetsService.ts index 147c4d0b5fb8..c61b1060899a 100644 --- a/packages/beacon-node/src/network/subnets/syncnetsService.ts +++ b/packages/beacon-node/src/network/subnets/syncnetsService.ts @@ -74,7 +74,7 @@ export class SyncnetsService implements SubnetsService { /** Call ONLY ONCE: Two epoch before the fork, re-subscribe all existing random subscriptions to the new fork */ subscribeSubnetsToNextFork(nextFork: ForkName): void { - this.logger.info("Suscribing to random attnets to next fork", {nextFork}); + this.logger.info("Subscribing to random attnets to next fork", {nextFork}); for (const subnet of this.subscriptionsCommittee.getAll()) { this.gossip.subscribeTopic({type: gossipType, fork: nextFork, subnet}); } @@ -82,7 +82,7 @@ export class SyncnetsService implements SubnetsService { /** Call ONLY ONCE: Two epochs after the fork, un-subscribe all subnets from the old fork */ unsubscribeSubnetsFromPrevFork(prevFork: ForkName): void { - this.logger.info("Unsuscribing to random attnets from prev fork", {prevFork}); + this.logger.info("Unsubscribing to random attnets from prev fork", {prevFork}); for (let subnet = 0; subnet < SYNC_COMMITTEE_SUBNET_COUNT; subnet++) { if (!this.opts?.subscribeAllSubnets) { this.gossip.unsubscribeTopic({type: gossipType, fork: prevFork, subnet}); From d1dc217d0018f926cc92eabc32908fbdefce6cb9 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 20 Feb 2024 16:27:48 +0100 Subject: [PATCH 70/71] feat: add logs to track number of http retries (#6458) --- packages/api/src/utils/client/client.ts | 6 +++--- packages/api/src/utils/client/httpClient.ts | 10 +++++++++- .../src/eth1/provider/jsonRpcHttpClient.ts | 9 ++++----- packages/spec-test-util/package.json | 2 -- packages/spec-test-util/src/downloadTests.ts | 3 +-- packages/utils/src/retry.ts | 16 +++++++++++++--- yarn.lock | 19 ------------------- 7 files changed, 30 insertions(+), 35 deletions(-) diff --git a/packages/api/src/utils/client/client.ts b/packages/api/src/utils/client/client.ts index 1782ceea57fd..430d302a070c 100644 --- a/packages/api/src/utils/client/client.ts +++ b/packages/api/src/utils/client/client.ts @@ -8,10 +8,10 @@ import {HttpStatusCode} from "./httpStatusCode.js"; /* eslint-disable @typescript-eslint/no-explicit-any */ type ExtraOpts = {retryAttempts?: number}; -type ParamatersWithOptionalExtaOpts any> = [...Parameters, ExtraOpts] | Parameters; +type ParametersWithOptionalExtraOpts any> = [...Parameters, ExtraOpts] | Parameters; export type ApiWithExtraOpts> = { - [K in keyof T]: (...args: ParamatersWithOptionalExtaOpts) => ReturnType; + [K in keyof T]: (...args: ParametersWithOptionalExtraOpts) => ReturnType; }; // See /packages/api/src/routes/index.ts for reasoning @@ -71,7 +71,7 @@ export function generateGenericJsonClient< const returnType = returnTypes[routeId as keyof ReturnTypes] as TypeJson | null; return async function request( - ...args: ParamatersWithOptionalExtaOpts + ...args: ParametersWithOptionalExtraOpts ): Promise> { try { // extract the extraOpts if provided diff --git a/packages/api/src/utils/client/httpClient.ts b/packages/api/src/utils/client/httpClient.ts index 57214c1ae04a..ba2ea0c15498 100644 --- a/packages/api/src/utils/client/httpClient.ts +++ b/packages/api/src/utils/client/httpClient.ts @@ -184,11 +184,19 @@ export class HttpClient implements IHttpClient { getBody: (res: Response) => Promise ): Promise<{status: HttpStatusCode; body: T}> { if (opts.retryAttempts !== undefined) { + const routeId = opts.routeId ?? DEFAULT_ROUTE_ID; + return retry( async (_attempt) => { return this.requestWithBodyWithFallbacks(opts, getBody); }, - {retries: opts.retryAttempts, retryDelay: 200} + { + retries: opts.retryAttempts, + retryDelay: 200, + onRetry: (e, attempt) => { + this.logger?.debug("Retrying request", {routeId, attempt, lastError: e.message}); + }, + } ); } else { return this.requestWithBodyWithFallbacks(opts, getBody); diff --git a/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts b/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts index 17809e047944..9655aba5fc6b 100644 --- a/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts +++ b/packages/beacon-node/src/eth1/provider/jsonRpcHttpClient.ts @@ -158,11 +158,7 @@ export class JsonRpcHttpClient implements IJsonRpcHttpClient { const routeId = opts?.routeId ?? "unknown"; const res = await retry>( - async (attempt) => { - /** If this is a retry, increment the retry counter for this method */ - if (attempt > 1) { - this.opts?.metrics?.retryCount.inc({routeId}); - } + async (_attempt) => { return this.fetchJson({jsonrpc: "2.0", id: this.id++, ...payload}, opts); }, { @@ -170,6 +166,9 @@ export class JsonRpcHttpClient implements IJsonRpcHttpClient { retryDelay: opts?.retryDelay ?? this.opts?.retryDelay ?? 0, shouldRetry: opts?.shouldRetry, signal: this.opts?.signal, + onRetry: () => { + this.opts?.metrics?.retryCount.inc({routeId}); + }, } ); return parseRpcResponse(res, payload); diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index 1b2218fff1e1..e96ee7f550f8 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -63,7 +63,6 @@ ], "dependencies": { "@lodestar/utils": "^1.15.1", - "async-retry": "^1.3.3", "axios": "^1.3.4", "rimraf": "^4.4.1", "snappyjs": "^0.7.0", @@ -71,7 +70,6 @@ "vitest": "^1.2.1" }, "devDependencies": { - "@types/async-retry": "1.4.3", "@types/tar": "^6.1.4" }, "peerDependencies": { diff --git a/packages/spec-test-util/src/downloadTests.ts b/packages/spec-test-util/src/downloadTests.ts index 9e90d5825bdf..e13478934927 100644 --- a/packages/spec-test-util/src/downloadTests.ts +++ b/packages/spec-test-util/src/downloadTests.ts @@ -6,7 +6,7 @@ import {promisify} from "node:util"; import {rimraf} from "rimraf"; import axios from "axios"; import {x as extractTar} from "tar"; -import retry from "async-retry"; +import {retry} from "@lodestar/utils"; export const defaultSpecTestsRepoUrl = "https://github.com/ethereum/consensus-spec-tests"; @@ -67,7 +67,6 @@ export async function downloadGenericSpecTests( const url = `${specTestsRepoUrl ?? defaultSpecTestsRepoUrl}/releases/download/${specVersion}/${test}.tar.gz`; await retry( - // async (bail) => { async () => { const {data, headers} = await axios({ method: "get", diff --git a/packages/utils/src/retry.ts b/packages/utils/src/retry.ts index 19ebffc16898..21d3b9a805e4 100644 --- a/packages/utils/src/retry.ts +++ b/packages/utils/src/retry.ts @@ -6,11 +6,17 @@ export type RetryOptions = { */ retries?: number; /** - * An optional Function that is invoked after the provided callback throws - * It expects a boolean to know if it should retry or not - * Useful to make retrying conditional on the type of error thrown + * An optional Function that is invoked after the provided callback throws. + * It expects a boolean to know if it should retry or not. + * Useful to make retrying conditional on the type of error thrown. */ shouldRetry?: (lastError: Error) => boolean; + /** + * An optional Function that is invoked right before a retry is performed. + * It's passed the Error that triggered it and a number identifying the attempt. + * Useful to track number of retries and errors in logs or metrics. + */ + onRetry?: (lastError: Error, attempt: number) => unknown; /** * Milliseconds to wait before retrying again */ @@ -27,10 +33,14 @@ export type RetryOptions = { export async function retry(fn: (attempt: number) => A | Promise, opts?: RetryOptions): Promise { const maxRetries = opts?.retries ?? 5; const shouldRetry = opts?.shouldRetry; + const onRetry = opts?.onRetry; let lastError: Error = Error("RetryError"); for (let i = 1; i <= maxRetries; i++) { try { + // If not the first attempt, invoke right before retrying + if (i > 1) onRetry?.(lastError, i); + return await fn(i); } catch (e) { lastError = e as Error; diff --git a/yarn.lock b/yarn.lock index c858ef47ddf0..669492e94737 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2810,13 +2810,6 @@ resolved "https://registry.npmjs.org/@types/abstract-leveldown/-/abstract-leveldown-5.0.1.tgz" integrity sha512-wYxU3kp5zItbxKmeRYCEplS2MW7DzyBnxPGj+GJVHZEUZiK/nn5Ei1sUFgURDh+X051+zsGe28iud3oHjrYWQQ== -"@types/async-retry@1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@types/async-retry/-/async-retry-1.4.3.tgz#8b78f6ce88d97e568961732cdd9e5325cdc8c246" - integrity sha512-B3C9QmmNULVPL2uSJQ088eGWTNPIeUk35hca6CV8rRDJ8GXuQJP5CCVWA1ZUCrb9xYP7Js/RkLqnNNwKhe+Zsw== - dependencies: - "@types/retry" "*" - "@types/buffer-xor@^2.0.0": version "2.0.0" resolved "https://registry.npmjs.org/@types/buffer-xor/-/buffer-xor-2.0.0.tgz" @@ -3965,13 +3958,6 @@ async-lock@^1.4.0: resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.0.tgz#c8b6630eff68fbbdd8a5b6eb763dac3bfbb8bf02" integrity sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ== -async-retry@^1.3.3: - version "1.3.3" - resolved "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz" - integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== - dependencies: - retry "0.13.1" - async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" @@ -10939,11 +10925,6 @@ ret@~0.2.0: resolved "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz" integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== -retry@0.13.1: - version "0.13.1" - resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" From fda3b19c4fbb9ff8eb71155a031737b2be0fe661 Mon Sep 17 00:00:00 2001 From: Cayman Date: Tue, 20 Feb 2024 13:16:26 -0500 Subject: [PATCH 71/71] v1.16.0 --- lerna.json | 2 +- packages/api/package.json | 10 ++++----- packages/beacon-node/package.json | 28 +++++++++++++------------- packages/cli/package.json | 26 ++++++++++++------------ packages/config/package.json | 6 +++--- packages/db/package.json | 8 ++++---- packages/flare/package.json | 14 ++++++------- packages/fork-choice/package.json | 12 +++++------ packages/light-client/package.json | 14 ++++++------- packages/logger/package.json | 6 +++--- packages/params/package.json | 2 +- packages/prover/package.json | 18 ++++++++--------- packages/reqresp/package.json | 12 +++++------ packages/spec-test-util/package.json | 4 ++-- packages/state-transition/package.json | 10 ++++----- packages/test-utils/package.json | 6 +++--- packages/types/package.json | 4 ++-- packages/utils/package.json | 2 +- packages/validator/package.json | 18 ++++++++--------- 19 files changed, 101 insertions(+), 101 deletions(-) diff --git a/lerna.json b/lerna.json index 5362d02551d8..a79413a21c37 100644 --- a/lerna.json +++ b/lerna.json @@ -4,7 +4,7 @@ ], "npmClient": "yarn", "useNx": true, - "version": "1.15.1", + "version": "1.16.0", "stream": true, "command": { "version": { diff --git a/packages/api/package.json b/packages/api/package.json index 8b5847c1a47e..db84e9618ad6 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -69,10 +69,10 @@ "dependencies": { "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/config": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", "eventsource": "^2.0.2", "qs": "^6.11.1" }, diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 8413f9523652..7608035cb440 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -100,8 +100,8 @@ "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", "@chainsafe/libp2p-gossipsub": "^11.2.1", - "@chainsafe/libp2p-noise": "^14.1.0", "@chainsafe/libp2p-identify": "^1.0.0", + "@chainsafe/libp2p-noise": "^14.1.0", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/prometheus-gc-stats": "^1.0.0", "@chainsafe/ssz": "^0.14.0", @@ -120,18 +120,18 @@ "@libp2p/peer-id-factory": "^4.0.3", "@libp2p/prometheus-metrics": "^3.0.10", "@libp2p/tcp": "9.0.10", - "@lodestar/api": "^1.15.1", - "@lodestar/config": "^1.15.1", - "@lodestar/db": "^1.15.1", - "@lodestar/fork-choice": "^1.15.1", - "@lodestar/light-client": "^1.15.1", - "@lodestar/logger": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/reqresp": "^1.15.1", - "@lodestar/state-transition": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", - "@lodestar/validator": "^1.15.1", + "@lodestar/api": "^1.16.0", + "@lodestar/config": "^1.16.0", + "@lodestar/db": "^1.16.0", + "@lodestar/fork-choice": "^1.16.0", + "@lodestar/light-client": "^1.16.0", + "@lodestar/logger": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/reqresp": "^1.16.0", + "@lodestar/state-transition": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", + "@lodestar/validator": "^1.16.0", "@multiformats/multiaddr": "^12.1.3", "@types/datastore-level": "^3.0.0", "buffer-xor": "^2.0.2", diff --git a/packages/cli/package.json b/packages/cli/package.json index 0d56f85a7434..0906047fd232 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/lodestar", - "version": "1.15.1", + "version": "1.16.0", "description": "Command line interface for lodestar", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -64,17 +64,17 @@ "@libp2p/crypto": "^3.0.4", "@libp2p/peer-id": "^4.0.4", "@libp2p/peer-id-factory": "^4.0.3", - "@lodestar/api": "^1.15.1", - "@lodestar/beacon-node": "^1.15.1", - "@lodestar/config": "^1.15.1", - "@lodestar/db": "^1.15.1", - "@lodestar/light-client": "^1.15.1", - "@lodestar/logger": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/state-transition": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", - "@lodestar/validator": "^1.15.1", + "@lodestar/api": "^1.16.0", + "@lodestar/beacon-node": "^1.16.0", + "@lodestar/config": "^1.16.0", + "@lodestar/db": "^1.16.0", + "@lodestar/light-client": "^1.16.0", + "@lodestar/logger": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/state-transition": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", + "@lodestar/validator": "^1.16.0", "@multiformats/multiaddr": "^12.1.3", "bip39": "^3.1.0", "deepmerge": "^4.3.1", @@ -94,7 +94,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.15.1", + "@lodestar/test-utils": "^1.16.0", "@types/debug": "^4.1.7", "@types/expand-tilde": "^2.0.0", "@types/got": "^9.6.12", diff --git a/packages/config/package.json b/packages/config/package.json index 2e2823cd6db4..669eb6f6e07c 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/config", - "version": "1.15.1", + "version": "1.16.0", "description": "Chain configuration required for lodestar", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -65,7 +65,7 @@ ], "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/params": "^1.15.1", - "@lodestar/types": "^1.15.1" + "@lodestar/params": "^1.16.0", + "@lodestar/types": "^1.16.0" } } diff --git a/packages/db/package.json b/packages/db/package.json index 930a79a4333a..50a1531d4b8c 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/db", - "version": "1.15.1", + "version": "1.16.0", "description": "DB modules of Lodestar", "author": "ChainSafe Systems", "homepage": "https://github.com/ChainSafe/lodestar#readme", @@ -36,13 +36,13 @@ }, "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/config": "^1.16.0", + "@lodestar/utils": "^1.16.0", "@types/levelup": "^4.3.3", "it-all": "^3.0.4", "level": "^8.0.0" }, "devDependencies": { - "@lodestar/logger": "^1.15.1" + "@lodestar/logger": "^1.16.0" } } diff --git a/packages/flare/package.json b/packages/flare/package.json index bc5f265f1f87..6281ea0f81f1 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/flare", - "version": "1.15.1", + "version": "1.16.0", "description": "Beacon chain debugging tool", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -60,12 +60,12 @@ "dependencies": { "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keygen": "^0.4.0", - "@lodestar/api": "^1.15.1", - "@lodestar/config": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/state-transition": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/api": "^1.16.0", + "@lodestar/config": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/state-transition": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", "source-map-support": "^0.5.21", "yargs": "^17.7.1" }, diff --git a/packages/fork-choice/package.json b/packages/fork-choice/package.json index ca1332b3ee14..f60551531589 100644 --- a/packages/fork-choice/package.json +++ b/packages/fork-choice/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": "./lib/index.js", "types": "./lib/index.d.ts", @@ -37,11 +37,11 @@ }, "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/state-transition": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1" + "@lodestar/config": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/state-transition": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0" }, "keywords": [ "ethereum", diff --git a/packages/light-client/package.json b/packages/light-client/package.json index ae65958da8e4..2f392b169f07 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -68,12 +68,12 @@ "@chainsafe/bls": "7.1.3", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/api": "^1.15.1", - "@lodestar/config": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/state-transition": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/api": "^1.16.0", + "@lodestar/config": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/state-transition": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", "mitt": "^3.0.0", "strict-event-emitter-types": "^2.0.0" }, diff --git a/packages/logger/package.json b/packages/logger/package.json index 29eec16d3bdd..e0b69b0a9a7d 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -66,14 +66,14 @@ }, "types": "lib/index.d.ts", "dependencies": { - "@lodestar/utils": "^1.15.1", + "@lodestar/utils": "^1.16.0", "winston": "^3.8.2", "winston-daily-rotate-file": "^4.7.1", "winston-transport": "^4.5.0" }, "devDependencies": { "@chainsafe/threads": "^1.11.1", - "@lodestar/test-utils": "^1.15.1", + "@lodestar/test-utils": "^1.16.0", "@types/triple-beam": "^1.3.2", "rimraf": "^4.4.1", "triple-beam": "^1.3.0" diff --git a/packages/params/package.json b/packages/params/package.json index ced76e18b548..8902b2bceb8e 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/params", - "version": "1.15.1", + "version": "1.16.0", "description": "Chain parameters required for lodestar", "author": "ChainSafe Systems", "license": "Apache-2.0", diff --git a/packages/prover/package.json b/packages/prover/package.json index 5c7d8ad8d691..a170b39dc7e7 100644 --- a/packages/prover/package.json +++ b/packages/prover/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -70,13 +70,13 @@ "@ethereumjs/tx": "^4.1.2", "@ethereumjs/util": "^8.0.6", "@ethereumjs/vm": "^6.4.2", - "@lodestar/api": "^1.15.1", - "@lodestar/config": "^1.15.1", - "@lodestar/light-client": "^1.15.1", - "@lodestar/logger": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/api": "^1.16.0", + "@lodestar/config": "^1.16.0", + "@lodestar/light-client": "^1.16.0", + "@lodestar/logger": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", "ethereum-cryptography": "^2.0.0", "find-up": "^6.3.0", "http-proxy": "^1.18.1", @@ -85,7 +85,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.15.1", + "@lodestar/test-utils": "^1.16.0", "@types/http-proxy": "^1.17.10", "@types/yargs": "^17.0.24", "axios": "^1.3.4", diff --git a/packages/reqresp/package.json b/packages/reqresp/package.json index 80fcb8d8b4f3..20627f4de384 100644 --- a/packages/reqresp/package.json +++ b/packages/reqresp/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -54,9 +54,9 @@ "dependencies": { "@chainsafe/fast-crc32c": "^4.1.1", "@libp2p/interface": "^1.1.1", - "@lodestar/config": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/config": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/utils": "^1.16.0", "it-all": "^3.0.4", "it-pipe": "^3.0.1", "snappy": "^7.2.2", @@ -65,8 +65,8 @@ "uint8arraylist": "^2.4.7" }, "devDependencies": { - "@lodestar/logger": "^1.15.1", - "@lodestar/types": "^1.15.1", + "@lodestar/logger": "^1.16.0", + "@lodestar/types": "^1.16.0", "libp2p": "1.1.1" }, "peerDependencies": { diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index e96ee7f550f8..8b4ab28da0fd 100644 --- a/packages/spec-test-util/package.json +++ b/packages/spec-test-util/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/spec-test-util", - "version": "1.15.1", + "version": "1.16.0", "description": "Spec test suite generator from yaml test files", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -62,7 +62,7 @@ "blockchain" ], "dependencies": { - "@lodestar/utils": "^1.15.1", + "@lodestar/utils": "^1.16.0", "axios": "^1.3.4", "rimraf": "^4.4.1", "snappyjs": "^0.7.0", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index f4a910d9f5c8..7c3e02a878b9 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -64,10 +64,10 @@ "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/config": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", "bigint-buffer": "^1.1.5", "buffer-xor": "^2.0.2" }, diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 5cb3164b3cbc..9d8e8c306e37 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@lodestar/test-utils", "private": true, - "version": "1.15.1", + "version": "1.16.0", "description": "Test utilities reused across other packages", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -59,8 +59,8 @@ "dependencies": { "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keystore": "^3.0.1", - "@lodestar/params": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/params": "^1.16.0", + "@lodestar/utils": "^1.16.0", "axios": "^1.3.4", "testcontainers": "^10.2.1", "tmp": "^0.2.1", diff --git a/packages/types/package.json b/packages/types/package.json index d84ebb33472d..c492eed43014 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": { ".": { @@ -74,7 +74,7 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/params": "^1.15.1", + "@lodestar/params": "^1.16.0", "ethereum-cryptography": "^2.0.0" }, "keywords": [ diff --git a/packages/utils/package.json b/packages/utils/package.json index 16f663e8f07d..06c89f6593ca 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -11,7 +11,7 @@ "bugs": { "url": "https://github.com/ChainSafe/lodestar/issues" }, - "version": "1.15.1", + "version": "1.16.0", "type": "module", "exports": "./lib/index.js", "files": [ diff --git a/packages/validator/package.json b/packages/validator/package.json index e7877ae458a0..c415d44c5a46 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/validator", - "version": "1.15.1", + "version": "1.16.0", "description": "A Typescript implementation of the validator client", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -47,18 +47,18 @@ "dependencies": { "@chainsafe/bls": "7.1.3", "@chainsafe/ssz": "^0.14.0", - "@lodestar/api": "^1.15.1", - "@lodestar/config": "^1.15.1", - "@lodestar/db": "^1.15.1", - "@lodestar/params": "^1.15.1", - "@lodestar/state-transition": "^1.15.1", - "@lodestar/types": "^1.15.1", - "@lodestar/utils": "^1.15.1", + "@lodestar/api": "^1.16.0", + "@lodestar/config": "^1.16.0", + "@lodestar/db": "^1.16.0", + "@lodestar/params": "^1.16.0", + "@lodestar/state-transition": "^1.16.0", + "@lodestar/types": "^1.16.0", + "@lodestar/utils": "^1.16.0", "bigint-buffer": "^1.1.5", "strict-event-emitter-types": "^2.0.0" }, "devDependencies": { - "@lodestar/test-utils": "^1.15.1", + "@lodestar/test-utils": "^1.16.0", "bigint-buffer": "^1.1.5", "rimraf": "^4.4.1" }