@aztec/prover-client 0.66.0 → 0.67.1-devnet
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/dest/block_builder/light.d.ts +4 -3
- package/dest/block_builder/light.d.ts.map +1 -1
- package/dest/block_builder/light.js +30 -20
- package/dest/index.d.ts +0 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -2
- package/dest/mocks/fixtures.d.ts +3 -3
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +2 -2
- package/dest/mocks/test_context.d.ts +10 -9
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +24 -13
- package/dest/orchestrator/block-building-helpers.d.ts +10 -6
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +27 -16
- package/dest/orchestrator/block-proving-state.d.ts +6 -5
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/block-proving-state.js +16 -8
- package/dest/orchestrator/epoch-proving-state.d.ts +1 -1
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/epoch-proving-state.js +3 -3
- package/dest/orchestrator/orchestrator.d.ts +11 -8
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +94 -58
- package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator_metrics.js +2 -5
- package/dest/prover-agent/memory-proving-queue.d.ts +2 -1
- package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
- package/dest/prover-agent/memory-proving-queue.js +241 -224
- package/dest/prover-agent/prover-agent.d.ts +11 -2
- package/dest/prover-agent/prover-agent.d.ts.map +1 -1
- package/dest/prover-agent/prover-agent.js +187 -160
- package/dest/prover-client/prover-client.d.ts +2 -3
- package/dest/prover-client/prover-client.d.ts.map +1 -1
- package/dest/prover-client/prover-client.js +6 -9
- package/dest/proving_broker/broker_prover_facade.d.ts +26 -0
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -0
- package/dest/proving_broker/broker_prover_facade.js +107 -0
- package/dest/proving_broker/proving_agent.d.ts +4 -3
- package/dest/proving_broker/proving_agent.d.ts.map +1 -1
- package/dest/proving_broker/proving_agent.js +74 -65
- package/dest/proving_broker/proving_broker.d.ts +27 -7
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +405 -258
- package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/persisted.js +4 -8
- package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_instrumentation.js +2 -8
- package/dest/proving_broker/proving_job_controller.d.ts +2 -1
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
- package/dest/proving_broker/proving_job_controller.js +15 -14
- package/dest/proving_broker/rpc.js +2 -2
- package/dest/test/mock_prover.d.ts +6 -6
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +5 -5
- package/package.json +18 -13
- package/src/block_builder/light.ts +31 -22
- package/src/index.ts +0 -1
- package/src/mocks/fixtures.ts +4 -4
- package/src/mocks/test_context.ts +39 -24
- package/src/orchestrator/block-building-helpers.ts +33 -20
- package/src/orchestrator/block-proving-state.ts +17 -6
- package/src/orchestrator/epoch-proving-state.ts +0 -2
- package/src/orchestrator/orchestrator.ts +111 -62
- package/src/orchestrator/orchestrator_metrics.ts +1 -11
- package/src/prover-agent/memory-proving-queue.ts +12 -7
- package/src/prover-agent/prover-agent.ts +67 -48
- package/src/prover-client/prover-client.ts +5 -12
- package/src/proving_broker/{caching_broker_facade.ts → broker_prover_facade.ts} +62 -85
- package/src/proving_broker/proving_agent.ts +74 -78
- package/src/proving_broker/proving_broker.ts +240 -73
- package/src/proving_broker/proving_broker_database/persisted.ts +2 -8
- package/src/proving_broker/proving_broker_instrumentation.ts +0 -7
- package/src/proving_broker/proving_job_controller.ts +13 -12
- package/src/proving_broker/rpc.ts +1 -1
- package/src/test/mock_prover.ts +7 -3
- package/dest/proving_broker/caching_broker_facade.d.ts +0 -30
- package/dest/proving_broker/caching_broker_facade.d.ts.map +0 -1
- package/dest/proving_broker/caching_broker_facade.js +0 -150
- package/dest/proving_broker/prover_cache/memory.d.ts +0 -9
- package/dest/proving_broker/prover_cache/memory.d.ts.map +0 -1
- package/dest/proving_broker/prover_cache/memory.js +0 -16
- package/src/proving_broker/prover_cache/memory.ts +0 -20
|
@@ -1,284 +1,433 @@
|
|
|
1
|
+
import { __esDecorate, __runInitializers } from "tslib";
|
|
1
2
|
import { ProvingRequestType, } from '@aztec/circuit-types';
|
|
2
|
-
import {
|
|
3
|
+
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
4
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
3
5
|
import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
4
6
|
import { PriorityMemoryQueue } from '@aztec/foundation/queue';
|
|
5
7
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
|
+
import { trackSpan } from '@aztec/telemetry-client';
|
|
6
9
|
import assert from 'assert';
|
|
7
10
|
import { ProvingBrokerInstrumentation } from './proving_broker_instrumentation.js';
|
|
8
11
|
/**
|
|
9
12
|
* A broker that manages proof requests and distributes them to workers based on their priority.
|
|
10
13
|
* It takes a backend that is responsible for storing and retrieving proof requests and results.
|
|
11
14
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
15
|
+
let ProvingBroker = (() => {
|
|
16
|
+
var _a;
|
|
17
|
+
let _instanceExtraInitializers = [];
|
|
18
|
+
let _cleanupPass_decorators;
|
|
19
|
+
return _a = class ProvingBroker {
|
|
20
|
+
constructor(database, client, { jobTimeoutMs = 30000, timeoutIntervalMs = 10000, maxRetries = 3, maxEpochsToKeepResultsFor = 1, maxParallelCleanUps = 20, } = {}, logger = createLogger('prover-client:proving-broker')) {
|
|
21
|
+
this.database = (__runInitializers(this, _instanceExtraInitializers), database);
|
|
22
|
+
this.logger = logger;
|
|
23
|
+
this.queues = {
|
|
24
|
+
[ProvingRequestType.PUBLIC_VM]: new PriorityMemoryQueue(provingJobComparator),
|
|
25
|
+
[ProvingRequestType.TUBE_PROOF]: new PriorityMemoryQueue(provingJobComparator),
|
|
26
|
+
[ProvingRequestType.PRIVATE_KERNEL_EMPTY]: new PriorityMemoryQueue(provingJobComparator),
|
|
27
|
+
[ProvingRequestType.PRIVATE_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
28
|
+
[ProvingRequestType.PUBLIC_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
29
|
+
[ProvingRequestType.MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
30
|
+
[ProvingRequestType.ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
31
|
+
[ProvingRequestType.BLOCK_MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
32
|
+
[ProvingRequestType.BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
33
|
+
[ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
34
|
+
[ProvingRequestType.BASE_PARITY]: new PriorityMemoryQueue(provingJobComparator),
|
|
35
|
+
[ProvingRequestType.ROOT_PARITY]: new PriorityMemoryQueue(provingJobComparator),
|
|
36
|
+
};
|
|
37
|
+
// holds a copy of the database in memory in order to quickly fulfill requests
|
|
38
|
+
// this is fine because this broker is the only one that can modify the database
|
|
39
|
+
this.jobsCache = new Map();
|
|
40
|
+
// as above, but for results
|
|
41
|
+
this.resultsCache = new Map();
|
|
42
|
+
// tracks when each job was enqueued
|
|
43
|
+
this.enqueuedAt = new Map();
|
|
44
|
+
// keeps track of which jobs are currently being processed
|
|
45
|
+
// in the event of a crash this information is lost, but that's ok
|
|
46
|
+
// the next time the broker starts it will recreate jobsCache and still
|
|
47
|
+
// accept results from the workers
|
|
48
|
+
this.inProgress = new Map();
|
|
49
|
+
// keep track of which proving job has been retried
|
|
50
|
+
this.retries = new Map();
|
|
51
|
+
// a map of promises that will be resolved when a job is settled
|
|
52
|
+
this.promises = new Map();
|
|
53
|
+
this.msTimeSource = () => Date.now();
|
|
54
|
+
/**
|
|
55
|
+
* The broker keeps track of the highest epoch its seen.
|
|
56
|
+
* This information is used for garbage collection: once it reaches the next epoch, it can start pruning the database of old state.
|
|
57
|
+
* This clean up pass is only done against _settled_ jobs. This pass will not cancel jobs that are in-progress or in-queue.
|
|
58
|
+
* It is a client responsibility to cancel jobs if they are no longer necessary.
|
|
59
|
+
* Example:
|
|
60
|
+
* proving epoch 11 - the broker will wipe all setlled jobs for epochs 9 and lower
|
|
61
|
+
* finished proving epoch 11 and got first job for epoch 12 -> the broker will wipe all setlled jobs for epochs 10 and lower
|
|
62
|
+
* reorged back to end of epoch 10 -> epoch 11 is skipped and epoch 12 starts -> the broker will wipe all setlled jobs for epochs 10 and lower
|
|
63
|
+
*/
|
|
64
|
+
this.epochHeight = 0;
|
|
65
|
+
this.maxEpochsToKeepResultsFor = 1;
|
|
66
|
+
this.measureQueueDepth = (type) => {
|
|
67
|
+
return this.queues[type].length();
|
|
68
|
+
};
|
|
69
|
+
this.countActiveJobs = (type) => {
|
|
70
|
+
let count = 0;
|
|
71
|
+
for (const { id } of this.inProgress.values()) {
|
|
72
|
+
const job = this.jobsCache.get(id);
|
|
73
|
+
if (job?.type === type) {
|
|
74
|
+
count++;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return count;
|
|
78
|
+
};
|
|
79
|
+
this.tracer = client.getTracer('ProvingBroker');
|
|
80
|
+
this.instrumentation = new ProvingBrokerInstrumentation(client);
|
|
81
|
+
this.cleanupPromise = new RunningPromise(this.cleanupPass.bind(this), this.logger, timeoutIntervalMs);
|
|
82
|
+
this.jobTimeoutMs = jobTimeoutMs;
|
|
83
|
+
this.maxRetries = maxRetries;
|
|
84
|
+
this.maxEpochsToKeepResultsFor = maxEpochsToKeepResultsFor;
|
|
85
|
+
this.maxParallelCleanUps = maxParallelCleanUps;
|
|
86
|
+
}
|
|
87
|
+
start() {
|
|
88
|
+
for (const [item, result] of this.database.allProvingJobs()) {
|
|
89
|
+
this.logger.info(`Restoring proving job id=${item.id} settled=${!!result}`, {
|
|
90
|
+
provingJobId: item.id,
|
|
91
|
+
status: result ? result.status : 'pending',
|
|
92
|
+
});
|
|
93
|
+
this.jobsCache.set(item.id, item);
|
|
94
|
+
this.promises.set(item.id, promiseWithResolvers());
|
|
95
|
+
if (result) {
|
|
96
|
+
this.promises.get(item.id).resolve(result);
|
|
97
|
+
this.resultsCache.set(item.id, result);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
this.enqueueJobInternal(item);
|
|
101
|
+
}
|
|
56
102
|
}
|
|
103
|
+
this.cleanupPromise.start();
|
|
104
|
+
this.instrumentation.monitorQueueDepth(this.measureQueueDepth);
|
|
105
|
+
this.instrumentation.monitorActiveJobs(this.countActiveJobs);
|
|
106
|
+
return Promise.resolve();
|
|
57
107
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
108
|
+
async stop() {
|
|
109
|
+
await this.cleanupPromise.stop();
|
|
110
|
+
}
|
|
111
|
+
async enqueueProvingJob(job) {
|
|
112
|
+
if (this.jobsCache.has(job.id)) {
|
|
113
|
+
const existing = this.jobsCache.get(job.id);
|
|
114
|
+
assert.deepStrictEqual(job, existing, 'Duplicate proving job ID');
|
|
115
|
+
this.logger.debug(`Duplicate proving job id=${job.id} epochNumber=${job.epochNumber}. Ignoring`, {
|
|
116
|
+
provingJobId: job.id,
|
|
117
|
+
});
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (this.isJobStale(job)) {
|
|
121
|
+
this.logger.warn(`Tried enqueueing stale proving job id=${job.id} epochNumber=${job.epochNumber}`, {
|
|
122
|
+
provingJobId: job.id,
|
|
123
|
+
});
|
|
124
|
+
throw new Error(`Epoch too old: job epoch ${job.epochNumber}, current epoch: ${this.epochHeight}`);
|
|
125
|
+
}
|
|
126
|
+
this.logger.info(`New proving job id=${job.id} epochNumber=${job.epochNumber}`, { provingJobId: job.id });
|
|
127
|
+
try {
|
|
128
|
+
// do this first so it acts as a "lock". If this job is enqueued again while we're saving it the if at the top will catch it.
|
|
129
|
+
this.jobsCache.set(job.id, job);
|
|
130
|
+
await this.database.addProvingJob(job);
|
|
131
|
+
this.enqueueJobInternal(job);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
this.logger.error(`Failed to save proving job id=${job.id}: ${err}`, err, { provingJobId: job.id });
|
|
135
|
+
this.jobsCache.delete(job.id);
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
waitForJobToSettle(id) {
|
|
140
|
+
const promiseWithResolvers = this.promises.get(id);
|
|
141
|
+
if (!promiseWithResolvers) {
|
|
142
|
+
this.logger.warn(`Job id=${id} not found`, { provingJobId: id });
|
|
143
|
+
return Promise.resolve({ status: 'rejected', reason: `Job ${id} not found` });
|
|
144
|
+
}
|
|
145
|
+
return promiseWithResolvers.promise;
|
|
146
|
+
}
|
|
147
|
+
async cancelProvingJob(id) {
|
|
148
|
+
if (!this.jobsCache.has(id)) {
|
|
149
|
+
this.logger.warn(`Can't cancel a job that doesn't exist id=${id}`, { provingJobId: id });
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// notify listeners of the cancellation
|
|
153
|
+
if (!this.resultsCache.has(id)) {
|
|
154
|
+
this.logger.info(`Cancelling job id=${id}`, { provingJobId: id });
|
|
155
|
+
await this.reportProvingJobError(id, 'Aborted', false);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async cleanUpProvingJobState(id) {
|
|
159
|
+
if (!this.jobsCache.has(id)) {
|
|
160
|
+
this.logger.warn(`Can't clean up a job that doesn't exist id=${id}`, { provingJobId: id });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (!this.resultsCache.has(id)) {
|
|
164
|
+
this.logger.warn(`Can't cleanup busy proving job: id=${id}`, { provingJobId: id });
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.logger.debug(`Cleaning up state for job id=${id}`, { provingJobId: id });
|
|
168
|
+
await this.database.deleteProvingJobAndResult(id);
|
|
169
|
+
this.jobsCache.delete(id);
|
|
170
|
+
this.promises.delete(id);
|
|
171
|
+
this.resultsCache.delete(id);
|
|
172
|
+
this.inProgress.delete(id);
|
|
173
|
+
this.retries.delete(id);
|
|
174
|
+
}
|
|
175
|
+
getProvingJobStatus(id) {
|
|
176
|
+
const result = this.resultsCache.get(id);
|
|
177
|
+
if (result) {
|
|
178
|
+
return Promise.resolve(result);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// no result yet, check if we know the item
|
|
182
|
+
const item = this.jobsCache.get(id);
|
|
183
|
+
if (!item) {
|
|
184
|
+
this.logger.warn(`Proving job id=${id} not found`, { provingJobId: id });
|
|
185
|
+
return Promise.resolve({ status: 'not-found' });
|
|
186
|
+
}
|
|
187
|
+
return Promise.resolve({ status: this.inProgress.has(id) ? 'in-progress' : 'in-queue' });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// eslint-disable-next-line require-await
|
|
191
|
+
async getProvingJob(filter = { allowList: [] }) {
|
|
192
|
+
const allowedProofs = Array.isArray(filter.allowList) && filter.allowList.length > 0
|
|
193
|
+
? [...filter.allowList]
|
|
194
|
+
: Object.values(ProvingRequestType).filter((x) => typeof x === 'number');
|
|
195
|
+
allowedProofs.sort(proofTypeComparator);
|
|
196
|
+
for (const proofType of allowedProofs) {
|
|
197
|
+
const queue = this.queues[proofType];
|
|
198
|
+
let enqueuedJob;
|
|
199
|
+
// exhaust the queue and make sure we're not sending a job that's already in progress
|
|
200
|
+
// or has already been completed
|
|
201
|
+
// this can happen if the broker crashes and restarts
|
|
202
|
+
// it's possible agents will report progress or results for jobs that are in the queue (after the restart)
|
|
203
|
+
while ((enqueuedJob = queue.getImmediate())) {
|
|
204
|
+
const job = this.jobsCache.get(enqueuedJob.id);
|
|
205
|
+
if (job && !this.inProgress.has(enqueuedJob.id) && !this.resultsCache.has(enqueuedJob.id)) {
|
|
206
|
+
const time = this.msTimeSource();
|
|
207
|
+
this.inProgress.set(job.id, {
|
|
208
|
+
id: job.id,
|
|
209
|
+
startedAt: time,
|
|
210
|
+
lastUpdatedAt: time,
|
|
211
|
+
});
|
|
212
|
+
const enqueuedAt = this.enqueuedAt.get(job.id);
|
|
213
|
+
if (enqueuedAt) {
|
|
214
|
+
this.instrumentation.recordJobWait(job.type, enqueuedAt);
|
|
215
|
+
}
|
|
216
|
+
return { job, time };
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return undefined;
|
|
221
|
+
}
|
|
222
|
+
async reportProvingJobError(id, err, retry = false) {
|
|
223
|
+
const info = this.inProgress.get(id);
|
|
63
224
|
const item = this.jobsCache.get(id);
|
|
225
|
+
const retries = this.retries.get(id) ?? 0;
|
|
64
226
|
if (!item) {
|
|
65
|
-
this.logger.warn(`
|
|
66
|
-
|
|
67
|
-
|
|
227
|
+
this.logger.warn(`Can't set error on unknown proving job id=${id} err=${err}`, { provingJoId: id });
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (!info) {
|
|
231
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`, {
|
|
232
|
+
provingJobId: id,
|
|
233
|
+
});
|
|
68
234
|
}
|
|
69
|
-
|
|
70
|
-
if (msSinceLastUpdate >= this.jobTimeoutMs) {
|
|
71
|
-
this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`);
|
|
235
|
+
else {
|
|
72
236
|
this.inProgress.delete(id);
|
|
237
|
+
}
|
|
238
|
+
if (this.resultsCache.has(id)) {
|
|
239
|
+
this.logger.warn(`Proving job id=${id} is already settled, ignoring err=${err}`, {
|
|
240
|
+
provingJobId: id,
|
|
241
|
+
});
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (retry && retries + 1 < this.maxRetries && !this.isJobStale(item)) {
|
|
245
|
+
this.logger.info(`Retrying proving job id=${id} type=${ProvingRequestType[item.type]} retry=${retries + 1} err=${err}`, {
|
|
246
|
+
provingJobId: id,
|
|
247
|
+
});
|
|
248
|
+
this.retries.set(id, retries + 1);
|
|
73
249
|
this.enqueueJobInternal(item);
|
|
74
|
-
this.instrumentation.
|
|
250
|
+
this.instrumentation.incRetriedJobs(item.type);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
this.logger.info(`Marking proving job as failed id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1} err=${err}`, {
|
|
254
|
+
provingJobId: id,
|
|
255
|
+
});
|
|
256
|
+
// save the result to the cache and notify clients of the job status
|
|
257
|
+
// this should work even if our database breaks because the result is cached in memory
|
|
258
|
+
const result = { status: 'rejected', reason: String(err) };
|
|
259
|
+
this.resultsCache.set(id, result);
|
|
260
|
+
this.promises.get(id).resolve(result);
|
|
261
|
+
this.instrumentation.incRejectedJobs(item.type);
|
|
262
|
+
if (info) {
|
|
263
|
+
const duration = this.msTimeSource() - info.startedAt;
|
|
264
|
+
this.instrumentation.recordJobDuration(item.type, duration);
|
|
265
|
+
}
|
|
266
|
+
try {
|
|
267
|
+
await this.database.setProvingJobError(id, err);
|
|
268
|
+
}
|
|
269
|
+
catch (saveErr) {
|
|
270
|
+
this.logger.error(`Failed to save proving job error status id=${id} jobErr=${err}`, saveErr, {
|
|
271
|
+
provingJobId: id,
|
|
272
|
+
});
|
|
273
|
+
throw saveErr;
|
|
75
274
|
}
|
|
76
275
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
276
|
+
reportProvingJobProgress(id, startedAt, filter) {
|
|
277
|
+
const job = this.jobsCache.get(id);
|
|
278
|
+
if (!job) {
|
|
279
|
+
this.logger.warn(`Proving job id=${id} does not exist`, { provingJobId: id });
|
|
280
|
+
return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
|
|
281
|
+
}
|
|
282
|
+
if (this.resultsCache.has(id)) {
|
|
283
|
+
this.logger.warn(`Proving job id=${id} has already been completed`, { provingJobId: id });
|
|
284
|
+
return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
|
|
285
|
+
}
|
|
286
|
+
const metadata = this.inProgress.get(id);
|
|
287
|
+
const now = this.msTimeSource();
|
|
288
|
+
if (!metadata) {
|
|
289
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} not found in the in-progress cache, adding it`, { provingJobId: id });
|
|
290
|
+
// the queue will still contain the item at this point!
|
|
291
|
+
// we need to be careful when popping off the queue to make sure we're not sending
|
|
292
|
+
// a job that's already in progress
|
|
293
|
+
this.inProgress.set(id, {
|
|
294
|
+
id,
|
|
295
|
+
startedAt,
|
|
296
|
+
lastUpdatedAt: this.msTimeSource(),
|
|
297
|
+
});
|
|
298
|
+
return Promise.resolve(undefined);
|
|
299
|
+
}
|
|
300
|
+
else if (startedAt <= metadata.startedAt) {
|
|
301
|
+
if (startedAt < metadata.startedAt) {
|
|
302
|
+
this.logger.info(`Proving job id=${id} type=${ProvingRequestType[job.type]} startedAt=${startedAt} older agent has taken job`, { provingJobId: id });
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} heartbeat`, { provingJobId: id });
|
|
306
|
+
}
|
|
307
|
+
metadata.startedAt = startedAt;
|
|
308
|
+
metadata.lastUpdatedAt = now;
|
|
309
|
+
return Promise.resolve(undefined);
|
|
310
|
+
}
|
|
311
|
+
else if (filter) {
|
|
312
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} already being worked on by another agent. Sending new one`, { provingJobId: id });
|
|
313
|
+
return this.getProvingJob(filter);
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
return Promise.resolve(undefined);
|
|
317
|
+
}
|
|
91
318
|
}
|
|
92
|
-
|
|
93
|
-
this.
|
|
94
|
-
this.
|
|
319
|
+
async reportProvingJobSuccess(id, value) {
|
|
320
|
+
const info = this.inProgress.get(id);
|
|
321
|
+
const item = this.jobsCache.get(id);
|
|
322
|
+
const retries = this.retries.get(id) ?? 0;
|
|
323
|
+
if (!item) {
|
|
324
|
+
this.logger.warn(`Proving job id=${id} not found`, { provingJobId: id });
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (!info) {
|
|
328
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`, {
|
|
329
|
+
provingJobId: id,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
this.inProgress.delete(id);
|
|
334
|
+
}
|
|
335
|
+
if (this.resultsCache.has(id)) {
|
|
336
|
+
this.logger.warn(`Proving job id=${id} already settled, ignoring result`, { provingJobId: id });
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
this.logger.info(`Proving job complete id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1}`, { provingJobId: id });
|
|
340
|
+
// save result to our local cache and notify clients
|
|
341
|
+
// if save to database fails, that's ok because we have the result in memory
|
|
342
|
+
// if the broker crashes and needs the result again, we're covered because we can just recompute it
|
|
343
|
+
const result = { status: 'fulfilled', value };
|
|
344
|
+
this.resultsCache.set(id, result);
|
|
345
|
+
this.promises.get(id).resolve(result);
|
|
346
|
+
this.instrumentation.incResolvedJobs(item.type);
|
|
347
|
+
if (info) {
|
|
348
|
+
const duration = this.msTimeSource() - info.startedAt;
|
|
349
|
+
this.instrumentation.recordJobDuration(item.type, duration);
|
|
350
|
+
}
|
|
351
|
+
try {
|
|
352
|
+
await this.database.setProvingJobResult(id, value);
|
|
353
|
+
}
|
|
354
|
+
catch (saveErr) {
|
|
355
|
+
this.logger.error(`Failed to save proving job result id=${id}`, saveErr, {
|
|
356
|
+
provingJobId: id,
|
|
357
|
+
});
|
|
358
|
+
throw saveErr;
|
|
359
|
+
}
|
|
95
360
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.instrumentation.monitorActiveJobs(this.countActiveJobs);
|
|
100
|
-
return Promise.resolve();
|
|
101
|
-
}
|
|
102
|
-
stop() {
|
|
103
|
-
return this.timeoutPromise.stop();
|
|
104
|
-
}
|
|
105
|
-
async enqueueProvingJob(job) {
|
|
106
|
-
if (this.jobsCache.has(job.id)) {
|
|
107
|
-
const existing = this.jobsCache.get(job.id);
|
|
108
|
-
assert.deepStrictEqual(job, existing, 'Duplicate proving job ID');
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
await this.database.addProvingJob(job);
|
|
112
|
-
this.jobsCache.set(job.id, job);
|
|
113
|
-
this.enqueueJobInternal(job);
|
|
114
|
-
}
|
|
115
|
-
waitForJobToSettle(id) {
|
|
116
|
-
const promiseWithResolvers = this.promises.get(id);
|
|
117
|
-
if (!promiseWithResolvers) {
|
|
118
|
-
return Promise.resolve({ status: 'rejected', reason: `Job ${id} not found` });
|
|
119
|
-
}
|
|
120
|
-
return promiseWithResolvers.promise;
|
|
121
|
-
}
|
|
122
|
-
async removeAndCancelProvingJob(id) {
|
|
123
|
-
this.logger.info(`Cancelling job id=${id}`);
|
|
124
|
-
await this.database.deleteProvingJobAndResult(id);
|
|
125
|
-
// notify listeners of the cancellation
|
|
126
|
-
if (!this.resultsCache.has(id)) {
|
|
127
|
-
this.promises.get(id)?.resolve({ status: 'rejected', reason: 'Aborted' });
|
|
128
|
-
}
|
|
129
|
-
this.jobsCache.delete(id);
|
|
130
|
-
this.promises.delete(id);
|
|
131
|
-
this.resultsCache.delete(id);
|
|
132
|
-
this.inProgress.delete(id);
|
|
133
|
-
this.retries.delete(id);
|
|
134
|
-
}
|
|
135
|
-
getProvingJobStatus(id) {
|
|
136
|
-
const result = this.resultsCache.get(id);
|
|
137
|
-
if (result) {
|
|
138
|
-
return Promise.resolve(result);
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
// no result yet, check if we know the item
|
|
142
|
-
const item = this.jobsCache.get(id);
|
|
143
|
-
if (!item) {
|
|
144
|
-
this.logger.warn(`Proving job id=${id} not found`);
|
|
145
|
-
return Promise.resolve({ status: 'not-found' });
|
|
361
|
+
async cleanupPass() {
|
|
362
|
+
await this.cleanupStaleJobs();
|
|
363
|
+
await this.reEnqueueExpiredJobs();
|
|
146
364
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// this can happen if the broker crashes and restarts
|
|
162
|
-
// it's possible agents will report progress or results for jobs that are in the queue (after the restart)
|
|
163
|
-
while ((job = queue.getImmediate())) {
|
|
164
|
-
if (!this.inProgress.has(job.id) && !this.resultsCache.has(job.id)) {
|
|
165
|
-
const time = this.timeSource();
|
|
166
|
-
this.inProgress.set(job.id, {
|
|
167
|
-
id: job.id,
|
|
168
|
-
startedAt: time,
|
|
169
|
-
lastUpdatedAt: time,
|
|
365
|
+
async cleanupStaleJobs() {
|
|
366
|
+
const jobIds = Array.from(this.jobsCache.keys());
|
|
367
|
+
const jobsToClean = [];
|
|
368
|
+
for (const id of jobIds) {
|
|
369
|
+
const job = this.jobsCache.get(id);
|
|
370
|
+
const isComplete = this.resultsCache.has(id);
|
|
371
|
+
if (isComplete && this.isJobStale(job)) {
|
|
372
|
+
jobsToClean.push(id);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (jobsToClean.length > 0) {
|
|
376
|
+
this.logger.info(`Cleaning up jobs=${jobsToClean.length}`);
|
|
377
|
+
await asyncPool(this.maxParallelCleanUps, jobsToClean, async (jobId) => {
|
|
378
|
+
await this.cleanUpProvingJobState(jobId);
|
|
170
379
|
});
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
async reEnqueueExpiredJobs() {
|
|
383
|
+
const inProgressEntries = Array.from(this.inProgress.entries());
|
|
384
|
+
for (const [id, metadata] of inProgressEntries) {
|
|
385
|
+
const item = this.jobsCache.get(id);
|
|
386
|
+
if (!item) {
|
|
387
|
+
this.logger.warn(`Proving job id=${id} not found. Removing it from the queue.`, { provingJobId: id });
|
|
388
|
+
this.inProgress.delete(id);
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
const now = this.msTimeSource();
|
|
392
|
+
const msSinceLastUpdate = now - metadata.lastUpdatedAt;
|
|
393
|
+
if (msSinceLastUpdate >= this.jobTimeoutMs) {
|
|
394
|
+
if (this.isJobStale(item)) {
|
|
395
|
+
// the job has timed out and it's also old, just cancel and move on
|
|
396
|
+
await this.cancelProvingJob(item.id);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`, { provingJobId: id });
|
|
400
|
+
this.inProgress.delete(id);
|
|
401
|
+
this.enqueueJobInternal(item);
|
|
402
|
+
this.instrumentation.incTimedOutJobs(item.type);
|
|
403
|
+
}
|
|
174
404
|
}
|
|
175
|
-
return { job, time };
|
|
176
405
|
}
|
|
177
406
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
if (!info) {
|
|
190
|
-
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
this.inProgress.delete(id);
|
|
194
|
-
}
|
|
195
|
-
if (retry && retries + 1 < this.maxRetries) {
|
|
196
|
-
this.logger.info(`Retrying proving job id=${id} type=${ProvingRequestType[item.type]} retry=${retries + 1}`);
|
|
197
|
-
this.retries.set(id, retries + 1);
|
|
198
|
-
this.enqueueJobInternal(item);
|
|
199
|
-
this.instrumentation.incRetriedJobs(item.type);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
this.logger.debug(`Marking proving job id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1} as failed`);
|
|
203
|
-
await this.database.setProvingJobError(id, err);
|
|
204
|
-
const result = { status: 'rejected', reason: String(err) };
|
|
205
|
-
this.resultsCache.set(id, result);
|
|
206
|
-
this.promises.get(id).resolve(result);
|
|
207
|
-
this.instrumentation.incRejectedJobs(item.type);
|
|
208
|
-
if (info) {
|
|
209
|
-
const duration = this.timeSource() - info.startedAt;
|
|
210
|
-
this.instrumentation.recordJobDuration(item.type, duration * 1000);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
reportProvingJobProgress(id, startedAt, filter) {
|
|
214
|
-
const job = this.jobsCache.get(id);
|
|
215
|
-
if (!job) {
|
|
216
|
-
this.logger.warn(`Proving job id=${id} does not exist`);
|
|
217
|
-
return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
|
|
218
|
-
}
|
|
219
|
-
const metadata = this.inProgress.get(id);
|
|
220
|
-
const now = this.timeSource();
|
|
221
|
-
if (!metadata) {
|
|
222
|
-
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} not found in the in-progress cache, adding it`);
|
|
223
|
-
// the queue will still contain the item at this point!
|
|
224
|
-
// we need to be careful when popping off the queue to make sure we're not sending
|
|
225
|
-
// a job that's already in progress
|
|
226
|
-
this.inProgress.set(id, {
|
|
227
|
-
id,
|
|
228
|
-
startedAt,
|
|
229
|
-
lastUpdatedAt: this.timeSource(),
|
|
230
|
-
});
|
|
231
|
-
return Promise.resolve(undefined);
|
|
232
|
-
}
|
|
233
|
-
else if (startedAt <= metadata.startedAt) {
|
|
234
|
-
if (startedAt < metadata.startedAt) {
|
|
235
|
-
this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} startedAt=${startedAt} older agent has taken job`);
|
|
407
|
+
enqueueJobInternal(job) {
|
|
408
|
+
if (!this.promises.has(job.id)) {
|
|
409
|
+
this.promises.set(job.id, promiseWithResolvers());
|
|
410
|
+
}
|
|
411
|
+
this.queues[job.type].put({
|
|
412
|
+
epochNumber: job.epochNumber,
|
|
413
|
+
id: job.id,
|
|
414
|
+
});
|
|
415
|
+
this.enqueuedAt.set(job.id, new Timer());
|
|
416
|
+
this.epochHeight = Math.max(this.epochHeight, job.epochNumber);
|
|
236
417
|
}
|
|
237
|
-
|
|
238
|
-
|
|
418
|
+
isJobStale(job) {
|
|
419
|
+
return job.epochNumber < this.epochHeight - this.maxEpochsToKeepResultsFor;
|
|
239
420
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
async reportProvingJobSuccess(id, value) {
|
|
253
|
-
const info = this.inProgress.get(id);
|
|
254
|
-
const item = this.jobsCache.get(id);
|
|
255
|
-
const retries = this.retries.get(id) ?? 0;
|
|
256
|
-
if (!item) {
|
|
257
|
-
this.logger.warn(`Proving job id=${id} not found`);
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
if (!info) {
|
|
261
|
-
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
this.inProgress.delete(id);
|
|
265
|
-
}
|
|
266
|
-
this.logger.debug(`Proving job complete id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1}`);
|
|
267
|
-
await this.database.setProvingJobResult(id, value);
|
|
268
|
-
const result = { status: 'fulfilled', value };
|
|
269
|
-
this.resultsCache.set(id, result);
|
|
270
|
-
this.promises.get(id).resolve(result);
|
|
271
|
-
this.instrumentation.incResolvedJobs(item.type);
|
|
272
|
-
}
|
|
273
|
-
enqueueJobInternal(job) {
|
|
274
|
-
if (!this.promises.has(job.id)) {
|
|
275
|
-
this.promises.set(job.id, promiseWithResolvers());
|
|
276
|
-
}
|
|
277
|
-
this.queues[job.type].put(job);
|
|
278
|
-
this.enqueuedAt.set(job.id, new Timer());
|
|
279
|
-
this.logger.debug(`Enqueued new proving job id=${job.id}`);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
421
|
+
},
|
|
422
|
+
(() => {
|
|
423
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
424
|
+
_cleanupPass_decorators = [trackSpan('ProvingBroker.cleanupPass')];
|
|
425
|
+
__esDecorate(_a, null, _cleanupPass_decorators, { kind: "method", name: "cleanupPass", static: false, private: false, access: { has: obj => "cleanupPass" in obj, get: obj => obj.cleanupPass }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
426
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
427
|
+
})(),
|
|
428
|
+
_a;
|
|
429
|
+
})();
|
|
430
|
+
export { ProvingBroker };
|
|
282
431
|
/**
|
|
283
432
|
* Compares two proving jobs and selects which one's more important
|
|
284
433
|
* @param a - A proving job
|
|
@@ -286,12 +435,10 @@ export class ProvingBroker {
|
|
|
286
435
|
* @returns A number indicating the relative priority of the two proving jobs
|
|
287
436
|
*/
|
|
288
437
|
function provingJobComparator(a, b) {
|
|
289
|
-
|
|
290
|
-
const bBlockNumber = b.blockNumber ?? 0;
|
|
291
|
-
if (aBlockNumber < bBlockNumber) {
|
|
438
|
+
if (a.epochNumber < b.epochNumber) {
|
|
292
439
|
return -1;
|
|
293
440
|
}
|
|
294
|
-
else if (
|
|
441
|
+
else if (a.epochNumber > b.epochNumber) {
|
|
295
442
|
return 1;
|
|
296
443
|
}
|
|
297
444
|
else {
|
|
@@ -349,4 +496,4 @@ const PROOF_TYPES_IN_PRIORITY_ORDER = [
|
|
|
349
496
|
ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP,
|
|
350
497
|
ProvingRequestType.PRIVATE_KERNEL_EMPTY,
|
|
351
498
|
];
|
|
352
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmluZ19icm9rZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdmluZ19icm9rZXIvcHJvdmluZ19icm9rZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQVNMLGtCQUFrQixHQUNuQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBNkIsY0FBYyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDNUcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBR2hELE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUc1QixPQUFPLEVBQXdCLDRCQUE0QixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFjekc7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUErQ3hCLFlBQ1UsUUFBK0IsRUFDdkMsTUFBdUIsRUFDdkIsRUFBRSxZQUFZLEdBQUcsS0FBTSxFQUFFLGlCQUFpQixHQUFHLEtBQU0sRUFBRSxVQUFVLEdBQUcsQ0FBQyxLQUErQixFQUFFLEVBQzVGLFNBQVMsaUJBQWlCLENBQUMsb0NBQW9DLENBQUM7UUFIaEUsYUFBUSxHQUFSLFFBQVEsQ0FBdUI7UUFHL0IsV0FBTSxHQUFOLE1BQU0sQ0FBMEQ7UUFsRGxFLFdBQU0sR0FBa0I7WUFDOUIsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLG1CQUFtQixDQUFhLG9CQUFvQixDQUFDO1lBQ3pGLENBQUMsa0JBQWtCLENBQUMsVUFBVSxDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBYSxvQkFBb0IsQ0FBQztZQUMxRixDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBYSxvQkFBb0IsQ0FBQztZ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
|
|
499
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmluZ19icm9rZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdmluZ19icm9rZXIvcHJvdmluZ19icm9rZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFTTCxrQkFBa0IsR0FDbkIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sRUFBNkIsY0FBYyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDNUcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hELE9BQU8sRUFBcUQsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFdkcsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRzVCLE9BQU8sRUFBd0IsNEJBQTRCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQWtCekc7OztHQUdHO0lBQ1UsYUFBYTs7OztzQkFBYixhQUFhO1lBK0R4QixZQUNVLFFBQStCLEVBQ3ZDLE1BQXVCLEVBQ3ZCLEVBQ0UsWUFBWSxHQUFHLEtBQU0sRUFDckIsaUJBQWlCLEdBQUcsS0FBTSxFQUMxQixVQUFVLEdBQUcsQ0FBQyxFQUNkLHlCQUF5QixHQUFHLENBQUMsRUFDN0IsbUJBQW1CLEdBQUcsRUFBRSxNQUNJLEVBQUUsRUFDeEIsU0FBUyxZQUFZLENBQUMsOEJBQThCLENBQUM7Z0JBVHJELGFBQVEsSUFoRVAsbURBQWEsRUFnRWQsUUFBUSxFQUF1QjtnQkFTL0IsV0FBTSxHQUFOLE1BQU0sQ0FBK0M7Z0JBeEV2RCxXQUFNLEdBQWtCO29CQUM5QixDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksbUJBQW1CLENB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
|