@aztec/prover-client 0.0.0-test.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dest/bin/get-proof-inputs.d.ts +2 -0
- package/dest/bin/get-proof-inputs.d.ts.map +1 -0
- package/dest/bin/get-proof-inputs.js +51 -0
- package/dest/block_builder/index.d.ts +6 -0
- package/dest/block_builder/index.d.ts.map +1 -0
- package/dest/block_builder/index.js +1 -0
- package/dest/block_builder/light.d.ts +33 -0
- package/dest/block_builder/light.d.ts.map +1 -0
- package/dest/block_builder/light.js +82 -0
- package/dest/config.d.ts +17 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +39 -0
- package/dest/index.d.ts +4 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +2 -0
- package/dest/mocks/fixtures.d.ts +20 -0
- package/dest/mocks/fixtures.d.ts.map +1 -0
- package/dest/mocks/fixtures.js +77 -0
- package/dest/mocks/test_context.d.ts +55 -0
- package/dest/mocks/test_context.d.ts.map +1 -0
- package/dest/mocks/test_context.js +193 -0
- package/dest/orchestrator/block-building-helpers.d.ts +55 -0
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -0
- package/dest/orchestrator/block-building-helpers.js +285 -0
- package/dest/orchestrator/block-proving-state.d.ts +76 -0
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/block-proving-state.js +269 -0
- package/dest/orchestrator/epoch-proving-state.d.ts +60 -0
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/epoch-proving-state.js +163 -0
- package/dest/orchestrator/index.d.ts +2 -0
- package/dest/orchestrator/index.d.ts.map +1 -0
- package/dest/orchestrator/index.js +1 -0
- package/dest/orchestrator/orchestrator.d.ts +110 -0
- package/dest/orchestrator/orchestrator.d.ts.map +1 -0
- package/dest/orchestrator/orchestrator.js +690 -0
- package/dest/orchestrator/orchestrator_metrics.d.ts +8 -0
- package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -0
- package/dest/orchestrator/orchestrator_metrics.js +17 -0
- package/dest/orchestrator/tx-proving-state.d.ts +34 -0
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/tx-proving-state.js +94 -0
- package/dest/prover-client/factory.d.ts +6 -0
- package/dest/prover-client/factory.d.ts.map +1 -0
- package/dest/prover-client/factory.js +5 -0
- package/dest/prover-client/index.d.ts +3 -0
- package/dest/prover-client/index.d.ts.map +1 -0
- package/dest/prover-client/index.js +2 -0
- package/dest/prover-client/prover-client.d.ts +42 -0
- package/dest/prover-client/prover-client.d.ts.map +1 -0
- package/dest/prover-client/prover-client.js +110 -0
- package/dest/prover-client/server-epoch-prover.d.ts +28 -0
- package/dest/prover-client/server-epoch-prover.d.ts.map +1 -0
- package/dest/prover-client/server-epoch-prover.js +40 -0
- package/dest/proving_broker/broker_prover_facade.d.ts +46 -0
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -0
- package/dest/proving_broker/broker_prover_facade.js +344 -0
- package/dest/proving_broker/config.d.ts +83 -0
- package/dest/proving_broker/config.d.ts.map +1 -0
- package/dest/proving_broker/config.js +104 -0
- package/dest/proving_broker/factory.d.ts +5 -0
- package/dest/proving_broker/factory.d.ts.map +1 -0
- package/dest/proving_broker/factory.js +9 -0
- package/dest/proving_broker/fixtures.d.ts +5 -0
- package/dest/proving_broker/fixtures.d.ts.map +1 -0
- package/dest/proving_broker/fixtures.js +12 -0
- package/dest/proving_broker/index.d.ts +10 -0
- package/dest/proving_broker/index.d.ts.map +1 -0
- package/dest/proving_broker/index.js +9 -0
- package/dest/proving_broker/proof_store/factory.d.ts +6 -0
- package/dest/proving_broker/proof_store/factory.d.ts.map +1 -0
- package/dest/proving_broker/proof_store/factory.js +36 -0
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +14 -0
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +1 -0
- package/dest/proving_broker/proof_store/gcs_proof_store.js +51 -0
- package/dest/proving_broker/proof_store/index.d.ts +4 -0
- package/dest/proving_broker/proof_store/index.d.ts.map +1 -0
- package/dest/proving_broker/proof_store/index.js +3 -0
- package/dest/proving_broker/proof_store/inline_proof_store.d.ts +15 -0
- package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -0
- package/dest/proving_broker/proof_store/inline_proof_store.js +41 -0
- package/dest/proving_broker/proof_store/proof_store.d.ts +36 -0
- package/dest/proving_broker/proof_store/proof_store.d.ts.map +1 -0
- package/dest/proving_broker/proof_store/proof_store.js +3 -0
- package/dest/proving_broker/proving_agent.d.ts +46 -0
- package/dest/proving_broker/proving_agent.d.ts.map +1 -0
- package/dest/proving_broker/proving_agent.js +134 -0
- package/dest/proving_broker/proving_agent_instrumentation.d.ts +8 -0
- package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +1 -0
- package/dest/proving_broker/proving_agent_instrumentation.js +16 -0
- package/dest/proving_broker/proving_broker.d.ts +64 -0
- package/dest/proving_broker/proving_broker.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker.js +570 -0
- package/dest/proving_broker/proving_broker_database/memory.d.ts +16 -0
- package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker_database/memory.js +54 -0
- package/dest/proving_broker/proving_broker_database/persisted.d.ts +25 -0
- package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker_database/persisted.js +182 -0
- package/dest/proving_broker/proving_broker_database.d.ts +39 -0
- package/dest/proving_broker/proving_broker_database.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker_database.js +3 -0
- package/dest/proving_broker/proving_broker_instrumentation.d.ts +29 -0
- package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker_instrumentation.js +110 -0
- package/dest/proving_broker/proving_job_controller.d.ts +33 -0
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -0
- package/dest/proving_broker/proving_job_controller.js +166 -0
- package/dest/proving_broker/rpc.d.ts +27 -0
- package/dest/proving_broker/rpc.d.ts.map +1 -0
- package/dest/proving_broker/rpc.js +66 -0
- package/dest/test/mock_prover.d.ts +35 -0
- package/dest/test/mock_prover.d.ts.map +1 -0
- package/dest/test/mock_prover.js +82 -0
- package/package.json +112 -0
- package/src/bin/get-proof-inputs.ts +59 -0
- package/src/block_builder/index.ts +6 -0
- package/src/block_builder/light.ts +101 -0
- package/src/config.ts +55 -0
- package/src/index.ts +4 -0
- package/src/mocks/fixtures.ts +117 -0
- package/src/mocks/test_context.ts +257 -0
- package/src/orchestrator/block-building-helpers.ts +553 -0
- package/src/orchestrator/block-proving-state.ts +379 -0
- package/src/orchestrator/epoch-proving-state.ts +252 -0
- package/src/orchestrator/index.ts +1 -0
- package/src/orchestrator/orchestrator.ts +971 -0
- package/src/orchestrator/orchestrator_metrics.ts +22 -0
- package/src/orchestrator/tx-proving-state.ts +139 -0
- package/src/prover-client/factory.ts +14 -0
- package/src/prover-client/index.ts +2 -0
- package/src/prover-client/prover-client.ts +162 -0
- package/src/prover-client/server-epoch-prover.ts +51 -0
- package/src/proving_broker/broker_prover_facade.ts +585 -0
- package/src/proving_broker/config.ts +138 -0
- package/src/proving_broker/factory.ts +18 -0
- package/src/proving_broker/fixtures.ts +15 -0
- package/src/proving_broker/index.ts +9 -0
- package/src/proving_broker/proof_store/factory.ts +42 -0
- package/src/proving_broker/proof_store/gcs_proof_store.ts +72 -0
- package/src/proving_broker/proof_store/index.ts +3 -0
- package/src/proving_broker/proof_store/inline_proof_store.ts +63 -0
- package/src/proving_broker/proof_store/proof_store.ts +54 -0
- package/src/proving_broker/proving_agent.ts +181 -0
- package/src/proving_broker/proving_agent_instrumentation.ts +21 -0
- package/src/proving_broker/proving_broker.ts +687 -0
- package/src/proving_broker/proving_broker_database/memory.ts +63 -0
- package/src/proving_broker/proving_broker_database/persisted.ts +218 -0
- package/src/proving_broker/proving_broker_database.ts +44 -0
- package/src/proving_broker/proving_broker_instrumentation.ts +145 -0
- package/src/proving_broker/proving_job_controller.ts +194 -0
- package/src/proving_broker/rpc.ts +95 -0
- package/src/test/mock_prover.ts +253 -0
|
@@ -0,0 +1,585 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AVM_PROOF_LENGTH_IN_FIELDS,
|
|
3
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
4
|
+
NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
|
|
5
|
+
RECURSIVE_PROOF_LENGTH,
|
|
6
|
+
TUBE_PROOF_LENGTH,
|
|
7
|
+
} from '@aztec/constants';
|
|
8
|
+
import { sha256 } from '@aztec/foundation/crypto';
|
|
9
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
10
|
+
import { type PromiseWithResolvers, RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
11
|
+
import { truncate } from '@aztec/foundation/string';
|
|
12
|
+
import type { AvmCircuitInputs } from '@aztec/stdlib/avm';
|
|
13
|
+
import {
|
|
14
|
+
type ProofAndVerificationKey,
|
|
15
|
+
type ProofUri,
|
|
16
|
+
type ProvingJobId,
|
|
17
|
+
type ProvingJobInputsMap,
|
|
18
|
+
type ProvingJobProducer,
|
|
19
|
+
type ProvingJobResultsMap,
|
|
20
|
+
type ProvingJobStatus,
|
|
21
|
+
type PublicInputsAndRecursiveProof,
|
|
22
|
+
type ServerCircuitProver,
|
|
23
|
+
makeProvingJobId,
|
|
24
|
+
} from '@aztec/stdlib/interfaces/server';
|
|
25
|
+
import type { BaseParityInputs, ParityPublicInputs, RootParityInputs } from '@aztec/stdlib/parity';
|
|
26
|
+
import { ProvingRequestType } from '@aztec/stdlib/proofs';
|
|
27
|
+
import type {
|
|
28
|
+
BaseOrMergeRollupPublicInputs,
|
|
29
|
+
BlockMergeRollupInputs,
|
|
30
|
+
BlockRootOrBlockMergePublicInputs,
|
|
31
|
+
BlockRootRollupInputs,
|
|
32
|
+
EmptyBlockRootRollupInputs,
|
|
33
|
+
MergeRollupInputs,
|
|
34
|
+
PrivateBaseRollupInputs,
|
|
35
|
+
PublicBaseRollupInputs,
|
|
36
|
+
RootRollupInputs,
|
|
37
|
+
RootRollupPublicInputs,
|
|
38
|
+
SingleTxBlockRootRollupInputs,
|
|
39
|
+
TubeInputs,
|
|
40
|
+
} from '@aztec/stdlib/rollup';
|
|
41
|
+
|
|
42
|
+
import { InlineProofStore, type ProofStore } from './proof_store/index.js';
|
|
43
|
+
|
|
44
|
+
// Perform a snapshot sync every 30 seconds
|
|
45
|
+
const SNAPSHOT_SYNC_INTERVAL_MS = 30_000;
|
|
46
|
+
|
|
47
|
+
const MAX_CONCURRENT_JOB_SETTLED_REQUESTS = 10;
|
|
48
|
+
const SNAPSHOT_SYNC_CHECK_MAX_REQUEST_SIZE = 1000;
|
|
49
|
+
|
|
50
|
+
type ProvingJob = {
|
|
51
|
+
id: ProvingJobId;
|
|
52
|
+
inputsUri?: ProofUri;
|
|
53
|
+
type: ProvingRequestType;
|
|
54
|
+
deferred: PromiseWithResolvers<any>;
|
|
55
|
+
abortFn: () => void;
|
|
56
|
+
signal?: AbortSignal;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export class BrokerCircuitProverFacade implements ServerCircuitProver {
|
|
60
|
+
private jobs: Map<ProvingJobId, ProvingJob> = new Map();
|
|
61
|
+
private runningPromise?: RunningPromise;
|
|
62
|
+
private timeOfLastSnapshotSync = Date.now();
|
|
63
|
+
private jobsToRetrieve: Set<ProvingJobId> = new Set();
|
|
64
|
+
|
|
65
|
+
constructor(
|
|
66
|
+
private broker: ProvingJobProducer,
|
|
67
|
+
private proofStore: ProofStore = new InlineProofStore(),
|
|
68
|
+
private failedProofStore?: ProofStore,
|
|
69
|
+
private pollIntervalMs = 1000,
|
|
70
|
+
private log = createLogger('prover-client:broker-circuit-prover-facade'),
|
|
71
|
+
) {}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* This is a critical section. This function can not be async since it writes
|
|
75
|
+
* to the jobs map which acts as a mutex, ensuring a job is only ever created once.
|
|
76
|
+
*
|
|
77
|
+
* This could be called in a SerialQueue if it needs to become async.
|
|
78
|
+
*/
|
|
79
|
+
private getOrCreateProvingJob<T extends ProvingRequestType>(
|
|
80
|
+
id: ProvingJobId,
|
|
81
|
+
type: T,
|
|
82
|
+
signal?: AbortSignal,
|
|
83
|
+
): { job: ProvingJob; isEnqueued: boolean } {
|
|
84
|
+
// Check if there is already a promise for this job
|
|
85
|
+
const existingJob = this.jobs.get(id);
|
|
86
|
+
if (existingJob) {
|
|
87
|
+
this.log.verbose(`Job already found in facade id=${id} type=${ProvingRequestType[type]}`, {
|
|
88
|
+
provingJobId: id,
|
|
89
|
+
provingJobType: ProvingRequestType[type],
|
|
90
|
+
});
|
|
91
|
+
return { job: existingJob, isEnqueued: true };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Create a promise for this job id, regardless of whether it was enqueued at the broker
|
|
95
|
+
// The running promise will monitor for the job to be completed and resolve it either way
|
|
96
|
+
const promise = promiseWithResolvers<ProvingJobResultsMap[T]>();
|
|
97
|
+
const abortFn = () => {
|
|
98
|
+
signal?.removeEventListener('abort', abortFn);
|
|
99
|
+
void this.broker.cancelProvingJob(id).catch(err => this.log.warn(`Error cancelling job id=${id}`, err));
|
|
100
|
+
};
|
|
101
|
+
const job: ProvingJob = {
|
|
102
|
+
id,
|
|
103
|
+
type,
|
|
104
|
+
deferred: promise,
|
|
105
|
+
abortFn,
|
|
106
|
+
signal,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
this.jobs.set(id, job);
|
|
110
|
+
return { job, isEnqueued: false };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private async enqueueJob<T extends ProvingRequestType>(
|
|
114
|
+
id: ProvingJobId,
|
|
115
|
+
type: T,
|
|
116
|
+
inputs: ProvingJobInputsMap[T],
|
|
117
|
+
epochNumber = 0,
|
|
118
|
+
signal?: AbortSignal,
|
|
119
|
+
): Promise<ProvingJobResultsMap[T]> {
|
|
120
|
+
const { job: job, isEnqueued } = this.getOrCreateProvingJob(id, type, signal);
|
|
121
|
+
if (isEnqueued) {
|
|
122
|
+
return job.deferred.promise;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const inputsUri = await this.proofStore.saveProofInput(id, type, inputs);
|
|
127
|
+
job.inputsUri = inputsUri;
|
|
128
|
+
const jobStatus = await this.broker.enqueueProvingJob({
|
|
129
|
+
id,
|
|
130
|
+
type,
|
|
131
|
+
inputsUri,
|
|
132
|
+
epochNumber,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// If we are here then the job was successfully accepted by the broker
|
|
136
|
+
// the returned status is for before any action was performed
|
|
137
|
+
if (jobStatus.status === 'fulfilled' || jobStatus.status === 'rejected') {
|
|
138
|
+
// Job was already completed by the broker
|
|
139
|
+
// No need to notify the broker on aborted job
|
|
140
|
+
this.log.verbose(
|
|
141
|
+
`Job already completed when sent to broker id=${id} type=${ProvingRequestType[type]} epochNumber=${epochNumber}`,
|
|
142
|
+
{
|
|
143
|
+
provingJobId: id,
|
|
144
|
+
provingJobType: ProvingRequestType[type],
|
|
145
|
+
epochNumber,
|
|
146
|
+
inputsUri: truncate(inputsUri),
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
// Job was not enqueued. It must be completed already, add to our set of already completed jobs
|
|
151
|
+
this.jobsToRetrieve.add(id);
|
|
152
|
+
} else {
|
|
153
|
+
// notify the broker if job is aborted
|
|
154
|
+
signal?.addEventListener('abort', job.abortFn);
|
|
155
|
+
|
|
156
|
+
// Job added for the first time
|
|
157
|
+
if (jobStatus.status === 'not-found') {
|
|
158
|
+
this.log.verbose(
|
|
159
|
+
`Job enqueued with broker id=${id} type=${ProvingRequestType[type]} epochNumber=${epochNumber}`,
|
|
160
|
+
{
|
|
161
|
+
provingJobId: id,
|
|
162
|
+
provingJobType: ProvingRequestType[type],
|
|
163
|
+
epochNumber,
|
|
164
|
+
inputsUri: truncate(inputsUri),
|
|
165
|
+
numOutstandingJobs: this.jobs.size,
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
} else {
|
|
169
|
+
// Job was previously sent to the broker but is not completed
|
|
170
|
+
this.log.verbose(
|
|
171
|
+
`Job already in queue or in progress when sent to broker id=${id} type=${ProvingRequestType[type]} epochNumber=${epochNumber}`,
|
|
172
|
+
{
|
|
173
|
+
provingJobId: id,
|
|
174
|
+
provingJobType: ProvingRequestType[type],
|
|
175
|
+
epochNumber,
|
|
176
|
+
inputsUri: truncate(inputsUri),
|
|
177
|
+
},
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
} catch (err) {
|
|
182
|
+
this.jobs.delete(job.id);
|
|
183
|
+
job.deferred.reject(err);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return job.deferred.promise as Promise<ProvingJobResultsMap[T]>;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
public start() {
|
|
190
|
+
if (this.runningPromise) {
|
|
191
|
+
throw new Error('BrokerCircuitProverFacade already started');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this.log.verbose('Starting BrokerCircuitProverFacade');
|
|
195
|
+
|
|
196
|
+
this.runningPromise = new RunningPromise(() => this.monitorForCompletedJobs(), this.log, this.pollIntervalMs);
|
|
197
|
+
this.runningPromise.start();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
public async stop(): Promise<void> {
|
|
201
|
+
if (!this.runningPromise) {
|
|
202
|
+
throw new Error('BrokerCircuitProverFacade not started');
|
|
203
|
+
}
|
|
204
|
+
this.log.verbose('Stopping BrokerCircuitProverFacade');
|
|
205
|
+
await this.runningPromise.stop();
|
|
206
|
+
|
|
207
|
+
// Reject any outstanding promises as stopped
|
|
208
|
+
for (const [_, v] of this.jobs) {
|
|
209
|
+
v.deferred.reject(new Error('Broker facade stopped'));
|
|
210
|
+
}
|
|
211
|
+
this.jobs.clear();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private async updateCompletedJobs() {
|
|
215
|
+
// Here we check for completed jobs. If everything works well (there are no service restarts etc) then all we need to do
|
|
216
|
+
// to maintain correct job state is to check for incrementally completed jobs. i.e. call getCompletedJobs with an empty array
|
|
217
|
+
// However, if there are any problems then we may lose sync with the broker's actual set of completed jobs.
|
|
218
|
+
// In this case we need to perform a full snapshot sync. This involves sending all of our outstanding job Ids to the broker
|
|
219
|
+
// and have the broker report on whether they are completed or not.
|
|
220
|
+
// We perform an incremental sync on every call of this function with a full snapshot sync periodically.
|
|
221
|
+
// This should keep us in sync without over-burdening the broker with snapshot sync requests
|
|
222
|
+
|
|
223
|
+
const getAllCompletedJobs = async (ids: ProvingJobId[]) => {
|
|
224
|
+
// In this function we take whatever set of snapshot ids and we ask the broker for completed job notifications
|
|
225
|
+
// We collect all returned notifications and return them
|
|
226
|
+
const allCompleted = new Set<ProvingJobId>();
|
|
227
|
+
try {
|
|
228
|
+
let numRequests = 0;
|
|
229
|
+
while (ids.length > 0) {
|
|
230
|
+
const slice = ids.splice(0, SNAPSHOT_SYNC_CHECK_MAX_REQUEST_SIZE);
|
|
231
|
+
const completed = await this.broker.getCompletedJobs(slice);
|
|
232
|
+
completed.forEach(id => allCompleted.add(id));
|
|
233
|
+
++numRequests;
|
|
234
|
+
}
|
|
235
|
+
if (numRequests === 0) {
|
|
236
|
+
const final = await this.broker.getCompletedJobs([]);
|
|
237
|
+
final.forEach(id => allCompleted.add(id));
|
|
238
|
+
}
|
|
239
|
+
} catch (err) {
|
|
240
|
+
this.log.error(`Error thrown when requesting completed job notifications from the broker`, err);
|
|
241
|
+
}
|
|
242
|
+
return allCompleted;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
const snapshotSyncIds: string[] = [];
|
|
246
|
+
const currentTime = Date.now();
|
|
247
|
+
const secondsSinceLastSnapshotSync = currentTime - this.timeOfLastSnapshotSync;
|
|
248
|
+
if (secondsSinceLastSnapshotSync > SNAPSHOT_SYNC_INTERVAL_MS) {
|
|
249
|
+
this.timeOfLastSnapshotSync = currentTime;
|
|
250
|
+
snapshotSyncIds.push(...this.jobs.keys());
|
|
251
|
+
this.log.trace(`Performing full snapshot sync of completed jobs with ${snapshotSyncIds.length} job(s)`);
|
|
252
|
+
} else {
|
|
253
|
+
this.log.trace(`Performing incremental sync of completed jobs`, { snapshotSyncIds });
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Now request the notifications from the broker
|
|
257
|
+
const snapshotIdsLength = snapshotSyncIds.length;
|
|
258
|
+
const completedJobs = await getAllCompletedJobs(snapshotSyncIds);
|
|
259
|
+
|
|
260
|
+
// We now have an additional set of completed job notifications to add to our cached set giving us the full set of jobs that we have been told are ready
|
|
261
|
+
// We filter this list to what we actually need, in case for any reason it is different and store in our cache
|
|
262
|
+
const allJobsReady = [...completedJobs, ...this.jobsToRetrieve];
|
|
263
|
+
this.jobsToRetrieve = new Set(allJobsReady.filter(id => this.jobs.has(id)));
|
|
264
|
+
|
|
265
|
+
if (completedJobs.size > 0) {
|
|
266
|
+
this.log.verbose(
|
|
267
|
+
`Check for job completion notifications returned ${completedJobs.size} job(s), snapshot ids length: ${snapshotIdsLength}, num outstanding jobs: ${this.jobs.size}, total jobs ready: ${this.jobsToRetrieve.size}`,
|
|
268
|
+
);
|
|
269
|
+
} else {
|
|
270
|
+
this.log.trace(
|
|
271
|
+
`Check for job completion notifications returned 0 jobs, snapshot ids length: ${snapshotIdsLength}, num outstanding jobs: ${this.jobs.size}, total jobs ready: ${this.jobsToRetrieve.size}`,
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private async retrieveJobsThatShouldBeReady() {
|
|
277
|
+
const convertJobResult = async <T extends ProvingRequestType>(
|
|
278
|
+
result: ProvingJobStatus,
|
|
279
|
+
jobType: ProvingRequestType,
|
|
280
|
+
): Promise<{
|
|
281
|
+
success: boolean;
|
|
282
|
+
reason?: string;
|
|
283
|
+
result?: ProvingJobResultsMap[T];
|
|
284
|
+
}> => {
|
|
285
|
+
if (result.status === 'fulfilled') {
|
|
286
|
+
const output = await this.proofStore.getProofOutput(result.value);
|
|
287
|
+
if (output.type === jobType) {
|
|
288
|
+
return { result: output.result as ProvingJobResultsMap[T], success: true };
|
|
289
|
+
} else {
|
|
290
|
+
return { success: false, reason: `Unexpected proof type: ${output.type}. Expected: ${jobType}` };
|
|
291
|
+
}
|
|
292
|
+
} else if (result.status === 'rejected') {
|
|
293
|
+
return { success: false, reason: result.reason };
|
|
294
|
+
} else {
|
|
295
|
+
throw new Error(`Unexpected proving job status ${result.status}`);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const processJob = async (job: ProvingJob) => {
|
|
300
|
+
// First retrieve the settled job from the broker
|
|
301
|
+
this.log.debug(`Received notification of completed job id=${job.id} type=${ProvingRequestType[job.type]}`);
|
|
302
|
+
let settledResult;
|
|
303
|
+
try {
|
|
304
|
+
settledResult = await this.broker.getProvingJobStatus(job.id);
|
|
305
|
+
} catch (err) {
|
|
306
|
+
// If an error occurs retrieving the job result then just log it and move on.
|
|
307
|
+
// We will try again on the next iteration
|
|
308
|
+
this.log.error(
|
|
309
|
+
`Error retrieving job result from broker job id=${job.id} type=${ProvingRequestType[job.type]}`,
|
|
310
|
+
err,
|
|
311
|
+
);
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Then convert the result and resolve/reject the promise
|
|
316
|
+
let result;
|
|
317
|
+
try {
|
|
318
|
+
result = await convertJobResult(settledResult, job.type);
|
|
319
|
+
} catch (err) {
|
|
320
|
+
// If an error occurs retrieving the job result then just log it and move on.
|
|
321
|
+
// We will try again on the next iteration
|
|
322
|
+
this.log.error(`Error processing job result job id=${job.id} type=${ProvingRequestType[job.type]}`, err);
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (result.success) {
|
|
327
|
+
this.log.verbose(`Resolved proving job id=${job.id} type=${ProvingRequestType[job.type]}`);
|
|
328
|
+
job.deferred.resolve(result.result);
|
|
329
|
+
} else {
|
|
330
|
+
this.log.error(
|
|
331
|
+
`Resolving proving job with error id=${job.id} type=${ProvingRequestType[job.type]}`,
|
|
332
|
+
result.reason,
|
|
333
|
+
);
|
|
334
|
+
if (result.reason !== 'Aborted') {
|
|
335
|
+
void this.backupFailedProofInputs(job);
|
|
336
|
+
}
|
|
337
|
+
job.deferred.reject(new Error(result.reason));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (job.abortFn && job.signal) {
|
|
341
|
+
job.signal?.removeEventListener('abort', job.abortFn);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Job is now processed removed from our cache
|
|
345
|
+
this.jobs.delete(job.id);
|
|
346
|
+
this.jobsToRetrieve.delete(job.id);
|
|
347
|
+
return true;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const toBeRetrieved = Array.from(this.jobsToRetrieve.values())
|
|
351
|
+
.map(id => this.jobs.get(id)!)
|
|
352
|
+
.filter(x => x !== undefined);
|
|
353
|
+
const totalJobsToRetrieve = toBeRetrieved.length;
|
|
354
|
+
let totalJobsRetrieved = 0;
|
|
355
|
+
while (toBeRetrieved.length > 0) {
|
|
356
|
+
const slice = toBeRetrieved.splice(0, MAX_CONCURRENT_JOB_SETTLED_REQUESTS);
|
|
357
|
+
const results = await Promise.all(slice.map(job => processJob(job!)));
|
|
358
|
+
totalJobsRetrieved += results.filter(x => x).length;
|
|
359
|
+
}
|
|
360
|
+
if (totalJobsToRetrieve > 0) {
|
|
361
|
+
this.log.verbose(
|
|
362
|
+
`Successfully retrieved ${totalJobsRetrieved} of ${totalJobsToRetrieve} jobs that should be ready, total ready jobs is now: ${this.jobsToRetrieve.size}`,
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private async backupFailedProofInputs(job: ProvingJob) {
|
|
368
|
+
try {
|
|
369
|
+
if (!this.failedProofStore || !job.inputsUri) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const inputs = await this.proofStore.getProofInput(job.inputsUri);
|
|
373
|
+
const uri = await this.failedProofStore.saveProofInput(job.id, inputs.type, inputs.inputs);
|
|
374
|
+
this.log.info(`Stored proof inputs for failed job id=${job.id} type=${ProvingRequestType[job.type]} at ${uri}`, {
|
|
375
|
+
id: job.id,
|
|
376
|
+
type: job.type,
|
|
377
|
+
uri,
|
|
378
|
+
});
|
|
379
|
+
} catch (err) {
|
|
380
|
+
this.log.error(
|
|
381
|
+
`Error backing up proof inputs for failed job id=${job.id} type=${ProvingRequestType[job.type]}`,
|
|
382
|
+
err,
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
private async monitorForCompletedJobs() {
|
|
388
|
+
// Monitoring for completed jobs involves 2 stages.
|
|
389
|
+
|
|
390
|
+
// 1. Update our list of completed jobs.
|
|
391
|
+
// We poll the broker for any new job completion notifications and after filtering/deduplication add them to our cached
|
|
392
|
+
// list of jobs that we have been told are ready.
|
|
393
|
+
await this.updateCompletedJobs();
|
|
394
|
+
|
|
395
|
+
// 2. Retrieve the jobs that should be ready.
|
|
396
|
+
// We have a list of jobs that we have been told are ready, so we go ahead and ask for their results
|
|
397
|
+
await this.retrieveJobsThatShouldBeReady();
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
getAvmProof(
|
|
401
|
+
inputs: AvmCircuitInputs,
|
|
402
|
+
signal?: AbortSignal,
|
|
403
|
+
epochNumber?: number,
|
|
404
|
+
): Promise<ProofAndVerificationKey<typeof AVM_PROOF_LENGTH_IN_FIELDS>> {
|
|
405
|
+
return this.enqueueJob(
|
|
406
|
+
this.generateId(ProvingRequestType.PUBLIC_VM, inputs, epochNumber),
|
|
407
|
+
ProvingRequestType.PUBLIC_VM,
|
|
408
|
+
inputs,
|
|
409
|
+
epochNumber,
|
|
410
|
+
signal,
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
getBaseParityProof(
|
|
415
|
+
inputs: BaseParityInputs,
|
|
416
|
+
signal?: AbortSignal,
|
|
417
|
+
epochNumber?: number,
|
|
418
|
+
): Promise<PublicInputsAndRecursiveProof<ParityPublicInputs, typeof RECURSIVE_PROOF_LENGTH>> {
|
|
419
|
+
return this.enqueueJob(
|
|
420
|
+
this.generateId(ProvingRequestType.BASE_PARITY, inputs, epochNumber),
|
|
421
|
+
ProvingRequestType.BASE_PARITY,
|
|
422
|
+
inputs,
|
|
423
|
+
epochNumber,
|
|
424
|
+
signal,
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
getBlockMergeRollupProof(
|
|
429
|
+
input: BlockMergeRollupInputs,
|
|
430
|
+
signal?: AbortSignal,
|
|
431
|
+
epochNumber?: number,
|
|
432
|
+
): Promise<
|
|
433
|
+
PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
434
|
+
> {
|
|
435
|
+
return this.enqueueJob(
|
|
436
|
+
this.generateId(ProvingRequestType.BLOCK_MERGE_ROLLUP, input, epochNumber),
|
|
437
|
+
ProvingRequestType.BLOCK_MERGE_ROLLUP,
|
|
438
|
+
input,
|
|
439
|
+
epochNumber,
|
|
440
|
+
signal,
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
getBlockRootRollupProof(
|
|
445
|
+
input: BlockRootRollupInputs,
|
|
446
|
+
signal?: AbortSignal,
|
|
447
|
+
epochNumber?: number,
|
|
448
|
+
): Promise<
|
|
449
|
+
PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
450
|
+
> {
|
|
451
|
+
return this.enqueueJob(
|
|
452
|
+
this.generateId(ProvingRequestType.BLOCK_ROOT_ROLLUP, input, epochNumber),
|
|
453
|
+
ProvingRequestType.BLOCK_ROOT_ROLLUP,
|
|
454
|
+
input,
|
|
455
|
+
epochNumber,
|
|
456
|
+
signal,
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
getSingleTxBlockRootRollupProof(
|
|
461
|
+
input: SingleTxBlockRootRollupInputs,
|
|
462
|
+
signal?: AbortSignal,
|
|
463
|
+
epochNumber?: number,
|
|
464
|
+
): Promise<
|
|
465
|
+
PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
466
|
+
> {
|
|
467
|
+
return this.enqueueJob(
|
|
468
|
+
this.generateId(ProvingRequestType.BLOCK_ROOT_ROLLUP, input, epochNumber),
|
|
469
|
+
ProvingRequestType.SINGLE_TX_BLOCK_ROOT_ROLLUP,
|
|
470
|
+
input,
|
|
471
|
+
epochNumber,
|
|
472
|
+
signal,
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
getEmptyBlockRootRollupProof(
|
|
477
|
+
input: EmptyBlockRootRollupInputs,
|
|
478
|
+
signal?: AbortSignal,
|
|
479
|
+
epochNumber?: number,
|
|
480
|
+
): Promise<
|
|
481
|
+
PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
482
|
+
> {
|
|
483
|
+
return this.enqueueJob(
|
|
484
|
+
this.generateId(ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP, input, epochNumber),
|
|
485
|
+
ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP,
|
|
486
|
+
input,
|
|
487
|
+
epochNumber,
|
|
488
|
+
signal,
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
getMergeRollupProof(
|
|
493
|
+
input: MergeRollupInputs,
|
|
494
|
+
signal?: AbortSignal,
|
|
495
|
+
epochNumber?: number,
|
|
496
|
+
): Promise<
|
|
497
|
+
PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
498
|
+
> {
|
|
499
|
+
return this.enqueueJob(
|
|
500
|
+
this.generateId(ProvingRequestType.MERGE_ROLLUP, input, epochNumber),
|
|
501
|
+
ProvingRequestType.MERGE_ROLLUP,
|
|
502
|
+
input,
|
|
503
|
+
epochNumber,
|
|
504
|
+
signal,
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
getPrivateBaseRollupProof(
|
|
508
|
+
baseRollupInput: PrivateBaseRollupInputs,
|
|
509
|
+
signal?: AbortSignal,
|
|
510
|
+
epochNumber?: number,
|
|
511
|
+
): Promise<
|
|
512
|
+
PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
513
|
+
> {
|
|
514
|
+
return this.enqueueJob(
|
|
515
|
+
this.generateId(ProvingRequestType.PRIVATE_BASE_ROLLUP, baseRollupInput, epochNumber),
|
|
516
|
+
ProvingRequestType.PRIVATE_BASE_ROLLUP,
|
|
517
|
+
baseRollupInput,
|
|
518
|
+
epochNumber,
|
|
519
|
+
signal,
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
getPublicBaseRollupProof(
|
|
524
|
+
inputs: PublicBaseRollupInputs,
|
|
525
|
+
signal?: AbortSignal,
|
|
526
|
+
epochNumber?: number,
|
|
527
|
+
): Promise<
|
|
528
|
+
PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH>
|
|
529
|
+
> {
|
|
530
|
+
return this.enqueueJob(
|
|
531
|
+
this.generateId(ProvingRequestType.PUBLIC_BASE_ROLLUP, inputs, epochNumber),
|
|
532
|
+
ProvingRequestType.PUBLIC_BASE_ROLLUP,
|
|
533
|
+
inputs,
|
|
534
|
+
epochNumber,
|
|
535
|
+
signal,
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
getRootParityProof(
|
|
540
|
+
inputs: RootParityInputs,
|
|
541
|
+
signal?: AbortSignal,
|
|
542
|
+
epochNumber?: number,
|
|
543
|
+
): Promise<PublicInputsAndRecursiveProof<ParityPublicInputs, typeof NESTED_RECURSIVE_PROOF_LENGTH>> {
|
|
544
|
+
return this.enqueueJob(
|
|
545
|
+
this.generateId(ProvingRequestType.ROOT_PARITY, inputs, epochNumber),
|
|
546
|
+
ProvingRequestType.ROOT_PARITY,
|
|
547
|
+
inputs,
|
|
548
|
+
epochNumber,
|
|
549
|
+
signal,
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
getRootRollupProof(
|
|
554
|
+
input: RootRollupInputs,
|
|
555
|
+
signal?: AbortSignal,
|
|
556
|
+
epochNumber?: number,
|
|
557
|
+
): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs, typeof RECURSIVE_PROOF_LENGTH>> {
|
|
558
|
+
return this.enqueueJob(
|
|
559
|
+
this.generateId(ProvingRequestType.ROOT_ROLLUP, input, epochNumber),
|
|
560
|
+
ProvingRequestType.ROOT_ROLLUP,
|
|
561
|
+
input,
|
|
562
|
+
epochNumber,
|
|
563
|
+
signal,
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
getTubeProof(
|
|
568
|
+
tubeInput: TubeInputs,
|
|
569
|
+
signal?: AbortSignal,
|
|
570
|
+
epochNumber?: number,
|
|
571
|
+
): Promise<ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>> {
|
|
572
|
+
return this.enqueueJob(
|
|
573
|
+
this.generateId(ProvingRequestType.TUBE_PROOF, tubeInput, epochNumber),
|
|
574
|
+
ProvingRequestType.TUBE_PROOF,
|
|
575
|
+
tubeInput,
|
|
576
|
+
epochNumber,
|
|
577
|
+
signal,
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
private generateId(type: ProvingRequestType, inputs: { toBuffer(): Buffer }, epochNumber = 0) {
|
|
582
|
+
const inputsHash = sha256(inputs.toBuffer());
|
|
583
|
+
return makeProvingJobId(epochNumber, type, inputsHash.toString('hex'));
|
|
584
|
+
}
|
|
585
|
+
}
|