From 0bcdee957c8b66401ec60a070ae453b6a0325279 Mon Sep 17 00:00:00 2001 From: matthewkeil Date: Mon, 3 Jun 2024 10:36:19 +0200 Subject: [PATCH] Revert "feat: switch bls to napi rebuild (#6616)" This reverts commit 97d9aa8b0c359c8b94e8759df4debe9d1544a97d. --- .wordlist.txt | 1 - package.json | 4 +- packages/beacon-node/package.json | 4 +- packages/beacon-node/src/chain/bls/index.ts | 5 +- .../beacon-node/src/chain/bls/maybeBatch.ts | 46 ++++ .../{multiThread.ts => multithread/index.ts} | 229 ++++++++++++---- .../chain/bls/{ => multithread}/jobItem.ts | 21 +- .../src/chain/bls/multithread/poolSize.ts | 16 ++ .../src/chain/bls/{ => multithread}/types.ts | 22 +- .../src/chain/bls/multithread/utils.ts | 19 ++ .../worker.ts} | 48 +++- .../beacon-node/src/chain/bls/singleThread.ts | 6 +- packages/beacon-node/src/chain/bls/utils.ts | 42 +-- .../beacon-node/src/chain/bls/verifySets.ts | 53 ---- .../test/e2e/chain/bls/multithread.test.ts | 4 +- .../test/unit/chain/bls/bls.test.ts | 5 +- .../test/unit/chain/bls/utils.test.ts | 2 +- packages/cli/package.json | 4 +- .../{preInitialization.ts => applyPreset.ts} | 40 --- packages/cli/src/cmds/beacon/handler.ts | 1 - packages/cli/src/index.ts | 12 +- packages/cli/src/options/globalOptions.ts | 7 - packages/cli/src/util/format.ts | 2 +- packages/flare/package.json | 3 +- packages/light-client/README.md | 6 - packages/light-client/package.json | 2 +- .../{preInitialization.ts => applyPreset.ts} | 0 packages/prover/src/cli/index.ts | 2 +- packages/state-transition/package.json | 4 +- .../test/unit/cachedBeaconState.test.ts | 2 +- .../test/unit/constants.test.ts | 10 + packages/test-utils/package.json | 2 +- packages/validator/package.json | 2 +- yarn.lock | 250 ++++++++++++++---- 34 files changed, 554 insertions(+), 322 deletions(-) create mode 100644 packages/beacon-node/src/chain/bls/maybeBatch.ts rename packages/beacon-node/src/chain/bls/{multiThread.ts => multithread/index.ts} (67%) rename packages/beacon-node/src/chain/bls/{ => multithread}/jobItem.ts (83%) create mode 100644 packages/beacon-node/src/chain/bls/multithread/poolSize.ts rename packages/beacon-node/src/chain/bls/{ => multithread}/types.ts (69%) create mode 100644 packages/beacon-node/src/chain/bls/multithread/utils.ts rename packages/beacon-node/src/chain/bls/{runBlsWorkReq.ts => multithread/worker.ts} (63%) delete mode 100644 packages/beacon-node/src/chain/bls/verifySets.ts rename packages/cli/src/{preInitialization.ts => applyPreset.ts} (63%) rename packages/prover/src/cli/{preInitialization.ts => applyPreset.ts} (100%) create mode 100644 packages/state-transition/test/unit/constants.test.ts diff --git a/.wordlist.txt b/.wordlist.txt index 5f0f7136456..64d72550755 100644 --- a/.wordlist.txt +++ b/.wordlist.txt @@ -169,7 +169,6 @@ orchestrator osx overriden params -peerDependency pid plaintext pre diff --git a/package.json b/package.json index 4bd777f5c0c..96e4b6166ca 100644 --- a/package.json +++ b/package.json @@ -36,8 +36,8 @@ "test-coverage:e2e": "c8 --config .c8rc.json --report-dir coverage/e2e/ --all npm run test:e2e", "test-coverage:e2e-sim": "c8 --config .c8rc.json --report-dir coverage/e2e-sim/ --all npm run test:e2e:sim", "test-coverage:spec": "c8 --config .c8rc.json --report-dir coverage/spec/ --all npm run test:spec", - "benchmark": "UV_THREADPOOL_SIZE=$(node -e 'console.log(require(`os`).availableParallelism())') yarn benchmark:files 'packages/*/test/perf/**/*.test.ts'", - "benchmark:files": "UV_THREADPOOL_SIZE=$(node -e 'console.log(require(`os`).availableParallelism())') NODE_OPTIONS='--max-old-space-size=4096 --loader=ts-node/esm' benchmark --config .benchrc.yaml --defaultBranch unstable", + "benchmark": "yarn benchmark:files 'packages/*/test/perf/**/*.test.ts'", + "benchmark:files": "NODE_OPTIONS='--max-old-space-size=4096 --loader=ts-node/esm' benchmark --config .benchrc.yaml --defaultBranch unstable", "release:create-rc": "node scripts/release/create_rc.mjs", "release:tag-rc": "node scripts/release/tag_rc.mjs", "release:tag-stable": "node scripts/release/tag_stable.mjs", diff --git a/packages/beacon-node/package.json b/packages/beacon-node/package.json index 8cf0636963a..5b9b39dc7eb 100644 --- a/packages/beacon-node/package.json +++ b/packages/beacon-node/package.json @@ -95,8 +95,8 @@ }, "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/bls": "^8.1.0", - "@chainsafe/blst": "^1.0.0", + "@chainsafe/bls": "7.1.3", + "@chainsafe/blst": "^0.2.10", "@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/index.ts b/packages/beacon-node/src/chain/bls/index.ts index e80a3f8e13f..f9898b13776 100644 --- a/packages/beacon-node/src/chain/bls/index.ts +++ b/packages/beacon-node/src/chain/bls/index.ts @@ -1,5 +1,4 @@ export type {IBlsVerifier} from "./interface.js"; -export type {JobQueueItemType} from "./jobItem.js"; -export type {BlsMultiThreadWorkerPoolModules} from "./multiThread.js"; -export {BlsMultiThreadWorkerPool} from "./multiThread.js"; +export type {BlsMultiThreadWorkerPoolModules, JobQueueItemType} from "./multithread/index.js"; +export {BlsMultiThreadWorkerPool} from "./multithread/index.js"; export {BlsSingleThreadVerifier} from "./singleThread.js"; diff --git a/packages/beacon-node/src/chain/bls/maybeBatch.ts b/packages/beacon-node/src/chain/bls/maybeBatch.ts new file mode 100644 index 00000000000..619ddf4d72e --- /dev/null +++ b/packages/beacon-node/src/chain/bls/maybeBatch.ts @@ -0,0 +1,46 @@ +import {CoordType, PublicKey} from "@chainsafe/bls/types"; +import bls from "@chainsafe/bls"; + +const MIN_SET_COUNT_TO_BATCH = 2; + +export type SignatureSetDeserialized = { + publicKey: PublicKey; + message: Uint8Array; + signature: Uint8Array; +}; + +/** + * Verify signatures sets with batch verification or regular core verify depending on the set count. + * Abstracted in a separate file to be consumed by the threaded pool and the main thread implementation. + */ +export function verifySignatureSetsMaybeBatch(sets: SignatureSetDeserialized[]): boolean { + try { + if (sets.length >= MIN_SET_COUNT_TO_BATCH) { + return bls.Signature.verifyMultipleSignatures( + sets.map((s) => ({ + publicKey: s.publicKey, + message: s.message, + // true = validate signature + signature: bls.Signature.fromBytes(s.signature, CoordType.affine, true), + })) + ); + } + + // .every on an empty array returns true + if (sets.length === 0) { + throw Error("Empty signature set"); + } + + // 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); + }); + } catch (_) { + // A signature could be malformed, in that case fromBytes throws error + // blst-ts `verifyMultipleSignatures` is also a fallible operation if mul_n_aggregate fails + // see https://github.com/ChainSafe/blst-ts/blob/b1ba6333f664b08e5c50b2b0d18c4f079203962b/src/lib.ts#L291 + return false; + } +} diff --git a/packages/beacon-node/src/chain/bls/multiThread.ts b/packages/beacon-node/src/chain/bls/multithread/index.ts similarity index 67% rename from packages/beacon-node/src/chain/bls/multiThread.ts rename to packages/beacon-node/src/chain/bls/multithread/index.ts index bdc80c18818..ede8e7982f2 100644 --- a/packages/beacon-node/src/chain/bls/multiThread.ts +++ b/packages/beacon-node/src/chain/bls/multithread/index.ts @@ -1,18 +1,26 @@ -import os from "node:os"; +/* eslint-disable @typescript-eslint/strict-boolean-expressions */ +import path from "node:path"; +import {spawn, Worker} from "@chainsafe/threads"; +// `threads` library creates self global variable which breaks `timeout-abort-controller` https://github.com/jacobheun/timeout-abort-controller/issues/9 +// Don't add an eslint disable here as a reminder that this has to be fixed eventually +// eslint-disable-next-line +// @ts-ignore +// eslint-disable-next-line +self = undefined; import bls from "@chainsafe/bls"; -import {PointFormat, PublicKey} from "@chainsafe/bls/types"; +import {Implementation, PointFormat, PublicKey} from "@chainsafe/bls/types"; import {Logger} from "@lodestar/utils"; import {ISignatureSet} from "@lodestar/state-transition"; -import {QueueError, QueueErrorCode} from "../../util/queue/index.js"; -import {Metrics} from "../../metrics/index.js"; -import {LinkedList} from "../../util/array.js"; -import {callInNextEventLoop} from "../../util/eventLoop.js"; -import {IBlsVerifier, VerifySignatureOpts} from "./interface.js"; -import {getAggregatedPubkey, getAggregatedPubkeysCount, getJobResultError} from "./utils.js"; -import {verifySets} from "./verifySets.js"; -import {BlsWorkReq, WorkResultCode} from "./types.js"; +import {LinkedList} from "../../../util/array.js"; +import {callInNextEventLoop} from "../../../util/eventLoop.js"; +import {QueueError, QueueErrorCode} from "../../../util/queue/index.js"; +import {Metrics} from "../../../metrics/index.js"; +import {IBlsVerifier, VerifySignatureOpts} from "../interface.js"; +import {getAggregatedPubkey, getAggregatedPubkeysCount} from "../utils.js"; +import {verifySignatureSetsMaybeBatch} from "../maybeBatch.js"; +import {BlsWorkReq, BlsWorkResult, WorkerData, WorkResultCode, WorkResultError} from "./types.js"; import {chunkifyMaximizeChunkSize} from "./utils.js"; -import {runBlsWorkReq} from "./runBlsWorkReq.js"; +import {defaultPoolSize} from "./poolSize.js"; import { JobQueueItem, JobQueueItemSameMessage, @@ -22,6 +30,9 @@ import { jobItemWorkReq, } from "./jobItem.js"; +// Worker constructor consider the path relative to the current working directory +const workerDir = process.env.NODE_ENV === "test" ? "../../../../lib/chain/bls/multithread" : "./"; + export type BlsMultiThreadWorkerPoolModules = { logger: Logger; metrics: Metrics | null; @@ -31,6 +42,11 @@ export type BlsMultiThreadWorkerPoolOptions = { blsVerifyAllMultiThread?: boolean; }; +export type {JobQueueItemType}; + +// 1 worker for the main thread +const blsPoolSize = Math.max(defaultPoolSize - 1, 1); + /** * Split big signature sets into smaller sets so they can be sent to multiple workers. * @@ -64,6 +80,30 @@ const MAX_BUFFER_WAIT_MS = 100; */ const MAX_JOBS_CAN_ACCEPT_WORK = 512; +type WorkerApi = { + verifyManySignatureSets(workReqArr: BlsWorkReq[]): Promise; +}; + +enum WorkerStatusCode { + notInitialized, + initializing, + initializationError, + idle, + running, +} + +type WorkerStatus = + | {code: WorkerStatusCode.notInitialized} + | {code: WorkerStatusCode.initializing; initPromise: Promise} + | {code: WorkerStatusCode.initializationError; error: Error} + | {code: WorkerStatusCode.idle; workerApi: WorkerApi} + | {code: WorkerStatusCode.running; workerApi: WorkerApi}; + +type WorkerDescriptor = { + worker: Worker; + status: WorkerStatus; +}; + /** * Wraps "threads" library thread pool queue system with the goals: * - Complete total outstanding jobs in total minimum time possible. @@ -76,11 +116,8 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { private readonly logger: Logger; private readonly metrics: Metrics | null; - private readonly format = PointFormat.uncompressed; - - private blsPoolSize: number; - private workersBusy = 0; - + private readonly format: PointFormat; + private readonly workers: WorkerDescriptor[]; private readonly jobs = new LinkedList(); private bufferedJobs: { jobs: LinkedList; @@ -91,43 +128,34 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { } | null = null; private blsVerifyAllMultiThread: boolean; private closed = false; + private workersBusy = 0; constructor(options: BlsMultiThreadWorkerPoolOptions, modules: BlsMultiThreadWorkerPoolModules) { - if (bls.implementation === "herumi") { - throw new Error("Herumi BLS implementation is not supported"); - } - - this.logger = modules.logger; + const {logger, metrics} = modules; + this.logger = logger; + this.metrics = metrics; this.blsVerifyAllMultiThread = options.blsVerifyAllMultiThread ?? false; - this.blsPoolSize = Number(process.env.UV_THREADPOOL_SIZE); - const defaultThreadpoolSize = os.availableParallelism(); - this.logger.info(`BLS libuv pool size: ${this.blsPoolSize}`); - /** - * Help users ensure that thread pool is large enough for optimal performance - * - * Node reports available CPUs. There is enough idle time on the main and - * network threads that setting UV_THREADPOOL_SIZE to $(nproc) provides the - * best performance. Recommend this value to consumers - */ - if (this.blsPoolSize < defaultThreadpoolSize) { - this.logger.warn( - `UV_THREADPOOL_SIZE=${this.blsPoolSize} which is less than available CPUs: ${defaultThreadpoolSize}. This will cause performance degradation.` - ); - } + // 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); - const {metrics} = modules; - this.metrics = metrics; if (metrics) { metrics.blsThreadPool.queueLength.addCollect(() => { metrics.blsThreadPool.queueLength.set(this.jobs.length); + metrics.blsThreadPool.workersBusy.set(this.workersBusy); }); } } canAcceptWork(): boolean { return ( - this.workersBusy < this.blsPoolSize && + this.workersBusy < blsPoolSize && // TODO: Should also bound the jobs queue? this.jobs.length < MAX_JOBS_CAN_ACCEPT_WORK ); @@ -146,15 +174,17 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { if (opts.verifyOnMainThread && !this.blsVerifyAllMultiThread) { const timer = this.metrics?.blsThreadPool.mainThreadDurationInThreadPool.startTimer(); - const isValid = verifySets( - sets.map((set) => ({ - publicKey: getAggregatedPubkey(set), - message: set.signingRoot.valueOf(), - signature: set.signature, - })) - ); - timer?.(); - return isValid; + try { + return verifySignatureSetsMaybeBatch( + sets.map((set) => ({ + publicKey: getAggregatedPubkey(set), + message: set.signingRoot.valueOf(), + signature: set.signature, + })) + ); + } finally { + if (timer) timer(); + } } // Split large array of sets into smaller. @@ -221,8 +251,56 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { for (const job of this.jobs) { job.reject(new QueueError({code: QueueErrorCode.QUEUE_ABORTED})); } - this.jobs.clear(); + + // Terminate all workers. await to ensure no workers are left hanging + await Promise.all( + Array.from(this.workers.entries()).map(([id, worker]) => + // NOTE: 'threads' has not yet updated types, and NodeJS complains with + // [DEP0132] DeprecationWarning: Passing a callback to worker.terminate() is deprecated. It returns a Promise instead. + (worker.worker.terminate() as unknown as Promise).catch((e: Error) => { + this.logger.error("Error terminating worker", {id}, e); + }) + ) + ); + } + + private createWorkers(implementation: Implementation, poolSize: number): WorkerDescriptor[] { + const workers: WorkerDescriptor[] = []; + + for (let i = 0; i < poolSize; i++) { + const workerData: WorkerData = {implementation, workerId: i}; + const worker = new Worker(path.join(workerDir, "worker.js"), { + workerData, + } as ConstructorParameters[1]); + + const workerDescriptor: WorkerDescriptor = { + worker, + status: {code: WorkerStatusCode.notInitialized}, + }; + workers.push(workerDescriptor); + + // TODO: Consider initializing only when necessary + const initPromise = 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, + }); + + workerDescriptor.status = {code: WorkerStatusCode.initializing, initPromise}; + + initPromise + .then((workerApi) => { + workerDescriptor.status = {code: WorkerStatusCode.idle, workerApi}; + // Potentially run jobs that were queued before initialization of the first worker + setTimeout(this.runJob, 0); + }) + .catch((error: Error) => { + workerDescriptor.status = {code: WorkerStatusCode.initializationError, error}; + }); + } + + return workers; } /** @@ -233,6 +311,18 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { throw new QueueError({code: QueueErrorCode.QUEUE_ABORTED}); } + // TODO: Consider if limiting queue size is necessary here. + // It would be bad to reject signatures because the node is slow. + // However, if the worker communication broke jobs won't ever finish + + if ( + this.workers.length > 0 && + this.workers[0].status.code === WorkerStatusCode.initializationError && + this.workers.every((worker) => worker.status.code === WorkerStatusCode.initializationError) + ) { + return job.reject(this.workers[0].status.error); + } + // Append batchable sets to `bufferedJobs`, starting a timeout to push them into `jobs`. // Do not call `runJob()`, it is called from `runBufferedJobs()` if (job.opts.batchable) { @@ -275,12 +365,24 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { return; } + // Find idle worker + const worker = this.workers.find((worker) => worker.status.code === WorkerStatusCode.idle); + if (!worker || worker.status.code !== WorkerStatusCode.idle) { + return; + } + // Prepare work package const jobsInput = this.prepareWork(); if (jobsInput.length === 0) { return; } + // TODO: After sending the work to the worker the main thread can drop the job arguments + // and free-up memory, only needs to keep the job's Promise handlers. + // Maybe it's not useful since all data referenced in jobs is likely referenced by others + + const workerApi = worker.status.workerApi; + worker.status = {code: WorkerStatusCode.running, workerApi}; this.workersBusy++; try { @@ -340,9 +442,9 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { // Only downside is the job promise may be resolved twice, but that's not an issue const [jobStartSec, jobStartNs] = process.hrtime(); - const workResult = await runBlsWorkReq(workReqs); + const workResult = await workerApi.verifyManySignatureSets(workReqs); const [jobEndSec, jobEndNs] = process.hrtime(); - const {batchRetries, batchSigsSuccess, workerStartTime, workerEndTime, results} = workResult; + const {workerId, batchRetries, batchSigsSuccess, workerStartTime, workerEndTime, results} = workResult; const [workerStartSec, workerStartNs] = workerStartTime; const [workerEndSec, workerEndNs] = workerEndTime; @@ -359,7 +461,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { // TODO: enable exhaustive switch case checks lint rule switch (job.type) { case JobQueueItemType.default: - if (jobResult.code !== WorkResultCode.success) { + if (!jobResult || jobResult.code !== WorkResultCode.success) { job.reject(getJobResultError(jobResult, i)); errorCount += sigSetCount; } else { @@ -370,7 +472,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { // handle result of the verification of aggregated signature against aggregated pubkeys case JobQueueItemType.sameMessage: - if (jobResult.code !== WorkResultCode.success) { + if (!jobResult || jobResult.code !== WorkResultCode.success) { job.reject(getJobResultError(jobResult, i)); errorCount += 1; } else { @@ -387,13 +489,12 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { } } - // TODO: (@matthewkeil) all of these metrics need to be revisited const workerJobTimeSec = workerEndSec - workerStartSec + (workerEndNs - workerStartNs) / 1e9; const latencyToWorkerSec = workerStartSec - jobStartSec + (workerStartNs - jobStartNs) / 1e9; const latencyFromWorkerSec = jobEndSec - workerEndSec + Number(jobEndNs - workerEndNs) / 1e9; this.metrics?.blsThreadPool.timePerSigSet.observe(workerJobTimeSec / startedSigSets); - this.metrics?.blsThreadPool.jobsWorkerTime.inc({workerId: 0}, workerJobTimeSec); + this.metrics?.blsThreadPool.jobsWorkerTime.inc({workerId}, workerJobTimeSec); this.metrics?.blsThreadPool.latencyToWorker.observe(latencyToWorkerSec); this.metrics?.blsThreadPool.latencyFromWorker.observe(latencyFromWorkerSec); this.metrics?.blsThreadPool.successJobsSignatureSetsCount.inc(successCount); @@ -411,6 +512,7 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { } } + worker.status = {code: WorkerStatusCode.idle, workerApi}; this.workersBusy--; // Potentially run a new job @@ -465,4 +567,21 @@ export class BlsMultiThreadWorkerPool implements IBlsVerifier { this.metrics?.blsThreadPool.sameMessageRetryJobs.inc(1); this.metrics?.blsThreadPool.sameMessageRetrySets.inc(job.sets.length); } + + /** For testing */ + private async waitTillInitialized(): Promise { + await Promise.all( + this.workers.map(async (worker) => { + if (worker.status.code === WorkerStatusCode.initializing) { + await worker.status.initPromise; + } + }) + ); + } +} + +function getJobResultError(jobResult: WorkResultError | null, i: number): Error { + const workerError = jobResult ? Error(jobResult.error.message) : Error(`No jobResult for index ${i}`); + if (jobResult?.error?.stack) workerError.stack = jobResult.error.stack; + return workerError; } diff --git a/packages/beacon-node/src/chain/bls/jobItem.ts b/packages/beacon-node/src/chain/bls/multithread/jobItem.ts similarity index 83% rename from packages/beacon-node/src/chain/bls/jobItem.ts rename to packages/beacon-node/src/chain/bls/multithread/jobItem.ts index c2a49aa6167..8b5c63df2ee 100644 --- a/packages/beacon-node/src/chain/bls/jobItem.ts +++ b/packages/beacon-node/src/chain/bls/multithread/jobItem.ts @@ -1,12 +1,11 @@ import bls from "@chainsafe/bls"; import {CoordType, PointFormat, PublicKey} from "@chainsafe/bls/types"; import {ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; -import {LinkedList} from "../../util/array.js"; -import {Metrics} from "../../metrics/metrics.js"; -import {VerifySignatureOpts} from "./interface.js"; -import {getAggregatedPubkey} from "./utils.js"; +import {VerifySignatureOpts} from "../interface.js"; +import {getAggregatedPubkey} from "../utils.js"; +import {LinkedList} from "../../../util/array.js"; +import {Metrics} from "../../../metrics/metrics.js"; import {BlsWorkReq} from "./types.js"; -import {randomBytesNonZero} from "./utils.js"; export type JobQueueItem = JobQueueItemDefault | JobQueueItemSameMessage; @@ -57,7 +56,7 @@ export function jobItemWorkReq(job: JobQueueItem, format: PointFormat, metrics: opts: job.opts, sets: job.sets.map((set) => ({ // this can throw, handled in the consumer code - publicKey: getAggregatedPubkey(set, metrics), + publicKey: getAggregatedPubkey(set, metrics).toBytes(format), signature: set.signature, message: set.signingRoot, })), @@ -74,19 +73,13 @@ export function jobItemWorkReq(job: JobQueueItem, format: PointFormat, metrics: const signatures = job.sets.map((set) => bls.Signature.fromBytes(set.signature, CoordType.affine, true)); timer?.(); - // adding verification randomness is napi specific. must not attempt with herumi until - // @chainsafe/bls is updated to support it with herumi - const randomness: Uint8Array[] = []; - for (let i = 0; i < job.sets.length; i++) { - randomness.push(randomBytesNonZero(8)); - } return { opts: job.opts, sets: [ { + publicKey: bls.PublicKey.aggregate(job.sets.map((set) => set.publicKey)).toBytes(format), + signature: bls.Signature.aggregate(signatures).toBytes(format), message: job.message, - publicKey: bls.PublicKey.aggregate(job.sets.map((set, i) => set.publicKey.multiplyBy(randomness[i]))), - signature: bls.Signature.aggregate(signatures.map((sig, i) => sig.multiplyBy(randomness[i]))), }, ], }; diff --git a/packages/beacon-node/src/chain/bls/multithread/poolSize.ts b/packages/beacon-node/src/chain/bls/multithread/poolSize.ts new file mode 100644 index 00000000000..9397f97849c --- /dev/null +++ b/packages/beacon-node/src/chain/bls/multithread/poolSize.ts @@ -0,0 +1,16 @@ +let defaultPoolSize: number; + +try { + if (typeof navigator !== "undefined") { + defaultPoolSize = navigator.hardwareConcurrency ?? 4; + } else { + defaultPoolSize = (await import("node:os")).availableParallelism(); + } +} catch (e) { + defaultPoolSize = 8; +} + +/** + * Cross-platform aprox number of logical cores + */ +export {defaultPoolSize}; diff --git a/packages/beacon-node/src/chain/bls/types.ts b/packages/beacon-node/src/chain/bls/multithread/types.ts similarity index 69% rename from packages/beacon-node/src/chain/bls/types.ts rename to packages/beacon-node/src/chain/bls/multithread/types.ts index 35ca894ae43..3ebc979b559 100644 --- a/packages/beacon-node/src/chain/bls/types.ts +++ b/packages/beacon-node/src/chain/bls/multithread/types.ts @@ -1,23 +1,19 @@ -import {PublicKey, Signature} from "@chainsafe/bls/types"; -import {VerifySignatureOpts} from "./interface.js"; +import {VerifySignatureOpts} from "../interface.js"; -export type DeserializedKeySet = { - publicKey: PublicKey; - message: Uint8Array; - signature: Uint8Array; +export type WorkerData = { + implementation: "herumi" | "blst-native"; + workerId: number; }; -export type DeserializedSet = { - publicKey: PublicKey; +export type SerializedSet = { + publicKey: Uint8Array; message: Uint8Array; - signature: Signature; + signature: Uint8Array; }; -export type WorkRequestSet = DeserializedKeySet | DeserializedSet; - export type BlsWorkReq = { opts: VerifySignatureOpts; - sets: WorkRequestSet[]; + sets: SerializedSet[]; }; export enum WorkResultCode { @@ -29,6 +25,8 @@ export type WorkResultError = {code: WorkResultCode.error; error: Error}; export type WorkResult = {code: WorkResultCode.success; result: R} | WorkResultError; export type BlsWorkResult = { + /** Ascending integer identifying the worker for metrics */ + workerId: number; /** Total num of batches that had to be retried */ batchRetries: number; /** Total num of sigs that have been successfully verified with batching */ diff --git a/packages/beacon-node/src/chain/bls/multithread/utils.ts b/packages/beacon-node/src/chain/bls/multithread/utils.ts new file mode 100644 index 00000000000..414decbb47b --- /dev/null +++ b/packages/beacon-node/src/chain/bls/multithread/utils.ts @@ -0,0 +1,19 @@ +/** + * Splits an array into an array of arrays maximizing the size of the smallest chunk. + */ +export function chunkifyMaximizeChunkSize(arr: T[], minPerChunk: number): T[][] { + const chunkCount = Math.floor(arr.length / minPerChunk); + if (chunkCount <= 1) { + return [arr]; + } + + // Prefer less chunks of bigger size + const perChunk = Math.ceil(arr.length / chunkCount); + const arrArr: T[][] = []; + + for (let i = 0; i < arr.length; i += perChunk) { + arrArr.push(arr.slice(i, i + perChunk)); + } + + return arrArr; +} diff --git a/packages/beacon-node/src/chain/bls/runBlsWorkReq.ts b/packages/beacon-node/src/chain/bls/multithread/worker.ts similarity index 63% rename from packages/beacon-node/src/chain/bls/runBlsWorkReq.ts rename to packages/beacon-node/src/chain/bls/multithread/worker.ts index 580e97728cf..0db88dcfccd 100644 --- a/packages/beacon-node/src/chain/bls/runBlsWorkReq.ts +++ b/packages/beacon-node/src/chain/bls/multithread/worker.ts @@ -1,6 +1,11 @@ -import {asyncVerifySets} from "./verifySets.js"; +/* 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 {verifySignatureSetsMaybeBatch, SignatureSetDeserialized} from "../maybeBatch.js"; +import {WorkerData, BlsWorkReq, WorkResult, WorkResultCode, SerializedSet, BlsWorkResult} from "./types.js"; import {chunkifyMaximizeChunkSize} from "./utils.js"; -import {BlsWorkReq, WorkResult, WorkResultCode, WorkRequestSet, BlsWorkResult} from "./types.js"; /** * Split batchable sets in chunks of minimum size 16. @@ -11,23 +16,36 @@ import {BlsWorkReq, WorkResult, WorkResultCode, WorkRequestSet, BlsWorkResult} f */ const BATCHABLE_MIN_PER_CHUNK = 16; -export async function runBlsWorkReq(workReqArr: BlsWorkReq[]): Promise { +// Cloned data from instatiation +const workerData = worker.workerData as WorkerData; +if (!workerData) throw Error("workerData must be defined"); +const {workerId} = workerData || {}; + +expose({ + async verifyManySignatureSets(workReqArr: BlsWorkReq[]): Promise { + return verifyManySignatureSets(workReqArr); + }, +}); + +function verifyManySignatureSets(workReqArr: BlsWorkReq[]): BlsWorkResult { const [startSec, startNs] = process.hrtime(); const results: WorkResult[] = []; let batchRetries = 0; let batchSigsSuccess = 0; // If there are multiple batchable sets attempt batch verification with them - const batchableSets: {idx: number; sets: WorkRequestSet[]}[] = []; - const nonBatchableSets: {idx: number; sets: WorkRequestSet[]}[] = []; + const batchableSets: {idx: number; sets: SignatureSetDeserialized[]}[] = []; + const nonBatchableSets: {idx: number; sets: SignatureSetDeserialized[]}[] = []; // Split sets between batchable and non-batchable preserving their original index in the req array for (let i = 0; i < workReqArr.length; i++) { const workReq = workReqArr[i]; + const sets = workReq.sets.map(deserializeSet); + if (workReq.opts.batchable) { - batchableSets.push({idx: i, sets: workReq.sets}); + batchableSets.push({idx: i, sets}); } else { - nonBatchableSets.push({idx: i, sets: workReq.sets}); + nonBatchableSets.push({idx: i, sets}); } } @@ -36,7 +54,7 @@ export async function runBlsWorkReq(workReqArr: BlsWorkReq[]): Promise(arr: T[], minPerChunk: number): T[][] { - const chunkCount = Math.floor(arr.length / minPerChunk); - if (chunkCount <= 1) { - return [arr]; - } - - // Prefer less chunks of bigger size - const perChunk = Math.ceil(arr.length / chunkCount); - const arrArr: T[][] = []; - - for (let i = 0; i < arr.length; i += perChunk) { - arrArr.push(arr.slice(i, i + perChunk)); - } - - return arrArr; -} - -/** - * `rand` must not be exactly zero. Otherwise it would allow the verification of invalid signatures - * See https://github.com/ChainSafe/blst-ts/issues/45 - */ -export function randomBytesNonZero(bytesCount: number): Uint8Array { - const rand = crypto.getRandomValues(new Uint8Array(bytesCount)); - for (let i = 0; i < bytesCount; i++) { - if (rand[i] !== 0) return rand; - } - rand[0] = 1; - return rand; -} - -export function getJobResultError(jobResult: WorkResultError | null, i: number): Error { - const workerError = jobResult ? Error(jobResult.error.message) : Error(`No jobResult for index ${i}`); - if (jobResult?.error?.stack) workerError.stack = jobResult.error.stack; - return workerError; -} diff --git a/packages/beacon-node/src/chain/bls/verifySets.ts b/packages/beacon-node/src/chain/bls/verifySets.ts deleted file mode 100644 index ebd8bbb44e3..00000000000 --- a/packages/beacon-node/src/chain/bls/verifySets.ts +++ /dev/null @@ -1,53 +0,0 @@ -import bls from "@chainsafe/bls"; -import {WorkRequestSet} from "./types.js"; - -const MIN_SET_COUNT_TO_BATCH = 2; - -/** - * Verify signatures sets with batch verification or regular core verify depending on the set count. - * Abstracted in a separate file to be consumed by the threaded pool and the main thread implementation. - */ -export function verifySets(sets: WorkRequestSet[]): boolean { - try { - if (sets.length >= MIN_SET_COUNT_TO_BATCH) { - return bls.verifyMultipleSignatures(sets); - } - - // .every on an empty array returns true - if (sets.length === 0) { - throw Error("Empty signature set"); - } - - // If too few signature sets verify them without batching - return sets.every(({message, publicKey, signature}) => bls.verify(publicKey, message, signature)); - } catch (_) { - // A signature could be malformed, in that case fromBytes throws error - // blst-ts `verifyMultipleSignatures` is also a fallible operation if mul_n_aggregate fails - // see https://github.com/ChainSafe/blst-ts/blob/b1ba6333f664b08e5c50b2b0d18c4f079203962b/src/lib.ts#L291 - return false; - } -} - -export async function asyncVerifySets(sets: WorkRequestSet[]): Promise { - try { - if (sets.length >= MIN_SET_COUNT_TO_BATCH) { - return await bls.asyncVerifyMultipleSignatures(sets); - } - - // .every on an empty array returns true - if (sets.length === 0) { - throw Error("Empty signature sets"); - } - - const promises = await Promise.all( - sets.map(({message, publicKey, signature}) => bls.asyncVerify(publicKey, message, signature)) - ); - // If too few signature sets verify them without batching - return promises.every((isValid) => isValid); - } catch (_) { - // A signature could be malformed, in that case fromBytes throws error - // blst-ts `verifyMultipleSignatures` is also a fallible operation if mul_n_aggregate fails - // see https://github.com/ChainSafe/blst-ts/blob/b1ba6333f664b08e5c50b2b0d18c4f079203962b/src/lib.ts#L291 - return false; - } -} 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 ceadb4ae4c7..bf1e7346943 100644 --- a/packages/beacon-node/test/e2e/chain/bls/multithread.test.ts +++ b/packages/beacon-node/test/e2e/chain/bls/multithread.test.ts @@ -2,7 +2,7 @@ import {describe, it, beforeAll, expect, beforeEach, afterEach} from "vitest"; import bls from "@chainsafe/bls"; import {PublicKey} from "@chainsafe/bls/types"; import {ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; -import {BlsMultiThreadWorkerPool} from "../../../../src/chain/bls/index.js"; +import {BlsMultiThreadWorkerPool} from "../../../../src/chain/bls/multithread/index.js"; import {testLogger} from "../../../utils/logger.js"; import {VerifySignatureOpts} from "../../../../src/chain/bls/interface.js"; @@ -50,6 +50,8 @@ describe("chain / bls / multithread queue", function () { const pool = new BlsMultiThreadWorkerPool({}, {logger, metrics: null}); // await terminating all workers afterEachCallbacks.push(() => pool.close()); + // Wait until initialized + await pool["waitTillInitialized"](); return pool; } 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 9bff307d3d8..e5b84426263 100644 --- a/packages/beacon-node/test/unit/chain/bls/bls.test.ts +++ b/packages/beacon-node/test/unit/chain/bls/bls.test.ts @@ -1,9 +1,10 @@ import bls from "@chainsafe/bls"; -import {CoordType, PublicKey} from "@chainsafe/bls/types"; +import {CoordType} from "@chainsafe/blst"; +import {PublicKey} from "@chainsafe/bls/types"; import {describe, it, expect, beforeEach} from "vitest"; import {ISignatureSet, SignatureSetType} from "@lodestar/state-transition"; import {BlsSingleThreadVerifier} from "../../../../src/chain/bls/singleThread.js"; -import {BlsMultiThreadWorkerPool} from "../../../../src/chain/bls/index.js"; +import {BlsMultiThreadWorkerPool} from "../../../../src/chain/bls/multithread/index.js"; import {testLogger} from "../../../utils/logger.js"; describe("BlsVerifier ", function () { diff --git a/packages/beacon-node/test/unit/chain/bls/utils.test.ts b/packages/beacon-node/test/unit/chain/bls/utils.test.ts index de7dd766acd..d492a36b4d5 100644 --- a/packages/beacon-node/test/unit/chain/bls/utils.test.ts +++ b/packages/beacon-node/test/unit/chain/bls/utils.test.ts @@ -1,5 +1,5 @@ import {describe, it, expect} from "vitest"; -import {chunkifyMaximizeChunkSize} from "../../../../src/chain/bls/utils.js"; +import {chunkifyMaximizeChunkSize} from "../../../../src/chain/bls/multithread/utils.js"; import {linspace} from "../../../../src/util/numpy.js"; describe("chain / bls / utils / chunkifyMaximizeChunkSize", () => { diff --git a/packages/cli/package.json b/packages/cli/package.json index 486a6427c81..f2016b606db 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -51,10 +51,10 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "^8.1.0", + "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keygen": "^0.4.0", "@chainsafe/bls-keystore": "^3.0.1", - "@chainsafe/blst": "^1.0.0", + "@chainsafe/blst": "^0.2.10", "@chainsafe/discv5": "^9.0.0", "@chainsafe/enr": "^3.0.0", "@chainsafe/persistent-merkle-tree": "^0.7.1", diff --git a/packages/cli/src/preInitialization.ts b/packages/cli/src/applyPreset.ts similarity index 63% rename from packages/cli/src/preInitialization.ts rename to packages/cli/src/applyPreset.ts index d15094ae00e..25f78b7d32a 100644 --- a/packages/cli/src/preInitialization.ts +++ b/packages/cli/src/applyPreset.ts @@ -1,5 +1,4 @@ // MUST import this file first before anything and not import any Lodestar code. -import os from "node:os"; // eslint-disable-next-line no-restricted-imports import {hasher} from "@chainsafe/persistent-merkle-tree/lib/hasher/as-sha256.js"; @@ -30,7 +29,6 @@ import {readFile} from "./util/file.js"; const network = valueOfArg("network"); const preset = valueOfArg("preset"); const presetFile = valueOfArg("presetFile"); -const uvThreadpoolSize = valueOfArg("uvThreadpoolSize"); // Apply preset flag if present if (preset) { @@ -63,44 +61,6 @@ else if (process.argv[2] === "dev") { setActivePreset(PresetName.minimal, {FIELD_ELEMENTS_PER_BLOB: 4096}); } -/** - * Sets the libuv thread pool size for worker threads. This is a critical - * component for effective node operations. Setting the environment variable - * must happen almost at the beginning of startup, BEFORE the worker pool is - * created by libuv. - * - * The trigger for creation of the libuv worker pool is scheduling async work - * that will queue for a worker. An example of things that can trigger that - * condition are async reading files from the OS. Some network operations and - * any native modules that utilize async work (like @chainsafe/blst-ts). - * - * Setting this value higher than the number of logical cores will not be a benefit - * because the kernel will need to do context switching to parallelize the work - * on a number of cores that is less than the number of requested threads. - * - * Setting this number lower than then number of cores will reduce the amount of - * bls work that can be concurrently done. Something like 70% of the work the - * cpu does to keep up with the chain is blst validation. - * - * There is a considerable amount of idle process time on both the main thread - * and network thread and setting this value to overlap that work will allow the - * kernel to utilize the idle time for additional bls verification. - * - * Empirical testing has shown that sizing the worker pool to be as large as - * the number of logical cores is optimal but this may change in the future. - */ -if (uvThreadpoolSize) { - process.env.UV_THREADPOOL_SIZE = uvThreadpoolSize; -} else if (process.env.UV_THREADPOOL_SIZE) { - /* no-op let user-set value carry through */ -} else { - process.env.UV_THREADPOOL_SIZE = os.availableParallelism().toString(); -} - -if (isNaN(parseInt(`${process.env.UV_THREADPOOL_SIZE}`))) { - throw new Error(`UV_THREADPOOL_SIZE=${process.env.UV_THREADPOOL_SIZE}, but must be set to a number`); -} - if (presetFile) { // Override the active preset with custom values from file // Do not modify the preset to use as a base by passing null diff --git a/packages/cli/src/cmds/beacon/handler.ts b/packages/cli/src/cmds/beacon/handler.ts index 444bbba8510..ec96081d3c7 100644 --- a/packages/cli/src/cmds/beacon/handler.ts +++ b/packages/cli/src/cmds/beacon/handler.ts @@ -52,7 +52,6 @@ export async function beaconHandler(args: BeaconArgs & GlobalArgs): Promise { diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index eb98b4ca65a..5cdccbacfee 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -1,15 +1,7 @@ #!/usr/bin/env node -/** - * MUST import first!! - * - applies preset - * - sets ssz hasher - * - sets libuv thread pool size - */ -import "./preInitialization.js"; -/** - * Everything else must be after!! - */ +// MUST import first to apply preset from args and set ssz hasher +import "./applyPreset.js"; import {YargsError} from "./util/index.js"; import {getLodestarCli, yarg} from "./cli.js"; import "source-map-support/register.js"; diff --git a/packages/cli/src/options/globalOptions.ts b/packages/cli/src/options/globalOptions.ts index 4bc11aff0eb..52a5090c679 100644 --- a/packages/cli/src/options/globalOptions.ts +++ b/packages/cli/src/options/globalOptions.ts @@ -10,7 +10,6 @@ type GlobalSingleArgs = { paramsFile?: string; preset: string; presetFile?: string; - uvThreadpoolSize?: number; }; export const defaultNetwork: NetworkName = "mainnet"; @@ -45,12 +44,6 @@ const globalSingleOptions: CliCommandOptions = { description: "Preset configuration file to override the active preset with custom values", type: "string", }, - - uvThreadpoolSize: { - hidden: true, - description: "Set the number of worker threads libuv should create", - type: "number", - }, }; export const rcConfigOption: [string, string, (configPath: string) => Record] = [ diff --git a/packages/cli/src/util/format.ts b/packages/cli/src/util/format.ts index b26da62527d..e673fa4d440 100644 --- a/packages/cli/src/util/format.ts +++ b/packages/cli/src/util/format.ts @@ -1,5 +1,5 @@ import bls from "@chainsafe/bls"; -import {CoordType} from "@chainsafe/bls/types"; +import {CoordType} from "@chainsafe/blst"; import {fromHexString} from "@chainsafe/ssz"; /** diff --git a/packages/flare/package.json b/packages/flare/package.json index f9d20626682..54a0dbec51f 100644 --- a/packages/flare/package.json +++ b/packages/flare/package.json @@ -58,9 +58,8 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "^8.1.0", + "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keygen": "^0.4.0", - "@chainsafe/blst": "^1.0.0", "@lodestar/api": "^1.19.0", "@lodestar/config": "^1.19.0", "@lodestar/params": "^1.19.0", diff --git a/packages/light-client/README.md b/packages/light-client/README.md index 224b43cb2fe..dd00777f81b 100644 --- a/packages/light-client/README.md +++ b/packages/light-client/README.md @@ -50,12 +50,6 @@ lodestar lightclient \ For this example we will assume there is a running beacon node at `https://lodestar-sepolia.chainsafe.io` -If you are running light-client on a server/node environment there is a faster version of bls that can help with performance. It is a peerDependency and needs to be installed separately by the consumer of this package. This was done so that for browser situations there is not a hard requirement for node-only code that will cause bundling errors. On startup, if running in a node environment, and `@chainsafe/blst` is installed the LightClient will automatically use the faster bls bindings. - -```sh -npm i -S @chainsafe/blst -``` - ```ts import {Lightclient, LightclientEvent} from "@lodestar/light-client"; import {LightClientRestTransport} from "@lodestar/light-client/transport"; diff --git a/packages/light-client/package.json b/packages/light-client/package.json index 3297c896fac..4f79eeb6127 100644 --- a/packages/light-client/package.json +++ b/packages/light-client/package.json @@ -72,7 +72,7 @@ "check-readme": "typescript-docs-verifier" }, "dependencies": { - "@chainsafe/bls": "^8.1.0", + "@chainsafe/bls": "7.1.3", "@chainsafe/persistent-merkle-tree": "^0.7.1", "@chainsafe/ssz": "^0.15.1", "@lodestar/api": "^1.19.0", diff --git a/packages/prover/src/cli/preInitialization.ts b/packages/prover/src/cli/applyPreset.ts similarity index 100% rename from packages/prover/src/cli/preInitialization.ts rename to packages/prover/src/cli/applyPreset.ts diff --git a/packages/prover/src/cli/index.ts b/packages/prover/src/cli/index.ts index 467fe6bf5d0..845831b32cb 100644 --- a/packages/prover/src/cli/index.ts +++ b/packages/prover/src/cli/index.ts @@ -1,7 +1,7 @@ #!/usr/bin/env node // MUST import first to apply preset from args and set ssz hasher -import "./preInitialization.js"; +import "./applyPreset.js"; import {YargsError} from "../utils/errors.js"; import {getLodestarProverCli, yarg} from "./cli.js"; import "source-map-support/register.js"; diff --git a/packages/state-transition/package.json b/packages/state-transition/package.json index ae90a5a302f..f3e84796d14 100644 --- a/packages/state-transition/package.json +++ b/packages/state-transition/package.json @@ -59,8 +59,8 @@ "types": "lib/index.d.ts", "dependencies": { "@chainsafe/as-sha256": "^0.4.1", - "@chainsafe/bls": "^8.1.0", - "@chainsafe/blst": "^1.0.0", + "@chainsafe/bls": "7.1.3", + "@chainsafe/blst": "^0.2.10", "@chainsafe/persistent-merkle-tree": "^0.7.1", "@chainsafe/persistent-ts": "^0.19.1", "@chainsafe/ssz": "^0.15.1", diff --git a/packages/state-transition/test/unit/cachedBeaconState.test.ts b/packages/state-transition/test/unit/cachedBeaconState.test.ts index 2563cf65064..2891cd3e621 100644 --- a/packages/state-transition/test/unit/cachedBeaconState.test.ts +++ b/packages/state-transition/test/unit/cachedBeaconState.test.ts @@ -174,7 +174,7 @@ describe("CachedBeaconState", () => { // confirm loadCachedBeaconState() result for (let i = 0; i < newCachedState.validators.length; i++) { expect(newCachedState.epochCtx.pubkey2index.get(newCachedState.validators.get(i).pubkey)).toBe(i); - expect(Uint8Array.from(newCachedState.epochCtx.index2pubkey[i].toBytes())).toEqual(pubkeys[i]); + expect(newCachedState.epochCtx.index2pubkey[i].toBytes()).toEqual(pubkeys[i]); } }); } diff --git a/packages/state-transition/test/unit/constants.test.ts b/packages/state-transition/test/unit/constants.test.ts new file mode 100644 index 00000000000..5b8cc66da73 --- /dev/null +++ b/packages/state-transition/test/unit/constants.test.ts @@ -0,0 +1,10 @@ +import {describe, it, expect} from "vitest"; +import * as blst from "@chainsafe/blst"; +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); + }); +}); diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 00c52ae9c50..25dca6031fd 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -57,7 +57,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "^8.1.0", + "@chainsafe/bls": "7.1.3", "@chainsafe/bls-keystore": "^3.0.1", "@chainsafe/blst": "^1.0.0", "@lodestar/params": "^1.19.0", diff --git a/packages/validator/package.json b/packages/validator/package.json index 649098c781f..7bd1cdae0ac 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -45,7 +45,7 @@ "blockchain" ], "dependencies": { - "@chainsafe/bls": "^8.1.0", + "@chainsafe/bls": "7.1.3", "@chainsafe/ssz": "^0.15.1", "@lodestar/api": "^1.19.0", "@lodestar/config": "^1.19.0", diff --git a/yarn.lock b/yarn.lock index f7fd7dd5afb..aed735f57f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -298,18 +298,27 @@ ethereum-cryptography "^2.0.0" uuid "^9.0.0" -"@chainsafe/bls@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@chainsafe/bls/-/bls-8.1.0.tgz#d0680ce1e8c10461f7c4c1b7be228a968d77efcb" - integrity sha512-C4a1gUpFHYzJG7aaik4w+7QTeJ4pGCDTZ28YUwAWOFaWgAJSK+769ib6CNBu5Txb3PpvcC5GuhICQaDopIgEHg== +"@chainsafe/bls@7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@chainsafe/bls/-/bls-7.1.3.tgz#8d488357b187a511cfb94c96eddc7aa9f62644a9" + integrity sha512-d21eYdWxDSb63n7nB+viD+3U4yJW8huiKRibJyh8X7btPLoXkvtmDf7geYyHVbKfLDgbuHkc+b48pfPQkUTLxA== dependencies: "@chainsafe/bls-keygen" "^0.4.0" - bls-eth-wasm "^1.1.1" + bls-eth-wasm "^0.4.8" + +"@chainsafe/blst@^0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@chainsafe/blst/-/blst-0.2.10.tgz#77802e5b1ff2d98ec1d25dcd5f7d27b89d376a40" + integrity sha512-ofecTL5fWsNwnpS2oUh56dDXJRmCEcDKNNBFDb2ux+WtvdjrdSq6B+L/eNlg+sVBzXbzrCw1jq8Y8+cYiHg32w== + dependencies: + "@types/tar" "^6.1.4" + node-fetch "^2.6.1" + node-gyp "^8.4.0" "@chainsafe/blst@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@chainsafe/blst/-/blst-1.0.0.tgz#0939f5b38389ca8ae00fcc6b6555063113f611a7" - integrity sha512-WQDxFvcG+glmusXnWQ3W4g2tvHuTQEK0/cIZz37TskZJqOqAtOogZsK3cD3j+OoxbdCRT6l08QUCOtPMOLe/zA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@chainsafe/blst/-/blst-1.1.0.tgz#5d225a2df0aa3766b3c0652a1dcc057388557456" + integrity sha512-5pkXm6xk4GhR1vEjxBvwvvyTU1XhW7E6ldZaGehgdYvbyoBsC9ECWpw6JzlLLtwZVXuDfNA/glYwo8ApCcMItw== dependencies: node-addon-api "^6.1.0" node-gyp "^10.0.1" @@ -1271,7 +1280,7 @@ rfdc "^1.3.0" yaml "^2.2.2" -"@gar/promisify@^1.1.3": +"@gar/promisify@^1.0.1", "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== @@ -2024,6 +2033,14 @@ lru-cache "^10.0.1" socks-proxy-agent "^8.0.3" +"@npmcli/fs@^1.0.0": + version "1.1.1" + resolved "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + "@npmcli/fs@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.0.tgz#f2a21c28386e299d1a9fae8051d35ad180e33109" @@ -2061,6 +2078,14 @@ npm-bundled "^3.0.0" npm-normalize-package-bin "^3.0.0" +"@npmcli/move-file@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + "@npmcli/move-file@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.0.tgz#417f585016081a0184cef3e38902cd917a9bbd02" @@ -2783,6 +2808,11 @@ dependencies: defer-to-connect "^2.0.1" +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + "@tootallnate/once@2": version "2.0.0" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" @@ -3577,7 +3607,7 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" -abbrev@^1.0.0: +abbrev@1, abbrev@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== @@ -3673,7 +3703,7 @@ agent-base@^7.1.1: dependencies: debug "^4.3.4" -agentkeepalive@^4.2.1: +agentkeepalive@^4.1.3, agentkeepalive@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.2.1.tgz#a7975cbb9f83b367f06c90cc51ff28fe7d499717" integrity sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA== @@ -4264,10 +4294,10 @@ bl@^5.0.0: inherits "^2.0.4" readable-stream "^3.4.0" -bls-eth-wasm@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bls-eth-wasm/-/bls-eth-wasm-1.2.1.tgz#85f165c17d8f16000f46695b56f72bf6af386825" - integrity sha512-hl4oBzZQmPGNb9Wt5GI+oEuHM6twGc5HzXCzNZMVLMMg+dltsOuvuioRyLolpDFbncC0BJbGPzP1ZTysUGkksw== +bls-eth-wasm@^0.4.8: + version "0.4.8" + resolved "https://registry.npmjs.org/bls-eth-wasm/-/bls-eth-wasm-0.4.8.tgz" + integrity sha512-ye7+G6KFLb3i9xSrLASAoYqOUK5WLB6XA5DD8Sh0UQpZ3T999ylsYbFdoOJpmvTDuBuMi23Vy8Jm0pn/GF01CA== bluebird@~3.4.1: version "3.4.7" @@ -4509,6 +4539,30 @@ cac@^6.7.14: resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== +cacache@^15.2.0: + version "15.3.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" + fs-minipass "^2.0.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^6.0.0" + minipass "^3.1.1" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^1.0.3" + p-map "^4.0.0" + promise-inflight "^1.0.1" + rimraf "^3.0.2" + ssri "^8.0.1" + tar "^6.0.2" + unique-filename "^1.1.1" + cacache@^16.1.0: version "16.1.1" resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.1.tgz#4e79fb91d3efffe0630d5ad32db55cc1b870669c" @@ -4553,9 +4607,9 @@ cacache@^17.0.0: unique-filename "^3.0.0" cacache@^18.0.0: - version "18.0.2" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.2.tgz#fd527ea0f03a603be5c0da5805635f8eef00c60c" - integrity sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw== + version "18.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-18.0.3.tgz#864e2c18414e1e141ae8763f31e46c2cb96d1b21" + integrity sha512-qXCd4rh6I07cnDqh8V48/94Tc/WSfj+o3Gn6NZ0aZovS255bUx8O13uKxRFd2eWG0xgsco7+YItQNPaa5E85hg== dependencies: "@npmcli/fs" "^3.1.0" fs-minipass "^3.0.0" @@ -5741,7 +5795,7 @@ enabled@2.0.x: resolved "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== -encoding@^0.1.13: +encoding@^0.1.12, encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== @@ -7028,15 +7082,15 @@ glob@^10.2.2: path-scurry "^1.10.1" glob@^10.3.10: - version "10.3.12" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" - integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== + version "10.4.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.1.tgz#0cfb01ab6a6b438177bfe6a58e2576f6efe909c2" + integrity sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw== dependencies: foreground-child "^3.1.0" - jackspeak "^2.3.6" - minimatch "^9.0.1" - minipass "^7.0.4" - path-scurry "^1.10.2" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + path-scurry "^1.11.1" glob@^7.1.3, glob@^7.1.4: version "7.2.3" @@ -7335,6 +7389,15 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -8167,7 +8230,7 @@ jackspeak@^2.0.3: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -jackspeak@^2.3.5, jackspeak@^2.3.6: +jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== @@ -8176,6 +8239,15 @@ jackspeak@^2.3.5, jackspeak@^2.3.6: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jackspeak@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.1.2.tgz#eada67ea949c6b71de50f1b09c92a961897b90ab" + integrity sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" @@ -8805,7 +8877,12 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== -lru-cache@^10.0.1, lru-cache@^10.1.0, lru-cache@^10.2.0, "lru-cache@^9.1.1 || ^10.0.0": +lru-cache@^10.0.1, lru-cache@^10.2.0: + version "10.2.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" + integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== + +lru-cache@^10.1.0, "lru-cache@^9.1.1 || ^10.0.0": version "10.2.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== @@ -8916,9 +8993,9 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1, make-fetch-happen@^11.1.1: ssri "^10.0.0" make-fetch-happen@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz#705d6f6cbd7faecb8eac2432f551e49475bfedf0" - integrity sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A== + version "13.0.1" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz#273ba2f78f45e1f3a6dca91cede87d9fa4821e36" + integrity sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA== dependencies: "@npmcli/agent" "^2.0.0" cacache "^18.0.0" @@ -8929,9 +9006,32 @@ make-fetch-happen@^13.0.0: minipass-flush "^1.0.5" minipass-pipeline "^1.2.4" negotiator "^0.6.3" + proc-log "^4.2.0" promise-retry "^2.0.1" ssri "^10.0.0" +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" + integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== + dependencies: + agentkeepalive "^4.1.3" + cacache "^15.2.0" + http-cache-semantics "^4.1.0" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-lambda "^1.0.1" + lru-cache "^6.0.0" + minipass "^3.1.3" + minipass-collect "^1.0.2" + minipass-fetch "^1.3.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.4" + negotiator "^0.6.2" + promise-retry "^2.0.1" + socks-proxy-agent "^6.0.0" + ssri "^8.0.0" + map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -9190,6 +9290,17 @@ minipass-collect@^2.0.1: dependencies: minipass "^7.0.3" +minipass-fetch@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" + integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== + dependencies: + minipass "^3.1.0" + minipass-sized "^1.0.3" + minizlib "^2.0.0" + optionalDependencies: + encoding "^0.1.12" + minipass-fetch@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.0.tgz#ca1754a5f857a3be99a9271277246ac0b44c3ff8" @@ -9227,7 +9338,7 @@ minipass-json-stream@^1.0.1: jsonparse "^1.3.1" minipass "^3.0.0" -minipass-pipeline@^1.2.4: +minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== @@ -9241,7 +9352,7 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: +minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3.1.6: version "3.3.6" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== @@ -9258,12 +9369,17 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4: +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": version "7.0.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== -minizlib@^2.1.1, minizlib@^2.1.2: +minipass@^7.0.2, minipass@^7.0.3, minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -9455,7 +9571,7 @@ natural-compare@^1.4.0: resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -negotiator@^0.6.3: +negotiator@^0.6.2, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== @@ -9539,6 +9655,22 @@ node-gyp@^10.0.1: tar "^6.1.2" which "^4.0.0" +node-gyp@^8.4.0: + version "8.4.1" + resolved "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz" + integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== + dependencies: + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.6" + make-fetch-happen "^9.1.0" + nopt "^5.0.0" + npmlog "^6.0.0" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.2" + which "^2.0.2" + node-gyp@^9.0.0, node-gyp@^9.4.0: version "9.4.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.4.1.tgz#8a1023e0d6766ecb52764cc3a734b36ff275e185" @@ -9623,6 +9755,13 @@ node-stdlib-browser@^1.2.0: util "^0.12.4" vm-browserify "^1.0.1" +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + nopt@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/nopt/-/nopt-6.0.0.tgz#245801d8ebf409c6df22ab9d95b65e1309cdb16d" @@ -9631,9 +9770,9 @@ nopt@^6.0.0: abbrev "^1.0.0" nopt@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.0.tgz#067378c68116f602f552876194fd11f1292503d7" - integrity sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA== + version "7.2.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.1.tgz#1cac0eab9b8e97c9093338446eddd40b2c8ca1e7" + integrity sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w== dependencies: abbrev "^2.0.0" @@ -10367,10 +10506,10 @@ path-scurry@^1.10.1, path-scurry@^1.6.1: lru-cache "^9.1.1 || ^10.0.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-scurry@^1.10.2: - version "1.10.2" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" - integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== dependencies: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -10541,6 +10680,11 @@ proc-log@^3.0.0: resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-3.0.0.tgz#fb05ef83ccd64fd7b20bbe9c8c1070fc08338dd8" integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A== +proc-log@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-4.2.0.tgz#b6f461e4026e75fdfe228b265e9f7a00779d7034" + integrity sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -11515,6 +11659,15 @@ snappyjs@^0.7.0: resolved "https://registry.yarnpkg.com/snappyjs/-/snappyjs-0.7.0.tgz#6096eac06382700ae7fdefa579dea5e2aa20f51c" 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== + dependencies: + agent-base "^6.0.2" + debug "^4.3.1" + socks "^2.6.1" + socks-proxy-agent@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6" @@ -11542,7 +11695,7 @@ socks-proxy-agent@^8.0.3: debug "^4.3.4" socks "^2.7.1" -socks@^2.6.2, socks@^2.7.1: +socks@^2.6.1, socks@^2.6.2, socks@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55" integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ== @@ -11678,6 +11831,13 @@ ssri@^10.0.0, ssri@^10.0.1: dependencies: minipass "^4.0.0" +ssri@^8.0.0, ssri@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" + integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== + dependencies: + minipass "^3.1.1" + ssri@^9.0.0, ssri@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057" @@ -12075,7 +12235,7 @@ tar@6.1.11: mkdirp "^1.0.3" yallist "^4.0.0" -tar@^6.1.11, tar@^6.1.13, tar@^6.1.2: +tar@^6.0.2, tar@^6.1.11, tar@^6.1.13, tar@^6.1.2: version "6.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==