UNPKG

125 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 node_core_1 = require("@neo-one/node-core");
6const utils_1 = require("@neo-one/utils");
7const bn_js_1 = require("bn.js");
8const lodash_1 = tslib_1.__importDefault(require("lodash"));
9const errors_1 = require("./errors");
10const getValidators_1 = require("./getValidators");
11const StorageCache_1 = require("./StorageCache");
12const wrapExecuteScripts_1 = require("./wrapExecuteScripts");
13class WriteBatchBlockchain {
14 constructor(options) {
15 this.settings = options.settings;
16 this.currentBlockInternal = options.currentBlock;
17 this.currentHeaderInternal = options.currentHeader;
18 this.storage = options.storage;
19 this.vm = options.vm;
20 this.getValidators = options.getValidators;
21 const output = new StorageCache_1.OutputStorageCache(() => this.storage.output);
22 this.caches = {
23 account: new StorageCache_1.ReadAllAddUpdateDeleteStorageCache({
24 name: 'account',
25 readAllStorage: () => this.storage.account,
26 update: (value, update) => value.update(update),
27 getKeyFromValue: (value) => ({ hash: value.hash }),
28 getKeyString: (key) => client_common_1.common.uInt160ToString(key.hash),
29 createAddChange: (value) => ({ type: 'account', value }),
30 createDeleteChange: (key) => ({ type: 'account', key }),
31 }),
32 accountUnspent: new StorageCache_1.ReadGetAllAddDeleteStorageCache({
33 name: 'accountUnspent',
34 readGetAllStorage: () => this.storage.accountUnspent,
35 getKeyFromValue: (value) => ({ hash: value.hash, input: value.input }),
36 getKeyString: (key) => `${client_common_1.common.uInt160ToString(key.hash)}:${client_common_1.common.uInt256ToString(key.input.hash)}:${key.input.index}`,
37 matchesPartialKey: (value, key) => client_common_1.common.uInt160Equal(value.hash, key.hash),
38 createAddChange: (value) => ({ type: 'accountUnspent', value }),
39 createDeleteChange: (key) => ({ type: 'accountUnspent', key }),
40 }),
41 accountUnclaimed: new StorageCache_1.ReadGetAllAddDeleteStorageCache({
42 name: 'accountUnclaimed',
43 readGetAllStorage: () => this.storage.accountUnclaimed,
44 getKeyFromValue: (value) => ({ hash: value.hash, input: value.input }),
45 getKeyString: (key) => `${client_common_1.common.uInt160ToString(key.hash)}:${client_common_1.common.uInt256ToString(key.input.hash)}:${key.input.index}`,
46 matchesPartialKey: (value, key) => client_common_1.common.uInt160Equal(value.hash, key.hash),
47 createAddChange: (value) => ({ type: 'accountUnclaimed', value }),
48 createDeleteChange: (key) => ({ type: 'accountUnclaimed', key }),
49 }),
50 action: new StorageCache_1.ReadGetAllAddStorageCache({
51 name: 'action',
52 readGetAllStorage: () => this.storage.action,
53 getKeyFromValue: (value) => ({
54 index: value.index,
55 }),
56 getKeyString: (key) => key.index.toString(10),
57 matchesPartialKey: (value, key) => (key.indexStart === undefined || value.index.gte(key.indexStart)) &&
58 (key.indexStop === undefined || value.index.lte(key.indexStop)),
59 createAddChange: (value) => ({ type: 'action', value }),
60 }),
61 asset: new StorageCache_1.ReadAddUpdateStorageCache({
62 name: 'asset',
63 readStorage: () => this.storage.asset,
64 update: (value, update) => value.update(update),
65 getKeyFromValue: (value) => ({ hash: value.hash }),
66 getKeyString: (key) => client_common_1.common.uInt256ToString(key.hash),
67 createAddChange: (value) => ({ type: 'asset', value }),
68 }),
69 block: new StorageCache_1.BlockLikeStorageCache({
70 name: 'block',
71 readStorage: () => ({
72 get: this.storage.block.get,
73 tryGet: this.storage.block.tryGet,
74 }),
75 createAddChange: (value) => ({ type: 'block', value }),
76 }),
77 blockData: new StorageCache_1.ReadAddStorageCache({
78 name: 'blockData',
79 readStorage: () => this.storage.blockData,
80 getKeyFromValue: (value) => ({ hash: value.hash }),
81 getKeyString: (key) => client_common_1.common.uInt256ToString(key.hash),
82 createAddChange: (value) => ({ type: 'blockData', value }),
83 }),
84 header: new StorageCache_1.BlockLikeStorageCache({
85 name: 'header',
86 readStorage: () => ({
87 get: this.storage.header.get,
88 tryGet: this.storage.header.tryGet,
89 }),
90 createAddChange: (value) => ({ type: 'header', value }),
91 }),
92 transaction: new StorageCache_1.ReadAddStorageCache({
93 name: 'transaction',
94 readStorage: () => this.storage.transaction,
95 getKeyFromValue: (value) => ({ hash: value.hash }),
96 getKeyString: (key) => client_common_1.common.uInt256ToString(key.hash),
97 createAddChange: (value) => ({ type: 'transaction', value }),
98 onAdd: async (value) => {
99 await Promise.all(value.outputs.map(async (out, index) => output.add({ hash: value.hash, index, output: out })));
100 },
101 allowDupes: true,
102 }),
103 transactionData: new StorageCache_1.ReadAddUpdateStorageCache({
104 name: 'transactionData',
105 readStorage: () => this.storage.transactionData,
106 update: (value, update) => value.update(update),
107 getKeyFromValue: (value) => ({ hash: value.hash }),
108 getKeyString: (key) => client_common_1.common.uInt256ToString(key.hash),
109 createAddChange: (value) => ({ type: 'transactionData', value }),
110 allowDupes: true,
111 }),
112 output,
113 contract: new StorageCache_1.ReadAddDeleteStorageCache({
114 name: 'contract',
115 readStorage: () => this.storage.contract,
116 getKeyFromValue: (value) => ({ hash: value.hash }),
117 getKeyString: (key) => client_common_1.common.uInt160ToString(key.hash),
118 createAddChange: (value) => ({ type: 'contract', value }),
119 createDeleteChange: (key) => ({ type: 'contract', key }),
120 }),
121 storageItem: new StorageCache_1.ReadGetAllAddUpdateDeleteStorageCache({
122 name: 'storageItem',
123 readGetAllStorage: () => this.storage.storageItem,
124 update: (value, update) => value.update(update),
125 getKeyFromValue: (value) => ({
126 hash: value.hash,
127 key: value.key,
128 }),
129 getKeyString: (key) => `${client_common_1.common.uInt160ToString(key.hash)}:${key.key.toString('hex')}`,
130 matchesPartialKey: (value, key) => (key.hash === undefined || client_common_1.common.uInt160Equal(value.hash, key.hash)) &&
131 (key.prefix === undefined || key.prefix.every((byte, idx) => value.key[idx] === byte)),
132 createAddChange: (value) => ({ type: 'storageItem', value }),
133 createDeleteChange: (key) => ({ type: 'storageItem', key }),
134 }),
135 validator: new StorageCache_1.ReadAllAddUpdateDeleteStorageCache({
136 name: 'validator',
137 readAllStorage: () => this.storage.validator,
138 getKeyFromValue: (value) => ({ publicKey: value.publicKey }),
139 getKeyString: (key) => client_common_1.common.ecPointToString(key.publicKey),
140 createAddChange: (value) => ({ type: 'validator', value }),
141 update: (value, update) => value.update(update),
142 createDeleteChange: (key) => ({ type: 'validator', key }),
143 }),
144 invocationData: new StorageCache_1.ReadAddStorageCache({
145 name: 'invocationData',
146 readStorage: () => this.storage.invocationData,
147 getKeyFromValue: (value) => ({ hash: value.hash }),
148 getKeyString: (key) => client_common_1.common.uInt256ToString(key.hash),
149 createAddChange: (value) => ({ type: 'invocationData', value }),
150 }),
151 validatorsCount: new StorageCache_1.ReadAddUpdateMetadataStorageCache({
152 name: 'validatorsCount',
153 readStorage: () => this.storage.validatorsCount,
154 createAddChange: (value) => ({ type: 'validatorsCount', value }),
155 update: (value, update) => value.update(update),
156 }),
157 };
158 this.account = this.caches.account;
159 this.accountUnspent = this.caches.accountUnspent;
160 this.accountUnclaimed = this.caches.accountUnclaimed;
161 this.action = this.caches.action;
162 this.asset = this.caches.asset;
163 this.block = this.caches.block;
164 this.blockData = this.caches.blockData;
165 this.header = this.caches.header;
166 this.transaction = this.caches.transaction;
167 this.transactionData = this.caches.transactionData;
168 this.output = this.caches.output;
169 this.contract = this.caches.contract;
170 this.storageItem = this.caches.storageItem;
171 this.validator = this.caches.validator;
172 this.invocationData = this.caches.invocationData;
173 this.validatorsCount = this.caches.validatorsCount;
174 }
175 get currentBlock() {
176 if (this.currentBlockInternal === undefined) {
177 throw new errors_1.GenesisBlockNotRegisteredError();
178 }
179 return this.currentBlockInternal;
180 }
181 get currentBlockIndex() {
182 return this.currentBlockInternal === undefined ? 0 : this.currentBlockInternal.index;
183 }
184 get currentHeader() {
185 if (this.currentHeaderInternal === undefined) {
186 throw new errors_1.GenesisBlockNotRegisteredError();
187 }
188 return this.currentHeaderInternal;
189 }
190 getChangeSet() {
191 return Object.values(this.caches).reduce((acc, cache) => acc.concat(cache.getChangeSet()), []);
192 }
193 getTrackedChangeSet() {
194 return Object.values(this.caches).reduce((acc, cache) => acc.concat(cache.getTrackedChangeSet()), []);
195 }
196 async persistBlock(block) {
197 const [maybePrevBlockData, outputContractsList] = await Promise.all([
198 block.index === 0 ? Promise.resolve(undefined) : this.blockData.get({ hash: block.previousHash }),
199 Promise.all([
200 ...new Set(block.transactions.reduce((acc, transaction) => acc.concat(transaction.outputs.map((output) => client_common_1.common.uInt160ToString(output.address))), [])),
201 ].map(async (hash) => this.contract.tryGet({ hash: client_common_1.common.stringToUInt160(hash) }))),
202 this.block.add(block),
203 this.header.add(block.header),
204 ]);
205 const prevBlockData = maybePrevBlockData === undefined
206 ? {
207 lastGlobalTransactionIndex: client_common_1.utils.NEGATIVE_ONE,
208 lastGlobalActionIndex: client_common_1.utils.NEGATIVE_ONE,
209 systemFee: client_common_1.utils.ZERO,
210 }
211 : {
212 lastGlobalTransactionIndex: maybePrevBlockData.lastGlobalTransactionIndex,
213 lastGlobalActionIndex: maybePrevBlockData.lastGlobalActionIndex,
214 systemFee: maybePrevBlockData.systemFee,
215 };
216 const outputContracts = {};
217 outputContractsList.filter(utils_1.utils.notNull).forEach((outputContract) => {
218 outputContracts[outputContract.hashHex] = outputContract;
219 });
220 const [utxo, rest] = lodash_1.default.partition(block.transactions.map((transaction, idx) => [idx, transaction]), ([idx, transaction]) => ((transaction.type === node_core_1.TransactionType.Claim && transaction instanceof node_core_1.ClaimTransaction) ||
221 (transaction.type === node_core_1.TransactionType.Contract && transaction instanceof node_core_1.ContractTransaction) ||
222 (transaction.type === node_core_1.TransactionType.Miner && transaction instanceof node_core_1.MinerTransaction)) &&
223 !transaction.outputs.some((output) => outputContracts[client_common_1.common.uInt160ToString(output.address)] !== undefined));
224 const [globalActionIndex] = await Promise.all([
225 rest.length > 0
226 ? this.persistTransactions(block, rest, prevBlockData.lastGlobalTransactionIndex, prevBlockData.lastGlobalActionIndex)
227 : Promise.resolve(prevBlockData.lastGlobalActionIndex),
228 utxo.length > 0
229 ?
230 this.persistUTXOTransactions(block, utxo, prevBlockData.lastGlobalTransactionIndex)
231 : Promise.resolve(),
232 ]);
233 await this.blockData.add(new node_core_1.BlockData({
234 hash: block.hash,
235 lastGlobalTransactionIndex: prevBlockData.lastGlobalTransactionIndex.add(new bn_js_1.BN(block.transactions.length)),
236 lastGlobalActionIndex: globalActionIndex,
237 systemFee: prevBlockData.systemFee.add(block.getSystemFee({
238 getOutput: this.output.get,
239 governingToken: this.settings.governingToken,
240 utilityToken: this.settings.utilityToken,
241 fees: this.settings.fees,
242 registerValidatorFee: this.settings.registerValidatorFee,
243 })),
244 }));
245 }
246 async persistUTXOTransactions(block, transactions, lastGlobalTransactionIndex) {
247 const inputs = [];
248 const claims = [];
249 const outputWithInputs = [];
250 for (const idxAndTransaction of transactions) {
251 const transaction = idxAndTransaction[1];
252 inputs.push(...transaction.inputs);
253 if (transaction.type === node_core_1.TransactionType.Claim && transaction instanceof node_core_1.ClaimTransaction) {
254 claims.push(...transaction.claims);
255 }
256 outputWithInputs.push(...this.getOutputWithInput(transaction));
257 }
258 await Promise.all([
259 Promise.all(transactions.map(async ([idx, transaction]) => this.transaction.add(transaction))),
260 Promise.all(transactions.map(async ([idx, transaction]) => this.transactionData.add(new node_core_1.TransactionData({
261 hash: transaction.hash,
262 startHeight: block.index,
263 blockHash: block.hash,
264 index: idx,
265 globalIndex: lastGlobalTransactionIndex.add(new bn_js_1.BN(idx + 1)),
266 })))),
267 this.updateAccounts(inputs, claims, outputWithInputs),
268 this.updateCoins(inputs, claims, block),
269 ]);
270 }
271 async persistTransactions(block, transactions, lastGlobalTransactionIndex, lastGlobalActionIndex) {
272 let globalActionIndex = lastGlobalActionIndex.add(client_common_1.utils.ONE);
273 for (const [idx, transaction] of transactions) {
274 globalActionIndex = await this.persistTransaction(block, transaction, idx, lastGlobalTransactionIndex, globalActionIndex);
275 }
276 return globalActionIndex.sub(client_common_1.utils.ONE);
277 }
278 async persistTransaction(block, transactionIn, transactionIndex, lastGlobalTransactionIndex, globalActionIndexIn) {
279 let globalActionIndex = globalActionIndexIn;
280 const transaction = transactionIn;
281 const claims = transaction.type === node_core_1.TransactionType.Claim && transaction instanceof node_core_1.ClaimTransaction ? transaction.claims : [];
282 let accountChanges = {};
283 let validatorChanges = {};
284 let validatorsCountChanges = [];
285 if (transaction.type === node_core_1.TransactionType.State && transaction instanceof node_core_1.StateTransaction) {
286 ({ accountChanges, validatorChanges, validatorsCountChanges } = await getValidators_1.getDescriptorChanges({
287 transactions: [transaction],
288 getAccount: async (hash) => this.account.tryGet({ hash }).then((account) => (account === undefined ? new node_core_1.Account({ hash }) : account)),
289 governingTokenHash: this.settings.governingToken.hashHex,
290 }));
291 }
292 await Promise.all([
293 this.transaction.add(transaction),
294 this.transactionData.add(new node_core_1.TransactionData({
295 hash: transaction.hash,
296 blockHash: block.hash,
297 startHeight: block.index,
298 index: transactionIndex,
299 globalIndex: lastGlobalTransactionIndex.add(new bn_js_1.BN(transactionIndex + 1)),
300 })),
301 this.updateAccounts(transaction.inputs, claims, this.getOutputWithInput(transaction), accountChanges),
302 this.updateCoins(transaction.inputs, claims, block),
303 this.processStateTransaction(validatorChanges, validatorsCountChanges),
304 ]);
305 if (transaction.type === node_core_1.TransactionType.Register && transaction instanceof node_core_1.RegisterTransaction) {
306 await this.asset.add(new node_core_1.Asset({
307 hash: transaction.hash,
308 type: transaction.asset.type,
309 name: transaction.asset.name,
310 amount: transaction.asset.amount,
311 precision: transaction.asset.precision,
312 owner: transaction.asset.owner,
313 admin: transaction.asset.admin,
314 issuer: transaction.asset.admin,
315 expiration: this.currentBlockIndex + 2 * 2000000,
316 isFrozen: false,
317 }));
318 }
319 else if (transaction.type === node_core_1.TransactionType.Issue && transaction instanceof node_core_1.IssueTransaction) {
320 const results = await Promise.all(Object.entries(transaction.getTransactionResults({
321 getOutput: this.output.get,
322 })));
323 await Promise.all(results.map(async ([assetHex, value]) => {
324 const hash = client_common_1.common.stringToUInt256(assetHex);
325 const asset = await this.asset.get({ hash });
326 await this.asset.update(asset, {
327 available: asset.available.add(value.neg()),
328 });
329 }));
330 }
331 else if (transaction.type === node_core_1.TransactionType.Enrollment && transaction instanceof node_core_1.EnrollmentTransaction) {
332 await this.validator.add(new node_core_1.Validator({
333 publicKey: transaction.publicKey,
334 }));
335 }
336 else if (transaction.type === node_core_1.TransactionType.Publish && transaction instanceof node_core_1.PublishTransaction) {
337 const contract = await this.contract.tryGet({
338 hash: transaction.contract.hash,
339 });
340 if (contract === undefined) {
341 await this.contract.add(transaction.contract);
342 }
343 }
344 else if (transaction.type === node_core_1.TransactionType.Invocation && transaction instanceof node_core_1.InvocationTransaction) {
345 const temporaryBlockchain = new WriteBatchBlockchain({
346 settings: this.settings,
347 currentBlock: this.currentBlockInternal,
348 currentHeader: this.currentHeader,
349 storage: this,
350 vm: this.vm,
351 getValidators: this.getValidators,
352 });
353 const migratedContractHashes = [];
354 const voteUpdates = [];
355 const actions = [];
356 const result = await wrapExecuteScripts_1.wrapExecuteScripts(async () => this.vm.executeScripts({
357 scripts: [{ code: transaction.script }],
358 blockchain: temporaryBlockchain,
359 scriptContainer: {
360 type: node_core_1.ScriptContainerType.Transaction,
361 value: transaction,
362 },
363 triggerType: node_core_1.TriggerType.Application,
364 action: {
365 blockIndex: block.index,
366 blockHash: block.hash,
367 transactionIndex,
368 transactionHash: transaction.hash,
369 },
370 gas: transaction.gas,
371 listeners: {
372 onLog: ({ message, scriptHash }) => {
373 actions.push(new node_core_1.LogAction({
374 index: globalActionIndex,
375 scriptHash,
376 message,
377 }));
378 globalActionIndex = globalActionIndex.add(client_common_1.utils.ONE);
379 },
380 onNotify: ({ args, scriptHash }) => {
381 actions.push(new node_core_1.NotificationAction({
382 index: globalActionIndex,
383 scriptHash,
384 args,
385 }));
386 globalActionIndex = globalActionIndex.add(client_common_1.utils.ONE);
387 },
388 onMigrateContract: ({ from, to }) => {
389 migratedContractHashes.push([from, to]);
390 },
391 onSetVotes: ({ address, votes }) => {
392 voteUpdates.push([address, votes]);
393 },
394 },
395 persistingBlock: block,
396 }));
397 const addActionsPromise = Promise.all(actions.map(async (action) => this.action.add(action)));
398 if (result instanceof node_core_1.InvocationResultSuccess) {
399 const assetChangeSet = temporaryBlockchain.asset.getChangeSet();
400 const assetHash = assetChangeSet
401 .map((change) => change.type === 'add' && change.change.type === 'asset' ? change.change.value.hash : undefined)
402 .find((value) => value !== undefined);
403 const contractsChangeSet = temporaryBlockchain.contract.getChangeSet();
404 const contractHashes = contractsChangeSet
405 .map((change) => change.type === 'add' && change.change.type === 'contract' ? change.change.value.hash : undefined)
406 .filter(utils_1.utils.notNull);
407 const deletedContractHashes = contractsChangeSet
408 .map((change) => change.type === 'delete' && change.change.type === 'contract' ? change.change.key.hash : undefined)
409 .filter(utils_1.utils.notNull);
410 const storageChanges = temporaryBlockchain.storageItem
411 .getChangeSet()
412 .map((change) => {
413 const addChange = change.type === 'add' && change.change.type === 'storageItem'
414 ? { value: change.change.value, subType: change.subType }
415 : undefined;
416 if (addChange !== undefined) {
417 const options = {
418 hash: addChange.value.hash,
419 key: addChange.value.key,
420 value: addChange.value.value,
421 };
422 return addChange.subType === 'add' ? new node_core_1.StorageChangeAdd(options) : new node_core_1.StorageChangeModify(options);
423 }
424 const deleteChange = change.type === 'delete' && change.change.type === 'storageItem' ? change.change.key : undefined;
425 if (deleteChange !== undefined) {
426 return new node_core_1.StorageChangeDelete(deleteChange);
427 }
428 return undefined;
429 })
430 .filter(utils_1.utils.notNull);
431 temporaryBlockchain.getTrackedChangeSet().forEach((change) => {
432 this.caches[change.type].addTrackedChange(change.key, change.value);
433 });
434 await Promise.all([
435 this.invocationData.add(new node_core_1.InvocationData({
436 hash: transaction.hash,
437 assetHash,
438 contractHashes,
439 deletedContractHashes,
440 migratedContractHashes,
441 voteUpdates,
442 blockIndex: block.index,
443 transactionIndex,
444 actionIndexStart: globalActionIndexIn,
445 actionIndexStop: globalActionIndex,
446 result,
447 storageChanges,
448 })),
449 addActionsPromise,
450 ]);
451 }
452 else {
453 await Promise.all([
454 this.invocationData.add(new node_core_1.InvocationData({
455 hash: transaction.hash,
456 assetHash: undefined,
457 contractHashes: [],
458 deletedContractHashes: [],
459 migratedContractHashes: [],
460 voteUpdates: [],
461 blockIndex: block.index,
462 transactionIndex,
463 actionIndexStart: globalActionIndexIn,
464 actionIndexStop: globalActionIndex,
465 result,
466 storageChanges: [],
467 })),
468 addActionsPromise,
469 ]);
470 }
471 }
472 return globalActionIndex;
473 }
474 async processStateTransaction(validatorChanges, validatorsCountChanges) {
475 const validatorsCount = await this.validatorsCount.tryGet();
476 const validatorsCountVotes = validatorsCount === undefined ? [] : [...validatorsCount.votes];
477 for (const [index, value] of validatorsCountChanges.entries()) {
478 validatorsCountVotes[index] = value;
479 }
480 await Promise.all([
481 Promise.all(Object.entries(validatorChanges).map(async ([publicKeyHex, { registered, votes }]) => {
482 const publicKey = client_common_1.common.hexToECPoint(publicKeyHex);
483 const validator = await this.validator.tryGet({ publicKey });
484 if (validator === undefined) {
485 await this.validator.add(new node_core_1.Validator({
486 publicKey,
487 registered,
488 votes,
489 }));
490 }
491 else if (((registered !== undefined && !registered) || (registered === undefined && !validator.registered)) &&
492 ((votes !== undefined && votes.eq(client_common_1.utils.ZERO)) || (votes === undefined && validator.votes.eq(client_common_1.utils.ZERO)))) {
493 await this.validator.delete({ publicKey: validator.publicKey });
494 }
495 else {
496 await this.validator.update(validator, { votes, registered });
497 }
498 })),
499 validatorsCount === undefined
500 ? this.validatorsCount.add(new node_core_1.ValidatorsCount({
501 votes: validatorsCountVotes,
502 }))
503 : (async () => {
504 await this.validatorsCount.update(validatorsCount, {
505 votes: validatorsCountVotes,
506 });
507 })(),
508 ]);
509 }
510 async updateAccounts(inputs, claims, outputs, accountChanges = {}) {
511 const [inputOutputs, claimOutputs] = await Promise.all([
512 this.getInputOutputs(inputs),
513 this.getInputOutputs(claims),
514 ]);
515 const addressValues = Object.entries(lodash_1.default.groupBy(inputOutputs
516 .map(({ output }) => [output.address, output.asset, output.value.neg()])
517 .concat(outputs.map(({ output }) => [output.address, output.asset, output.value])), ([address]) => client_common_1.common.uInt160ToHex(address)));
518 const addressSpent = this.groupByAddress(inputOutputs);
519 const addressClaimed = lodash_1.default.mapValues(this.groupByAddress(claimOutputs), (values) => values.map(({ input }) => input));
520 const addressOutputs = lodash_1.default.groupBy(outputs, (output) => client_common_1.common.uInt160ToHex(output.output.address));
521 await Promise.all(addressValues.map(async ([address, values]) => {
522 const spent = addressSpent[address];
523 const claimed = addressClaimed[address];
524 const outs = addressOutputs[address];
525 const changes = accountChanges[address];
526 await this.updateAccount(client_common_1.common.hexToUInt160(address), values.map(([_address, asset, value]) => [asset, value]), spent === undefined ? [] : spent, claimed === undefined ? [] : claimed, outs === undefined ? [] : outs, changes === undefined ? [] : changes);
527 }));
528 }
529 getOutputWithInput(transaction) {
530 return transaction.outputs.map((output, index) => ({
531 output,
532 input: new node_core_1.Input({ hash: transaction.hash, index }),
533 }));
534 }
535 async getInputOutputs(inputs) {
536 return Promise.all(inputs.map(async (input) => {
537 const output = await this.output.get(input);
538 return { input, output };
539 }));
540 }
541 groupByAddress(inputOutputs) {
542 return lodash_1.default.groupBy(inputOutputs, ({ output }) => client_common_1.common.uInt160ToHex(output.address));
543 }
544 async updateAccount(address, values, spent, claimed, outputs, votes) {
545 const account = await this.account.tryGet({ hash: address });
546 const balances = values.reduce((acc, [asset, value]) => {
547 const key = client_common_1.common.uInt256ToHex(asset);
548 if (acc[key] === undefined) {
549 acc[key] = client_common_1.utils.ZERO;
550 }
551 acc[key] = acc[key].add(value);
552 return acc;
553 }, account === undefined
554 ? {}
555 : Object.entries(account.balances).reduce((acc, [key, value]) => {
556 if (value === undefined) {
557 return Object.assign({}, acc, { [key]: client_common_1.utils.ZERO });
558 }
559 return Object.assign({}, acc, { [key]: value });
560 }, {}));
561 const promises = [];
562 promises.push(...spent.map(async ({ input }) => this.accountUnspent.delete({
563 hash: address,
564 input,
565 })));
566 promises.push(...outputs.map(async ({ input }) => this.accountUnspent.add(new node_core_1.AccountUnspent({ hash: address, input }))));
567 promises.push(...claimed.map(async (input) => this.accountUnclaimed.delete({
568 hash: address,
569 input,
570 })));
571 promises.push(...spent
572 .filter(({ output }) => client_common_1.common.uInt256Equal(output.asset, this.settings.governingToken.hash))
573 .map(async ({ input }) => this.accountUnclaimed.add(new node_core_1.AccountUnclaimed({ hash: address, input }))));
574 if (account === undefined) {
575 promises.push(this.account.add(new node_core_1.Account({
576 hash: address,
577 balances,
578 votes,
579 })));
580 }
581 else {
582 promises.push(this.account.update(account, { balances, votes }).then(async (newAccount) => {
583 if (newAccount.isDeletable()) {
584 await this.account.delete({ hash: address });
585 }
586 }));
587 }
588 await Promise.all(promises);
589 }
590 async updateCoins(inputs, claims, block) {
591 const inputClaims = inputs
592 .map((input) => ({ type: 'input', input, hash: input.hash }))
593 .concat(claims.map((input) => ({ type: 'claim', input, hash: input.hash })));
594 const hashInputClaims = Object.entries(lodash_1.default.groupBy(inputClaims, ({ hash }) => client_common_1.common.uInt256ToHex(hash)));
595 await Promise.all(hashInputClaims.map(async ([hash, values]) => this.updateCoin(client_common_1.common.hexToUInt256(hash), values, block)));
596 }
597 async updateCoin(hash, inputClaims, block) {
598 const spentCoins = await this.transactionData.get({ hash });
599 const endHeights = Object.assign({}, spentCoins.endHeights);
600 const claimed = Object.assign({}, spentCoins.claimed);
601 for (const inputClaim of inputClaims) {
602 if (inputClaim.type === 'input') {
603 endHeights[inputClaim.input.index] = block.index;
604 }
605 else {
606 claimed[inputClaim.input.index] = true;
607 }
608 }
609 await this.transactionData.update(spentCoins, {
610 endHeights,
611 claimed,
612 });
613 }
614}
615exports.WriteBatchBlockchain = WriteBatchBlockchain;
616
617//# sourceMappingURL=data:application/json;charset=utf8;base64,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VSxDQUFDLE9BQU8sQ0FBRSxDQUFDO1FBRTFDLEtBQUssTUFBTSxVQUFVLElBQUksV0FBVyxFQUFFO1lBQ3BDLElBQUksVUFBVSxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUU7Z0JBQy9CLFVBQVUsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7YUFDbEQ7aUJBQU07Z0JBQ0wsT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDO2FBQ3hDO1NBQ0Y7UUFFRCxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRTtZQUM1QyxVQUFVO1lBQ1YsT0FBTztTQUNSLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQXAzQkQsb0RBbzNCQyIsImZpbGUiOiJuZW8tb25lLW5vZGUtYmxvY2tjaGFpbi9zcmMvV3JpdGVCYXRjaEJsb2NrY2hhaW4uanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0c2xpbnQ6ZGlzYWJsZSBuby1hcnJheS1tdXRhdGlvbiBuby1vYmplY3QtbXV0YXRpb25cbmltcG9ydCB7IGNvbW1vbiwgRUNQb2ludCwgVUludDE2MCwgVUludDI1NiwgdXRpbHMgfSBmcm9tICdAbmVvLW9uZS9jbGllbnQtY29tbW9uJztcbmltcG9ydCB7XG4gIEFjY291bnQsXG4gIEFjY291bnRLZXksXG4gIEFjY291bnRVbmNsYWltZWQsXG4gIEFjY291bnRVbmNsYWltZWRLZXksXG4gIEFjY291bnRVbmNsYWltZWRzS2V5LFxuICBBY2NvdW50VW5zcGVudCxcbiAgQWNjb3VudFVuc3BlbnRLZXksXG4gIEFjY291bnRVbnNwZW50c0tleSxcbiAgQWNjb3VudFVwZGF0ZSxcbiAgQWN0aW9uLFxuICBBY3Rpb25LZXksXG4gIEFjdGlvbnNLZXksXG4gIEFzc2V0LFxuICBBc3NldEtleSxcbiAgQXNzZXRVcGRhdGUsXG4gIEJsb2NrLFxuICBCbG9ja2NoYWluU3RvcmFnZSxcbiAgQmxvY2tEYXRhLFxuICBCbG9ja0RhdGFLZXksXG4gIENoYW5nZVNldCxcbiAgQ2xhaW1UcmFuc2FjdGlvbixcbiAgQ29udHJhY3QsXG4gIENvbnRyYWN0S2V5LFxuICBDb250cmFjdFRyYW5zYWN0aW9uLFxuICBFbnJvbGxtZW50VHJhbnNhY3Rpb24sXG4gIEhlYWRlcixcbiAgSW5wdXQsXG4gIEludm9jYXRpb25EYXRhLFxuICBJbnZvY2F0aW9uRGF0YUtleSxcbiAgSW52b2NhdGlvblJlc3VsdFN1Y2Nlc3MsXG4gIEludm9jYXRpb25UcmFuc2FjdGlvbixcbiAgSXNzdWVUcmFuc2FjdGlvbixcbiAgTG9nQWN0aW9uLFxuICBNaW5lclRyYW5zYWN0aW9uLFxuICBOb3RpZmljYXRpb25BY3Rpb24sXG4gIE91dHB1dCxcbiAgUHVibGlzaFRyYW5zYWN0aW9uLFxuICBSZWdpc3RlclRyYW5zYWN0aW9uLFxuICBTY3JpcHRDb250YWluZXJUeXBlLFxuICBTdGF0ZVRyYW5zYWN0aW9uLFxuICBTdG9yYWdlQ2hhbmdlQWRkLFxuICBTdG9yYWdlQ2hhbmdlRGVsZXRlLFxuICBTdG9yYWdlQ2hhbmdlTW9kaWZ5LFxuICBTdG9yYWdlSXRlbSxcbiAgU3RvcmFnZUl0ZW1LZXksXG4gIFN0b3JhZ2VJdGVtc0tleSxcbiAgU3RvcmFnZUl0ZW1VcGRhdGUsXG4gIFRyYW5zYWN0aW9uLFxuICBUcmFuc2FjdGlvbkRhdGEsXG4gIFRyYW5zYWN0aW9uRGF0YUtleSxcbiAgVHJhbnNhY3Rpb25EYXRhVXBkYXRlLFxuICBUcmFuc2FjdGlvbktleSxcbiAgVHJhbnNhY3Rpb25UeXBlLFxuICBUcmlnZ2VyVHlwZSxcbiAgVmFsaWRhdG9yLFxuICBWYWxpZGF0b3JLZXksXG4gIFZhbGlkYXRvcnNDb3VudCxcbiAgVmFsaWRhdG9yc0NvdW50VXBkYXRlLFxuICBWYWxpZGF0b3JVcGRhdGUsXG4gIFZNLFxuICBXcml0ZUJsb2NrY2hhaW4sXG59IGZyb20gJ0BuZW8tb25lL25vZGUtY29yZSc7XG5pbXBvcnQgeyB1dGlscyBhcyBjb21tb25VdGlscyB9IGZyb20gJ0BuZW8tb25lL3V0aWxzJztcbmltcG9ydCB7IEJOIH0gZnJvbSAnYm4uanMnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEdlbmVzaXNCbG9ja05vdFJlZ2lzdGVyZWRFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IEFjY291bnRDaGFuZ2VzLCBnZXREZXNjcmlwdG9yQ2hhbmdlcywgVmFsaWRhdG9yQ2hhbmdlcywgVmFsaWRhdG9yc0NvdW50Q2hhbmdlcyB9IGZyb20gJy4vZ2V0VmFsaWRhdG9ycyc7XG5pbXBvcnQge1xuICBCbG9ja0xpa2VTdG9yYWdlQ2FjaGUsXG4gIE91dHB1dFN0b3JhZ2VDYWNoZSxcbiAgUmVhZEFkZERlbGV0ZVN0b3JhZ2VDYWNoZSxcbiAgUmVhZEFkZFN0b3JhZ2VDYWNoZSxcbiAgUmVhZEFkZFVwZGF0ZU1ldGFkYXRhU3RvcmFnZUNhY2hlLFxuICBSZWFkQWRkVXBkYXRlU3RvcmFnZUNhY2hlLFxuICBSZWFkQWxsQWRkVXBkYXRlRGVsZXRlU3RvcmFnZUNhY2hlLFxuICBSZWFkR2V0QWxsQWRkRGVsZXRlU3RvcmFnZUNhY2hlLFxuICBSZWFkR2V0QWxsQWRkU3RvcmFnZUNhY2hlLFxuICBSZWFkR2V0QWxsQWRkVXBkYXRlRGVsZXRlU3RvcmFnZUNhY2hlLFxuICBUcmFja2VkQ2hhbmdlU2V0LFxufSBmcm9tICcuL1N0b3JhZ2VDYWNoZSc7XG5pbXBvcnQgeyB3cmFwRXhlY3V0ZVNjcmlwdHMgfSBmcm9tICcuL3dyYXBFeGVjdXRlU2NyaXB0cyc7XG5cbmludGVyZmFjZSBXcml0ZUJhdGNoQmxvY2tjaGFpbk9wdGlvbnMge1xuICByZWFkb25seSBzZXR0aW5nczogV3JpdGVCbG9ja2NoYWluWydzZXR0aW5ncyddO1xuICByZWFkb25seSBjdXJyZW50QmxvY2s6IFdyaXRlQmxvY2tjaGFpblsnY3VycmVudEJsb2NrJ10gfCB1bmRlZmluZWQ7XG4gIHJlYWRvbmx5IGN1cnJlbnRIZWFkZXI6IFdyaXRlQmxvY2tjaGFpblsnY3VycmVudEhlYWRlciddIHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBzdG9yYWdlOiBCbG9ja2NoYWluU3RvcmFnZTtcbiAgcmVhZG9ubHkgdm06IFZNO1xuICByZWFkb25seSBnZXRWYWxpZGF0b3JzOiBXcml0ZUJsb2NrY2hhaW5bJ2dldFZhbGlkYXRvcnMnXTtcbn1cblxuaW50ZXJmYWNlIENhY2hlcyB7XG4gIHJlYWRvbmx5IGFjY291bnQ6IFJlYWRBbGxBZGRVcGRhdGVEZWxldGVTdG9yYWdlQ2FjaGU8QWNjb3VudEtleSwgQWNjb3VudCwgQWNjb3VudFVwZGF0ZT47XG4gIHJlYWRvbmx5IGFjY291bnRVbnNwZW50OiBSZWFkR2V0QWxsQWRkRGVsZXRlU3RvcmFnZUNhY2hlPEFjY291bnRVbnNwZW50S2V5LCBBY2NvdW50VW5zcGVudHNLZXksIEFjY291bnRVbnNwZW50PjtcbiAgcmVhZG9ubHkgYWNjb3VudFVuY2xhaW1lZDogUmVhZEdldEFsbEFkZERlbGV0ZVN0b3JhZ2VDYWNoZTxcbiAgICBBY2NvdW50VW5jbGFpbWVkS2V5LFxuICAgIEFjY291bnRVbmNsYWltZWRzS2V5LFxuICAgIEFjY291bnRVbmNsYWltZWRcbiAgPjtcbiAgcmVhZG9ubHkgYWN0aW9uOiBSZWFkR2V0QWxsQWRkU3RvcmFnZUNhY2hlPEFjdGlvbktleSwgQWN0aW9uc0tleSwgQWN0aW9uPjtcbiAgcmVhZG9ubHkgYXNzZXQ6IFJlYWRBZGRVcGRhdGVTdG9yYWdlQ2FjaGU8QXNzZXRLZXksIEFzc2V0LCBBc3NldFVwZGF0ZT47XG4gIHJlYWRvbmx5IGJsb2NrOiBCbG9ja0xpa2VTdG9yYWdlQ2FjaGU8QmxvY2s+O1xuICByZWFkb25seSBibG9ja0RhdGE6IFJlYWRBZGRTdG9yYWdlQ2FjaGU8QmxvY2tEYXRhS2V5LCBCbG9ja0RhdGE+O1xuICByZWFkb25seSBoZWFkZXI6IEJsb2NrTGlrZVN0b3JhZ2VDYWNoZTxIZWFkZXI+O1xuICByZWFkb25seSB0cmFuc2FjdGlvbjogUmVhZEFkZFN0b3JhZ2VDYWNoZTxUcmFuc2FjdGlvbktleSwgVHJhbnNhY3Rpb24+O1xuICByZWFkb25seSB0cmFuc2FjdGlvbkRhdGE6IFJlYWRBZGRVcGRhdGVTdG9yYWdlQ2FjaGU8VHJhbnNhY3Rpb25EYXRhS2V5LCBUcmFuc2FjdGlvbkRhdGEsIFRyYW5zYWN0aW9uRGF0YVVwZGF0ZT47XG4gIHJlYWRvbmx5IG91dHB1dDogT3V0cHV0U3RvcmFnZUNhY2hlO1xuICByZWFkb25seSBjb250cmFjdDogUmVhZEFkZERlbGV0ZVN0b3JhZ2VDYWNoZTxDb250cmFjdEtleSwgQ29udHJhY3Q+O1xuICByZWFkb25seSBzdG9yYWdlSXRlbTogUmVhZEdldEFsbEFkZFVwZGF0ZURlbGV0ZVN0b3JhZ2VDYWNoZTxcbiAgICBTdG9yYWdlSXRlbUtleSxcbiAgICBTdG9yYWdlSXRlbXNLZXksXG4gICAgU3RvcmFnZUl0ZW0sXG4gICAgU3RvcmFnZUl0ZW1VcGRhdGVcbiAgPjtcbiAgcmVhZG9ubHkgdmFsaWRhdG9yOiBSZWFkQWxsQWRkVXBkYXRlRGVsZXRlU3RvcmFnZUNhY2hlPFZhbGlkYXRvcktleSwgVmFsaWRhdG9yLCBWYWxpZGF0b3JVcGRhdGU+O1xuICByZWFkb25seSBpbnZvY2F0aW9uRGF0YTogUmVhZEFkZFN0b3JhZ2VDYWNoZTxJbnZvY2F0aW9uRGF0YUtleSwgSW52b2NhdGlvbkRhdGE+O1xuICByZWFkb25seSB2YWxpZGF0b3JzQ291bnQ6IFJlYWRBZGRVcGRhdGVNZXRhZGF0YVN0b3JhZ2VDYWNoZTxWYWxpZGF0b3JzQ291bnQsIFZhbGlkYXRvcnNDb3VudFVwZGF0ZT47XG59XG5cbmludGVyZmFjZSBJbnB1dENsYWltIHtcbiAgcmVhZG9ubHkgdHlwZTogJ2NsYWltJyB8ICdpbnB1dCc7XG4gIHJlYWRvbmx5IGhhc2g6IFVJbnQyNTY7XG4gIHJlYWRvbmx5IGlucHV0OiBJbnB1dDtcbn1cblxuaW50ZXJmYWNlIE91dHB1dFdpdGhJbnB1dCB7XG4gIHJlYWRvbmx5IG91dHB1dDogT3V0cHV0O1xuICByZWFkb25seSBpbnB1dDogSW5wdXQ7XG59XG5cbmV4cG9ydCBjbGFzcyBXcml0ZUJhdGNoQmxvY2tjaGFpbiB7XG4gIHB1YmxpYyByZWFkb25seSBzZXR0aW5nczogV3JpdGVCbG9ja2NoYWluWydzZXR0aW5ncyddO1xuICBwdWJsaWMgcmVhZG9ubHkgYWNjb3VudDogUmVhZEFsbEFkZFVwZGF0ZURlbGV0ZVN0b3JhZ2VDYWNoZTxBY2NvdW50S2V5LCBBY2NvdW50LCBBY2NvdW50VXBkYXRlPjtcbiAgcHVibGljIHJlYWRvbmx5IGFjY291bnRVbnNwZW50OiBSZWFkR2V0QWxsQWRkRGVsZXRlU3RvcmFnZUNhY2hlPFxuICAgIEFjY291bnRVbnNwZW50S2V5LFxuICAgIEFjY291bnRVbnNwZW50c0tleSxcbiAgICBBY2NvdW50VW5zcGVudFxuICA+O1xuICBwdWJsaWMgcmVhZG9ubHkgYWNjb3VudFVuY2xhaW1lZDogUmVhZEdldEFsbEFkZERlbGV0ZVN0b3JhZ2VDYWNoZTxcbiAgICBBY2NvdW50VW5jbGFpbWVkS2V5LFxuICAgIEFjY291bnRVbmNsYWltZWRzS2V5LFxuICAgIEFjY291bnRVbmNsYWltZWRcbiAgPjtcbiAgcHVibGljIHJlYWRvbmx5IGFjdGlvbjogUmVhZEdldEFsbEFkZFN0b3JhZ2VDYWNoZTxBY3Rpb25LZXksIEFjdGlvbnNLZXksIEFjdGlvbj47XG4gIHB1YmxpYyByZWFkb25seSBhc3NldDogUmVhZEFkZFVwZGF0ZVN0b3JhZ2VDYWNoZTxBc3NldEtleSwgQXNzZXQsIEFzc2V0VXBkYXRlPjtcbiAgcHVibGljIHJlYWRvbmx5IGJsb2NrOiBCbG9ja0xpa2VTdG9yYWdlQ2FjaGU8QmxvY2s+O1xuICBwdWJsaWMgcmVhZG9ubHkgYmxvY2tEYXRhOiBSZWFkQWRkU3RvcmFnZUNhY2hlPEJsb2NrRGF0YUtleSwgQmxvY2tEYXRhPjtcbiAgcHVibGljIHJlYWRvbmx5IGhlYWRlcjogQmxvY2tMaWtlU3RvcmFnZUNhY2hlPEhlYWRlcj47XG4gIHB1YmxpYyByZWFkb25seSB0cmFuc2FjdGlvbjogUmVhZEFkZFN0b3JhZ2VDYWNoZTxUcmFuc2FjdGlvbktleSwgVHJhbnNhY3Rpb24+O1xuICBwdWJsaWMgcmVhZG9ubHkgdHJhbnNhY3Rpb25EYXRhOiBSZWFkQWRkVXBkYXRlU3RvcmFnZUNhY2hlPFxuICAgIFRyYW5zYWN0aW9uRGF0YUtleSxcbiAgICBUcmFuc2FjdGlvbkRhdGEsXG4gICAgVHJhbnNhY3Rpb25EYXRhVXBkYXRlXG4gID47XG4gIHB1YmxpYyByZWFkb25seSBvdXRwdXQ6IE91dHB1dFN0b3JhZ2VDYWNoZTtcbiAgcHVibGljIHJlYWRvbmx5IGNvbnRyYWN0OiBSZWFkQWRkRGVsZXRlU3RvcmFnZUNhY2hlPENvbnRyYWN0S2V5LCBDb250cmFjdD47XG4gIHB1YmxpYyByZWFkb25seSBzdG9yYWdlSXRlbTogUmVhZEdldEFsbEFkZFVwZGF0ZURlbGV0ZVN0b3JhZ2VDYWNoZTxcbiAgICBTdG9yYWdlSXRlbUtleSxcbiAgICBTdG9yYWdlSXRlbXNLZXksXG4gICAgU3RvcmFnZUl0ZW0sXG4gICAgU3RvcmFnZUl0ZW1VcGRhdGVcbiAgPjtcbiAgcHVibGljIHJlYWRvbmx5IHZhbGlkYXRvcjogUmVhZEFsbEFkZFVwZGF0ZURlbGV0ZVN0b3JhZ2VDYWNoZTxWYWxpZGF0b3JLZXksIFZhbGlkYXRvciwgVmFsaWRhdG9yVXBkYXRlPjtcbiAgcHVibGljIHJlYWRvbmx5IGludm9jYXRpb25EYXRhOiBSZWFkQWRkU3RvcmFnZUNhY2hlPEludm9jYXRpb25EYXRhS2V5LCBJbnZvY2F0aW9uRGF0YT47XG4gIHB1YmxpYyByZWFkb25seSB2YWxpZGF0b3JzQ291bnQ6IFJlYWRBZGRVcGRhdGVNZXRhZGF0YVN0b3JhZ2VDYWNoZTxWYWxpZGF0b3JzQ291bnQsIFZhbGlkYXRvcnNDb3VudFVwZGF0ZT47XG4gIHB1YmxpYyByZWFkb25seSBnZXRWYWxpZGF0b3JzOiBXcml0ZUJsb2NrY2hhaW5bJ2dldFZhbGlkYXRvcnMnXTtcbiAgcHJpdmF0ZSByZWFkb25seSBjdXJyZW50QmxvY2tJbnRlcm5hbDogV3JpdGVCbG9ja2NoYWluWydjdXJyZW50QmxvY2snXSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBjdXJyZW50SGVhZGVySW50ZXJuYWw6IFdyaXRlQmxvY2tjaGFpblsnY3VycmVudEhlYWRlciddIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0b3JhZ2U6IEJsb2NrY2hhaW5TdG9yYWdlO1xuICBwcml2YXRlIHJlYWRvbmx5IHZtOiBWTTtcbiAgcHJpdmF0ZSByZWFkb25seSBjYWNoZXM6IENhY2hlcztcblxuICBwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9uczogV3JpdGVCYXRjaEJsb2NrY2hhaW5PcHRpb25zKSB7XG4gICAgdGhpcy5zZXR0aW5ncyA9IG9wdGlvbnMuc2V0dGluZ3M7XG4gICAgdGhpcy5jdXJyZW50QmxvY2tJbnRlcm5hbCA9IG9wdGlvbnMuY3VycmVudEJsb2NrO1xuICAgIHRoaXMuY3VycmVudEhlYWRlckludGVybmFsID0gb3B0aW9ucy5jdXJyZW50SGVhZGVyO1xuICAgIHRoaXMuc3RvcmFnZSA9IG9wdGlvbnMuc3RvcmFnZTtcbiAgICB0aGlzLnZtID0gb3B0aW9ucy52bTtcbiAgICB0aGlzLmdldFZhbGlkYXRvcnMgPSBvcHRpb25zLmdldFZhbGlkYXRvcnM7XG5cbiAgICBjb25zdCBvdXRwdXQgPSBuZXcgT3V0cHV0U3RvcmFnZUNhY2hlKCgpID0+IHRoaXMuc3RvcmFnZS5vdXRwdXQpO1xuICAgIHRoaXMuY2FjaGVzID0ge1xuICAgICAgYWNjb3VudDogbmV3IFJlYWRBbGxBZGRVcGRhdGVEZWxldGVTdG9yYWdlQ2FjaGUoe1xuICAgICAgICBuYW1lOiAnYWNjb3VudCcsXG4gICAgICAgIHJlYWRBbGxTdG9yYWdlOiAoKSA9PiB0aGlzLnN0b3JhZ2UuYWNjb3VudCxcbiAgICAgICAgdXBkYXRlOiAodmFsdWUsIHVwZGF0ZSkgPT4gdmFsdWUudXBkYXRlKHVwZGF0ZSksXG4gICAgICAgIGdldEtleUZyb21WYWx1ZTogKHZhbHVlKSA9PiAoeyBoYXNoOiB2YWx1ZS5oYXNoIH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+IGNvbW1vbi51SW50MTYwVG9TdHJpbmcoa2V5Lmhhc2gpLFxuICAgICAgICBjcmVhdGVBZGRDaGFuZ2U6ICh2YWx1ZSkgPT4gKHsgdHlwZTogJ2FjY291bnQnLCB2YWx1ZSB9KSxcbiAgICAgICAgY3JlYXRlRGVsZXRlQ2hhbmdlOiAoa2V5KSA9PiAoeyB0eXBlOiAnYWNjb3VudCcsIGtleSB9KSxcbiAgICAgIH0pLFxuICAgICAgYWNjb3VudFVuc3BlbnQ6IG5ldyBSZWFkR2V0QWxsQWRkRGVsZXRlU3RvcmFnZUNhY2hlKHtcbiAgICAgICAgbmFtZTogJ2FjY291bnRVbnNwZW50JyxcbiAgICAgICAgcmVhZEdldEFsbFN0b3JhZ2U6ICgpID0+IHRoaXMuc3RvcmFnZS5hY2NvdW50VW5zcGVudCxcbiAgICAgICAgZ2V0S2V5RnJvbVZhbHVlOiAodmFsdWUpID0+ICh7IGhhc2g6IHZhbHVlLmhhc2gsIGlucHV0OiB2YWx1ZS5pbnB1dCB9KSxcbiAgICAgICAgZ2V0S2V5U3RyaW5nOiAoa2V5KSA9PlxuICAgICAgICAgIGAke2NvbW1vbi51SW50MTYwVG9TdHJpbmcoa2V5Lmhhc2gpfToke2NvbW1vbi51SW50MjU2VG9TdHJpbmcoa2V5LmlucHV0Lmhhc2gpfToke2tleS5pbnB1dC5pbmRleH1gLFxuICAgICAgICBtYXRjaGVzUGFydGlhbEtleTogKHZhbHVlLCBrZXkpID0+IGNvbW1vbi51SW50MTYwRXF1YWwodmFsdWUuaGFzaCwga2V5Lmhhc2gpLFxuICAgICAgICBjcmVhdGVBZGRDaGFuZ2U6ICh2YWx1ZSkgPT4gKHsgdHlwZTogJ2FjY291bnRVbnNwZW50JywgdmFsdWUgfSksXG4gICAgICAgIGNyZWF0ZURlbGV0ZUNoYW5nZTogKGtleSkgPT4gKHsgdHlwZTogJ2FjY291bnRVbnNwZW50Jywga2V5IH0pLFxuICAgICAgfSksXG4gICAgICBhY2NvdW50VW5jbGFpbWVkOiBuZXcgUmVhZEdldEFsbEFkZERlbGV0ZVN0b3JhZ2VDYWNoZSh7XG4gICAgICAgIG5hbWU6ICdhY2NvdW50VW5jbGFpbWVkJyxcbiAgICAgICAgcmVhZEdldEFsbFN0b3JhZ2U6ICgpID0+IHRoaXMuc3RvcmFnZS5hY2NvdW50VW5jbGFpbWVkLFxuICAgICAgICBnZXRLZXlGcm9tVmFsdWU6ICh2YWx1ZSkgPT4gKHsgaGFzaDogdmFsdWUuaGFzaCwgaW5wdXQ6IHZhbHVlLmlucHV0IH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+XG4gICAgICAgICAgYCR7Y29tbW9uLnVJbnQxNjBUb1N0cmluZyhrZXkuaGFzaCl9OiR7Y29tbW9uLnVJbnQyNTZUb1N0cmluZyhrZXkuaW5wdXQuaGFzaCl9OiR7a2V5LmlucHV0LmluZGV4fWAsXG4gICAgICAgIG1hdGNoZXNQYXJ0aWFsS2V5OiAodmFsdWUsIGtleSkgPT4gY29tbW9uLnVJbnQxNjBFcXVhbCh2YWx1ZS5oYXNoLCBrZXkuaGFzaCksXG4gICAgICAgIGNyZWF0ZUFkZENoYW5nZTogKHZhbHVlKSA9PiAoeyB0eXBlOiAnYWNjb3VudFVuY2xhaW1lZCcsIHZhbHVlIH0pLFxuICAgICAgICBjcmVhdGVEZWxldGVDaGFuZ2U6IChrZXkpID0+ICh7IHR5cGU6ICdhY2NvdW50VW5jbGFpbWVkJywga2V5IH0pLFxuICAgICAgfSksXG4gICAgICBhY3Rpb246IG5ldyBSZWFkR2V0QWxsQWRkU3RvcmFnZUNhY2hlKHtcbiAgICAgICAgbmFtZTogJ2FjdGlvbicsXG4gICAgICAgIHJlYWRHZXRBbGxTdG9yYWdlOiAoKSA9PiB0aGlzLnN0b3JhZ2UuYWN0aW9uLFxuICAgICAgICBnZXRLZXlGcm9tVmFsdWU6ICh2YWx1ZSkgPT4gKHtcbiAgICAgICAgICBpbmRleDogdmFsdWUuaW5kZXgsXG4gICAgICAgIH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+IGtleS5pbmRleC50b1N0cmluZygxMCksXG4gICAgICAgIG1hdGNoZXNQYXJ0aWFsS2V5OiAodmFsdWUsIGtleSkgPT5cbiAgICAgICAgICAoa2V5LmluZGV4U3RhcnQgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZS5pbmRleC5ndGUoa2V5LmluZGV4U3RhcnQpKSAmJlxuICAgICAgICAgIChrZXkuaW5kZXhTdG9wID09PSB1bmRlZmluZWQgfHwgdmFsdWUuaW5kZXgubHRlKGtleS5pbmRleFN0b3ApKSxcbiAgICAgICAgY3JlYXRlQWRkQ2hhbmdlOiAodmFsdWUpID0+ICh7IHR5cGU6ICdhY3Rpb24nLCB2YWx1ZSB9KSxcbiAgICAgIH0pLFxuICAgICAgYXNzZXQ6IG5ldyBSZWFkQWRkVXBkYXRlU3RvcmFnZUNhY2hlKHtcbiAgICAgICAgbmFtZTogJ2Fzc2V0JyxcbiAgICAgICAgcmVhZFN0b3JhZ2U6ICgpID0+IHRoaXMuc3RvcmFnZS5hc3NldCxcbiAgICAgICAgdXBkYXRlOiAodmFsdWUsIHVwZGF0ZSkgPT4gdmFsdWUudXBkYXRlKHVwZGF0ZSksXG4gICAgICAgIGdldEtleUZyb21WYWx1ZTogKHZhbHVlKSA9PiAoeyBoYXNoOiB2YWx1ZS5oYXNoIH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+IGNvbW1vbi51SW50MjU2VG9TdHJpbmcoa2V5Lmhhc2gpLFxuICAgICAgICBjcmVhdGVBZGRDaGFuZ2U6ICh2YWx1ZSkgPT4gKHsgdHlwZTogJ2Fzc2V0JywgdmFsdWUgfSksXG4gICAgICB9KSxcbiAgICAgIGJsb2NrOiBuZXcgQmxvY2tMaWtlU3RvcmFnZUNhY2hlKHtcbiAgICAgICAgbmFtZTogJ2Jsb2NrJyxcbiAgICAgICAgcmVhZFN0b3JhZ2U6ICgpID0+ICh7XG4gICAgICAgICAgZ2V0OiB0aGlzLnN0b3JhZ2UuYmxvY2suZ2V0LFxuICAgICAgICAgIHRyeUdldDogdGhpcy5zdG9yYWdlLmJsb2NrLnRyeUdldCxcbiAgICAgICAgfSksXG4gICAgICAgIGNyZWF0ZUFkZENoYW5nZTogKHZhbHVlKSA9PiAoeyB0eXBlOiAnYmxvY2snLCB2YWx1ZSB9KSxcbiAgICAgIH0pLFxuICAgICAgYmxvY2tEYXRhOiBuZXcgUmVhZEFkZFN0b3JhZ2VDYWNoZSh7XG4gICAgICAgIG5hbWU6ICdibG9ja0RhdGEnLFxuICAgICAgICByZWFkU3RvcmFnZTogKCkgPT4gdGhpcy5zdG9yYWdlLmJsb2NrRGF0YSxcbiAgICAgICAgZ2V0S2V5RnJvbVZhbHVlOiAodmFsdWUpID0+ICh7IGhhc2g6IHZhbHVlLmhhc2ggfSksXG4gICAgICAgIGdldEtleVN0cmluZzogKGtleSkgPT4gY29tbW9uLnVJbnQyNTZUb1N0cmluZyhrZXkuaGFzaCksXG4gICAgICAgIGNyZWF0ZUFkZENoYW5nZTogKHZhbHVlKSA9PiAoeyB0eXBlOiAnYmxvY2tEYXRhJywgdmFsdWUgfSksXG4gICAgICB9KSxcbiAgICAgIGhlYWRlcjogbmV3IEJsb2NrTGlrZVN0b3JhZ2VDYWNoZSh7XG4gICAgICAgIG5hbWU6ICdoZWFkZXInLFxuICAgICAgICByZWFkU3RvcmFnZTogKCkgPT4gKHtcbiAgICAgICAgICBnZXQ6IHRoaXMuc3RvcmFnZS5oZWFkZXIuZ2V0LFxuICAgICAgICAgIHRyeUdldDogdGhpcy5zdG9yYWdlLmhlYWRlci50cnlHZXQsXG4gICAgICAgIH0pLFxuICAgICAgICBjcmVhdGVBZGRDaGFuZ2U6ICh2YWx1ZSkgPT4gKHsgdHlwZTogJ2hlYWRlcicsIHZhbHVlIH0pLFxuICAgICAgfSksXG4gICAgICB0cmFuc2FjdGlvbjogbmV3IFJlYWRBZGRTdG9yYWdlQ2FjaGUoe1xuICAgICAgICBuYW1lOiAndHJhbnNhY3Rpb24nLFxuICAgICAgICByZWFkU3RvcmFnZTogKCkgPT4gdGhpcy5zdG9yYWdlLnRyYW5zYWN0aW9uLFxuICAgICAgICBnZXRLZXlGcm9tVmFsdWU6ICh2YWx1ZSkgPT4gKHsgaGFzaDogdmFsdWUuaGFzaCB9KSxcbiAgICAgICAgZ2V0S2V5U3RyaW5nOiAoa2V5KSA9PiBjb21tb24udUludDI1NlRvU3RyaW5nKGtleS5oYXNoKSxcbiAgICAgICAgY3JlYXRlQWRkQ2hhbmdlOiAodmFsdWUpID0+ICh7IHR5cGU6ICd0cmFuc2FjdGlvbicsIHZhbHVlIH0pLFxuICAgICAgICBvbkFkZDogYXN5bmMgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgICAgICB2YWx1ZS5vdXRwdXRzLm1hcChhc3luYyAob3V0LCBpbmRleCkgPT4gb3V0cHV0LmFkZCh7IGhhc2g6IHZhbHVlLmhhc2gsIGluZGV4LCBvdXRwdXQ6IG91dCB9KSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgYWxsb3dEdXBlczogdHJ1ZSxcbiAgICAgIH0pLFxuICAgICAgdHJhbnNhY3Rpb25EYXRhOiBuZXcgUmVhZEFkZFVwZGF0ZVN0b3JhZ2VDYWNoZSh7XG4gICAgICAgIG5hbWU6ICd0cmFuc2FjdGlvbkRhdGEnLFxuICAgICAgICByZWFkU3RvcmFnZTogKCkgPT4gdGhpcy5zdG9yYWdlLnRyYW5zYWN0aW9uRGF0YSxcbiAgICAgICAgdXBkYXRlOiAodmFsdWUsIHVwZGF0ZSkgPT4gdmFsdWUudXBkYXRlKHVwZGF0ZSksXG4gICAgICAgIGdldEtleUZyb21WYWx1ZTogKHZhbHVlKSA9PiAoeyBoYXNoOiB2YWx1ZS5oYXNoIH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+IGNvbW1vbi51SW50MjU2VG9TdHJpbmcoa2V5Lmhhc2gpLFxuICAgICAgICBjcmVhdGVBZGRDaGFuZ2U6ICh2YWx1ZSkgPT4gKHsgdHlwZTogJ3RyYW5zYWN0aW9uRGF0YScsIHZhbHVlIH0pLFxuICAgICAgICBhbGxvd0R1cGVzOiB0cnVlLFxuICAgICAgfSksXG4gICAgICBvdXRwdXQsXG4gICAgICBjb250cmFjdDogbmV3IFJlYWRBZGREZWxldGVTdG9yYWdlQ2FjaGUoe1xuICAgICAgICBuYW1lOiAnY29udHJhY3QnLFxuICAgICAgICByZWFkU3RvcmFnZTogKCkgPT4gdGhpcy5zdG9yYWdlLmNvbnRyYWN0LFxuICAgICAgICBnZXRLZXlGcm9tVmFsdWU6ICh2YWx1ZSkgPT4gKHsgaGFzaDogdmFsdWUuaGFzaCB9KSxcbiAgICAgICAgZ2V0S2V5U3RyaW5nOiAoa2V5KSA9PiBjb21tb24udUludDE2MFRvU3RyaW5nKGtleS5oYXNoKSxcbiAgICAgICAgY3JlYXRlQWRkQ2hhbmdlOiAodmFsdWUpID0+ICh7IHR5cGU6ICdjb250cmFjdCcsIHZhbHVlIH0pLFxuICAgICAgICBjcmVhdGVEZWxldGVDaGFuZ2U6IChrZXkpID0+ICh7IHR5cGU6ICdjb250cmFjdCcsIGtleSB9KSxcbiAgICAgIH0pLFxuICAgICAgc3RvcmFnZUl0ZW06IG5ldyBSZWFkR2V0QWxsQWRkVXBkYXRlRGVsZXRlU3RvcmFnZUNhY2hlKHtcbiAgICAgICAgbmFtZTogJ3N0b3JhZ2VJdGVtJyxcbiAgICAgICAgcmVhZEdldEFsbFN0b3JhZ2U6ICgpID0+IHRoaXMuc3RvcmFnZS5zdG9yYWdlSXRlbSxcbiAgICAgICAgdXBkYXRlOiAodmFsdWUsIHVwZGF0ZSkgPT4gdmFsdWUudXBkYXRlKHVwZGF0ZSksXG4gICAgICAgIGdldEtleUZyb21WYWx1ZTogKHZhbHVlKSA9PiAoe1xuICAgICAgICAgIGhhc2g6IHZhbHVlLmhhc2gsXG4gICAgICAgICAga2V5OiB2YWx1ZS5rZXksXG4gICAgICAgIH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+IGAke2NvbW1vbi51SW50MTYwVG9TdHJpbmcoa2V5Lmhhc2gpfToke2tleS5rZXkudG9TdHJpbmcoJ2hleCcpfWAsXG4gICAgICAgIG1hdGNoZXNQYXJ0aWFsS2V5OiAodmFsdWUsIGtleSkgPT5cbiAgICAgICAgICAoa2V5Lmhhc2ggPT09IHVuZGVmaW5lZCB8fCBjb21tb24udUludDE2MEVxdWFsKHZhbHVlLmhhc2gsIGtleS5oYXNoKSkgJiZcbiAgICAgICAgICAoa2V5LnByZWZpeCA9PT0gdW5kZWZpbmVkIHx8IGtleS5wcmVmaXguZXZlcnkoKGJ5dGUsIGlkeCkgPT4gdmFsdWUua2V5W2lkeF0gPT09IGJ5dGUpKSxcbiAgICAgICAgY3JlYXRlQWRkQ2hhbmdlOiAodmFsdWUpID0+ICh7IHR5cGU6ICdzdG9yYWdlSXRlbScsIHZhbHVlIH0pLFxuICAgICAgICBjcmVhdGVEZWxldGVDaGFuZ2U6IChrZXkpID0+ICh7IHR5cGU6ICdzdG9yYWdlSXRlbScsIGtleSB9KSxcbiAgICAgIH0pLFxuICAgICAgdmFsaWRhdG9yOiBuZXcgUmVhZEFsbEFkZFVwZGF0ZURlbGV0ZVN0b3JhZ2VDYWNoZSh7XG4gICAgICAgIG5hbWU6ICd2YWxpZGF0b3InLFxuICAgICAgICByZWFkQWxsU3RvcmFnZTogKCkgPT4gdGhpcy5zdG9yYWdlLnZhbGlkYXRvcixcbiAgICAgICAgZ2V0S2V5RnJvbVZhbHVlOiAodmFsdWUpID0+ICh7IHB1YmxpY0tleTogdmFsdWUucHVibGljS2V5IH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+IGNvbW1vbi5lY1BvaW50VG9TdHJpbmcoa2V5LnB1YmxpY0tleSksXG4gICAgICAgIGNyZWF0ZUFkZENoYW5nZTogKHZhbHVlKSA9PiAoeyB0eXBlOiAndmFsaWRhdG9yJywgdmFsdWUgfSksXG4gICAgICAgIHVwZGF0ZTogKHZhbHVlLCB1cGRhdGUpID0+IHZhbHVlLnVwZGF0ZSh1cGRhdGUpLFxuICAgICAgICBjcmVhdGVEZWxldGVDaGFuZ2U6IChrZXkpID0+ICh7IHR5cGU6ICd2YWxpZGF0b3InLCBrZXkgfSksXG4gICAgICB9KSxcbiAgICAgIGludm9jYXRpb25EYXRhOiBuZXcgUmVhZEFkZFN0b3JhZ2VDYWNoZSh7XG4gICAgICAgIG5hbWU6ICdpbnZvY2F0aW9uRGF0YScsXG4gICAgICAgIHJlYWRTdG9yYWdlOiAoKSA9PiB0aGlzLnN0b3JhZ2UuaW52b2NhdGlvbkRhdGEsXG4gICAgICAgIGdldEtleUZyb21WYWx1ZTogKHZhbHVlKSA9PiAoeyBoYXNoOiB2YWx1ZS5oYXNoIH0pLFxuICAgICAgICBnZXRLZXlTdHJpbmc6IChrZXkpID0+IGNvbW1vbi51SW50MjU2VG9TdHJpbmcoa2V5Lmhhc2gpLFxuICAgICAgICBjcmVhdGVBZGRDaGFuZ2U6ICh2YWx1ZSkgPT4gKHsgdHlwZTogJ2ludm9jYXRpb25EYXRhJywgdmFsdWUgfSksXG4gICAgICB9KSxcbiAgICAgIHZhbGlkYXRvcnNDb3VudDogbmV3IFJlYWRBZGRVcGRhdGVNZXRhZGF0YVN0b3JhZ2VDYWNoZSh7XG4gICAgICAgIG5hbWU6ICd2YWxpZGF0b3JzQ291bnQnLFxuICAgICAgICByZWFkU3RvcmFnZTogKCkgPT4gdGhpcy5zdG9yYWdlLnZhbGlkYXRvcnNDb3VudCxcbiAgICAgICAgY3JlYXRlQWRkQ2hhbmdlOiAodmFsdWUpID0+ICh7IHR5cGU6ICd2YWxpZGF0b3JzQ291bnQnLCB2YWx1ZSB9KSxcbiAgICAgICAgdXBkYXRlOiAodmFsdWUsIHVwZGF0ZSkgPT4gdmFsdWUudXBkYXRlKHVwZGF0ZSksXG4gICAgICB9KSxcbiAgICB9O1xuXG4gICAgdGhpcy5hY2NvdW50ID0gdGhpcy5jYWNoZXMuYWNjb3VudDtcbiAgICB0aGlzLmFjY291bnRVbnNwZW50ID0gdGhpcy5jYWNoZXMuYWNjb3VudFVuc3BlbnQ7XG4gICAgdGhpcy5hY2NvdW50VW5jbGFpbWVkID0gdGhpcy5jYWNoZXMuYWNjb3VudFVuY2xhaW1lZDtcbiAgICB0aGlzLmFjdGlvbiA9IHRoaXMuY2FjaGVzLmFjdGlvbjtcbiAgICB0aGlzLmFzc2V0ID0gdGhpcy5jYWNoZXMuYXNzZXQ7XG4gICAgdGhpcy5ibG9jayA9IHRoaXMuY2FjaGVzLmJsb2NrO1xuICAgIHRoaXMuYmxvY2tEYXRhID0gdGhpcy5jYWNoZXMuYmxvY2tEYXRhO1xuICAgIHRoaXMuaGVhZGVyID0gdGhpcy5jYWNoZXMuaGVhZGVyO1xuICAgIHRoaXMudHJhbnNhY3Rpb24gPSB0aGlzLmNhY2hlcy50cmFuc2FjdGlvbjtcbiAgICB0aGlzLnRyYW5zYWN0aW9uRGF0YSA9IHRoaXMuY2FjaGVzLnRyYW5zYWN0aW9uRGF0YTtcbiAgICB0aGlzLm91dHB1dCA9IHRoaXMuY2FjaGVzLm91dHB1dDtcbiAgICB0aGlzLmNvbnRyYWN0ID0gdGhpcy5jYWNoZXMuY29udHJhY3Q7XG4gICAgdGhpcy5zdG9yYWdlSXRlbSA9IHRoaXMuY2FjaGVzLnN0b3JhZ2VJdGVtO1xuICAgIHRoaXMudmFsaWRhdG9yID0gdGhpcy5jYWNoZXMudmFsaWRhdG9yO1xuICAgIHRoaXMuaW52b2NhdGlvbkRhdGEgPSB0aGlzLmNhY2hlcy5pbnZvY2F0aW9uRGF0YTtcbiAgICB0aGlzLnZhbGlkYXRvcnNDb3VudCA9IHRoaXMuY2FjaGVzLnZhbGlkYXRvcnNDb3VudDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY3VycmVudEJsb2NrKCk6IEJsb2NrIHtcbiAgICBpZiAodGhpcy5jdXJyZW50QmxvY2tJbnRlcm5hbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgR2VuZXNpc0Jsb2NrTm90UmVnaXN0ZXJlZEVycm9yKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY3VycmVudEJsb2NrSW50ZXJuYWw7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGN1cnJlbnRCbG9ja0luZGV4KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudEJsb2NrSW50ZXJuYWwgPT09IHVuZGVmaW5lZCA/IDAgOiB0aGlzLmN1cnJlbnRCbG9ja0ludGVybmFsLmluZGV4O1xuICB9XG5cbiAgcHVibGljIGdldCBjdXJyZW50SGVhZGVyKCk6IEhlYWRlciB7XG4gICAgaWYgKHRoaXMuY3VycmVudEhlYWRlckludGVybmFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBHZW5lc2lzQmxvY2tOb3RSZWdpc3RlcmVkRXJyb3IoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jdXJyZW50SGVhZGVySW50ZXJuYWw7XG4gIH1cblxuICBwdWJsaWMgZ2V0Q2hhbmdlU2V0KCk6IENoYW5nZVNldCB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5jYWNoZXMpLnJlZHVjZTxDaGFuZ2VTZXQ+KChhY2MsIGNhY2hlKSA9PiBhY2MuY29uY2F0KGNhY2hlLmdldENoYW5nZVNldCgpKSwgW10pO1xuICB9XG5cbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFueVxuICBwdWJsaWMgZ2V0VHJhY2tlZENoYW5nZVNldCgpOiBUcmFja2VkQ2hhbmdlU2V0PGFueSwgYW55LCBhbnk+IHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYW55XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5jYWNoZXMpLnJlZHVjZTxUcmFja2VkQ2hhbmdlU2V0PGFueSwgYW55LCBhbnk+PihcbiAgICAgIChhY2MsIGNhY2hlKSA9PiBhY2MuY29uY2F0KGNhY2hlLmdldFRyYWNrZWRDaGFuZ2VTZXQoKSksXG4gICAgICBbXSxcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHBlcnNpc3RCbG9jayhibG9jazogQmxvY2spOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBbbWF5YmVQcmV2QmxvY2tEYXRhLCBvdXRwdXRDb250cmFjdHNMaXN0XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIGJsb2NrLmluZGV4ID09PSAwID8gUHJvbWlzZS5yZXNvbHZlKHVuZGVmaW5lZCkgOiB0aGlzLmJsb2NrRGF0YS5nZXQoeyBoYXNoOiBibG9jay5wcmV2aW91c0hhc2ggfSksXG4gICAgICBQcm9taXNlLmFsbChcbiAgICAgICAgW1xuICAgICAgICAgIC4uLm5ldyBTZXQoXG4gICAgICAgICAgICBibG9jay50cmFuc2FjdGlvbnMucmVkdWNlPHN0cmluZ1tdPihcbiAgICAgICAgICAgICAgKGFjYywgdHJhbnNhY3Rpb24pID0+XG4gICAgICAgICAgICAgICAgYWNjLmNvbmNhdCh0cmFuc2FjdGlvbi5vdXRwdXRzLm1hcCgob3V0cHV0KSA9PiBjb21tb24udUludDE2MFRvU3RyaW5nKG91dHB1dC5hZGRyZXNzKSkpLFxuXG4gICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICApLFxuICAgICAgICBdLm1hcChhc3luYyAoaGFzaCkgPT4gdGhpcy5jb250cmFjdC50cnlHZXQoeyBoYXNoOiBjb21tb24uc3RyaW5nVG9VSW50MTYwKGhhc2gpIH0pKSxcbiAgICAgICksXG5cbiAgICAgIHRoaXMuYmxvY2suYWRkKGJsb2NrKSxcbiAgICAgIHRoaXMuaGVhZGVyLmFkZChibG9jay5oZWFkZXIpLFxuICAgIF0pO1xuXG4gICAgY29uc3QgcHJldkJsb2NrRGF0YSA9XG4gICAgICBtYXliZVByZXZCbG9ja0RhdGEgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIGxhc3RHbG9iYWxUcmFuc2FjdGlvbkluZGV4OiB1dGlscy5ORUdBVElWRV9PTkUsXG4gICAgICAgICAgICBsYXN0R2xvYmFsQWN0aW9uSW5kZXg6IHV0aWxzLk5FR0FUSVZFX09ORSxcbiAgICAgICAgICAgIHN5c3RlbUZlZTogdXRpbHMuWkVSTyxcbiAgICAgICAgICB9XG4gICAgICAgIDoge1xuICAgICAgICAgICAgbGFzdEdsb2JhbFRyYW5zYWN0aW9uSW5kZXg6IG1heWJlUHJldkJsb2NrRGF0YS5sYXN0R2xvYmFsVHJhbnNhY3Rpb25JbmRleCxcbiAgICAgICAgICAgIGxhc3RHbG9iYWxBY3Rpb25JbmRleDogbWF5YmVQcmV2QmxvY2tEYXRhLmxhc3RHbG9iYWxBY3Rpb25JbmRleCxcbiAgICAgICAgICAgIHN5c3RlbUZlZTogbWF5YmVQcmV2QmxvY2tEYXRhLnN5c3RlbUZlZSxcbiAgICAgICAgICB9O1xuXG4gICAgY29uc3Qgb3V0cHV0Q29udHJhY3RzOiB7IFtrZXk6IHN0cmluZ106IENvbnRyYWN0IHwgdW5kZWZpbmVkIH0gPSB7fTtcbiAgICBvdXRwdXRDb250cmFjdHNMaXN0LmZpbHRlcihjb21tb25VdGlscy5ub3ROdWxsKS5mb3JFYWNoKChvdXRwdXRDb250cmFjdCkgPT4ge1xuICAgICAgb3V0cHV0Q29udHJhY3RzW291dHB1dENvbnRyYWN0Lmhhc2hIZXhdID0gb3V0cHV0Q29udHJhY3Q7XG4gICAgfSk7XG5cbiAgICBjb25zdCBbdXR4bywgcmVzdF0gPSBfLnBhcnRpdGlvbihcbiAgICAgIGJsb2NrLnRyYW5zYWN0aW9ucy5tYXA8W251bWJlciwgVHJhbnNhY3Rpb25dPigodHJhbnNhY3Rpb24sIGlkeCkgPT4gW2lkeCwgdHJhbnNhY3Rpb25dKSxcbiAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWRcbiAgICAgIChbaWR4LCB0cmFuc2FjdGlvbl0pID0+XG4gICAgICAgICgodHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkNsYWltICYmIHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgQ2xhaW1UcmFuc2FjdGlvbikgfHxcbiAgICAgICAgICAodHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkNvbnRyYWN0ICYmIHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgQ29udHJhY3RUcmFuc2FjdGlvbikgfHxcbiAgICAgICAgICAodHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLk1pbmVyICYmIHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgTWluZXJUcmFuc2FjdGlvbikpICYmXG4gICAgICAgICF0cmFuc2FjdGlvbi5vdXRwdXRzLnNvbWUoKG91dHB1dCkgPT4gb3V0cHV0Q29udHJhY3RzW2NvbW1vbi51SW50MTYwVG9TdHJpbmcob3V0cHV0LmFkZHJlc3MpXSAhPT0gdW5kZWZpbmVkKSxcbiAgICApO1xuXG4gICAgY29uc3QgW2dsb2JhbEFjdGlvbkluZGV4XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIHJlc3QubGVuZ3RoID4gMFxuICAgICAgICA/IHRoaXMucGVyc2lzdFRyYW5zYWN0aW9ucyhcbiAgICAgICAgICAgIGJsb2NrLFxuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFueVxuICAgICAgICAgICAgcmVzdCBhcyBhbnksXG4gICAgICAgICAgICBwcmV2QmxvY2tEYXRhLmxhc3RHbG9iYWxUcmFuc2FjdGlvbkluZGV4LFxuICAgICAgICAgICAgcHJldkJsb2NrRGF0YS5sYXN0R2xvYmFsQWN0aW9uSW5kZXgsXG4gICAgICAgICAgKVxuICAgICAgICA6IFByb21pc2UucmVzb2x2ZShwcmV2QmxvY2tEYXRhLmxhc3RHbG9iYWxBY3Rpb25JbmRleCksXG4gICAgICB1dHhvLmxlbmd0aCA+IDBcbiAgICAgICAgPyAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tYW55XG4gICAgICAgICAgdGhpcy5wZXJzaXN0VVRYT1RyYW5zYWN0aW9ucyhibG9jaywgdXR4byBhcyBhbnksIHByZXZCbG9ja0RhdGEubGFzdEdsb2JhbFRyYW5zYWN0aW9uSW5kZXgpXG4gICAgICAgIDogUHJvbWlzZS5yZXNvbHZlKCksXG4gICAgXSk7XG5cbiAgICBhd2FpdCB0aGlzLmJsb2NrRGF0YS5hZGQoXG4gICAgICBuZXcgQmxvY2tEYXRhKHtcbiAgICAgICAgaGFzaDogYmxvY2suaGFzaCxcbiAgICAgICAgbGFzdEdsb2JhbFRyYW5zYWN0aW9uSW5kZXg6IHByZXZCbG9ja0RhdGEubGFzdEdsb2JhbFRyYW5zYWN0aW9uSW5kZXguYWRkKG5ldyBCTihibG9jay50cmFuc2FjdGlvbnMubGVuZ3RoKSksXG5cbiAgICAgICAgbGFzdEdsb2JhbEFjdGlvbkluZGV4OiBnbG9iYWxBY3Rpb25JbmRleCxcbiAgICAgICAgc3lzdGVtRmVlOiBwcmV2QmxvY2tEYXRhLnN5c3RlbUZlZS5hZGQoXG4gICAgICAgICAgYmxvY2suZ2V0U3lzdGVtRmVlKHtcbiAgICAgICAgICAgIGdldE91dHB1dDogdGhpcy5vdXRwdXQuZ2V0LFxuICAgICAgICAgICAgZ292ZXJuaW5nVG9rZW46IHRoaXMuc2V0dGluZ3MuZ292ZXJuaW5nVG9rZW4sXG4gICAgICAgICAgICB1dGlsaXR5VG9rZW46IHRoaXMuc2V0dGluZ3MudXRpbGl0eVRva2VuLFxuICAgICAgICAgICAgZmVlczogdGhpcy5zZXR0aW5ncy5mZWVzLFxuICAgICAgICAgICAgcmVnaXN0ZXJWYWxpZGF0b3JGZWU6IHRoaXMuc2V0dGluZ3MucmVnaXN0ZXJWYWxpZGF0b3JGZWUsXG4gICAgICAgICAgfSksXG4gICAgICAgICksXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwZXJzaXN0VVRYT1RyYW5zYWN0aW9ucyhcbiAgICBibG9jazogQmxvY2ssXG4gICAgdHJhbnNhY3Rpb25zOiBSZWFkb25seUFycmF5PHJlYWRvbmx5IFtudW1iZXIsIChDb250cmFjdFRyYW5zYWN0aW9uIHwgQ2xhaW1UcmFuc2FjdGlvbiB8IE1pbmVyVHJhbnNhY3Rpb24pXT4sXG4gICAgbGFzdEdsb2JhbFRyYW5zYWN0aW9uSW5kZXg6IEJOLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBpbnB1dHMgPSBbXTtcbiAgICBjb25zdCBjbGFpbXMgPSBbXTtcbiAgICBjb25zdCBvdXRwdXRXaXRoSW5wdXRzID0gW107XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZCBuby1sb29wLXN0YXRlbWVudCBuby1kZWFkLXN0b3JlXG4gICAgZm9yIChjb25zdCBpZHhBbmRUcmFuc2FjdGlvbiBvZiB0cmFuc2FjdGlvbnMpIHtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gaWR4QW5kVHJhbnNhY3Rpb25bMV07XG4gICAgICBpbnB1dHMucHVzaCguLi50cmFuc2FjdGlvbi5pbnB1dHMpO1xuICAgICAgaWYgKHRyYW5zYWN0aW9uLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5DbGFpbSAmJiB0cmFuc2FjdGlvbiBpbnN0YW5jZW9mIENsYWltVHJhbnNhY3Rpb24pIHtcbiAgICAgICAgY2xhaW1zLnB1c2goLi4udHJhbnNhY3Rpb24uY2xhaW1zKTtcbiAgICAgIH1cbiAgICAgIG91dHB1dFdpdGhJbnB1dHMucHVzaCguLi50aGlzLmdldE91dHB1dFdpdGhJbnB1dCh0cmFuc2FjdGlvbikpO1xuICAgIH1cbiAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICBQcm9taXNlLmFsbChcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZFxuICAgICAgICB0cmFuc2FjdGlvbnMubWFwKGFzeW5jIChbaWR4LCB0cmFuc2FjdGlvbl0pID0+IHRoaXMudHJhbnNhY3Rpb24uYWRkKHRyYW5zYWN0aW9uKSksXG4gICAgICApLFxuICAgICAgUHJvbWlzZS5hbGwoXG4gICAgICAgIHRyYW5zYWN0aW9ucy5tYXAoYXN5bmMgKFtpZHgsIHRyYW5zYWN0aW9uXSkgPT5cbiAgICAgICAgICB0aGlzLnRyYW5zYWN0aW9uRGF0YS5hZGQoXG4gICAgICAgICAgICBuZXcgVHJhbnNhY3Rpb25EYXRhKHtcbiAgICAgICAgICAgICAgaGFzaDogdHJhbnNhY3Rpb24uaGFzaCxcbiAgICAgICAgICAgICAgc3RhcnRIZWlnaHQ6IGJsb2NrLmluZGV4LFxuICAgICAgICAgICAgICBibG9ja0hhc2g6IGJsb2NrLmhhc2gsXG4gICAgICAgICAgICAgIGluZGV4OiBpZHgsXG4gICAgICAgICAgICAgIGdsb2JhbEluZGV4OiBsYXN0R2xvYmFsVHJhbnNhY3Rpb25JbmRleC5hZGQobmV3IEJOKGlkeCArIDEpKSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICksXG4gICAgICAgICksXG4gICAgICApLFxuXG4gICAgICB0aGlzLnVwZGF0ZUFjY291bnRzKGlucHV0cywgY2xhaW1zLCBvdXRwdXRXaXRoSW5wdXRzKSxcbiAgICAgIHRoaXMudXBkYXRlQ29pbnMoaW5wdXRzLCBjbGFpbXMsIGJsb2NrKSxcbiAgICBdKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcGVyc2lzdFRyYW5zYWN0aW9ucyhcbiAgICBibG9jazogQmxvY2ssXG4gICAgdHJhbnNhY3Rpb25zOiBSZWFkb25seUFycmF5PHJlYWRvbmx5IFtudW1iZXIsIFRyYW5zYWN0aW9uXT4sXG4gICAgbGFzdEdsb2JhbFRyYW5zYWN0aW9uSW5kZXg6IEJOLFxuICAgIGxhc3RHbG9iYWxBY3Rpb25JbmRleDogQk4sXG4gICk6IFByb21pc2U8Qk4+IHtcbiAgICBsZXQgZ2xvYmFsQWN0aW9uSW5kZXggPSBsYXN0R2xvYmFsQWN0aW9uSW5kZXguYWRkKHV0aWxzLk9ORSk7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gICAgZm9yIChjb25zdCBbaWR4LCB0cmFuc2FjdGlvbl0gb2YgdHJhbnNhY3Rpb25zKSB7XG4gICAgICBnbG9iYWxBY3Rpb25JbmRleCA9IGF3YWl0IHRoaXMucGVyc2lzdFRyYW5zYWN0aW9uKFxuICAgICAgICBibG9jayxcbiAgICAgICAgdHJhbnNhY3Rpb24sXG4gICAgICAgIGlkeCxcbiAgICAgICAgbGFzdEdsb2JhbFRyYW5zYWN0aW9uSW5kZXgsXG4gICAgICAgIGdsb2JhbEFjdGlvbkluZGV4LFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2xvYmFsQWN0aW9uSW5kZXguc3ViKHV0aWxzLk9ORSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBlcnNpc3RUcmFuc2FjdGlvbihcbiAgICBibG9jazogQmxvY2ssXG4gICAgdHJhbnNhY3Rpb25JbjogVHJhbnNhY3Rpb24sXG4gICAgdHJhbnNhY3Rpb25JbmRleDogbnVtYmVyLFxuICAgIGxhc3RHbG9iYWxUcmFuc2FjdGlvbkluZGV4OiBCTixcbiAgICBnbG9iYWxBY3Rpb25JbmRleEluOiBCTixcbiAgKTogUHJvbWlzZTxCTj4ge1xuICAgIGxldCBnbG9iYWxBY3Rpb25JbmRleCA9IGdsb2JhbEFjdGlvbkluZGV4SW47XG4gICAgY29uc3QgdHJhbnNhY3Rpb24gPSB0cmFuc2FjdGlvbkluO1xuICAgIGNvbnN0IGNsYWltcyA9XG4gICAgICB0cmFuc2FjdGlvbi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuQ2xhaW0gJiYgdHJhbnNhY3Rpb24gaW5zdGFuY2VvZiBDbGFpbVRyYW5zYWN0aW9uID8gdHJhbnNhY3Rpb24uY2xhaW1zIDogW107XG4gICAgbGV0IGFjY291bnRDaGFuZ2VzID0ge307XG4gICAgbGV0IHZhbGlkYXRvckNoYW5nZXMgPSB7fTtcbiAgICBsZXQgdmFsaWRhdG9yc0NvdW50Q2hhbmdlczogVmFsaWRhdG9yc0NvdW50Q2hhbmdlcyA9IFtdO1xuICAgIGlmICh0cmFuc2FjdGlvbi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3RhdGUgJiYgdHJhbnNhY3Rpb24gaW5zdGFuY2VvZiBTdGF0ZVRyYW5zYWN0aW9uKSB7XG4gICAgICAoeyBhY2NvdW50Q2hhbmdlcywgdmFsaWRhdG9yQ2hhbmdlcywgdmFsaWRhdG9yc0NvdW50Q2hhbmdlcyB9ID0gYXdhaXQgZ2V0RGVzY3JpcHRvckNoYW5nZXMoe1xuICAgICAgICB0cmFuc2FjdGlvbnM6IFt0cmFuc2FjdGlvbl0sXG4gICAgICAgIGdldEFjY291bnQ6IGFzeW5jIChoYXNoKSA9PlxuICAgICAgICAgIHRoaXMuYWNjb3VudC50cnlHZXQoeyBoYXNoIH0pLnRoZW4oKGFjY291bnQpID0+IChhY2NvdW50ID09PSB1bmRlZmluZWQgPyBuZXcgQWNjb3VudCh7IGhhc2ggfSkgOiBhY2NvdW50KSksXG5cbiAgICAgICAgZ292ZXJuaW5nVG9rZW5IYXNoOiB0aGlzLnNldHRpbmdzLmdvdmVybmluZ1Rva2VuLmhhc2hIZXgsXG4gICAgICB9KSk7XG4gICAgfVxuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIHRoaXMudHJhbnNhY3Rpb24uYWRkKHRyYW5zYWN0aW9uKSxcbiAgICAgIHRoaXMudHJhbnNhY3Rpb25EYXRhLmFkZChcbiAgICAgICAgbmV3IFRyYW5zYWN0aW9uRGF0YSh7XG4gICAgICAgICAgaGFzaDogdHJhbnNhY3Rpb24uaGFzaCxcbiAgICAgICAgICBibG9ja0hhc2g6IGJsb2NrLmhhc2gsXG4gICAgICAgICAgc3RhcnRIZWlnaHQ6IGJsb2NrLmluZGV4LFxuICAgICAgICAgIGluZGV4OiB0cmFuc2FjdGlvbkluZGV4LFxuICAgICAgICAgIGdsb2JhbEluZGV4OiBsYXN0R2xvYmFsVHJhbnNhY3Rpb25JbmRleC5hZGQobmV3IEJOKHRyYW5zYWN0aW9uSW5kZXggKyAxKSksXG4gICAgICAgIH0pLFxuICAgICAgKSxcblxuICAgICAgdGhpcy51cGRhdGVBY2NvdW50cyh0cmFuc2FjdGlvbi5pbnB1dHMsIGNsYWltcywgdGhpcy5nZXRPdXRwdXRXaXRoSW5wdXQodHJhbnNhY3Rpb24pLCBhY2NvdW50Q2hhbmdlcyksXG5cbiAgICAgIHRoaXMudXBkYXRlQ29pbnModHJhbnNhY3Rpb24uaW5wdXRzLCBjbGFpbXMsIGJsb2NrKSxcbiAgICAgIHRoaXMucHJvY2Vzc1N0YXRlVHJhbnNhY3Rpb24odmFsaWRhdG9yQ2hhbmdlcywgdmFsaWRhdG9yc0NvdW50Q2hhbmdlcyksXG4gICAgXSk7XG5cbiAgICBpZiAodHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlJlZ2lzdGVyICYmIHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgUmVnaXN0ZXJUcmFuc2FjdGlvbikge1xuICAgICAgYXdhaXQgdGhpcy5hc3NldC5hZGQoXG4gICAgICAgIG5ldyBBc3NldCh7XG4gICAgICAgICAgaGFzaDogdHJhbnNhY3Rpb24uaGFzaCxcbiAgICAgICAgICB0eXBlOiB0cmFuc2FjdGlvbi5hc3NldC50eXBlLFxuICAgICAgICAgIG5hbWU6IHRyYW5zYWN0aW9uLmFzc2V0Lm5hbWUsXG4gICAgICAgICAgYW1vdW50OiB0cmFuc2FjdGlvbi5hc3NldC5hbW91bnQsXG4gICAgICAgICAgcHJlY2lzaW9uOiB0cmFuc2FjdGlvbi5hc3NldC5wcmVjaXNpb24sXG4gICAgICAgICAgb3duZXI6IHRyYW5zYWN0aW9uLmFzc2V0Lm93bmVyLFxuICAgICAgICAgIGFkbWluOiB0cmFuc2FjdGlvbi5hc3NldC5hZG1pbixcbiAgICAgICAgICBpc3N1ZXI6IHRyYW5zYWN0aW9uLmFzc2V0LmFkbWluLFxuICAgICAgICAgIGV4cGlyYXRpb246IHRoaXMuY3VycmVudEJsb2NrSW5kZXggKyAyICogMjAwMDAwMCxcbiAgICAgICAgICBpc0Zyb3plbjogZmFsc2UsXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKHRyYW5zYWN0aW9uLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5Jc3N1ZSAmJiB0cmFuc2FjdGlvbiBpbnN0YW5jZW9mIElzc3VlVHJhbnNhY3Rpb24pIHtcbiAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgT2JqZWN0LmVudHJpZXMoXG4gICAgICAgICAgdHJhbnNhY3Rpb24uZ2V0VHJhbnNhY3Rpb25SZXN1bHRzKHtcbiAgICAgICAgICAgIGdldE91dHB1dDogdGhpcy5vdXRwdXQuZ2V0LFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKTtcblxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIHJlc3VsdHMubWFwKGFzeW5jIChbYXNzZXRIZXgsIHZhbHVlXSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGhhc2ggPSBjb21tb24uc3RyaW5nVG9VSW50MjU2KGFzc2V0SGV4KTtcbiAgICAgICAgICBjb25zdCBhc3NldCA9IGF3YWl0IHRoaXMuYXNzZXQuZ2V0KHsgaGFzaCB9KTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmFzc2V0LnVwZGF0ZShhc3NldCwge1xuICAgICAgICAgICAgYXZhaWxhYmxlOiBhc3NldC5hdmFpbGFibGUuYWRkKHZhbHVlLm5lZygpKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLkVucm9sbG1lbnQgJiYgdHJhbnNhY3Rpb24gaW5zdGFuY2VvZiBFbnJvbGxtZW50VHJhbnNhY3Rpb24pIHtcbiAgICAgIGF3YWl0IHRoaXMudmFsaWRhdG9yLmFkZChcbiAgICAgICAgbmV3IFZhbGlkYXRvcih7XG4gICAgICAgICAgcHVibGljS2V5OiB0cmFuc2FjdGlvbi5wdWJsaWNLZXksXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9IGVsc2UgaWYgKHRyYW5zYWN0aW9uLnR5cGUgPT09IFRyYW5zYWN0aW9uVHlwZS5QdWJsaXNoICYmIHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgUHVibGlzaFRyYW5zYWN0aW9uKSB7XG4gICAgICBjb25zdCBjb250cmFjdCA9IGF3YWl0IHRoaXMuY29udHJhY3QudHJ5R2V0KHtcbiAgICAgICAgaGFzaDogdHJhbnNhY3Rpb24uY29udHJhY3QuaGFzaCxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoY29udHJhY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBhd2FpdCB0aGlzLmNvbnRyYWN0LmFkZCh0cmFuc2FjdGlvbi5jb250cmFjdCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0cmFuc2FjdGlvbi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuSW52b2NhdGlvbiAmJiB0cmFuc2FjdGlvbiBpbnN0YW5jZW9mIEludm9jYXRpb25UcmFuc2FjdGlvbikge1xuICAgICAgY29uc3QgdGVtcG9yYXJ5QmxvY2tjaGFpbiA9IG5ldyBXcml0ZUJhdGNoQmxvY2tjaGFpbih7XG4gICAgICAgIHNldHRpbmdzOiB0aGlzLnNldHRpbmdzLFxuICAgICAgICBjdXJyZW50QmxvY2s6IHRoaXMuY3VycmVudEJsb2NrSW50ZXJuYWwsXG4gICAgICAgIGN1cnJlbnRIZWFkZXI6IHRoaXMuY3VycmVudEhlYWRlcixcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWFueVxuICAgICAgICBzdG9yYWdlOiB0aGlzIGFzIGFueSxcbiAgICAgICAgdm06IHRoaXMudm0sXG4gICAgICAgIGdldFZhbGlkYXRvcnM6IHRoaXMuZ2V0VmFsaWRhdG9ycyxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBtaWdyYXRlZENvbnRyYWN0SGFzaGVzOiBBcnJheTxyZWFkb25seSBbVUludDE2MCwgVUludDE2MF0+ID0gW107XG4gICAgICBjb25zdCB2b3RlVXBkYXRlczogQXJyYXk8cmVhZG9ubHkgW1VJbnQxNjAsIFJlYWRvbmx5QXJyYXk8RUNQb2ludD5dPiA9IFtdO1xuICAgICAgY29uc3QgYWN0aW9uczogQXJyYXk8Tm90aWZpY2F0aW9uQWN0aW9uIHwgTG9nQWN0aW9uPiA9IFtdO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd3JhcEV4ZWN1dGVTY3JpcHRzKGFzeW5jICgpID0+XG4gICAgICAgIHRoaXMudm0uZXhlY3V0ZVNjcmlwdHMoe1xuICAgICAgICAgIHNjcmlwdHM6IFt7IGNvZGU6IHRyYW5zYWN0aW9uLnNjcmlwdCB9XSxcbiAgICAgICAgICBibG9ja2NoYWluOiB0ZW1wb3JhcnlCbG9ja2NoYWluLFxuICAgICAgICAgIHNjcmlwdENvbnRhaW5lcjoge1xuICAgICAgICAgICAgdHlwZTogU2NyaXB0Q29udGFpbmVyVHlwZS5UcmFuc2FjdGlvbixcbiAgICAgICAgICAgIHZhbHVlOiB0cmFuc2FjdGlvbixcbiAgICAgICAgICB9LFxuXG4gICAgICAgICAgdHJpZ2dlclR5cGU6IFRyaWdnZXJUeXBlLkFwcGxpY2F0aW9uLFxuICAgICAgICAgIGFjdGlvbjoge1xuICAgICAgICAgICAgYmxvY2tJbmRleDogYmxvY2suaW5kZXgsXG4gICAgICAgICAgICBibG9ja0hhc2g6IGJsb2NrLmhhc2gsXG4gICAgICAgICAgICB0cmFuc2FjdGlvbkluZGV4LFxuICAgICAgICAgICAgdHJhbnNhY3Rpb25IYXNoOiB0cmFuc2FjdGlvbi5oYXNoLFxuICAgICAgICAgIH0sXG5cbiAgICAgICAgICBnYXM6IHRyYW5zYWN0aW9uLmdhcyxcbiAgICAgICAgICBsaXN0ZW5lcnM6IHtcbiAgICAgICAgICAgIG9uTG9nOiAoeyBtZXNzYWdlLCBzY3JpcHRIYXNoIH0pID0+IHtcbiAgICAgICAgICAgICAgYWN0aW9ucy5wdXNoKFxuICAgICAgICAgICAgICAgIG5ldyBMb2dBY3Rpb24oe1xuICAgICAgICAgICAgICAgICAgaW5kZXg6IGdsb2JhbEFjdGlvbkluZGV4LFxuICAgICAgICAgICAgICAgICAgc2NyaXB0SGFzaCxcbiAgICAgICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgZ2xvYmFsQWN0aW9uSW5kZXggPSBnbG9iYWxBY3Rpb25JbmRleC5hZGQodXRpbHMuT05FKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbk5vdGlmeTogKHsgYXJncywgc2NyaXB0SGFzaCB9KSA9PiB7XG4gICAgICAgICAgICAgIGFjdGlvbnMucHVzaChcbiAgICAgICAgICAgICAgICBuZXcgTm90aWZpY2F0aW9uQWN0aW9uKHtcbiAgICAgICAgICAgICAgICAgIGluZGV4OiBnbG9iYWxBY3Rpb25JbmRleCxcbiAgICAgICAgICAgICAgICAgIHNjcmlwdEhhc2gsXG4gICAgICAgICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgIGdsb2JhbEFjdGlvbkluZGV4ID0gZ2xvYmFsQWN0aW9uSW5kZXguYWRkKHV0aWxzLk9ORSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb25NaWdyYXRlQ29udHJhY3Q6ICh7IGZyb20sIHRvIH0pID0+IHtcbiAgICAgICAgICAgICAgbWlncmF0ZWRDb250cmFjdEhhc2hlcy5wdXNoKFtmcm9tLCB0b10gYXMgY29uc3QpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uU2V0Vm90ZXM6ICh7IGFkZHJlc3MsIHZvdGVzIH0pID0+IHtcbiAgICAgICAgICAgICAgdm90ZVVwZGF0ZXMucHVzaChbYWRkcmVzcywgdm90ZXNdIGFzIGNvbnN0KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcblxuICAgICAgICAgIHBlcnNpc3RpbmdCbG9jazogYmxvY2ssXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgY29uc3QgYWRkQWN0aW9uc1Byb21pc2UgPSBQcm9taXNlLmFsbChhY3Rpb25zLm1hcChhc3luYyAoYWN0aW9uKSA9PiB0aGlzLmFjdGlvbi5hZGQoYWN0aW9uKSkpO1xuXG4gICAgICBpZiAocmVzdWx0IGluc3RhbmNlb2YgSW52b2NhdGlvblJlc3VsdFN1Y2Nlc3MpIHtcbiAgICAgICAgY29uc3QgYXNzZXRDaGFuZ2VTZXQgPSB0ZW1wb3JhcnlCbG9ja2NoYWluLmFzc2V0LmdldENoYW5nZVNldCgpO1xuICAgICAgICBjb25zdCBhc3NldEhhc2ggPSBhc3NldENoYW5nZVNldFxuICAgICAgICAgIC5tYXAoKGNoYW5nZSkgPT5cbiAgICAgICAgICAgIGNoYW5nZS50eXBlID09PSAnYWRkJyAmJiBjaGFuZ2UuY2hhbmdlLnR5cGUgPT09ICdhc3NldCcgPyBjaGFuZ2UuY2hhbmdlLnZhbHVlLmhhc2ggOiB1bmRlZmluZWQsXG4gICAgICAgICAgKVxuICAgICAgICAgIC5maW5kKCh2YWx1ZSkgPT4gdmFsdWUgIT09IHVuZGVmaW5lZCk7XG5cbiAgICAgICAgY29uc3QgY29udHJhY3RzQ2hhbmdlU2V0ID0gdGVtcG9yYXJ5QmxvY2tjaGFpbi5jb250cmFjdC5nZXRDaGFuZ2VTZXQoKTtcbiAgICAgICAgY29uc3QgY29udHJhY3RIYXNoZXMgPSBjb250cmFjdHNDaGFuZ2VTZXRcbiAgICAgICAgICAubWFwKChjaGFuZ2UpID0+XG4gICAgICAgICAgICBjaGFuZ2UudHlwZSA9PT0gJ2FkZCcgJiYgY2hhbmdlLmNoYW5nZS50eXBlID09PSAnY29udHJhY3QnID8gY2hhbmdlLmNoYW5nZS52YWx1ZS5oYXNoIDogdW5kZWZpbmVkLFxuICAgICAgICAgIClcbiAgICAgICAgICAuZmlsdGVyKGNvbW1vblV0aWxzLm5vdE51bGwpO1xuXG4gICAgICAgIGNvbnN0IGRlbGV0ZWRDb250cmFjdEhhc2hlcyA9IGNvbnRyYWN0c0NoYW5nZVNldFxuICAgICAgICAgIC5tYXAoKGNoYW5nZSkgPT5cbiAgICAgICAgICAgIGNoYW5nZS50eXBlID09PSAnZGVsZXRlJyAmJiBjaGFuZ2UuY2hhbmdlLnR5cGUgPT09ICdjb250cmFjdCcgPyBjaGFuZ2UuY2hhbmdlLmtleS5oYXNoIDogdW5kZWZpbmVkLFxuICAgICAgICAgIClcbiAgICAgICAgICAuZmlsdGVyKGNvbW1vblV0aWxzLm5vdE51bGwpO1xuXG4gICAgICAgIGNvbnN0IHN0b3JhZ2VDaGFuZ2VzID0gdGVtcG9yYXJ5QmxvY2tjaGFpbi5zdG9yYWdlSXRlbVxuICAgICAgICAgIC5nZXRDaGFuZ2VTZXQoKVxuICAgICAgICAgIC5tYXAoKGNoYW5nZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYWRkQ2hhbmdlID1cbiAgICAgICAgICAgICAgY2hhbmdlLnR5cGUgPT09ICdhZGQnICYmIGNoYW5nZS5jaGFuZ2UudHlwZSA9PT0gJ3N0b3JhZ2VJdGVtJ1xuICAgICAgICAgICAgICAgID8geyB2YWx1ZTogY2hhbmdlLmNoYW5nZS52YWx1ZSwgc3ViVHlwZTogY2hhbmdlLnN1YlR5cGUgfVxuICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKGFkZENoYW5nZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgaGFzaDogYWRkQ2hhbmdlLnZhbHVlLmhhc2gsXG4gICAgICAgICAgICAgICAga2V5OiBhZGRDaGFuZ2UudmFsdWUua2V5LFxuICAgICAgICAgICAgICAgIHZhbHVlOiBhZGRDaGFuZ2UudmFsdWUudmFsdWUsXG4gICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgcmV0dXJuIGFkZENoYW5nZS5zdWJUeXBlID09PSAnYWRkJyA/IG5ldyBTdG9yYWdlQ2hhbmdlQWRkKG9wdGlvbnMpIDogbmV3IFN0b3JhZ2VDaGFuZ2VNb2RpZnkob3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGRlbGV0ZUNoYW5nZSA9XG4gICAgICAgICAgICAgIGNoYW5nZS50eXBlID09PSAnZGVsZXRlJyAmJiBjaGFuZ2UuY2hhbmdlLnR5cGUgPT09ICdzdG9yYWdlSXRlbScgPyBjaGFuZ2UuY2hhbmdlLmtleSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChkZWxldGVDaGFuZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICByZXR1cm4gbmV3IFN0b3JhZ2VDaGFuZ2VEZWxldGUoZGVsZXRlQ2hhbmdlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5maWx0ZXIoY29tbW9uVXRpbHMubm90TnVsbCk7XG5cbiAgICAgICAgdGVtcG9yYXJ5QmxvY2tjaGFpbi5nZXRUcmFja2VkQ2hhbmdlU2V0KCkuZm9yRWFjaCgoY2hhbmdlKSA9PiB7XG4gICAgICAgICAgdGhpcy5jYWNoZXNbY2hhbmdlLnR5cGUgYXMga2V5b2YgQ2FjaGVzXS5hZGRUcmFja2VkQ2hhbmdlKGNoYW5nZS5rZXksIGNoYW5nZS52YWx1ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgdGhpcy5pbnZvY2F0aW9uRGF0YS5hZGQoXG4gICAgICAgICAgICBuZXcgSW52b2NhdGlvbkRhdGEoe1xuICAgICAgICAgICAgICBoYXNoOiB0cmFuc2FjdGlvbi5oYXNoLFxuICAgICAgICAgICAgICBhc3NldEhhc2gsXG4gICAgICAgICAgICAgIGNvbnRyYWN0SGFzaGVzLFxuICAgICAgICAgICAgICBkZWxldGVkQ29udHJhY3RIYXNoZXMsXG4gICAgICAgICAgICAgIG1pZ3JhdGVkQ29udHJhY3RIYXNoZXMsXG4gICAgICAgICAgICAgIHZvdGVVcGRhdGVzLFxuICAgICAgICAgICAgICBibG9ja0luZGV4OiBibG9jay5pbmRleCxcbiAgICAgICAgICAgICAgdHJhbnNhY3Rpb25JbmRleCxcbiAgICAgICAgICAgICAgYWN0aW9uSW5kZXhTdGFydDogZ2xvYmFsQWN0aW9uSW5kZXhJbixcbiAgICAgICAgICAgICAgYWN0aW9uSW5kZXhTdG9wOiBnbG9iYWxBY3Rpb25JbmRleCxcbiAgICAgICAgICAgICAgcmVzdWx0LFxuICAgICAgICAgICAgICBzdG9yYWdlQ2hhbmdlcyxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICksXG4gICAgICAgICAgYWRkQWN0aW9uc1Byb21pc2UsXG4gICAgICAgIF0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgIHRoaXMuaW52b2NhdGlvbkRhdGEuYWRkKFxuICAgICAgICAgICAgbmV3IEludm9jYXRpb25EYXRhKHtcbiAgICAgICAgICAgICAgaGFzaDogdHJhbnNhY3Rpb24uaGFzaCxcbiAgICAgICAgICAgICAgYXNzZXRIYXNoOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgIGNvbnRyYWN0SGFzaGVzOiBbXSxcbiAgICAgICAgICAgICAgZGVsZXRlZENvbnRyYWN0SGFzaGVzOiBbXSxcbiAgICAgICAgICAgICAgbWlncmF0ZWRDb250cmFjdEhhc2hlczogW10sXG4gICAgICAgICAgICAgIHZvdGVVcGRhdGVzOiBbXSxcbiAgICAgICAgICAgICAgYmxvY2tJbmRleDogYmxvY2suaW5kZXgsXG4gICAgICAgICAgICAgIHRyYW5zYWN0aW9uSW5kZXgsXG4gICAgICAgICAgICAgIGFjdGlvbkluZGV4U3RhcnQ6IGdsb2JhbEFjdGlvbkluZGV4SW4sXG4gICAgICAgICAgICAgIGFjdGlvbkluZGV4U3RvcDogZ2xvYmFsQWN0aW9uSW5kZXgsXG4gICAgICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICAgICAgc3RvcmFnZUNoYW5nZXM6IFtdLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhZGRBY3Rpb25zUHJvbWlzZSxcbiAgICAgICAgXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGdsb2JhbEFjdGlvbkluZGV4O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzU3RhdGVUcmFuc2FjdGlvbihcbiAgICB2YWxpZGF0b3JDaGFuZ2VzOiBWYWxpZGF0b3JDaGFuZ2VzLFxuICAgIHZhbGlkYXRvcnNDb3VudENoYW5nZXM6IFZhbGlkYXRvcnNDb3VudENoYW5nZXMsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHZhbGlkYXRvcnNDb3VudCA9IGF3YWl0IHRoaXMudmFsaWRhdG9yc0NvdW50LnRyeUdldCgpO1xuICAgIGNvbnN0IHZhbGlkYXRvcnNDb3VudFZvdGVzID0gdmFsaWRhdG9yc0NvdW50ID09PSB1bmRlZmluZWQgPyBbXSA6IFsuLi52YWxpZGF0b3JzQ291bnQudm90ZXNdO1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1sb29wLXN0YXRlbWVudFxuICAgIGZvciAoY29uc3QgW2luZGV4LCB2YWx1ZV0gb2YgdmFsaWRhdG9yc0NvdW50Q2hhbmdlcy5lbnRyaWVzKCkpIHtcbiAgICAgIHZhbGlkYXRvcnNDb3VudFZvdGVzW2luZGV4XSA9IHZhbHVlO1xuICAgIH1cblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIFByb21pc2UuYWxsKFxuICAgICAgICBPYmplY3QuZW50cmllcyh2YWxpZGF0b3JDaGFuZ2VzKS5tYXAoYXN5bmMgKFtwdWJsaWNLZXlIZXgsIHsgcmVnaXN0ZXJlZCwgdm90ZXMgfV0pID0+IHtcbiAgICAgICAgICBjb25zdCBwdWJsaWNLZXkgPSBjb21tb24uaGV4VG9FQ1BvaW50KHB1YmxpY0tleUhleCk7XG4gICAgICAgICAgY29uc3QgdmFsaWRhdG9yID0gYXdhaXQgdGhpcy52YWxpZGF0b3IudHJ5R2V0KHsgcHVibGljS2V5IH0pO1xuICAgICAgICAgIGlmICh2YWxpZGF0b3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy52YWxpZGF0b3IuYWRkKFxuICAgICAgICAgICAgICBuZXcgVmFsaWRhdG9yKHtcbiAgICAgICAgICAgICAgICBwdWJsaWNLZXksXG4gICAgICAgICAgICAgICAgcmVnaXN0ZXJlZCxcbiAgICAgICAgICAgICAgICB2b3RlcyxcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAoKHJlZ2lzdGVyZWQgIT09IHVuZGVmaW5lZCAmJiAhcmVnaXN0ZXJlZCkgfHwgKHJlZ2lzdGVyZWQgPT09IHVuZGVmaW5lZCAmJiAhdmFsaWRhdG9yLnJlZ2lzdGVyZWQpKSAmJlxuICAgICAgICAgICAgKCh2b3RlcyAhPT0gdW5kZWZpbmVkICYmIHZvdGVzLmVxKHV0aWxzLlpFUk8pKSB8fCAodm90ZXMgPT09IHVuZGVmaW5lZCAmJiB2YWxpZGF0b3Iudm90ZXMuZXEodXRpbHMuWkVSTykpKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy52YWxpZGF0b3IuZGVsZXRlKHsgcHVibGljS2V5OiB2YWxpZGF0b3IucHVibGljS2V5IH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnZhbGlkYXRvci51cGRhdGUodmFsaWRhdG9yLCB7IHZvdGVzLCByZWdpc3RlcmVkIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICApLFxuICAgICAgdmFsaWRhdG9yc0NvdW50ID09PSB1bmRlZmluZWRcbiAgICAgICAgPyB0aGlzLnZhbGlkYXRvcnNDb3VudC5hZGQoXG4gICAgICAgICAgICBuZXcgVmFsaWRhdG9yc0NvdW50KHtcbiAgICAgICAgICAgICAgdm90ZXM6IHZhbGlkYXRvcnNDb3VudFZvdGVzLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKVxuICAgICAgICA6IChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnZhbGlkYXRvcnNDb3VudC51cGRhdGUodmFsaWRhdG9yc0NvdW50LCB7XG4gICAgICAgICAgICAgIHZvdGVzOiB2YWxpZGF0b3JzQ291bnRWb3RlcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pKCksXG4gICAgXSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUFjY291bnRzKFxuICAgIGlucHV0czogcmVhZG9ubHkgSW5wdXRbXSxcbiAgICBjbGFpbXM6IHJlYWRvbmx5IElucHV0W10sXG4gICAgb3V0cHV0czogcmVhZG9ubHkgT3V0cHV0V2l0aElucHV0W10sXG4gICAgYWNjb3VudENoYW5nZXM6IEFjY291bnRDaGFuZ2VzID0ge30sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IFtpbnB1dE91dHB1dHMsIGNsYWltT3V0cHV0c10gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICB0aGlzLmdldElucHV0T3V0cHV0cyhpbnB1dHMpLFxuICAgICAgdGhpcy5nZXRJbnB1dE91dHB1dHMoY2xhaW1zKSxcbiAgICBdKTtcblxuICAgIGNvbnN0IGFkZHJlc3NWYWx1ZXMgPSBPYmplY3QuZW50cmllcyhcbiAgICAgIF8uZ3JvdXBCeShcbiAgICAgICAgaW5wdXRPdXRwdXRzXG4gICAgICAgICAgLm1hcDxbVUludDE2MCwgVUludDI1NiwgQk5dPigoeyBvdXRwdXQgfSkgPT4gW291dHB1dC5hZGRyZXNzLCBvdXRwdXQuYXNzZXQsIG91dHB1dC52YWx1ZS5uZWcoKV0pXG4gICAgICAgICAgLmNvbmNhdChvdXRwdXRzLm1hcDxbVUludDE2MCwgVUludDI1NiwgQk5dPigoeyBvdXRwdXQgfSkgPT4gW291dHB1dC5hZGRyZXNzLCBvdXRwdXQuYXNzZXQsIG91dHB1dC52YWx1ZV0pKSxcbiAgICAgICAgKFthZGRyZXNzXSkgPT4gY29tbW9uLnVJbnQxNjBUb0hleChhZGRyZXNzKSxcbiAgICAgICksXG4gICAgKTtcblxuICAgIGNvbnN0IGFkZHJlc3NTcGVudCA9IHRoaXMuZ3JvdXBCeUFkZHJlc3MoaW5wdXRPdXRwdXRzKTtcbiAgICBjb25zdCBhZGRyZXNzQ2xhaW1lZCA9IF8ubWFwVmFsdWVzKHRoaXMuZ3JvdXBCeUFkZHJlc3MoY2xhaW1PdXRwdXRzKSwgKHZhbHVlcykgPT4gdmFsdWVzLm1hcCgoeyBpbnB1dCB9KSA9PiBpbnB1dCkpO1xuXG4gICAgY29uc3QgYWRkcmVzc091dHB1dHMgPSBfLmdyb3VwQnkob3V0cHV0cywgKG91dHB1dCkgPT4gY29tbW9uLnVJbnQxNjBUb0hleChvdXRwdXQub3V0cHV0LmFkZHJlc3MpKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgYWRkcmVzc1ZhbHVlcy5tYXAoYXN5bmMgKFthZGRyZXNzLCB2YWx1ZXNdKSA9PiB7XG4gICAgICAgIGNvbnN0IHNwZW50ID0gYWRkcmVzc1NwZW50W2FkZHJlc3NdIGFzIHJlYWRvbmx5IE91dHB1dFdpdGhJbnB1dFtdIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBjbGFpbWVkID0gYWRkcmVzc0NsYWltZWRbYWRkcmVzc10gYXMgcmVhZG9ubHkgSW5wdXRbXSB8IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3Qgb3V0cyA9IGFkZHJlc3NPdXRwdXRzW2FkZHJlc3NdIGFzIHJlYWRvbmx5IE91dHB1dFdpdGhJbnB1dFtdIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBjaGFuZ2VzID0gYWNjb3VudENoYW5nZXNbYWRkcmVzc10gYXMgcmVhZG9ubHkgRUNQb2ludFtdIHwgdW5kZWZpbmVkO1xuICAgICAgICBhd2FpdCB0aGlzLnVwZGF0ZUFjY291bnQoXG4gICAgICAgICAgY29tbW9uLmhleFRvVUludDE2MChhZGRyZXNzKSxcbiAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkXG4gICAgICAgICAgdmFsdWVzLm1hcDxyZWFkb25seSBbVUludDI1NiwgQk5dPigoW19hZGRyZXNzLCBhc3NldCwgdmFsdWVdKSA9PiBbYXNzZXQsIHZhbHVlXSBhcyBjb25zdCksXG4gICAgICAgICAgc3BlbnQgPT09IHVuZGVmaW5lZCA/IFtdIDogc3BlbnQsXG4gICAgICAgICAgY2xhaW1lZCA9PT0gdW5kZWZpbmVkID8gW10gOiBjbGFpbWVkLFxuICAgICAgICAgIG91dHMgPT09IHVuZGVmaW5lZCA/IFtdIDogb3V0cyxcbiAgICAgICAgICBjaGFuZ2VzID09PSB1bmRlZmluZWQgPyBbXSA6IGNoYW5nZXMsXG4gICAgICAgICk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRPdXRwdXRXaXRoSW5wdXQodHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uKTogcmVhZG9ubHkgT3V0cHV0V2l0aElucHV0W10ge1xuICAgIHJldHVybiB0cmFuc2FjdGlvbi5vdXRwdXRzLm1hcCgob3V0cHV0LCBpbmRleCkgPT4gKHtcbiAgICAgIG91dHB1dCxcbiAgICAgIGlucHV0OiBuZXcgSW5wdXQoeyBoYXNoOiB0cmFuc2FjdGlvbi5oYXNoLCBpbmRleCB9KSxcbiAgICB9KSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldElucHV0T3V0cHV0cyhcbiAgICBpbnB1dHM6IHJlYWRvbmx5IElucHV0W10sXG4gICk6IFByb21pc2U8XG4gICAgUmVhZG9ubHlBcnJheTx7XG4gICAgICByZWFkb25seSBpbnB1dDogSW5wdXQ7XG4gICAgICByZWFkb25seSBvdXRwdXQ6IE91dHB1dDtcbiAgICB9PlxuICA+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoXG4gICAgICBpbnB1dHMubWFwKGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgICBjb25zdCBvdXRwdXQgPSBhd2FpdCB0aGlzLm91dHB1dC5nZXQoaW5wdXQpO1xuXG4gICAgICAgIHJldHVybiB7IGlucHV0LCBvdXRwdXQgfTtcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGdyb3VwQnlBZGRyZXNzKFxuICAgIGlucHV0T3V0cHV0czogcmVhZG9ubHkgT3V0cHV0V2l0aElucHV0W10sXG4gICk6IHsgcmVhZG9ubHkgW2tleTogc3RyaW5nXTogcmVhZG9ubHkgT3V0cHV0V2l0aElucHV0W10gfSB7XG4gICAgcmV0dXJuIF8uZ3JvdXBCeShpbnB1dE91dHB1dHMsICh7IG91dHB1dCB9KSA9PiBjb21tb24udUludDE2MFRvSGV4KG91dHB1dC5hZGRyZXNzKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHVwZGF0ZUFjY291bnQoXG4gICAgYWRkcmVzczogVUludDE2MCxcbiAgICB2YWx1ZXM6IFJlYWRvbmx5QXJyYXk8cmVhZG9ubHkgW1VJbnQyNTYsIEJOXT4sXG4gICAgc3BlbnQ6IHJlYWRvbmx5IE91dHB1dFdpdGhJbnB1dFtdLFxuICAgIGNsYWltZWQ6IHJlYWRvbmx5IElucHV0W10sXG4gICAgb3V0cHV0czogcmVhZG9ubHkgT3V0cHV0V2l0aElucHV0W10sXG4gICAgdm90ZXM6IHJlYWRvbmx5IEVDUG9pbnRbXSxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgYWNjb3VudCA9IGF3YWl0IHRoaXMuYWNjb3VudC50cnlHZXQoeyBoYXNoOiBhZGRyZXNzIH0pO1xuXG4gICAgY29uc3QgYmFsYW5jZXMgPSB2YWx1ZXMucmVkdWNlPHsgW2Fzc2V0OiBzdHJpbmddOiBCTiB9PihcbiAgICAgIChhY2MsIFthc3NldCwgdmFsdWVdKSA9PiB7XG4gICAgICAgIGNvbnN0IGtleSA9IGNvbW1vbi51SW50MjU2VG9IZXgoYXNzZXQpO1xuICAgICAgICBpZiAoKGFjY1trZXldIGFzIEJOIHwgdW5kZWZpbmVkKSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgYWNjW2tleV0gPSB1dGlscy5aRVJPO1xuICAgICAgICB9XG4gICAgICAgIGFjY1trZXldID0gYWNjW2tleV0uYWRkKHZhbHVlKTtcblxuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSxcbiAgICAgIGFjY291bnQgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IHt9XG4gICAgICAgIDogT2JqZWN0LmVudHJpZXMoYWNjb3VudC5iYWxhbmNlcykucmVkdWNlPHsgW2Fzc2V0OiBzdHJpbmddOiBCTiB9PigoYWNjLCBba2V5LCB2YWx1ZV0pID0+IHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4uYWNjLFxuICAgICAgICAgICAgICAgIFtrZXldOiB1dGlscy5aRVJPLFxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5hY2MsXG4gICAgICAgICAgICAgIFtrZXldOiB2YWx1ZSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSwge30pLFxuICAgICk7XG5cbiAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgIHByb21pc2VzLnB1c2goXG4gICAgICAuLi5zcGVudC5tYXAoYXN5bmMgKHsgaW5wdXQgfSkgPT5cbiAgICAgICAgdGhpcy5hY2NvdW50VW5zcGVudC5kZWxldGUoe1xuICAgICAgICAgIGhhc2g6IGFkZHJlc3MsXG4gICAgICAgICAgaW5wdXQsXG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgcHJvbWlzZXMucHVzaChcbiAgICAgIC4uLm91dHB1dHMubWFwKGFzeW5jICh7IGlucHV0IH0pID0+IHRoaXMuYWNjb3VudFVuc3BlbnQuYWRkKG5ldyBBY2NvdW50VW5zcGVudCh7IGhhc2g6IGFkZHJlc3MsIGlucHV0IH0pKSksXG4gICAgKTtcblxuICAgIHByb21pc2VzLnB1c2goXG4gICAgICAuLi5jbGFpbWVkLm1hcChhc3luYyAoaW5wdXQpID0+XG4gICAgICAgIHRoaXMuYWNjb3VudFVuY2xhaW1lZC5kZWxldGUoe1xuICAgICAgICAgIGhhc2g6IGFkZHJlc3MsXG4gICAgICAgICAgaW5wdXQsXG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgcHJvbWlzZXMucHVzaChcbiAgICAgIC4uLnNwZW50XG4gICAgICAgIC5maWx0ZXIoKHsgb3V0cHV0IH0pID0+IGNvbW1vbi51SW50MjU2RXF1YWwob3V0cHV0LmFzc2V0LCB0aGlzLnNldHRpbmdzLmdvdmVybmluZ1Rva2VuLmhhc2gpKVxuICAgICAgICAubWFwKGFzeW5jICh7IGlucHV0IH0pID0+IHRoaXMuYWNjb3VudFVuY2xhaW1lZC5hZGQobmV3IEFjY291bnRVbmNsYWltZWQoeyBoYXNoOiBhZGRyZXNzLCBpbnB1dCB9KSkpLFxuICAgICk7XG5cbiAgICBpZiAoYWNjb3VudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9taXNlcy5wdXNoKFxuICAgICAgICB0aGlzLmFjY291bnQuYWRkKFxuICAgICAgICAgIG5ldyBBY2NvdW50KHtcbiAgICAgICAgICAgIGhhc2g6IGFkZHJlc3MsXG4gICAgICAgICAgICBiYWxhbmNlcyxcbiAgICAgICAgICAgIHZvdGVzLFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvbWlzZXMucHVzaChcbiAgICAgICAgdGhpcy5hY2NvdW50LnVwZGF0ZShhY2NvdW50LCB7IGJhbGFuY2VzLCB2b3RlcyB9KS50aGVuKGFzeW5jIChuZXdBY2NvdW50KSA9PiB7XG4gICAgICAgICAgaWYgKG5ld0FjY291bnQuaXNEZWxldGFibGUoKSkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5hY2NvdW50LmRlbGV0ZSh7IGhhc2g6IGFkZHJlc3MgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDb2lucyhpbnB1dHM6IHJlYWRvbmx5IElucHV0W10sIGNsYWltczogcmVhZG9ubHkgSW5wdXRbXSwgYmxvY2s6IEJsb2NrKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaW5wdXRDbGFpbXMgPSBpbnB1dHNcbiAgICAgIC5tYXA8SW5wdXRDbGFpbT4oKGlucHV0KSA9PiAoeyB0eXBlOiAnaW5wdXQnLCBpbnB1dCwgaGFzaDogaW5wdXQuaGFzaCB9KSlcbiAgICAgIC5jb25jYXQoY2xhaW1zLm1hcDxJbnB1dENsYWltPigoaW5wdXQpID0+ICh7IHR5cGU6ICdjbGFpbScsIGlucHV0LCBoYXNoOiBpbnB1dC5oYXNoIH0pKSk7XG5cbiAgICBjb25zdCBoYXNoSW5wdXRDbGFpbXMgPSBPYmplY3QuZW50cmllcyhfLmdyb3VwQnkoaW5wdXRDbGFpbXMsICh7IGhhc2ggfSkgPT4gY29tbW9uLnVJbnQyNTZUb0hleChoYXNoKSkpO1xuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBoYXNoSW5wdXRDbGFpbXMubWFwKGFzeW5jIChbaGFzaCwgdmFsdWVzXSkgPT4gdGhpcy51cGRhdGVDb2luKGNvbW1vbi5oZXhUb1VJbnQyNTYoaGFzaCksIHZhbHVlcywgYmxvY2spKSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB1cGRhdGVDb2luKGhhc2g6IFVJbnQyNTYsIGlucHV0Q2xhaW1zOiByZWFkb25seSBJbnB1dENsYWltW10sIGJsb2NrOiBCbG9jayk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHNwZW50Q29pbnMgPSBhd2FpdCB0aGlzLnRyYW5zYWN0aW9uRGF0YS5nZXQoeyBoYXNoIH0pO1xuICAgIGNvbnN0IGVuZEhlaWdodHMgPSB7IC4uLnNwZW50Q29pbnMuZW5kSGVpZ2h0cyB9O1xuICAgIGNvbnN0IGNsYWltZWQgPSB7IC4uLnNwZW50Q29pbnMuY2xhaW1lZCB9O1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSBuby1sb29wLXN0YXRlbWVudFxuICAgIGZvciAoY29uc3QgaW5wdXRDbGFpbSBvZiBpbnB1dENsYWltcykge1xuICAgICAgaWYgKGlucHV0Q2xhaW0udHlwZSA9PT0gJ2lucHV0Jykge1xuICAgICAgICBlbmRIZWlnaHRzW2lucHV0Q2xhaW0uaW5wdXQuaW5kZXhdID0gYmxvY2suaW5kZXg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjbGFpbWVkW2lucHV0Q2xhaW0uaW5wdXQuaW5kZXhdID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnRyYW5zYWN0aW9uRGF0YS51cGRhdGUoc3BlbnRDb2lucywge1xuICAgICAgZW5kSGVpZ2h0cyxcbiAgICAgIGNsYWltZWQsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==