From 514b6057ead3232e76687acb4bb0a5e7f0275b57 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 9 Jul 2024 22:31:35 +0100 Subject: [PATCH 01/44] docs: fix search, redirects and broken links (#6940) --- CONTRIBUTING.md | 2 +- docs/package.json | 12 +- docs/sidebars.ts | 5 + docs/yarn.lock | 1861 +++++-------------------------------- packages/prover/README.md | 2 +- 5 files changed, 241 insertions(+), 1641 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 903f9ee32da7..9592f3bb0237 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,7 +50,7 @@ Contributing to tests: ## Devcontainer -A [devcontainer](https://containers.dev/) [configuration](.devcontainer/devcontainer.json) is provided to help speed up linux based development environment setup. It will be used by [GitHub Codespaces](https://github.com/features/codespaces) or directly inside VS Code via your local through this [extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). +A [devcontainer](https://containers.dev/) [configuration](https://github.com/ChainSafe/lodestar/blob/unstable/.devcontainer/devcontainer.json) is provided to help speed up linux based development environment setup. It will be used by [GitHub Codespaces](https://github.com/features/codespaces) or directly inside VS Code via your local through this [extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). ### Common Issues diff --git a/docs/package.json b/docs/package.json index 6159ba123215..bf1495c9b657 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,10 +14,10 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^3.4.0", - "@docusaurus/plugin-client-redirects": "^3.4.0", - "@docusaurus/preset-classic": "^3.4.0", - "@docusaurus/theme-mermaid": "^3.4.0", + "@docusaurus/core": "3.2.0", + "@docusaurus/plugin-client-redirects": "3.2.0", + "@docusaurus/preset-classic": "3.2.0", + "@docusaurus/theme-mermaid": "3.2.0", "@easyops-cn/docusaurus-search-local": "^0.40.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", @@ -26,8 +26,8 @@ "react-dom": "^18.0.0" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.4.0", - "@docusaurus/types": "^3.4.0" + "@docusaurus/module-type-aliases": "3.2.0", + "@docusaurus/types": "3.2.0" }, "browserslist": { "production": [ diff --git a/docs/sidebars.ts b/docs/sidebars.ts index a82421a961cb..16bd9586d1a1 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -69,6 +69,11 @@ const sidebars: SidebarsConfig = { label: "Contributing", collapsed: false, items: [ + { + type: "doc", + label: "Getting Started", + id: "contribution/getting-started", + }, { type: "category", label: "Advanced Topics", diff --git a/docs/yarn.lock b/docs/yarn.lock index a2c90a3ace6c..41966c013183 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -154,24 +154,11 @@ "@babel/highlight" "^7.23.4" chalk "^2.4.2" -"@babel/code-frame@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== -"@babel/compat-data@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" - integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw== - "@babel/core@^7.19.6", "@babel/core@^7.23.3": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b" @@ -193,27 +180,6 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/core@^7.21.3": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4" - integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.7" - "@babel/generator" "^7.24.7" - "@babel/helper-compilation-targets" "^7.24.7" - "@babel/helper-module-transforms" "^7.24.7" - "@babel/helpers" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/template" "^7.24.7" - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - "@babel/generator@^7.23.3", "@babel/generator@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" @@ -224,16 +190,6 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/generator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d" - integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA== - dependencies: - "@babel/types" "^7.24.7" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" - "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -241,13 +197,6 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-annotate-as-pure@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" - integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== - dependencies: - "@babel/types" "^7.24.7" - "@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956" @@ -255,14 +204,6 @@ dependencies: "@babel/types" "^7.22.15" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" - integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" @@ -274,17 +215,6 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-compilation-targets@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9" - integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg== - dependencies: - "@babel/compat-data" "^7.24.7" - "@babel/helper-validator-option" "^7.24.7" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - "@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.6": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.0.tgz#fc7554141bdbfa2d17f7b4b80153b9b090e5d158" @@ -300,21 +230,6 @@ "@babel/helper-split-export-declaration" "^7.22.6" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz#2eaed36b3a1c11c53bdf80d53838b293c52f5b3b" - integrity sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.7" - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-function-name" "^7.24.7" - "@babel/helper-member-expression-to-functions" "^7.24.7" - "@babel/helper-optimise-call-expression" "^7.24.7" - "@babel/helper-replace-supers" "^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" - semver "^6.3.1" - "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1" @@ -324,15 +239,6 @@ regexpu-core "^5.3.1" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz#be4f435a80dc2b053c76eeb4b7d16dd22cfc89da" - integrity sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.7" - regexpu-core "^5.3.1" - semver "^6.3.1" - "@babel/helper-define-polyfill-provider@^0.5.0": version "0.5.0" resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz#465805b7361f461e86c680f1de21eaf88c25901b" @@ -344,29 +250,11 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" - integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== - dependencies: - "@babel/helper-compilation-targets" "^7.22.6" - "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - "@babel/helper-environment-visitor@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== -"@babel/helper-environment-visitor@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" - integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== - dependencies: - "@babel/types" "^7.24.7" - "@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" @@ -375,14 +263,6 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.23.0" -"@babel/helper-function-name@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" - integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== - dependencies: - "@babel/template" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" @@ -390,13 +270,6 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-hoist-variables@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" - integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== - dependencies: - "@babel/types" "^7.24.7" - "@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" @@ -404,14 +277,6 @@ dependencies: "@babel/types" "^7.23.0" -"@babel/helper-member-expression-to-functions@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz#67613d068615a70e4ed5101099affc7a41c5225f" - integrity sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/helper-module-imports@^7.22.15": version "7.22.15" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" @@ -419,14 +284,6 @@ dependencies: "@babel/types" "^7.22.15" -"@babel/helper-module-imports@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" - integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/helper-module-transforms@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" @@ -438,17 +295,6 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" -"@babel/helper-module-transforms@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8" - integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ== - dependencies: - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-module-imports" "^7.24.7" - "@babel/helper-simple-access" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" - "@babel/helper-validator-identifier" "^7.24.7" - "@babel/helper-optimise-call-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" @@ -456,23 +302,11 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-optimise-call-expression@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" - integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== - dependencies: - "@babel/types" "^7.24.7" - "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== -"@babel/helper-plugin-utils@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0" - integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== - "@babel/helper-remap-async-to-generator@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" @@ -482,15 +316,6 @@ "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-wrap-function" "^7.22.20" -"@babel/helper-remap-async-to-generator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz#b3f0f203628522713849d49403f1a414468be4c7" - integrity sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.7" - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-wrap-function" "^7.24.7" - "@babel/helper-replace-supers@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" @@ -500,15 +325,6 @@ "@babel/helper-member-expression-to-functions" "^7.22.15" "@babel/helper-optimise-call-expression" "^7.22.5" -"@babel/helper-replace-supers@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz#f933b7eed81a1c0265740edc91491ce51250f765" - integrity sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg== - dependencies: - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-member-expression-to-functions" "^7.24.7" - "@babel/helper-optimise-call-expression" "^7.24.7" - "@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" @@ -516,14 +332,6 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-simple-access@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" - integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" @@ -531,14 +339,6 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" - integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" @@ -546,43 +346,21 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-split-export-declaration@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" - integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== - dependencies: - "@babel/types" "^7.24.7" - "@babel/helper-string-parser@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== -"@babel/helper-string-parser@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2" - integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg== - "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - "@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== -"@babel/helper-validator-option@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" - integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw== - "@babel/helper-wrap-function@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" @@ -592,16 +370,6 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.22.19" -"@babel/helper-wrap-function@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz#52d893af7e42edca7c6d2c6764549826336aae1f" - integrity sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw== - dependencies: - "@babel/helper-function-name" "^7.24.7" - "@babel/template" "^7.24.7" - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/helpers@^7.24.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b" @@ -611,14 +379,6 @@ "@babel/traverse" "^7.24.0" "@babel/types" "^7.24.0" -"@babel/helpers@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416" - integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg== - dependencies: - "@babel/template" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/highlight@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" @@ -628,34 +388,11 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== - dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - "@babel/parser@^7.22.7", "@babel/parser@^7.24.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== -"@babel/parser@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" - integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== - -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz#fd059fd27b184ea2b4c7e646868a9a381bbc3055" - integrity sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ== - dependencies: - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a" @@ -663,13 +400,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz#468096ca44bbcbe8fcc570574e12eb1950e18107" - integrity sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d" @@ -679,15 +409,6 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-optional-chaining" "^7.23.3" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" - integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" - "@babel/plugin-transform-optional-chaining" "^7.24.7" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7": version "7.23.7" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b" @@ -696,14 +417,6 @@ "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz#71b21bb0286d5810e63a1538aa901c58e87375ec" - integrity sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg== - dependencies: - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": version "7.21.0-placeholder-for-preset-env.2" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" @@ -751,13 +464,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-syntax-import-assertions@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" - integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-import-attributes@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz#992aee922cf04512461d7dae3ff6951b90a2dc06" @@ -765,13 +471,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-syntax-import-attributes@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" - integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -793,13 +492,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-syntax-jsx@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" - integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -863,13 +555,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-syntax-typescript@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz#58d458271b4d3b6bb27ee6ac9525acbb259bad1c" - integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" @@ -885,13 +570,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-arrow-functions@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" - integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-async-generator-functions@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz#9adaeb66fc9634a586c5df139c6240d41ed801ce" @@ -902,16 +580,6 @@ "@babel/helper-remap-async-to-generator" "^7.22.20" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-transform-async-generator-functions@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz#7330a5c50e05181ca52351b8fd01642000c96cfd" - integrity sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g== - dependencies: - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-remap-async-to-generator" "^7.24.7" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-transform-async-to-generator@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa" @@ -921,15 +589,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-remap-async-to-generator" "^7.22.20" -"@babel/plugin-transform-async-to-generator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" - integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== - dependencies: - "@babel/helper-module-imports" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-remap-async-to-generator" "^7.24.7" - "@babel/plugin-transform-block-scoped-functions@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" @@ -937,13 +596,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-block-scoped-functions@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" - integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-block-scoping@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" @@ -951,13 +603,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-block-scoping@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz#42063e4deb850c7bd7c55e626bf4e7ab48e6ce02" - integrity sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-class-properties@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz#35c377db11ca92a785a718b6aa4e3ed1eb65dc48" @@ -966,14 +611,6 @@ "@babel/helper-create-class-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-class-properties@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834" - integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-class-static-block@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz#2a202c8787a8964dd11dfcedf994d36bfc844ab5" @@ -983,15 +620,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-transform-class-static-block@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" - integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-transform-classes@^7.23.8": version "7.23.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" @@ -1006,20 +634,6 @@ "@babel/helper-split-export-declaration" "^7.22.6" globals "^11.1.0" -"@babel/plugin-transform-classes@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz#4ae6ef43a12492134138c1e45913f7c46c41b4bf" - integrity sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.7" - "@babel/helper-compilation-targets" "^7.24.7" - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-function-name" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-replace-supers" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" - globals "^11.1.0" - "@babel/plugin-transform-computed-properties@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" @@ -1028,14 +642,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/template" "^7.22.15" -"@babel/plugin-transform-computed-properties@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" - integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/template" "^7.24.7" - "@babel/plugin-transform-destructuring@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" @@ -1043,13 +649,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-destructuring@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz#a097f25292defb6e6cc16d6333a4cfc1e3c72d9e" - integrity sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-dotall-regex@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50" @@ -1058,14 +657,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-dotall-regex@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" - integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-duplicate-keys@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce" @@ -1073,13 +664,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-duplicate-keys@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" - integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-dynamic-import@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz#c7629e7254011ac3630d47d7f34ddd40ca535143" @@ -1088,14 +672,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-dynamic-import@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" - integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18" @@ -1104,14 +680,6 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-exponentiation-operator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" - integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-export-namespace-from@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz#084c7b25e9a5c8271e987a08cf85807b80283191" @@ -1120,14 +688,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-export-namespace-from@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" - integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-transform-for-of@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" @@ -1136,14 +696,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" -"@babel/plugin-transform-for-of@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" - integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" - "@babel/plugin-transform-function-name@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" @@ -1153,15 +705,6 @@ "@babel/helper-function-name" "^7.23.0" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-function-name@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz#6d8601fbffe665c894440ab4470bc721dd9131d6" - integrity sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w== - dependencies: - "@babel/helper-compilation-targets" "^7.24.7" - "@babel/helper-function-name" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-json-strings@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz#a871d9b6bd171976efad2e43e694c961ffa3714d" @@ -1170,14 +713,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-json-strings@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" - integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-transform-literals@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" @@ -1185,13 +720,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-literals@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz#36b505c1e655151a9d7607799a9988fc5467d06c" - integrity sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-logical-assignment-operators@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz#e599f82c51d55fac725f62ce55d3a0886279ecb5" @@ -1200,14 +728,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-logical-assignment-operators@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" - integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-transform-member-expression-literals@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" @@ -1215,13 +735,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-member-expression-literals@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" - integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-modules-amd@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d" @@ -1230,14 +743,6 @@ "@babel/helper-module-transforms" "^7.23.3" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-modules-amd@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" - integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== - dependencies: - "@babel/helper-module-transforms" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-modules-commonjs@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" @@ -1247,15 +752,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-simple-access" "^7.22.5" -"@babel/plugin-transform-modules-commonjs@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz#9fd5f7fdadee9085886b183f1ad13d1ab260f4ab" - integrity sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ== - dependencies: - "@babel/helper-module-transforms" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-simple-access" "^7.24.7" - "@babel/plugin-transform-modules-systemjs@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz#105d3ed46e4a21d257f83a2f9e2ee4203ceda6be" @@ -1266,16 +762,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-validator-identifier" "^7.22.20" -"@babel/plugin-transform-modules-systemjs@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz#f8012316c5098f6e8dee6ecd58e2bc6f003d0ce7" - integrity sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw== - dependencies: - "@babel/helper-hoist-variables" "^7.24.7" - "@babel/helper-module-transforms" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-validator-identifier" "^7.24.7" - "@babel/plugin-transform-modules-umd@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9" @@ -1284,14 +770,6 @@ "@babel/helper-module-transforms" "^7.23.3" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-modules-umd@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" - integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== - dependencies: - "@babel/helper-module-transforms" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" @@ -1300,14 +778,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" - integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-new-target@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980" @@ -1315,13 +785,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-new-target@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" - integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-nullish-coalescing-operator@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz#45556aad123fc6e52189ea749e33ce090637346e" @@ -1330,14 +793,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" - integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-transform-numeric-separator@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz#03d08e3691e405804ecdd19dd278a40cca531f29" @@ -1346,14 +801,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-transform-numeric-separator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" - integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-transform-object-rest-spread@^7.24.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.0.tgz#7b836ad0088fdded2420ce96d4e1d3ed78b71df1" @@ -1365,16 +812,6 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.23.3" -"@babel/plugin-transform-object-rest-spread@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" - integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== - dependencies: - "@babel/helper-compilation-targets" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.24.7" - "@babel/plugin-transform-object-super@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" @@ -1383,14 +820,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-replace-supers" "^7.22.20" -"@babel/plugin-transform-object-super@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" - integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-replace-supers" "^7.24.7" - "@babel/plugin-transform-optional-catch-binding@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz#318066de6dacce7d92fa244ae475aa8d91778017" @@ -1399,14 +828,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-transform-optional-catch-binding@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" - integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-transform-optional-chaining@^7.23.3", "@babel/plugin-transform-optional-chaining@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017" @@ -1416,15 +837,6 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-transform-optional-chaining@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz#b8f6848a80cf2da98a8a204429bec04756c6d454" - integrity sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-transform-parameters@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" @@ -1432,13 +844,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-parameters@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" - integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-private-methods@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz#b2d7a3c97e278bfe59137a978d53b2c2e038c0e4" @@ -1447,14 +852,6 @@ "@babel/helper-create-class-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-private-methods@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e" - integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-private-property-in-object@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz#3ec711d05d6608fd173d9b8de39872d8dbf68bf5" @@ -1465,16 +862,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-transform-private-property-in-object@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" - integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.7" - "@babel/helper-create-class-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-transform-property-literals@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" @@ -1482,13 +869,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-property-literals@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" - integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-react-constant-elements@^7.18.12": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.23.3.tgz#5efc001d07ef0f7da0d73c3a86c132f73d28e43c" @@ -1496,13 +876,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-react-constant-elements@^7.21.3": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz#b85e8f240b14400277f106c9c9b585d9acf608a1" - integrity sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-react-display-name@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz#70529f034dd1e561045ad3c8152a267f0d7b6200" @@ -1544,14 +917,6 @@ "@babel/helper-plugin-utils" "^7.22.5" regenerator-transform "^0.15.2" -"@babel/plugin-transform-regenerator@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" - integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - regenerator-transform "^0.15.2" - "@babel/plugin-transform-reserved-words@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8" @@ -1559,13 +924,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-reserved-words@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" - integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-runtime@^7.22.9": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.0.tgz#e308fe27d08b74027d42547081eefaf4f2ffbcc9" @@ -1585,13 +943,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-shorthand-properties@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" - integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-spread@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" @@ -1600,14 +951,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" -"@babel/plugin-transform-spread@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" - integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" - "@babel/plugin-transform-sticky-regex@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04" @@ -1615,13 +958,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-sticky-regex@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" - integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-template-literals@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" @@ -1629,13 +965,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-template-literals@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" - integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-typeof-symbol@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4" @@ -1643,13 +972,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-typeof-symbol@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz#f074be466580d47d6e6b27473a840c9f9ca08fb0" - integrity sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-typescript@^7.23.3": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz#aa36a94e5da8d94339ae3a4e22d40ed287feb34c" @@ -1660,16 +982,6 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-typescript" "^7.23.3" -"@babel/plugin-transform-typescript@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.7.tgz#b006b3e0094bf0813d505e0c5485679eeaf4a881" - integrity sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.7" - "@babel/helper-create-class-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-syntax-typescript" "^7.24.7" - "@babel/plugin-transform-unicode-escapes@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925" @@ -1677,13 +989,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-unicode-escapes@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" - integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-unicode-property-regex@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz#19e234129e5ffa7205010feec0d94c251083d7ad" @@ -1692,14 +997,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-unicode-property-regex@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" - integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-unicode-regex@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc" @@ -1708,14 +1005,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-unicode-regex@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" - integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/plugin-transform-unicode-sets-regex@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz#4fb6f0a719c2c5859d11f6b55a050cc987f3799e" @@ -1724,14 +1013,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-unicode-sets-regex@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9" - integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/preset-env@^7.19.4", "@babel/preset-env@^7.22.9": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.0.tgz#11536a7f4b977294f0bdfad780f01a8ac8e183fc" @@ -1818,93 +1099,6 @@ core-js-compat "^3.31.0" semver "^6.3.1" -"@babel/preset-env@^7.20.2": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.7.tgz#ff067b4e30ba4a72f225f12f123173e77b987f37" - integrity sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ== - dependencies: - "@babel/compat-data" "^7.24.7" - "@babel/helper-compilation-targets" "^7.24.7" - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-validator-option" "^7.24.7" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.7" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.7" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.7" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.24.7" - "@babel/plugin-syntax-import-attributes" "^7.24.7" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.24.7" - "@babel/plugin-transform-async-generator-functions" "^7.24.7" - "@babel/plugin-transform-async-to-generator" "^7.24.7" - "@babel/plugin-transform-block-scoped-functions" "^7.24.7" - "@babel/plugin-transform-block-scoping" "^7.24.7" - "@babel/plugin-transform-class-properties" "^7.24.7" - "@babel/plugin-transform-class-static-block" "^7.24.7" - "@babel/plugin-transform-classes" "^7.24.7" - "@babel/plugin-transform-computed-properties" "^7.24.7" - "@babel/plugin-transform-destructuring" "^7.24.7" - "@babel/plugin-transform-dotall-regex" "^7.24.7" - "@babel/plugin-transform-duplicate-keys" "^7.24.7" - "@babel/plugin-transform-dynamic-import" "^7.24.7" - "@babel/plugin-transform-exponentiation-operator" "^7.24.7" - "@babel/plugin-transform-export-namespace-from" "^7.24.7" - "@babel/plugin-transform-for-of" "^7.24.7" - "@babel/plugin-transform-function-name" "^7.24.7" - "@babel/plugin-transform-json-strings" "^7.24.7" - "@babel/plugin-transform-literals" "^7.24.7" - "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" - "@babel/plugin-transform-member-expression-literals" "^7.24.7" - "@babel/plugin-transform-modules-amd" "^7.24.7" - "@babel/plugin-transform-modules-commonjs" "^7.24.7" - "@babel/plugin-transform-modules-systemjs" "^7.24.7" - "@babel/plugin-transform-modules-umd" "^7.24.7" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" - "@babel/plugin-transform-new-target" "^7.24.7" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" - "@babel/plugin-transform-numeric-separator" "^7.24.7" - "@babel/plugin-transform-object-rest-spread" "^7.24.7" - "@babel/plugin-transform-object-super" "^7.24.7" - "@babel/plugin-transform-optional-catch-binding" "^7.24.7" - "@babel/plugin-transform-optional-chaining" "^7.24.7" - "@babel/plugin-transform-parameters" "^7.24.7" - "@babel/plugin-transform-private-methods" "^7.24.7" - "@babel/plugin-transform-private-property-in-object" "^7.24.7" - "@babel/plugin-transform-property-literals" "^7.24.7" - "@babel/plugin-transform-regenerator" "^7.24.7" - "@babel/plugin-transform-reserved-words" "^7.24.7" - "@babel/plugin-transform-shorthand-properties" "^7.24.7" - "@babel/plugin-transform-spread" "^7.24.7" - "@babel/plugin-transform-sticky-regex" "^7.24.7" - "@babel/plugin-transform-template-literals" "^7.24.7" - "@babel/plugin-transform-typeof-symbol" "^7.24.7" - "@babel/plugin-transform-unicode-escapes" "^7.24.7" - "@babel/plugin-transform-unicode-property-regex" "^7.24.7" - "@babel/plugin-transform-unicode-regex" "^7.24.7" - "@babel/plugin-transform-unicode-sets-regex" "^7.24.7" - "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.4" - babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.31.0" - semver "^6.3.1" - "@babel/preset-modules@0.1.6-no-external-plugins": version "0.1.6-no-external-plugins" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" @@ -1937,17 +1131,6 @@ "@babel/plugin-transform-modules-commonjs" "^7.23.3" "@babel/plugin-transform-typescript" "^7.23.3" -"@babel/preset-typescript@^7.21.0": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz#66cd86ea8f8c014855671d5ea9a737139cbbfef1" - integrity sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.7" - "@babel/helper-validator-option" "^7.24.7" - "@babel/plugin-syntax-jsx" "^7.24.7" - "@babel/plugin-transform-modules-commonjs" "^7.24.7" - "@babel/plugin-transform-typescript" "^7.24.7" - "@babel/regjsgen@^0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" @@ -1977,15 +1160,6 @@ "@babel/parser" "^7.24.0" "@babel/types" "^7.24.0" -"@babel/template@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" - integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== - dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/types" "^7.24.7" - "@babel/traverse@^7.22.8", "@babel/traverse@^7.24.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" @@ -2002,22 +1176,6 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/traverse@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5" - integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA== - dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/generator" "^7.24.7" - "@babel/helper-environment-visitor" "^7.24.7" - "@babel/helper-function-name" "^7.24.7" - "@babel/helper-hoist-variables" "^7.24.7" - "@babel/helper-split-export-declaration" "^7.24.7" - "@babel/parser" "^7.24.7" - "@babel/types" "^7.24.7" - debug "^4.3.1" - globals "^11.1.0" - "@babel/types@^7.20.0", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.4.4": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" @@ -2027,15 +1185,6 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@babel/types@^7.21.3", "@babel/types@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" - integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== - dependencies: - "@babel/helper-string-parser" "^7.24.7" - "@babel/helper-validator-identifier" "^7.24.7" - to-fast-properties "^2.0.0" - "@braintree/sanitize-url@^6.0.1": version "6.0.4" resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" @@ -2141,10 +1290,10 @@ webpack-merge "^5.9.0" webpackbar "^5.0.2" -"@docusaurus/core@3.4.0", "@docusaurus/core@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.4.0.tgz#bdbf1af4b2f25d1bf4a5b62ec6137d84c821cb3c" - integrity sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w== +"@docusaurus/core@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-3.2.0.tgz#10acb993fb76960890d1aa43025245aaa8dcdbbb" + integrity sha512-WTO6vW4404nhTmK9NL+95nd13I1JveFwZ8iOBYxb4xt+N2S3KzY+mm+1YtWw2vV37FbYfH+w+KrlrRaWuy5Hzw== dependencies: "@babel/core" "^7.23.3" "@babel/generator" "^7.23.3" @@ -2156,12 +1305,14 @@ "@babel/runtime" "^7.22.6" "@babel/runtime-corejs3" "^7.22.6" "@babel/traverse" "^7.22.8" - "@docusaurus/cssnano-preset" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/cssnano-preset" "3.2.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/mdx-loader" "3.2.0" + "@docusaurus/react-loadable" "5.5.2" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" + "@svgr/webpack" "^6.5.1" autoprefixer "^10.4.14" babel-loader "^9.1.3" babel-plugin-dynamic-import-node "^2.3.3" @@ -2175,8 +1326,8 @@ copy-webpack-plugin "^11.0.0" core-js "^3.31.1" css-loader "^6.8.1" - css-minimizer-webpack-plugin "^5.0.1" - cssnano "^6.1.2" + css-minimizer-webpack-plugin "^4.2.2" + cssnano "^5.1.15" del "^6.1.1" detect-port "^1.5.1" escape-html "^1.0.3" @@ -2196,7 +1347,7 @@ prompts "^2.4.2" react-dev-utils "^12.0.1" react-helmet-async "^1.3.0" - react-loadable "npm:@docusaurus/react-loadable@6.0.0" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" react-loadable-ssr-addon-v5-slorber "^1.0.1" react-router "^5.3.4" react-router-config "^5.1.1" @@ -2225,14 +1376,14 @@ postcss-sort-media-queries "^4.4.1" tslib "^2.6.0" -"@docusaurus/cssnano-preset@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz#dc7922b3bbeabcefc9b60d0161680d81cf72c368" - integrity sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ== +"@docusaurus/cssnano-preset@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-3.2.0.tgz#0e0fbf19873a726f92e670b9d511e9f2828d6097" + integrity sha512-H88RXGUia7r/VF3XfyoA4kbwgpUZcKsObF6VvwBOP91EdArTf6lnHbJ/x8Ca79KS/zf98qaWyBGzW+5ez58Iyw== dependencies: - cssnano-preset-advanced "^6.1.2" - postcss "^8.4.38" - postcss-sort-media-queries "^5.2.0" + cssnano-preset-advanced "^5.3.10" + postcss "^8.4.26" + postcss-sort-media-queries "^4.4.1" tslib "^2.6.0" "@docusaurus/logger@3.1.1": @@ -2243,10 +1394,10 @@ chalk "^4.1.2" tslib "^2.6.0" -"@docusaurus/logger@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.4.0.tgz#8b0ac05c7f3dac2009066e2f964dee8209a77403" - integrity sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q== +"@docusaurus/logger@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-3.2.0.tgz#99d2b09478bcba69c964ec0c8600d855fb8e9e0f" + integrity sha512-Z1R1NcOGXZ8CkIJSvjvyxnuDDSlx/+1xlh20iVTw1DZRjonFmI3T3tTgk40YpXyWUYQpIgAoqqPMpuseMMdgRQ== dependencies: chalk "^4.1.2" tslib "^2.6.0" @@ -2283,14 +1434,14 @@ vfile "^6.0.1" webpack "^5.88.1" -"@docusaurus/mdx-loader@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz#483d7ab57928fdbb5c8bd1678098721a930fc5f6" - integrity sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw== +"@docusaurus/mdx-loader@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-3.2.0.tgz#d17f17ae1bb38255643c82705dda719b23c27831" + integrity sha512-JtkI5o6R/rJSr1Y23cHKz085aBJCvJw3AYHihJ7r+mBX+O8EuQIynG0e6/XpbSCpr7Ino0U50UtxaXcEbFwg9Q== dependencies: - "@docusaurus/logger" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" "@mdx-js/mdx" "^3.0.0" "@slorber/remark-comment" "^1.0.0" escape-html "^1.0.3" @@ -2327,46 +1478,47 @@ react-helmet-async "*" react-loadable "npm:@docusaurus/react-loadable@5.5.2" -"@docusaurus/module-type-aliases@3.4.0", "@docusaurus/module-type-aliases@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz#2653bde58fc1aa3dbc626a6c08cfb63a37ae1bb8" - integrity sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw== +"@docusaurus/module-type-aliases@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-3.2.0.tgz#ef883d8418f37e551eca72adc409014e720786d4" + integrity sha512-jRSp9YkvBwwNz6Xgy0RJPsnie+Ebb//gy7GdbkJ2pW2gvvlYKGib2+jSF0pfIzvyZLulfCynS1KQdvDKdSl8zQ== dependencies: - "@docusaurus/types" "3.4.0" + "@docusaurus/react-loadable" "5.5.2" + "@docusaurus/types" "3.2.0" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" "@types/react-router-dom" "*" react-helmet-async "*" - react-loadable "npm:@docusaurus/react-loadable@6.0.0" - -"@docusaurus/plugin-client-redirects@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.4.0.tgz#10eafc9adcf3f9be7cc33d77e816040dc7a8d368" - integrity sha512-Pr8kyh/+OsmYCvdZhc60jy/FnrY6flD2TEAhl4rJxeVFxnvvRgEhoaIVX8q9MuJmaQoh6frPk94pjs7/6YgBDQ== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" + +"@docusaurus/plugin-client-redirects@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-client-redirects/-/plugin-client-redirects-3.2.0.tgz#4c98c185620ce10830e1cc8a7f16a807857cb654" + integrity sha512-re5bgvYOgBHmevlI8HO3fZHL7mvX2lAULr4E89n/bQ5kgekLLhsaerWrAah22ZluMZyJC2439EGjR63E9Ba6KA== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" eta "^2.2.0" fs-extra "^11.1.1" lodash "^4.17.21" tslib "^2.6.0" -"@docusaurus/plugin-content-blog@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz#6373632fdbababbda73a13c4a08f907d7de8f007" - integrity sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/plugin-content-blog@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.2.0.tgz#b7b43e71634272a80a9532dc166731332391cb4b" + integrity sha512-MABqwjSicyHmYEfQueMthPCz18JkVxhK3EGhXTSRWwReAZ0UTuw9pG6+Wo+uXAugDaIcJH28rVZSwTDINPm2bw== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/mdx-loader" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" cheerio "^1.0.0-rc.12" feed "^4.2.2" fs-extra "^11.1.1" @@ -2378,19 +1530,19 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-docs@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz#3088973f72169a2a6d533afccec7153c8720d332" - integrity sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/module-type-aliases" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/plugin-content-docs@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.2.0.tgz#6e4f727a0cce301b9d9361bf41ca6a978fe79475" + integrity sha512-uuqhahmsBnirxOz+SXksnWt7+wc+iN4ntxNRH48BUgo7QRNLATWjHCgI8t6zrMJxK4o+QL9DhLaPDlFHs91B3Q== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/mdx-loader" "3.2.0" + "@docusaurus/module-type-aliases" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" "@types/react-router-config" "^5.0.7" combine-promises "^1.1.0" fs-extra "^11.1.1" @@ -2421,96 +1573,96 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-pages@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz#1846172ca0355c7d32a67ef8377750ce02bbb8ad" - integrity sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/plugin-content-pages@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.2.0.tgz#df28a6ee6b52c4b292a726f29f39b119756caf44" + integrity sha512-4ofAN7JDsdb4tODO9OIrizWY5DmEJXr0eu+UDIkLqGP+gXXTahJZv8h2mlxO+lPXGXRCVBOfA14OG1hOYJVPwA== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/mdx-loader" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" fs-extra "^11.1.1" tslib "^2.6.0" webpack "^5.88.1" -"@docusaurus/plugin-debug@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz#74e4ec5686fa314c26f3ac150bacadbba7f06948" - integrity sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg== +"@docusaurus/plugin-debug@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-3.2.0.tgz#643d13d403685c2b9bdb3b65bec8050847b920a3" + integrity sha512-p6WxtO5XZGz66y6QNQtCJwBefq4S6/w75XaXVvH1/2P9uaijvF7R+Cm2EWQZ5WsvA5wl//DFWblyDHRyVC207Q== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" + "@docusaurus/core" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils" "3.2.0" fs-extra "^11.1.1" react-json-view-lite "^1.2.0" tslib "^2.6.0" -"@docusaurus/plugin-google-analytics@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz#5f59fc25329a59decc231936f6f9fb5663da3c55" - integrity sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA== +"@docusaurus/plugin-google-analytics@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.2.0.tgz#770151947c0ee49500586e9200631852ab97e23a" + integrity sha512-//TepJTEyAZSvBwHKEbXHu9xT/VkK3wUil2ZakKvQZYfUC01uWn6A1E3toa8R7WhCy1xPUeIukqmJy1Clg8njQ== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" tslib "^2.6.0" -"@docusaurus/plugin-google-gtag@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz#42489ac5fe1c83b5523ceedd5ef74f9aa8bc251b" - integrity sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA== +"@docusaurus/plugin-google-gtag@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.2.0.tgz#65fc7ddc242185c3a10e60308471564075229406" + integrity sha512-3s6zxlaMMb87MW2Rxy6EnSRDs0WDEQPuHilZZH402C8kOrUnIwlhlfjWZ4ZyLDziGl/Eec/DvD0PVqj0qHRomA== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" "@types/gtag.js" "^0.0.12" tslib "^2.6.0" -"@docusaurus/plugin-google-tag-manager@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz#cebb03a5ffa1e70b37d95601442babea251329ff" - integrity sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ== +"@docusaurus/plugin-google-tag-manager@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.2.0.tgz#730c28a43ff5073f595509c6cb77ce4311a2e369" + integrity sha512-rAKtsJ11vPHA7dTAqWCgyIy7AyFRF/lpI77Zd/4HKgqcIvIayVBvL3QtelhUazfYTLTH6ls6kQ9wjMcIFxRiGg== dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" tslib "^2.6.0" -"@docusaurus/plugin-sitemap@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz#b091d64d1e3c6c872050189999580187537bcbc6" - integrity sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/plugin-sitemap@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.2.0.tgz#cae7c92a8631072fff39dd5caf5ea7608c795540" + integrity sha512-gnWDFt6MStjLkdtt63Lzc+14EPSd8B6mzJGJp9GQMvWDUoMAUijUqpVIHYQq+DPMcI4PJZ5I2nsl5XFf1vOldA== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" fs-extra "^11.1.1" sitemap "^7.1.1" tslib "^2.6.0" -"@docusaurus/preset-classic@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz#6082a32fbb465b0cb2c2a50ebfc277cff2c0f139" - integrity sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/plugin-content-blog" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/plugin-content-pages" "3.4.0" - "@docusaurus/plugin-debug" "3.4.0" - "@docusaurus/plugin-google-analytics" "3.4.0" - "@docusaurus/plugin-google-gtag" "3.4.0" - "@docusaurus/plugin-google-tag-manager" "3.4.0" - "@docusaurus/plugin-sitemap" "3.4.0" - "@docusaurus/theme-classic" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/theme-search-algolia" "3.4.0" - "@docusaurus/types" "3.4.0" +"@docusaurus/preset-classic@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-3.2.0.tgz#f64d970eace76c61e4f1b4b7d85d9f69d4a2dd0e" + integrity sha512-t7tXyk8kUgT7hUqEOgSJnPs+Foem9ucuan/a9QVYaVFCDjp92Sb2FpCY8bVasAokYCjodYe2LfpAoSCj5YDYWg== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/plugin-content-blog" "3.2.0" + "@docusaurus/plugin-content-docs" "3.2.0" + "@docusaurus/plugin-content-pages" "3.2.0" + "@docusaurus/plugin-debug" "3.2.0" + "@docusaurus/plugin-google-analytics" "3.2.0" + "@docusaurus/plugin-google-gtag" "3.2.0" + "@docusaurus/plugin-google-tag-manager" "3.2.0" + "@docusaurus/plugin-sitemap" "3.2.0" + "@docusaurus/theme-classic" "3.2.0" + "@docusaurus/theme-common" "3.2.0" + "@docusaurus/theme-search-algolia" "3.2.0" + "@docusaurus/types" "3.2.0" "@docusaurus/react-loadable@5.5.2": version "5.5.2" @@ -2520,23 +1672,23 @@ "@types/react" "*" prop-types "^15.6.2" -"@docusaurus/theme-classic@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz#1b0f48edec3e3ec8927843554b9f11e5927b0e52" - integrity sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/module-type-aliases" "3.4.0" - "@docusaurus/plugin-content-blog" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/plugin-content-pages" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/theme-translations" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/theme-classic@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-3.2.0.tgz#4aa229f1a4b1b4c138a5c80089f1d8146f56252c" + integrity sha512-4oSO5BQOJ5ja7WYdL6jK1n4J96tp+VJHamdwao6Ea252sA3W3vvR0otTflG4p4XVjNZH6hlPQoi5lKW0HeRgfQ== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/mdx-loader" "3.2.0" + "@docusaurus/module-type-aliases" "3.2.0" + "@docusaurus/plugin-content-blog" "3.2.0" + "@docusaurus/plugin-content-docs" "3.2.0" + "@docusaurus/plugin-content-pages" "3.2.0" + "@docusaurus/theme-common" "3.2.0" + "@docusaurus/theme-translations" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" "@mdx-js/react" "^3.0.0" clsx "^2.0.0" copy-text-to-clipboard "^3.2.0" @@ -2551,18 +1703,18 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-common@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.4.0.tgz#01f2b728de6cb57f6443f52fc30675cf12a5d49f" - integrity sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA== - dependencies: - "@docusaurus/mdx-loader" "3.4.0" - "@docusaurus/module-type-aliases" "3.4.0" - "@docusaurus/plugin-content-blog" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/plugin-content-pages" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" +"@docusaurus/theme-common@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.2.0.tgz#67f5f1a1e265e1f1a5b9fa7bfb4bf7b98dfcf981" + integrity sha512-sFbw9XviNJJ+760kAcZCQMQ3jkNIznGqa6MQ70E5BnbP+ja36kGgPOfjcsvAcNey1H1Rkhh3p2Mhf4HVLdKVVw== + dependencies: + "@docusaurus/mdx-loader" "3.2.0" + "@docusaurus/module-type-aliases" "3.2.0" + "@docusaurus/plugin-content-blog" "3.2.0" + "@docusaurus/plugin-content-docs" "3.2.0" + "@docusaurus/plugin-content-pages" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -2572,32 +1724,32 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-mermaid@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-mermaid/-/theme-mermaid-3.4.0.tgz#ef1d2231d0858767f67538b4fafd7d0ce2a3e845" - integrity sha512-3w5QW0HEZ2O6x2w6lU3ZvOe1gNXP2HIoKDMJBil1VmLBc9PmpAG17VmfhI/p3L2etNmOiVs5GgniUqvn8AFEGQ== - dependencies: - "@docusaurus/core" "3.4.0" - "@docusaurus/module-type-aliases" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/types" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" +"@docusaurus/theme-mermaid@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-mermaid/-/theme-mermaid-3.2.0.tgz#b6d43b853ccc562a9c0be28e1100dad6324b8a8f" + integrity sha512-PvN6K6m3JaM9cr9oSPyba6OlwAiSfBzqQtNqdgPFDjakKuT4kj6JODfExi+HKtWuxayOVRQlRl7zTnWxM4sTVw== + dependencies: + "@docusaurus/core" "3.2.0" + "@docusaurus/module-type-aliases" "3.2.0" + "@docusaurus/theme-common" "3.2.0" + "@docusaurus/types" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" mermaid "^10.4.0" tslib "^2.6.0" -"@docusaurus/theme-search-algolia@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz#c499bad71d668df0d0f15b0e5e33e2fc4e330fcc" - integrity sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q== +"@docusaurus/theme-search-algolia@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.2.0.tgz#05338b37753dd13899fb0296f2c57130e9893dbf" + integrity sha512-PgvF4qHoqJp8+GfqClUbTF/zYNOsz4De251IuzXon7+7FAXwvb2qmYtA2nEwyMbB7faKOz33Pxzv+y+153KS/g== dependencies: "@docsearch/react" "^3.5.2" - "@docusaurus/core" "3.4.0" - "@docusaurus/logger" "3.4.0" - "@docusaurus/plugin-content-docs" "3.4.0" - "@docusaurus/theme-common" "3.4.0" - "@docusaurus/theme-translations" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-validation" "3.4.0" + "@docusaurus/core" "3.2.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/plugin-content-docs" "3.2.0" + "@docusaurus/theme-common" "3.2.0" + "@docusaurus/theme-translations" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-validation" "3.2.0" algoliasearch "^4.18.0" algoliasearch-helper "^3.13.3" clsx "^2.0.0" @@ -2607,10 +1759,10 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz#e6355d01352886c67e38e848b2542582ea3070af" - integrity sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg== +"@docusaurus/theme-translations@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-3.2.0.tgz#02a0e9bd0ed8cebc21a2f1e5b6d252b0e5ee39a9" + integrity sha512-VXzZJBuyVEmwUYyud+7IgJQEBRM6R2u/s10Rp3DOP19CBQxeKgHYTKkKhFtDeKMHDassb665kjgOi0YlJfUT6w== dependencies: fs-extra "^11.1.1" tslib "^2.6.0" @@ -2638,10 +1790,10 @@ webpack "^5.88.1" webpack-merge "^5.9.0" -"@docusaurus/types@3.4.0", "@docusaurus/types@^3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.4.0.tgz#237c3f737e9db3f7c1a5935a3ef48d6eadde8292" - integrity sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A== +"@docusaurus/types@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.2.0.tgz#c5bfd000ad4f72e9a7e6beff79905f9ea165fcd3" + integrity sha512-uG3FfTkkkbZIPPNYx6xRfZHKeGyRd/inIT1cqvYt1FobFLd+7WhRXrSBqwJ9JajJjEAjNioRMVFgGofGf/Wdww== dependencies: "@mdx-js/mdx" "^3.0.0" "@types/history" "^4.7.11" @@ -2660,10 +1812,10 @@ dependencies: tslib "^2.6.0" -"@docusaurus/utils-common@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.4.0.tgz#2a43fefd35b85ab9fcc6833187e66c15f8bfbbc6" - integrity sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ== +"@docusaurus/utils-common@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-3.2.0.tgz#6163a2c415d150d6df73a8aceec6004f0ba3bb06" + integrity sha512-WEQT5L2lT/tBQgDRgeZQAIi9YJBrwEILb1BuObQn1St3T/4K1gx5fWwOT8qdLOov296XLd1FQg9Ywu27aE9svw== dependencies: tslib "^2.6.0" @@ -2678,18 +1830,16 @@ js-yaml "^4.1.0" tslib "^2.6.0" -"@docusaurus/utils-validation@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz#0176f6e503ff45f4390ec2ecb69550f55e0b5eb7" - integrity sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g== +"@docusaurus/utils-validation@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.2.0.tgz#b53463d9dc6eb335a2ad93ed4b3c397162533e6d" + integrity sha512-rCzMTqwNrBrEOyU8EaD1fYWdig4TDhfj+YLqB8DY68VUAqSIgbY+yshpqFKB0bznFYNBJbn0bGpvVuImQOa/vA== dependencies: - "@docusaurus/logger" "3.4.0" - "@docusaurus/utils" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - fs-extra "^11.2.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/utils" "3.2.0" + "@docusaurus/utils-common" "3.2.0" joi "^17.9.2" js-yaml "^4.1.0" - lodash "^4.17.21" tslib "^2.6.0" "@docusaurus/utils@3.1.1", "@docusaurus/utils@^2 || ^3": @@ -2715,14 +1865,14 @@ url-loader "^4.1.1" webpack "^5.88.1" -"@docusaurus/utils@3.4.0": - version "3.4.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.4.0.tgz#c508e20627b7a55e2b541e4a28c95e0637d6a204" - integrity sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g== +"@docusaurus/utils@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.2.0.tgz#1312221d224eb2cbaaaf53d24efca3e1e976db3e" + integrity sha512-3rgrE7iL60yV2JQivlcoxUNNTK2APmn+OHLUmTvX2pueIM8DEOCEFHpJO4MiWjFO7V/Wq3iA/W1M03JnjdugVw== dependencies: - "@docusaurus/logger" "3.4.0" - "@docusaurus/utils-common" "3.4.0" - "@svgr/webpack" "^8.1.0" + "@docusaurus/logger" "3.2.0" + "@docusaurus/utils-common" "3.2.0" + "@svgr/webpack" "^6.5.1" escape-string-regexp "^4.0.0" file-loader "^6.2.0" fs-extra "^11.1.1" @@ -2738,7 +1888,6 @@ shelljs "^0.8.5" tslib "^2.6.0" url-loader "^4.1.1" - utility-types "^3.10.0" webpack "^5.88.1" "@easyops-cn/autocomplete.js@^0.38.1": @@ -2848,7 +1997,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.9": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -3095,90 +2244,46 @@ p-map "^4.0.0" webpack-sources "^3.2.2" -"@svgr/babel-plugin-add-jsx-attribute@8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz#4001f5d5dd87fa13303e36ee106e3ff3a7eb8b22" - integrity sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g== - "@svgr/babel-plugin-add-jsx-attribute@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== -"@svgr/babel-plugin-remove-jsx-attribute@*", "@svgr/babel-plugin-remove-jsx-attribute@8.0.0": +"@svgr/babel-plugin-remove-jsx-attribute@*": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz#69177f7937233caca3a1afb051906698f2f59186" integrity sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA== -"@svgr/babel-plugin-remove-jsx-empty-expression@*", "@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0": +"@svgr/babel-plugin-remove-jsx-empty-expression@*": version "8.0.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz#c2c48104cfd7dcd557f373b70a56e9e3bdae1d44" integrity sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA== -"@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz#8fbb6b2e91fa26ac5d4aa25c6b6e4f20f9c0ae27" - integrity sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ== - "@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz#fb9d22ea26d2bc5e0a44b763d4c46d5d3f596c60" integrity sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg== -"@svgr/babel-plugin-svg-dynamic-title@8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz#1d5ba1d281363fc0f2f29a60d6d936f9bbc657b0" - integrity sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og== - "@svgr/babel-plugin-svg-dynamic-title@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz#01b2024a2b53ffaa5efceaa0bf3e1d5a4c520ce4" integrity sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw== -"@svgr/babel-plugin-svg-em-dimensions@8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz#35e08df300ea8b1d41cb8f62309c241b0369e501" - integrity sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g== - "@svgr/babel-plugin-svg-em-dimensions@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz#dd3fa9f5b24eb4f93bcf121c3d40ff5facecb217" integrity sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA== -"@svgr/babel-plugin-transform-react-native-svg@8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz#90a8b63998b688b284f255c6a5248abd5b28d754" - integrity sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q== - "@svgr/babel-plugin-transform-react-native-svg@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz#1d8e945a03df65b601551097d8f5e34351d3d305" integrity sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg== -"@svgr/babel-plugin-transform-svg-component@8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz#013b4bfca88779711f0ed2739f3f7efcefcf4f7e" - integrity sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw== - "@svgr/babel-plugin-transform-svg-component@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz#48620b9e590e25ff95a80f811544218d27f8a250" integrity sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ== -"@svgr/babel-preset@8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-8.1.0.tgz#0e87119aecdf1c424840b9d4565b7137cabf9ece" - integrity sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "8.0.0" - "@svgr/babel-plugin-remove-jsx-attribute" "8.0.0" - "@svgr/babel-plugin-remove-jsx-empty-expression" "8.0.0" - "@svgr/babel-plugin-replace-jsx-attribute-value" "8.0.0" - "@svgr/babel-plugin-svg-dynamic-title" "8.0.0" - "@svgr/babel-plugin-svg-em-dimensions" "8.0.0" - "@svgr/babel-plugin-transform-react-native-svg" "8.1.0" - "@svgr/babel-plugin-transform-svg-component" "8.0.0" - "@svgr/babel-preset@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.5.1.tgz#b90de7979c8843c5c580c7e2ec71f024b49eb828" @@ -3193,17 +2298,6 @@ "@svgr/babel-plugin-transform-react-native-svg" "^6.5.1" "@svgr/babel-plugin-transform-svg-component" "^6.5.1" -"@svgr/core@8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-8.1.0.tgz#41146f9b40b1a10beaf5cc4f361a16a3c1885e88" - integrity sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA== - dependencies: - "@babel/core" "^7.21.3" - "@svgr/babel-preset" "8.1.0" - camelcase "^6.2.0" - cosmiconfig "^8.1.3" - snake-case "^3.0.4" - "@svgr/core@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.5.1.tgz#d3e8aa9dbe3fbd747f9ee4282c1c77a27410488a" @@ -3215,14 +2309,6 @@ camelcase "^6.2.0" cosmiconfig "^7.0.1" -"@svgr/hast-util-to-babel-ast@8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz#6952fd9ce0f470e1aded293b792a2705faf4ffd4" - integrity sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q== - dependencies: - "@babel/types" "^7.21.3" - entities "^4.4.0" - "@svgr/hast-util-to-babel-ast@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz#81800bd09b5bcdb968bf6ee7c863d2288fdb80d2" @@ -3231,16 +2317,6 @@ "@babel/types" "^7.20.0" entities "^4.4.0" -"@svgr/plugin-jsx@8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz#96969f04a24b58b174ee4cd974c60475acbd6928" - integrity sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA== - dependencies: - "@babel/core" "^7.21.3" - "@svgr/babel-preset" "8.1.0" - "@svgr/hast-util-to-babel-ast" "8.0.0" - svg-parser "^2.0.4" - "@svgr/plugin-jsx@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz#0e30d1878e771ca753c94e69581c7971542a7072" @@ -3251,15 +2327,6 @@ "@svgr/hast-util-to-babel-ast" "^6.5.1" svg-parser "^2.0.4" -"@svgr/plugin-svgo@8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz#b115b7b967b564f89ac58feae89b88c3decd0f00" - integrity sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA== - dependencies: - cosmiconfig "^8.1.3" - deepmerge "^4.3.1" - svgo "^3.0.2" - "@svgr/plugin-svgo@^6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz#0f91910e988fc0b842f88e0960c2862e022abe84" @@ -3283,20 +2350,6 @@ "@svgr/plugin-jsx" "^6.5.1" "@svgr/plugin-svgo" "^6.5.1" -"@svgr/webpack@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-8.1.0.tgz#16f1b5346f102f89fda6ec7338b96a701d8be0c2" - integrity sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA== - dependencies: - "@babel/core" "^7.21.3" - "@babel/plugin-transform-react-constant-elements" "^7.21.3" - "@babel/preset-env" "^7.20.2" - "@babel/preset-react" "^7.18.6" - "@babel/preset-typescript" "^7.21.0" - "@svgr/core" "8.1.0" - "@svgr/plugin-jsx" "8.1.0" - "@svgr/plugin-svgo" "8.1.0" - "@szmarczak/http-timer@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" @@ -4019,18 +3072,6 @@ autoprefixer@^10.4.12, autoprefixer@^10.4.14: picocolors "^1.0.0" postcss-value-parser "^4.2.0" -autoprefixer@^10.4.19: - version "10.4.19" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" - integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== - dependencies: - browserslist "^4.23.0" - caniuse-lite "^1.0.30001599" - fraction.js "^4.3.7" - normalize-range "^0.1.2" - picocolors "^1.0.0" - postcss-value-parser "^4.2.0" - babel-loader@^9.1.3: version "9.1.3" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" @@ -4046,15 +3087,6 @@ babel-plugin-dynamic-import-node@^2.3.3: dependencies: object.assign "^4.1.0" -babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.11" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" - integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== - dependencies: - "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.2" - semver "^6.3.1" - babel-plugin-polyfill-corejs2@^0.4.8: version "0.4.8" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz#dbcc3c8ca758a290d47c3c6a490d59429b0d2269" @@ -4064,14 +3096,6 @@ babel-plugin-polyfill-corejs2@^0.4.8: "@babel/helper-define-polyfill-provider" "^0.5.0" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.10.4: - version "0.10.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" - integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" - core-js-compat "^3.36.1" - babel-plugin-polyfill-corejs3@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz#9eea32349d94556c2ad3ab9b82ebb27d4bf04a81" @@ -4087,13 +3111,6 @@ babel-plugin-polyfill-regenerator@^0.5.5: dependencies: "@babel/helper-define-polyfill-provider" "^0.5.0" -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" - integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.2" - bail@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" @@ -4285,11 +3302,6 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001591: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001594.tgz#bea552414cd52c2d0c985ed9206314a696e685f5" integrity sha512-VblSX6nYqyJVs8DKFMldE2IVCJjZ225LW00ydtUWwh5hk9IfkTOffO6r8gJNsH0qqqeAF8KrbMYA2VEwTlGW5g== -caniuse-lite@^1.0.30001599: - version "1.0.30001629" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001629.tgz#907a36f4669031bd8a1a8dbc2fa08b29e0db297e" - integrity sha512-c3dl911slnQhmxUIT4HhYzT7wnBK/XYpGnYLOj4nJBaRiw52Ibe7YxlDaAeRECvA786zCuExhxIUJ2K7nHMrBw== - ccount@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" @@ -4466,7 +3478,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colord@^2.9.1, colord@^2.9.3: +colord@^2.9.1: version "2.9.3" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== @@ -4626,13 +3638,6 @@ core-js-compat@^3.31.0, core-js-compat@^3.34.0: dependencies: browserslist "^4.22.3" -core-js-compat@^3.36.1: - version "3.37.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" - integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== - dependencies: - browserslist "^4.23.0" - core-js-pure@^3.30.2: version "3.36.0" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.36.0.tgz#ffb34330b14e594d6a9835cf5843b4123f1d95db" @@ -4677,7 +3682,7 @@ cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" -cosmiconfig@^8.1.3, cosmiconfig@^8.3.5: +cosmiconfig@^8.3.5: version "8.3.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== @@ -4708,11 +3713,6 @@ css-declaration-sorter@^6.3.1: resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== -css-declaration-sorter@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz#6dec1c9523bc4a643e088aab8f09e67a54961024" - integrity sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow== - css-loader@^6.8.1: version "6.10.0" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.10.0.tgz#7c172b270ec7b833951b52c348861206b184a4b7" @@ -4739,18 +3739,6 @@ css-minimizer-webpack-plugin@^4.2.2: serialize-javascript "^6.0.0" source-map "^0.6.1" -css-minimizer-webpack-plugin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz#33effe662edb1a0bf08ad633c32fa75d0f7ec565" - integrity sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - cssnano "^6.0.1" - jest-worker "^29.4.3" - postcss "^8.4.24" - schema-utils "^4.0.1" - serialize-javascript "^6.0.1" - css-select@^4.1.3: version "4.3.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" @@ -4781,22 +3769,6 @@ css-tree@^1.1.2, css-tree@^1.1.3: mdn-data "2.0.14" source-map "^0.6.1" -css-tree@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" - integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== - dependencies: - mdn-data "2.0.30" - source-map-js "^1.0.1" - -css-tree@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" - integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== - dependencies: - mdn-data "2.0.28" - source-map-js "^1.0.1" - css-what@^6.0.1, css-what@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" @@ -4819,19 +3791,6 @@ cssnano-preset-advanced@^5.3.10: postcss-reduce-idents "^5.2.0" postcss-zindex "^5.1.0" -cssnano-preset-advanced@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz#82b090872b8f98c471f681d541c735acf8b94d3f" - integrity sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ== - dependencies: - autoprefixer "^10.4.19" - browserslist "^4.23.0" - cssnano-preset-default "^6.1.2" - postcss-discard-unused "^6.0.5" - postcss-merge-idents "^6.0.3" - postcss-reduce-idents "^6.0.3" - postcss-zindex "^6.0.2" - cssnano-preset-default@^5.2.14: version "5.2.14" resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz#309def4f7b7e16d71ab2438052093330d9ab45d8" @@ -4867,52 +3826,11 @@ cssnano-preset-default@^5.2.14: postcss-svgo "^5.1.0" postcss-unique-selectors "^5.1.1" -cssnano-preset-default@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz#adf4b89b975aa775f2750c89dbaf199bbd9da35e" - integrity sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg== - dependencies: - browserslist "^4.23.0" - css-declaration-sorter "^7.2.0" - cssnano-utils "^4.0.2" - postcss-calc "^9.0.1" - postcss-colormin "^6.1.0" - postcss-convert-values "^6.1.0" - postcss-discard-comments "^6.0.2" - postcss-discard-duplicates "^6.0.3" - postcss-discard-empty "^6.0.3" - postcss-discard-overridden "^6.0.2" - postcss-merge-longhand "^6.0.5" - postcss-merge-rules "^6.1.1" - postcss-minify-font-values "^6.1.0" - postcss-minify-gradients "^6.0.3" - postcss-minify-params "^6.1.0" - postcss-minify-selectors "^6.0.4" - postcss-normalize-charset "^6.0.2" - postcss-normalize-display-values "^6.0.2" - postcss-normalize-positions "^6.0.2" - postcss-normalize-repeat-style "^6.0.2" - postcss-normalize-string "^6.0.2" - postcss-normalize-timing-functions "^6.0.2" - postcss-normalize-unicode "^6.1.0" - postcss-normalize-url "^6.0.2" - postcss-normalize-whitespace "^6.0.2" - postcss-ordered-values "^6.0.2" - postcss-reduce-initial "^6.1.0" - postcss-reduce-transforms "^6.0.2" - postcss-svgo "^6.0.3" - postcss-unique-selectors "^6.0.4" - cssnano-utils@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== -cssnano-utils@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-4.0.2.tgz#56f61c126cd0f11f2eef1596239d730d9fceff3c" - integrity sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ== - cssnano@^5.1.15, cssnano@^5.1.8: version "5.1.15" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf" @@ -4922,14 +3840,6 @@ cssnano@^5.1.15, cssnano@^5.1.8: lilconfig "^2.0.3" yaml "^1.10.2" -cssnano@^6.0.1, cssnano@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-6.1.2.tgz#4bd19e505bd37ee7cf0dc902d3d869f6d79c66b8" - integrity sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA== - dependencies: - cssnano-preset-default "^6.1.2" - lilconfig "^3.1.1" - csso@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" @@ -4937,13 +3847,6 @@ csso@^4.2.0: dependencies: css-tree "^1.1.2" -csso@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" - integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== - dependencies: - css-tree "~2.2.0" - csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" @@ -5286,7 +4189,7 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deepmerge@^4.2.2, deepmerge@^4.3.1: +deepmerge@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== @@ -5987,7 +4890,7 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^11.1.1, fs-extra@^11.2.0: +fs-extra@^11.1.1: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== @@ -6888,7 +5791,7 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jest-worker@^29.1.2, jest-worker@^29.4.3: +jest-worker@^29.1.2: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== @@ -7049,11 +5952,6 @@ lilconfig@^2.0.3: resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== -lilconfig@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" - integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ== - lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -7435,16 +6333,6 @@ mdn-data@2.0.14: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== -mdn-data@2.0.28: - version "2.0.28" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" - integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== - -mdn-data@2.0.30: - version "2.0.30" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" - integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -8601,14 +7489,6 @@ postcss-calc@^8.2.3: postcss-selector-parser "^6.0.9" postcss-value-parser "^4.2.0" -postcss-calc@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" - integrity sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ== - dependencies: - postcss-selector-parser "^6.0.11" - postcss-value-parser "^4.2.0" - postcss-colormin@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f" @@ -8619,16 +7499,6 @@ postcss-colormin@^5.3.1: colord "^2.9.1" postcss-value-parser "^4.2.0" -postcss-colormin@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-6.1.0.tgz#076e8d3fb291fbff7b10e6b063be9da42ff6488d" - integrity sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw== - dependencies: - browserslist "^4.23.0" - caniuse-api "^3.0.0" - colord "^2.9.3" - postcss-value-parser "^4.2.0" - postcss-convert-values@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" @@ -8637,54 +7507,26 @@ postcss-convert-values@^5.1.3: browserslist "^4.21.4" postcss-value-parser "^4.2.0" -postcss-convert-values@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz#3498387f8efedb817cbc63901d45bd1ceaa40f48" - integrity sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w== - dependencies: - browserslist "^4.23.0" - postcss-value-parser "^4.2.0" - postcss-discard-comments@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== -postcss-discard-comments@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz#e768dcfdc33e0216380623652b0a4f69f4678b6c" - integrity sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw== - postcss-discard-duplicates@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== -postcss-discard-duplicates@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz#d121e893c38dc58a67277f75bb58ba43fce4c3eb" - integrity sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw== - postcss-discard-empty@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== -postcss-discard-empty@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz#ee39c327219bb70473a066f772621f81435a79d9" - integrity sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ== - postcss-discard-overridden@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== -postcss-discard-overridden@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz#4e9f9c62ecd2df46e8fdb44dc17e189776572e2d" - integrity sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ== - postcss-discard-unused@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz#8974e9b143d887677304e558c1166d3762501142" @@ -8692,13 +7534,6 @@ postcss-discard-unused@^5.1.0: dependencies: postcss-selector-parser "^6.0.5" -postcss-discard-unused@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz#c1b0e8c032c6054c3fbd22aaddba5b248136f338" - integrity sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA== - dependencies: - postcss-selector-parser "^6.0.16" - postcss-loader@^7.3.3: version "7.3.4" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.4.tgz#aed9b79ce4ed7e9e89e56199d25ad1ec8f606209" @@ -8716,14 +7551,6 @@ postcss-merge-idents@^5.1.1: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-merge-idents@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz#7b9c31c7bc823c94bec50f297f04e3c2b838ea65" - integrity sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g== - dependencies: - cssnano-utils "^4.0.2" - postcss-value-parser "^4.2.0" - postcss-merge-longhand@^5.1.7: version "5.1.7" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" @@ -8732,14 +7559,6 @@ postcss-merge-longhand@^5.1.7: postcss-value-parser "^4.2.0" stylehacks "^5.1.1" -postcss-merge-longhand@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz#ba8a8d473617c34a36abbea8dda2b215750a065a" - integrity sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^6.1.1" - postcss-merge-rules@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c" @@ -8750,16 +7569,6 @@ postcss-merge-rules@^5.1.4: cssnano-utils "^3.1.0" postcss-selector-parser "^6.0.5" -postcss-merge-rules@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz#7aa539dceddab56019469c0edd7d22b64c3dea9d" - integrity sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ== - dependencies: - browserslist "^4.23.0" - caniuse-api "^3.0.0" - cssnano-utils "^4.0.2" - postcss-selector-parser "^6.0.16" - postcss-minify-font-values@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" @@ -8767,13 +7576,6 @@ postcss-minify-font-values@^5.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-minify-font-values@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz#a0e574c02ee3f299be2846369211f3b957ea4c59" - integrity sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg== - dependencies: - postcss-value-parser "^4.2.0" - postcss-minify-gradients@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" @@ -8783,15 +7585,6 @@ postcss-minify-gradients@^5.1.1: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-minify-gradients@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz#ca3eb55a7bdb48a1e187a55c6377be918743dbd6" - integrity sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q== - dependencies: - colord "^2.9.3" - cssnano-utils "^4.0.2" - postcss-value-parser "^4.2.0" - postcss-minify-params@^5.1.4: version "5.1.4" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" @@ -8801,15 +7594,6 @@ postcss-minify-params@^5.1.4: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-minify-params@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz#54551dec77b9a45a29c3cb5953bf7325a399ba08" - integrity sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA== - dependencies: - browserslist "^4.23.0" - cssnano-utils "^4.0.2" - postcss-value-parser "^4.2.0" - postcss-minify-selectors@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" @@ -8817,13 +7601,6 @@ postcss-minify-selectors@^5.2.1: dependencies: postcss-selector-parser "^6.0.5" -postcss-minify-selectors@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz#197f7d72e6dd19eed47916d575d69dc38b396aff" - integrity sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ== - dependencies: - postcss-selector-parser "^6.0.16" - postcss-modules-extract-imports@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" @@ -8857,11 +7634,6 @@ postcss-normalize-charset@^5.1.0: resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== -postcss-normalize-charset@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz#1ec25c435057a8001dac942942a95ffe66f721e1" - integrity sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ== - postcss-normalize-display-values@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" @@ -8869,13 +7641,6 @@ postcss-normalize-display-values@^5.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-display-values@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz#54f02764fed0b288d5363cbb140d6950dbbdd535" - integrity sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-positions@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" @@ -8883,13 +7648,6 @@ postcss-normalize-positions@^5.1.1: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz#e982d284ec878b9b819796266f640852dbbb723a" - integrity sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-repeat-style@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" @@ -8897,13 +7655,6 @@ postcss-normalize-repeat-style@^5.1.1: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz#f8006942fd0617c73f049dd8b6201c3a3040ecf3" - integrity sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-string@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" @@ -8911,13 +7662,6 @@ postcss-normalize-string@^5.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz#e3cc6ad5c95581acd1fc8774b309dd7c06e5e363" - integrity sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-timing-functions@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" @@ -8925,13 +7669,6 @@ postcss-normalize-timing-functions@^5.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz#40cb8726cef999de984527cbd9d1db1f3e9062c0" - integrity sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-unicode@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" @@ -8940,14 +7677,6 @@ postcss-normalize-unicode@^5.1.1: browserslist "^4.21.4" postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz#aaf8bbd34c306e230777e80f7f12a4b7d27ce06e" - integrity sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg== - dependencies: - browserslist "^4.23.0" - postcss-value-parser "^4.2.0" - postcss-normalize-url@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" @@ -8956,13 +7685,6 @@ postcss-normalize-url@^5.1.0: normalize-url "^6.0.1" postcss-value-parser "^4.2.0" -postcss-normalize-url@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz#292792386be51a8de9a454cb7b5c58ae22db0f79" - integrity sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ== - dependencies: - postcss-value-parser "^4.2.0" - postcss-normalize-whitespace@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" @@ -8970,13 +7692,6 @@ postcss-normalize-whitespace@^5.1.1: dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz#fbb009e6ebd312f8b2efb225c2fcc7cf32b400cd" - integrity sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q== - dependencies: - postcss-value-parser "^4.2.0" - postcss-ordered-values@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" @@ -8985,14 +7700,6 @@ postcss-ordered-values@^5.1.3: cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-ordered-values@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz#366bb663919707093451ab70c3f99c05672aaae5" - integrity sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q== - dependencies: - cssnano-utils "^4.0.2" - postcss-value-parser "^4.2.0" - postcss-reduce-idents@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz#c89c11336c432ac4b28792f24778859a67dfba95" @@ -9000,13 +7707,6 @@ postcss-reduce-idents@^5.2.0: dependencies: postcss-value-parser "^4.2.0" -postcss-reduce-idents@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz#b0d9c84316d2a547714ebab523ec7d13704cd486" - integrity sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA== - dependencies: - postcss-value-parser "^4.2.0" - postcss-reduce-initial@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6" @@ -9015,14 +7715,6 @@ postcss-reduce-initial@^5.1.2: browserslist "^4.21.4" caniuse-api "^3.0.0" -postcss-reduce-initial@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz#4401297d8e35cb6e92c8e9586963e267105586ba" - integrity sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw== - dependencies: - browserslist "^4.23.0" - caniuse-api "^3.0.0" - postcss-reduce-transforms@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" @@ -9030,21 +7722,6 @@ postcss-reduce-transforms@^5.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-reduce-transforms@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz#6fa2c586bdc091a7373caeee4be75a0f3e12965d" - integrity sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.16: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" - integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: version "6.0.15" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535" @@ -9060,13 +7737,6 @@ postcss-sort-media-queries@^4.4.1: dependencies: sort-css-media-queries "2.1.0" -postcss-sort-media-queries@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz#4556b3f982ef27d3bac526b99b6c0d3359a6cf97" - integrity sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA== - dependencies: - sort-css-media-queries "2.2.0" - postcss-svgo@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" @@ -9075,14 +7745,6 @@ postcss-svgo@^5.1.0: postcss-value-parser "^4.2.0" svgo "^2.7.0" -postcss-svgo@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-6.0.3.tgz#1d6e180d6df1fa8a3b30b729aaa9161e94f04eaa" - integrity sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g== - dependencies: - postcss-value-parser "^4.2.0" - svgo "^3.2.0" - postcss-unique-selectors@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" @@ -9090,13 +7752,6 @@ postcss-unique-selectors@^5.1.1: dependencies: postcss-selector-parser "^6.0.5" -postcss-unique-selectors@^6.0.4: - version "6.0.4" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz#983ab308896b4bf3f2baaf2336e14e52c11a2088" - integrity sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg== - dependencies: - postcss-selector-parser "^6.0.16" - postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" @@ -9107,11 +7762,6 @@ postcss-zindex@^5.1.0: resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== -postcss-zindex@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-6.0.2.tgz#e498304b83a8b165755f53db40e2ea65a99b56e1" - integrity sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg== - postcss@^8.4.17, postcss@^8.4.21, postcss@^8.4.26, postcss@^8.4.33: version "8.4.35" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7" @@ -9121,15 +7771,6 @@ postcss@^8.4.17, postcss@^8.4.21, postcss@^8.4.26, postcss@^8.4.33: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.24, postcss@^8.4.38: - version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" - pretty-error@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" @@ -9367,13 +8008,6 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: "@types/react" "*" prop-types "^15.6.2" -"react-loadable@npm:@docusaurus/react-loadable@6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz#de6c7f73c96542bd70786b8e522d535d69069dc4" - integrity sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ== - dependencies: - "@types/react" "*" - react-router-config@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" @@ -9774,7 +8408,7 @@ schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0, schema-utils@^4.0.1: +schema-utils@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== @@ -10003,14 +8637,6 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -snake-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" - integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== - dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" - sockjs@^0.3.24: version "0.3.24" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" @@ -10025,16 +8651,6 @@ sort-css-media-queries@2.1.0: resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== -sort-css-media-queries@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz#aa33cf4a08e0225059448b6c40eddbf9f1c8334c" - integrity sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA== - -source-map-js@^1.0.1, source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" @@ -10221,14 +8837,6 @@ stylehacks@^5.1.1: browserslist "^4.21.4" postcss-selector-parser "^6.0.4" -stylehacks@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.1.1.tgz#543f91c10d17d00a440430362d419f79c25545a6" - integrity sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg== - dependencies: - browserslist "^4.23.0" - postcss-selector-parser "^6.0.16" - stylis@^4.1.3: version "4.3.1" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.1.tgz#ed8a9ebf9f76fe1e12d462f5cc3c4c980b23a7eb" @@ -10278,19 +8886,6 @@ svgo@^2.7.0, svgo@^2.8.0: picocolors "^1.0.0" stable "^0.1.8" -svgo@^3.0.2, svgo@^3.2.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.3.2.tgz#ad58002652dffbb5986fc9716afe52d869ecbda8" - integrity sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw== - dependencies: - "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^5.1.0" - css-tree "^2.3.1" - css-what "^6.1.0" - csso "^5.0.5" - picocolors "^1.0.0" - tapable@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" diff --git a/packages/prover/README.md b/packages/prover/README.md index b98340698bbe..a2a04123cd76 100644 --- a/packages/prover/README.md +++ b/packages/prover/README.md @@ -74,7 +74,7 @@ lodestar-prover proxy \ There can be different implementations of the web3 providers and each can handle the RPC request differently. We call those different provider types. We had provided builtin support for common providers e.g. web3.js, ethers or any eip1193 compatible providers. We inspect given provider instance at runtime to detect the correct provider type. -If your project is using some provider type which is not among above list, you have the option to register a custom provider type with the `createVerifiedExecutionProvider` with the option `providerTypes` which will be an array of your supported provider types. Your custom provider types will have higher priority than default provider types. Please see [existing provide types implementations](./src/provider_types/) to know how to implement your own if needed. +If your project is using some provider type which is not among above list, you have the option to register a custom provider type with the `createVerifiedExecutionProvider` with the option `providerTypes` which will be an array of your supported provider types. Your custom provider types will have higher priority than default provider types. Please see [existing provide types implementations](https://github.com/ChainSafe/lodestar/tree/unstable/packages/prover/src/provider_types) to know how to implement your own if needed. ## Supported Web3 Methods From a0f2dcce59642af44e9188e90c29cb7366d2dab3 Mon Sep 17 00:00:00 2001 From: Cayman Date: Thu, 11 Jul 2024 02:20:46 -0400 Subject: [PATCH 02/44] chore: optimize getSlotFromOffset (#6941) * chore: optimize getSlotFromOffset * chore: add perf test --- packages/beacon-node/src/util/sszBytes.ts | 23 +++++++++++---- .../test/perf/util/dataview.test.ts | 29 +++++++++++++++++++ .../test/unit/util/sszBytes.test.ts | 11 ++++++- 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 packages/beacon-node/test/perf/util/dataview.test.ts diff --git a/packages/beacon-node/src/util/sszBytes.ts b/packages/beacon-node/src/util/sszBytes.ts index 802b9a266ab1..f87b899e9591 100644 --- a/packages/beacon-node/src/util/sszBytes.ts +++ b/packages/beacon-node/src/util/sszBytes.ts @@ -198,11 +198,24 @@ export function getSlotFromBlobSidecarSerialized(data: Uint8Array): Slot | null return getSlotFromOffset(data, SLOT_BYTES_POSITION_IN_SIGNED_BLOB_SIDECAR); } -function getSlotFromOffset(data: Uint8Array, offset: number): Slot { - // TODO: Optimize - const dv = new DataView(data.buffer, data.byteOffset, data.byteLength); - // Read only the first 4 bytes of Slot, max value is 4,294,967,295 will be reached 1634 years after genesis - return dv.getUint32(offset, true); +/** + * Read only the first 4 bytes of Slot, max value is 4,294,967,295 will be reached 1634 years after genesis + * + * If the high bytes are not zero, return null + */ +function getSlotFromOffset(data: Uint8Array, offset: number): Slot | null { + return checkSlotHighBytes(data, offset) ? getSlotFromOffsetTrusted(data, offset) : null; +} + +/** + * Read only the first 4 bytes of Slot, max value is 4,294,967,295 will be reached 1634 years after genesis + */ +function getSlotFromOffsetTrusted(data: Uint8Array, offset: number): Slot { + return (data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24)) >>> 0; +} + +function checkSlotHighBytes(data: Uint8Array, offset: number): boolean { + return (data[offset + 4] | data[offset + 5] | data[offset + 6] | data[offset + 7]) === 0; } function toBase64(data: Uint8Array): string { diff --git a/packages/beacon-node/test/perf/util/dataview.test.ts b/packages/beacon-node/test/perf/util/dataview.test.ts new file mode 100644 index 000000000000..e0f28a5079e3 --- /dev/null +++ b/packages/beacon-node/test/perf/util/dataview.test.ts @@ -0,0 +1,29 @@ +import {itBench} from "@dapplion/benchmark"; + +describe("dataview", function () { + const data = Uint8Array.from([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); + + itBench({ + id: "getUint32 - dataview", + beforeEach: () => { + return 0; + }, + fn: (offset) => { + const view = new DataView(data.buffer, data.byteOffset, data.byteLength); + view.getUint32(offset, true); + }, + }); + + itBench({ + id: "getUint32 - manual", + beforeEach: () => { + return 0; + }, + fn: (offset) => { + // check high bytes for non-zero values + (data[offset + 4] | data[offset + 5] | data[offset + 6] | data[offset + 7]) === 0; + // create the uint32 + (data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24)) >>> 0; + }, + }); +}); diff --git a/packages/beacon-node/test/unit/util/sszBytes.test.ts b/packages/beacon-node/test/unit/util/sszBytes.test.ts index bb5fc67a7ce6..4285f4ca88b5 100644 --- a/packages/beacon-node/test/unit/util/sszBytes.test.ts +++ b/packages/beacon-node/test/unit/util/sszBytes.test.ts @@ -4,7 +4,7 @@ import {fromHex, toHex} from "@lodestar/utils"; import { getAttDataBase64FromAttestationSerialized, getAttDataBase64FromSignedAggregateAndProofSerialized, - getAggregationBitsFromAttestationSerialized as getAggregationBitsFromAttestationSerialized, + getAggregationBitsFromAttestationSerialized, getBlockRootFromAttestationSerialized, getBlockRootFromSignedAggregateAndProofSerialized, getSlotFromAttestationSerialized, @@ -126,6 +126,15 @@ describe("aggregateAndProof SSZ serialized picking", () => { expect(getAttDataBase64FromSignedAggregateAndProofSerialized(Buffer.alloc(size))).toBeNull(); } }); + it("getSlotFromSignedAggregateAndProofSerialized - invalid data - large slots", () => { + const serialize = (slot: Slot): Uint8Array => { + const s = ssz.phase0.SignedAggregateAndProof.defaultValue(); + s.message.aggregate.data.slot = slot; + return ssz.phase0.SignedAggregateAndProof.serialize(s); + }; + expect(getSlotFromSignedAggregateAndProofSerialized(serialize(0xffffffff))).toBe(0xffffffff); + expect(getSlotFromSignedAggregateAndProofSerialized(serialize(0x0100000000))).toBeNull(); + }); }); describe("signedBeaconBlock SSZ serialized picking", () => { From 1a35ee8971c6687a907bed2c0fbd5c1fcdf880fb Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 15 Jul 2024 15:19:58 +0100 Subject: [PATCH 03/44] feat: add option to disable thread pool for keystore decryption (#6949) --- .../keymanager/decryptKeystoreDefinitions.ts | 69 ++++++++++++++----- packages/cli/src/cmds/validator/options.ts | 8 +++ .../cli/src/cmds/validator/signers/index.ts | 2 + .../decryptKeystoreDefinitions.test.ts | 23 ++++--- 4 files changed, 77 insertions(+), 25 deletions(-) diff --git a/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts b/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts index 2901fd6cdfb5..076da70adcdb 100644 --- a/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts +++ b/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts @@ -1,5 +1,7 @@ +import fs from "node:fs"; import path from "node:path"; import bls from "@chainsafe/bls"; +import {Keystore} from "@chainsafe/bls-keystore"; import {SignerLocal, SignerType} from "@lodestar/validator"; import {LogLevel, Logger} from "@lodestar/utils"; import {lockFilepath, unlockFilepath} from "../../../util/lockfile.js"; @@ -7,11 +9,13 @@ import {LocalKeystoreDefinition} from "./interface.js"; import {clearKeystoreCache, loadKeystoreCache, writeKeystoreCache} from "./keystoreCache.js"; import {DecryptKeystoresThreadPool} from "./decryptKeystores/index.js"; -type KeystoreDecryptOptions = { +export type KeystoreDecryptOptions = { ignoreLockFile?: boolean; onDecrypt?: (index: number) => void; // Try to use the cache file if it exists cacheFilePath?: string; + /** Use main thread to decrypt keystores */ + disableThreadPool?: boolean; logger: Pick; signal: AbortSignal; }; @@ -57,14 +61,50 @@ export async function decryptKeystoreDefinitions( const signers = new Array(keystoreCount); const passwords = new Array(keystoreCount); const errors: KeystoreDecryptError[] = []; - const decryptKeystores = new DecryptKeystoresThreadPool(keystoreCount, opts.signal); - for (const [index, definition] of keystoreDefinitions.entries()) { - lockKeystore(definition.keystorePath, opts); + if (!opts.disableThreadPool) { + const decryptKeystores = new DecryptKeystoresThreadPool(keystoreCount, opts.signal); + + for (const [index, definition] of keystoreDefinitions.entries()) { + lockKeystore(definition.keystorePath, opts); + + decryptKeystores.queue( + definition, + (secretKeyBytes: Uint8Array) => { + const signer: SignerLocal = { + type: SignerType.Local, + secretKey: bls.SecretKey.fromBytes(secretKeyBytes), + }; + + signers[index] = signer; + passwords[index] = definition.password; + + if (opts?.onDecrypt) { + opts?.onDecrypt(index); + } + }, + (error: Error) => { + // In-progress tasks can't be canceled, so there's a chance that multiple errors may be caught + // add to the list of errors + errors.push({keystoreFile: path.basename(definition.keystorePath), error}); + // cancel all pending tasks, no need to continue decrypting after we hit one error + decryptKeystores.cancel(); + } + ); + } + + await decryptKeystores.completed(); + } else { + // Decrypt keystores in main thread + for (const [index, definition] of keystoreDefinitions.entries()) { + lockKeystore(definition.keystorePath, opts); + + try { + const keystore = Keystore.parse(fs.readFileSync(definition.keystorePath, "utf8")); + + // Memory-hogging function + const secretKeyBytes = await keystore.decrypt(definition.password); - decryptKeystores.queue( - definition, - (secretKeyBytes: Uint8Array) => { const signer: SignerLocal = { type: SignerType.Local, secretKey: bls.SecretKey.fromBytes(secretKeyBytes), @@ -76,19 +116,14 @@ export async function decryptKeystoreDefinitions( if (opts?.onDecrypt) { opts?.onDecrypt(index); } - }, - (error: Error) => { - // In-progress tasks can't be canceled, so there's a chance that multiple errors may be caught - // add to the list of errors - errors.push({keystoreFile: path.basename(definition.keystorePath), error}); - // cancel all pending tasks, no need to continue decrypting after we hit one error - decryptKeystores.cancel(); + } catch (e) { + errors.push({keystoreFile: path.basename(definition.keystorePath), error: e as Error}); + // stop processing, no need to continue decrypting after we hit one error + break; } - ); + } } - await decryptKeystores.completed(); - if (errors.length > 0) { // If an error occurs, the program isn't going to be running, // so we should unlock all lockfiles we created diff --git a/packages/cli/src/cmds/validator/options.ts b/packages/cli/src/cmds/validator/options.ts index 08548edb1072..fc7cb197c5aa 100644 --- a/packages/cli/src/cmds/validator/options.ts +++ b/packages/cli/src/cmds/validator/options.ts @@ -55,6 +55,7 @@ export type IValidatorCliArgs = AccountValidatorArgs & importKeystores?: string[]; importKeystoresPassword?: string; + disableKeystoresThreadPool?: boolean; "http.requestWireFormat"?: string; "http.responseWireFormat"?: string; @@ -301,6 +302,13 @@ export const validatorOptions: CliCommandOptions = { type: "string", }, + disableKeystoresThreadPool: { + hidden: true, + description: + "Disable thread pool and instead use main thread to decrypt keystores. This can speed up decryption in testing environments like Kurtosis", + type: "boolean", + }, + doppelgangerProtection: { alias: ["doppelgangerProtectionEnabled"], description: "Enables Doppelganger protection", diff --git a/packages/cli/src/cmds/validator/signers/index.ts b/packages/cli/src/cmds/validator/signers/index.ts index be028461c0ee..95daf7e69b0d 100644 --- a/packages/cli/src/cmds/validator/signers/index.ts +++ b/packages/cli/src/cmds/validator/signers/index.ts @@ -99,6 +99,7 @@ export async function getSignersFromArgs( ignoreLockFile: args.force, onDecrypt: needle, cacheFilePath: path.join(accountPaths.cacheDir, "imported_keystores.cache"), + disableThreadPool: args["disableKeystoresThreadPool"], logger, signal, }); @@ -133,6 +134,7 @@ export async function getSignersFromArgs( ignoreLockFile: args.force, onDecrypt: needle, cacheFilePath: path.join(accountPaths.cacheDir, "local_keystores.cache"), + disableThreadPool: args["disableKeystoresThreadPool"], logger, signal, }); diff --git a/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts b/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts index 8f1a82a55c3e..10f6b34bd152 100644 --- a/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts +++ b/packages/cli/test/unit/validator/decryptKeystoreDefinitions.test.ts @@ -5,7 +5,10 @@ import {rimraf} from "rimraf"; import {getKeystoresStr} from "@lodestar/test-utils"; import {cachedSeckeysHex} from "../../utils/cachedKeys.js"; import {testFilesDir} from "../../utils.js"; -import {decryptKeystoreDefinitions} from "../../../src/cmds/validator/keymanager/decryptKeystoreDefinitions.js"; +import { + decryptKeystoreDefinitions, + KeystoreDecryptOptions, +} from "../../../src/cmds/validator/keymanager/decryptKeystoreDefinitions.js"; import {LocalKeystoreDefinition} from "../../../src/cmds/validator/keymanager/interface.js"; import {LockfileError, unlockFilepath} from "../../../src/util/lockfile.js"; @@ -56,16 +59,20 @@ describe("decryptKeystoreDefinitions", () => { } }); - testDecryptKeystoreDefinitions(cacheFilePath); + testDecryptKeystoreDefinitions({cacheFilePath}); }); describe("without keystore cache", () => { testDecryptKeystoreDefinitions(); }); - function testDecryptKeystoreDefinitions(cacheFilePath?: string): void { + describe("disabled thread pool", () => { + testDecryptKeystoreDefinitions({disableThreadPool: true}); + }); + + function testDecryptKeystoreDefinitions(opts?: Partial): void { it("decrypt keystores", async () => { - const signers = await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath}); + const signers = await decryptKeystoreDefinitions(definitions, {logger: console, signal, ...opts}); expect(signers.length).toBe(secretKeys.length); for (const signer of signers) { const hexSecret = signer.secretKey.toHex(); @@ -75,11 +82,11 @@ describe("decryptKeystoreDefinitions", () => { }); it("fail to decrypt keystores if lockfiles already exist", async () => { - await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath}); + await decryptKeystoreDefinitions(definitions, {logger: console, signal, ...opts}); // lockfiles should exist after the first run try { - await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath}); + await decryptKeystoreDefinitions(definitions, {logger: console, signal, ...opts}); expect.fail("Second decrypt should fail due to failure to get lockfile"); } catch (e) { expect((e as LockfileError).code).toBe("ELOCKED"); @@ -87,10 +94,10 @@ describe("decryptKeystoreDefinitions", () => { }); it("decrypt keystores if lockfiles already exist if ignoreLockFile=true", async () => { - await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath}); + await decryptKeystoreDefinitions(definitions, {logger: console, signal, ...opts}); // lockfiles should exist after the first run - await decryptKeystoreDefinitions(definitions, {logger: console, signal, cacheFilePath, ignoreLockFile: true}); + await decryptKeystoreDefinitions(definitions, {logger: console, signal, ...opts, ignoreLockFile: true}); }); } }); From 9103f5655b05d5f74d036cec9760dc87b566163d Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 15 Jul 2024 16:19:52 +0100 Subject: [PATCH 04/44] fix: default to json if client accepts all media types (#6950) --- packages/api/src/utils/headers.ts | 7 ++++++- packages/api/src/utils/server/handler.ts | 2 +- packages/api/test/unit/utils/headers.test.ts | 10 +++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/api/src/utils/headers.ts b/packages/api/src/utils/headers.ts index 0646bb109fbb..5ef5346612fa 100644 --- a/packages/api/src/utils/headers.ts +++ b/packages/api/src/utils/headers.ts @@ -44,7 +44,12 @@ export function parseAcceptHeader(accept?: string, supported = SUPPORTED_MEDIA_T // Normalize here, using 1 as the default qvalue const quality = current.includes(";") ? current.split(";") : [current, "q=1"]; - const mediaType = quality[0].trim(); + let mediaType = quality[0].trim(); + + if (mediaType === "*/*") { + // Default to json if all media types are accepted + mediaType = MediaType.json; + } // If the mime type isn't acceptable, move on to the next entry if (!isSupportedMediaType(mediaType, supported)) { diff --git a/packages/api/src/utils/server/handler.ts b/packages/api/src/utils/server/handler.ts index 479212493885..a3cd9a43a56a 100644 --- a/packages/api/src/utils/server/handler.ts +++ b/packages/api/src/utils/server/handler.ts @@ -44,7 +44,7 @@ export function createFastifyHandler( if (definition.resp.isEmpty) { // Ignore Accept header, the response will be sent without body responseMediaType = null; - } else if (acceptHeader === undefined || acceptHeader === "*/*") { + } else if (acceptHeader === undefined) { // Default to json to not force user to set header, e.g. when using curl responseMediaType = MediaType.json; } else { diff --git a/packages/api/test/unit/utils/headers.test.ts b/packages/api/test/unit/utils/headers.test.ts index c3bcf6bc79c2..3416335b0dcd 100644 --- a/packages/api/test/unit/utils/headers.test.ts +++ b/packages/api/test/unit/utils/headers.test.ts @@ -5,13 +5,15 @@ describe("utils / headers", () => { describe("parseAcceptHeader", () => { const testCases: {header: string | undefined; expected: MediaType | null}[] = [ {header: undefined, expected: null}, - {header: "*/*", expected: null}, + {header: "*/*", expected: MediaType.json}, {header: "application/json", expected: MediaType.json}, {header: "application/octet-stream", expected: MediaType.ssz}, {header: "application/invalid", expected: null}, {header: "application/invalid;q=1,application/octet-stream;q=0.1", expected: MediaType.ssz}, {header: "application/octet-stream;q=0.5,application/json;q=1", expected: MediaType.json}, {header: "application/octet-stream;q=1,application/json;q=0.1", expected: MediaType.ssz}, + {header: "application/octet-stream;q=1,application/json;q=0.9", expected: MediaType.ssz}, + {header: "application/octet-stream;q=1,*/*;q=0.9", expected: MediaType.ssz}, {header: "application/octet-stream,application/json;q=0.1", expected: MediaType.ssz}, {header: "application/octet-stream;,application/json;q=0.1", expected: MediaType.json}, {header: "application/octet-stream;q=2,application/json;q=0.1", expected: MediaType.json}, @@ -20,6 +22,12 @@ describe("utils / headers", () => { {header: "application/octet-stream ; q=0.5 , application/json ; q=1", expected: MediaType.json}, {header: "application/octet-stream ; q=1 , application/json ; q=0.1", expected: MediaType.ssz}, {header: "application/octet-stream;q=1,application/json;q=0.1", expected: MediaType.ssz}, + { + // Default Accept header set by chrome browser + header: + "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + expected: MediaType.json, + }, // The implementation is order dependent, however, RFC-9110 doesn't specify a preference. // The following tests serve to document the behavior at the time of implementation- not a From c3d7f2fbfc1cbe318d628b32aa65dafcfdc884a9 Mon Sep 17 00:00:00 2001 From: guha-rahul <52607971+guha-rahul@users.noreply.github.com> Date: Mon, 15 Jul 2024 22:43:57 +0530 Subject: [PATCH 05/44] docs: updated Light Client url in Readme (#6948) Update README.md Corrected the lightclient prover url --- packages/light-client/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/light-client/README.md b/packages/light-client/README.md index dd00777f81b5..5d5e480afd08 100644 --- a/packages/light-client/README.md +++ b/packages/light-client/README.md @@ -26,7 +26,7 @@ Access to an beacon node that supports the light client specification is necessa - `/eth/v1/beacon/light_client/bootstrap/{block_root}` - `/eth/v0/beacon/light_client/committee_root` -System requirements are quite low so its possible to run a light client in the browser as part of a website. There are a few examples of this on github that you can use as reference, our [prover](https://chainsafe.github.io/lodestar/lightclient-prover/prover) being one of them. +System requirements are quite low so its possible to run a light client in the browser as part of a website. There are a few examples of this on github that you can use as reference, our [prover](https://chainsafe.github.io/lodestar/libraries/lightclient-prover/prover) being one of them. You can find more information about the light-client protocol in the [specification](https://github.com/ethereum/consensus-specs). From 748913579b055834ed4311c493cbf2e303b3c937 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 15 Jul 2024 20:57:45 +0100 Subject: [PATCH 06/44] fix: add workaround to fix compatibility with go-eth2-client (#6953) * fix: add workaround to fix compatibility with go-eth2-client * Skip more endpoints * Move comments around * Fix assertion --- packages/beacon-node/src/api/rest/base.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/beacon-node/src/api/rest/base.ts b/packages/beacon-node/src/api/rest/base.ts index 20439290e939..4f5d9284f91b 100644 --- a/packages/beacon-node/src/api/rest/base.ts +++ b/packages/beacon-node/src/api/rest/base.ts @@ -94,6 +94,18 @@ export class RestApiServer { const operationId = getOperationId(req); this.logger.debug(`Req ${req.id} ${req.ip} ${operationId}`); metrics?.requests.inc({operationId}); + + // Workaround to fix compatibility with go-eth2-client + // See https://github.com/attestantio/go-eth2-client/issues/144 + if ( + // go-eth2-client supports handling SSZ data in response for these endpoints + !["produceBlindedBlock", "produceBlockV3", "getBlockV2", "getStateV2"].includes(operationId) && + // Only Vouch seems to override default header + ["Go-http-client", "Vouch"].includes(req.headers["user-agent"]?.split("/")[0] ?? "") + ) { + // Override Accept header to force server to return JSON + req.headers.accept = "application/json"; + } }); server.addHook("preHandler", async (req, _res) => { From f66aae47d7a1312b41359e825bca51f017bfb32f Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 15 Jul 2024 21:01:23 +0100 Subject: [PATCH 07/44] fix: expose metadata headers to scripts running in the browser (#6952) --- packages/api/src/utils/headers.ts | 6 ++++++ packages/api/src/utils/metadata.ts | 7 +++++++ .../test/e2e/api/impl/lightclient/endpoint.test.ts | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/api/src/utils/headers.ts b/packages/api/src/utils/headers.ts index 5ef5346612fa..5f3c6e3e1dfc 100644 --- a/packages/api/src/utils/headers.ts +++ b/packages/api/src/utils/headers.ts @@ -4,6 +4,12 @@ export enum HttpHeader { ContentType = "content-type", Accept = "accept", Authorization = "authorization", + /** + * Used to indicate which response headers should be made available to + * scripts running in the browser, in response to a cross-origin request. + * https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers + */ + ExposeHeaders = "access-control-expose-headers", } export enum MediaType { diff --git a/packages/api/src/utils/metadata.ts b/packages/api/src/utils/metadata.ts index 8376113efec8..1eaa4132119f 100644 --- a/packages/api/src/utils/metadata.ts +++ b/packages/api/src/utils/metadata.ts @@ -5,6 +5,7 @@ import {StringType, ssz, stringType} from "@lodestar/types"; import {ResponseMetadataCodec} from "./types.js"; import {toBoolean} from "./serdes.js"; import {toForkName} from "./fork.js"; +import {HttpHeader} from "./headers.js"; export const VersionType = new ContainerType({ /** @@ -90,6 +91,7 @@ export const ExecutionOptimisticCodec: ResponseMetadataCodec ExecutionOptimisticType.fromJson(val), toHeadersObject: (val) => ({ [MetaHeader.ExecutionOptimistic]: val.executionOptimistic.toString(), + [HttpHeader.ExposeHeaders]: MetaHeader.ExecutionOptimistic, }), fromHeaders: (headers) => ({ executionOptimistic: toBoolean(headers.getOrDefault(MetaHeader.ExecutionOptimistic, "false")), @@ -101,6 +103,7 @@ export const VersionCodec: ResponseMetadataCodec = { fromJson: (val) => VersionType.fromJson(val), toHeadersObject: (val) => ({ [MetaHeader.Version]: val.version, + [HttpHeader.ExposeHeaders]: MetaHeader.Version, }), fromHeaders: (headers) => ({ version: toForkName(headers.getRequired(MetaHeader.Version)), @@ -113,6 +116,7 @@ export const ExecutionOptimisticAndVersionCodec: ResponseMetadataCodec ({ [MetaHeader.ExecutionOptimistic]: val.executionOptimistic.toString(), [MetaHeader.Version]: val.version, + [HttpHeader.ExposeHeaders]: [MetaHeader.ExecutionOptimistic, MetaHeader.Version].toString(), }), fromHeaders: (headers) => ({ executionOptimistic: toBoolean(headers.getOrDefault(MetaHeader.ExecutionOptimistic, "false")), @@ -126,6 +130,7 @@ export const ExecutionOptimisticAndFinalizedCodec: ResponseMetadataCodec ({ [MetaHeader.ExecutionOptimistic]: val.executionOptimistic.toString(), [MetaHeader.Finalized]: val.finalized.toString(), + [HttpHeader.ExposeHeaders]: [MetaHeader.ExecutionOptimistic, MetaHeader.Finalized].toString(), }), fromHeaders: (headers) => ({ executionOptimistic: toBoolean(headers.getOrDefault(MetaHeader.ExecutionOptimistic, "false")), @@ -141,6 +146,7 @@ export const ExecutionOptimisticFinalizedAndVersionCodec: ResponseMetadataCodec< [MetaHeader.ExecutionOptimistic]: val.executionOptimistic.toString(), [MetaHeader.Finalized]: val.finalized.toString(), [MetaHeader.Version]: val.version, + [HttpHeader.ExposeHeaders]: [MetaHeader.ExecutionOptimistic, MetaHeader.Finalized, MetaHeader.Version].toString(), }), fromHeaders: (headers) => ({ executionOptimistic: toBoolean(headers.getOrDefault(MetaHeader.ExecutionOptimistic, "false")), @@ -156,6 +162,7 @@ export const ExecutionOptimisticAndDependentRootCodec: ResponseMetadataCodec ({ [MetaHeader.ExecutionOptimistic]: val.executionOptimistic.toString(), [MetaHeader.DependentRoot]: val.dependentRoot, + [HttpHeader.ExposeHeaders]: [MetaHeader.ExecutionOptimistic, MetaHeader.DependentRoot].toString(), }), fromHeaders: (headers) => ({ executionOptimistic: toBoolean(headers.getOrDefault(MetaHeader.ExecutionOptimistic, "false")), diff --git a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts index 0f13575a5ec4..afb4863dbe44 100644 --- a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts @@ -2,7 +2,7 @@ import {describe, it, beforeEach, afterEach, expect} from "vitest"; import bls from "@chainsafe/bls"; import {createBeaconConfig, ChainConfig} from "@lodestar/config"; import {chainConfig as chainConfigDef} from "@lodestar/config/default"; -import {getClient, routes} from "@lodestar/api"; +import {getClient, HttpHeader, routes} from "@lodestar/api"; import {sleep} from "@lodestar/utils"; import {ForkName, SYNC_COMMITTEE_SIZE} from "@lodestar/params"; import {Validator} from "@lodestar/validator"; @@ -102,6 +102,8 @@ describe("lightclient api", function () { expect(update.attestedHeader.beacon.slot).toBe(slot - 1); // version is set expect(res.meta().version).toBe(ForkName.altair); + // Ensure version header is made available to scripts running in the browser + expect(res.headers.get(HttpHeader.ExposeHeaders)?.includes("Eth-Consensus-Version")).toBe(true); }); it.skip("getLightClientFinalityUpdate()", async function () { From d6175da2fa471972a469d054800d1fcf899025ee Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 16 Jul 2024 00:16:27 +0100 Subject: [PATCH 08/44] fix: update user-agent check for go-eth2-client (#6958) * fix: update user-agent check for go-eth2-client * Remove confusing comment --- packages/beacon-node/src/api/rest/base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/beacon-node/src/api/rest/base.ts b/packages/beacon-node/src/api/rest/base.ts index 4f5d9284f91b..5f191bf76beb 100644 --- a/packages/beacon-node/src/api/rest/base.ts +++ b/packages/beacon-node/src/api/rest/base.ts @@ -101,7 +101,7 @@ export class RestApiServer { // go-eth2-client supports handling SSZ data in response for these endpoints !["produceBlindedBlock", "produceBlockV3", "getBlockV2", "getStateV2"].includes(operationId) && // Only Vouch seems to override default header - ["Go-http-client", "Vouch"].includes(req.headers["user-agent"]?.split("/")[0] ?? "") + ["go-eth2-client", "Go-http-client", "Vouch"].includes(req.headers["user-agent"]?.split("/")[0] ?? "") ) { // Override Accept header to force server to return JSON req.headers.accept = "application/json"; From 79380f0961cf7c02a9466a0ce6d47b448023ca4d Mon Sep 17 00:00:00 2001 From: Cayman Date: Mon, 15 Jul 2024 21:46:34 -0400 Subject: [PATCH 09/44] chore: decompose AttesterStatus (#6945) * chore: separate epoch transition cache flags * chore: refactor active epoch indices * chore: use number[] for flags * chore: fully decompose AttesterStatus * chore: fix lint * chore: reuse epoch transition cache arrays * chore: add isActivePrevEpoch to metrics * chore: remove dead code * chore: refactor * chore: fix up perf tests * chore: add functions back --- .../src/chain/rewards/attestationsRewards.ts | 14 +- .../src/metrics/validatorMonitor.ts | 39 +++-- .../src/cache/epochTransitionCache.ts | 138 +++++++++++++----- .../src/epoch/getAttestationDeltas.ts | 24 +-- .../src/epoch/getRewardsAndPenalties.ts | 18 +-- .../src/epoch/processInactivityUpdates.ts | 8 +- .../src/epoch/processPendingAttestations.ts | 22 +-- packages/state-transition/src/metrics.ts | 10 +- .../state-transition/src/stateTransition.ts | 12 +- .../src/util/attesterStatus.ts | 53 +++---- .../test/perf/analyzeEpochs.ts | 4 +- .../test/perf/epoch/array.test.ts | 60 ++++++++ .../test/perf/epoch/utilPhase0.ts | 47 +++--- 13 files changed, 287 insertions(+), 162 deletions(-) create mode 100644 packages/state-transition/test/perf/epoch/array.test.ts diff --git a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts b/packages/beacon-node/src/chain/rewards/attestationsRewards.ts index 3b4583826349..e909e4b1b57e 100644 --- a/packages/beacon-node/src/chain/rewards/attestationsRewards.ts +++ b/packages/beacon-node/src/chain/rewards/attestationsRewards.ts @@ -140,7 +140,7 @@ function computeTotalAttestationsRewardsAltair( validatorIds: (ValidatorIndex | string)[] = [] ): TotalAttestationsReward[] { const rewards = []; - const {statuses} = transitionCache; + const {flags} = transitionCache; const {epochCtx, config} = state; const validatorIndices = validatorIds .map((id) => (typeof id === "number" ? id : epochCtx.pubkey2index.get(id))) @@ -148,13 +148,13 @@ function computeTotalAttestationsRewardsAltair( const inactivityPenaltyDenominator = config.INACTIVITY_SCORE_BIAS * INACTIVITY_PENALTY_QUOTIENT_ALTAIR; - for (let i = 0; i < statuses.length; i++) { + for (let i = 0; i < flags.length; i++) { if (validatorIndices.length && !validatorIndices.includes(i)) { continue; } - const status = statuses[i]; - if (!hasMarkers(status.flags, FLAG_ELIGIBLE_ATTESTER)) { + const flag = flags[i]; + if (!hasMarkers(flag, FLAG_ELIGIBLE_ATTESTER)) { continue; } @@ -162,13 +162,13 @@ function computeTotalAttestationsRewardsAltair( const currentRewards = {...defaultAttestationsReward, validatorIndex: i}; - if (hasMarkers(status.flags, FLAG_PREV_SOURCE_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_SOURCE_ATTESTER_UNSLASHED)) { currentRewards.source = idealRewards[effectiveBalanceIncrement].source; } else { currentRewards.source = penalties[effectiveBalanceIncrement].source * -1; // Negative reward to indicate penalty } - if (hasMarkers(status.flags, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { currentRewards.target = idealRewards[effectiveBalanceIncrement].target; } else { currentRewards.target = penalties[effectiveBalanceIncrement].target * -1; @@ -179,7 +179,7 @@ function computeTotalAttestationsRewardsAltair( currentRewards.inactivity = Math.floor(inactivityPenaltyNumerator / inactivityPenaltyDenominator) * -1; } - if (hasMarkers(status.flags, FLAG_PREV_HEAD_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_HEAD_ATTESTER_UNSLASHED)) { currentRewards.head = idealRewards[effectiveBalanceIncrement].head; } diff --git a/packages/beacon-node/src/metrics/validatorMonitor.ts b/packages/beacon-node/src/metrics/validatorMonitor.ts index a9d783786e88..e5c8eef83679 100644 --- a/packages/beacon-node/src/metrics/validatorMonitor.ts +++ b/packages/beacon-node/src/metrics/validatorMonitor.ts @@ -1,6 +1,5 @@ import { computeEpochAtSlot, - AttesterStatus, parseAttesterFlags, CachedBeaconStateAllForks, CachedBeaconStateAltair, @@ -39,7 +38,14 @@ export enum OpSource { export type ValidatorMonitor = { registerLocalValidator(index: number): void; registerLocalValidatorInSyncCommittee(index: number, untilEpoch: Epoch): void; - registerValidatorStatuses(currentEpoch: Epoch, statuses: AttesterStatus[], balances?: number[]): void; + registerValidatorStatuses( + currentEpoch: Epoch, + inclusionDelays: number[], + flags: number[], + isActiveCurrEpoch: boolean[], + isActivePrevEpoch: boolean[], + balances?: number[] + ): void; registerBeaconBlock(src: OpSource, seenTimestampSec: Seconds, block: BeaconBlock): void; registerBlobSidecar(src: OpSource, seenTimestampSec: Seconds, blob: deneb.BlobSidecar): void; registerImportedBlock(block: BeaconBlock, data: {proposerBalanceDelta: number}): void; @@ -115,12 +121,17 @@ type ValidatorStatus = { inclusionDistance: number; }; -function statusToSummary(status: AttesterStatus): ValidatorStatus { - const flags = parseAttesterFlags(status.flags); +function statusToSummary( + inclusionDelay: number, + flag: number, + isActiveInCurrentEpoch: boolean, + isActiveInPreviousEpoch: boolean +): ValidatorStatus { + const flags = parseAttesterFlags(flag); return { isSlashed: flags.unslashed, - isActiveInCurrentEpoch: status.active, - isActiveInPreviousEpoch: status.active, + isActiveInCurrentEpoch, + isActiveInPreviousEpoch, // TODO: Implement currentEpochEffectiveBalance: 0, @@ -130,7 +141,7 @@ function statusToSummary(status: AttesterStatus): ValidatorStatus { isCurrSourceAttester: flags.currSourceAttester, isCurrTargetAttester: flags.currTargetAttester, isCurrHeadAttester: flags.currHeadAttester, - inclusionDistance: status.inclusionDelay, + inclusionDistance: inclusionDelay, }; } @@ -287,7 +298,7 @@ export function createValidatorMonitor( } }, - registerValidatorStatuses(currentEpoch, statuses, balances) { + registerValidatorStatuses(currentEpoch, inclusionDelays, flags, isActiveCurrEpoch, isActiveInPrevEpoch, balances) { // Prevent registering status for the same epoch twice. processEpoch() may be ran more than once for the same epoch. if (currentEpoch <= lastRegisteredStatusEpoch) { return; @@ -301,12 +312,12 @@ export function createValidatorMonitor( // - One to account for it being the previous epoch. // - One to account for the state advancing an epoch whilst generating the validator // statuses. - const status = statuses[index]; - if (status === undefined) { - continue; - } - - const summary = statusToSummary(status); + const summary = statusToSummary( + inclusionDelays[index], + flags[index], + isActiveCurrEpoch[index], + isActiveInPrevEpoch[index] + ); if (summary.isPrevSourceAttester) { metrics.validatorMonitor.prevEpochOnChainSourceAttesterHit.inc(); diff --git a/packages/state-transition/src/cache/epochTransitionCache.ts b/packages/state-transition/src/cache/epochTransitionCache.ts index dc4edf26e084..dfe6bdd8e102 100644 --- a/packages/state-transition/src/cache/epochTransitionCache.ts +++ b/packages/state-transition/src/cache/epochTransitionCache.ts @@ -3,8 +3,6 @@ import {intDiv} from "@lodestar/utils"; import {EPOCHS_PER_SLASHINGS_VECTOR, FAR_FUTURE_EPOCH, ForkSeq, MAX_EFFECTIVE_BALANCE} from "@lodestar/params"; import { - AttesterStatus, - createAttesterStatus, hasMarkers, FLAG_UNSLASHED, FLAG_ELIGIBLE_ATTESTER, @@ -128,7 +126,12 @@ export interface EpochTransitionCache { * - prev attester flag set * With a status flag to check this conditions at once we just have to mask with an OR of the conditions. */ - statuses: AttesterStatus[]; + + proposerIndices: number[]; + + inclusionDelays: number[]; + + flags: number[]; /** * balances array will be populated by processRewardsAndPenalties() and consumed by processEffectiveBalanceUpdates(). @@ -161,6 +164,18 @@ export interface EpochTransitionCache { */ nextEpochTotalActiveBalanceByIncrement: number; + /** + * Track by validator index if it's active in the prev epoch. + * Used in metrics + */ + isActivePrevEpoch: boolean[]; + + /** + * Track by validator index if it's active in the current epoch. + * Used in metrics + */ + isActiveCurrEpoch: boolean[]; + /** * Track by validator index if it's active in the next epoch. * Used in `processEffectiveBalanceUpdates` to save one loop over validators after epoch process. @@ -168,6 +183,21 @@ export interface EpochTransitionCache { isActiveNextEpoch: boolean[]; } +// reuse arrays to avoid memory reallocation and gc +// WARNING: this is not async safe +/** WARNING: reused, never gc'd */ +const isActivePrevEpoch = new Array(); +/** WARNING: reused, never gc'd */ +const isActiveCurrEpoch = new Array(); +/** WARNING: reused, never gc'd */ +const isActiveNextEpoch = new Array(); +/** WARNING: reused, never gc'd */ +const proposerIndices = new Array(); +/** WARNING: reused, never gc'd */ +const inclusionDelays = new Array(); +/** WARNING: reused, never gc'd */ +const flags = new Array(); + export function beforeProcessEpoch( state: CachedBeaconStateAllForks, opts?: EpochTransitionCacheOpts @@ -188,9 +218,6 @@ export function beforeProcessEpoch( const indicesEligibleForActivation: ValidatorIndex[] = []; const indicesToEject: ValidatorIndex[] = []; const nextEpochShufflingActiveValidatorIndices: ValidatorIndex[] = []; - const isActivePrevEpoch: boolean[] = []; - const isActiveNextEpoch: boolean[] = []; - const statuses: AttesterStatus[] = []; let totalActiveStakeByIncrement = 0; @@ -200,6 +227,32 @@ export function beforeProcessEpoch( const validators = state.validators.getAllReadonlyValues(); const validatorCount = validators.length; + // pre-fill with true (most validators are active) + isActivePrevEpoch.length = validatorCount; + isActiveCurrEpoch.length = validatorCount; + isActiveNextEpoch.length = validatorCount; + isActivePrevEpoch.fill(true); + isActiveCurrEpoch.fill(true); + isActiveNextEpoch.fill(true); + + // During the epoch transition, additional data is precomputed to avoid traversing any state a second + // time. Attestations are a big part of this, and each validator has a "status" to represent its + // precomputed participation. + // - proposerIndex: number; // -1 when not included by any proposer + // - inclusionDelay: number; + // - flags: number; // bitfield of AttesterFlags + proposerIndices.length = validatorCount; + inclusionDelays.length = validatorCount; + flags.length = validatorCount; + proposerIndices.fill(-1); + inclusionDelays.fill(0); + // flags.fill(0); + // flags will be zero'd out below + // In the first loop, set slashed+eligibility + // In the second loop, set participation flags + // TODO: optimize by combining the two loops + // likely will require splitting into phase0 and post-phase0 versions + // Clone before being mutated in processEffectiveBalanceUpdates epochCtx.beforeEpochTransition(); @@ -207,14 +260,14 @@ export function beforeProcessEpoch( for (let i = 0; i < validatorCount; i++) { const validator = validators[i]; - const status = createAttesterStatus(); + let flag = 0; if (validator.slashed) { if (slashingsEpoch === validator.withdrawableEpoch) { indicesToSlash.push(i); } } else { - status.flags |= FLAG_UNSLASHED; + flag |= FLAG_UNSLASHED; } const {activationEpoch, exitEpoch} = validator; @@ -223,19 +276,24 @@ export function beforeProcessEpoch( const isActiveNext = activationEpoch <= nextEpoch && nextEpoch < exitEpoch; const isActiveNext2 = activationEpoch <= nextEpoch2 && nextEpoch2 < exitEpoch; - isActivePrevEpoch.push(isActivePrev); + if (!isActivePrev) { + isActivePrevEpoch[i] = false; + } // Both active validators and slashed-but-not-yet-withdrawn validators are eligible to receive penalties. // This is done to prevent self-slashing from being a way to escape inactivity leaks. // TODO: Consider using an array of `eligibleValidatorIndices: number[]` if (isActivePrev || (validator.slashed && prevEpoch + 1 < validator.withdrawableEpoch)) { eligibleValidatorIndices.push(i); - status.flags |= FLAG_ELIGIBLE_ATTESTER; + flag |= FLAG_ELIGIBLE_ATTESTER; } + flags[i] = flag; + if (isActiveCurr) { - status.active = true; totalActiveStakeByIncrement += effectiveBalancesByIncrements[i]; + } else { + isActiveCurrEpoch[i] = false; } // To optimize process_registry_updates(): @@ -278,16 +336,16 @@ export function beforeProcessEpoch( // // Use `else` since indicesEligibleForActivationQueue + indicesEligibleForActivation + indicesToEject are mutually exclusive else if ( - status.active && + isActiveCurr && validator.exitEpoch === FAR_FUTURE_EPOCH && validator.effectiveBalance <= config.EJECTION_BALANCE ) { indicesToEject.push(i); } - statuses.push(status); - - isActiveNextEpoch.push(isActiveNext); + if (!isActiveNext) { + isActiveNextEpoch[i] = false; + } if (isActiveNext2) { nextEpochShufflingActiveValidatorIndices.push(i); @@ -312,7 +370,9 @@ export function beforeProcessEpoch( if (forkSeq === ForkSeq.phase0) { processPendingAttestations( state as CachedBeaconStatePhase0, - statuses, + proposerIndices, + inclusionDelays, + flags, (state as CachedBeaconStatePhase0).previousEpochAttestations.getAllReadonly(), prevEpoch, FLAG_PREV_SOURCE_ATTESTER, @@ -321,7 +381,9 @@ export function beforeProcessEpoch( ); processPendingAttestations( state as CachedBeaconStatePhase0, - statuses, + proposerIndices, + inclusionDelays, + flags, (state as CachedBeaconStatePhase0).currentEpochAttestations.getAllReadonly(), currentEpoch, FLAG_CURR_SOURCE_ATTESTER, @@ -330,23 +392,15 @@ export function beforeProcessEpoch( ); } else { const previousEpochParticipation = (state as CachedBeaconStateAltair).previousEpochParticipation.getAll(); - for (let i = 0; i < previousEpochParticipation.length; i++) { - const status = statuses[i]; - // this is required to pass random spec tests in altair - if (isActivePrevEpoch[i]) { - // FLAG_PREV are indexes [0,1,2] - status.flags |= previousEpochParticipation[i]; - } - } - const currentEpochParticipation = (state as CachedBeaconStateAltair).currentEpochParticipation.getAll(); - for (let i = 0; i < currentEpochParticipation.length; i++) { - const status = statuses[i]; - // this is required to pass random spec tests in altair - if (status.active) { - // FLAG_PREV are indexes [3,4,5], so shift by 3 - status.flags |= currentEpochParticipation[i] << 3; - } + for (let i = 0; i < validatorCount; i++) { + flags[i] |= + // checking active status first is required to pass random spec tests in altair + // in practice, inactive validators will have 0 participation + // FLAG_PREV are indexes [0,1,2] + (isActivePrevEpoch[i] ? previousEpochParticipation[i] : 0) | + // FLAG_CURR are indexes [3,4,5], so shift by 3 + (isActiveCurrEpoch[i] ? currentEpochParticipation[i] << 3 : 0); } } @@ -361,19 +415,19 @@ export function beforeProcessEpoch( const FLAG_PREV_HEAD_ATTESTER_UNSLASHED = FLAG_PREV_HEAD_ATTESTER | FLAG_UNSLASHED; const FLAG_CURR_TARGET_UNSLASHED = FLAG_CURR_TARGET_ATTESTER | FLAG_UNSLASHED; - for (let i = 0; i < statuses.length; i++) { - const status = statuses[i]; + for (let i = 0; i < validatorCount; i++) { const effectiveBalanceByIncrement = effectiveBalancesByIncrements[i]; - if (hasMarkers(status.flags, FLAG_PREV_SOURCE_ATTESTER_UNSLASHED)) { + const flag = flags[i]; + if (hasMarkers(flag, FLAG_PREV_SOURCE_ATTESTER_UNSLASHED)) { prevSourceUnslStake += effectiveBalanceByIncrement; } - if (hasMarkers(status.flags, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { prevTargetUnslStake += effectiveBalanceByIncrement; } - if (hasMarkers(status.flags, FLAG_PREV_HEAD_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_HEAD_ATTESTER_UNSLASHED)) { prevHeadUnslStake += effectiveBalanceByIncrement; } - if (hasMarkers(status.flags, FLAG_CURR_TARGET_UNSLASHED)) { + if (hasMarkers(flag, FLAG_CURR_TARGET_UNSLASHED)) { currTargetUnslStake += effectiveBalanceByIncrement; } } @@ -421,8 +475,12 @@ export function beforeProcessEpoch( nextEpochShufflingActiveValidatorIndices, // to be updated in processEffectiveBalanceUpdates nextEpochTotalActiveBalanceByIncrement: 0, + isActivePrevEpoch, + isActiveCurrEpoch, isActiveNextEpoch, - statuses, + proposerIndices, + inclusionDelays, + flags, // Will be assigned in processRewardsAndPenalties() balances: undefined, diff --git a/packages/state-transition/src/epoch/getAttestationDeltas.ts b/packages/state-transition/src/epoch/getAttestationDeltas.ts index 94d08b5d8ec6..dd69738a55b5 100644 --- a/packages/state-transition/src/epoch/getAttestationDeltas.ts +++ b/packages/state-transition/src/epoch/getAttestationDeltas.ts @@ -52,7 +52,8 @@ export function getAttestationDeltas( state: CachedBeaconStatePhase0, cache: EpochTransitionCache ): [number[], number[]] { - const validatorCount = cache.statuses.length; + const {flags, proposerIndices, inclusionDelays} = cache; + const validatorCount = flags.length; const rewards = newZeroedArray(validatorCount); const penalties = newZeroedArray(validatorCount); @@ -77,12 +78,11 @@ export function getAttestationDeltas( // effectiveBalance is multiple of EFFECTIVE_BALANCE_INCREMENT and less than MAX_EFFECTIVE_BALANCE // so there are limited values of them like 32, 31, 30 const rewardPnaltyItemCache = new Map(); - const {statuses} = cache; const {effectiveBalanceIncrements} = state.epochCtx; - for (let i = 0; i < statuses.length; i++) { + for (let i = 0; i < flags.length; i++) { + const flag = flags[i]; const effectiveBalanceIncrement = effectiveBalanceIncrements[i]; const effectiveBalance = effectiveBalanceIncrement * EFFECTIVE_BALANCE_INCREMENT; - const status = statuses[i]; let rewardItem = rewardPnaltyItemCache.get(effectiveBalanceIncrement); if (!rewardItem) { @@ -121,14 +121,14 @@ export function getAttestationDeltas( } = rewardItem; // inclusion speed bonus - if (hasMarkers(status.flags, FLAG_PREV_SOURCE_ATTESTER_OR_UNSLASHED)) { - rewards[status.proposerIndex] += proposerReward; - rewards[i] += Math.floor(maxAttesterReward / status.inclusionDelay); + if (hasMarkers(flag, FLAG_PREV_SOURCE_ATTESTER_OR_UNSLASHED)) { + rewards[proposerIndices[i]] += proposerReward; + rewards[i] += Math.floor(maxAttesterReward / inclusionDelays[i]); } - if (hasMarkers(status.flags, FLAG_ELIGIBLE_ATTESTER)) { + if (hasMarkers(flag, FLAG_ELIGIBLE_ATTESTER)) { // expected FFG source - if (hasMarkers(status.flags, FLAG_PREV_SOURCE_ATTESTER_OR_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_SOURCE_ATTESTER_OR_UNSLASHED)) { // justification-participation reward rewards[i] += sourceCheckpointReward; } else { @@ -137,7 +137,7 @@ export function getAttestationDeltas( } // expected FFG target - if (hasMarkers(status.flags, FLAG_PREV_TARGET_ATTESTER_OR_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_TARGET_ATTESTER_OR_UNSLASHED)) { // boundary-attestation reward rewards[i] += targetCheckpointReward; } else { @@ -146,7 +146,7 @@ export function getAttestationDeltas( } // expected head - if (hasMarkers(status.flags, FLAG_PREV_HEAD_ATTESTER_OR_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_HEAD_ATTESTER_OR_UNSLASHED)) { // canonical-participation reward rewards[i] += headReward; } else { @@ -158,7 +158,7 @@ export function getAttestationDeltas( if (isInInactivityLeak) { penalties[i] += basePenalty; - if (!hasMarkers(status.flags, FLAG_PREV_TARGET_ATTESTER_OR_UNSLASHED)) { + if (!hasMarkers(flag, FLAG_PREV_TARGET_ATTESTER_OR_UNSLASHED)) { penalties[i] += finalityDelayPenalty; } } diff --git a/packages/state-transition/src/epoch/getRewardsAndPenalties.ts b/packages/state-transition/src/epoch/getRewardsAndPenalties.ts index dcffe986e0bb..bf766fe4666a 100644 --- a/packages/state-transition/src/epoch/getRewardsAndPenalties.ts +++ b/packages/state-transition/src/epoch/getRewardsAndPenalties.ts @@ -29,7 +29,7 @@ type RewardPenaltyItem = { }; /** - * An aggregate of getFlagIndexDeltas and getInactivityPenaltyDeltas that loop through process.statuses 1 time instead of 4. + * An aggregate of getFlagIndexDeltas and getInactivityPenaltyDeltas that loop through process.flags 1 time instead of 4. * * - On normal mainnet conditions * - prevSourceAttester: 98% @@ -62,10 +62,10 @@ export function getRewardsAndPenaltiesAltair( fork === ForkSeq.altair ? INACTIVITY_PENALTY_QUOTIENT_ALTAIR : INACTIVITY_PENALTY_QUOTIENT_BELLATRIX; const penaltyDenominator = config.INACTIVITY_SCORE_BIAS * inactivityPenalityMultiplier; - const {statuses} = cache; - for (let i = 0; i < statuses.length; i++) { - const status = statuses[i]; - if (!hasMarkers(status.flags, FLAG_ELIGIBLE_ATTESTER)) { + const {flags} = cache; + for (let i = 0; i < flags.length; i++) { + const flag = flags[i]; + if (!hasMarkers(flag, FLAG_ELIGIBLE_ATTESTER)) { continue; } @@ -98,7 +98,7 @@ export function getRewardsAndPenaltiesAltair( rewardPenaltyItem; // same logic to getFlagIndexDeltas - if (hasMarkers(status.flags, FLAG_PREV_SOURCE_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_SOURCE_ATTESTER_UNSLASHED)) { if (!isInInactivityLeakBn) { rewards[i] += timelySourceReward; } @@ -106,7 +106,7 @@ export function getRewardsAndPenaltiesAltair( penalties[i] += timelySourcePenalty; } - if (hasMarkers(status.flags, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { if (!isInInactivityLeakBn) { rewards[i] += timelyTargetReward; } @@ -114,7 +114,7 @@ export function getRewardsAndPenaltiesAltair( penalties[i] += timelyTargetPenalty; } - if (hasMarkers(status.flags, FLAG_PREV_HEAD_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_HEAD_ATTESTER_UNSLASHED)) { if (!isInInactivityLeakBn) { rewards[i] += timelyHeadReward; } @@ -122,7 +122,7 @@ export function getRewardsAndPenaltiesAltair( // Same logic to getInactivityPenaltyDeltas // TODO: if we have limited value in inactivityScores we can provide a cache too - if (!hasMarkers(status.flags, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { + if (!hasMarkers(flag, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { const penaltyNumerator = effectiveBalanceIncrement * EFFECTIVE_BALANCE_INCREMENT * state.inactivityScores.get(i); penalties[i] += Math.floor(penaltyNumerator / penaltyDenominator); } diff --git a/packages/state-transition/src/epoch/processInactivityUpdates.ts b/packages/state-transition/src/epoch/processInactivityUpdates.ts index 5a84f9a48b66..aedb077d6bbe 100644 --- a/packages/state-transition/src/epoch/processInactivityUpdates.ts +++ b/packages/state-transition/src/epoch/processInactivityUpdates.ts @@ -4,7 +4,7 @@ import * as attesterStatusUtil from "../util/attesterStatus.js"; import {isInInactivityLeak} from "../util/index.js"; /** - * Mutates `inactivityScores` from pre-calculated validator statuses. + * Mutates `inactivityScores` from pre-calculated validator flags. * * PERF: Cost = iterate over an array of size $VALIDATOR_COUNT + 'proportional' to how many validtors are inactive or * have been inactive in the past, i.e. that require an update to their inactivityScore. Worst case = all validators @@ -24,7 +24,7 @@ export function processInactivityUpdates(state: CachedBeaconStateAltair, cache: const {config, inactivityScores} = state; const {INACTIVITY_SCORE_BIAS, INACTIVITY_SCORE_RECOVERY_RATE} = config; - const {statuses, eligibleValidatorIndices} = cache; + const {flags, eligibleValidatorIndices} = cache; const inActivityLeak = isInInactivityLeak(state); // this avoids importing FLAG_ELIGIBLE_ATTESTER inside the for loop, check the compiled code @@ -34,11 +34,11 @@ export function processInactivityUpdates(state: CachedBeaconStateAltair, cache: for (let j = 0; j < eligibleValidatorIndices.length; j++) { const i = eligibleValidatorIndices[j]; - const status = statuses[i]; + const flag = flags[i]; let inactivityScore = inactivityScoresArr[i]; const prevInactivityScore = inactivityScore; - if (hasMarkers(status.flags, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { + if (hasMarkers(flag, FLAG_PREV_TARGET_ATTESTER_UNSLASHED)) { inactivityScore -= Math.min(1, inactivityScore); } else { inactivityScore += INACTIVITY_SCORE_BIAS; diff --git a/packages/state-transition/src/epoch/processPendingAttestations.ts b/packages/state-transition/src/epoch/processPendingAttestations.ts index 8f68e9735036..a6043be77524 100644 --- a/packages/state-transition/src/epoch/processPendingAttestations.ts +++ b/packages/state-transition/src/epoch/processPendingAttestations.ts @@ -1,10 +1,10 @@ import {byteArrayEquals} from "@chainsafe/ssz"; import {Epoch, phase0} from "@lodestar/types"; import {CachedBeaconStatePhase0} from "../types.js"; -import {computeStartSlotAtEpoch, getBlockRootAtSlot, AttesterStatus} from "../util/index.js"; +import {computeStartSlotAtEpoch, getBlockRootAtSlot} from "../util/index.js"; /** - * Mutates `statuses` from all pending attestations. + * Mutates `proposerIndices`, `inclusionDelays` and `flags` from all pending attestations. * * PERF: Cost 'proportional' to attestation count + how many bits per attestation + how many flags the attestation triggers * @@ -16,7 +16,9 @@ import {computeStartSlotAtEpoch, getBlockRootAtSlot, AttesterStatus} from "../ut */ export function processPendingAttestations( state: CachedBeaconStatePhase0, - statuses: AttesterStatus[], + proposerIndices: number[], + inclusionDelays: number[], + flags: number[], attestations: phase0.PendingAttestation[], epoch: Epoch, sourceFlag: number, @@ -53,21 +55,19 @@ export function processPendingAttestations( if (epoch === prevEpoch) { for (const p of participants) { - const status = statuses[p]; - if (status.proposerIndex === -1 || status.inclusionDelay > inclusionDelay) { - status.proposerIndex = proposerIndex; - status.inclusionDelay = inclusionDelay; + if (proposerIndices[p] === -1 || inclusionDelays[p] > inclusionDelay) { + proposerIndices[p] = proposerIndex; + inclusionDelays[p] = inclusionDelay; } } } for (const p of participants) { - const status = statuses[p]; - status.flags |= sourceFlag; + flags[p] |= sourceFlag; if (attVotedTargetRoot) { - status.flags |= targetFlag; + flags[p] |= targetFlag; if (attVotedHeadRoot) { - status.flags |= headFlag; + flags[p] |= headFlag; } } } diff --git a/packages/state-transition/src/metrics.ts b/packages/state-transition/src/metrics.ts index 62062bbfc539..12cec46d9a49 100644 --- a/packages/state-transition/src/metrics.ts +++ b/packages/state-transition/src/metrics.ts @@ -2,7 +2,6 @@ import {Epoch} from "@lodestar/types"; import {Gauge, Histogram} from "@lodestar/utils"; import {CachedBeaconStateAllForks} from "./types.js"; import {StateCloneSource, StateHashTreeRootSource} from "./stateTransition.js"; -import {AttesterStatus} from "./util/attesterStatus.js"; import {EpochTransitionStep} from "./epoch/index.js"; export type BeaconStateTransitionMetrics = { @@ -21,7 +20,14 @@ export type BeaconStateTransitionMetrics = { postStateBalancesNodesPopulatedHit: Gauge; postStateValidatorsNodesPopulatedMiss: Gauge; postStateValidatorsNodesPopulatedHit: Gauge; - registerValidatorStatuses: (currentEpoch: Epoch, statuses: AttesterStatus[], balances?: number[]) => void; + registerValidatorStatuses: ( + currentEpoch: Epoch, + inclusionDelays: number[], + flags: number[], + isActiveCurrEpoch: boolean[], + isActivePrevEpoch: boolean[], + balances?: number[] + ) => void; }; export function onStateCloneMetrics( diff --git a/packages/state-transition/src/stateTransition.ts b/packages/state-transition/src/stateTransition.ts index 7602f4d9acc2..78bcaa140c62 100644 --- a/packages/state-transition/src/stateTransition.ts +++ b/packages/state-transition/src/stateTransition.ts @@ -195,8 +195,16 @@ function processSlotsWithTransientCache( processEpoch(fork, postState, epochTransitionCache, metrics); - const {currentEpoch, statuses, balances} = epochTransitionCache; - metrics?.registerValidatorStatuses(currentEpoch, statuses, balances); + const {currentEpoch, inclusionDelays, flags, isActiveCurrEpoch, isActivePrevEpoch, balances} = + epochTransitionCache; + metrics?.registerValidatorStatuses( + currentEpoch, + inclusionDelays, + flags, + isActiveCurrEpoch, + isActivePrevEpoch, + balances + ); postState.slot++; diff --git a/packages/state-transition/src/util/attesterStatus.ts b/packages/state-transition/src/util/attesterStatus.ts index 4f746615cbec..effacef47e06 100644 --- a/packages/state-transition/src/util/attesterStatus.ts +++ b/packages/state-transition/src/util/attesterStatus.ts @@ -1,45 +1,27 @@ import {TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX} from "@lodestar/params"; -export const FLAG_PREV_SOURCE_ATTESTER = 1 << 0; -export const FLAG_PREV_TARGET_ATTESTER = 1 << 1; -export const FLAG_PREV_HEAD_ATTESTER = 1 << 2; -export const FLAG_CURR_SOURCE_ATTESTER = 1 << 3; -export const FLAG_CURR_TARGET_ATTESTER = 1 << 4; -export const FLAG_CURR_HEAD_ATTESTER = 1 << 5; +// We pack both previous and current epoch attester flags +// as well as slashed and eligibility flags into a single number +// to save space in our epoch transition cache. +// Note: the order of the flags is important for efficiently translating +// from the BeaconState flags to our flags. +// [prevSource, prevTarget, prevHead, currSource, currTarget, currHead, unslashed, eligible] +export const FLAG_PREV_SOURCE_ATTESTER = 1 << TIMELY_SOURCE_FLAG_INDEX; +export const FLAG_PREV_TARGET_ATTESTER = 1 << TIMELY_TARGET_FLAG_INDEX; +export const FLAG_PREV_HEAD_ATTESTER = 1 << TIMELY_HEAD_FLAG_INDEX; + +export const FLAG_CURR_SOURCE_ATTESTER = 1 << (3 + TIMELY_SOURCE_FLAG_INDEX); +export const FLAG_CURR_TARGET_ATTESTER = 1 << (3 + TIMELY_TARGET_FLAG_INDEX); +export const FLAG_CURR_HEAD_ATTESTER = 1 << (3 + TIMELY_HEAD_FLAG_INDEX); export const FLAG_UNSLASHED = 1 << 6; export const FLAG_ELIGIBLE_ATTESTER = 1 << 7; -// Precompute OR flags + +// Precompute OR flags used in epoch processing export const FLAG_PREV_SOURCE_ATTESTER_UNSLASHED = FLAG_PREV_SOURCE_ATTESTER | FLAG_UNSLASHED; export const FLAG_PREV_TARGET_ATTESTER_UNSLASHED = FLAG_PREV_TARGET_ATTESTER | FLAG_UNSLASHED; export const FLAG_PREV_HEAD_ATTESTER_UNSLASHED = FLAG_PREV_HEAD_ATTESTER | FLAG_UNSLASHED; -/** 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 TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX; -const TIMELY_HEAD = 1 << TIMELY_HEAD_FLAG_INDEX; - -/** - * During the epoch transition, additional data is precomputed to avoid traversing any state a second - * time. Attestations are a big part of this, and each validator has a "status" to represent its - * precomputed participation. - */ -export type AttesterStatus = { - flags: number; - proposerIndex: number; // -1 when not included by any proposer - inclusionDelay: number; - active: boolean; -}; - -export function createAttesterStatus(): AttesterStatus { - return { - flags: 0, - proposerIndex: -1, - inclusionDelay: 0, - active: false, - }; -} - export function hasMarkers(flags: number, markers: number): boolean { return (flags & markers) === markers; } @@ -81,6 +63,11 @@ export function toAttesterFlags(flagsObj: AttesterFlags): number { return flag; } +/** 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 TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX; +const TIMELY_HEAD = 1 << TIMELY_HEAD_FLAG_INDEX; + export type ParticipationFlags = { timelySource: boolean; timelyTarget: boolean; diff --git a/packages/state-transition/test/perf/analyzeEpochs.ts b/packages/state-transition/test/perf/analyzeEpochs.ts index c2f09fcc5521..6f61bc81abbc 100644 --- a/packages/state-transition/test/perf/analyzeEpochs.ts +++ b/packages/state-transition/test/perf/analyzeEpochs.ts @@ -114,8 +114,8 @@ async function analyzeEpochs(network: NetworkName, fromEpoch?: number): Promise< const attesterFlagsCount = {...attesterFlagsCountZero}; const keys = Object.keys(attesterFlagsCountZero) as (keyof typeof attesterFlagsCountZero)[]; - for (const status of cache.statuses) { - const flags = parseAttesterFlags(status.flags); + for (const flag of cache.flags) { + const flags = parseAttesterFlags(flag); for (const key of keys) { if (flags[key]) attesterFlagsCount[key]++; } diff --git a/packages/state-transition/test/perf/epoch/array.test.ts b/packages/state-transition/test/perf/epoch/array.test.ts new file mode 100644 index 000000000000..eafd349e982f --- /dev/null +++ b/packages/state-transition/test/perf/epoch/array.test.ts @@ -0,0 +1,60 @@ +import {itBench} from "@dapplion/benchmark"; + +/* +July 14, 2024 +- AMD Ryzen Threadripper 1950X 16-Core Processor +- Linux 5.15.0-113-generic +- Node v20.12.2 + + array + ✔ Array.fill - length 1000000 148.1271 ops/s 6.750961 ms/op - 109 runs 1.24 s + ✔ Array push - length 1000000 35.63945 ops/s 28.05879 ms/op - 158 runs 4.97 s + ✔ Array.get 2.002555e+9 ops/s 0.4993620 ns/op - 66 runs 7.96 s + ✔ Uint8Array.get 2.002383e+9 ops/s 0.4994050 ns/op - 512 runs 0.903 s +*/ + +describe("array", () => { + const N = 1_000_000; + itBench({ + id: `Array.fill - length ${N}`, + fn: () => { + new Array(N).fill(0); + for (let i = 0; i < N; i++) { + void 0; + } + }, + }); + itBench({ + id: `Array push - length ${N}`, + fn: () => { + const arr: boolean[] = []; + for (let i = 0; i < N; i++) { + arr.push(true); + } + }, + }); + itBench({ + id: "Array.get", + runsFactor: N, + beforeEach: () => { + return new Array(N).fill(8); + }, + fn: (arr) => { + for (let i = 0; i < N; i++) { + arr[N - 1]; + } + }, + }); + itBench({ + id: "Uint8Array.get", + runsFactor: N, + beforeEach: () => { + return new Uint8Array(N); + }, + fn: (arr) => { + for (let i = 0; i < N; i++) { + arr[N - 1]; + } + }, + }); +}); diff --git a/packages/state-transition/test/perf/epoch/utilPhase0.ts b/packages/state-transition/test/perf/epoch/utilPhase0.ts index f73399ee108f..026506510979 100644 --- a/packages/state-transition/test/perf/epoch/utilPhase0.ts +++ b/packages/state-transition/test/perf/epoch/utilPhase0.ts @@ -1,10 +1,4 @@ -import { - AttesterFlags, - FLAG_ELIGIBLE_ATTESTER, - hasMarkers, - AttesterStatus, - toAttesterFlags, -} from "../../../src/index.js"; +import {AttesterFlags, FLAG_ELIGIBLE_ATTESTER, hasMarkers, toAttesterFlags} from "../../../src/index.js"; import {CachedBeaconStatePhase0, CachedBeaconStateAltair, EpochTransitionCache} from "../../../src/types.js"; /** @@ -19,16 +13,18 @@ export function generateBalanceDeltasEpochTransitionCache( ): EpochTransitionCache { const vc = state.validators.length; - const statuses = generateStatuses(state.validators.length, flagFactors); + const {proposerIndices, inclusionDelays, flags} = generateStatuses(state.validators.length, flagFactors); const eligibleValidatorIndices: number[] = []; - for (let i = 0; i < statuses.length; i++) { - if (hasMarkers(statuses[i].flags, FLAG_ELIGIBLE_ATTESTER)) { + for (let i = 0; i < flags.length; i++) { + if (hasMarkers(flags[i], FLAG_ELIGIBLE_ATTESTER)) { eligibleValidatorIndices.push(i); } } const cache: Partial = { - statuses, + proposerIndices, + inclusionDelays, + flags, eligibleValidatorIndices, totalActiveStakeByIncrement: vc, baseRewardPerIncrement: 726, @@ -45,19 +41,21 @@ export function generateBalanceDeltasEpochTransitionCache( export type FlagFactors = Record | number; -function generateStatuses(vc: number, flagFactors: FlagFactors): AttesterStatus[] { +function generateStatuses( + vc: number, + flagFactors: FlagFactors +): {proposerIndices: number[]; inclusionDelays: number[]; flags: number[]} { const totalProposers = 32; - const statuses = new Array(vc); + const proposerIndices = new Array(vc); + const inclusionDelays = new Array(vc); + const flags = new Array(vc).fill(0); for (let i = 0; i < vc; i++) { // Set to number to set all validators to the same value if (typeof flagFactors === "number") { - statuses[i] = { - flags: flagFactors, - proposerIndex: i % totalProposers, - inclusionDelay: 1 + (i % 4), - active: true, - }; + proposerIndices[i] = i % totalProposers; + inclusionDelays[i] = 1 + (i % 4); + flags[i] = flagFactors; } else { // Use a factor to set some validators to this flag const flagsObj: AttesterFlags = { @@ -70,14 +68,11 @@ function generateStatuses(vc: number, flagFactors: FlagFactors): AttesterStatus[ unslashed: i < vc * flagFactors.unslashed, // 6 eligibleAttester: i < vc * flagFactors.eligibleAttester, // 7 }; - statuses[i] = { - flags: toAttesterFlags(flagsObj), - proposerIndex: i % totalProposers, - inclusionDelay: 1 + (i % 4), - active: true, - }; + proposerIndices[i] = i % totalProposers; + inclusionDelays[i] = 1 + (i % 4); + flags[i] = toAttesterFlags(flagsObj); } } - return statuses; + return {proposerIndices, inclusionDelays, flags}; } From e57e4b7d10bfe2558484a6f722cc9959f0256b1d Mon Sep 17 00:00:00 2001 From: Cayman Date: Tue, 16 Jul 2024 05:11:03 -0400 Subject: [PATCH 10/44] chore: remove unused metricsRegistries (#6957) --- packages/cli/src/cmds/beacon/handler.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/cli/src/cmds/beacon/handler.ts b/packages/cli/src/cmds/beacon/handler.ts index e24089194185..4d788efa231a 100644 --- a/packages/cli/src/cmds/beacon/handler.ts +++ b/packages/cli/src/cmds/beacon/handler.ts @@ -1,6 +1,5 @@ import path from "node:path"; import {getHeapStatistics} from "node:v8"; -import {Registry} from "prom-client"; import {ErrorAborted} from "@lodestar/utils"; import {LevelDbController} from "@lodestar/db"; import {BeaconNode, BeaconDb} from "@lodestar/beacon-node"; @@ -61,13 +60,6 @@ export async function beaconHandler(args: BeaconArgs & GlobalArgs): Promise Date: Tue, 16 Jul 2024 17:43:54 +0800 Subject: [PATCH 11/44] fix: sepolia genesis delay (#6961) * fix sepolia genesis delay * Update packages/config/src/chainConfig/networks/sepolia.ts --------- Co-authored-by: Nico Flaig --- packages/config/src/chainConfig/networks/sepolia.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/config/src/chainConfig/networks/sepolia.ts b/packages/config/src/chainConfig/networks/sepolia.ts index ab6facbec72e..51102cfafa7d 100644 --- a/packages/config/src/chainConfig/networks/sepolia.ts +++ b/packages/config/src/chainConfig/networks/sepolia.ts @@ -17,6 +17,7 @@ export const sepoliaChainConfig: ChainConfig = { // # Sunday, June 19, 2022 2:00:00 PM +UTC MIN_GENESIS_TIME: 1655647200, GENESIS_FORK_VERSION: b("0x90000069"), + GENESIS_DELAY: 86400, // Forking // --------------------------------------------------------------- From c6369ee5fe2c41f922e36afaedd7db4d8a69b15f Mon Sep 17 00:00:00 2001 From: Cayman Date: Tue, 16 Jul 2024 08:20:34 -0400 Subject: [PATCH 12/44] chore: bump @chainsafe/bls-keystore (#6956) --- packages/cli/package.json | 2 +- packages/test-utils/package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 4f27d030c735..61559cebe590 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -53,7 +53,7 @@ "dependencies": { "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keygen": "^0.4.0", - "@chainsafe/bls-keystore": "^3.0.1", + "@chainsafe/bls-keystore": "^3.1.0", "@chainsafe/blst": "^0.2.11", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 45fb3d0e0909..0fd948a6d1c4 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -58,7 +58,7 @@ ], "dependencies": { "@chainsafe/bls": "7.1.3", - "@chainsafe/bls-keystore": "^3.0.1", + "@chainsafe/bls-keystore": "^3.1.0", "@lodestar/params": "^1.20.1", "@lodestar/utils": "^1.20.1", "axios": "^1.3.4", diff --git a/yarn.lock b/yarn.lock index 19f39c58ea4f..8496d0df111a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -290,10 +290,10 @@ "@noble/hashes" "^1.0.0" "@scure/bip39" "^1.0.0" -"@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== +"@chainsafe/bls-keystore@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@chainsafe/bls-keystore/-/bls-keystore-3.1.0.tgz#cdc466e4bc710e710b2a511e4fbaa909fbcd518a" + integrity sha512-OR9hV9N53woNc6R2d08O3Oi3Ykx7uZARMx51W+WFP1fDaFSA/QaMraPGGA8tSx7livkb/Scwe3Basj9Pib67HA== dependencies: ethereum-cryptography "^2.0.0" uuid "^9.0.0" From c78b6cee36b5f3b0fda9e0ac11fad350af7341a1 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Thu, 18 Jul 2024 16:11:52 +0500 Subject: [PATCH 13/44] feat: add cli flag to disable light client server (#6913) * Add disable flag * Add util function to check lightclient server * Add reqresp checks * Add api checks * Fix beacon-node usage of lightclient server * Fix types * Fix the code with feedback * Disable gossipsub topic for lightclient * Fix the types * Update the type checks * Clean reassingment * Update code --- .../src/api/impl/lightclient/index.ts | 20 ++++++++++++++----- .../src/chain/archiver/archiveBlocks.ts | 6 ++++-- .../src/chain/blocks/importBlock.ts | 2 +- packages/beacon-node/src/chain/chain.ts | 7 ++++--- packages/beacon-node/src/chain/interface.ts | 2 +- .../src/chain/lightClient/index.ts | 1 + .../validation/lightClientFinalityUpdate.ts | 3 +++ .../validation/lightClientOptimisticUpdate.ts | 3 +++ .../src/network/core/networkCore.ts | 14 +++++++++---- .../src/network/gossip/gossipsub.ts | 12 ++++++++--- .../beacon-node/src/network/gossip/topic.ts | 8 +++++--- packages/beacon-node/src/network/options.ts | 7 +++++-- .../src/network/reqresp/ReqRespBeaconNode.ts | 6 ++++-- .../reqresp/handlers/lightClientBootstrap.ts | 3 +++ .../handlers/lightClientFinalityUpdate.ts | 3 +++ .../handlers/lightClientOptimisticUpdate.ts | 3 +++ .../handlers/lightClientUpdatesByRange.ts | 3 +++ .../beacon-node/src/node/utils/lightclient.ts | 7 +++++++ .../lightClientFinalityUpdate.test.ts | 3 ++- .../lightClientOptimisticUpdate.test.ts | 3 ++- packages/cli/src/cmds/beacon/handler.ts | 4 ++++ packages/cli/src/cmds/beacon/options.ts | 6 ++++++ packages/utils/src/index.ts | 2 +- packages/utils/src/types.ts | 7 +++++++ 24 files changed, 106 insertions(+), 29 deletions(-) create mode 100644 packages/beacon-node/src/node/utils/lightclient.ts diff --git a/packages/beacon-node/src/api/impl/lightclient/index.ts b/packages/beacon-node/src/api/impl/lightclient/index.ts index 13deb16a9cb0..0dd366accf68 100644 --- a/packages/beacon-node/src/api/impl/lightclient/index.ts +++ b/packages/beacon-node/src/api/impl/lightclient/index.ts @@ -3,7 +3,7 @@ import {routes} from "@lodestar/api"; import {ApplicationMethods} from "@lodestar/api/server"; import {MAX_REQUEST_LIGHT_CLIENT_UPDATES, MAX_REQUEST_LIGHT_CLIENT_COMMITTEE_HASHES} from "@lodestar/params"; import {ApiModules} from "../types.js"; - +import {assertLightClientServer} from "../../../node/utils/lightclient.js"; // TODO: Import from lightclient/server package export function getLightclientApi({ @@ -12,9 +12,12 @@ export function getLightclientApi({ }: Pick): ApplicationMethods { return { async getLightClientUpdatesByRange({startPeriod, count}) { + const lightClientServer = chain.lightClientServer; + assertLightClientServer(lightClientServer); + const maxAllowedCount = Math.min(MAX_REQUEST_LIGHT_CLIENT_UPDATES, count); const periods = Array.from({length: maxAllowedCount}, (_ignored, i) => i + startPeriod); - const updates = await Promise.all(periods.map((period) => chain.lightClientServer.getUpdate(period))); + const updates = await Promise.all(periods.map((period) => lightClientServer.getUpdate(period))); return { data: updates, meta: {versions: updates.map((update) => config.getForkName(update.attestedHeader.beacon.slot))}, @@ -22,6 +25,8 @@ export function getLightclientApi({ }, async getLightClientOptimisticUpdate() { + assertLightClientServer(chain.lightClientServer); + const update = chain.lightClientServer.getOptimisticUpdate(); if (update === null) { throw Error("No optimistic update available"); @@ -30,6 +35,8 @@ export function getLightclientApi({ }, async getLightClientFinalityUpdate() { + assertLightClientServer(chain.lightClientServer); + const update = chain.lightClientServer.getFinalityUpdate(); if (update === null) { throw Error("No finality update available"); @@ -38,16 +45,19 @@ export function getLightclientApi({ }, async getLightClientBootstrap({blockRoot}) { + assertLightClientServer(chain.lightClientServer); + const bootstrapProof = await chain.lightClientServer.getBootstrap(fromHex(blockRoot)); return {data: bootstrapProof, meta: {version: config.getForkName(bootstrapProof.header.beacon.slot)}}; }, async getLightClientCommitteeRoot({startPeriod, count}) { + const lightClientServer = chain.lightClientServer; + assertLightClientServer(lightClientServer); + const maxAllowedCount = Math.min(MAX_REQUEST_LIGHT_CLIENT_COMMITTEE_HASHES, count); const periods = Array.from({length: maxAllowedCount}, (_ignored, i) => i + startPeriod); - const committeeHashes = await Promise.all( - periods.map((period) => chain.lightClientServer.getCommitteeRoot(period)) - ); + const committeeHashes = await Promise.all(periods.map((period) => lightClientServer.getCommitteeRoot(period))); return {data: committeeHashes}; }, }; diff --git a/packages/beacon-node/src/chain/archiver/archiveBlocks.ts b/packages/beacon-node/src/chain/archiver/archiveBlocks.ts index 71fa9fb61b2e..76bfe651ad77 100644 --- a/packages/beacon-node/src/chain/archiver/archiveBlocks.ts +++ b/packages/beacon-node/src/chain/archiver/archiveBlocks.ts @@ -32,7 +32,7 @@ export async function archiveBlocks( config: ChainForkConfig, db: IBeaconDb, forkChoice: IForkChoice, - lightclientServer: LightClientServer, + lightclientServer: LightClientServer | undefined, logger: Logger, finalizedCheckpoint: CheckpointHex, currentEpoch: Epoch, @@ -111,7 +111,9 @@ export async function archiveBlocks( nonCheckpointBlockRoots.push(block.root); } - await lightclientServer.pruneNonCheckpointData(nonCheckpointBlockRoots); + if (lightclientServer) { + await lightclientServer.pruneNonCheckpointData(nonCheckpointBlockRoots); + } logger.verbose("Archiving of finalized blocks complete", { totalArchived: finalizedCanonicalBlocks.length, diff --git a/packages/beacon-node/src/chain/blocks/importBlock.ts b/packages/beacon-node/src/chain/blocks/importBlock.ts index e67b6d1e9dbc..906be51434c2 100644 --- a/packages/beacon-node/src/chain/blocks/importBlock.ts +++ b/packages/beacon-node/src/chain/blocks/importBlock.ts @@ -305,7 +305,7 @@ export async function importBlock( // we want to import block asap so do this in the next event loop callInNextEventLoop(() => { try { - this.lightClientServer.onImportBlockHead( + this.lightClientServer?.onImportBlockHead( block.message as BeaconBlock, postState as CachedBeaconStateAltair, parentBlockSlot diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index a6912d952b68..61f044d4f895 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -126,7 +126,7 @@ export class BeaconChain implements IBeaconChain { readonly clock: IClock; readonly emitter: ChainEventEmitter; readonly regen: QueuedStateRegenerator; - readonly lightClientServer: LightClientServer; + readonly lightClientServer?: LightClientServer; readonly reprocessController: ReprocessController; // Ops pool @@ -305,7 +305,9 @@ export class BeaconChain implements IBeaconChain { signal, }); - const lightClientServer = new LightClientServer(opts, {config, db, metrics, emitter, logger}); + if (!opts.disableLightClientServer) { + this.lightClientServer = new LightClientServer(opts, {config, db, metrics, emitter, logger}); + } this.reprocessController = new ReprocessController(this.metrics); @@ -316,7 +318,6 @@ export class BeaconChain implements IBeaconChain { this.regen = regen; this.bls = bls; this.emitter = emitter; - this.lightClientServer = lightClientServer; this.archiver = new Archiver(db, this, logger, signal, opts); // always run PrepareNextSlotScheduler except for fork_choice spec tests diff --git a/packages/beacon-node/src/chain/interface.ts b/packages/beacon-node/src/chain/interface.ts index e412d8e8aafa..aa70b0bdcce4 100644 --- a/packages/beacon-node/src/chain/interface.ts +++ b/packages/beacon-node/src/chain/interface.ts @@ -95,7 +95,7 @@ export interface IBeaconChain { readonly clock: IClock; readonly emitter: ChainEventEmitter; readonly regen: IStateRegenerator; - readonly lightClientServer: LightClientServer; + readonly lightClientServer?: LightClientServer; readonly reprocessController: ReprocessController; readonly pubkey2index: PubkeyIndexMap; readonly index2pubkey: Index2PubkeyCache; diff --git a/packages/beacon-node/src/chain/lightClient/index.ts b/packages/beacon-node/src/chain/lightClient/index.ts index 6d713109f945..0230ca48c8be 100644 --- a/packages/beacon-node/src/chain/lightClient/index.ts +++ b/packages/beacon-node/src/chain/lightClient/index.ts @@ -60,6 +60,7 @@ import { export type LightClientServerOpts = { disableLightClientServerOnImportBlockHead?: boolean; + disableLightClientServer?: boolean; }; type DependentRootHex = RootHex; diff --git a/packages/beacon-node/src/chain/validation/lightClientFinalityUpdate.ts b/packages/beacon-node/src/chain/validation/lightClientFinalityUpdate.ts index 23b91dba5fd9..f4865c73f8e4 100644 --- a/packages/beacon-node/src/chain/validation/lightClientFinalityUpdate.ts +++ b/packages/beacon-node/src/chain/validation/lightClientFinalityUpdate.ts @@ -3,6 +3,7 @@ import {LightClientFinalityUpdate} from "@lodestar/types"; import {IBeaconChain} from "../interface.js"; import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js"; import {GossipAction} from "../errors/index.js"; +import {assertLightClientServer} from "../../node/utils/lightclient.js"; import {updateReceivedTooEarly} from "./lightClientOptimisticUpdate.js"; // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#light_client_finality_update @@ -11,6 +12,8 @@ export function validateLightClientFinalityUpdate( chain: IBeaconChain, gossipedFinalityUpdate: LightClientFinalityUpdate ): void { + assertLightClientServer(chain.lightClientServer); + // [IGNORE] No other finality_update with a lower or equal finalized_header.slot was already forwarded on the network const gossipedFinalitySlot = gossipedFinalityUpdate.finalizedHeader.beacon.slot; const localFinalityUpdate = chain.lightClientServer.getFinalityUpdate(); diff --git a/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts b/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts index 54b69f56808c..182321984af5 100644 --- a/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts +++ b/packages/beacon-node/src/chain/validation/lightClientOptimisticUpdate.ts @@ -5,6 +5,7 @@ import {IBeaconChain} from "../interface.js"; import {LightClientError, LightClientErrorCode} from "../errors/lightClientError.js"; import {GossipAction} from "../errors/index.js"; import {MAXIMUM_GOSSIP_CLOCK_DISPARITY} from "../../constants/index.js"; +import {assertLightClientServer} from "../../node/utils/lightclient.js"; // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update export function validateLightClientOptimisticUpdate( @@ -12,6 +13,8 @@ export function validateLightClientOptimisticUpdate( chain: IBeaconChain, gossipedOptimisticUpdate: LightClientOptimisticUpdate ): void { + assertLightClientServer(chain.lightClientServer); + // [IGNORE] No other optimistic_update with a lower or equal attested_header.slot was already forwarded on the network const gossipedAttestedSlot = gossipedOptimisticUpdate.attestedHeader.beacon.slot; const localOptimisticUpdate = chain.lightClientServer.getOptimisticUpdate(); diff --git a/packages/beacon-node/src/network/core/networkCore.ts b/packages/beacon-node/src/network/core/networkCore.ts index fdd2b681602f..07b346bc29e4 100644 --- a/packages/beacon-node/src/network/core/networkCore.ts +++ b/packages/beacon-node/src/network/core/networkCore.ts @@ -499,9 +499,12 @@ export class NetworkCore implements INetworkCore { private subscribeCoreTopicsAtFork(fork: ForkName): void { if (this.subscribedForks.has(fork)) return; this.subscribedForks.add(fork); - const {subscribeAllSubnets} = this.opts; + const {subscribeAllSubnets, disableLightClientServer} = this.opts; - for (const topic of getCoreTopicsAtFork(fork, {subscribeAllSubnets})) { + for (const topic of getCoreTopicsAtFork(fork, { + subscribeAllSubnets, + disableLightClientServer, + })) { this.gossip.subscribeTopic({...topic, fork}); } } @@ -509,9 +512,12 @@ export class NetworkCore implements INetworkCore { private unsubscribeCoreTopicsAtFork(fork: ForkName): void { if (!this.subscribedForks.has(fork)) return; this.subscribedForks.delete(fork); - const {subscribeAllSubnets} = this.opts; + const {subscribeAllSubnets, disableLightClientServer} = this.opts; - for (const topic of getCoreTopicsAtFork(fork, {subscribeAllSubnets})) { + for (const topic of getCoreTopicsAtFork(fork, { + subscribeAllSubnets, + disableLightClientServer, + })) { this.gossip.unsubscribeTopic({...topic, fork}); } } diff --git a/packages/beacon-node/src/network/gossip/gossipsub.ts b/packages/beacon-node/src/network/gossip/gossipsub.ts index 4066452f1e3b..e6977abe8ce6 100644 --- a/packages/beacon-node/src/network/gossip/gossipsub.ts +++ b/packages/beacon-node/src/network/gossip/gossipsub.ts @@ -56,6 +56,7 @@ export type Eth2GossipsubOpts = { gossipsubAwaitHandler?: boolean; disableFloodPublish?: boolean; skipParamsLog?: boolean; + disableLightClientServer?: boolean; }; /** @@ -124,7 +125,9 @@ export class Eth2Gossipsub extends GossipSub { isFinite(config.BELLATRIX_FORK_EPOCH) ? GOSSIP_MAX_SIZE_BELLATRIX : GOSSIP_MAX_SIZE ), metricsRegister: metricsRegister as MetricsRegister | null, - metricsTopicStrToLabel: metricsRegister ? getMetricsTopicStrToLabel(config) : undefined, + metricsTopicStrToLabel: metricsRegister + ? getMetricsTopicStrToLabel(config, {disableLightClientServer: opts.disableLightClientServer ?? false}) + : undefined, asyncValidation: true, maxOutboundBufferSize: MAX_OUTBOUND_BUFFER_SIZE, @@ -321,11 +324,14 @@ function attSubnetLabel(subnet: number): string { else return `0${subnet}`; } -function getMetricsTopicStrToLabel(config: BeaconConfig): TopicStrToLabel { +function getMetricsTopicStrToLabel(config: BeaconConfig, opts: {disableLightClientServer: boolean}): TopicStrToLabel { const metricsTopicStrToLabel = new Map(); for (const {name: fork} of config.forksAscendingEpochOrder) { - const topics = getCoreTopicsAtFork(fork, {subscribeAllSubnets: true}); + const topics = getCoreTopicsAtFork(fork, { + subscribeAllSubnets: true, + disableLightClientServer: opts.disableLightClientServer, + }); for (const topic of topics) { metricsTopicStrToLabel.set(stringifyGossipTopic(config, {...topic, fork}), topic.type); } diff --git a/packages/beacon-node/src/network/gossip/topic.ts b/packages/beacon-node/src/network/gossip/topic.ts index 0f3f6942a10a..4923b71e6887 100644 --- a/packages/beacon-node/src/network/gossip/topic.ts +++ b/packages/beacon-node/src/network/gossip/topic.ts @@ -201,7 +201,7 @@ export function parseGossipTopic(forkDigestContext: ForkDigestContext, topicStr: */ export function getCoreTopicsAtFork( fork: ForkName, - opts: {subscribeAllSubnets?: boolean} + opts: {subscribeAllSubnets?: boolean; disableLightClientServer?: boolean} ): GossipTopicTypeMap[keyof GossipTopicTypeMap][] { // Common topics for all forks const topics: GossipTopicTypeMap[keyof GossipTopicTypeMap][] = [ @@ -227,8 +227,10 @@ export function getCoreTopicsAtFork( // Any fork after altair included if (ForkSeq[fork] >= ForkSeq.altair) { topics.push({type: GossipType.sync_committee_contribution_and_proof}); - topics.push({type: GossipType.light_client_optimistic_update}); - topics.push({type: GossipType.light_client_finality_update}); + if (!opts.disableLightClientServer) { + topics.push({type: GossipType.light_client_optimistic_update}); + topics.push({type: GossipType.light_client_finality_update}); + } } if (opts.subscribeAllSubnets) { diff --git a/packages/beacon-node/src/network/options.ts b/packages/beacon-node/src/network/options.ts index 713ca4b21ad0..d2070873261b 100644 --- a/packages/beacon-node/src/network/options.ts +++ b/packages/beacon-node/src/network/options.ts @@ -8,11 +8,11 @@ import {SubnetsServiceOpts} from "./subnets/interface.js"; export interface NetworkOptions extends PeerManagerOpts, // remove all Functions - Omit, + Omit, NetworkProcessorOpts, PeerRpcScoreOpts, SubnetsServiceOpts, - Eth2GossipsubOpts { + Omit { localMultiaddrs: string[]; bootMultiaddrs?: string[]; subscribeAllSubnets?: boolean; @@ -22,6 +22,7 @@ export interface NetworkOptions private?: boolean; useWorker?: boolean; maxYoungGenerationSizeMb?: number; + disableLightClientServer?: boolean; } export const defaultNetworkOptions: NetworkOptions = { @@ -41,4 +42,6 @@ export const defaultNetworkOptions: NetworkOptions = { slotsToSubscribeBeforeAggregatorDuty: 2, // this should only be set to true if useWorker is true beaconAttestationBatchValidation: true, + // This will enable the light client server by default + disableLightClientServer: false, }; diff --git a/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts b/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts index 8d131e9e9945..d34b379f4ccd 100644 --- a/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts +++ b/packages/beacon-node/src/network/reqresp/ReqRespBeaconNode.ts @@ -51,7 +51,7 @@ export interface ReqRespBeaconNodeModules { getHandler: GetReqRespHandlerFn; } -export type ReqRespBeaconNodeOpts = ReqRespOpts; +export type ReqRespBeaconNodeOpts = ReqRespOpts & {disableLightClientServer?: boolean}; /** * Implementation of Ethereum Consensus p2p Req/Resp domain. @@ -72,6 +72,7 @@ export class ReqRespBeaconNode extends ReqResp { private readonly config: BeaconConfig; protected readonly logger: Logger; + protected readonly disableLightClientServer: boolean; constructor(modules: ReqRespBeaconNodeModules, options: ReqRespBeaconNodeOpts = {}) { const {events, peersData, peerRpcScores, metadata, metrics, logger} = modules; @@ -95,6 +96,7 @@ export class ReqRespBeaconNode extends ReqResp { } ); + this.disableLightClientServer = options.disableLightClientServer ?? false; this.peerRpcScores = peerRpcScores; this.peersData = peersData; this.config = modules.config; @@ -233,7 +235,7 @@ export class ReqRespBeaconNode extends ReqResp { ); } - if (ForkSeq[fork] >= ForkSeq.altair) { + if (ForkSeq[fork] >= ForkSeq.altair && !this.disableLightClientServer) { // Should be okay to enable before altair, but for consistency only enable afterwards protocolsAtFork.push( [protocols.LightClientBootstrap(this.config), this.getHandler(ReqRespMethod.LightClientBootstrap)], diff --git a/packages/beacon-node/src/network/reqresp/handlers/lightClientBootstrap.ts b/packages/beacon-node/src/network/reqresp/handlers/lightClientBootstrap.ts index 06277eb533a3..d14e0945e977 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/lightClientBootstrap.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/lightClientBootstrap.ts @@ -8,8 +8,11 @@ import { import {Root} from "@lodestar/types"; import {IBeaconChain} from "../../../chain/index.js"; import {ReqRespMethod, responseSszTypeByMethod} from "../types.js"; +import {assertLightClientServer} from "../../../node/utils/lightclient.js"; export async function* onLightClientBootstrap(requestBody: Root, chain: IBeaconChain): AsyncIterable { + assertLightClientServer(chain.lightClientServer); + try { const bootstrap = await chain.lightClientServer.getBootstrap(requestBody); const fork = chain.config.getForkName(bootstrap.header.beacon.slot); diff --git a/packages/beacon-node/src/network/reqresp/handlers/lightClientFinalityUpdate.ts b/packages/beacon-node/src/network/reqresp/handlers/lightClientFinalityUpdate.ts index 064f9f6ef4e3..2468b0b64f4b 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/lightClientFinalityUpdate.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/lightClientFinalityUpdate.ts @@ -1,8 +1,11 @@ import {ResponseOutgoing, RespStatus, ResponseError} from "@lodestar/reqresp"; import {IBeaconChain} from "../../../chain/index.js"; import {ReqRespMethod, responseSszTypeByMethod} from "../types.js"; +import {assertLightClientServer} from "../../../node/utils/lightclient.js"; export async function* onLightClientFinalityUpdate(chain: IBeaconChain): AsyncIterable { + assertLightClientServer(chain.lightClientServer); + const update = chain.lightClientServer.getFinalityUpdate(); if (update === null) { throw new ResponseError(RespStatus.RESOURCE_UNAVAILABLE, "No latest finality update available"); diff --git a/packages/beacon-node/src/network/reqresp/handlers/lightClientOptimisticUpdate.ts b/packages/beacon-node/src/network/reqresp/handlers/lightClientOptimisticUpdate.ts index 16001024573e..ba8371910c02 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/lightClientOptimisticUpdate.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/lightClientOptimisticUpdate.ts @@ -1,8 +1,11 @@ import {ResponseOutgoing, ResponseError, RespStatus} from "@lodestar/reqresp"; import {IBeaconChain} from "../../../chain/index.js"; import {ReqRespMethod, responseSszTypeByMethod} from "../types.js"; +import {assertLightClientServer} from "../../../node/utils/lightclient.js"; export async function* onLightClientOptimisticUpdate(chain: IBeaconChain): AsyncIterable { + assertLightClientServer(chain.lightClientServer); + const update = chain.lightClientServer.getOptimisticUpdate(); if (update === null) { throw new ResponseError(RespStatus.RESOURCE_UNAVAILABLE, "No latest optimistic update available"); diff --git a/packages/beacon-node/src/network/reqresp/handlers/lightClientUpdatesByRange.ts b/packages/beacon-node/src/network/reqresp/handlers/lightClientUpdatesByRange.ts index 8dd7e36142cc..eb0e3c3d3f4e 100644 --- a/packages/beacon-node/src/network/reqresp/handlers/lightClientUpdatesByRange.ts +++ b/packages/beacon-node/src/network/reqresp/handlers/lightClientUpdatesByRange.ts @@ -9,11 +9,14 @@ import { } from "@lodestar/reqresp"; import {IBeaconChain} from "../../../chain/index.js"; import {ReqRespMethod, responseSszTypeByMethod} from "../types.js"; +import {assertLightClientServer} from "../../../node/utils/lightclient.js"; export async function* onLightClientUpdatesByRange( requestBody: altair.LightClientUpdatesByRange, chain: IBeaconChain ): AsyncIterable { + assertLightClientServer(chain.lightClientServer); + const count = Math.min(MAX_REQUEST_LIGHT_CLIENT_UPDATES, requestBody.count); for (let period = requestBody.startPeriod; period < requestBody.startPeriod + count; period++) { try { diff --git a/packages/beacon-node/src/node/utils/lightclient.ts b/packages/beacon-node/src/node/utils/lightclient.ts new file mode 100644 index 000000000000..99d7b587e06f --- /dev/null +++ b/packages/beacon-node/src/node/utils/lightclient.ts @@ -0,0 +1,7 @@ +import {LightClientServer} from "../../chain/lightClient/index.js"; + +export function assertLightClientServer(server: LightClientServer | undefined): asserts server is LightClientServer { + if (!server) { + throw Error("Light client server is disabled"); + } +} diff --git a/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts b/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts index 70dda2535521..ef4364abc366 100644 --- a/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/lightClientFinalityUpdate.test.ts @@ -2,6 +2,7 @@ import {describe, it, expect, beforeEach, afterEach, vi} from "vitest"; import {createChainForkConfig, defaultChainConfig} from "@lodestar/config"; import {altair, ssz} from "@lodestar/types"; import {computeTimeAtSlot} from "@lodestar/state-transition"; +import {RequiredSelective} from "@lodestar/utils"; import {validateLightClientFinalityUpdate} from "../../../../src/chain/validation/lightClientFinalityUpdate.js"; import {LightClientErrorCode} from "../../../../src/chain/errors/lightClientError.js"; import {IBeaconChain} from "../../../../src/chain/index.js"; @@ -30,7 +31,7 @@ describe("Light Client Finality Update validation", function () { } }); - function mockChain(): IBeaconChain { + function mockChain(): RequiredSelective { const chain = getMockedBeaconChain(); vi.spyOn(chain, "genesisTime", "get").mockReturnValue(0); return chain; diff --git a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts index 386a08641273..b63a08757380 100644 --- a/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/lightClientOptimisticUpdate.test.ts @@ -2,6 +2,7 @@ import {describe, it, expect, beforeEach, afterEach, vi} from "vitest"; import {createChainForkConfig, defaultChainConfig} from "@lodestar/config"; import {altair, ssz} from "@lodestar/types"; import {computeTimeAtSlot} from "@lodestar/state-transition"; +import {RequiredSelective} from "@lodestar/utils"; import {validateLightClientOptimisticUpdate} from "../../../../src/chain/validation/lightClientOptimisticUpdate.js"; import {LightClientErrorCode} from "../../../../src/chain/errors/lightClientError.js"; import {IBeaconChain} from "../../../../src/chain/index.js"; @@ -30,7 +31,7 @@ describe("Light Client Optimistic Update validation", function () { } }); - function mockChain(): IBeaconChain { + function mockChain(): RequiredSelective { const chain = getMockedBeaconChain({config}); vi.spyOn(chain, "genesisTime", "get").mockReturnValue(0); vi.spyOn(chain.lightClientServer, "getOptimisticUpdate"); diff --git a/packages/cli/src/cmds/beacon/handler.ts b/packages/cli/src/cmds/beacon/handler.ts index 4d788efa231a..42128b45e4a5 100644 --- a/packages/cli/src/cmds/beacon/handler.ts +++ b/packages/cli/src/cmds/beacon/handler.ts @@ -194,6 +194,10 @@ export async function beaconHandlerInit(args: BeaconArgs & GlobalArgs) { // Inject ENR to beacon options beaconNodeOptions.set({network: {discv5: {enr: enr.encodeTxt(), config: {enrUpdate: !enr.ip && !enr.ip6}}}}); + if (args.disableLightClientServer) { + beaconNodeOptions.set({chain: {disableLightClientServer: true}}); + } + if (args.private) { beaconNodeOptions.set({network: {private: true}}); } else { diff --git a/packages/cli/src/cmds/beacon/options.ts b/packages/cli/src/cmds/beacon/options.ts index 1ec508696a13..5b57b58e82e2 100644 --- a/packages/cli/src/cmds/beacon/options.ts +++ b/packages/cli/src/cmds/beacon/options.ts @@ -22,6 +22,7 @@ type BeaconExtraArgs = { private?: boolean; validatorMonitorLogs?: boolean; attachToGlobalThis?: boolean; + disableLightClientServer?: boolean; }; export const beaconExtraOptions: CliCommandOptions = { @@ -140,6 +141,11 @@ export const beaconExtraOptions: CliCommandOptions = { description: "Attach the beacon node to `globalThis`. Useful to inspect a running beacon node.", type: "boolean", }, + + disableLightClientServer: { + description: "Disable light client server.", + type: "boolean", + }, }; type ENRArgs = { diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 29e2cac2da21..2057e50e07bc 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -16,7 +16,7 @@ export * from "./notNullish.js"; export * from "./sleep.js"; export * from "./sort.js"; export * from "./timeout.js"; -export {type RecursivePartial, bnToNum} from "./types.js"; +export {type RecursivePartial, bnToNum, type RequiredSelective} from "./types.js"; export * from "./url.js"; export * from "./verifyMerkleBranch.js"; export * from "./promise.js"; diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index 935c13cda2c1..62b04ca9a72f 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -25,3 +25,10 @@ export type NonEmptyArray = [T, ...T[]]; export type ArrayToTuple> = { [Index in keyof Tuple]: Tuple[Index]; }; + +/** + * Convert optional attributes of an object to required + */ +export type RequiredSelective = T & { + [K in Keys]-?: T[K]; +}; From 5f375804dffdf6d6f275c498454cfcbdda6926c4 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Thu, 18 Jul 2024 18:47:03 +0100 Subject: [PATCH 14/44] chore: pin nodejs version to 22.4 (#6964) * chore: pin nodejs version to 22.4 * More pinning --- .github/workflows/benchmark.yml | 2 +- .github/workflows/binaries.yml | 2 +- .github/workflows/docs-check.yml | 4 ++-- .github/workflows/docs.yml | 8 ++++---- .github/workflows/publish-dev.yml | 4 ++-- .github/workflows/publish-rc.yml | 2 +- .github/workflows/publish-stable.yml | 2 +- .github/workflows/test-sim-merge.yml | 2 +- .github/workflows/test-sim.yml | 12 ++++++------ .github/workflows/test.yml | 14 +++++++------- Dockerfile | 6 +++--- package.json | 2 +- 12 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index e515bef7f92a..671434fe19ad 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -33,7 +33,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 22.4 check-latest: true cache: yarn - name: Node.js version diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 469b0803c378..722894424b91 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -42,7 +42,7 @@ jobs: sudo apt-get install -y build-essential python3 - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - run: | mkdir -p dist yarn global add caxa@3.0.1 diff --git a/.github/workflows/docs-check.yml b/.github/workflows/docs-check.yml index 021e5019760d..bd7310995d62 100644 --- a/.github/workflows/docs-check.yml +++ b/.github/workflows/docs-check.yml @@ -15,8 +15,8 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 22 - cache: yarn + node-version: 22.4 + cache: yarn - name: Node.js version id: node run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 63db55435edf..a4c0f18cdbe3 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,9 +7,9 @@ on: workflow_dispatch: inputs: ref: - description: 'Ref to deploy, defaults to `unstable`' + description: "Ref to deploy, defaults to `unstable`" required: false - default: 'unstable' + default: "unstable" type: string jobs: @@ -31,9 +31,9 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 22.4 check-latest: true - cache: yarn + cache: yarn - name: Node.js version id: node diff --git a/.github/workflows/publish-dev.yml b/.github/workflows/publish-dev.yml index da045764dd41..fb4197b75da9 100644 --- a/.github/workflows/publish-dev.yml +++ b/.github/workflows/publish-dev.yml @@ -20,10 +20,10 @@ jobs: fetch-depth: 0 - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 22.4 registry-url: "https://registry.npmjs.org" check-latest: true - cache: yarn + cache: yarn - name: Node.js version id: node run: echo "v8CppApiVersion=$(node --print "process.versions.modules")" >> $GITHUB_OUTPUT diff --git a/.github/workflows/publish-rc.yml b/.github/workflows/publish-rc.yml index 35831822bcdc..f8f3b21ff349 100644 --- a/.github/workflows/publish-rc.yml +++ b/.github/workflows/publish-rc.yml @@ -61,7 +61,7 @@ jobs: - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - name: Generate changelog run: node scripts/generate_changelog.mjs ${{ needs.tag.outputs.prev_tag }} ${{ needs.tag.outputs.tag }} CHANGELOG.md diff --git a/.github/workflows/publish-stable.yml b/.github/workflows/publish-stable.yml index 741c060e4d20..9c41693f26f2 100644 --- a/.github/workflows/publish-stable.yml +++ b/.github/workflows/publish-stable.yml @@ -67,7 +67,7 @@ jobs: - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - name: Generate changelog run: node scripts/generate_changelog.mjs ${{ needs.tag.outputs.prev_tag }} ${{ needs.tag.outputs.tag }} CHANGELOG.md diff --git a/.github/workflows/test-sim-merge.yml b/.github/workflows/test-sim-merge.yml index ad79bc2c0035..0042a9337bc3 100644 --- a/.github/workflows/test-sim-merge.yml +++ b/.github/workflows/test-sim-merge.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 22 + node-version: 22.4 check-latest: true cache: yarn - name: Node.js version diff --git a/.github/workflows/test-sim.yml b/.github/workflows/test-sim.yml index ff28149537d3..fbe2691da637 100644 --- a/.github/workflows/test-sim.yml +++ b/.github/workflows/test-sim.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 sim-test-multifork: name: Multifork sim test @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - name: Load env variables uses: ./.github/actions/dotenv - name: Download required docker images before running tests @@ -71,7 +71,7 @@ jobs: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - name: Load env variables uses: ./.github/actions/dotenv - name: Download required docker images before running tests @@ -100,7 +100,7 @@ jobs: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - name: Load env variables uses: ./.github/actions/dotenv - name: Download required docker images before running tests @@ -129,7 +129,7 @@ jobs: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - name: Load env variables uses: ./.github/actions/dotenv - name: Download required docker images before running tests @@ -158,7 +158,7 @@ jobs: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" with: - node: 22 + node: 22.4 - name: Load env variables uses: ./.github/actions/dotenv - name: Download required docker images before running tests diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f55eb661629f..c801b0462d60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false matrix: - node: [22] + node: [22.4] steps: # - Uses YAML anchors in the future - uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: strategy: fail-fast: false matrix: - node: [22] + node: [22.4] steps: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" @@ -74,7 +74,7 @@ jobs: strategy: fail-fast: false matrix: - node: [22] + node: [22.4] steps: - uses: actions/checkout@v4 @@ -95,7 +95,7 @@ jobs: strategy: fail-fast: false matrix: - node: [22] + node: [22.4] steps: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" @@ -134,7 +134,7 @@ jobs: strategy: fail-fast: false matrix: - node: [22] + node: [22.4] steps: # - Uses YAML anchors in the future - uses: actions/checkout@v4 @@ -171,7 +171,7 @@ jobs: strategy: fail-fast: false matrix: - node: [22] + node: [22.4] steps: # - Uses YAML anchors in the future - uses: actions/checkout@v4 @@ -195,7 +195,7 @@ jobs: strategy: fail-fast: false matrix: - node: [22] + node: [22.4] steps: - uses: actions/checkout@v4 - uses: "./.github/actions/setup-and-build" diff --git a/Dockerfile b/Dockerfile index fdab1140af47..c65cac28d51d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # --platform=$BUILDPLATFORM is used build javascript source with host arch # Otherwise TS builds on emulated archs and can be extremely slow (+1h) -FROM --platform=${BUILDPLATFORM:-amd64} node:22-alpine as build_src +FROM --platform=${BUILDPLATFORM:-amd64} node:22.4-alpine as build_src ARG COMMIT WORKDIR /usr/app RUN apk update && apk add --no-cache g++ make python3 py3-setuptools && rm -rf /var/cache/apk/* @@ -21,7 +21,7 @@ RUN cd packages/cli && GIT_COMMIT=${COMMIT} yarn write-git-data # Copy built src + node_modules to build native packages for archs different than host. # Note: This step is redundant for the host arch -FROM node:22-alpine as build_deps +FROM node:22.4-alpine as build_deps WORKDIR /usr/app RUN apk update && apk add --no-cache g++ make python3 py3-setuptools && rm -rf /var/cache/apk/* @@ -35,7 +35,7 @@ RUN cd node_modules/classic-level && yarn rebuild # Copy built src + node_modules to a new layer to prune unnecessary fs # Previous layer weights 7.25GB, while this final 488MB (as of Oct 2020) -FROM node:22-alpine +FROM node:22.4-alpine WORKDIR /usr/app COPY --from=build_deps /usr/app . diff --git a/package.json b/package.json index e4464b3b5a9f..87ccd7e9f031 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "root", "private": true, "engines": { - "node": ">=20.1.0 <21 || >=22 <23" + "node": ">=20.1.0 <21 || >=22 <22.5" }, "packageManager": "yarn@1.22.22+sha256.c17d3797fb9a9115bf375e31bfd30058cac6bc9c3b8807a3d8cb2094794b51ca", "workspaces": [ From fed08fe5107a809d8862494ae6a86ebc6f2f0ee9 Mon Sep 17 00:00:00 2001 From: Cayman Date: Thu, 18 Jul 2024 14:07:10 -0400 Subject: [PATCH 15/44] chore: refactor block and state api utils (#6963) * chore: refactor block and state api utils * Update packages/beacon-node/src/api/impl/beacon/blocks/utils.ts Co-authored-by: Nico Flaig * Update packages/beacon-node/src/api/impl/beacon/state/utils.ts Co-authored-by: Nico Flaig * chore: address pr comments * chore: tiny cleanup * Use more informative return types * Align block and state utils * Let server handler deserialize state bytes --------- Co-authored-by: Nico Flaig --- .../src/api/impl/beacon/blocks/index.ts | 14 ++-- .../src/api/impl/beacon/blocks/utils.ts | 50 ++++++------ .../src/api/impl/beacon/rewards/index.ts | 6 +- .../src/api/impl/beacon/state/index.ts | 14 ++-- .../src/api/impl/beacon/state/utils.ts | 80 +++++++++++-------- .../beacon-node/src/api/impl/debug/index.ts | 18 ++++- .../beacon-node/src/api/impl/proof/index.ts | 8 +- 7 files changed, 110 insertions(+), 80 deletions(-) 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 177f58aebb95..1b8a59cc8967 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/index.ts @@ -34,7 +34,7 @@ import {ApiModules} from "../../types.js"; import {validateGossipBlock} from "../../../../chain/validation/block.js"; import {verifyBlocksInEpoch} from "../../../../chain/blocks/verifyBlock.js"; import {BeaconChain} from "../../../../chain/chain.js"; -import {resolveBlockId, toBeaconHeaderResponse} from "./utils.js"; +import {getBlockResponse, toBeaconHeaderResponse} from "./utils.js"; type PublishBlockOpts = ImportBlockOpts; @@ -371,7 +371,7 @@ export function getBeaconBlockApi({ }, async getBlockHeader({blockId}) { - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); return { data: toBeaconHeaderResponse(config, block, true), meta: {executionOptimistic, finalized}, @@ -379,7 +379,7 @@ export function getBeaconBlockApi({ }, async getBlockV2({blockId}) { - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); return { data: block, meta: { @@ -391,7 +391,7 @@ export function getBeaconBlockApi({ }, async getBlindedBlock({blockId}) { - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); const fork = config.getForkName(block.message.slot); return { data: isForkExecution(fork) @@ -406,7 +406,7 @@ export function getBeaconBlockApi({ }, async getBlockAttestations({blockId}) { - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); return { data: Array.from(block.message.body.attestations), meta: {executionOptimistic, finalized}, @@ -445,7 +445,7 @@ export function getBeaconBlockApi({ } // Slow path - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); return { data: {root: config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message)}, meta: {executionOptimistic, finalized}, @@ -464,7 +464,7 @@ export function getBeaconBlockApi({ }, async getBlobSidecars({blockId, indices}) { - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); const blockRoot = config.getForkTypes(block.message.slot).BeaconBlock.hashTreeRoot(block.message); let {blobSidecars} = (await db.blobSidecars.get(blockRoot)) ?? {}; diff --git a/packages/beacon-node/src/api/impl/beacon/blocks/utils.ts b/packages/beacon-node/src/api/impl/beacon/blocks/utils.ts index f0d243967c22..fe4fc5ca3dc0 100644 --- a/packages/beacon-node/src/api/impl/beacon/blocks/utils.ts +++ b/packages/beacon-node/src/api/impl/beacon/blocks/utils.ts @@ -1,7 +1,8 @@ import {routes} from "@lodestar/api"; import {blockToHeader} from "@lodestar/state-transition"; import {ChainForkConfig} from "@lodestar/config"; -import {SignedBeaconBlock} from "@lodestar/types"; +import {RootHex, SignedBeaconBlock, Slot} from "@lodestar/types"; +import {IForkChoice} from "@lodestar/fork-choice"; import {GENESIS_SLOT} from "../../../../constants/index.js"; import {ApiError, ValidationError} from "../../errors.js"; import {IBeaconChain} from "../../../../chain/interface.js"; @@ -22,44 +23,29 @@ export function toBeaconHeaderResponse( }; } -export async function resolveBlockId( - chain: IBeaconChain, - blockId: routes.beacon.BlockId -): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean}> { - const res = await resolveBlockIdOrNull(chain, blockId); - if (!res) { - throw new ApiError(404, `No block found for id '${blockId}'`); - } - - return res; -} - -async function resolveBlockIdOrNull( - chain: IBeaconChain, - blockId: routes.beacon.BlockId -): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean} | null> { +export function resolveBlockId(forkChoice: IForkChoice, blockId: routes.beacon.BlockId): RootHex | Slot { blockId = String(blockId).toLowerCase(); if (blockId === "head") { - return chain.getBlockByRoot(chain.forkChoice.getHead().blockRoot); + return forkChoice.getHead().blockRoot; } if (blockId === "genesis") { - return chain.getCanonicalBlockAtSlot(GENESIS_SLOT); + return GENESIS_SLOT; } if (blockId === "finalized") { - return chain.getCanonicalBlockAtSlot(chain.forkChoice.getFinalizedBlock().slot); + return forkChoice.getFinalizedBlock().blockRoot; } if (blockId === "justified") { - return chain.getBlockByRoot(chain.forkChoice.getJustifiedBlock().blockRoot); + return forkChoice.getJustifiedBlock().blockRoot; } if (blockId.startsWith("0x")) { if (!rootHexRegex.test(blockId)) { throw new ValidationError(`Invalid block id '${blockId}'`, "blockId"); } - return chain.getBlockByRoot(blockId); + return blockId; } // block id must be slot @@ -67,5 +53,23 @@ async function resolveBlockIdOrNull( if (isNaN(blockSlot) && isNaN(blockSlot - 0)) { throw new ValidationError(`Invalid block id '${blockId}'`, "blockId"); } - return chain.getCanonicalBlockAtSlot(blockSlot); + return blockSlot; +} + +export async function getBlockResponse( + chain: IBeaconChain, + blockId: routes.beacon.BlockId +): Promise<{block: SignedBeaconBlock; executionOptimistic: boolean; finalized: boolean}> { + const rootOrSlot = resolveBlockId(chain.forkChoice, blockId); + + const res = + typeof rootOrSlot === "string" + ? await chain.getBlockByRoot(rootOrSlot) + : await chain.getCanonicalBlockAtSlot(rootOrSlot); + + if (!res) { + throw new ApiError(404, `No block found for id '${blockId}'`); + } + + return res; } diff --git a/packages/beacon-node/src/api/impl/beacon/rewards/index.ts b/packages/beacon-node/src/api/impl/beacon/rewards/index.ts index 96399db27b4f..8d8a77701b91 100644 --- a/packages/beacon-node/src/api/impl/beacon/rewards/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/rewards/index.ts @@ -1,14 +1,14 @@ import {routes} from "@lodestar/api"; import {ApplicationMethods} from "@lodestar/api/server"; import {ApiModules} from "../../types.js"; -import {resolveBlockId} from "../blocks/utils.js"; +import {getBlockResponse} from "../blocks/utils.js"; export function getBeaconRewardsApi({ chain, }: Pick): ApplicationMethods { return { async getBlockRewards({blockId}) { - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); const data = await chain.getBlockRewards(block.message); return {data, meta: {executionOptimistic, finalized}}; }, @@ -17,7 +17,7 @@ export function getBeaconRewardsApi({ return {data: rewards, meta: {executionOptimistic, finalized}}; }, async getSyncCommitteeRewards({blockId, validatorIds}) { - const {block, executionOptimistic, finalized} = await resolveBlockId(chain, blockId); + const {block, executionOptimistic, finalized} = await getBlockResponse(chain, blockId); const data = await chain.getSyncCommitteeRewards(block.message, validatorIds); return {data, meta: {executionOptimistic, finalized}}; }, diff --git a/packages/beacon-node/src/api/impl/beacon/state/index.ts b/packages/beacon-node/src/api/impl/beacon/state/index.ts index 201cc875123e..9d9646ee8cf3 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/index.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/index.ts @@ -15,7 +15,7 @@ import { filterStateValidatorsByStatus, getStateValidatorIndex, getValidatorStatus, - resolveStateId, + getStateResponse, toValidatorResponse, } from "./utils.js"; @@ -26,7 +26,7 @@ export function getBeaconStateApi({ async function getState( stateId: routes.beacon.StateId ): Promise<{state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean}> { - return resolveStateId(chain, stateId); + return getStateResponse(chain, stateId); } return { @@ -76,7 +76,7 @@ export function getBeaconStateApi({ }, async getStateValidators({stateId, validatorIds = [], statuses = []}) { - const {state, executionOptimistic, finalized} = await resolveStateId(chain, stateId); + const {state, executionOptimistic, finalized} = await getStateResponse(chain, stateId); const currentEpoch = getCurrentEpoch(state); const {validators, balances} = state; // Get the validators sub tree once for all the loop const {pubkey2index} = chain.getHeadState().epochCtx; @@ -131,7 +131,7 @@ export function getBeaconStateApi({ }, async getStateValidator({stateId, validatorId}) { - const {state, executionOptimistic, finalized} = await resolveStateId(chain, stateId); + const {state, executionOptimistic, finalized} = await getStateResponse(chain, stateId); const {pubkey2index} = chain.getHeadState().epochCtx; const resp = getStateValidatorIndex(validatorId, state, pubkey2index); @@ -152,7 +152,7 @@ export function getBeaconStateApi({ }, async getStateValidatorBalances({stateId, validatorIds = []}) { - const {state, executionOptimistic, finalized} = await resolveStateId(chain, stateId); + const {state, executionOptimistic, finalized} = await getStateResponse(chain, stateId); if (validatorIds.length) { const headState = chain.getHeadState(); @@ -193,7 +193,7 @@ export function getBeaconStateApi({ }, async getEpochCommittees({stateId, ...filters}) { - const {state, executionOptimistic, finalized} = await resolveStateId(chain, stateId); + const {state, executionOptimistic, finalized} = await getStateResponse(chain, stateId); const stateCached = state as CachedBeaconStateAltair; if (stateCached.epochCtx === undefined) { @@ -235,7 +235,7 @@ export function getBeaconStateApi({ */ async getEpochSyncCommittees({stateId, epoch}) { // TODO: Should pick a state with the provided epoch too - const {state, executionOptimistic, finalized} = await resolveStateId(chain, stateId); + const {state, executionOptimistic, finalized} = await getStateResponse(chain, stateId); // TODO: If possible compute the syncCommittees in advance of the fork and expose them here. // So the validators can prepare and potentially attest the first block. Not critical tho, it's very unlikely diff --git a/packages/beacon-node/src/api/impl/beacon/state/utils.ts b/packages/beacon-node/src/api/impl/beacon/state/utils.ts index 73f7134e1530..a2079afaf9b8 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/utils.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/utils.ts @@ -1,53 +1,31 @@ import {routes} from "@lodestar/api"; import {FAR_FUTURE_EPOCH, GENESIS_SLOT} from "@lodestar/params"; import {BeaconStateAllForks, PubkeyIndexMap} from "@lodestar/state-transition"; -import {BLSPubkey, Epoch, phase0, ValidatorIndex} from "@lodestar/types"; +import {BLSPubkey, Epoch, phase0, RootHex, Slot, ValidatorIndex} from "@lodestar/types"; import {fromHex} from "@lodestar/utils"; -import {IBeaconChain, StateGetOpts} from "../../../../chain/index.js"; +import {IForkChoice} from "@lodestar/fork-choice"; +import {IBeaconChain} from "../../../../chain/index.js"; import {ApiError, ValidationError} from "../../errors.js"; -import {isOptimisticBlock} from "../../../../util/forkChoice.js"; -export async function resolveStateId( - chain: IBeaconChain, - stateId: routes.beacon.StateId, - opts?: StateGetOpts -): Promise<{state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean}> { - const stateRes = await resolveStateIdOrNull(chain, stateId, opts); - if (!stateRes) { - throw new ApiError(404, `No state found for id '${stateId}'`); - } - - return stateRes; -} - -async function resolveStateIdOrNull( - chain: IBeaconChain, - stateId: routes.beacon.StateId, - opts?: StateGetOpts -): Promise<{state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null> { +export function resolveStateId(forkChoice: IForkChoice, stateId: routes.beacon.StateId): RootHex | Slot { if (stateId === "head") { - // TODO: This is not OK, head and headState must be fetched atomically - const head = chain.forkChoice.getHead(); - const headState = chain.getHeadState(); - return {state: headState, executionOptimistic: isOptimisticBlock(head), finalized: false}; + return forkChoice.getHead().stateRoot; } if (stateId === "genesis") { - return chain.getStateBySlot(GENESIS_SLOT, opts); + return GENESIS_SLOT; } if (stateId === "finalized") { - const checkpoint = chain.forkChoice.getFinalizedCheckpoint(); - return chain.getStateByCheckpoint(checkpoint); + return forkChoice.getFinalizedBlock().stateRoot; } if (stateId === "justified") { - const checkpoint = chain.forkChoice.getJustifiedCheckpoint(); - return chain.getStateByCheckpoint(checkpoint); + return forkChoice.getJustifiedBlock().stateRoot; } if (typeof stateId === "string" && stateId.startsWith("0x")) { - return chain.getStateByStateRoot(stateId, opts); + return stateId; } // id must be slot @@ -56,7 +34,45 @@ async function resolveStateIdOrNull( throw new ValidationError(`Invalid block id '${stateId}'`, "blockId"); } - return chain.getStateBySlot(blockSlot, opts); + return blockSlot; +} + +export async function getStateResponse( + chain: IBeaconChain, + stateId: routes.beacon.StateId +): Promise<{state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean}> { + const rootOrSlot = resolveStateId(chain.forkChoice, stateId); + + const res = + typeof rootOrSlot === "string" + ? await chain.getStateByStateRoot(rootOrSlot) + : await chain.getStateBySlot(rootOrSlot); + + if (!res) { + throw new ApiError(404, `No state found for id '${stateId}'`); + } + + return res; +} + +export async function getStateResponseWithRegen( + chain: IBeaconChain, + stateId: routes.beacon.StateId +): Promise<{state: BeaconStateAllForks | Uint8Array; executionOptimistic: boolean; finalized: boolean}> { + const rootOrSlot = resolveStateId(chain.forkChoice, stateId); + + const res = + typeof rootOrSlot === "string" + ? await chain.getStateByStateRoot(rootOrSlot, {allowRegen: true}) + : rootOrSlot >= chain.forkChoice.getFinalizedBlock().slot + ? await chain.getStateBySlot(rootOrSlot, {allowRegen: true}) + : null; // TODO implement historical state regen + + if (!res) { + throw new ApiError(404, `No state found for id '${stateId}'`); + } + + return res; } /** diff --git a/packages/beacon-node/src/api/impl/debug/index.ts b/packages/beacon-node/src/api/impl/debug/index.ts index f1254ae1b7fb..4edb8ba9b2dd 100644 --- a/packages/beacon-node/src/api/impl/debug/index.ts +++ b/packages/beacon-node/src/api/impl/debug/index.ts @@ -1,8 +1,10 @@ import {routes} from "@lodestar/api"; import {ApplicationMethods} from "@lodestar/api/server"; -import {resolveStateId} from "../beacon/state/utils.js"; +import {BeaconState} from "@lodestar/types"; +import {getStateResponseWithRegen} from "../beacon/state/utils.js"; import {ApiModules} from "../types.js"; import {isOptimisticBlock} from "../../../util/forkChoice.js"; +import {getStateSlotFromBytes} from "../../../util/multifork.js"; export function getDebugApi({ chain, @@ -34,11 +36,19 @@ export function getDebugApi({ }, async getStateV2({stateId}, context) { - const {state, executionOptimistic, finalized} = await resolveStateId(chain, stateId, {allowRegen: true}); + const {state, executionOptimistic, finalized} = await getStateResponseWithRegen(chain, stateId); + let slot: number, data: Uint8Array | BeaconState; + if (state instanceof Uint8Array) { + slot = getStateSlotFromBytes(state); + data = state; + } else { + slot = state.slot; + data = context?.returnBytes ? state.serialize() : state.toValue(); + } return { - data: context?.returnBytes ? state.serialize() : state.toValue(), + data, meta: { - version: config.getForkName(state.slot), + version: config.getForkName(slot), executionOptimistic, finalized, }, diff --git a/packages/beacon-node/src/api/impl/proof/index.ts b/packages/beacon-node/src/api/impl/proof/index.ts index a581fb8eed59..9e1a33940225 100644 --- a/packages/beacon-node/src/api/impl/proof/index.ts +++ b/packages/beacon-node/src/api/impl/proof/index.ts @@ -2,8 +2,8 @@ import {CompactMultiProof, createProof, ProofType} from "@chainsafe/persistent-m import {routes} from "@lodestar/api"; import {ApplicationMethods} from "@lodestar/api/server"; import {ApiModules} from "../types.js"; -import {resolveStateId} from "../beacon/state/utils.js"; -import {resolveBlockId} from "../beacon/blocks/utils.js"; +import {getStateResponse} from "../beacon/state/utils.js"; +import {getBlockResponse} from "../beacon/blocks/utils.js"; import {ApiOptions} from "../../options.js"; export function getProofApi( @@ -21,7 +21,7 @@ export function getProofApi( throw new Error("Requested proof is too large."); } - const {state} = await resolveStateId(chain, stateId); + const {state} = await getStateResponse(chain, stateId); // Commit any changes before computing the state root. In normal cases the state should have no changes here state.commit(); @@ -40,7 +40,7 @@ export function getProofApi( throw new Error("Requested proof is too large."); } - const {block} = await resolveBlockId(chain, blockId); + const {block} = await getBlockResponse(chain, blockId); // Commit any changes before computing the state root. In normal cases the state should have no changes here const blockNode = config.getForkTypes(block.message.slot).BeaconBlock.toView(block.message).node; From 3fb0f5cc6c121e154fef3ee06c0ffd6f59a4c840 Mon Sep 17 00:00:00 2001 From: g11tech Date: Fri, 19 Jul 2024 14:54:05 +0530 Subject: [PATCH 16/44] fix: fix the publish blinded block api parsing for optional header verison (#6966) --- packages/api/src/beacon/routes/beacon/block.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/api/src/beacon/routes/beacon/block.ts b/packages/api/src/beacon/routes/beacon/block.ts index cbf206e51a4a..73680ac0afc2 100644 --- a/packages/api/src/beacon/routes/beacon/block.ts +++ b/packages/api/src/beacon/routes/beacon/block.ts @@ -444,7 +444,16 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions { - const fork = toForkName(fromHeaders(headers, MetaHeader.Version)); + let fork: ForkName; + // As per spec, version header is optional for JSON requests + const versionHeader = fromHeaders(headers, MetaHeader.Version, false); + if (versionHeader !== undefined) { + fork = toForkName(versionHeader); + } else { + // Determine fork from slot in JSON payload + fork = config.getForkName((body as SignedBlindedBeaconBlock).message.slot); + } + return { signedBlindedBlock: getExecutionForkTypes(fork).SignedBlindedBeaconBlock.fromJson(body), }; From 81f9d976a92ebcbb6b361a748f31d62728620528 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 23 Jul 2024 09:56:56 +0100 Subject: [PATCH 17/44] fix: ignore noisy eventstream errors due to DNS resolution errors (#6972) --- packages/api/src/beacon/client/events.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/src/beacon/client/events.ts b/packages/api/src/beacon/client/events.ts index 35383083ee44..2d63925a738a 100644 --- a/packages/api/src/beacon/client/events.ts +++ b/packages/api/src/beacon/client/events.ts @@ -44,7 +44,7 @@ export function getClient(config: ChainForkConfig, baseUrl: string): ApiClient { const errEs = err as unknown as EventSourceError; // Ignore noisy errors due to beacon node being offline - if (!errEs.message?.includes("ECONNREFUSED")) { + if (!/ECONNREFUSED|EAI_AGAIN/.test(errEs.message ?? "")) { // If there is no message it likely indicates that the server closed the connection onError?.(new Error(errEs.message ?? "Server closed connection")); } From 27012f96ec70725d1440069a1c6ca0f0424ea8ab Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 23 Jul 2024 10:49:03 +0100 Subject: [PATCH 18/44] fix: return finalized as false if finalized epoch is genesis epoch (#6965) * fix: return finalized as false if called with genesis slot or epoch * Update genesis epoch / slot checks --- packages/beacon-node/src/chain/chain.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 61f044d4f895..081de6f85063 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -36,7 +36,7 @@ import { import {CheckpointWithHex, ExecutionStatus, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice"; import {ProcessShutdownCallback} from "@lodestar/validator"; import {Logger, gweiToWei, isErrorAborted, pruneSetToMax, sleep, toHex} from "@lodestar/utils"; -import {ForkSeq, SLOTS_PER_EPOCH} from "@lodestar/params"; +import {ForkSeq, GENESIS_SLOT, SLOTS_PER_EPOCH} from "@lodestar/params"; import {GENESIS_EPOCH, ZERO_HASH} from "../constants/index.js"; import {IBeaconDb} from "../db/index.js"; @@ -430,7 +430,11 @@ export class BeaconChain implements IBeaconChain { {dontTransferCache: true}, RegenCaller.restApi ); - return {state, executionOptimistic: isOptimisticBlock(block), finalized: slot === finalizedBlock.slot}; + return { + state, + executionOptimistic: isOptimisticBlock(block), + finalized: slot === finalizedBlock.slot && finalizedBlock.slot !== GENESIS_SLOT, + }; } else { // Just check if state is already in the cache. If it's not dialed to the correct slot, // do not bother in advancing the state. restApiCanTriggerRegen == false means do no work @@ -440,7 +444,13 @@ export class BeaconChain implements IBeaconChain { } const state = this.regen.getStateSync(block.stateRoot); - return state && {state, executionOptimistic: isOptimisticBlock(block), finalized: slot === finalizedBlock.slot}; + return ( + state && { + state, + executionOptimistic: isOptimisticBlock(block), + finalized: slot === finalizedBlock.slot && finalizedBlock.slot !== GENESIS_SLOT, + } + ); } } else { // request for finalized state @@ -458,10 +468,11 @@ export class BeaconChain implements IBeaconChain { if (opts?.allowRegen) { const state = await this.regen.getState(stateRoot, RegenCaller.restApi); const block = this.forkChoice.getBlock(state.latestBlockHeader.hashTreeRoot()); + const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch; return { state, executionOptimistic: block != null && isOptimisticBlock(block), - finalized: state.epochCtx.epoch <= this.forkChoice.getFinalizedCheckpoint().epoch, + finalized: state.epochCtx.epoch <= finalizedEpoch && finalizedEpoch !== GENESIS_EPOCH, }; } @@ -473,10 +484,11 @@ export class BeaconChain implements IBeaconChain { const cachedStateCtx = this.regen.getStateSync(stateRoot); if (cachedStateCtx) { const block = this.forkChoice.getBlock(cachedStateCtx.latestBlockHeader.hashTreeRoot()); + const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch; return { state: cachedStateCtx, executionOptimistic: block != null && isOptimisticBlock(block), - finalized: cachedStateCtx.epochCtx.epoch <= this.forkChoice.getFinalizedCheckpoint().epoch, + finalized: cachedStateCtx.epochCtx.epoch <= finalizedEpoch && finalizedEpoch !== GENESIS_EPOCH, }; } @@ -491,10 +503,11 @@ export class BeaconChain implements IBeaconChain { const cachedStateCtx = this.regen.getCheckpointStateSync(checkpoint); if (cachedStateCtx) { const block = this.forkChoice.getBlock(cachedStateCtx.latestBlockHeader.hashTreeRoot()); + const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch; return { state: cachedStateCtx, executionOptimistic: block != null && isOptimisticBlock(block), - finalized: cachedStateCtx.epochCtx.epoch <= this.forkChoice.getFinalizedCheckpoint().epoch, + finalized: cachedStateCtx.epochCtx.epoch <= finalizedEpoch && finalizedEpoch !== GENESIS_EPOCH, }; } From a187851b6a7b1b9be446f71812401d16312719da Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Wed, 24 Jul 2024 08:39:58 +0100 Subject: [PATCH 19/44] fix: start clock last when initializing validator client (#6973) --- packages/validator/src/validator.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/validator/src/validator.ts b/packages/validator/src/validator.ts index 706cf7410b43..785d3de1db2a 100644 --- a/packages/validator/src/validator.ts +++ b/packages/validator/src/validator.ts @@ -128,23 +128,17 @@ export class Validator { if (opts.closed) { this.state = Status.closed; } else { - // "start" the validator - // Instantiates block and attestation services and runs them once the chain has been started. - this.state = Status.running; - this.clock.start(this.controller.signal); - this.chainHeaderTracker.start(this.controller.signal); - // Add notifier to warn user if primary node is unhealthy as there might // not be any errors in the logs due to fallback nodes handling the requests const {httpClient} = this.api; if (httpClient.urlsInits.length > 1) { const primaryNodeUrl = toSafePrintableUrl(httpClient.urlsInits[0].baseUrl); - this.clock?.runEveryEpoch(async () => { + this.clock.runEveryEpoch(async () => { // Only emit warning if URL score is 0 to prevent false positives // if just a single request fails which might happen due to other reasons if (httpClient.urlsScore[0] === 0) { - this.logger?.warn("Primary beacon node is unhealthy", {url: primaryNodeUrl}); + this.logger.warn("Primary beacon node is unhealthy", {url: primaryNodeUrl}); } }); } @@ -158,6 +152,11 @@ export class Validator { .catch((e) => this.logger.error("Error on fetchBeaconHealth", {}, e)) ); } + + // "start" the validator + this.state = Status.running; + this.clock.start(this.controller.signal); + this.chainHeaderTracker.start(this.controller.signal); } } @@ -178,8 +177,6 @@ export class Validator { let api: ApiClient; const {clientOrUrls, globalInit} = opts.api; if (typeof clientOrUrls === "string" || Array.isArray(clientOrUrls)) { - // This new api instance can make do with default timeout as a faster timeout is - // not necessary since this instance won't be used for validator duties api = getClient( { urls: typeof clientOrUrls === "string" ? [clientOrUrls] : clientOrUrls, @@ -329,6 +326,7 @@ export class Validator { strictFeeRecipientCheck, }); + // Instantiates block and attestation services and runs them once the chain has been started. return Validator.init(opts, genesis, metrics); } From acbedaf14031b8ee74bdeb18f845732479d0ede1 Mon Sep 17 00:00:00 2001 From: Cayman Date: Wed, 24 Jul 2024 10:36:15 -0400 Subject: [PATCH 20/44] feat: add yamux stream muxer (#5886) feat: add yamux support --- packages/beacon-node/package.json | 1 + .../beacon-node/src/network/libp2p/index.ts | 3 +- yarn.lock | 147 +++++++++++++----- 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 80d61cb119cb..56aa1e406897 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -102,6 +102,7 @@ "@chainsafe/libp2p-gossipsub": "^13.0.0", "@chainsafe/libp2p-identify": "^1.0.0", "@chainsafe/libp2p-noise": "^15.0.0", + "@chainsafe/libp2p-yamux": "^6.0.2", "@chainsafe/persistent-merkle-tree": "^0.7.1", "@chainsafe/prometheus-gc-stats": "^1.0.0", "@chainsafe/ssz": "^0.15.1", diff --git a/packages/beacon-node/src/network/libp2p/index.ts b/packages/beacon-node/src/network/libp2p/index.ts index a0d58033cf2f..edd39e09cec7 100644 --- a/packages/beacon-node/src/network/libp2p/index.ts +++ b/packages/beacon-node/src/network/libp2p/index.ts @@ -10,6 +10,7 @@ import {mplex} from "@libp2p/mplex"; import {prometheusMetrics} from "@libp2p/prometheus-metrics"; import {tcp} from "@libp2p/tcp"; import {noise} from "@chainsafe/libp2p-noise"; +import {yamux} from "@chainsafe/libp2p-yamux"; import {defaultNetworkOptions, NetworkOptions} from "../options.js"; import {Eth2PeerDataStore} from "../peers/datastore.js"; import {Libp2p, LodestarComponents} from "../interface.js"; @@ -85,7 +86,7 @@ export async function createNodeJsLibp2p( }, }), ], - streamMuxers: [mplex({maxInboundStreams: 256})], + streamMuxers: [yamux({maxInboundStreams: 256}), mplex({maxInboundStreams: 256})], peerDiscovery, metrics: nodeJsLibp2pOpts.metrics ? prometheusMetrics({ diff --git a/yarn.lock b/yarn.lock index 8496d0df111a..0f01b9e7e294 100644 --- a/yarn.lock +++ b/yarn.lock @@ -436,6 +436,19 @@ uint8arrays "^5.0.0" wherearewe "^2.0.1" +"@chainsafe/libp2p-yamux@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@chainsafe/libp2p-yamux/-/libp2p-yamux-6.0.2.tgz#ba94c38ebfe2761d20b0986ff8d832fc05c2ce15" + integrity sha512-S5OkLHqYhEVMQQ4BTgnRANEIbGTQhaC23glCgBwGdeoTRtMpIozwDiPfljFLCm0RYWdCRJw9oFztO95KUHjptA== + dependencies: + "@libp2p/interface" "^1.1.3" + "@libp2p/utils" "^5.2.5" + get-iterator "^2.0.1" + it-foreach "^2.0.6" + it-pipe "^3.0.1" + it-pushable "^3.2.3" + uint8arraylist "^2.4.8" + "@chainsafe/netmask@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@chainsafe/netmask/-/netmask-2.0.0.tgz#0d4a75f47919f65011da4327a3845c9661f1038a" @@ -1530,6 +1543,18 @@ progress-events "^1.0.0" uint8arraylist "^2.4.8" +"@libp2p/interface@^1.1.3": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-1.2.0.tgz#3b5fdc5d96cffe17a8c88cc29ed78c70516b0a7f" + integrity sha512-ImnGNl3El/AukgaojACT8i9SNW1FOsrThcQU/qA3w5tEBR5p84Uwgzl/nxa4X5vGinItUJ9jLEJmtkQJENoiGQ== + dependencies: + "@multiformats/multiaddr" "^12.2.1" + it-pushable "^3.2.3" + it-stream-types "^2.0.1" + multiformats "^13.1.0" + progress-events "^1.0.0" + uint8arraylist "^2.4.8" + "@libp2p/logger@^4.0.11", "@libp2p/logger@^4.0.6": version "4.0.11" resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.11.tgz#671692a0cceee73a0c0bf9b5f05ea14fde05f5e5" @@ -1688,6 +1713,27 @@ "@types/sinon" "^17.0.3" stream-to-it "^1.0.0" +"@libp2p/utils@^5.2.5": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@libp2p/utils/-/utils-5.3.1.tgz#1d3ff7e494f78503f33e1c8df4ad4a13209d594b" + integrity sha512-FdGzRU50PJLYSEOmVXqqtq27yjUVXkU4QNRZzMVuXF9L/sKgSC2oXwj0Satc9fHx5tG3MCX1ZOSAmYEIl2fu+w== + dependencies: + "@chainsafe/is-ip" "^2.0.2" + "@libp2p/interface" "^1.2.0" + "@libp2p/logger" "^4.0.10" + "@multiformats/multiaddr" "^12.2.1" + "@multiformats/multiaddr-matcher" "^1.2.0" + delay "^6.0.0" + get-iterator "^2.0.1" + is-loopback-addr "^2.0.2" + it-pushable "^3.2.3" + it-stream-types "^2.0.1" + netmask "^2.0.2" + p-defer "^4.0.1" + race-event "^1.2.0" + race-signal "^1.0.2" + uint8arraylist "^2.4.8" + "@libp2p/utils@^5.3.2": version "5.3.2" resolved "https://registry.yarnpkg.com/@libp2p/utils/-/utils-5.3.2.tgz#044881910350fb22ed0f9db35e6f68f7e8948801" @@ -3671,6 +3717,13 @@ agent-base@^7.0.2, agent-base@^7.1.0: dependencies: debug "^4.3.4" +agent-base@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + agentkeepalive@^4.1.3, agentkeepalive@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" @@ -7354,7 +7407,7 @@ http-proxy-agent@^7.0.0: agent-base "^7.1.0" debug "^4.3.4" -http-proxy-agent@^7.0.1, http-proxy-agent@^7.0.2: +http-proxy-agent@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== @@ -7400,18 +7453,18 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" -https-proxy-agent@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" - integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== +https-proxy-agent@^7.0.0, https-proxy-agent@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" + integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== dependencies: agent-base "^7.0.2" debug "4" -https-proxy-agent@^7.0.3, https-proxy-agent@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" - integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== +https-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== dependencies: agent-base "^7.0.2" debug "4" @@ -10206,7 +10259,7 @@ p-waterfall@2.1.1: dependencies: p-reduce "^2.0.0" -pac-proxy-agent@^7.0.1: +pac-proxy-agent@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz#6b9ddc002ec3ff0ba5fdf4a8a21d363bcc612d75" integrity sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A== @@ -10630,19 +10683,19 @@ proxy-addr@^2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-agent@6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.4.0.tgz#b4e2dd51dee2b377748aef8d45604c2d7608652d" - integrity sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ== +proxy-agent@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.3.0.tgz#72f7bb20eb06049db79f7f86c49342c34f9ba08d" + integrity sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og== dependencies: agent-base "^7.0.2" debug "^4.3.4" - http-proxy-agent "^7.0.1" - https-proxy-agent "^7.0.3" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" lru-cache "^7.14.1" - pac-proxy-agent "^7.0.1" + pac-proxy-agent "^7.0.0" proxy-from-env "^1.1.0" - socks-proxy-agent "^8.0.2" + socks-proxy-agent "^8.0.1" proxy-from-env@^1.1.0: version "1.1.0" @@ -11304,13 +11357,6 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" -semver@7.6.0, semver@^7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" - 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" @@ -11323,6 +11369,13 @@ semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semve dependencies: lru-cache "^6.0.0" +semver@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + serialize-error@^11.0.1: version "11.0.3" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-11.0.3.tgz#b54f439e15da5b4961340fbbd376b6b04aa52e92" @@ -11531,6 +11584,15 @@ socks-proxy-agent@^7.0.0: debug "^4.3.3" socks "^2.6.2" +socks-proxy-agent@^8.0.1: + version "8.0.3" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz#6b2da3d77364fde6292e810b496cb70440b9b89d" + integrity sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A== + dependencies: + agent-base "^7.1.1" + debug "^4.3.4" + socks "^2.7.1" + socks-proxy-agent@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad" @@ -12027,7 +12089,16 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar-fs@3.0.5, tar-fs@^3.0.5: +tar-fs@3.0.4, tar-fs@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.4.tgz#a21dc60a2d5d9f55e0089ccd78124f1d3771dbbf" + integrity sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w== + dependencies: + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^3.1.5" + +tar-fs@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.5.tgz#f954d77767e4e6edf973384e1eb95f8f81d64ed9" integrity sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg== @@ -12038,15 +12109,6 @@ tar-fs@3.0.5, tar-fs@^3.0.5: bare-fs "^2.1.1" bare-path "^2.1.0" -tar-fs@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.4.tgz#a21dc60a2d5d9f55e0089ccd78124f1d3771dbbf" - integrity sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w== - dependencies: - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^3.1.5" - tar-fs@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" @@ -13627,7 +13689,20 @@ yargs@16.2.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@17.7.2, yargs@^17.1.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== + 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" + +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== From 2b627548d1af4879e6c0890cfa43d5c0ec57ddf5 Mon Sep 17 00:00:00 2001 From: Cayman Date: Thu, 25 Jul 2024 01:13:59 -0600 Subject: [PATCH 21/44] feat: use napi-rs blst bindings (#6894) --- dashboards/lodestar_block_processor.json | 4 +- dashboards/lodestar_bls_thread_pool.json | 8 +- packages/beacon-node/package.json | 3 +- .../beacon-node/src/chain/bls/interface.ts | 2 +- .../beacon-node/src/chain/bls/maybeBatch.ts | 15 +- .../src/chain/bls/multithread/index.ts | 16 +- .../src/chain/bls/multithread/jobItem.ts | 24 +- .../src/chain/bls/multithread/types.ts | 1 - .../src/chain/bls/multithread/worker.ts | 5 +- .../beacon-node/src/chain/bls/singleThread.ts | 14 +- packages/beacon-node/src/chain/bls/utils.ts | 5 +- .../opPools/aggregatedAttestationPool.ts | 4 +- .../src/chain/opPools/attestationPool.ts | 10 +- .../chain/opPools/syncCommitteeMessagePool.ts | 7 +- .../opPools/syncContributionAndProofPool.ts | 5 +- .../beacon-node/src/chain/opPools/utils.ts | 5 +- .../signatureSets/aggregateAndProof.ts | 2 +- .../signatureSets/selectionProof.ts | 2 +- .../syncCommitteeContribution.ts | 2 +- .../src/metrics/metrics/lodestar.ts | 6 +- .../e2e/api/impl/lightclient/endpoint.test.ts | 4 +- .../test/e2e/chain/bls/multithread.test.ts | 5 +- packages/beacon-node/test/mocks/mockedBls.ts | 2 +- .../perf/api/impl/validator/attester.test.ts | 3 +- .../beacon-node/test/perf/bls/bls.test.ts | 43 +-- packages/beacon-node/test/spec/bls/bls.ts | 56 ++-- packages/beacon-node/test/spec/general/bls.ts | 76 ++++-- .../test/spec/presets/light_client/sync.ts | 3 - .../test/unit/chain/bls/bls.test.ts | 10 +- .../test/unit/chain/genesis/genesis.test.ts | 2 +- .../opPools/aggregatedAttestationPool.test.ts | 13 +- .../unit/chain/opPools/syncCommittee.test.ts | 6 +- .../opPools/syncCommitteeContribution.test.ts | 11 +- ...idateGossipAttestationsSameAttData.test.ts | 5 +- .../validation/blsToExecutionChange.test.ts | 15 +- .../chain/validation/voluntaryExit.test.ts | 7 +- packages/beacon-node/test/utils/cache.ts | 2 +- .../beacon-node/test/utils/node/validator.ts | 2 +- packages/beacon-node/test/utils/state.ts | 4 +- packages/cli/package.json | 3 +- .../cmds/validator/blsToExecutionChange.ts | 7 +- .../keymanager/decryptKeystoreDefinitions.ts | 6 +- .../cli/src/cmds/validator/keymanager/impl.ts | 4 +- .../validator/keymanager/keystoreCache.ts | 7 +- .../cli/src/cmds/validator/signers/index.ts | 7 +- .../cli/src/cmds/validator/voluntaryExit.ts | 6 +- packages/cli/src/util/format.ts | 5 +- .../keymanager/keystoreCache.test.ts | 4 +- .../crucible/assertions/nodeAssertion.ts | 5 +- .../utils/crucible/externalSignerServer.ts | 2 +- .../cli/test/utils/crucible/interfaces.ts | 2 +- packages/flare/package.json | 2 +- packages/flare/src/cmds/selfSlashAttester.ts | 5 +- packages/flare/src/cmds/selfSlashProposer.ts | 2 +- packages/flare/src/util/deriveSecretKeys.ts | 5 +- packages/light-client/package.json | 1 + packages/state-transition/package.json | 3 +- .../src/block/processDeposit.ts | 9 +- .../state-transition/src/cache/epochCache.ts | 5 +- .../state-transition/src/cache/pubkeyCache.ts | 5 +- .../state-transition/src/cache/stateCache.ts | 5 +- .../src/epoch/processSyncCommitteeUpdates.ts | 4 +- .../src/signatureSets/blsToExecutionChange.ts | 5 +- packages/state-transition/src/util/interop.ts | 5 +- .../src/util/signatureSets.ts | 9 +- .../src/util/syncCommittee.ts | 4 +- .../state-transition/test/perf/block/util.ts | 4 +- packages/state-transition/test/perf/util.ts | 5 +- .../perf/util/loadState/loadState.test.ts | 5 +- .../test/unit/constants.test.ts | 2 +- .../unit/signatureSets/signatureSets.test.ts | 4 +- packages/test-utils/package.json | 2 +- packages/test-utils/src/keystores.ts | 4 +- packages/validator/package.json | 2 +- .../src/services/externalSignerSync.ts | 5 +- .../validator/src/services/validatorStore.ts | 2 +- packages/validator/src/types.ts | 2 +- .../test/unit/services/attestation.test.ts | 4 +- .../unit/services/attestationDuties.test.ts | 4 +- .../test/unit/services/block.test.ts | 4 +- .../test/unit/services/blockDuties.test.ts | 4 +- .../unit/services/externalSignerSync.test.ts | 5 +- .../test/unit/services/indicesService.test.ts | 6 +- .../unit/services/syncCommitteDuties.test.ts | 6 +- .../test/unit/services/syncCommittee.test.ts | 4 +- .../test/unit/validatorStore.test.ts | 4 +- .../validator/test/utils/validatorStore.ts | 2 +- yarn.lock | 255 ++++++++++++------ 88 files changed, 485 insertions(+), 386 deletions(-) diff --git a/dashboards/lodestar_block_processor.json b/dashboards/lodestar_block_processor.json index e29d3522ce60..50513613c680 100644 --- a/dashboards/lodestar_block_processor.json +++ b/dashboards/lodestar_block_processor.json @@ -5101,7 +5101,7 @@ "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", - "expr": "rate(lodestar_bls_thread_pool_signature_deserialization_main_thread_time_seconds_bucket[$rate_interval])", + "expr": "rate(lodestar_gossip_block_gossip_validate_time_bucket[$rate_interval])", "format": "heatmap", "instant": false, "legendFormat": "time", @@ -5273,7 +5273,7 @@ "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", - "expr": "rate(lodestar_bls_thread_pool_signature_deserialization_main_thread_time_seconds_sum[$rate_interval]) / rate(lodestar_bls_thread_pool_signature_deserialization_main_thread_time_seconds_count[$rate_interval])", + "expr": "rate(lodestar_gossip_block_gossip_validate_time_sum[$rate_interval]) / rate(lodestar_gossip_block_gossip_validate_time_count[$rate_interval])", "format": "heatmap", "instant": false, "legendFormat": "time", diff --git a/dashboards/lodestar_bls_thread_pool.json b/dashboards/lodestar_bls_thread_pool.json index 92b7d00d3783..867d9fd322c4 100644 --- a/dashboards/lodestar_bls_thread_pool.json +++ b/dashboards/lodestar_bls_thread_pool.json @@ -1174,9 +1174,9 @@ "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", - "expr": "rate(lodestar_bls_thread_pool_signature_deserialization_main_thread_time_seconds_sum[$rate_interval]) * 384", + "expr": "rate(lodestar_bls_thread_pool_aggregate_with_randomness_main_thread_time_seconds_sum[$rate_interval]) * 384", "instant": false, - "legendFormat": "signature_deserialization", + "legendFormat": "aggregate_with_randomness", "range": true, "refId": "A" }, @@ -1270,7 +1270,7 @@ "disableTextWrap": false, "editorMode": "code", "exemplar": false, - "expr": "rate(lodestar_bls_thread_pool_signature_deserialization_main_thread_time_seconds_bucket[$rate_interval])", + "expr": "rate(lodestar_bls_thread_pool_aggregate_with_randomness_main_thread_time_seconds_bucket[$rate_interval])", "format": "heatmap", "fullMetaSearch": false, "includeNullMetadata": true, @@ -1281,7 +1281,7 @@ "useBackend": false } ], - "title": "Main Thread Signature Aggregation Time", + "title": "Main Thread AggregateWithRandomness Time", "type": "heatmap" }, { diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 56aa1e406897..f2d58647d91f 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -95,8 +95,7 @@ }, "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/bls": "7.1.3", - "@chainsafe/blst": "^0.2.11", + "@chainsafe/blst": "^2.0.1", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", "@chainsafe/libp2p-gossipsub": "^13.0.0", diff --git a/packages/beacon-node/src/chain/bls/interface.ts b/packages/beacon-node/src/chain/bls/interface.ts index e9c98ba1920e..f37db9b34aeb 100644 --- a/packages/beacon-node/src/chain/bls/interface.ts +++ b/packages/beacon-node/src/chain/bls/interface.ts @@ -1,4 +1,4 @@ -import {PublicKey} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {ISignatureSet} from "@lodestar/state-transition"; export type VerifySignatureOpts = { diff --git a/packages/beacon-node/src/chain/bls/maybeBatch.ts b/packages/beacon-node/src/chain/bls/maybeBatch.ts index 619ddf4d72ec..e300b8ff8b76 100644 --- a/packages/beacon-node/src/chain/bls/maybeBatch.ts +++ b/packages/beacon-node/src/chain/bls/maybeBatch.ts @@ -1,5 +1,4 @@ -import {CoordType, PublicKey} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; +import {PublicKey, Signature, verify, verifyMultipleAggregateSignatures} from "@chainsafe/blst"; const MIN_SET_COUNT_TO_BATCH = 2; @@ -16,12 +15,12 @@ export type SignatureSetDeserialized = { export function verifySignatureSetsMaybeBatch(sets: SignatureSetDeserialized[]): boolean { try { if (sets.length >= MIN_SET_COUNT_TO_BATCH) { - return bls.Signature.verifyMultipleSignatures( + return verifyMultipleAggregateSignatures( sets.map((s) => ({ - publicKey: s.publicKey, - message: s.message, + pk: s.publicKey, + msg: s.message, // true = validate signature - signature: bls.Signature.fromBytes(s.signature, CoordType.affine, true), + sig: Signature.fromBytes(s.signature, true), })) ); } @@ -34,8 +33,8 @@ export function verifySignatureSetsMaybeBatch(sets: SignatureSetDeserialized[]): // If too few signature sets verify them without batching return sets.every((set) => { // true = validate signature - const sig = bls.Signature.fromBytes(set.signature, CoordType.affine, true); - return sig.verify(set.publicKey, set.message); + const sig = Signature.fromBytes(set.signature, true); + return verify(set.message, set.publicKey, sig); }); } catch (_) { // A signature could be malformed, in that case fromBytes throws error diff --git a/packages/beacon-node/src/chain/bls/multithread/index.ts b/packages/beacon-node/src/chain/bls/multithread/index.ts index 23e6f1bb460b..3725fa4bcb1c 100644 --- a/packages/beacon-node/src/chain/bls/multithread/index.ts +++ b/packages/beacon-node/src/chain/bls/multithread/index.ts @@ -7,8 +7,7 @@ import {spawn, Worker} from "@chainsafe/threads"; // @ts-ignore // eslint-disable-next-line self = undefined; -import bls from "@chainsafe/bls"; -import {Implementation, PointFormat, PublicKey} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {Logger} from "@lodestar/utils"; import {ISignatureSet} from "@lodestar/state-transition"; import {QueueError, QueueErrorCode} from "../../../util/queue/index.js"; @@ -116,7 +115,6 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { private readonly logger: Logger; private readonly metrics: Metrics | null; - private readonly format: PointFormat; private readonly workers: WorkerDescriptor[]; private readonly jobs = new LinkedList(); private bufferedJobs: { @@ -136,14 +134,10 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { this.metrics = metrics; this.blsVerifyAllMultiThread = options.blsVerifyAllMultiThread ?? false; - // TODO: Allow to customize implementation - const implementation = bls.implementation; - // Use compressed for herumi for now. // THe worker is not able to deserialize from uncompressed // `Error: err _wrapDeserialize` - this.format = implementation === "blst-native" ? PointFormat.uncompressed : PointFormat.compressed; - this.workers = this.createWorkers(implementation, blsPoolSize); + this.workers = this.createWorkers(blsPoolSize); if (metrics) { metrics.blsThreadPool.queueLength.addCollect(() => { @@ -265,11 +259,11 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { ); } - private createWorkers(implementation: Implementation, poolSize: number): WorkerDescriptor[] { + private createWorkers(poolSize: number): WorkerDescriptor[] { const workers: WorkerDescriptor[] = []; for (let i = 0; i < poolSize; i++) { - const workerData: WorkerData = {implementation, workerId: i}; + const workerData: WorkerData = {workerId: i}; const worker = new Worker(path.join(workerDir, "worker.js"), { workerData, } as ConstructorParameters[1]); @@ -400,7 +394,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { try { // Note: This can throw, must be handled per-job. // Pubkey and signature aggregation is defered here - workReq = jobItemWorkReq(job, this.format, this.metrics); + workReq = jobItemWorkReq(job, this.metrics); } catch (e) { this.metrics?.blsThreadPool.errorAggregateSignatureSetsCount.inc({type: job.type}); diff --git a/packages/beacon-node/src/chain/bls/multithread/jobItem.ts b/packages/beacon-node/src/chain/bls/multithread/jobItem.ts index 8b5c63df2eeb..035d56e56df2 100644 --- a/packages/beacon-node/src/chain/bls/multithread/jobItem.ts +++ b/packages/beacon-node/src/chain/bls/multithread/jobItem.ts @@ -1,5 +1,4 @@ -import bls from "@chainsafe/bls"; -import {CoordType, PointFormat, PublicKey} from "@chainsafe/bls/types"; +import {PublicKey, aggregateWithRandomness} from "@chainsafe/blst"; import {ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; import {VerifySignatureOpts} from "../interface.js"; import {getAggregatedPubkey} from "../utils.js"; @@ -49,36 +48,37 @@ export function jobItemSigSets(job: JobQueueItem): number { * Prepare BlsWorkReq from JobQueueItem * WARNING: May throw with untrusted user input */ -export function jobItemWorkReq(job: JobQueueItem, format: PointFormat, metrics: Metrics | null): BlsWorkReq { +export function jobItemWorkReq(job: JobQueueItem, metrics: Metrics | null): BlsWorkReq { switch (job.type) { case JobQueueItemType.default: return { opts: job.opts, sets: job.sets.map((set) => ({ // this can throw, handled in the consumer code - publicKey: getAggregatedPubkey(set, metrics).toBytes(format), + publicKey: getAggregatedPubkey(set, metrics).toBytes(), signature: set.signature, message: set.signingRoot, })), }; case JobQueueItemType.sameMessage: { - // validate signature = true, this is slow code on main thread so should only run with network thread mode (useWorker=true) - // For a node subscribing to all subnets, with 1 signature per validator per epoch it takes around 80s - // to deserialize 750_000 signatures per epoch + // This is slow code on main thread (mainly signature deserialization + group check). + // Ideally it can be taken off-thread, but in the mean time, keep track of total time spent here. + // As of July 2024, for a node subscribing to all subnets, with 1 signature per validator per epoch, + // it takes around 2.02 min to perform this operation for a single epoch. // cpu profile on main thread has 250s idle so this only works until we reach 3M validators // However, for normal node with only 2 to 7 subnet subscriptions per epoch this works until 27M validators // and not a problem in the near future - // this is monitored on v1.11.0 https://github.com/ChainSafe/lodestar/pull/5912#issuecomment-1700320307 - const timer = metrics?.blsThreadPool.signatureDeserializationMainThreadDuration.startTimer(); - const signatures = job.sets.map((set) => bls.Signature.fromBytes(set.signature, CoordType.affine, true)); + // this is monitored on v1.21.0 https://github.com/ChainSafe/lodestar/pull/6894/files#r1687359225 + const timer = metrics?.blsThreadPool.aggregateWithRandomnessMainThreadDuration.startTimer(); + const {pk, sig} = aggregateWithRandomness(job.sets.map((set) => ({pk: set.publicKey, sig: set.signature}))); timer?.(); return { opts: job.opts, sets: [ { - publicKey: bls.PublicKey.aggregate(job.sets.map((set) => set.publicKey)).toBytes(format), - signature: bls.Signature.aggregate(signatures).toBytes(format), + publicKey: pk.toBytes(), + signature: sig.toBytes(), message: job.message, }, ], diff --git a/packages/beacon-node/src/chain/bls/multithread/types.ts b/packages/beacon-node/src/chain/bls/multithread/types.ts index 3ebc979b559e..74d400a9aa62 100644 --- a/packages/beacon-node/src/chain/bls/multithread/types.ts +++ b/packages/beacon-node/src/chain/bls/multithread/types.ts @@ -1,7 +1,6 @@ import {VerifySignatureOpts} from "../interface.js"; export type WorkerData = { - implementation: "herumi" | "blst-native"; workerId: number; }; diff --git a/packages/beacon-node/src/chain/bls/multithread/worker.ts b/packages/beacon-node/src/chain/bls/multithread/worker.ts index 0db88dcfccd8..9073920df19c 100644 --- a/packages/beacon-node/src/chain/bls/multithread/worker.ts +++ b/packages/beacon-node/src/chain/bls/multithread/worker.ts @@ -1,8 +1,7 @@ /* eslint-disable @typescript-eslint/strict-boolean-expressions */ import worker from "node:worker_threads"; import {expose} from "@chainsafe/threads/worker"; -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {verifySignatureSetsMaybeBatch, SignatureSetDeserialized} from "../maybeBatch.js"; import {WorkerData, BlsWorkReq, WorkResult, WorkResultCode, SerializedSet, BlsWorkResult} from "./types.js"; import {chunkifyMaximizeChunkSize} from "./utils.js"; @@ -109,7 +108,7 @@ function verifyManySignatureSets(workReqArr: BlsWorkReq[]): BlsWorkResult { function deserializeSet(set: SerializedSet): SignatureSetDeserialized { return { - publicKey: bls.PublicKey.fromBytes(set.publicKey, CoordType.affine), + publicKey: PublicKey.fromBytes(set.publicKey), message: set.message, signature: set.signature, }; diff --git a/packages/beacon-node/src/chain/bls/singleThread.ts b/packages/beacon-node/src/chain/bls/singleThread.ts index 58ef6b6d9eec..4e2875b1cea9 100644 --- a/packages/beacon-node/src/chain/bls/singleThread.ts +++ b/packages/beacon-node/src/chain/bls/singleThread.ts @@ -1,6 +1,4 @@ -import {PublicKey, Signature} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/blst"; +import {PublicKey, Signature, aggregatePublicKeys, aggregateSignatures, verify} from "@chainsafe/blst"; import {ISignatureSet} from "@lodestar/state-transition"; import {Metrics} from "../../metrics/index.js"; import {IBlsVerifier} from "./interface.js"; @@ -40,12 +38,12 @@ export class BlsSingleThreadVerifier implements IBlsVerifier { message: Uint8Array ): Promise { const timer = this.metrics?.blsThreadPool.mainThreadDurationInThreadPool.startTimer(); - const pubkey = bls.PublicKey.aggregate(sets.map((set) => set.publicKey)); + const pubkey = aggregatePublicKeys(sets.map((set) => set.publicKey)); let isAllValid = true; // validate signature = true const signatures = sets.map((set) => { try { - return bls.Signature.fromBytes(set.signature, CoordType.affine, true); + return Signature.fromBytes(set.signature, true); } catch (_) { // at least one set has malformed signature isAllValid = false; @@ -54,8 +52,8 @@ export class BlsSingleThreadVerifier implements IBlsVerifier { }); if (isAllValid) { - const signature = bls.Signature.aggregate(signatures as Signature[]); - isAllValid = signature.verify(pubkey, message); + const signature = aggregateSignatures(signatures as Signature[]); + isAllValid = verify(message, pubkey, signature); } let result: boolean[]; @@ -67,7 +65,7 @@ export class BlsSingleThreadVerifier implements IBlsVerifier { if (sig === null) { return false; } - return sig.verify(set.publicKey, message); + return verify(message, set.publicKey, sig); }); } diff --git a/packages/beacon-node/src/chain/bls/utils.ts b/packages/beacon-node/src/chain/bls/utils.ts index 4a3a027f31ac..63f2bdd80458 100644 --- a/packages/beacon-node/src/chain/bls/utils.ts +++ b/packages/beacon-node/src/chain/bls/utils.ts @@ -1,5 +1,4 @@ -import type {PublicKey} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; +import {PublicKey, aggregatePublicKeys} from "@chainsafe/blst"; import {ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; import {Metrics} from "../../metrics/metrics.js"; @@ -10,7 +9,7 @@ export function getAggregatedPubkey(signatureSet: ISignatureSet, metrics: Metric case SignatureSetType.aggregate: { const timer = metrics?.blsThreadPool.pubkeysAggregationMainThreadDuration.startTimer(); - const pubkeys = bls.PublicKey.aggregate(signatureSet.pubkeys); + const pubkeys = aggregatePublicKeys(signatureSet.pubkeys); timer?.(); return pubkeys; } diff --git a/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts b/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts index c94e5d81e823..556e1f397d60 100644 --- a/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts +++ b/packages/beacon-node/src/chain/opPools/aggregatedAttestationPool.ts @@ -1,5 +1,5 @@ -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {aggregateSignatures} from "@chainsafe/blst"; import {ForkName, ForkSeq, MAX_ATTESTATIONS, MIN_ATTESTATION_INCLUSION_DELAY, SLOTS_PER_EPOCH} from "@lodestar/params"; import {phase0, Epoch, Slot, ssz, ValidatorIndex, RootHex} from "@lodestar/types"; import { @@ -383,7 +383,7 @@ export function aggregateInto(attestation1: AttestationWithIndex, attestation2: const signature1 = signatureFromBytesNoCheck(attestation1.attestation.signature); const signature2 = signatureFromBytesNoCheck(attestation2.attestation.signature); - attestation1.attestation.signature = bls.Signature.aggregate([signature1, signature2]).toBytes(); + attestation1.attestation.signature = aggregateSignatures([signature1, signature2]).toBytes(); } /** diff --git a/packages/beacon-node/src/chain/opPools/attestationPool.ts b/packages/beacon-node/src/chain/opPools/attestationPool.ts index 804d8798cbc2..2b511598f9a4 100644 --- a/packages/beacon-node/src/chain/opPools/attestationPool.ts +++ b/packages/beacon-node/src/chain/opPools/attestationPool.ts @@ -1,6 +1,5 @@ -import {PointFormat, Signature} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; import {BitArray} from "@chainsafe/ssz"; +import {Signature, aggregateSignatures} from "@chainsafe/blst"; import {phase0, Slot, RootHex} from "@lodestar/types"; import {MapDef} from "@lodestar/utils"; import {IClock} from "../../util/clock.js"; @@ -191,10 +190,7 @@ function aggregateAttestationInto(aggregate: AggregateFast, attestation: phase0. } aggregate.aggregationBits.set(bitIndex, true); - aggregate.signature = bls.Signature.aggregate([ - aggregate.signature, - signatureFromBytesNoCheck(attestation.signature), - ]); + aggregate.signature = aggregateSignatures([aggregate.signature, signatureFromBytesNoCheck(attestation.signature)]); return InsertOutcome.Aggregated; } @@ -217,6 +213,6 @@ function fastToAttestation(aggFast: AggregateFast): phase0.Attestation { return { data: aggFast.data, aggregationBits: aggFast.aggregationBits, - signature: aggFast.signature.toBytes(PointFormat.compressed), + signature: aggFast.signature.toBytes(), }; } diff --git a/packages/beacon-node/src/chain/opPools/syncCommitteeMessagePool.ts b/packages/beacon-node/src/chain/opPools/syncCommitteeMessagePool.ts index 03552992a72a..90a310841f01 100644 --- a/packages/beacon-node/src/chain/opPools/syncCommitteeMessagePool.ts +++ b/packages/beacon-node/src/chain/opPools/syncCommitteeMessagePool.ts @@ -1,6 +1,5 @@ -import {PointFormat, Signature} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; import {BitArray, toHexString} from "@chainsafe/ssz"; +import {Signature, aggregateSignatures} from "@chainsafe/blst"; import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; import {altair, Root, Slot, SubcommitteeIndex} from "@lodestar/types"; import {MapDef} from "@lodestar/utils"; @@ -108,7 +107,7 @@ export class SyncCommitteeMessagePool { return { ...contribution, aggregationBits: contribution.aggregationBits, - signature: contribution.signature.toBytes(PointFormat.compressed), + signature: contribution.signature.toBytes(), }; } @@ -136,7 +135,7 @@ function aggregateSignatureInto( } contribution.aggregationBits.set(indexInSubcommittee, true); - contribution.signature = bls.Signature.aggregate([ + contribution.signature = aggregateSignatures([ contribution.signature, signatureFromBytesNoCheck(signature.signature), ]); diff --git a/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts b/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts index 51b433fd6e50..7834ae534501 100644 --- a/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts +++ b/packages/beacon-node/src/chain/opPools/syncContributionAndProofPool.ts @@ -1,6 +1,5 @@ -import type {Signature} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; import {BitArray, toHexString} from "@chainsafe/ssz"; +import {Signature, aggregateSignatures} from "@chainsafe/blst"; import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_SIZE} from "@lodestar/params"; import {altair, Slot, Root, ssz} from "@lodestar/types"; import {G2_POINT_AT_INFINITY} from "@lodestar/state-transition"; @@ -182,6 +181,6 @@ export function aggregate(bestContributionBySubnet: Map, slot: Slot, slotsRetained: * No need to verify Signature is valid, already run sig-verify = false */ export function signatureFromBytesNoCheck(signature: Uint8Array): Signature { - return bls.Signature.fromBytes(signature, CoordType.affine, false); + return Signature.fromBytes(signature); } /** diff --git a/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts b/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts index 2bc2e62c861f..59787341cfb9 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts @@ -1,4 +1,4 @@ -import type {PublicKey} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {DOMAIN_AGGREGATE_AND_PROOF} from "@lodestar/params"; import {ssz} from "@lodestar/types"; import {Epoch, phase0} from "@lodestar/types"; diff --git a/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts b/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts index 09e0a5ef12be..5e129a88aa20 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts @@ -1,4 +1,4 @@ -import type {PublicKey} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {DOMAIN_SELECTION_PROOF} from "@lodestar/params"; import {phase0, Slot, ssz} from "@lodestar/types"; import {computeSigningRoot, createSingleSignatureSetFromComponents, ISignatureSet} from "@lodestar/state-transition"; diff --git a/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts b/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts index 71b7970716e9..0e1eaefef7c6 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts @@ -1,4 +1,4 @@ -import type {PublicKey} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {altair, ssz} from "@lodestar/types"; import {DOMAIN_SYNC_COMMITTEE} from "@lodestar/params"; import {CachedBeaconStateAltair, computeSigningRoot, ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; diff --git a/packages/beacon-node/src/metrics/metrics/lodestar.ts b/packages/beacon-node/src/metrics/metrics/lodestar.ts index 5ebdbac48959..f43a3f1cdbe6 100644 --- a/packages/beacon-node/src/metrics/metrics/lodestar.ts +++ b/packages/beacon-node/src/metrics/metrics/lodestar.ts @@ -482,9 +482,9 @@ export function createLodestarMetrics( name: "lodestar_bls_thread_pool_batchable_sig_sets_total", help: "Count of total batchable signature sets", }), - signatureDeserializationMainThreadDuration: register.histogram({ - name: "lodestar_bls_thread_pool_signature_deserialization_main_thread_time_seconds", - help: "Total time spent deserializing signatures on main thread", + aggregateWithRandomnessMainThreadDuration: register.histogram({ + name: "lodestar_bls_thread_pool_aggregate_with_randomness_main_thread_time_seconds", + help: "Total time performing aggregateWithRandomness on main thread", buckets: [0.001, 0.005, 0.01, 0.1], }), pubkeysAggregationMainThreadDuration: register.histogram({ diff --git a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts index afb4863dbe44..81154005af68 100644 --- a/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts +++ b/packages/beacon-node/test/e2e/api/impl/lightclient/endpoint.test.ts @@ -1,5 +1,5 @@ import {describe, it, beforeEach, afterEach, expect} from "vitest"; -import bls from "@chainsafe/bls"; +import {aggregateSerializedPublicKeys} from "@chainsafe/blst"; import {createBeaconConfig, ChainConfig} from "@lodestar/config"; import {chainConfig as chainConfigDef} from "@lodestar/config/default"; import {getClient, HttpHeader, routes} from "@lodestar/api"; @@ -129,7 +129,7 @@ describe("lightclient api", function () { const committeePubkeys = Array.from({length: SYNC_COMMITTEE_SIZE}, (_, i) => i % 2 === 0 ? pubkeys[0] : pubkeys[1] ); - const aggregatePubkey = bls.aggregatePublicKeys(committeePubkeys); + const aggregatePubkey = aggregateSerializedPublicKeys(committeePubkeys).toBytes(); // single committee hash since we requested for the first period expect(committeeRes.value()).toEqual([ ssz.altair.SyncCommittee.hashTreeRoot({ diff --git a/packages/beacon-node/test/e2e/chain/bls/multithread.test.ts b/packages/beacon-node/test/e2e/chain/bls/multithread.test.ts index bf1e73469433..25f0d5133bcd 100644 --- a/packages/beacon-node/test/e2e/chain/bls/multithread.test.ts +++ b/packages/beacon-node/test/e2e/chain/bls/multithread.test.ts @@ -1,6 +1,5 @@ import {describe, it, beforeAll, expect, beforeEach, afterEach} from "vitest"; -import bls from "@chainsafe/bls"; -import {PublicKey} from "@chainsafe/bls/types"; +import {PublicKey, SecretKey} from "@chainsafe/blst"; import {ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; import {BlsMultiThreadWorkerPool} from "../../../../src/chain/bls/multithread/index.js"; import {testLogger} from "../../../utils/logger.js"; @@ -29,7 +28,7 @@ describe("chain / bls / multithread queue", function () { beforeAll(() => { for (let i = 0; i < 3; i++) { - const sk = bls.SecretKey.fromBytes(Buffer.alloc(32, i + 1)); + const sk = SecretKey.fromBytes(Buffer.alloc(32, i + 1)); const msg = Buffer.alloc(32, i + 1); const pk = sk.toPublicKey(); const sig = sk.sign(msg); diff --git a/packages/beacon-node/test/mocks/mockedBls.ts b/packages/beacon-node/test/mocks/mockedBls.ts index 0ecec5f13bde..bc6bbf361de5 100644 --- a/packages/beacon-node/test/mocks/mockedBls.ts +++ b/packages/beacon-node/test/mocks/mockedBls.ts @@ -1,4 +1,4 @@ -import {PublicKey} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {IBlsVerifier} from "../../src/chain/bls/index.js"; export class BlsVerifierMock implements IBlsVerifier { diff --git a/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts b/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts index 10527fdf94b5..803d6c84c408 100644 --- a/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts +++ b/packages/beacon-node/test/perf/api/impl/validator/attester.test.ts @@ -1,5 +1,4 @@ import {itBench} from "@dapplion/benchmark"; -import {PointFormat} from "@chainsafe/bls/types"; // eslint-disable-next-line import/no-relative-packages import {generatePerfTestCachedStatePhase0, numValidators} from "../../../../../../state-transition/test/perf/util.js"; import {getPubkeysForIndices} from "../../../../../src/api/impl/validator/utils.js"; @@ -36,7 +35,7 @@ describe("api / impl / validator", () => { fn: () => { for (let i = 0; i < reqCount; i++) { const pubkey = state.epochCtx.index2pubkey[i]; - pubkey.toBytes(PointFormat.compressed); + pubkey.toBytes(); } }, }); diff --git a/packages/beacon-node/test/perf/bls/bls.test.ts b/packages/beacon-node/test/perf/bls/bls.test.ts index a982cc55e499..988052f4a95c 100644 --- a/packages/beacon-node/test/perf/bls/bls.test.ts +++ b/packages/beacon-node/test/perf/bls/bls.test.ts @@ -1,7 +1,14 @@ import crypto from "node:crypto"; import {itBench} from "@dapplion/benchmark"; -import bls from "@chainsafe/bls"; -import {CoordType, type PublicKey, type SecretKey} from "@chainsafe/bls/types"; +import { + PublicKey, + SecretKey, + Signature, + aggregatePublicKeys, + aggregateSignatures, + verify, + verifyMultipleAggregateSignatures, +} from "@chainsafe/blst"; import {linspace} from "../../../src/util/numpy.js"; describe("BLS ops", function () { @@ -20,7 +27,7 @@ describe("BLS ops", function () { const bytes = new Uint8Array(32); const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); dataView.setUint32(0, i + 1, true); - const secretKey = bls.SecretKey.fromBytes(bytes); + const secretKey = SecretKey.fromKeygen(bytes); const publicKey = secretKey.toPublicKey(); keypair = {secretKey, publicKey}; keypairs.set(i, keypair); @@ -53,8 +60,8 @@ describe("BLS ops", function () { } // Note: getSet() caches the value, does not re-compute every time - itBench({id: `BLS verify - ${bls.implementation}`, beforeEach: () => getSet(0)}, (set) => { - const isValid = bls.Signature.fromBytes(set.signature).verify(set.publicKey, set.message); + itBench({id: "BLS verify - blst", beforeEach: () => getSet(0)}, (set) => { + const isValid = verify(set.message, set.publicKey, Signature.fromBytes(set.signature)); if (!isValid) throw Error("Invalid"); }); @@ -62,14 +69,14 @@ describe("BLS ops", function () { // We may want to bundle up to 32 sets in a single batch. for (const count of [3, 8, 32, 64, 128]) { itBench({ - id: `BLS verifyMultipleSignatures ${count} - ${bls.implementation}`, + id: `BLS verifyMultipleSignatures ${count} - blst`, beforeEach: () => linspace(0, count - 1).map((i) => getSet(i)), fn: (sets) => { - const isValid = bls.Signature.verifyMultipleSignatures( + const isValid = verifyMultipleAggregateSignatures( sets.map((set) => ({ - publicKey: set.publicKey, - message: set.message, - signature: bls.Signature.fromBytes(set.signature), + pk: set.publicKey, + msg: set.message, + sig: Signature.fromBytes(set.signature), })) ); if (!isValid) throw Error("Invalid"); @@ -86,7 +93,7 @@ describe("BLS ops", function () { fn: () => { for (const signature of signatures) { // true = validate signature - bls.Signature.fromBytes(signature, CoordType.affine, true); + Signature.fromBytes(signature, true); } }, }); @@ -97,15 +104,13 @@ describe("BLS ops", function () { // TODO: figure out why it does not work with 256 or more for (const count of [3, 8, 32, 64, 128]) { itBench({ - id: `BLS verifyMultipleSignatures - same message - ${count} - ${bls.implementation}`, + id: `BLS verifyMultipleSignatures - same message - ${count} - blst`, beforeEach: () => linspace(0, count - 1).map((i) => getSetSameMessage(i)), fn: (sets) => { // aggregate and verify aggregated signatures - const aggregatedPubkey = bls.PublicKey.aggregate(sets.map((set) => set.publicKey)); - const aggregatedSignature = bls.Signature.aggregate( - sets.map((set) => bls.Signature.fromBytes(set.signature, CoordType.affine, false)) - ); - const isValid = aggregatedSignature.verify(aggregatedPubkey, sets[0].message); + const aggregatedPubkey = aggregatePublicKeys(sets.map((set) => set.publicKey)); + const aggregatedSignature = aggregateSignatures(sets.map((set) => Signature.fromBytes(set.signature))); + const isValid = verify(sets[0].message, aggregatedPubkey, aggregatedSignature); if (!isValid) throw Error("Invalid"); }, }); @@ -114,10 +119,10 @@ describe("BLS ops", function () { // Attestations in Mainnet contain 128 max on average for (const count of [32, 128]) { itBench({ - id: `BLS aggregatePubkeys ${count} - ${bls.implementation}`, + id: `BLS aggregatePubkeys ${count} - blst`, beforeEach: () => linspace(0, count - 1).map((i) => getKeypair(i).publicKey), fn: (pubkeys) => { - bls.PublicKey.aggregate(pubkeys); + aggregatePublicKeys(pubkeys); }, }); } diff --git a/packages/beacon-node/test/spec/bls/bls.ts b/packages/beacon-node/test/spec/bls/bls.ts index c8d42ad84c5f..5af15bcb8eb2 100644 --- a/packages/beacon-node/test/spec/bls/bls.ts +++ b/packages/beacon-node/test/spec/bls/bls.ts @@ -1,7 +1,14 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; +import { + PublicKey, + SecretKey, + Signature, + aggregateSignatures, + aggregateVerify, + fastAggregateVerify, + verifyMultipleAggregateSignatures, + verify as _verify, +} from "@chainsafe/blst"; import {fromHexString} from "@chainsafe/ssz"; -import {toHexString} from "@lodestar/utils"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -31,7 +38,15 @@ export const testFnByType: Record any)> = { */ function aggregate_verify(input: {pubkeys: string[]; messages: string[]; signature: string}): boolean { const {pubkeys, messages, signature} = input; - return bls.verifyMultiple(pubkeys.map(fromHexString), messages.map(fromHexString), fromHexString(signature)); + try { + return aggregateVerify( + messages.map(fromHexString), + pubkeys.map((pk) => PublicKey.fromHex(pk)), + Signature.fromHex(signature) + ); + } catch (e) { + return false; + } } /** @@ -41,8 +56,8 @@ function aggregate_verify(input: {pubkeys: string[]; messages: string[]; signatu * ``` */ function aggregate(input: string[]): string { - const pks = input.map((pkHex) => bls.Signature.fromHex(pkHex)); - const agg = bls.Signature.aggregate(pks); + const pks = input.map((pkHex) => Signature.fromHex(pkHex)); + const agg = aggregateSignatures(pks); return agg.toHex(); } @@ -58,9 +73,10 @@ function aggregate(input: string[]): string { function fast_aggregate_verify(input: {pubkeys: string[]; message: string; signature: string}): boolean | null { const {pubkeys, message, signature} = input; try { - return bls.Signature.fromBytes(fromHexString(signature), undefined, true).verifyAggregate( - pubkeys.map((hex) => bls.PublicKey.fromBytes(fromHexString(hex), CoordType.jacobian, true)), - fromHexString(message) + return fastAggregateVerify( + fromHexString(message), + pubkeys.map((hex) => PublicKey.fromHex(hex, true)), + Signature.fromHex(signature, true) ); } catch (e) { return false; @@ -80,11 +96,11 @@ function fast_aggregate_verify(input: {pubkeys: string[]; message: string; signa function batch_verify(input: {pubkeys: string[]; messages: string[]; signatures: string[]}): boolean | null { const {pubkeys, messages, signatures} = input; try { - return bls.Signature.verifyMultipleSignatures( + return verifyMultipleAggregateSignatures( pubkeys.map((pubkey, i) => ({ - publicKey: bls.PublicKey.fromBytes(fromHexString(pubkey), CoordType.jacobian, true), - message: fromHexString(messages[i]), - signature: bls.Signature.fromBytes(fromHexString(signatures[i]), undefined, true), + pk: PublicKey.fromHex(pubkey, true), + msg: fromHexString(messages[i]), + sig: Signature.fromHex(signatures[i], true), })) ); } catch (e) { @@ -103,8 +119,8 @@ function batch_verify(input: {pubkeys: string[]; messages: string[]; signatures: */ function sign(input: {privkey: string; message: string}): string | null { const {privkey, message} = input; - const signature = bls.sign(fromHexString(privkey), fromHexString(message)); - return toHexString(signature); + const signature = SecretKey.fromHex(privkey).sign(fromHexString(message)); + return signature.toHex(); } /** @@ -119,7 +135,11 @@ function sign(input: {privkey: string; message: string}): string | null { */ function verify(input: {pubkey: string; message: string; signature: string}): boolean { const {pubkey, message, signature} = input; - return bls.verify(fromHexString(pubkey), fromHexString(message), fromHexString(signature)); + try { + return _verify(fromHexString(message), PublicKey.fromHex(pubkey), Signature.fromHex(signature)); + } catch (e) { + return false; + } } /** @@ -131,7 +151,7 @@ function verify(input: {pubkey: string; message: string; signature: string}): bo */ function deserialization_G1(input: {pubkey: string}): boolean { try { - bls.PublicKey.fromBytes(fromHexString(input.pubkey), CoordType.jacobian, true); + PublicKey.fromHex(input.pubkey, true); return true; } catch (e) { return false; @@ -147,7 +167,7 @@ function deserialization_G1(input: {pubkey: string}): boolean { */ function deserialization_G2(input: {signature: string}): boolean { try { - bls.Signature.fromBytes(fromHexString(input.signature), undefined, true); + Signature.fromHex(input.signature, true); return true; } catch (e) { return false; diff --git a/packages/beacon-node/test/spec/general/bls.ts b/packages/beacon-node/test/spec/general/bls.ts index 88c1d79bcb79..010a5b9be53d 100644 --- a/packages/beacon-node/test/spec/general/bls.ts +++ b/packages/beacon-node/test/spec/general/bls.ts @@ -1,8 +1,15 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; import {fromHexString} from "@chainsafe/ssz"; +import { + PublicKey, + SecretKey, + Signature, + aggregateSerializedPublicKeys, + aggregateSignatures, + aggregateVerify, + fastAggregateVerify, + verify as _verify, +} from "@chainsafe/blst"; import {InputType} from "@lodestar/spec-test-util"; -import {toHexString} from "@lodestar/utils"; import {TestRunnerFn} from "../utils/types.js"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -63,10 +70,14 @@ type BlsTestCase = { * output: BLS Signature -- expected output, single BLS signature or empty. * ``` */ -function aggregate(input: string[]): string { - const pks = input.map((pkHex) => bls.Signature.fromHex(pkHex)); - const agg = bls.Signature.aggregate(pks); - return agg.toHex(); +function aggregate(input: string[]): string | null { + try { + const pks = input.map((pkHex) => Signature.fromHex(pkHex)); + const agg = aggregateSignatures(pks); + return agg.toHex(); + } catch (e) { + return null; + } } /** @@ -80,7 +91,15 @@ function aggregate(input: string[]): string { */ function aggregate_verify(input: {pubkeys: string[]; messages: string[]; signature: string}): boolean { const {pubkeys, messages, signature} = input; - return bls.verifyMultiple(pubkeys.map(fromHexString), messages.map(fromHexString), fromHexString(signature)); + try { + return aggregateVerify( + messages.map(fromHexString), + pubkeys.map((pk) => PublicKey.fromHex(pk)), + Signature.fromHex(signature) + ); + } catch (e) { + return false; + } } /** @@ -95,8 +114,11 @@ function eth_aggregate_pubkeys(input: string[]): string | null { if (pk === G1_POINT_AT_INFINITY) return null; } - const agg = bls.aggregatePublicKeys(input.map((hex) => fromHexString(hex))); - return toHexString(agg); + try { + return aggregateSerializedPublicKeys(input.map((hex) => fromHexString(hex))).toHex(); + } catch (e) { + return null; + } } /** @@ -120,11 +142,15 @@ function eth_fast_aggregate_verify(input: {pubkeys: string[]; message: string; s if (pk === G1_POINT_AT_INFINITY) return false; } - return bls.verifyAggregate( - pubkeys.map((hex) => fromHexString(hex)), - fromHexString(message), - fromHexString(signature) - ); + try { + return fastAggregateVerify( + fromHexString(message), + pubkeys.map((hex) => PublicKey.fromHex(hex)), + Signature.fromHex(signature) + ); + } catch (e) { + return false; + } } /** @@ -139,9 +165,10 @@ function eth_fast_aggregate_verify(input: {pubkeys: string[]; message: string; s function fast_aggregate_verify(input: {pubkeys: string[]; message: string; signature: string}): boolean | null { const {pubkeys, message, signature} = input; try { - return bls.Signature.fromBytes(fromHexString(signature), undefined, true).verifyAggregate( - pubkeys.map((hex) => bls.PublicKey.fromBytes(fromHexString(hex), CoordType.jacobian, true)), - fromHexString(message) + return fastAggregateVerify( + fromHexString(message), + pubkeys.map((hex) => PublicKey.fromHex(hex, true)), + Signature.fromHex(signature, true) ); } catch (e) { return false; @@ -156,8 +183,11 @@ function fast_aggregate_verify(input: {pubkeys: string[]; message: string; signa */ function sign(input: {privkey: string; message: string}): string | null { const {privkey, message} = input; - const signature = bls.sign(fromHexString(privkey), fromHexString(message)); - return toHexString(signature); + try { + return SecretKey.fromHex(privkey).sign(fromHexString(message)).toHex(); + } catch (e) { + return null; + } } /** @@ -169,5 +199,9 @@ function sign(input: {privkey: string; message: string}): string | null { */ function verify(input: {pubkey: string; message: string; signature: string}): boolean { const {pubkey, message, signature} = input; - return bls.verify(fromHexString(pubkey), fromHexString(message), fromHexString(signature)); + try { + return _verify(fromHexString(message), PublicKey.fromHex(pubkey), Signature.fromHex(signature)); + } catch (e) { + return false; + } } diff --git a/packages/beacon-node/test/spec/presets/light_client/sync.ts b/packages/beacon-node/test/spec/presets/light_client/sync.ts index 4b264e5b65e4..bfd3d0d0bb3d 100644 --- a/packages/beacon-node/test/spec/presets/light_client/sync.ts +++ b/packages/beacon-node/test/spec/presets/light_client/sync.ts @@ -1,5 +1,4 @@ import {expect} from "vitest"; -import {init} from "@chainsafe/bls/switchable"; import {isForkLightClient} from "@lodestar/params"; import {altair, phase0, RootHex, Slot, ssz, sszTypesFor} from "@lodestar/types"; import {InputType} from "@lodestar/spec-test-util"; @@ -78,8 +77,6 @@ const UPDATE_FILE_NAME = "^(update)_([0-9a-zA-Z_]+)$"; export const sync: TestRunnerFn = (fork) => { return { testFunction: async (testcase) => { - await init("blst-native"); - // Grab only the ALTAIR_FORK_EPOCH, since the domains are the same as minimal const config = createBeaconConfig( pickConfigForkEpochs(testcase.config), diff --git a/packages/beacon-node/test/unit/chain/bls/bls.test.ts b/packages/beacon-node/test/unit/chain/bls/bls.test.ts index e5b844262632..4203d7f9768c 100644 --- a/packages/beacon-node/test/unit/chain/bls/bls.test.ts +++ b/packages/beacon-node/test/unit/chain/bls/bls.test.ts @@ -1,7 +1,5 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/blst"; -import {PublicKey} from "@chainsafe/bls/types"; import {describe, it, expect, beforeEach} from "vitest"; +import {PublicKey, SecretKey, Signature} from "@chainsafe/blst"; import {ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; import {BlsSingleThreadVerifier} from "../../../../src/chain/bls/singleThread.js"; import {BlsMultiThreadWorkerPool} from "../../../../src/chain/bls/multithread/index.js"; @@ -10,7 +8,7 @@ import {testLogger} from "../../../utils/logger.js"; describe("BlsVerifier ", function () { // take time for creating thread pool const numKeys = 3; - const secretKeys = Array.from({length: numKeys}, (_, i) => bls.SecretKey.fromKeygen(Buffer.alloc(32, i))); + const secretKeys = Array.from({length: numKeys}, (_, i) => SecretKey.fromKeygen(Buffer.alloc(32, i))); const verifiers = [ new BlsSingleThreadVerifier({metrics: null}), new BlsMultiThreadWorkerPool({}, {metrics: null, logger: testLogger()}), @@ -46,7 +44,7 @@ describe("BlsVerifier ", function () { it("should return false if at least one signature is malformed", async () => { // signature is malformed const malformedSignature = Buffer.alloc(96, 10); - expect(() => bls.Signature.fromBytes(malformedSignature, CoordType.affine, true)).toThrow(); + expect(() => Signature.fromBytes(malformedSignature, true, true)).toThrow(); sets[1].signature = malformedSignature; expect(await verifier.verifySignatureSets(sets)).toBe(false); }); @@ -79,7 +77,7 @@ describe("BlsVerifier ", function () { it("should return false for malformed signature", async () => { // signature is malformed const malformedSignature = Buffer.alloc(96, 10); - expect(() => bls.Signature.fromBytes(malformedSignature, CoordType.affine, true)).toThrow(); + expect(() => Signature.fromBytes(malformedSignature, true, true)).toThrow(); sets[1].signature = malformedSignature; expect(await verifier.verifySignatureSetsSameMessage(sets, signingRoot)).toEqual([true, false, true]); }); diff --git a/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts b/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts index 986ca074242f..f836e3621cc9 100644 --- a/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts +++ b/packages/beacon-node/test/unit/chain/genesis/genesis.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import type {SecretKey, PublicKey} from "@chainsafe/bls/types"; import {toHexString} from "@chainsafe/ssz"; import {describe, it, expect} from "vitest"; +import {PublicKey, SecretKey} from "@chainsafe/blst"; import {DOMAIN_DEPOSIT, MAX_EFFECTIVE_BALANCE} from "@lodestar/params"; import {config} from "@lodestar/config/default"; import {computeDomain, computeSigningRoot, interopSecretKey, ZERO_HASH} from "@lodestar/state-transition"; 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 3c248ad4d194..800984fa84bc 100644 --- a/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts +++ b/packages/beacon-node/test/unit/chain/opPools/aggregatedAttestationPool.test.ts @@ -1,7 +1,6 @@ -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 {SecretKey, Signature, fastAggregateVerify} from "@chainsafe/blst"; import {CachedBeaconStateAllForks, newFilledArray} from "@lodestar/state-transition"; import {FAR_FUTURE_EPOCH, ForkName, MAX_EFFECTIVE_BALANCE, SLOTS_PER_EPOCH} from "@lodestar/params"; import {ssz, phase0} from "@lodestar/types"; @@ -303,8 +302,8 @@ describe("MatchingDataAttestationGroup aggregateInto", function () { let sk2: SecretKey; beforeAll(async () => { - sk1 = bls.SecretKey.fromBytes(Buffer.alloc(32, 1)); - sk2 = bls.SecretKey.fromBytes(Buffer.alloc(32, 2)); + sk1 = SecretKey.fromBytes(Buffer.alloc(32, 1)); + sk2 = SecretKey.fromBytes(Buffer.alloc(32, 2)); attestation1.signature = sk1.sign(attestationDataRoot).toBytes(); attestation2.signature = sk2.sign(attestationDataRoot).toBytes(); }); @@ -315,7 +314,9 @@ describe("MatchingDataAttestationGroup aggregateInto", function () { aggregateInto(attWithIndex1, attWithIndex2); expect(renderBitArray(attWithIndex1.attestation.aggregationBits)).toEqual(renderBitArray(mergedBitArray)); - const aggregatedSignature = bls.Signature.fromBytes(attWithIndex1.attestation.signature, undefined, true); - expect(aggregatedSignature.verifyAggregate([sk1.toPublicKey(), sk2.toPublicKey()], attestationDataRoot)).toBe(true); + const aggregatedSignature = Signature.fromBytes(attWithIndex1.attestation.signature, true, true); + expect(fastAggregateVerify(attestationDataRoot, [sk1.toPublicKey(), sk2.toPublicKey()], aggregatedSignature)).toBe( + true + ); }); }); diff --git a/packages/beacon-node/test/unit/chain/opPools/syncCommittee.test.ts b/packages/beacon-node/test/unit/chain/opPools/syncCommittee.test.ts index 3cb5d496bf9b..507c78d560b6 100644 --- a/packages/beacon-node/test/unit/chain/opPools/syncCommittee.test.ts +++ b/packages/beacon-node/test/unit/chain/opPools/syncCommittee.test.ts @@ -1,6 +1,6 @@ -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; import {describe, it, expect, beforeEach, beforeAll, afterEach, vi, MockedObject} from "vitest"; +import {SecretKey} from "@chainsafe/blst"; import {altair} from "@lodestar/types"; import {SyncCommitteeMessagePool} from "../../../../src/chain/opPools/index.js"; import {Clock} from "../../../../src/util/clock.js"; @@ -18,7 +18,7 @@ describe("chain / opPools / SyncCommitteeMessagePool", function () { const cutOffTime = 1; beforeAll(async () => { - const sk = bls.SecretKey.fromBytes(Buffer.alloc(32, 1)); + const sk = SecretKey.fromBytes(Buffer.alloc(32, 1)); syncCommittee = { slot, beaconBlockRoot, @@ -42,7 +42,7 @@ describe("chain / opPools / SyncCommitteeMessagePool", function () { clockStub.secFromSlot.mockReturnValue(0); let contribution = cache.getContribution(subcommitteeIndex, syncCommittee.slot, syncCommittee.beaconBlockRoot); expect(contribution).not.toBeNull(); - const newSecretKey = bls.SecretKey.fromBytes(Buffer.alloc(32, 2)); + const newSecretKey = SecretKey.fromBytes(Buffer.alloc(32, 2)); const newSyncCommittee: altair.SyncCommitteeMessage = { slot: syncCommittee.slot, beaconBlockRoot, diff --git a/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts b/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts index dd303673f61e..e34a5d006272 100644 --- a/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts +++ b/packages/beacon-node/test/unit/chain/opPools/syncCommitteeContribution.test.ts @@ -1,7 +1,6 @@ -import type {SecretKey} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; import {BitArray} from "@chainsafe/ssz"; import {describe, it, expect, beforeEach, beforeAll} from "vitest"; +import {SecretKey, Signature, fastAggregateVerify} from "@chainsafe/blst"; import {newFilledArray} from "@lodestar/state-transition"; import {ssz} from "@lodestar/types"; import {SYNC_COMMITTEE_SIZE, SYNC_COMMITTEE_SUBNET_COUNT} from "@lodestar/params"; @@ -83,7 +82,7 @@ describe("aggregate", function () { let bestContributionBySubnet: Map; beforeAll(async () => { for (let i = 0; i < SYNC_COMMITTEE_SUBNET_COUNT; i++) { - sks.push(bls.SecretKey.fromBytes(Buffer.alloc(32, i + 1))); + sks.push(SecretKey.fromBytes(Buffer.alloc(32, i + 1))); } bestContributionBySubnet = new Map(); }); @@ -112,10 +111,10 @@ describe("aggregate", function () { renderBitArray(BitArray.fromBoolArray(expectSyncCommittees)) ); expect( - bls.verifyAggregate( - testSks.map((sk) => sk.toPublicKey().toBytes()), + fastAggregateVerify( blockRoot, - syncAggregate.syncCommitteeSignature + testSks.map((sk) => sk.toPublicKey()), + Signature.fromBytes(syncAggregate.syncCommitteeSignature) ) ).toBe(true); }); diff --git a/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts b/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts index cc6dc26f1a36..24fae8a03f0b 100644 --- a/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/attestation/validateGossipAttestationsSameAttData.test.ts @@ -1,6 +1,5 @@ -import bls from "@chainsafe/bls"; -import type {PublicKey, SecretKey} from "@chainsafe/bls/types"; import {afterEach, beforeEach, describe, expect, it, vi} from "vitest"; +import {PublicKey, SecretKey} from "@chainsafe/blst"; import {ForkName} from "@lodestar/params"; import {SignatureSetType} from "@lodestar/state-transition"; import {ssz} from "@lodestar/types"; @@ -49,7 +48,7 @@ describe("validateGossipAttestationsSameAttData", () => { const bytes = new Uint8Array(32); const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); dataView.setUint32(0, i + 1, true); - const secretKey = bls.SecretKey.fromBytes(bytes); + const secretKey = SecretKey.fromKeygen(bytes); const publicKey = secretKey.toPublicKey(); keypair = {secretKey, publicKey}; keypairs.set(i, keypair); diff --git a/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts b/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts index f83b900beb69..8d5032ed3ec7 100644 --- a/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/blsToExecutionChange.test.ts @@ -1,7 +1,6 @@ import {digest} from "@chainsafe/as-sha256"; -import bls from "@chainsafe/bls"; -import {PointFormat} from "@chainsafe/bls/types"; import {describe, it, beforeEach, afterEach, vi} from "vitest"; +import {SecretKey} from "@chainsafe/blst"; import {config as defaultConfig} from "@lodestar/config/default"; import {computeSigningRoot} from "@lodestar/state-transition"; import {capella, ssz} from "@lodestar/types"; @@ -29,12 +28,12 @@ describe("validate bls to execution change", () => { // Validator has to be active for long enough stateEmpty.slot = defaultConfig.SHARD_COMMITTEE_PERIOD * SLOTS_PER_EPOCH; // A withdrawal key which we will keep same on the two vals we generate - const wsk = bls.SecretKey.fromKeygen(); + const wsk = SecretKey.fromKeygen(Buffer.alloc(32)); // Generate and add first val - const sk1 = bls.SecretKey.fromKeygen(); - const pubkey1 = sk1.toPublicKey().toBytes(PointFormat.compressed); - const fromBlsPubkey = wsk.toPublicKey().toBytes(PointFormat.compressed); + const sk1 = SecretKey.fromKeygen(Buffer.alloc(32, 1)); + const pubkey1 = sk1.toPublicKey().toBytes(); + const fromBlsPubkey = wsk.toPublicKey().toBytes(); const withdrawalCredentials = digest(fromBlsPubkey); withdrawalCredentials[0] = BLS_WITHDRAWAL_PREFIX; const validator = ssz.phase0.Validator.toViewDU({ @@ -50,8 +49,8 @@ describe("validate bls to execution change", () => { stateEmpty.validators[0] = validator; // Gen and add second val - const sk2 = bls.SecretKey.fromKeygen(); - const pubkey2 = sk2.toPublicKey().toBytes(PointFormat.compressed); + const sk2 = SecretKey.fromKeygen(Buffer.alloc(32, 2)); + const pubkey2 = sk2.toPublicKey().toBytes(); // Set the next validator to already eth1 credential const withdrawalCredentialsTwo = digest(fromBlsPubkey); withdrawalCredentialsTwo[0] = ETH1_ADDRESS_WITHDRAWAL_PREFIX; diff --git a/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts b/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts index 3966815c28ce..d556ff610961 100644 --- a/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts +++ b/packages/beacon-node/test/unit/chain/validation/voluntaryExit.test.ts @@ -1,6 +1,5 @@ -import bls from "@chainsafe/bls"; -import {PointFormat} from "@chainsafe/bls/types"; import {describe, it, beforeEach, beforeAll, vi, afterEach} from "vitest"; +import {SecretKey} from "@chainsafe/blst"; import {config} from "@lodestar/config/default"; import { CachedBeaconStateAllForks, @@ -25,7 +24,7 @@ describe("validate voluntary exit", () => { let opPool: MockedBeaconChain["opPool"]; beforeAll(() => { - const sk = bls.SecretKey.fromKeygen(); + const sk = SecretKey.fromKeygen(Buffer.alloc(32)); const stateEmpty = ssz.phase0.BeaconState.defaultValue(); @@ -34,7 +33,7 @@ describe("validate voluntary exit", () => { // Add a validator that's active since genesis and ready to exit const validator = ssz.phase0.Validator.toViewDU({ - pubkey: sk.toPublicKey().toBytes(PointFormat.compressed), + pubkey: sk.toPublicKey().toBytes(), withdrawalCredentials: Buffer.alloc(32, 0), effectiveBalance: 32e9, slashed: false, diff --git a/packages/beacon-node/test/utils/cache.ts b/packages/beacon-node/test/utils/cache.ts index 767956226776..9d5d3566c99d 100644 --- a/packages/beacon-node/test/utils/cache.ts +++ b/packages/beacon-node/test/utils/cache.ts @@ -1,4 +1,4 @@ -import type {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {toHexString} from "@chainsafe/ssz"; export function memoOnce(fn: () => R): () => R { diff --git a/packages/beacon-node/test/utils/node/validator.ts b/packages/beacon-node/test/utils/node/validator.ts index c9a705ae3dc1..4ec60dcc8b4f 100644 --- a/packages/beacon-node/test/utils/node/validator.ts +++ b/packages/beacon-node/test/utils/node/validator.ts @@ -1,6 +1,6 @@ import tmp from "tmp"; import {vi} from "vitest"; -import type {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {LevelDbController} from "@lodestar/db"; import {interopSecretKey} from "@lodestar/state-transition"; import {SlashingProtection, Validator, Signer, SignerType, ValidatorProposerConfig} from "@lodestar/validator"; diff --git a/packages/beacon-node/test/utils/state.ts b/packages/beacon-node/test/utils/state.ts index 10a653bf9498..1e9f614e8093 100644 --- a/packages/beacon-node/test/utils/state.ts +++ b/packages/beacon-node/test/utils/state.ts @@ -1,4 +1,4 @@ -import bls from "@chainsafe/bls"; +import {SecretKey} from "@chainsafe/blst"; import {config as minimalConfig} from "@lodestar/config/default"; import { BeaconStateAllForks, @@ -55,7 +55,7 @@ export function generateState( opts.validators ?? (withPubkey ? Array.from({length: numValidators}, (_, i) => { - const sk = bls.SecretKey.fromBytes(Buffer.alloc(32, i + 1)); + const sk = SecretKey.fromBytes(Buffer.alloc(32, i + 1)); return generateValidator({ ...validatorOpts, pubkey: sk.toPublicKey().toBytes(), diff --git a/packages/cli/package.json b/packages/cli/package.json index 75cde84082ea..cbeda803ba7e 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -51,10 +51,9 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keygen": "^0.4.0", "@chainsafe/bls-keystore": "^3.1.0", - "@chainsafe/blst": "^0.2.11", + "@chainsafe/blst": "^2.0.1", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", "@chainsafe/persistent-merkle-tree": "^0.7.1", diff --git a/packages/cli/src/cmds/validator/blsToExecutionChange.ts b/packages/cli/src/cmds/validator/blsToExecutionChange.ts index 960662b108ea..3a2fabcc37eb 100644 --- a/packages/cli/src/cmds/validator/blsToExecutionChange.ts +++ b/packages/cli/src/cmds/validator/blsToExecutionChange.ts @@ -1,6 +1,5 @@ import {fromHexString} from "@chainsafe/ssz"; -import bls from "@chainsafe/bls"; -import {PointFormat} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {computeSigningRoot} from "@lodestar/state-transition"; import {DOMAIN_BLS_TO_EXECUTION_CHANGE, ForkName} from "@lodestar/params"; import {createBeaconConfig} from "@lodestar/config"; @@ -68,8 +67,8 @@ like to choose for BLS To Execution Change.", throw new Error(`Validator pubkey ${publicKey} not found in state`); } - const blsPrivkey = bls.SecretKey.fromBytes(fromHexString(args.fromBlsPrivkey)); - const fromBlsPubkey = blsPrivkey.toPublicKey().toBytes(PointFormat.compressed); + const blsPrivkey = SecretKey.fromBytes(fromHexString(args.fromBlsPrivkey)); + const fromBlsPubkey = blsPrivkey.toPublicKey().toBytes(); const blsToExecutionChange: capella.BLSToExecutionChange = { validatorIndex: validator.index, diff --git a/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts b/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts index 076da70adcdb..0ce0646c978a 100644 --- a/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts +++ b/packages/cli/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import path from "node:path"; -import bls from "@chainsafe/bls"; +import {SecretKey} from "@chainsafe/blst"; import {Keystore} from "@chainsafe/bls-keystore"; import {SignerLocal, SignerType} from "@lodestar/validator"; import {LogLevel, Logger} from "@lodestar/utils"; @@ -73,7 +73,7 @@ export async function decryptKeystoreDefinitions( (secretKeyBytes: Uint8Array) => { const signer: SignerLocal = { type: SignerType.Local, - secretKey: bls.SecretKey.fromBytes(secretKeyBytes), + secretKey: SecretKey.fromBytes(secretKeyBytes), }; signers[index] = signer; @@ -107,7 +107,7 @@ export async function decryptKeystoreDefinitions( const signer: SignerLocal = { type: SignerType.Local, - secretKey: bls.SecretKey.fromBytes(secretKeyBytes), + secretKey: SecretKey.fromBytes(secretKeyBytes), }; signers[index] = signer; diff --git a/packages/cli/src/cmds/validator/keymanager/impl.ts b/packages/cli/src/cmds/validator/keymanager/impl.ts index 36ded66976b1..b3b7c9f458bc 100644 --- a/packages/cli/src/cmds/validator/keymanager/impl.ts +++ b/packages/cli/src/cmds/validator/keymanager/impl.ts @@ -1,6 +1,6 @@ -import bls from "@chainsafe/bls"; import {Keystore} from "@chainsafe/bls-keystore"; import {fromHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import { DeleteRemoteKeyStatus, DeletionStatus, @@ -149,7 +149,7 @@ export class KeymanagerApi implements Api { decryptKeystores.queue( {keystoreStr, password}, async (secretKeyBytes: Uint8Array) => { - const secretKey = bls.SecretKey.fromBytes(secretKeyBytes); + const secretKey = SecretKey.fromBytes(secretKeyBytes); // Persist the key to disk for restarts, before adding to in-memory store // If the keystore exist and has a lock it will throw diff --git a/packages/cli/src/cmds/validator/keymanager/keystoreCache.ts b/packages/cli/src/cmds/validator/keymanager/keystoreCache.ts index 1f1c6cd6e79f..85b1702892ee 100644 --- a/packages/cli/src/cmds/validator/keymanager/keystoreCache.ts +++ b/packages/cli/src/cmds/validator/keymanager/keystoreCache.ts @@ -1,8 +1,7 @@ import fs from "node:fs"; import path from "node:path"; -import bls from "@chainsafe/bls"; import {Keystore} from "@chainsafe/bls-keystore"; -import {PointFormat} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {SignerLocal, SignerType} from "@lodestar/validator"; import {fromHex, toHex} from "@lodestar/utils"; import {writeFile600Perm} from "../../../util/file.js"; @@ -40,8 +39,8 @@ export async function loadKeystoreCache( const result: SignerLocal[] = []; for (const [index, k] of keystores.entries()) { const secretKeyBytes = Uint8Array.prototype.slice.call(secretKeyConcatenatedBytes, index * 32, (index + 1) * 32); - const secretKey = bls.SecretKey.fromBytes(secretKeyBytes); - const publicKey = secretKey.toPublicKey().toBytes(PointFormat.compressed); + const secretKey = SecretKey.fromBytes(secretKeyBytes); + const publicKey = secretKey.toPublicKey().toBytes(); if (toHex(publicKey) !== toHex(fromHex(k.pubkey))) { throw new Error( diff --git a/packages/cli/src/cmds/validator/signers/index.ts b/packages/cli/src/cmds/validator/signers/index.ts index 95daf7e69b0d..c155b52d186a 100644 --- a/packages/cli/src/cmds/validator/signers/index.ts +++ b/packages/cli/src/cmds/validator/signers/index.ts @@ -1,7 +1,6 @@ import path from "node:path"; -import bls from "@chainsafe/bls"; import {deriveEth2ValidatorKeys, deriveKeyFromMnemonic} from "@chainsafe/bls-keygen"; -import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {interopSecretKey} from "@lodestar/state-transition"; import {externalSignerGetKeys, Signer, SignerType} from "@lodestar/validator"; import {LogLevel, Logger, isValidHttpUrl} from "@lodestar/utils"; @@ -72,7 +71,7 @@ export async function getSignersFromArgs( const indexes = parseRange(args.mnemonicIndexes); return indexes.map((index) => ({ type: SignerType.Local, - secretKey: bls.SecretKey.fromBytes(deriveEth2ValidatorKeys(masterSK, index).signing), + secretKey: SecretKey.fromBytes(deriveEth2ValidatorKeys(masterSK, index).signing), })); } @@ -150,7 +149,7 @@ export async function getSignersFromArgs( export function getSignerPubkeyHex(signer: Signer): string { switch (signer.type) { case SignerType.Local: - return toHexString(signer.secretKey.toPublicKey().toBytes()); + return signer.secretKey.toPublicKey().toHex(); case SignerType.Remote: return signer.pubkey; diff --git a/packages/cli/src/cmds/validator/voluntaryExit.ts b/packages/cli/src/cmds/validator/voluntaryExit.ts index a08f33eb6bad..279076b619f2 100644 --- a/packages/cli/src/cmds/validator/voluntaryExit.ts +++ b/packages/cli/src/cmds/validator/voluntaryExit.ts @@ -1,5 +1,5 @@ import inquirer from "inquirer"; -import bls from "@chainsafe/bls"; +import {Signature} from "@chainsafe/blst"; import { computeEpochAtSlot, computeSigningRoot, @@ -8,7 +8,7 @@ import { } from "@lodestar/state-transition"; import {createBeaconConfig, BeaconConfig} from "@lodestar/config"; import {phase0, ssz, ValidatorIndex, Epoch} from "@lodestar/types"; -import {CliCommand, toHex} from "@lodestar/utils"; +import {CliCommand, fromHex, toHex} from "@lodestar/utils"; import {externalSignerPostSignature, SignableMessageType, Signer, SignerType} from "@lodestar/validator"; import {ApiClient, getClient} from "@lodestar/api"; import {ensure0xPrefix, YargsError, wrapError} from "../../util/index.js"; @@ -161,7 +161,7 @@ async function processVoluntaryExit( data: voluntaryExit, type: SignableMessageType.VOLUNTARY_EXIT, }); - signature = bls.Signature.fromHex(signatureHex); + signature = Signature.fromBytes(fromHex(signatureHex)); break; } default: diff --git a/packages/cli/src/util/format.ts b/packages/cli/src/util/format.ts index e673fa4d4408..01c2753193a4 100644 --- a/packages/cli/src/util/format.ts +++ b/packages/cli/src/util/format.ts @@ -1,5 +1,4 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/blst"; +import {PublicKey} from "@chainsafe/blst"; import {fromHexString} from "@chainsafe/ssz"; /** @@ -52,7 +51,7 @@ export function parseRange(range: string): number[] { export function assertValidPubkeysHex(pubkeysHex: string[]): void { for (const pubkeyHex of pubkeysHex) { const pubkeyBytes = fromHexString(pubkeyHex); - bls.PublicKey.fromBytes(pubkeyBytes, CoordType.jacobian, true); + PublicKey.fromBytes(pubkeyBytes, true); } } 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 0f4d0126bb20..8d3dbb989b5d 100644 --- a/packages/cli/test/unit/cmds/validator/keymanager/keystoreCache.test.ts +++ b/packages/cli/test/unit/cmds/validator/keymanager/keystoreCache.test.ts @@ -3,7 +3,7 @@ import {randomBytes} from "node:crypto"; import {describe, it, expect, beforeEach, vi} from "vitest"; import tmp from "tmp"; import {Keystore} from "@chainsafe/bls-keystore"; -import bls from "@chainsafe/bls"; +import {SecretKey} from "@chainsafe/blst"; import {interopSecretKey} from "@lodestar/state-transition"; import {SignerLocal, SignerType} from "@lodestar/validator"; import {loadKeystoreCache, writeKeystoreCache} from "../../../../../src/cmds/validator/keymanager/keystoreCache.js"; @@ -27,7 +27,7 @@ describe("keystoreCache", () => { keystoreCacheFile = tmp.tmpNameSync({postfix: ".cache"}); for (let i = 0; i < numberOfSigners; i++) { - const secretKey = bls.SecretKey.fromBytes(interopSecretKey(i).toBytes()); + const secretKey = SecretKey.fromBytes(interopSecretKey(i).toBytes()); const keystorePath = tmp.tmpNameSync({postfix: ".json"}); const password = secretKey.toHex(); const keystore = await Keystore.create( diff --git a/packages/cli/test/utils/crucible/assertions/nodeAssertion.ts b/packages/cli/test/utils/crucible/assertions/nodeAssertion.ts index 69039accb182..9659cc34e7bf 100644 --- a/packages/cli/test/utils/crucible/assertions/nodeAssertion.ts +++ b/packages/cli/test/utils/crucible/assertions/nodeAssertion.ts @@ -1,5 +1,6 @@ -import type {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {routes} from "@lodestar/api/beacon"; +import {toHex} from "@lodestar/utils"; import {AssertionResult, ValidatorClientKeys, Assertion, ValidatorClient} from "../interfaces.js"; import {arrayEquals} from "../utils/index.js"; import {neverMatcher} from "./matchers.js"; @@ -38,7 +39,7 @@ export const nodeAssertion: Assertion<"node", {health: number; keyManagerKeys: s } const expectedPublicKeys = node.validator - ? getAllKeys(node.validator.keys).map((k) => k.toPublicKey().toHex()) + ? getAllKeys(node.validator.keys).map((k) => toHex(k.toPublicKey().toBytes())) : []; if (!arrayEquals(keyManagerKeys.sort(), expectedPublicKeys.sort())) { diff --git a/packages/cli/test/utils/crucible/externalSignerServer.ts b/packages/cli/test/utils/crucible/externalSignerServer.ts index 25071d1ee545..bd8576d214c2 100644 --- a/packages/cli/test/utils/crucible/externalSignerServer.ts +++ b/packages/cli/test/utils/crucible/externalSignerServer.ts @@ -1,6 +1,6 @@ -import type {SecretKey} from "@chainsafe/bls/types"; import {fromHexString} from "@chainsafe/ssz"; import {fastify, FastifyInstance} from "fastify"; +import {SecretKey} from "@chainsafe/blst"; import {EXTERNAL_SIGNER_BASE_PORT} from "./constants.js"; /* eslint-disable no-console */ diff --git a/packages/cli/test/utils/crucible/interfaces.ts b/packages/cli/test/utils/crucible/interfaces.ts index 44358561cea5..db4b1f3b8901 100644 --- a/packages/cli/test/utils/crucible/interfaces.ts +++ b/packages/cli/test/utils/crucible/interfaces.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import {ChildProcess} from "node:child_process"; -import type {SecretKey} from "@chainsafe/bls/types"; import {Web3} from "web3"; +import {SecretKey} from "@chainsafe/blst"; import {ApiClient} from "@lodestar/api"; import {ApiClient as KeyManagerApi} from "@lodestar/api/keymanager"; import {ChainForkConfig} from "@lodestar/config"; diff --git a/packages/flare/package.json b/packages/flare/package.json index c735642ad8e4..a962bf3ddc2d 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -58,7 +58,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "7.1.3", + "@chainsafe/blst": "^2.0.1", "@chainsafe/bls-keygen": "^0.4.0", "@lodestar/api": "^1.20.2", "@lodestar/config": "^1.20.2", diff --git a/packages/flare/src/cmds/selfSlashAttester.ts b/packages/flare/src/cmds/selfSlashAttester.ts index 6c42372f45c7..8b43e6a92cb0 100644 --- a/packages/flare/src/cmds/selfSlashAttester.ts +++ b/packages/flare/src/cmds/selfSlashAttester.ts @@ -1,5 +1,4 @@ -import bls from "@chainsafe/bls"; -import type {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey, aggregateSignatures} from "@chainsafe/blst"; import {getClient} from "@lodestar/api"; import {phase0, ssz} from "@lodestar/types"; import {config as chainConfig} from "@lodestar/config/default"; @@ -149,5 +148,5 @@ function signAttestationDataBigint( const signingRoot = computeSigningRoot(ssz.phase0.AttestationDataBigint, data, proposerDomain); const sigs = sks.map((sk) => sk.sign(signingRoot)); - return bls.Signature.aggregate(sigs).toBytes(); + return aggregateSignatures(sigs).toBytes(); } diff --git a/packages/flare/src/cmds/selfSlashProposer.ts b/packages/flare/src/cmds/selfSlashProposer.ts index 0b71d5558af8..8b11ff2ce4dc 100644 --- a/packages/flare/src/cmds/selfSlashProposer.ts +++ b/packages/flare/src/cmds/selfSlashProposer.ts @@ -1,4 +1,4 @@ -import type {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {getClient} from "@lodestar/api"; import {phase0, ssz} from "@lodestar/types"; import {config as chainConfig} from "@lodestar/config/default"; diff --git a/packages/flare/src/util/deriveSecretKeys.ts b/packages/flare/src/util/deriveSecretKeys.ts index 272cf87c09c4..5017fc6e7508 100644 --- a/packages/flare/src/util/deriveSecretKeys.ts +++ b/packages/flare/src/util/deriveSecretKeys.ts @@ -1,6 +1,5 @@ -import bls from "@chainsafe/bls"; -import type {SecretKey} from "@chainsafe/bls/types"; import {deriveEth2ValidatorKeys, deriveKeyFromMnemonic} from "@chainsafe/bls-keygen"; +import {SecretKey} from "@chainsafe/blst"; import {interopSecretKey} from "@lodestar/state-transition"; import {CliCommandOptions} from "@lodestar/utils"; import {YargsError} from "./errors.js"; @@ -42,7 +41,7 @@ export function deriveSecretKeys(args: SecretKeysArgs): SecretKey[] { return indexes.map((index) => { const {signing} = deriveEth2ValidatorKeys(masterSK, index); - return bls.SecretKey.fromBytes(signing); + return SecretKey.fromBytes(signing); }); } diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 8b433375f07f..6576bddfee6a 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -74,6 +74,7 @@ }, "dependencies": { "@chainsafe/bls": "7.1.3", + "@chainsafe/blst": "^0.2.0", "@chainsafe/persistent-merkle-tree": "^0.7.1", "@chainsafe/ssz": "^0.15.1", "@lodestar/api": "^1.20.2", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index b032f5204af3..c9c16a672c18 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -59,8 +59,7 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/bls": "7.1.3", - "@chainsafe/blst": "^0.2.11", + "@chainsafe/blst": "^2.0.1", "@chainsafe/persistent-merkle-tree": "^0.7.1", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.15.1", diff --git a/packages/state-transition/src/block/processDeposit.ts b/packages/state-transition/src/block/processDeposit.ts index dae37d5d0afe..7ade79fd7739 100644 --- a/packages/state-transition/src/block/processDeposit.ts +++ b/packages/state-transition/src/block/processDeposit.ts @@ -1,5 +1,4 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; +import {PublicKey, Signature, verify} from "@chainsafe/blst"; import {phase0, ssz} from "@lodestar/types"; import {verifyMerkleBranch} from "@lodestar/utils"; @@ -56,9 +55,9 @@ export function processDeposit(fork: ForkSeq, state: CachedBeaconStateAllForks, const signingRoot = computeSigningRoot(ssz.phase0.DepositMessage, depositMessage, domain); try { // Pubkeys must be checked for group + inf. This must be done only once when the validator deposit is processed - const publicKey = bls.PublicKey.fromBytes(pubkey, CoordType.affine, true); - const signature = bls.Signature.fromBytes(deposit.data.signature, CoordType.affine, true); - if (!signature.verify(publicKey, signingRoot)) { + const publicKey = PublicKey.fromBytes(pubkey, true); + const signature = Signature.fromBytes(deposit.data.signature, true); + if (!verify(signingRoot, publicKey, signature)) { return; } } catch (e) { diff --git a/packages/state-transition/src/cache/epochCache.ts b/packages/state-transition/src/cache/epochCache.ts index 9565898eb09d..ae2e5786ef28 100644 --- a/packages/state-transition/src/cache/epochCache.ts +++ b/packages/state-transition/src/cache/epochCache.ts @@ -1,5 +1,4 @@ -import {CoordType} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; +import {PublicKey} from "@chainsafe/blst"; import {BLSSignature, CommitteeIndex, Epoch, Slot, ValidatorIndex, phase0, SyncPeriod} from "@lodestar/types"; import {createBeaconConfig, BeaconConfig, ChainConfig} from "@lodestar/config"; import { @@ -762,7 +761,7 @@ export class EpochCache { addPubkey(index: ValidatorIndex, pubkey: Uint8Array): void { this.pubkey2index.set(pubkey, index); - this.index2pubkey[index] = bls.PublicKey.fromBytes(pubkey, CoordType.jacobian); // Optimize for aggregation + this.index2pubkey[index] = PublicKey.fromBytes(pubkey); // Optimize for aggregation } getShufflingAtSlot(slot: Slot): EpochShuffling { diff --git a/packages/state-transition/src/cache/pubkeyCache.ts b/packages/state-transition/src/cache/pubkeyCache.ts index fdc343ff4ec7..0fd7a80fe990 100644 --- a/packages/state-transition/src/cache/pubkeyCache.ts +++ b/packages/state-transition/src/cache/pubkeyCache.ts @@ -1,5 +1,4 @@ -import {CoordType, PublicKey} from "@chainsafe/bls/types"; -import bls from "@chainsafe/bls"; +import {PublicKey} from "@chainsafe/blst"; import {ValidatorIndex} from "@lodestar/types"; import {BeaconStateAllForks} from "./types.js"; @@ -72,6 +71,6 @@ export function syncPubkeys( // Pubkeys must be checked for group + inf. This must be done only once when the validator deposit is processed. // Afterwards any public key is the state consider validated. // > Do not do any validation here - index2pubkey.push(bls.PublicKey.fromBytes(pubkey, CoordType.jacobian)); // Optimize for aggregation + index2pubkey.push(PublicKey.fromBytes(pubkey)); // Optimize for aggregation } } diff --git a/packages/state-transition/src/cache/stateCache.ts b/packages/state-transition/src/cache/stateCache.ts index 8b45152a3646..f4e637e5d665 100644 --- a/packages/state-transition/src/cache/stateCache.ts +++ b/packages/state-transition/src/cache/stateCache.ts @@ -1,5 +1,4 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; +import {PublicKey} from "@chainsafe/blst"; import {BeaconConfig} from "@lodestar/config"; import {loadState} from "../util/loadState/loadState.js"; import {EpochCache, EpochCacheImmutableData, EpochCacheOpts} from "./epochCache.js"; @@ -180,7 +179,7 @@ export function loadCachedBeaconState bls.PublicKey.fromBytes(pk, CoordType.jacobian)); + const pubkeysModObj = pubkeysMod.map((pk) => PublicKey.fromBytes(pk)); const pubkeys = Array.from({length: vc}, (_, i) => pubkeysMod[i % keypairsMod]); return {pubkeysMod, pubkeysModObj, pubkeys}; } diff --git a/packages/state-transition/test/perf/util/loadState/loadState.test.ts b/packages/state-transition/test/perf/util/loadState/loadState.test.ts index 5d40c64f6ab4..a8a1b1399dc5 100644 --- a/packages/state-transition/test/perf/util/loadState/loadState.test.ts +++ b/packages/state-transition/test/perf/util/loadState/loadState.test.ts @@ -1,6 +1,5 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; import {itBench, setBenchOpts} from "@dapplion/benchmark"; +import {PublicKey} from "@chainsafe/blst"; import {loadState} from "../../../../src/util/loadState/loadState.js"; import {createCachedBeaconState} from "../../../../src/cache/stateCache.js"; import {Index2PubkeyCache, PubkeyIndexMap} from "../../../../src/cache/pubkeyCache.js"; @@ -78,7 +77,7 @@ describe("loadState", function () { const validator = validators.getReadonly(validatorIndex); const pubkey = validator.pubkey; pubkey2index.set(pubkey, validatorIndex); - index2pubkey[validatorIndex] = bls.PublicKey.fromBytes(pubkey, CoordType.jacobian); + index2pubkey[validatorIndex] = PublicKey.fromBytes(pubkey); } // skip computimg shuffling in performance test because in reality we have a ShufflingCache // eslint-disable-next-line @typescript-eslint/explicit-function-return-type diff --git a/packages/state-transition/test/unit/constants.test.ts b/packages/state-transition/test/unit/constants.test.ts index 5b8cc66da73a..1cb17472218b 100644 --- a/packages/state-transition/test/unit/constants.test.ts +++ b/packages/state-transition/test/unit/constants.test.ts @@ -5,6 +5,6 @@ import {G2_POINT_AT_INFINITY} from "../../src/index.js"; describe("constants", () => { it("G2_POINT_AT_INFINITY", () => { const p2 = blst.Signature.fromBytes(G2_POINT_AT_INFINITY); - expect(p2.value.is_inf()).toBe(true); + expect(() => p2.sigValidate(true)).toThrow(); }); }); diff --git a/packages/state-transition/test/unit/signatureSets/signatureSets.test.ts b/packages/state-transition/test/unit/signatureSets/signatureSets.test.ts index 1a5b15e1b041..353b68195636 100644 --- a/packages/state-transition/test/unit/signatureSets/signatureSets.test.ts +++ b/packages/state-transition/test/unit/signatureSets/signatureSets.test.ts @@ -1,7 +1,7 @@ import crypto from "node:crypto"; import {describe, it, expect} from "vitest"; -import bls from "@chainsafe/bls"; import {BitArray} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {config} from "@lodestar/config/default"; import {phase0, capella, ValidatorIndex, BLSSignature, ssz} from "@lodestar/types"; import {FAR_FUTURE_EPOCH, MAX_EFFECTIVE_BALANCE} from "@lodestar/params"; @@ -61,7 +61,7 @@ describe("signatureSets", () => { exit: FAR_FUTURE_EPOCH, }); for (const validator of validators) { - validator.pubkey = bls.SecretKey.fromKeygen().toPublicKey().toBytes(); + validator.pubkey = SecretKey.fromKeygen(Buffer.alloc(32)).toPublicKey().toBytes(); } const state = generateCachedState(config, {validators}); diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 714fcbcf8c41..ee8935849636 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -57,7 +57,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "7.1.3", + "@chainsafe/blst": "^2.0.1", "@chainsafe/bls-keystore": "^3.1.0", "@lodestar/params": "^1.20.2", "@lodestar/utils": "^1.20.2", diff --git a/packages/test-utils/src/keystores.ts b/packages/test-utils/src/keystores.ts index 2321fde30bd4..0014ac6c761f 100644 --- a/packages/test-utils/src/keystores.ts +++ b/packages/test-utils/src/keystores.ts @@ -1,5 +1,5 @@ -import bls from "@chainsafe/bls"; import {Keystore} from "@chainsafe/bls-keystore"; +import {SecretKey} from "@chainsafe/blst"; import {fromHex} from "@lodestar/utils"; /** @@ -10,7 +10,7 @@ export async function getKeystoresStr(password: string, secretKeys: string[]): P for (const secretKey of secretKeys) { const sk = fromHex(secretKey); - const pk = bls.SecretKey.fromBytes(sk).toPublicKey().toBytes(); + const pk = SecretKey.fromBytes(sk).toPublicKey().toBytes(); const keystore = await Keystore.create(password, sk, pk, ""); keystoresStr.push(keystore.stringify()); } diff --git a/packages/validator/package.json b/packages/validator/package.json index 5290698d4adb..3451763a94bc 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -45,7 +45,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "7.1.3", + "@chainsafe/blst": "^2.0.1", "@chainsafe/ssz": "^0.15.1", "@lodestar/api": "^1.20.2", "@lodestar/config": "^1.20.2", diff --git a/packages/validator/src/services/externalSignerSync.ts b/packages/validator/src/services/externalSignerSync.ts index edfc0f5bc350..03db612249b4 100644 --- a/packages/validator/src/services/externalSignerSync.ts +++ b/packages/validator/src/services/externalSignerSync.ts @@ -1,6 +1,5 @@ -import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; import {fromHexString} from "@chainsafe/ssz"; +import {PublicKey} from "@chainsafe/blst"; import {ChainForkConfig} from "@lodestar/config"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; import {toSafePrintableUrl} from "@lodestar/utils"; @@ -79,6 +78,6 @@ export function pollExternalSignerPubkeys( function assertValidPubkeysHex(pubkeysHex: string[]): void { for (const pubkeyHex of pubkeysHex) { const pubkeyBytes = fromHexString(pubkeyHex); - bls.PublicKey.fromBytes(pubkeyBytes, CoordType.jacobian, true); + PublicKey.fromBytes(pubkeyBytes, true); } } diff --git a/packages/validator/src/services/validatorStore.ts b/packages/validator/src/services/validatorStore.ts index ef675ff4a001..b1564d6e7d2b 100644 --- a/packages/validator/src/services/validatorStore.ts +++ b/packages/validator/src/services/validatorStore.ts @@ -1,5 +1,5 @@ -import type {SecretKey} from "@chainsafe/bls/types"; import {BitArray, fromHexString, toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import { computeEpochAtSlot, computeSigningRoot, diff --git a/packages/validator/src/types.ts b/packages/validator/src/types.ts index 9a2314269234..dd44fd49c61e 100644 --- a/packages/validator/src/types.ts +++ b/packages/validator/src/types.ts @@ -1,4 +1,4 @@ -import type {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {BLSPubkey} from "@lodestar/types"; import {DatabaseController} from "@lodestar/db"; diff --git a/packages/validator/test/unit/services/attestation.test.ts b/packages/validator/test/unit/services/attestation.test.ts index e1254d1c6a52..0ffec323ee30 100644 --- a/packages/validator/test/unit/services/attestation.test.ts +++ b/packages/validator/test/unit/services/attestation.test.ts @@ -1,6 +1,6 @@ import {describe, it, expect, beforeAll, beforeEach, afterEach, vi} from "vitest"; -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {ssz} from "@lodestar/types"; import {routes} from "@lodestar/api"; import {AttestationService, AttestationServiceOpts} from "../../../src/services/attestation.js"; @@ -28,7 +28,7 @@ describe("AttestationService", function () { let pubkeys: Uint8Array[]; // Initialize pubkeys in before() so bls is already initialized beforeAll(() => { - const secretKeys = Array.from({length: 1}, (_, i) => bls.SecretKey.fromBytes(Buffer.alloc(32, i + 1))); + const secretKeys = Array.from({length: 1}, (_, i) => SecretKey.fromBytes(Buffer.alloc(32, i + 1))); pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); validatorStore.votingPubkeys.mockReturnValue(pubkeys.map(toHexString)); validatorStore.hasVotingPubkey.mockReturnValue(true); diff --git a/packages/validator/test/unit/services/attestationDuties.test.ts b/packages/validator/test/unit/services/attestationDuties.test.ts index f7154a3a174e..ad54c0735eea 100644 --- a/packages/validator/test/unit/services/attestationDuties.test.ts +++ b/packages/validator/test/unit/services/attestationDuties.test.ts @@ -1,7 +1,7 @@ import {describe, it, expect, beforeAll, vi, Mocked, beforeEach, afterEach} from "vitest"; import {toBufferBE} from "bigint-buffer"; -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {chainConfig} from "@lodestar/config/default"; import {routes} from "@lodestar/api"; import {ssz} from "@lodestar/types"; @@ -37,7 +37,7 @@ describe("AttestationDutiesService", function () { }; beforeAll(async () => { - const secretKeys = [bls.SecretKey.fromBytes(toBufferBE(BigInt(98), 32))]; + const secretKeys = [SecretKey.fromBytes(toBufferBE(BigInt(98), 32))]; pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); validatorStore = await initValidatorStore(secretKeys, api, chainConfig); }); diff --git a/packages/validator/test/unit/services/block.test.ts b/packages/validator/test/unit/services/block.test.ts index 6864e62906d1..641ca620a1b5 100644 --- a/packages/validator/test/unit/services/block.test.ts +++ b/packages/validator/test/unit/services/block.test.ts @@ -1,6 +1,6 @@ import {describe, it, expect, beforeAll, beforeEach, afterEach, vi} from "vitest"; -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {createChainForkConfig} from "@lodestar/config"; import {config as mainnetConfig} from "@lodestar/config/default"; import {sleep} from "@lodestar/utils"; @@ -25,7 +25,7 @@ describe("BlockDutiesService", function () { const config = createChainForkConfig(mainnetConfig); beforeAll(() => { - const secretKeys = Array.from({length: 2}, (_, i) => bls.SecretKey.fromBytes(Buffer.alloc(32, i + 1))); + const secretKeys = Array.from({length: 2}, (_, i) => SecretKey.fromBytes(Buffer.alloc(32, i + 1))); pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); validatorStore.votingPubkeys.mockReturnValue(pubkeys.map(toHexString)); }); diff --git a/packages/validator/test/unit/services/blockDuties.test.ts b/packages/validator/test/unit/services/blockDuties.test.ts index c1edcc955b2d..bc4053b704c8 100644 --- a/packages/validator/test/unit/services/blockDuties.test.ts +++ b/packages/validator/test/unit/services/blockDuties.test.ts @@ -1,7 +1,7 @@ import {describe, it, expect, beforeAll, beforeEach, afterEach, vi} from "vitest"; import {toBufferBE} from "bigint-buffer"; -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {routes} from "@lodestar/api"; import {chainConfig} from "@lodestar/config/default"; import {toHex} from "@lodestar/utils"; @@ -19,7 +19,7 @@ describe("BlockDutiesService", function () { let pubkeys: Uint8Array[]; // Initialize pubkeys in before() so bls is already initialized beforeAll(async () => { - const secretKeys = Array.from({length: 3}, (_, i) => bls.SecretKey.fromBytes(toBufferBE(BigInt(i + 1), 32))); + const secretKeys = Array.from({length: 3}, (_, i) => SecretKey.fromBytes(toBufferBE(BigInt(i + 1), 32))); pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); validatorStore = await initValidatorStore(secretKeys, api); }); diff --git a/packages/validator/test/unit/services/externalSignerSync.test.ts b/packages/validator/test/unit/services/externalSignerSync.test.ts index 5fdf7d5ae5b2..8dc7bff7e469 100644 --- a/packages/validator/test/unit/services/externalSignerSync.test.ts +++ b/packages/validator/test/unit/services/externalSignerSync.test.ts @@ -1,7 +1,6 @@ import {MockedFunction, afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; import {toBufferBE} from "bigint-buffer"; -import bls from "@chainsafe/bls"; -import {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {createChainForkConfig} from "@lodestar/config"; import {chainConfig} from "@lodestar/config/default"; import {ExternalSignerOptions, pollExternalSignerPubkeys} from "../../../src/services/externalSignerSync.js"; @@ -32,7 +31,7 @@ describe("External signer sync", () => { beforeAll(() => { vi.useFakeTimers(); - secretKeys = Array.from({length: 3}, (_, i) => bls.SecretKey.fromBytes(toBufferBE(BigInt(i + 1), 32))); + secretKeys = Array.from({length: 3}, (_, i) => SecretKey.fromBytes(toBufferBE(BigInt(i + 1), 32))); pubkeys = secretKeys.map((sk) => sk.toPublicKey().toHex()); externalSignerGetKeysStub = vi.mocked(externalSignerGetKeys); }); diff --git a/packages/validator/test/unit/services/indicesService.test.ts b/packages/validator/test/unit/services/indicesService.test.ts index b94ec6fa398a..8332bac7cfd6 100644 --- a/packages/validator/test/unit/services/indicesService.test.ts +++ b/packages/validator/test/unit/services/indicesService.test.ts @@ -1,7 +1,7 @@ import {describe, it, expect, beforeAll} from "vitest"; import {toBufferBE} from "bigint-buffer"; -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {getApiClientStub} from "../../utils/apiStub.js"; import {testLogger} from "../../utils/logger.js"; import {IndicesService} from "../../../src/services/indices.js"; @@ -14,8 +14,8 @@ describe("IndicesService", function () { beforeAll(() => { const secretKeys = [ - bls.SecretKey.fromBytes(toBufferBE(BigInt(98), 32)), - bls.SecretKey.fromBytes(toBufferBE(BigInt(99), 32)), + SecretKey.fromBytes(toBufferBE(BigInt(98), 32)), + SecretKey.fromBytes(toBufferBE(BigInt(99), 32)), ]; pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); }); diff --git a/packages/validator/test/unit/services/syncCommitteDuties.test.ts b/packages/validator/test/unit/services/syncCommitteDuties.test.ts index c44360485d09..52f2071f9102 100644 --- a/packages/validator/test/unit/services/syncCommitteDuties.test.ts +++ b/packages/validator/test/unit/services/syncCommitteDuties.test.ts @@ -1,8 +1,8 @@ import {describe, it, expect, beforeAll, beforeEach, afterEach} from "vitest"; import {when} from "vitest-when"; import {toBufferBE} from "bigint-buffer"; -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {createChainForkConfig} from "@lodestar/config"; import {config as mainnetConfig} from "@lodestar/config/default"; import {routes} from "@lodestar/api"; @@ -43,8 +43,8 @@ describe("SyncCommitteeDutiesService", function () { beforeAll(async () => { const secretKeys = [ - bls.SecretKey.fromBytes(toBufferBE(BigInt(98), 32)), - bls.SecretKey.fromBytes(toBufferBE(BigInt(99), 32)), + SecretKey.fromBytes(toBufferBE(BigInt(98), 32)), + SecretKey.fromBytes(toBufferBE(BigInt(99), 32)), ]; pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); validatorStore = await initValidatorStore(secretKeys, api, altair0Config); diff --git a/packages/validator/test/unit/services/syncCommittee.test.ts b/packages/validator/test/unit/services/syncCommittee.test.ts index b6cba32fc96b..c65912f12e9a 100644 --- a/packages/validator/test/unit/services/syncCommittee.test.ts +++ b/packages/validator/test/unit/services/syncCommittee.test.ts @@ -1,6 +1,6 @@ import {describe, it, expect, beforeAll, beforeEach, afterEach, vi} from "vitest"; -import bls from "@chainsafe/bls"; import {toHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {createChainForkConfig} from "@lodestar/config"; import {config as mainnetConfig} from "@lodestar/config/default"; import {ssz} from "@lodestar/types"; @@ -37,7 +37,7 @@ describe("SyncCommitteeService", function () { }); beforeAll(() => { - const secretKeys = Array.from({length: 1}, (_, i) => bls.SecretKey.fromBytes(Buffer.alloc(32, i + 1))); + const secretKeys = Array.from({length: 1}, (_, i) => SecretKey.fromBytes(Buffer.alloc(32, i + 1))); pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); validatorStore.votingPubkeys.mockReturnValue(pubkeys.map(toHexString)); validatorStore.hasVotingPubkey.mockReturnValue(true); diff --git a/packages/validator/test/unit/validatorStore.test.ts b/packages/validator/test/unit/validatorStore.test.ts index 3f7f0792f378..3d8d88ee3e64 100644 --- a/packages/validator/test/unit/validatorStore.test.ts +++ b/packages/validator/test/unit/validatorStore.test.ts @@ -1,7 +1,7 @@ import {describe, it, expect, beforeEach, afterEach, vi} from "vitest"; import {toBufferBE} from "bigint-buffer"; -import bls from "@chainsafe/bls"; import {toHexString, fromHexString} from "@chainsafe/ssz"; +import {SecretKey} from "@chainsafe/blst"; import {chainConfig} from "@lodestar/config/default"; import {bellatrix} from "@lodestar/types"; import {routes} from "@lodestar/api"; @@ -92,7 +92,7 @@ describe("ValidatorStore", function () { }); }); -const secretKeys = Array.from({length: 3}, (_, i) => bls.SecretKey.fromBytes(toBufferBE(BigInt(i + 1), 32))); +const secretKeys = Array.from({length: 3}, (_, i) => SecretKey.fromBytes(toBufferBE(BigInt(i + 1), 32))); const pubkeys = secretKeys.map((sk) => sk.toPublicKey().toBytes()); const valRegF00G100 = { diff --git a/packages/validator/test/utils/validatorStore.ts b/packages/validator/test/utils/validatorStore.ts index 5fe530ea0cfe..d3037ce522b9 100644 --- a/packages/validator/test/utils/validatorStore.ts +++ b/packages/validator/test/utils/validatorStore.ts @@ -1,4 +1,4 @@ -import {SecretKey} from "@chainsafe/bls/types"; +import {SecretKey} from "@chainsafe/blst"; import {ApiClient} from "@lodestar/api"; import {chainConfig} from "@lodestar/config/default"; import {createBeaconConfig, ChainConfig} from "@lodestar/config"; diff --git a/yarn.lock b/yarn.lock index 0f01b9e7e294..e00d7e97c217 100644 --- a/yarn.lock +++ b/yarn.lock @@ -306,7 +306,32 @@ "@chainsafe/bls-keygen" "^0.4.0" bls-eth-wasm "^0.4.8" -"@chainsafe/blst@^0.2.11": +"@chainsafe/blst-darwin-arm64@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-darwin-arm64/-/blst-darwin-arm64-2.0.1.tgz#d96d6dd906a6c9c809d6f5b5539e031ccff63b25" + integrity sha512-ZmRLimvo+BoMcpalzuS3Pj0j6l2cSDU7qMBwjch49ljkrsr4/rls7COMW8MSyDyVUSfzg0agotAByYfs+Bg3ZQ== + +"@chainsafe/blst-darwin-x64@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-darwin-x64/-/blst-darwin-x64-2.0.1.tgz#56018c5955337a5e2b754e941bdcda0a2c6f1a84" + integrity sha512-5DPtmKhia5/k0szjsrgxF7GCOE5pnSRcsLvtlChzkLY7KhfxnGt5XeNtCK6NoAAfcxzN8mZrwvvzDfsDmImTQg== + +"@chainsafe/blst-linux-arm64-gnu@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-arm64-gnu/-/blst-linux-arm64-gnu-2.0.1.tgz#23a66095eaf4c23a8c54ef7df27d9c80d45ebb32" + integrity sha512-REIW0uM9a97iasE+RX+M1yEmIywOF1ly9/xl7JTYYASXoDDQD2eL06k17N5kXE/382wU28fU/h6V2qmWcqiWAQ== + +"@chainsafe/blst-linux-x64-gnu@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-x64-gnu/-/blst-linux-x64-gnu-2.0.1.tgz#1769640e9b9140ee3e4142520c00d09c9ebc66e9" + integrity sha512-zH7GkMI+wWVKGp5MA+8A2EGx9fe5/jktz/KB2SrGhBu956IXh7qCV9mMCOzA4mmpxSuxjzD4auXpQc/D4uApLw== + +"@chainsafe/blst-win32-x64-msvc@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-win32-x64-msvc/-/blst-win32-x64-msvc-2.0.1.tgz#dfebc2ea23875bc02ffac11d2d15bf6e644d59ed" + integrity sha512-RcOo1Sl1Ai5igp56l3I5kwWkesfbD14PBoUcoR61phvIHnhyZzOtVX6rhuCYwcl0IIgSDSWtNNMdSwX34GGmxA== + +"@chainsafe/blst@^0.2.0": version "0.2.11" resolved "https://registry.yarnpkg.com/@chainsafe/blst/-/blst-0.2.11.tgz#5ec85cd663592819d1dc51127e75dfd834250e3d" integrity sha512-URyOLq5GtxBoxibOnd2pgLydCy0UZzbiIIBcsRAvGxAsRzjZL04TsQfwRkz5aphU3a1ebeRoMmI/HHyMCiFSQg== @@ -315,6 +340,17 @@ node-fetch "^2.6.1" node-gyp "^8.4.0" +"@chainsafe/blst@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@chainsafe/blst/-/blst-2.0.1.tgz#9e8ceb6766fcb231e4fa378eee6378275018a159" + integrity sha512-+sIlLzFb6htv1WH3XIF2WDN+qlstGpo8Zl5ibxzT6VsiBSswsH05AQMpd4uQfRO1uFKhEk9JDKi8bHvIDmN8Jg== + optionalDependencies: + "@chainsafe/blst-darwin-arm64" "2.0.1" + "@chainsafe/blst-darwin-x64" "2.0.1" + "@chainsafe/blst-linux-arm64-gnu" "2.0.1" + "@chainsafe/blst-linux-x64-gnu" "2.0.1" + "@chainsafe/blst-win32-x64-msvc" "2.0.1" + "@chainsafe/discv5@^9.0.0": version "9.0.0" resolved "https://registry.yarnpkg.com/@chainsafe/discv5/-/discv5-9.0.0.tgz#05d4d9d671894b41f0fafa8f32c48ae3ed761bd1" @@ -1555,6 +1591,29 @@ progress-events "^1.0.0" uint8arraylist "^2.4.8" +"@libp2p/interface@^1.2.0", "@libp2p/interface@^1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@libp2p/interface/-/interface-1.6.1.tgz#dc8f1a49da7ee81cd068e872bde3445c3b631d45" + integrity sha512-bpkIYTvZhGGc/ajITKvgFpaP8UtPWoSj+xHVrj6zyAN8U/cAqN0IQQt4a7daJr5VZa8B86i4d1iccdG42/mz+g== + dependencies: + "@multiformats/multiaddr" "^12.2.3" + it-pushable "^3.2.3" + it-stream-types "^2.0.1" + multiformats "^13.1.0" + progress-events "^1.0.0" + uint8arraylist "^2.4.8" + +"@libp2p/logger@^4.0.10": + version "4.0.17" + resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.17.tgz#1ae663bb2dec3c7e6b29d2195756f64e5e77d939" + integrity sha512-NPGN27uOXFGuKkxnX39InMvxS0lMenq6/aFqQHN1N0f0S3LaG9RuTcz/VE3qyO1Ik1aAockR6qqCwbfFxJuO0g== + dependencies: + "@libp2p/interface" "^1.6.1" + "@multiformats/multiaddr" "^12.2.3" + debug "^4.3.4" + interface-datastore "^8.2.11" + multiformats "^13.1.0" + "@libp2p/logger@^4.0.11", "@libp2p/logger@^4.0.6": version "4.0.11" resolved "https://registry.yarnpkg.com/@libp2p/logger/-/logger-4.0.11.tgz#671692a0cceee73a0c0bf9b5f05ea14fde05f5e5" @@ -1845,6 +1904,19 @@ uint8-varint "^2.0.1" uint8arrays "^5.0.0" +"@multiformats/multiaddr@^12.2.3": + version "12.3.0" + resolved "https://registry.yarnpkg.com/@multiformats/multiaddr/-/multiaddr-12.3.0.tgz#b1422813446e5cdec4b0f6cba51f93239f390884" + integrity sha512-JQ8Gc/jgucqqvEaDTFN/AvxlYDHEE7lgEWLMYW7hKZkWggER+GvG/tVxUgUxIP8M0vFpvEHKKHE0lKzyMsgi8Q== + dependencies: + "@chainsafe/is-ip" "^2.0.1" + "@chainsafe/netmask" "^2.0.0" + "@libp2p/interface" "^1.0.0" + "@multiformats/dns" "^1.0.3" + multiformats "^13.0.0" + uint8-varint "^2.0.1" + uint8arrays "^5.0.0" + "@napi-rs/snappy-android-arm-eabi@7.2.2": version "7.2.2" resolved "https://registry.yarnpkg.com/@napi-rs/snappy-android-arm-eabi/-/snappy-android-arm-eabi-7.2.2.tgz#85fee3ba198dad4b444b5f12bceebcf72db0d65e" @@ -2061,7 +2133,7 @@ "@npmcli/fs@^1.0.0": version "1.1.1" - resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== dependencies: "@gar/promisify" "^1.0.1" @@ -7407,7 +7479,7 @@ http-proxy-agent@^7.0.0: agent-base "^7.1.0" debug "^4.3.4" -http-proxy-agent@^7.0.2: +http-proxy-agent@^7.0.1, http-proxy-agent@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== @@ -7453,14 +7525,6 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" -https-proxy-agent@^7.0.0, https-proxy-agent@^7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" - integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== - dependencies: - agent-base "^7.0.2" - debug "4" - https-proxy-agent@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" @@ -7469,6 +7533,22 @@ https-proxy-agent@^7.0.2: agent-base "^7.0.2" debug "4" +https-proxy-agent@^7.0.3, https-proxy-agent@^7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + +https-proxy-agent@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz#8e97b841a029ad8ddc8731f26595bad868cb4168" + integrity sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -7675,16 +7755,19 @@ internal-slot@^1.0.5: has "^1.0.3" side-channel "^1.0.4" +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz" integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= -ip@^1.1.8: - version "1.1.9" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.9.tgz#8dfbcc99a754d07f425310b86a99546b1151e396" - integrity sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ== - ip@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105" @@ -8301,6 +8384,11 @@ js-yaml@^3.10.0: argparse "^1.0.7" esprima "^4.0.0" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + jsdom@^23.0.1: version "23.0.1" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-23.0.1.tgz#ede7ff76e89ca035b11178d200710d8982ebfee0" @@ -8972,7 +9060,7 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1, make-fetch-happen@^11.1.1: make-fetch-happen@^9.1.0: version "9.1.0" - resolved "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== dependencies: agentkeepalive "^4.1.3" @@ -9584,7 +9672,7 @@ node-gyp-build@^4.3.0: node-gyp@^8.4.0: version "8.4.1" - resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== dependencies: env-paths "^2.2.0" @@ -10259,27 +10347,26 @@ p-waterfall@2.1.1: dependencies: p-reduce "^2.0.0" -pac-proxy-agent@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.0.1.tgz#6b9ddc002ec3ff0ba5fdf4a8a21d363bcc612d75" - integrity sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A== +pac-proxy-agent@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz#0fb02496bd9fb8ae7eb11cfd98386daaac442f58" + integrity sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg== dependencies: "@tootallnate/quickjs-emscripten" "^0.23.0" agent-base "^7.0.2" debug "^4.3.4" get-uri "^6.0.1" http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.2" - pac-resolver "^7.0.0" - socks-proxy-agent "^8.0.2" + https-proxy-agent "^7.0.5" + pac-resolver "^7.0.1" + socks-proxy-agent "^8.0.4" -pac-resolver@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.0.tgz#79376f1ca26baf245b96b34c339d79bff25e900c" - integrity sha512-Fd9lT9vJbHYRACT8OhCbZBbxr6KRSawSovFpy8nDGshaK99S/EBhVIHp9+crhxrsZOuvLpgL1n23iyPg6Rl2hg== +pac-resolver@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6" + integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg== dependencies: degenerator "^5.0.0" - ip "^1.1.8" netmask "^2.0.2" pacote@^15.2.0: @@ -10683,19 +10770,19 @@ proxy-addr@^2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-agent@6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.3.0.tgz#72f7bb20eb06049db79f7f86c49342c34f9ba08d" - integrity sha512-0LdR757eTj/JfuU7TL2YCuAZnxWXu3tkJbg4Oq3geW/qFNT/32T0sp2HnZ9O0lMR4q3vwAt0+xCA8SR0WAD0og== +proxy-agent@6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.4.0.tgz#b4e2dd51dee2b377748aef8d45604c2d7608652d" + integrity sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ== dependencies: agent-base "^7.0.2" debug "^4.3.4" - http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.0" + http-proxy-agent "^7.0.1" + https-proxy-agent "^7.0.3" lru-cache "^7.14.1" - pac-proxy-agent "^7.0.0" + pac-proxy-agent "^7.0.1" proxy-from-env "^1.1.0" - socks-proxy-agent "^8.0.1" + socks-proxy-agent "^8.0.2" proxy-from-env@^1.1.0: version "1.1.0" @@ -11357,6 +11444,13 @@ semver@7.5.3: dependencies: lru-cache "^6.0.0" +semver@7.6.0, semver@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + 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" @@ -11369,13 +11463,6 @@ semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semve dependencies: lru-cache "^6.0.0" -semver@^7.6.0: - version "7.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" - integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== - dependencies: - lru-cache "^6.0.0" - serialize-error@^11.0.1: version "11.0.3" resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-11.0.3.tgz#b54f439e15da5b4961340fbbd376b6b04aa52e92" @@ -11567,13 +11654,13 @@ snappyjs@^0.7.0: integrity sha512-u5iEEXkMe2EInQio6Wv9LWHOQYRDbD2O9hzS27GpT/lwfIQhTCnHCTqedqHIHe9ZcvQo+9au6vngQayipz1NYw== socks-proxy-agent@^6.0.0: - version "6.1.1" - resolved "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz" - integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew== + version "6.2.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" + integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== dependencies: agent-base "^6.0.2" - debug "^4.3.1" - socks "^2.6.1" + debug "^4.3.3" + socks "^2.6.2" socks-proxy-agent@^7.0.0: version "7.0.0" @@ -11584,15 +11671,6 @@ socks-proxy-agent@^7.0.0: debug "^4.3.3" socks "^2.6.2" -socks-proxy-agent@^8.0.1: - version "8.0.3" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.3.tgz#6b2da3d77364fde6292e810b496cb70440b9b89d" - integrity sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A== - dependencies: - agent-base "^7.1.1" - debug "^4.3.4" - socks "^2.7.1" - socks-proxy-agent@^8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz#5acbd7be7baf18c46a3f293a840109a430a640ad" @@ -11602,7 +11680,16 @@ socks-proxy-agent@^8.0.2: debug "^4.3.4" socks "^2.7.1" -socks@^2.6.1, socks@^2.6.2, socks@^2.7.1: +socks-proxy-agent@^8.0.4: + version "8.0.4" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz#9071dca17af95f483300316f4b063578fa0db08c" + integrity sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw== + dependencies: + agent-base "^7.1.1" + debug "^4.3.4" + socks "^2.8.3" + +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== @@ -11610,6 +11697,14 @@ socks@^2.6.1, socks@^2.6.2, socks@^2.7.1: ip "^2.0.0" smart-buffer "^4.2.0" +socks@^2.8.3: + version "2.8.3" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.3.tgz#1ebd0f09c52ba95a09750afe3f3f9f724a800cb5" + integrity sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw== + dependencies: + ip-address "^9.0.5" + smart-buffer "^4.2.0" + sonic-boom@^3.7.0: version "3.8.0" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.8.0.tgz#e442c5c23165df897d77c3c14ef3ca40dec66a66" @@ -11707,6 +11802,11 @@ sprintf-js@^1.1.2: resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz" integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" @@ -12089,16 +12189,7 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar-fs@3.0.4, tar-fs@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.4.tgz#a21dc60a2d5d9f55e0089ccd78124f1d3771dbbf" - integrity sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w== - dependencies: - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^3.1.5" - -tar-fs@^3.0.5: +tar-fs@3.0.5, tar-fs@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.5.tgz#f954d77767e4e6edf973384e1eb95f8f81d64ed9" integrity sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg== @@ -12109,6 +12200,15 @@ tar-fs@^3.0.5: bare-fs "^2.1.1" bare-path "^2.1.0" +tar-fs@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.4.tgz#a21dc60a2d5d9f55e0089ccd78124f1d3771dbbf" + integrity sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w== + dependencies: + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^3.1.5" + tar-fs@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.1.tgz#e44086c1c60d31a4f0cf893b1c4e155dabfae9e2" @@ -13689,20 +13789,7 @@ yargs@16.2.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -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== - 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" - -yargs@^17.1.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.1: +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== From 3ecee0797af760e5a14a7a98e9779340ab51ee55 Mon Sep 17 00:00:00 2001 From: Matthew Keil Date: Fri, 26 Jul 2024 14:21:00 -0400 Subject: [PATCH 22/44] chore: bump blst-ts version (#6980) * chore: bump blst-ts version * chore: delete personal script --- packages/beacon-node/package.json | 2 +- packages/cli/package.json | 2 +- packages/flare/package.json | 2 +- packages/state-transition/package.json | 2 +- packages/test-utils/package.json | 2 +- packages/validator/package.json | 2 +- yarn.lock | 92 ++++++++++++-------------- 7 files changed, 49 insertions(+), 55 deletions(-) diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index f2d58647d91f..dcb5bd2d35a6 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -95,7 +95,7 @@ }, "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/blst": "^2.0.1", + "@chainsafe/blst": "^2.0.3", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", "@chainsafe/libp2p-gossipsub": "^13.0.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index cbeda803ba7e..6b7bf36bacd2 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -53,7 +53,7 @@ "dependencies": { "@chainsafe/bls-keygen": "^0.4.0", "@chainsafe/bls-keystore": "^3.1.0", - "@chainsafe/blst": "^2.0.1", + "@chainsafe/blst": "^2.0.3", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", "@chainsafe/persistent-merkle-tree": "^0.7.1", diff --git a/packages/flare/package.json b/packages/flare/package.json index a962bf3ddc2d..9e9560d32dd8 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -58,7 +58,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/blst": "^2.0.1", + "@chainsafe/blst": "^2.0.3", "@chainsafe/bls-keygen": "^0.4.0", "@lodestar/api": "^1.20.2", "@lodestar/config": "^1.20.2", diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index c9c16a672c18..0271f64b684f 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/blst": "^2.0.1", + "@chainsafe/blst": "^2.0.3", "@chainsafe/persistent-merkle-tree": "^0.7.1", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.15.1", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index ee8935849636..d0b551b20c59 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -57,7 +57,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/blst": "^2.0.1", + "@chainsafe/blst": "^2.0.3", "@chainsafe/bls-keystore": "^3.1.0", "@lodestar/params": "^1.20.2", "@lodestar/utils": "^1.20.2", diff --git a/packages/validator/package.json b/packages/validator/package.json index 3451763a94bc..abf5f8797d89 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -45,7 +45,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/blst": "^2.0.1", + "@chainsafe/blst": "^2.0.3", "@chainsafe/ssz": "^0.15.1", "@lodestar/api": "^1.20.2", "@lodestar/config": "^1.20.2", diff --git a/yarn.lock b/yarn.lock index e00d7e97c217..f41593e92c44 100644 --- a/yarn.lock +++ b/yarn.lock @@ -306,30 +306,40 @@ "@chainsafe/bls-keygen" "^0.4.0" bls-eth-wasm "^0.4.8" -"@chainsafe/blst-darwin-arm64@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chainsafe/blst-darwin-arm64/-/blst-darwin-arm64-2.0.1.tgz#d96d6dd906a6c9c809d6f5b5539e031ccff63b25" - integrity sha512-ZmRLimvo+BoMcpalzuS3Pj0j6l2cSDU7qMBwjch49ljkrsr4/rls7COMW8MSyDyVUSfzg0agotAByYfs+Bg3ZQ== +"@chainsafe/blst-darwin-arm64@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-darwin-arm64/-/blst-darwin-arm64-2.0.3.tgz#28ecbcdbaeaebb1cf07a4e8edeaf7b138bc96f22" + integrity sha512-7LGFMBXhB5eM8zLQgblm471NjqnOhI0dv+OohmgWBwjA3Ph4rxTd0CRorZMiqy770MbiLninnYSWiTbjXLY6eQ== -"@chainsafe/blst-darwin-x64@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chainsafe/blst-darwin-x64/-/blst-darwin-x64-2.0.1.tgz#56018c5955337a5e2b754e941bdcda0a2c6f1a84" - integrity sha512-5DPtmKhia5/k0szjsrgxF7GCOE5pnSRcsLvtlChzkLY7KhfxnGt5XeNtCK6NoAAfcxzN8mZrwvvzDfsDmImTQg== +"@chainsafe/blst-darwin-x64@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-darwin-x64/-/blst-darwin-x64-2.0.3.tgz#d50cfd591a5b1698202ee97242e0f28a8c76d2be" + integrity sha512-RRgMLuP8rmd84+ht35Rc/vMDsvK6NZgJlchqis1ve0/Na3550gqVgbVY7Y8YDuW8VpGAslII56rDZNqEl7tVmg== -"@chainsafe/blst-linux-arm64-gnu@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-arm64-gnu/-/blst-linux-arm64-gnu-2.0.1.tgz#23a66095eaf4c23a8c54ef7df27d9c80d45ebb32" - integrity sha512-REIW0uM9a97iasE+RX+M1yEmIywOF1ly9/xl7JTYYASXoDDQD2eL06k17N5kXE/382wU28fU/h6V2qmWcqiWAQ== +"@chainsafe/blst-linux-arm64-gnu@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-arm64-gnu/-/blst-linux-arm64-gnu-2.0.3.tgz#05d0028d757a00126628fa6d498f3c8925dda259" + integrity sha512-zkCTMuv3pnWR2xtfcazt7PlJqnltH9yOHSjFy1U7/izowU1KUSSptcvJi+26i2tI5NNWbHVNCb8CqKbRxOdNTQ== -"@chainsafe/blst-linux-x64-gnu@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-x64-gnu/-/blst-linux-x64-gnu-2.0.1.tgz#1769640e9b9140ee3e4142520c00d09c9ebc66e9" - integrity sha512-zH7GkMI+wWVKGp5MA+8A2EGx9fe5/jktz/KB2SrGhBu956IXh7qCV9mMCOzA4mmpxSuxjzD4auXpQc/D4uApLw== +"@chainsafe/blst-linux-arm64-musl@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-arm64-musl/-/blst-linux-arm64-musl-2.0.3.tgz#c6d924fc346d0e50f77d44dfdfe08a9010eceae3" + integrity sha512-aQA9W7TpqoYjMc6WiLJ1rMdrU+vG7kjaOr1ZdCijlBOVer3OP5qdBD16GfjeqaxIQsmMHzHkBf/isczONZ9sjw== -"@chainsafe/blst-win32-x64-msvc@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chainsafe/blst-win32-x64-msvc/-/blst-win32-x64-msvc-2.0.1.tgz#dfebc2ea23875bc02ffac11d2d15bf6e644d59ed" - integrity sha512-RcOo1Sl1Ai5igp56l3I5kwWkesfbD14PBoUcoR61phvIHnhyZzOtVX6rhuCYwcl0IIgSDSWtNNMdSwX34GGmxA== +"@chainsafe/blst-linux-x64-gnu@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-x64-gnu/-/blst-linux-x64-gnu-2.0.3.tgz#0edc16cab944f9f55529d742e157fcf85455a8ce" + integrity sha512-pZtZ9tVmmqInEqSF8+SJGtVynBw4pDOYNzUVSfpHcwBpyIl3TZzuewCQfh487FcJ52c2vXelpA8MucBuRDiDZg== + +"@chainsafe/blst-linux-x64-musl@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-linux-x64-musl/-/blst-linux-x64-musl-2.0.3.tgz#be61d9f50fe35bb4c8692e90583b998701b0409c" + integrity sha512-w/X5+QjDbJTiqlXkiv0TXnuWdkfMRvoTFJcy3RyM7s1ra1kvoB6JRjJMirUJUoJNcMhzThZqjWPeVVpiCrqrVw== + +"@chainsafe/blst-win32-x64-msvc@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst-win32-x64-msvc/-/blst-win32-x64-msvc-2.0.3.tgz#e4666de90c9fb4f26667decc6bd3f49e8e5b2e46" + integrity sha512-yHy8cF+PTpuOYiBx962gGH2+c2DY38x2Th7HijlBBFbytW+D/nMka1DTuuyuOVIb/un2aEVf7pVBUgXTbQHEwQ== "@chainsafe/blst@^0.2.0": version "0.2.11" @@ -340,16 +350,18 @@ node-fetch "^2.6.1" node-gyp "^8.4.0" -"@chainsafe/blst@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chainsafe/blst/-/blst-2.0.1.tgz#9e8ceb6766fcb231e4fa378eee6378275018a159" - integrity sha512-+sIlLzFb6htv1WH3XIF2WDN+qlstGpo8Zl5ibxzT6VsiBSswsH05AQMpd4uQfRO1uFKhEk9JDKi8bHvIDmN8Jg== +"@chainsafe/blst@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@chainsafe/blst/-/blst-2.0.3.tgz#12ae2544cb04a8cade626a6d5263d08432bdda4a" + integrity sha512-VMyqXAwgNtiHWj1ksEnHFxD2pmw+0VqQLCeNFacE5xPfscPcj+EVjmexbYdUTae52SfVx1E0F83kk1xLY5GwPw== optionalDependencies: - "@chainsafe/blst-darwin-arm64" "2.0.1" - "@chainsafe/blst-darwin-x64" "2.0.1" - "@chainsafe/blst-linux-arm64-gnu" "2.0.1" - "@chainsafe/blst-linux-x64-gnu" "2.0.1" - "@chainsafe/blst-win32-x64-msvc" "2.0.1" + "@chainsafe/blst-darwin-arm64" "2.0.3" + "@chainsafe/blst-darwin-x64" "2.0.3" + "@chainsafe/blst-linux-arm64-gnu" "2.0.3" + "@chainsafe/blst-linux-arm64-musl" "2.0.3" + "@chainsafe/blst-linux-x64-gnu" "2.0.3" + "@chainsafe/blst-linux-x64-musl" "2.0.3" + "@chainsafe/blst-win32-x64-msvc" "2.0.3" "@chainsafe/discv5@^9.0.0": version "9.0.0" @@ -11951,16 +11963,7 @@ string-argv@~0.3.1: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -13595,16 +13598,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== From 30b8a23b3790af2e16fe30d509b1811fcd206bca Mon Sep 17 00:00:00 2001 From: Phil Ngo <58080811+philknows@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:35:32 -0400 Subject: [PATCH 23/44] chore: add additional instructions for hotfixes in release.md (#6971) * Add additional instructions for hotfix * fix merge conflict title Co-authored-by: Cayman * resolving conflicts Co-authored-by: Cayman * minor fixes addressed * address comments * spelling fix Co-authored-by: Nico Flaig --------- Co-authored-by: Cayman Co-authored-by: Nico Flaig --- RELEASE.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 91b450baa34a..ad96c918a1b5 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -74,7 +74,7 @@ If there is a bug discovered during the testing period which significantly impac For example: After 3-5 days of testing, is performance equal to or better than latest stable? - **Yes**: Continue to the next release step -- **No**: If it a small issue fixable quickly (hot-fix)? +- **No**: If it a small issue fixable quickly (hotfix)? - **Yes**: Merge fix(es) to `unstable`, push the fix(es) to `rc/v1.1.0` branch, go to step 2, incrementing the rc version - **No**: abort the release. Close the `chore: v1.1.0 release` PR, delete the branch, and start the whole release process over. @@ -106,11 +106,11 @@ Tagging a stable release will trigger CI to publish to NPM, dockerhub, and Githu ### 6. Announce - Double check that Github release is correct -- Publish to Social Media +- Follow [Publish to Social Media](#publish-to-social-media) steps -## Hot-fix release +## Hotfix release -If a stable version requires an immediate hot-fix before the next release, a hot-fix release is started. +If a stable version requires an immediate fix before the next release, a hotfix release is started. A similar process for a stable release is used, with the three differences. @@ -162,7 +162,60 @@ Tagging a release candidate will trigger CI to publish to NPM, dockerhub, and Gi - `git tag -am "v1.1.1-rc.0" v1.1.1-rc.0` - `git push origin v1.1.1-rc.0` -Continue following the "test release candidate" and "merge release candidate" sections. Testing window may be modified depending on the severity of the bug fixed. +### 3. Test hotfix release candidate + +Once a hotfix release candidate is created, the Lodestar team may begin a modified hotfix testing period consisting of a quick sanity check or longer if required. + +If the hotfix does not address the purpose of the hotfix release, or there is another bug discovered during this modified hotfix testing period which significantly impacts performance, security, or stability, and it is determined that it is no longer prudent to promote the `rc.x` candidate to `stable`, then it will await an additional fix by the team. The fix will be committed to `unstable` first, then cherrypicked into the `rc/v1.1.1` hotfix branch. Then we publish and promote the new commit to `rc.x+1`. The modified hotfix testing period will reset. + +For example: After modified hotfix testing period, is the original bug resolved? Is performance equal to or better than latest stable? + +- **Yes**: Continue to the next release step +- **No**: If it a small issue fixable quickly with another hotfix? + - **Yes**: Merge fix(es) to `unstable`, push the fix(es) to `rc/v1.1.1` hotfix branch, go to step 2, incrementing the rc version + - **No**: Abort the release. Close the `chore: v1.1.v release` PR, delete the branch, and start the whole release process over. + +### 4. Merge hotfix release candidate + +- Ensure step 3 testing is successful and there is sufficient consensus to release `v1.1.1`. +- Approving the `chore: v1.1.1 release` PR means a team member marks the release as safe, after personally reviewing and / or testing it. +- Merge `chore: v1.1.1 release` PR to stable **with "merge commit"** strategy to preserve all history. +- Merge `stable` into `unstable` **with merge commit** strategy. Due to branch protections in `unstable` must open a PR. If there are conflicts, those must be resolved manually. Gitflow may cause changes that conflict between stable and unstable, for example due to a hotfix that is backported. If that happens, disable branch protections in unstable, merge locally fixing conflicts, run lint + tests, push, and re-enable branch protections. See "Backporting merge conflicts from stable to unstable". + +Pull the latest commits on both `stable` and `unstable` branches: +- `git checkout stable && git pull origin stable` +- `git checkout unstable && git pull origin unstable` + +Merge `stable` into `unstable`, resolving conflicts: +- `git checkout unstable && git merge stable` +- Resolve conflicts +- Sanity check locally before pushing by using: `git diff unstable origin/unstable` +- Disable `unstable` branch protection +- `git push` +- Enable `unstable` branch protection + +### 5. Tag stable hotfix release + +Tagging a stable release will trigger CI to publish to NPM, dockerhub, and Github releases. + +#### All-in-one script (for example version `v1.1.1`): + +- `git checkout stable` +- `yarn release:tag-stable 1.1.1` + - Must be run locally from a write-access account capable of triggering CI. + +#### Manual steps (for example version `v1.1.1`): + +- Check out the new stable + - `git checkout stable` +- Tag it as `v1.1.1` with an annotated tag, push commit and tag. + - `git tag -am "v1.1.1" v1.1.1` + - `git push origin v1.1.1` + +### 6. Announce + +- Double check that Github release is correct +- Follow [Publish to Social Media](#publish-to-social-media) steps ## Dev release @@ -280,7 +333,7 @@ Lodestar used `master` as the single target for feature branches. - QA is done on `v1.1.x` branch - Fixes on rc are done on `v1.1.x`, then re-tag - Once released final `v1.1.0` tag is on a branch that is never merged -- Hot-fixes are either cherry-picked from `master` or done on the `v1.1.x` branch, never merged +- Hotfixes are either cherry-picked from `master` or done on the `v1.1.x` branch, never merged However, this had some issues: From 59f72d016758124d1dd34bba8229e465a021d400 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Mon, 29 Jul 2024 17:31:23 +0100 Subject: [PATCH 24/44] docs: fix formatting of RELEASE.md file (#6985) --- RELEASE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE.md b/RELEASE.md index ad96c918a1b5..3379b40f3720 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -183,10 +183,12 @@ For example: After modified hotfix testing period, is the original bug resolved? - Merge `stable` into `unstable` **with merge commit** strategy. Due to branch protections in `unstable` must open a PR. If there are conflicts, those must be resolved manually. Gitflow may cause changes that conflict between stable and unstable, for example due to a hotfix that is backported. If that happens, disable branch protections in unstable, merge locally fixing conflicts, run lint + tests, push, and re-enable branch protections. See "Backporting merge conflicts from stable to unstable". Pull the latest commits on both `stable` and `unstable` branches: + - `git checkout stable && git pull origin stable` - `git checkout unstable && git pull origin unstable` Merge `stable` into `unstable`, resolving conflicts: + - `git checkout unstable && git merge stable` - Resolve conflicts - Sanity check locally before pushing by using: `git diff unstable origin/unstable` From c23d70cedc33db79222c80646a2c2deee53152e1 Mon Sep 17 00:00:00 2001 From: Cayman Date: Tue, 30 Jul 2024 00:12:56 -0600 Subject: [PATCH 25/44] feat: add historical state regen (#6033) * feat: add historical state regen * chore: wire up metrics * chore: make historical state regen module optional * chore: persist pubkey cache across historical state regen runs * chore: cleanup worker termination * chore: fix worker usage * fix: swap Level for ClassicLevel for multithreading * fix: getStateV2 state handling hack * chore: update classic-level * chore: fix build errors * chore: add comments * chore: fix test worker path * chore: simplify function naming * chore: optimize getSlotFromOffset * chore: refactor to avoid needless deserialization * fix: update metrics names * feat: add historical state regen dashboard * fix: update vm dashboards with historical state worker * chore: fix test data * feat: transfer state across worker boundary * chore: address some pr comments * chore: clean module close * feat: add metrics --------- Co-authored-by: Matthew Keil Co-authored-by: Tuyen Nguyen --- .../lodestar_historical_state_regen.json | 2646 +++++++++++++++++ dashboards/lodestar_vm_host.json | 318 +- .../src/api/impl/beacon/state/utils.ts | 2 +- packages/beacon-node/src/chain/chain.ts | 87 +- .../historicalState/getHistoricalState.ts | 111 + .../src/chain/historicalState/index.ts | 67 + .../src/chain/historicalState/types.ts | 54 + .../src/chain/historicalState/worker.ts | 231 ++ packages/beacon-node/src/chain/interface.ts | 4 + .../beacon-node/src/metrics/server/http.ts | 7 +- packages/beacon-node/src/node/nodejs.ts | 15 +- packages/db/src/controller/level.ts | 7 +- 12 files changed, 3461 insertions(+), 88 deletions(-) create mode 100644 dashboards/lodestar_historical_state_regen.json create mode 100644 packages/beacon-node/src/chain/historicalState/getHistoricalState.ts create mode 100644 packages/beacon-node/src/chain/historicalState/index.ts create mode 100644 packages/beacon-node/src/chain/historicalState/types.ts create mode 100644 packages/beacon-node/src/chain/historicalState/worker.ts diff --git a/dashboards/lodestar_historical_state_regen.json b/dashboards/lodestar_historical_state_regen.json new file mode 100644 index 000000000000..20eddcd1f31e --- /dev/null +++ b/dashboards/lodestar_historical_state_regen.json @@ -0,0 +1,2646 @@ +{ + "__inputs": [ + { + "description": "", + "label": "Prometheus", + "name": "DS_PROMETHEUS", + "pluginId": "prometheus", + "pluginName": "Prometheus", + "type": "datasource" + }, + { + "description": "", + "label": "Beacon node job name", + "name": "VAR_BEACON_JOB", + "type": "constant", + "value": "beacon" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [ + { + "asDropdown": true, + "icon": "external link", + "includeVars": true, + "keepTime": true, + "tags": [ + "lodestar" + ], + "targetBlank": false, + "title": "Lodestar dashboards", + "tooltip": "", + "type": "dashboards", + "url": "" + } + ], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 535, + "panels": [], + "title": "VM", + "type": "row" + }, + { + "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": 30, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "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": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 536, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "lodestar_historical_state_worker_nodejs_heap_space_size_used_bytes{job=~\"$beacon_job|beacon\"}", + "interval": "", + "legendFormat": "{{space}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "lodestar_historical_state_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"}", + "hide": false, + "interval": "", + "legendFormat": "external_memory", + "range": true, + "refId": "B" + } + ], + "title": "Heap Allocations", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "GC Time", + "axisPlacement": "left", + "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": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "C" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisLabel", + "value": "GC Bytes" + }, + { + "id": "unit", + "value": "decbytes" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 537, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.4.0-beta1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_worker_nodejs_gc_pause_seconds_total{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "hide": false, + "legendFormat": "{{gctype}}", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_worker_nodejs_gc_reclaimed_bytes_total{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "format": "time_series", + "hide": false, + "legendFormat": "{{gctype}}", + "range": true, + "refId": "C" + } + ], + "title": "GC pause time rate + reclaimed bytes", + "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": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "p50" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "p90" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "p99" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "semi-dark-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "min" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "dark-blue", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "set_immediate" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "max" + }, + "properties": [ + { + "id": "custom.fillBelowTo", + "value": "min" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 9 + }, + "id": 538, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg_over_time(lodestar_historical_state_worker_nodejs_eventloop_lag_min_seconds{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "hide": false, + "legendFormat": "min", + "range": true, + "refId": "0" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg_over_time(lodestar_historical_state_worker_nodejs_eventloop_lag_p50_seconds{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg_over_time(lodestar_historical_state_worker_nodejs_eventloop_lag_p90_seconds{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "hide": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg_over_time(lodestar_historical_state_worker_nodejs_eventloop_lag_p99_seconds{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "hide": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg_over_time(lodestar_historical_state_worker_nodejs_eventloop_lag_max_seconds{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "hide": false, + "legendFormat": "max", + "range": true, + "refId": "D" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "avg_over_time(lodestar_historical_state_worker_nodejs_eventloop_lag_seconds{job=~\"$beacon_job|beacon\"}[$rate_interval])", + "hide": false, + "legendFormat": "set_immediate", + "range": true, + "refId": "E" + } + ], + "title": "Event loop lag", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 25, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "refId": "A" + } + ], + "title": "Job Queue", + "type": "row" + }, + { + "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": 10, + "gradientMode": "opacity", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.4.0-beta1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_queue_job_time_seconds_sum[$rate_interval])", + "instant": false, + "interval": "", + "legendFormat": "block_processor", + "refId": "A" + } + ], + "title": "Utilization rate", + "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": 30, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "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": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 81, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "12*rate(lodestar_historical_state_queue_job_time_seconds_count[6m])", + "instant": false, + "interval": "", + "legendFormat": "block_processor", + "refId": "A" + } + ], + "title": "Jobs / slot", + "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": 30, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 100, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_queue_job_time_seconds_sum[$rate_interval])/rate(lodestar_historical_state_queue_job_time_seconds_count[$rate_interval])", + "instant": false, + "interval": "", + "legendFormat": "block_processor", + "refId": "A" + } + ], + "title": "Job time", + "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": 30, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 128, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "lodestar_historical_state_queue_length", + "instant": false, + "interval": "", + "legendFormat": "block_processor", + "refId": "A" + } + ], + "title": "Queue length", + "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": 30, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 34 + }, + "id": 127, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_queue_job_wait_time_seconds_sum[$rate_interval])/rate(lodestar_historical_state_queue_job_wait_time_seconds_count[$rate_interval])", + "instant": false, + "interval": "", + "legendFormat": "block_processor", + "refId": "A" + } + ], + "title": "Job wait time", + "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": 30, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 2, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "percentunit" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 34 + }, + "id": 126, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_queue_dropped_jobs_total[$rate_interval])/(rate(lodestar_historical_state_queue_job_time_seconds_count[$rate_interval])+rate(lodestar_historical_state_queue_dropped_jobs_total[$rate_interval]))", + "instant": false, + "interval": "", + "legendFormat": "block_processor", + "refId": "A" + } + ], + "title": "Dropped jobs %", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 108, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "refId": "A" + } + ], + "title": "Beacon state transition", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 43 + }, + "id": 528, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Magma", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "10.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "32*12*rate(lodestar_historical_state_stfn_epoch_transition_seconds_bucket[$rate_interval])", + "format": "heatmap", + "interval": "", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "Epoch transition time", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 43 + }, + "id": 529, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Magma", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "10.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "12*rate(lodestar_historical_state_stfn_process_block_seconds_bucket[$rate_interval])", + "format": "heatmap", + "interval": "", + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "Process block time", + "type": "heatmap" + }, + { + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "id": 120, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(lodestar_historical_state_stfn_epoch_transition_seconds_sum[$rate_interval])\n/\nrate(lodestar_historical_state_stfn_epoch_transition_seconds_count[$rate_interval])", + "interval": "", + "legendFormat": "epoch transition", + "range": true, + "refId": "A" + } + ], + "title": "Epoch transition avg time", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 51 + }, + "id": 121, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_process_block_seconds_sum[$rate_interval])\n/\nrate(lodestar_historical_state_stfn_process_block_seconds_count[$rate_interval])", + "interval": "", + "legendFormat": "process block time", + "range": true, + "refId": "A" + } + ], + "title": "Process block avg time", + "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": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 534, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_epoch_transition_step_seconds_sum[$rate_interval])\n/\nrate(lodestar_historical_state_stfn_epoch_transition_step_seconds_count[$rate_interval])", + "instant": false, + "legendFormat": "{{step}}", + "range": true, + "refId": "A" + } + ], + "title": "Epoch Transition By Steps", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 525, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_process_block_commit_seconds_sum[$rate_interval])\n/\nrate(lodestar_historical_state_stfn_process_block_commit_seconds_count[$rate_interval])", + "interval": "", + "legendFormat": "process block time", + "range": true, + "refId": "A" + } + ], + "title": "Process block commit step avg time", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 4, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 67 + }, + "id": 524, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(lodestar_historical_state_stfn_epoch_transition_commit_seconds_sum[$rate_interval])\n/\nrate(lodestar_historical_state_stfn_epoch_transition_commit_seconds_count[$rate_interval])", + "interval": "", + "legendFormat": "epoch transition", + "range": true, + "refId": "A" + } + ], + "title": "Epoch transition commit step avg time", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "process block time" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "orange", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 67 + }, + "id": 123, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(lodestar_historical_state_stfn_process_block_seconds_sum[6m])", + "interval": "", + "legendFormat": "process block time", + "range": true, + "refId": "A" + } + ], + "title": "Process block utilization rate", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "process block time" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "orange", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 75 + }, + "id": 122, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "rate(lodestar_historical_state_stfn_epoch_transition_seconds_sum[13m])", + "interval": "", + "legendFormat": "process block time", + "range": true, + "refId": "A" + } + ], + "title": "Epoch transition utilization rate", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "process block time" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 75 + }, + "id": 125, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "12*rate(lodestar_historical_state_stfn_process_block_seconds_count[6m])", + "interval": "", + "legendFormat": "process block time", + "range": true, + "refId": "A" + } + ], + "title": "process block / slot", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "min": 0, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "number of epoch transition" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 83 + }, + "id": 124, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "384 * rate(lodestar_historical_state_stfn_epoch_transition_seconds_count[13m])", + "interval": "", + "legendFormat": "number of epoch transition", + "range": true, + "refId": "A" + } + ], + "title": "Epoch transitions / epoch", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 83 + }, + "id": 527, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_validators_nodes_populated_miss_total{source=\"stateTransition\"} [$rate_interval])\n/on(instance)\nrate(lodestar_historical_state_stfn_state_cloned_count_count[$rate_interval])", + "interval": "", + "legendFormat": "stateTransition-validators", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_balances_nodes_populated_miss_total{source=\"stateTransition\"} [$rate_interval])\n/on(instance)\nrate(lodestar_historical_state_stfn_state_cloned_count_count[$rate_interval])", + "hide": false, + "legendFormat": "stateTransition-balances", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_validators_nodes_populated_miss_total{source=\"processSlots\"} [$rate_interval])\n/on(instance)\nrate(lodestar_historical_state_stfn_state_cloned_count_count[$rate_interval])", + "hide": false, + "legendFormat": "processSlots-validators", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_balances_nodes_populated_miss_total{source=\"processSlots\"} [$rate_interval])\n/on(instance)\nrate(lodestar_historical_state_stfn_state_cloned_count_count[$rate_interval])", + "hide": false, + "legendFormat": "processSlots-balances", + "range": true, + "refId": "D" + } + ], + "title": "State SSZ cache miss rate on preState", + "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": 22, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 91 + }, + "id": 526, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_hash_tree_root_seconds_sum[$rate_interval])\n/ on(source)\nrate(lodestar_historical_state_stfn_hash_tree_root_seconds_count[$rate_interval])", + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "State hash_tree_root avg time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 91 + }, + "id": 523, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Magma", + "steps": 50 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "show": true, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false + } + }, + "pluginVersion": "10.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_state_cloned_count_bucket[$rate_interval])", + "format": "heatmap", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Clone count per state", + "type": "heatmap" + }, + { + "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": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [] + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 99 + }, + "id": 521, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_balances_nodes_populated_miss_total{source=\"processSlots\"} [$rate_interval])\n/\nrate(lodestar_historical_state_stfn_state_clone_total[$rate_interval])", + "legendFormat": "balances-{{source}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_balances_nodes_populated_miss_total{source=\"stateTransition\"} [$rate_interval])\n/\nrate(lodestar_historical_state_stfn_state_clone_total[$rate_interval])", + "hide": false, + "legendFormat": "balances-{{source}}", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_validators_nodes_populated_miss_total{source=\"processSlots\"} [$rate_interval])\n/\nrate(lodestar_historical_state_stfn_state_clone_total[$rate_interval])", + "hide": false, + "legendFormat": "validators-{{source}}", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_stfn_validators_nodes_populated_miss_total{source=\"stateTransition\"} [$rate_interval])\n/\nrate(lodestar_historical_state_stfn_state_clone_total[$rate_interval])", + "hide": false, + "legendFormat": "validators-{{source}}", + "range": true, + "refId": "D" + } + ], + "title": "State transition fn nodes populated cache miss", + "type": "timeseries" + } + ], + "refresh": "10s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "lodestar" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "auto": true, + "auto_count": 30, + "auto_min": "10s", + "current": { + "selected": false, + "text": "1h", + "value": "1h" + }, + "hide": 0, + "label": "rate() interval", + "name": "rate_interval", + "options": [ + { + "selected": false, + "text": "auto", + "value": "$__auto_interval_rate_interval" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "10m", + "value": "10m" + }, + { + "selected": false, + "text": "30m", + "value": "30m" + }, + { + "selected": true, + "text": "1h", + "value": "1h" + }, + { + "selected": false, + "text": "6h", + "value": "6h" + }, + { + "selected": false, + "text": "12h", + "value": "12h" + }, + { + "selected": false, + "text": "1d", + "value": "1d" + }, + { + "selected": false, + "text": "7d", + "value": "7d" + }, + { + "selected": false, + "text": "14d", + "value": "14d" + }, + { + "selected": false, + "text": "30d", + "value": "30d" + } + ], + "query": "1m,10m,30m,1h,6h,12h,1d,7d,14d,30d", + "queryValue": "", + "refresh": 2, + "skipUrlSync": false, + "type": "interval" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus_local" + }, + "filters": [ + { + "condition": "", + "key": "instance", + "operator": "=", + "value": "unstable-lg1k-hzax41" + } + ], + "hide": 0, + "name": "Filters", + "skipUrlSync": false, + "type": "adhoc" + }, + { + "description": "Job name used in Prometheus config to scrape Beacon node", + "hide": 2, + "label": "Beacon node job name", + "name": "beacon_job", + "query": "${VAR_BEACON_JOB}", + "skipUrlSync": false, + "type": "constant" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "utc", + "title": "Lodestar - historical state regen", + "uid": "lodestar_historical_state_regen", + "version": 32, + "weekStart": "monday" +} diff --git a/dashboards/lodestar_vm_host.json b/dashboards/lodestar_vm_host.json index 3f6c18bc19c1..457d4d120fa4 100644 --- a/dashboards/lodestar_vm_host.json +++ b/dashboards/lodestar_vm_host.json @@ -177,7 +177,7 @@ }, "editorMode": "code", "exemplar": false, - "expr": "(sum(nodejs_heap_size_total_bytes) + sum(discv5_worker_nodejs_heap_size_total_bytes) + sum(network_worker_nodejs_heap_size_total_bytes))\nor\n(sum(nodejs_heap_size_total_bytes) + sum(discv5_worker_nodejs_heap_size_total_bytes))", + "expr": "(sum(nodejs_heap_size_total_bytes) + sum(discv5_worker_nodejs_heap_size_total_bytes) + sum(network_worker_nodejs_heap_size_total_bytes) + sum(lodestar_historical_state_worker_nodejs_heap_size_total_bytes))\nor\n(sum(nodejs_heap_size_total_bytes) + sum(discv5_worker_nodejs_heap_size_total_bytes) + sum(lodestar_historical_state_worker_nodejs_heap_size_total_bytes))", "hide": false, "interval": "", "legendFormat": "node allocated heap", @@ -191,7 +191,7 @@ }, "editorMode": "code", "exemplar": false, - "expr": "(sum(nodejs_heap_size_used_bytes) + sum(discv5_worker_nodejs_heap_size_used_bytes) + sum(network_worker_nodejs_heap_size_used_bytes)) \nor\n(sum(nodejs_heap_size_used_bytes) + sum(discv5_worker_nodejs_heap_size_used_bytes)) ", + "expr": "(sum(nodejs_heap_size_used_bytes) + sum(discv5_worker_nodejs_heap_size_used_bytes) + sum(network_worker_nodejs_heap_size_used_bytes) + sum(lodestar_historical_state_worker_nodejs_heap_size_used_bytes)) \nor\n(sum(nodejs_heap_size_used_bytes) + sum(discv5_worker_nodejs_heap_size_used_bytes) + sum(lodestar_historical_state_worker_nodejs_heap_size_used_bytes)) ", "hide": false, "interval": "", "legendFormat": "node used heap", @@ -205,7 +205,7 @@ }, "editorMode": "code", "exemplar": false, - "expr": "(sum(nodejs_external_memory_bytes) + sum(discv5_worker_nodejs_external_memory_bytes) + sum(network_worker_nodejs_external_memory_bytes))\nor\n(sum(nodejs_external_memory_bytes) + sum(discv5_worker_nodejs_external_memory_bytes))", + "expr": "(sum(nodejs_external_memory_bytes) + sum(discv5_worker_nodejs_external_memory_bytes) + sum(network_worker_nodejs_external_memory_bytes) + sum(lodestar_historical_state_worker_nodejs_external_memory_bytes))\nor\n(sum(nodejs_external_memory_bytes) + sum(discv5_worker_nodejs_external_memory_bytes) + sum(lodestar_historical_state_worker_nodejs_external_memory_bytes))", "hide": false, "interval": "", "legendFormat": "node external memory", @@ -291,7 +291,7 @@ "uid": "${DS_PROMETHEUS}" }, "editorMode": "code", - "expr": "sum by (space) ({__name__=~\"nodejs_heap_space_size_used_bytes|network_worker_nodejs_heap_space_size_used_bytes|discv5_worker_nodejs_heap_space_size_used_bytes\"})", + "expr": "sum by (space) ({__name__=~\"nodejs_heap_space_size_used_bytes|network_worker_nodejs_heap_space_size_used_bytes|discv5_worker_nodejs_heap_space_size_used_bytes|lodestar_historical_state_worker_nodejs_heap_space_size_used_bytes\")", "hide": false, "interval": "", "legendFormat": "{{space}}", @@ -305,7 +305,7 @@ }, "editorMode": "code", "exemplar": false, - "expr": "(nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + discv5_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + network_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"})\nor\n(nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + discv5_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"})", + "expr": "(nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + discv5_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + network_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + lodestar_historical_state_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"})\nor\n(nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + discv5_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"} + lodestar_historical_state_worker_nodejs_external_memory_bytes{job=~\"$beacon_job|beacon\"})", "hide": false, "interval": "", "legendFormat": "external_memory", @@ -786,6 +786,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -883,6 +884,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1000,6 +1002,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1027,6 +1030,222 @@ "x": 0, "y": 34 }, + "id": 562, + "options": { + "graph": {}, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "7.4.5", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "lodestar_historical_state_worker_nodejs_heap_space_size_used_bytes", + "interval": "", + "legendFormat": "{{space}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "lodestar_historical_state_worker_nodejs_external_memory_bytes", + "hide": false, + "interval": "", + "legendFormat": "external_memory", + "range": true, + "refId": "B" + } + ], + "title": "Historical State Worker Thread - Heap Allocations", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "GC Time", + "axisPlacement": "left", + "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": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "unit": "percentunit" + }, + "overrides": [ + { + "matcher": { + "id": "byFrameRefID", + "options": "C" + }, + "properties": [ + { + "id": "custom.axisPlacement", + "value": "right" + }, + { + "id": "custom.axisLabel", + "value": "GC Bytes" + }, + { + "id": "unit", + "value": "decbytes" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 34 + }, + "id": 563, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "8.4.0-beta1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_worker_nodejs_gc_pause_seconds_total[$rate_interval])", + "hide": false, + "legendFormat": "{{gctype}}", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "expr": "rate(lodestar_historical_state_worker_nodejs_gc_reclaimed_bytes_total[$rate_interval])", + "format": "time_series", + "hide": false, + "legendFormat": "{{gctype}}", + "range": true, + "refId": "C" + } + ], + "title": "HIstorical State Worker Thread - GC pause time rate + reclaimed bytes", + "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": 30, + "gradientMode": "opacity", + "hideFrom": { + "graph": false, + "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": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 42 + }, "id": 542, "options": { "graph": {}, @@ -1097,6 +1316,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1143,7 +1363,7 @@ "h": 8, "w": 12, "x": 12, - "y": 34 + "y": 42 }, "id": 548, "options": { @@ -1199,7 +1419,7 @@ "h": 1, "w": 24, "x": 0, - "y": 42 + "y": 50 }, "id": 12, "panels": [], @@ -1239,6 +1459,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1368,7 +1589,7 @@ "h": 8, "w": 12, "x": 0, - "y": 43 + "y": 51 }, "id": 555, "options": { @@ -1483,6 +1704,7 @@ "tooltip": false, "viz": false }, + "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, @@ -1612,7 +1834,7 @@ "h": 8, "w": 12, "x": 12, - "y": 43 + "y": 51 }, "id": 559, "options": { @@ -1856,7 +2078,7 @@ "h": 8, "w": 12, "x": 0, - "y": 51 + "y": 59 }, "id": 560, "options": { @@ -2100,7 +2322,7 @@ "h": 8, "w": 12, "x": 12, - "y": 51 + "y": 59 }, "id": 561, "options": { @@ -2241,7 +2463,7 @@ "h": 8, "w": 12, "x": 0, - "y": 59 + "y": 67 }, "id": 6, "options": { @@ -2364,7 +2586,7 @@ "h": 8, "w": 12, "x": 12, - "y": 59 + "y": 67 }, "id": 42, "options": { @@ -2443,7 +2665,7 @@ "h": 8, "w": 12, "x": 12, - "y": 67 + "y": 75 }, "id": 268, "options": { @@ -2484,7 +2706,7 @@ "h": 1, "w": 24, "x": 0, - "y": 75 + "y": 83 }, "id": 104, "panels": [], @@ -2550,7 +2772,7 @@ "h": 6, "w": 12, "x": 0, - "y": 76 + "y": 84 }, "id": 102, "options": { @@ -2659,7 +2881,7 @@ "h": 6, "w": 12, "x": 12, - "y": 76 + "y": 84 }, "id": 172, "options": { @@ -2744,7 +2966,7 @@ "h": 6, "w": 12, "x": 0, - "y": 82 + "y": 90 }, "id": 171, "options": { @@ -2787,7 +3009,7 @@ "h": 6, "w": 12, "x": 12, - "y": 82 + "y": 90 }, "id": 99, "options": { @@ -2828,7 +3050,7 @@ "h": 1, "w": 24, "x": 0, - "y": 88 + "y": 96 }, "id": 367, "panels": [], @@ -2894,7 +3116,7 @@ "h": 8, "w": 12, "x": 0, - "y": 89 + "y": 97 }, "id": 353, "options": { @@ -2977,7 +3199,7 @@ "h": 8, "w": 12, "x": 12, - "y": 89 + "y": 97 }, "id": 355, "options": { @@ -3059,7 +3281,7 @@ "h": 8, "w": 12, "x": 0, - "y": 97 + "y": 105 }, "id": 357, "options": { @@ -3522,7 +3744,7 @@ "h": 8, "w": 12, "x": 12, - "y": 97 + "y": 105 }, "id": 359, "links": [], @@ -3665,7 +3887,7 @@ "h": 8, "w": 12, "x": 0, - "y": 105 + "y": 113 }, "id": 361, "options": { @@ -3774,7 +3996,7 @@ "h": 8, "w": 12, "x": 12, - "y": 105 + "y": 113 }, "id": 363, "options": { @@ -3866,7 +4088,7 @@ "h": 8, "w": 12, "x": 0, - "y": 113 + "y": 121 }, "id": 365, "options": { @@ -3919,7 +4141,7 @@ "h": 1, "w": 24, "x": 0, - "y": 121 + "y": 129 }, "id": 46, "panels": [], @@ -3985,7 +4207,7 @@ "h": 8, "w": 12, "x": 0, - "y": 122 + "y": 130 }, "id": 48, "options": { @@ -4112,7 +4334,7 @@ "h": 8, "w": 12, "x": 12, - "y": 122 + "y": 130 }, "id": 50, "options": { @@ -4155,7 +4377,7 @@ "h": 1, "w": 24, "x": 0, - "y": 130 + "y": 138 }, "id": 527, "panels": [], @@ -4221,7 +4443,7 @@ "h": 8, "w": 12, "x": 0, - "y": 131 + "y": 139 }, "id": 529, "options": { @@ -4366,7 +4588,7 @@ "h": 8, "w": 12, "x": 12, - "y": 131 + "y": 139 }, "id": 531, "options": { @@ -4410,7 +4632,7 @@ "h": 1, "w": 24, "x": 0, - "y": 139 + "y": 147 }, "id": 86, "panels": [], @@ -4475,7 +4697,7 @@ "h": 11, "w": 12, "x": 0, - "y": 140 + "y": 148 }, "id": 84, "options": { @@ -4558,7 +4780,7 @@ "h": 11, "w": 12, "x": 12, - "y": 140 + "y": 148 }, "id": 87, "options": { @@ -4639,7 +4861,7 @@ "h": 8, "w": 12, "x": 0, - "y": 151 + "y": 159 }, "id": 516, "options": { @@ -4730,7 +4952,7 @@ "h": 8, "w": 12, "x": 12, - "y": 151 + "y": 159 }, "id": 515, "options": { @@ -4809,7 +5031,7 @@ "h": 8, "w": 12, "x": 0, - "y": 159 + "y": 167 }, "id": 513, "options": { @@ -4888,7 +5110,7 @@ "h": 8, "w": 12, "x": 12, - "y": 159 + "y": 167 }, "id": 517, "options": { @@ -4928,7 +5150,7 @@ "h": 1, "w": 24, "x": 0, - "y": 167 + "y": 175 }, "id": 164, "panels": [], @@ -4995,7 +5217,7 @@ "h": 9, "w": 12, "x": 0, - "y": 168 + "y": 176 }, "id": 160, "options": { @@ -5079,7 +5301,7 @@ "h": 9, "w": 12, "x": 12, - "y": 168 + "y": 176 }, "id": 162, "options": { @@ -5163,7 +5385,7 @@ "h": 9, "w": 12, "x": 0, - "y": 177 + "y": 185 }, "id": 481, "options": { @@ -5247,7 +5469,7 @@ "h": 9, "w": 12, "x": 12, - "y": 177 + "y": 185 }, "id": 480, "options": { @@ -5354,7 +5576,7 @@ "h": 8, "w": 12, "x": 0, - "y": 186 + "y": 194 }, "id": 535, "options": { @@ -5459,7 +5681,7 @@ "h": 8, "w": 12, "x": 12, - "y": 186 + "y": 194 }, "id": 537, "options": { @@ -5540,7 +5762,7 @@ "h": 8, "w": 12, "x": 0, - "y": 194 + "y": 202 }, "id": 533, "options": { diff --git a/packages/beacon-node/src/api/impl/beacon/state/utils.ts b/packages/beacon-node/src/api/impl/beacon/state/utils.ts index a2079afaf9b8..7bea4fec7071 100644 --- a/packages/beacon-node/src/api/impl/beacon/state/utils.ts +++ b/packages/beacon-node/src/api/impl/beacon/state/utils.ts @@ -66,7 +66,7 @@ export async function getStateResponseWithRegen( ? await chain.getStateByStateRoot(rootOrSlot, {allowRegen: true}) : rootOrSlot >= chain.forkChoice.getFinalizedBlock().slot ? await chain.getStateBySlot(rootOrSlot, {allowRegen: true}) - : null; // TODO implement historical state regen + : await chain.getHistoricalStateBySlot(rootOrSlot); if (!res) { throw new ApiError(404, `No state found for id '${stateId}'`); diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index 081de6f85063..f32a44bf4e5d 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -89,6 +89,7 @@ import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produ import {computeNewStateRoot} from "./produceBlock/computeNewStateRoot.js"; import {BlockInput} from "./blocks/types.js"; import {SeenAttestationDatas} from "./seenCache/seenAttestationData.js"; +import {HistoricalStateRegen} from "./historicalState/index.js"; import {BlockRewards, computeBlockRewards} from "./rewards/blockRewards.js"; import {ShufflingCache} from "./shufflingCache.js"; import {BlockStateCacheImpl} from "./stateCache/blockStateCacheImpl.js"; @@ -128,6 +129,7 @@ export class BeaconChain implements IBeaconChain { readonly regen: QueuedStateRegenerator; readonly lightClientServer?: LightClientServer; readonly reprocessController: ReprocessController; + readonly historicalStateRegen?: HistoricalStateRegen; // Ops pool readonly attestationPool: AttestationPool; @@ -185,6 +187,7 @@ export class BeaconChain implements IBeaconChain { eth1, executionEngine, executionBuilder, + historicalStateRegen, }: { config: BeaconConfig; db: IBeaconDb; @@ -197,6 +200,7 @@ export class BeaconChain implements IBeaconChain { eth1: IEth1ForBlockProduction; executionEngine: IExecutionEngine; executionBuilder?: IExecutionBuilder; + historicalStateRegen?: HistoricalStateRegen; } ) { this.opts = opts; @@ -211,6 +215,7 @@ export class BeaconChain implements IBeaconChain { this.eth1 = eth1; this.executionEngine = executionEngine; this.executionBuilder = executionBuilder; + this.historicalStateRegen = historicalStateRegen; const signal = this.abortController.signal; const emitter = new ChainEventEmitter(); // by default, verify signatures on both main threads and worker threads @@ -418,47 +423,61 @@ export class BeaconChain implements IBeaconChain { ): Promise<{state: BeaconStateAllForks; executionOptimistic: boolean; finalized: boolean} | null> { const finalizedBlock = this.forkChoice.getFinalizedBlock(); - if (slot >= finalizedBlock.slot) { - // request for non-finalized state - - if (opts?.allowRegen) { - // Find closest canonical block to slot, then trigger regen - const block = this.forkChoice.getCanonicalBlockClosestLteSlot(slot) ?? finalizedBlock; - const state = await this.regen.getBlockSlotState( - block.blockRoot, - slot, - {dontTransferCache: true}, - RegenCaller.restApi - ); - return { + if (slot < finalizedBlock.slot) { + // request for finalized state not supported in this API + // fall back to caller to look in db or getHistoricalStateBySlot + return null; + } + + if (opts?.allowRegen) { + // Find closest canonical block to slot, then trigger regen + const block = this.forkChoice.getCanonicalBlockClosestLteSlot(slot) ?? finalizedBlock; + const state = await this.regen.getBlockSlotState( + block.blockRoot, + slot, + {dontTransferCache: true}, + RegenCaller.restApi + ); + return { + state, + executionOptimistic: isOptimisticBlock(block), + finalized: slot === finalizedBlock.slot && finalizedBlock.slot !== GENESIS_SLOT, + }; + } else { + // Just check if state is already in the cache. If it's not dialed to the correct slot, + // do not bother in advancing the state. restApiCanTriggerRegen == false means do no work + const block = this.forkChoice.getCanonicalBlockAtSlot(slot); + if (!block) { + return null; + } + + const state = this.regen.getStateSync(block.stateRoot); + return ( + state && { state, executionOptimistic: isOptimisticBlock(block), finalized: slot === finalizedBlock.slot && finalizedBlock.slot !== GENESIS_SLOT, - }; - } else { - // Just check if state is already in the cache. If it's not dialed to the correct slot, - // do not bother in advancing the state. restApiCanTriggerRegen == false means do no work - const block = this.forkChoice.getCanonicalBlockAtSlot(slot); - if (!block) { - return null; } + ); + } + } - const state = this.regen.getStateSync(block.stateRoot); - return ( - state && { - state, - executionOptimistic: isOptimisticBlock(block), - finalized: slot === finalizedBlock.slot && finalizedBlock.slot !== GENESIS_SLOT, - } - ); - } - } else { - // request for finalized state + async getHistoricalStateBySlot( + slot: number + ): Promise<{state: Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> { + const finalizedBlock = this.forkChoice.getFinalizedBlock(); + + if (slot >= finalizedBlock.slot) { + return null; + } - // do not attempt regen, just check if state is already in DB - const state = await this.db.stateArchive.get(slot); - return state && {state, executionOptimistic: false, finalized: true}; + // request for finalized state using historical state regen + const stateSerialized = await this.historicalStateRegen?.getHistoricalState(slot); + if (!stateSerialized) { + return null; } + + return {state: stateSerialized, executionOptimistic: false, finalized: true}; } async getStateByStateRoot( diff --git a/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts b/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts new file mode 100644 index 000000000000..ada4f3c284d7 --- /dev/null +++ b/packages/beacon-node/src/chain/historicalState/getHistoricalState.ts @@ -0,0 +1,111 @@ +import { + BeaconStateAllForks, + CachedBeaconStateAllForks, + DataAvailableStatus, + ExecutionPayloadStatus, + PubkeyIndexMap, + createCachedBeaconState, + stateTransition, +} from "@lodestar/state-transition"; +import {BeaconConfig} from "@lodestar/config"; +import {IBeaconDb} from "../../db/index.js"; +import {HistoricalStateRegenMetrics, RegenErrorType} from "./types.js"; + +/** + * Populate a PubkeyIndexMap with any new entries based on a BeaconState + */ +export function syncPubkeyCache(state: BeaconStateAllForks, pubkey2index: PubkeyIndexMap): void { + // Get the validators sub tree once for all the loop + const validators = state.validators; + + const newCount = state.validators.length; + for (let i = pubkey2index.size; i < newCount; i++) { + const pubkey = validators.getReadonly(i).pubkey; + pubkey2index.set(pubkey, i); + } +} + +/** + * Get the nearest BeaconState at or before a slot + */ +export async function getNearestState( + slot: number, + config: BeaconConfig, + db: IBeaconDb, + pubkey2index: PubkeyIndexMap +): Promise { + const states = await db.stateArchive.values({limit: 1, lte: slot, reverse: true}); + if (!states.length) { + throw new Error("No near state found in the database"); + } + + const state = states[0]; + syncPubkeyCache(state, pubkey2index); + + return createCachedBeaconState( + state, + { + config, + pubkey2index, + index2pubkey: [], + }, + { + skipSyncPubkeys: true, + } + ); +} + +/** + * Get and regenerate a historical state + */ +export async function getHistoricalState( + slot: number, + config: BeaconConfig, + db: IBeaconDb, + pubkey2index: PubkeyIndexMap, + metrics?: HistoricalStateRegenMetrics +): Promise { + const regenTimer = metrics?.regenTime.startTimer(); + + const loadStateTimer = metrics?.loadStateTime.startTimer(); + let state = await getNearestState(slot, config, db, pubkey2index).catch((e) => { + metrics?.regenErrorCount.inc({reason: RegenErrorType.loadState}); + throw e; + }); + loadStateTimer?.(); + + const transitionTimer = metrics?.stateTransitionTime.startTimer(); + let blockCount = 0; + for await (const block of db.blockArchive.valuesStream({gt: state.slot, lte: slot})) { + try { + state = stateTransition( + state, + block, + { + verifyProposer: false, + verifySignatures: false, + verifyStateRoot: false, + executionPayloadStatus: ExecutionPayloadStatus.valid, + dataAvailableStatus: DataAvailableStatus.available, + }, + metrics + ); + } catch (e) { + metrics?.regenErrorCount.inc({reason: RegenErrorType.blockProcessing}); + throw e; + } + blockCount++; + if (Buffer.compare(state.hashTreeRoot(), block.message.stateRoot) !== 0) { + metrics?.regenErrorCount.inc({reason: RegenErrorType.invalidStateRoot}); + } + } + metrics?.stateTransitionBlocks.observe(blockCount); + transitionTimer?.(); + + const serializeTimer = metrics?.stateSerializationTime.startTimer(); + const stateBytes = state.serialize(); + serializeTimer?.(); + + regenTimer?.(); + return stateBytes; +} diff --git a/packages/beacon-node/src/chain/historicalState/index.ts b/packages/beacon-node/src/chain/historicalState/index.ts new file mode 100644 index 000000000000..8688bcf9f372 --- /dev/null +++ b/packages/beacon-node/src/chain/historicalState/index.ts @@ -0,0 +1,67 @@ +import path from "node:path"; +import {ModuleThread, Thread, spawn, Worker} from "@chainsafe/threads"; +import {chainConfigToJson} from "@lodestar/config"; +import {LoggerNode} from "@lodestar/logger/node"; +import { + HistoricalStateRegenInitModules, + HistoricalStateRegenModules, + HistoricalStateWorkerApi, + HistoricalStateWorkerData, +} from "./types.js"; + +// Worker constructor consider the path relative to the current working directory +const WORKER_DIR = process.env.NODE_ENV === "test" ? "../../../lib/chain/historicalState" : "./"; + +/** + * HistoricalStateRegen limits the damage from recreating historical states + * by running regen in a separate worker thread. + */ +export class HistoricalStateRegen implements HistoricalStateWorkerApi { + private readonly api: ModuleThread; + private readonly logger: LoggerNode; + + constructor(modules: HistoricalStateRegenModules) { + this.api = modules.api; + this.logger = modules.logger; + modules.signal?.addEventListener("abort", () => this.close(), {once: true}); + } + static async init(modules: HistoricalStateRegenInitModules): Promise { + const workerData: HistoricalStateWorkerData = { + chainConfigJson: chainConfigToJson(modules.config), + genesisValidatorsRoot: modules.config.genesisValidatorsRoot, + genesisTime: modules.opts.genesisTime, + maxConcurrency: 1, + maxLength: 50, + dbLocation: modules.opts.dbLocation, + metricsEnabled: Boolean(modules.metrics), + loggerOpts: modules.logger.toOpts(), + }; + + const worker = new Worker(path.join(WORKER_DIR, "worker.js"), { + workerData, + } as ConstructorParameters[1]); + + const api = await spawn(worker, { + // A Lodestar Node may do very expensive task at start blocking the event loop and causing + // the initialization to timeout. The number below is big enough to almost disable the timeout + timeout: 5 * 60 * 1000, + }); + + return new HistoricalStateRegen({...modules, api}); + } + + async scrapeMetrics(): Promise { + return this.api.scrapeMetrics(); + } + + async close(): Promise { + await this.api.close(); + this.logger.debug("Terminating historical state worker"); + await Thread.terminate(this.api); + this.logger.debug("Terminated historical state worker"); + } + + async getHistoricalState(slot: number): Promise { + return this.api.getHistoricalState(slot); + } +} diff --git a/packages/beacon-node/src/chain/historicalState/types.ts b/packages/beacon-node/src/chain/historicalState/types.ts new file mode 100644 index 000000000000..5bc813141a5d --- /dev/null +++ b/packages/beacon-node/src/chain/historicalState/types.ts @@ -0,0 +1,54 @@ +import {ModuleThread} from "@chainsafe/threads"; +import {BeaconConfig} from "@lodestar/config"; +import {LoggerNode, LoggerNodeOpts} from "@lodestar/logger/node"; +import {BeaconStateTransitionMetrics} from "@lodestar/state-transition"; +import {Gauge, Histogram} from "@lodestar/utils"; +import {Metrics} from "../../metrics/index.js"; + +export type HistoricalStateRegenInitModules = { + opts: { + genesisTime: number; + dbLocation: string; + }; + config: BeaconConfig; + logger: LoggerNode; + metrics: Metrics | null; + signal?: AbortSignal; +}; +export type HistoricalStateRegenModules = HistoricalStateRegenInitModules & { + api: ModuleThread; +}; + +export type HistoricalStateWorkerData = { + chainConfigJson: Record; + genesisValidatorsRoot: Uint8Array; + genesisTime: number; + maxConcurrency: number; + maxLength: number; + dbLocation: string; + metricsEnabled: boolean; + loggerOpts: LoggerNodeOpts; +}; + +export type HistoricalStateWorkerApi = { + close(): Promise; + scrapeMetrics(): Promise; + getHistoricalState(slot: number): Promise; +}; + +export enum RegenErrorType { + loadState = "load_state", + invalidStateRoot = "invalid_state_root", + blockProcessing = "block_processing", +} + +export type HistoricalStateRegenMetrics = BeaconStateTransitionMetrics & { + regenTime: Histogram; + loadStateTime: Histogram; + stateTransitionTime: Histogram; + stateTransitionBlocks: Histogram; + stateSerializationTime: Histogram; + regenRequestCount: Gauge; + regenSuccessCount: Gauge; + regenErrorCount: Gauge<{reason: RegenErrorType}>; +}; diff --git a/packages/beacon-node/src/chain/historicalState/worker.ts b/packages/beacon-node/src/chain/historicalState/worker.ts new file mode 100644 index 000000000000..9a9f9cc9cd0e --- /dev/null +++ b/packages/beacon-node/src/chain/historicalState/worker.ts @@ -0,0 +1,231 @@ +import worker from "node:worker_threads"; +import {Transfer, expose} from "@chainsafe/threads/worker"; +import {createBeaconConfig, chainConfigFromJson} from "@lodestar/config"; +import {getNodeLogger} from "@lodestar/logger/node"; +import { + EpochTransitionStep, + PubkeyIndexMap, + StateCloneSource, + StateHashTreeRootSource, +} from "@lodestar/state-transition"; +import {LevelDbController} from "@lodestar/db"; +import {RegistryMetricCreator, collectNodeJSMetrics} from "../../metrics/index.js"; +import {JobFnQueue} from "../../util/queue/fnQueue.js"; +import {QueueMetrics} from "../../util/queue/options.js"; +import {BeaconDb} from "../../db/index.js"; +import { + HistoricalStateRegenMetrics, + HistoricalStateWorkerApi, + HistoricalStateWorkerData, + RegenErrorType, +} from "./types.js"; +import {getHistoricalState} from "./getHistoricalState.js"; + +// most of this setup copied from networkCoreWorker.ts + +const workerData = worker.workerData as HistoricalStateWorkerData; + +// TODO: Pass options from main thread for logging +// TODO: Logging won't be visible in file loggers +const logger = getNodeLogger(workerData.loggerOpts); + +logger.info("Historical state worker started"); + +const config = createBeaconConfig(chainConfigFromJson(workerData.chainConfigJson), workerData.genesisValidatorsRoot); + +const db = new BeaconDb(config, await LevelDbController.create({name: workerData.dbLocation}, {logger})); + +const abortController = new AbortController(); + +// Set up metrics, nodejs, state transition, queue +const metricsRegister = workerData.metricsEnabled ? new RegistryMetricCreator() : null; +let historicalStateRegenMetrics: HistoricalStateRegenMetrics | undefined; +let queueMetrics: QueueMetrics | undefined; +if (metricsRegister) { + const closeMetrics = collectNodeJSMetrics(metricsRegister, "lodestar_historical_state_worker_"); + abortController.signal.addEventListener("abort", closeMetrics, {once: true}); + + historicalStateRegenMetrics = { + // state transition metrics + epochTransitionTime: metricsRegister.histogram({ + name: "lodestar_historical_state_stfn_epoch_transition_seconds", + help: "Time to process a single epoch transition in seconds", + // Epoch transitions are 100ms on very fast clients, and average 800ms on heavy networks + buckets: [0.01, 0.05, 0.1, 0.2, 0.5, 0.75, 1, 1.25, 1.5, 3, 10], + }), + epochTransitionCommitTime: metricsRegister.histogram({ + name: "lodestar_historical_state_stfn_epoch_transition_commit_seconds", + help: "Time to call commit after process a single epoch transition in seconds", + buckets: [0.01, 0.05, 0.1, 0.2, 0.5, 0.75, 1], + }), + epochTransitionStepTime: metricsRegister.histogram<{step: EpochTransitionStep}>({ + name: "lodestar_historical_state_stfn_epoch_transition_step_seconds", + help: "Time to call each step of epoch transition in seconds", + labelNames: ["step"], + buckets: [0.01, 0.05, 0.1, 0.2, 0.5, 0.75, 1], + }), + processBlockTime: metricsRegister.histogram({ + name: "lodestar_historical_state_stfn_process_block_seconds", + help: "Time to process a single block in seconds", + // TODO: Add metrics for each step + // Block processing can take 5-40ms, 100ms max + buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1], + }), + processBlockCommitTime: metricsRegister.histogram({ + name: "lodestar_historical_state_stfn_process_block_commit_seconds", + help: "Time to call commit after process a single block in seconds", + buckets: [0.005, 0.01, 0.02, 0.05, 0.1, 1], + }), + stateHashTreeRootTime: metricsRegister.histogram<{source: StateHashTreeRootSource}>({ + name: "lodestar_historical_state_stfn_hash_tree_root_seconds", + help: "Time to compute the hash tree root of a post state in seconds", + buckets: [0.05, 0.1, 0.2, 0.5, 1, 1.5], + labelNames: ["source"], + }), + preStateBalancesNodesPopulatedMiss: metricsRegister.gauge<{source: StateCloneSource}>({ + name: "lodestar_historical_state_stfn_balances_nodes_populated_miss_total", + help: "Total count state.balances nodesPopulated is false on stfn", + labelNames: ["source"], + }), + preStateBalancesNodesPopulatedHit: metricsRegister.gauge<{source: StateCloneSource}>({ + name: "lodestar_historical_state_stfn_balances_nodes_populated_hit_total", + help: "Total count state.balances nodesPopulated is true on stfn", + labelNames: ["source"], + }), + preStateValidatorsNodesPopulatedMiss: metricsRegister.gauge<{source: StateCloneSource}>({ + name: "lodestar_historical_state_stfn_validators_nodes_populated_miss_total", + help: "Total count state.validators nodesPopulated is false on stfn", + labelNames: ["source"], + }), + preStateValidatorsNodesPopulatedHit: metricsRegister.gauge<{source: StateCloneSource}>({ + name: "lodestar_historical_state_stfn_validators_nodes_populated_hit_total", + help: "Total count state.validators nodesPopulated is true on stfn", + labelNames: ["source"], + }), + preStateClonedCount: metricsRegister.histogram({ + name: "lodestar_historical_state_stfn_state_cloned_count", + help: "Histogram of cloned count per state every time state.clone() is called", + buckets: [1, 2, 5, 10, 50, 250], + }), + postStateBalancesNodesPopulatedHit: metricsRegister.gauge({ + name: "lodestar_historical_state_stfn_post_state_balances_nodes_populated_hit_total", + help: "Total count state.validators nodesPopulated is true on stfn for post state", + }), + postStateBalancesNodesPopulatedMiss: metricsRegister.gauge({ + name: "lodestar_historical_state_stfn_post_state_balances_nodes_populated_miss_total", + help: "Total count state.validators nodesPopulated is false on stfn for post state", + }), + postStateValidatorsNodesPopulatedHit: metricsRegister.gauge({ + name: "lodestar_historical_state_stfn_post_state_validators_nodes_populated_hit_total", + help: "Total count state.validators nodesPopulated is true on stfn for post state", + }), + postStateValidatorsNodesPopulatedMiss: metricsRegister.gauge({ + name: "lodestar_historical_state_stfn_post_state_validators_nodes_populated_miss_total", + help: "Total count state.validators nodesPopulated is false on stfn for post state", + }), + registerValidatorStatuses: () => {}, + + // historical state regen metrics + regenTime: metricsRegister.histogram({ + name: "lodestar_historical_state_regen_time_seconds", + help: "Time to regenerate a historical state in seconds", + // Historical state regen can take up to 3h as of Aug 2024 + // 5m, 10m, 30m, 1h, 3h + buckets: [5 * 60, 10 * 60, 30 * 60, 60 * 60, 180 * 60], + }), + loadStateTime: metricsRegister.histogram({ + name: "lodestar_historical_state_load_nearest_state_time_seconds", + help: "Time to load a nearest historical state from the database in seconds", + // 30s, 1m, 2m, 4m + buckets: [30, 60, 120, 240], + }), + stateTransitionTime: metricsRegister.histogram({ + name: "lodestar_historical_state_state_transition_time_seconds", + help: "Time to run state transition to regen historical state in seconds", + // 5m, 10m, 30m, 1h, 3h + buckets: [5 * 60, 10 * 60, 30 * 60, 60 * 60, 180 * 60], + }), + stateTransitionBlocks: metricsRegister.histogram({ + name: "lodestar_historical_state_state_transition_blocks", + help: "Count of blocks processed during state transition to regen historical state", + // given archiveStateEpochFrequency=1024, it could process up to 32768 blocks + buckets: [10, 100, 1000, 10000, 30000], + }), + stateSerializationTime: metricsRegister.histogram({ + name: "lodestar_historical_state_serialization_time_seconds", + help: "Time to serialize a historical state in seconds", + buckets: [0.25, 0.5, 1, 2], + }), + regenRequestCount: metricsRegister.gauge({ + name: "lodestar_historical_state_request_count", + help: "Count of total historical state requests", + }), + regenSuccessCount: metricsRegister.gauge({ + name: "lodestar_historical_state_success_count", + help: "Count of successful historical state regen", + }), + regenErrorCount: metricsRegister.gauge<{reason: RegenErrorType}>({ + name: "lodestar_historical_state_error_count", + help: "Count of failed historical state regen", + labelNames: ["reason"], + }), + }; + + queueMetrics = { + length: metricsRegister.gauge({ + name: "lodestar_historical_state_queue_length", + help: "Count of total regen queue length", + }), + droppedJobs: metricsRegister.gauge({ + name: "lodestar_historical_state_queue_dropped_jobs_total", + help: "Count of total regen queue dropped jobs", + }), + jobTime: metricsRegister.histogram({ + name: "lodestar_historical_state_queue_job_time_seconds", + help: "Time to process regen queue job in seconds", + buckets: [0.01, 0.1, 1, 10, 100], + }), + jobWaitTime: metricsRegister.histogram({ + name: "lodestar_historical_state_queue_job_wait_time_seconds", + help: "Time from job added to the regen queue to starting in seconds", + buckets: [0.01, 0.1, 1, 10, 100], + }), + concurrency: metricsRegister.gauge({ + name: "lodestar_historical_state_queue_concurrency", + help: "Current concurrency of regen queue", + }), + }; +} + +const queue = new JobFnQueue( + { + maxConcurrency: workerData.maxConcurrency, + maxLength: workerData.maxLength, + signal: abortController.signal, + }, + queueMetrics +); + +const pubkey2index = new PubkeyIndexMap(); + +const api: HistoricalStateWorkerApi = { + async close() { + abortController.abort(); + }, + async scrapeMetrics() { + return metricsRegister?.metrics() ?? ""; + }, + async getHistoricalState(slot) { + historicalStateRegenMetrics?.regenRequestCount.inc(); + + const stateBytes = await queue.push(() => + getHistoricalState(slot, config, db, pubkey2index, historicalStateRegenMetrics) + ); + const result = Transfer(stateBytes, [stateBytes.buffer]) as unknown as Uint8Array; + + historicalStateRegenMetrics?.regenSuccessCount.inc(); + return result; + }, +}; + +expose(api); diff --git a/packages/beacon-node/src/chain/interface.ts b/packages/beacon-node/src/chain/interface.ts index aa70b0bdcce4..3bde2e4acb7a 100644 --- a/packages/beacon-node/src/chain/interface.ts +++ b/packages/beacon-node/src/chain/interface.ts @@ -142,6 +142,10 @@ export interface IBeaconChain { getHeadStateAtCurrentEpoch(regenCaller: RegenCaller): Promise; getHeadStateAtEpoch(epoch: Epoch, regenCaller: RegenCaller): Promise; + getHistoricalStateBySlot( + slot: Slot + ): Promise<{state: Uint8Array; executionOptimistic: boolean; finalized: boolean} | null>; + /** Returns a local state canonical at `slot` */ getStateBySlot( slot: Slot, diff --git a/packages/beacon-node/src/metrics/server/http.ts b/packages/beacon-node/src/metrics/server/http.ts index d8fbb289e951..e197dcfa2a25 100644 --- a/packages/beacon-node/src/metrics/server/http.ts +++ b/packages/beacon-node/src/metrics/server/http.ts @@ -24,9 +24,9 @@ export async function getHttpMetricsServer( opts: HttpMetricsServerOpts, { register, - getOtherMetrics = async () => "", + getOtherMetrics = async () => [], logger, - }: {register: Registry; getOtherMetrics?: () => Promise; logger: Logger} + }: {register: Registry; getOtherMetrics?: () => Promise; logger: Logger} ): Promise { // New registry to metric the metrics. Using the same registry would deadlock the .metrics promise const httpServerRegister = new RegistryMetricCreator(); @@ -53,7 +53,8 @@ export async function getHttpMetricsServer( } else { // Get scrape time metrics const httpServerMetrics = await httpServerRegister.metrics(); - const metricsStr = `${metricsRes[0].result}\n\n${metricsRes[1]}\n\n${httpServerMetrics}`; + const metrics = [metricsRes[0].result, httpServerMetrics, ...metricsRes[1]]; + const metricsStr = metrics.join("\n\n"); res.writeHead(200, {"content-type": register.contentType}).end(metricsStr); } } else { diff --git a/packages/beacon-node/src/node/nodejs.ts b/packages/beacon-node/src/node/nodejs.ts index a1147b60bea2..088541a6b5d5 100644 --- a/packages/beacon-node/src/node/nodejs.ts +++ b/packages/beacon-node/src/node/nodejs.ts @@ -21,6 +21,7 @@ import {getApi, BeaconRestApiServer} from "../api/index.js"; import {initializeExecutionEngine, initializeExecutionBuilder} from "../execution/index.js"; import {initializeEth1ForBlockProduction} from "../eth1/index.js"; import {initCKZG, loadEthereumTrustedSetup, TrustedFileMode} from "../util/kzg.js"; +import {HistoricalStateRegen} from "../chain/historicalState/index.js"; import {IBeaconNodeOptions} from "./options.js"; import {runNodeNotifier} from "./notifier.js"; @@ -194,6 +195,17 @@ export class BeaconNode { ) : null; + const historicalStateRegen = await HistoricalStateRegen.init({ + opts: { + genesisTime: anchorState.genesisTime, + dbLocation: opts.db.name, + }, + config, + metrics, + logger: logger.child({module: LoggerModule.chain}), + signal, + }); + const chain = new BeaconChain(opts.chain, { config, db, @@ -216,6 +228,7 @@ export class BeaconNode { executionBuilder: opts.executionBuilder.enabled ? initializeExecutionBuilder(opts.executionBuilder, config, metrics, logger) : undefined, + historicalStateRegen, }); // Load persisted data from disk to in-memory caches @@ -274,7 +287,7 @@ export class BeaconNode { const metricsServer = opts.metrics.enabled ? await getHttpMetricsServer(opts.metrics, { register: (metrics as Metrics).register, - getOtherMetrics: () => network.scrapeMetrics(), + getOtherMetrics: async () => Promise.all([network.scrapeMetrics(), historicalStateRegen.scrapeMetrics()]), logger: logger.child({module: LoggerModule.metrics}), }) : null; diff --git a/packages/db/src/controller/level.ts b/packages/db/src/controller/level.ts index 07ebef8e8a22..084b577b6a01 100644 --- a/packages/db/src/controller/level.ts +++ b/packages/db/src/controller/level.ts @@ -44,7 +44,12 @@ export class LevelDbController implements DatabaseController { const db = - opts.db || new ClassicLevel(opts.name || "beaconchain", {keyEncoding: "binary", valueEncoding: "binary"}); + opts.db || + new ClassicLevel(opts.name || "beaconchain", { + keyEncoding: "binary", + valueEncoding: "binary", + multithreading: true, + }); try { await db.open(); From 4c3199a42eb9b88a38f660f550ea4eea905eb1a7 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 30 Jul 2024 13:45:19 +0100 Subject: [PATCH 26/44] fix: sanitize url in http client debug logs and metrics (#6974) * fix: sanitize url in http client debug logs and metrics * Improve naming consistency * Clean up * Re-assign baseUrl to fix type inference --- packages/api/src/utils/client/httpClient.ts | 31 ++++++++++++------- packages/api/src/utils/client/request.ts | 7 ++++- .../src/eth1/provider/eth1Provider.ts | 4 +-- .../beacon-node/src/execution/builder/http.ts | 4 +-- .../beacon-node/src/execution/engine/index.ts | 4 +-- .../src/cmds/validator/signers/logSigners.ts | 4 +-- packages/utils/src/url.ts | 4 +-- .../src/services/externalSignerSync.ts | 4 +-- packages/validator/src/validator.ts | 6 ++-- 9 files changed, 41 insertions(+), 27 deletions(-) diff --git a/packages/api/src/utils/client/httpClient.ts b/packages/api/src/utils/client/httpClient.ts index 27757aa0846c..e11e35dc85c7 100644 --- a/packages/api/src/utils/client/httpClient.ts +++ b/packages/api/src/utils/client/httpClient.ts @@ -1,4 +1,4 @@ -import {ErrorAborted, Logger, MapDef, TimeoutError, isValidHttpUrl, retry} from "@lodestar/utils"; +import {ErrorAborted, Logger, MapDef, TimeoutError, isValidHttpUrl, retry, toPrintableUrl} from "@lodestar/utils"; import {mergeHeaders} from "../headers.js"; import {Endpoint} from "../types.js"; import {WireFormat} from "../wireFormat.js"; @@ -115,7 +115,12 @@ export class HttpClient implements IHttpClient { } // De-duplicate by baseUrl, having two baseUrls with different token or timeouts does not make sense if (!this.urlsInits.some((opt) => opt.baseUrl === urlInit.baseUrl)) { - this.urlsInits.push({...urlInit, urlIndex: i} as UrlInitRequired); + this.urlsInits.push({ + ...urlInit, + baseUrl: urlInit.baseUrl, + urlIndex: i, + printableUrl: toPrintableUrl(urlInit.baseUrl), + }); } } @@ -134,7 +139,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, baseUrl: this.urlsInits[i].baseUrl}, this.urlsScore[i]); + metrics.urlsScore.set({urlIndex: i, baseUrl: this.urlsInits[i].printableUrl}, this.urlsScore[i]); } }); } @@ -185,12 +190,12 @@ export class HttpClient implements IHttpClient { // - If url[0] is good, only send to 0 // - If url[0] has recently errored, send to both 0, 1, etc until url[0] does not error for some time for (; i < this.urlsInits.length; i++) { - const baseUrl = this.urlsInits[i].baseUrl; + const {printableUrl} = this.urlsInits[i]; const routeId = definition.operationId; if (i > 0) { - this.metrics?.requestToFallbacks.inc({routeId, baseUrl}); - this.logger?.debug("Requesting fallback URL", {routeId, baseUrl, score: this.urlsScore[i]}); + this.metrics?.requestToFallbacks.inc({routeId, baseUrl: printableUrl}); + this.logger?.debug("Requesting fallback URL", {routeId, baseUrl: printableUrl, score: this.urlsScore[i]}); } // eslint-disable-next-line @typescript-eslint/naming-convention @@ -217,7 +222,11 @@ export class HttpClient implements IHttpClient { if (++errorCount >= requestCount) { resolve(res); } else { - this.logger?.debug("Request error, retrying", {routeId, baseUrl}, res.error() as Error); + this.logger?.debug( + "Request error, retrying", + {routeId, baseUrl: printableUrl}, + res.error() as Error + ); } } }, @@ -229,7 +238,7 @@ export class HttpClient implements IHttpClient { if (++errorCount >= requestCount) { reject(err); } else { - this.logger?.debug("Request error, retrying", {routeId, baseUrl}, err); + this.logger?.debug("Request error, retrying", {routeId, baseUrl: printableUrl}, err); } } ); @@ -347,7 +356,7 @@ export class HttpClient implements IHttpClient { abortSignals.forEach((s) => s?.addEventListener("abort", onSignalAbort)); const routeId = definition.operationId; - const {baseUrl, requestWireFormat, responseWireFormat} = init; + const {printableUrl, requestWireFormat, responseWireFormat} = init; const timer = this.metrics?.requestTime.startTimer({routeId}); try { @@ -359,7 +368,7 @@ export class HttpClient implements IHttpClient { if (!apiResponse.ok) { await apiResponse.errorBody(); this.logger?.debug("API response error", {routeId, status: apiResponse.status}); - this.metrics?.requestErrors.inc({routeId, baseUrl}); + this.metrics?.requestErrors.inc({routeId, baseUrl: printableUrl}); return apiResponse; } @@ -376,7 +385,7 @@ export class HttpClient implements IHttpClient { streamTimer?.(); } } catch (e) { - this.metrics?.requestErrors.inc({routeId, baseUrl}); + this.metrics?.requestErrors.inc({routeId, baseUrl: printableUrl}); if (isAbortedError(e)) { if (abortSignals.some((s) => s?.aborted)) { diff --git a/packages/api/src/utils/client/request.ts b/packages/api/src/utils/client/request.ts index 9c36ad111972..2040f1bbc5a9 100644 --- a/packages/api/src/utils/client/request.ts +++ b/packages/api/src/utils/client/request.ts @@ -28,7 +28,12 @@ export type OptionalRequestInit = { }; export type UrlInit = ApiRequestInit & {baseUrl?: string}; -export type UrlInitRequired = ApiRequestInit & {urlIndex: number; baseUrl: string}; +export type UrlInitRequired = ApiRequestInit & { + urlIndex: number; + baseUrl: string; + /** Used in logs and metrics to prevent leaking user credentials */ + printableUrl: string; +}; export type ApiRequestInit = ExtraRequestInit & OptionalRequestInit & RequestInit; export type ApiRequestInitRequired = Required & UrlInitRequired; diff --git a/packages/beacon-node/src/eth1/provider/eth1Provider.ts b/packages/beacon-node/src/eth1/provider/eth1Provider.ts index 493884c0b5f0..3af909cd132e 100644 --- a/packages/beacon-node/src/eth1/provider/eth1Provider.ts +++ b/packages/beacon-node/src/eth1/provider/eth1Provider.ts @@ -1,7 +1,7 @@ import {toHexString} from "@chainsafe/ssz"; import {phase0} from "@lodestar/types"; import {ChainConfig} from "@lodestar/config"; -import {fromHex, isErrorAborted, createElapsedTimeTracker, toSafePrintableUrl} from "@lodestar/utils"; +import {fromHex, isErrorAborted, createElapsedTimeTracker, toPrintableUrl} from "@lodestar/utils"; import {Logger} from "@lodestar/logger"; import {FetchError, isFetchError} from "@lodestar/api"; @@ -84,7 +84,7 @@ export class Eth1Provider implements IEth1Provider { jwtVersion: opts.jwtVersion, metrics: metrics, }); - this.logger?.info("Eth1 provider", {urls: providerUrls.map(toSafePrintableUrl).toString()}); + this.logger?.info("Eth1 provider", {urls: providerUrls.map(toPrintableUrl).toString()}); this.rpc.emitter.on(JsonRpcHttpClientEvent.RESPONSE, () => { const oldState = this.state; diff --git a/packages/beacon-node/src/execution/builder/http.ts b/packages/beacon-node/src/execution/builder/http.ts index 9791f93a8ee2..934b874f5ae3 100644 --- a/packages/beacon-node/src/execution/builder/http.ts +++ b/packages/beacon-node/src/execution/builder/http.ts @@ -14,7 +14,7 @@ import {ChainForkConfig} from "@lodestar/config"; import {Logger} from "@lodestar/logger"; import {getClient, ApiClient as BuilderApi} from "@lodestar/api/builder"; import {SLOTS_PER_EPOCH, ForkExecution} from "@lodestar/params"; -import {toSafePrintableUrl} from "@lodestar/utils"; +import {toPrintableUrl} from "@lodestar/utils"; import {Metrics} from "../../metrics/metrics.js"; import {IExecutionBuilder} from "./interface.js"; @@ -64,7 +64,7 @@ export class ExecutionBuilderHttp implements IExecutionBuilder { }, {config, metrics: metrics?.builderHttpClient} ); - logger?.info("External builder", {url: toSafePrintableUrl(baseUrl)}); + logger?.info("External builder", {url: toPrintableUrl(baseUrl)}); this.config = config; this.issueLocalFcUWithFeeRecipient = opts.issueLocalFcUWithFeeRecipient; diff --git a/packages/beacon-node/src/execution/engine/index.ts b/packages/beacon-node/src/execution/engine/index.ts index 2d92a439c86d..581933d24296 100644 --- a/packages/beacon-node/src/execution/engine/index.ts +++ b/packages/beacon-node/src/execution/engine/index.ts @@ -1,4 +1,4 @@ -import {fromHex, toSafePrintableUrl} from "@lodestar/utils"; +import {fromHex, toPrintableUrl} from "@lodestar/utils"; import {JsonRpcHttpClient} from "../../eth1/provider/jsonRpcHttpClient.js"; import {IExecutionEngine} from "./interface.js"; import {ExecutionEngineDisabled} from "./disabled.js"; @@ -39,7 +39,7 @@ export function getExecutionEngineHttp( jwtId: opts.jwtId, jwtVersion: opts.jwtVersion, }); - modules.logger.info("Execution client", {urls: opts.urls.map(toSafePrintableUrl).toString()}); + modules.logger.info("Execution client", {urls: opts.urls.map(toPrintableUrl).toString()}); return new ExecutionEngineHttp(rpc, modules); } diff --git a/packages/cli/src/cmds/validator/signers/logSigners.ts b/packages/cli/src/cmds/validator/signers/logSigners.ts index 47b0edc3a4d8..20aa50d25ff6 100644 --- a/packages/cli/src/cmds/validator/signers/logSigners.ts +++ b/packages/cli/src/cmds/validator/signers/logSigners.ts @@ -1,5 +1,5 @@ import {Signer, SignerLocal, SignerRemote, SignerType} from "@lodestar/validator"; -import {LogLevel, Logger, toSafePrintableUrl} from "@lodestar/utils"; +import {LogLevel, Logger, toPrintableUrl} from "@lodestar/utils"; import {YargsError} from "../../../util/errors.js"; import {IValidatorCliArgs} from "../options.js"; @@ -29,7 +29,7 @@ export function logSigners(logger: Pick, signers: Signer[ } for (const {url, pubkeys} of groupRemoteSignersByUrl(remoteSigners)) { - logger.info(`Remote signers on URL: ${toSafePrintableUrl(url)}`); + logger.info(`Remote signers on URL: ${toPrintableUrl(url)}`); for (const pubkey of pubkeys) { logger.info(pubkey); } diff --git a/packages/utils/src/url.ts b/packages/utils/src/url.ts index 7d0b23347617..f00b70edbde2 100644 --- a/packages/utils/src/url.ts +++ b/packages/utils/src/url.ts @@ -20,10 +20,10 @@ export function isValidHttpUrl(urlStr: string): boolean { } /** - * Sanitize URL to prevent leaking user credentials in logs + * Sanitize URL to prevent leaking user credentials in logs or metrics * * Note: `urlStr` must be a valid URL */ -export function toSafePrintableUrl(urlStr: string): string { +export function toPrintableUrl(urlStr: string): string { return new URL(urlStr).origin; } diff --git a/packages/validator/src/services/externalSignerSync.ts b/packages/validator/src/services/externalSignerSync.ts index 03db612249b4..2f1880dda1bb 100644 --- a/packages/validator/src/services/externalSignerSync.ts +++ b/packages/validator/src/services/externalSignerSync.ts @@ -2,7 +2,7 @@ import {fromHexString} from "@chainsafe/ssz"; import {PublicKey} from "@chainsafe/blst"; import {ChainForkConfig} from "@lodestar/config"; import {SLOTS_PER_EPOCH} from "@lodestar/params"; -import {toSafePrintableUrl} from "@lodestar/utils"; +import {toPrintableUrl} from "@lodestar/utils"; import {LoggerVc} from "../util/index.js"; import {externalSignerGetKeys} from "../util/externalSignerClient.js"; @@ -35,7 +35,7 @@ export function pollExternalSignerPubkeys( async function fetchExternalSignerPubkeys(): Promise { // External signer URL is already validated earlier const externalSignerUrl = externalSigner.url as string; - const printableUrl = toSafePrintableUrl(externalSignerUrl); + const printableUrl = toPrintableUrl(externalSignerUrl); try { logger.debug("Fetching public keys from external signer", {url: printableUrl}); diff --git a/packages/validator/src/validator.ts b/packages/validator/src/validator.ts index 785d3de1db2a..461762560fee 100644 --- a/packages/validator/src/validator.ts +++ b/packages/validator/src/validator.ts @@ -2,7 +2,7 @@ import {toHexString} from "@chainsafe/ssz"; import {BLSPubkey, phase0, ssz} from "@lodestar/types"; import {createBeaconConfig, BeaconConfig, ChainForkConfig} from "@lodestar/config"; import {Genesis} from "@lodestar/types/phase0"; -import {Logger, toSafePrintableUrl} from "@lodestar/utils"; +import {Logger, toPrintableUrl} from "@lodestar/utils"; import {getClient, ApiClient, routes, ApiRequestInit, defaultInit} from "@lodestar/api"; import {computeEpochAtSlot, getCurrentSlot} from "@lodestar/state-transition"; import {Clock, IClock} from "./util/clock.js"; @@ -132,7 +132,7 @@ export class Validator { // not be any errors in the logs due to fallback nodes handling the requests const {httpClient} = this.api; if (httpClient.urlsInits.length > 1) { - const primaryNodeUrl = toSafePrintableUrl(httpClient.urlsInits[0].baseUrl); + const primaryNodeUrl = toPrintableUrl(httpClient.urlsInits[0].baseUrl); this.clock.runEveryEpoch(async () => { // Only emit warning if URL score is 0 to prevent false positives @@ -293,7 +293,7 @@ export class Validator { // not necessary since this instance won't be used for validator duties api = getClient({urls, globalInit: {signal: opts.abortController.signal, ...globalInit}}, {config, logger}); logger.info("Beacon node", { - urls: urls.map(toSafePrintableUrl).toString(), + urls: urls.map(toPrintableUrl).toString(), requestWireFormat: globalInit?.requestWireFormat ?? defaultInit.requestWireFormat, responseWireFormat: globalInit?.responseWireFormat ?? defaultInit.responseWireFormat, }); From 48a5a94db54f3ccdb4de167e2fba809a73a8e923 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 30 Jul 2024 14:46:28 +0100 Subject: [PATCH 27/44] docs: add note to local testnet setup (#6984) * docs: add note to local testnet setup * Add Kurtosis to wordlist --- .wordlist.txt | 1 + .../contribution/advanced-topics/setting-up-a-testnet.md | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.wordlist.txt b/.wordlist.txt index 46ca81441348..7ba20c86be99 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -54,6 +54,7 @@ JSObjects JWT KDE Kubernetes +Kurtosis LGPL LGPLv LMD diff --git a/docs/pages/contribution/advanced-topics/setting-up-a-testnet.md b/docs/pages/contribution/advanced-topics/setting-up-a-testnet.md index f7c4bfece237..04cac75c4b0a 100644 --- a/docs/pages/contribution/advanced-topics/setting-up-a-testnet.md +++ b/docs/pages/contribution/advanced-topics/setting-up-a-testnet.md @@ -6,6 +6,10 @@ title: Setting Up a Testnet To quickly test and run Lodestar we recommend starting a local testnet. We recommend a simple configuration of two beacon nodes with multiple validators. The [dev scripts](https://github.com/ChainSafe/lodestar/tree/unstable/scripts/dev) can used for simplicity but below instructions provide more insights on how it works and include details about different configurations. +:::note +The testnet set up in this guide is meant to be short-lived / ephemeral and should primarily be used for development and testing. Please refer to [Ethereum In a Box](https://github.com/rocknet/ethiab) or [Kurtosis ethereum package](https://github.com/ethpandaops/ethereum-package) to set up a long-lived private network or devnet. +::: + **Terminal 1** Run a beacon node as a **bootnode**, with 8 validators with the following command. From 8826e1a960277f9b288a5c550d76d35530ddeb63 Mon Sep 17 00:00:00 2001 From: Nico Flaig Date: Tue, 30 Jul 2024 17:01:57 +0100 Subject: [PATCH 28/44] docs: update prover and light client documentation (#6983) * Update lc cli flags to use camelCase * Update reference to light client beacon api spec * Fix browser bundle reference and min version * Update prover readme title * Remove redundancy in docs sidebar * Remove v0 lodestar-specific route * Add references to beacon api explorer --- docs/sidebars.ts | 7 +++++-- packages/light-client/README.md | 19 +++++++++---------- packages/prover/README.md | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/sidebars.ts b/docs/sidebars.ts index 16bd9586d1a1..d9a4839a90c4 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -53,12 +53,15 @@ const sidebars: SidebarsConfig = { { type: "category", label: "Light Client", - items: ["libraries/lightclient-prover/lightclient-cli", "libraries/lightclient-prover/lightclient"], + items: [ + {type: "doc", label: "Getting Started", id: "libraries/lightclient-prover/lightclient"}, + "libraries/lightclient-prover/lightclient-cli", + ], }, { type: "category", label: "Prover", - items: ["libraries/lightclient-prover/prover"], + items: [{type: "doc", label: "Getting Started", id: "libraries/lightclient-prover/prover"}], }, ], }, diff --git a/packages/light-client/README.md b/packages/light-client/README.md index 5d5e480afd08..cd3a0265008a 100644 --- a/packages/light-client/README.md +++ b/packages/light-client/README.md @@ -18,13 +18,12 @@ The evolution of light clients is emblematic of the broader trajectory of Ethere ## Requirements for Running a Light-Client -Access to an beacon node that supports the light client specification is necessary. The client must support the following routes from the [consensus API spec](https://github.com/ethereum/consensus-specs/tree/dev): +Access to an beacon node that supports the light client specification is necessary. The client must support the following routes from the [consensus API spec](https://github.com/ethereum/beacon-APIs/tree/v2.5.0/apis/beacon/light_client): -- `/eth/v1/beacon/light_client/updates` -- `/eth/v1/beacon/light_client/optimistic_update` -- `/eth/v1/beacon/light_client/finality_update` -- `/eth/v1/beacon/light_client/bootstrap/{block_root}` -- `/eth/v0/beacon/light_client/committee_root` +- [`GET /eth/v1/beacon/light_client/updates`](https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.5.0#/Beacon/getLightClientUpdatesByRange) +- [`GET /eth/v1/beacon/light_client/optimistic_update`](https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.5.0#/Beacon/getLightClientOptimisticUpdate) +- [`GET /eth/v1/beacon/light_client/finality_update`](https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.5.0#/Beacon/getLightClientFinalityUpdate) +- [`GET /eth/v1/beacon/light_client/bootstrap/{block_root}`](https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.5.0#/Beacon/getLightClientBootstrap) System requirements are quite low so its possible to run a light client in the browser as part of a website. There are a few examples of this on github that you can use as reference, our [prover](https://chainsafe.github.io/lodestar/libraries/lightclient-prover/prover) being one of them. @@ -42,8 +41,8 @@ It is possible to start up the light-client as a standalone process. ```bash lodestar lightclient \ --network sepolia \ - --beacon-api-url https://lodestar-sepolia.chainsafe.io \ - --checkpoint-root "0xccaff4b99986a7b05e06738f1828a32e40799b277fd9f9ff069be55341fe0229" + --beaconApiUrl https://lodestar-sepolia.chainsafe.io \ + --checkpointRoot "0xccaff4b99986a7b05e06738f1828a32e40799b277fd9f9ff069be55341fe0229" ``` ## Light-Client Programmatic Example @@ -93,12 +92,12 @@ lightclient.emitter.on(LightclientEvent.lightClientOptimisticHeader, async (opti ## Browser Integration -If you want to use Lightclient in browser and facing some issues in building it with bundlers like webpack, vite. We suggest to use our distribution build. The support for single distribution build is started from `1.19.0` version. +If you want to use Lightclient in browser and facing some issues in building it with bundlers like webpack, vite. We suggest to use our distribution build. The support for single distribution build is started from `1.20.0` version. Directly link the dist build with the `