@bitgo-beta/sdk-coin-eth 4.4.1-beta.97 → 4.4.1-beta.971

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +1458 -0
  2. package/dist/src/erc20Token.d.ts +13 -5
  3. package/dist/src/erc20Token.d.ts.map +1 -1
  4. package/dist/src/erc20Token.js +61 -23
  5. package/dist/src/eth.d.ts +22 -533
  6. package/dist/src/eth.d.ts.map +1 -1
  7. package/dist/src/eth.js +198 -1613
  8. package/dist/src/gteth.d.ts +0 -4
  9. package/dist/src/gteth.d.ts.map +1 -1
  10. package/dist/src/gteth.js +1 -11
  11. package/dist/src/hteth.d.ts +8 -0
  12. package/dist/src/hteth.d.ts.map +1 -0
  13. package/dist/src/hteth.js +14 -0
  14. package/dist/src/index.d.ts +1 -0
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/index.js +7 -2
  17. package/dist/src/lib/index.d.ts +5 -13
  18. package/dist/src/lib/index.d.ts.map +1 -1
  19. package/dist/src/lib/index.js +18 -30
  20. package/dist/src/lib/messages/index.d.ts +3 -0
  21. package/dist/src/lib/messages/index.d.ts.map +1 -0
  22. package/dist/src/lib/messages/index.js +6 -0
  23. package/dist/src/lib/transactionBuilder.d.ts +9 -213
  24. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  25. package/dist/src/lib/transactionBuilder.js +18 -677
  26. package/dist/src/lib/transferBuilder.d.ts +2 -50
  27. package/dist/src/lib/transferBuilder.d.ts.map +1 -1
  28. package/dist/src/lib/transferBuilder.js +3 -199
  29. package/dist/src/lib/transferBuilders/index.d.ts +2 -3
  30. package/dist/src/lib/transferBuilders/index.d.ts.map +1 -1
  31. package/dist/src/lib/transferBuilders/index.js +6 -14
  32. package/dist/src/lib/walletUtil.d.ts +0 -25
  33. package/dist/src/lib/walletUtil.d.ts.map +1 -1
  34. package/dist/src/lib/walletUtil.js +2 -27
  35. package/dist/src/register.d.ts.map +1 -1
  36. package/dist/src/register.js +3 -1
  37. package/dist/src/teth.d.ts +0 -3
  38. package/dist/src/teth.d.ts.map +1 -1
  39. package/dist/src/teth.js +1 -8
  40. package/package.json +12 -17
  41. package/dist/src/lib/contractCall.d.ts +0 -8
  42. package/dist/src/lib/contractCall.d.ts.map +0 -1
  43. package/dist/src/lib/contractCall.js +0 -17
  44. package/dist/src/lib/iface.d.ts +0 -130
  45. package/dist/src/lib/iface.d.ts.map +0 -1
  46. package/dist/src/lib/iface.js +0 -8
  47. package/dist/src/lib/keyPair.d.ts +0 -26
  48. package/dist/src/lib/keyPair.d.ts.map +0 -1
  49. package/dist/src/lib/keyPair.js +0 -66
  50. package/dist/src/lib/transaction.d.ts +0 -64
  51. package/dist/src/lib/transaction.d.ts.map +0 -1
  52. package/dist/src/lib/transaction.js +0 -137
  53. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts +0 -47
  54. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.d.ts.map +0 -1
  55. package/dist/src/lib/transferBuilders/baseNFTTransferBuilder.js +0 -113
  56. package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts +0 -14
  57. package/dist/src/lib/transferBuilders/transferBuilderERC1155.d.ts.map +0 -1
  58. package/dist/src/lib/transferBuilders/transferBuilderERC1155.js +0 -83
  59. package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts +0 -13
  60. package/dist/src/lib/transferBuilders/transferBuilderERC721.d.ts.map +0 -1
  61. package/dist/src/lib/transferBuilders/transferBuilderERC721.js +0 -68
  62. package/dist/src/lib/types.d.ts +0 -39
  63. package/dist/src/lib/types.d.ts.map +0 -1
  64. package/dist/src/lib/types.js +0 -137
  65. package/dist/src/lib/utils.d.ts +0 -227
  66. package/dist/src/lib/utils.d.ts.map +0 -1
  67. package/dist/src/lib/utils.js +0 -577
package/dist/src/eth.js CHANGED
@@ -7,91 +7,37 @@ exports.Eth = exports.optionalDeps = void 0;
7
7
  /**
8
8
  * @prettier
9
9
  */
10
- const utxo_lib_1 = require("@bitgo-beta/utxo-lib");
11
- const bignumber_js_1 = require("bignumber.js");
12
- const crypto_1 = require("crypto");
13
- const debug_1 = __importDefault(require("debug"));
14
- const keccak_1 = __importDefault(require("keccak"));
10
+ const secp256k1_1 = require("@bitgo-beta/secp256k1");
15
11
  const lodash_1 = __importDefault(require("lodash"));
16
- const secp256k1_1 = __importDefault(require("secp256k1"));
17
12
  const superagent_1 = __importDefault(require("superagent"));
18
- const erc20Token_1 = require("./erc20Token");
19
13
  const sdk_core_1 = require("@bitgo-beta/sdk-core");
20
- const sdk_lib_mpc_1 = require("@bitgo-beta/sdk-lib-mpc");
14
+ const abstract_eth_1 = require("@bitgo-beta/abstract-eth");
15
+ Object.defineProperty(exports, "optionalDeps", { enumerable: true, get: function () { return abstract_eth_1.optionalDeps; } });
21
16
  const statics_1 = require("@bitgo-beta/statics");
22
- const tx_1 = require("@ethereumjs/tx");
17
+ const bignumber_js_1 = require("bignumber.js");
23
18
  const lib_1 = require("./lib");
24
- const ethereumjs_util_1 = require("ethereumjs-util");
25
- const bn_js_1 = __importDefault(require("bn.js"));
26
- const eth_sig_util_1 = require("@metamask/eth-sig-util");
27
- const debug = debug_1.default('bitgo:v2:eth');
28
- exports.optionalDeps = {
29
- get ethAbi() {
30
- try {
31
- return require('ethereumjs-abi');
32
- }
33
- catch (e) {
34
- debug('unable to load ethereumjs-abi:');
35
- debug(e.stack);
36
- throw new sdk_core_1.EthereumLibraryUnavailableError(`ethereumjs-abi`);
37
- }
38
- },
39
- get ethUtil() {
40
- try {
41
- return require('ethereumjs-util');
42
- }
43
- catch (e) {
44
- debug('unable to load ethereumjs-util:');
45
- debug(e.stack);
46
- throw new sdk_core_1.EthereumLibraryUnavailableError(`ethereumjs-util`);
47
- }
48
- },
49
- get EthTx() {
50
- try {
51
- return require('@ethereumjs/tx');
52
- }
53
- catch (e) {
54
- debug('unable to load @ethereumjs/tx');
55
- debug(e.stack);
56
- throw new sdk_core_1.EthereumLibraryUnavailableError(`@ethereumjs/tx`);
57
- }
58
- },
59
- get EthCommon() {
60
- try {
61
- return require('@ethereumjs/common');
62
- }
63
- catch (e) {
64
- debug('unable to load @ethereumjs/common:');
65
- debug(e.stack);
66
- throw new sdk_core_1.EthereumLibraryUnavailableError(`@ethereumjs/common`);
67
- }
68
- },
69
- };
70
- class Eth extends sdk_core_1.BaseCoin {
19
+ const erc20Token_1 = require("./erc20Token");
20
+ class Eth extends abstract_eth_1.AbstractEthLikeNewCoins {
71
21
  constructor(bitgo, staticsCoin) {
72
- super(bitgo);
73
- /**
74
- * Get the data required to make an ETH function call defined by the given types and values
75
- *
76
- * @param functionName The name of the function being called, e.g. transfer
77
- * @param types The types of the function call in order
78
- * @param values The values of the function call in order
79
- * @return {Buffer} The combined data for the function call
80
- */
81
- this.getMethodCallData = (functionName, types, values) => {
82
- return Buffer.concat([
83
- // function signature
84
- exports.optionalDeps.ethAbi.methodID(functionName, types),
85
- // function arguments
86
- exports.optionalDeps.ethAbi.rawEncode(types, values),
87
- ]);
88
- };
89
- this.staticsCoin = staticsCoin;
90
- this.sendMethodName = 'sendMultiSig';
22
+ super(bitgo, staticsCoin);
91
23
  }
92
24
  static createInstance(bitgo, staticsCoin) {
93
25
  return new Eth(bitgo, staticsCoin);
94
26
  }
27
+ allowsAccountConsolidations() {
28
+ return true;
29
+ }
30
+ /** @inheritDoc */
31
+ supportsTss() {
32
+ return true;
33
+ }
34
+ /** inherited doc */
35
+ getDefaultMultisigType() {
36
+ return sdk_core_1.multisigTypes.tss;
37
+ }
38
+ getMPCAlgorithm() {
39
+ return 'ecdsa';
40
+ }
95
41
  /**
96
42
  * Gets correct Eth Common object based on params from either recovery or tx building
97
43
  * @param eip1559 {EIP1559} configs that specify whether we should construct an eip1559 tx
@@ -100,20 +46,20 @@ class Eth extends sdk_core_1.BaseCoin {
100
46
  static getEthCommon(eip1559, replayProtectionOptions) {
101
47
  // if eip1559 params are specified, default to london hardfork, otherwise,
102
48
  // default to tangerine whistle to avoid replay protection issues
103
- const defaultHardfork = !!eip1559 ? 'london' : exports.optionalDeps.EthCommon.Hardfork.TangerineWhistle;
104
- const defaultCommon = new exports.optionalDeps.EthCommon.default({
105
- chain: exports.optionalDeps.EthCommon.Chain.Mainnet,
49
+ const defaultHardfork = !!eip1559 ? 'london' : abstract_eth_1.optionalDeps.EthCommon.Hardfork.TangerineWhistle;
50
+ const defaultCommon = new abstract_eth_1.optionalDeps.EthCommon.default({
51
+ chain: abstract_eth_1.optionalDeps.EthCommon.Chain.Mainnet,
106
52
  hardfork: defaultHardfork,
107
53
  });
108
54
  // if replay protection options are set, override the default common setting
109
55
  const ethCommon = replayProtectionOptions
110
- ? exports.optionalDeps.EthCommon.default.isSupportedChainId(new exports.optionalDeps.ethUtil.BN(replayProtectionOptions.chain))
111
- ? new exports.optionalDeps.EthCommon.default({
56
+ ? abstract_eth_1.optionalDeps.EthCommon.default.isSupportedChainId(new abstract_eth_1.optionalDeps.ethUtil.BN(replayProtectionOptions.chain))
57
+ ? new abstract_eth_1.optionalDeps.EthCommon.default({
112
58
  chain: replayProtectionOptions.chain,
113
59
  hardfork: replayProtectionOptions.hardfork,
114
60
  })
115
- : exports.optionalDeps.EthCommon.default.custom({
116
- chainId: new exports.optionalDeps.ethUtil.BN(replayProtectionOptions.chain),
61
+ : abstract_eth_1.optionalDeps.EthCommon.default.custom({
62
+ chainId: new abstract_eth_1.optionalDeps.ethUtil.BN(replayProtectionOptions.chain),
117
63
  defaultHardfork: replayProtectionOptions.hardfork,
118
64
  })
119
65
  : defaultCommon;
@@ -121,1017 +67,45 @@ class Eth extends sdk_core_1.BaseCoin {
121
67
  }
122
68
  static buildTransaction(params) {
123
69
  // if eip1559 params are specified, default to london hardfork, otherwise,
124
- // default to tangerine whistle to avoid replay protection issues
125
- const ethCommon = Eth.getEthCommon(params.eip1559, params.replayProtectionOptions);
126
- const baseParams = {
127
- to: params.to,
128
- nonce: params.nonce,
129
- value: params.value,
130
- data: params.data,
131
- gasLimit: new exports.optionalDeps.ethUtil.BN(params.gasLimit),
132
- };
133
- const unsignedEthTx = !!params.eip1559
134
- ? exports.optionalDeps.EthTx.FeeMarketEIP1559Transaction.fromTxData({
135
- ...baseParams,
136
- maxFeePerGas: new exports.optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas),
137
- maxPriorityFeePerGas: new exports.optionalDeps.ethUtil.BN(params.eip1559.maxPriorityFeePerGas),
138
- }, { common: ethCommon })
139
- : exports.optionalDeps.EthTx.Transaction.fromTxData({
140
- ...baseParams,
141
- gasPrice: new exports.optionalDeps.ethUtil.BN(params.gasPrice),
142
- }, { common: ethCommon });
143
- return unsignedEthTx;
144
- }
145
- /** @inheritDoc */
146
- supportsTss() {
147
- return true;
148
- }
149
- /** @inheritDoc */
150
- isEVM() {
151
- return true;
152
- }
153
- getMPCAlgorithm() {
154
- return 'ecdsa';
155
- }
156
- /**
157
- * Returns the factor between the base unit and its smallest subdivison
158
- * @return {number}
159
- */
160
- getBaseFactor() {
161
- // 10^18
162
- return '1000000000000000000';
163
- }
164
- getChain() {
165
- return 'eth';
166
- }
167
- getFamily() {
168
- return 'eth';
169
- }
170
- getNetwork() {
171
- var _a;
172
- return (_a = this.staticsCoin) === null || _a === void 0 ? void 0 : _a.network;
173
- }
174
- getFullName() {
175
- return 'Ethereum';
176
- }
177
- /**
178
- * Flag for sending value of 0
179
- * @returns {boolean} True if okay to send 0 value, false otherwise
180
- */
181
- valuelessTransferAllowed() {
182
- return true;
183
- }
184
- /**
185
- * Flag for sending data along with transactions
186
- * @returns {boolean} True if okay to send tx data (ETH), false otherwise
187
- */
188
- transactionDataAllowed() {
189
- return true;
190
- }
191
- /**
192
- * Evaluates whether an address string is valid for this coin
193
- * @param address
194
- */
195
- isValidAddress(address) {
196
- return exports.optionalDeps.ethUtil.isValidAddress(exports.optionalDeps.ethUtil.addHexPrefix(address));
197
- }
198
- /**
199
- * Return boolean indicating whether input is valid public key for the coin.
200
- *
201
- * @param {String} pub the pub to be checked
202
- * @returns {Boolean} is it valid?
203
- */
204
- isValidPub(pub) {
205
- try {
206
- return utxo_lib_1.bip32.fromBase58(pub).isNeutered();
207
- }
208
- catch (e) {
209
- return false;
210
- }
211
- }
212
- /**
213
- * Default gas price from platform
214
- * @returns {BigNumber}
215
- */
216
- getRecoveryGasPrice() {
217
- return new exports.optionalDeps.ethUtil.BN('20000000000');
218
- }
219
- /**
220
- * Default gas limit from platform
221
- * @returns {BigNumber}
222
- */
223
- getRecoveryGasLimit() {
224
- return new exports.optionalDeps.ethUtil.BN('500000');
225
- }
226
- /**
227
- * Default expire time for a contract call (1 week)
228
- * @returns {number} Time in seconds
229
- */
230
- getDefaultExpireTime() {
231
- return Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 * 7;
232
- }
233
- /**
234
- * Query Etherscan for the balance of an address
235
- * @param address {String} the ETH address
236
- * @returns {BigNumber} address balance
237
- */
238
- async queryAddressBalance(address) {
239
- const result = await this.recoveryBlockchainExplorerQuery({
240
- module: 'account',
241
- action: 'balance',
242
- address: address,
243
- });
244
- // throw if the result does not exist or the result is not a valid number
245
- if (!result || !result.result || isNaN(result.result)) {
246
- throw new Error(`Could not obtain address balance for ${address} from Etherscan, got: ${result.result}`);
247
- }
248
- return new exports.optionalDeps.ethUtil.BN(result.result, 10);
249
- }
250
- /**
251
- * Query Etherscan for the balance of an address for a token
252
- * @param tokenContractAddress {String} address where the token smart contract is hosted
253
- * @param walletContractAddress {String} address of the wallet
254
- * @returns {BigNumber} token balaance in base units
255
- */
256
- async queryAddressTokenBalance(tokenContractAddress, walletContractAddress) {
257
- if (!exports.optionalDeps.ethUtil.isValidAddress(tokenContractAddress)) {
258
- throw new Error('cannot get balance for invalid token address');
259
- }
260
- if (!exports.optionalDeps.ethUtil.isValidAddress(walletContractAddress)) {
261
- throw new Error('cannot get token balance for invalid wallet address');
262
- }
263
- const result = await this.recoveryBlockchainExplorerQuery({
264
- module: 'account',
265
- action: 'tokenbalance',
266
- contractaddress: tokenContractAddress,
267
- address: walletContractAddress,
268
- tag: 'latest',
269
- });
270
- // throw if the result does not exist or the result is not a valid number
271
- if (!result || !result.result || isNaN(result.result)) {
272
- throw new Error(`Could not obtain token address balance for ${tokenContractAddress} from Etherscan, got: ${result.result}`);
273
- }
274
- return new exports.optionalDeps.ethUtil.BN(result.result, 10);
275
- }
276
- /**
277
- * Get transfer operation for coin
278
- * @param recipient recipient info
279
- * @param expireTime expiry time
280
- * @param contractSequenceId sequence id
281
- * @returns {Array} operation array
282
- */
283
- getOperation(recipient, expireTime, contractSequenceId) {
284
- return [
285
- ['string', 'address', 'uint', 'bytes', 'uint', 'uint'],
286
- [
287
- 'ETHER',
288
- new exports.optionalDeps.ethUtil.BN(exports.optionalDeps.ethUtil.stripHexPrefix(recipient.address), 16),
289
- recipient.amount,
290
- Buffer.from(exports.optionalDeps.ethUtil.stripHexPrefix(exports.optionalDeps.ethUtil.padToEven(recipient.data || '')), 'hex'),
291
- expireTime,
292
- contractSequenceId,
293
- ],
294
- ];
295
- }
296
- getOperationSha3ForExecuteAndConfirm(recipients, expireTime, contractSequenceId) {
297
- if (!recipients || !Array.isArray(recipients)) {
298
- throw new Error('expecting array of recipients');
299
- }
300
- // Right now we only support 1 recipient
301
- if (recipients.length !== 1) {
302
- throw new Error('must send to exactly 1 recipient');
303
- }
304
- if (!lodash_1.default.isNumber(expireTime)) {
305
- throw new Error('expireTime must be number of seconds since epoch');
306
- }
307
- if (!lodash_1.default.isNumber(contractSequenceId)) {
308
- throw new Error('contractSequenceId must be number');
309
- }
310
- // Check inputs
311
- recipients.forEach(function (recipient) {
312
- if (!lodash_1.default.isString(recipient.address) ||
313
- !exports.optionalDeps.ethUtil.isValidAddress(exports.optionalDeps.ethUtil.addHexPrefix(recipient.address))) {
314
- throw new Error('Invalid address: ' + recipient.address);
315
- }
316
- let amount;
317
- try {
318
- amount = new bignumber_js_1.BigNumber(recipient.amount);
319
- }
320
- catch (e) {
321
- throw new Error('Invalid amount for: ' + recipient.address + ' - should be numeric');
322
- }
323
- recipient.amount = amount.toFixed(0);
324
- if (recipient.data && !lodash_1.default.isString(recipient.data)) {
325
- throw new Error('Data for recipient ' + recipient.address + ' - should be of type hex string');
326
- }
327
- });
328
- const recipient = recipients[0];
329
- return exports.optionalDeps.ethUtil.bufferToHex(exports.optionalDeps.ethAbi.soliditySHA3(...this.getOperation(recipient, expireTime, contractSequenceId)));
330
- }
331
- /**
332
- * Queries the contract (via Etherscan) for the next sequence ID
333
- * @param address {String} address of the contract
334
- * @returns {Number} sequence ID
335
- */
336
- async querySequenceId(address) {
337
- // Get sequence ID using contract call
338
- const sequenceIdMethodSignature = exports.optionalDeps.ethAbi.methodID('getNextSequenceId', []);
339
- const sequenceIdArgs = exports.optionalDeps.ethAbi.rawEncode([], []);
340
- const sequenceIdData = Buffer.concat([sequenceIdMethodSignature, sequenceIdArgs]).toString('hex');
341
- const result = await this.recoveryBlockchainExplorerQuery({
342
- module: 'proxy',
343
- action: 'eth_call',
344
- to: address,
345
- data: sequenceIdData,
346
- tag: 'latest',
347
- });
348
- if (!result || !result.result) {
349
- throw new Error('Could not obtain sequence ID from Etherscan, got: ' + result.result);
350
- }
351
- const sequenceIdHex = result.result;
352
- return new exports.optionalDeps.ethUtil.BN(sequenceIdHex.slice(2), 16).toNumber();
353
- }
354
- /**
355
- * Helper function for signTransaction for the rare case that SDK is doing the second signature
356
- * Note: we are expecting this to be called from the offline vault
357
- * @param params.txPrebuild
358
- * @param params.signingKeyNonce
359
- * @param params.walletContractAddress
360
- * @param params.prv
361
- * @returns {{txHex: *}}
362
- */
363
- signFinal(params) {
364
- const txPrebuild = params.txPrebuild;
365
- if (!lodash_1.default.isNumber(params.signingKeyNonce) && !lodash_1.default.isNumber(params.txPrebuild.halfSigned.backupKeyNonce)) {
366
- throw new Error('must have at least one of signingKeyNonce and backupKeyNonce as a parameter, and it must be a number');
367
- }
368
- if (lodash_1.default.isUndefined(params.walletContractAddress)) {
369
- throw new Error('params must include walletContractAddress, but got undefined');
370
- }
371
- const signingNode = utxo_lib_1.bip32.fromBase58(params.prv);
372
- const signingKey = signingNode.privateKey;
373
- if (lodash_1.default.isUndefined(signingKey)) {
374
- throw new Error('missing private key');
375
- }
376
- const txInfo = {
377
- recipient: txPrebuild.recipients[0],
378
- expireTime: txPrebuild.halfSigned.expireTime,
379
- contractSequenceId: txPrebuild.halfSigned.contractSequenceId,
380
- signature: txPrebuild.halfSigned.signature,
381
- };
382
- const sendMethodArgs = this.getSendMethodArgs(txInfo);
383
- const methodSignature = exports.optionalDeps.ethAbi.methodID(this.sendMethodName, lodash_1.default.map(sendMethodArgs, 'type'));
384
- const encodedArgs = exports.optionalDeps.ethAbi.rawEncode(lodash_1.default.map(sendMethodArgs, 'type'), lodash_1.default.map(sendMethodArgs, 'value'));
385
- const sendData = Buffer.concat([methodSignature, encodedArgs]);
386
- const ethTxParams = {
387
- to: params.walletContractAddress,
388
- nonce: params.signingKeyNonce !== undefined ? params.signingKeyNonce : params.txPrebuild.halfSigned.backupKeyNonce,
389
- value: 0,
390
- gasPrice: new exports.optionalDeps.ethUtil.BN(txPrebuild.gasPrice),
391
- gasLimit: new exports.optionalDeps.ethUtil.BN(txPrebuild.gasLimit),
392
- data: sendData,
393
- };
394
- const unsignedEthTx = Eth.buildTransaction({
395
- ...ethTxParams,
396
- eip1559: params.txPrebuild.eip1559,
397
- replayProtectionOptions: params.txPrebuild.replayProtectionOptions,
398
- });
399
- const ethTx = unsignedEthTx.sign(signingKey);
400
- return { txHex: ethTx.serialize().toString('hex') };
401
- }
402
- /**
403
- * Assemble keychain and half-sign prebuilt transaction
404
- * @param params
405
- * - txPrebuild
406
- * - prv
407
- * @returns {Promise<SignedTransaction>}
408
- */
409
- async signTransaction(params) {
410
- const txPrebuild = params.txPrebuild;
411
- const userPrv = params.prv;
412
- const EXPIRETIME_DEFAULT = 60 * 60 * 24 * 7; // This signature will be valid for 1 week
413
- if (lodash_1.default.isUndefined(txPrebuild) || !lodash_1.default.isObject(txPrebuild)) {
414
- if (!lodash_1.default.isUndefined(txPrebuild) && !lodash_1.default.isObject(txPrebuild)) {
415
- throw new Error(`txPrebuild must be an object, got type ${typeof txPrebuild}`);
416
- }
417
- throw new Error('missing txPrebuild parameter');
418
- }
419
- if (lodash_1.default.isUndefined(userPrv) || !lodash_1.default.isString(userPrv)) {
420
- if (!lodash_1.default.isUndefined(userPrv) && !lodash_1.default.isString(userPrv)) {
421
- throw new Error(`prv must be a string, got type ${typeof userPrv}`);
422
- }
423
- throw new Error('missing prv parameter to sign transaction');
424
- }
425
- params.recipients = txPrebuild.recipients || params.recipients;
426
- // if no recipients in either params or txPrebuild, then throw an error
427
- if (!params.recipients || !Array.isArray(params.recipients)) {
428
- throw new Error('recipients missing or not array');
429
- }
430
- if (params.recipients.length == 0) {
431
- throw new Error('recipients empty');
432
- }
433
- // Normally the SDK provides the first signature for an ETH tx, but occasionally it provides the second and final one.
434
- if (params.isLastSignature) {
435
- // In this case when we're doing the second (final) signature, the logic is different.
436
- return this.signFinal(params);
437
- }
438
- const secondsSinceEpoch = Math.floor(new Date().getTime() / 1000);
439
- const expireTime = params.expireTime || secondsSinceEpoch + EXPIRETIME_DEFAULT;
440
- const sequenceId = txPrebuild.nextContractSequenceId;
441
- if (lodash_1.default.isUndefined(sequenceId)) {
442
- throw new Error('transaction prebuild missing required property nextContractSequenceId');
443
- }
444
- const operationHash = this.getOperationSha3ForExecuteAndConfirm(params.recipients, expireTime, sequenceId);
445
- const signature = sdk_core_1.Util.ethSignMsgHash(operationHash, sdk_core_1.Util.xprvToEthPrivateKey(userPrv));
446
- const txParams = {
447
- eip1559: params.txPrebuild.eip1559,
448
- isBatch: params.txPrebuild.isBatch,
449
- recipients: params.recipients,
450
- expireTime: expireTime,
451
- contractSequenceId: sequenceId,
452
- sequenceId: params.sequenceId,
453
- operationHash: operationHash,
454
- signature: signature,
455
- gasLimit: params.gasLimit,
456
- gasPrice: params.gasPrice,
457
- hopTransaction: txPrebuild.hopTransaction,
458
- backupKeyNonce: txPrebuild.backupKeyNonce,
459
- custodianTransactionId: params.custodianTransactionId,
460
- };
461
- return { halfSigned: txParams };
462
- }
463
- /**
464
- * Ensure either enterprise or newFeeAddress is passed, to know whether to create new key or use enterprise key
465
- * @param params
466
- * @param params.enterprise {String} the enterprise id to associate with this key
467
- * @param params.newFeeAddress {Boolean} create a new fee address (enterprise not needed in this case)
468
- */
469
- preCreateBitGo(params) {
470
- // We always need params object, since either enterprise or newFeeAddress is required
471
- if (!lodash_1.default.isObject(params)) {
472
- throw new Error(`preCreateBitGo must be passed a params object. Got ${params} (type ${typeof params})`);
473
- }
474
- if (lodash_1.default.isUndefined(params.enterprise) && lodash_1.default.isUndefined(params.newFeeAddress)) {
475
- throw new Error('expecting enterprise when adding BitGo key. If you want to create a new ETH bitgo key, set the newFeeAddress parameter to true.');
476
- }
477
- // Check whether key should be an enterprise key or a BitGo key for a new fee address
478
- if (!lodash_1.default.isUndefined(params.enterprise) && !lodash_1.default.isUndefined(params.newFeeAddress)) {
479
- throw new Error(`Incompatible arguments - cannot pass both enterprise and newFeeAddress parameter.`);
480
- }
481
- if (!lodash_1.default.isUndefined(params.enterprise) && !lodash_1.default.isString(params.enterprise)) {
482
- throw new Error(`enterprise should be a string - got ${params.enterprise} (type ${typeof params.enterprise})`);
483
- }
484
- if (!lodash_1.default.isUndefined(params.newFeeAddress) && !lodash_1.default.isBoolean(params.newFeeAddress)) {
485
- throw new Error(`newFeeAddress should be a boolean - got ${params.newFeeAddress} (type ${typeof params.newFeeAddress})`);
486
- }
487
- }
488
- /**
489
- * Queries public block explorer to get the next ETH nonce that should be used for the given ETH address
490
- * @param address
491
- * @returns {*}
492
- */
493
- async getAddressNonce(address) {
494
- // Get nonce for backup key (should be 0)
495
- let nonce = 0;
496
- const result = await this.recoveryBlockchainExplorerQuery({
497
- module: 'account',
498
- action: 'txlist',
499
- address,
500
- });
501
- if (!result || !Array.isArray(result.result)) {
502
- throw new Error('Unable to find next nonce from Etherscan, got: ' + JSON.stringify(result));
503
- }
504
- const backupKeyTxList = result.result;
505
- if (backupKeyTxList.length > 0) {
506
- // Calculate last nonce used
507
- const outgoingTxs = backupKeyTxList.filter((tx) => tx.from === address);
508
- nonce = outgoingTxs.length;
509
- }
510
- return nonce;
511
- }
512
- /**
513
- * Helper function for recover()
514
- * This transforms the unsigned transaction information into a format the BitGo offline vault expects
515
- * @param txInfo
516
- * @param ethTx
517
- * @param userKey
518
- * @param backupKey
519
- * @param gasPrice
520
- * @param gasLimit
521
- * @param eip1559
522
- * @param replayProtectionOptions
523
- * @returns {Promise<OfflineVaultTxInfo>}
524
- */
525
- async formatForOfflineVault(txInfo, ethTx, userKey, backupKey, gasPrice, gasLimit, eip1559, replayProtectionOptions) {
526
- if (!ethTx.to) {
527
- throw new Error('Eth tx must have a `to` address');
528
- }
529
- const backupHDNode = utxo_lib_1.bip32.fromBase58(backupKey);
530
- const backupSigningKey = backupHDNode.publicKey;
531
- const response = {
532
- tx: ethTx.serialize().toString('hex'),
533
- userKey,
534
- backupKey,
535
- coin: this.getChain(),
536
- gasPrice: exports.optionalDeps.ethUtil.bufferToInt(gasPrice).toFixed(),
537
- gasLimit,
538
- recipients: [txInfo.recipient],
539
- walletContractAddress: ethTx.to.toString(),
540
- amount: txInfo.recipient.amount,
541
- backupKeyNonce: await this.getAddressNonce(`0x${exports.optionalDeps.ethUtil.publicToAddress(backupSigningKey, true).toString('hex')}`),
542
- eip1559,
543
- replayProtectionOptions,
544
- };
545
- lodash_1.default.extend(response, txInfo);
546
- response.nextContractSequenceId = response.contractSequenceId;
547
- return response;
548
- }
549
- /**
550
- * Helper function for recover()
551
- * This transforms the unsigned transaction information into a format the BitGo offline vault expects
552
- * @param txInfo
553
- * @param ethTx
554
- * @param userKey
555
- * @param backupKey
556
- * @param gasPrice
557
- * @param gasLimit
558
- * @param eip1559
559
- * @param replayProtectionOptions
560
- * @returns {Promise<OfflineVaultTxInfo>}
561
- */
562
- formatForOfflineVaultTSS(txInfo, ethTx, userKey, backupKey, gasPrice, gasLimit, backupKeyNonce, eip1559, replayProtectionOptions) {
563
- if (!ethTx.to) {
564
- throw new Error('Eth tx must have a `to` address');
565
- }
566
- const response = {
567
- tx: ethTx.serialize().toString('hex'),
568
- txHex: ethTx.getMessageToSign(false).toString('hex'),
569
- userKey,
570
- backupKey,
571
- coin: this.getChain(),
572
- gasPrice: exports.optionalDeps.ethUtil.bufferToInt(gasPrice).toFixed(),
573
- gasLimit,
574
- recipients: [txInfo.recipient],
575
- walletContractAddress: ethTx.to.toString(),
576
- amount: txInfo.recipient.amount,
577
- backupKeyNonce: backupKeyNonce,
578
- eip1559,
579
- replayProtectionOptions,
580
- };
581
- lodash_1.default.extend(response, txInfo);
582
- return response;
583
- }
584
- /**
585
- * Check whether the gas price passed in by user are within our max and min bounds
586
- * If they are not set, set them to the defaults
587
- * @param userGasPrice user defined gas price
588
- * @returns the gas price to use for this transaction
589
- */
590
- setGasPrice(userGasPrice) {
591
- if (!userGasPrice) {
592
- return statics_1.ethGasConfigs.defaultGasPrice;
593
- }
594
- const gasPriceMax = statics_1.ethGasConfigs.maximumGasPrice;
595
- const gasPriceMin = statics_1.ethGasConfigs.minimumGasPrice;
596
- if (userGasPrice < gasPriceMin || userGasPrice > gasPriceMax) {
597
- throw new Error(`Gas price must be between ${gasPriceMin} and ${gasPriceMax}`);
598
- }
599
- return userGasPrice;
600
- }
601
- /**
602
- * Check whether gas limit passed in by user are within our max and min bounds
603
- * If they are not set, set them to the defaults
604
- * @param userGasLimit user defined gas limit
605
- * @returns the gas limit to use for this transaction
606
- */
607
- setGasLimit(userGasLimit) {
608
- if (!userGasLimit) {
609
- return statics_1.ethGasConfigs.defaultGasLimit;
610
- }
611
- const gasLimitMax = statics_1.ethGasConfigs.maximumGasLimit;
612
- const gasLimitMin = statics_1.ethGasConfigs.minimumGasLimit;
613
- if (userGasLimit < gasLimitMin || userGasLimit > gasLimitMax) {
614
- throw new Error(`Gas limit must be between ${gasLimitMin} and ${gasLimitMax}`);
615
- }
616
- return userGasLimit;
617
- }
618
- validateRecoveryParams(params) {
619
- if (lodash_1.default.isUndefined(params.userKey)) {
620
- throw new Error('missing userKey');
621
- }
622
- if (lodash_1.default.isUndefined(params.backupKey)) {
623
- throw new Error('missing backupKey');
624
- }
625
- if (lodash_1.default.isUndefined(params.walletPassphrase) && !params.userKey.startsWith('xpub') && !params.isTss) {
626
- throw new Error('missing wallet passphrase');
627
- }
628
- if (lodash_1.default.isUndefined(params.walletContractAddress) || !this.isValidAddress(params.walletContractAddress)) {
629
- throw new Error('invalid walletContractAddress');
630
- }
631
- if (lodash_1.default.isUndefined(params.recoveryDestination) || !this.isValidAddress(params.recoveryDestination)) {
632
- throw new Error('invalid recoveryDestination');
633
- }
634
- }
635
- async signRecoveryTSS(userKeyCombined, backupKeyCombined, txHex, { rangeProofChallenge, } = {}) {
636
- const MPC = new sdk_core_1.Ecdsa();
637
- const signerOneIndex = userKeyCombined.xShare.i;
638
- const signerTwoIndex = backupKeyCombined.xShare.i;
639
- rangeProofChallenge =
640
- rangeProofChallenge !== null && rangeProofChallenge !== void 0 ? rangeProofChallenge : sdk_lib_mpc_1.EcdsaTypes.serializeNtildeWithProofs(await sdk_lib_mpc_1.EcdsaRangeProof.generateNtilde());
641
- const userToBackupPaillierChallenge = await sdk_lib_mpc_1.EcdsaPaillierProof.generateP(sdk_core_1.hexToBigInt(userKeyCombined.yShares[signerTwoIndex].n));
642
- const backupToUserPaillierChallenge = await sdk_lib_mpc_1.EcdsaPaillierProof.generateP(sdk_core_1.hexToBigInt(backupKeyCombined.yShares[signerOneIndex].n));
643
- const userXShare = MPC.appendChallenge(userKeyCombined.xShare, rangeProofChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: userToBackupPaillierChallenge }));
644
- const userYShare = MPC.appendChallenge(userKeyCombined.yShares[signerTwoIndex], rangeProofChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: backupToUserPaillierChallenge }));
645
- const backupXShare = MPC.appendChallenge(backupKeyCombined.xShare, rangeProofChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: backupToUserPaillierChallenge }));
646
- const backupYShare = MPC.appendChallenge(backupKeyCombined.yShares[signerOneIndex], rangeProofChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: userToBackupPaillierChallenge }));
647
- const signShares = await MPC.signShare(userXShare, userYShare);
648
- const signConvertS21 = await MPC.signConvertStep1({
649
- xShare: backupXShare,
650
- yShare: backupYShare,
651
- kShare: signShares.kShare,
652
- });
653
- const signConvertS12 = await MPC.signConvertStep2({
654
- aShare: signConvertS21.aShare,
655
- wShare: signShares.wShare,
656
- });
657
- const signConvertS21_2 = await MPC.signConvertStep3({
658
- muShare: signConvertS12.muShare,
659
- bShare: signConvertS21.bShare,
660
- });
661
- const [signCombineOne, signCombineTwo] = [
662
- MPC.signCombine({
663
- gShare: signConvertS12.gShare,
664
- signIndex: {
665
- i: signConvertS12.muShare.i,
666
- j: signConvertS12.muShare.j,
667
- },
668
- }),
669
- MPC.signCombine({
670
- gShare: signConvertS21_2.gShare,
671
- signIndex: {
672
- i: signConvertS21_2.signIndex.i,
673
- j: signConvertS21_2.signIndex.j,
674
- },
675
- }),
676
- ];
677
- const MESSAGE = Buffer.from(txHex, 'hex');
678
- const [signA, signB] = [
679
- MPC.sign(MESSAGE, signCombineOne.oShare, signCombineTwo.dShare, keccak_1.default('keccak256')),
680
- MPC.sign(MESSAGE, signCombineTwo.oShare, signCombineOne.dShare, keccak_1.default('keccak256')),
681
- ];
682
- return MPC.constructSignature([signA, signB]);
683
- }
684
- /**
685
- * Helper which combines key shares of user and backup
686
- * */
687
- getKeyCombinedFromTssKeyShares(userPublicOrPrivateKeyShare, backupPrivateOrPublicKeyShare, walletPassphrase) {
688
- let backupPrv;
689
- let userPrv;
690
- try {
691
- backupPrv = this.bitgo.decrypt({
692
- input: backupPrivateOrPublicKeyShare,
693
- password: walletPassphrase,
694
- });
695
- userPrv = this.bitgo.decrypt({
696
- input: userPublicOrPrivateKeyShare,
697
- password: walletPassphrase,
698
- });
699
- }
700
- catch (e) {
701
- throw new Error(`Error decrypting backup keychain: ${e.message}`);
702
- }
703
- const userSigningMaterial = JSON.parse(userPrv);
704
- const backupSigningMaterial = JSON.parse(backupPrv);
705
- if (!userSigningMaterial.backupNShare) {
706
- throw new Error('Invalid user key - missing backupNShare');
707
- }
708
- if (!backupSigningMaterial.userNShare) {
709
- throw new Error('Invalid backup key - missing userNShare');
710
- }
711
- const MPC = new sdk_core_1.Ecdsa();
712
- const userKeyCombined = MPC.keyCombine(userSigningMaterial.pShare, [
713
- userSigningMaterial.bitgoNShare,
714
- userSigningMaterial.backupNShare,
715
- ]);
716
- const backupKeyCombined = MPC.keyCombine(backupSigningMaterial.pShare, [
717
- backupSigningMaterial.bitgoNShare,
718
- backupSigningMaterial.userNShare,
719
- ]);
720
- if (userKeyCombined.xShare.y !== backupKeyCombined.xShare.y ||
721
- userKeyCombined.xShare.chaincode !== backupKeyCombined.xShare.chaincode) {
722
- throw new Error('Common keychains do not match');
723
- }
724
- return [userKeyCombined, backupKeyCombined];
725
- }
726
- /**
727
- * Helper which Adds signatures to tx object and re-serializes tx
728
- * */
729
- getSignedTxFromSignature(ethCommon, tx, signature) {
730
- // get signed Tx from signature
731
- const txData = tx.toJSON();
732
- const yParity = signature.recid;
733
- const baseParams = {
734
- to: txData.to,
735
- nonce: new bn_js_1.default(ethereumjs_util_1.stripHexPrefix(txData.nonce), 'hex'),
736
- value: new bn_js_1.default(ethereumjs_util_1.stripHexPrefix(txData.value), 'hex'),
737
- gasLimit: new bn_js_1.default(ethereumjs_util_1.stripHexPrefix(txData.gasLimit), 'hex'),
738
- data: txData.data,
739
- r: ethereumjs_util_1.addHexPrefix(signature.r),
740
- s: ethereumjs_util_1.addHexPrefix(signature.s),
741
- };
742
- let finalTx;
743
- if (txData.maxFeePerGas && txData.maxPriorityFeePerGas) {
744
- finalTx = tx_1.FeeMarketEIP1559Transaction.fromTxData({
745
- ...baseParams,
746
- maxPriorityFeePerGas: new bn_js_1.default(ethereumjs_util_1.stripHexPrefix(txData.maxPriorityFeePerGas), 'hex'),
747
- maxFeePerGas: new bn_js_1.default(ethereumjs_util_1.stripHexPrefix(txData.maxFeePerGas), 'hex'),
748
- v: new bn_js_1.default(yParity.toString()),
749
- }, { common: ethCommon });
750
- }
751
- else if (txData.gasPrice) {
752
- const v = BigInt(35) + BigInt(yParity) + BigInt(ethCommon.chainIdBN().toNumber()) * BigInt(2);
753
- finalTx = tx_1.Transaction.fromTxData({
754
- ...baseParams,
755
- v: new bn_js_1.default(v.toString()),
756
- gasPrice: new bn_js_1.default(ethereumjs_util_1.stripHexPrefix(txData.gasPrice.toString()), 'hex'),
757
- }, { common: ethCommon });
758
- }
759
- return finalTx;
760
- }
761
- /**
762
- * Builds a funds recovery transaction without BitGo
763
- * @param params
764
- * @param params.userKey {String} [encrypted] xprv
765
- * @param params.backupKey {String} [encrypted] xprv or xpub if the xprv is held by a KRS provider
766
- * @param params.walletPassphrase {String} used to decrypt userKey and backupKey
767
- * @param params.walletContractAddress {String} the ETH address of the wallet contract
768
- * @param params.krsProvider {String} necessary if backup key is held by KRS
769
- * @param params.recoveryDestination {String} target address to send recovered funds to
770
- * @param params.bitgoFeeAddress {String} wrong chain wallet fee address for evm based cross chain recovery txn
771
- * @param params.bitgoDestinationAddress {String} target bitgo address where fee will be sent for evm based cross chain recovery txn
772
- */
773
- async recover(params) {
774
- if (params.isTss) {
775
- return this.recoverTSS(params);
776
- }
777
- return this.recoverEthLike(params);
778
- }
779
- /**
780
- * Builds a unsigned (for cold, custody wallet) or
781
- * half-signed (for hot wallet) evm cross chain recovery transaction with
782
- * same expected arguments as recover method.
783
- * This helps recover funds from evm based wrong chain.
784
- */
785
- async recoverEthLikeforEvmBasedRecovery(params) {
786
- var _a, _b, _c, _d, _e;
787
- this.validateEvmBasedRecoveryParams(params);
788
- // Clean up whitespace from entered values
789
- const userKey = params.userKey.replace(/\s/g, '');
790
- const bitgoFeeAddress = (_a = params.bitgoFeeAddress) === null || _a === void 0 ? void 0 : _a.replace(/\s/g, '');
791
- const bitgoDestinationAddress = (_b = params.bitgoDestinationAddress) === null || _b === void 0 ? void 0 : _b.replace(/\s/g, '');
792
- const recoveryDestination = (_c = params.recoveryDestination) === null || _c === void 0 ? void 0 : _c.replace(/\s/g, '');
793
- const walletContractAddress = (_d = params.walletContractAddress) === null || _d === void 0 ? void 0 : _d.replace(/\s/g, '');
794
- const tokenContractAddress = (_e = params.tokenContractAddress) === null || _e === void 0 ? void 0 : _e.replace(/\s/g, '');
795
- let userSigningKey;
796
- let userKeyPrv;
797
- if (params.walletPassphrase) {
798
- if (!userKey.startsWith('xpub') && !userKey.startsWith('xprv')) {
799
- try {
800
- userKeyPrv = this.bitgo.decrypt({
801
- input: userKey,
802
- password: params.walletPassphrase,
803
- });
804
- }
805
- catch (e) {
806
- throw new Error(`Error decrypting user keychain: ${e.message}`);
807
- }
808
- }
809
- const keyPair = new lib_1.KeyPair({ prv: userKeyPrv });
810
- userSigningKey = keyPair.getKeys().prv;
811
- if (!userSigningKey) {
812
- throw new Error('no private key');
813
- }
814
- }
815
- const gasLimit = new exports.optionalDeps.ethUtil.BN(this.setGasLimit(params.gasLimit));
816
- const gasPrice = params.eip1559
817
- ? new exports.optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas)
818
- : new exports.optionalDeps.ethUtil.BN(this.setGasPrice(params.gasPrice));
819
- const bitgoFeeAddressNonce = await this.getAddressNonce(bitgoFeeAddress);
820
- // get balance of bitgoFeeAddress to ensure funds are available to pay fees
821
- const bitgoFeeAddressBalance = await this.queryAddressBalance(bitgoFeeAddress);
822
- const totalGasNeeded = gasPrice.mul(gasLimit);
823
- const weiToGwei = 10 ** 9;
824
- if (bitgoFeeAddressBalance.lt(totalGasNeeded)) {
825
- throw new Error(`Fee address ${bitgoFeeAddressBalance} has balance ${(bitgoFeeAddressBalance / weiToGwei).toString()} Gwei.` +
826
- `This address must have a balance of at least ${(totalGasNeeded / weiToGwei).toString()}` +
827
- ` Gwei to perform recoveries. Try sending some ${this.getChain()} to this address then retry.`);
828
- }
829
- if (tokenContractAddress) {
830
- return this.recoverEthLikeTokenforEvmBasedRecovery(params, bitgoFeeAddressNonce, gasLimit, gasPrice, userKey, userSigningKey);
831
- }
832
- // get balance of wallet
833
- const txAmount = await this.queryAddressBalance(walletContractAddress);
834
- const bitgoFeePercentage = 0; // TODO: BG-71912 can change the fee% here.
835
- const bitgoFeeAmount = txAmount * (bitgoFeePercentage / 100);
836
- // build recipients object
837
- const recipients = [
838
- {
839
- address: recoveryDestination,
840
- amount: new bignumber_js_1.BigNumber(txAmount).minus(bitgoFeeAmount).toFixed(),
841
- },
842
- ];
843
- if (bitgoFeePercentage > 0) {
844
- if (lodash_1.default.isUndefined(bitgoDestinationAddress) || !this.isValidAddress(bitgoDestinationAddress)) {
845
- throw new Error('invalid bitgoDestinationAddress');
846
- }
847
- recipients.push({
848
- address: bitgoDestinationAddress,
849
- amount: bitgoFeeAmount.toString(10),
850
- });
851
- }
852
- // calculate batch data
853
- const BATCH_METHOD_NAME = 'batch';
854
- const BATCH_METHOD_TYPES = ['address[]', 'uint256[]'];
855
- const batchExecutionInfo = this.getBatchExecutionInfo(recipients);
856
- const batchData = exports.optionalDeps.ethUtil.addHexPrefix(this.getMethodCallData(BATCH_METHOD_NAME, BATCH_METHOD_TYPES, batchExecutionInfo.values).toString('hex'));
857
- // Get sequence ID using contract call
858
- // we need to wait between making two polygonscan calls to avoid getting banned
859
- await new Promise((resolve) => setTimeout(resolve, 1000));
860
- const sequenceId = await this.querySequenceId(walletContractAddress);
861
- const txInfo = {
862
- recipients: recipients,
863
- expireTime: this.getDefaultExpireTime(),
864
- contractSequenceId: sequenceId,
865
- gasLimit: gasLimit.toString(10),
866
- isEvmBasedCrossChainRecovery: true,
867
- };
868
- const network = this.getNetwork();
869
- const batcherContractAddress = network === null || network === void 0 ? void 0 : network.batcherContractAddress;
870
- const txBuilder = this.getTransactionBuilder();
871
- txBuilder.counter(bitgoFeeAddressNonce);
872
- txBuilder.contract(walletContractAddress);
873
- let txFee;
874
- if (params.eip1559) {
875
- txFee = {
876
- eip1559: {
877
- maxPriorityFeePerGas: params.eip1559.maxPriorityFeePerGas,
878
- maxFeePerGas: params.eip1559.maxFeePerGas,
879
- },
880
- };
881
- }
882
- else {
883
- txFee = { fee: gasPrice.toString() };
884
- }
885
- txBuilder.fee({
886
- ...txFee,
887
- gasLimit: gasLimit.toString(),
888
- });
889
- const transferBuilder = txBuilder.transfer();
890
- transferBuilder
891
- .amount(batchExecutionInfo.totalAmount)
892
- .contractSequenceId(sequenceId)
893
- .expirationTime(this.getDefaultExpireTime())
894
- .to(batcherContractAddress)
895
- .data(batchData);
896
- if (params.walletPassphrase) {
897
- txBuilder.transfer().key(userSigningKey);
898
- }
899
- const tx = await txBuilder.build();
900
- const response = {
901
- txHex: tx.toBroadcastFormat(),
902
- userKey,
903
- coin: this.getChain(),
904
- gasPrice: exports.optionalDeps.ethUtil.bufferToInt(gasPrice).toFixed(),
905
- gasLimit,
906
- recipients: txInfo.recipients,
907
- walletContractAddress: tx.toJson().to,
908
- amount: batchExecutionInfo.totalAmount,
909
- backupKeyNonce: bitgoFeeAddressNonce,
910
- eip1559: params.eip1559,
911
- };
912
- lodash_1.default.extend(response, txInfo);
913
- response.nextContractSequenceId = response.contractSequenceId;
914
- if (params.walletPassphrase) {
915
- const halfSignedTxn = {
916
- halfSigned: {
917
- txHex: tx.toBroadcastFormat(),
918
- recipients: txInfo.recipients,
919
- expireTime: txInfo.expireTime,
920
- },
921
- };
922
- lodash_1.default.extend(response, halfSignedTxn);
923
- const feesUsed = {
924
- gasPrice: exports.optionalDeps.ethUtil.bufferToInt(gasPrice).toFixed(),
925
- gasLimit: exports.optionalDeps.ethUtil.bufferToInt(gasLimit).toFixed(),
926
- };
927
- response['feesUsed'] = feesUsed;
928
- }
929
- return response;
930
- }
931
- async recoverEthLikeTokenforEvmBasedRecovery(params, bitgoFeeAddressNonce, gasLimit, gasPrice, userKey, userSigningKey) {
932
- var _a;
933
- // get token balance of wallet
934
- const txAmount = await this.queryAddressTokenBalance(params.tokenContractAddress, params.walletContractAddress);
935
- // build recipients object
936
- const recipients = [
937
- {
938
- address: params.recoveryDestination,
939
- amount: new bignumber_js_1.BigNumber(txAmount).toFixed(),
940
- },
941
- ];
942
- // Get sequence ID using contract call
943
- // we need to wait between making two polygonscan calls to avoid getting banned
944
- await new Promise((resolve) => setTimeout(resolve, 1000));
945
- const sequenceId = await this.querySequenceId(params.walletContractAddress);
946
- const txInfo = {
947
- recipients: recipients,
948
- expireTime: this.getDefaultExpireTime(),
949
- contractSequenceId: sequenceId,
950
- gasLimit: gasLimit.toString(10),
951
- isEvmBasedCrossChainRecovery: true,
952
- };
953
- const txBuilder = this.getTransactionBuilder();
954
- txBuilder.counter(bitgoFeeAddressNonce);
955
- txBuilder.contract(params.walletContractAddress);
956
- let txFee;
957
- if (params.eip1559) {
958
- txFee = {
959
- eip1559: {
960
- maxPriorityFeePerGas: params.eip1559.maxPriorityFeePerGas,
961
- maxFeePerGas: params.eip1559.maxFeePerGas,
962
- },
963
- };
964
- }
965
- else {
966
- txFee = { fee: gasPrice.toString() };
967
- }
968
- txBuilder.fee({
969
- ...txFee,
970
- gasLimit: gasLimit.toString(),
971
- });
972
- const transferBuilder = txBuilder.transfer();
973
- const network = this.getNetwork();
974
- const token = (_a = lib_1.getToken(params.tokenContractAddress, network)) === null || _a === void 0 ? void 0 : _a.name;
975
- transferBuilder
976
- .amount(txAmount)
977
- .contractSequenceId(sequenceId)
978
- .expirationTime(this.getDefaultExpireTime())
979
- .to(params.recoveryDestination)
980
- .coin(token);
981
- if (params.walletPassphrase) {
982
- txBuilder.transfer().key(userSigningKey);
983
- }
984
- const tx = await txBuilder.build();
985
- const response = {
986
- txHex: tx.toBroadcastFormat(),
987
- userKey,
988
- coin: token,
989
- gasPrice: exports.optionalDeps.ethUtil.bufferToInt(gasPrice).toFixed(),
990
- gasLimit,
991
- recipients: txInfo.recipients,
992
- walletContractAddress: tx.toJson().to,
993
- amount: txAmount.toString(),
994
- backupKeyNonce: bitgoFeeAddressNonce,
995
- eip1559: params.eip1559,
996
- };
997
- lodash_1.default.extend(response, txInfo);
998
- response.nextContractSequenceId = response.contractSequenceId;
999
- if (params.walletPassphrase) {
1000
- const halfSignedTxn = {
1001
- halfSigned: {
1002
- txHex: tx.toBroadcastFormat(),
1003
- recipients: txInfo.recipients,
1004
- expireTime: txInfo.expireTime,
1005
- },
1006
- };
1007
- lodash_1.default.extend(response, halfSignedTxn);
1008
- const feesUsed = {
1009
- gasPrice: exports.optionalDeps.ethUtil.bufferToInt(gasPrice).toFixed(),
1010
- gasLimit: exports.optionalDeps.ethUtil.bufferToInt(gasLimit).toFixed(),
1011
- };
1012
- response['feesUsed'] = feesUsed;
1013
- }
1014
- return response;
1015
- }
1016
- validateEvmBasedRecoveryParams(params) {
1017
- if (lodash_1.default.isUndefined(params.bitgoFeeAddress) || !this.isValidAddress(params.bitgoFeeAddress)) {
1018
- throw new Error('invalid bitgoFeeAddress');
1019
- }
1020
- if (lodash_1.default.isUndefined(params.walletContractAddress) || !this.isValidAddress(params.walletContractAddress)) {
1021
- throw new Error('invalid walletContractAddress');
1022
- }
1023
- if (lodash_1.default.isUndefined(params.recoveryDestination) || !this.isValidAddress(params.recoveryDestination)) {
1024
- throw new Error('invalid recoveryDestination');
1025
- }
1026
- }
1027
- /**
1028
- * Create a new transaction builder for the current chain
1029
- * @return a new transaction builder
1030
- */
1031
- getTransactionBuilder() {
1032
- return new lib_1.TransactionBuilder(statics_1.coins.get(this.getBaseChain()));
1033
- }
1034
- /**
1035
- * Get the base chain that the coin exists on.
1036
- */
1037
- getBaseChain() {
1038
- return this.getChain();
1039
- }
1040
- /**
1041
- * Return types, values, and total amount in wei to send in a batch transaction, using the method signature
1042
- * `distributeBatch(address[], uint256[])`
1043
- * @param {Recipient[]} recipients - transaction recipients
1044
- * @returns {GetBatchExecutionInfoRT} information needed to execute the batch transaction
1045
- */
1046
- getBatchExecutionInfo(recipients) {
1047
- const addresses = [];
1048
- const amounts = [];
1049
- let sum = new bignumber_js_1.BigNumber('0');
1050
- lodash_1.default.forEach(recipients, ({ address, amount }) => {
1051
- addresses.push(address);
1052
- amounts.push(amount);
1053
- sum = sum.plus(amount);
1054
- });
1055
- return {
1056
- values: [addresses, amounts],
1057
- totalAmount: sum.toFixed(),
1058
- };
1059
- }
1060
- /**
1061
- * Recovers a tx with TSS key shares
1062
- * same expected arguments as recover method, but with TSS key shares
1063
- */
1064
- async recoverTSS(params) {
1065
- this.validateRecoveryParams(params);
1066
- const isUnsignedSweep = sdk_core_1.getIsUnsignedSweep(params);
1067
- // Clean up whitespace from entered values
1068
- const userPublicOrPrivateKeyShare = params.userKey.replace(/\s/g, '');
1069
- const backupPrivateOrPublicKeyShare = params.backupKey.replace(/\s/g, '');
1070
- // Set new eth tx fees (using default config values from platform)
1071
- const gasLimit = new exports.optionalDeps.ethUtil.BN(this.setGasLimit(params.gasLimit));
1072
- const gasPrice = params.eip1559
1073
- ? new exports.optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas)
1074
- : new exports.optionalDeps.ethUtil.BN(this.setGasPrice(params.gasPrice));
1075
- const [backupKeyAddress, userKeyCombined, backupKeyCombined] = (() => {
1076
- if (isUnsignedSweep) {
1077
- const backupKeyPair = new lib_1.KeyPair({ pub: backupPrivateOrPublicKeyShare });
1078
- return [backupKeyPair.getAddress(), undefined, undefined];
1079
- }
1080
- else {
1081
- const [userKeyCombined, backupKeyCombined] = this.getKeyCombinedFromTssKeyShares(userPublicOrPrivateKeyShare, backupPrivateOrPublicKeyShare, params.walletPassphrase);
1082
- const backupKeyPair = new lib_1.KeyPair({ pub: backupKeyCombined.xShare.y });
1083
- return [backupKeyPair.getAddress(), userKeyCombined, backupKeyCombined];
1084
- }
1085
- })();
1086
- const backupKeyNonce = await this.getAddressNonce(backupKeyAddress);
1087
- // get balance of backupKey to ensure funds are available to pay fees
1088
- const backupKeyBalance = await this.queryAddressBalance(backupKeyAddress);
1089
- const totalGasNeeded = gasPrice.mul(gasLimit);
1090
- const weiToGwei = 10 ** 9;
1091
- if (backupKeyBalance.lt(totalGasNeeded)) {
1092
- throw new Error(`Backup key address ${backupKeyAddress} has balance ${(backupKeyBalance / weiToGwei).toString()} Gwei.` +
1093
- `This address must have a balance of at least ${(totalGasNeeded / weiToGwei).toString()}` +
1094
- ` Gwei to perform recoveries. Try sending some ETH to this address then retry.`);
1095
- }
1096
- // get balance of wallet and deduct fees to get transaction amount, wallet contract address acts as base address for tss?
1097
- const txAmount = backupKeyBalance.sub(totalGasNeeded);
1098
- // build recipients object
1099
- const recipients = [
1100
- {
1101
- address: params.recoveryDestination,
1102
- amount: txAmount.toString(10),
1103
- },
1104
- ];
1105
- const txInfo = {
1106
- recipient: recipients[0],
1107
- expireTime: this.getDefaultExpireTime(),
1108
- gasLimit: gasLimit.toString(10),
1109
- };
1110
- const txParams = {
1111
- to: params.recoveryDestination,
1112
- nonce: backupKeyNonce,
1113
- value: txAmount,
1114
- gasPrice: gasPrice,
1115
- gasLimit: gasLimit,
1116
- data: Buffer.from('0x'),
1117
- eip1559: params.eip1559,
1118
- replayProtectionOptions: params.replayProtectionOptions,
70
+ // default to tangerine whistle to avoid replay protection issues
71
+ const ethCommon = Eth.getEthCommon(params.eip1559, params.replayProtectionOptions);
72
+ const baseParams = {
73
+ to: params.to,
74
+ nonce: params.nonce,
75
+ value: params.value,
76
+ data: params.data,
77
+ gasLimit: new abstract_eth_1.optionalDeps.ethUtil.BN(params.gasLimit),
1119
78
  };
1120
- let tx = Eth.buildTransaction(txParams);
1121
- if (isUnsignedSweep) {
1122
- return this.formatForOfflineVaultTSS(txInfo, tx, userPublicOrPrivateKeyShare, backupPrivateOrPublicKeyShare, gasPrice, gasLimit, backupKeyNonce, params.eip1559, params.replayProtectionOptions);
79
+ const unsignedEthTx = !!params.eip1559
80
+ ? abstract_eth_1.optionalDeps.EthTx.FeeMarketEIP1559Transaction.fromTxData({
81
+ ...baseParams,
82
+ maxFeePerGas: new abstract_eth_1.optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas),
83
+ maxPriorityFeePerGas: new abstract_eth_1.optionalDeps.ethUtil.BN(params.eip1559.maxPriorityFeePerGas),
84
+ }, { common: ethCommon })
85
+ : abstract_eth_1.optionalDeps.EthTx.Transaction.fromTxData({
86
+ ...baseParams,
87
+ gasPrice: new abstract_eth_1.optionalDeps.ethUtil.BN(params.gasPrice),
88
+ }, { common: ethCommon });
89
+ return unsignedEthTx;
90
+ }
91
+ /**
92
+ * Make a query to Etherscan for information such as balance, token balance, solidity calls
93
+ * @param query {Object} key-value pairs of parameters to append after /api
94
+ * @returns {Object} response from Etherscan
95
+ */
96
+ async recoveryBlockchainExplorerQuery(query) {
97
+ const token = sdk_core_1.common.Environments[this.bitgo.getEnv()].etherscanApiToken;
98
+ if (token) {
99
+ query.apikey = token;
100
+ }
101
+ const response = await superagent_1.default.get(sdk_core_1.common.Environments[this.bitgo.getEnv()].etherscanBaseUrl + '/api').query(query);
102
+ if (!response.ok) {
103
+ throw new Error('could not reach Etherscan');
1123
104
  }
1124
- const signableHex = tx.getMessageToSign(false).toString('hex');
1125
- if (!userKeyCombined || !backupKeyCombined) {
1126
- throw new Error('Missing key combined shares for user or backup');
105
+ if (response.body.status === '0' && response.body.message === 'NOTOK') {
106
+ throw new Error('Etherscan rate limit reached');
1127
107
  }
1128
- const signature = await this.signRecoveryTSS(userKeyCombined, backupKeyCombined, signableHex);
1129
- const ethCommmon = Eth.getEthCommon(params.eip1559, params.replayProtectionOptions);
1130
- tx = this.getSignedTxFromSignature(ethCommmon, tx, signature);
1131
- return {
1132
- id: ethereumjs_util_1.addHexPrefix(tx.hash().toString('hex')),
1133
- tx: ethereumjs_util_1.addHexPrefix(tx.serialize().toString('hex')),
1134
- };
108
+ return response.body;
1135
109
  }
1136
110
  /**
1137
111
  * Recovers a tx with non-TSS keys
@@ -1144,19 +118,19 @@ class Eth extends sdk_core_1.BaseCoin {
1144
118
  return this.recoverEthLikeforEvmBasedRecovery(params);
1145
119
  }
1146
120
  this.validateRecoveryParams(params);
1147
- const isKrsRecovery = sdk_core_1.getIsKrsRecovery(params);
1148
- const isUnsignedSweep = sdk_core_1.getIsUnsignedSweep(params);
121
+ const isKrsRecovery = (0, sdk_core_1.getIsKrsRecovery)(params);
122
+ const isUnsignedSweep = (0, sdk_core_1.getIsUnsignedSweep)(params);
1149
123
  if (isKrsRecovery) {
1150
- sdk_core_1.checkKrsProvider(this, params.krsProvider, { checkCoinFamilySupport: false });
124
+ (0, sdk_core_1.checkKrsProvider)(this, params.krsProvider, { checkCoinFamilySupport: false });
1151
125
  }
1152
126
  // Clean up whitespace from entered values
1153
127
  let userKey = params.userKey.replace(/\s/g, '');
1154
128
  const backupKey = params.backupKey.replace(/\s/g, '');
1155
129
  // Set new eth tx fees (using default config values from platform)
1156
- const gasLimit = new exports.optionalDeps.ethUtil.BN(this.setGasLimit(params.gasLimit));
130
+ const gasLimit = new abstract_eth_1.optionalDeps.ethUtil.BN(this.setGasLimit(params.gasLimit));
1157
131
  const gasPrice = params.eip1559
1158
- ? new exports.optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas)
1159
- : new exports.optionalDeps.ethUtil.BN(this.setGasPrice(params.gasPrice));
132
+ ? new abstract_eth_1.optionalDeps.ethUtil.BN(params.eip1559.maxFeePerGas)
133
+ : new abstract_eth_1.optionalDeps.ethUtil.BN(this.setGasPrice(params.gasPrice));
1160
134
  if (!userKey.startsWith('xpub') && !userKey.startsWith('xprv')) {
1161
135
  try {
1162
136
  userKey = this.bitgo.decrypt({
@@ -1171,9 +145,9 @@ class Eth extends sdk_core_1.BaseCoin {
1171
145
  let backupKeyAddress;
1172
146
  let backupSigningKey;
1173
147
  if (isKrsRecovery || isUnsignedSweep) {
1174
- const backupHDNode = utxo_lib_1.bip32.fromBase58(backupKey);
148
+ const backupHDNode = secp256k1_1.bip32.fromBase58(backupKey);
1175
149
  backupSigningKey = backupHDNode.publicKey;
1176
- backupKeyAddress = `0x${exports.optionalDeps.ethUtil.publicToAddress(backupSigningKey, true).toString('hex')}`;
150
+ backupKeyAddress = `0x${abstract_eth_1.optionalDeps.ethUtil.publicToAddress(backupSigningKey, true).toString('hex')}`;
1177
151
  }
1178
152
  else {
1179
153
  // Decrypt backup private key and get address
@@ -1187,12 +161,12 @@ class Eth extends sdk_core_1.BaseCoin {
1187
161
  catch (e) {
1188
162
  throw new Error(`Error decrypting backup keychain: ${e.message}`);
1189
163
  }
1190
- const backupHDNode = utxo_lib_1.bip32.fromBase58(backupPrv);
164
+ const backupHDNode = secp256k1_1.bip32.fromBase58(backupPrv);
1191
165
  backupSigningKey = backupHDNode.privateKey;
1192
166
  if (!backupHDNode) {
1193
167
  throw new Error('no private key');
1194
168
  }
1195
- backupKeyAddress = `0x${exports.optionalDeps.ethUtil.privateToAddress(backupSigningKey).toString('hex')}`;
169
+ backupKeyAddress = `0x${abstract_eth_1.optionalDeps.ethUtil.privateToAddress(backupSigningKey).toString('hex')}`;
1196
170
  }
1197
171
  const backupKeyNonce = await this.getAddressNonce(backupKeyAddress);
1198
172
  // get balance of backupKey to ensure funds are available to pay fees
@@ -1206,6 +180,9 @@ class Eth extends sdk_core_1.BaseCoin {
1206
180
  }
1207
181
  // get balance of wallet and deduct fees to get transaction amount
1208
182
  const txAmount = await this.queryAddressBalance(params.walletContractAddress);
183
+ if (new bignumber_js_1.BigNumber(txAmount).isLessThanOrEqualTo(0)) {
184
+ throw new Error('Wallet does not have enough funds to recover');
185
+ }
1209
186
  // build recipients object
1210
187
  const recipients = [
1211
188
  {
@@ -1239,8 +216,8 @@ class Eth extends sdk_core_1.BaseCoin {
1239
216
  };
1240
217
  // calculate send data
1241
218
  const sendMethodArgs = this.getSendMethodArgs(txInfo);
1242
- const methodSignature = exports.optionalDeps.ethAbi.methodID(this.sendMethodName, lodash_1.default.map(sendMethodArgs, 'type'));
1243
- const encodedArgs = exports.optionalDeps.ethAbi.rawEncode(lodash_1.default.map(sendMethodArgs, 'type'), lodash_1.default.map(sendMethodArgs, 'value'));
219
+ const methodSignature = abstract_eth_1.optionalDeps.ethAbi.methodID(this.sendMethodName, lodash_1.default.map(sendMethodArgs, 'type'));
220
+ const encodedArgs = abstract_eth_1.optionalDeps.ethAbi.rawEncode(lodash_1.default.map(sendMethodArgs, 'type'), lodash_1.default.map(sendMethodArgs, 'value'));
1244
221
  const sendData = Buffer.concat([methodSignature, encodedArgs]);
1245
222
  const txParams = {
1246
223
  to: params.walletContractAddress,
@@ -1261,7 +238,7 @@ class Eth extends sdk_core_1.BaseCoin {
1261
238
  tx = tx.sign(backupSigningKey);
1262
239
  }
1263
240
  const signedTx = {
1264
- id: exports.optionalDeps.ethUtil.bufferToHex(tx.hash()),
241
+ id: abstract_eth_1.optionalDeps.ethUtil.bufferToHex(tx.hash()),
1265
242
  tx: tx.serialize().toString('hex'),
1266
243
  };
1267
244
  if (isKrsRecovery) {
@@ -1270,294 +247,140 @@ class Eth extends sdk_core_1.BaseCoin {
1270
247
  }
1271
248
  return signedTx;
1272
249
  }
1273
- /**
1274
- * Recover an unsupported token from a BitGo multisig wallet
1275
- * This builds a half-signed transaction, for which there will be an admin route to co-sign and broadcast. Optionally
1276
- * the user can set params.broadcast = true and the half-signed tx will be sent to BitGo for cosigning and broadcasting
1277
- * @param params
1278
- * @param params.wallet the wallet to recover the token from
1279
- * @param params.tokenContractAddress the contract address of the unsupported token
1280
- * @param params.recipient the destination address recovered tokens should be sent to
1281
- * @param params.walletPassphrase the wallet passphrase
1282
- * @param params.prv the xprv
1283
- * @param params.broadcast if true, we will automatically submit the half-signed tx to BitGo for cosigning and broadcasting
1284
- */
1285
- async recoverToken(params) {
1286
- if (!lodash_1.default.isObject(params)) {
1287
- throw new Error(`recoverToken must be passed a params object. Got ${params} (type ${typeof params})`);
1288
- }
1289
- if (lodash_1.default.isUndefined(params.tokenContractAddress) || !lodash_1.default.isString(params.tokenContractAddress)) {
1290
- throw new Error(`tokenContractAddress must be a string, got ${params.tokenContractAddress} (type ${typeof params.tokenContractAddress})`);
1291
- }
1292
- if (!this.isValidAddress(params.tokenContractAddress)) {
1293
- throw new Error('tokenContractAddress not a valid address');
1294
- }
1295
- if (lodash_1.default.isUndefined(params.wallet) || !(params.wallet instanceof sdk_core_1.Wallet)) {
1296
- throw new Error(`wallet must be a wallet instance, got ${params.wallet} (type ${typeof params.wallet})`);
1297
- }
1298
- if (lodash_1.default.isUndefined(params.recipient) || !lodash_1.default.isString(params.recipient)) {
1299
- throw new Error(`recipient must be a string, got ${params.recipient} (type ${typeof params.recipient})`);
1300
- }
1301
- if (!this.isValidAddress(params.recipient)) {
1302
- throw new Error('recipient not a valid address');
1303
- }
1304
- if (!exports.optionalDeps.ethUtil.bufferToHex || !exports.optionalDeps.ethAbi.soliditySHA3) {
1305
- throw new Error('ethereum not fully supported in this environment');
1306
- }
1307
- // Get token balance from external API
1308
- const coinSpecific = params.wallet.coinSpecific();
1309
- if (!coinSpecific || !lodash_1.default.isString(coinSpecific.baseAddress)) {
1310
- throw new Error('missing required coin specific property baseAddress');
1311
- }
1312
- const recoveryAmount = await this.queryAddressTokenBalance(params.tokenContractAddress, coinSpecific.baseAddress);
1313
- if (params.broadcast) {
1314
- // We're going to create a normal ETH transaction that sends an amount of 0 ETH to the
1315
- // tokenContractAddress and encode the unsupported-token-send data in the data field
1316
- // #tricksy
1317
- const sendMethodArgs = [
1318
- {
1319
- name: '_to',
1320
- type: 'address',
1321
- value: params.recipient,
1322
- },
1323
- {
1324
- name: '_value',
1325
- type: 'uint256',
1326
- value: recoveryAmount.toString(10),
1327
- },
1328
- ];
1329
- const methodSignature = exports.optionalDeps.ethAbi.methodID('transfer', lodash_1.default.map(sendMethodArgs, 'type'));
1330
- const encodedArgs = exports.optionalDeps.ethAbi.rawEncode(lodash_1.default.map(sendMethodArgs, 'type'), lodash_1.default.map(sendMethodArgs, 'value'));
1331
- const sendData = Buffer.concat([methodSignature, encodedArgs]);
1332
- const broadcastParams = {
1333
- address: params.tokenContractAddress,
1334
- amount: '0',
1335
- data: sendData.toString('hex'),
1336
- };
1337
- if (params.walletPassphrase) {
1338
- broadcastParams.walletPassphrase = params.walletPassphrase;
1339
- }
1340
- else if (params.prv) {
1341
- broadcastParams.prv = params.prv;
1342
- }
1343
- return await params.wallet.send(broadcastParams);
1344
- }
1345
- const recipient = {
1346
- address: params.recipient,
1347
- amount: recoveryAmount.toString(10),
1348
- };
1349
- // This signature will be valid for one week
1350
- const expireTime = Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 * 7;
1351
- // Get sequence ID. We do this by building a 'fake' eth transaction, so the platform will increment and return us the new sequence id
1352
- // This _does_ require the user to have a non-zero wallet balance
1353
- const { nextContractSequenceId, gasPrice, gasLimit } = (await params.wallet.prebuildTransaction({
1354
- recipients: [
1355
- {
1356
- address: params.recipient,
1357
- amount: '1',
1358
- },
1359
- ],
1360
- }));
1361
- // these recoveries need to be processed by support, but if the customer sends any transactions before recovery is
1362
- // complete the sequence ID will be invalid. artificially inflate the sequence ID to allow more time for processing
1363
- const safeSequenceId = nextContractSequenceId + 1000;
1364
- // Build sendData for ethereum tx
1365
- const operationTypes = ['string', 'address', 'uint', 'address', 'uint', 'uint'];
1366
- const operationArgs = [
1367
- // "ERC20" has been added here so that ether operation hashes, signatures cannot be re-used for tokenSending
1368
- 'ERC20',
1369
- new exports.optionalDeps.ethUtil.BN(exports.optionalDeps.ethUtil.stripHexPrefix(recipient.address), 16),
1370
- recipient.amount,
1371
- new exports.optionalDeps.ethUtil.BN(exports.optionalDeps.ethUtil.stripHexPrefix(params.tokenContractAddress), 16),
1372
- expireTime,
1373
- safeSequenceId,
1374
- ];
1375
- const operationHash = exports.optionalDeps.ethUtil.bufferToHex(exports.optionalDeps.ethAbi.soliditySHA3(operationTypes, operationArgs));
1376
- const userPrv = await params.wallet.getPrv({
1377
- prv: params.prv,
1378
- walletPassphrase: params.walletPassphrase,
1379
- });
1380
- const signature = sdk_core_1.Util.ethSignMsgHash(operationHash, sdk_core_1.Util.xprvToEthPrivateKey(userPrv));
1381
- return {
1382
- halfSigned: {
1383
- recipient: recipient,
1384
- expireTime: expireTime,
1385
- contractSequenceId: safeSequenceId,
1386
- operationHash: operationHash,
1387
- signature: signature,
1388
- gasLimit: gasLimit,
1389
- gasPrice: gasPrice,
1390
- tokenContractAddress: params.tokenContractAddress,
1391
- walletId: params.wallet.id(),
1392
- },
1393
- };
1394
- }
1395
- /**
1396
- * Build arguments to call the send method on the wallet contract
1397
- * @param txInfo
1398
- */
1399
- getSendMethodArgs(txInfo) {
1400
- // Method signature is
1401
- // sendMultiSig(address toAddress, uint value, bytes data, uint expireTime, uint sequenceId, bytes signature)
1402
- return [
1403
- {
1404
- name: 'toAddress',
1405
- type: 'address',
1406
- value: txInfo.recipient.address,
1407
- },
1408
- {
1409
- name: 'value',
1410
- type: 'uint',
1411
- value: txInfo.recipient.amount,
1412
- },
1413
- {
1414
- name: 'data',
1415
- type: 'bytes',
1416
- value: exports.optionalDeps.ethUtil.toBuffer(exports.optionalDeps.ethUtil.addHexPrefix(txInfo.recipient.data || '')),
1417
- },
1418
- {
1419
- name: 'expireTime',
1420
- type: 'uint',
1421
- value: txInfo.expireTime,
1422
- },
1423
- {
1424
- name: 'sequenceId',
1425
- type: 'uint',
1426
- value: txInfo.contractSequenceId,
1427
- },
1428
- {
1429
- name: 'signature',
1430
- type: 'bytes',
1431
- value: exports.optionalDeps.ethUtil.toBuffer(exports.optionalDeps.ethUtil.addHexPrefix(txInfo.signature)),
1432
- },
1433
- ];
250
+ async buildUnsignedSweepTxnTSS(params) {
251
+ // Coin-specific logic for ETH
252
+ return this.buildUnsignedSweepTxnMPCv2(params);
1434
253
  }
1435
254
  /**
1436
- * Make a query to Etherscan for information such as balance, token balance, solidity calls
1437
- * @param query {Object} key-value pairs of parameters to append after /api
1438
- * @returns {Object} response from Etherscan
255
+ * Return boolean indicating whether input is valid public key for the coin.
256
+ *
257
+ * @param {String} pub the pub to be checked
258
+ * @returns {Boolean} is it valid?
1439
259
  */
1440
- async recoveryBlockchainExplorerQuery(query) {
1441
- const token = sdk_core_1.common.Environments[this.bitgo.getEnv()].etherscanApiToken;
1442
- if (token) {
1443
- query.apikey = token;
1444
- }
1445
- const response = await superagent_1.default.get(sdk_core_1.common.Environments[this.bitgo.getEnv()].etherscanBaseUrl + '/api').query(query);
1446
- if (!response.ok) {
1447
- throw new Error('could not reach Etherscan');
260
+ isValidPub(pub) {
261
+ try {
262
+ return secp256k1_1.bip32.fromBase58(pub).isNeutered();
1448
263
  }
1449
- if (response.body.status === '0' && response.body.message === 'NOTOK') {
1450
- throw new Error('Etherscan rate limit reached');
264
+ catch (e) {
265
+ return false;
1451
266
  }
1452
- return response.body;
1453
267
  }
1454
268
  /**
1455
- * Creates the extra parameters needed to build a hop transaction
1456
- * @param buildParams The original build parameters
1457
- * @returns extra parameters object to merge with the original build parameters object and send to the platform
269
+ * Helper function for signTransaction for the rare case that SDK is doing the second signature
270
+ * Note: we are expecting this to be called from the offline vault
271
+ * @param params.txPrebuild
272
+ * @param params.signingKeyNonce
273
+ * @param params.walletContractAddress
274
+ * @param params.prv
275
+ * @returns {{txHex: *}}
1458
276
  */
1459
- async createHopTransactionParams(buildParams) {
1460
- const wallet = buildParams.wallet;
1461
- const recipients = buildParams.recipients;
1462
- const walletPassphrase = buildParams.walletPassphrase;
1463
- const userKeychain = await this.keychains().get({ id: wallet.keyIds()[0] });
1464
- const userPrv = wallet.getUserPrv({ keychain: userKeychain, walletPassphrase });
1465
- const userPrvBuffer = utxo_lib_1.bip32.fromBase58(userPrv).privateKey;
1466
- if (!userPrvBuffer) {
1467
- throw new Error('invalid userPrv');
277
+ signFinal(params) {
278
+ const txPrebuild = params.txPrebuild;
279
+ if (!lodash_1.default.isNumber(params.signingKeyNonce) && !lodash_1.default.isNumber(params.txPrebuild.halfSigned?.backupKeyNonce)) {
280
+ throw new Error('must have at least one of signingKeyNonce and backupKeyNonce as a parameter, and it must be a number');
281
+ }
282
+ if (lodash_1.default.isUndefined(params.walletContractAddress)) {
283
+ throw new Error('params must include walletContractAddress, but got undefined');
1468
284
  }
1469
- if (!recipients || !Array.isArray(recipients)) {
1470
- throw new Error('expecting array of recipients');
285
+ const signingNode = secp256k1_1.bip32.fromBase58(params.prv);
286
+ const signingKey = signingNode.privateKey;
287
+ if (lodash_1.default.isUndefined(signingKey)) {
288
+ throw new Error('missing private key');
1471
289
  }
1472
- // Right now we only support 1 recipient
1473
- if (recipients.length !== 1) {
1474
- throw new Error('must send to exactly 1 recipient');
290
+ let recipient;
291
+ let txInfo;
292
+ if (txPrebuild.recipients) {
293
+ recipient = txPrebuild.recipients[0];
294
+ txInfo = {
295
+ recipient,
296
+ expireTime: txPrebuild.halfSigned?.expireTime,
297
+ contractSequenceId: txPrebuild.halfSigned?.contractSequenceId,
298
+ signature: txPrebuild.halfSigned?.signature,
299
+ };
1475
300
  }
1476
- const recipientAddress = recipients[0].address;
1477
- const recipientAmount = recipients[0].amount;
1478
- const feeEstimateParams = {
1479
- recipient: recipientAddress,
1480
- amount: recipientAmount,
1481
- hop: true,
1482
- };
1483
- const feeEstimate = await this.feeEstimate(feeEstimateParams);
1484
- const gasLimit = feeEstimate.gasLimitEstimate;
1485
- const gasPrice = Math.round(feeEstimate.feeEstimate / gasLimit);
1486
- const gasPriceMax = gasPrice * 5;
1487
- // Payment id a random number so its different for every tx
1488
- const paymentId = Math.floor(Math.random() * 10000000000).toString();
1489
- const hopDigest = Eth.getHopDigest([
1490
- recipientAddress,
1491
- recipientAmount,
1492
- gasPriceMax.toString(),
1493
- gasLimit.toString(),
1494
- paymentId,
1495
- ]);
1496
- const userReqSig = exports.optionalDeps.ethUtil.addHexPrefix(Buffer.from(secp256k1_1.default.ecdsaSign(hopDigest, userPrvBuffer).signature).toString('hex'));
1497
- return {
1498
- hopParams: {
1499
- gasPriceMax,
1500
- userReqSig,
1501
- paymentId,
1502
- },
1503
- gasLimit,
301
+ const sendMethodArgs = this.getSendMethodArgs(txInfo);
302
+ const methodSignature = abstract_eth_1.optionalDeps.ethAbi.methodID(this.sendMethodName, lodash_1.default.map(sendMethodArgs, 'type'));
303
+ const encodedArgs = abstract_eth_1.optionalDeps.ethAbi.rawEncode(lodash_1.default.map(sendMethodArgs, 'type'), lodash_1.default.map(sendMethodArgs, 'value'));
304
+ const sendData = Buffer.concat([methodSignature, encodedArgs]);
305
+ const ethTxParams = {
306
+ to: params.walletContractAddress,
307
+ nonce: params.signingKeyNonce !== undefined ? params.signingKeyNonce : params.txPrebuild.halfSigned?.backupKeyNonce,
308
+ value: 0,
309
+ gasPrice: new abstract_eth_1.optionalDeps.ethUtil.BN(txPrebuild.gasPrice),
310
+ gasLimit: new abstract_eth_1.optionalDeps.ethUtil.BN(txPrebuild.gasLimit),
311
+ data: sendData,
1504
312
  };
313
+ const unsignedEthTx = Eth.buildTransaction({
314
+ ...ethTxParams,
315
+ eip1559: params.txPrebuild.eip1559,
316
+ replayProtectionOptions: params.txPrebuild.replayProtectionOptions,
317
+ });
318
+ const ethTx = unsignedEthTx.sign(signingKey);
319
+ return { txHex: ethTx.serialize().toString('hex') };
1505
320
  }
1506
321
  /**
1507
- * Validates that the hop prebuild from the HSM is valid and correct
1508
- * @param wallet The wallet that the prebuild is for
1509
- * @param hopPrebuild The prebuild to validate
1510
- * @param originalParams The original parameters passed to prebuildTransaction
1511
- * @returns void
1512
- * @throws Error if The prebuild is invalid
322
+ * Assemble keychain and half-sign prebuilt transaction
323
+ * @param params
324
+ * - txPrebuild
325
+ * - prv
326
+ * @returns {Promise<SignedTransaction>}
1513
327
  */
1514
- async validateHopPrebuild(wallet, hopPrebuild, originalParams) {
1515
- const { tx, id, signature } = hopPrebuild;
1516
- // first, validate the HSM signature
1517
- const serverXpub = sdk_core_1.common.Environments[this.bitgo.getEnv()].hsmXpub;
1518
- const serverPubkeyBuffer = utxo_lib_1.bip32.fromBase58(serverXpub).publicKey;
1519
- const signatureBuffer = Buffer.from(exports.optionalDeps.ethUtil.stripHexPrefix(signature), 'hex');
1520
- const messageBuffer = Buffer.from(exports.optionalDeps.ethUtil.padToEven(exports.optionalDeps.ethUtil.stripHexPrefix(id)), 'hex');
1521
- const sig = new Uint8Array(signatureBuffer.slice(1));
1522
- const isValidSignature = secp256k1_1.default.ecdsaVerify(sig, messageBuffer, serverPubkeyBuffer);
1523
- if (!isValidSignature) {
1524
- throw new Error(`Hop txid signature invalid - pub: ${serverXpub}, msg: ${messageBuffer === null || messageBuffer === void 0 ? void 0 : messageBuffer.toString()}, sig: ${signatureBuffer === null || signatureBuffer === void 0 ? void 0 : signatureBuffer.toString()}`);
328
+ async signTransaction(params) {
329
+ if (params.isEvmBasedCrossChainRecovery) {
330
+ return super.signTransaction(params);
1525
331
  }
1526
- const builtHopTx = exports.optionalDeps.EthTx.TransactionFactory.fromSerializedData(exports.optionalDeps.ethUtil.toBuffer(tx));
1527
- // If original params are given, we can check them against the transaction prebuild params
1528
- if (!lodash_1.default.isNil(originalParams)) {
1529
- const { recipients } = originalParams;
1530
- // Then validate that the tx params actually equal the requested params
1531
- const originalAmount = new bignumber_js_1.BigNumber(recipients[0].amount);
1532
- const originalDestination = recipients[0].address;
1533
- const hopAmount = new bignumber_js_1.BigNumber(exports.optionalDeps.ethUtil.bufferToHex(builtHopTx.value));
1534
- if (!builtHopTx.to) {
1535
- throw new Error(`Transaction does not have a destination address`);
1536
- }
1537
- const hopDestination = builtHopTx.to.toString();
1538
- if (!hopAmount.eq(originalAmount)) {
1539
- throw new Error(`Hop amount: ${hopAmount} does not equal original amount: ${originalAmount}`);
332
+ const txPrebuild = params.txPrebuild;
333
+ const userPrv = params.prv;
334
+ const EXPIRETIME_DEFAULT = 60 * 60 * 24 * 7; // This signature will be valid for 1 week
335
+ if (lodash_1.default.isUndefined(txPrebuild) || !lodash_1.default.isObject(txPrebuild)) {
336
+ if (!lodash_1.default.isUndefined(txPrebuild) && !lodash_1.default.isObject(txPrebuild)) {
337
+ throw new Error(`txPrebuild must be an object, got type ${typeof txPrebuild}`);
1540
338
  }
1541
- if (hopDestination.toLowerCase() !== originalDestination.toLowerCase()) {
1542
- throw new Error(`Hop destination: ${hopDestination} does not equal original recipient: ${hopDestination}`);
339
+ throw new Error('missing txPrebuild parameter');
340
+ }
341
+ if (lodash_1.default.isUndefined(userPrv) || !lodash_1.default.isString(userPrv)) {
342
+ if (!lodash_1.default.isUndefined(userPrv) && !lodash_1.default.isString(userPrv)) {
343
+ throw new Error(`prv must be a string, got type ${typeof userPrv}`);
1543
344
  }
345
+ throw new Error('missing prv parameter to sign transaction');
1544
346
  }
1545
- if (!builtHopTx.verifySignature()) {
1546
- // We dont want to continue at all in this case, at risk of ETH being stuck on the hop address
1547
- throw new Error(`Invalid hop transaction signature, txid: ${id}`);
347
+ params.recipients = txPrebuild.recipients || params.recipients;
348
+ // if no recipients in either params or txPrebuild, then throw an error
349
+ if (!params.recipients || !Array.isArray(params.recipients)) {
350
+ throw new Error('recipients missing or not array');
1548
351
  }
1549
- if (exports.optionalDeps.ethUtil.addHexPrefix(builtHopTx.hash().toString('hex')) !== id) {
1550
- throw new Error(`Signed hop txid does not equal actual txid`);
352
+ if (params.recipients.length == 0) {
353
+ throw new Error('recipients empty');
1551
354
  }
1552
- }
1553
- /**
1554
- * Gets the hop digest for the user to sign. This is validated in the HSM to prove that the user requested this tx
1555
- * @param paramsArr The parameters to hash together for the digest
1556
- */
1557
- static getHopDigest(paramsArr) {
1558
- const hash = keccak_1.default('keccak256');
1559
- hash.update([Eth.hopTransactionSalt, ...paramsArr].join('$'));
1560
- return hash.digest();
355
+ // Normally the SDK provides the first signature for an ETH tx, but occasionally it provides the second and final one.
356
+ if (params.isLastSignature) {
357
+ // In this case when we're doing the second (final) signature, the logic is different.
358
+ return this.signFinal(params);
359
+ }
360
+ const secondsSinceEpoch = Math.floor(new Date().getTime() / 1000);
361
+ const expireTime = params.expireTime || secondsSinceEpoch + EXPIRETIME_DEFAULT;
362
+ const sequenceId = txPrebuild.nextContractSequenceId;
363
+ if (lodash_1.default.isUndefined(sequenceId)) {
364
+ throw new Error('transaction prebuild missing required property nextContractSequenceId');
365
+ }
366
+ const operationHash = this.getOperationSha3ForExecuteAndConfirm(params.recipients, expireTime, sequenceId);
367
+ const signature = sdk_core_1.Util.ethSignMsgHash(operationHash, sdk_core_1.Util.xprvToEthPrivateKey(userPrv));
368
+ const txParams = {
369
+ eip1559: params.txPrebuild.eip1559,
370
+ isBatch: params.txPrebuild.isBatch,
371
+ recipients: params.recipients,
372
+ expireTime: expireTime,
373
+ contractSequenceId: sequenceId,
374
+ sequenceId: params.sequenceId,
375
+ operationHash: operationHash,
376
+ signature: signature,
377
+ gasLimit: params.gasLimit,
378
+ gasPrice: params.gasPrice,
379
+ hopTransaction: txPrebuild.hopTransaction,
380
+ backupKeyNonce: txPrebuild.backupKeyNonce,
381
+ custodianTransactionId: params.custodianTransactionId,
382
+ };
383
+ return { halfSigned: txParams };
1561
384
  }
1562
385
  /**
1563
386
  * Modify prebuild before sending it to the server. Add things like hop transaction params
@@ -1585,216 +408,11 @@ class Eth extends sdk_core_1.BaseCoin {
1585
408
  return {};
1586
409
  }
1587
410
  /**
1588
- * Modify prebuild after receiving it from the server. Add things like nlocktime
1589
- */
1590
- async postProcessPrebuild(params) {
1591
- if (!lodash_1.default.isUndefined(params.hopTransaction) && !lodash_1.default.isUndefined(params.wallet) && !lodash_1.default.isUndefined(params.buildParams)) {
1592
- await this.validateHopPrebuild(params.wallet, params.hopTransaction, params.buildParams);
1593
- }
1594
- return params;
1595
- }
1596
- /**
1597
- * Coin-specific things done before signing a transaction, i.e. verification
1598
- * @param params
1599
- */
1600
- async presignTransaction(params) {
1601
- if (!lodash_1.default.isUndefined(params.hopTransaction) && !lodash_1.default.isUndefined(params.wallet) && !lodash_1.default.isUndefined(params.buildParams)) {
1602
- await this.validateHopPrebuild(params.wallet, params.hopTransaction);
1603
- }
1604
- return params;
1605
- }
1606
- /**
1607
- * Fetch fee estimate information from the server
1608
- * @param {Object} params The params passed into the function
1609
- * @param {Boolean} [params.hop] True if we should estimate fee for a hop transaction
1610
- * @param {String} [params.recipient] The recipient of the transaction to estimate a send to
1611
- * @param {String} [params.data] The ETH tx data to estimate a send for
1612
- * @returns {Object} The fee info returned from the server
1613
- */
1614
- async feeEstimate(params) {
1615
- const query = {};
1616
- if (params && params.hop) {
1617
- query.hop = params.hop;
1618
- }
1619
- if (params && params.recipient) {
1620
- query.recipient = params.recipient;
1621
- }
1622
- if (params && params.data) {
1623
- query.data = params.data;
1624
- }
1625
- if (params && params.amount) {
1626
- query.amount = params.amount;
1627
- }
1628
- return await this.bitgo.get(this.url('/tx/fee')).query(query).result();
1629
- }
1630
- /**
1631
- * Generate secp256k1 key pair
1632
- *
1633
- * @param seed
1634
- * @returns {Object} object with generated pub and prv
1635
- */
1636
- generateKeyPair(seed) {
1637
- if (!seed) {
1638
- // An extended private key has both a normal 256 bit private key and a 256
1639
- // bit chain code, both of which must be random. 512 bits is therefore the
1640
- // maximum entropy and gives us maximum security against cracking.
1641
- seed = crypto_1.randomBytes(512 / 8);
1642
- }
1643
- const extendedKey = utxo_lib_1.bip32.fromSeed(seed);
1644
- const xpub = extendedKey.neutered().toBase58();
1645
- return {
1646
- pub: xpub,
1647
- prv: extendedKey.toBase58(),
1648
- };
1649
- }
1650
- async parseTransaction(params) {
1651
- return {};
1652
- }
1653
- /**
1654
- * Make sure an address is a wallet address and throw an error if it's not.
1655
- * @param {Object} params
1656
- * @param {String} params.address The derived address string on the network
1657
- * @param {Object} params.coinSpecific Coin-specific details for the address such as a forwarderVersion
1658
- * @param {String} params.baseAddress The base address of the wallet on the network
1659
- * @throws {InvalidAddressError}
1660
- * @throws {InvalidAddressVerificationObjectPropertyError}
1661
- * @throws {UnexpectedAddressError}
1662
- * @returns {Boolean} True iff address is a wallet address
1663
- */
1664
- async isWalletAddress(params) {
1665
- const ethUtil = exports.optionalDeps.ethUtil;
1666
- let expectedAddress;
1667
- let actualAddress;
1668
- const { address, coinSpecific, baseAddress, impliedForwarderVersion = coinSpecific === null || coinSpecific === void 0 ? void 0 : coinSpecific.forwarderVersion } = params;
1669
- if (address && !this.isValidAddress(address)) {
1670
- throw new sdk_core_1.InvalidAddressError(`invalid address: ${address}`);
1671
- }
1672
- // base address is required to calculate the salt which is used in calculateForwarderV1Address method
1673
- if (lodash_1.default.isUndefined(baseAddress) || !this.isValidAddress(baseAddress)) {
1674
- throw new sdk_core_1.InvalidAddressError('invalid base address');
1675
- }
1676
- if (!lodash_1.default.isObject(coinSpecific)) {
1677
- throw new sdk_core_1.InvalidAddressVerificationObjectPropertyError('address validation failure: coinSpecific field must be an object');
1678
- }
1679
- if (impliedForwarderVersion === 0 || impliedForwarderVersion === 3) {
1680
- return true;
1681
- }
1682
- else {
1683
- const ethNetwork = this.getNetwork();
1684
- const forwarderFactoryAddress = ethNetwork === null || ethNetwork === void 0 ? void 0 : ethNetwork.forwarderFactoryAddress;
1685
- const forwarderImplementationAddress = ethNetwork === null || ethNetwork === void 0 ? void 0 : ethNetwork.forwarderImplementationAddress;
1686
- const initcode = lib_1.getProxyInitcode(forwarderImplementationAddress);
1687
- const saltBuffer = ethUtil.setLengthLeft(Buffer.from(ethUtil.padToEven(ethUtil.stripHexPrefix(coinSpecific.salt || '')), 'hex'), 32);
1688
- // Hash the wallet base address with the given salt, so the address directly relies on the base address
1689
- const calculationSalt = exports.optionalDeps.ethUtil.bufferToHex(exports.optionalDeps.ethAbi.soliditySHA3(['address', 'bytes32'], [baseAddress, saltBuffer]));
1690
- expectedAddress = lib_1.calculateForwarderV1Address(forwarderFactoryAddress, calculationSalt, initcode);
1691
- actualAddress = address;
1692
- }
1693
- if (expectedAddress !== actualAddress) {
1694
- throw new sdk_core_1.UnexpectedAddressError(`address validation failure: expected ${expectedAddress} but got ${address}`);
1695
- }
1696
- return true;
1697
- }
1698
- verifyCoin(txPrebuild) {
1699
- return txPrebuild.coin === this.getChain();
1700
- }
1701
- verifyTssTransaction(params) {
1702
- var _a;
1703
- const { txParams, txPrebuild, wallet } = params;
1704
- if (!(txParams === null || txParams === void 0 ? void 0 : txParams.recipients) &&
1705
- !(((_a = txParams.prebuildTx) === null || _a === void 0 ? void 0 : _a.consolidateId) ||
1706
- (txParams.type && ['acceleration', 'fillNonce', 'transferToken'].includes(txParams.type)))) {
1707
- throw new Error(`missing txParams`);
1708
- }
1709
- if (!wallet || !txPrebuild) {
1710
- throw new Error(`missing params`);
1711
- }
1712
- if (txParams.hop && txParams.recipients && txParams.recipients.length > 1) {
1713
- throw new Error(`tx cannot be both a batch and hop transaction`);
1714
- }
1715
- return true;
1716
- }
1717
- /**
1718
- * Verify that a transaction prebuild complies with the original intention
1719
- *
1720
- * @param params
1721
- * @param params.txParams params object passed to send
1722
- * @param params.txPrebuild prebuild object returned by server
1723
- * @param params.wallet Wallet object to obtain keys to verify against
1724
- * @returns {boolean}
411
+ * Create a new transaction builder for the current chain
412
+ * @return a new transaction builder
1725
413
  */
1726
- async verifyTransaction(params) {
1727
- const ethNetwork = this.getNetwork();
1728
- const { txParams, txPrebuild, wallet, walletType } = params;
1729
- if (walletType === 'tss') {
1730
- return this.verifyTssTransaction(params);
1731
- }
1732
- if (!(txParams === null || txParams === void 0 ? void 0 : txParams.recipients) || !(txPrebuild === null || txPrebuild === void 0 ? void 0 : txPrebuild.recipients) || !wallet) {
1733
- throw new Error(`missing params`);
1734
- }
1735
- if (txParams.hop && txParams.recipients.length > 1) {
1736
- throw new Error(`tx cannot be both a batch and hop transaction`);
1737
- }
1738
- if (txPrebuild.recipients.length !== 1) {
1739
- throw new Error(`txPrebuild should only have 1 recipient but ${txPrebuild.recipients.length} found`);
1740
- }
1741
- if (txParams.hop && txPrebuild.hopTransaction) {
1742
- // Check recipient amount for hop transaction
1743
- if (txParams.recipients.length !== 1) {
1744
- throw new Error(`hop transaction only supports 1 recipient but ${txParams.recipients.length} found`);
1745
- }
1746
- // Check tx sends to hop address
1747
- const decodedHopTx = exports.optionalDeps.EthTx.TransactionFactory.fromSerializedData(exports.optionalDeps.ethUtil.toBuffer(txPrebuild.hopTransaction.tx));
1748
- const expectedHopAddress = exports.optionalDeps.ethUtil.stripHexPrefix(decodedHopTx.getSenderAddress().toString());
1749
- const actualHopAddress = exports.optionalDeps.ethUtil.stripHexPrefix(txPrebuild.recipients[0].address);
1750
- if (expectedHopAddress.toLowerCase() !== actualHopAddress.toLowerCase()) {
1751
- throw new Error('recipient address of txPrebuild does not match hop address');
1752
- }
1753
- // Convert TransactionRecipient array to Recipient array
1754
- const recipients = txParams.recipients.map((r) => {
1755
- return {
1756
- address: r.address,
1757
- amount: typeof r.amount === 'number' ? r.amount.toString() : r.amount,
1758
- };
1759
- });
1760
- // Check destination address and amount
1761
- await this.validateHopPrebuild(wallet, txPrebuild.hopTransaction, { recipients });
1762
- }
1763
- else if (txParams.recipients.length > 1) {
1764
- // Check total amount for batch transaction
1765
- let expectedTotalAmount = new bignumber_js_1.BigNumber(0);
1766
- for (let i = 0; i < txParams.recipients.length; i++) {
1767
- expectedTotalAmount = expectedTotalAmount.plus(txParams.recipients[i].amount);
1768
- }
1769
- if (!expectedTotalAmount.isEqualTo(txPrebuild.recipients[0].amount)) {
1770
- throw new Error('batch transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client');
1771
- }
1772
- // Check batch transaction is sent to the batcher contract address for the chain
1773
- const batcherContractAddress = ethNetwork === null || ethNetwork === void 0 ? void 0 : ethNetwork.batcherContractAddress;
1774
- if (!batcherContractAddress ||
1775
- batcherContractAddress.toLowerCase() !== txPrebuild.recipients[0].address.toLowerCase()) {
1776
- throw new Error('recipient address of txPrebuild does not match batcher address');
1777
- }
1778
- }
1779
- else {
1780
- // Check recipient address and amount for normal transaction
1781
- if (txParams.recipients.length !== 1) {
1782
- throw new Error(`normal transaction only supports 1 recipient but ${txParams.recipients.length} found`);
1783
- }
1784
- const expectedAmount = new bignumber_js_1.BigNumber(txParams.recipients[0].amount);
1785
- if (!expectedAmount.isEqualTo(txPrebuild.recipients[0].amount)) {
1786
- throw new Error('normal transaction amount in txPrebuild received from BitGo servers does not match txParams supplied by client');
1787
- }
1788
- if (this.isETHAddress(txParams.recipients[0].address) &&
1789
- txParams.recipients[0].address !== txPrebuild.recipients[0].address) {
1790
- throw new Error('destination address in normal txPrebuild does not match that in txParams supplied by client');
1791
- }
1792
- }
1793
- // Check coin is correct for all transaction types
1794
- if (!this.verifyCoin(txPrebuild)) {
1795
- throw new Error(`coin in txPrebuild did not match that in txParams supplied by client`);
1796
- }
1797
- return true;
414
+ getTransactionBuilder() {
415
+ return new lib_1.TransactionBuilder(statics_1.coins.get(this.getBaseChain()));
1798
416
  }
1799
417
  /** @inheritDoc */
1800
418
  supportsMessageSigning() {
@@ -1804,39 +422,6 @@ class Eth extends sdk_core_1.BaseCoin {
1804
422
  supportsSigningTypedData() {
1805
423
  return true;
1806
424
  }
1807
- /**
1808
- * Transform message to accommodate specific blockchain requirements.
1809
- * @param message the message to prepare
1810
- * @return string the prepared message.
1811
- */
1812
- encodeMessage(message) {
1813
- const prefix = `\u0019Ethereum Signed Message:\n${message.length}`;
1814
- return prefix.concat(message);
1815
- }
1816
- /**
1817
- * Transform the Typed data to accomodate the blockchain requirements (EIP-712)
1818
- * @param typedData the typed data to prepare
1819
- * @return a buffer of the result
1820
- */
1821
- encodeTypedData(typedData) {
1822
- const version = typedData.version;
1823
- if (version === eth_sig_util_1.SignTypedDataVersion.V1) {
1824
- throw new Error('SignTypedData v1 is not supported due to security concerns');
1825
- }
1826
- const typedDataRaw = JSON.parse(typedData.typedDataRaw);
1827
- const sanitizedData = eth_sig_util_1.TypedDataUtils.sanitizeData(typedDataRaw);
1828
- const parts = [Buffer.from('1901', 'hex')];
1829
- const eip712Domain = 'EIP712Domain';
1830
- parts.push(eth_sig_util_1.TypedDataUtils.hashStruct(eip712Domain, sanitizedData.domain, sanitizedData.types, version));
1831
- if (sanitizedData.primaryType !== eip712Domain) {
1832
- parts.push(eth_sig_util_1.TypedDataUtils.hashStruct(sanitizedData.primaryType, sanitizedData.message, sanitizedData.types, version));
1833
- }
1834
- return Buffer.concat(parts);
1835
- }
1836
- isETHAddress(address) {
1837
- return !!address.match(/0x[a-fA-F0-9]{40}/);
1838
- }
1839
425
  }
1840
426
  exports.Eth = Eth;
1841
- Eth.hopTransactionSalt = 'bitgoHopAddressRequestSalt';
1842
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2V0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTs7R0FFRztBQUNILG1EQUE2QztBQUM3QywrQ0FBeUM7QUFDekMsbUNBQXFDO0FBQ3JDLGtEQUE2QjtBQUM3QixvREFBNEI7QUFDNUIsb0RBQXVCO0FBQ3ZCLDBEQUFrQztBQUNsQyw0REFBaUM7QUFFakMsNkNBQTBDO0FBQzFDLG1EQW9DOEI7QUFDOUIseURBQTBGO0FBRTFGLGlEQUF5RztBQUV6Ryx1Q0FBK0Y7QUFFL0YsK0JBT2U7QUFDZixxREFBK0Q7QUFDL0Qsa0RBQXVCO0FBQ3ZCLHlEQUE0RjtBQUk1RixNQUFNLEtBQUssR0FBRyxlQUFRLENBQUMsY0FBYyxDQUFDLENBQUM7QUFFMUIsUUFBQSxZQUFZLEdBQUc7SUFDMUIsSUFBSSxNQUFNO1FBQ1IsSUFBSTtZQUNGLE9BQU8sT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7U0FDbEM7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLEtBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1lBQ3hDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDZixNQUFNLElBQUksMENBQStCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztTQUM3RDtJQUNILENBQUM7SUFFRCxJQUFJLE9BQU87UUFDVCxJQUFJO1lBQ0YsT0FBTyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztTQUNuQztRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsS0FBSyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7WUFDekMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNmLE1BQU0sSUFBSSwwQ0FBK0IsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1NBQzlEO0lBQ0gsQ0FBQztJQUVELElBQUksS0FBSztRQUNQLElBQUk7WUFDRixPQUFPLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FB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YSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBRXhHLElBQUksYUFBYSxDQUFDLFdBQVcsS0FBSyxZQUFZLEVBQUU7WUFDOUMsS0FBSyxDQUFDLElBQUksQ0FDUiw2QkFBYyxDQUFDLFVBQVUsQ0FDdkIsYUFBYSxDQUFDLFdBQXFCLEVBQ25DLGFBQWEsQ0FBQyxPQUFPLEVBQ3JCLGFBQWEsQ0FBQyxLQUFLLEVBQ25CLE9BQU8sQ0FDUixDQUNGLENBQUM7U0FDSDtRQUNELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRU8sWUFBWSxDQUFDLE9BQWU7UUFDbEMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0lBQzlDLENBQUM7O0FBM3BFSCxrQkE0cEVDO0FBM3BFUSxzQkFBa0IsR0FBRyw0QkFBNEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHByZXR0aWVyXG4gKi9cbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvLWJldGEvdXR4by1saWInO1xuaW1wb3J0IHsgQmlnTnVtYmVyIH0gZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IHJhbmRvbUJ5dGVzIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCBkZWJ1Z0xpYiBmcm9tICdkZWJ1Zyc7XG5pbXBvcnQgS2VjY2FrIGZyb20gJ2tlY2Nhayc7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHNlY3AyNTZrMSBmcm9tICdzZWNwMjU2azEnO1xuaW1wb3J0IHJlcXVlc3QgZnJvbSAnc3VwZXJhZ2VudCc7XG5cbmltcG9ydCB7IEVyYzIwVG9rZW4gfSBmcm9tICcuL2VyYzIwVG9rZW4nO1xuaW1wb3J0IHtcbiAgQWRkcmVzc0NvaW5TcGVjaWZpYyxcbiAgQmFzZUNvaW4sXG4gIEJpdEdvQmFzZSxcbiAgY2hlY2tLcnNQcm92aWRlcixcbiAgY29tbW9uLFxuICBFQ0RTQSxcbiAgRWNkc2EsXG4gIEVDRFNBTWV0aG9kVHlwZXMsXG4gIEV0aGVyZXVtTGlicmFyeVVuYXZhaWxhYmxlRXJyb3IsXG4gIEZlZUVzdGltYXRlT3B0aW9ucyxcbiAgRnVsbHlTaWduZWRUcmFuc2FjdGlvbixcbiAgZ2V0SXNLcnNSZWNvdmVyeSxcbiAgZ2V0SXNVbnNpZ25lZFN3ZWVwLFxuICBIYWxmU2lnbmVkVHJhbnNhY3Rpb24sXG4gIGhleFRvQmlnSW50LFxuICBJbnZhbGlkQWRkcmVzc0Vycm9yLFxuICBJbnZhbGlkQWRkcmVzc1ZlcmlmaWNhdGlvbk9iamVjdFByb3BlcnR5RXJyb3IsXG4gIElXYWxsZXQsXG4gIEtleVBhaXIsXG4gIE1QQ0FsZ29yaXRobSxcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBQcmVidWlsZFRyYW5zYWN0aW9uUmVzdWx0LFxuICBQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zIGFzIEJhc2VQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBSZWNpcGllbnQsXG4gIFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMgYXMgQmFzZVNpZ25UcmFuc2FjdGlvbk9wdGlvbnMsXG4gIFRyYW5zYWN0aW9uUGFyYW1zLFxuICBUcmFuc2FjdGlvblByZWJ1aWxkIGFzIEJhc2VUcmFuc2FjdGlvblByZWJ1aWxkLFxuICBUcmFuc2FjdGlvblJlY2lwaWVudCxcbiAgVHlwZWREYXRhLFxuICBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yLFxuICBVdGlsLFxuICBWZXJpZnlBZGRyZXNzT3B0aW9ucyBhcyBCYXNlVmVyaWZ5QWRkcmVzc09wdGlvbnMsXG4gIFZlcmlmeVRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgV2FsbGV0LFxufSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgeyBFY2RzYVBhaWxsaWVyUHJvb2YsIEVjZHNhUmFuZ2VQcm9vZiwgRWNkc2FUeXBlcyB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1saWItbXBjJztcblxuaW1wb3J0IHsgQmFzZUNvaW4gYXMgU3RhdGljc0Jhc2VDb2luLCBjb2lucywgRXRoZXJldW1OZXR3b3JrLCBldGhHYXNDb25maWdzIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgdHlwZSAqIGFzIEV0aFR4TGliIGZyb20gJ0BldGhlcmV1bWpzL3R4JztcbmltcG9ydCB7IEZlZU1hcmtldEVJUDE1NTlUcmFuc2FjdGlvbiwgVHJhbnNhY3Rpb24gYXMgTGVnYWN5VHJhbnNhY3Rpb24gfSBmcm9tICdAZXRoZXJldW1qcy90eCc7XG5pbXBvcnQgdHlwZSAqIGFzIEV0aENvbW1vbiBmcm9tICdAZXRoZXJldW1qcy9jb21tb24nO1xuaW1wb3J0IHtcbiAgY2FsY3VsYXRlRm9yd2FyZGVyVjFBZGRyZXNzLFxuICBnZXRQcm94eUluaXRjb2RlLFxuICBnZXRUb2tlbixcbiAgS2V5UGFpciBhcyBLZXlQYWlyTGliLFxuICBUcmFuc2FjdGlvbkJ1aWxkZXIsXG4gIFRyYW5zZmVyQnVpbGRlcixcbn0gZnJvbSAnLi9saWInO1xuaW1wb3J0IHsgYWRkSGV4UHJlZml4LCBzdHJpcEhleFByZWZpeCB9IGZyb20gJ2V0aGVyZXVtanMtdXRpbCc7XG5pbXBvcnQgQk4gZnJvbSAnYm4uanMnO1xuaW1wb3J0IHsgU2lnblR5cGVkRGF0YVZlcnNpb24sIFR5cGVkRGF0YVV0aWxzLCBUeXBlZE1lc3NhZ2UgfSBmcm9tICdAbWV0YW1hc2svZXRoLXNpZy11dGlsJztcblxuZXhwb3J0IHsgUmVjaXBpZW50LCBIYWxmU2lnbmVkVHJhbnNhY3Rpb24sIEZ1bGx5U2lnbmVkVHJhbnNhY3Rpb24gfTtcblxuY29uc3QgZGVidWcgPSBkZWJ1Z0xpYignYml0Z286djI6ZXRoJyk7XG5cbmV4cG9ydCBjb25zdCBvcHRpb25hbERlcHMgPSB7XG4gIGdldCBldGhBYmkoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiByZXF1aXJlKCdldGhlcmV1bWpzLWFiaScpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGRlYnVnKCd1bmFibGUgdG8gbG9hZCBldGhlcmV1bWpzLWFiaTonKTtcbiAgICAgIGRlYnVnKGUuc3RhY2spO1xuICAgICAgdGhyb3cgbmV3IEV0aGVyZXVtTGlicmFyeVVuYXZhaWxhYmxlRXJyb3IoYGV0aGVyZXVtanMtYWJpYCk7XG4gICAgfVxuICB9LFxuXG4gIGdldCBldGhVdGlsKCkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gcmVxdWlyZSgnZXRoZXJldW1qcy11dGlsJyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZGVidWcoJ3VuYWJsZSB0byBsb2FkIGV0aGVyZXVtanMtdXRpbDonKTtcbiAgICAgIGRlYnVnKGUuc3RhY2spO1xuICAgICAgdGhyb3cgbmV3IEV0aGVyZXVtTGlicmFyeVVuYXZhaWxhYmxlRXJyb3IoYGV0aGVyZXVtanMtdXRpbGApO1xuICAgIH1cbiAgfSxcblxuICBnZXQgRXRoVHgoKTogdHlwZW9mIEV0aFR4TGliIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHJlcXVpcmUoJ0BldGhlcmV1bWpzL3R4Jyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZGVidWcoJ3VuYWJsZSB0byBsb2FkIEBldGhlcmV1bWpzL3R4Jyk7XG4gICAgICBkZWJ1ZyhlLnN0YWNrKTtcbiAgICAgIHRocm93IG5ldyBFdGhlcmV1bUxpYnJhcnlVbmF2YWlsYWJsZUVycm9yKGBAZXRoZXJldW1qcy90eGApO1xuICAgIH1cbiAgfSxcblxuICBnZXQgRXRoQ29tbW9uKCk6IHR5cGVvZiBFdGhDb21tb24ge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gcmVxdWlyZSgnQGV0aGVyZXVtanMvY29tbW9uJyk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZGVidWcoJ3VuYWJsZSB0byBsb2FkIEBldGhlcmV1bWpzL2NvbW1vbjonKTtcbiAgICAgIGRlYnVnKGUuc3RhY2spO1xuICAgICAgdGhyb3cgbmV3IEV0aGVyZXVtTGlicmFyeVVuYXZhaWxhYmxlRXJyb3IoYEBldGhlcmV1bWpzL2NvbW1vbmApO1xuICAgIH1cbiAgfSxcbn07XG5cbi8qKlxuICogVGhlIGV4dHJhIHBhcmFtZXRlcnMgdG8gc2VuZCB0byBwbGF0Zm9ybSBidWlsZCByb3V0ZSBmb3IgaG9wIHRyYW5zYWN0aW9uc1xuICovXG5pbnRlcmZhY2UgSG9wUGFyYW1zIHtcbiAgaG9wUGFyYW1zOiB7XG4gICAgZ2FzUHJpY2VNYXg6IG51bWJlcjtcbiAgICB1c2VyUmVxU2lnOiBzdHJpbmc7XG4gICAgcGF5bWVudElkOiBzdHJpbmc7XG4gIH07XG4gIGdhc0xpbWl0OiBudW1iZXI7XG59XG5cbi8qKlxuICogVGhlIHByZWJ1aWx0IGhvcCB0cmFuc2FjdGlvbiByZXR1cm5lZCBmcm9tIHRoZSBIU01cbiAqL1xuaW50ZXJmYWNlIEhvcFByZWJ1aWxkIHtcbiAgdHg6IHN0cmluZztcbiAgaWQ6IHN0cmluZztcbiAgc2lnbmF0dXJlOiBzdHJpbmc7XG4gIHBheW1lbnRJZDogc3RyaW5nO1xuICBnYXNQcmljZTogbnVtYmVyO1xuICBnYXNMaW1pdDogbnVtYmVyO1xuICBhbW91bnQ6IG51bWJlcjtcbiAgcmVjaXBpZW50OiBzdHJpbmc7XG4gIG5vbmNlOiBudW1iZXI7XG4gIHVzZXJSZXFTaWc6IHN0cmluZztcbiAgZ2FzUHJpY2VNYXg6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIEVJUDE1NTkge1xuICBtYXhQcmlvcml0eUZlZVBlckdhczogbnVtYmVyO1xuICBtYXhGZWVQZXJHYXM6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFJlcGxheVByb3RlY3Rpb25PcHRpb25zIHtcbiAgY2hhaW46IHN0cmluZyB8IG51bWJlcjtcbiAgaGFyZGZvcms6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTaWduRmluYWxPcHRpb25zIHtcbiAgdHhQcmVidWlsZDoge1xuICAgIGVpcDE1NTk/OiBFSVAxNTU5O1xuICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zPzogUmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM7XG4gICAgZ2FzUHJpY2U/OiBzdHJpbmc7XG4gICAgZ2FzTGltaXQ6IHN0cmluZztcbiAgICByZWNpcGllbnRzOiBSZWNpcGllbnRbXTtcbiAgICBoYWxmU2lnbmVkOiB7XG4gICAgICBleHBpcmVUaW1lOiBudW1iZXI7XG4gICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IG51bWJlcjtcbiAgICAgIGJhY2t1cEtleU5vbmNlPzogbnVtYmVyO1xuICAgICAgc2lnbmF0dXJlOiBzdHJpbmc7XG4gICAgICB0eEhleD86IHN0cmluZztcbiAgICB9O1xuICAgIG5leHRDb250cmFjdFNlcXVlbmNlSWQ/OiBudW1iZXI7XG4gICAgaG9wVHJhbnNhY3Rpb24/OiBzdHJpbmc7XG4gICAgYmFja3VwS2V5Tm9uY2U/OiBudW1iZXI7XG4gICAgaXNCYXRjaD86IGJvb2xlYW47XG4gICAgdHhIZXg/OiBzdHJpbmc7XG4gICAgZXhwaXJlVGltZT86IG51bWJlcjtcbiAgfTtcbiAgc2lnbmluZ0tleU5vbmNlOiBudW1iZXI7XG4gIHdhbGxldENvbnRyYWN0QWRkcmVzczogc3RyaW5nO1xuICBwcnY6IHN0cmluZztcbiAgcmVjaXBpZW50czogUmVjaXBpZW50W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnblRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIEJhc2VTaWduVHJhbnNhY3Rpb25PcHRpb25zLCBTaWduRmluYWxPcHRpb25zIHtcbiAgaXNMYXN0U2lnbmF0dXJlPzogYm9vbGVhbjtcbiAgZXhwaXJlVGltZTogbnVtYmVyO1xuICBzZXF1ZW5jZUlkOiBudW1iZXI7XG4gIGdhc0xpbWl0OiBudW1iZXI7XG4gIGdhc1ByaWNlOiBudW1iZXI7XG4gIGN1c3RvZGlhblRyYW5zYWN0aW9uSWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIFNpZ25lZFRyYW5zYWN0aW9uID0gSGFsZlNpZ25lZFRyYW5zYWN0aW9uIHwgRnVsbHlTaWduZWRUcmFuc2FjdGlvbjtcblxuZXhwb3J0IGludGVyZmFjZSBGZWVzVXNlZCB7XG4gIGdhc1ByaWNlOiBudW1iZXI7XG4gIGdhc0xpbWl0OiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBQcmVjcmVhdGVCaXRHb09wdGlvbnMge1xuICBlbnRlcnByaXNlPzogc3RyaW5nO1xuICBuZXdGZWVBZGRyZXNzPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE9mZmxpbmVWYXVsdFR4SW5mbyB7XG4gIG5leHRDb250cmFjdFNlcXVlbmNlSWQ/OiBzdHJpbmc7XG4gIGNvbnRyYWN0U2VxdWVuY2VJZD86IHN0cmluZztcbiAgdHg/OiBzdHJpbmc7XG4gIHR4SGV4Pzogc3RyaW5nO1xuICB1c2VyS2V5Pzogc3RyaW5nO1xuICBiYWNrdXBLZXk/OiBzdHJpbmc7XG4gIGNvaW46IHN0cmluZztcbiAgZ2FzUHJpY2U6IG51bWJlcjtcbiAgZ2FzTGltaXQ6IG51bWJlcjtcbiAgcmVjaXBpZW50czogUmVjaXBpZW50W107XG4gIHdhbGxldENvbnRyYWN0QWRkcmVzczogc3RyaW5nO1xuICBhbW91bnQ6IHN0cmluZztcbiAgYmFja3VwS2V5Tm9uY2U6IG51bWJlcjtcbiAgLy8gRm9yIEV0aCBTcGVjaWZpYyBDb2luc1xuICBlaXAxNTU5PzogRUlQMTU1OTtcbiAgcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM/OiBSZXBsYXlQcm90ZWN0aW9uT3B0aW9ucztcbiAgLy8gRm9yIEhvdCBXYWxsZXQgRXZtQmFzZWRDcm9zc0NoYWluUmVjb3ZlcnkgU3BlY2lmaWNcbiAgaGFsZlNpZ25lZD86IEhhbGZTaWduZWRUcmFuc2FjdGlvbjtcbiAgZmVlc1VzZWQ/OiBGZWVzVXNlZDtcbiAgaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeT86IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBVbmZvcm1hdHRlZFR4SW5mbyB7XG4gIHJlY2lwaWVudDogUmVjaXBpZW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY292ZXJPcHRpb25zIHtcbiAgdXNlcktleTogc3RyaW5nO1xuICBiYWNrdXBLZXk6IHN0cmluZztcbiAgd2FsbGV0UGFzc3BocmFzZT86IHN0cmluZztcbiAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBzdHJpbmc7IC8vIHVzZSB0aGlzIGFzIHdhbGxldEJhc2VBZGRyZXNzIGZvciBUU1NcbiAgcmVjb3ZlcnlEZXN0aW5hdGlvbjogc3RyaW5nO1xuICBrcnNQcm92aWRlcj86IHN0cmluZztcbiAgZ2FzUHJpY2U/OiBudW1iZXI7XG4gIGdhc0xpbWl0PzogbnVtYmVyO1xuICBlaXAxNTU5PzogRUlQMTU1OTtcbiAgcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM/OiBSZXBsYXlQcm90ZWN0aW9uT3B0aW9ucztcbiAgaXNUc3M/OiBib29sZWFuO1xuICBiaXRnb0ZlZUFkZHJlc3M/OiBzdHJpbmc7XG4gIGJpdGdvRGVzdGluYXRpb25BZGRyZXNzPzogc3RyaW5nO1xuICB0b2tlbkNvbnRyYWN0QWRkcmVzcz86IHN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgR2V0QmF0Y2hFeGVjdXRpb25JbmZvUlQgPSB7XG4gIHZhbHVlczogW3N0cmluZ1tdLCBzdHJpbmdbXV07XG4gIHRvdGFsQW1vdW50OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkVHJhbnNhY3Rpb25QYXJhbXMge1xuICB0bzogc3RyaW5nO1xuICBub25jZT86IG51bWJlcjtcbiAgdmFsdWU6IG51bWJlcjtcbiAgZGF0YT86IEJ1ZmZlcjtcbiAgZ2FzUHJpY2U/OiBudW1iZXI7XG4gIGdhc0xpbWl0PzogbnVtYmVyO1xuICBlaXAxNTU5PzogRUlQMTU1OTtcbiAgcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM/OiBSZXBsYXlQcm90ZWN0aW9uT3B0aW9ucztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZWNvdmVyeUluZm8ge1xuICBpZDogc3RyaW5nO1xuICB0eDogc3RyaW5nO1xuICBiYWNrdXBLZXk/OiBzdHJpbmc7XG4gIGNvaW4/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBSZWNvdmVyVG9rZW5PcHRpb25zIHtcbiAgdG9rZW5Db250cmFjdEFkZHJlc3M6IHN0cmluZztcbiAgd2FsbGV0OiBXYWxsZXQ7XG4gIHJlY2lwaWVudDogc3RyaW5nO1xuICBicm9hZGNhc3Q/OiBib29sZWFuO1xuICB3YWxsZXRQYXNzcGhyYXNlPzogc3RyaW5nO1xuICBwcnY/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0U2VuZE1ldGhvZEFyZ3NPcHRpb25zIHtcbiAgcmVjaXBpZW50OiBSZWNpcGllbnQ7XG4gIGV4cGlyZVRpbWU6IG51bWJlcjtcbiAgY29udHJhY3RTZXF1ZW5jZUlkOiBudW1iZXI7XG4gIHNpZ25hdHVyZTogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlbmRNZXRob2RBcmdzIHtcbiAgbmFtZTogc3RyaW5nO1xuICB0eXBlOiBzdHJpbmc7XG4gIHZhbHVlOiBhbnk7XG59XG5cbmludGVyZmFjZSBIb3BUcmFuc2FjdGlvbkJ1aWxkT3B0aW9ucyB7XG4gIHdhbGxldDogV2FsbGV0O1xuICByZWNpcGllbnRzOiBSZWNpcGllbnRbXTtcbiAgd2FsbGV0UGFzc3BocmFzZTogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgQnVpbGRPcHRpb25zIHtcbiAgaG9wPzogYm9vbGVhbjtcbiAgd2FsbGV0PzogV2FsbGV0O1xuICByZWNpcGllbnRzPzogUmVjaXBpZW50W107XG4gIHdhbGxldFBhc3NwaHJhc2U/OiBzdHJpbmc7XG4gIFtpbmRleDogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuaW50ZXJmYWNlIEZlZUVzdGltYXRlIHtcbiAgZ2FzTGltaXRFc3RpbWF0ZTogbnVtYmVyO1xuICBmZWVFc3RpbWF0ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyYW5zYWN0aW9uUHJlYnVpbGQgZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb25QcmVidWlsZCB7XG4gIGhvcFRyYW5zYWN0aW9uPzogSG9wUHJlYnVpbGQ7XG4gIGJ1aWxkUGFyYW1zOiB7XG4gICAgcmVjaXBpZW50czogUmVjaXBpZW50W107XG4gIH07XG4gIHJlY2lwaWVudHM6IFRyYW5zYWN0aW9uUmVjaXBpZW50W107XG4gIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IHN0cmluZztcbiAgZ2FzUHJpY2U6IG51bWJlcjtcbiAgZ2FzTGltaXQ6IG51bWJlcjtcbiAgaXNCYXRjaDogYm9vbGVhbjtcbiAgY29pbjogc3RyaW5nO1xuICB0b2tlbj86IHN0cmluZztcbn1cblxuLy8gVE9ETzogVGhpcyBpbnRlcmZhY2Ugd2lsbCBuZWVkIHRvIGJlIHVwZGF0ZWQgZm9yIHRoZSBuZXcgZmVlIG1vZGVsIGludHJvZHVjZWQgaW4gdGhlIExvbmRvbiBIYXJkIEZvcmtcbmludGVyZmFjZSBFdGhUcmFuc2FjdGlvblBhcmFtcyBleHRlbmRzIFRyYW5zYWN0aW9uUGFyYW1zIHtcbiAgZ2FzUHJpY2U/OiBudW1iZXI7XG4gIGdhc0xpbWl0PzogbnVtYmVyO1xuICBob3BQYXJhbXM/OiBIb3BQYXJhbXM7XG4gIGhvcD86IGJvb2xlYW47XG4gIHByZWJ1aWxkVHg/OiBQcmVidWlsZFRyYW5zYWN0aW9uUmVzdWx0O1xufVxuXG5pbnRlcmZhY2UgVmVyaWZ5RXRoVHJhbnNhY3Rpb25PcHRpb25zIGV4dGVuZHMgVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgdHhQcmVidWlsZDogVHJhbnNhY3Rpb25QcmVidWlsZDtcbiAgdHhQYXJhbXM6IEV0aFRyYW5zYWN0aW9uUGFyYW1zO1xufVxuXG5pbnRlcmZhY2UgUHJlc2lnblRyYW5zYWN0aW9uT3B0aW9ucyBleHRlbmRzIFRyYW5zYWN0aW9uUHJlYnVpbGQsIEJhc2VQcmVzaWduVHJhbnNhY3Rpb25PcHRpb25zIHtcbiAgd2FsbGV0OiBXYWxsZXQ7XG59XG5cbmludGVyZmFjZSBSZWNvdmVyVG9rZW5UcmFuc2FjdGlvbiB7XG4gIGhhbGZTaWduZWQ6IHtcbiAgICByZWNpcGllbnQ6IFJlY2lwaWVudDtcbiAgICBleHBpcmVUaW1lOiBudW1iZXI7XG4gICAgY29udHJhY3RTZXF1ZW5jZUlkOiBudW1iZXI7XG4gICAgb3BlcmF0aW9uSGFzaDogc3RyaW5nO1xuICAgIHNpZ25hdHVyZTogc3RyaW5nO1xuICAgIGdhc0xpbWl0OiBudW1iZXI7XG4gICAgZ2FzUHJpY2U6IG51bWJlcjtcbiAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogc3RyaW5nO1xuICAgIHdhbGxldElkOiBzdHJpbmc7XG4gIH07XG59XG5cbmludGVyZmFjZSBFdGhBZGRyZXNzQ29pblNwZWNpZmljcyBleHRlbmRzIEFkZHJlc3NDb2luU3BlY2lmaWMge1xuICBmb3J3YXJkZXJWZXJzaW9uOiBudW1iZXI7XG4gIHNhbHQ/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBWZXJpZnlFdGhBZGRyZXNzT3B0aW9ucyBleHRlbmRzIEJhc2VWZXJpZnlBZGRyZXNzT3B0aW9ucyB7XG4gIGJhc2VBZGRyZXNzOiBzdHJpbmc7XG4gIGNvaW5TcGVjaWZpYzogRXRoQWRkcmVzc0NvaW5TcGVjaWZpY3M7XG4gIGZvcndhcmRlclZlcnNpb246IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIEV0aCBleHRlbmRzIEJhc2VDb2luIHtcbiAgc3RhdGljIGhvcFRyYW5zYWN0aW9uU2FsdCA9ICdiaXRnb0hvcEFkZHJlc3NSZXF1ZXN0U2FsdCc7XG4gIHByb3RlY3RlZCByZWFkb25seSBzZW5kTWV0aG9kTmFtZTogJ3NlbmRNdWx0aVNpZycgfCAnc2VuZE11bHRpU2lnVG9rZW4nO1xuXG4gIHJlYWRvbmx5IHN0YXRpY3NDb2luPzogUmVhZG9ubHk8U3RhdGljc0Jhc2VDb2luPjtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28pO1xuICAgIHRoaXMuc3RhdGljc0NvaW4gPSBzdGF0aWNzQ29pbjtcbiAgICB0aGlzLnNlbmRNZXRob2ROYW1lID0gJ3NlbmRNdWx0aVNpZyc7XG4gIH1cblxuICBzdGF0aWMgY3JlYXRlSW5zdGFuY2UoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KTogQmFzZUNvaW4ge1xuICAgIHJldHVybiBuZXcgRXRoKGJpdGdvLCBzdGF0aWNzQ29pbik7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBjb3JyZWN0IEV0aCBDb21tb24gb2JqZWN0IGJhc2VkIG9uIHBhcmFtcyBmcm9tIGVpdGhlciByZWNvdmVyeSBvciB0eCBidWlsZGluZ1xuICAgKiBAcGFyYW0gZWlwMTU1OSB7RUlQMTU1OX0gY29uZmlncyB0aGF0IHNwZWNpZnkgd2hldGhlciB3ZSBzaG91bGQgY29uc3RydWN0IGFuIGVpcDE1NTkgdHhcbiAgICogQHBhcmFtIHJlcGxheVByb3RlY3Rpb25PcHRpb25zIHtSZXBsYXlQcm90ZWN0aW9uT3B0aW9uc30gY2hlY2sgaWYgY2hhaW4gaWQgc3VwcG9ydHMgcmVwbGF5IHByb3RlY3Rpb25cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldEV0aENvbW1vbihlaXAxNTU5PzogRUlQMTU1OSwgcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM/OiBSZXBsYXlQcm90ZWN0aW9uT3B0aW9ucykge1xuICAgIC8vIGlmIGVpcDE1NTkgcGFyYW1zIGFyZSBzcGVjaWZpZWQsIGRlZmF1bHQgdG8gbG9uZG9uIGhhcmRmb3JrLCBvdGhlcndpc2UsXG4gICAgLy8gZGVmYXVsdCB0byB0YW5nZXJpbmUgd2hpc3RsZSB0byBhdm9pZCByZXBsYXkgcHJvdGVjdGlvbiBpc3N1ZXNcbiAgICBjb25zdCBkZWZhdWx0SGFyZGZvcmsgPSAhIWVpcDE1NTkgPyAnbG9uZG9uJyA6IG9wdGlvbmFsRGVwcy5FdGhDb21tb24uSGFyZGZvcmsuVGFuZ2VyaW5lV2hpc3RsZTtcbiAgICBjb25zdCBkZWZhdWx0Q29tbW9uID0gbmV3IG9wdGlvbmFsRGVwcy5FdGhDb21tb24uZGVmYXVsdCh7XG4gICAgICBjaGFpbjogb3B0aW9uYWxEZXBzLkV0aENvbW1vbi5DaGFpbi5NYWlubmV0LFxuICAgICAgaGFyZGZvcms6IGRlZmF1bHRIYXJkZm9yayxcbiAgICB9KTtcblxuICAgIC8vIGlmIHJlcGxheSBwcm90ZWN0aW9uIG9wdGlvbnMgYXJlIHNldCwgb3ZlcnJpZGUgdGhlIGRlZmF1bHQgY29tbW9uIHNldHRpbmdcbiAgICBjb25zdCBldGhDb21tb24gPSByZXBsYXlQcm90ZWN0aW9uT3B0aW9uc1xuICAgICAgPyBvcHRpb25hbERlcHMuRXRoQ29tbW9uLmRlZmF1bHQuaXNTdXBwb3J0ZWRDaGFpbklkKG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihyZXBsYXlQcm90ZWN0aW9uT3B0aW9ucy5jaGFpbikpXG4gICAgICAgID8gbmV3IG9wdGlvbmFsRGVwcy5FdGhDb21tb24uZGVmYXVsdCh7XG4gICAgICAgICAgICBjaGFpbjogcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnMuY2hhaW4sXG4gICAgICAgICAgICBoYXJkZm9yazogcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnMuaGFyZGZvcmssXG4gICAgICAgICAgfSlcbiAgICAgICAgOiBvcHRpb25hbERlcHMuRXRoQ29tbW9uLmRlZmF1bHQuY3VzdG9tKHtcbiAgICAgICAgICAgIGNoYWluSWQ6IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihyZXBsYXlQcm90ZWN0aW9uT3B0aW9ucy5jaGFpbiksXG4gICAgICAgICAgICBkZWZhdWx0SGFyZGZvcms6IHJlcGxheVByb3RlY3Rpb25PcHRpb25zLmhhcmRmb3JrLFxuICAgICAgICAgIH0pXG4gICAgICA6IGRlZmF1bHRDb21tb247XG4gICAgcmV0dXJuIGV0aENvbW1vbjtcbiAgfVxuXG4gIHN0YXRpYyBidWlsZFRyYW5zYWN0aW9uKHBhcmFtczogQnVpbGRUcmFuc2FjdGlvblBhcmFtcyk6IEV0aFR4TGliLkZlZU1hcmtldEVJUDE1NTlUcmFuc2FjdGlvbiB8IEV0aFR4TGliLlRyYW5zYWN0aW9uIHtcbiAgICAvLyBpZiBlaXAxNTU5IHBhcmFtcyBhcmUgc3BlY2lmaWVkLCBkZWZhdWx0IHRvIGxvbmRvbiBoYXJkZm9yaywgb3RoZXJ3aXNlLFxuICAgIC8vIGRlZmF1bHQgdG8gdGFuZ2VyaW5lIHdoaXN0bGUgdG8gYXZvaWQgcmVwbGF5IHByb3RlY3Rpb24gaXNzdWVzXG4gICAgY29uc3QgZXRoQ29tbW9uID0gRXRoLmdldEV0aENvbW1vbihwYXJhbXMuZWlwMTU1OSwgcGFyYW1zLnJlcGxheVByb3RlY3Rpb25PcHRpb25zKTtcblxuICAgIGNvbnN0IGJhc2VQYXJhbXMgPSB7XG4gICAgICB0bzogcGFyYW1zLnRvLFxuICAgICAgbm9uY2U6IHBhcmFtcy5ub25jZSxcbiAgICAgIHZhbHVlOiBwYXJhbXMudmFsdWUsXG4gICAgICBkYXRhOiBwYXJhbXMuZGF0YSxcbiAgICAgIGdhc0xpbWl0OiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4ocGFyYW1zLmdhc0xpbWl0KSxcbiAgICB9O1xuXG4gICAgY29uc3QgdW5zaWduZWRFdGhUeCA9ICEhcGFyYW1zLmVpcDE1NTlcbiAgICAgID8gb3B0aW9uYWxEZXBzLkV0aFR4LkZlZU1hcmtldEVJUDE1NTlUcmFuc2FjdGlvbi5mcm9tVHhEYXRhKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIC4uLmJhc2VQYXJhbXMsXG4gICAgICAgICAgICBtYXhGZWVQZXJHYXM6IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihwYXJhbXMuZWlwMTU1OS5tYXhGZWVQZXJHYXMpLFxuICAgICAgICAgICAgbWF4UHJpb3JpdHlGZWVQZXJHYXM6IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihwYXJhbXMuZWlwMTU1OS5tYXhQcmlvcml0eUZlZVBlckdhcyksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IGNvbW1vbjogZXRoQ29tbW9uIH1cbiAgICAgICAgKVxuICAgICAgOiBvcHRpb25hbERlcHMuRXRoVHguVHJhbnNhY3Rpb24uZnJvbVR4RGF0YShcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICAgICAgZ2FzUHJpY2U6IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihwYXJhbXMuZ2FzUHJpY2UpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgeyBjb21tb246IGV0aENvbW1vbiB9XG4gICAgICAgICk7XG5cbiAgICByZXR1cm4gdW5zaWduZWRFdGhUeDtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c1RzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBpc0VWTSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGdldE1QQ0FsZ29yaXRobSgpOiBNUENBbGdvcml0aG0ge1xuICAgIHJldHVybiAnZWNkc2EnO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGZhY3RvciBiZXR3ZWVuIHRoZSBiYXNlIHVuaXQgYW5kIGl0cyBzbWFsbGVzdCBzdWJkaXZpc29uXG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIGdldEJhc2VGYWN0b3IoKTogc3RyaW5nIHtcbiAgICAvLyAxMF4xOFxuICAgIHJldHVybiAnMTAwMDAwMDAwMDAwMDAwMDAwMCc7XG4gIH1cblxuICBnZXRDaGFpbigpOiBzdHJpbmcge1xuICAgIHJldHVybiAnZXRoJztcbiAgfVxuXG4gIGdldEZhbWlseSgpOiBzdHJpbmcge1xuICAgIHJldHVybiAnZXRoJztcbiAgfVxuXG4gIGdldE5ldHdvcmsoKTogRXRoZXJldW1OZXR3b3JrIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0aWNzQ29pbj8ubmV0d29yayBhcyBFdGhlcmV1bU5ldHdvcms7XG4gIH1cblxuICBnZXRGdWxsTmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiAnRXRoZXJldW0nO1xuICB9XG5cbiAgLyoqXG4gICAqIEZsYWcgZm9yIHNlbmRpbmcgdmFsdWUgb2YgMFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBva2F5IHRvIHNlbmQgMCB2YWx1ZSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICB2YWx1ZWxlc3NUcmFuc2ZlckFsbG93ZWQoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogRmxhZyBmb3Igc2VuZGluZyBkYXRhIGFsb25nIHdpdGggdHJhbnNhY3Rpb25zXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG9rYXkgdG8gc2VuZCB0eCBkYXRhIChFVEgpLCBmYWxzZSBvdGhlcndpc2VcbiAgICovXG4gIHRyYW5zYWN0aW9uRGF0YUFsbG93ZWQoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogRXZhbHVhdGVzIHdoZXRoZXIgYW4gYWRkcmVzcyBzdHJpbmcgaXMgdmFsaWQgZm9yIHRoaXMgY29pblxuICAgKiBAcGFyYW0gYWRkcmVzc1xuICAgKi9cbiAgaXNWYWxpZEFkZHJlc3MoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIG9wdGlvbmFsRGVwcy5ldGhVdGlsLmlzVmFsaWRBZGRyZXNzKG9wdGlvbmFsRGVwcy5ldGhVdGlsLmFkZEhleFByZWZpeChhZGRyZXNzKSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIGlucHV0IGlzIHZhbGlkIHB1YmxpYyBrZXkgZm9yIHRoZSBjb2luLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHViIHRoZSBwdWIgdG8gYmUgY2hlY2tlZFxuICAgKiBAcmV0dXJucyB7Qm9vbGVhbn0gaXMgaXQgdmFsaWQ/XG4gICAqL1xuICBpc1ZhbGlkUHViKHB1Yjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBiaXAzMi5mcm9tQmFzZTU4KHB1YikuaXNOZXV0ZXJlZCgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVmYXVsdCBnYXMgcHJpY2UgZnJvbSBwbGF0Zm9ybVxuICAgKiBAcmV0dXJucyB7QmlnTnVtYmVyfVxuICAgKi9cbiAgZ2V0UmVjb3ZlcnlHYXNQcmljZSgpOiBhbnkge1xuICAgIHJldHVybiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4oJzIwMDAwMDAwMDAwJyk7XG4gIH1cblxuICAvKipcbiAgICogRGVmYXVsdCBnYXMgbGltaXQgZnJvbSBwbGF0Zm9ybVxuICAgKiBAcmV0dXJucyB7QmlnTnVtYmVyfVxuICAgKi9cbiAgZ2V0UmVjb3ZlcnlHYXNMaW1pdCgpOiBhbnkge1xuICAgIHJldHVybiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4oJzUwMDAwMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgZXhwaXJlIHRpbWUgZm9yIGEgY29udHJhY3QgY2FsbCAoMSB3ZWVrKVxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaW1lIGluIHNlY29uZHNcbiAgICovXG4gIGdldERlZmF1bHRFeHBpcmVUaW1lKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKSArIDYwICogNjAgKiAyNCAqIDc7XG4gIH1cblxuICAvKipcbiAgICogUXVlcnkgRXRoZXJzY2FuIGZvciB0aGUgYmFsYW5jZSBvZiBhbiBhZGRyZXNzXG4gICAqIEBwYXJhbSBhZGRyZXNzIHtTdHJpbmd9IHRoZSBFVEggYWRkcmVzc1xuICAgKiBAcmV0dXJucyB7QmlnTnVtYmVyfSBhZGRyZXNzIGJhbGFuY2VcbiAgICovXG4gIGFzeW5jIHF1ZXJ5QWRkcmVzc0JhbGFuY2UoYWRkcmVzczogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJlY292ZXJ5QmxvY2tjaGFpbkV4cGxvcmVyUXVlcnkoe1xuICAgICAgbW9kdWxlOiAnYWNjb3VudCcsXG4gICAgICBhY3Rpb246ICdiYWxhbmNlJyxcbiAgICAgIGFkZHJlc3M6IGFkZHJlc3MsXG4gICAgfSk7XG4gICAgLy8gdGhyb3cgaWYgdGhlIHJlc3VsdCBkb2VzIG5vdCBleGlzdCBvciB0aGUgcmVzdWx0IGlzIG5vdCBhIHZhbGlkIG51bWJlclxuICAgIGlmICghcmVzdWx0IHx8ICFyZXN1bHQucmVzdWx0IHx8IGlzTmFOKHJlc3VsdC5yZXN1bHQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBvYnRhaW4gYWRkcmVzcyBiYWxhbmNlIGZvciAke2FkZHJlc3N9IGZyb20gRXRoZXJzY2FuLCBnb3Q6ICR7cmVzdWx0LnJlc3VsdH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihyZXN1bHQucmVzdWx0LCAxMCk7XG4gIH1cblxuICAvKipcbiAgICogUXVlcnkgRXRoZXJzY2FuIGZvciB0aGUgYmFsYW5jZSBvZiBhbiBhZGRyZXNzIGZvciBhIHRva2VuXG4gICAqIEBwYXJhbSB0b2tlbkNvbnRyYWN0QWRkcmVzcyB7U3RyaW5nfSBhZGRyZXNzIHdoZXJlIHRoZSB0b2tlbiBzbWFydCBjb250cmFjdCBpcyBob3N0ZWRcbiAgICogQHBhcmFtIHdhbGxldENvbnRyYWN0QWRkcmVzcyB7U3RyaW5nfSBhZGRyZXNzIG9mIHRoZSB3YWxsZXRcbiAgICogQHJldHVybnMge0JpZ051bWJlcn0gdG9rZW4gYmFsYWFuY2UgaW4gYmFzZSB1bml0c1xuICAgKi9cbiAgYXN5bmMgcXVlcnlBZGRyZXNzVG9rZW5CYWxhbmNlKHRva2VuQ29udHJhY3RBZGRyZXNzOiBzdHJpbmcsIHdhbGxldENvbnRyYWN0QWRkcmVzczogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICBpZiAoIW9wdGlvbmFsRGVwcy5ldGhVdGlsLmlzVmFsaWRBZGRyZXNzKHRva2VuQ29udHJhY3RBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3QgZ2V0IGJhbGFuY2UgZm9yIGludmFsaWQgdG9rZW4gYWRkcmVzcycpO1xuICAgIH1cbiAgICBpZiAoIW9wdGlvbmFsRGVwcy5ldGhVdGlsLmlzVmFsaWRBZGRyZXNzKHdhbGxldENvbnRyYWN0QWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGdldCB0b2tlbiBiYWxhbmNlIGZvciBpbnZhbGlkIHdhbGxldCBhZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5yZWNvdmVyeUJsb2NrY2hhaW5FeHBsb3JlclF1ZXJ5KHtcbiAgICAgIG1vZHVsZTogJ2FjY291bnQnLFxuICAgICAgYWN0aW9uOiAndG9rZW5iYWxhbmNlJyxcbiAgICAgIGNvbnRyYWN0YWRkcmVzczogdG9rZW5Db250cmFjdEFkZHJlc3MsXG4gICAgICBhZGRyZXNzOiB3YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICB0YWc6ICdsYXRlc3QnLFxuICAgIH0pO1xuICAgIC8vIHRocm93IGlmIHRoZSByZXN1bHQgZG9lcyBub3QgZXhpc3Qgb3IgdGhlIHJlc3VsdCBpcyBub3QgYSB2YWxpZCBudW1iZXJcbiAgICBpZiAoIXJlc3VsdCB8fCAhcmVzdWx0LnJlc3VsdCB8fCBpc05hTihyZXN1bHQucmVzdWx0KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ291bGQgbm90IG9idGFpbiB0b2tlbiBhZGRyZXNzIGJhbGFuY2UgZm9yICR7dG9rZW5Db250cmFjdEFkZHJlc3N9IGZyb20gRXRoZXJzY2FuLCBnb3Q6ICR7cmVzdWx0LnJlc3VsdH1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHJlc3VsdC5yZXN1bHQsIDEwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdHJhbnNmZXIgb3BlcmF0aW9uIGZvciBjb2luXG4gICAqIEBwYXJhbSByZWNpcGllbnQgcmVjaXBpZW50IGluZm9cbiAgICogQHBhcmFtIGV4cGlyZVRpbWUgZXhwaXJ5IHRpbWVcbiAgICogQHBhcmFtIGNvbnRyYWN0U2VxdWVuY2VJZCBzZXF1ZW5jZSBpZFxuICAgKiBAcmV0dXJucyB7QXJyYXl9IG9wZXJhdGlvbiBhcnJheVxuICAgKi9cbiAgZ2V0T3BlcmF0aW9uKHJlY2lwaWVudDogUmVjaXBpZW50LCBleHBpcmVUaW1lOiBudW1iZXIsIGNvbnRyYWN0U2VxdWVuY2VJZDogbnVtYmVyKTogKHN0cmluZyB8IEJ1ZmZlcilbXVtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgWydzdHJpbmcnLCAnYWRkcmVzcycsICd1aW50JywgJ2J5dGVzJywgJ3VpbnQnLCAndWludCddLFxuICAgICAgW1xuICAgICAgICAnRVRIRVInLFxuICAgICAgICBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4ob3B0aW9uYWxEZXBzLmV0aFV0aWwuc3RyaXBIZXhQcmVmaXgocmVjaXBpZW50LmFkZHJlc3MpLCAxNiksXG4gICAgICAgIHJlY2lwaWVudC5hbW91bnQsXG4gICAgICAgIEJ1ZmZlci5mcm9tKG9wdGlvbmFsRGVwcy5ldGhVdGlsLnN0cmlwSGV4UHJlZml4KG9wdGlvbmFsRGVwcy5ldGhVdGlsLnBhZFRvRXZlbihyZWNpcGllbnQuZGF0YSB8fCAnJykpLCAnaGV4JyksXG4gICAgICAgIGV4cGlyZVRpbWUsXG4gICAgICAgIGNvbnRyYWN0U2VxdWVuY2VJZCxcbiAgICAgIF0sXG4gICAgXTtcbiAgfVxuXG4gIGdldE9wZXJhdGlvblNoYTNGb3JFeGVjdXRlQW5kQ29uZmlybShcbiAgICByZWNpcGllbnRzOiBSZWNpcGllbnRbXSxcbiAgICBleHBpcmVUaW1lOiBudW1iZXIsXG4gICAgY29udHJhY3RTZXF1ZW5jZUlkOiBudW1iZXJcbiAgKTogc3RyaW5nIHtcbiAgICBpZiAoIXJlY2lwaWVudHMgfHwgIUFycmF5LmlzQXJyYXkocmVjaXBpZW50cykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0aW5nIGFycmF5IG9mIHJlY2lwaWVudHMnKTtcbiAgICB9XG5cbiAgICAvLyBSaWdodCBub3cgd2Ugb25seSBzdXBwb3J0IDEgcmVjaXBpZW50XG4gICAgaWYgKHJlY2lwaWVudHMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ211c3Qgc2VuZCB0byBleGFjdGx5IDEgcmVjaXBpZW50Jyk7XG4gICAgfVxuXG4gICAgaWYgKCFfLmlzTnVtYmVyKGV4cGlyZVRpbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGlyZVRpbWUgbXVzdCBiZSBudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBlcG9jaCcpO1xuICAgIH1cblxuICAgIGlmICghXy5pc051bWJlcihjb250cmFjdFNlcXVlbmNlSWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbnRyYWN0U2VxdWVuY2VJZCBtdXN0IGJlIG51bWJlcicpO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlucHV0c1xuICAgIHJlY2lwaWVudHMuZm9yRWFjaChmdW5jdGlvbiAocmVjaXBpZW50KSB7XG4gICAgICBpZiAoXG4gICAgICAgICFfLmlzU3RyaW5nKHJlY2lwaWVudC5hZGRyZXNzKSB8fFxuICAgICAgICAhb3B0aW9uYWxEZXBzLmV0aFV0aWwuaXNWYWxpZEFkZHJlc3Mob3B0aW9uYWxEZXBzLmV0aFV0aWwuYWRkSGV4UHJlZml4KHJlY2lwaWVudC5hZGRyZXNzKSlcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYWRkcmVzczogJyArIHJlY2lwaWVudC5hZGRyZXNzKTtcbiAgICAgIH1cblxuICAgICAgbGV0IGFtb3VudDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGFtb3VudCA9IG5ldyBCaWdOdW1iZXIocmVjaXBpZW50LmFtb3VudCk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhbW91bnQgZm9yOiAnICsgcmVjaXBpZW50LmFkZHJlc3MgKyAnIC0gc2hvdWxkIGJlIG51bWVyaWMnKTtcbiAgICAgIH1cblxuICAgICAgcmVjaXBpZW50LmFtb3VudCA9IGFtb3VudC50b0ZpeGVkKDApO1xuXG4gICAgICBpZiAocmVjaXBpZW50LmRhdGEgJiYgIV8uaXNTdHJpbmcocmVjaXBpZW50LmRhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRGF0YSBmb3IgcmVjaXBpZW50ICcgKyByZWNpcGllbnQuYWRkcmVzcyArICcgLSBzaG91bGQgYmUgb2YgdHlwZSBoZXggc3RyaW5nJyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCByZWNpcGllbnQgPSByZWNpcGllbnRzWzBdO1xuICAgIHJldHVybiBvcHRpb25hbERlcHMuZXRoVXRpbC5idWZmZXJUb0hleChcbiAgICAgIG9wdGlvbmFsRGVwcy5ldGhBYmkuc29saWRpdHlTSEEzKC4uLnRoaXMuZ2V0T3BlcmF0aW9uKHJlY2lwaWVudCwgZXhwaXJlVGltZSwgY29udHJhY3RTZXF1ZW5jZUlkKSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFF1ZXJpZXMgdGhlIGNvbnRyYWN0ICh2aWEgRXRoZXJzY2FuKSBmb3IgdGhlIG5leHQgc2VxdWVuY2UgSURcbiAgICogQHBhcmFtIGFkZHJlc3Mge1N0cmluZ30gYWRkcmVzcyBvZiB0aGUgY29udHJhY3RcbiAgICogQHJldHVybnMge051bWJlcn0gc2VxdWVuY2UgSURcbiAgICovXG4gIGFzeW5jIHF1ZXJ5U2VxdWVuY2VJZChhZGRyZXNzOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIC8vIEdldCBzZXF1ZW5jZSBJRCB1c2luZyBjb250cmFjdCBjYWxsXG4gICAgY29uc3Qgc2VxdWVuY2VJZE1ldGhvZFNpZ25hdHVyZSA9IG9wdGlvbmFsRGVwcy5ldGhBYmkubWV0aG9kSUQoJ2dldE5leHRTZXF1ZW5jZUlkJywgW10pO1xuICAgIGNvbnN0IHNlcXVlbmNlSWRBcmdzID0gb3B0aW9uYWxEZXBzLmV0aEFiaS5yYXdFbmNvZGUoW10sIFtdKTtcbiAgICBjb25zdCBzZXF1ZW5jZUlkRGF0YSA9IEJ1ZmZlci5jb25jYXQoW3NlcXVlbmNlSWRNZXRob2RTaWduYXR1cmUsIHNlcXVlbmNlSWRBcmdzXSkudG9TdHJpbmcoJ2hleCcpO1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucmVjb3ZlcnlCbG9ja2NoYWluRXhwbG9yZXJRdWVyeSh7XG4gICAgICBtb2R1bGU6ICdwcm94eScsXG4gICAgICBhY3Rpb246ICdldGhfY2FsbCcsXG4gICAgICB0bzogYWRkcmVzcyxcbiAgICAgIGRhdGE6IHNlcXVlbmNlSWREYXRhLFxuICAgICAgdGFnOiAnbGF0ZXN0JyxcbiAgICB9KTtcbiAgICBpZiAoIXJlc3VsdCB8fCAhcmVzdWx0LnJlc3VsdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3Qgb2J0YWluIHNlcXVlbmNlIElEIGZyb20gRXRoZXJzY2FuLCBnb3Q6ICcgKyByZXN1bHQucmVzdWx0KTtcbiAgICB9XG4gICAgY29uc3Qgc2VxdWVuY2VJZEhleCA9IHJlc3VsdC5yZXN1bHQ7XG4gICAgcmV0dXJuIG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihzZXF1ZW5jZUlkSGV4LnNsaWNlKDIpLCAxNikudG9OdW1iZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gZm9yIHNpZ25UcmFuc2FjdGlvbiBmb3IgdGhlIHJhcmUgY2FzZSB0aGF0IFNESyBpcyBkb2luZyB0aGUgc2Vjb25kIHNpZ25hdHVyZVxuICAgKiBOb3RlOiB3ZSBhcmUgZXhwZWN0aW5nIHRoaXMgdG8gYmUgY2FsbGVkIGZyb20gdGhlIG9mZmxpbmUgdmF1bHRcbiAgICogQHBhcmFtIHBhcmFtcy50eFByZWJ1aWxkXG4gICAqIEBwYXJhbSBwYXJhbXMuc2lnbmluZ0tleU5vbmNlXG4gICAqIEBwYXJhbSBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzXG4gICAqIEBwYXJhbSBwYXJhbXMucHJ2XG4gICAqIEByZXR1cm5zIHt7dHhIZXg6ICp9fVxuICAgKi9cbiAgc2lnbkZpbmFsKHBhcmFtczogU2lnbkZpbmFsT3B0aW9ucyk6IEZ1bGx5U2lnbmVkVHJhbnNhY3Rpb24ge1xuICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBwYXJhbXMudHhQcmVidWlsZDtcblxuICAgIGlmICghXy5pc051bWJlcihwYXJhbXMuc2lnbmluZ0tleU5vbmNlKSAmJiAhXy5pc051bWJlcihwYXJhbXMudHhQcmVidWlsZC5oYWxmU2lnbmVkLmJhY2t1cEtleU5vbmNlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBvZiBzaWduaW5nS2V5Tm9uY2UgYW5kIGJhY2t1cEtleU5vbmNlIGFzIGEgcGFyYW1ldGVyLCBhbmQgaXQgbXVzdCBiZSBhIG51bWJlcidcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhcmFtcyBtdXN0IGluY2x1ZGUgd2FsbGV0Q29udHJhY3RBZGRyZXNzLCBidXQgZ290IHVuZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHNpZ25pbmdOb2RlID0gYmlwMzIuZnJvbUJhc2U1OChwYXJhbXMucHJ2KTtcbiAgICBjb25zdCBzaWduaW5nS2V5ID0gc2lnbmluZ05vZGUucHJpdmF0ZUtleTtcbiAgICBpZiAoXy5pc1VuZGVmaW5lZChzaWduaW5nS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHByaXZhdGUga2V5Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgdHhJbmZvID0ge1xuICAgICAgcmVjaXBpZW50OiB0eFByZWJ1aWxkLnJlY2lwaWVudHNbMF0sXG4gICAgICBleHBpcmVUaW1lOiB0eFByZWJ1aWxkLmhhbGZTaWduZWQuZXhwaXJlVGltZSxcbiAgICAgIGNvbnRyYWN0U2VxdWVuY2VJZDogdHhQcmVidWlsZC5oYWxmU2lnbmVkLmNvbnRyYWN0U2VxdWVuY2VJZCxcbiAgICAgIHNpZ25hdHVyZTogdHhQcmVidWlsZC5oYWxmU2lnbmVkLnNpZ25hdHVyZSxcbiAgICB9O1xuXG4gICAgY29uc3Qgc2VuZE1ldGhvZEFyZ3MgPSB0aGlzLmdldFNlbmRNZXRob2RBcmdzKHR4SW5mbyk7XG4gICAgY29uc3QgbWV0aG9kU2lnbmF0dXJlID0gb3B0aW9uYWxEZXBzLmV0aEFiaS5tZXRob2RJRCh0aGlzLnNlbmRNZXRob2ROYW1lLCBfLm1hcChzZW5kTWV0aG9kQXJncywgJ3R5cGUnKSk7XG4gICAgY29uc3QgZW5jb2RlZEFyZ3MgPSBvcHRpb25hbERlcHMuZXRoQWJpLnJhd0VuY29kZShfLm1hcChzZW5kTWV0aG9kQXJncywgJ3R5cGUnKSwgXy5tYXAoc2VuZE1ldGhvZEFyZ3MsICd2YWx1ZScpKTtcbiAgICBjb25zdCBzZW5kRGF0YSA9IEJ1ZmZlci5jb25jYXQoW21ldGhvZFNpZ25hdHVyZSwgZW5jb2RlZEFyZ3NdKTtcblxuICAgIGNvbnN0IGV0aFR4UGFyYW1zID0ge1xuICAgICAgdG86IHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICBub25jZTpcbiAgICAgICAgcGFyYW1zLnNpZ25pbmdLZXlOb25jZSAhPT0gdW5kZWZpbmVkID8gcGFyYW1zLnNpZ25pbmdLZXlOb25jZSA6IHBhcmFtcy50eFByZWJ1aWxkLmhhbGZTaWduZWQuYmFja3VwS2V5Tm9uY2UsXG4gICAgICB2YWx1ZTogMCxcbiAgICAgIGdhc1ByaWNlOiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4odHhQcmVidWlsZC5nYXNQcmljZSksXG4gICAgICBnYXNMaW1pdDogbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHR4UHJlYnVpbGQuZ2FzTGltaXQpLFxuICAgICAgZGF0YTogc2VuZERhdGEsXG4gICAgfTtcblxuICAgIGNvbnN0IHVuc2lnbmVkRXRoVHggPSBFdGguYnVpbGRUcmFuc2FjdGlvbih7XG4gICAgICAuLi5ldGhUeFBhcmFtcyxcbiAgICAgIGVpcDE1NTk6IHBhcmFtcy50eFByZWJ1aWxkLmVpcDE1NTksXG4gICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9uczogcGFyYW1zLnR4UHJlYnVpbGQucmVwbGF5UHJvdGVjdGlvbk9wdGlvbnMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBldGhUeCA9IHVuc2lnbmVkRXRoVHguc2lnbihzaWduaW5nS2V5KTtcblxuICAgIHJldHVybiB7IHR4SGV4OiBldGhUeC5zZXJpYWxpemUoKS50b1N0cmluZygnaGV4JykgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NlbWJsZSBrZXljaGFpbiBhbmQgaGFsZi1zaWduIHByZWJ1aWx0IHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICogLSB0eFByZWJ1aWxkXG4gICAqIC0gcHJ2XG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFNpZ25lZFRyYW5zYWN0aW9uPn1cbiAgICovXG4gIGFzeW5jIHNpZ25UcmFuc2FjdGlvbihwYXJhbXM6IFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPFNpZ25lZFRyYW5zYWN0aW9uPiB7XG4gICAgY29uc3QgdHhQcmVidWlsZCA9IHBhcmFtcy50eFByZWJ1aWxkO1xuXG4gICAgY29uc3QgdXNlclBydiA9IHBhcmFtcy5wcnY7XG4gICAgY29uc3QgRVhQSVJFVElNRV9ERUZBVUxUID0gNjAgKiA2MCAqIDI0ICogNzsgLy8gVGhpcyBzaWduYXR1cmUgd2lsbCBiZSB2YWxpZCBmb3IgMSB3ZWVrXG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZCh0eFByZWJ1aWxkKSB8fCAhXy5pc09iamVjdCh0eFByZWJ1aWxkKSkge1xuICAgICAgaWYgKCFfLmlzVW5kZWZpbmVkKHR4UHJlYnVpbGQpICYmICFfLmlzT2JqZWN0KHR4UHJlYnVpbGQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdHhQcmVidWlsZCBtdXN0IGJlIGFuIG9iamVjdCwgZ290IHR5cGUgJHt0eXBlb2YgdHhQcmVidWlsZH1gKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB0eFByZWJ1aWxkIHBhcmFtZXRlcicpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHVzZXJQcnYpIHx8ICFfLmlzU3RyaW5nKHVzZXJQcnYpKSB7XG4gICAgICBpZiAoIV8uaXNVbmRlZmluZWQodXNlclBydikgJiYgIV8uaXNTdHJpbmcodXNlclBydikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBwcnYgbXVzdCBiZSBhIHN0cmluZywgZ290IHR5cGUgJHt0eXBlb2YgdXNlclBydn1gKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBwcnYgcGFyYW1ldGVyIHRvIHNpZ24gdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICBwYXJhbXMucmVjaXBpZW50cyA9IHR4UHJlYnVpbGQucmVjaXBpZW50cyB8fCBwYXJhbXMucmVjaXBpZW50cztcblxuICAgIC8vIGlmIG5vIHJlY2lwaWVudHMgaW4gZWl0aGVyIHBhcmFtcyBvciB0eFByZWJ1aWxkLCB0aGVuIHRocm93IGFuIGVycm9yXG4gICAgaWYgKCFwYXJhbXMucmVjaXBpZW50cyB8fCAhQXJyYXkuaXNBcnJheShwYXJhbXMucmVjaXBpZW50cykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncmVjaXBpZW50cyBtaXNzaW5nIG9yIG5vdCBhcnJheScpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMucmVjaXBpZW50cy5sZW5ndGggPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWNpcGllbnRzIGVtcHR5Jyk7XG4gICAgfVxuXG4gICAgLy8gTm9ybWFsbHkgdGhlIFNESyBwcm92aWRlcyB0aGUgZmlyc3Qgc2lnbmF0dXJlIGZvciBhbiBFVEggdHgsIGJ1dCBvY2Nhc2lvbmFsbHkgaXQgcHJvdmlkZXMgdGhlIHNlY29uZCBhbmQgZmluYWwgb25lLlxuICAgIGlmIChwYXJhbXMuaXNMYXN0U2lnbmF0dXJlKSB7XG4gICAgICAvLyBJbiB0aGlzIGNhc2Ugd2hlbiB3ZSdyZSBkb2luZyB0aGUgc2Vjb25kIChmaW5hbCkgc2lnbmF0dXJlLCB0aGUgbG9naWMgaXMgZGlmZmVyZW50LlxuICAgICAgcmV0dXJuIHRoaXMuc2lnbkZpbmFsKHBhcmFtcyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2Vjb25kc1NpbmNlRXBvY2ggPSBNYXRoLmZsb29yKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG4gICAgY29uc3QgZXhwaXJlVGltZSA9IHBhcmFtcy5leHBpcmVUaW1lIHx8IHNlY29uZHNTaW5jZUVwb2NoICsgRVhQSVJFVElNRV9ERUZBVUxUO1xuICAgIGNvbnN0IHNlcXVlbmNlSWQgPSB0eFByZWJ1aWxkLm5leHRDb250cmFjdFNlcXVlbmNlSWQ7XG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZChzZXF1ZW5jZUlkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0cmFuc2FjdGlvbiBwcmVidWlsZCBtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IG5leHRDb250cmFjdFNlcXVlbmNlSWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBvcGVyYXRpb25IYXNoID0gdGhpcy5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0ocGFyYW1zLnJlY2lwaWVudHMsIGV4cGlyZVRpbWUsIHNlcXVlbmNlSWQpO1xuICAgIGNvbnN0IHNpZ25hdHVyZSA9IFV0aWwuZXRoU2lnbk1zZ0hhc2gob3BlcmF0aW9uSGFzaCwgVXRpbC54cHJ2VG9FdGhQcml2YXRlS2V5KHVzZXJQcnYpKTtcblxuICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgZWlwMTU1OTogcGFyYW1zLnR4UHJlYnVpbGQuZWlwMTU1OSxcbiAgICAgIGlzQmF0Y2g6IHBhcmFtcy50eFByZWJ1aWxkLmlzQmF0Y2gsXG4gICAgICByZWNpcGllbnRzOiBwYXJhbXMucmVjaXBpZW50cyxcbiAgICAgIGV4cGlyZVRpbWU6IGV4cGlyZVRpbWUsXG4gICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IHNlcXVlbmNlSWQsXG4gICAgICBzZXF1ZW5jZUlkOiBwYXJhbXMuc2VxdWVuY2VJZCxcbiAgICAgIG9wZXJhdGlvbkhhc2g6IG9wZXJhdGlvbkhhc2gsXG4gICAgICBzaWduYXR1cmU6IHNpZ25hdHVyZSxcbiAgICAgIGdhc0xpbWl0OiBwYXJhbXMuZ2FzTGltaXQsXG4gICAgICBnYXNQcmljZTogcGFyYW1zLmdhc1ByaWNlLFxuICAgICAgaG9wVHJhbnNhY3Rpb246IHR4UHJlYnVpbGQuaG9wVHJhbnNhY3Rpb24sXG4gICAgICBiYWNrdXBLZXlOb25jZTogdHhQcmVidWlsZC5iYWNrdXBLZXlOb25jZSxcbiAgICAgIGN1c3RvZGlhblRyYW5zYWN0aW9uSWQ6IHBhcmFtcy5jdXN0b2RpYW5UcmFuc2FjdGlvbklkLFxuICAgIH07XG4gICAgcmV0dXJuIHsgaGFsZlNpZ25lZDogdHhQYXJhbXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbnN1cmUgZWl0aGVyIGVudGVycHJpc2Ugb3IgbmV3RmVlQWRkcmVzcyBpcyBwYXNzZWQsIHRvIGtub3cgd2hldGhlciB0byBjcmVhdGUgbmV3IGtleSBvciB1c2UgZW50ZXJwcmlzZSBrZXlcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiBAcGFyYW0gcGFyYW1zLmVudGVycHJpc2Uge1N0cmluZ30gdGhlIGVudGVycHJpc2UgaWQgdG8gYXNzb2NpYXRlIHdpdGggdGhpcyBrZXlcbiAgICogQHBhcmFtIHBhcmFtcy5uZXdGZWVBZGRyZXNzIHtCb29sZWFufSBjcmVhdGUgYSBuZXcgZmVlIGFkZHJlc3MgKGVudGVycHJpc2Ugbm90IG5lZWRlZCBpbiB0aGlzIGNhc2UpXG4gICAqL1xuICBwcmVDcmVhdGVCaXRHbyhwYXJhbXM6IFByZWNyZWF0ZUJpdEdvT3B0aW9ucyk6IHZvaWQge1xuICAgIC8vIFdlIGFsd2F5cyBuZWVkIHBhcmFtcyBvYmplY3QsIHNpbmNlIGVpdGhlciBlbnRlcnByaXNlIG9yIG5ld0ZlZUFkZHJlc3MgaXMgcmVxdWlyZWRcbiAgICBpZiAoIV8uaXNPYmplY3QocGFyYW1zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBwcmVDcmVhdGVCaXRHbyBtdXN0IGJlIHBhc3NlZCBhIHBhcmFtcyBvYmplY3QuIEdvdCAke3BhcmFtc30gKHR5cGUgJHt0eXBlb2YgcGFyYW1zfSlgKTtcbiAgICB9XG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMuZW50ZXJwcmlzZSkgJiYgXy5pc1VuZGVmaW5lZChwYXJhbXMubmV3RmVlQWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ2V4cGVjdGluZyBlbnRlcnByaXNlIHdoZW4gYWRkaW5nIEJpdEdvIGtleS4gSWYgeW91IHdhbnQgdG8gY3JlYXRlIGEgbmV3IEVUSCBiaXRnbyBrZXksIHNldCB0aGUgbmV3RmVlQWRkcmVzcyBwYXJhbWV0ZXIgdG8gdHJ1ZS4nXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIENoZWNrIHdoZXRoZXIga2V5IHNob3VsZCBiZSBhbiBlbnRlcnByaXNlIGtleSBvciBhIEJpdEdvIGtleSBmb3IgYSBuZXcgZmVlIGFkZHJlc3NcbiAgICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmVudGVycHJpc2UpICYmICFfLmlzVW5kZWZpbmVkKHBhcmFtcy5uZXdGZWVBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbmNvbXBhdGlibGUgYXJndW1lbnRzIC0gY2Fubm90IHBhc3MgYm90aCBlbnRlcnByaXNlIGFuZCBuZXdGZWVBZGRyZXNzIHBhcmFtZXRlci5gKTtcbiAgICB9XG5cbiAgICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmVudGVycHJpc2UpICYmICFfLmlzU3RyaW5nKHBhcmFtcy5lbnRlcnByaXNlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBlbnRlcnByaXNlIHNob3VsZCBiZSBhIHN0cmluZyAtIGdvdCAke3BhcmFtcy5lbnRlcnByaXNlfSAodHlwZSAke3R5cGVvZiBwYXJhbXMuZW50ZXJwcmlzZX0pYCk7XG4gICAgfVxuXG4gICAgaWYgKCFfLmlzVW5kZWZpbmVkKHBhcmFtcy5uZXdGZWVBZGRyZXNzKSAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLm5ld0ZlZUFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBuZXdGZWVBZGRyZXNzIHNob3VsZCBiZSBhIGJvb2xlYW4gLSBnb3QgJHtwYXJhbXMubmV3RmVlQWRkcmVzc30gKHR5cGUgJHt0eXBlb2YgcGFyYW1zLm5ld0ZlZUFkZHJlc3N9KWBcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFF1ZXJpZXMgcHVibGljIGJsb2NrIGV4cGxvcmVyIHRvIGdldCB0aGUgbmV4dCBFVEggbm9uY2UgdGhhdCBzaG91bGQgYmUgdXNlZCBmb3IgdGhlIGdpdmVuIEVUSCBhZGRyZXNzXG4gICAqIEBwYXJhbSBhZGRyZXNzXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgYXN5bmMgZ2V0QWRkcmVzc05vbmNlKGFkZHJlc3M6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgLy8gR2V0IG5vbmNlIGZvciBiYWNrdXAga2V5IChzaG91bGQgYmUgMClcbiAgICBsZXQgbm9uY2UgPSAwO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5yZWNvdmVyeUJsb2NrY2hhaW5FeHBsb3JlclF1ZXJ5KHtcbiAgICAgIG1vZHVsZTogJ2FjY291bnQnLFxuICAgICAgYWN0aW9uOiAndHhsaXN0JyxcbiAgICAgIGFkZHJlc3MsXG4gICAgfSk7XG4gICAgaWYgKCFyZXN1bHQgfHwgIUFycmF5LmlzQXJyYXkocmVzdWx0LnJlc3VsdCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGZpbmQgbmV4dCBub25jZSBmcm9tIEV0aGVyc2NhbiwgZ290OiAnICsgSlNPTi5zdHJpbmdpZnkocmVzdWx0KSk7XG4gICAgfVxuICAgIGNvbnN0IGJhY2t1cEtleVR4TGlzdCA9IHJlc3VsdC5yZXN1bHQ7XG4gICAgaWYgKGJhY2t1cEtleVR4TGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBDYWxjdWxhdGUgbGFzdCBub25jZSB1c2VkXG4gICAgICBjb25zdCBvdXRnb2luZ1R4cyA9IGJhY2t1cEtleVR4TGlzdC5maWx0ZXIoKHR4KSA9PiB0eC5mcm9tID09PSBhZGRyZXNzKTtcbiAgICAgIG5vbmNlID0gb3V0Z29pbmdUeHMubGVuZ3RoO1xuICAgIH1cbiAgICByZXR1cm4gbm9uY2U7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIGZvciByZWNvdmVyKClcbiAgICogVGhpcyB0cmFuc2Zvcm1zIHRoZSB1bnNpZ25lZCB0cmFuc2FjdGlvbiBpbmZvcm1hdGlvbiBpbnRvIGEgZm9ybWF0IHRoZSBCaXRHbyBvZmZsaW5lIHZhdWx0IGV4cGVjdHNcbiAgICogQHBhcmFtIHR4SW5mb1xuICAgKiBAcGFyYW0gZXRoVHhcbiAgICogQHBhcmFtIHVzZXJLZXlcbiAgICogQHBhcmFtIGJhY2t1cEtleVxuICAgKiBAcGFyYW0gZ2FzUHJpY2VcbiAgICogQHBhcmFtIGdhc0xpbWl0XG4gICAqIEBwYXJhbSBlaXAxNTU5XG4gICAqIEBwYXJhbSByZXBsYXlQcm90ZWN0aW9uT3B0aW9uc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxPZmZsaW5lVmF1bHRUeEluZm8+fVxuICAgKi9cbiAgYXN5bmMgZm9ybWF0Rm9yT2ZmbGluZVZhdWx0KFxuICAgIHR4SW5mbzogVW5mb3JtYXR0ZWRUeEluZm8sXG4gICAgZXRoVHg6IEV0aFR4TGliLlRyYW5zYWN0aW9uIHwgRXRoVHhMaWIuRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLFxuICAgIHVzZXJLZXk6IHN0cmluZyxcbiAgICBiYWNrdXBLZXk6IHN0cmluZyxcbiAgICBnYXNQcmljZTogQnVmZmVyLFxuICAgIGdhc0xpbWl0OiBudW1iZXIsXG4gICAgZWlwMTU1OT86IEVJUDE1NTksXG4gICAgcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM/OiBSZXBsYXlQcm90ZWN0aW9uT3B0aW9uc1xuICApOiBQcm9taXNlPE9mZmxpbmVWYXVsdFR4SW5mbz4ge1xuICAgIGlmICghZXRoVHgudG8pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRXRoIHR4IG11c3QgaGF2ZSBhIGB0b2AgYWRkcmVzcycpO1xuICAgIH1cbiAgICBjb25zdCBiYWNrdXBIRE5vZGUgPSBiaXAzMi5mcm9tQmFzZTU4KGJhY2t1cEtleSk7XG4gICAgY29uc3QgYmFja3VwU2lnbmluZ0tleSA9IGJhY2t1cEhETm9kZS5wdWJsaWNLZXk7XG4gICAgY29uc3QgcmVzcG9uc2U6IE9mZmxpbmVWYXVsdFR4SW5mbyA9IHtcbiAgICAgIHR4OiBldGhUeC5zZXJpYWxpemUoKS50b1N0cmluZygnaGV4JyksXG4gICAgICB1c2VyS2V5LFxuICAgICAgYmFja3VwS2V5LFxuICAgICAgY29pbjogdGhpcy5nZXRDaGFpbigpLFxuICAgICAgZ2FzUHJpY2U6IG9wdGlvbmFsRGVwcy5ldGhVdGlsLmJ1ZmZlclRvSW50KGdhc1ByaWNlKS50b0ZpeGVkKCksXG4gICAgICBnYXNMaW1pdCxcbiAgICAgIHJlY2lwaWVudHM6IFt0eEluZm8ucmVjaXBpZW50XSxcbiAgICAgIHdhbGxldENvbnRyYWN0QWRkcmVzczogZXRoVHgudG8udG9TdHJpbmcoKSxcbiAgICAgIGFtb3VudDogdHhJbmZvLnJlY2lwaWVudC5hbW91bnQsXG4gICAgICBiYWNrdXBLZXlOb25jZTogYXdhaXQgdGhpcy5nZXRBZGRyZXNzTm9uY2UoXG4gICAgICAgIGAweCR7b3B0aW9uYWxEZXBzLmV0aFV0aWwucHVibGljVG9BZGRyZXNzKGJhY2t1cFNpZ25pbmdLZXksIHRydWUpLnRvU3RyaW5nKCdoZXgnKX1gXG4gICAgICApLFxuICAgICAgZWlwMTU1OSxcbiAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zLFxuICAgIH07XG4gICAgXy5leHRlbmQocmVzcG9uc2UsIHR4SW5mbyk7XG4gICAgcmVzcG9uc2UubmV4dENvbnRyYWN0U2VxdWVuY2VJZCA9IHJlc3BvbnNlLmNvbnRyYWN0U2VxdWVuY2VJZDtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIGZvciByZWNvdmVyKClcbiAgICogVGhpcyB0cmFuc2Zvcm1zIHRoZSB1bnNpZ25lZCB0cmFuc2FjdGlvbiBpbmZvcm1hdGlvbiBpbnRvIGEgZm9ybWF0IHRoZSBCaXRHbyBvZmZsaW5lIHZhdWx0IGV4cGVjdHNcbiAgICogQHBhcmFtIHR4SW5mb1xuICAgKiBAcGFyYW0gZXRoVHhcbiAgICogQHBhcmFtIHVzZXJLZXlcbiAgICogQHBhcmFtIGJhY2t1cEtleVxuICAgKiBAcGFyYW0gZ2FzUHJpY2VcbiAgICogQHBhcmFtIGdhc0xpbWl0XG4gICAqIEBwYXJhbSBlaXAxNTU5XG4gICAqIEBwYXJhbSByZXBsYXlQcm90ZWN0aW9uT3B0aW9uc1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxPZmZsaW5lVmF1bHRUeEluZm8+fVxuICAgKi9cbiAgZm9ybWF0Rm9yT2ZmbGluZVZhdWx0VFNTKFxuICAgIHR4SW5mbzogVW5mb3JtYXR0ZWRUeEluZm8sXG4gICAgZXRoVHg6IEV0aFR4TGliLlRyYW5zYWN0aW9uIHwgRXRoVHhMaWIuRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLFxuICAgIHVzZXJLZXk6IHN0cmluZyxcbiAgICBiYWNrdXBLZXk6IHN0cmluZyxcbiAgICBnYXNQcmljZTogQnVmZmVyLFxuICAgIGdhc0xpbWl0OiBudW1iZXIsXG4gICAgYmFja3VwS2V5Tm9uY2U6IG51bWJlcixcbiAgICBlaXAxNTU5PzogRUlQMTU1OSxcbiAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9ucz86IFJlcGxheVByb3RlY3Rpb25PcHRpb25zXG4gICk6IE9mZmxpbmVWYXVsdFR4SW5mbyB7XG4gICAgaWYgKCFldGhUeC50bykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFdGggdHggbXVzdCBoYXZlIGEgYHRvYCBhZGRyZXNzJyk7XG4gICAgfVxuICAgIGNvbnN0IHJlc3BvbnNlOiBPZmZsaW5lVmF1bHRUeEluZm8gPSB7XG4gICAgICB0eDogZXRoVHguc2VyaWFsaXplKCkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgdHhIZXg6IGV0aFR4LmdldE1lc3NhZ2VUb1NpZ24oZmFsc2UpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIHVzZXJLZXksXG4gICAgICBiYWNrdXBLZXksXG4gICAgICBjb2luOiB0aGlzLmdldENoYWluKCksXG4gICAgICBnYXNQcmljZTogb3B0aW9uYWxEZXBzLmV0aFV0aWwuYnVmZmVyVG9JbnQoZ2FzUHJpY2UpLnRvRml4ZWQoKSxcbiAgICAgIGdhc0xpbWl0LFxuICAgICAgcmVjaXBpZW50czogW3R4SW5mby5yZWNpcGllbnRdLFxuICAgICAgd2FsbGV0Q29udHJhY3RBZGRyZXNzOiBldGhUeC50by50b1N0cmluZygpLFxuICAgICAgYW1vdW50OiB0eEluZm8ucmVjaXBpZW50LmFtb3VudCxcbiAgICAgIGJhY2t1cEtleU5vbmNlOiBiYWNrdXBLZXlOb25jZSxcbiAgICAgIGVpcDE1NTksXG4gICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9ucyxcbiAgICB9O1xuICAgIF8uZXh0ZW5kKHJlc3BvbnNlLCB0eEluZm8pO1xuICAgIHJldHVybiByZXNwb25zZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayB3aGV0aGVyIHRoZSBnYXMgcHJpY2UgcGFzc2VkIGluIGJ5IHVzZXIgYXJlIHdpdGhpbiBvdXIgbWF4IGFuZCBtaW4gYm91bmRzXG4gICAqIElmIHRoZXkgYXJlIG5vdCBzZXQsIHNldCB0aGVtIHRvIHRoZSBkZWZhdWx0c1xuICAgKiBAcGFyYW0gdXNlckdhc1ByaWNlIHVzZXIgZGVmaW5lZCBnYXMgcHJpY2VcbiAgICogQHJldHVybnMgdGhlIGdhcyBwcmljZSB0byB1c2UgZm9yIHRoaXMgdHJhbnNhY3Rpb25cbiAgICovXG4gIHNldEdhc1ByaWNlKHVzZXJHYXNQcmljZT86IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKCF1c2VyR2FzUHJpY2UpIHtcbiAgICAgIHJldHVybiBldGhHYXNDb25maWdzLmRlZmF1bHRHYXNQcmljZTtcbiAgICB9XG5cbiAgICBjb25zdCBnYXNQcmljZU1heCA9IGV0aEdhc0NvbmZpZ3MubWF4aW11bUdhc1ByaWNlO1xuICAgIGNvbnN0IGdhc1ByaWNlTWluID0gZXRoR2FzQ29uZmlncy5taW5pbXVtR2FzUHJpY2U7XG4gICAgaWYgKHVzZXJHYXNQcmljZSA8IGdhc1ByaWNlTWluIHx8IHVzZXJHYXNQcmljZSA+IGdhc1ByaWNlTWF4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEdhcyBwcmljZSBtdXN0IGJlIGJldHdlZW4gJHtnYXNQcmljZU1pbn0gYW5kICR7Z2FzUHJpY2VNYXh9YCk7XG4gICAgfVxuICAgIHJldHVybiB1c2VyR2FzUHJpY2U7XG4gIH1cbiAgLyoqXG4gICAqIENoZWNrIHdoZXRoZXIgZ2FzIGxpbWl0IHBhc3NlZCBpbiBieSB1c2VyIGFyZSB3aXRoaW4gb3VyIG1heCBhbmQgbWluIGJvdW5kc1xuICAgKiBJZiB0aGV5IGFyZSBub3Qgc2V0LCBzZXQgdGhlbSB0byB0aGUgZGVmYXVsdHNcbiAgICogQHBhcmFtIHVzZXJHYXNMaW1pdCB1c2VyIGRlZmluZWQgZ2FzIGxpbWl0XG4gICAqIEByZXR1cm5zIHRoZSBnYXMgbGltaXQgdG8gdXNlIGZvciB0aGlzIHRyYW5zYWN0aW9uXG4gICAqL1xuICBzZXRHYXNMaW1pdCh1c2VyR2FzTGltaXQ/OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmICghdXNlckdhc0xpbWl0KSB7XG4gICAgICByZXR1cm4gZXRoR2FzQ29uZmlncy5kZWZhdWx0R2FzTGltaXQ7XG4gICAgfVxuICAgIGNvbnN0IGdhc0xpbWl0TWF4ID0gZXRoR2FzQ29uZmlncy5tYXhpbXVtR2FzTGltaXQ7XG4gICAgY29uc3QgZ2FzTGltaXRNaW4gPSBldGhHYXNDb25maWdzLm1pbmltdW1HYXNMaW1pdDtcbiAgICBpZiAodXNlckdhc0xpbWl0IDwgZ2FzTGltaXRNaW4gfHwgdXNlckdhc0xpbWl0ID4gZ2FzTGltaXRNYXgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgR2FzIGxpbWl0IG11c3QgYmUgYmV0d2VlbiAke2dhc0xpbWl0TWlufSBhbmQgJHtnYXNMaW1pdE1heH1gKTtcbiAgICB9XG4gICAgcmV0dXJuIHVzZXJHYXNMaW1pdDtcbiAgfVxuXG4gIHZhbGlkYXRlUmVjb3ZlcnlQYXJhbXMocGFyYW1zOiBSZWNvdmVyT3B0aW9ucyk6IHZvaWQge1xuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy51c2VyS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHVzZXJLZXknKTtcbiAgICB9XG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMuYmFja3VwS2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJhY2t1cEtleScpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSAmJiAhcGFyYW1zLnVzZXJLZXkuc3RhcnRzV2l0aCgneHB1YicpICYmICFwYXJhbXMuaXNUc3MpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB3YWxsZXQgcGFzc3BocmFzZScpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MpIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgd2FsbGV0Q29udHJhY3RBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKF8uaXNVbmRlZmluZWQocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24nKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNpZ25SZWNvdmVyeVRTUyhcbiAgICB1c2VyS2V5Q29tYmluZWQ6IEVDRFNBLktleUNvbWJpbmVkLFxuICAgIGJhY2t1cEtleUNvbWJpbmVkOiBFQ0RTQS5LZXlDb21iaW5lZCxcbiAgICB0eEhleDogc3RyaW5nLFxuICAgIHtcbiAgICAgIHJhbmdlUHJvb2ZDaGFsbGVuZ2UsXG4gICAgfToge1xuICAgICAgcmFuZ2VQcm9vZkNoYWxsZW5nZT86IEVjZHNhVHlwZXMuU2VyaWFsaXplZE50aWxkZTtcbiAgICB9ID0ge31cbiAgKTogUHJvbWlzZTxFQ0RTQU1ldGhvZFR5cGVzLlNpZ25hdHVyZT4ge1xuICAgIGNvbnN0IE1QQyA9IG5ldyBFY2RzYSgpO1xuICAgIGNvbnN0IHNpZ25lck9uZUluZGV4ID0gdXNlcktleUNvbWJpbmVkLnhTaGFyZS5pO1xuICAgIGNvbnN0IHNpZ25lclR3b0luZGV4ID0gYmFja3VwS2V5Q29tYmluZWQueFNoYXJlLmk7XG5cbiAgICByYW5nZVByb29mQ2hhbGxlbmdlID1cbiAgICAgIHJhbmdlUHJvb2ZDaGFsbGVuZ2UgPz8gRWNkc2FUeXBlcy5zZXJpYWxpemVOdGlsZGVXaXRoUHJvb2ZzKGF3YWl0IEVjZHNhUmFuZ2VQcm9vZi5nZW5lcmF0ZU50aWxkZSgpKTtcblxuICAgIGNvbnN0IHVzZXJUb0JhY2t1cFBhaWxsaWVyQ2hhbGxlbmdlID0gYXdhaXQgRWNkc2FQYWlsbGllclByb29mLmdlbmVyYXRlUChcbiAgICAgIGhleFRvQmlnSW50KHVzZXJLZXlDb21iaW5lZC55U2hhcmVzW3NpZ25lclR3b0luZGV4XS5uKVxuICAgICk7XG4gICAgY29uc3QgYmFja3VwVG9Vc2VyUGFpbGxpZXJDaGFsbGVuZ2UgPSBhd2FpdCBFY2RzYVBhaWxsaWVyUHJvb2YuZ2VuZXJhdGVQKFxuICAgICAgaGV4VG9CaWdJbnQoYmFja3VwS2V5Q29tYmluZWQueVNoYXJlc1tzaWduZXJPbmVJbmRleF0ubilcbiAgICApO1xuXG4gICAgY29uc3QgdXNlclhTaGFyZSA9IE1QQy5hcHBlbmRDaGFsbGVuZ2UoXG4gICAgICB1c2VyS2V5Q29tYmluZWQueFNoYXJlLFxuICAgICAgcmFuZ2VQcm9vZkNoYWxsZW5nZSxcbiAgICAgIEVjZHNhVHlwZXMuc2VyaWFsaXplUGFpbGxpZXJDaGFsbGVuZ2UoeyBwOiB1c2VyVG9CYWNrdXBQYWlsbGllckNoYWxsZW5nZSB9KVxuICAgICk7XG4gICAgY29uc3QgdXNlcllTaGFyZSA9IE1QQy5hcHBlbmRDaGFsbGVuZ2UoXG4gICAgICB1c2VyS2V5Q29tYmluZWQueVNoYXJlc1tzaWduZXJUd29JbmRleF0sXG4gICAgICByYW5nZVByb29mQ2hhbGxlbmdlLFxuICAgICAgRWNkc2FUeXBlcy5zZXJpYWxpemVQYWlsbGllckNoYWxsZW5nZSh7IHA6IGJhY2t1cFRvVXNlclBhaWxsaWVyQ2hhbGxlbmdlIH0pXG4gICAgKTtcbiAgICBjb25zdCBiYWNrdXBYU2hhcmUgPSBNUEMuYXBwZW5kQ2hhbGxlbmdlKFxuICAgICAgYmFja3VwS2V5Q29tYmluZWQueFNoYXJlLFxuICAgICAgcmFuZ2VQcm9vZkNoYWxsZW5nZSxcbiAgICAgIEVjZHNhVHlwZXMuc2VyaWFsaXplUGFpbGxpZXJDaGFsbGVuZ2UoeyBwOiBiYWNrdXBUb1VzZXJQYWlsbGllckNoYWxsZW5nZSB9KVxuICAgICk7XG4gICAgY29uc3QgYmFja3VwWVNoYXJlID0gTVBDLmFwcGVuZENoYWxsZW5nZShcbiAgICAgIGJhY2t1cEtleUNvbWJpbmVkLnlTaGFyZXNbc2lnbmVyT25lSW5kZXhdLFxuICAgICAgcmFuZ2VQcm9vZkNoYWxsZW5nZSxcbiAgICAgIEVjZHNhVHlwZXMuc2VyaWFsaXplUGFpbGxpZXJDaGFsbGVuZ2UoeyBwOiB1c2VyVG9CYWNrdXBQYWlsbGllckNoYWxsZW5nZSB9KVxuICAgICk7XG5cbiAgICBjb25zdCBzaWduU2hhcmVzOiBFQ0RTQS5TaWduU2hhcmVSVCA9IGF3YWl0IE1QQy5zaWduU2hhcmUodXNlclhTaGFyZSwgdXNlcllTaGFyZSk7XG5cbiAgICBjb25zdCBzaWduQ29udmVydFMyMSA9IGF3YWl0IE1QQy5zaWduQ29udmVydFN0ZXAxKHtcbiAgICAgIHhTaGFyZTogYmFja3VwWFNoYXJlLFxuICAgICAgeVNoYXJlOiBiYWNrdXBZU2hhcmUsIC8vIFlTaGFyZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBvdGhlciBwYXJ0aWNpcGFudCBzaWduZXJPbmVcbiAgICAgIGtTaGFyZTogc2lnblNoYXJlcy5rU2hhcmUsXG4gICAgfSk7XG4gICAgY29uc3Qgc2lnbkNvbnZlcnRTMTIgPSBhd2FpdCBNUEMuc2lnbkNvbnZlcnRTdGVwMih7XG4gICAgICBhU2hhcmU6IHNpZ25Db252ZXJ0UzIxLmFTaGFyZSxcbiAgICAgIHdTaGFyZTogc2lnblNoYXJlcy53U2hhcmUsXG4gICAgfSk7XG4gICAgY29uc3Qgc2lnbkNvbnZlcnRTMjFfMiA9IGF3YWl0IE1QQy5zaWduQ29udmVydFN0ZXAzKHtcbiAgICAgIG11U2hhcmU6IHNpZ25Db252ZXJ0UzEyLm11U2hhcmUsXG4gICAgICBiU2hhcmU6IHNpZ25Db252ZXJ0UzIxLmJTaGFyZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IFtzaWduQ29tYmluZU9uZSwgc2lnbkNvbWJpbmVUd29dID0gW1xuICAgICAgTVBDLnNpZ25Db21iaW5lKHtcbiAgICAgICAgZ1NoYXJlOiBzaWduQ29udmVydFMxMi5nU2hhcmUsXG4gICAgICAgIHNpZ25JbmRleDoge1xuICAgICAgICAgIGk6IHNpZ25Db252ZXJ0UzEyLm11U2hhcmUuaSxcbiAgICAgICAgICBqOiBzaWduQ29udmVydFMxMi5tdVNoYXJlLmosXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICAgIE1QQy5zaWduQ29tYmluZSh7XG4gICAgICAgIGdTaGFyZTogc2lnbkNvbnZlcnRTMjFfMi5nU2hhcmUsXG4gICAgICAgIHNpZ25JbmRleDoge1xuICAgICAgICAgIGk6IHNpZ25Db252ZXJ0UzIxXzIuc2lnbkluZGV4LmksXG4gICAgICAgICAgajogc2lnbkNvbnZlcnRTMjFfMi5zaWduSW5kZXguaixcbiAgICAgICAgfSxcbiAgICAgIH0pLFxuICAgIF07XG5cbiAgICBjb25zdCBNRVNTQUdFID0gQnVmZmVyLmZyb20odHhIZXgsICdoZXgnKTtcblxuICAgIGNvbnN0IFtzaWduQSwgc2lnbkJdID0gW1xuICAgICAgTVBDLnNpZ24oTUVTU0FHRSwgc2lnbkNvbWJpbmVPbmUub1NoYXJlLCBzaWduQ29tYmluZVR3by5kU2hhcmUsIEtlY2Nhaygna2VjY2FrMjU2JykpLFxuICAgICAgTVBDLnNpZ24oTUVTU0FHRSwgc2lnbkNvbWJpbmVUd28ub1NoYXJlLCBzaWduQ29tYmluZU9uZS5kU2hhcmUsIEtlY2Nhaygna2VjY2FrMjU2JykpLFxuICAgIF07XG5cbiAgICByZXR1cm4gTVBDLmNvbnN0cnVjdFNpZ25hdHVyZShbc2lnbkEsIHNpZ25CXSk7XG4gIH1cblxuICAvKipcbiAgICogSGVscGVyIHdoaWNoIGNvbWJpbmVzIGtleSBzaGFyZXMgb2YgdXNlciBhbmQgYmFja3VwXG4gICAqICovXG4gIHByaXZhdGUgZ2V0S2V5Q29tYmluZWRGcm9tVHNzS2V5U2hhcmVzKFxuICAgIHVzZXJQdWJsaWNPclByaXZhdGVLZXlTaGFyZTogc3RyaW5nLFxuICAgIGJhY2t1cFByaXZhdGVPclB1YmxpY0tleVNoYXJlOiBzdHJpbmcsXG4gICAgd2FsbGV0UGFzc3BocmFzZT86IHN0cmluZ1xuICApOiBbRUNEU0FNZXRob2RUeXBlcy5LZXlDb21iaW5lZCwgRUNEU0FNZXRob2RUeXBlcy5LZXlDb21iaW5lZF0ge1xuICAgIGxldCBiYWNrdXBQcnY7XG4gICAgbGV0IHVzZXJQcnY7XG4gICAgdHJ5IHtcbiAgICAgIGJhY2t1cFBydiA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgIGlucHV0OiBiYWNrdXBQcml2YXRlT3JQdWJsaWNLZXlTaGFyZSxcbiAgICAgICAgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICB9KTtcbiAgICAgIHVzZXJQcnYgPSB0aGlzLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICBpbnB1dDogdXNlclB1YmxpY09yUHJpdmF0ZUtleVNoYXJlLFxuICAgICAgICBwYXNzd29yZDogd2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyBiYWNrdXAga2V5Y2hhaW46ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cblxuICAgIGNvbnN0IHVzZXJTaWduaW5nTWF0ZXJpYWwgPSBKU09OLnBhcnNlKHVzZXJQcnYpIGFzIEVDRFNBTWV0aG9kVHlwZXMuU2lnbmluZ01hdGVyaWFsO1xuICAgIGNvbnN0IGJhY2t1cFNpZ25pbmdNYXRlcmlhbCA9IEpTT04ucGFyc2UoYmFja3VwUHJ2KSBhcyBFQ0RTQU1ldGhvZFR5cGVzLlNpZ25pbmdNYXRlcmlhbDtcblxuICAgIGlmICghdXNlclNpZ25pbmdNYXRlcmlhbC5iYWNrdXBOU2hhcmUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB1c2VyIGtleSAtIG1pc3NpbmcgYmFja3VwTlNoYXJlJyk7XG4gICAgfVxuXG4gICAgaWYgKCFiYWNrdXBTaWduaW5nTWF0ZXJpYWwudXNlck5TaGFyZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGJhY2t1cCBrZXkgLSBtaXNzaW5nIHVzZXJOU2hhcmUnKTtcbiAgICB9XG5cbiAgICBjb25zdCBNUEMgPSBuZXcgRWNkc2EoKTtcblxuICAgIGNvbnN0IHVzZXJLZXlDb21iaW5lZCA9IE1QQy5rZXlDb21iaW5lKHVzZXJTaWduaW5nTWF0ZXJpYWwucFNoYXJlLCBbXG4gICAgICB1c2VyU2lnbmluZ01hdGVyaWFsLmJpdGdvTlNoYXJlLFxuICAgICAgdXNlclNpZ25pbmdNYXRlcmlhbC5iYWNrdXBOU2hhcmUsXG4gICAgXSk7XG4gICAgY29uc3QgYmFja3VwS2V5Q29tYmluZWQgPSBNUEMua2V5Q29tYmluZShiYWNrdXBTaWduaW5nTWF0ZXJpYWwucFNoYXJlLCBbXG4gICAgICBiYWNrdXBTaWduaW5nTWF0ZXJpYWwuYml0Z29OU2hhcmUsXG4gICAgICBiYWNrdXBTaWduaW5nTWF0ZXJpYWwudXNlck5TaGFyZSxcbiAgICBdKTtcblxuICAgIGlmIChcbiAgICAgIHVzZXJLZXlDb21iaW5lZC54U2hhcmUueSAhPT0gYmFja3VwS2V5Q29tYmluZWQueFNoYXJlLnkgfHxcbiAgICAgIHVzZXJLZXlDb21iaW5lZC54U2hhcmUuY2hhaW5jb2RlICE9PSBiYWNrdXBLZXlDb21iaW5lZC54U2hhcmUuY2hhaW5jb2RlXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbW1vbiBrZXljaGFpbnMgZG8gbm90IG1hdGNoJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFt1c2VyS2V5Q29tYmluZWQsIGJhY2t1cEtleUNvbWJpbmVkXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgd2hpY2ggQWRkcyBzaWduYXR1cmVzIHRvIHR4IG9iamVjdCBhbmQgcmUtc2VyaWFsaXplcyB0eFxuICAgKiAqL1xuICBwcml2YXRlIGdldFNpZ25lZFR4RnJvbVNpZ25hdHVyZShcbiAgICBldGhDb21tb246IEV0aENvbW1vbi5kZWZhdWx0LFxuICAgIHR4OiBFdGhUeExpYi5GZWVNYXJrZXRFSVAxNTU5VHJhbnNhY3Rpb24gfCBFdGhUeExpYi5UcmFuc2FjdGlvbixcbiAgICBzaWduYXR1cmU6IEVDRFNBTWV0aG9kVHlwZXMuU2lnbmF0dXJlXG4gICkge1xuICAgIC8vIGdldCBzaWduZWQgVHggZnJvbSBzaWduYXR1cmVcbiAgICBjb25zdCB0eERhdGEgPSB0eC50b0pTT04oKTtcbiAgICBjb25zdCB5UGFyaXR5ID0gc2lnbmF0dXJlLnJlY2lkO1xuICAgIGNvbnN0IGJhc2VQYXJhbXMgPSB7XG4gICAgICB0bzogdHhEYXRhLnRvLFxuICAgICAgbm9uY2U6IG5ldyBCTihzdHJpcEhleFByZWZpeCh0eERhdGEubm9uY2UhKSwgJ2hleCcpLFxuICAgICAgdmFsdWU6IG5ldyBCTihzdHJpcEhleFByZWZpeCh0eERhdGEudmFsdWUhKSwgJ2hleCcpLFxuICAgICAgZ2FzTGltaXQ6IG5ldyBCTihzdHJpcEhleFByZWZpeCh0eERhdGEuZ2FzTGltaXQhKSwgJ2hleCcpLFxuICAgICAgZGF0YTogdHhEYXRhLmRhdGEsXG4gICAgICByOiBhZGRIZXhQcmVmaXgoc2lnbmF0dXJlLnIpLFxuICAgICAgczogYWRkSGV4UHJlZml4KHNpZ25hdHVyZS5zKSxcbiAgICB9O1xuXG4gICAgbGV0IGZpbmFsVHg7XG4gICAgaWYgKHR4RGF0YS5tYXhGZWVQZXJHYXMgJiYgdHhEYXRhLm1heFByaW9yaXR5RmVlUGVyR2FzKSB7XG4gICAgICBmaW5hbFR4ID0gRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLmZyb21UeERhdGEoXG4gICAgICAgIHtcbiAgICAgICAgICAuLi5iYXNlUGFyYW1zLFxuICAgICAgICAgIG1heFByaW9yaXR5RmVlUGVyR2FzOiBuZXcgQk4oc3RyaXBIZXhQcmVmaXgodHhEYXRhLm1heFByaW9yaXR5RmVlUGVyR2FzISksICdoZXgnKSxcbiAgICAgICAgICBtYXhGZWVQZXJHYXM6IG5ldyBCTihzdHJpcEhleFByZWZpeCh0eERhdGEubWF4RmVlUGVyR2FzISksICdoZXgnKSxcbiAgICAgICAgICB2OiBuZXcgQk4oeVBhcml0eS50b1N0cmluZygpKSxcbiAgICAgICAgfSxcbiAgICAgICAgeyBjb21tb246IGV0aENvbW1vbiB9XG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAodHhEYXRhLmdhc1ByaWNlKSB7XG4gICAgICBjb25zdCB2ID0gQmlnSW50KDM1KSArIEJpZ0ludCh5UGFyaXR5KSArIEJpZ0ludChldGhDb21tb24uY2hhaW5JZEJOKCkudG9OdW1iZXIoKSkgKiBCaWdJbnQoMik7XG4gICAgICBmaW5hbFR4ID0gTGVnYWN5VHJhbnNhY3Rpb24uZnJvbVR4RGF0YShcbiAgICAgICAge1xuICAgICAgICAgIC4uLmJhc2VQYXJhbXMsXG4gICAgICAgICAgdjogbmV3IEJOKHYudG9TdHJpbmcoKSksXG4gICAgICAgICAgZ2FzUHJpY2U6IG5ldyBCTihzdHJpcEhleFByZWZpeCh0eERhdGEuZ2FzUHJpY2UhLnRvU3RyaW5nKCkpLCAnaGV4JyksXG4gICAgICAgIH0sXG4gICAgICAgIHsgY29tbW9uOiBldGhDb21tb24gfVxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmluYWxUeDtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgYSBmdW5kcyByZWNvdmVyeSB0cmFuc2FjdGlvbiB3aXRob3V0IEJpdEdvXG4gICAqIEBwYXJhbSBwYXJhbXNcbiAgICogQHBhcmFtIHBhcmFtcy51c2VyS2V5IHtTdHJpbmd9IFtlbmNyeXB0ZWRdIHhwcnZcbiAgICogQHBhcmFtIHBhcmFtcy5iYWNrdXBLZXkge1N0cmluZ30gW2VuY3J5cHRlZF0geHBydiBvciB4cHViIGlmIHRoZSB4cHJ2IGlzIGhlbGQgYnkgYSBLUlMgcHJvdmlkZXJcbiAgICogQHBhcmFtIHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlIHtTdHJpbmd9IHVzZWQgdG8gZGVjcnlwdCB1c2VyS2V5IGFuZCBiYWNrdXBLZXlcbiAgICogQHBhcmFtIHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3Mge1N0cmluZ30gdGhlIEVUSCBhZGRyZXNzIG9mIHRoZSB3YWxsZXQgY29udHJhY3RcbiAgICogQHBhcmFtIHBhcmFtcy5rcnNQcm92aWRlciB7U3RyaW5nfSBuZWNlc3NhcnkgaWYgYmFja3VwIGtleSBpcyBoZWxkIGJ5IEtSU1xuICAgKiBAcGFyYW0gcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24ge1N0cmluZ30gdGFyZ2V0IGFkZHJlc3MgdG8gc2VuZCByZWNvdmVyZWQgZnVuZHMgdG9cbiAgICogQHBhcmFtIHBhcmFtcy5iaXRnb0ZlZUFkZHJlc3Mge1N0cmluZ30gd3JvbmcgY2hhaW4gd2FsbGV0IGZlZSBhZGRyZXNzIGZvciBldm0gYmFzZWQgY3Jvc3MgY2hhaW4gcmVjb3ZlcnkgdHhuXG4gICAqIEBwYXJhbSBwYXJhbXMuYml0Z29EZXN0aW5hdGlvbkFkZHJlc3Mge1N0cmluZ30gdGFyZ2V0IGJpdGdvIGFkZHJlc3Mgd2hlcmUgZmVlIHdpbGwgYmUgc2VudCBmb3IgZXZtIGJhc2VkIGNyb3NzIGNoYWluIHJlY292ZXJ5IHR4blxuICAgKi9cbiAgYXN5bmMgcmVjb3ZlcihwYXJhbXM6IFJlY292ZXJPcHRpb25zKTogUHJvbWlzZTxSZWNvdmVyeUluZm8gfCBPZmZsaW5lVmF1bHRUeEluZm8+IHtcbiAgICBpZiAocGFyYW1zLmlzVHNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWNvdmVyVFNTKHBhcmFtcyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnJlY292ZXJFdGhMaWtlKHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgdW5zaWduZWQgKGZvciBjb2xkLCBjdXN0b2R5IHdhbGxldCkgb3JcbiAgICogaGFsZi1zaWduZWQgKGZvciBob3Qgd2FsbGV0KSBldm0gY3Jvc3MgY2hhaW4gcmVjb3ZlcnkgdHJhbnNhY3Rpb24gd2l0aFxuICAgKiBzYW1lIGV4cGVjdGVkIGFyZ3VtZW50cyBhcyByZWNvdmVyIG1ldGhvZC5cbiAgICogVGhpcyBoZWxwcyByZWNvdmVyIGZ1bmRzIGZyb20gZXZtIGJhc2VkIHdyb25nIGNoYWluLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlY292ZXJFdGhMaWtlZm9yRXZtQmFzZWRSZWNvdmVyeShcbiAgICBwYXJhbXM6IFJlY292ZXJPcHRpb25zXG4gICk6IFByb21pc2U8UmVjb3ZlcnlJbmZvIHwgT2ZmbGluZVZhdWx0VHhJbmZvPiB7XG4gICAgdGhpcy52YWxpZGF0ZUV2bUJhc2VkUmVjb3ZlcnlQYXJhbXMocGFyYW1zKTtcblxuICAgIC8vIENsZWFuIHVwIHdoaXRlc3BhY2UgZnJvbSBlbnRlcmVkIHZhbHVlc1xuICAgIGNvbnN0IHVzZXJLZXkgPSBwYXJhbXMudXNlcktleS5yZXBsYWNlKC9cXHMvZywgJycpO1xuICAgIGNvbnN0IGJpdGdvRmVlQWRkcmVzcyA9IHBhcmFtcy5iaXRnb0ZlZUFkZHJlc3M/LnJlcGxhY2UoL1xccy9nLCAnJykgYXMgc3RyaW5nO1xuICAgIGNvbnN0IGJpdGdvRGVzdGluYXRpb25BZGRyZXNzID0gcGFyYW1zLmJpdGdvRGVzdGluYXRpb25BZGRyZXNzPy5yZXBsYWNlKC9cXHMvZywgJycpIGFzIHN0cmluZztcbiAgICBjb25zdCByZWNvdmVyeURlc3RpbmF0aW9uID0gcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24/LnJlcGxhY2UoL1xccy9nLCAnJykgYXMgc3RyaW5nO1xuICAgIGNvbnN0IHdhbGxldENvbnRyYWN0QWRkcmVzcyA9IHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3M/LnJlcGxhY2UoL1xccy9nLCAnJykgYXMgc3RyaW5nO1xuICAgIGNvbnN0IHRva2VuQ29udHJhY3RBZGRyZXNzID0gcGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzPy5yZXBsYWNlKC9cXHMvZywgJycpIGFzIHN0cmluZztcblxuICAgIGxldCB1c2VyU2lnbmluZ0tleTtcbiAgICBsZXQgdXNlcktleVBydjtcbiAgICBpZiAocGFyYW1zLndhbGxldFBhc3NwaHJhc2UpIHtcbiAgICAgIGlmICghdXNlcktleS5zdGFydHNXaXRoKCd4cHViJykgJiYgIXVzZXJLZXkuc3RhcnRzV2l0aCgneHBydicpKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdXNlcktleVBydiA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgICAgICBpbnB1dDogdXNlcktleSxcbiAgICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZGVjcnlwdGluZyB1c2VyIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBrZXlQYWlyID0gbmV3IEtleVBhaXJMaWIoeyBwcnY6IHVzZXJLZXlQcnYgfSk7XG4gICAgICB1c2VyU2lnbmluZ0tleSA9IGtleVBhaXIuZ2V0S2V5cygpLnBydjtcbiAgICAgIGlmICghdXNlclNpZ25pbmdLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlIGtleScpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGdhc0xpbWl0ID0gbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHRoaXMuc2V0R2FzTGltaXQocGFyYW1zLmdhc0xpbWl0KSk7XG4gICAgY29uc3QgZ2FzUHJpY2UgPSBwYXJhbXMuZWlwMTU1OVxuICAgICAgPyBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4ocGFyYW1zLmVpcDE1NTkubWF4RmVlUGVyR2FzKVxuICAgICAgOiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4odGhpcy5zZXRHYXNQcmljZShwYXJhbXMuZ2FzUHJpY2UpKTtcblxuICAgIGNvbnN0IGJpdGdvRmVlQWRkcmVzc05vbmNlID0gYXdhaXQgdGhpcy5nZXRBZGRyZXNzTm9uY2UoYml0Z29GZWVBZGRyZXNzKTtcblxuICAgIC8vIGdldCBiYWxhbmNlIG9mIGJpdGdvRmVlQWRkcmVzcyB0byBlbnN1cmUgZnVuZHMgYXJlIGF2YWlsYWJsZSB0byBwYXkgZmVlc1xuICAgIGNvbnN0IGJpdGdvRmVlQWRkcmVzc0JhbGFuY2UgPSBhd2FpdCB0aGlzLnF1ZXJ5QWRkcmVzc0JhbGFuY2UoYml0Z29GZWVBZGRyZXNzKTtcbiAgICBjb25zdCB0b3RhbEdhc05lZWRlZCA9IGdhc1ByaWNlLm11bChnYXNMaW1pdCk7XG4gICAgY29uc3Qgd2VpVG9Hd2VpID0gMTAgKiogOTtcbiAgICBpZiAoYml0Z29GZWVBZGRyZXNzQmFsYW5jZS5sdCh0b3RhbEdhc05lZWRlZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZlZSBhZGRyZXNzICR7Yml0Z29GZWVBZGRyZXNzQmFsYW5jZX0gaGFzIGJhbGFuY2UgJHsoYml0Z29GZWVBZGRyZXNzQmFsYW5jZSAvIHdlaVRvR3dlaSkudG9TdHJpbmcoKX0gR3dlaS5gICtcbiAgICAgICAgICBgVGhpcyBhZGRyZXNzIG11c3QgaGF2ZSBhIGJhbGFuY2Ugb2YgYXQgbGVhc3QgJHsodG90YWxHYXNOZWVkZWQgLyB3ZWlUb0d3ZWkpLnRvU3RyaW5nKCl9YCArXG4gICAgICAgICAgYCBHd2VpIHRvIHBlcmZvcm0gcmVjb3Zlcmllcy4gVHJ5IHNlbmRpbmcgc29tZSAke3RoaXMuZ2V0Q2hhaW4oKX0gdG8gdGhpcyBhZGRyZXNzIHRoZW4gcmV0cnkuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodG9rZW5Db250cmFjdEFkZHJlc3MpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlY292ZXJFdGhMaWtlVG9rZW5mb3JFdm1CYXNlZFJlY292ZXJ5KFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgIGJpdGdvRmVlQWRkcmVzc05vbmNlLFxuICAgICAgICBnYXNMaW1pdCxcbiAgICAgICAgZ2FzUHJpY2UsXG4gICAgICAgIHVzZXJLZXksXG4gICAgICAgIHVzZXJTaWduaW5nS2V5XG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIGdldCBiYWxhbmNlIG9mIHdhbGxldFxuICAgIGNvbnN0IHR4QW1vdW50ID0gYXdhaXQgdGhpcy5xdWVyeUFkZHJlc3NCYWxhbmNlKHdhbGxldENvbnRyYWN0QWRkcmVzcyk7XG5cbiAgICBjb25zdCBiaXRnb0ZlZVBlcmNlbnRhZ2UgPSAwOyAvLyBUT0RPOiBCRy03MTkxMiBjYW4gY2hhbmdlIHRoZSBmZWUlIGhlcmUuXG4gICAgY29uc3QgYml0Z29GZWVBbW91bnQgPSB0eEFtb3VudCAqIChiaXRnb0ZlZVBlcmNlbnRhZ2UgLyAxMDApO1xuXG4gICAgLy8gYnVpbGQgcmVjaXBpZW50cyBvYmplY3RcbiAgICBjb25zdCByZWNpcGllbnRzOiBSZWNpcGllbnRbXSA9IFtcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczogcmVjb3ZlcnlEZXN0aW5hdGlvbixcbiAgICAgICAgYW1vdW50OiBuZXcgQmlnTnVtYmVyKHR4QW1vdW50KS5taW51cyhiaXRnb0ZlZUFtb3VudCkudG9GaXhlZCgpLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgaWYgKGJpdGdvRmVlUGVyY2VudGFnZSA+IDApIHtcbiAgICAgIGlmIChfLmlzVW5kZWZpbmVkKGJpdGdvRGVzdGluYXRpb25BZGRyZXNzKSB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhiaXRnb0Rlc3RpbmF0aW9uQWRkcmVzcykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpdGdvRGVzdGluYXRpb25BZGRyZXNzJyk7XG4gICAgICB9XG5cbiAgICAgIHJlY2lwaWVudHMucHVzaCh7XG4gICAgICAgIGFkZHJlc3M6IGJpdGdvRGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgICBhbW91bnQ6IGJpdGdvRmVlQW1vdW50LnRvU3RyaW5nKDEwKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIGNhbGN1bGF0ZSBiYXRjaCBkYXRhXG4gICAgY29uc3QgQkFUQ0hfTUVUSE9EX05BTUUgPSAnYmF0Y2gnO1xuICAgIGNvbnN0IEJBVENIX01FVEhPRF9UWVBFUyA9IFsnYWRkcmVzc1tdJywgJ3VpbnQyNTZbXSddO1xuICAgIGNvbnN0IGJhdGNoRXhlY3V0aW9uSW5mbyA9IHRoaXMuZ2V0QmF0Y2hFeGVjdXRpb25JbmZvKHJlY2lwaWVudHMpO1xuICAgIGNvbnN0IGJhdGNoRGF0YSA9IG9wdGlvbmFsRGVwcy5ldGhVdGlsLmFkZEhleFByZWZpeChcbiAgICAgIHRoaXMuZ2V0TWV0aG9kQ2FsbERhdGEoQkFUQ0hfTUVUSE9EX05BTUUsIEJBVENIX01FVEhPRF9UWVBFUywgYmF0Y2hFeGVjdXRpb25JbmZvLnZhbHVlcykudG9TdHJpbmcoJ2hleCcpXG4gICAgKTtcblxuICAgIC8vIEdldCBzZXF1ZW5jZSBJRCB1c2luZyBjb250cmFjdCBjYWxsXG4gICAgLy8gd2UgbmVlZCB0byB3YWl0IGJldHdlZW4gbWFraW5nIHR3byBwb2x5Z29uc2NhbiBjYWxscyB0byBhdm9pZCBnZXR0aW5nIGJhbm5lZFxuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMDApKTtcbiAgICBjb25zdCBzZXF1ZW5jZUlkID0gYXdhaXQgdGhpcy5xdWVyeVNlcXVlbmNlSWQod2FsbGV0Q29udHJhY3RBZGRyZXNzKTtcblxuICAgIGNvbnN0IHR4SW5mbyA9IHtcbiAgICAgIHJlY2lwaWVudHM6IHJlY2lwaWVudHMsXG4gICAgICBleHBpcmVUaW1lOiB0aGlzLmdldERlZmF1bHRFeHBpcmVUaW1lKCksXG4gICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IHNlcXVlbmNlSWQsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQudG9TdHJpbmcoMTApLFxuICAgICAgaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeTogdHJ1ZSxcbiAgICB9O1xuXG4gICAgY29uc3QgbmV0d29yayA9IHRoaXMuZ2V0TmV0d29yaygpO1xuICAgIGNvbnN0IGJhdGNoZXJDb250cmFjdEFkZHJlc3MgPSBuZXR3b3JrPy5iYXRjaGVyQ29udHJhY3RBZGRyZXNzIGFzIHN0cmluZztcblxuICAgIGNvbnN0IHR4QnVpbGRlciA9IHRoaXMuZ2V0VHJhbnNhY3Rpb25CdWlsZGVyKCkgYXMgVHJhbnNhY3Rpb25CdWlsZGVyO1xuICAgIHR4QnVpbGRlci5jb3VudGVyKGJpdGdvRmVlQWRkcmVzc05vbmNlKTtcbiAgICB0eEJ1aWxkZXIuY29udHJhY3Qod2FsbGV0Q29udHJhY3RBZGRyZXNzKTtcbiAgICBsZXQgdHhGZWU7XG4gICAgaWYgKHBhcmFtcy5laXAxNTU5KSB7XG4gICAgICB0eEZlZSA9IHtcbiAgICAgICAgZWlwMTU1OToge1xuICAgICAgICAgIG1heFByaW9yaXR5RmVlUGVyR2FzOiBwYXJhbXMuZWlwMTU1OS5tYXhQcmlvcml0eUZlZVBlckdhcyxcbiAgICAgICAgICBtYXhGZWVQZXJHYXM6IHBhcmFtcy5laXAxNTU5Lm1heEZlZVBlckdhcyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHR4RmVlID0geyBmZWU6IGdhc1ByaWNlLnRvU3RyaW5nKCkgfTtcbiAgICB9XG4gICAgdHhCdWlsZGVyLmZlZSh7XG4gICAgICAuLi50eEZlZSxcbiAgICAgIGdhc0xpbWl0OiBnYXNMaW1pdC50b1N0cmluZygpLFxuICAgIH0pO1xuXG4gICAgY29uc3QgdHJhbnNmZXJCdWlsZGVyID0gdHhCdWlsZGVyLnRyYW5zZmVyKCkgYXMgVHJhbnNmZXJCdWlsZGVyO1xuXG4gICAgdHJhbnNmZXJCdWlsZGVyXG4gICAgICAuYW1vdW50KGJhdGNoRXhlY3V0aW9uSW5mby50b3RhbEFtb3VudClcbiAgICAgIC5jb250cmFjdFNlcXVlbmNlSWQoc2VxdWVuY2VJZClcbiAgICAgIC5leHBpcmF0aW9uVGltZSh0aGlzLmdldERlZmF1bHRFeHBpcmVUaW1lKCkpXG4gICAgICAudG8oYmF0Y2hlckNvbnRyYWN0QWRkcmVzcylcbiAgICAgIC5kYXRhKGJhdGNoRGF0YSk7XG5cbiAgICBpZiAocGFyYW1zLndhbGxldFBhc3NwaHJhc2UpIHtcbiAgICAgIHR4QnVpbGRlci50cmFuc2ZlcigpLmtleSh1c2VyU2lnbmluZ0tleSk7XG4gICAgfVxuXG4gICAgY29uc3QgdHggPSBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcblxuICAgIGNvbnN0IHJlc3BvbnNlOiBPZmZsaW5lVmF1bHRUeEluZm8gPSB7XG4gICAgICB0eEhleDogdHgudG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgIHVzZXJLZXksXG4gICAgICBjb2luOiB0aGlzLmdldENoYWluKCksXG4gICAgICBnYXNQcmljZTogb3B0aW9uYWxEZXBzLmV0aFV0aWwuYnVmZmVyVG9JbnQoZ2FzUHJpY2UpLnRvRml4ZWQoKSxcbiAgICAgIGdhc0xpbWl0LFxuICAgICAgcmVjaXBpZW50czogdHhJbmZvLnJlY2lwaWVudHMsXG4gICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHR4LnRvSnNvbigpLnRvLFxuICAgICAgYW1vdW50OiBiYXRjaEV4ZWN1dGlvbkluZm8udG90YWxBbW91bnQsXG4gICAgICBiYWNrdXBLZXlOb25jZTogYml0Z29GZWVBZGRyZXNzTm9uY2UsXG4gICAgICBlaXAxNTU5OiBwYXJhbXMuZWlwMTU1OSxcbiAgICB9O1xuICAgIF8uZXh0ZW5kKHJlc3BvbnNlLCB0eEluZm8pO1xuICAgIHJlc3BvbnNlLm5leHRDb250cmFjdFNlcXVlbmNlSWQgPSByZXNwb25zZS5jb250cmFjdFNlcXVlbmNlSWQ7XG5cbiAgICBpZiAocGFyYW1zLndhbGxldFBhc3NwaHJhc2UpIHtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeG46IEhhbGZTaWduZWRUcmFuc2FjdGlvbiA9IHtcbiAgICAgICAgaGFsZlNpZ25lZDoge1xuICAgICAgICAgIHR4SGV4OiB0eC50b0Jyb2FkY2FzdEZvcm1hdCgpLFxuICAgICAgICAgIHJlY2lwaWVudHM6IHR4SW5mby5yZWNpcGllbnRzLFxuICAgICAgICAgIGV4cGlyZVRpbWU6IHR4SW5mby5leHBpcmVUaW1lLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHJlc3BvbnNlLCBoYWxmU2lnbmVkVHhuKTtcblxuICAgICAgY29uc3QgZmVlc1VzZWQ6IEZlZXNVc2VkID0ge1xuICAgICAgICBnYXNQcmljZTogb3B0aW9uYWxEZXBzLmV0aFV0aWwuYnVmZmVyVG9JbnQoZ2FzUHJpY2UpLnRvRml4ZWQoKSxcbiAgICAgICAgZ2FzTGltaXQ6IG9wdGlvbmFsRGVwcy5ldGhVdGlsLmJ1ZmZlclRvSW50KGdhc0xpbWl0KS50b0ZpeGVkKCksXG4gICAgICB9O1xuICAgICAgcmVzcG9uc2VbJ2ZlZXNVc2VkJ10gPSBmZWVzVXNlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH1cblxuICBhc3luYyByZWNvdmVyRXRoTGlrZVRva2VuZm9yRXZtQmFzZWRSZWNvdmVyeShcbiAgICBwYXJhbXM6IFJlY292ZXJPcHRpb25zLFxuICAgIGJpdGdvRmVlQWRkcmVzc05vbmNlOiBudW1iZXIsXG4gICAgZ2FzTGltaXQsXG4gICAgZ2FzUHJpY2UsXG4gICAgdXNlcktleSxcbiAgICB1c2VyU2lnbmluZ0tleVxuICApIHtcbiAgICAvLyBnZXQgdG9rZW4gYmFsYW5jZSBvZiB3YWxsZXRcbiAgICBjb25zdCB0eEFtb3VudCA9IGF3YWl0IHRoaXMucXVlcnlBZGRyZXNzVG9rZW5CYWxhbmNlKFxuICAgICAgcGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzIGFzIHN0cmluZyxcbiAgICAgIHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3NcbiAgICApO1xuXG4gICAgLy8gYnVpbGQgcmVjaXBpZW50cyBvYmplY3RcbiAgICBjb25zdCByZWNpcGllbnRzOiBSZWNpcGllbnRbXSA9IFtcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudDogbmV3IEJpZ051bWJlcih0eEFtb3VudCkudG9GaXhlZCgpLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgLy8gR2V0IHNlcXVlbmNlIElEIHVzaW5nIGNvbnRyYWN0IGNhbGxcbiAgICAvLyB3ZSBuZWVkIHRvIHdhaXQgYmV0d2VlbiBtYWtpbmcgdHdvIHBvbHlnb25zY2FuIGNhbGxzIHRvIGF2b2lkIGdldHRpbmcgYmFubmVkXG4gICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMTAwMCkpO1xuICAgIGNvbnN0IHNlcXVlbmNlSWQgPSBhd2FpdCB0aGlzLnF1ZXJ5U2VxdWVuY2VJZChwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzKTtcblxuICAgIGNvbnN0IHR4SW5mbyA9IHtcbiAgICAgIHJlY2lwaWVudHM6IHJlY2lwaWVudHMsXG4gICAgICBleHBpcmVUaW1lOiB0aGlzLmdldERlZmF1bHRFeHBpcmVUaW1lKCksXG4gICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IHNlcXVlbmNlSWQsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQudG9TdHJpbmcoMTApLFxuICAgICAgaXNFdm1CYXNlZENyb3NzQ2hhaW5SZWNvdmVyeTogdHJ1ZSxcbiAgICB9O1xuXG4gICAgY29uc3QgdHhCdWlsZGVyID0gdGhpcy5nZXRUcmFuc2FjdGlvbkJ1aWxkZXIoKSBhcyBUcmFuc2FjdGlvbkJ1aWxkZXI7XG4gICAgdHhCdWlsZGVyLmNvdW50ZXIoYml0Z29GZWVBZGRyZXNzTm9uY2UpO1xuICAgIHR4QnVpbGRlci5jb250cmFjdChwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzIGFzIHN0cmluZyk7XG4gICAgbGV0IHR4RmVlO1xuICAgIGlmIChwYXJhbXMuZWlwMTU1OSkge1xuICAgICAgdHhGZWUgPSB7XG4gICAgICAgIGVpcDE1NTk6IHtcbiAgICAgICAgICBtYXhQcmlvcml0eUZlZVBlckdhczogcGFyYW1zLmVpcDE1NTkubWF4UHJpb3JpdHlGZWVQZXJHYXMsXG4gICAgICAgICAgbWF4RmVlUGVyR2FzOiBwYXJhbXMuZWlwMTU1OS5tYXhGZWVQZXJHYXMsXG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICB0eEZlZSA9IHsgZmVlOiBnYXNQcmljZS50b1N0cmluZygpIH07XG4gICAgfVxuICAgIHR4QnVpbGRlci5mZWUoe1xuICAgICAgLi4udHhGZWUsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQudG9TdHJpbmcoKSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHRyYW5zZmVyQnVpbGRlciA9IHR4QnVpbGRlci50cmFuc2ZlcigpIGFzIFRyYW5zZmVyQnVpbGRlcjtcblxuICAgIGNvbnN0IG5ldHdvcmsgPSB0aGlzLmdldE5ldHdvcmsoKTtcbiAgICBjb25zdCB0b2tlbiA9IGdldFRva2VuKHBhcmFtcy50b2tlbkNvbnRyYWN0QWRkcmVzcyBhcyBzdHJpbmcsIG5ldHdvcmsgYXMgRXRoZXJldW1OZXR3b3JrKT8ubmFtZSBhcyBzdHJpbmc7XG5cbiAgICB0cmFuc2ZlckJ1aWxkZXJcbiAgICAgIC5hbW91bnQodHhBbW91bnQpXG4gICAgICAuY29udHJhY3RTZXF1ZW5jZUlkKHNlcXVlbmNlSWQpXG4gICAgICAuZXhwaXJhdGlvblRpbWUodGhpcy5nZXREZWZhdWx0RXhwaXJlVGltZSgpKVxuICAgICAgLnRvKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKVxuICAgICAgLmNvaW4odG9rZW4pO1xuXG4gICAgaWYgKHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICB0eEJ1aWxkZXIudHJhbnNmZXIoKS5rZXkodXNlclNpZ25pbmdLZXkpO1xuICAgIH1cblxuICAgIGNvbnN0IHR4ID0gYXdhaXQgdHhCdWlsZGVyLmJ1aWxkKCk7XG5cbiAgICBjb25zdCByZXNwb25zZTogT2ZmbGluZVZhdWx0VHhJbmZvID0ge1xuICAgICAgdHhIZXg6IHR4LnRvQnJvYWRjYXN0Rm9ybWF0KCksXG4gICAgICB1c2VyS2V5LFxuICAgICAgY29pbjogdG9rZW4sXG4gICAgICBnYXNQcmljZTogb3B0aW9uYWxEZXBzLmV0aFV0aWwuYnVmZmVyVG9JbnQoZ2FzUHJpY2UpLnRvRml4ZWQoKSxcbiAgICAgIGdhc0xpbWl0LFxuICAgICAgcmVjaXBpZW50czogdHhJbmZvLnJlY2lwaWVudHMsXG4gICAgICB3YWxsZXRDb250cmFjdEFkZHJlc3M6IHR4LnRvSnNvbigpLnRvLFxuICAgICAgYW1vdW50OiB0eEFtb3VudC50b1N0cmluZygpLFxuICAgICAgYmFja3VwS2V5Tm9uY2U6IGJpdGdvRmVlQWRkcmVzc05vbmNlLFxuICAgICAgZWlwMTU1OTogcGFyYW1zLmVpcDE1NTksXG4gICAgfTtcbiAgICBfLmV4dGVuZChyZXNwb25zZSwgdHhJbmZvKTtcbiAgICByZXNwb25zZS5uZXh0Q29udHJhY3RTZXF1ZW5jZUlkID0gcmVzcG9uc2UuY29udHJhY3RTZXF1ZW5jZUlkO1xuXG4gICAgaWYgKHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlKSB7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHhuOiBIYWxmU2lnbmVkVHJhbnNhY3Rpb24gPSB7XG4gICAgICAgIGhhbGZTaWduZWQ6IHtcbiAgICAgICAgICB0eEhleDogdHgudG9Ccm9hZGNhc3RGb3JtYXQoKSxcbiAgICAgICAgICByZWNpcGllbnRzOiB0eEluZm8ucmVjaXBpZW50cyxcbiAgICAgICAgICBleHBpcmVUaW1lOiB0eEluZm8uZXhwaXJlVGltZSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBfLmV4dGVuZChyZXNwb25zZSwgaGFsZlNpZ25lZFR4bik7XG5cbiAgICAgIGNvbnN0IGZlZXNVc2VkOiBGZWVzVXNlZCA9IHtcbiAgICAgICAgZ2FzUHJpY2U6IG9wdGlvbmFsRGVwcy5ldGhVdGlsLmJ1ZmZlclRvSW50KGdhc1ByaWNlKS50b0ZpeGVkKCksXG4gICAgICAgIGdhc0xpbWl0OiBvcHRpb25hbERlcHMuZXRoVXRpbC5idWZmZXJUb0ludChnYXNMaW1pdCkudG9GaXhlZCgpLFxuICAgICAgfTtcbiAgICAgIHJlc3BvbnNlWydmZWVzVXNlZCddID0gZmVlc1VzZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3BvbnNlO1xuICB9XG5cbiAgdmFsaWRhdGVFdm1CYXNlZFJlY292ZXJ5UGFyYW1zKHBhcmFtczogUmVjb3Zlck9wdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMuYml0Z29GZWVBZGRyZXNzKSB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMuYml0Z29GZWVBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpdGdvRmVlQWRkcmVzcycpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MpIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgd2FsbGV0Q29udHJhY3RBZGRyZXNzJyk7XG4gICAgfVxuXG4gICAgaWYgKF8uaXNVbmRlZmluZWQocGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24pIHx8ICF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IHRyYW5zYWN0aW9uIGJ1aWxkZXIgZm9yIHRoZSBjdXJyZW50IGNoYWluXG4gICAqIEByZXR1cm4gYSBuZXcgdHJhbnNhY3Rpb24gYnVpbGRlclxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFRyYW5zYWN0aW9uQnVpbGRlcigpOiBUcmFuc2FjdGlvbkJ1aWxkZXIge1xuICAgIHJldHVybiBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyKGNvaW5zLmdldCh0aGlzLmdldEJhc2VDaGFpbigpKSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBiYXNlIGNoYWluIHRoYXQgdGhlIGNvaW4gZXhpc3RzIG9uLlxuICAgKi9cbiAgZ2V0QmFzZUNoYWluKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Q2hhaW4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdHlwZXMsIHZhbHVlcywgYW5kIHRvdGFsIGFtb3VudCBpbiB3ZWkgdG8gc2VuZCBpbiBhIGJhdGNoIHRyYW5zYWN0aW9uLCB1c2luZyB0aGUgbWV0aG9kIHNpZ25hdHVyZVxuICAgKiBgZGlzdHJpYnV0ZUJhdGNoKGFkZHJlc3NbXSwgdWludDI1NltdKWBcbiAgICogQHBhcmFtIHtSZWNpcGllbnRbXX0gcmVjaXBpZW50cyAtIHRyYW5zYWN0aW9uIHJlY2lwaWVudHNcbiAgICogQHJldHVybnMge0dldEJhdGNoRXhlY3V0aW9uSW5mb1JUfSBpbmZvcm1hdGlvbiBuZWVkZWQgdG8gZXhlY3V0ZSB0aGUgYmF0Y2ggdHJhbnNhY3Rpb25cbiAgICovXG4gIGdldEJhdGNoRXhlY3V0aW9uSW5mbyhyZWNpcGllbnRzOiBSZWNpcGllbnRbXSk6IEdldEJhdGNoRXhlY3V0aW9uSW5mb1JUIHtcbiAgICBjb25zdCBhZGRyZXNzZXM6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgYW1vdW50czogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgc3VtID0gbmV3IEJpZ051bWJlcignMCcpO1xuICAgIF8uZm9yRWFjaChyZWNpcGllbnRzLCAoeyBhZGRyZXNzLCBhbW91bnQgfSkgPT4ge1xuICAgICAgYWRkcmVzc2VzLnB1c2goYWRkcmVzcyk7XG4gICAgICBhbW91bnRzLnB1c2goYW1vdW50KTtcbiAgICAgIHN1bSA9IHN1bS5wbHVzKGFtb3VudCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdmFsdWVzOiBbYWRkcmVzc2VzLCBhbW91bnRzXSxcbiAgICAgIHRvdGFsQW1vdW50OiBzdW0udG9GaXhlZCgpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBkYXRhIHJlcXVpcmVkIHRvIG1ha2UgYW4gRVRIIGZ1bmN0aW9uIGNhbGwgZGVmaW5lZCBieSB0aGUgZ2l2ZW4gdHlwZXMgYW5kIHZhbHVlc1xuICAgKlxuICAgKiBAcGFyYW0gZnVuY3Rpb25OYW1lIFRoZSBuYW1lIG9mIHRoZSBmdW5jdGlvbiBiZWluZyBjYWxsZWQsIGUuZy4gdHJhbnNmZXJcbiAgICogQHBhcmFtIHR5cGVzIFRoZSB0eXBlcyBvZiB0aGUgZnVuY3Rpb24gY2FsbCBpbiBvcmRlclxuICAgKiBAcGFyYW0gdmFsdWVzIFRoZSB2YWx1ZXMgb2YgdGhlIGZ1bmN0aW9uIGNhbGwgaW4gb3JkZXJcbiAgICogQHJldHVybiB7QnVmZmVyfSBUaGUgY29tYmluZWQgZGF0YSBmb3IgdGhlIGZ1bmN0aW9uIGNhbGxcbiAgICovXG4gIGdldE1ldGhvZENhbGxEYXRhID0gKGZ1bmN0aW9uTmFtZSwgdHlwZXMsIHZhbHVlcykgPT4ge1xuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtcbiAgICAgIC8vIGZ1bmN0aW9uIHNpZ25hdHVyZVxuICAgICAgb3B0aW9uYWxEZXBzLmV0aEFiaS5tZXRob2RJRChmdW5jdGlvbk5hbWUsIHR5cGVzKSxcbiAgICAgIC8vIGZ1bmN0aW9uIGFyZ3VtZW50c1xuICAgICAgb3B0aW9uYWxEZXBzLmV0aEFiaS5yYXdFbmNvZGUodHlwZXMsIHZhbHVlcyksXG4gICAgXSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlY292ZXJzIGEgdHggd2l0aCBUU1Mga2V5IHNoYXJlc1xuICAgKiBzYW1lIGV4cGVjdGVkIGFyZ3VtZW50cyBhcyByZWNvdmVyIG1ldGhvZCwgYnV0IHdpdGggVFNTIGtleSBzaGFyZXNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWNvdmVyVFNTKHBhcmFtczogUmVjb3Zlck9wdGlvbnMpOiBQcm9taXNlPFJlY292ZXJ5SW5mbyB8IE9mZmxpbmVWYXVsdFR4SW5mbz4ge1xuICAgIHRoaXMudmFsaWRhdGVSZWNvdmVyeVBhcmFtcyhwYXJhbXMpO1xuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9IGdldElzVW5zaWduZWRTd2VlcChwYXJhbXMpO1xuXG4gICAgLy8gQ2xlYW4gdXAgd2hpdGVzcGFjZSBmcm9tIGVudGVyZWQgdmFsdWVzXG4gICAgY29uc3QgdXNlclB1YmxpY09yUHJpdmF0ZUtleVNoYXJlID0gcGFyYW1zLnVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBiYWNrdXBQcml2YXRlT3JQdWJsaWNLZXlTaGFyZSA9IHBhcmFtcy5iYWNrdXBLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcblxuICAgIC8vIFNldCBuZXcgZXRoIHR4IGZlZXMgKHVzaW5nIGRlZmF1bHQgY29uZmlnIHZhbHVlcyBmcm9tIHBsYXRmb3JtKVxuICAgIGNvbnN0IGdhc0xpbWl0ID0gbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHRoaXMuc2V0R2FzTGltaXQocGFyYW1zLmdhc0xpbWl0KSk7XG4gICAgY29uc3QgZ2FzUHJpY2UgPSBwYXJhbXMuZWlwMTU1OVxuICAgICAgPyBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4ocGFyYW1zLmVpcDE1NTkubWF4RmVlUGVyR2FzKVxuICAgICAgOiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4odGhpcy5zZXRHYXNQcmljZShwYXJhbXMuZ2FzUHJpY2UpKTtcblxuICAgIGNvbnN0IFtiYWNrdXBLZXlBZGRyZXNzLCB1c2VyS2V5Q29tYmluZWQsIGJhY2t1cEtleUNvbWJpbmVkXSA9ICgoKTogW1xuICAgICAgc3RyaW5nLFxuICAgICAgRUNEU0FNZXRob2RUeXBlcy5LZXlDb21iaW5lZCB8IHVuZGVmaW5lZCxcbiAgICAgIEVDRFNBTWV0aG9kVHlwZXMuS2V5Q29tYmluZWQgfCB1bmRlZmluZWRcbiAgICBdID0+IHtcbiAgICAgIGlmIChpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgICAgY29uc3QgYmFja3VwS2V5UGFpciA9IG5ldyBLZXlQYWlyTGliKHsgcHViOiBiYWNrdXBQcml2YXRlT3JQdWJsaWNLZXlTaGFyZSB9KTtcbiAgICAgICAgcmV0dXJuIFtiYWNrdXBLZXlQYWlyLmdldEFkZHJlc3MoKSwgdW5kZWZpbmVkLCB1bmRlZmluZWRdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgW3VzZXJLZXlDb21iaW5lZCwgYmFja3VwS2V5Q29tYmluZWRdID0gdGhpcy5nZXRLZXlDb21iaW5lZEZyb21Uc3NLZXlTaGFyZXMoXG4gICAgICAgICAgdXNlclB1YmxpY09yUHJpdmF0ZUtleVNoYXJlLFxuICAgICAgICAgIGJhY2t1cFByaXZhdGVPclB1YmxpY0tleVNoYXJlLFxuICAgICAgICAgIHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGJhY2t1cEtleVBhaXIgPSBuZXcgS2V5UGFpckxpYih7IHB1YjogYmFja3VwS2V5Q29tYmluZWQueFNoYXJlLnkgfSk7XG4gICAgICAgIHJldHVybiBbYmFja3VwS2V5UGFpci5nZXRBZGRyZXNzKCksIHVzZXJLZXlDb21iaW5lZCwgYmFja3VwS2V5Q29tYmluZWRdO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICBjb25zdCBiYWNrdXBLZXlOb25jZSA9IGF3YWl0IHRoaXMuZ2V0QWRkcmVzc05vbmNlKGJhY2t1cEtleUFkZHJlc3MpO1xuXG4gICAgLy8gZ2V0IGJhbGFuY2Ugb2YgYmFja3VwS2V5IHRvIGVuc3VyZSBmdW5kcyBhcmUgYXZhaWxhYmxlIHRvIHBheSBmZWVzXG4gICAgY29uc3QgYmFja3VwS2V5QmFsYW5jZSA9IGF3YWl0IHRoaXMucXVlcnlBZGRyZXNzQmFsYW5jZShiYWNrdXBLZXlBZGRyZXNzKTtcblxuICAgIGNvbnN0IHRvdGFsR2FzTmVlZGVkID0gZ2FzUHJpY2UubXVsKGdhc0xpbWl0KTtcbiAgICBjb25zdCB3ZWlUb0d3ZWkgPSAxMCAqKiA5O1xuICAgIGlmIChiYWNrdXBLZXlCYWxhbmNlLmx0KHRvdGFsR2FzTmVlZGVkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQmFja3VwIGtleSBhZGRyZXNzICR7YmFja3VwS2V5QWRkcmVzc30gaGFzIGJhbGFuY2UgJHsoYmFja3VwS2V5QmFsYW5jZSAvIHdlaVRvR3dlaSkudG9TdHJpbmcoKX0gR3dlaS5gICtcbiAgICAgICAgICBgVGhpcyBhZGRyZXNzIG11c3QgaGF2ZSBhIGJhbGFuY2Ugb2YgYXQgbGVhc3QgJHsodG90YWxHYXNOZWVkZWQgLyB3ZWlUb0d3ZWkpLnRvU3RyaW5nKCl9YCArXG4gICAgICAgICAgYCBHd2VpIHRvIHBlcmZvcm0gcmVjb3Zlcmllcy4gVHJ5IHNlbmRpbmcgc29tZSBFVEggdG8gdGhpcyBhZGRyZXNzIHRoZW4gcmV0cnkuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBnZXQgYmFsYW5jZSBvZiB3YWxsZXQgYW5kIGRlZHVjdCBmZWVzIHRvIGdldCB0cmFuc2FjdGlvbiBhbW91bnQsIHdhbGxldCBjb250cmFjdCBhZGRyZXNzIGFjdHMgYXMgYmFzZSBhZGRyZXNzIGZvciB0c3M/XG4gICAgY29uc3QgdHhBbW91bnQgPSBiYWNrdXBLZXlCYWxhbmNlLnN1Yih0b3RhbEdhc05lZWRlZCk7XG5cbiAgICAvLyBidWlsZCByZWNpcGllbnRzIG9iamVjdFxuICAgIGNvbnN0IHJlY2lwaWVudHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6IHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICBhbW91bnQ6IHR4QW1vdW50LnRvU3RyaW5nKDEwKSxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIGNvbnN0IHR4SW5mbyA9IHtcbiAgICAgIHJlY2lwaWVudDogcmVjaXBpZW50c1swXSxcbiAgICAgIGV4cGlyZVRpbWU6IHRoaXMuZ2V0RGVmYXVsdEV4cGlyZVRpbWUoKSxcbiAgICAgIGdhc0xpbWl0OiBnYXNMaW1pdC50b1N0cmluZygxMCksXG4gICAgfTtcblxuICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgdG86IHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLCAvLyBubyBjb250cmFjdCBhZGRyZXNzLCBzbyB0aGlzIGZpZWxkIHNob3VsZCBub3QgYmUgdXNlZCBhbnl3YXlzXG4gICAgICBub25jZTogYmFja3VwS2V5Tm9uY2UsXG4gICAgICB2YWx1ZTogdHhBbW91bnQsXG4gICAgICBnYXNQcmljZTogZ2FzUHJpY2UsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQsXG4gICAgICBkYXRhOiBCdWZmZXIuZnJvbSgnMHgnKSwgLy8gbm8gY29udHJhY3QgY2FsbFxuICAgICAgZWlwMTU1OTogcGFyYW1zLmVpcDE1NTksXG4gICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9uczogcGFyYW1zLnJlcGxheVByb3RlY3Rpb25PcHRpb25zLFxuICAgIH07XG5cbiAgICBsZXQgdHggPSBFdGguYnVpbGRUcmFuc2FjdGlvbih0eFBhcmFtcyk7XG5cbiAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICByZXR1cm4gdGhpcy5mb3JtYXRGb3JPZmZsaW5lVmF1bHRUU1MoXG4gICAgICAgIHR4SW5mbyxcbiAgICAgICAgdHgsXG4gICAgICAgIHVzZXJQdWJsaWNPclByaXZhdGVLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwUHJpdmF0ZU9yUHVibGljS2V5U2hhcmUsXG4gICAgICAgIGdhc1ByaWNlLFxuICAgICAgICBnYXNMaW1pdCxcbiAgICAgICAgYmFja3VwS2V5Tm9uY2UsXG4gICAgICAgIHBhcmFtcy5laXAxNTU5LFxuICAgICAgICBwYXJhbXMucmVwbGF5UHJvdGVjdGlvbk9wdGlvbnNcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2lnbmFibGVIZXggPSB0eC5nZXRNZXNzYWdlVG9TaWduKGZhbHNlKS50b1N0cmluZygnaGV4Jyk7XG4gICAgaWYgKCF1c2VyS2V5Q29tYmluZWQgfHwgIWJhY2t1cEtleUNvbWJpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcga2V5IGNvbWJpbmVkIHNoYXJlcyBmb3IgdXNlciBvciBiYWNrdXAnKTtcbiAgICB9XG4gICAgY29uc3Qgc2lnbmF0dXJlID0gYXdhaXQgdGhpcy5zaWduUmVjb3ZlcnlUU1ModXNlcktleUNvbWJpbmVkLCBiYWNrdXBLZXlDb21iaW5lZCwgc2lnbmFibGVIZXgpO1xuICAgIGNvbnN0IGV0aENvbW1tb24gPSBFdGguZ2V0RXRoQ29tbW9uKHBhcmFtcy5laXAxNTU5LCBwYXJhbXMucmVwbGF5UHJvdGVjdGlvbk9wdGlvbnMpO1xuICAgIHR4ID0gdGhpcy5nZXRTaWduZWRUeEZyb21TaWduYXR1cmUoZXRoQ29tbW1vbiwgdHgsIHNpZ25hdHVyZSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IGFkZEhleFByZWZpeCh0eC5oYXNoKCkudG9TdHJpbmcoJ2hleCcpKSxcbiAgICAgIHR4OiBhZGRIZXhQcmVmaXgodHguc2VyaWFsaXplKCkudG9TdHJpbmcoJ2hleCcpKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY292ZXJzIGEgdHggd2l0aCBub24tVFNTIGtleXNcbiAgICogc2FtZSBleHBlY3RlZCBhcmd1bWVudHMgYXMgcmVjb3ZlciBtZXRob2QgKG9yaWdpbmFsIGxvZ2ljIGJlZm9yZSBhZGRpbmcgVFNTIHJlY292ZXIgcGF0aClcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWNvdmVyRXRoTGlrZShwYXJhbXM6IFJlY292ZXJPcHRpb25zKTogUHJvbWlzZTxSZWNvdmVyeUluZm8gfCBPZmZsaW5lVmF1bHRUeEluZm8+IHtcbiAgICAvLyBiaXRnb0ZlZUFkZHJlc3MgaXMgb25seSBkZWZpbmVkIHdoZW4gaXQgaXMgYSBldm0gY3Jvc3MgY2hhaW4gcmVjb3ZlcnlcbiAgICAvLyBhcyB3ZSB1c2UgZmVlIGZyb20gdGhpcyB3cm9uZyBjaGFpbiBhZGRyZXNzIGZvciB0aGUgcmVjb3ZlcnkgdHhuIG9uIHRoZSBjb3JyZWN0IGNoYWluLlxuICAgIGlmIChwYXJhbXMuYml0Z29GZWVBZGRyZXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWNvdmVyRXRoTGlrZWZvckV2bUJhc2VkUmVjb3ZlcnkocGFyYW1zKTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlUmVjb3ZlcnlQYXJhbXMocGFyYW1zKTtcbiAgICBjb25zdCBpc0tyc1JlY292ZXJ5ID0gZ2V0SXNLcnNSZWNvdmVyeShwYXJhbXMpO1xuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9IGdldElzVW5zaWduZWRTd2VlcChwYXJhbXMpO1xuXG4gICAgaWYgKGlzS3JzUmVjb3ZlcnkpIHtcbiAgICAgIGNoZWNrS3JzUHJvdmlkZXIodGhpcywgcGFyYW1zLmtyc1Byb3ZpZGVyLCB7IGNoZWNrQ29pbkZhbWlseVN1cHBvcnQ6IGZhbHNlIH0pO1xuICAgIH1cblxuICAgIC8vIENsZWFuIHVwIHdoaXRlc3BhY2UgZnJvbSBlbnRlcmVkIHZhbHVlc1xuICAgIGxldCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBiYWNrdXBLZXkgPSBwYXJhbXMuYmFja3VwS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG5cbiAgICAvLyBTZXQgbmV3IGV0aCB0eCBmZWVzICh1c2luZyBkZWZhdWx0IGNvbmZpZyB2YWx1ZXMgZnJvbSBwbGF0Zm9ybSlcblxuICAgIGNvbnN0IGdhc0xpbWl0ID0gbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHRoaXMuc2V0R2FzTGltaXQocGFyYW1zLmdhc0xpbWl0KSk7XG4gICAgY29uc3QgZ2FzUHJpY2UgPSBwYXJhbXMuZWlwMTU1OVxuICAgICAgPyBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4ocGFyYW1zLmVpcDE1NTkubWF4RmVlUGVyR2FzKVxuICAgICAgOiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4odGhpcy5zZXRHYXNQcmljZShwYXJhbXMuZ2FzUHJpY2UpKTtcbiAgICBpZiAoIXVzZXJLZXkuc3RhcnRzV2l0aCgneHB1YicpICYmICF1c2VyS2V5LnN0YXJ0c1dpdGgoJ3hwcnYnKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdXNlcktleSA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgICAgaW5wdXQ6IHVzZXJLZXksXG4gICAgICAgICAgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBkZWNyeXB0aW5nIHVzZXIga2V5Y2hhaW46ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBiYWNrdXBLZXlBZGRyZXNzO1xuICAgIGxldCBiYWNrdXBTaWduaW5nS2V5O1xuXG4gICAgaWYgKGlzS3JzUmVjb3ZlcnkgfHwgaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICBjb25zdCBiYWNrdXBIRE5vZGUgPSBiaXAzMi5mcm9tQmFzZTU4KGJhY2t1cEtleSk7XG4gICAgICBiYWNrdXBTaWduaW5nS2V5ID0gYmFja3VwSEROb2RlLnB1YmxpY0tleTtcbiAgICAgIGJhY2t1cEtleUFkZHJlc3MgPSBgMHgke29wdGlvbmFsRGVwcy5ldGhVdGlsLnB1YmxpY1RvQWRkcmVzcyhiYWNrdXBTaWduaW5nS2V5LCB0cnVlKS50b1N0cmluZygnaGV4Jyl9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVjcnlwdCBiYWNrdXAgcHJpdmF0ZSBrZXkgYW5kIGdldCBhZGRyZXNzXG4gICAgICBsZXQgYmFja3VwUHJ2O1xuXG4gICAgICB0cnkge1xuICAgICAgICBiYWNrdXBQcnYgPSB0aGlzLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICAgIGlucHV0OiBiYWNrdXBLZXksXG4gICAgICAgICAgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBkZWNyeXB0aW5nIGJhY2t1cCBrZXljaGFpbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGJhY2t1cEhETm9kZSA9IGJpcDMyLmZyb21CYXNlNTgoYmFja3VwUHJ2KTtcbiAgICAgIGJhY2t1cFNpZ25pbmdLZXkgPSBiYWNrdXBIRE5vZGUucHJpdmF0ZUtleTtcbiAgICAgIGlmICghYmFja3VwSEROb2RlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbm8gcHJpdmF0ZSBrZXknKTtcbiAgICAgIH1cbiAgICAgIGJhY2t1cEtleUFkZHJlc3MgPSBgMHgke29wdGlvbmFsRGVwcy5ldGhVdGlsLnByaXZhdGVUb0FkZHJlc3MoYmFja3VwU2lnbmluZ0tleSkudG9TdHJpbmcoJ2hleCcpfWA7XG4gICAgfVxuXG4gICAgY29uc3QgYmFja3VwS2V5Tm9uY2UgPSBhd2FpdCB0aGlzLmdldEFkZHJlc3NOb25jZShiYWNrdXBLZXlBZGRyZXNzKTtcblxuICAgIC8vIGdldCBiYWxhbmNlIG9mIGJhY2t1cEtleSB0byBlbnN1cmUgZnVuZHMgYXJlIGF2YWlsYWJsZSB0byBwYXkgZmVlc1xuICAgIGNvbnN0IGJhY2t1cEtleUJhbGFuY2UgPSBhd2FpdCB0aGlzLnF1ZXJ5QWRkcmVzc0JhbGFuY2UoYmFja3VwS2V5QWRkcmVzcyk7XG5cbiAgICBjb25zdCB0b3RhbEdhc05lZWRlZCA9IGdhc1ByaWNlLm11bChnYXNMaW1pdCk7XG4gICAgY29uc3Qgd2VpVG9Hd2VpID0gMTAgKiogOTtcbiAgICBpZiAoYmFja3VwS2V5QmFsYW5jZS5sdCh0b3RhbEdhc05lZWRlZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEJhY2t1cCBrZXkgYWRkcmVzcyAke2JhY2t1cEtleUFkZHJlc3N9IGhhcyBiYWxhbmNlICR7KGJhY2t1cEtleUJhbGFuY2UgLyB3ZWlUb0d3ZWkpLnRvU3RyaW5nKCl9IEd3ZWkuYCArXG4gICAgICAgICAgYFRoaXMgYWRkcmVzcyBtdXN0IGhhdmUgYSBiYWxhbmNlIG9mIGF0IGxlYXN0ICR7KHRvdGFsR2FzTmVlZGVkIC8gd2VpVG9Hd2VpKS50b1N0cmluZygpfWAgK1xuICAgICAgICAgIGAgR3dlaSB0byBwZXJmb3JtIHJlY292ZXJpZXMuIFRyeSBzZW5kaW5nIHNvbWUgRVRIIHRvIHRoaXMgYWRkcmVzcyB0aGVuIHJldHJ5LmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gZ2V0IGJhbGFuY2Ugb2Ygd2FsbGV0IGFuZCBkZWR1Y3QgZmVlcyB0byBnZXQgdHJhbnNhY3Rpb24gYW1vdW50XG4gICAgY29uc3QgdHhBbW91bnQgPSBhd2FpdCB0aGlzLnF1ZXJ5QWRkcmVzc0JhbGFuY2UocGFyYW1zLndhbGxldENvbnRyYWN0QWRkcmVzcyk7XG5cbiAgICAvLyBidWlsZCByZWNpcGllbnRzIG9iamVjdFxuICAgIGNvbnN0IHJlY2lwaWVudHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6IHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uLFxuICAgICAgICBhbW91bnQ6IHR4QW1vdW50LnRvU3RyaW5nKDEwKSxcbiAgICAgIH0sXG4gICAgXTtcblxuICAgIC8vIEdldCBzZXF1ZW5jZSBJRCB1c2luZyBjb250cmFjdCBjYWxsXG4gICAgLy8gd2UgbmVlZCB0byB3YWl0IGJldHdlZW4gbWFraW5nIHR3byBldGhlcnNjYW4gY2FsbHMgdG8gYXZvaWQgZ2V0dGluZyBiYW5uZWRcbiAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDAwKSk7XG4gICAgY29uc3Qgc2VxdWVuY2VJZCA9IGF3YWl0IHRoaXMucXVlcnlTZXF1ZW5jZUlkKHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MpO1xuXG4gICAgbGV0IG9wZXJhdGlvbkhhc2gsIHNpZ25hdHVyZTtcbiAgICAvLyBHZXQgb3BlcmF0aW9uIGhhc2ggYW5kIHNpZ24gaXRcbiAgICBpZiAoIWlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgb3BlcmF0aW9uSGFzaCA9IHRoaXMuZ2V0T3BlcmF0aW9uU2hhM0ZvckV4ZWN1dGVBbmRDb25maXJtKHJlY2lwaWVudHMsIHRoaXMuZ2V0RGVmYXVsdEV4cGlyZVRpbWUoKSwgc2VxdWVuY2VJZCk7XG4gICAgICBzaWduYXR1cmUgPSBVdGlsLmV0aFNpZ25Nc2dIYXNoKG9wZXJhdGlvbkhhc2gsIFV0aWwueHBydlRvRXRoUHJpdmF0ZUtleSh1c2VyS2V5KSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIFV0aWwuZWNSZWNvdmVyRXRoQWRkcmVzcyhvcGVyYXRpb25IYXNoLCBzaWduYXR1cmUpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdHhJbmZvID0ge1xuICAgICAgcmVjaXBpZW50OiByZWNpcGllbnRzWzBdLFxuICAgICAgZXhwaXJlVGltZTogdGhpcy5nZXREZWZhdWx0RXhwaXJlVGltZSgpLFxuICAgICAgY29udHJhY3RTZXF1ZW5jZUlkOiBzZXF1ZW5jZUlkLFxuICAgICAgb3BlcmF0aW9uSGFzaDogb3BlcmF0aW9uSGFzaCxcbiAgICAgIHNpZ25hdHVyZTogc2lnbmF0dXJlLFxuICAgICAgZ2FzTGltaXQ6IGdhc0xpbWl0LnRvU3RyaW5nKDEwKSxcbiAgICB9O1xuXG4gICAgLy8gY2FsY3VsYXRlIHNlbmQgZGF0YVxuICAgIGNvbnN0IHNlbmRNZXRob2RBcmdzID0gdGhpcy5nZXRTZW5kTWV0aG9kQXJncyh0eEluZm8pO1xuICAgIGNvbnN0IG1ldGhvZFNpZ25hdHVyZSA9IG9wdGlvbmFsRGVwcy5ldGhBYmkubWV0aG9kSUQodGhpcy5zZW5kTWV0aG9kTmFtZSwgXy5tYXAoc2VuZE1ldGhvZEFyZ3MsICd0eXBlJykpO1xuICAgIGNvbnN0IGVuY29kZWRBcmdzID0gb3B0aW9uYWxEZXBzLmV0aEFiaS5yYXdFbmNvZGUoXy5tYXAoc2VuZE1ldGhvZEFyZ3MsICd0eXBlJyksIF8ubWFwKHNlbmRNZXRob2RBcmdzLCAndmFsdWUnKSk7XG4gICAgY29uc3Qgc2VuZERhdGEgPSBCdWZmZXIuY29uY2F0KFttZXRob2RTaWduYXR1cmUsIGVuY29kZWRBcmdzXSk7XG5cbiAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgIHRvOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgbm9uY2U6IGJhY2t1cEtleU5vbmNlLFxuICAgICAgdmFsdWU6IDAsXG4gICAgICBnYXNQcmljZTogZ2FzUHJpY2UsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQsXG4gICAgICBkYXRhOiBzZW5kRGF0YSxcbiAgICAgIGVpcDE1NTk6IHBhcmFtcy5laXAxNTU5LFxuICAgICAgcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnM6IHBhcmFtcy5yZXBsYXlQcm90ZWN0aW9uT3B0aW9ucyxcbiAgICB9O1xuXG4gICAgLy8gQnVpbGQgY29udHJhY3QgY2FsbCBhbmQgc2lnbiBpdFxuICAgIGxldCB0eCA9IEV0aC5idWlsZFRyYW5zYWN0aW9uKHR4UGFyYW1zKTtcblxuICAgIGlmIChpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIHJldHVybiB0aGlzLmZvcm1hdEZvck9mZmxpbmVWYXVsdChcbiAgICAgICAgdHhJbmZvLFxuICAgICAgICB0eCxcbiAgICAgICAgdXNlcktleSxcbiAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICBnYXNQcmljZSxcbiAgICAgICAgZ2FzTGltaXQsXG4gICAgICAgIHBhcmFtcy5laXAxNTU5LFxuICAgICAgICBwYXJhbXMucmVwbGF5UHJvdGVjdGlvbk9wdGlvbnNcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCFpc0tyc1JlY292ZXJ5KSB7XG4gICAgICB0eCA9IHR4LnNpZ24oYmFja3VwU2lnbmluZ0tleSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2lnbmVkVHg6IFJlY292ZXJ5SW5mbyA9IHtcbiAgICAgIGlkOiBvcHRpb25hbERlcHMuZXRoVXRpbC5idWZmZXJUb0hleCh0eC5oYXNoKCkpLFxuICAgICAgdHg6IHR4LnNlcmlhbGl6ZSgpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICB9O1xuXG4gICAgaWYgKGlzS3JzUmVjb3ZlcnkpIHtcbiAgICAgIHNpZ25lZFR4LmJhY2t1cEtleSA9IGJhY2t1cEtleTtcbiAgICAgIHNpZ25lZFR4LmNvaW4gPSB0aGlzLmdldENoYWluKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNpZ25lZFR4O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY292ZXIgYW4gdW5zdXBwb3J0ZWQgdG9rZW4gZnJvbSBhIEJpdEdvIG11bHRpc2lnIHdhbGxldFxuICAgKiBUaGlzIGJ1aWxkcyBhIGhhbGYtc2lnbmVkIHRyYW5zYWN0aW9uLCBmb3Igd2hpY2ggdGhlcmUgd2lsbCBiZSBhbiBhZG1pbiByb3V0ZSB0byBjby1zaWduIGFuZCBicm9hZGNhc3QuIE9wdGlvbmFsbHlcbiAgICogdGhlIHVzZXIgY2FuIHNldCBwYXJhbXMuYnJvYWRjYXN0ID0gdHJ1ZSBhbmQgdGhlIGhhbGYtc2lnbmVkIHR4IHdpbGwgYmUgc2VudCB0byBCaXRHbyBmb3IgY29zaWduaW5nIGFuZCBicm9hZGNhc3RpbmdcbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiBAcGFyYW0gcGFyYW1zLndhbGxldCB0aGUgd2FsbGV0IHRvIHJlY292ZXIgdGhlIHRva2VuIGZyb21cbiAgICogQHBhcmFtIHBhcmFtcy50b2tlbkNvbnRyYWN0QWRkcmVzcyB0aGUgY29udHJhY3QgYWRkcmVzcyBvZiB0aGUgdW5zdXBwb3J0ZWQgdG9rZW5cbiAgICogQHBhcmFtIHBhcmFtcy5yZWNpcGllbnQgdGhlIGRlc3RpbmF0aW9uIGFkZHJlc3MgcmVjb3ZlcmVkIHRva2VucyBzaG91bGQgYmUgc2VudCB0b1xuICAgKiBAcGFyYW0gcGFyYW1zLndhbGxldFBhc3NwaHJhc2UgdGhlIHdhbGxldCBwYXNzcGhyYXNlXG4gICAqIEBwYXJhbSBwYXJhbXMucHJ2IHRoZSB4cHJ2XG4gICAqIEBwYXJhbSBwYXJhbXMuYnJvYWRjYXN0IGlmIHRydWUsIHdlIHdpbGwgYXV0b21hdGljYWxseSBzdWJtaXQgdGhlIGhhbGYtc2lnbmVkIHR4IHRvIEJpdEdvIGZvciBjb3NpZ25pbmcgYW5kIGJyb2FkY2FzdGluZ1xuICAgKi9cbiAgYXN5bmMgcmVjb3ZlclRva2VuKHBhcmFtczogUmVjb3ZlclRva2VuT3B0aW9ucyk6IFByb21pc2U8UmVjb3ZlclRva2VuVHJhbnNhY3Rpb24+IHtcbiAgICBpZiAoIV8uaXNPYmplY3QocGFyYW1zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGByZWNvdmVyVG9rZW4gbXVzdCBiZSBwYXNzZWQgYSBwYXJhbXMgb2JqZWN0LiBHb3QgJHtwYXJhbXN9ICh0eXBlICR7dHlwZW9mIHBhcmFtc30pYCk7XG4gICAgfVxuXG4gICAgaWYgKF8uaXNVbmRlZmluZWQocGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzKSB8fCAhXy5pc1N0cmluZyhwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGB0b2tlbkNvbnRyYWN0QWRkcmVzcyBtdXN0IGJlIGEgc3RyaW5nLCBnb3QgJHtcbiAgICAgICAgICBwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3NcbiAgICAgICAgfSAodHlwZSAke3R5cGVvZiBwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3N9KWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy50b2tlbkNvbnRyYWN0QWRkcmVzcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndG9rZW5Db250cmFjdEFkZHJlc3Mgbm90IGEgdmFsaWQgYWRkcmVzcycpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy53YWxsZXQpIHx8ICEocGFyYW1zLndhbGxldCBpbnN0YW5jZW9mIFdhbGxldCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgd2FsbGV0IG11c3QgYmUgYSB3YWxsZXQgaW5zdGFuY2UsIGdvdCAke3BhcmFtcy53YWxsZXR9ICh0eXBlICR7dHlwZW9mIHBhcmFtcy53YWxsZXR9KWApO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtcy5yZWNpcGllbnQpIHx8ICFfLmlzU3RyaW5nKHBhcmFtcy5yZWNpcGllbnQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHJlY2lwaWVudCBtdXN0IGJlIGEgc3RyaW5nLCBnb3QgJHtwYXJhbXMucmVjaXBpZW50fSAodHlwZSAke3R5cGVvZiBwYXJhbXMucmVjaXBpZW50fSlgKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaXNWYWxpZEFkZHJlc3MocGFyYW1zLnJlY2lwaWVudCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncmVjaXBpZW50IG5vdCBhIHZhbGlkIGFkZHJlc3MnKTtcbiAgICB9XG5cbiAgICBpZiAoIW9wdGlvbmFsRGVwcy5ldGhVdGlsLmJ1ZmZlclRvSGV4IHx8ICFvcHRpb25hbERlcHMuZXRoQWJpLnNvbGlkaXR5U0hBMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdldGhlcmV1bSBub3QgZnVsbHkgc3VwcG9ydGVkIGluIHRoaXMgZW52aXJvbm1lbnQnKTtcbiAgICB9XG5cbiAgICAvLyBHZXQgdG9rZW4gYmFsYW5jZSBmcm9tIGV4dGVybmFsIEFQSVxuICAgIGNvbnN0IGNvaW5TcGVjaWZpYyA9IHBhcmFtcy53YWxsZXQuY29pblNwZWNpZmljKCk7XG4gICAgaWYgKCFjb2luU3BlY2lmaWMgfHwgIV8uaXNTdHJpbmcoY29pblNwZWNpZmljLmJhc2VBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIHJlcXVpcmVkIGNvaW4gc3BlY2lmaWMgcHJvcGVydHkgYmFzZUFkZHJlc3MnKTtcbiAgICB9XG4gICAgY29uc3QgcmVjb3ZlcnlBbW91bnQgPSBhd2FpdCB0aGlzLnF1ZXJ5QWRkcmVzc1Rva2VuQmFsYW5jZShwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MsIGNvaW5TcGVjaWZpYy5iYXNlQWRkcmVzcyk7XG5cbiAgICBpZiAocGFyYW1zLmJyb2FkY2FzdCkge1xuICAgICAgLy8gV2UncmUgZ29pbmcgdG8gY3JlYXRlIGEgbm9ybWFsIEVUSCB0cmFuc2FjdGlvbiB0aGF0IHNlbmRzIGFuIGFtb3VudCBvZiAwIEVUSCB0byB0aGVcbiAgICAgIC8vIHRva2VuQ29udHJhY3RBZGRyZXNzIGFuZCBlbmNvZGUgdGhlIHVuc3VwcG9ydGVkLXRva2VuLXNlbmQgZGF0YSBpbiB0aGUgZGF0YSBmaWVsZFxuICAgICAgLy8gI3RyaWNrc3lcbiAgICAgIGNvbnN0IHNlbmRNZXRob2RBcmdzID0gW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ190bycsXG4gICAgICAgICAgdHlwZTogJ2FkZHJlc3MnLFxuICAgICAgICAgIHZhbHVlOiBwYXJhbXMucmVjaXBpZW50LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ192YWx1ZScsXG4gICAgICAgICAgdHlwZTogJ3VpbnQyNTYnLFxuICAgICAgICAgIHZhbHVlOiByZWNvdmVyeUFtb3VudC50b1N0cmluZygxMCksXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgY29uc3QgbWV0aG9kU2lnbmF0dXJlID0gb3B0aW9uYWxEZXBzLmV0aEFiaS5tZXRob2RJRCgndHJhbnNmZXInLCBfLm1hcChzZW5kTWV0aG9kQXJncywgJ3R5cGUnKSk7XG4gICAgICBjb25zdCBlbmNvZGVkQXJncyA9IG9wdGlvbmFsRGVwcy5ldGhBYmkucmF3RW5jb2RlKF8ubWFwKHNlbmRNZXRob2RBcmdzLCAndHlwZScpLCBfLm1hcChzZW5kTWV0aG9kQXJncywgJ3ZhbHVlJykpO1xuICAgICAgY29uc3Qgc2VuZERhdGEgPSBCdWZmZXIuY29uY2F0KFttZXRob2RTaWduYXR1cmUsIGVuY29kZWRBcmdzXSk7XG5cbiAgICAgIGNvbnN0IGJyb2FkY2FzdFBhcmFtczogYW55ID0ge1xuICAgICAgICBhZGRyZXNzOiBwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogJzAnLFxuICAgICAgICBkYXRhOiBzZW5kRGF0YS50b1N0cmluZygnaGV4JyksXG4gICAgICB9O1xuXG4gICAgICBpZiAocGFyYW1zLndhbGxldFBhc3NwaHJhc2UpIHtcbiAgICAgICAgYnJvYWRjYXN0UGFyYW1zLndhbGxldFBhc3NwaHJhc2UgPSBwYXJhbXMud2FsbGV0UGFzc3BocmFzZTtcbiAgICAgIH0gZWxzZSBpZiAocGFyYW1zLnBydikge1xuICAgICAgICBicm9hZGNhc3RQYXJhbXMucHJ2ID0gcGFyYW1zLnBydjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGF3YWl0IHBhcmFtcy53YWxsZXQuc2VuZChicm9hZGNhc3RQYXJhbXMpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlY2lwaWVudCA9IHtcbiAgICAgIGFkZHJlc3M6IHBhcmFtcy5yZWNpcGllbnQsXG4gICAgICBhbW91bnQ6IHJlY292ZXJ5QW1vdW50LnRvU3RyaW5nKDEwKSxcbiAgICB9O1xuXG4gICAgLy8gVGhpcyBzaWduYXR1cmUgd2lsbCBiZSB2YWxpZCBmb3Igb25lIHdlZWtcbiAgICBjb25zdCBleHBpcmVUaW1lID0gTWF0aC5mbG9vcihuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDApICsgNjAgKiA2MCAqIDI0ICogNztcblxuICAgIC8vIEdldCBzZXF1ZW5jZSBJRC4gV2UgZG8gdGhpcyBieSBidWlsZGluZyBhICdmYWtlJyBldGggdHJhbnNhY3Rpb24sIHNvIHRoZSBwbGF0Zm9ybSB3aWxsIGluY3JlbWVudCBhbmQgcmV0dXJuIHVzIHRoZSBuZXcgc2VxdWVuY2UgaWRcbiAgICAvLyBUaGlzIF9kb2VzXyByZXF1aXJlIHRoZSB1c2VyIHRvIGhhdmUgYSBub24temVybyB3YWxsZXQgYmFsYW5jZVxuICAgIGNvbnN0IHsgbmV4dENvbnRyYWN0U2VxdWVuY2VJZCwgZ2FzUHJpY2UsIGdhc0xpbWl0IH0gPSAoYXdhaXQgcGFyYW1zLndhbGxldC5wcmVidWlsZFRyYW5zYWN0aW9uKHtcbiAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IHBhcmFtcy5yZWNpcGllbnQsXG4gICAgICAgICAgYW1vdW50OiAnMScsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pKSBhcyBhbnk7XG5cbiAgICAvLyB0aGVzZSByZWNvdmVyaWVzIG5lZWQgdG8gYmUgcHJvY2Vzc2VkIGJ5IHN1cHBvcnQsIGJ1dCBpZiB0aGUgY3VzdG9tZXIgc2VuZHMgYW55IHRyYW5zYWN0aW9ucyBiZWZvcmUgcmVjb3ZlcnkgaXNcbiAgICAvLyBjb21wbGV0ZSB0aGUgc2VxdWVuY2UgSUQgd2lsbCBiZSBpbnZhbGlkLiBhcnRpZmljaWFsbHkgaW5mbGF0ZSB0aGUgc2VxdWVuY2UgSUQgdG8gYWxsb3cgbW9yZSB0aW1lIGZvciBwcm9jZXNzaW5nXG4gICAgY29uc3Qgc2FmZVNlcXVlbmNlSWQgPSBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkICsgMTAwMDtcblxuICAgIC8vIEJ1aWxkIHNlbmREYXRhIGZvciBldGhlcmV1bSB0eFxuICAgIGNvbnN0IG9wZXJhdGlvblR5cGVzID0gWydzdHJpbmcnLCAnYWRkcmVzcycsICd1aW50JywgJ2FkZHJlc3MnLCAndWludCcsICd1aW50J107XG4gICAgY29uc3Qgb3BlcmF0aW9uQXJncyA9IFtcbiAgICAgIC8vIFwiRVJDMjBcIiBoYXMgYmVlbiBhZGRlZCBoZXJlIHNvIHRoYXQgZXRoZXIgb3BlcmF0aW9uIGhhc2hlcywgc2lnbmF0dXJlcyBjYW5ub3QgYmUgcmUtdXNlZCBmb3IgdG9rZW5TZW5kaW5nXG4gICAgICAnRVJDMjAnLFxuICAgICAgbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKG9wdGlvbmFsRGVwcy5ldGhVdGlsLnN0cmlwSGV4UHJlZml4KHJlY2lwaWVudC5hZGRyZXNzKSwgMTYpLFxuICAgICAgcmVjaXBpZW50LmFtb3VudCxcbiAgICAgIG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihvcHRpb25hbERlcHMuZXRoVXRpbC5zdHJpcEhleFByZWZpeChwYXJhbXMudG9rZW5Db250cmFjdEFkZHJlc3MpLCAxNiksXG4gICAgICBleHBpcmVUaW1lLFxuICAgICAgc2FmZVNlcXVlbmNlSWQsXG4gICAgXTtcblxuICAgIGNvbnN0IG9wZXJhdGlvbkhhc2ggPSBvcHRpb25hbERlcHMuZXRoVXRpbC5idWZmZXJUb0hleChcbiAgICAgIG9wdGlvbmFsRGVwcy5ldGhBYmkuc29saWRpdHlTSEEzKG9wZXJhdGlvblR5cGVzLCBvcGVyYXRpb25BcmdzKVxuICAgICk7XG5cbiAgICBjb25zdCB1c2VyUHJ2ID0gYXdhaXQgcGFyYW1zLndhbGxldC5nZXRQcnYoe1xuICAgICAgcHJ2OiBwYXJhbXMucHJ2LFxuICAgICAgd2FsbGV0UGFzc3BocmFzZTogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgfSk7XG5cbiAgICBjb25zdCBzaWduYXR1cmUgPSBVdGlsLmV0aFNpZ25Nc2dIYXNoKG9wZXJhdGlvbkhhc2gsIFV0aWwueHBydlRvRXRoUHJpdmF0ZUtleSh1c2VyUHJ2KSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaGFsZlNpZ25lZDoge1xuICAgICAgICByZWNpcGllbnQ6IHJlY2lwaWVudCxcbiAgICAgICAgZXhwaXJlVGltZTogZXhwaXJlVGltZSxcbiAgICAgICAgY29udHJhY3RTZXF1ZW5jZUlkOiBzYWZlU2VxdWVuY2VJZCxcbiAgICAgICAgb3BlcmF0aW9uSGFzaDogb3BlcmF0aW9uSGFzaCxcbiAgICAgICAgc2lnbmF0dXJlOiBzaWduYXR1cmUsXG4gICAgICAgIGdhc0xpbWl0OiBnYXNMaW1pdCxcbiAgICAgICAgZ2FzUHJpY2U6IGdhc1ByaWNlLFxuICAgICAgICB0b2tlbkNvbnRyYWN0QWRkcmVzczogcGFyYW1zLnRva2VuQ29udHJhY3RBZGRyZXNzLFxuICAgICAgICB3YWxsZXRJZDogcGFyYW1zLndhbGxldC5pZCgpLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGFyZ3VtZW50cyB0byBjYWxsIHRoZSBzZW5kIG1ldGhvZCBvbiB0aGUgd2FsbGV0IGNvbnRyYWN0XG4gICAqIEBwYXJhbSB0eEluZm9cbiAgICovXG4gIGdldFNlbmRNZXRob2RBcmdzKHR4SW5mbzogR2V0U2VuZE1ldGhvZEFyZ3NPcHRpb25zKTogU2VuZE1ldGhvZEFyZ3NbXSB7XG4gICAgLy8gTWV0aG9kIHNpZ25hdHVyZSBpc1xuICAgIC8vIHNlbmRNdWx0aVNpZyhhZGRyZXNzIHRvQWRkcmVzcywgdWludCB2YWx1ZSwgYnl0ZXMgZGF0YSwgdWludCBleHBpcmVUaW1lLCB1aW50IHNlcXVlbmNlSWQsIGJ5dGVzIHNpZ25hdHVyZSlcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICBuYW1lOiAndG9BZGRyZXNzJyxcbiAgICAgICAgdHlwZTogJ2FkZHJlc3MnLFxuICAgICAgICB2YWx1ZTogdHhJbmZvLnJlY2lwaWVudC5hZGRyZXNzLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ3ZhbHVlJyxcbiAgICAgICAgdHlwZTogJ3VpbnQnLFxuICAgICAgICB2YWx1ZTogdHhJbmZvLnJlY2lwaWVudC5hbW91bnQsXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnZGF0YScsXG4gICAgICAgIHR5cGU6ICdieXRlcycsXG4gICAgICAgIHZhbHVlOiBvcHRpb25hbERlcHMuZXRoVXRpbC50b0J1ZmZlcihvcHRpb25hbERlcHMuZXRoVXRpbC5hZGRIZXhQcmVmaXgodHhJbmZvLnJlY2lwaWVudC5kYXRhIHx8ICcnKSksXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBuYW1lOiAnZXhwaXJlVGltZScsXG4gICAgICAgIHR5cGU6ICd1aW50JyxcbiAgICAgICAgdmFsdWU6IHR4SW5mby5leHBpcmVUaW1lLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ3NlcXVlbmNlSWQnLFxuICAgICAgICB0eXBlOiAndWludCcsXG4gICAgICAgIHZhbHVlOiB0eEluZm8uY29udHJhY3RTZXF1ZW5jZUlkLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogJ3NpZ25hdHVyZScsXG4gICAgICAgIHR5cGU6ICdieXRlcycsXG4gICAgICAgIHZhbHVlOiBvcHRpb25hbERlcHMuZXRoVXRpbC50b0J1ZmZlcihvcHRpb25hbERlcHMuZXRoVXRpbC5hZGRIZXhQcmVmaXgodHhJbmZvLnNpZ25hdHVyZSkpLFxuICAgICAgfSxcbiAgICBdO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgYSBxdWVyeSB0byBFdGhlcnNjYW4gZm9yIGluZm9ybWF0aW9uIHN1Y2ggYXMgYmFsYW5jZSwgdG9rZW4gYmFsYW5jZSwgc29saWRpdHkgY2FsbHNcbiAgICogQHBhcmFtIHF1ZXJ5IHtPYmplY3R9IGtleS12YWx1ZSBwYWlycyBvZiBwYXJhbWV0ZXJzIHRvIGFwcGVuZCBhZnRlciAvYXBpXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IHJlc3BvbnNlIGZyb20gRXRoZXJzY2FuXG4gICAqL1xuICBhc3luYyByZWNvdmVyeUJsb2NrY2hhaW5FeHBsb3JlclF1ZXJ5KHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCB0b2tlbiA9IGNvbW1vbi5FbnZpcm9ubWVudHNbdGhpcy5iaXRnby5nZXRFbnYoKV0uZXRoZXJzY2FuQXBpVG9rZW47XG4gICAgaWYgKHRva2VuKSB7XG4gICAgICBxdWVyeS5hcGlrZXkgPSB0b2tlbjtcbiAgICB9XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0LmdldChjb21tb24uRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLmV0aGVyc2NhbkJhc2VVcmwgKyAnL2FwaScpLnF1ZXJ5KHF1ZXJ5KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWNoIEV0aGVyc2NhbicpO1xuICAgIH1cblxuICAgIGlmIChyZXNwb25zZS5ib2R5LnN0YXR1cyA9PT0gJzAnICYmIHJlc3BvbnNlLmJvZHkubWVzc2FnZSA9PT0gJ05PVE9LJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFdGhlcnNjYW4gcmF0ZSBsaW1pdCByZWFjaGVkJyk7XG4gICAgfVxuICAgIHJldHVybiByZXNwb25zZS5ib2R5O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGV4dHJhIHBhcmFtZXRlcnMgbmVlZGVkIHRvIGJ1aWxkIGEgaG9wIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBidWlsZFBhcmFtcyBUaGUgb3JpZ2luYWwgYnVpbGQgcGFyYW1ldGVyc1xuICAgKiBAcmV0dXJucyBleHRyYSBwYXJhbWV0ZXJzIG9iamVjdCB0byBtZXJnZSB3aXRoIHRoZSBvcmlnaW5hbCBidWlsZCBwYXJhbWV0ZXJzIG9iamVjdCBhbmQgc2VuZCB0byB0aGUgcGxhdGZvcm1cbiAgICovXG4gIGFzeW5jIGNyZWF0ZUhvcFRyYW5zYWN0aW9uUGFyYW1zKGJ1aWxkUGFyYW1zOiBIb3BUcmFuc2FjdGlvbkJ1aWxkT3B0aW9ucyk6IFByb21pc2U8SG9wUGFyYW1zPiB7XG4gICAgY29uc3Qgd2FsbGV0ID0gYnVpbGRQYXJhbXMud2FsbGV0O1xuICAgIGNvbnN0IHJlY2lwaWVudHMgPSBidWlsZFBhcmFtcy5yZWNpcGllbnRzO1xuICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSBidWlsZFBhcmFtcy53YWxsZXRQYXNzcGhyYXNlO1xuXG4gICAgY29uc3QgdXNlcktleWNoYWluID0gYXdhaXQgdGhpcy5rZXljaGFpbnMoKS5nZXQoeyBpZDogd2FsbGV0LmtleUlkcygpWzBdIH0pO1xuICAgIGNvbnN0IHVzZXJQcnYgPSB3YWxsZXQuZ2V0VXNlclBydih7IGtleWNoYWluOiB1c2VyS2V5Y2hhaW4sIHdhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgY29uc3QgdXNlclBydkJ1ZmZlciA9IGJpcDMyLmZyb21CYXNlNTgodXNlclBydikucHJpdmF0ZUtleTtcbiAgICBpZiAoIXVzZXJQcnZCdWZmZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCB1c2VyUHJ2Jyk7XG4gICAgfVxuICAgIGlmICghcmVjaXBpZW50cyB8fCAhQXJyYXkuaXNBcnJheShyZWNpcGllbnRzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RpbmcgYXJyYXkgb2YgcmVjaXBpZW50cycpO1xuICAgIH1cblxuICAgIC8vIFJpZ2h0IG5vdyB3ZSBvbmx5IHN1cHBvcnQgMSByZWNpcGllbnRcbiAgICBpZiAocmVjaXBpZW50cy5sZW5ndGggIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbXVzdCBzZW5kIHRvIGV4YWN0bHkgMSByZWNpcGllbnQnKTtcbiAgICB9XG4gICAgY29uc3QgcmVjaXBpZW50QWRkcmVzcyA9IHJlY2lwaWVudHNbMF0uYWRkcmVzcztcbiAgICBjb25zdCByZWNpcGllbnRBbW91bnQgPSByZWNpcGllbnRzWzBdLmFtb3VudDtcbiAgICBjb25zdCBmZWVFc3RpbWF0ZVBhcmFtcyA9IHtcbiAgICAgIHJlY2lwaWVudDogcmVjaXBpZW50QWRkcmVzcyxcbiAgICAgIGFtb3VudDogcmVjaXBpZW50QW1vdW50LFxuICAgICAgaG9wOiB0cnVlLFxuICAgIH07XG4gICAgY29uc3QgZmVlRXN0aW1hdGU6IEZlZUVzdGltYXRlID0gYXdhaXQgdGhpcy5mZWVFc3RpbWF0ZShmZWVFc3RpbWF0ZVBhcmFtcyk7XG5cbiAgICBjb25zdCBnYXNMaW1pdCA9IGZlZUVzdGltYXRlLmdhc0xpbWl0RXN0aW1hdGU7XG4gICAgY29uc3QgZ2FzUHJpY2UgPSBNYXRoLnJvdW5kKGZlZUVzdGltYXRlLmZlZUVzdGltYXRlIC8gZ2FzTGltaXQpO1xuICAgIGNvbnN0IGdhc1ByaWNlTWF4ID0gZ2FzUHJpY2UgKiA1O1xuICAgIC8vIFBheW1lbnQgaWQgYSByYW5kb20gbnVtYmVyIHNvIGl0cyBkaWZmZXJlbnQgZm9yIGV2ZXJ5IHR4XG4gICAgY29uc3QgcGF5bWVudElkID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMDAwMDAwMDApLnRvU3RyaW5nKCk7XG4gICAgY29uc3QgaG9wRGlnZXN0OiBCdWZmZXIgPSBFdGguZ2V0SG9wRGlnZXN0KFtcbiAgICAgIHJlY2lwaWVudEFkZHJlc3MsXG4gICAgICByZWNpcGllbnRBbW91bnQsXG4gICAgICBnYXNQcmljZU1heC50b1N0cmluZygpLFxuICAgICAgZ2FzTGltaXQudG9TdHJpbmcoKSxcbiAgICAgIHBheW1lbnRJZCxcbiAgICBdKTtcblxuICAgIGNvbnN0IHVzZXJSZXFTaWcgPSBvcHRpb25hbERlcHMuZXRoVXRpbC5hZGRIZXhQcmVmaXgoXG4gICAgICBCdWZmZXIuZnJvbShzZWNwMjU2azEuZWNkc2FTaWduKGhvcERpZ2VzdCwgdXNlclBydkJ1ZmZlcikuc2lnbmF0dXJlKS50b1N0cmluZygnaGV4JylcbiAgICApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGhvcFBhcmFtczoge1xuICAgICAgICBnYXNQcmljZU1heCxcbiAgICAgICAgdXNlclJlcVNpZyxcbiAgICAgICAgcGF5bWVudElkLFxuICAgICAgfSxcbiAgICAgIGdhc0xpbWl0LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoYXQgdGhlIGhvcCBwcmVidWlsZCBmcm9tIHRoZSBIU00gaXMgdmFsaWQgYW5kIGNvcnJlY3RcbiAgICogQHBhcmFtIHdhbGxldCBUaGUgd2FsbGV0IHRoYXQgdGhlIHByZWJ1aWxkIGlzIGZvclxuICAgKiBAcGFyYW0gaG9wUHJlYnVpbGQgVGhlIHByZWJ1aWxkIHRvIHZhbGlkYXRlXG4gICAqIEBwYXJhbSBvcmlnaW5hbFBhcmFtcyBUaGUgb3JpZ2luYWwgcGFyYW1ldGVycyBwYXNzZWQgdG8gcHJlYnVpbGRUcmFuc2FjdGlvblxuICAgKiBAcmV0dXJucyB2b2lkXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgVGhlIHByZWJ1aWxkIGlzIGludmFsaWRcbiAgICovXG4gIGFzeW5jIHZhbGlkYXRlSG9wUHJlYnVpbGQoXG4gICAgd2FsbGV0OiBJV2FsbGV0LFxuICAgIGhvcFByZWJ1aWxkOiBIb3BQcmVidWlsZCxcbiAgICBvcmlnaW5hbFBhcmFtcz86IHsgcmVjaXBpZW50czogUmVjaXBpZW50W10gfVxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IHR4LCBpZCwgc2lnbmF0dXJlIH0gPSBob3BQcmVidWlsZDtcblxuICAgIC8vIGZpcnN0LCB2YWxpZGF0ZSB0aGUgSFNNIHNpZ25hdHVyZVxuICAgIGNvbnN0IHNlcnZlclhwdWIgPSBjb21tb24uRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLmhzbVhwdWI7XG4gICAgY29uc3Qgc2VydmVyUHVia2V5QnVmZmVyOiBCdWZmZXIgPSBiaXAzMi5mcm9tQmFzZTU4KHNlcnZlclhwdWIpLnB1YmxpY0tleTtcbiAgICBjb25zdCBzaWduYXR1cmVCdWZmZXI6IEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKG9wdGlvbmFsRGVwcy5ldGhVdGlsLnN0cmlwSGV4UHJlZml4KHNpZ25hdHVyZSksICdoZXgnKTtcbiAgICBjb25zdCBtZXNzYWdlQnVmZmVyOiBCdWZmZXIgPSBCdWZmZXIuZnJvbShcbiAgICAgIG9wdGlvbmFsRGVwcy5ldGhVdGlsLnBhZFRvRXZlbihvcHRpb25hbERlcHMuZXRoVXRpbC5zdHJpcEhleFByZWZpeChpZCkpLFxuICAgICAgJ2hleCdcbiAgICApO1xuXG4gICAgY29uc3Qgc2lnID0gbmV3IFVpbnQ4QXJyYXkoc2lnbmF0dXJlQnVmZmVyLnNsaWNlKDEpKTtcbiAgICBjb25zdCBpc1ZhbGlkU2lnbmF0dXJlOiBib29sZWFuID0gc2VjcDI1NmsxLmVjZHNhVmVyaWZ5KHNpZywgbWVzc2FnZUJ1ZmZlciwgc2VydmVyUHVia2V5QnVmZmVyKTtcbiAgICBpZiAoIWlzVmFsaWRTaWduYXR1cmUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEhvcCB0eGlkIHNpZ25hdHVyZSBpbnZhbGlkIC0gcHViOiAke3NlcnZlclhwdWJ9LCBtc2c6ICR7bWVzc2FnZUJ1ZmZlcj8udG9TdHJpbmcoKX0sIHNpZzogJHtzaWduYXR1cmVCdWZmZXI/LnRvU3RyaW5nKCl9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBidWlsdEhvcFR4ID0gb3B0aW9uYWxEZXBzLkV0aFR4LlRyYW5zYWN0aW9uRmFjdG9yeS5mcm9tU2VyaWFsaXplZERhdGEob3B0aW9uYWxEZXBzLmV0aFV0aWwudG9CdWZmZXIodHgpKTtcbiAgICAvLyBJZiBvcmlnaW5hbCBwYXJhbXMgYXJlIGdpdmVuLCB3ZSBjYW4gY2hlY2sgdGhlbSBhZ2FpbnN0IHRoZSB0cmFuc2FjdGlvbiBwcmVidWlsZCBwYXJhbXNcbiAgICBpZiAoIV8uaXNOaWwob3JpZ2luYWxQYXJhbXMpKSB7XG4gICAgICBjb25zdCB7IHJlY2lwaWVudHMgfSA9IG9yaWdpbmFsUGFyYW1zO1xuXG4gICAgICAvLyBUaGVuIHZhbGlkYXRlIHRoYXQgdGhlIHR4IHBhcmFtcyBhY3R1YWxseSBlcXVhbCB0aGUgcmVxdWVzdGVkIHBhcmFtc1xuICAgICAgY29uc3Qgb3JpZ2luYWxBbW91bnQgPSBuZXcgQmlnTnVtYmVyKHJlY2lwaWVudHNbMF0uYW1vdW50KTtcbiAgICAgIGNvbnN0IG9yaWdpbmFsRGVzdGluYXRpb246IHN0cmluZyA9IHJlY2lwaWVudHNbMF0uYWRkcmVzcztcblxuICAgICAgY29uc3QgaG9wQW1vdW50ID0gbmV3IEJpZ051bWJlcihvcHRpb25hbERlcHMuZXRoVXRpbC5idWZmZXJUb0hleChidWlsdEhvcFR4LnZhbHVlKSk7XG4gICAgICBpZiAoIWJ1aWx0SG9wVHgudG8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUcmFuc2FjdGlvbiBkb2VzIG5vdCBoYXZlIGEgZGVzdGluYXRpb24gYWRkcmVzc2ApO1xuICAgICAgfVxuICAgICAgY29uc3QgaG9wRGVzdGluYXRpb24gPSBidWlsdEhvcFR4LnRvLnRvU3RyaW5nKCk7XG4gICAgICBpZiAoIWhvcEFtb3VudC5lcShvcmlnaW5hbEFtb3VudCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBIb3AgYW1vdW50OiAke2hvcEFtb3VudH0gZG9lcyBub3QgZXF1YWwgb3JpZ2luYWwgYW1vdW50OiAke29yaWdpbmFsQW1vdW50fWApO1xuICAgICAgfVxuICAgICAgaWYgKGhvcERlc3RpbmF0aW9uLnRvTG93ZXJDYXNlKCkgIT09IG9yaWdpbmFsRGVzdGluYXRpb24udG9Mb3dlckNhc2UoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEhvcCBkZXN0aW5hdGlvbjogJHtob3BEZXN0aW5hdGlvbn0gZG9lcyBub3QgZXF1YWwgb3JpZ2luYWwgcmVjaXBpZW50OiAke2hvcERlc3RpbmF0aW9ufWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghYnVpbHRIb3BUeC52ZXJpZnlTaWduYXR1cmUoKSkge1xuICAgICAgLy8gV2UgZG9udCB3YW50IHRvIGNvbnRpbnVlIGF0IGFsbCBpbiB0aGlzIGNhc2UsIGF0IHJpc2sgb2YgRVRIIGJlaW5nIHN0dWNrIG9uIHRoZSBob3AgYWRkcmVzc1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGhvcCB0cmFuc2FjdGlvbiBzaWduYXR1cmUsIHR4aWQ6ICR7aWR9YCk7XG4gICAgfVxuICAgIGlmIChvcHRpb25hbERlcHMuZXRoVXRpbC5hZGRIZXhQcmVmaXgoYnVpbHRIb3BUeC5oYXNoKCkudG9TdHJpbmcoJ2hleCcpKSAhPT0gaWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU2lnbmVkIGhvcCB0eGlkIGRvZXMgbm90IGVxdWFsIGFjdHVhbCB0eGlkYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGhvcCBkaWdlc3QgZm9yIHRoZSB1c2VyIHRvIHNpZ24uIFRoaXMgaXMgdmFsaWRhdGVkIGluIHRoZSBIU00gdG8gcHJvdmUgdGhhdCB0aGUgdXNlciByZXF1ZXN0ZWQgdGhpcyB0eFxuICAgKiBAcGFyYW0gcGFyYW1zQXJyIFRoZSBwYXJhbWV0ZXJzIHRvIGhhc2ggdG9nZXRoZXIgZm9yIHRoZSBkaWdlc3RcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldEhvcERpZ2VzdChwYXJhbXNBcnI6IHN0cmluZ1tdKTogQnVmZmVyIHtcbiAgICBjb25zdCBoYXNoID0gS2VjY2FrKCdrZWNjYWsyNTYnKTtcbiAgICBoYXNoLnVwZGF0ZShbRXRoLmhvcFRyYW5zYWN0aW9uU2FsdCwgLi4ucGFyYW1zQXJyXS5qb2luKCckJykpO1xuICAgIHJldHVybiBoYXNoLmRpZ2VzdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vZGlmeSBwcmVidWlsZCBiZWZvcmUgc2VuZGluZyBpdCB0byB0aGUgc2VydmVyLiBBZGQgdGhpbmdzIGxpa2UgaG9wIHRyYW5zYWN0aW9uIHBhcmFtc1xuICAgKiBAcGFyYW0gYnVpbGRQYXJhbXMgVGhlIHdoaXRlbGlzdGVkIHBhcmFtZXRlcnMgZm9yIHRoaXMgcHJlYnVpbGRcbiAgICogQHBhcmFtIGJ1aWxkUGFyYW1zLmhvcCBUcnVlIGlmIHRoaXMgc2hvdWxkIHByZWJ1aWxkIGEgaG9wIHR4LCBlbHNlIGZhbHNlXG4gICAqIEBwYXJhbSBidWlsZFBhcmFtcy5yZWNpcGllbnRzIFRoZSByZWNpcGllbnRzIGFycmF5IG9mIHRoaXMgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIGJ1aWxkUGFyYW1zLndhbGxldCBUaGUgd2FsbGV0IHNlbmRpbmcgdGhpcyB0eFxuICAgKiBAcGFyYW0gYnVpbGRQYXJhbXMud2FsbGV0UGFzc3BocmFzZSB0aGUgcGFzc3BocmFzZSBmb3IgdGhpcyB3YWxsZXRcbiAgICovXG4gIGFzeW5jIGdldEV4dHJhUHJlYnVpbGRQYXJhbXMoYnVpbGRQYXJhbXM6IEJ1aWxkT3B0aW9ucyk6IFByb21pc2U8QnVpbGRPcHRpb25zPiB7XG4gICAgaWYgKFxuICAgICAgIV8uaXNVbmRlZmluZWQoYnVpbGRQYXJhbXMuaG9wKSAmJlxuICAgICAgYnVpbGRQYXJhbXMuaG9wICYmXG4gICAgICAhXy5pc1VuZGVmaW5lZChidWlsZFBhcmFtcy53YWxsZXQpICYmXG4gICAgICAhXy5pc1VuZGVmaW5lZChidWlsZFBhcmFtcy5yZWNpcGllbnRzKSAmJlxuICAgICAgIV8uaXNVbmRlZmluZWQoYnVpbGRQYXJhbXMud2FsbGV0UGFzc3BocmFzZSlcbiAgICApIHtcbiAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgRXJjMjBUb2tlbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEhvcCB0cmFuc2FjdGlvbnMgYXJlIG5vdCBlbmFibGVkIGZvciBFUkMtMjAgdG9rZW5zLCBub3IgYXJlIHRoZXkgbmVjZXNzYXJ5LiBQbGVhc2UgcmVtb3ZlIHRoZSAnaG9wJyBwYXJhbWV0ZXIgYW5kIHRyeSBhZ2Fpbi5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gKGF3YWl0IHRoaXMuY3JlYXRlSG9wVHJhbnNhY3Rpb25QYXJhbXMoe1xuICAgICAgICB3YWxsZXQ6IGJ1aWxkUGFyYW1zLndhbGxldCxcbiAgICAgICAgcmVjaXBpZW50czogYnVpbGRQYXJhbXMucmVjaXBpZW50cyxcbiAgICAgICAgd2FsbGV0UGFzc3BocmFzZTogYnVpbGRQYXJhbXMud2FsbGV0UGFzc3BocmFzZSxcbiAgICAgIH0pKSBhcyBhbnk7XG4gICAgfVxuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb2RpZnkgcHJlYnVpbGQgYWZ0ZXIgcmVjZWl2aW5nIGl0IGZyb20gdGhlIHNlcnZlci4gQWRkIHRoaW5ncyBsaWtlIG5sb2NrdGltZVxuICAgKi9cbiAgYXN5bmMgcG9zdFByb2Nlc3NQcmVidWlsZChwYXJhbXM6IFRyYW5zYWN0aW9uUHJlYnVpbGQpOiBQcm9taXNlPFRyYW5zYWN0aW9uUHJlYnVpbGQ+IHtcbiAgICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmhvcFRyYW5zYWN0aW9uKSAmJiAhXy5pc1VuZGVmaW5lZChwYXJhbXMud2FsbGV0KSAmJiAhXy5pc1VuZGVmaW5lZChwYXJhbXMuYnVpbGRQYXJhbXMpKSB7XG4gICAgICBhd2FpdCB0aGlzLnZhbGlkYXRlSG9wUHJlYnVpbGQocGFyYW1zLndhbGxldCwgcGFyYW1zLmhvcFRyYW5zYWN0aW9uLCBwYXJhbXMuYnVpbGRQYXJhbXMpO1xuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgLyoqXG4gICAqIENvaW4tc3BlY2lmaWMgdGhpbmdzIGRvbmUgYmVmb3JlIHNpZ25pbmcgYSB0cmFuc2FjdGlvbiwgaS5lLiB2ZXJpZmljYXRpb25cbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKi9cbiAgYXN5bmMgcHJlc2lnblRyYW5zYWN0aW9uKHBhcmFtczogUHJlc2lnblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8UHJlc2lnblRyYW5zYWN0aW9uT3B0aW9ucz4ge1xuICAgIGlmICghXy5pc1VuZGVmaW5lZChwYXJhbXMuaG9wVHJhbnNhY3Rpb24pICYmICFfLmlzVW5kZWZpbmVkKHBhcmFtcy53YWxsZXQpICYmICFfLmlzVW5kZWZpbmVkKHBhcmFtcy5idWlsZFBhcmFtcykpIHtcbiAgICAgIGF3YWl0IHRoaXMudmFsaWRhdGVIb3BQcmVidWlsZChwYXJhbXMud2FsbGV0LCBwYXJhbXMuaG9wVHJhbnNhY3Rpb24pO1xuICAgIH1cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoIGZlZSBlc3RpbWF0ZSBpbmZvcm1hdGlvbiBmcm9tIHRoZSBzZXJ2ZXJcbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtcyBUaGUgcGFyYW1zIHBhc3NlZCBpbnRvIHRoZSBmdW5jdGlvblxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtwYXJhbXMuaG9wXSBUcnVlIGlmIHdlIHNob3VsZCBlc3RpbWF0ZSBmZWUgZm9yIGEgaG9wIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbcGFyYW1zLnJlY2lwaWVudF0gVGhlIHJlY2lwaWVudCBvZiB0aGUgdHJhbnNhY3Rpb24gdG8gZXN0aW1hdGUgYSBzZW5kIHRvXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbcGFyYW1zLmRhdGFdIFRoZSBFVEggdHggZGF0YSB0byBlc3RpbWF0ZSBhIHNlbmQgZm9yXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBmZWUgaW5mbyByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXJcbiAgICovXG4gIGFzeW5jIGZlZUVzdGltYXRlKHBhcmFtczogRmVlRXN0aW1hdGVPcHRpb25zKTogUHJvbWlzZTxGZWVFc3RpbWF0ZT4ge1xuICAgIGNvbnN0IHF1ZXJ5OiBGZWVFc3RpbWF0ZU9wdGlvbnMgPSB7fTtcbiAgICBpZiAocGFyYW1zICYmIHBhcmFtcy5ob3ApIHtcbiAgICAgIHF1ZXJ5LmhvcCA9IHBhcmFtcy5ob3A7XG4gICAgfVxuICAgIGlmIChwYXJhbXMgJiYgcGFyYW1zLnJlY2lwaWVudCkge1xuICAgICAgcXVlcnkucmVjaXBpZW50ID0gcGFyYW1zLnJlY2lwaWVudDtcbiAgICB9XG4gICAgaWYgKHBhcmFtcyAmJiBwYXJhbXMuZGF0YSkge1xuICAgICAgcXVlcnkuZGF0YSA9IHBhcmFtcy5kYXRhO1xuICAgIH1cbiAgICBpZiAocGFyYW1zICYmIHBhcmFtcy5hbW91bnQpIHtcbiAgICAgIHF1ZXJ5LmFtb3VudCA9IHBhcmFtcy5hbW91bnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuYml0Z28uZ2V0KHRoaXMudXJsKCcvdHgvZmVlJykpLnF1ZXJ5KHF1ZXJ5KS5yZXN1bHQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBzZWNwMjU2azEga2V5IHBhaXJcbiAgICpcbiAgICogQHBhcmFtIHNlZWRcbiAgICogQHJldHVybnMge09iamVjdH0gb2JqZWN0IHdpdGggZ2VuZXJhdGVkIHB1YiBhbmQgcHJ2XG4gICAqL1xuICBnZW5lcmF0ZUtleVBhaXIoc2VlZDogQnVmZmVyKTogS2V5UGFpciB7XG4gICAgaWYgKCFzZWVkKSB7XG4gICAgICAvLyBBbiBleHRlbmRlZCBwcml2YXRlIGtleSBoYXMgYm90aCBhIG5vcm1hbCAyNTYgYml0IHByaXZhdGUga2V5IGFuZCBhIDI1NlxuICAgICAgLy8gYml0IGNoYWluIGNvZGUsIGJvdGggb2Ygd2hpY2ggbXVzdCBiZSByYW5kb20uIDUxMiBiaXRzIGlzIHRoZXJlZm9yZSB0aGVcbiAgICAgIC8vIG1heGltdW0gZW50cm9weSBhbmQgZ2l2ZXMgdXMgbWF4aW11bSBzZWN1cml0eSBhZ2FpbnN0IGNyYWNraW5nLlxuICAgICAgc2VlZCA9IHJhbmRvbUJ5dGVzKDUxMiAvIDgpO1xuICAgIH1cbiAgICBjb25zdCBleHRlbmRlZEtleSA9IGJpcDMyLmZyb21TZWVkKHNlZWQpO1xuICAgIGNvbnN0IHhwdWIgPSBleHRlbmRlZEtleS5uZXV0ZXJlZCgpLnRvQmFzZTU4KCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHB1YjogeHB1YixcbiAgICAgIHBydjogZXh0ZW5kZWRLZXkudG9CYXNlNTgoKSxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgcGFyc2VUcmFuc2FjdGlvbihwYXJhbXM6IFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zKTogUHJvbWlzZTxQYXJzZWRUcmFuc2FjdGlvbj4ge1xuICAgIHJldHVybiB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlIHN1cmUgYW4gYWRkcmVzcyBpcyBhIHdhbGxldCBhZGRyZXNzIGFuZCB0aHJvdyBhbiBlcnJvciBpZiBpdCdzIG5vdC5cbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLmFkZHJlc3MgVGhlIGRlcml2ZWQgYWRkcmVzcyBzdHJpbmcgb24gdGhlIG5ldHdvcmtcbiAgICogQHBhcmFtIHtPYmplY3R9IHBhcmFtcy5jb2luU3BlY2lmaWMgQ29pbi1zcGVjaWZpYyBkZXRhaWxzIGZvciB0aGUgYWRkcmVzcyBzdWNoIGFzIGEgZm9yd2FyZGVyVmVyc2lvblxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLmJhc2VBZGRyZXNzIFRoZSBiYXNlIGFkZHJlc3Mgb2YgdGhlIHdhbGxldCBvbiB0aGUgbmV0d29ya1xuICAgKiBAdGhyb3dzIHtJbnZhbGlkQWRkcmVzc0Vycm9yfVxuICAgKiBAdGhyb3dzIHtJbnZhbGlkQWRkcmVzc1ZlcmlmaWNhdGlvbk9iamVjdFByb3BlcnR5RXJyb3J9XG4gICAqIEB0aHJvd3Mge1VuZXhwZWN0ZWRBZGRyZXNzRXJyb3J9XG4gICAqIEByZXR1cm5zIHtCb29sZWFufSBUcnVlIGlmZiBhZGRyZXNzIGlzIGEgd2FsbGV0IGFkZHJlc3NcbiAgICovXG4gIGFzeW5jIGlzV2FsbGV0QWRkcmVzcyhwYXJhbXM6IFZlcmlmeUV0aEFkZHJlc3NPcHRpb25zKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgZXRoVXRpbCA9IG9wdGlvbmFsRGVwcy5ldGhVdGlsO1xuXG4gICAgbGV0IGV4cGVjdGVkQWRkcmVzcztcbiAgICBsZXQgYWN0dWFsQWRkcmVzcztcblxuICAgIGNvbnN0IHsgYWRkcmVzcywgY29pblNwZWNpZmljLCBiYXNlQWRkcmVzcywgaW1wbGllZEZvcndhcmRlclZlcnNpb24gPSBjb2luU3BlY2lmaWM/LmZvcndhcmRlclZlcnNpb24gfSA9IHBhcmFtcztcblxuICAgIGlmIChhZGRyZXNzICYmICF0aGlzLmlzVmFsaWRBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcihgaW52YWxpZCBhZGRyZXNzOiAke2FkZHJlc3N9YCk7XG4gICAgfVxuXG4gICAgLy8gYmFzZSBhZGRyZXNzIGlzIHJlcXVpcmVkIHRvIGNhbGN1bGF0ZSB0aGUgc2FsdCB3aGljaCBpcyB1c2VkIGluIGNhbGN1bGF0ZUZvcndhcmRlclYxQWRkcmVzcyBtZXRob2RcbiAgICBpZiAoXy5pc1VuZGVmaW5lZChiYXNlQWRkcmVzcykgfHwgIXRoaXMuaXNWYWxpZEFkZHJlc3MoYmFzZUFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFkZHJlc3NFcnJvcignaW52YWxpZCBiYXNlIGFkZHJlc3MnKTtcbiAgICB9XG5cbiAgICBpZiAoIV8uaXNPYmplY3QoY29pblNwZWNpZmljKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBZGRyZXNzVmVyaWZpY2F0aW9uT2JqZWN0UHJvcGVydHlFcnJvcihcbiAgICAgICAgJ2FkZHJlc3MgdmFsaWRhdGlvbiBmYWlsdXJlOiBjb2luU3BlY2lmaWMgZmllbGQgbXVzdCBiZSBhbiBvYmplY3QnXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChpbXBsaWVkRm9yd2FyZGVyVmVyc2lvbiA9PT0gMCB8fCBpbXBsaWVkRm9yd2FyZGVyVmVyc2lvbiA9PT0gMykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGV0aE5ldHdvcmsgPSB0aGlzLmdldE5ldHdvcmsoKTtcbiAgICAgIGNvbnN0IGZvcndhcmRlckZhY3RvcnlBZGRyZXNzID0gZXRoTmV0d29yaz8uZm9yd2FyZGVyRmFjdG9yeUFkZHJlc3MgYXMgc3RyaW5nO1xuICAgICAgY29uc3QgZm9yd2FyZGVySW1wbGVtZW50YXRpb25BZGRyZXNzID0gZXRoTmV0d29yaz8uZm9yd2FyZGVySW1wbGVtZW50YXRpb25BZGRyZXNzIGFzIHN0cmluZztcblxuICAgICAgY29uc3QgaW5pdGNvZGUgPSBnZXRQcm94eUluaXRjb2RlKGZvcndhcmRlckltcGxlbWVudGF0aW9uQWRkcmVzcyk7XG4gICAgICBjb25zdCBzYWx0QnVmZmVyID0gZXRoVXRpbC5zZXRMZW5ndGhMZWZ0KFxuICAgICAgICBCdWZmZXIuZnJvbShldGhVdGlsLnBhZFRvRXZlbihldGhVdGlsLnN0cmlwSGV4UHJlZml4KGNvaW5TcGVjaWZpYy5zYWx0IHx8ICcnKSksICdoZXgnKSxcbiAgICAgICAgMzJcbiAgICAgICk7XG5cbiAgICAgIC8vIEhhc2ggdGhlIHdhbGxldCBiYXNlIGFkZHJlc3Mgd2l0aCB0aGUgZ2l2ZW4gc2FsdCwgc28gdGhlIGFkZHJlc3MgZGlyZWN0bHkgcmVsaWVzIG9uIHRoZSBiYXNlIGFkZHJlc3NcbiAgICAgIGNvbnN0IGNhbGN1bGF0aW9uU2FsdCA9IG9wdGlvbmFsRGVwcy5ldGhVdGlsLmJ1ZmZlclRvSGV4KFxuICAgICAgICBvcHRpb25hbERlcHMuZXRoQWJpLnNvbGlkaXR5U0hBMyhbJ2FkZHJlc3MnLCAnYnl0ZXMzMiddLCBbYmFzZUFkZHJlc3MsIHNhbHRCdWZmZXJdKVxuICAgICAgKTtcblxuICAgICAgZXhwZWN0ZWRBZGRyZXNzID0gY2FsY3VsYXRlRm9yd2FyZGVyVjFBZGRyZXNzKGZvcndhcmRlckZhY3RvcnlBZGRyZXNzLCBjYWxjdWxhdGlvblNhbHQsIGluaXRjb2RlKTtcbiAgICAgIGFjdHVhbEFkZHJlc3MgPSBhZGRyZXNzO1xuICAgIH1cblxuICAgIGlmIChleHBlY3RlZEFkZHJlc3MgIT09IGFjdHVhbEFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBVbmV4cGVjdGVkQWRkcmVzc0Vycm9yKGBhZGRyZXNzIHZhbGlkYXRpb24gZmFpbHVyZTogZXhwZWN0ZWQgJHtleHBlY3RlZEFkZHJlc3N9IGJ1dCBnb3QgJHthZGRyZXNzfWApO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgdmVyaWZ5Q29pbih0eFByZWJ1aWxkOiBUcmFuc2FjdGlvblByZWJ1aWxkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHR4UHJlYnVpbGQuY29pbiA9PT0gdGhpcy5nZXRDaGFpbigpO1xuICB9XG5cbiAgdmVyaWZ5VHNzVHJhbnNhY3Rpb24ocGFyYW1zOiBWZXJpZnlFdGhUcmFuc2FjdGlvbk9wdGlvbnMpOiBib29sZWFuIHtcbiAgICBjb25zdCB7IHR4UGFyYW1zLCB0eFByZWJ1aWxkLCB3YWxsZXQgfSA9IHBhcmFtcztcbiAgICBpZiAoXG4gICAgICAhdHhQYXJhbXM/LnJlY2lwaWVudHMgJiZcbiAgICAgICEoXG4gICAgICAgIHR4UGFyYW1zLnByZWJ1aWxkVHg/LmNvbnNvbGlkYXRlSWQgfHxcbiAgICAgICAgKHR4UGFyYW1zLnR5cGUgJiYgWydhY2NlbGVyYXRpb24nLCAnZmlsbE5vbmNlJywgJ3RyYW5zZmVyVG9rZW4nXS5pbmNsdWRlcyh0eFBhcmFtcy50eXBlKSlcbiAgICAgIClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbWlzc2luZyB0eFBhcmFtc2ApO1xuICAgIH1cbiAgICBpZiAoIXdhbGxldCB8fCAhdHhQcmVidWlsZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBtaXNzaW5nIHBhcmFtc2ApO1xuICAgIH1cbiAgICBpZiAodHhQYXJhbXMuaG9wICYmIHR4UGFyYW1zLnJlY2lwaWVudHMgJiYgdHhQYXJhbXMucmVjaXBpZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHR4IGNhbm5vdCBiZSBib3RoIGEgYmF0Y2ggYW5kIGhvcCB0cmFuc2FjdGlvbmApO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZnkgdGhhdCBhIHRyYW5zYWN0aW9uIHByZWJ1aWxkIGNvbXBsaWVzIHdpdGggdGhlIG9yaWdpbmFsIGludGVudGlvblxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zXG4gICAqIEBwYXJhbSBwYXJhbXMudHhQYXJhbXMgcGFyYW1zIG9iamVjdCBwYXNzZWQgdG8gc2VuZFxuICAgKiBAcGFyYW0gcGFyYW1zLnR4UHJlYnVpbGQgcHJlYnVpbGQgb2JqZWN0IHJldHVybmVkIGJ5IHNlcnZlclxuICAgKiBAcGFyYW0gcGFyYW1zLndhbGxldCBXYWxsZXQgb2JqZWN0IHRvIG9idGFpbiBrZXlzIHRvIHZlcmlmeSBhZ2FpbnN0XG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgYXN5bmMgdmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zOiBWZXJpZnlFdGhUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBldGhOZXR3b3JrID0gdGhpcy5nZXROZXR3b3JrKCk7XG4gICAgY29uc3QgeyB0eFBhcmFtcywgdHhQcmVidWlsZCwgd2FsbGV0LCB3YWxsZXRUeXBlIH0gPSBwYXJhbXM7XG5cbiAgICBpZiAod2FsbGV0VHlwZSA9PT0gJ3RzcycpIHtcbiAgICAgIHJldHVybiB0aGlzLnZlcmlmeVRzc1RyYW5zYWN0aW9uKHBhcmFtcyk7XG4gICAgfVxuXG4gICAgaWYgKCF0eFBhcmFtcz8ucmVjaXBpZW50cyB8fCAhdHhQcmVidWlsZD8ucmVjaXBpZW50cyB8fCAhd2FsbGV0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYG1pc3NpbmcgcGFyYW1zYCk7XG4gICAgfVxuICAgIGlmICh0eFBhcmFtcy5ob3AgJiYgdHhQYXJhbXMucmVjaXBpZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHR4IGNhbm5vdCBiZSBib3RoIGEgYmF0Y2ggYW5kIGhvcCB0cmFuc2FjdGlvbmApO1xuICAgIH1cbiAgICBpZiAodHhQcmVidWlsZC5yZWNpcGllbnRzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB0eFByZWJ1aWxkIHNob3VsZCBvbmx5IGhhdmUgMSByZWNpcGllbnQgYnV0ICR7dHhQcmVidWlsZC5yZWNpcGllbnRzLmxlbmd0aH0gZm91bmRgKTtcbiAgICB9XG4gICAgaWYgKHR4UGFyYW1zLmhvcCAmJiB0eFByZWJ1aWxkLmhvcFRyYW5zYWN0aW9uKSB7XG4gICAgICAvLyBDaGVjayByZWNpcGllbnQgYW1vdW50IGZvciBob3AgdHJhbnNhY3Rpb25cbiAgICAgIGlmICh0eFBhcmFtcy5yZWNpcGllbnRzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGhvcCB0cmFuc2FjdGlvbiBvbmx5IHN1cHBvcnRzIDEgcmVjaXBpZW50IGJ1dCAke3R4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RofSBmb3VuZGApO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayB0eCBzZW5kcyB0byBob3AgYWRkcmVzc1xuICAgICAgY29uc3QgZGVjb2RlZEhvcFR4ID0gb3B0aW9uYWxEZXBzLkV0aFR4LlRyYW5zYWN0aW9uRmFjdG9yeS5mcm9tU2VyaWFsaXplZERhdGEoXG4gICAgICAgIG9wdGlvbmFsRGVwcy5ldGhVdGlsLnRvQnVmZmVyKHR4UHJlYnVpbGQuaG9wVHJhbnNhY3Rpb24udHgpXG4gICAgICApO1xuICAgICAgY29uc3QgZXhwZWN0ZWRIb3BBZGRyZXNzID0gb3B0aW9uYWxEZXBzLmV0aFV0aWwuc3RyaXBIZXhQcmVmaXgoZGVjb2RlZEhvcFR4LmdldFNlbmRlckFkZHJlc3MoKS50b1N0cmluZygpKTtcbiAgICAgIGNvbnN0IGFjdHVhbEhvcEFkZHJlc3MgPSBvcHRpb25hbERlcHMuZXRoVXRpbC5zdHJpcEhleFByZWZpeCh0eFByZWJ1aWxkLnJlY2lwaWVudHNbMF0uYWRkcmVzcyk7XG4gICAgICBpZiAoZXhwZWN0ZWRIb3BBZGRyZXNzLnRvTG93ZXJDYXNlKCkgIT09IGFjdHVhbEhvcEFkZHJlc3MudG9Mb3dlckNhc2UoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3JlY2lwaWVudCBhZGRyZXNzIG9mIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggaG9wIGFkZHJlc3MnKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ29udmVydCBUcmFuc2FjdGlvblJlY2lwaWVudCBhcnJheSB0byBSZWNpcGllbnQgYXJyYXlcbiAgICAgIGNvbnN0IHJlY2lwaWVudHM6IFJlY2lwaWVudFtdID0gdHhQYXJhbXMucmVjaXBpZW50cy5tYXAoKHIpID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBhZGRyZXNzOiByLmFkZHJlc3MsXG4gICAgICAgICAgYW1vdW50OiB0eXBlb2Ygci5hbW91bnQgPT09ICdudW1iZXInID8gci5hbW91bnQudG9TdHJpbmcoKSA6IHIuYW1vdW50LFxuICAgICAgICB9O1xuICAgICAgfSk7XG5cbiAgICAgIC8vIENoZWNrIGRlc3RpbmF0aW9uIGFkZHJlc3MgYW5kIGFtb3VudFxuICAgICAgYXdhaXQgdGhpcy52YWxpZGF0ZUhvcFByZWJ1aWxkKHdhbGxldCwgdHhQcmVidWlsZC5ob3BUcmFuc2FjdGlvbiwgeyByZWNpcGllbnRzIH0pO1xuICAgIH0gZWxzZSBpZiAodHhQYXJhbXMucmVjaXBpZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAvLyBDaGVjayB0b3RhbCBhbW91bnQgZm9yIGJhdGNoIHRyYW5zYWN0aW9uXG4gICAgICBsZXQgZXhwZWN0ZWRUb3RhbEFtb3VudCA9IG5ldyBCaWdOdW1iZXIoMCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHR4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgZXhwZWN0ZWRUb3RhbEFtb3VudCA9IGV4cGVjdGVkVG90YWxBbW91bnQucGx1cyh0eFBhcmFtcy5yZWNpcGllbnRzW2ldLmFtb3VudCk7XG4gICAgICB9XG4gICAgICBpZiAoIWV4cGVjdGVkVG90YWxBbW91bnQuaXNFcXVhbFRvKHR4UHJlYnVpbGQucmVjaXBpZW50c1swXS5hbW91bnQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnYmF0Y2ggdHJhbnNhY3Rpb24gYW1vdW50IGluIHR4UHJlYnVpbGQgcmVjZWl2ZWQgZnJvbSBCaXRHbyBzZXJ2ZXJzIGRvZXMgbm90IG1hdGNoIHR4UGFyYW1zIHN1cHBsaWVkIGJ5IGNsaWVudCdcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgYmF0Y2ggdHJhbnNhY3Rpb24gaXMgc2VudCB0byB0aGUgYmF0Y2hlciBjb250cmFjdCBhZGRyZXNzIGZvciB0aGUgY2hhaW5cbiAgICAgIGNvbnN0IGJhdGNoZXJDb250cmFjdEFkZHJlc3MgPSBldGhOZXR3b3JrPy5iYXRjaGVyQ29udHJhY3RBZGRyZXNzO1xuICAgICAgaWYgKFxuICAgICAgICAhYmF0Y2hlckNvbnRyYWN0QWRkcmVzcyB8fFxuICAgICAgICBiYXRjaGVyQ29udHJhY3RBZGRyZXNzLnRvTG93ZXJDYXNlKCkgIT09IHR4UHJlYnVpbGQucmVjaXBpZW50c1swXS5hZGRyZXNzLnRvTG93ZXJDYXNlKClcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3JlY2lwaWVudCBhZGRyZXNzIG9mIHR4UHJlYnVpbGQgZG9lcyBub3QgbWF0Y2ggYmF0Y2hlciBhZGRyZXNzJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIENoZWNrIHJlY2lwaWVudCBhZGRyZXNzIGFuZCBhbW91bnQgZm9yIG5vcm1hbCB0cmFuc2FjdGlvblxuICAgICAgaWYgKHR4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm9ybWFsIHRyYW5zYWN0aW9uIG9ubHkgc3VwcG9ydHMgMSByZWNpcGllbnQgYnV0ICR7dHhQYXJhbXMucmVjaXBpZW50cy5sZW5ndGh9IGZvdW5kYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBleHBlY3RlZEFtb3VudCA9IG5ldyBCaWdOdW1iZXIodHhQYXJhbXMucmVjaXBpZW50c1swXS5hbW91bnQpO1xuICAgICAgaWYgKCFleHBlY3RlZEFtb3VudC5pc0VxdWFsVG8odHhQcmVidWlsZC5yZWNpcGllbnRzWzBdLmFtb3VudCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICdub3JtYWwgdHJhbnNhY3Rpb24gYW1vdW50IGluIHR4UHJlYnVpbGQgcmVjZWl2ZWQgZnJvbSBCaXRHbyBzZXJ2ZXJzIGRvZXMgbm90IG1hdGNoIHR4UGFyYW1zIHN1cHBsaWVkIGJ5IGNsaWVudCdcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGlmIChcbiAgICAgICAgdGhpcy5pc0VUSEFkZHJlc3ModHhQYXJhbXMucmVjaXBpZW50c1swXS5hZGRyZXNzKSAmJlxuICAgICAgICB0eFBhcmFtcy5yZWNpcGllbnRzWzBdLmFkZHJlc3MgIT09IHR4UHJlYnVpbGQucmVjaXBpZW50c1swXS5hZGRyZXNzXG4gICAgICApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkZXN0aW5hdGlvbiBhZGRyZXNzIGluIG5vcm1hbCB0eFByZWJ1aWxkIGRvZXMgbm90IG1hdGNoIHRoYXQgaW4gdHhQYXJhbXMgc3VwcGxpZWQgYnkgY2xpZW50Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIENoZWNrIGNvaW4gaXMgY29ycmVjdCBmb3IgYWxsIHRyYW5zYWN0aW9uIHR5cGVzXG4gICAgaWYgKCF0aGlzLnZlcmlmeUNvaW4odHhQcmVidWlsZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgY29pbiBpbiB0eFByZWJ1aWxkIGRpZCBub3QgbWF0Y2ggdGhhdCBpbiB0eFBhcmFtcyBzdXBwbGllZCBieSBjbGllbnRgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgc3VwcG9ydHNNZXNzYWdlU2lnbmluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c1NpZ25pbmdUeXBlZERhdGEoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtIG1lc3NhZ2UgdG8gYWNjb21tb2RhdGUgc3BlY2lmaWMgYmxvY2tjaGFpbiByZXF1aXJlbWVudHMuXG4gICAqIEBwYXJhbSBtZXNzYWdlIHRoZSBtZXNzYWdlIHRvIHByZXBhcmVcbiAgICogQHJldHVybiBzdHJpbmcgdGhlIHByZXBhcmVkIG1lc3NhZ2UuXG4gICAqL1xuICBlbmNvZGVNZXNzYWdlKG1lc3NhZ2U6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgcHJlZml4ID0gYFxcdTAwMTlFdGhlcmV1bSBTaWduZWQgTWVzc2FnZTpcXG4ke21lc3NhZ2UubGVuZ3RofWA7XG4gICAgcmV0dXJuIHByZWZpeC5jb25jYXQobWVzc2FnZSk7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtIHRoZSBUeXBlZCBkYXRhIHRvIGFjY29tb2RhdGUgdGhlIGJsb2NrY2hhaW4gcmVxdWlyZW1lbnRzIChFSVAtNzEyKVxuICAgKiBAcGFyYW0gdHlwZWREYXRhIHRoZSB0eXBlZCBkYXRhIHRvIHByZXBhcmVcbiAgICogQHJldHVybiBhIGJ1ZmZlciBvZiB0aGUgcmVzdWx0XG4gICAqL1xuICBlbmNvZGVUeXBlZERhdGEodHlwZWREYXRhOiBUeXBlZERhdGEpOiBCdWZmZXIge1xuICAgIGNvbnN0IHZlcnNpb24gPSB0eXBlZERhdGEudmVyc2lvbjtcbiAgICBpZiAodmVyc2lvbiA9PT0gU2lnblR5cGVkRGF0YVZlcnNpb24uVjEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU2lnblR5cGVkRGF0YSB2MSBpcyBub3Qgc3VwcG9ydGVkIGR1ZSB0byBzZWN1cml0eSBjb25jZXJucycpO1xuICAgIH1cbiAgICBjb25zdCB0eXBlZERhdGFSYXcgPSBKU09OLnBhcnNlKHR5cGVkRGF0YS50eXBlZERhdGFSYXcpO1xuICAgIGNvbnN0IHNhbml0aXplZERhdGEgPSBUeXBlZERhdGFVdGlscy5zYW5pdGl6ZURhdGEodHlwZWREYXRhUmF3IGFzIHVua25vd24gYXMgVHlwZWRNZXNzYWdlPGFueT4pO1xuICAgIGNvbnN0IHBhcnRzID0gW0J1ZmZlci5mcm9tKCcxOTAxJywgJ2hleCcpXTtcbiAgICBjb25zdCBlaXA3MTJEb21haW4gPSAnRUlQNzEyRG9tYWluJztcbiAgICBwYXJ0cy5wdXNoKFR5cGVkRGF0YVV0aWxzLmhhc2hTdHJ1Y3QoZWlwNzEyRG9tYWluLCBzYW5pdGl6ZWREYXRhLmRvbWFpbiwgc2FuaXRpemVkRGF0YS50eXBlcywgdmVyc2lvbikpO1xuXG4gICAgaWYgKHNhbml0aXplZERhdGEucHJpbWFyeVR5cGUgIT09IGVpcDcxMkRvbWFpbikge1xuICAgICAgcGFydHMucHVzaChcbiAgICAgICAgVHlwZWREYXRhVXRpbHMuaGFzaFN0cnVjdChcbiAgICAgICAgICBzYW5pdGl6ZWREYXRhLnByaW1hcnlUeXBlIGFzIHN0cmluZyxcbiAgICAgICAgICBzYW5pdGl6ZWREYXRhLm1lc3NhZ2UsXG4gICAgICAgICAgc2FuaXRpemVkRGF0YS50eXBlcyxcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KHBhcnRzKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNFVEhBZGRyZXNzKGFkZHJlc3M6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIWFkZHJlc3MubWF0Y2goLzB4W2EtZkEtRjAtOV17NDB9Lyk7XG4gIH1cbn1cbiJdfQ==
427
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2V0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTs7R0FFRztBQUNILHFEQUE4QztBQUM5QyxvREFBdUI7QUFDdkIsNERBQWlDO0FBQ2pDLG1EQWM4QjtBQUM5QiwyREFtQmtDO0FBa0JoQyw2RkFwQkEsMkJBQVksT0FvQkE7QUFqQmQsaURBQXlFO0FBRXpFLCtDQUF5QztBQUV6QywrQkFBMkM7QUFDM0MsNkNBQTBDO0FBcUIxQyxNQUFhLEdBQUksU0FBUSxzQ0FBdUI7SUFDOUMsWUFBc0IsS0FBZ0IsRUFBRSxXQUF1QztRQUM3RSxLQUFLLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQzVCLENBQUM7SUFFRCxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQWdCLEVBQUUsV0FBdUM7UUFDN0UsT0FBTyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVELDJCQUEyQjtRQUN6QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsV0FBVztRQUNULE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELG9CQUFvQjtJQUNwQixzQkFBc0I7UUFDcEIsT0FBTyx3QkFBYSxDQUFDLEdBQUcsQ0FBQztJQUMzQixDQUFDO0lBRUQsZUFBZTtRQUNiLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFpQixFQUFFLHVCQUFpRDtRQUM5RiwwRUFBMEU7UUFDMUUsaUVBQWlFO1FBQ2pFLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsMkJBQVksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDO1FBQ2hHLE1BQU0sYUFBYSxHQUFHLElBQUks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N0IsT0FBTyxJQUFJLHdCQUFrQixDQUFDLGVBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLHNCQUFzQjtRQUNwQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsd0JBQXdCO1FBQ3RCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztDQUNGO0FBNWVELGtCQTRlQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHByZXR0aWVyXG4gKi9cbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvLWJldGEvc2VjcDI1NmsxJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgcmVxdWVzdCBmcm9tICdzdXBlcmFnZW50JztcbmltcG9ydCB7XG4gIEJhc2VDb2luLFxuICBCaXRHb0Jhc2UsXG4gIGNoZWNrS3JzUHJvdmlkZXIsXG4gIGNvbW1vbixcbiAgRnVsbHlTaWduZWRUcmFuc2FjdGlvbixcbiAgZ2V0SXNVbnNpZ25lZFN3ZWVwLFxuICBnZXRJc0tyc1JlY292ZXJ5LFxuICBIYWxmU2lnbmVkVHJhbnNhY3Rpb24sXG4gIE1QQ0FsZ29yaXRobSxcbiAgUmVjaXBpZW50LFxuICBVdGlsLFxuICBNdWx0aXNpZ1R5cGUsXG4gIG11bHRpc2lnVHlwZXMsXG59IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1jb3JlJztcbmltcG9ydCB7XG4gIEFic3RyYWN0RXRoTGlrZU5ld0NvaW5zLFxuICBCdWlsZE9wdGlvbnMsXG4gIEJ1aWxkVHJhbnNhY3Rpb25QYXJhbXMsXG4gIEVJUDE1NTksXG4gIEZlZXNVc2VkLFxuICBHZXRCYXRjaEV4ZWN1dGlvbkluZm9SVCxcbiAgR2V0U2VuZE1ldGhvZEFyZ3NPcHRpb25zLFxuICBSZWNvdmVyeUluZm8sXG4gIFJlY292ZXJPcHRpb25zLFxuICBSZXBsYXlQcm90ZWN0aW9uT3B0aW9ucyxcbiAgU2VuZE1ldGhvZEFyZ3MsXG4gIFNpZ25lZFRyYW5zYWN0aW9uLFxuICBTaWduRmluYWxPcHRpb25zLFxuICBTaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBUcmFuc2FjdGlvblByZWJ1aWxkLFxuICBPZmZsaW5lVmF1bHRUeEluZm8sXG4gIG9wdGlvbmFsRGVwcyxcbiAgVW5zaWduZWRTd2VlcFR4TVBDdjIsXG59IGZyb20gJ0BiaXRnby1iZXRhL2Fic3RyYWN0LWV0aCc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBTdGF0aWNzQmFzZUNvaW4sIGNvaW5zIH0gZnJvbSAnQGJpdGdvLWJldGEvc3RhdGljcyc7XG5pbXBvcnQgdHlwZSAqIGFzIEV0aFR4TGliIGZyb20gJ0BldGhlcmV1bWpzL3R4JztcbmltcG9ydCB7IEJpZ051bWJlciB9IGZyb20gJ2JpZ251bWJlci5qcyc7XG5cbmltcG9ydCB7IFRyYW5zYWN0aW9uQnVpbGRlciB9IGZyb20gJy4vbGliJztcbmltcG9ydCB7IEVyYzIwVG9rZW4gfSBmcm9tICcuL2VyYzIwVG9rZW4nO1xuXG5leHBvcnQge1xuICBCdWlsZFRyYW5zYWN0aW9uUGFyYW1zLFxuICBSZWNpcGllbnQsXG4gIEhhbGZTaWduZWRUcmFuc2FjdGlvbixcbiAgRmVlc1VzZWQsXG4gIEZ1bGx5U2lnbmVkVHJhbnNhY3Rpb24sXG4gIEdldEJhdGNoRXhlY3V0aW9uSW5mb1JULFxuICBHZXRTZW5kTWV0aG9kQXJnc09wdGlvbnMsXG4gIFRyYW5zYWN0aW9uUHJlYnVpbGQsXG4gIE9mZmxpbmVWYXVsdFR4SW5mbyxcbiAgb3B0aW9uYWxEZXBzLFxuICBSZWNvdmVyT3B0aW9ucyxcbiAgUmVjb3ZlcnlJbmZvLFxuICBTZW5kTWV0aG9kQXJncyxcbiAgU2lnbkZpbmFsT3B0aW9ucyxcbiAgU2lnbmVkVHJhbnNhY3Rpb24sXG4gIFNpZ25UcmFuc2FjdGlvbk9wdGlvbnMsXG59O1xuXG5leHBvcnQgY2xhc3MgRXRoIGV4dGVuZHMgQWJzdHJhY3RFdGhMaWtlTmV3Q29pbnMge1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoYml0Z286IEJpdEdvQmFzZSwgc3RhdGljc0NvaW4/OiBSZWFkb25seTxTdGF0aWNzQmFzZUNvaW4+KSB7XG4gICAgc3VwZXIoYml0Z28sIHN0YXRpY3NDb2luKTtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVJbnN0YW5jZShiaXRnbzogQml0R29CYXNlLCBzdGF0aWNzQ29pbj86IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj4pOiBCYXNlQ29pbiB7XG4gICAgcmV0dXJuIG5ldyBFdGgoYml0Z28sIHN0YXRpY3NDb2luKTtcbiAgfVxuXG4gIGFsbG93c0FjY291bnRDb25zb2xpZGF0aW9ucygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c1RzcygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBpbmhlcml0ZWQgZG9jICovXG4gIGdldERlZmF1bHRNdWx0aXNpZ1R5cGUoKTogTXVsdGlzaWdUeXBlIHtcbiAgICByZXR1cm4gbXVsdGlzaWdUeXBlcy50c3M7XG4gIH1cblxuICBnZXRNUENBbGdvcml0aG0oKTogTVBDQWxnb3JpdGhtIHtcbiAgICByZXR1cm4gJ2VjZHNhJztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGNvcnJlY3QgRXRoIENvbW1vbiBvYmplY3QgYmFzZWQgb24gcGFyYW1zIGZyb20gZWl0aGVyIHJlY292ZXJ5IG9yIHR4IGJ1aWxkaW5nXG4gICAqIEBwYXJhbSBlaXAxNTU5IHtFSVAxNTU5fSBjb25maWdzIHRoYXQgc3BlY2lmeSB3aGV0aGVyIHdlIHNob3VsZCBjb25zdHJ1Y3QgYW4gZWlwMTU1OSB0eFxuICAgKiBAcGFyYW0gcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnMge1JlcGxheVByb3RlY3Rpb25PcHRpb25zfSBjaGVjayBpZiBjaGFpbiBpZCBzdXBwb3J0cyByZXBsYXkgcHJvdGVjdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0RXRoQ29tbW9uKGVpcDE1NTk/OiBFSVAxNTU5LCByZXBsYXlQcm90ZWN0aW9uT3B0aW9ucz86IFJlcGxheVByb3RlY3Rpb25PcHRpb25zKSB7XG4gICAgLy8gaWYgZWlwMTU1OSBwYXJhbXMgYXJlIHNwZWNpZmllZCwgZGVmYXVsdCB0byBsb25kb24gaGFyZGZvcmssIG90aGVyd2lzZSxcbiAgICAvLyBkZWZhdWx0IHRvIHRhbmdlcmluZSB3aGlzdGxlIHRvIGF2b2lkIHJlcGxheSBwcm90ZWN0aW9uIGlzc3Vlc1xuICAgIGNvbnN0IGRlZmF1bHRIYXJkZm9yayA9ICEhZWlwMTU1OSA/ICdsb25kb24nIDogb3B0aW9uYWxEZXBzLkV0aENvbW1vbi5IYXJkZm9yay5UYW5nZXJpbmVXaGlzdGxlO1xuICAgIGNvbnN0IGRlZmF1bHRDb21tb24gPSBuZXcgb3B0aW9uYWxEZXBzLkV0aENvbW1vbi5kZWZhdWx0KHtcbiAgICAgIGNoYWluOiBvcHRpb25hbERlcHMuRXRoQ29tbW9uLkNoYWluLk1haW5uZXQsXG4gICAgICBoYXJkZm9yazogZGVmYXVsdEhhcmRmb3JrLFxuICAgIH0pO1xuXG4gICAgLy8gaWYgcmVwbGF5IHByb3RlY3Rpb24gb3B0aW9ucyBhcmUgc2V0LCBvdmVycmlkZSB0aGUgZGVmYXVsdCBjb21tb24gc2V0dGluZ1xuICAgIGNvbnN0IGV0aENvbW1vbiA9IHJlcGxheVByb3RlY3Rpb25PcHRpb25zXG4gICAgICA/IG9wdGlvbmFsRGVwcy5FdGhDb21tb24uZGVmYXVsdC5pc1N1cHBvcnRlZENoYWluSWQobmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHJlcGxheVByb3RlY3Rpb25PcHRpb25zLmNoYWluKSlcbiAgICAgICAgPyBuZXcgb3B0aW9uYWxEZXBzLkV0aENvbW1vbi5kZWZhdWx0KHtcbiAgICAgICAgICAgIGNoYWluOiByZXBsYXlQcm90ZWN0aW9uT3B0aW9ucy5jaGFpbixcbiAgICAgICAgICAgIGhhcmRmb3JrOiByZXBsYXlQcm90ZWN0aW9uT3B0aW9ucy5oYXJkZm9yayxcbiAgICAgICAgICB9KVxuICAgICAgICA6IG9wdGlvbmFsRGVwcy5FdGhDb21tb24uZGVmYXVsdC5jdXN0b20oe1xuICAgICAgICAgICAgY2hhaW5JZDogbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHJlcGxheVByb3RlY3Rpb25PcHRpb25zLmNoYWluKSxcbiAgICAgICAgICAgIGRlZmF1bHRIYXJkZm9yazogcmVwbGF5UHJvdGVjdGlvbk9wdGlvbnMuaGFyZGZvcmssXG4gICAgICAgICAgfSlcbiAgICAgIDogZGVmYXVsdENvbW1vbjtcbiAgICByZXR1cm4gZXRoQ29tbW9uO1xuICB9XG5cbiAgc3RhdGljIGJ1aWxkVHJhbnNhY3Rpb24ocGFyYW1zOiBCdWlsZFRyYW5zYWN0aW9uUGFyYW1zKTogRXRoVHhMaWIuRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uIHwgRXRoVHhMaWIuVHJhbnNhY3Rpb24ge1xuICAgIC8vIGlmIGVpcDE1NTkgcGFyYW1zIGFyZSBzcGVjaWZpZWQsIGRlZmF1bHQgdG8gbG9uZG9uIGhhcmRmb3JrLCBvdGhlcndpc2UsXG4gICAgLy8gZGVmYXVsdCB0byB0YW5nZXJpbmUgd2hpc3RsZSB0byBhdm9pZCByZXBsYXkgcHJvdGVjdGlvbiBpc3N1ZXNcbiAgICBjb25zdCBldGhDb21tb24gPSBFdGguZ2V0RXRoQ29tbW9uKHBhcmFtcy5laXAxNTU5LCBwYXJhbXMucmVwbGF5UHJvdGVjdGlvbk9wdGlvbnMpO1xuXG4gICAgY29uc3QgYmFzZVBhcmFtcyA9IHtcbiAgICAgIHRvOiBwYXJhbXMudG8sXG4gICAgICBub25jZTogcGFyYW1zLm5vbmNlLFxuICAgICAgdmFsdWU6IHBhcmFtcy52YWx1ZSxcbiAgICAgIGRhdGE6IHBhcmFtcy5kYXRhLFxuICAgICAgZ2FzTGltaXQ6IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTihwYXJhbXMuZ2FzTGltaXQpLFxuICAgIH07XG5cbiAgICBjb25zdCB1bnNpZ25lZEV0aFR4ID0gISFwYXJhbXMuZWlwMTU1OVxuICAgICAgPyBvcHRpb25hbERlcHMuRXRoVHguRmVlTWFya2V0RUlQMTU1OVRyYW5zYWN0aW9uLmZyb21UeERhdGEoXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uYmFzZVBhcmFtcyxcbiAgICAgICAgICAgIG1heEZlZVBlckdhczogbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHBhcmFtcy5laXAxNTU5Lm1heEZlZVBlckdhcyksXG4gICAgICAgICAgICBtYXhQcmlvcml0eUZlZVBlckdhczogbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHBhcmFtcy5laXAxNTU5Lm1heFByaW9yaXR5RmVlUGVyR2FzKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgY29tbW9uOiBldGhDb21tb24gfVxuICAgICAgICApXG4gICAgICA6IG9wdGlvbmFsRGVwcy5FdGhUeC5UcmFuc2FjdGlvbi5mcm9tVHhEYXRhKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIC4uLmJhc2VQYXJhbXMsXG4gICAgICAgICAgICBnYXNQcmljZTogbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHBhcmFtcy5nYXNQcmljZSksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB7IGNvbW1vbjogZXRoQ29tbW9uIH1cbiAgICAgICAgKTtcblxuICAgIHJldHVybiB1bnNpZ25lZEV0aFR4O1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgYSBxdWVyeSB0byBFdGhlcnNjYW4gZm9yIGluZm9ybWF0aW9uIHN1Y2ggYXMgYmFsYW5jZSwgdG9rZW4gYmFsYW5jZSwgc29saWRpdHkgY2FsbHNcbiAgICogQHBhcmFtIHF1ZXJ5IHtPYmplY3R9IGtleS12YWx1ZSBwYWlycyBvZiBwYXJhbWV0ZXJzIHRvIGFwcGVuZCBhZnRlciAvYXBpXG4gICAqIEByZXR1cm5zIHtPYmplY3R9IHJlc3BvbnNlIGZyb20gRXRoZXJzY2FuXG4gICAqL1xuICBhc3luYyByZWNvdmVyeUJsb2NrY2hhaW5FeHBsb3JlclF1ZXJ5KHF1ZXJ5OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCB0b2tlbiA9IGNvbW1vbi5FbnZpcm9ubWVudHNbdGhpcy5iaXRnby5nZXRFbnYoKV0uZXRoZXJzY2FuQXBpVG9rZW47XG4gICAgaWYgKHRva2VuKSB7XG4gICAgICBxdWVyeS5hcGlrZXkgPSB0b2tlbjtcbiAgICB9XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0LmdldChjb21tb24uRW52aXJvbm1lbnRzW3RoaXMuYml0Z28uZ2V0RW52KCldLmV0aGVyc2NhbkJhc2VVcmwgKyAnL2FwaScpLnF1ZXJ5KHF1ZXJ5KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWNoIEV0aGVyc2NhbicpO1xuICAgIH1cblxuICAgIGlmIChyZXNwb25zZS5ib2R5LnN0YXR1cyA9PT0gJzAnICYmIHJlc3BvbnNlLmJvZHkubWVzc2FnZSA9PT0gJ05PVE9LJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFdGhlcnNjYW4gcmF0ZSBsaW1pdCByZWFjaGVkJyk7XG4gICAgfVxuICAgIHJldHVybiByZXNwb25zZS5ib2R5O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY292ZXJzIGEgdHggd2l0aCBub24tVFNTIGtleXNcbiAgICogc2FtZSBleHBlY3RlZCBhcmd1bWVudHMgYXMgcmVjb3ZlciBtZXRob2QgKG9yaWdpbmFsIGxvZ2ljIGJlZm9yZSBhZGRpbmcgVFNTIHJlY292ZXIgcGF0aClcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWNvdmVyRXRoTGlrZShwYXJhbXM6IFJlY292ZXJPcHRpb25zKTogUHJvbWlzZTxSZWNvdmVyeUluZm8gfCBPZmZsaW5lVmF1bHRUeEluZm8+IHtcbiAgICAvLyBiaXRnb0ZlZUFkZHJlc3MgaXMgb25seSBkZWZpbmVkIHdoZW4gaXQgaXMgYSBldm0gY3Jvc3MgY2hhaW4gcmVjb3ZlcnlcbiAgICAvLyBhcyB3ZSB1c2UgZmVlIGZyb20gdGhpcyB3cm9uZyBjaGFpbiBhZGRyZXNzIGZvciB0aGUgcmVjb3ZlcnkgdHhuIG9uIHRoZSBjb3JyZWN0IGNoYWluLlxuICAgIGlmIChwYXJhbXMuYml0Z29GZWVBZGRyZXNzKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWNvdmVyRXRoTGlrZWZvckV2bUJhc2VkUmVjb3ZlcnkocGFyYW1zKTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlUmVjb3ZlcnlQYXJhbXMocGFyYW1zKTtcbiAgICBjb25zdCBpc0tyc1JlY292ZXJ5ID0gZ2V0SXNLcnNSZWNvdmVyeShwYXJhbXMpO1xuICAgIGNvbnN0IGlzVW5zaWduZWRTd2VlcCA9IGdldElzVW5zaWduZWRTd2VlcChwYXJhbXMpO1xuXG4gICAgaWYgKGlzS3JzUmVjb3ZlcnkpIHtcbiAgICAgIGNoZWNrS3JzUHJvdmlkZXIodGhpcywgcGFyYW1zLmtyc1Byb3ZpZGVyLCB7IGNoZWNrQ29pbkZhbWlseVN1cHBvcnQ6IGZhbHNlIH0pO1xuICAgIH1cblxuICAgIC8vIENsZWFuIHVwIHdoaXRlc3BhY2UgZnJvbSBlbnRlcmVkIHZhbHVlc1xuICAgIGxldCB1c2VyS2V5ID0gcGFyYW1zLnVzZXJLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcbiAgICBjb25zdCBiYWNrdXBLZXkgPSBwYXJhbXMuYmFja3VwS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG5cbiAgICAvLyBTZXQgbmV3IGV0aCB0eCBmZWVzICh1c2luZyBkZWZhdWx0IGNvbmZpZyB2YWx1ZXMgZnJvbSBwbGF0Zm9ybSlcblxuICAgIGNvbnN0IGdhc0xpbWl0ID0gbmV3IG9wdGlvbmFsRGVwcy5ldGhVdGlsLkJOKHRoaXMuc2V0R2FzTGltaXQocGFyYW1zLmdhc0xpbWl0KSk7XG4gICAgY29uc3QgZ2FzUHJpY2UgPSBwYXJhbXMuZWlwMTU1OVxuICAgICAgPyBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4ocGFyYW1zLmVpcDE1NTkubWF4RmVlUGVyR2FzKVxuICAgICAgOiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4odGhpcy5zZXRHYXNQcmljZShwYXJhbXMuZ2FzUHJpY2UpKTtcbiAgICBpZiAoIXVzZXJLZXkuc3RhcnRzV2l0aCgneHB1YicpICYmICF1c2VyS2V5LnN0YXJ0c1dpdGgoJ3hwcnYnKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdXNlcktleSA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgICAgaW5wdXQ6IHVzZXJLZXksXG4gICAgICAgICAgcGFzc3dvcmQ6IHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBkZWNyeXB0aW5nIHVzZXIga2V5Y2hhaW46ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBiYWNrdXBLZXlBZGRyZXNzOiBzdHJpbmc7XG4gICAgbGV0IGJhY2t1cFNpZ25pbmdLZXk7XG5cbiAgICBpZiAoaXNLcnNSZWNvdmVyeSB8fCBpc1Vuc2lnbmVkU3dlZXApIHtcbiAgICAgIGNvbnN0IGJhY2t1cEhETm9kZSA9IGJpcDMyLmZyb21CYXNlNTgoYmFja3VwS2V5KTtcbiAgICAgIGJhY2t1cFNpZ25pbmdLZXkgPSBiYWNrdXBIRE5vZGUucHVibGljS2V5O1xuICAgICAgYmFja3VwS2V5QWRkcmVzcyA9IGAweCR7b3B0aW9uYWxEZXBzLmV0aFV0aWwucHVibGljVG9BZGRyZXNzKGJhY2t1cFNpZ25pbmdLZXksIHRydWUpLnRvU3RyaW5nKCdoZXgnKX1gO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWNyeXB0IGJhY2t1cCBwcml2YXRlIGtleSBhbmQgZ2V0IGFkZHJlc3NcbiAgICAgIGxldCBiYWNrdXBQcnY7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGJhY2t1cFBydiA9IHRoaXMuYml0Z28uZGVjcnlwdCh7XG4gICAgICAgICAgaW5wdXQ6IGJhY2t1cEtleSxcbiAgICAgICAgICBwYXNzd29yZDogcGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIH0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGRlY3J5cHRpbmcgYmFja3VwIGtleWNoYWluOiAke2UubWVzc2FnZX1gKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmFja3VwSEROb2RlID0gYmlwMzIuZnJvbUJhc2U1OChiYWNrdXBQcnYpO1xuICAgICAgYmFja3VwU2lnbmluZ0tleSA9IGJhY2t1cEhETm9kZS5wcml2YXRlS2V5O1xuICAgICAgaWYgKCFiYWNrdXBIRE5vZGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlIGtleScpO1xuICAgICAgfVxuICAgICAgYmFja3VwS2V5QWRkcmVzcyA9IGAweCR7b3B0aW9uYWxEZXBzLmV0aFV0aWwucHJpdmF0ZVRvQWRkcmVzcyhiYWNrdXBTaWduaW5nS2V5KS50b1N0cmluZygnaGV4Jyl9YDtcbiAgICB9XG5cbiAgICBjb25zdCBiYWNrdXBLZXlOb25jZSA9IGF3YWl0IHRoaXMuZ2V0QWRkcmVzc05vbmNlKGJhY2t1cEtleUFkZHJlc3MpO1xuXG4gICAgLy8gZ2V0IGJhbGFuY2Ugb2YgYmFja3VwS2V5IHRvIGVuc3VyZSBmdW5kcyBhcmUgYXZhaWxhYmxlIHRvIHBheSBmZWVzXG4gICAgY29uc3QgYmFja3VwS2V5QmFsYW5jZSA9IGF3YWl0IHRoaXMucXVlcnlBZGRyZXNzQmFsYW5jZShiYWNrdXBLZXlBZGRyZXNzKTtcblxuICAgIGNvbnN0IHRvdGFsR2FzTmVlZGVkID0gZ2FzUHJpY2UubXVsKGdhc0xpbWl0KTtcbiAgICBjb25zdCB3ZWlUb0d3ZWkgPSAxMCAqKiA5O1xuICAgIGlmIChiYWNrdXBLZXlCYWxhbmNlLmx0KHRvdGFsR2FzTmVlZGVkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQmFja3VwIGtleSBhZGRyZXNzICR7YmFja3VwS2V5QWRkcmVzc30gaGFzIGJhbGFuY2UgJHsoYmFja3VwS2V5QmFsYW5jZSAvIHdlaVRvR3dlaSkudG9TdHJpbmcoKX0gR3dlaS5gICtcbiAgICAgICAgICBgVGhpcyBhZGRyZXNzIG11c3QgaGF2ZSBhIGJhbGFuY2Ugb2YgYXQgbGVhc3QgJHsodG90YWxHYXNOZWVkZWQgLyB3ZWlUb0d3ZWkpLnRvU3RyaW5nKCl9YCArXG4gICAgICAgICAgYCBHd2VpIHRvIHBlcmZvcm0gcmVjb3Zlcmllcy4gVHJ5IHNlbmRpbmcgc29tZSBFVEggdG8gdGhpcyBhZGRyZXNzIHRoZW4gcmV0cnkuYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBnZXQgYmFsYW5jZSBvZiB3YWxsZXQgYW5kIGRlZHVjdCBmZWVzIHRvIGdldCB0cmFuc2FjdGlvbiBhbW91bnRcbiAgICBjb25zdCB0eEFtb3VudCA9IGF3YWl0IHRoaXMucXVlcnlBZGRyZXNzQmFsYW5jZShwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzKTtcbiAgICBpZiAobmV3IEJpZ051bWJlcih0eEFtb3VudCkuaXNMZXNzVGhhbk9yRXF1YWxUbygwKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdXYWxsZXQgZG9lcyBub3QgaGF2ZSBlbm91Z2ggZnVuZHMgdG8gcmVjb3ZlcicpO1xuICAgIH1cblxuICAgIC8vIGJ1aWxkIHJlY2lwaWVudHMgb2JqZWN0XG4gICAgY29uc3QgcmVjaXBpZW50cyA9IFtcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczogcGFyYW1zLnJlY292ZXJ5RGVzdGluYXRpb24sXG4gICAgICAgIGFtb3VudDogdHhBbW91bnQudG9TdHJpbmcoMTApLFxuICAgICAgfSxcbiAgICBdO1xuXG4gICAgLy8gR2V0IHNlcXVlbmNlIElEIHVzaW5nIGNvbnRyYWN0IGNhbGxcbiAgICAvLyB3ZSBuZWVkIHRvIHdhaXQgYmV0d2VlbiBtYWtpbmcgdHdvIGV0aGVyc2NhbiBjYWxscyB0byBhdm9pZCBnZXR0aW5nIGJhbm5lZFxuICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMDApKTtcbiAgICBjb25zdCBzZXF1ZW5jZUlkID0gYXdhaXQgdGhpcy5xdWVyeVNlcXVlbmNlSWQocGFyYW1zLndhbGxldENvbnRyYWN0QWRkcmVzcyk7XG5cbiAgICBsZXQgb3BlcmF0aW9uSGFzaCwgc2lnbmF0dXJlO1xuICAgIC8vIEdldCBvcGVyYXRpb24gaGFzaCBhbmQgc2lnbiBpdFxuICAgIGlmICghaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICBvcGVyYXRpb25IYXNoID0gdGhpcy5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0ocmVjaXBpZW50cywgdGhpcy5nZXREZWZhdWx0RXhwaXJlVGltZSgpLCBzZXF1ZW5jZUlkKTtcbiAgICAgIHNpZ25hdHVyZSA9IFV0aWwuZXRoU2lnbk1zZ0hhc2gob3BlcmF0aW9uSGFzaCwgVXRpbC54cHJ2VG9FdGhQcml2YXRlS2V5KHVzZXJLZXkpKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgVXRpbC5lY1JlY292ZXJFdGhBZGRyZXNzKG9wZXJhdGlvbkhhc2gsIHNpZ25hdHVyZSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzaWduYXR1cmUnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB0eEluZm8gPSB7XG4gICAgICByZWNpcGllbnQ6IHJlY2lwaWVudHNbMF0sXG4gICAgICBleHBpcmVUaW1lOiB0aGlzLmdldERlZmF1bHRFeHBpcmVUaW1lKCksXG4gICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IHNlcXVlbmNlSWQsXG4gICAgICBvcGVyYXRpb25IYXNoOiBvcGVyYXRpb25IYXNoLFxuICAgICAgc2lnbmF0dXJlOiBzaWduYXR1cmUsXG4gICAgICBnYXNMaW1pdDogZ2FzTGltaXQudG9TdHJpbmcoMTApLFxuICAgIH07XG5cbiAgICAvLyBjYWxjdWxhdGUgc2VuZCBkYXRhXG4gICAgY29uc3Qgc2VuZE1ldGhvZEFyZ3MgPSB0aGlzLmdldFNlbmRNZXRob2RBcmdzKHR4SW5mbyk7XG4gICAgY29uc3QgbWV0aG9kU2lnbmF0dXJlID0gb3B0aW9uYWxEZXBzLmV0aEFiaS5tZXRob2RJRCh0aGlzLnNlbmRNZXRob2ROYW1lLCBfLm1hcChzZW5kTWV0aG9kQXJncywgJ3R5cGUnKSk7XG4gICAgY29uc3QgZW5jb2RlZEFyZ3MgPSBvcHRpb25hbERlcHMuZXRoQWJpLnJhd0VuY29kZShfLm1hcChzZW5kTWV0aG9kQXJncywgJ3R5cGUnKSwgXy5tYXAoc2VuZE1ldGhvZEFyZ3MsICd2YWx1ZScpKTtcbiAgICBjb25zdCBzZW5kRGF0YSA9IEJ1ZmZlci5jb25jYXQoW21ldGhvZFNpZ25hdHVyZSwgZW5jb2RlZEFyZ3NdKTtcblxuICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgdG86IHBhcmFtcy53YWxsZXRDb250cmFjdEFkZHJlc3MsXG4gICAgICBub25jZTogYmFja3VwS2V5Tm9uY2UsXG4gICAgICB2YWx1ZTogMCxcbiAgICAgIGdhc1ByaWNlOiBnYXNQcmljZSxcbiAgICAgIGdhc0xpbWl0OiBnYXNMaW1pdCxcbiAgICAgIGRhdGE6IHNlbmREYXRhLFxuICAgICAgZWlwMTU1OTogcGFyYW1zLmVpcDE1NTksXG4gICAgICByZXBsYXlQcm90ZWN0aW9uT3B0aW9uczogcGFyYW1zLnJlcGxheVByb3RlY3Rpb25PcHRpb25zLFxuICAgIH07XG5cbiAgICAvLyBCdWlsZCBjb250cmFjdCBjYWxsIGFuZCBzaWduIGl0XG4gICAgbGV0IHR4ID0gRXRoLmJ1aWxkVHJhbnNhY3Rpb24odHhQYXJhbXMpO1xuXG4gICAgaWYgKGlzVW5zaWduZWRTd2VlcCkge1xuICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0Rm9yT2ZmbGluZVZhdWx0KFxuICAgICAgICB0eEluZm8sXG4gICAgICAgIHR4LFxuICAgICAgICB1c2VyS2V5LFxuICAgICAgICBiYWNrdXBLZXksXG4gICAgICAgIGdhc1ByaWNlLFxuICAgICAgICBnYXNMaW1pdCxcbiAgICAgICAgcGFyYW1zLmVpcDE1NTksXG4gICAgICAgIHBhcmFtcy5yZXBsYXlQcm90ZWN0aW9uT3B0aW9uc1xuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoIWlzS3JzUmVjb3ZlcnkpIHtcbiAgICAgIHR4ID0gdHguc2lnbihiYWNrdXBTaWduaW5nS2V5KTtcbiAgICB9XG5cbiAgICBjb25zdCBzaWduZWRUeDogUmVjb3ZlcnlJbmZvID0ge1xuICAgICAgaWQ6IG9wdGlvbmFsRGVwcy5ldGhVdGlsLmJ1ZmZlclRvSGV4KHR4Lmhhc2goKSksXG4gICAgICB0eDogdHguc2VyaWFsaXplKCkudG9TdHJpbmcoJ2hleCcpLFxuICAgIH07XG5cbiAgICBpZiAoaXNLcnNSZWNvdmVyeSkge1xuICAgICAgc2lnbmVkVHguYmFja3VwS2V5ID0gYmFja3VwS2V5O1xuICAgICAgc2lnbmVkVHguY29pbiA9IHRoaXMuZ2V0Q2hhaW4oKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2lnbmVkVHg7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgYnVpbGRVbnNpZ25lZFN3ZWVwVHhuVFNTKHBhcmFtczogUmVjb3Zlck9wdGlvbnMpOiBQcm9taXNlPE9mZmxpbmVWYXVsdFR4SW5mbyB8IFVuc2lnbmVkU3dlZXBUeE1QQ3YyPiB7XG4gICAgLy8gQ29pbi1zcGVjaWZpYyBsb2dpYyBmb3IgRVRIXG4gICAgcmV0dXJuIHRoaXMuYnVpbGRVbnNpZ25lZFN3ZWVwVHhuTVBDdjIocGFyYW1zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgaW5wdXQgaXMgdmFsaWQgcHVibGljIGtleSBmb3IgdGhlIGNvaW4uXG4gICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwdWIgdGhlIHB1YiB0byBiZSBjaGVja2VkXG4gICAqIEByZXR1cm5zIHtCb29sZWFufSBpcyBpdCB2YWxpZD9cbiAgICovXG4gIGlzVmFsaWRQdWIocHViOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGJpcDMyLmZyb21CYXNlNTgocHViKS5pc05ldXRlcmVkKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gZm9yIHNpZ25UcmFuc2FjdGlvbiBmb3IgdGhlIHJhcmUgY2FzZSB0aGF0IFNESyBpcyBkb2luZyB0aGUgc2Vjb25kIHNpZ25hdHVyZVxuICAgKiBOb3RlOiB3ZSBhcmUgZXhwZWN0aW5nIHRoaXMgdG8gYmUgY2FsbGVkIGZyb20gdGhlIG9mZmxpbmUgdmF1bHRcbiAgICogQHBhcmFtIHBhcmFtcy50eFByZWJ1aWxkXG4gICAqIEBwYXJhbSBwYXJhbXMuc2lnbmluZ0tleU5vbmNlXG4gICAqIEBwYXJhbSBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzXG4gICAqIEBwYXJhbSBwYXJhbXMucHJ2XG4gICAqIEByZXR1cm5zIHt7dHhIZXg6ICp9fVxuICAgKi9cbiAgc2lnbkZpbmFsKHBhcmFtczogU2lnbkZpbmFsT3B0aW9ucyk6IEZ1bGx5U2lnbmVkVHJhbnNhY3Rpb24ge1xuICAgIGNvbnN0IHR4UHJlYnVpbGQgPSBwYXJhbXMudHhQcmVidWlsZDtcblxuICAgIGlmICghXy5pc051bWJlcihwYXJhbXMuc2lnbmluZ0tleU5vbmNlKSAmJiAhXy5pc051bWJlcihwYXJhbXMudHhQcmVidWlsZC5oYWxmU2lnbmVkPy5iYWNrdXBLZXlOb25jZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ211c3QgaGF2ZSBhdCBsZWFzdCBvbmUgb2Ygc2lnbmluZ0tleU5vbmNlIGFuZCBiYWNrdXBLZXlOb25jZSBhcyBhIHBhcmFtZXRlciwgYW5kIGl0IG11c3QgYmUgYSBudW1iZXInXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdwYXJhbXMgbXVzdCBpbmNsdWRlIHdhbGxldENvbnRyYWN0QWRkcmVzcywgYnV0IGdvdCB1bmRlZmluZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBzaWduaW5nTm9kZSA9IGJpcDMyLmZyb21CYXNlNTgocGFyYW1zLnBydik7XG4gICAgY29uc3Qgc2lnbmluZ0tleSA9IHNpZ25pbmdOb2RlLnByaXZhdGVLZXk7XG4gICAgaWYgKF8uaXNVbmRlZmluZWQoc2lnbmluZ0tleSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBwcml2YXRlIGtleScpO1xuICAgIH1cblxuICAgIGxldCByZWNpcGllbnQ6IFJlY2lwaWVudDtcbiAgICBsZXQgdHhJbmZvO1xuICAgIGlmICh0eFByZWJ1aWxkLnJlY2lwaWVudHMpIHtcbiAgICAgIHJlY2lwaWVudCA9IHR4UHJlYnVpbGQucmVjaXBpZW50c1swXTtcbiAgICAgIHR4SW5mbyA9IHtcbiAgICAgICAgcmVjaXBpZW50LFxuICAgICAgICBleHBpcmVUaW1lOiB0eFByZWJ1aWxkLmhhbGZTaWduZWQ/LmV4cGlyZVRpbWUgYXMgbnVtYmVyLFxuICAgICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IHR4UHJlYnVpbGQuaGFsZlNpZ25lZD8uY29udHJhY3RTZXF1ZW5jZUlkIGFzIG51bWJlcixcbiAgICAgICAgc2lnbmF0dXJlOiB0eFByZWJ1aWxkLmhhbGZTaWduZWQ/LnNpZ25hdHVyZSBhcyBzdHJpbmcsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHNlbmRNZXRob2RBcmdzID0gdGhpcy5nZXRTZW5kTWV0aG9kQXJncyh0eEluZm8pO1xuICAgIGNvbnN0IG1ldGhvZFNpZ25hdHVyZSA9IG9wdGlvbmFsRGVwcy5ldGhBYmkubWV0aG9kSUQodGhpcy5zZW5kTWV0aG9kTmFtZSwgXy5tYXAoc2VuZE1ldGhvZEFyZ3MsICd0eXBlJykpO1xuICAgIGNvbnN0IGVuY29kZWRBcmdzID0gb3B0aW9uYWxEZXBzLmV0aEFiaS5yYXdFbmNvZGUoXy5tYXAoc2VuZE1ldGhvZEFyZ3MsICd0eXBlJyksIF8ubWFwKHNlbmRNZXRob2RBcmdzLCAndmFsdWUnKSk7XG4gICAgY29uc3Qgc2VuZERhdGEgPSBCdWZmZXIuY29uY2F0KFttZXRob2RTaWduYXR1cmUsIGVuY29kZWRBcmdzXSk7XG5cbiAgICBjb25zdCBldGhUeFBhcmFtcyA9IHtcbiAgICAgIHRvOiBwYXJhbXMud2FsbGV0Q29udHJhY3RBZGRyZXNzLFxuICAgICAgbm9uY2U6XG4gICAgICAgIHBhcmFtcy5zaWduaW5nS2V5Tm9uY2UgIT09IHVuZGVmaW5lZCA/IHBhcmFtcy5zaWduaW5nS2V5Tm9uY2UgOiBwYXJhbXMudHhQcmVidWlsZC5oYWxmU2lnbmVkPy5iYWNrdXBLZXlOb25jZSxcbiAgICAgIHZhbHVlOiAwLFxuICAgICAgZ2FzUHJpY2U6IG5ldyBvcHRpb25hbERlcHMuZXRoVXRpbC5CTih0eFByZWJ1aWxkLmdhc1ByaWNlKSxcbiAgICAgIGdhc0xpbWl0OiBuZXcgb3B0aW9uYWxEZXBzLmV0aFV0aWwuQk4odHhQcmVidWlsZC5nYXNMaW1pdCksXG4gICAgICBkYXRhOiBzZW5kRGF0YSxcbiAgICB9O1xuXG4gICAgY29uc3QgdW5zaWduZWRFdGhUeCA9IEV0aC5idWlsZFRyYW5zYWN0aW9uKHtcbiAgICAgIC4uLmV0aFR4UGFyYW1zLFxuICAgICAgZWlwMTU1OTogcGFyYW1zLnR4UHJlYnVpbGQuZWlwMTU1OSxcbiAgICAgIHJlcGxheVByb3RlY3Rpb25PcHRpb25zOiBwYXJhbXMudHhQcmVidWlsZC5yZXBsYXlQcm90ZWN0aW9uT3B0aW9ucyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGV0aFR4ID0gdW5zaWduZWRFdGhUeC5zaWduKHNpZ25pbmdLZXkpO1xuXG4gICAgcmV0dXJuIHsgdHhIZXg6IGV0aFR4LnNlcmlhbGl6ZSgpLnRvU3RyaW5nKCdoZXgnKSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFzc2VtYmxlIGtleWNoYWluIGFuZCBoYWxmLXNpZ24gcHJlYnVpbHQgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHBhcmFtc1xuICAgKiAtIHR4UHJlYnVpbGRcbiAgICogLSBwcnZcbiAgICogQHJldHVybnMge1Byb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+fVxuICAgKi9cbiAgYXN5bmMgc2lnblRyYW5zYWN0aW9uKHBhcmFtczogU2lnblRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8U2lnbmVkVHJhbnNhY3Rpb24+IHtcbiAgICBpZiAocGFyYW1zLmlzRXZtQmFzZWRDcm9zc0NoYWluUmVjb3ZlcnkpIHtcbiAgICAgIHJldHVybiBzdXBlci5zaWduVHJhbnNhY3Rpb24ocGFyYW1zKTtcbiAgICB9XG4gICAgY29uc3QgdHhQcmVidWlsZCA9IHBhcmFtcy50eFByZWJ1aWxkO1xuXG4gICAgY29uc3QgdXNlclBydiA9IHBhcmFtcy5wcnY7XG4gICAgY29uc3QgRVhQSVJFVElNRV9ERUZBVUxUID0gNjAgKiA2MCAqIDI0ICogNzsgLy8gVGhpcyBzaWduYXR1cmUgd2lsbCBiZSB2YWxpZCBmb3IgMSB3ZWVrXG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZCh0eFByZWJ1aWxkKSB8fCAhXy5pc09iamVjdCh0eFByZWJ1aWxkKSkge1xuICAgICAgaWYgKCFfLmlzVW5kZWZpbmVkKHR4UHJlYnVpbGQpICYmICFfLmlzT2JqZWN0KHR4UHJlYnVpbGQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdHhQcmVidWlsZCBtdXN0IGJlIGFuIG9iamVjdCwgZ290IHR5cGUgJHt0eXBlb2YgdHhQcmVidWlsZH1gKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB0eFByZWJ1aWxkIHBhcmFtZXRlcicpO1xuICAgIH1cblxuICAgIGlmIChfLmlzVW5kZWZpbmVkKHVzZXJQcnYpIHx8ICFfLmlzU3RyaW5nKHVzZXJQcnYpKSB7XG4gICAgICBpZiAoIV8uaXNVbmRlZmluZWQodXNlclBydikgJiYgIV8uaXNTdHJpbmcodXNlclBydikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBwcnYgbXVzdCBiZSBhIHN0cmluZywgZ290IHR5cGUgJHt0eXBlb2YgdXNlclBydn1gKTtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBwcnYgcGFyYW1ldGVyIHRvIHNpZ24gdHJhbnNhY3Rpb24nKTtcbiAgICB9XG5cbiAgICBwYXJhbXMucmVjaXBpZW50cyA9IHR4UHJlYnVpbGQucmVjaXBpZW50cyB8fCBwYXJhbXMucmVjaXBpZW50cztcblxuICAgIC8vIGlmIG5vIHJlY2lwaWVudHMgaW4gZWl0aGVyIHBhcmFtcyBvciB0eFByZWJ1aWxkLCB0aGVuIHRocm93IGFuIGVycm9yXG4gICAgaWYgKCFwYXJhbXMucmVjaXBpZW50cyB8fCAhQXJyYXkuaXNBcnJheShwYXJhbXMucmVjaXBpZW50cykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncmVjaXBpZW50cyBtaXNzaW5nIG9yIG5vdCBhcnJheScpO1xuICAgIH1cblxuICAgIGlmIChwYXJhbXMucmVjaXBpZW50cy5sZW5ndGggPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWNpcGllbnRzIGVtcHR5Jyk7XG4gICAgfVxuXG4gICAgLy8gTm9ybWFsbHkgdGhlIFNESyBwcm92aWRlcyB0aGUgZmlyc3Qgc2lnbmF0dXJlIGZvciBhbiBFVEggdHgsIGJ1dCBvY2Nhc2lvbmFsbHkgaXQgcHJvdmlkZXMgdGhlIHNlY29uZCBhbmQgZmluYWwgb25lLlxuICAgIGlmIChwYXJhbXMuaXNMYXN0U2lnbmF0dXJlKSB7XG4gICAgICAvLyBJbiB0aGlzIGNhc2Ugd2hlbiB3ZSdyZSBkb2luZyB0aGUgc2Vjb25kIChmaW5hbCkgc2lnbmF0dXJlLCB0aGUgbG9naWMgaXMgZGlmZmVyZW50LlxuICAgICAgcmV0dXJuIHRoaXMuc2lnbkZpbmFsKHBhcmFtcyk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2Vjb25kc1NpbmNlRXBvY2ggPSBNYXRoLmZsb29yKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG4gICAgY29uc3QgZXhwaXJlVGltZSA9IHBhcmFtcy5leHBpcmVUaW1lIHx8IHNlY29uZHNTaW5jZUVwb2NoICsgRVhQSVJFVElNRV9ERUZBVUxUO1xuICAgIGNvbnN0IHNlcXVlbmNlSWQgPSB0eFByZWJ1aWxkLm5leHRDb250cmFjdFNlcXVlbmNlSWQ7XG5cbiAgICBpZiAoXy5pc1VuZGVmaW5lZChzZXF1ZW5jZUlkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0cmFuc2FjdGlvbiBwcmVidWlsZCBtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5IG5leHRDb250cmFjdFNlcXVlbmNlSWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBvcGVyYXRpb25IYXNoID0gdGhpcy5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0ocGFyYW1zLnJlY2lwaWVudHMsIGV4cGlyZVRpbWUsIHNlcXVlbmNlSWQpO1xuICAgIGNvbnN0IHNpZ25hdHVyZSA9IFV0aWwuZXRoU2lnbk1zZ0hhc2gob3BlcmF0aW9uSGFzaCwgVXRpbC54cHJ2VG9FdGhQcml2YXRlS2V5KHVzZXJQcnYpKTtcblxuICAgIGNvbnN0IHR4UGFyYW1zID0ge1xuICAgICAgZWlwMTU1OTogcGFyYW1zLnR4UHJlYnVpbGQuZWlwMTU1OSxcbiAgICAgIGlzQmF0Y2g6IHBhcmFtcy50eFByZWJ1aWxkLmlzQmF0Y2gsXG4gICAgICByZWNpcGllbnRzOiBwYXJhbXMucmVjaXBpZW50cyxcbiAgICAgIGV4cGlyZVRpbWU6IGV4cGlyZVRpbWUsXG4gICAgICBjb250cmFjdFNlcXVlbmNlSWQ6IHNlcXVlbmNlSWQsXG4gICAgICBzZXF1ZW5jZUlkOiBwYXJhbXMuc2VxdWVuY2VJZCxcbiAgICAgIG9wZXJhdGlvbkhhc2g6IG9wZXJhdGlvbkhhc2gsXG4gICAgICBzaWduYXR1cmU6IHNpZ25hdHVyZSxcbiAgICAgIGdhc0xpbWl0OiBwYXJhbXMuZ2FzTGltaXQsXG4gICAgICBnYXNQcmljZTogcGFyYW1zLmdhc1ByaWNlLFxuICAgICAgaG9wVHJhbnNhY3Rpb246IHR4UHJlYnVpbGQuaG9wVHJhbnNhY3Rpb24sXG4gICAgICBiYWNrdXBLZXlOb25jZTogdHhQcmVidWlsZC5iYWNrdXBLZXlOb25jZSxcbiAgICAgIGN1c3RvZGlhblRyYW5zYWN0aW9uSWQ6IHBhcmFtcy5jdXN0b2RpYW5UcmFuc2FjdGlvbklkLFxuICAgIH07XG4gICAgcmV0dXJuIHsgaGFsZlNpZ25lZDogdHhQYXJhbXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb2RpZnkgcHJlYnVpbGQgYmVmb3JlIHNlbmRpbmcgaXQgdG8gdGhlIHNlcnZlci4gQWRkIHRoaW5ncyBsaWtlIGhvcCB0cmFuc2FjdGlvbiBwYXJhbXNcbiAgICogQHBhcmFtIGJ1aWxkUGFyYW1zIFRoZSB3aGl0ZWxpc3RlZCBwYXJhbWV0ZXJzIGZvciB0aGlzIHByZWJ1aWxkXG4gICAqIEBwYXJhbSBidWlsZFBhcmFtcy5ob3AgVHJ1ZSBpZiB0aGlzIHNob3VsZCBwcmVidWlsZCBhIGhvcCB0eCwgZWxzZSBmYWxzZVxuICAgKiBAcGFyYW0gYnVpbGRQYXJhbXMucmVjaXBpZW50cyBUaGUgcmVjaXBpZW50cyBhcnJheSBvZiB0aGlzIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSBidWlsZFBhcmFtcy53YWxsZXQgVGhlIHdhbGxldCBzZW5kaW5nIHRoaXMgdHhcbiAgICogQHBhcmFtIGJ1aWxkUGFyYW1zLndhbGxldFBhc3NwaHJhc2UgdGhlIHBhc3NwaHJhc2UgZm9yIHRoaXMgd2FsbGV0XG4gICAqL1xuICBhc3luYyBnZXRFeHRyYVByZWJ1aWxkUGFyYW1zKGJ1aWxkUGFyYW1zOiBCdWlsZE9wdGlvbnMpOiBQcm9taXNlPEJ1aWxkT3B0aW9ucz4ge1xuICAgIGlmIChcbiAgICAgICFfLmlzVW5kZWZpbmVkKGJ1aWxkUGFyYW1zLmhvcCkgJiZcbiAgICAgIGJ1aWxkUGFyYW1zLmhvcCAmJlxuICAgICAgIV8uaXNVbmRlZmluZWQoYnVpbGRQYXJhbXMud2FsbGV0KSAmJlxuICAgICAgIV8uaXNVbmRlZmluZWQoYnVpbGRQYXJhbXMucmVjaXBpZW50cykgJiZcbiAgICAgICFfLmlzVW5kZWZpbmVkKGJ1aWxkUGFyYW1zLndhbGxldFBhc3NwaHJhc2UpXG4gICAgKSB7XG4gICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIEVyYzIwVG9rZW4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBIb3AgdHJhbnNhY3Rpb25zIGFyZSBub3QgZW5hYmxlZCBmb3IgRVJDLTIwIHRva2Vucywgbm9yIGFyZSB0aGV5IG5lY2Vzc2FyeS4gUGxlYXNlIHJlbW92ZSB0aGUgJ2hvcCcgcGFyYW1ldGVyIGFuZCB0cnkgYWdhaW4uYFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmNyZWF0ZUhvcFRyYW5zYWN0aW9uUGFyYW1zKHtcbiAgICAgICAgd2FsbGV0OiBidWlsZFBhcmFtcy53YWxsZXQsXG4gICAgICAgIHJlY2lwaWVudHM6IGJ1aWxkUGFyYW1zLnJlY2lwaWVudHMsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IGJ1aWxkUGFyYW1zLndhbGxldFBhc3NwaHJhc2UsXG4gICAgICB9KSkgYXMgYW55O1xuICAgIH1cbiAgICByZXR1cm4ge307XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IHRyYW5zYWN0aW9uIGJ1aWxkZXIgZm9yIHRoZSBjdXJyZW50IGNoYWluXG4gICAqIEByZXR1cm4gYSBuZXcgdHJhbnNhY3Rpb24gYnVpbGRlclxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFRyYW5zYWN0aW9uQnVpbGRlcigpOiBUcmFuc2FjdGlvbkJ1aWxkZXIge1xuICAgIHJldHVybiBuZXcgVHJhbnNhY3Rpb25CdWlsZGVyKGNvaW5zLmdldCh0aGlzLmdldEJhc2VDaGFpbigpKSk7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgc3VwcG9ydHNNZXNzYWdlU2lnbmluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBzdXBwb3J0c1NpZ25pbmdUeXBlZERhdGEoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiJdfQ==