UNPKG

95.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const client_common_1 = require("@neo-one/client-common");
5const client_switch_1 = require("@neo-one/client-switch");
6const logger_1 = require("@neo-one/logger");
7const node_core_1 = require("@neo-one/node-core");
8const utils_1 = require("@neo-one/utils");
9const bn_js_1 = require("bn.js");
10const js_priority_queue_1 = tslib_1.__importDefault(require("js-priority-queue"));
11const rxjs_1 = require("rxjs");
12const operators_1 = require("rxjs/operators");
13const errors_1 = require("./errors");
14const getValidators_1 = require("./getValidators");
15const wrapExecuteScripts_1 = require("./wrapExecuteScripts");
16const WriteBatchBlockchain_1 = require("./WriteBatchBlockchain");
17const logger = logger_1.createChild(logger_1.nodeLogger, { component: 'blockchain' });
18const blockFailures = client_switch_1.globalStats.createMeasureInt64('persist/failures', client_switch_1.MeasureUnit.UNIT);
19const blockCurrent = client_switch_1.globalStats.createMeasureInt64('persist/current', client_switch_1.MeasureUnit.UNIT);
20const blockProgress = client_switch_1.globalStats.createMeasureInt64('persist/progress', client_switch_1.MeasureUnit.UNIT);
21const blockDurationMs = client_switch_1.globalStats.createMeasureDouble('persist/duration', client_switch_1.MeasureUnit.MS, 'time to persist block in milliseconds');
22const blockLatencySec = client_switch_1.globalStats.createMeasureDouble('persist/latency', client_switch_1.MeasureUnit.SEC, "'The latency from block timestamp to persist'");
23const NEO_BLOCKCHAIN_PERSIST_BLOCK_DURATION_MS = client_switch_1.globalStats.createView('neo_blockchain_persist_block_duration_ms', blockDurationMs, client_switch_1.AggregationType.DISTRIBUTION, [], 'distribution of the persist duration', [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000]);
24client_switch_1.globalStats.registerView(NEO_BLOCKCHAIN_PERSIST_BLOCK_DURATION_MS);
25const NEO_BLOCKCHAIN_PERSIST_BLOCK_FAILURES_TOTAL = client_switch_1.globalStats.createView('neo_blockchain_persist_block_failures_total', blockFailures, client_switch_1.AggregationType.COUNT, [], 'total blockchain failures');
26client_switch_1.globalStats.registerView(NEO_BLOCKCHAIN_PERSIST_BLOCK_FAILURES_TOTAL);
27const NEO_BLOCKCHAIN_BLOCK_INDEX_GAUGE = client_switch_1.globalStats.createView('neo_blockchain_block_index', blockCurrent, client_switch_1.AggregationType.LAST_VALUE, [], 'the current block index');
28client_switch_1.globalStats.registerView(NEO_BLOCKCHAIN_BLOCK_INDEX_GAUGE);
29const NEO_BLOCKCHAIN_PERSISTING_BLOCK_INDEX_GAUGE = client_switch_1.globalStats.createView('neo_blockchain_persisting_block_index', blockProgress, client_switch_1.AggregationType.LAST_VALUE, [], 'The current in progress persist index');
30client_switch_1.globalStats.registerView(NEO_BLOCKCHAIN_PERSISTING_BLOCK_INDEX_GAUGE);
31const NEO_BLOCKCHAIN_PERSIST_BLOCK_LATENCY_SECONDS = client_switch_1.globalStats.createView('neo_blockchain_persist_block_latency_seconds', blockLatencySec, client_switch_1.AggregationType.DISTRIBUTION, [], 'The latency from block timestamp to persist', [1, 2, 5, 7.5, 10, 12.5, 15, 17.5, 20]);
32client_switch_1.globalStats.registerView(NEO_BLOCKCHAIN_PERSIST_BLOCK_LATENCY_SECONDS);
33class Blockchain {
34 constructor(options) {
35 this.mutablePersistingBlocks = false;
36 this.mutableBlockQueue = new js_priority_queue_1.default({
37 comparator: (a, b) => a.block.index - b.block.index,
38 });
39 this.mutableInQueue = new Set();
40 this.mutableRunning = false;
41 this.mutableBlock$ = new rxjs_1.Subject();
42 this.getValidators = async (transactions) => {
43 logger.debug({ title: 'neo_blockchain_get_validators' });
44 return getValidators_1.getValidators(this, transactions);
45 };
46 this.calculateClaimAmount = async (claims) => {
47 logger.debug({ title: 'neo_blockchain_calculate_claim_amount' });
48 const spentCoins = await Promise.all(claims.map(async (claim) => this.tryGetSpentCoin(claim)));
49 const filteredSpentCoinsIn = spentCoins.filter(utils_1.utils.notNull);
50 if (spentCoins.length !== filteredSpentCoinsIn.length) {
51 throw new errors_1.CoinUnspentError(spentCoins.length - filteredSpentCoinsIn.length);
52 }
53 const filteredSpentCoins = filteredSpentCoinsIn.filter((spentCoin) => {
54 if (spentCoin.claimed) {
55 throw new errors_1.CoinClaimedError(client_common_1.common.uInt256ToString(spentCoin.output.asset), spentCoin.output.value.toString(10));
56 }
57 if (!client_common_1.common.uInt256Equal(spentCoin.output.asset, this.settings.governingToken.hash)) {
58 throw new errors_1.InvalidClaimError(client_common_1.common.uInt256ToString(spentCoin.output.asset), client_common_1.common.uInt256ToString(this.settings.governingToken.hash));
59 }
60 return true;
61 });
62 return node_core_1.utils.calculateClaimAmount({
63 coins: filteredSpentCoins.map((coin) => ({
64 value: coin.output.value,
65 startHeight: coin.startHeight,
66 endHeight: coin.endHeight,
67 })),
68 decrementInterval: this.settings.decrementInterval,
69 generationAmount: this.settings.generationAmount,
70 getSystemFee: async (index) => {
71 const header = await this.header.get({
72 hashOrIndex: index,
73 });
74 const blockData = await this.blockData.get({
75 hash: header.hash,
76 });
77 return blockData.systemFee;
78 },
79 });
80 };
81 this.verifyScript = async ({ scriptContainer, hash, witness, }) => {
82 let { verification } = witness;
83 if (verification.length === 0) {
84 const builder = new client_common_1.ScriptBuilder();
85 builder.emitAppCallVerification(hash);
86 verification = builder.build();
87 }
88 else if (!client_common_1.common.uInt160Equal(hash, client_common_1.crypto.toScriptHash(verification))) {
89 throw new errors_1.WitnessVerifyError();
90 }
91 const blockchain = this.createWriteBlockchain();
92 const mutableActions = [];
93 let globalActionIndex = new bn_js_1.BN(0);
94 const executeResult = await this.vm.executeScripts({
95 scripts: [{ code: witness.invocation }, { code: verification }],
96 blockchain,
97 scriptContainer,
98 triggerType: node_core_1.TriggerType.Verification,
99 action: node_core_1.NULL_ACTION,
100 gas: node_core_1.utils.ONE_HUNDRED_MILLION,
101 listeners: {
102 onLog: ({ message, scriptHash }) => {
103 mutableActions.push(new node_core_1.LogAction({
104 index: globalActionIndex,
105 scriptHash,
106 message,
107 }));
108 globalActionIndex = globalActionIndex.add(node_core_1.utils.ONE);
109 },
110 onNotify: ({ args, scriptHash }) => {
111 mutableActions.push(new node_core_1.NotificationAction({
112 index: globalActionIndex,
113 scriptHash,
114 args,
115 }));
116 globalActionIndex = globalActionIndex.add(node_core_1.utils.ONE);
117 },
118 },
119 });
120 const result = { actions: mutableActions, hash, witness };
121 const { stack, state, errorMessage } = executeResult;
122 if (state === client_common_1.VMState.Fault) {
123 return Object.assign({}, result, { failureMessage: errorMessage === undefined ? 'Script execution ended in a FAULT state' : errorMessage });
124 }
125 if (stack.length !== 1) {
126 return Object.assign({}, result, { failureMessage: `Verification did not return one result. This may be a bug in the ` +
127 `smart contract compiler or the smart contract itself. If you are using the NEO•ONE compiler please file an issue. Found ${stack.length} results.` });
128 }
129 const top = stack[0];
130 if (!top.asBoolean()) {
131 return Object.assign({}, result, { failureMessage: 'Verification did not succeed.' });
132 }
133 return result;
134 };
135 this.tryGetInvocationData = async (transaction) => {
136 const data = await this.invocationData.tryGet({
137 hash: transaction.hash,
138 });
139 if (data === undefined) {
140 return undefined;
141 }
142 const [asset, contracts, actions] = await Promise.all([
143 data.assetHash === undefined ? Promise.resolve(undefined) : this.asset.get({ hash: data.assetHash }),
144 Promise.all(data.contractHashes.map(async (contractHash) => this.contract.tryGet({ hash: contractHash }))),
145 data.actionIndexStart.eq(data.actionIndexStop)
146 ? Promise.resolve([])
147 : this.action
148 .getAll$({
149 indexStart: data.actionIndexStart,
150 indexStop: data.actionIndexStop.sub(node_core_1.utils.ONE),
151 })
152 .pipe(operators_1.toArray())
153 .toPromise(),
154 ]);
155 return {
156 asset,
157 contracts: contracts.filter(utils_1.utils.notNull),
158 deletedContractHashes: data.deletedContractHashes,
159 migratedContractHashes: data.migratedContractHashes,
160 voteUpdates: data.voteUpdates,
161 result: data.result,
162 actions,
163 storageChanges: data.storageChanges,
164 };
165 };
166 this.tryGetTransactionData = async (transaction) => this.transactionData.tryGet({ hash: transaction.hash });
167 this.getUnclaimed = async (hash) => this.accountUnclaimed
168 .getAll$({ hash })
169 .pipe(operators_1.toArray())
170 .toPromise()
171 .then((values) => values.map((value) => value.input));
172 this.getUnspent = async (hash) => {
173 const unspent = await this.accountUnspent
174 .getAll$({ hash })
175 .pipe(operators_1.toArray())
176 .toPromise();
177 return unspent.map((value) => value.input);
178 };
179 this.getAllValidators = async () => this.validator.all$.pipe(operators_1.toArray()).toPromise();
180 this.isSpent = async (input) => {
181 const transactionData = await this.transactionData.tryGet({
182 hash: input.hash,
183 });
184 return (transactionData !== undefined && transactionData.endHeights[input.index] !== undefined);
185 };
186 this.tryGetSpentCoin = async (input) => {
187 const [transactionData, output] = await Promise.all([
188 this.transactionData.tryGet({ hash: input.hash }),
189 this.output.get(input),
190 ]);
191 if (transactionData === undefined) {
192 return undefined;
193 }
194 const endHeight = transactionData.endHeights[input.index];
195 if (endHeight === undefined) {
196 return undefined;
197 }
198 const claimed = transactionData.claimed[input.index];
199 return {
200 output,
201 startHeight: transactionData.startHeight,
202 endHeight,
203 claimed: !!claimed,
204 };
205 };
206 this.storage = options.storage;
207 this.mutableCurrentBlock = options.currentBlock;
208 this.mutablePreviousBlock = options.previousBlock;
209 this.mutableCurrentHeader = options.currentHeader;
210 this.vm = options.vm;
211 this.settings$ = new rxjs_1.BehaviorSubject(options.settings);
212 client_switch_1.globalStats.record([
213 {
214 measure: blockProgress,
215 value: this.currentBlockIndex,
216 },
217 {
218 measure: blockCurrent,
219 value: this.currentBlockIndex,
220 },
221 ]);
222 const self = this;
223 this.deserializeWireContext = {
224 get messageMagic() {
225 return self.settings.messageMagic;
226 },
227 };
228 this.feeContext = {
229 get getOutput() {
230 return self.output.get;
231 },
232 get governingToken() {
233 return self.settings.governingToken;
234 },
235 get utilityToken() {
236 return self.settings.utilityToken;
237 },
238 get fees() {
239 return self.settings.fees;
240 },
241 get registerValidatorFee() {
242 return self.settings.registerValidatorFee;
243 },
244 };
245 this.serializeJSONContext = {
246 get addressVersion() {
247 return self.settings.addressVersion;
248 },
249 get feeContext() {
250 return self.feeContext;
251 },
252 get tryGetInvocationData() {
253 return self.tryGetInvocationData;
254 },
255 get tryGetTransactionData() {
256 return self.tryGetTransactionData;
257 },
258 get getUnclaimed() {
259 return self.getUnclaimed;
260 },
261 get getUnspent() {
262 return self.getUnspent;
263 },
264 };
265 this.start();
266 }
267 static async create({ settings, storage, vm }) {
268 const [currentBlock, currentHeader] = await Promise.all([
269 storage.block.tryGetLatest(),
270 storage.header.tryGetLatest(),
271 ]);
272 let previousBlock;
273 if (currentBlock !== undefined) {
274 previousBlock = await storage.block.tryGet({ hashOrIndex: currentBlock.index - 1 });
275 }
276 const blockchain = new Blockchain({
277 currentBlock,
278 currentHeader,
279 previousBlock,
280 settings,
281 storage,
282 vm,
283 });
284 if (currentHeader === undefined) {
285 await blockchain.persistHeaders([settings.genesisBlock.header]);
286 }
287 if (currentBlock === undefined) {
288 await blockchain.persistBlock({ block: settings.genesisBlock });
289 }
290 return blockchain;
291 }
292 get settings() {
293 return this.settings$.getValue();
294 }
295 get currentBlock() {
296 if (this.mutableCurrentBlock === undefined) {
297 throw new errors_1.GenesisBlockNotRegisteredError();
298 }
299 return this.mutableCurrentBlock;
300 }
301 get previousBlock() {
302 return this.mutablePreviousBlock;
303 }
304 get currentHeader() {
305 if (this.mutableCurrentHeader === undefined) {
306 throw new errors_1.GenesisBlockNotRegisteredError();
307 }
308 return this.mutableCurrentHeader;
309 }
310 get currentBlockIndex() {
311 return this.mutableCurrentBlock === undefined ? -1 : this.currentBlock.index;
312 }
313 get block$() {
314 return this.mutableBlock$;
315 }
316 get isPersistingBlock() {
317 return this.mutablePersistingBlocks;
318 }
319 get account() {
320 return this.storage.account;
321 }
322 get accountUnclaimed() {
323 return this.storage.accountUnclaimed;
324 }
325 get accountUnspent() {
326 return this.storage.accountUnspent;
327 }
328 get action() {
329 return this.storage.action;
330 }
331 get asset() {
332 return this.storage.asset;
333 }
334 get block() {
335 return this.storage.block;
336 }
337 get blockData() {
338 return this.storage.blockData;
339 }
340 get header() {
341 return this.storage.header;
342 }
343 get transaction() {
344 return this.storage.transaction;
345 }
346 get transactionData() {
347 return this.storage.transactionData;
348 }
349 get output() {
350 return this.storage.output;
351 }
352 get contract() {
353 return this.storage.contract;
354 }
355 get storageItem() {
356 return this.storage.storageItem;
357 }
358 get validator() {
359 return this.storage.validator;
360 }
361 get invocationData() {
362 return this.storage.invocationData;
363 }
364 get validatorsCount() {
365 return this.storage.validatorsCount;
366 }
367 async stop() {
368 if (!this.mutableRunning) {
369 return;
370 }
371 if (this.mutablePersistingBlocks) {
372 const doneRunningPromise = new Promise((resolve) => {
373 this.mutableDoneRunningResolve = resolve;
374 });
375 this.mutableRunning = false;
376 await doneRunningPromise;
377 this.mutableDoneRunningResolve = undefined;
378 }
379 else {
380 this.mutableRunning = false;
381 }
382 logger.info({ title: 'neo_blockchain_stop' }, 'NEO blockchain stopped.');
383 }
384 updateSettings(settings) {
385 this.settings$.next(settings);
386 }
387 async persistBlock({ block, unsafe = false, }) {
388 return new Promise((resolve, reject) => {
389 if (this.mutableInQueue.has(block.hashHex)) {
390 resolve();
391 return;
392 }
393 this.mutableInQueue.add(block.hashHex);
394 this.mutableBlockQueue.queue({
395 block,
396 resolve,
397 reject,
398 unsafe,
399 });
400 this.persistBlocksAsync();
401 });
402 }
403 async persistHeaders(_headers) {
404 }
405 async verifyBlock(block) {
406 await block.verify({
407 genesisBlock: this.settings.genesisBlock,
408 tryGetBlock: this.block.tryGet,
409 tryGetHeader: this.header.tryGet,
410 isSpent: this.isSpent,
411 getAsset: this.asset.get,
412 getOutput: this.output.get,
413 tryGetAccount: this.account.tryGet,
414 getValidators: this.getValidators,
415 standbyValidators: this.settings.standbyValidators,
416 getAllValidators: this.getAllValidators,
417 calculateClaimAmount: async (claims) => this.calculateClaimAmount(claims),
418 verifyScript: async (options) => this.verifyScript(options),
419 currentHeight: this.mutableCurrentBlock === undefined ? 0 : this.mutableCurrentBlock.index,
420 governingToken: this.settings.governingToken,
421 utilityToken: this.settings.utilityToken,
422 fees: this.settings.fees,
423 registerValidatorFee: this.settings.registerValidatorFee,
424 });
425 }
426 async verifyConsensusPayload(payload) {
427 await payload.verify({
428 getValidators: async () => this.getValidators([]),
429 verifyScript: async (options) => this.verifyScript(options),
430 currentIndex: this.mutableCurrentBlock === undefined ? 0 : this.mutableCurrentBlock.index,
431 currentBlockHash: this.currentBlock.hash,
432 });
433 }
434 async verifyTransaction({ transaction, memPool, }) {
435 try {
436 const verifications = await transaction.verify({
437 calculateClaimAmount: this.calculateClaimAmount,
438 isSpent: this.isSpent,
439 getAsset: this.asset.get,
440 getOutput: this.output.get,
441 tryGetAccount: this.account.tryGet,
442 standbyValidators: this.settings.standbyValidators,
443 getAllValidators: this.getAllValidators,
444 verifyScript: async (options) => this.verifyScript(options),
445 governingToken: this.settings.governingToken,
446 utilityToken: this.settings.utilityToken,
447 fees: this.settings.fees,
448 registerValidatorFee: this.settings.registerValidatorFee,
449 currentHeight: this.currentBlockIndex,
450 memPool,
451 });
452 return { verifications };
453 }
454 catch (error) {
455 if (error.code === undefined || typeof error.code !== 'string' || !error.code.includes('VERIFY')) {
456 throw new errors_1.UnknownVerifyError(error.message);
457 }
458 throw error;
459 }
460 }
461 async invokeScript(script) {
462 const transaction = new node_core_1.InvocationTransaction({
463 script,
464 gas: client_common_1.common.ONE_HUNDRED_FIXED8,
465 });
466 return this.invokeTransaction(transaction);
467 }
468 async invokeTransaction(transaction) {
469 const blockchain = this.createWriteBlockchain();
470 const mutableActions = [];
471 let globalActionIndex = new bn_js_1.BN(0);
472 const result = await wrapExecuteScripts_1.wrapExecuteScripts(async () => this.vm.executeScripts({
473 scripts: [{ code: transaction.script }],
474 blockchain,
475 scriptContainer: {
476 type: node_core_1.ScriptContainerType.Transaction,
477 value: transaction,
478 },
479 listeners: {
480 onLog: ({ message, scriptHash }) => {
481 mutableActions.push(new node_core_1.LogAction({
482 index: globalActionIndex,
483 scriptHash,
484 message,
485 }));
486 globalActionIndex = globalActionIndex.add(node_core_1.utils.ONE);
487 },
488 onNotify: ({ args, scriptHash }) => {
489 mutableActions.push(new node_core_1.NotificationAction({
490 index: globalActionIndex,
491 scriptHash,
492 args,
493 }));
494 globalActionIndex = globalActionIndex.add(node_core_1.utils.ONE);
495 },
496 },
497 triggerType: node_core_1.TriggerType.Application,
498 action: node_core_1.NULL_ACTION,
499 gas: transaction.gas,
500 skipWitnessVerify: true,
501 }));
502 return {
503 result,
504 actions: mutableActions,
505 };
506 }
507 async reset() {
508 await this.stop();
509 await this.storage.reset();
510 this.mutableCurrentHeader = undefined;
511 this.mutableCurrentBlock = undefined;
512 this.mutablePreviousBlock = undefined;
513 this.start();
514 await this.persistHeaders([this.settings.genesisBlock.header]);
515 await this.persistBlock({ block: this.settings.genesisBlock });
516 }
517 async persistBlocksAsync() {
518 if (this.mutablePersistingBlocks || !this.mutableRunning) {
519 return;
520 }
521 this.mutablePersistingBlocks = true;
522 let entry;
523 try {
524 entry = this.cleanBlockQueue();
525 while (this.mutableRunning && entry !== undefined && entry.block.index === this.currentBlockIndex + 1) {
526 const startTime = Date.now();
527 const entryNonNull = entry;
528 const logData = {
529 [utils_1.Labels.NEO_BLOCK_INDEX]: entry.block.index,
530 title: 'neo_blockchain_persist_block_top_level',
531 };
532 try {
533 await this.persistBlockInternal(entryNonNull.block, entryNonNull.unsafe);
534 logger.debug(logData);
535 client_switch_1.globalStats.record([
536 {
537 measure: blockDurationMs,
538 value: Date.now() - startTime,
539 },
540 ]);
541 }
542 catch (error) {
543 logger.error(Object.assign({ error }, logData));
544 client_switch_1.globalStats.record([
545 {
546 measure: blockFailures,
547 value: 1,
548 },
549 ]);
550 throw error;
551 }
552 entry.resolve();
553 this.mutableBlock$.next(entry.block);
554 client_switch_1.globalStats.record([
555 {
556 measure: blockCurrent,
557 value: entry.block.index,
558 },
559 {
560 measure: blockLatencySec,
561 value: Date.now() - entry.block.timestamp,
562 },
563 ]);
564 entry = this.cleanBlockQueue();
565 }
566 if (entry !== undefined) {
567 this.mutableBlockQueue.queue(entry);
568 }
569 }
570 catch (error) {
571 if (entry !== undefined) {
572 entry.reject(error);
573 }
574 }
575 finally {
576 this.mutablePersistingBlocks = false;
577 if (this.mutableDoneRunningResolve !== undefined) {
578 this.mutableDoneRunningResolve();
579 this.mutableDoneRunningResolve = undefined;
580 }
581 }
582 }
583 cleanBlockQueue() {
584 let entry = this.dequeBlockQueue();
585 while (entry !== undefined && entry.block.index <= this.currentBlockIndex) {
586 entry.resolve();
587 entry = this.dequeBlockQueue();
588 }
589 return entry;
590 }
591 dequeBlockQueue() {
592 if (this.mutableBlockQueue.length > 0) {
593 return this.mutableBlockQueue.dequeue();
594 }
595 return undefined;
596 }
597 start() {
598 this.mutableBlock$ = new rxjs_1.Subject();
599 this.mutablePersistingBlocks = false;
600 this.mutableBlockQueue = new js_priority_queue_1.default({
601 comparator: (a, b) => a.block.index - b.block.index,
602 });
603 this.mutableInQueue = new Set();
604 this.mutableDoneRunningResolve = undefined;
605 this.mutableRunning = true;
606 logger.info({ title: 'neo_blockchain_start' }, 'NEO blockchain started.');
607 }
608 async persistBlockInternal(block, unsafe) {
609 client_switch_1.globalStats.record([
610 {
611 measure: blockProgress,
612 value: block.index,
613 },
614 ]);
615 if (!unsafe) {
616 await this.verifyBlock(block);
617 }
618 const blockchain = this.createWriteBlockchain();
619 await blockchain.persistBlock(block);
620 await this.storage.commit(blockchain.getChangeSet());
621 this.mutablePreviousBlock = this.mutableCurrentBlock;
622 this.mutableCurrentBlock = block;
623 this.mutableCurrentHeader = block.header;
624 }
625 createWriteBlockchain() {
626 return new WriteBatchBlockchain_1.WriteBatchBlockchain({
627 settings: this.settings,
628 currentBlock: this.mutableCurrentBlock,
629 currentHeader: this.mutableCurrentHeader,
630 storage: this.storage,
631 vm: this.vm,
632 getValidators: this.getValidators,
633 });
634 }
635}
636exports.Blockchain = Blockchain;
637
638//# sourceMappingURL=data:application/json;charset=utf8;base64,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RyxLQUFLLENBQUMsTUFBTSxDQUFDO0lBQzNDLENBQUM7SUFFTyxxQkFBcUI7UUFDM0IsT0FBTyxJQUFJLDJDQUFvQixDQUFDO1lBQzlCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTtZQUN2QixZQUFZLEVBQUUsSUFBSSxDQUFDLG1CQUFtQjtZQUN0QyxhQUFhLEVBQUUsSUFBSSxDQUFDLG9CQUFvQjtZQUN4QyxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87WUFDckIsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFO1lBQ1gsYUFBYSxFQUFFLElBQUksQ0FBQyxhQUFhO1NBQ2xDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQW4wQkQsZ0NBbTBCQyIsImZpbGUiOiJuZW8tb25lLW5vZGUtYmxvY2tjaGFpbi9zcmMvQmxvY2tjaGFpbi5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNvbW1vbiwgY3J5cHRvLCBFQ1BvaW50LCBTY3JpcHRCdWlsZGVyLCBVSW50MTYwLCBWTVN0YXRlIH0gZnJvbSAnQG5lby1vbmUvY2xpZW50LWNvbW1vbic7XG5pbXBvcnQgeyBBZ2dyZWdhdGlvblR5cGUsIGdsb2JhbFN0YXRzLCBNZWFzdXJlVW5pdCB9IGZyb20gJ0BuZW8tb25lL2NsaWVudC1zd2l0Y2gnO1xuaW1wb3J0IHsgY3JlYXRlQ2hpbGQsIG5vZGVMb2dnZXIgfSBmcm9tICdAbmVvLW9uZS9sb2dnZXInO1xuaW1wb3J0IHtcbiAgQWN0aW9uLFxuICBCbG9jayxcbiAgQmxvY2tjaGFpbiBhcyBCbG9ja2NoYWluVHlwZSxcbiAgQ2FsbFJlY2VpcHQsXG4gIENvbnNlbnN1c1BheWxvYWQsXG4gIEhlYWRlcixcbiAgSW5wdXQsXG4gIEludm9jYXRpb25UcmFuc2FjdGlvbixcbiAgTG9nQWN0aW9uLFxuICBOb3RpZmljYXRpb25BY3Rpb24sXG4gIE5VTExfQUNUSU9OLFxuICBPdXRwdXQsXG4gIE91dHB1dEtleSxcbiAgU2NyaXB0Q29udGFpbmVyVHlwZSxcbiAgU2VyaWFsaXphYmxlSW52b2NhdGlvbkRhdGEsXG4gIFNldHRpbmdzLFxuICBTdG9yYWdlLFxuICBUcmFuc2FjdGlvbixcbiAgVHJhbnNhY3Rpb25EYXRhLFxuICBUcmlnZ2VyVHlwZSxcbiAgdXRpbHMsXG4gIFZhbGlkYXRvcixcbiAgVmVyaWZ5U2NyaXB0T3B0aW9ucyxcbiAgVmVyaWZ5U2NyaXB0UmVzdWx0LFxuICBWZXJpZnlUcmFuc2FjdGlvblJlc3VsdCxcbiAgVk0sXG59IGZyb20gJ0BuZW8tb25lL25vZGUtY29yZSc7XG5pbXBvcnQgeyBMYWJlbHMsIHV0aWxzIGFzIGNvbW1vblV0aWxzIH0gZnJvbSAnQG5lby1vbmUvdXRpbHMnO1xuaW1wb3J0IHsgQk4gfSBmcm9tICdibi5qcyc7XG5pbXBvcnQgUHJpb3JpdHlRdWV1ZSBmcm9tICdqcy1wcmlvcml0eS1xdWV1ZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRvQXJyYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1xuICBDb2luQ2xhaW1lZEVycm9yLFxuICBDb2luVW5zcGVudEVycm9yLFxuICBHZW5lc2lzQmxvY2tOb3RSZWdpc3RlcmVkRXJyb3IsXG4gIEludmFsaWRDbGFpbUVycm9yLFxuICBVbmtub3duVmVyaWZ5RXJyb3IsXG4gIFdpdG5lc3NWZXJpZnlFcnJvcixcbn0gZnJvbSAnLi9lcnJvcnMnO1xuaW1wb3J0IHsgZ2V0VmFsaWRhdG9ycyB9IGZyb20gJy4vZ2V0VmFsaWRhdG9ycyc7XG5pbXBvcnQgeyB3cmFwRXhlY3V0ZVNjcmlwdHMgfSBmcm9tICcuL3dyYXBFeGVjdXRlU2NyaXB0cyc7XG5pbXBvcnQgeyBXcml0ZUJhdGNoQmxvY2tjaGFpbiB9IGZyb20gJy4vV3JpdGVCYXRjaEJsb2NrY2hhaW4nO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVDaGlsZChub2RlTG9nZ2VyLCB7IGNvbXBvbmVudDogJ2Jsb2NrY2hhaW4nIH0pO1xuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUJsb2NrY2hhaW5PcHRpb25zIHtcbiAgcmVhZG9ubHkgc2V0dGluZ3M6IFNldHRpbmdzO1xuICByZWFkb25seSBzdG9yYWdlOiBTdG9yYWdlO1xuICByZWFkb25seSB2bTogVk07XG59XG5leHBvcnQgaW50ZXJmYWNlIEJsb2NrY2hhaW5PcHRpb25zIGV4dGVuZHMgQ3JlYXRlQmxvY2tjaGFpbk9wdGlvbnMge1xuICByZWFkb25seSBjdXJyZW50QmxvY2s6IEJsb2NrY2hhaW5UeXBlWydjdXJyZW50QmxvY2snXSB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgcHJldmlvdXNCbG9jazogQmxvY2tjaGFpblR5cGVbJ3ByZXZpb3VzQmxvY2snXSB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgY3VycmVudEhlYWRlcjogQmxvY2tjaGFpblR5cGVbJ2N1cnJlbnRIZWFkZXInXSB8IHVuZGVmaW5lZDtcbn1cblxuaW50ZXJmYWNlIFNwZW50Q29pbiB7XG4gIHJlYWRvbmx5IG91dHB1dDogT3V0cHV0O1xuICByZWFkb25seSBzdGFydEhlaWdodDogbnVtYmVyO1xuICByZWFkb25seSBlbmRIZWlnaHQ6IG51bWJlcjtcbiAgcmVhZG9ubHkgY2xhaW1lZDogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIEVudHJ5IHtcbiAgcmVhZG9ubHkgYmxvY2s6IEJsb2NrO1xuICByZWFkb25seSByZXNvbHZlOiAoKSA9PiB2b2lkO1xuICByZWFkb25seSByZWplY3Q6IChlcnJvcjogRXJyb3IpID0+IHZvaWQ7XG4gIHJlYWRvbmx5IHVuc2FmZTogYm9vbGVhbjtcbn1cblxuY29uc3QgYmxvY2tGYWlsdXJlcyA9IGdsb2JhbFN0YXRzLmNyZWF0ZU1lYXN1cmVJbnQ2NCgncGVyc2lzdC9mYWlsdXJlcycsIE1lYXN1cmVVbml0LlVOSVQpO1xuY29uc3QgYmxvY2tDdXJyZW50ID0gZ2xvYmFsU3RhdHMuY3JlYXRlTWVhc3VyZUludDY0KCdwZXJzaXN0L2N1cnJlbnQnLCBNZWFzdXJlVW5pdC5VTklUKTtcbmNvbnN0IGJsb2NrUHJvZ3Jlc3MgPSBnbG9iYWxTdGF0cy5jcmVhdGVNZWFzdXJlSW50NjQoJ3BlcnNpc3QvcHJvZ3Jlc3MnLCBNZWFzdXJlVW5pdC5VTklUKTtcblxuY29uc3QgYmxvY2tEdXJhdGlvbk1zID0gZ2xvYmFsU3RhdHMuY3JlYXRlTWVhc3VyZURvdWJsZShcbiAgJ3BlcnNpc3QvZHVyYXRpb24nLFxuICBNZWFzdXJlVW5pdC5NUyxcbiAgJ3RpbWUgdG8gcGVyc2lzdCBibG9jayBpbiBtaWxsaXNlY29uZHMnLFxuKTtcbmNvbnN0IGJsb2NrTGF0ZW5jeVNlYyA9IGdsb2JhbFN0YXRzLmNyZWF0ZU1lYXN1cmVEb3VibGUoXG4gICdwZXJzaXN0L2xhdGVuY3knLFxuICBNZWFzdXJlVW5pdC5TRUMsXG4gIFwiJ1RoZSBsYXRlbmN5IGZyb20gYmxvY2sgdGltZXN0YW1wIHRvIHBlcnNpc3QnXCIsXG4pO1xuXG5jb25zdCBORU9fQkxPQ0tDSEFJTl9QRVJTSVNUX0JMT0NLX0RVUkFUSU9OX01TID0gZ2xvYmFsU3RhdHMuY3JlYXRlVmlldyhcbiAgJ25lb19ibG9ja2NoYWluX3BlcnNpc3RfYmxvY2tfZHVyYXRpb25fbXMnLFxuICBibG9ja0R1cmF0aW9uTXMsXG4gIEFnZ3JlZ2F0aW9uVHlwZS5ESVNUUklCVVRJT04sXG4gIFtdLFxuICAnZGlzdHJpYnV0aW9uIG9mIHRoZSBwZXJzaXN0IGR1cmF0aW9uJyxcbiAgWzUsIDEwLCAyNSwgNTAsIDEwMCwgMjUwLCA1MDAsIDEwMDAsIDI1MDAsIDUwMDAsIDEwMDAwXSxcbik7XG5nbG9iYWxTdGF0cy5yZWdpc3RlclZpZXcoTkVPX0JMT0NLQ0hBSU5fUEVSU0lTVF9CTE9DS19EVVJBVElPTl9NUyk7XG5cbmNvbnN0IE5FT19CTE9DS0NIQUlOX1BFUlNJU1RfQkxPQ0tfRkFJTFVSRVNfVE9UQUwgPSBnbG9iYWxTdGF0cy5jcmVhdGVWaWV3KFxuICAnbmVvX2Jsb2NrY2hhaW5fcGVyc2lzdF9ibG9ja19mYWlsdXJlc190b3RhbCcsXG4gIGJsb2NrRmFpbHVyZXMsXG4gIEFnZ3JlZ2F0aW9uVHlwZS5DT1VOVCxcbiAgW10sXG4gICd0b3RhbCBibG9ja2NoYWluIGZhaWx1cmVzJyxcbik7XG5nbG9iYWxTdGF0cy5yZWdpc3RlclZpZXcoTkVPX0JMT0NLQ0hBSU5fUEVSU0lTVF9CTE9DS19GQUlMVVJFU19UT1RBTCk7XG5cbmNvbnN0IE5FT19CTE9DS0NIQUlOX0JMT0NLX0lOREVYX0dBVUdFID0gZ2xvYmFsU3RhdHMuY3JlYXRlVmlldyhcbiAgJ25lb19ibG9ja2NoYWluX2Jsb2NrX2luZGV4JyxcbiAgYmxvY2tDdXJyZW50LFxuICBBZ2dyZWdhdGlvblR5cGUuTEFTVF9WQUxVRSxcbiAgW10sXG4gICd0aGUgY3VycmVudCBibG9jayBpbmRleCcsXG4pO1xuZ2xvYmFsU3RhdHMucmVnaXN0ZXJWaWV3KE5FT19CTE9DS0NIQUlOX0JMT0NLX0lOREVYX0dBVUdFKTtcblxuY29uc3QgTkVPX0JMT0NLQ0hBSU5fUEVSU0lTVElOR19CTE9DS19JTkRFWF9HQVVHRSA9IGdsb2JhbFN0YXRzLmNyZWF0ZVZpZXcoXG4gICduZW9fYmxvY2tjaGFpbl9wZXJzaXN0aW5nX2Jsb2NrX2luZGV4JyxcbiAgYmxvY2tQcm9ncmVzcyxcbiAgQWdncmVnYXRpb25UeXBlLkxBU1RfVkFMVUUsXG4gIFtdLFxuICAnVGhlIGN1cnJlbnQgaW4gcHJvZ3Jlc3MgcGVyc2lzdCBpbmRleCcsXG4pO1xuZ2xvYmFsU3RhdHMucmVnaXN0ZXJWaWV3KE5FT19CTE9DS0NIQUlOX1BFUlNJU1RJTkdfQkxPQ0tfSU5ERVhfR0FVR0UpO1xuXG5jb25zdCBORU9fQkxPQ0tDSEFJTl9QRVJTSVNUX0JMT0NLX0xBVEVOQ1lfU0VDT05EUyA9IGdsb2JhbFN0YXRzLmNyZWF0ZVZpZXcoXG4gICduZW9fYmxvY2tjaGFpbl9wZXJzaXN0X2Jsb2NrX2xhdGVuY3lfc2Vjb25kcycsXG4gIGJsb2NrTGF0ZW5jeVNlYyxcbiAgQWdncmVnYXRpb25UeXBlLkRJU1RSSUJVVElPTixcbiAgW10sXG4gICdUaGUgbGF0ZW5jeSBmcm9tIGJsb2NrIHRpbWVzdGFtcCB0byBwZXJzaXN0JyxcbiAgWzEsIDIsIDUsIDcuNSwgMTAsIDEyLjUsIDE1LCAxNy41LCAyMF0sXG4pO1xuZ2xvYmFsU3RhdHMucmVnaXN0ZXJWaWV3KE5FT19CTE9DS0NIQUlOX1BFUlNJU1RfQkxPQ0tfTEFURU5DWV9TRUNPTkRTKTtcblxuZXhwb3J0IGNsYXNzIEJsb2NrY2hhaW4ge1xuICBwdWJsaWMgc3RhdGljIGFzeW5jIGNyZWF0ZSh7IHNldHRpbmdzLCBzdG9yYWdlLCB2bSB9OiBDcmVhdGVCbG9ja2NoYWluT3B0aW9ucyk6IFByb21pc2U8QmxvY2tjaGFpblR5cGU+IHtcbiAgICBjb25zdCBbY3VycmVudEJsb2NrLCBjdXJyZW50SGVhZGVyXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIHN0b3JhZ2UuYmxvY2sudHJ5R2V0TGF0ZXN0KCksXG4gICAgICBzdG9yYWdlLmhlYWRlci50cnlHZXRMYXRlc3QoKSxcbiAgICBdKTtcbiAgICBsZXQgcHJldmlvdXNCbG9jaztcbiAgICBpZiAoY3VycmVudEJsb2NrICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHByZXZpb3VzQmxvY2sgPSBhd2FpdCBzdG9yYWdlLmJsb2NrLnRyeUdldCh7IGhhc2hPckluZGV4OiBjdXJyZW50QmxvY2suaW5kZXggLSAxIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGJsb2NrY2hhaW4gPSBuZXcgQmxvY2tjaGFpbih7XG4gICAgICBjdXJyZW50QmxvY2ssXG4gICAgICBjdXJyZW50SGVhZGVyLFxuICAgICAgcHJldmlvdXNCbG9jayxcbiAgICAgIHNldHRpbmdzLFxuICAgICAgc3RvcmFnZSxcbiAgICAgIHZtLFxuICAgIH0pO1xuXG4gICAgaWYgKGN1cnJlbnRIZWFkZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgYXdhaXQgYmxvY2tjaGFpbi5wZXJzaXN0SGVhZGVycyhbc2V0dGluZ3MuZ2VuZXNpc0Jsb2NrLmhlYWRlcl0pO1xuICAgIH1cblxuICAgIGlmIChjdXJyZW50QmxvY2sgPT09IHVuZGVmaW5lZCkge1xuICAgICAgYXdhaXQgYmxvY2tjaGFpbi5wZXJzaXN0QmxvY2soeyBibG9jazogc2V0dGluZ3MuZ2VuZXNpc0Jsb2NrIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBibG9ja2NoYWluO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGRlc2VyaWFsaXplV2lyZUNvbnRleHQ6IEJsb2NrY2hhaW5UeXBlWydkZXNlcmlhbGl6ZVdpcmVDb250ZXh0J107XG4gIHB1YmxpYyByZWFkb25seSBzZXJpYWxpemVKU09OQ29udGV4dDogQmxvY2tjaGFpblR5cGVbJ3NlcmlhbGl6ZUpTT05Db250ZXh0J107XG4gIHB1YmxpYyByZWFkb25seSBmZWVDb250ZXh0OiBCbG9ja2NoYWluVHlwZVsnZmVlQ29udGV4dCddO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3MkOiBCZWhhdmlvclN1YmplY3Q8U2V0dGluZ3M+O1xuICBwcml2YXRlIHJlYWRvbmx5IHN0b3JhZ2U6IFN0b3JhZ2U7XG4gIHByaXZhdGUgbXV0YWJsZUN1cnJlbnRCbG9jazogQmxvY2tjaGFpblR5cGVbJ2N1cnJlbnRCbG9jayddIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIG11dGFibGVQcmV2aW91c0Jsb2NrOiBCbG9ja2NoYWluVHlwZVsnY3VycmVudEJsb2NrJ10gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgbXV0YWJsZUN1cnJlbnRIZWFkZXI6IEJsb2NrY2hhaW5UeXBlWydjdXJyZW50SGVhZGVyJ10gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgbXV0YWJsZVBlcnNpc3RpbmdCbG9ja3MgPSBmYWxzZTtcbiAgcHJpdmF0ZSBtdXRhYmxlQmxvY2tRdWV1ZTogUHJpb3JpdHlRdWV1ZTxFbnRyeT4gPSBuZXcgUHJpb3JpdHlRdWV1ZSh7XG4gICAgY29tcGFyYXRvcjogKGEsIGIpID0+IGEuYmxvY2suaW5kZXggLSBiLmJsb2NrLmluZGV4LFxuICB9KTtcbiAgcHJpdmF0ZSBtdXRhYmxlSW5RdWV1ZTogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgdm06IFZNO1xuICBwcml2YXRlIG11dGFibGVSdW5uaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgbXV0YWJsZURvbmVSdW5uaW5nUmVzb2x2ZTogKCgpID0+IHZvaWQpIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIG11dGFibGVCbG9jayQ6IFN1YmplY3Q8QmxvY2s+ID0gbmV3IFN1YmplY3QoKTtcblxuICBwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9uczogQmxvY2tjaGFpbk9wdGlvbnMpIHtcbiAgICB0aGlzLnN0b3JhZ2UgPSBvcHRpb25zLnN0b3JhZ2U7XG4gICAgdGhpcy5tdXRhYmxlQ3VycmVudEJsb2NrID0gb3B0aW9ucy5jdXJyZW50QmxvY2s7XG4gICAgdGhpcy5tdXRhYmxlUHJldmlvdXNCbG9jayA9IG9wdGlvbnMucHJldmlvdXNCbG9jaztcbiAgICB0aGlzLm11dGFibGVDdXJyZW50SGVhZGVyID0gb3B0aW9ucy5jdXJyZW50SGVhZGVyO1xuICAgIHRoaXMudm0gPSBvcHRpb25zLnZtO1xuXG4gICAgdGhpcy5zZXR0aW5ncyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KG9wdGlvbnMuc2V0dGluZ3MpO1xuXG4gICAgZ2xvYmFsU3RhdHMucmVjb3JkKFtcbiAgICAgIHtcbiAgICAgICAgbWVhc3VyZTogYmxvY2tQcm9ncmVzcyxcbiAgICAgICAgdmFsdWU6IHRoaXMuY3VycmVudEJsb2NrSW5kZXgsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBtZWFzdXJlOiBibG9ja0N1cnJlbnQsXG4gICAgICAgIHZhbHVlOiB0aGlzLmN1cnJlbnRCbG9ja0luZGV4LFxuICAgICAgfSxcbiAgICBdKTtcblxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby10aGlzLWFzc2lnbm1lbnRcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICB0aGlzLmRlc2VyaWFsaXplV2lyZUNvbnRleHQgPSB7XG4gICAgICBnZXQgbWVzc2FnZU1hZ2ljKCkge1xuICAgICAgICByZXR1cm4gc2VsZi5zZXR0aW5ncy5tZXNzYWdlTWFnaWM7XG4gICAgICB9LFxuICAgIH07XG5cbiAgICB0aGlzLmZlZUNvbnRleHQgPSB7XG4gICAgICBnZXQgZ2V0T3V0cHV0KCkge1xuICAgICAgICByZXR1cm4gc2VsZi5vdXRwdXQuZ2V0O1xuICAgICAgfSxcbiAgICAgIGdldCBnb3Zlcm5pbmdUb2tlbigpIHtcbiAgICAgICAgcmV0dXJuIHNlbGYuc2V0dGluZ3MuZ292ZXJuaW5nVG9rZW47XG4gICAgICB9LFxuICAgICAgZ2V0IHV0aWxpdHlUb2tlbigpIHtcbiAgICAgICAgcmV0dXJuIHNlbGYuc2V0dGluZ3MudXRpbGl0eVRva2VuO1xuICAgICAgfSxcbiAgICAgIGdldCBmZWVzKCkge1xuICAgICAgICByZXR1cm4gc2VsZi5zZXR0aW5ncy5mZWVzO1xuICAgICAgfSxcbiAgICAgIGdldCByZWdpc3RlclZhbGlkYXRvckZlZSgpIHtcbiAgICAgICAgcmV0dXJuIHNlbGYuc2V0dGluZ3MucmVnaXN0ZXJWYWxpZGF0b3JGZWU7XG4gICAgICB9LFxuICAgIH07XG5cbiAgICB0aGlzLnNlcmlhbGl6ZUpTT05Db250ZXh0ID0ge1xuICAgICAgZ2V0IGFkZHJlc3NWZXJzaW9uKCkge1xuICAgICAgICByZXR1cm4gc2VsZi5zZXR0aW5ncy5hZGRyZXNzVmVyc2lvbjtcbiAgICAgIH0sXG4gICAgICBnZXQgZmVlQ29udGV4dCgpIHtcbiAgICAgICAgcmV0dXJuIHNlbGYuZmVlQ29udGV4dDtcbiAgICAgIH0sXG4gICAgICBnZXQgdHJ5R2V0SW52b2NhdGlvbkRhdGEoKSB7XG4gICAgICAgIHJldHVybiBzZWxmLnRyeUdldEludm9jYXRpb25EYXRhO1xuICAgICAgfSxcbiAgICAgIGdldCB0cnlHZXRUcmFuc2FjdGlvbkRhdGEoKSB7XG4gICAgICAgIHJldHVybiBzZWxmLnRyeUdldFRyYW5zYWN0aW9uRGF0YTtcbiAgICAgIH0sXG4gICAgICBnZXQgZ2V0VW5jbGFpbWVkKCkge1xuICAgICAgICByZXR1cm4gc2VsZi5nZXRVbmNsYWltZWQ7XG4gICAgICB9LFxuICAgICAgZ2V0IGdldFVuc3BlbnQoKSB7XG4gICAgICAgIHJldHVybiBzZWxmLmdldFVuc3BlbnQ7XG4gICAgICB9LFxuICAgIH07XG5cbiAgICB0aGlzLnN0YXJ0KCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHNldHRpbmdzKCk6IFNldHRpbmdzIHtcbiAgICByZXR1cm4gdGhpcy5zZXR0aW5ncyQuZ2V0VmFsdWUoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY3VycmVudEJsb2NrKCk6IEJsb2NrIHtcbiAgICBpZiAodGhpcy5tdXRhYmxlQ3VycmVudEJsb2NrID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBHZW5lc2lzQmxvY2tOb3RSZWdpc3RlcmVkRXJyb3IoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tdXRhYmxlQ3VycmVudEJsb2NrO1xuICB9XG5cbiAgcHVibGljIGdldCBwcmV2aW91c0Jsb2NrKCk6IEJsb2NrIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5tdXRhYmxlUHJldmlvdXNCbG9jaztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY3VycmVudEhlYWRlcigpOiBIZWFkZXIge1xuICAgIGlmICh0aGlzLm11dGFibGVDdXJyZW50SGVhZGVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBHZW5lc2lzQmxvY2tOb3RSZWdpc3RlcmVkRXJyb3IoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tdXRhYmxlQ3VycmVudEhlYWRlcjtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY3VycmVudEJsb2NrSW5kZXgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5tdXRhYmxlQ3VycmVudEJsb2NrID09PSB1bmRlZmluZWQgPyAtMSA6IHRoaXMuY3VycmVudEJsb2NrLmluZGV4O1xuICB9XG5cbiAgcHVibGljIGdldCBibG9jayQoKTogT2JzZXJ2YWJsZTxCbG9jaz4ge1xuICAgIHJldHVybiB0aGlzLm11dGFibGVCbG9jayQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGlzUGVyc2lzdGluZ0Jsb2NrKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm11dGFibGVQZXJzaXN0aW5nQmxvY2tzO1xuICB9XG5cbiAgcHVibGljIGdldCBhY2NvdW50KCk6IEJsb2NrY2hhaW5UeXBlWydhY2NvdW50J10ge1xuICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuYWNjb3VudDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYWNjb3VudFVuY2xhaW1lZCgpOiBCbG9ja2NoYWluVHlwZVsnYWNjb3VudFVuY2xhaW1lZCddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmFjY291bnRVbmNsYWltZWQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGFjY291bnRVbnNwZW50KCk6IEJsb2NrY2hhaW5UeXBlWydhY2NvdW50VW5zcGVudCddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmFjY291bnRVbnNwZW50O1xuICB9XG5cbiAgcHVibGljIGdldCBhY3Rpb24oKTogQmxvY2tjaGFpblR5cGVbJ2FjdGlvbiddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmFjdGlvbjtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYXNzZXQoKTogQmxvY2tjaGFpblR5cGVbJ2Fzc2V0J10ge1xuICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuYXNzZXQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGJsb2NrKCk6IEJsb2NrY2hhaW5UeXBlWydibG9jayddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmJsb2NrO1xuICB9XG5cbiAgcHVibGljIGdldCBibG9ja0RhdGEoKTogQmxvY2tjaGFpblR5cGVbJ2Jsb2NrRGF0YSddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmJsb2NrRGF0YTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaGVhZGVyKCk6IEJsb2NrY2hhaW5UeXBlWydoZWFkZXInXSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5oZWFkZXI7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHRyYW5zYWN0aW9uKCk6IEJsb2NrY2hhaW5UeXBlWyd0cmFuc2FjdGlvbiddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLnRyYW5zYWN0aW9uO1xuICB9XG5cbiAgcHVibGljIGdldCB0cmFuc2FjdGlvbkRhdGEoKTogQmxvY2tjaGFpblR5cGVbJ3RyYW5zYWN0aW9uRGF0YSddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLnRyYW5zYWN0aW9uRGF0YTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgb3V0cHV0KCk6IEJsb2NrY2hhaW5UeXBlWydvdXRwdXQnXSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5vdXRwdXQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGNvbnRyYWN0KCk6IEJsb2NrY2hhaW5UeXBlWydjb250cmFjdCddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmNvbnRyYWN0O1xuICB9XG5cbiAgcHVibGljIGdldCBzdG9yYWdlSXRlbSgpOiBCbG9ja2NoYWluVHlwZVsnc3RvcmFnZUl0ZW0nXSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5zdG9yYWdlSXRlbTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdmFsaWRhdG9yKCk6IEJsb2NrY2hhaW5UeXBlWyd2YWxpZGF0b3InXSB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZS52YWxpZGF0b3I7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGludm9jYXRpb25EYXRhKCk6IEJsb2NrY2hhaW5UeXBlWydpbnZvY2F0aW9uRGF0YSddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmludm9jYXRpb25EYXRhO1xuICB9XG5cbiAgcHVibGljIGdldCB2YWxpZGF0b3JzQ291bnQoKTogQmxvY2tjaGFpblR5cGVbJ3ZhbGlkYXRvcnNDb3VudCddIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLnZhbGlkYXRvcnNDb3VudDtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzdG9wKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5tdXRhYmxlUnVubmluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm11dGFibGVQZXJzaXN0aW5nQmxvY2tzKSB7XG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgcHJvbWlzZS1tdXN0LWNvbXBsZXRlXG4gICAgICBjb25zdCBkb25lUnVubmluZ1Byb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICB0aGlzLm11dGFibGVEb25lUnVubmluZ1Jlc29sdmUgPSByZXNvbHZlO1xuICAgICAgfSk7XG4gICAgICB0aGlzLm11dGFibGVSdW5uaW5nID0gZmFsc2U7XG5cbiAgICAgIGF3YWl0IGRvbmVSdW5uaW5nUHJvbWlzZTtcbiAgICAgIHRoaXMubXV0YWJsZURvbmVSdW5uaW5nUmVzb2x2ZSA9IHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tdXRhYmxlUnVubmluZyA9IGZhbHNlO1xuICAgIH1cblxuICAgIGxvZ2dlci5pbmZvKHsgdGl0bGU6ICduZW9fYmxvY2tjaGFpbl9zdG9wJyB9LCAnTkVPIGJsb2NrY2hhaW4gc3RvcHBlZC4nKTtcbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGVTZXR0aW5ncyhzZXR0aW5nczogU2V0dGluZ3MpOiB2b2lkIHtcbiAgICB0aGlzLnNldHRpbmdzJC5uZXh0KHNldHRpbmdzKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBwZXJzaXN0QmxvY2soe1xuICAgIGJsb2NrLFxuICAgIHVuc2FmZSA9IGZhbHNlLFxuICB9OiB7XG4gICAgcmVhZG9ubHkgYmxvY2s6IEJsb2NrO1xuICAgIHJlYWRvbmx5IHVuc2FmZT86IGJvb2xlYW47XG4gIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgcHJvbWlzZS1tdXN0LWNvbXBsZXRlXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGlmICh0aGlzLm11dGFibGVJblF1ZXVlLmhhcyhibG9jay5oYXNoSGV4KSkge1xuICAgICAgICByZXNvbHZlKCk7XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5tdXRhYmxlSW5RdWV1ZS5hZGQoYmxvY2suaGFzaEhleCk7XG5cbiAgICAgIHRoaXMubXV0YWJsZUJsb2NrUXVldWUucXVldWUoe1xuICAgICAgICBibG9jayxcbiAgICAgICAgcmVzb2x2ZSxcbiAgICAgICAgcmVqZWN0LFxuICAgICAgICB1bnNhZmUsXG4gICAgICB9KTtcblxuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgICB0aGlzLnBlcnNpc3RCbG9ja3NBc3luYygpO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHBlcnNpc3RIZWFkZXJzKF9oZWFkZXJzOiByZWFkb25seSBIZWFkZXJbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIFdlIGRvbid0IGV2ZXIganVzdCBwZXJzaXN0IHRoZSBoZWFkZXJzLlxuICB9XG5cbiAgcHVibGljIGFzeW5jIHZlcmlmeUJsb2NrKGJsb2NrOiBCbG9jayk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGJsb2NrLnZlcmlmeSh7XG4gICAgICBnZW5lc2lzQmxvY2s6IHRoaXMuc2V0dGluZ3MuZ2VuZXNpc0Jsb2NrLFxuICAgICAgdHJ5R2V0QmxvY2s6IHRoaXMuYmxvY2sudHJ5R2V0LFxuICAgICAgdHJ5R2V0SGVhZGVyOiB0aGlzLmhlYWRlci50cnlHZXQsXG4gICAgICBpc1NwZW50OiB0aGlzLmlzU3BlbnQsXG4gICAgICBnZXRBc3NldDogdGhpcy5hc3NldC5nZXQsXG4gICAgICBnZXRPdXRwdXQ6IHRoaXMub3V0cHV0LmdldCxcbiAgICAgIHRyeUdldEFjY291bnQ6IHRoaXMuYWNjb3VudC50cnlHZXQsXG4gICAgICBnZXRWYWxpZGF0b3JzOiB0aGlzLmdldFZhbGlkYXRvcnMsXG4gICAgICBzdGFuZGJ5VmFsaWRhdG9yczogdGhpcy5zZXR0aW5ncy5zdGFuZGJ5VmFsaWRhdG9ycyxcbiAgICAgIGdldEFsbFZhbGlkYXRvcnM6IHRoaXMuZ2V0QWxsVmFsaWRhdG9ycyxcbiAgICAgIGNhbGN1bGF0ZUNsYWltQW1vdW50OiBhc3luYyAoY2xhaW1zKSA9PiB0aGlzLmNhbGN1bGF0ZUNsYWltQW1vdW50KGNsYWltcyksXG4gICAgICB2ZXJpZnlTY3JpcHQ6IGFzeW5jIChvcHRpb25zKSA9PiB0aGlzLnZlcmlmeVNjcmlwdChvcHRpb25zKSxcbiAgICAgIGN1cnJlbnRIZWlnaHQ6IHRoaXMubXV0YWJsZUN1cnJlbnRCbG9jayA9PT0gdW5kZWZpbmVkID8gMCA6IHRoaXMubXV0YWJsZUN1cnJlbnRCbG9jay5pbmRleCxcbiAgICAgIGdvdmVybmluZ1Rva2VuOiB0aGlzLnNldHRpbmdzLmdvdmVybmluZ1Rva2VuLFxuICAgICAgdXRpbGl0eVRva2VuOiB0aGlzLnNldHRpbmdzLnV0aWxpdHlUb2tlbixcbiAgICAgIGZlZXM6IHRoaXMuc2V0dGluZ3MuZmVlcyxcbiAgICAgIHJlZ2lzdGVyVmFsaWRhdG9yRmVlOiB0aGlzLnNldHRpbmdzLnJlZ2lzdGVyVmFsaWRhdG9yRmVlLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHZlcmlmeUNvbnNlbnN1c1BheWxvYWQocGF5bG9hZDogQ29uc2Vuc3VzUGF5bG9hZCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHBheWxvYWQudmVyaWZ5KHtcbiAgICAgIGdldFZhbGlkYXRvcnM6IGFzeW5jICgpID0+IHRoaXMuZ2V0VmFsaWRhdG9ycyhbXSksXG4gICAgICB2ZXJpZnlTY3JpcHQ6IGFzeW5jIChvcHRpb25zKSA9PiB0aGlzLnZlcmlmeVNjcmlwdChvcHRpb25zKSxcbiAgICAgIGN1cnJlbnRJbmRleDogdGhpcy5tdXRhYmxlQ3VycmVudEJsb2NrID09PSB1bmRlZmluZWQgPyAwIDogdGhpcy5tdXRhYmxlQ3VycmVudEJsb2NrLmluZGV4LFxuICAgICAgY3VycmVudEJsb2NrSGFzaDogdGhpcy5jdXJyZW50QmxvY2suaGFzaCxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyB2ZXJpZnlUcmFuc2FjdGlvbih7XG4gICAgdHJhbnNhY3Rpb24sXG4gICAgbWVtUG9vbCxcbiAgfToge1xuICAgIHJlYWRvbmx5IHRyYW5zYWN0aW9uOiBUcmFuc2FjdGlvbjtcbiAgICByZWFkb25seSBtZW1Qb29sPzogcmVhZG9ubHkgVHJhbnNhY3Rpb25bXTtcbiAgfSk6IFByb21pc2U8VmVyaWZ5VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdmVyaWZpY2F0aW9ucyA9IGF3YWl0IHRyYW5zYWN0aW9uLnZlcmlmeSh7XG4gICAgICAgIGNhbGN1bGF0ZUNsYWltQW1vdW50OiB0aGlzLmNhbGN1bGF0ZUNsYWltQW1vdW50LFxuICAgICAgICBpc1NwZW50OiB0aGlzLmlzU3BlbnQsXG4gICAgICAgIGdldEFzc2V0OiB0aGlzLmFzc2V0LmdldCxcbiAgICAgICAgZ2V0T3V0cHV0OiB0aGlzLm91dHB1dC5nZXQsXG4gICAgICAgIHRyeUdldEFjY291bnQ6IHRoaXMuYWNjb3VudC50cnlHZXQsXG4gICAgICAgIHN0YW5kYnlWYWxpZGF0b3JzOiB0aGlzLnNldHRpbmdzLnN0YW5kYnlWYWxpZGF0b3JzLFxuICAgICAgICBnZXRBbGxWYWxpZGF0b3JzOiB0aGlzLmdldEFsbFZhbGlkYXRvcnMsXG4gICAgICAgIHZlcmlmeVNjcmlwdDogYXN5bmMgKG9wdGlvbnMpID0+IHRoaXMudmVyaWZ5U2NyaXB0KG9wdGlvbnMpLFxuICAgICAgICBnb3Zlcm5pbmdUb2tlbjogdGhpcy5zZXR0aW5ncy5nb3Zlcm5pbmdUb2tlbixcbiAgICAgICAgdXRpbGl0eVRva2VuOiB0aGlzLnNldHRpbmdzLnV0aWxpdHlUb2tlbixcbiAgICAgICAgZmVlczogdGhpcy5zZXR0aW5ncy5mZWVzLFxuICAgICAgICByZWdpc3RlclZhbGlkYXRvckZlZTogdGhpcy5zZXR0aW5ncy5yZWdpc3RlclZhbGlkYXRvckZlZSxcbiAgICAgICAgY3VycmVudEhlaWdodDogdGhpcy5jdXJyZW50QmxvY2tJbmRleCxcbiAgICAgICAgbWVtUG9vbCxcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4geyB2ZXJpZmljYXRpb25zIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvci5jb2RlID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIGVycm9yLmNvZGUgIT09ICdzdHJpbmcnIHx8ICFlcnJvci5jb2RlLmluY2x1ZGVzKCdWRVJJRlknKSkge1xuICAgICAgICB0aHJvdyBuZXcgVW5rbm93blZlcmlmeUVycm9yKGVycm9yLm1lc3NhZ2UpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgaW52b2tlU2NyaXB0KHNjcmlwdDogQnVmZmVyKTogUHJvbWlzZTxDYWxsUmVjZWlwdD4ge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gbmV3IEludm9jYXRpb25UcmFuc2FjdGlvbih7XG4gICAgICBzY3JpcHQsXG4gICAgICBnYXM6IGNvbW1vbi5PTkVfSFVORFJFRF9GSVhFRDgsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5pbnZva2VUcmFuc2FjdGlvbih0cmFuc2FjdGlvbik7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgaW52b2tlVHJhbnNhY3Rpb24odHJhbnNhY3Rpb246IEludm9jYXRpb25UcmFuc2FjdGlvbik6IFByb21pc2U8Q2FsbFJlY2VpcHQ+IHtcbiAgICBjb25zdCBibG9ja2NoYWluID0gdGhpcy5jcmVhdGVXcml0ZUJsb2NrY2hhaW4oKTtcblxuICAgIGNvbnN0IG11dGFibGVBY3Rpb25zOiBBY3Rpb25bXSA9IFtdO1xuICAgIGxldCBnbG9iYWxBY3Rpb25JbmRleCA9IG5ldyBCTigwKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3cmFwRXhlY3V0ZVNjcmlwdHMoYXN5bmMgKCkgPT5cbiAgICAgIHRoaXMudm0uZXhlY3V0ZVNjcmlwdHMoe1xuICAgICAgICBzY3JpcHRzOiBbeyBjb2RlOiB0cmFuc2FjdGlvbi5zY3JpcHQgfV0sXG4gICAgICAgIGJsb2NrY2hhaW4sXG4gICAgICAgIHNjcmlwdENvbnRhaW5lcjoge1xuICAgICAgICAgIHR5cGU6IFNjcmlwdENvbnRhaW5lclR5cGUuVHJhbnNhY3Rpb24sXG4gICAgICAgICAgdmFsdWU6IHRyYW5zYWN0aW9uLFxuICAgICAgICB9LFxuICAgICAgICBsaXN0ZW5lcnM6IHtcbiAgICAgICAgICBvbkxvZzogKHsgbWVzc2FnZSwgc2NyaXB0SGFzaCB9KSA9PiB7XG4gICAgICAgICAgICBtdXRhYmxlQWN0aW9ucy5wdXNoKFxuICAgICAgICAgICAgICBuZXcgTG9nQWN0aW9uKHtcbiAgICAgICAgICAgICAgICBpbmRleDogZ2xvYmFsQWN0aW9uSW5kZXgsXG4gICAgICAgICAgICAgICAgc2NyaXB0SGFzaCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGdsb2JhbEFjdGlvbkluZGV4ID0gZ2xvYmFsQWN0aW9uSW5kZXguYWRkKHV0aWxzLk9ORSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICBvbk5vdGlmeTogKHsgYXJncywgc2NyaXB0SGFzaCB9KSA9PiB7XG4gICAgICAgICAgICBtdXRhYmxlQWN0aW9ucy5wdXNoKFxuICAgICAgICAgICAgICBuZXcgTm90aWZpY2F0aW9uQWN0aW9uKHtcbiAgICAgICAgICAgICAgICBpbmRleDogZ2xvYmFsQWN0aW9uSW5kZXgsXG4gICAgICAgICAgICAgICAgc2NyaXB0SGFzaCxcbiAgICAgICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGdsb2JhbEFjdGlvbkluZGV4ID0gZ2xvYmFsQWN0aW9uSW5kZXguYWRkKHV0aWxzLk9ORSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcblxuICAgICAgICB0cmlnZ2VyVHlwZTogVHJpZ2dlclR5cGUuQXBwbGljYXRpb24sXG4gICAgICAgIGFjdGlvbjogTlVMTF9BQ1RJT04sXG4gICAgICAgIGdhczogdHJhbnNhY3Rpb24uZ2FzLFxuICAgICAgICBza2lwV2l0bmVzc1ZlcmlmeTogdHJ1ZSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVzdWx0LFxuICAgICAgYWN0aW9uczogbXV0YWJsZUFjdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZXNldCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnN0b3AoKTtcbiAgICBhd2FpdCB0aGlzLnN0b3JhZ2UucmVzZXQoKTtcbiAgICB0aGlzLm11dGFibGVDdXJyZW50SGVhZGVyID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubXV0YWJsZUN1cnJlbnRCbG9jayA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm11dGFibGVQcmV2aW91c0Jsb2NrID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuc3RhcnQoKTtcbiAgICBhd2FpdCB0aGlzLnBlcnNpc3RIZWFkZXJzKFt0aGlzLnNldHRpbmdzLmdlbmVzaXNCbG9jay5oZWFkZXJdKTtcbiAgICBhd2FpdCB0aGlzLnBlcnNpc3RCbG9jayh7IGJsb2NrOiB0aGlzLnNldHRpbmdzLmdlbmVzaXNCbG9jayB9KTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBnZXRWYWxpZGF0b3JzID0gYXN5bmMgKHRyYW5zYWN0aW9uczogcmVhZG9ubHkgVHJhbnNhY3Rpb25bXSk6IFByb21pc2U8cmVhZG9ubHkgRUNQb2ludFtdPiA9PiB7XG4gICAgbG9nZ2VyLmRlYnVnKHsgdGl0bGU6ICduZW9fYmxvY2tjaGFpbl9nZXRfdmFsaWRhdG9ycycgfSk7XG5cbiAgICByZXR1cm4gZ2V0VmFsaWRhdG9ycyh0aGlzLCB0cmFuc2FjdGlvbnMpO1xuICB9O1xuXG4gIHB1YmxpYyByZWFkb25seSBjYWxjdWxhdGVDbGFpbUFtb3VudCA9IGFzeW5jIChjbGFpbXM6IHJlYWRvbmx5IElucHV0W10pOiBQcm9taXNlPEJOPiA9PiB7XG4gICAgbG9nZ2VyLmRlYnVnKHsgdGl0bGU6ICduZW9fYmxvY2tjaGFpbl9jYWxjdWxhdGVfY2xhaW1fYW1vdW50JyB9KTtcbiAgICBjb25zdCBzcGVudENvaW5zID0gYXdhaXQgUHJvbWlzZS5hbGwoY2xhaW1zLm1hcChhc3luYyAoY2xhaW0pID0+IHRoaXMudHJ5R2V0U3BlbnRDb2luKGNsYWltKSkpO1xuXG4gICAgY29uc3QgZmlsdGVyZWRTcGVudENvaW5zSW4gPSBzcGVudENvaW5zLmZpbHRlcihjb21tb25VdGlscy5ub3ROdWxsKTtcbiAgICBpZiAoc3BlbnRDb2lucy5sZW5ndGggIT09IGZpbHRlcmVkU3BlbnRDb2luc0luLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IENvaW5VbnNwZW50RXJyb3Ioc3BlbnRDb2lucy5sZW5ndGggLSBmaWx0ZXJlZFNwZW50Q29pbnNJbi5sZW5ndGgpO1xuICAgIH1cblxuICAgIGNvbnN0IGZpbHRlcmVkU3BlbnRDb2lucyA9IGZpbHRlcmVkU3BlbnRDb2luc0luLmZpbHRlcigoc3BlbnRDb2luKSA9PiB7XG4gICAgICBpZiAoc3BlbnRDb2luLmNsYWltZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvaW5DbGFpbWVkRXJyb3IoY29tbW9uLnVJbnQyNTZUb1N0cmluZyhzcGVudENvaW4ub3V0cHV0LmFzc2V0KSwgc3BlbnRDb2luLm91dHB1dC52YWx1ZS50b1N0cmluZygxMCkpO1xuICAgICAgfVxuICAgICAgaWYgKCFjb21tb24udUludDI1NkVxdWFsKHNwZW50Q29pbi5vdXRwdXQuYXNzZXQsIHRoaXMuc2V0dGluZ3MuZ292ZXJuaW5nVG9rZW4uaGFzaCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRDbGFpbUVycm9yKFxuICAgICAgICAgIGNvbW1vbi51SW50MjU2VG9TdHJpbmcoc3BlbnRDb2luLm91dHB1dC5hc3NldCksXG4gICAgICAgICAgY29tbW9uLnVJbnQyNTZUb1N0cmluZyh0aGlzLnNldHRpbmdzLmdvdmVybmluZ1Rva2VuLmhhc2gpLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9KTtcblxuICAgIHJldHVybiB1dGlscy5jYWxjdWxhdGVDbGFpbUFtb3VudCh7XG4gICAgICBjb2luczogZmlsdGVyZWRTcGVudENvaW5zLm1hcCgoY29pbikgPT4gKHtcbiAgICAgICAgdmFsdWU6IGNvaW4ub3V0cHV0LnZhbHVlLFxuICAgICAgICBzdGFydEhlaWdodDogY29pbi5zdGFydEhlaWdodCxcbiAgICAgICAgZW5kSGVpZ2h0OiBjb2luLmVuZEhlaWdodCxcbiAgICAgIH0pKSxcblxuICAgICAgZGVjcmVtZW50SW50ZXJ2YWw6IHRoaXMuc2V0dGluZ3MuZGVjcmVtZW50SW50ZXJ2YWwsXG4gICAgICBnZW5lcmF0aW9uQW1vdW50OiB0aGlzLnNldHRpbmdzLmdlbmVyYXRpb25BbW91bnQsXG4gICAgICBnZXRTeXN0ZW1GZWU6IGFzeW5jIChpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBoZWFkZXIgPSBhd2FpdCB0aGlzLmhlYWRlci5nZXQoe1xuICAgICAgICAgIGhhc2hPckluZGV4OiBpbmRleCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgYmxvY2tEYXRhID0gYXdhaXQgdGhpcy5ibG9ja0RhdGEuZ2V0KHtcbiAgICAgICAgICBoYXNoOiBoZWFkZXIuaGFzaCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGJsb2NrRGF0YS5zeXN0ZW1GZWU7XG4gICAgICB9LFxuICAgIH0pO1xuICB9O1xuXG4gIHByaXZhdGUgYXN5bmMgcGVyc2lzdEJsb2Nrc0FzeW5jKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm11dGFibGVQZXJzaXN0aW5nQmxvY2tzIHx8ICF0aGlzLm11dGFibGVSdW5uaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5tdXRhYmxlUGVyc2lzdGluZ0Jsb2NrcyA9IHRydWU7XG4gICAgbGV0IGVudHJ5OiBFbnRyeSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgZW50cnkgPSB0aGlzLmNsZWFuQmxvY2tRdWV1ZSgpO1xuXG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tbG9vcC1zdGF0ZW1lbnRcbiAgICAgIHdoaWxlICh0aGlzLm11dGFibGVSdW5uaW5nICYmIGVudHJ5ICE9PSB1bmRlZmluZWQgJiYgZW50cnkuYmxvY2suaW5kZXggPT09IHRoaXMuY3VycmVudEJsb2NrSW5kZXggKyAxKSB7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAgICAgY29uc3QgZW50cnlOb25OdWxsID0gZW50cnk7XG4gICAgICAgIGNvbnN0IGxvZ0RhdGEgPSB7XG4gICAgICAgICAgW0xhYmVscy5ORU9fQkxPQ0tfSU5ERVhdOiBlbnRyeS5ibG9jay5pbmRleCxcbiAgICAgICAgICB0aXRsZTogJ25lb19ibG9ja2NoYWluX3BlcnNpc3RfYmxvY2tfdG9wX2xldmVsJyxcbiAgICAgICAgfTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnBlcnNpc3RCbG9ja0ludGVybmFsKGVudHJ5Tm9uTnVsbC5ibG9jaywgZW50cnlOb25OdWxsLnVuc2FmZSk7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKGxvZ0RhdGEpO1xuICAgICAgICAgIGdsb2JhbFN0YXRzLnJlY29yZChbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG1lYXN1cmU6IGJsb2NrRHVyYXRpb25NcyxcbiAgICAgICAgICAgICAgdmFsdWU6IERhdGUubm93KCkgLSBzdGFydFRpbWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGxvZ2dlci5lcnJvcih7IGVycm9yLCAuLi5sb2dEYXRhIH0pO1xuICAgICAgICAgIGdsb2JhbFN0YXRzLnJlY29yZChbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIG1lYXN1cmU6IGJsb2NrRmFpbHVyZXMsXG4gICAgICAgICAgICAgIHZhbHVlOiAxLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdKTtcblxuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG5cbiAgICAgICAgZW50cnkucmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLm11dGFibGVCbG9jayQubmV4dChlbnRyeS5ibG9jayk7XG4gICAgICAgIGdsb2JhbFN0YXRzLnJlY29yZChbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWVhc3VyZTogYmxvY2tDdXJyZW50LFxuICAgICAgICAgICAgdmFsdWU6IGVudHJ5LmJsb2NrLmluZGV4LFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWVhc3VyZTogYmxvY2tMYXRlbmN5U2VjLFxuICAgICAgICAgICAgdmFsdWU6IERhdGUubm93KCkgLSBlbnRyeS5ibG9jay50aW1lc3RhbXAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG5cbiAgICAgICAgZW50cnkgPSB0aGlzLmNsZWFuQmxvY2tRdWV1ZSgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZW50cnkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLm11dGFibGVCbG9ja1F1ZXVlLnF1ZXVlKGVudHJ5KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVudHJ5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZW50cnkucmVqZWN0KGVycm9yKTtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5tdXRhYmxlUGVyc2lzdGluZ0Jsb2NrcyA9IGZhbHNlO1xuICAgICAgaWYgKHRoaXMubXV0YWJsZURvbmVSdW5uaW5nUmVzb2x2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMubXV0YWJsZURvbmVSdW5uaW5nUmVzb2x2ZSgpO1xuICAgICAgICB0aGlzLm11dGFibGVEb25lUnVubmluZ1Jlc29sdmUgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjbGVhbkJsb2NrUXVldWUoKTogRW50cnkgfCB1bmRlZmluZWQge1xuICAgIGxldCBlbnRyeSA9IHRoaXMuZGVxdWVCbG9ja1F1ZXVlKCk7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gICAgd2hpbGUgKGVudHJ5ICE9PSB1bmRlZmluZWQgJiYgZW50cnkuYmxvY2suaW5kZXggPD0gdGhpcy5jdXJyZW50QmxvY2tJbmRleCkge1xuICAgICAgZW50cnkucmVzb2x2ZSgpO1xuICAgICAgZW50cnkgPSB0aGlzLmRlcXVlQmxvY2tRdWV1ZSgpO1xuICAgIH1cblxuICAgIHJldHVybiBlbnRyeTtcbiAgfVxuXG4gIHByaXZhdGUgZGVxdWVCbG9ja1F1ZXVlKCk6IEVudHJ5IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy5tdXRhYmxlQmxvY2tRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gdGhpcy5tdXRhYmxlQmxvY2tRdWV1ZS5kZXF1ZXVlKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgdmVyaWZ5U2NyaXB0ID0gYXN5bmMgKHtcbiAgICBzY3JpcHRDb250YWluZXIsXG4gICAgaGFzaCxcbiAgICB3aXRuZXNzLFxuICB9OiBWZXJpZnlTY3JpcHRPcHRpb25zKTogUHJvbWlzZTxWZXJpZnlTY3JpcHRSZXN1bHQ+ID0+IHtcbiAgICBsZXQgeyB2ZXJpZmljYXRpb24gfSA9IHdpdG5lc3M7XG4gICAgaWYgKHZlcmlmaWNhdGlvbi5sZW5ndGggPT09IDApIHtcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgU2NyaXB0QnVpbGRlcigpO1xuICAgICAgYnVpbGRlci5lbWl0QXBwQ2FsbFZlcmlmaWNhdGlvbihoYXNoKTtcbiAgICAgIHZlcmlmaWNhdGlvbiA9IGJ1aWxkZXIuYnVpbGQoKTtcbiAgICB9IGVsc2UgaWYgKCFjb21tb24udUludDE2MEVxdWFsKGhhc2gsIGNyeXB0by50b1NjcmlwdEhhc2godmVyaWZpY2F0aW9uKSkpIHtcbiAgICAgIHRocm93IG5ldyBXaXRuZXNzVmVyaWZ5RXJyb3IoKTtcbiAgICB9XG5cbiAgICBjb25zdCBibG9ja2NoYWluID0gdGhpcy5jcmVhdGVXcml0ZUJsb2NrY2hhaW4oKTtcbiAgICBjb25zdCBtdXRhYmxlQWN0aW9uczogQWN0aW9uW10gPSBbXTtcbiAgICBsZXQgZ2xvYmFsQWN0aW9uSW5kZXggPSBuZXcgQk4oMCk7XG4gICAgY29uc3QgZXhlY3V0ZVJlc3VsdCA9IGF3YWl0IHRoaXMudm0uZXhlY3V0ZVNjcmlwdHMoe1xuICAgICAgc2NyaXB0czogW3sgY29kZTogd2l0bmVzcy5pbnZvY2F0aW9uIH0sIHsgY29kZTogdmVyaWZpY2F0aW9uIH1dLFxuICAgICAgYmxvY2tjaGFpbixcbiAgICAgIHNjcmlwdENvbnRhaW5lcixcbiAgICAgIHRyaWdnZXJUeXBlOiBUcmlnZ2VyVHlwZS5WZXJpZmljYXRpb24sXG4gICAgICBhY3Rpb246IE5VTExfQUNUSU9OLFxuICAgICAgZ2FzOiB1dGlscy5PTkVfSFVORFJFRF9NSUxMSU9OLFxuICAgICAgbGlzdGVuZXJzOiB7XG4gICAgICAgIG9uTG9nOiAoeyBtZXNzYWdlLCBzY3JpcHRIYXNoIH0pID0+IHtcbiAgICAgICAgICBtdXRhYmxlQWN0aW9ucy5wdXNoKFxuICAgICAgICAgICAgbmV3IExvZ0FjdGlvbih7XG4gICAgICAgICAgICAgIGluZGV4OiBnbG9iYWxBY3Rpb25JbmRleCxcbiAgICAgICAgICAgICAgc2NyaXB0SGFzaCxcbiAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBnbG9iYWxBY3Rpb25JbmRleCA9IGdsb2JhbEFjdGlvbkluZGV4LmFkZCh1dGlscy5PTkUpO1xuICAgICAgICB9LFxuICAgICAgICBvbk5vdGlmeTogKHsgYXJncywgc2NyaXB0SGFzaCB9KSA9PiB7XG4gICAgICAgICAgbXV0YWJsZUFjdGlvbnMucHVzaChcbiAgICAgICAgICAgIG5ldyBOb3RpZmljYXRpb25BY3Rpb24oe1xuICAgICAgICAgICAgICBpbmRleDogZ2xvYmFsQWN0aW9uSW5kZXgsXG4gICAgICAgICAgICAgIHNjcmlwdEhhc2gsXG4gICAgICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgZ2xvYmFsQWN0aW9uSW5kZXggPSBnbG9iYWxBY3Rpb25JbmRleC5hZGQodXRpbHMuT05FKTtcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0ID0geyBhY3Rpb25zOiBtdXRhYmxlQWN0aW9ucywgaGFzaCwgd2l0bmVzcyB9O1xuXG4gICAgY29uc3QgeyBzdGFjaywgc3RhdGUsIGVycm9yTWVzc2FnZSB9ID0gZXhlY3V0ZVJlc3VsdDtcbiAgICBpZiAoc3RhdGUgPT09IFZNU3RhdGUuRmF1bHQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgZmFpbHVyZU1lc3NhZ2U6IGVycm9yTWVzc2FnZSA9PT0gdW5kZWZpbmVkID8gJ1NjcmlwdCBleGVjdXRpb24gZW5kZWQgaW4gYSBGQVVMVCBzdGF0ZScgOiBlcnJvck1lc3NhZ2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChzdGFjay5sZW5ndGggIT09IDEpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnJlc3VsdCxcbiAgICAgICAgZmFpbHVyZU1lc3NhZ2U6XG4gICAgICAgICAgYFZlcmlmaWNhdGlvbiBkaWQgbm90IHJldHVybiBvbmUgcmVzdWx0LiBUaGlzIG1heSBiZSBhIGJ1ZyBpbiB0aGUgYCArXG4gICAgICAgICAgYHNtYXJ0IGNvbnRyYWN0IGNvbXBpbGVyIG9yIHRoZSBzbWFydCBjb250cmFjdCBpdHNlbGYuIElmIHlvdSBhcmUgdXNpbmcgdGhlIE5FT+KAok9ORSBjb21waWxlciBwbGVhc2UgZmlsZSBhbiBpc3N1ZS4gRm91bmQgJHtzdGFjay5sZW5ndGh9IHJlc3VsdHMuYCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgdG9wID0gc3RhY2tbMF07XG4gICAgaWYgKCF0b3AuYXNCb29sZWFuKCkpIHtcbiAgICAgIHJldHVybiB7IC4uLnJlc3VsdCwgZmFpbHVyZU1lc3NhZ2U6ICdWZXJpZmljYXRpb24gZGlkIG5vdCBzdWNjZWVkLicgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgdHJ5R2V0SW52b2NhdGlvbkRhdGEgPSBhc3luYyAoXG4gICAgdHJhbnNhY3Rpb246IEludm9jYXRpb25UcmFuc2FjdGlvbixcbiAgKTogUHJvbWlzZTxTZXJpYWxpemFibGVJbnZvY2F0aW9uRGF0YSB8IHVuZGVmaW5lZD4gPT4ge1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLmludm9jYXRpb25EYXRhLnRyeUdldCh7XG4gICAgICBoYXNoOiB0cmFuc2FjdGlvbi5oYXNoLFxuICAgIH0pO1xuXG4gICAgaWYgKGRhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCBbYXNzZXQsIGNvbnRyYWN0cywgYWN0aW9uc10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICBkYXRhLmFzc2V0SGFzaCA9PT0gdW5kZWZpbmVkID8gUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCkgOiB0aGlzLmFzc2V0LmdldCh7IGhhc2g6IGRhdGEuYXNzZXRIYXNoIH0pLFxuICAgICAgUHJvbWlzZS5hbGwoZGF0YS5jb250cmFjdEhhc2hlcy5tYXAoYXN5bmMgKGNvbnRyYWN0SGFzaCkgPT4gdGhpcy5jb250cmFjdC50cnlHZXQoeyBoYXNoOiBjb250cmFjdEhhc2ggfSkpKSxcbiAgICAgIGRhdGEuYWN0aW9uSW5kZXhTdGFydC5lcShkYXRhLmFjdGlvbkluZGV4U3RvcClcbiAgICAgICAgPyBQcm9taXNlLnJlc29sdmUoW10pXG4gICAgICAgIDogdGhpcy5hY3Rpb25cbiAgICAgICAgICAgIC5nZXRBbGwkKHtcbiAgICAgICAgICAgICAgaW5kZXhTdGFydDogZGF0YS5hY3Rpb25JbmRleFN0YXJ0LFxuICAgICAgICAgICAgICBpbmRleFN0b3A6IGRhdGEuYWN0aW9uSW5kZXhTdG9wLnN1Yih1dGlscy5PTkUpLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5waXBlKHRvQXJyYXkoKSlcbiAgICAgICAgICAgIC50b1Byb21pc2UoKSxcbiAgICBdKTtcblxuICAgIHJldHVybiB7XG4gICAgICBhc3NldCxcbiAgICAgIGNvbnRyYWN0czogY29udHJhY3RzLmZpbHRlcihjb21tb25VdGlscy5ub3ROdWxsKSxcbiAgICAgIGRlbGV0ZWRDb250cmFjdEhhc2hlczogZGF0YS5kZWxldGVkQ29udHJhY3RIYXNoZXMsXG4gICAgICBtaWdyYXRlZENvbnRyYWN0SGFzaGVzOiBkYXRhLm1pZ3JhdGVkQ29udHJhY3RIYXNoZXMsXG4gICAgICB2b3RlVXBkYXRlczogZGF0YS52b3RlVXBkYXRlcyxcbiAgICAgIHJlc3VsdDogZGF0YS5yZXN1bHQsXG4gICAgICBhY3Rpb25zLFxuICAgICAgc3RvcmFnZUNoYW5nZXM6IGRhdGEuc3RvcmFnZUNoYW5nZXMsXG4gICAgfTtcbiAgfTtcbiAgcHJpdmF0ZSByZWFkb25seSB0cnlHZXRUcmFuc2FjdGlvbkRhdGEgPSBhc3luYyAodHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogUHJvbWlzZTxUcmFuc2FjdGlvbkRhdGEgfCB1bmRlZmluZWQ+ID0+XG4gICAgdGhpcy50cmFuc2FjdGlvbkRhdGEudHJ5R2V0KHsgaGFzaDogdHJhbnNhY3Rpb24uaGFzaCB9KTtcbiAgcHJpdmF0ZSByZWFkb25seSBnZXRVbmNsYWltZWQgPSBhc3luYyAoaGFzaDogVUludDE2MCk6IFByb21pc2U8cmVhZG9ubHkgSW5wdXRbXT4gPT5cbiAgICB0aGlzLmFjY291bnRVbmNsYWltZWRcbiAgICAgIC5nZXRBbGwkKHsgaGFzaCB9KVxuICAgICAgLnBpcGUodG9BcnJheSgpKVxuICAgICAgLnRvUHJvbWlzZSgpXG4gICAgICAudGhlbigodmFsdWVzKSA9PiB2YWx1ZXMubWFwKCh2YWx1ZSkgPT4gdmFsdWUuaW5wdXQpKTtcbiAgcHJpdmF0ZSByZWFkb25seSBnZXRVbnNwZW50ID0gYXN5bmMgKGhhc2g6IFVJbnQxNjApOiBQcm9taXNlPHJlYWRvbmx5IElucHV0W10+ID0+IHtcbiAgICBjb25zdCB1bnNwZW50ID0gYXdhaXQgdGhpcy5hY2NvdW50VW5zcGVudFxuICAgICAgLmdldEFsbCQoeyBoYXNoIH0pXG4gICAgICAucGlwZSh0b0FycmF5KCkpXG4gICAgICAudG9Qcm9taXNlKCk7XG5cbiAgICByZXR1cm4gdW5zcGVudC5tYXAoKHZhbHVlKSA9PiB2YWx1ZS5pbnB1dCk7XG4gIH07XG4gIHByaXZhdGUgcmVhZG9ubHkgZ2V0QWxsVmFsaWRhdG9ycyA9IGFzeW5jICgpOiBQcm9taXNlPHJlYWRvbmx5IFZhbGlkYXRvcltdPiA9PlxuICAgIHRoaXMudmFsaWRhdG9yLmFsbCQucGlwZSh0b0FycmF5KCkpLnRvUHJvbWlzZSgpO1xuICBwcml2YXRlIHJlYWRvbmx5IGlzU3BlbnQgPSBhc3luYyAoaW5wdXQ6IE91dHB1dEtleSk6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uRGF0YSA9IGF3YWl0IHRoaXMudHJhbnNhY3Rpb25EYXRhLnRyeUdldCh7XG4gICAgICBoYXNoOiBpbnB1dC5oYXNoLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIHRyYW5zYWN0aW9uRGF0YSAhPT0gdW5kZWZpbmVkICYmICh0cmFuc2FjdGlvbkRhdGEuZW5kSGVpZ2h0c1tpbnB1dC5pbmRleF0gYXMgbnVtYmVyIHwgdW5kZWZpbmVkKSAhPT0gdW5kZWZpbmVkXG4gICAgKTtcbiAgfTtcbiAgcHJpdmF0ZSByZWFkb25seSB0cnlHZXRTcGVudENvaW4gPSBhc3luYyAoaW5wdXQ6IElucHV0KTogUHJvbWlzZTxTcGVudENvaW4gfCB1bmRlZmluZWQ+ID0+IHtcbiAgICBjb25zdCBbdHJhbnNhY3Rpb25EYXRhLCBvdXRwdXRdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgdGhpcy50cmFuc2FjdGlvbkRhdGEudHJ5R2V0KHsgaGFzaDogaW5wdXQuaGFzaCB9KSxcbiAgICAgIHRoaXMub3V0cHV0LmdldChpbnB1dCksXG4gICAgXSk7XG5cbiAgICBpZiAodHJhbnNhY3Rpb25EYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgZW5kSGVpZ2h0ID0gdHJhbnNhY3Rpb25EYXRhLmVuZEhlaWdodHNbaW5wdXQuaW5kZXhdIGFzIG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICBpZiAoZW5kSGVpZ2h0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgY2xhaW1lZCA9IHRyYW5zYWN0aW9uRGF0YS5jbGFpbWVkW2lucHV0LmluZGV4XTtcblxuICAgIHJldHVybiB7XG4gICAgICBvdXRwdXQsXG4gICAgICBzdGFydEhlaWdodDogdHJhbnNhY3Rpb25EYXRhLnN0YXJ0SGVpZ2h0LFxuICAgICAgZW5kSGVpZ2h0LFxuICAgICAgY2xhaW1lZDogISFjbGFpbWVkLFxuICAgIH07XG4gIH07XG5cbiAgcHJpdmF0ZSBzdGFydCgpOiB2b2lkIHtcbiAgICB0aGlzLm11dGFibGVCbG9jayQgPSBuZXcgU3ViamVjdCgpO1xuICAgIHRoaXMubXV0YWJsZVBlcnNpc3RpbmdCbG9ja3MgPSBmYWxzZTtcbiAgICB0aGlzLm11dGFibGVCbG9ja1F1ZXVlID0gbmV3IFByaW9yaXR5UXVldWUoe1xuICAgICAgY29tcGFyYXRvcjogKGEsIGIpID0+IGEuYmxvY2suaW5kZXggLSBiLmJsb2NrLmluZGV4LFxuICAgIH0pO1xuXG4gICAgdGhpcy5tdXRhYmxlSW5RdWV1ZSA9IG5ldyBTZXQoKTtcbiAgICB0aGlzLm11dGFibGVEb25lUnVubmluZ1Jlc29sdmUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5tdXRhYmxlUnVubmluZyA9IHRydWU7XG4gICAgbG9nZ2VyLmluZm8oeyB0aXRsZTogJ25lb19ibG9ja2NoYWluX3N0YXJ0JyB9LCAnTkVPIGJsb2NrY2hhaW4gc3RhcnRlZC4nKTtcbiAgfVxuXG4gIC8vIHByaXZhdGUgcmVhZG9ubHkgZ2V0Vm90ZXMgPSBhc3luYyAodHJhbnNhY3Rpb25zOiByZWFkb25seSBUcmFuc2FjdGlvbltdKTogUHJvbWlzZTxyZWFkb25seSBWb3RlW10+ID0+IHtcbiAgLy8gICBjb25zdCBpbnB1dHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgLy8gICAgIHRyYW5zYWN0aW9ucy5tYXAoYXN5bmMgKHRyYW5zYWN0aW9uKSA9PlxuICAvLyAgICAgICB0cmFuc2FjdGlvbi5nZXRSZWZlcmVuY2VzKHtcbiAgLy8gICAgICAgICBnZXRPdXRwdXQ6IHRoaXMub3V0cHV0LmdldCxcbiAgLy8gICAgICAgfSksXG4gIC8vICAgICApLFxuICAvLyAgICkudGhlbigocmVzdWx0cykgPT5cbiAgLy8gICAgIHJlc3VsdHMucmVkdWNlKChhY2MsIGlucHV0UmVzdWx0cykgPT4gYWNjLmNvbmNhdChpbnB1dFJlc3VsdHMpLCBbXSkubWFwKChvdXRwdXQpID0+ICh7XG4gIC8vICAgICAgIGFkZHJlc3M6IG91dHB1dC5hZGRyZXNzLFxuICAvLyAgICAgICBhc3NldDogb3V0cHV0LmFzc2V0LFxuICAvLyAgICAgICB2YWx1ZTogb3V0cHV0LnZhbHVlLm5lZygpLFxuICAvLyAgICAgfSkpLFxuICAvLyAgICk7XG5cbiAgLy8gICBjb25zdCBvdXRwdXRzID0gdHJhbnNhY3Rpb25zXG4gIC8vICAgICAucmVkdWNlPHJlYWRvbmx5IE91dHB1dFtdPigoYWNjLCB0cmFuc2FjdGlvbikgPT4gYWNjLmNvbmNhdCh0cmFuc2FjdGlvbi5vdXRwdXRzKSwgW10pXG4gIC8vICAgICAubWFwKChvdXRwdXQpID0+ICh7XG4gIC8vICAgICAgIGFkZHJlc3M6IG91dHB1dC5hZGRyZXNzLFxuICAvLyAgICAgICBhc3NldDogb3V0cHV0LmFzc2V0LFxuICAvLyAgICAgICB2YWx1ZTogb3V0cHV0LnZhbHVlLFxuICAvLyAgICAgfSkpO1xuXG4gIC8vICAgY29uc3QgY2hhbmdlcyA9IF8uZnJvbVBhaXJzKFxuICAvLyAgICAgT2JqZWN0LmVudHJpZXMoXG4gIC8vICAgICAgIF8uZ3JvdXBCeShcbiAgLy8gICAgICAgICBpbnB1dHNcbiAgLy8gICAgICAgICAgIC5jb25jYXQob3V0cHV0cylcbiAgLy8gICAgICAgICAgIC5maWx0ZXIoKG91dHB1dCkgPT4gY29tbW9uLnVJbnQyNTZFcXVhbChvdXRwdXQuYXNzZXQsIHRoaXMuc2V0dGluZ3MuZ292ZXJuaW5nVG9rZW4uaGFzaCkpLFxuXG4gIC8vICAgICAgICAgKG91dHB1dCkgPT4gY29tbW9uLnVJbnQxNjBUb0hleChvdXRwdXQuYWRkcmVzcyksXG4gIC8vICAgICAgICksXG4gIC8vICAgICApLm1hcCgoW2FkZHJlc3NIZXgsIGFkZHJlc3NPdXRwdXRzXSkgPT4gW1xuICAvLyAgICAgICBhZGRyZXNzSGV4LFxuICAvLyAgICAgICBhZGRyZXNzT3V0cHV0cy5yZWR1Y2UoKGFjYywgb3V0cHV0KSA9PiBhY2MuYWRkKG91dHB1dC52YWx1ZSksIHV0aWxzLlpFUk8pLFxuICAvLyAgICAgXSksXG4gIC8vICAgKTtcblxuICAvLyAgIGNvbnN0IHZvdGVzID0gYXdhaXQgdGhpcy5hY2NvdW50LmFsbCRcbiAgLy8gICAgIC5waXBlKFxuICAvLyAgICAgICBmaWx0ZXIoKGFjY291bnQpID0+IGFjY291bnQudm90ZXMubGVuZ3RoID4gMCksXG4gIC8vICAgICAgIG1hcCgoYWNjb3VudCkgPT4ge1xuICAvLyAgICAgICAgIGxldCBiYWxhbmNlID0gYWNjb3VudC5iYWxhbmNlc1t0aGlzLnNldHRpbmdzLmdvdmVybmluZ1Rva2VuLmhhc2hIZXhdO1xuICAvLyAgICAgICAgIGJhbGFuY2UgPSBiYWxhbmNlID09PSB1bmRlZmluZWQgPyB1dGlscy5aRVJPIDogYmFsYW5jZTtcbiAgLy8gICAgICAgICBjb25zdCBjaGFuZ2UgPSBjaGFuZ2VzW2FjY291bnQuaGFzaEhleF07XG4gIC8vICAgICAgICAgYmFsYW5jZSA9IGJhbGFuY2UuYWRkKGNoYW5nZSA9PT0gdW5kZWZpbmVkID8gdXRpbHMuWkVSTyA6IGNoYW5nZSk7XG5cbiAgLy8gICAgICAgICByZXR1cm4gYmFsYW5jZS5sdGUodXRpbHMuWkVSTylcbiAgLy8gICAgICAgICAgID8gdW5kZWZpbmVkXG4gIC8vICAgICAgICAgICA6IHtcbiAgLy8gICAgICAgICAgICAgICBwdWJsaWNLZXlzOiBhY2NvdW50LnZvdGVzLFxuICAvLyAgICAgICAgICAgICAgIGNvdW50OiBiYWxhbmNlLFxuICAvLyAgICAgICAgICAgICB9O1xuICAvLyAgICAgICB9KSxcbiAgLy8gICAgICAgdG9BcnJheSgpLFxuICAvLyAgICAgKVxuICAvLyAgICAgLnRvUHJvbWlzZSgpO1xuICAvLyAgIGlmICh2b3Rlcy5sZW5ndGggPT09IDApIHtcbiAgLy8gICAgIHJldHVybiBbXG4gIC8vICAgICAgIHtcbiAgLy8gICAgICAgICBwdWJsaWNLZXlzOiB0aGlzLnNldHRpbmdzLnN0YW5kYnlWYWxpZGF0b3JzLFxuICAvLyAgICAgICAgIGNvdW50OiB0aGlzLnNldHRpbmdzLmdvdmVybmluZ1Rva2VuLmFzc2V0LmFtb3VudCxcbiAgLy8gICAgICAgfSxcbiAgLy8gICAgIF07XG4gIC8vICAgfVxuXG4gIC8vICAgcmV0dXJuIHZvdGVzLmZpbHRlcihjb21tb25VdGlscy5ub3ROdWxsKTtcbiAgLy8gfTtcblxuICBwcml2YXRlIGFzeW5jIHBlcnNpc3RCbG9ja0ludGVybmFsKGJsb2NrOiBCbG9jaywgdW5zYWZlPzogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgIGdsb2JhbFN0YXRzLnJlY29yZChbXG4gICAgICB7XG4gICAgICAgIG1lYXN1cmU6IGJsb2NrUHJvZ3Jlc3MsXG4gICAgICAgIHZhbHVlOiBibG9jay5pbmRleCxcbiAgICAgIH0sXG4gICAgXSk7XG5cbiAgICBpZiAoIXVuc2FmZSkge1xuICAgICAgYXdhaXQgdGhpcy52ZXJpZnlCbG9jayhibG9jayk7XG4gICAgfVxuXG4gICAgY29uc3QgYmxvY2tjaGFpbiA9IHRoaXMuY3JlYXRlV3JpdGVCbG9ja2NoYWluKCk7XG5cbiAgICBhd2FpdCBibG9ja2NoYWluLnBlcnNpc3RCbG9jayhibG9jayk7XG4gICAgYXdhaXQgdGhpcy5zdG9yYWdlLmNvbW1pdChibG9ja2NoYWluLmdldENoYW5nZVNldCgpKTtcblxuICAgIHRoaXMubXV0YWJsZVByZXZpb3VzQmxvY2sgPSB0aGlzLm11dGFibGVDdXJyZW50QmxvY2s7XG4gICAgdGhpcy5tdXRhYmxlQ3VycmVudEJsb2NrID0gYmxvY2s7XG4gICAgdGhpcy5tdXRhYmxlQ3VycmVudEhlYWRlciA9IGJsb2NrLmhlYWRlcjtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlV3JpdGVCbG9ja2NoYWluKCk6IFdyaXRlQmF0Y2hCbG9ja2NoYWluIHtcbiAgICByZXR1cm4gbmV3IFdyaXRlQmF0Y2hCbG9ja2NoYWluKHtcbiAgICAgIHNldHRpbmdzOiB0aGlzLnNldHRpbmdzLFxuICAgICAgY3VycmVudEJsb2NrOiB0aGlzLm11dGFibGVDdXJyZW50QmxvY2ssXG4gICAgICBjdXJyZW50SGVhZGVyOiB0aGlzLm11dGFibGVDdXJyZW50SGVhZGVyLFxuICAgICAgc3RvcmFnZTogdGhpcy5zdG9yYWdlLFxuICAgICAgdm06IHRoaXMudm0sXG4gICAgICBnZXRWYWxpZGF0b3JzOiB0aGlzLmdldFZhbGlkYXRvcnMsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==