@aztec/prover-client 0.67.1 → 0.68.0

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