diff --git a/spartan/aztec-network/templates/prover-node.yaml b/spartan/aztec-network/templates/prover-node.yaml index 9b055ad3100..6e21c5a9f0c 100644 --- a/spartan/aztec-network/templates/prover-node.yaml +++ b/spartan/aztec-network/templates/prover-node.yaml @@ -160,6 +160,8 @@ spec: value: "{{ .Values.proverNode.txGathering.intervalMs }}" - name: PROVER_NODE_TX_GATHERING_MAX_PARALLEL_REQUESTS value: "{{ .Values.proverNode.txGathering.maxParallelRequests }}" + - name: PROVER_FAILED_PROOF_STORE + value: "{{ .Values.proverNode.failedProofStore }}" - name: OTEL_RESOURCE_ATTRIBUTES value: service.name={{ .Release.Name }},service.namespace={{ .Release.Namespace }},service.version={{ .Chart.AppVersion }},environment={{ .Values.environment | default "production" }} - name: L1_CHAIN_ID diff --git a/spartan/aztec-network/values.yaml b/spartan/aztec-network/values.yaml index 0f14931793c..4e876984110 100644 --- a/spartan/aztec-network/values.yaml +++ b/spartan/aztec-network/values.yaml @@ -165,6 +165,7 @@ proverNode: timeoutMs: 60000 intervalMs: 1000 maxParallelRequests: 100 + failedProofStore: "" pxe: logLevel: "debug; info: aztec:simulator, json-rpc" diff --git a/yarn-project/circuit-types/src/interfaces/prover-client.ts b/yarn-project/circuit-types/src/interfaces/prover-client.ts index 384bf8331ec..04492e953f4 100644 --- a/yarn-project/circuit-types/src/interfaces/prover-client.ts +++ b/yarn-project/circuit-types/src/interfaces/prover-client.ts @@ -23,7 +23,10 @@ export type ProverConfig = ActualProverConfig & { nodeUrl?: string; /** Identifier of the prover */ proverId: Fr; + /** Number of proving agents to start within the prover. */ proverAgentCount: number; + /** Store for failed proof inputs. */ + failedProofStore?: string; }; export const ProverConfigSchema = z.object({ @@ -60,6 +63,11 @@ export const proverConfigMappings: ConfigMappingsType = { description: 'The number of prover agents to start', ...numberConfigHelper(1), }, + failedProofStore: { + env: 'PROVER_FAILED_PROOF_STORE', + description: + 'Store for failed proof inputs. Google cloud storage is only supported at the moment. Set this value as gs://bucket-name/path/to/store.', + }, }; function parseProverId(str: string) { diff --git a/yarn-project/circuit-types/src/interfaces/proving-job.ts b/yarn-project/circuit-types/src/interfaces/proving-job.ts index dff39c8c757..495c0e0aa87 100644 --- a/yarn-project/circuit-types/src/interfaces/proving-job.ts +++ b/yarn-project/circuit-types/src/interfaces/proving-job.ts @@ -29,7 +29,7 @@ import { type ZodFor } from '@aztec/foundation/schemas'; import { z } from 'zod'; -import { type CircuitName } from '../stats/index.js'; +import { type ServerCircuitName } from '../stats/index.js'; export type ProofAndVerificationKey = { proof: RecursiveProof; @@ -95,7 +95,7 @@ export enum ProvingRequestType { TUBE_PROOF, } -export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): CircuitName { +export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): ServerCircuitName { switch (type) { case ProvingRequestType.PUBLIC_VM: return 'avm-circuit'; @@ -121,11 +121,12 @@ export function mapProvingRequestTypeToCircuitName(type: ProvingRequestType): Ci return 'root-parity'; case ProvingRequestType.TUBE_PROOF: return 'tube-circuit'; - default: + default: { + const _exhaustive: never = type; throw new Error(`Cannot find circuit name for proving request type: ${type}`); + } } } - export type AvmProvingRequest = z.infer; export const AvmProvingRequestSchema = z.object({ @@ -150,7 +151,42 @@ export const ProvingJobInputs = z.discriminatedUnion('type', [ z.object({ type: z.literal(ProvingRequestType.ROOT_ROLLUP), inputs: RootRollupInputs.schema }), z.object({ type: z.literal(ProvingRequestType.TUBE_PROOF), inputs: TubeInputs.schema }), ]); + +export function getProvingJobInputClassFor(type: ProvingRequestType) { + switch (type) { + case ProvingRequestType.PUBLIC_VM: + return AvmCircuitInputs; + case ProvingRequestType.PRIVATE_BASE_ROLLUP: + return PrivateBaseRollupInputs; + case ProvingRequestType.PUBLIC_BASE_ROLLUP: + return PublicBaseRollupInputs; + case ProvingRequestType.MERGE_ROLLUP: + return MergeRollupInputs; + case ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP: + return EmptyBlockRootRollupInputs; + case ProvingRequestType.BLOCK_ROOT_ROLLUP: + return BlockRootRollupInputs; + case ProvingRequestType.SINGLE_TX_BLOCK_ROOT_ROLLUP: + return SingleTxBlockRootRollupInputs; + case ProvingRequestType.BLOCK_MERGE_ROLLUP: + return BlockMergeRollupInputs; + case ProvingRequestType.ROOT_ROLLUP: + return RootRollupInputs; + case ProvingRequestType.BASE_PARITY: + return BaseParityInputs; + case ProvingRequestType.ROOT_PARITY: + return RootParityInputs; + case ProvingRequestType.TUBE_PROOF: + return TubeInputs; + default: { + const _exhaustive: never = type; + throw new Error(`Cannot find circuit inputs class for proving type ${type}`); + } + } +} + export type ProvingJobInputs = z.infer; + export type ProvingJobInputsMap = { [ProvingRequestType.PUBLIC_VM]: AvmCircuitInputs; [ProvingRequestType.PRIVATE_BASE_ROLLUP]: PrivateBaseRollupInputs; diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index 4c95539ea0f..e874bbea9f4 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -73,7 +73,15 @@ export type NodeSyncedChainHistoryStats = { dbSize: number; }; -export type CircuitName = +export type ClientCircuitName = + | 'private-kernel-init' + | 'private-kernel-inner' + | 'private-kernel-reset' + | 'private-kernel-tail' + | 'private-kernel-tail-to-public' + | 'app-circuit'; + +export type ServerCircuitName = | 'base-parity' | 'root-parity' | 'private-base-rollup' @@ -84,15 +92,11 @@ export type CircuitName = | 'empty-block-root-rollup' | 'block-merge-rollup' | 'root-rollup' - | 'private-kernel-init' - | 'private-kernel-inner' - | 'private-kernel-reset' - | 'private-kernel-tail' - | 'private-kernel-tail-to-public' - | 'app-circuit' | 'avm-circuit' | 'tube-circuit'; +export type CircuitName = ClientCircuitName | ServerCircuitName; + /** Stats for circuit simulation. */ export type CircuitSimulationStats = { /** name of the event. */ diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 1862daa6bea..a20595e5cc4 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -116,6 +116,7 @@ export type EnvVar = | 'PROVER_BROKER_JOB_MAX_RETRIES' | 'PROVER_COORDINATION_NODE_URL' | 'PROVER_DISABLED' + | 'PROVER_FAILED_PROOF_STORE' | 'PROVER_ID' | 'PROVER_JOB_POLL_INTERVAL_MS' | 'PROVER_JOB_TIMEOUT_MS' diff --git a/yarn-project/prover-client/package.json b/yarn-project/prover-client/package.json index e4363feffd5..cad67d34c47 100644 --- a/yarn-project/prover-client/package.json +++ b/yarn-project/prover-client/package.json @@ -30,7 +30,8 @@ "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", "bb": "node --no-warnings ./dest/bb/index.js", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=3500000 --forceExit", - "test:debug": "LOG_LEVEL=debug NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=1500000 --forceExit --testNamePattern prover/bb_prover/parity" + "test:debug": "LOG_LEVEL=debug NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=1500000 --forceExit --testNamePattern prover/bb_prover/parity", + "get-proof-inputs": "node --no-warnings ./dest/bin/get-proof-inputs.js" }, "jest": { "moduleNameMapper": { @@ -76,6 +77,7 @@ "@aztec/simulator": "workspace:^", "@aztec/telemetry-client": "workspace:^", "@aztec/world-state": "workspace:^", + "@google-cloud/storage": "^7.15.0", "@noir-lang/types": "portal:../../noir/packages/types", "commander": "^12.1.0", "lodash.chunk": "^4.2.0", diff --git a/yarn-project/prover-client/src/bin/get-proof-inputs.ts b/yarn-project/prover-client/src/bin/get-proof-inputs.ts new file mode 100644 index 00000000000..08d28435881 --- /dev/null +++ b/yarn-project/prover-client/src/bin/get-proof-inputs.ts @@ -0,0 +1,60 @@ +/* eslint-disable no-console */ +import { AVM_HINTS_FILENAME, AVM_PUBLIC_INPUTS_FILENAME } from '@aztec/bb-prover'; +import { type ProofUri, ProvingJobInputs, ProvingRequestType } from '@aztec/circuit-types'; +import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; +import { createLogger } from '@aztec/foundation/log'; + +import { mkdirSync, writeFileSync } from 'fs'; + +import { createProofStoreForUri } from '../proving_broker/index.js'; + +const logger = createLogger('prover-client:get-proof-inputs'); + +function printUsage() { + console.error('Usage: get-proof-inputs [out-dir=.]'); +} + +async function main() { + if (process.argv[2] === '--help') { + printUsage(); + return; + } + + const uri = process.argv[2]; + const outDir = process.argv[3] || '.'; + if (!uri) { + printUsage(); + throw new Error('Missing proof URI'); + } + + mkdirSync(outDir, { recursive: true }); + + const proofStore = createProofStoreForUri(uri); + logger.info(`Processing uri ${uri}`); + const input = await proofStore.getProofInput(uri as ProofUri); + logger.info(`Found inputs for ${ProvingRequestType[input.type]}`); + writeProofInputs(input, outDir); + + console.log(jsonParseWithSchema(jsonStringify(input), ProvingJobInputs).inputs); +} + +// This mimics the behavior of bb-prover/src/bb/execute.ts +function writeProofInputs(input: ProvingJobInputs, outDir: string) { + switch (input.type) { + case ProvingRequestType.PUBLIC_VM: { + writeFileSync(`${outDir}/${AVM_PUBLIC_INPUTS_FILENAME}`, input.inputs.output.toBuffer()); + logger.info(`Wrote AVM public inputs to ${AVM_PUBLIC_INPUTS_FILENAME}`); + writeFileSync(`${outDir}/${AVM_HINTS_FILENAME}`, input.inputs.avmHints.toBuffer()); + logger.info(`Wrote AVM hints to ${AVM_HINTS_FILENAME}`); + break; + } + default: { + throw new Error(`Unimplemented proving request type: ${ProvingRequestType[input.type]}`); + } + } +} + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts index 9cf02f5457f..465ddb60e12 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.test.ts @@ -11,7 +11,7 @@ import { AbortError } from '@aztec/foundation/error'; import { sleep } from '@aztec/foundation/sleep'; import { getTelemetryClient } from '@aztec/telemetry-client'; -import { InlineProofStore, type ProofStore } from '../proving_broker/proof_store.js'; +import { InlineProofStore, type ProofStore } from '../proving_broker/proof_store/index.js'; import { MemoryProvingQueue } from './memory-proving-queue.js'; describe('MemoryProvingQueue', () => { diff --git a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts index b62e3d3f003..182d7733f58 100644 --- a/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts +++ b/yarn-project/prover-client/src/prover-agent/memory-proving-queue.ts @@ -40,7 +40,7 @@ import { type PromiseWithResolvers, RunningPromise, promiseWithResolvers } from import { PriorityMemoryQueue } from '@aztec/foundation/queue'; import { type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; -import { InlineProofStore, type ProofStore } from '../proving_broker/proof_store.js'; +import { InlineProofStore, type ProofStore } from '../proving_broker/proof_store/index.js'; import { ProvingQueueMetrics } from './queue_metrics.js'; type ProvingJobWithResolvers = ProvingJob & diff --git a/yarn-project/prover-client/src/prover-agent/prover-agent.ts b/yarn-project/prover-client/src/prover-agent/prover-agent.ts index cbf6484fd7a..16eeb991fa5 100644 --- a/yarn-project/prover-client/src/prover-agent/prover-agent.ts +++ b/yarn-project/prover-client/src/prover-agent/prover-agent.ts @@ -20,7 +20,7 @@ import { trackSpan, } from '@aztec/telemetry-client'; -import { InlineProofStore } from '../proving_broker/proof_store.js'; +import { InlineProofStore } from '../proving_broker/proof_store/index.js'; const PRINT_THRESHOLD_NS = 6e10; // 60 seconds diff --git a/yarn-project/prover-client/src/prover-client/prover-client.ts b/yarn-project/prover-client/src/prover-client/prover-client.ts index bb1fcd33b8c..1017e93d844 100644 --- a/yarn-project/prover-client/src/prover-client/prover-client.ts +++ b/yarn-project/prover-client/src/prover-client/prover-client.ts @@ -18,7 +18,7 @@ import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-clien import { type ProverClientConfig } from '../config.js'; import { ProvingOrchestrator } from '../orchestrator/orchestrator.js'; import { BrokerCircuitProverFacade } from '../proving_broker/broker_prover_facade.js'; -import { InlineProofStore } from '../proving_broker/proof_store.js'; +import { InlineProofStore, type ProofStore, createProofStore } from '../proving_broker/proof_store/index.js'; import { ProvingAgent } from '../proving_broker/proving_agent.js'; import { ServerEpochProver } from './server-epoch-prover.js'; @@ -27,6 +27,9 @@ export class ProverClient implements EpochProverManager { private running = false; private agents: ProvingAgent[] = []; + private proofStore: ProofStore; + private failedProofStore: ProofStore | undefined; + private constructor( private config: ProverClientConfig, private worldState: ForkMerkleTreeOperations, @@ -34,10 +37,13 @@ export class ProverClient implements EpochProverManager { private agentClient?: ProvingJobConsumer, private telemetry: TelemetryClient = getTelemetryClient(), private log = createLogger('prover-client:tx-prover'), - ) {} + ) { + this.proofStore = new InlineProofStore(); + this.failedProofStore = this.config.failedProofStore ? createProofStore(this.config.failedProofStore) : undefined; + } public createEpochProver(): EpochProver { - const facade = new BrokerCircuitProverFacade(this.orchestratorClient); + const facade = new BrokerCircuitProverFacade(this.orchestratorClient, this.proofStore, this.failedProofStore); const orchestrator = new ProvingOrchestrator(this.worldState, facade, this.config.proverId, this.telemetry); return new ServerEpochProver(facade, orchestrator); } diff --git a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.test.ts b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.test.ts index b512274ab6b..a502209d510 100644 --- a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.test.ts +++ b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.test.ts @@ -8,21 +8,23 @@ import { jest } from '@jest/globals'; import { MockProver, TestBroker } from '../test/mock_prover.js'; import { BrokerCircuitProverFacade } from './broker_prover_facade.js'; -import { InlineProofStore } from './proof_store.js'; +import { InlineProofStore } from './proof_store/index.js'; describe('BrokerCircuitProverFacade', () => { let facade: BrokerCircuitProverFacade; let proofStore: InlineProofStore; + let errorProofStore: InlineProofStore; let broker: TestBroker; let prover: MockProver; let agentPollInterval: number; beforeEach(async () => { proofStore = new InlineProofStore(); + errorProofStore = new InlineProofStore(); prover = new MockProver(); agentPollInterval = 100; broker = new TestBroker(2, prover, proofStore, agentPollInterval); - facade = new BrokerCircuitProverFacade(broker, proofStore); + facade = new BrokerCircuitProverFacade(broker, proofStore, errorProofStore); await broker.start(); facade.start(); @@ -31,6 +33,7 @@ describe('BrokerCircuitProverFacade', () => { afterEach(async () => { await broker.stop(); await facade.stop(); + jest.restoreAllMocks(); }); it('sends jobs to the broker', async () => { @@ -39,11 +42,13 @@ describe('BrokerCircuitProverFacade', () => { jest.spyOn(broker, 'enqueueProvingJob'); jest.spyOn(prover, 'getBaseParityProof'); + jest.spyOn(errorProofStore, 'saveProofInput'); await expect(facade.getBaseParityProof(inputs, controller.signal, 42)).resolves.toBeDefined(); expect(broker.enqueueProvingJob).toHaveBeenCalled(); expect(prover.getBaseParityProof).toHaveBeenCalledWith(inputs, expect.anything(), 42); + expect(errorProofStore.saveProofInput).not.toHaveBeenCalled(); }); it('handles multiple calls for the same job', async () => { @@ -103,6 +108,7 @@ describe('BrokerCircuitProverFacade', () => { const resultPromise = promiseWithResolvers(); jest.spyOn(broker, 'enqueueProvingJob'); jest.spyOn(prover, 'getBaseParityProof').mockReturnValue(resultPromise.promise); + jest.spyOn(errorProofStore, 'saveProofInput'); // send N identical proof requests const CALLS = 50; @@ -136,6 +142,8 @@ describe('BrokerCircuitProverFacade', () => { expect(broker.enqueueProvingJob).toHaveBeenCalledTimes(2); // but no new jobs where created expect(prover.getBaseParityProof).toHaveBeenCalledTimes(1); + // and the proof input will have been backed up + expect(errorProofStore.saveProofInput).toHaveBeenCalled(); }); it('handles aborts', async () => { @@ -145,6 +153,7 @@ describe('BrokerCircuitProverFacade', () => { const resultPromise = promiseWithResolvers(); jest.spyOn(broker, 'enqueueProvingJob'); jest.spyOn(prover, 'getBaseParityProof').mockReturnValue(resultPromise.promise); + jest.spyOn(errorProofStore, 'saveProofInput'); const promise = facade.getBaseParityProof(inputs, controller.signal, 42).catch(err => ({ err })); @@ -154,6 +163,7 @@ describe('BrokerCircuitProverFacade', () => { controller.abort(); await expect(promise).resolves.toEqual({ err: new Error('Aborted') }); + expect(errorProofStore.saveProofInput).not.toHaveBeenCalled(); }); it('rejects jobs when the facade is stopped', async () => { diff --git a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts index 7cb69f6990f..833979906d1 100644 --- a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts +++ b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts @@ -1,5 +1,6 @@ import { type ProofAndVerificationKey, + type ProofUri, type ProvingJobId, type ProvingJobInputsMap, type ProvingJobProducer, @@ -41,10 +42,7 @@ import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise' import { SerialQueue } from '@aztec/foundation/queue'; import { truncate } from '@aztec/foundation/string'; -import { InlineProofStore, type ProofStore } from './proof_store.js'; - -// 20 minutes, roughly the length of an Aztec epoch. If a proof isn't ready in this amount of time then we've failed to prove the whole epoch -const MAX_WAIT_MS = 1_200_000; +import { InlineProofStore, type ProofStore } from './proof_store/index.js'; // Perform a snapshot sync every 30 seconds const SNAPSHOT_SYNC_INTERVAL_MS = 30_000; @@ -55,6 +53,7 @@ const SNAPSHOT_SYNC_CHECK_MAX_REQUEST_SIZE = 1000; type ProvingJob = { id: ProvingJobId; type: ProvingRequestType; + inputsUri: ProofUri; promise: PromiseWithResolvers; abortFn?: () => Promise; signal?: AbortSignal; @@ -70,7 +69,7 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { constructor( private broker: ProvingJobProducer, private proofStore: ProofStore = new InlineProofStore(), - private waitTimeoutMs = MAX_WAIT_MS, + private failedProofStore?: ProofStore, private pollIntervalMs = 1000, private log = createLogger('prover-client:broker-circuit-prover-facade'), ) {} @@ -125,6 +124,7 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { const job: ProvingJob = { id, type, + inputsUri, promise, abortFn, signal, @@ -335,6 +335,9 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { `Resolving proving job with error id=${job.id} type=${ProvingRequestType[job.type]}`, result.reason, ); + if (result.reason !== 'Aborted') { + void this.backupFailedProofInputs(job); + } job.promise.reject(new Error(result.reason)); } @@ -365,6 +368,26 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { } } + private async backupFailedProofInputs(job: ProvingJob) { + try { + if (!this.failedProofStore) { + return; + } + const inputs = await this.proofStore.getProofInput(job.inputsUri); + const uri = await this.failedProofStore.saveProofInput(job.id, inputs.type, inputs.inputs); + this.log.info(`Stored proof inputs for failed job id=${job.id} type=${ProvingRequestType[job.type]} at ${uri}`, { + id: job.id, + type: job.type, + uri, + }); + } catch (err) { + this.log.error( + `Error backing up proof inputs for failed job id=${job.id} type=${ProvingRequestType[job.type]}`, + err, + ); + } + } + private async monitorForCompletedJobs() { // Monitoring for completed jobs involves 2 stages. diff --git a/yarn-project/prover-client/src/proving_broker/index.ts b/yarn-project/prover-client/src/proving_broker/index.ts index 39775dbb7b0..70440f4982a 100644 --- a/yarn-project/prover-client/src/proving_broker/index.ts +++ b/yarn-project/prover-client/src/proving_broker/index.ts @@ -4,6 +4,6 @@ export * from './rpc.js'; export * from './proving_broker_database.js'; export * from './proving_broker_database/memory.js'; export * from './proving_broker_database/persisted.js'; -export * from './proof_store.js'; +export * from './proof_store/index.js'; export * from './factory.js'; export * from './config.js'; diff --git a/yarn-project/prover-client/src/proving_broker/proof_store/factory.ts b/yarn-project/prover-client/src/proving_broker/proof_store/factory.ts new file mode 100644 index 00000000000..84f3b5fa1cc --- /dev/null +++ b/yarn-project/prover-client/src/proving_broker/proof_store/factory.ts @@ -0,0 +1,42 @@ +import { createLogger } from '@aztec/foundation/log'; + +import { GoogleCloudStorageProofStore } from './gcs_proof_store.js'; +import { InlineProofStore } from './inline_proof_store.js'; +import { type ProofStore } from './proof_store.js'; + +export function createProofStore(config: string | undefined, logger = createLogger('prover-client:proof-store')) { + if (config === undefined) { + logger.info('Creating inline proof store'); + return new InlineProofStore(); + } else if (config.startsWith('gs://')) { + try { + const url = new URL(config); + const bucket = url.host; + const path = url.pathname.replace(/^\/+/, ''); + logger.info(`Creating google cloud proof store at ${bucket}`, { bucket, path }); + return new GoogleCloudStorageProofStore(bucket, path); + } catch (err) { + throw new Error( + `Invalid google cloud proof store definition: '${config}'. Supported values are 'gs://bucket-name/path/to/store'.`, + ); + } + } else { + throw new Error(`Unknown proof store config: '${config}'. Supported values are 'gs://bucket-name/path/to/store'.`); + } +} + +export function createProofStoreForUri( + uri: string, + logger = createLogger('prover-client:proof-store'), +): Pick { + if (uri.startsWith('data://')) { + return createProofStore(undefined, logger); + } else if (uri.startsWith('gs://')) { + const url = new URL(uri); + const basePath = url.pathname.replace(/^\/+/, '').split('/').slice(0, -3); + url.pathname = basePath.join('/'); + return createProofStore(uri, logger); + } else { + throw new Error(`Unknown proof store config: '${uri}'. Supported protocols are 'data://' and 'gs://'.`); + } +} diff --git a/yarn-project/prover-client/src/proving_broker/proof_store/gcs_proof_store.ts b/yarn-project/prover-client/src/proving_broker/proof_store/gcs_proof_store.ts new file mode 100644 index 00000000000..cdf434d2f1d --- /dev/null +++ b/yarn-project/prover-client/src/proving_broker/proof_store/gcs_proof_store.ts @@ -0,0 +1,72 @@ +import { + type ProofUri, + type ProvingJobId, + type ProvingJobInputs, + type ProvingJobInputsMap, + type ProvingJobResult, + type ProvingJobResultsMap, + ProvingRequestType, + getProvingJobInputClassFor, +} from '@aztec/circuit-types'; + +import { Storage } from '@google-cloud/storage'; +import { join } from 'path'; + +import { type ProofStore } from './proof_store.js'; + +const INPUTS_PATH = 'inputs'; + +export class GoogleCloudStorageProofStore implements ProofStore { + private readonly storage: Storage; + + constructor(private readonly bucketName: string, private readonly path: string) { + this.storage = new Storage(); + } + + public async saveProofInput( + id: ProvingJobId, + type: T, + inputs: ProvingJobInputsMap[T], + ): Promise { + const path = join(this.path, INPUTS_PATH, ProvingRequestType[type], id); + const file = this.storage.bucket(this.bucketName).file(path); + await file.save(inputs.toBuffer()); + return file.cloudStorageURI.toString() as ProofUri; + } + + saveProofOutput( + _id: ProvingJobId, + _type: T, + _result: ProvingJobResultsMap[T], + ): Promise { + throw new Error('Not implemented'); + } + + public async getProofInput(uri: ProofUri): Promise { + try { + const url = new URL(uri); + const bucket = this.storage.bucket(url.host); + const path = url.pathname.replace(/^\/+/, ''); + const file = bucket.file(path); + if (!(await file.exists())) { + throw new Error(`File at ${uri} does not exist`); + } + + const typeString = path.split('/').at(-2); + const type = typeString ? ProvingRequestType[typeString as keyof typeof ProvingRequestType] : undefined; + if (type === undefined) { + throw new Error(`Unrecognized proof type ${type} in path ${path}`); + } + + const contents = await file.download(); + const inputs = getProvingJobInputClassFor(type).fromBuffer(contents[0]); + return { inputs, type } as ProvingJobInputs; + } catch (err) { + throw new Error(`Error getting proof input at ${uri}: ${err}`); + } + } + + getProofOutput(_uri: ProofUri): Promise { + throw new Error('Not implemented'); + } +} diff --git a/yarn-project/prover-client/src/proving_broker/proof_store/index.ts b/yarn-project/prover-client/src/proving_broker/proof_store/index.ts new file mode 100644 index 00000000000..6281606d68a --- /dev/null +++ b/yarn-project/prover-client/src/proving_broker/proof_store/index.ts @@ -0,0 +1,3 @@ +export * from './proof_store.js'; +export * from './inline_proof_store.js'; +export * from './factory.js'; diff --git a/yarn-project/prover-client/src/proving_broker/proof_store.ts b/yarn-project/prover-client/src/proving_broker/proof_store/inline_proof_store.ts similarity index 59% rename from yarn-project/prover-client/src/proving_broker/proof_store.ts rename to yarn-project/prover-client/src/proving_broker/proof_store/inline_proof_store.ts index 9f605170ed3..58a0cb8e524 100644 --- a/yarn-project/prover-client/src/proving_broker/proof_store.ts +++ b/yarn-project/prover-client/src/proving_broker/proof_store/inline_proof_store.ts @@ -10,50 +10,7 @@ import { import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc'; import { type ZodFor } from '@aztec/foundation/schemas'; -/** - * A database for storing proof inputs and outputs. - */ -export interface ProofStore { - /** - * Save a proof input to the database. - * @param jobId - The ID of the job the proof input is associated with. - * @param type - The type of the proving request. - * @param inputs - The proof input to save. - * @returns The URI of the saved proof input. - */ - saveProofInput( - jobId: ProvingJobId, - type: T, - inputs: ProvingJobInputsMap[T], - ): Promise; - - /** - * Save a proof output to the database. - * @param jobId - The ID of the job the proof input is associated with. - * @param type - The type of the proving request. - * @param result - The proof output to save. - * @returns The URI of the saved proof output. - */ - saveProofOutput( - id: ProvingJobId, - type: T, - result: ProvingJobResultsMap[T], - ): Promise; - - /** - * Retrieve a proof input from the database. - * @param uri - The URI of the proof input to retrieve. - * @returns The proof input. - */ - getProofInput(uri: ProofUri): Promise; - - /** - * Retrieve a proof output from the database. - * @param uri - The URI of the proof output to retrieve. - * @returns The proof output. - */ - getProofOutput(uri: ProofUri): Promise; -} +import { type ProofStore } from './proof_store.js'; // use an ASCII encoded data uri https://datatracker.ietf.org/doc/html/rfc2397#section-2 // we do this to avoid double encoding to base64 (since the inputs already serialize to a base64 string) diff --git a/yarn-project/prover-client/src/proving_broker/proof_store/proof_store.ts b/yarn-project/prover-client/src/proving_broker/proof_store/proof_store.ts new file mode 100644 index 00000000000..7b3820240f2 --- /dev/null +++ b/yarn-project/prover-client/src/proving_broker/proof_store/proof_store.ts @@ -0,0 +1,54 @@ +import { + type ProofUri, + type ProvingJobId, + type ProvingJobInputs, + type ProvingJobInputsMap, + type ProvingJobResult, + type ProvingJobResultsMap, + type ProvingRequestType, +} from '@aztec/circuit-types'; + +/** + * A database for storing proof inputs and outputs. + */ +export interface ProofStore { + /** + * Save a proof input to the database. + * @param jobId - The ID of the job the proof input is associated with. + * @param type - The type of the proving request. + * @param inputs - The proof input to save. + * @returns The URI of the saved proof input. + */ + saveProofInput( + jobId: ProvingJobId, + type: T, + inputs: ProvingJobInputsMap[T], + ): Promise; + + /** + * Save a proof output to the database. + * @param jobId - The ID of the job the proof input is associated with. + * @param type - The type of the proving request. + * @param result - The proof output to save. + * @returns The URI of the saved proof output. + */ + saveProofOutput( + id: ProvingJobId, + type: T, + result: ProvingJobResultsMap[T], + ): Promise; + + /** + * Retrieve a proof input from the database. + * @param uri - The URI of the proof input to retrieve. + * @returns The proof input. + */ + getProofInput(uri: ProofUri): Promise; + + /** + * Retrieve a proof output from the database. + * @param uri - The URI of the proof output to retrieve. + * @returns The proof output. + */ + getProofOutput(uri: ProofUri): Promise; +} diff --git a/yarn-project/prover-client/src/proving_broker/proving_agent.test.ts b/yarn-project/prover-client/src/proving_broker/proving_agent.test.ts index aea11548e44..edaa6bba016 100644 --- a/yarn-project/prover-client/src/proving_broker/proving_agent.test.ts +++ b/yarn-project/prover-client/src/proving_broker/proving_agent.test.ts @@ -23,7 +23,7 @@ import { promiseWithResolvers } from '@aztec/foundation/promise'; import { jest } from '@jest/globals'; import { MockProver } from '../test/mock_prover.js'; -import { type ProofStore } from './proof_store.js'; +import { type ProofStore } from './proof_store/index.js'; import { ProvingAgent } from './proving_agent.js'; describe('ProvingAgent', () => { diff --git a/yarn-project/prover-client/src/proving_broker/proving_agent.ts b/yarn-project/prover-client/src/proving_broker/proving_agent.ts index 68fcb4fb410..bba0099463b 100644 --- a/yarn-project/prover-client/src/proving_broker/proving_agent.ts +++ b/yarn-project/prover-client/src/proving_broker/proving_agent.ts @@ -20,7 +20,7 @@ import { trackSpan, } from '@aztec/telemetry-client'; -import { type ProofStore } from './proof_store.js'; +import { type ProofStore } from './proof_store/index.js'; import { ProvingAgentInstrumentation } from './proving_agent_instrumentation.js'; import { ProvingJobController, ProvingJobControllerStatus } from './proving_job_controller.js'; diff --git a/yarn-project/prover-client/src/test/mock_prover.ts b/yarn-project/prover-client/src/test/mock_prover.ts index 35fa567f921..1f9c5d6cab9 100644 --- a/yarn-project/prover-client/src/test/mock_prover.ts +++ b/yarn-project/prover-client/src/test/mock_prover.ts @@ -44,7 +44,7 @@ import { } from '@aztec/circuits.js/testing'; import { times } from '@aztec/foundation/collection'; -import { InlineProofStore, type ProofStore } from '../proving_broker/proof_store.js'; +import { InlineProofStore, type ProofStore } from '../proving_broker/proof_store/index.js'; import { ProvingAgent } from '../proving_broker/proving_agent.js'; import { ProvingBroker } from '../proving_broker/proving_broker.js'; import { InMemoryBrokerDatabase } from '../proving_broker/proving_broker_database/memory.js'; diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 81d027a8b50..cf5d80eacad 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -1064,6 +1064,7 @@ __metadata: "@aztec/simulator": "workspace:^" "@aztec/telemetry-client": "workspace:^" "@aztec/world-state": "workspace:^" + "@google-cloud/storage": "npm:^7.15.0" "@jest/globals": "npm:^29.5.0" "@noir-lang/types": "portal:../../noir/packages/types" "@types/jest": "npm:^29.5.0" @@ -2451,6 +2452,16 @@ __metadata: languageName: node linkType: hard +"@google-cloud/paginator@npm:^5.0.0": + version: 5.0.2 + resolution: "@google-cloud/paginator@npm:5.0.2" + dependencies: + arrify: "npm:^2.0.0" + extend: "npm:^3.0.2" + checksum: 10/b64ba2029b77fdcf3c827aea0b6d128122fd1d2f4aa8c1ba70747cba0659d4216a283769fb3bbeb8f726176f5282624637f02c30f118a010e05838411da0cb76 + languageName: node + linkType: hard + "@google-cloud/precise-date@npm:^4.0.0": version: 4.0.0 resolution: "@google-cloud/precise-date@npm:4.0.0" @@ -2458,6 +2469,43 @@ __metadata: languageName: node linkType: hard +"@google-cloud/projectify@npm:^4.0.0": + version: 4.0.0 + resolution: "@google-cloud/projectify@npm:4.0.0" + checksum: 10/fdccdda0b50855c35541d71c46a6603f3302ff1a00108d946272cb2167435da00e2a2da5963fe489f4f5a4a9eb6320abeb97d3269974a972ae89f5df8451922d + languageName: node + linkType: hard + +"@google-cloud/promisify@npm:^4.0.0": + version: 4.0.0 + resolution: "@google-cloud/promisify@npm:4.0.0" + checksum: 10/c5de81321b3a5c567edcbe0b941fb32644611147f3ba22f20575918c225a979988a99bc2ebda05ac914fa8714b0a54c69be72c3f46c7a64c3b19db7d7fba8d04 + languageName: node + linkType: hard + +"@google-cloud/storage@npm:^7.15.0": + version: 7.15.0 + resolution: "@google-cloud/storage@npm:7.15.0" + dependencies: + "@google-cloud/paginator": "npm:^5.0.0" + "@google-cloud/projectify": "npm:^4.0.0" + "@google-cloud/promisify": "npm:^4.0.0" + abort-controller: "npm:^3.0.0" + async-retry: "npm:^1.3.3" + duplexify: "npm:^4.1.3" + fast-xml-parser: "npm:^4.4.1" + gaxios: "npm:^6.0.2" + google-auth-library: "npm:^9.6.3" + html-entities: "npm:^2.5.2" + mime: "npm:^3.0.0" + p-limit: "npm:^3.0.1" + retry-request: "npm:^7.0.0" + teeny-request: "npm:^9.0.0" + uuid: "npm:^8.0.0" + checksum: 10/b9898537125974e0c787ad351d3adf5cfec8c1c1bb98bdf2a56bcbc89ea84f719c9efed35aa14f309f934b97b8f9ffb161de6ba3cecc32961c3d8786c246c849 + languageName: node + linkType: hard + "@grpc/grpc-js@npm:^1.1.8": version: 1.12.5 resolution: "@grpc/grpc-js@npm:1.12.5" @@ -4846,6 +4894,13 @@ __metadata: languageName: node linkType: hard +"@tootallnate/once@npm:2": + version: 2.0.0 + resolution: "@tootallnate/once@npm:2.0.0" + checksum: 10/ad87447820dd3f24825d2d947ebc03072b20a42bfc96cbafec16bff8bbda6c1a81fcb0be56d5b21968560c5359a0af4038a68ba150c3e1694fe4c109a063bed8 + languageName: node + linkType: hard + "@tootallnate/quickjs-emscripten@npm:^0.23.0": version: 0.23.0 resolution: "@tootallnate/quickjs-emscripten@npm:0.23.0" @@ -5002,6 +5057,13 @@ __metadata: languageName: node linkType: hard +"@types/caseless@npm:*": + version: 0.12.5 + resolution: "@types/caseless@npm:0.12.5" + checksum: 10/f6a3628add76d27005495914c9c3873a93536957edaa5b69c63b46fe10b4649a6fecf16b676c1695f46aab851da47ec6047dcf3570fa8d9b6883492ff6d074e0 + languageName: node + linkType: hard + "@types/chai-as-promised@npm:^8.0.1": version: 8.0.1 resolution: "@types/chai-as-promised@npm:8.0.1" @@ -5710,6 +5772,18 @@ __metadata: languageName: node linkType: hard +"@types/request@npm:^2.48.8": + version: 2.48.12 + resolution: "@types/request@npm:2.48.12" + dependencies: + "@types/caseless": "npm:*" + "@types/node": "npm:*" + "@types/tough-cookie": "npm:*" + form-data: "npm:^2.5.0" + checksum: 10/a7b3f9f14cacc18fe235bb8e57eff1232a04bd3fa3dad29371f24a5d96db2cd295a0c8b6b34ed7efa3efbbcff845febb02c9635cd68c54811c947ea66ae22090 + languageName: node + linkType: hard + "@types/resolve@npm:1.20.2": version: 1.20.2 resolution: "@types/resolve@npm:1.20.2" @@ -5862,6 +5936,13 @@ __metadata: languageName: node linkType: hard +"@types/tough-cookie@npm:*": + version: 4.0.5 + resolution: "@types/tough-cookie@npm:4.0.5" + checksum: 10/01fd82efc8202670865928629697b62fe9bf0c0dcbc5b1c115831caeb073a2c0abb871ff393d7df1ae94ea41e256cb87d2a5a91fd03cdb1b0b4384e08d4ee482 + languageName: node + linkType: hard + "@types/wrap-ansi@npm:^3.0.0": version: 3.0.0 resolution: "@types/wrap-ansi@npm:3.0.0" @@ -6618,6 +6699,15 @@ __metadata: languageName: node linkType: hard +"abort-controller@npm:^3.0.0": + version: 3.0.0 + resolution: "abort-controller@npm:3.0.0" + dependencies: + event-target-shim: "npm:^5.0.0" + checksum: 10/ed84af329f1828327798229578b4fe03a4dd2596ba304083ebd2252666bdc1d7647d66d0b18704477e1f8aa315f055944aa6e859afebd341f12d0a53c37b4b40 + languageName: node + linkType: hard + "abortable-iterator@npm:^5.0.1": version: 5.0.1 resolution: "abortable-iterator@npm:5.0.1" @@ -6722,6 +6812,15 @@ __metadata: languageName: node linkType: hard +"agent-base@npm:6": + version: 6.0.2 + resolution: "agent-base@npm:6.0.2" + dependencies: + debug: "npm:4" + checksum: 10/21fb903e0917e5cb16591b4d0ef6a028a54b83ac30cd1fca58dece3d4e0990512a8723f9f83130d88a41e2af8b1f7be1386fda3ea2d181bb1a62155e75e95e23 + languageName: node + linkType: hard + "agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": version: 7.1.1 resolution: "agent-base@npm:7.1.1" @@ -7100,6 +7199,13 @@ __metadata: languageName: node linkType: hard +"arrify@npm:^2.0.0": + version: 2.0.1 + resolution: "arrify@npm:2.0.1" + checksum: 10/067c4c1afd182806a82e4c1cb8acee16ab8b5284fbca1ce29408e6e91281c36bb5b612f6ddfbd40a0f7a7e0c75bf2696eb94c027f6e328d6e9c52465c98e4209 + languageName: node + linkType: hard + "asap@npm:^2.0.0": version: 2.0.6 resolution: "asap@npm:2.0.6" @@ -7192,6 +7298,15 @@ __metadata: languageName: node linkType: hard +"async-retry@npm:^1.3.3": + version: 1.3.3 + resolution: "async-retry@npm:1.3.3" + dependencies: + retry: "npm:0.13.1" + checksum: 10/38a7152ff7265a9321ea214b9c69e8224ab1febbdec98efbbde6e562f17ff68405569b796b1c5271f354aef8783665d29953f051f68c1fc45306e61aec82fdc4 + languageName: node + linkType: hard + "async@npm:^2.6.4": version: 2.6.4 resolution: "async@npm:2.6.4" @@ -8431,7 +8546,7 @@ __metadata: languageName: node linkType: hard -"combined-stream@npm:^1.0.8": +"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" dependencies: @@ -9916,7 +10031,7 @@ __metadata: languageName: node linkType: hard -"duplexify@npm:^4.1.1": +"duplexify@npm:^4.1.1, duplexify@npm:^4.1.3": version: 4.1.3 resolution: "duplexify@npm:4.1.3" dependencies: @@ -10760,6 +10875,13 @@ __metadata: languageName: node linkType: hard +"event-target-shim@npm:^5.0.0": + version: 5.0.1 + resolution: "event-target-shim@npm:5.0.1" + checksum: 10/49ff46c3a7facbad3decb31f597063e761785d7fdb3920d4989d7b08c97a61c2f51183e2f3a03130c9088df88d4b489b1b79ab632219901f184f85158508f4c8 + languageName: node + linkType: hard + "eventemitter3@npm:^4.0.0": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" @@ -11005,6 +11127,17 @@ __metadata: languageName: node linkType: hard +"fast-xml-parser@npm:^4.4.1": + version: 4.5.1 + resolution: "fast-xml-parser@npm:4.5.1" + dependencies: + strnum: "npm:^1.0.5" + bin: + fxparser: src/cli/cli.js + checksum: 10/17ce5908e798de1b6d12a39d26f04ac3b582ea9ce28f3a6e3b9c401edcb74790f28df84d75377608af53308ff8caad2b244ba1283cc4b5b4cf4cc7bd532a9983 + languageName: node + linkType: hard + "fastest-levenshtein@npm:^1.0.12": version: 1.0.16 resolution: "fastest-levenshtein@npm:1.0.16" @@ -11219,6 +11352,18 @@ __metadata: languageName: node linkType: hard +"form-data@npm:^2.5.0": + version: 2.5.2 + resolution: "form-data@npm:2.5.2" + dependencies: + asynckit: "npm:^0.4.0" + combined-stream: "npm:^1.0.6" + mime-types: "npm:^2.1.12" + safe-buffer: "npm:^5.2.1" + checksum: 10/ef602e52f0bfcc8f8c346b8783f6dbd2fb271596788d42cf929dddaa50bd61e97da21f01464b4524e77872682264765e53c75ac1ab1466ea23f5c96de585faff + languageName: node + linkType: hard + "form-data@npm:^4.0.0": version: 4.0.0 resolution: "form-data@npm:4.0.0" @@ -11392,7 +11537,7 @@ __metadata: languageName: node linkType: hard -"gaxios@npm:^6.0.0, gaxios@npm:^6.0.3, gaxios@npm:^6.1.1": +"gaxios@npm:^6.0.0, gaxios@npm:^6.0.2, gaxios@npm:^6.0.3, gaxios@npm:^6.1.1": version: 6.7.1 resolution: "gaxios@npm:6.7.1" dependencies: @@ -11684,7 +11829,7 @@ __metadata: languageName: node linkType: hard -"google-auth-library@npm:^9.0.0, google-auth-library@npm:^9.7.0": +"google-auth-library@npm:^9.0.0, google-auth-library@npm:^9.6.3, google-auth-library@npm:^9.7.0": version: 9.15.0 resolution: "google-auth-library@npm:9.15.0" dependencies: @@ -11966,7 +12111,7 @@ __metadata: languageName: node linkType: hard -"html-entities@npm:^2.4.0": +"html-entities@npm:^2.4.0, html-entities@npm:^2.5.2": version: 2.5.2 resolution: "html-entities@npm:2.5.2" checksum: 10/4ec12ebdf2d5ba8192c68e1aef3c1e4a4f36b29246a0a88464fe278a54517d0196d3489af46a3145c7ecacb4fc5fd50497be19eb713b810acab3f0efcf36fdc2 @@ -12106,6 +12251,17 @@ __metadata: languageName: node linkType: hard +"http-proxy-agent@npm:^5.0.0": + version: 5.0.0 + resolution: "http-proxy-agent@npm:5.0.0" + dependencies: + "@tootallnate/once": "npm:2" + agent-base: "npm:6" + debug: "npm:4" + checksum: 10/5ee19423bc3e0fd5f23ce991b0755699ad2a46a440ce9cec99e8126bb98448ad3479d2c0ea54be5519db5b19a4ffaa69616bac01540db18506dd4dac3dc418f0 + languageName: node + linkType: hard + "http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.1": version: 7.0.2 resolution: "http-proxy-agent@npm:7.0.2" @@ -12152,6 +12308,16 @@ __metadata: languageName: node linkType: hard +"https-proxy-agent@npm:^5.0.0": + version: 5.0.1 + resolution: "https-proxy-agent@npm:5.0.1" + dependencies: + agent-base: "npm:6" + debug: "npm:4" + checksum: 10/f0dce7bdcac5e8eaa0be3c7368bb8836ed010fb5b6349ffb412b172a203efe8f807d9a6681319105ea1b6901e1972c7b5ea899672a7b9aad58309f766dcbe0df + languageName: node + linkType: hard + "https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.2, https-proxy-agent@npm:^7.0.3": version: 7.0.4 resolution: "https-proxy-agent@npm:7.0.4" @@ -14863,6 +15029,15 @@ __metadata: languageName: node linkType: hard +"mime@npm:^3.0.0": + version: 3.0.0 + resolution: "mime@npm:3.0.0" + bin: + mime: cli.js + checksum: 10/b2d31580deb58be89adaa1877cbbf152b7604b980fd7ef8f08b9e96bfedf7d605d9c23a8ba62aa12c8580b910cd7c1d27b7331d0f40f7a14e17d5a0bbec3b49f + languageName: node + linkType: hard + "mimic-fn@npm:^2.1.0": version: 2.1.0 resolution: "mimic-fn@npm:2.1.0" @@ -15918,7 +16093,7 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": +"p-limit@npm:^3.0.1, p-limit@npm:^3.0.2, p-limit@npm:^3.1.0": version: 3.1.0 resolution: "p-limit@npm:3.1.0" dependencies: @@ -17378,20 +17553,31 @@ __metadata: languageName: node linkType: hard -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10/1f914879f97e7ee931ad05fe3afa629bd55270fc6cf1c1e589b6a99fab96d15daad0fa1a52a00c729ec0078045fe3e399bd4fd0c93bcc906957bdc17f89cb8e6 +"retry-request@npm:^7.0.0": + version: 7.0.2 + resolution: "retry-request@npm:7.0.2" + dependencies: + "@types/request": "npm:^2.48.8" + extend: "npm:^3.0.2" + teeny-request: "npm:^9.0.0" + checksum: 10/8f4c927d41dd575fc460aad7b762fb0a33542097201c3c1a31529ad17fa8af3ac0d2a45bf4a2024d079913e9c2dd431566070fe33321c667ac87ebb400de5917 languageName: node linkType: hard -"retry@npm:^0.13.1": +"retry@npm:0.13.1, retry@npm:^0.13.1": version: 0.13.1 resolution: "retry@npm:0.13.1" checksum: 10/6125ec2e06d6e47e9201539c887defba4e47f63471db304c59e4b82fc63c8e89ca06a77e9d34939a9a42a76f00774b2f46c0d4a4cbb3e287268bd018ed69426d languageName: node linkType: hard +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10/1f914879f97e7ee931ad05fe3afa629bd55270fc6cf1c1e589b6a99fab96d15daad0fa1a52a00c729ec0078045fe3e399bd4fd0c93bcc906957bdc17f89cb8e6 + languageName: node + linkType: hard + "reusify@npm:^1.0.4": version: 1.0.4 resolution: "reusify@npm:1.0.4" @@ -18327,6 +18513,15 @@ __metadata: languageName: node linkType: hard +"stream-events@npm:^1.0.5": + version: 1.0.5 + resolution: "stream-events@npm:1.0.5" + dependencies: + stubs: "npm:^3.0.0" + checksum: 10/969ce82e34bfbef5734629cc06f9d7f3705a9ceb8fcd6a526332f9159f1f8bbfdb1a453f3ced0b728083454f7706adbbe8428bceb788a0287ca48ba2642dc3fc + languageName: node + linkType: hard + "stream-http@npm:^3.0.0": version: 3.2.0 resolution: "stream-http@npm:3.2.0" @@ -18593,6 +18788,20 @@ __metadata: languageName: node linkType: hard +"strnum@npm:^1.0.5": + version: 1.0.5 + resolution: "strnum@npm:1.0.5" + checksum: 10/d3117975db8372d4d7b2c07601ed2f65bf21cc48d741f37a8617b76370d228f2ec26336e53791ebc3638264d23ca54e6c241f57f8c69bd4941c63c79440525ca + languageName: node + linkType: hard + +"stubs@npm:^3.0.0": + version: 3.0.0 + resolution: "stubs@npm:3.0.0" + checksum: 10/dec7b82186e3743317616235c59bfb53284acc312cb9f4c3e97e2205c67a5c158b0ca89db5927e52351582e90a2672822eeaec9db396e23e56893d2a8676e024 + languageName: node + linkType: hard + "stylus-lookup@npm:^3.0.1": version: 3.0.2 resolution: "stylus-lookup@npm:3.0.2" @@ -18816,6 +19025,19 @@ __metadata: languageName: node linkType: hard +"teeny-request@npm:^9.0.0": + version: 9.0.0 + resolution: "teeny-request@npm:9.0.0" + dependencies: + http-proxy-agent: "npm:^5.0.0" + https-proxy-agent: "npm:^5.0.0" + node-fetch: "npm:^2.6.9" + stream-events: "npm:^1.0.5" + uuid: "npm:^9.0.0" + checksum: 10/44daabb6c2e239c3daed0218ebdafb50c7141c16d7257a6cfef786dbff56d7853c2c02c97934f7ed57818ce5861ac16c5f52f3a16fa292bd4caf53483d386443 + languageName: node + linkType: hard + "terser-webpack-plugin@npm:^5.3.10": version: 5.3.10 resolution: "terser-webpack-plugin@npm:5.3.10" @@ -19806,7 +20028,7 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^8.3.2": +"uuid@npm:^8.0.0, uuid@npm:^8.3.2": version: 8.3.2 resolution: "uuid@npm:8.3.2" bin: