From 398be86c6d1c6a7c0ecbfd5c90b77e142bb49f09 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 23 Jan 2024 15:04:35 +0100 Subject: [PATCH 01/45] feat: schedule deneb on chiado (#6342) --- packages/config/src/chainConfig/networks/chiado.ts | 1 + packages/config/src/chainConfig/networks/gnosis.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/packages/config/src/chainConfig/networks/chiado.ts b/packages/config/src/chainConfig/networks/chiado.ts index 01739cf1d4eb..43b13a210dac 100644 --- a/packages/config/src/chainConfig/networks/chiado.ts +++ b/packages/config/src/chainConfig/networks/chiado.ts @@ -37,4 +37,5 @@ export const chiadoChainConfig: ChainConfig = { CAPELLA_FORK_EPOCH: 244224, // Wed May 24 2023 13:12:00 GMT+0000 // Deneb DENEB_FORK_VERSION: b("0x0400006f"), + DENEB_FORK_EPOCH: 516608, // Wed Jan 31 2024 18:15:40 GMT+0000 }; diff --git a/packages/config/src/chainConfig/networks/gnosis.ts b/packages/config/src/chainConfig/networks/gnosis.ts index 6f3ccfed39e6..7bafaa0225b1 100644 --- a/packages/config/src/chainConfig/networks/gnosis.ts +++ b/packages/config/src/chainConfig/networks/gnosis.ts @@ -23,11 +23,17 @@ export const gnosisChainConfig: ChainConfig = { ETH1_FOLLOW_DISTANCE: 1024, CHURN_LIMIT_QUOTIENT: 4096, + // Validator cycle + MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: 2, + // Deposit contract DEPOSIT_CHAIN_ID: 100, DEPOSIT_NETWORK_ID: 100, DEPOSIT_CONTRACT_ADDRESS: b("0x0b98057ea310f4d31f2a452b414647007d1645d9"), + // Networking + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 16384, + // Dec 8, 2021, 13:00 UTC MIN_GENESIS_TIME: 1638968400, MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 4096, From 43994ba8ef665c98d7ec6dcbb5338ebf5906f249 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 23 Jan 2024 17:05:04 +0100 Subject: [PATCH 02/45] fix: update beacon max-old-space-size to 8192 (#6343) * feat: increase default memory limit to 8GB * Revise comments --- Dockerfile | 6 +++--- docker-compose.yml | 6 +++--- docs/pages/tools/flamegraphs.md | 2 +- lodestar | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5a9541e06f1a..a9e597c2fb9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,9 +39,9 @@ FROM node:20-alpine WORKDIR /usr/app COPY --from=build_deps /usr/app . -# NodeJS applications have a default memory limit of 2.5GB. -# This limit is bit tight for a Prater node, it is recommended to raise the limit +# NodeJS applications have a default memory limit of 4GB on most machines. +# This limit is bit tight for a Mainnet node, it is recommended to raise the limit # since memory may spike during certain network conditions. -ENV NODE_OPTIONS=--max-old-space-size=4096 +ENV NODE_OPTIONS=--max-old-space-size=8192 ENTRYPOINT ["node", "./packages/cli/bin/lodestar"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index cab1245d351e..d8c6122e3537 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,11 +11,11 @@ services: - "9000:9000" # P2P port # - "9596:9596" # REST API port command: beacon --dataDir /data --rest --rest.address 0.0.0.0 --metrics --logFile /logs/beacon.log --logFileLevel debug --logFileDailyRotate 5 - # NodeJS applications have a default memory limit of 2.5GB. - # This limit is bit tight for a Prater node, it is recommended to raise the limit + # NodeJS applications have a default memory limit of 4GB on most machines. + # This limit is bit tight for a Mainnet node, it is recommended to raise the limit # since memory may spike during certain network conditions. environment: - NODE_OPTIONS: --max-old-space-size=4096 + NODE_OPTIONS: --max-old-space-size=8192 prometheus: build: docker/prometheus diff --git a/docs/pages/tools/flamegraphs.md b/docs/pages/tools/flamegraphs.md index d6f45303a9aa..119cc7dc10e5 100644 --- a/docs/pages/tools/flamegraphs.md +++ b/docs/pages/tools/flamegraphs.md @@ -18,7 +18,7 @@ Next we need to update the Lodestar service by modifying the start script. We ne ```sh node \ --perf-basic-prof \ - --max-old-space-size=4096 \ + --max-old-space-size=8192 \ /usr/src/lodestar/packages/cli/bin/lodestar \ beacon \ --rcConfig /home/devops/beacon/rcconfig.yml diff --git a/lodestar b/lodestar index 2101d94b77cb..0b20ba4c9bcd 100755 --- a/lodestar +++ b/lodestar @@ -2,6 +2,6 @@ # Convenience script to run the lodestar binary from built source # -# ./lodestar.sh beacon --network prater +# ./lodestar.sh beacon --network mainnet -node --trace-deprecation --max-old-space-size=4096 ./packages/cli/bin/lodestar.js "$@" \ No newline at end of file +node --trace-deprecation --max-old-space-size=8192 ./packages/cli/bin/lodestar.js "$@" \ No newline at end of file From 92ed3479a6ac59b75d100b9738ee437b2e80a748 Mon Sep 17 00:00:00 2001 From: Phil Ngo Date: Tue, 23 Jan 2024 11:06:39 -0500 Subject: [PATCH 03/45] v1.15.0 --- lerna.json | 2 +- packages/api/package.json | 10 +++++----- packages/beacon-node/package.json | 26 +++++++++++++------------- 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 | 8 ++++---- 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, 102 insertions(+), 102 deletions(-) diff --git a/lerna.json b/lerna.json index 487caa95b0a2..2a9439d49715 100644 --- a/lerna.json +++ b/lerna.json @@ -4,7 +4,7 @@ ], "npmClient": "yarn", "useNx": true, - "version": "1.14.0", + "version": "1.15.0", "stream": true, "command": { "version": { diff --git a/packages/api/package.json b/packages/api/package.json index e1a52c47b489..533961953b9a 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -71,10 +71,10 @@ "dependencies": { "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/config": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.0", "eventsource": "^2.0.2", "qs": "^6.11.1" }, diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 3ddde8540670..8ce625fb0d54 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -121,18 +121,18 @@ "@libp2p/peer-id-factory": "^4.0.3", "@libp2p/prometheus-metrics": "^3.0.10", "@libp2p/tcp": "9.0.10", - "@lodestar/api": "^1.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/db": "^1.14.0", - "@lodestar/fork-choice": "^1.14.0", - "@lodestar/light-client": "^1.14.0", - "@lodestar/logger": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/reqresp": "^1.14.0", - "@lodestar/state-transition": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", - "@lodestar/validator": "^1.14.0", + "@lodestar/api": "^1.15.0", + "@lodestar/config": "^1.15.0", + "@lodestar/db": "^1.15.0", + "@lodestar/fork-choice": "^1.15.0", + "@lodestar/light-client": "^1.15.0", + "@lodestar/logger": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/reqresp": "^1.15.0", + "@lodestar/state-transition": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.0", + "@lodestar/validator": "^1.15.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 243dee688417..616dce9d4f68 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/lodestar", - "version": "1.14.0", + "version": "1.15.0", "description": "Command line interface for lodestar", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -66,17 +66,17 @@ "@libp2p/crypto": "^3.0.4", "@libp2p/peer-id": "^4.0.4", "@libp2p/peer-id-factory": "^4.0.3", - "@lodestar/api": "^1.14.0", - "@lodestar/beacon-node": "^1.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/db": "^1.14.0", - "@lodestar/light-client": "^1.14.0", - "@lodestar/logger": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/state-transition": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", - "@lodestar/validator": "^1.14.0", + "@lodestar/api": "^1.15.0", + "@lodestar/beacon-node": "^1.15.0", + "@lodestar/config": "^1.15.0", + "@lodestar/db": "^1.15.0", + "@lodestar/light-client": "^1.15.0", + "@lodestar/logger": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/state-transition": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.0", + "@lodestar/validator": "^1.15.0", "@multiformats/multiaddr": "^12.1.3", "@types/lockfile": "^1.0.2", "bip39": "^3.1.0", @@ -97,7 +97,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.14.0", + "@lodestar/test-utils": "^1.15.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 3b0a649e78c5..a36da8c6240a 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/config", - "version": "1.14.0", + "version": "1.15.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.14.0", - "@lodestar/types": "^1.14.0" + "@lodestar/params": "^1.15.0", + "@lodestar/types": "^1.15.0" } } diff --git a/packages/db/package.json b/packages/db/package.json index d99b21d80b9b..f11e5b48995c 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/db", - "version": "1.14.0", + "version": "1.15.0", "description": "DB modules of Lodestar", "author": "ChainSafe Systems", "homepage": "https://github.com/ChainSafe/lodestar#readme", @@ -38,13 +38,13 @@ }, "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/config": "^1.15.0", + "@lodestar/utils": "^1.15.0", "@types/levelup": "^4.3.3", "it-all": "^3.0.4", "level": "^8.0.0" }, "devDependencies": { - "@lodestar/logger": "^1.14.0" + "@lodestar/logger": "^1.15.0" } } diff --git a/packages/flare/package.json b/packages/flare/package.json index 7417cf93c63d..93973110ab8a 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/flare", - "version": "1.14.0", + "version": "1.15.0", "description": "Beacon chain debugging tool", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -60,12 +60,12 @@ "dependencies": { "@chainsafe/bls": "7.1.1", "@chainsafe/bls-keygen": "^0.3.0", - "@lodestar/api": "^1.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/state-transition": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/api": "^1.15.0", + "@lodestar/config": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/state-transition": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.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 495c67a8e80b..606dec811bbc 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.14.0", + "version": "1.15.0", "type": "module", "exports": "./lib/index.js", "types": "./lib/index.d.ts", @@ -39,11 +39,11 @@ }, "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/state-transition": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0" + "@lodestar/config": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/state-transition": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.0" }, "keywords": [ "ethereum", diff --git a/packages/light-client/package.json b/packages/light-client/package.json index dee231409730..456600cbd0bc 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -70,12 +70,12 @@ "@chainsafe/bls": "7.1.1", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/api": "^1.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/state-transition": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/api": "^1.15.0", + "@lodestar/config": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/state-transition": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.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 2f450ee5be12..f1a5ddad1a06 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -66,14 +66,14 @@ }, "types": "lib/index.d.ts", "dependencies": { - "@lodestar/utils": "^1.14.0", + "@lodestar/utils": "^1.15.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.14.0", + "@lodestar/test-utils": "^1.15.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 2586c73566aa..d41dae06816e 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/params", - "version": "1.14.0", + "version": "1.15.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 05f7c33579b4..600f4b4d4d75 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -72,13 +72,13 @@ "@ethereumjs/tx": "^4.1.2", "@ethereumjs/util": "^8.0.6", "@ethereumjs/vm": "^6.4.2", - "@lodestar/api": "^1.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/light-client": "^1.14.0", - "@lodestar/logger": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/api": "^1.15.0", + "@lodestar/config": "^1.15.0", + "@lodestar/light-client": "^1.15.0", + "@lodestar/logger": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.0", "ethereum-cryptography": "^1.2.0", "find-up": "^6.3.0", "http-proxy": "^1.18.1", @@ -87,7 +87,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.14.0", + "@lodestar/test-utils": "^1.15.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 c19af565c397..3856177449d3 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -56,9 +56,9 @@ "dependencies": { "@chainsafe/fast-crc32c": "^4.1.1", "@libp2p/interface": "^1.1.1", - "@lodestar/config": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/config": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/utils": "^1.15.0", "it-all": "^3.0.4", "it-pipe": "^3.0.1", "snappy": "^7.2.2", @@ -67,8 +67,8 @@ "uint8arraylist": "^2.4.7" }, "devDependencies": { - "@lodestar/logger": "^1.14.0", - "@lodestar/types": "^1.14.0", + "@lodestar/logger": "^1.15.0", + "@lodestar/types": "^1.15.0", "libp2p": "1.1.1" }, "peerDependencies": { diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index 899d6438d939..f8d953e408fd 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.14.0", + "version": "1.15.0", "description": "Spec test suite generator from yaml test files", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -62,13 +62,13 @@ "blockchain" ], "dependencies": { - "@lodestar/utils": "^1.14.0", + "@lodestar/utils": "^1.15.0", "async-retry": "^1.3.3", "axios": "^1.3.4", - "vitest": "^1.2.1", "rimraf": "^4.4.1", "snappyjs": "^0.7.0", - "tar": "^6.1.13" + "tar": "^6.1.13", + "vitest": "^1.2.1" }, "devDependencies": { "@types/async-retry": "1.4.3", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index cbde9b062177..8a1aea19f140 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -63,10 +63,10 @@ "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/config": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.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 d4a1df589e8f..038cd743bdd7 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.14.0", + "version": "1.15.0", "description": "Test utilities reused across other packages", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -60,8 +60,8 @@ "dependencies": { "@chainsafe/bls": "7.1.1", "@chainsafe/bls-keystore": "^3.0.0", - "@lodestar/params": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/params": "^1.15.0", + "@lodestar/utils": "^1.15.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 b51acbef6801..1e9b811becfa 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.14.0", + "version": "1.15.0", "type": "module", "exports": { ".": { @@ -73,7 +73,7 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/params": "^1.14.0" + "@lodestar/params": "^1.15.0" }, "keywords": [ "ethereum", diff --git a/packages/utils/package.json b/packages/utils/package.json index fcc0f5ac36c1..fa1dd4fdd829 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.14.0", + "version": "1.15.0", "type": "module", "exports": "./lib/index.js", "files": [ diff --git a/packages/validator/package.json b/packages/validator/package.json index 92c3e92d04a1..020792107c3b 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/validator", - "version": "1.14.0", + "version": "1.15.0", "description": "A Typescript implementation of the validator client", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -49,18 +49,18 @@ "dependencies": { "@chainsafe/bls": "7.1.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/api": "^1.14.0", - "@lodestar/config": "^1.14.0", - "@lodestar/db": "^1.14.0", - "@lodestar/params": "^1.14.0", - "@lodestar/state-transition": "^1.14.0", - "@lodestar/types": "^1.14.0", - "@lodestar/utils": "^1.14.0", + "@lodestar/api": "^1.15.0", + "@lodestar/config": "^1.15.0", + "@lodestar/db": "^1.15.0", + "@lodestar/params": "^1.15.0", + "@lodestar/state-transition": "^1.15.0", + "@lodestar/types": "^1.15.0", + "@lodestar/utils": "^1.15.0", "bigint-buffer": "^1.1.5", "strict-event-emitter-types": "^2.0.0" }, "devDependencies": { - "@lodestar/test-utils": "^1.14.0", + "@lodestar/test-utils": "^1.15.0", "bigint-buffer": "^1.1.5", "rimraf": "^4.4.1" } From 01d47b9a0901c9f03a01ef68c819f4e592cbfd8b Mon Sep 17 00:00:00 2001 From: Julien Date: Thu, 25 Jan 2024 02:00:48 -0800 Subject: [PATCH 04/45] 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 05/45] 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 06/45] 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 07/45] 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 08/45] 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 09/45] 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 10/45] 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 11/45] 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 12/45] 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 13/45] 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 14/45] 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 15/45] 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 16/45] 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 17/45] 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 18/45] 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 19/45] 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 20/45] 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 21/45] 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 22/45] 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 23/45] 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 24/45] 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 25/45] 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 26/45] 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 27/45] 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 28/45] 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 29/45] 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 30/45] 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 31/45] 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 32/45] 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 33/45] 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 34/45] 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 1857a49404f2ad965025333f0f6b3422d4c1943f Mon Sep 17 00:00:00 2001 From: Phil Ngo <58080811+philknows@users.noreply.github.com> Date: Wed, 7 Feb 2024 08:39:24 -0500 Subject: [PATCH 35/45] chore: v1.15.1 release (#6379) * v1.15.1 * fix: ignore stale keystore lockfiles (#6363) * fix: ignore stale keystore lockfiles * Update error message if lockfile is already acquired * Update keymanager lockfile e2e tests * 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 * fix: parse --blindedLocal flag value as boolean (#6403) --------- Co-authored-by: Nico Flaig Co-authored-by: g11tech --- lerna.json | 2 +- packages/api/package.json | 10 ++-- packages/beacon-node/package.json | 26 ++++----- .../blocks/verifyBlocksExecutionPayloads.ts | 4 +- packages/cli/package.json | 30 +++++------ packages/cli/src/cmds/validator/options.ts | 2 +- packages/cli/src/util/lockfile.ts | 54 +++++++++++-------- .../test/e2e/importKeystoresFromApi.test.ts | 8 +-- .../decryptKeystoreDefinitions.test.ts | 13 +++-- packages/config/package.json | 6 +-- packages/db/package.json | 8 +-- packages/db/src/controller/level.ts | 2 +- packages/flare/package.json | 14 ++--- packages/fork-choice/package.json | 12 ++--- .../fork-choice/src/protoArray/interface.ts | 2 +- .../fork-choice/src/protoArray/protoArray.ts | 45 ++++++++-------- .../protoArray/executionStatusUpdates.test.ts | 10 ++-- 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 +++---- yarn.lock | 19 +++---- 29 files changed, 187 insertions(+), 176 deletions(-) diff --git a/lerna.json b/lerna.json index 2a9439d49715..5362d02551d8 100644 --- a/lerna.json +++ b/lerna.json @@ -4,7 +4,7 @@ ], "npmClient": "yarn", "useNx": true, - "version": "1.15.0", + "version": "1.15.1", "stream": true, "command": { "version": { diff --git a/packages/api/package.json b/packages/api/package.json index 533961953b9a..e9fa0936c3f8 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -71,10 +71,10 @@ "dependencies": { "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/types": "^1.15.0", - "@lodestar/utils": "^1.15.0", + "@lodestar/config": "^1.15.1", + "@lodestar/params": "^1.15.1", + "@lodestar/types": "^1.15.1", + "@lodestar/utils": "^1.15.1", "eventsource": "^2.0.2", "qs": "^6.11.1" }, diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 8ce625fb0d54..e2366bb86051 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -121,18 +121,18 @@ "@libp2p/peer-id-factory": "^4.0.3", "@libp2p/prometheus-metrics": "^3.0.10", "@libp2p/tcp": "9.0.10", - "@lodestar/api": "^1.15.0", - "@lodestar/config": "^1.15.0", - "@lodestar/db": "^1.15.0", - "@lodestar/fork-choice": "^1.15.0", - "@lodestar/light-client": "^1.15.0", - "@lodestar/logger": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/reqresp": "^1.15.0", - "@lodestar/state-transition": "^1.15.0", - "@lodestar/types": "^1.15.0", - "@lodestar/utils": "^1.15.0", - "@lodestar/validator": "^1.15.0", + "@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", "@multiformats/multiaddr": "^12.1.3", "@types/datastore-level": "^3.0.0", "buffer-xor": "^2.0.2", 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/cli/package.json b/packages/cli/package.json index 616dce9d4f68..839d42c7b3d6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@chainsafe/lodestar", - "version": "1.15.0", + "version": "1.15.1", "description": "Command line interface for lodestar", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -66,19 +66,18 @@ "@libp2p/crypto": "^3.0.4", "@libp2p/peer-id": "^4.0.4", "@libp2p/peer-id-factory": "^4.0.3", - "@lodestar/api": "^1.15.0", - "@lodestar/beacon-node": "^1.15.0", - "@lodestar/config": "^1.15.0", - "@lodestar/db": "^1.15.0", - "@lodestar/light-client": "^1.15.0", - "@lodestar/logger": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/state-transition": "^1.15.0", - "@lodestar/types": "^1.15.0", - "@lodestar/utils": "^1.15.0", - "@lodestar/validator": "^1.15.0", + "@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", "@multiformats/multiaddr": "^12.1.3", - "@types/lockfile": "^1.0.2", "bip39": "^3.1.0", "deepmerge": "^4.3.1", "ethers": "^6.7.0", @@ -87,9 +86,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", @@ -97,12 +96,13 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.15.0", + "@lodestar/test-utils": "^1.15.1", "@types/debug": "^4.1.7", "@types/expand-tilde": "^2.0.0", "@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/cmds/validator/options.ts b/packages/cli/src/cmds/validator/options.ts index ecc8ad32ca87..6d8d40f2dfdb 100644 --- a/packages/cli/src/cmds/validator/options.ts +++ b/packages/cli/src/cmds/validator/options.ts @@ -267,7 +267,7 @@ export const validatorOptions: CliCommandOptions = { }, blindedLocal: { - type: "string", + type: "boolean", description: "Request fetching local block in blinded format for produceBlockV3", defaultDescription: `${defaultOptions.blindedLocal}`, }, 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/config/package.json b/packages/config/package.json index a36da8c6240a..0f47077b7ea5 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/config", - "version": "1.15.0", + "version": "1.15.1", "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.0", - "@lodestar/types": "^1.15.0" + "@lodestar/params": "^1.15.1", + "@lodestar/types": "^1.15.1" } } diff --git a/packages/db/package.json b/packages/db/package.json index f11e5b48995c..7de4789864a3 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/db", - "version": "1.15.0", + "version": "1.15.1", "description": "DB modules of Lodestar", "author": "ChainSafe Systems", "homepage": "https://github.com/ChainSafe/lodestar#readme", @@ -38,13 +38,13 @@ }, "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.15.0", - "@lodestar/utils": "^1.15.0", + "@lodestar/config": "^1.15.1", + "@lodestar/utils": "^1.15.1", "@types/levelup": "^4.3.3", "it-all": "^3.0.4", "level": "^8.0.0" }, "devDependencies": { - "@lodestar/logger": "^1.15.0" + "@lodestar/logger": "^1.15.1" } } 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 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 ); diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 456600cbd0bc..73fad280129c 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -70,12 +70,12 @@ "@chainsafe/bls": "7.1.1", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/api": "^1.15.0", - "@lodestar/config": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/state-transition": "^1.15.0", - "@lodestar/types": "^1.15.0", - "@lodestar/utils": "^1.15.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", "mitt": "^3.0.0", "strict-event-emitter-types": "^2.0.0" }, diff --git a/packages/logger/package.json b/packages/logger/package.json index f1a5ddad1a06..ea649cffb958 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -66,14 +66,14 @@ }, "types": "lib/index.d.ts", "dependencies": { - "@lodestar/utils": "^1.15.0", + "@lodestar/utils": "^1.15.1", "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.0", + "@lodestar/test-utils": "^1.15.1", "@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 d41dae06816e..d94090b3f6ea 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/params", - "version": "1.15.0", + "version": "1.15.1", "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 600f4b4d4d75..7ca0090b58aa 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -72,13 +72,13 @@ "@ethereumjs/tx": "^4.1.2", "@ethereumjs/util": "^8.0.6", "@ethereumjs/vm": "^6.4.2", - "@lodestar/api": "^1.15.0", - "@lodestar/config": "^1.15.0", - "@lodestar/light-client": "^1.15.0", - "@lodestar/logger": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/types": "^1.15.0", - "@lodestar/utils": "^1.15.0", + "@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", "ethereum-cryptography": "^1.2.0", "find-up": "^6.3.0", "http-proxy": "^1.18.1", @@ -87,7 +87,7 @@ "yargs": "^17.7.1" }, "devDependencies": { - "@lodestar/test-utils": "^1.15.0", + "@lodestar/test-utils": "^1.15.1", "@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 3856177449d3..66700cf317d0 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -56,9 +56,9 @@ "dependencies": { "@chainsafe/fast-crc32c": "^4.1.1", "@libp2p/interface": "^1.1.1", - "@lodestar/config": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/utils": "^1.15.0", + "@lodestar/config": "^1.15.1", + "@lodestar/params": "^1.15.1", + "@lodestar/utils": "^1.15.1", "it-all": "^3.0.4", "it-pipe": "^3.0.1", "snappy": "^7.2.2", @@ -67,8 +67,8 @@ "uint8arraylist": "^2.4.7" }, "devDependencies": { - "@lodestar/logger": "^1.15.0", - "@lodestar/types": "^1.15.0", + "@lodestar/logger": "^1.15.1", + "@lodestar/types": "^1.15.1", "libp2p": "1.1.1" }, "peerDependencies": { diff --git a/packages/spec-test-util/package.json b/packages/spec-test-util/package.json index f8d953e408fd..e94fc35c7111 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.0", + "version": "1.15.1", "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.0", + "@lodestar/utils": "^1.15.1", "async-retry": "^1.3.3", "axios": "^1.3.4", "rimraf": "^4.4.1", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index 8a1aea19f140..ed76e116fe82 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -63,10 +63,10 @@ "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/config": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/types": "^1.15.0", - "@lodestar/utils": "^1.15.0", + "@lodestar/config": "^1.15.1", + "@lodestar/params": "^1.15.1", + "@lodestar/types": "^1.15.1", + "@lodestar/utils": "^1.15.1", "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 038cd743bdd7..1d976c5e609e 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.0", + "version": "1.15.1", "description": "Test utilities reused across other packages", "author": "ChainSafe Systems", "license": "Apache-2.0", @@ -60,8 +60,8 @@ "dependencies": { "@chainsafe/bls": "7.1.1", "@chainsafe/bls-keystore": "^3.0.0", - "@lodestar/params": "^1.15.0", - "@lodestar/utils": "^1.15.0", + "@lodestar/params": "^1.15.1", + "@lodestar/utils": "^1.15.1", "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 1e9b811becfa..3888eeae2cc2 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.0", + "version": "1.15.1", "type": "module", "exports": { ".": { @@ -73,7 +73,7 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/ssz": "^0.14.0", - "@lodestar/params": "^1.15.0" + "@lodestar/params": "^1.15.1" }, "keywords": [ "ethereum", diff --git a/packages/utils/package.json b/packages/utils/package.json index fa1dd4fdd829..1a5497c94581 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.0", + "version": "1.15.1", "type": "module", "exports": "./lib/index.js", "files": [ diff --git a/packages/validator/package.json b/packages/validator/package.json index 020792107c3b..bbc64ede4de0 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -1,6 +1,6 @@ { "name": "@lodestar/validator", - "version": "1.15.0", + "version": "1.15.1", "description": "A Typescript implementation of the validator client", "author": "ChainSafe Systems", "license": "LGPL-3.0", @@ -49,18 +49,18 @@ "dependencies": { "@chainsafe/bls": "7.1.1", "@chainsafe/ssz": "^0.14.0", - "@lodestar/api": "^1.15.0", - "@lodestar/config": "^1.15.0", - "@lodestar/db": "^1.15.0", - "@lodestar/params": "^1.15.0", - "@lodestar/state-transition": "^1.15.0", - "@lodestar/types": "^1.15.0", - "@lodestar/utils": "^1.15.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", "bigint-buffer": "^1.1.5", "strict-event-emitter-types": "^2.0.0" }, "devDependencies": { - "@lodestar/test-utils": "^1.15.0", + "@lodestar/test-utils": "^1.15.1", "bigint-buffer": "^1.1.5", "rimraf": "^4.4.1" } diff --git a/yarn.lock b/yarn.lock index 27754c484466..ce67d0db390d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2955,11 +2955,6 @@ "@types/level-errors" "*" "@types/node" "*" -"@types/lockfile@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@types/lockfile/-/lockfile-1.0.2.tgz#3f77e84171a2b7e3198bd5717c7547a54393baf8" - integrity sha512-jD5VbvhfMhaYN4M3qPJuhMVUg3Dfc4tvPvLEAXn6GXbs/ajDFtCQahX37GIE65ipTI3I+hEvNaXS3MYAn9Ce3Q== - "@types/lodash@^4.14.192": version "4.14.192" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.192.tgz#5790406361a2852d332d41635d927f1600811285" @@ -3043,6 +3038,13 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== +"@types/proper-lockfile@^4.1.4": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@types/proper-lockfile/-/proper-lockfile-4.1.4.tgz#cd9fab92bdb04730c1ada542c356f03620f84008" + integrity sha512-uo2ABllncSqg9F1D4nugVl9v93RmjxF6LJzQLMLDdPaXCUIDPeOJ21Gbqi43xNKzBi/WQ0Q0dICqufzQbMjipQ== + dependencies: + "@types/retry" "*" + "@types/qs@^6.9.7": version "6.9.7" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" @@ -9045,13 +9047,6 @@ locate-path@^7.1.0: dependencies: p-locate "^6.0.0" -lockfile@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz" - integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA== - dependencies: - signal-exit "^3.0.2" - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" From d1caa1f61730551908ab2b969b972c7978909e87 Mon Sep 17 00:00:00 2001 From: Cayman Date: Wed, 7 Feb 2024 14:13:45 -0500 Subject: [PATCH 36/45] 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 37/45] 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 38/45] 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 39/45] 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 40/45] 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 41/45] 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 42/45] 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 43/45] 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 44/45] 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 9014c8c7e78b9ad9c811aa0bee2e9b528b5b54c6 Mon Sep 17 00:00:00 2001 From: harkamal Date: Wed, 24 Jan 2024 17:38:11 +0530 Subject: [PATCH 45/45] feat: placeholder PR for electra add types stub and epoch config fix types --- .../test/spec/presets/fork.test.ts | 2 + .../test/spec/presets/transition.test.ts | 8 + .../upgradeLightClientHeader.test.ts | 33 +++- .../test/unit/network/fork.test.ts | 13 +- packages/beacon-node/test/utils/config.ts | 8 + .../config/src/chainConfig/configs/mainnet.ts | 4 + .../config/src/chainConfig/configs/minimal.ts | 4 + packages/config/src/chainConfig/types.ts | 6 + packages/config/src/forkConfig/index.ts | 10 +- packages/light-client/src/spec/utils.ts | 4 + packages/params/src/forkName.ts | 2 + .../test/unit/upgradeState.test.ts | 8 + packages/types/src/allForks/sszTypes.ts | 38 +++++ packages/types/src/electra/index.ts | 3 + packages/types/src/electra/sszTypes.ts | 148 ++++++++++++++++++ packages/types/src/electra/types.ts | 29 ++++ packages/types/src/sszTypes.ts | 1 + packages/types/src/types.ts | 1 + packages/validator/src/util/params.ts | 5 + 19 files changed, 323 insertions(+), 4 deletions(-) create mode 100644 packages/types/src/electra/index.ts create mode 100644 packages/types/src/electra/sszTypes.ts create mode 100644 packages/types/src/electra/types.ts diff --git a/packages/beacon-node/test/spec/presets/fork.test.ts b/packages/beacon-node/test/spec/presets/fork.test.ts index 228ab6a38935..c880d24bbbe3 100644 --- a/packages/beacon-node/test/spec/presets/fork.test.ts +++ b/packages/beacon-node/test/spec/presets/fork.test.ts @@ -35,6 +35,8 @@ const fork: TestRunnerFn = (forkNext) => { return slotFns.upgradeStateToCapella(preState as CachedBeaconStateBellatrix); case ForkName.deneb: return slotFns.upgradeStateToDeneb(preState as CachedBeaconStateCapella); + case ForkName.electra: + throw Error("not Implemented"); } }, options: { diff --git a/packages/beacon-node/test/spec/presets/transition.test.ts b/packages/beacon-node/test/spec/presets/transition.test.ts index 77919d76c3b1..1f98dbb41f58 100644 --- a/packages/beacon-node/test/spec/presets/transition.test.ts +++ b/packages/beacon-node/test/spec/presets/transition.test.ts @@ -102,6 +102,14 @@ function getTransitionConfig(fork: ForkName, forkEpoch: number): Partial${toFork}`, function () { + lcHeaderByFork[fromFork].beacon.slot = testSlots[fromFork]; + lcHeaderByFork[toFork].beacon.slot = testSlots[fromFork]; + + expect(() => { + upgradeLightClientHeader(config, toFork, lcHeaderByFork[fromFork]); + }).toThrow("Not Implemented"); + }); + } + + // Since electra is not implemented for loop is till deneb (Object.values(ForkName).length-1) + // Once electra is implemnted run for loop till Object.values(ForkName).length + + // for (let i = ForkSeq.altair; i < Object.values(ForkName).length; i++) { + + for (let i = ForkSeq.altair; i < Object.values(ForkName).length - 1; i++) { for (let j = i; j > 0; j--) { const fromFork = ForkName[ForkSeq[i] as ForkName]; const toFork = ForkName[ForkSeq[j] as ForkName]; diff --git a/packages/beacon-node/test/unit/network/fork.test.ts b/packages/beacon-node/test/unit/network/fork.test.ts index be748d2e8185..bbe1c0870d30 100644 --- a/packages/beacon-node/test/unit/network/fork.test.ts +++ b/packages/beacon-node/test/unit/network/fork.test.ts @@ -9,12 +9,14 @@ function getForkConfig({ bellatrix, capella, deneb, + electra, }: { phase0: number; altair: number; bellatrix: number; capella: number; deneb: number; + electra: number; }): BeaconConfig { const forks: Record = { phase0: { @@ -57,6 +59,14 @@ function getForkConfig({ prevVersion: Buffer.from([0, 0, 0, 3]), prevForkName: ForkName.capella, }, + electra: { + name: ForkName.electra, + seq: ForkSeq.electra, + epoch: electra, + version: Buffer.from([0, 0, 0, 5]), + prevVersion: Buffer.from([0, 0, 0, 4]), + prevForkName: ForkName.deneb, + }, }; const forksAscendingEpochOrder = Object.values(forks); const forksDescendingEpochOrder = Object.values(forks).reverse(); @@ -133,9 +143,10 @@ const testScenarios = [ for (const testScenario of testScenarios) { const {phase0, altair, bellatrix, capella, testCases} = testScenario; const deneb = Infinity; + const electra = Infinity; describe(`network / fork: phase0: ${phase0}, altair: ${altair}, bellatrix: ${bellatrix} capella: ${capella}`, () => { - const forkConfig = getForkConfig({phase0, altair, bellatrix, capella, deneb}); + const forkConfig = getForkConfig({phase0, altair, bellatrix, capella, deneb, electra}); const forks = forkConfig.forks; for (const testCase of testCases) { const {epoch, currentFork, nextFork, activeForks} = testCase; diff --git a/packages/beacon-node/test/utils/config.ts b/packages/beacon-node/test/utils/config.ts index 54c058d30722..2aad1c14c03e 100644 --- a/packages/beacon-node/test/utils/config.ts +++ b/packages/beacon-node/test/utils/config.ts @@ -31,5 +31,13 @@ export function getConfig(fork: ForkName, forkEpoch = 0): ChainForkConfig { CAPELLA_FORK_EPOCH: 0, DENEB_FORK_EPOCH: forkEpoch, }); + case ForkName.electra: + return createChainForkConfig({ + ALTAIR_FORK_EPOCH: 0, + BELLATRIX_FORK_EPOCH: 0, + CAPELLA_FORK_EPOCH: 0, + DENEB_FORK_EPOCH: 0, + ELECTRA_FORK_EPOCH: forkEpoch, + }); } } diff --git a/packages/config/src/chainConfig/configs/mainnet.ts b/packages/config/src/chainConfig/configs/mainnet.ts index 9d060330d201..8f5051394551 100644 --- a/packages/config/src/chainConfig/configs/mainnet.ts +++ b/packages/config/src/chainConfig/configs/mainnet.ts @@ -49,6 +49,10 @@ export const chainConfig: ChainConfig = { DENEB_FORK_VERSION: b("0x04000000"), DENEB_FORK_EPOCH: 269568, // March 13, 2024, 01:55:35pm UTC + // Electra + ELECTRA_FORK_VERSION: b("0x05000000"), + ELECTRA_FORK_EPOCH: Infinity, + // Time parameters // --------------------------------------------------------------- // 12 seconds diff --git a/packages/config/src/chainConfig/configs/minimal.ts b/packages/config/src/chainConfig/configs/minimal.ts index 6c0a13d8abb2..a8a9834c1592 100644 --- a/packages/config/src/chainConfig/configs/minimal.ts +++ b/packages/config/src/chainConfig/configs/minimal.ts @@ -46,6 +46,10 @@ export const chainConfig: ChainConfig = { DENEB_FORK_VERSION: b("0x04000001"), DENEB_FORK_EPOCH: Infinity, + // Electra + ELECTRA_FORK_VERSION: b("0x05000001"), + ELECTRA_FORK_EPOCH: Infinity, + // Time parameters // --------------------------------------------------------------- // [customized] Faster for testing purposes diff --git a/packages/config/src/chainConfig/types.ts b/packages/config/src/chainConfig/types.ts index 20e8119332f3..21d29257d26a 100644 --- a/packages/config/src/chainConfig/types.ts +++ b/packages/config/src/chainConfig/types.ts @@ -40,6 +40,9 @@ export type ChainConfig = { // DENEB DENEB_FORK_VERSION: Uint8Array; DENEB_FORK_EPOCH: number; + // ELECTRA + ELECTRA_FORK_VERSION: Uint8Array; + ELECTRA_FORK_EPOCH: number; // Time parameters SECONDS_PER_SLOT: number; @@ -96,6 +99,9 @@ export const chainConfigTypes: SpecTypes = { // DENEB DENEB_FORK_VERSION: "bytes", DENEB_FORK_EPOCH: "number", + // ELECTRA + ELECTRA_FORK_VERSION: "bytes", + ELECTRA_FORK_EPOCH: "number", // Time parameters SECONDS_PER_SLOT: "number", diff --git a/packages/config/src/forkConfig/index.ts b/packages/config/src/forkConfig/index.ts index d630f1ddfc88..efb27ca1505f 100644 --- a/packages/config/src/forkConfig/index.ts +++ b/packages/config/src/forkConfig/index.ts @@ -55,10 +55,18 @@ export function createForkConfig(config: ChainConfig): ForkConfig { prevVersion: config.CAPELLA_FORK_VERSION, prevForkName: ForkName.capella, }; + const electra: ForkInfo = { + name: ForkName.electra, + seq: ForkSeq.electra, + epoch: config.ELECTRA_FORK_EPOCH, + version: config.ELECTRA_FORK_VERSION, + prevVersion: config.DENEB_FORK_VERSION, + prevForkName: ForkName.deneb, + }; /** Forks in order order of occurence, `phase0` first */ // Note: Downstream code relies on proper ordering. - const forks = {phase0, altair, bellatrix, capella, deneb}; + const forks = {phase0, altair, bellatrix, capella, deneb, electra}; // Prevents allocating an array on every getForkInfo() call const forksAscendingEpochOrder = Object.values(forks); diff --git a/packages/light-client/src/spec/utils.ts b/packages/light-client/src/spec/utils.ts index 0ff1775f55c1..333ee006703a 100644 --- a/packages/light-client/src/spec/utils.ts +++ b/packages/light-client/src/spec/utils.ts @@ -105,6 +105,10 @@ export function upgradeLightClientHeader( // Break if no further upgradation is required else fall through if (ForkSeq[targetFork] <= ForkSeq.deneb) break; + + // eslint-disable-next-line no-fallthrough + case ForkName.electra: + throw Error("Not Implemented"); } return upgradedHeader; } diff --git a/packages/params/src/forkName.ts b/packages/params/src/forkName.ts index 142684c313f4..bbb72a7972fa 100644 --- a/packages/params/src/forkName.ts +++ b/packages/params/src/forkName.ts @@ -7,6 +7,7 @@ export enum ForkName { bellatrix = "bellatrix", capella = "capella", deneb = "deneb", + electra = "electra", } /** @@ -18,6 +19,7 @@ export enum ForkSeq { bellatrix = 2, capella = 3, deneb = 4, + electra = 5, } export type ForkPreLightClient = ForkName.phase0; diff --git a/packages/state-transition/test/unit/upgradeState.test.ts b/packages/state-transition/test/unit/upgradeState.test.ts index 2ea8eef182ac..75ba415c1bea 100644 --- a/packages/state-transition/test/unit/upgradeState.test.ts +++ b/packages/state-transition/test/unit/upgradeState.test.ts @@ -55,5 +55,13 @@ function getConfig(fork: ForkName, forkEpoch = 0): ChainForkConfig { CAPELLA_FORK_EPOCH: 0, DENEB_FORK_EPOCH: forkEpoch, }); + case ForkName.electra: + return createChainForkConfig({ + ALTAIR_FORK_EPOCH: 0, + BELLATRIX_FORK_EPOCH: 0, + CAPELLA_FORK_EPOCH: 0, + DENEB_FORK_EPOCH: 0, + ELECTRA_FORK_EPOCH: forkEpoch, + }); } } diff --git a/packages/types/src/allForks/sszTypes.ts b/packages/types/src/allForks/sszTypes.ts index 7174bc52e89c..6030215ac8ca 100644 --- a/packages/types/src/allForks/sszTypes.ts +++ b/packages/types/src/allForks/sszTypes.ts @@ -3,6 +3,7 @@ import {ssz as altair} from "../altair/index.js"; import {ssz as bellatrix} from "../bellatrix/index.js"; import {ssz as capella} from "../capella/index.js"; import {ssz as deneb} from "../deneb/index.js"; +import {ssz as electra} from "../electra/index.js"; /** * Index the ssz types that differ by fork @@ -44,6 +45,13 @@ export const allForks = { BeaconState: deneb.BeaconState, Metadata: altair.Metadata, }, + electra: { + BeaconBlockBody: electra.BeaconBlockBody, + BeaconBlock: electra.BeaconBlock, + SignedBeaconBlock: electra.SignedBeaconBlock, + BeaconState: electra.BeaconState, + Metadata: altair.Metadata, + }, }; /** @@ -85,6 +93,17 @@ export const allForksExecution = { SignedBuilderBid: deneb.SignedBuilderBid, SSEPayloadAttributes: deneb.SSEPayloadAttributes, }, + electra: { + BeaconBlockBody: electra.BeaconBlockBody, + BeaconBlock: electra.BeaconBlock, + SignedBeaconBlock: electra.SignedBeaconBlock, + BeaconState: electra.BeaconState, + ExecutionPayload: electra.ExecutionPayload, + ExecutionPayloadHeader: electra.ExecutionPayloadHeader, + BuilderBid: electra.BuilderBid, + SignedBuilderBid: electra.SignedBuilderBid, + SSEPayloadAttributes: electra.SSEPayloadAttributes, + }, }; /** @@ -107,6 +126,11 @@ export const allForksBlinded = { BeaconBlock: deneb.BlindedBeaconBlock, SignedBeaconBlock: deneb.SignedBlindedBeaconBlock, }, + electra: { + BeaconBlockBody: electra.BlindedBeaconBlockBody, + BeaconBlock: electra.BlindedBeaconBlock, + SignedBeaconBlock: electra.SignedBlindedBeaconBlock, + }, }; export const allForksLightClient = { @@ -150,6 +174,16 @@ export const allForksLightClient = { LightClientOptimisticUpdate: deneb.LightClientOptimisticUpdate, LightClientStore: deneb.LightClientStore, }, + electra: { + BeaconBlock: electra.BeaconBlock, + BeaconBlockBody: electra.BeaconBlockBody, + LightClientHeader: electra.LightClientHeader, + LightClientBootstrap: electra.LightClientBootstrap, + LightClientUpdate: electra.LightClientUpdate, + LightClientFinalityUpdate: electra.LightClientFinalityUpdate, + LightClientOptimisticUpdate: electra.LightClientOptimisticUpdate, + LightClientStore: electra.LightClientStore, + }, }; export const allForksBlobs = { @@ -157,4 +191,8 @@ export const allForksBlobs = { BlobSidecar: deneb.BlobSidecar, ExecutionPayloadAndBlobsBundle: deneb.ExecutionPayloadAndBlobsBundle, }, + electra: { + BlobSidecar: electra.BlobSidecar, + ExecutionPayloadAndBlobsBundle: electra.ExecutionPayloadAndBlobsBundle, + }, }; diff --git a/packages/types/src/electra/index.ts b/packages/types/src/electra/index.ts new file mode 100644 index 000000000000..7856cd729620 --- /dev/null +++ b/packages/types/src/electra/index.ts @@ -0,0 +1,3 @@ +export * from "./types.js"; +export * as ts from "./types.js"; +export * as ssz from "./sszTypes.js"; diff --git a/packages/types/src/electra/sszTypes.ts b/packages/types/src/electra/sszTypes.ts new file mode 100644 index 000000000000..30690a499845 --- /dev/null +++ b/packages/types/src/electra/sszTypes.ts @@ -0,0 +1,148 @@ +import {ContainerType} from "@chainsafe/ssz"; +import {ssz as primitiveSsz} from "../primitive/index.js"; +import {ssz as denebSsz} from "../deneb/index.js"; + +const {BLSSignature} = primitiveSsz; + +export const ExecutionPayload = new ContainerType( + { + ...denebSsz.ExecutionPayload.fields, + }, + {typeName: "ExecutionPayload", jsonCase: "eth2"} +); + +export const ExecutionPayloadHeader = new ContainerType( + { + ...denebSsz.ExecutionPayloadHeader.fields, + }, + {typeName: "ExecutionPayloadHeader", jsonCase: "eth2"} +); + +export const BeaconBlockBody = new ContainerType( + { + ...denebSsz.BeaconBlockBody.fields, + }, + {typeName: "BeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const BeaconBlock = new ContainerType( + { + ...denebSsz.BeaconBlock.fields, + }, + {typeName: "BeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const SignedBeaconBlock = new ContainerType( + { + message: BeaconBlock, + signature: BLSSignature, + }, + {typeName: "SignedBeaconBlock", jsonCase: "eth2"} +); + +export const BlobSidecar = new ContainerType( + { + ...denebSsz.BlobSidecar.fields, + }, + {typeName: "BlobSidecar", jsonCase: "eth2"} +); + +export const BlindedBeaconBlockBody = new ContainerType( + { + ...denebSsz.BlindedBeaconBlockBody.fields, + }, + {typeName: "BlindedBeaconBlockBody", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const BlindedBeaconBlock = new ContainerType( + { + ...denebSsz.BlindedBeaconBlock.fields, + }, + {typeName: "BlindedBeaconBlock", jsonCase: "eth2", cachePermanentRootStruct: true} +); + +export const SignedBlindedBeaconBlock = new ContainerType( + { + message: BlindedBeaconBlock, + signature: BLSSignature, + }, + {typeName: "SignedBlindedBeaconBlock", jsonCase: "eth2"} +); + +export const BuilderBid = new ContainerType( + { + ...denebSsz.BuilderBid.fields, + }, + {typeName: "BuilderBid", jsonCase: "eth2"} +); + +export const SignedBuilderBid = new ContainerType( + { + message: BuilderBid, + signature: BLSSignature, + }, + {typeName: "SignedBuilderBid", jsonCase: "eth2"} +); + +export const ExecutionPayloadAndBlobsBundle = new ContainerType( + { + ...denebSsz.ExecutionPayloadAndBlobsBundle.fields, + }, + {typeName: "ExecutionPayloadAndBlobsBundle", jsonCase: "eth2"} +); + +export const BeaconState = new ContainerType( + { + ...denebSsz.BeaconState.fields, + }, + {typeName: "BeaconState", jsonCase: "eth2"} +); + +export const LightClientHeader = new ContainerType( + { + ...denebSsz.LightClientHeader.fields, + }, + {typeName: "LightClientHeader", jsonCase: "eth2"} +); + +export const LightClientBootstrap = new ContainerType( + { + ...denebSsz.LightClientBootstrap.fields, + }, + {typeName: "LightClientBootstrap", jsonCase: "eth2"} +); + +export const LightClientUpdate = new ContainerType( + { + ...denebSsz.LightClientUpdate.fields, + }, + {typeName: "LightClientUpdate", jsonCase: "eth2"} +); + +export const LightClientFinalityUpdate = new ContainerType( + { + ...denebSsz.LightClientFinalityUpdate.fields, + }, + {typeName: "LightClientFinalityUpdate", jsonCase: "eth2"} +); + +export const LightClientOptimisticUpdate = new ContainerType( + { + ...denebSsz.LightClientOptimisticUpdate.fields, + }, + {typeName: "LightClientOptimisticUpdate", jsonCase: "eth2"} +); + +export const LightClientStore = new ContainerType( + { + ...denebSsz.LightClientStore.fields, + }, + {typeName: "LightClientStore", jsonCase: "eth2"} +); + +export const SSEPayloadAttributes = new ContainerType( + { + ...denebSsz.SSEPayloadAttributes.fields, + }, + {typeName: "SSEPayloadAttributes", jsonCase: "eth2"} +); diff --git a/packages/types/src/electra/types.ts b/packages/types/src/electra/types.ts new file mode 100644 index 000000000000..198259eed1dd --- /dev/null +++ b/packages/types/src/electra/types.ts @@ -0,0 +1,29 @@ +import {ValueOf} from "@chainsafe/ssz"; +import * as ssz from "./sszTypes.js"; + +export type BlobSidecar = ValueOf; +export type ExecutionPayloadAndBlobsBundle = ValueOf; + +export type ExecutionPayload = ValueOf; +export type ExecutionPayloadHeader = ValueOf; + +export type BeaconBlockBody = ValueOf; +export type BeaconBlock = ValueOf; +export type SignedBeaconBlock = ValueOf; + +export type BeaconState = ValueOf; + +export type BlindedBeaconBlockBody = ValueOf; +export type BlindedBeaconBlock = ValueOf; +export type SignedBlindedBeaconBlock = ValueOf; + +export type BuilderBid = ValueOf; +export type SignedBuilderBid = ValueOf; +export type SSEPayloadAttributes = ValueOf; + +export type LightClientHeader = ValueOf; +export type LightClientBootstrap = ValueOf; +export type LightClientUpdate = ValueOf; +export type LightClientFinalityUpdate = ValueOf; +export type LightClientOptimisticUpdate = ValueOf; +export type LightClientStore = ValueOf; diff --git a/packages/types/src/sszTypes.ts b/packages/types/src/sszTypes.ts index 2a7df948a447..ff3e77ab6947 100644 --- a/packages/types/src/sszTypes.ts +++ b/packages/types/src/sszTypes.ts @@ -4,6 +4,7 @@ export {ssz as altair} from "./altair/index.js"; export {ssz as bellatrix} from "./bellatrix/index.js"; export {ssz as capella} from "./capella/index.js"; export {ssz as deneb} from "./deneb/index.js"; +export {ssz as electra} from "./electra/index.js"; import {ssz as allForksSsz} from "./allForks/index.js"; export const allForks = allForksSsz.allForks; diff --git a/packages/types/src/types.ts b/packages/types/src/types.ts index e2e416fa3667..fbd7d5621da0 100644 --- a/packages/types/src/types.ts +++ b/packages/types/src/types.ts @@ -6,6 +6,7 @@ export {ts as altair} from "./altair/index.js"; export {ts as bellatrix} from "./bellatrix/index.js"; export {ts as capella} from "./capella/index.js"; export {ts as deneb} from "./deneb/index.js"; +export {ts as electra} from "./electra/index.js"; export {ts as allForks} from "./allForks/index.js"; diff --git a/packages/validator/src/util/params.ts b/packages/validator/src/util/params.ts index 006ae3fadbbb..f316ea1b270d 100644 --- a/packages/validator/src/util/params.ts +++ b/packages/validator/src/util/params.ts @@ -73,6 +73,7 @@ function getSpecCriticalParams(localConfig: ChainConfig): Record