@aztec/prover-client 0.62.0 → 0.63.1
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/mocks/fixtures.d.ts +2 -4
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +8 -15
- package/dest/mocks/test_context.d.ts +3 -2
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +16 -15
- package/dest/orchestrator/block-building-helpers.d.ts +5 -13
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +28 -16
- package/dest/orchestrator/orchestrator.d.ts +3 -2
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +23 -22
- package/dest/orchestrator/tx-proving-state.d.ts +3 -3
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +31 -22
- package/dest/prover-agent/memory-proving-queue.d.ts +8 -9
- package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
- package/dest/prover-agent/memory-proving-queue.js +6 -9
- package/dest/prover-agent/prover-agent.d.ts +7 -6
- package/dest/prover-agent/prover-agent.d.ts.map +1 -1
- package/dest/prover-agent/prover-agent.js +18 -10
- package/dest/prover-agent/rpc.d.ts +4 -5
- package/dest/prover-agent/rpc.d.ts.map +1 -1
- package/dest/prover-agent/rpc.js +9 -72
- package/dest/proving_broker/proving_broker.d.ts +45 -0
- package/dest/proving_broker/proving_broker.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker.js +298 -0
- package/dest/proving_broker/proving_broker_interface.d.ts +61 -0
- package/dest/proving_broker/proving_broker_interface.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker_interface.js +2 -0
- package/dest/proving_broker/proving_job_database/memory.d.ts +14 -0
- package/dest/proving_broker/proving_job_database/memory.d.ts.map +1 -0
- package/dest/proving_broker/proving_job_database/memory.js +35 -0
- package/dest/proving_broker/proving_job_database/persisted.d.ts +15 -0
- package/dest/proving_broker/proving_job_database/persisted.d.ts.map +1 -0
- package/dest/proving_broker/proving_job_database/persisted.js +34 -0
- package/dest/proving_broker/proving_job_database.d.ts +35 -0
- package/dest/proving_broker/proving_job_database.d.ts.map +1 -0
- package/dest/proving_broker/proving_job_database.js +2 -0
- package/dest/test/mock_prover.d.ts +5 -6
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +5 -8
- package/dest/tx-prover/tx-prover.js +2 -2
- package/package.json +13 -12
- package/src/mocks/fixtures.ts +12 -36
- package/src/mocks/test_context.ts +21 -32
- package/src/orchestrator/block-building-helpers.ts +35 -18
- package/src/orchestrator/orchestrator.ts +41 -27
- package/src/orchestrator/tx-proving-state.ts +45 -32
- package/src/prover-agent/memory-proving-queue.ts +15 -24
- package/src/prover-agent/prover-agent.ts +29 -16
- package/src/prover-agent/rpc.ts +9 -120
- package/src/proving_broker/proving_broker.ts +372 -0
- package/src/proving_broker/proving_broker_interface.ts +74 -0
- package/src/proving_broker/proving_job_database/memory.ts +43 -0
- package/src/proving_broker/proving_job_database/persisted.ts +44 -0
- package/src/proving_broker/proving_job_database.ts +44 -0
- package/src/test/mock_prover.ts +17 -15
- package/src/tx-prover/tx-prover.ts +1 -1
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { ProvingRequestType, } from '@aztec/circuit-types';
|
|
2
|
+
import { createDebugLogger } from '@aztec/foundation/log';
|
|
3
|
+
import { RunningPromise } from '@aztec/foundation/promise';
|
|
4
|
+
import { PriorityMemoryQueue } from '@aztec/foundation/queue';
|
|
5
|
+
import assert from 'assert';
|
|
6
|
+
/**
|
|
7
|
+
* A broker that manages proof requests and distributes them to workers based on their priority.
|
|
8
|
+
* It takes a backend that is responsible for storing and retrieving proof requests and results.
|
|
9
|
+
*/
|
|
10
|
+
export class ProvingBroker {
|
|
11
|
+
constructor(database, { jobTimeoutSec = 30, timeoutIntervalSec = 10, maxRetries = 3 } = {}, logger = createDebugLogger('aztec:prover-client:proof-request-broker')) {
|
|
12
|
+
this.database = database;
|
|
13
|
+
this.logger = logger;
|
|
14
|
+
this.queues = {
|
|
15
|
+
[ProvingRequestType.PUBLIC_VM]: new PriorityMemoryQueue(provingJobComparator),
|
|
16
|
+
[ProvingRequestType.TUBE_PROOF]: new PriorityMemoryQueue(provingJobComparator),
|
|
17
|
+
[ProvingRequestType.PRIVATE_KERNEL_EMPTY]: new PriorityMemoryQueue(provingJobComparator),
|
|
18
|
+
[ProvingRequestType.PRIVATE_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
19
|
+
[ProvingRequestType.PUBLIC_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
20
|
+
[ProvingRequestType.MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
21
|
+
[ProvingRequestType.ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
22
|
+
[ProvingRequestType.BLOCK_MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
23
|
+
[ProvingRequestType.BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
24
|
+
[ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
|
|
25
|
+
[ProvingRequestType.BASE_PARITY]: new PriorityMemoryQueue(provingJobComparator),
|
|
26
|
+
[ProvingRequestType.ROOT_PARITY]: new PriorityMemoryQueue(provingJobComparator),
|
|
27
|
+
};
|
|
28
|
+
// holds a copy of the database in memory in order to quickly fulfill requests
|
|
29
|
+
// this is fine because this broker is the only one that can modify the database
|
|
30
|
+
this.jobsCache = new Map();
|
|
31
|
+
// as above, but for results
|
|
32
|
+
this.resultsCache = new Map();
|
|
33
|
+
// keeps track of which jobs are currently being processed
|
|
34
|
+
// in the event of a crash this information is lost, but that's ok
|
|
35
|
+
// the next time the broker starts it will recreate jobsCache and still
|
|
36
|
+
// accept results from the workers
|
|
37
|
+
this.inProgress = new Map();
|
|
38
|
+
// keep track of which proving job has been retried
|
|
39
|
+
this.retries = new Map();
|
|
40
|
+
this.timeSource = () => Math.floor(Date.now() / 1000);
|
|
41
|
+
this.timeoutCheck = () => {
|
|
42
|
+
const inProgressEntries = Array.from(this.inProgress.entries());
|
|
43
|
+
for (const [id, metadata] of inProgressEntries) {
|
|
44
|
+
const item = this.jobsCache.get(id);
|
|
45
|
+
if (!item) {
|
|
46
|
+
this.logger.warn(`Proving job id=${id} not found. Removing it from the queue.`);
|
|
47
|
+
this.inProgress.delete(id);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const secondsSinceLastUpdate = this.timeSource() - metadata.lastUpdatedAt;
|
|
51
|
+
if (secondsSinceLastUpdate >= this.jobTimeoutSec) {
|
|
52
|
+
this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`);
|
|
53
|
+
this.inProgress.delete(id);
|
|
54
|
+
this.enqueueJobInternal(item);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
this.timeoutPromise = new RunningPromise(this.timeoutCheck, timeoutIntervalSec * 1000);
|
|
59
|
+
this.jobTimeoutSec = jobTimeoutSec;
|
|
60
|
+
this.maxRetries = maxRetries;
|
|
61
|
+
}
|
|
62
|
+
// eslint-disable-next-line require-await
|
|
63
|
+
async start() {
|
|
64
|
+
for (const [item, result] of this.database.allProvingJobs()) {
|
|
65
|
+
this.logger.info(`Restoring proving job id=${item.id} settled=${!!result}`);
|
|
66
|
+
this.jobsCache.set(item.id, item);
|
|
67
|
+
if (result) {
|
|
68
|
+
this.resultsCache.set(item.id, result);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.logger.debug(`Re-enqueuing proving job id=${item.id}`);
|
|
72
|
+
this.enqueueJobInternal(item);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this.timeoutPromise.start();
|
|
76
|
+
}
|
|
77
|
+
stop() {
|
|
78
|
+
return this.timeoutPromise.stop();
|
|
79
|
+
}
|
|
80
|
+
async enqueueProvingJob(job) {
|
|
81
|
+
if (this.jobsCache.has(job.id)) {
|
|
82
|
+
const existing = this.jobsCache.get(job.id);
|
|
83
|
+
assert.deepStrictEqual(job, existing, 'Duplicate proving job ID');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
await this.database.addProvingJob(job);
|
|
87
|
+
this.jobsCache.set(job.id, job);
|
|
88
|
+
this.enqueueJobInternal(job);
|
|
89
|
+
}
|
|
90
|
+
async removeAndCancelProvingJob(id) {
|
|
91
|
+
this.logger.info(`Cancelling job id=${id}`);
|
|
92
|
+
await this.database.deleteProvingJobAndResult(id);
|
|
93
|
+
this.jobsCache.delete(id);
|
|
94
|
+
this.resultsCache.delete(id);
|
|
95
|
+
this.inProgress.delete(id);
|
|
96
|
+
this.retries.delete(id);
|
|
97
|
+
}
|
|
98
|
+
// eslint-disable-next-line require-await
|
|
99
|
+
async getProvingJobStatus(id) {
|
|
100
|
+
const result = this.resultsCache.get(id);
|
|
101
|
+
if (!result) {
|
|
102
|
+
// no result yet, check if we know the item
|
|
103
|
+
const item = this.jobsCache.get(id);
|
|
104
|
+
if (!item) {
|
|
105
|
+
this.logger.warn(`Proving job id=${id} not found`);
|
|
106
|
+
return Promise.resolve({ status: 'not-found' });
|
|
107
|
+
}
|
|
108
|
+
return Promise.resolve({ status: this.inProgress.has(id) ? 'in-progress' : 'in-queue' });
|
|
109
|
+
}
|
|
110
|
+
else if ('value' in result) {
|
|
111
|
+
return Promise.resolve({ status: 'resolved', value: result.value });
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
return Promise.resolve({ status: 'rejected', error: result.error });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// eslint-disable-next-line require-await
|
|
118
|
+
async getProvingJob(filter = {}) {
|
|
119
|
+
const allowedProofs = filter.allowList
|
|
120
|
+
? [...filter.allowList]
|
|
121
|
+
: Object.values(ProvingRequestType).filter((x) => typeof x === 'number');
|
|
122
|
+
allowedProofs.sort(proofTypeComparator);
|
|
123
|
+
for (const proofType of allowedProofs) {
|
|
124
|
+
const queue = this.queues[proofType];
|
|
125
|
+
let job;
|
|
126
|
+
// exhaust the queue and make sure we're not sending a job that's already in progress
|
|
127
|
+
// or has already been completed
|
|
128
|
+
// this can happen if the broker crashes and restarts
|
|
129
|
+
// it's possible agents will report progress or results for jobs that are no longer in the queue
|
|
130
|
+
while ((job = queue.getImmediate())) {
|
|
131
|
+
if (!this.inProgress.has(job.id) && !this.resultsCache.has(job.id)) {
|
|
132
|
+
const time = this.timeSource();
|
|
133
|
+
this.inProgress.set(job.id, {
|
|
134
|
+
id: job.id,
|
|
135
|
+
startedAt: time,
|
|
136
|
+
lastUpdatedAt: time,
|
|
137
|
+
});
|
|
138
|
+
return { job, time };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
async reportProvingJobError(id, err, retry = false) {
|
|
145
|
+
const info = this.inProgress.get(id);
|
|
146
|
+
const item = this.jobsCache.get(id);
|
|
147
|
+
const retries = this.retries.get(id) ?? 0;
|
|
148
|
+
if (!item) {
|
|
149
|
+
this.logger.warn(`Proving job id=${id} not found`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (!info) {
|
|
153
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
this.inProgress.delete(id);
|
|
157
|
+
}
|
|
158
|
+
if (retry && retries + 1 < this.maxRetries) {
|
|
159
|
+
this.logger.info(`Retrying proving job id=${id} type=${ProvingRequestType[item.type]} retry=${retries + 1}`);
|
|
160
|
+
this.retries.set(id, retries + 1);
|
|
161
|
+
this.enqueueJobInternal(item);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.logger.debug(`Marking proving job id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1} as failed`);
|
|
165
|
+
await this.database.setProvingJobError(id, err);
|
|
166
|
+
this.resultsCache.set(id, { error: String(err) });
|
|
167
|
+
}
|
|
168
|
+
reportProvingJobProgress(id, startedAt, filter) {
|
|
169
|
+
const job = this.jobsCache.get(id);
|
|
170
|
+
if (!job) {
|
|
171
|
+
this.logger.warn(`Proving job id=${id} does not exist`);
|
|
172
|
+
return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
|
|
173
|
+
}
|
|
174
|
+
const metadata = this.inProgress.get(id);
|
|
175
|
+
const now = this.timeSource();
|
|
176
|
+
if (!metadata) {
|
|
177
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} not found in the in-progress cache, adding it`);
|
|
178
|
+
// the queue will still contain the item at this point!
|
|
179
|
+
// we need to be careful when popping off the queue to make sure we're not sending
|
|
180
|
+
// a job that's already in progress
|
|
181
|
+
this.inProgress.set(id, {
|
|
182
|
+
id,
|
|
183
|
+
startedAt,
|
|
184
|
+
lastUpdatedAt: this.timeSource(),
|
|
185
|
+
});
|
|
186
|
+
return Promise.resolve(undefined);
|
|
187
|
+
}
|
|
188
|
+
else if (startedAt <= metadata.startedAt) {
|
|
189
|
+
if (startedAt < metadata.startedAt) {
|
|
190
|
+
this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} startedAt=${startedAt} older agent has taken job`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} heartbeat`);
|
|
194
|
+
}
|
|
195
|
+
metadata.startedAt = startedAt;
|
|
196
|
+
metadata.lastUpdatedAt = now;
|
|
197
|
+
return Promise.resolve(undefined);
|
|
198
|
+
}
|
|
199
|
+
else if (filter) {
|
|
200
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} already being worked on by another agent. Sending new one`);
|
|
201
|
+
return this.getProvingJob(filter);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
return Promise.resolve(undefined);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async reportProvingJobSuccess(id, value) {
|
|
208
|
+
const info = this.inProgress.get(id);
|
|
209
|
+
const item = this.jobsCache.get(id);
|
|
210
|
+
const retries = this.retries.get(id) ?? 0;
|
|
211
|
+
if (!item) {
|
|
212
|
+
this.logger.warn(`Proving job id=${id} not found`);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (!info) {
|
|
216
|
+
this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.inProgress.delete(id);
|
|
220
|
+
}
|
|
221
|
+
this.logger.debug(`Proving job complete id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1}`);
|
|
222
|
+
await this.database.setProvingJobResult(id, value);
|
|
223
|
+
this.resultsCache.set(id, { value });
|
|
224
|
+
}
|
|
225
|
+
enqueueJobInternal(job) {
|
|
226
|
+
this.queues[job.type].put(job);
|
|
227
|
+
this.logger.debug(`Enqueued new proving job id=${job.id}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Compares two proving jobs and selects which one's more important
|
|
232
|
+
* @param a - A proving job
|
|
233
|
+
* @param b - Another proving job
|
|
234
|
+
* @returns A number indicating the relative priority of the two proving jobs
|
|
235
|
+
*/
|
|
236
|
+
function provingJobComparator(a, b) {
|
|
237
|
+
if (a.blockNumber < b.blockNumber) {
|
|
238
|
+
return -1;
|
|
239
|
+
}
|
|
240
|
+
else if (a.blockNumber > b.blockNumber) {
|
|
241
|
+
return 1;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Compares two proofs and selects which one's more important.
|
|
249
|
+
* If some proofs does not exist in the priority array then it's considered the least important.
|
|
250
|
+
*
|
|
251
|
+
* @param a - A proof type
|
|
252
|
+
* @param b - Another proof type
|
|
253
|
+
* @returns A number indicating the relative priority of the two proof types
|
|
254
|
+
*/
|
|
255
|
+
function proofTypeComparator(a, b) {
|
|
256
|
+
const indexOfA = PROOF_TYPES_IN_PRIORITY_ORDER.indexOf(a);
|
|
257
|
+
const indexOfB = PROOF_TYPES_IN_PRIORITY_ORDER.indexOf(b);
|
|
258
|
+
if (indexOfA === indexOfB) {
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
else if (indexOfA === -1) {
|
|
262
|
+
// a is some new proof that didn't get added to the array
|
|
263
|
+
// b is more important because we know about it
|
|
264
|
+
return 1;
|
|
265
|
+
}
|
|
266
|
+
else if (indexOfB === -1) {
|
|
267
|
+
// the opposite of the previous if branch
|
|
268
|
+
return -1;
|
|
269
|
+
}
|
|
270
|
+
else if (indexOfA < indexOfB) {
|
|
271
|
+
return -1;
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
return 1;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Relative priority of each proof type. Proofs higher up on the list are more important and should be prioritized
|
|
279
|
+
* over proofs lower on the list.
|
|
280
|
+
*
|
|
281
|
+
* The aim is that this will speed up block proving as the closer we get to a block's root proof the more likely it
|
|
282
|
+
* is to get picked up by agents
|
|
283
|
+
*/
|
|
284
|
+
const PROOF_TYPES_IN_PRIORITY_ORDER = [
|
|
285
|
+
ProvingRequestType.BLOCK_ROOT_ROLLUP,
|
|
286
|
+
ProvingRequestType.BLOCK_MERGE_ROLLUP,
|
|
287
|
+
ProvingRequestType.ROOT_ROLLUP,
|
|
288
|
+
ProvingRequestType.MERGE_ROLLUP,
|
|
289
|
+
ProvingRequestType.PUBLIC_BASE_ROLLUP,
|
|
290
|
+
ProvingRequestType.PRIVATE_BASE_ROLLUP,
|
|
291
|
+
ProvingRequestType.PUBLIC_VM,
|
|
292
|
+
ProvingRequestType.TUBE_PROOF,
|
|
293
|
+
ProvingRequestType.ROOT_PARITY,
|
|
294
|
+
ProvingRequestType.BASE_PARITY,
|
|
295
|
+
ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP,
|
|
296
|
+
ProvingRequestType.PRIVATE_KERNEL_EMPTY,
|
|
297
|
+
];
|
|
298
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmluZ19icm9rZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdmluZ19icm9rZXIvcHJvdmluZ19icm9rZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLGtCQUFrQixHQU1uQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUU5RCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFpQjVCOzs7R0FHRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBdUN4QixZQUNVLFFBQTRCLEVBQ3BDLEVBQUUsYUFBYSxHQUFHLEVBQUUsRUFBRSxrQkFBa0IsR0FBRyxFQUFFLEVBQUUsVUFBVSxHQUFHLENBQUMsS0FBK0IsRUFBRSxFQUN0RixTQUFTLGlCQUFpQixDQUFDLDBDQUEwQyxDQUFDO1FBRnRFLGFBQVEsR0FBUixRQUFRLENBQW9CO1FBRTVCLFdBQU0sR0FBTixNQUFNLENBQWdFO1FBekN4RSxXQUFNLEdBQWtCO1lBQzlCLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBZSxvQkFBb0IsQ0FBQztZQUMzRixDQUFDLGtCQUFrQixDQUFDLFVBQVUsQ0FBQyxFQUFFLElBQUksbUJBQW1CLENBQWUsb0JBQW9CLENBQUM7WUFDNUYsQ0FBQyxrQkFBa0IsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLElBQUksbUJBQW1CLENBQWUsb0JBQW9CLENBQUM7WUFFdEcsQ0FBQyxrQkFBa0IsQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLElBQUksbUJBQW1CLENBQWUsb0JBQW9CLENBQUM7WUFDckcsQ0FBQyxrQkFBa0IsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLElBQUksbUJBQW1CLENBQWUsb0JBQW9CLENBQUM7WUFDcEcsQ0FBQyxrQkFBa0IsQ0FBQyxZQUFZLENBQUMsRUFBRSxJQUFJLG1CQUFtQixDQUFlLG9CQUFvQixDQUFDO1lBQzlGLENBQUMsa0JBQWtCLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBZSxvQkFBb0IsQ0FBQztZQUU3RixDQUFDLGtCQUFrQixDQUFDLGtCQUFrQixDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBZSxvQkFBb0IsQ0FBQztZQUNwRyxDQUFDLGtCQUFrQixDQUFDLGlCQUFpQixDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBZSxvQkFBb0IsQ0FBQztZQUNuRyxDQUFDLGtCQUFrQixDQUFDLHVCQUF1QixDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBZSxvQkFBb0IsQ0FBQztZQUV6RyxDQUFDLGtCQUFrQixDQUFDLFdBQVcsQ0FBQyxFQUFFLElBQUksbUJBQW1CLENBQWUsb0JBQW9CLENBQUM7WUFDN0YsQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsRUFBRSxJQUFJLG1CQUFtQixDQUFlLG9CQUFvQixDQUFDO1NBQzlGLENBQUM7UUFFRiw4RUFBOEU7UUFDOUUsZ0ZBQWdGO1FBQ3hFLGNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQztRQUM1RCw0QkFBNEI7UUFDcEIsaUJBQVksR0FBRyxJQUFJLEdBQUcsRUFBc0MsQ0FBQztRQUVyRSwwREFBMEQ7UUFDMUQsa0VBQWtFO1FBQ2xFLHVFQUF1RTtRQUN2RSxrQ0FBa0M7UUFDMUIsZUFBVSxHQUFHLElBQUksR0FBRyxFQUFzQyxDQUFDO1FBRW5FLG1EQUFtRDtRQUMzQyxZQUFPLEdBQUcsSUFBSSxHQUFHLEVBQTBCLENBQUM7UUFHNUMsZUFBVSxHQUFHLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1FBbU5qRCxpQkFBWSxHQUFHLEdBQUcsRUFBRTtZQUMxQixNQUFNLGlCQUFpQixHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ2hFLEtBQUssTUFBTSxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO2dCQUMvQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO29CQUNWLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLHlDQUF5QyxDQUFDLENBQUM7b0JBQ2hGLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUMzQixTQUFTO2dCQUNYLENBQUM7Z0JBRUQsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQztnQkFDMUUsSUFBSSxzQkFBc0IsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7b0JBQ2pELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLDBDQUEwQyxDQUFDLENBQUM7b0JBQ2pGLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUMzQixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ2hDLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQyxDQUFDO1FBM05BLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxjQUFjLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsQ0FBQztRQUN2RixJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztRQUNuQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztJQUMvQixDQUFDO0lBRUQseUNBQXlDO0lBQ2xDLEtBQUssQ0FBQyxLQUFLO1FBQ2hCLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUM7WUFDNUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsNEJBQTRCLElBQUksQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFFNUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNsQyxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDekMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLCtCQUErQixJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDNUQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hDLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU0sSUFBSTtRQUNULE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0lBRU0sS0FBSyxDQUFDLGlCQUFpQixDQUFDLEdBQWlCO1FBQzlDLElBQUksSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7WUFDL0IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQzVDLE1BQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLFFBQVEsRUFBRSwwQkFBMEIsQ0FBQyxDQUFDO1lBQ2xFLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRU0sS0FBSyxDQUFDLHlCQUF5QixDQUFDLEVBQWtCO1FBQ3ZELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzVDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyx5QkFBeUIsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUVsRCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMzQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQseUNBQXlDO0lBQ2xDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxFQUFrQjtRQUNqRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWiwyQ0FBMkM7WUFDM0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFFcEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNWLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUNuRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUNsRCxDQUFDO1lBRUQsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDM0YsQ0FBQzthQUFNLElBQUksT0FBTyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQzdCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3RFLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDdEUsQ0FBQztJQUNILENBQUM7SUFFRCx5Q0FBeUM7SUFDekMsS0FBSyxDQUFDLGFBQWEsQ0FDakIsU0FBOEIsRUFBRTtRQUVoQyxNQUFNLGFBQWEsR0FBeUIsTUFBTSxDQUFDLFNBQVM7WUFDMUQsQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1lBQ3ZCLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUEyQixFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssUUFBUSxDQUFDLENBQUM7UUFDcEcsYUFBYSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBRXhDLEtBQUssTUFBTSxTQUFTLElBQUksYUFBYSxFQUFFLENBQUM7WUFDdEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNyQyxJQUFJLEdBQTZCLENBQUM7WUFDbEMscUZBQXFGO1lBQ3JGLGdDQUFnQztZQUNoQyxxREFBcUQ7WUFDckQsZ0dBQWdHO1lBQ2hHLE9BQU8sQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLFlBQVksRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO29CQUNuRSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7b0JBQy9CLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUU7d0JBQzFCLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFBRTt3QkFDVixTQUFTLEVBQUUsSUFBSTt3QkFDZixhQUFhLEVBQUUsSUFBSTtxQkFDcEIsQ0FBQyxDQUFDO29CQUVILE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLENBQUM7Z0JBQ3ZCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxLQUFLLENBQUMscUJBQXFCLENBQUMsRUFBa0IsRUFBRSxHQUFVLEVBQUUsS0FBSyxHQUFHLEtBQUs7UUFDdkUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNWLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ25ELE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsU0FBUyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUM7UUFDNUcsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBRUQsSUFBSSxLQUFLLElBQUksT0FBTyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDM0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsMkJBQTJCLEVBQUUsU0FBUyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDN0csSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNsQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUIsT0FBTztRQUNULENBQUM7UUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDZiwwQkFBMEIsRUFBRSxTQUFTLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLE9BQU8sR0FBRyxDQUFDLFlBQVksQ0FDNUcsQ0FBQztRQUNGLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELHdCQUF3QixDQUN0QixFQUFrQixFQUNsQixTQUFpQixFQUNqQixNQUE0QjtRQUU1QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNuQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDVCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3hELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN6QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQ2Qsa0JBQWtCLEVBQUUsU0FBUyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGdEQUFnRCxDQUMxRyxDQUFDO1lBQ0YsdURBQXVEO1lBQ3ZELGtGQUFrRjtZQUNsRixtQ0FBbUM7WUFDbkMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFO2dCQUN0QixFQUFFO2dCQUNGLFNBQVM7Z0JBQ1QsYUFBYSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUU7YUFDakMsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7YUFBTSxJQUFJLFNBQVMsSUFBSSxRQUFRLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDM0MsSUFBSSxTQUFTLEdBQUcsUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNuQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDZixrQkFBa0IsRUFBRSxTQUFTLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsY0FBYyxTQUFTLDRCQUE0QixDQUM3RyxDQUFDO1lBQ0osQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixFQUFFLFNBQVMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUMzRixDQUFDO1lBQ0QsUUFBUSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7WUFDL0IsUUFBUSxDQUFDLGFBQWEsR0FBRyxHQUFHLENBQUM7WUFDN0IsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7YUFBTSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUNkLGtCQUFrQixFQUFFLFNBQ2xCLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQzdCLDREQUE0RCxDQUM3RCxDQUFDO1lBQ0YsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLHVCQUF1QixDQUFDLEVBQWtCLEVBQUUsS0FBb0I7UUFDcEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDckMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNWLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLFlBQVksQ0FBQyxDQUFDO1lBQ25ELE9BQU87UUFDVCxDQUFDO1FBRUQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsU0FBUyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLDZCQUE2QixDQUFDLENBQUM7UUFDNUcsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixDQUFDO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ2YsMkJBQTJCLEVBQUUsU0FBUyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixPQUFPLEdBQUcsQ0FBQyxFQUFFLENBQ25HLENBQUM7UUFDRixNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsbUJBQW1CLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ25ELElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQXFCTyxrQkFBa0IsQ0FBQyxHQUFpQjtRQUMxQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzdELENBQUM7Q0FDRjtBQU1EOzs7OztHQUtHO0FBQ0gsU0FBUyxvQkFBb0IsQ0FBQyxDQUFlLEVBQUUsQ0FBZTtJQUM1RCxJQUFJLENBQUMsQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2xDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDWixDQUFDO1NBQU0sSUFBSSxDQUFDLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN6QyxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFTLG1CQUFtQixDQUFDLENBQXFCLEVBQUUsQ0FBcUI7SUFDdkUsTUFBTSxRQUFRLEdBQUcsNkJBQTZCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFELE1BQU0sUUFBUSxHQUFHLDZCQUE2QixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRCxJQUFJLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUMxQixPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7U0FBTSxJQUFJLFFBQVEsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzNCLHlEQUF5RDtRQUN6RCwrQ0FBK0M7UUFDL0MsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDO1NBQU0sSUFBSSxRQUFRLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMzQix5Q0FBeUM7UUFDekMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNaLENBQUM7U0FBTSxJQUFJLFFBQVEsR0FBRyxRQUFRLEVBQUUsQ0FBQztRQUMvQixPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ1osQ0FBQztTQUFNLENBQUM7UUFDTixPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSw2QkFBNkIsR0FBeUI7SUFDMUQsa0JBQWtCLENBQUMsaUJBQWlCO0lBQ3BDLGtCQUFrQixDQUFDLGtCQUFrQjtJQUNyQyxrQkFBa0IsQ0FBQyxXQUFXO0lBQzlCLGtCQUFrQixDQUFDLFlBQVk7SUFDL0Isa0JBQWtCLENBQUMsa0JBQWtCO0lBQ3JDLGtCQUFrQixDQUFDLG1CQUFtQjtJQUN0QyxrQkFBa0IsQ0FBQyxTQUFTO0lBQzVCLGtCQUFrQixDQUFDLFVBQVU7SUFDN0Isa0JBQWtCLENBQUMsV0FBVztJQUM5QixrQkFBa0IsQ0FBQyxXQUFXO0lBQzlCLGtCQUFrQixDQUFDLHVCQUF1QjtJQUMxQyxrQkFBa0IsQ0FBQyxvQkFBb0I7Q0FDeEMsQ0FBQyJ9
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ProvingRequestType, type V2ProofOutput, type V2ProvingJob, type V2ProvingJobId, type V2ProvingJobStatus } from '@aztec/circuit-types';
|
|
2
|
+
/**
|
|
3
|
+
* An interface for the proving orchestrator. The producer uses this to enqueue jobs for agents
|
|
4
|
+
*/
|
|
5
|
+
export interface ProvingJobProducer {
|
|
6
|
+
/**
|
|
7
|
+
* Enqueues a proving job
|
|
8
|
+
* @param job - The job to enqueue
|
|
9
|
+
*/
|
|
10
|
+
enqueueProvingJob(job: V2ProvingJob): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Cancels a proving job and clears all of its
|
|
13
|
+
* @param id - The ID of the job to cancel
|
|
14
|
+
*/
|
|
15
|
+
removeAndCancelProvingJob(id: V2ProvingJobId): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns the current status fof the proving job
|
|
18
|
+
* @param id - The ID of the job to get the status of
|
|
19
|
+
*/
|
|
20
|
+
getProvingJobStatus(id: V2ProvingJobId): Promise<V2ProvingJobStatus>;
|
|
21
|
+
}
|
|
22
|
+
export interface ProvingJobFilter<T extends ProvingRequestType[]> {
|
|
23
|
+
allowList?: T;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* An interface for proving agents to request jobs and report results
|
|
27
|
+
*/
|
|
28
|
+
export interface ProvingJobConsumer {
|
|
29
|
+
/**
|
|
30
|
+
* Gets a proving job to work on
|
|
31
|
+
* @param filter - Optional filter for the type of job to get
|
|
32
|
+
*/
|
|
33
|
+
getProvingJob<T extends ProvingRequestType[]>(filter?: ProvingJobFilter<T>): Promise<{
|
|
34
|
+
job: V2ProvingJob;
|
|
35
|
+
time: number;
|
|
36
|
+
} | undefined>;
|
|
37
|
+
/**
|
|
38
|
+
* Marks a proving job as successful
|
|
39
|
+
* @param id - The ID of the job to report success for
|
|
40
|
+
* @param result - The result of the job
|
|
41
|
+
*/
|
|
42
|
+
reportProvingJobSuccess(id: V2ProvingJobId, result: V2ProofOutput): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Marks a proving job as errored
|
|
45
|
+
* @param id - The ID of the job to report an error for
|
|
46
|
+
* @param err - The error that occurred while processing the job
|
|
47
|
+
* @param retry - Whether to retry the job
|
|
48
|
+
*/
|
|
49
|
+
reportProvingJobError(id: V2ProvingJobId, err: Error, retry?: boolean): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Sends a heartbeat to the broker to indicate that the agent is still working on the given proving job
|
|
52
|
+
* @param id - The ID of the job to report progress for
|
|
53
|
+
* @param startedAt - The unix epoch when the job was started
|
|
54
|
+
* @param filter - Optional filter for the type of job to get
|
|
55
|
+
*/
|
|
56
|
+
reportProvingJobProgress<F extends ProvingRequestType[]>(id: V2ProvingJobId, startedAt: number, filter?: ProvingJobFilter<F>): Promise<{
|
|
57
|
+
job: V2ProvingJob;
|
|
58
|
+
time: number;
|
|
59
|
+
} | undefined>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=proving_broker_interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proving_broker_interface.d.ts","sourceRoot":"","sources":["../../src/proving_broker/proving_broker_interface.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,iBAAiB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD;;;OAGG;IACH,yBAAyB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;;OAGG;IACH,mBAAmB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,kBAAkB,EAAE;IAC9D,SAAS,CAAC,EAAE,CAAC,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,aAAa,CAAC,CAAC,SAAS,kBAAkB,EAAE,EAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC;QAAE,GAAG,EAAE,YAAY,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;IAE5D;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElF;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtF;;;;;OAKG;IACH,wBAAwB,CAAC,CAAC,SAAS,kBAAkB,EAAE,EACrD,EAAE,EAAE,cAAc,EAClB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC;QAAE,GAAG,EAAE,YAAY,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAC;CAC7D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { V2ProofOutput, V2ProvingJob, V2ProvingJobId, V2ProvingJobResult } from '@aztec/circuit-types';
|
|
2
|
+
import { type ProvingJobDatabase } from '../proving_job_database.js';
|
|
3
|
+
export declare class InMemoryDatabase implements ProvingJobDatabase {
|
|
4
|
+
private jobs;
|
|
5
|
+
private results;
|
|
6
|
+
getProvingJob(id: V2ProvingJobId): V2ProvingJob | undefined;
|
|
7
|
+
getProvingJobResult(id: V2ProvingJobId): V2ProvingJobResult | undefined;
|
|
8
|
+
addProvingJob(request: V2ProvingJob): Promise<void>;
|
|
9
|
+
setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise<void>;
|
|
10
|
+
setProvingJobError(id: V2ProvingJobId, error: Error): Promise<void>;
|
|
11
|
+
deleteProvingJobAndResult(id: V2ProvingJobId): Promise<void>;
|
|
12
|
+
allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | undefined]>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/proving_broker/proving_job_database/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE5G,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE,qBAAa,gBAAiB,YAAW,kBAAkB;IACzD,OAAO,CAAC,IAAI,CAA2C;IACvD,OAAO,CAAC,OAAO,CAAiD;IAEhE,aAAa,CAAC,EAAE,EAAE,cAAc,GAAG,YAAY,GAAG,SAAS;IAI3D,mBAAmB,CAAC,EAAE,EAAE,cAAc,GAAG,kBAAkB,GAAG,SAAS;IAIvE,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAK5E,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnE,yBAAyB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,cAAc,IAAI,QAAQ,CAAC,CAAC,YAAY,EAAE,kBAAkB,GAAG,SAAS,CAAC,CAAC;CAK5E"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export class InMemoryDatabase {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.jobs = new Map();
|
|
4
|
+
this.results = new Map();
|
|
5
|
+
}
|
|
6
|
+
getProvingJob(id) {
|
|
7
|
+
return this.jobs.get(id);
|
|
8
|
+
}
|
|
9
|
+
getProvingJobResult(id) {
|
|
10
|
+
return this.results.get(id);
|
|
11
|
+
}
|
|
12
|
+
addProvingJob(request) {
|
|
13
|
+
this.jobs.set(request.id, request);
|
|
14
|
+
return Promise.resolve();
|
|
15
|
+
}
|
|
16
|
+
setProvingJobResult(id, value) {
|
|
17
|
+
this.results.set(id, { value });
|
|
18
|
+
return Promise.resolve();
|
|
19
|
+
}
|
|
20
|
+
setProvingJobError(id, error) {
|
|
21
|
+
this.results.set(id, { error: String(error) });
|
|
22
|
+
return Promise.resolve();
|
|
23
|
+
}
|
|
24
|
+
deleteProvingJobAndResult(id) {
|
|
25
|
+
this.jobs.delete(id);
|
|
26
|
+
this.results.delete(id);
|
|
27
|
+
return Promise.resolve();
|
|
28
|
+
}
|
|
29
|
+
*allProvingJobs() {
|
|
30
|
+
for (const item of this.jobs.values()) {
|
|
31
|
+
yield [item, this.results.get(item.id)];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpbmdfYnJva2VyL3Byb3Zpbmdfam9iX2RhdGFiYXNlL21lbW9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxNQUFNLE9BQU8sZ0JBQWdCO0lBQTdCO1FBQ1UsU0FBSSxHQUFHLElBQUksR0FBRyxFQUFnQyxDQUFDO1FBQy9DLFlBQU8sR0FBRyxJQUFJLEdBQUcsRUFBc0MsQ0FBQztJQW9DbEUsQ0FBQztJQWxDQyxhQUFhLENBQUMsRUFBa0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBRUQsbUJBQW1CLENBQUMsRUFBa0I7UUFDcEMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRUQsYUFBYSxDQUFDLE9BQXFCO1FBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbkMsT0FBTyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVELG1CQUFtQixDQUFDLEVBQWtCLEVBQUUsS0FBb0I7UUFDMUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNoQyxPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsa0JBQWtCLENBQUMsRUFBa0IsRUFBRSxLQUFZO1FBQ2pELElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLE9BQU8sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFRCx5QkFBeUIsQ0FBQyxFQUFrQjtRQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN4QixPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsQ0FBQyxjQUFjO1FBQ2IsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDdEMsTUFBTSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQVUsQ0FBQztRQUNuRCxDQUFDO0lBQ0gsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type V2ProofOutput, V2ProvingJob, type V2ProvingJobId, V2ProvingJobResult } from '@aztec/circuit-types';
|
|
2
|
+
import { type AztecKVStore } from '@aztec/kv-store';
|
|
3
|
+
import { type ProvingJobDatabase } from '../proving_job_database.js';
|
|
4
|
+
export declare class PersistedProvingJobDatabase implements ProvingJobDatabase {
|
|
5
|
+
private store;
|
|
6
|
+
private jobs;
|
|
7
|
+
private jobResults;
|
|
8
|
+
constructor(store: AztecKVStore);
|
|
9
|
+
addProvingJob(job: V2ProvingJob): Promise<void>;
|
|
10
|
+
allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | undefined]>;
|
|
11
|
+
deleteProvingJobAndResult(id: V2ProvingJobId): Promise<void>;
|
|
12
|
+
setProvingJobError(id: V2ProvingJobId, err: Error): Promise<void>;
|
|
13
|
+
setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=persisted.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persisted.d.ts","sourceRoot":"","sources":["../../../src/proving_broker/proving_job_database/persisted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACjH,OAAO,EAAE,KAAK,YAAY,EAAiB,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAErE,qBAAa,2BAA4B,YAAW,kBAAkB;IAIxD,OAAO,CAAC,KAAK;IAHzB,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,UAAU,CAAmC;gBAEjC,KAAK,EAAE,YAAY;IAKjC,aAAa,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,cAAc,IAAI,QAAQ,CAAC,CAAC,YAAY,EAAE,kBAAkB,GAAG,SAAS,CAAC,CAAC;IAS3E,yBAAyB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtD,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjE,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAInF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { V2ProvingJob, V2ProvingJobResult } from '@aztec/circuit-types';
|
|
2
|
+
export class PersistedProvingJobDatabase {
|
|
3
|
+
constructor(store) {
|
|
4
|
+
this.store = store;
|
|
5
|
+
this.jobs = store.openMap('proving_jobs');
|
|
6
|
+
this.jobResults = store.openMap('proving_job_results');
|
|
7
|
+
}
|
|
8
|
+
async addProvingJob(job) {
|
|
9
|
+
await this.jobs.set(job.id, JSON.stringify(job));
|
|
10
|
+
}
|
|
11
|
+
*allProvingJobs() {
|
|
12
|
+
for (const jobStr of this.jobs.values()) {
|
|
13
|
+
const job = V2ProvingJob.parse(JSON.parse(jobStr));
|
|
14
|
+
const resultStr = this.jobResults.get(job.id);
|
|
15
|
+
const result = resultStr ? V2ProvingJobResult.parse(JSON.parse(resultStr)) : undefined;
|
|
16
|
+
yield [job, result];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
deleteProvingJobAndResult(id) {
|
|
20
|
+
return this.store.transaction(() => {
|
|
21
|
+
void this.jobs.delete(id);
|
|
22
|
+
void this.jobResults.delete(id);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
async setProvingJobError(id, err) {
|
|
26
|
+
const res = { error: err.message };
|
|
27
|
+
await this.jobResults.set(id, JSON.stringify(res));
|
|
28
|
+
}
|
|
29
|
+
async setProvingJobResult(id, value) {
|
|
30
|
+
const res = { value };
|
|
31
|
+
await this.jobResults.set(id, JSON.stringify(res));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVyc2lzdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3Byb3ZpbmdfYnJva2VyL3Byb3Zpbmdfam9iX2RhdGFiYXNlL3BlcnNpc3RlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXNCLFlBQVksRUFBdUIsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUtqSCxNQUFNLE9BQU8sMkJBQTJCO0lBSXRDLFlBQW9CLEtBQW1CO1FBQW5CLFVBQUssR0FBTCxLQUFLLENBQWM7UUFDckMsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRCxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQWlCO1FBQ25DLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVELENBQUMsY0FBYztRQUNiLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sR0FBRyxHQUFHLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ25ELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUM5QyxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUN2RixNQUFNLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3RCLENBQUM7SUFDSCxDQUFDO0lBRUQseUJBQXlCLENBQUMsRUFBa0I7UUFDMUMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUU7WUFDakMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUMxQixLQUFLLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxFQUFrQixFQUFFLEdBQVU7UUFDckQsTUFBTSxHQUFHLEdBQXVCLEVBQUUsS0FBSyxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN2RCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxFQUFrQixFQUFFLEtBQW9CO1FBQ2hFLE1BQU0sR0FBRyxHQUF1QixFQUFFLEtBQUssRUFBRSxDQUFDO1FBQzFDLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNyRCxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type V2ProofOutput, type V2ProvingJob, type V2ProvingJobId, type V2ProvingJobResult } from '@aztec/circuit-types';
|
|
2
|
+
/**
|
|
3
|
+
* A database for storing proof requests and their results
|
|
4
|
+
*/
|
|
5
|
+
export interface ProvingJobDatabase {
|
|
6
|
+
/**
|
|
7
|
+
* Saves a proof request so it can be retrieved later
|
|
8
|
+
* @param request - The proof request to save
|
|
9
|
+
*/
|
|
10
|
+
addProvingJob(request: V2ProvingJob): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Removes a proof request from the backend
|
|
13
|
+
* @param id - The ID of the proof request to remove
|
|
14
|
+
*/
|
|
15
|
+
deleteProvingJobAndResult(id: V2ProvingJobId): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns an iterator over all saved proving jobs
|
|
18
|
+
*/
|
|
19
|
+
allProvingJobs(): Iterable<[V2ProvingJob, V2ProvingJobResult | undefined]>;
|
|
20
|
+
/**
|
|
21
|
+
* Saves the result of a proof request
|
|
22
|
+
* @param id - The ID of the proof request to save the result for
|
|
23
|
+
* @param ProvingRequestType - The type of proof that was requested
|
|
24
|
+
* @param value - The result of the proof request
|
|
25
|
+
*/
|
|
26
|
+
setProvingJobResult(id: V2ProvingJobId, value: V2ProofOutput): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Saves an error that occurred while processing a proof request
|
|
29
|
+
* @param id - The ID of the proof request to save the error for
|
|
30
|
+
* @param ProvingRequestType - The type of proof that was requested
|
|
31
|
+
* @param err - The error that occurred while processing the proof request
|
|
32
|
+
*/
|
|
33
|
+
setProvingJobError(id: V2ProvingJobId, err: Error): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=proving_job_database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proving_job_database.d.ts","sourceRoot":"","sources":["../../src/proving_broker/proving_job_database.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAE9B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD;;;OAGG;IACH,yBAAyB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D;;OAEG;IACH,cAAc,IAAI,QAAQ,CAAC,CAAC,YAAY,EAAE,kBAAkB,GAAG,SAAS,CAAC,CAAC,CAAC;IAE3E;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7E;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type ProofAndVerificationKey, type PublicInputsAndRecursiveProof, type ServerCircuitProver } from '@aztec/circuit-types';
|
|
2
|
-
import { type BaseOrMergeRollupPublicInputs, type BlockRootOrBlockMergePublicInputs, type KernelCircuitPublicInputs, type
|
|
2
|
+
import { type BaseOrMergeRollupPublicInputs, type BlockRootOrBlockMergePublicInputs, type KernelCircuitPublicInputs, type RootRollupPublicInputs, TUBE_PROOF_LENGTH } from '@aztec/circuits.js';
|
|
3
3
|
export declare class MockProver implements ServerCircuitProver {
|
|
4
4
|
constructor();
|
|
5
|
-
getAvmProof(): Promise<ProofAndVerificationKey<
|
|
6
|
-
getBaseParityProof(): Promise<import("@aztec/circuits.js").
|
|
7
|
-
getRootParityProof(): Promise<import("@aztec/circuits.js").
|
|
5
|
+
getAvmProof(): Promise<ProofAndVerificationKey<4291>>;
|
|
6
|
+
getBaseParityProof(): Promise<PublicInputsAndRecursiveProof<import("@aztec/circuits.js").ParityPublicInputs, 463>>;
|
|
7
|
+
getRootParityProof(): Promise<PublicInputsAndRecursiveProof<import("@aztec/circuits.js").ParityPublicInputs, 463>>;
|
|
8
8
|
getPrivateBaseRollupProof(): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>>;
|
|
9
9
|
getPublicBaseRollupProof(): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>>;
|
|
10
10
|
getMergeRollupProof(): Promise<PublicInputsAndRecursiveProof<BaseOrMergeRollupPublicInputs>>;
|
|
@@ -12,8 +12,7 @@ export declare class MockProver implements ServerCircuitProver {
|
|
|
12
12
|
getEmptyBlockRootRollupProof(): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>>;
|
|
13
13
|
getBlockRootRollupProof(): Promise<PublicInputsAndRecursiveProof<BlockRootOrBlockMergePublicInputs>>;
|
|
14
14
|
getEmptyPrivateKernelProof(): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>>;
|
|
15
|
-
getEmptyTubeProof(): Promise<PublicInputsAndRecursiveProof<KernelCircuitPublicInputs>>;
|
|
16
15
|
getRootRollupProof(): Promise<PublicInputsAndRecursiveProof<RootRollupPublicInputs>>;
|
|
17
|
-
getTubeProof(): Promise<ProofAndVerificationKey<
|
|
16
|
+
getTubeProof(): Promise<ProofAndVerificationKey<typeof TUBE_PROOF_LENGTH>>;
|
|
18
17
|
}
|
|
19
18
|
//# sourceMappingURL=mock_prover.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock_prover.d.ts","sourceRoot":"","sources":["../../src/test/mock_prover.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EAGzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,6BAA6B,EAClC,KAAK,iCAAiC,EACtC,KAAK,yBAAyB,
|
|
1
|
+
{"version":3,"file":"mock_prover.d.ts","sourceRoot":"","sources":["../../src/test/mock_prover.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EAGzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,6BAA6B,EAClC,KAAK,iCAAiC,EACtC,KAAK,yBAAyB,EAG9B,KAAK,sBAAsB,EAC3B,iBAAiB,EAIlB,MAAM,oBAAoB,CAAC;AAS5B,qBAAa,UAAW,YAAW,mBAAmB;;IAGpD,WAAW;IASX,kBAAkB;IAUlB,kBAAkB;IAUlB,yBAAyB,IAAI,OAAO,CAAC,6BAA6B,CAAC,6BAA6B,CAAC,CAAC;IAUlG,wBAAwB,IAAI,OAAO,CAAC,6BAA6B,CAAC,6BAA6B,CAAC,CAAC;IAUjG,mBAAmB,IAAI,OAAO,CAAC,6BAA6B,CAAC,6BAA6B,CAAC,CAAC;IAU5F,wBAAwB;IAUxB,4BAA4B,IAAI,OAAO,CAAC,6BAA6B,CAAC,iCAAiC,CAAC,CAAC;IAUzG,uBAAuB,IAAI,OAAO,CAAC,6BAA6B,CAAC,iCAAiC,CAAC,CAAC;IAUpG,0BAA0B,IAAI,OAAO,CAAC,6BAA6B,CAAC,yBAAyB,CAAC,CAAC;IAU/F,kBAAkB,IAAI,OAAO,CAAC,6BAA6B,CAAC,sBAAsB,CAAC,CAAC;IAUpF,YAAY,IAAI,OAAO,CAAC,uBAAuB,CAAC,OAAO,iBAAiB,CAAC,CAAC;CAK3E"}
|
package/dest/test/mock_prover.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { makeProofAndVerificationKey, makePublicInputsAndRecursiveProof, } from '@aztec/circuit-types';
|
|
2
|
-
import { AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, RECURSIVE_PROOF_LENGTH, TUBE_PROOF_LENGTH, VerificationKeyData, makeEmptyRecursiveProof, makeRecursiveProof, } from '@aztec/circuits.js';
|
|
3
|
-
import { makeBaseOrMergeRollupPublicInputs, makeBlockRootOrBlockMergeRollupPublicInputs, makeKernelCircuitPublicInputs,
|
|
2
|
+
import { AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, NESTED_RECURSIVE_PROOF_LENGTH, RECURSIVE_PROOF_LENGTH, TUBE_PROOF_LENGTH, VerificationKeyData, makeEmptyRecursiveProof, makeRecursiveProof, } from '@aztec/circuits.js';
|
|
3
|
+
import { makeBaseOrMergeRollupPublicInputs, makeBlockRootOrBlockMergeRollupPublicInputs, makeKernelCircuitPublicInputs, makeParityPublicInputs, makeRootRollupPublicInputs, } from '@aztec/circuits.js/testing';
|
|
4
4
|
export class MockProver {
|
|
5
5
|
constructor() { }
|
|
6
6
|
getAvmProof() {
|
|
7
7
|
return Promise.resolve(makeProofAndVerificationKey(makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS), VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS)));
|
|
8
8
|
}
|
|
9
9
|
getBaseParityProof() {
|
|
10
|
-
return Promise.resolve(
|
|
10
|
+
return Promise.resolve(makePublicInputsAndRecursiveProof(makeParityPublicInputs(), makeRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()));
|
|
11
11
|
}
|
|
12
12
|
getRootParityProof() {
|
|
13
|
-
return Promise.resolve(
|
|
13
|
+
return Promise.resolve(makePublicInputsAndRecursiveProof(makeParityPublicInputs(), makeRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()));
|
|
14
14
|
}
|
|
15
15
|
getPrivateBaseRollupProof() {
|
|
16
16
|
return Promise.resolve(makePublicInputsAndRecursiveProof(makeBaseOrMergeRollupPublicInputs(), makeRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()));
|
|
@@ -33,9 +33,6 @@ export class MockProver {
|
|
|
33
33
|
getEmptyPrivateKernelProof() {
|
|
34
34
|
return Promise.resolve(makePublicInputsAndRecursiveProof(makeKernelCircuitPublicInputs(), makeRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()));
|
|
35
35
|
}
|
|
36
|
-
getEmptyTubeProof() {
|
|
37
|
-
return Promise.resolve(makePublicInputsAndRecursiveProof(makeKernelCircuitPublicInputs(), makeRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()));
|
|
38
|
-
}
|
|
39
36
|
getRootRollupProof() {
|
|
40
37
|
return Promise.resolve(makePublicInputsAndRecursiveProof(makeRootRollupPublicInputs(), makeRecursiveProof(RECURSIVE_PROOF_LENGTH), VerificationKeyData.makeFakeHonk()));
|
|
41
38
|
}
|
|
@@ -43,4 +40,4 @@ export class MockProver {
|
|
|
43
40
|
return Promise.resolve(makeProofAndVerificationKey(makeRecursiveProof(TUBE_PROOF_LENGTH), VerificationKeyData.makeFake()));
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9ja19wcm92ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdC9tb2NrX3Byb3Zlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBSUwsMkJBQTJCLEVBQzNCLGlDQUFpQyxHQUNsQyxNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFDTCwwQkFBMEIsRUFDMUIscUNBQXFDLEVBSXJDLDZCQUE2QixFQUM3QixzQkFBc0IsRUFFdEIsaUJBQWlCLEVBQ2pCLG1CQUFtQixFQUNuQix1QkFBdUIsRUFDdkIsa0JBQWtCLEdBQ25CLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUNMLGlDQUFpQyxFQUNqQywyQ0FBMkMsRUFDM0MsNkJBQTZCLEVBQzdCLHNCQUFzQixFQUN0QiwwQkFBMEIsR0FDM0IsTUFBTSw0QkFBNEIsQ0FBQztBQUVwQyxNQUFNLE9BQU8sVUFBVTtJQUNyQixnQkFBZSxDQUFDO0lBRWhCLFdBQVc7UUFDVCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLDJCQUEyQixDQUN6Qix1QkFBdUIsQ0FBQywwQkFBMEIsQ0FBQyxFQUNuRCxtQkFBbUIsQ0FBQyxRQUFRLENBQUMscUNBQXFDLENBQUMsQ0FDcEUsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELGtCQUFrQjtRQUNoQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQixzQkFBc0IsRUFBRSxFQUN4QixrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELGtCQUFrQjtRQUNoQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQixzQkFBc0IsRUFBRSxFQUN4QixrQkFBa0IsQ0FBQyw2QkFBNkIsQ0FBQyxFQUNqRCxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELHlCQUF5QjtRQUN2QixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQixpQ0FBaUMsRUFBRSxFQUNuQyxrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELHdCQUF3QjtRQUN0QixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQixpQ0FBaUMsRUFBRSxFQUNuQyxrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELG1CQUFtQjtRQUNqQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQixpQ0FBaUMsRUFBRSxFQUNuQyxrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELHdCQUF3QjtRQUN0QixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQiwyQ0FBMkMsRUFBRSxFQUM3QyxrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELDRCQUE0QjtRQUMxQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQiwyQ0FBMkMsRUFBRSxFQUM3QyxrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELHVCQUF1QjtRQUNyQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQiwyQ0FBMkMsRUFBRSxFQUM3QyxrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELDBCQUEwQjtRQUN4QixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQiw2QkFBNkIsRUFBRSxFQUMvQixrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELGtCQUFrQjtRQUNoQixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLGlDQUFpQyxDQUMvQiwwQkFBMEIsRUFBRSxFQUM1QixrQkFBa0IsQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FDbkMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELFlBQVk7UUFDVixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQ3BCLDJCQUEyQixDQUFDLGtCQUFrQixDQUFDLGlCQUFpQixDQUFDLEVBQUUsbUJBQW1CLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FDbkcsQ0FBQztJQUNKLENBQUM7Q0FDRiJ9
|