@bitgo/sdk-api 1.3.0-dev.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/dist/package.json +20 -9
  3. package/dist/src/api.d.ts.map +1 -1
  4. package/dist/src/api.js +5 -5
  5. package/dist/src/bitgoAPI.d.ts +227 -6
  6. package/dist/src/bitgoAPI.d.ts.map +1 -1
  7. package/dist/src/bitgoAPI.js +612 -17
  8. package/dist/src/types.d.ts +110 -9
  9. package/dist/src/types.d.ts.map +1 -1
  10. package/dist/src/types.js +2 -14
  11. package/dist/src/util.d.ts +0 -8
  12. package/dist/src/util.d.ts.map +1 -1
  13. package/dist/src/util.js +2 -21
  14. package/dist/src/v1/blockchain.d.ts +5 -0
  15. package/dist/src/v1/blockchain.d.ts.map +1 -0
  16. package/dist/src/v1/blockchain.js +114 -0
  17. package/dist/src/v1/keychains.d.ts +5 -0
  18. package/dist/src/v1/keychains.d.ts.map +1 -0
  19. package/dist/src/v1/keychains.js +315 -0
  20. package/dist/src/v1/markets.d.ts +5 -0
  21. package/dist/src/v1/markets.d.ts.map +1 -0
  22. package/dist/src/v1/markets.js +63 -0
  23. package/dist/src/v1/pendingapproval.d.ts +6 -0
  24. package/dist/src/v1/pendingapproval.d.ts.map +1 -0
  25. package/dist/src/v1/pendingapproval.js +322 -0
  26. package/dist/src/v1/pendingapprovals.d.ts +6 -0
  27. package/dist/src/v1/pendingapprovals.d.ts.map +1 -0
  28. package/dist/src/v1/pendingapprovals.js +68 -0
  29. package/dist/src/v1/transactionBuilder.d.ts +5 -0
  30. package/dist/src/v1/transactionBuilder.d.ts.map +1 -0
  31. package/dist/src/v1/transactionBuilder.js +889 -0
  32. package/dist/src/v1/travelRule.d.ts +5 -0
  33. package/dist/src/v1/travelRule.d.ts.map +1 -0
  34. package/dist/src/v1/travelRule.js +257 -0
  35. package/dist/src/v1/wallet.d.ts +6 -0
  36. package/dist/src/v1/wallet.d.ts.map +1 -0
  37. package/dist/src/v1/wallet.js +2095 -0
  38. package/dist/src/v1/wallets.d.ts +5 -0
  39. package/dist/src/v1/wallets.d.ts.map +1 -0
  40. package/dist/src/v1/wallets.js +472 -0
  41. package/dist/web/main.js +1 -1
  42. package/dist/web/main.js.LICENSE.txt +41 -0
  43. package/package.json +20 -9
  44. package/dist/tsconfig.tsbuildinfo +0 -7006
@@ -0,0 +1,889 @@
1
+ "use strict";
2
+ /**
3
+ * @hidden
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ /**
7
+ */
8
+ //
9
+ // TransactionBuilder
10
+ // A utility for building and signing transactions
11
+ //
12
+ // Copyright 2014, BitGo, Inc. All Rights Reserved.
13
+ //
14
+ const utxo_lib_1 = require("@bitgo/utxo-lib");
15
+ const Bluebird = require("bluebird");
16
+ const utxolib = require("@bitgo/utxo-lib");
17
+ const _ = require("lodash");
18
+ const unspents_1 = require("@bitgo/unspents");
19
+ const debugLib = require("debug");
20
+ const debug = debugLib('bitgo:v1:txb');
21
+ const sdk_core_1 = require("@bitgo/sdk-core");
22
+ //
23
+ // TransactionBuilder
24
+ // @params:
25
+ // wallet: a wallet object to send from
26
+ // recipients: array of recipient objects and the amount to send to each e.g. [{address: '38BKDNZbPcLogvVbcx2ekJ9E6Vv94DqDqw', amount: 1500}, {address: '36eL8yQqCn1HMRmVFFo49t2PJ3pai8wQam', amount: 2000}]
27
+ // fee: the fee to use with this transaction. if not provided, a default, minimum fee will be used.
28
+ // feeRate: the amount of fee per kilobyte - optional - specify either fee, feeRate, or feeTxConfirmTarget but not more than one
29
+ // feeTxConfirmTarget: calculate the fees per kilobyte such that the transaction will be confirmed in this number of blocks
30
+ // maxFeeRate: The maximum fee per kb to use in satoshis, for safety purposes when using dynamic fees
31
+ // minConfirms: the minimum confirmations an output must have before spending
32
+ // forceChangeAtEnd: force the change address to be the last output
33
+ // changeAddress: specify the change address rather than generate a new one
34
+ // noSplitChange: set to true to disable automatic change splitting for purposes of unspent management
35
+ // targetWalletUnspents: specify a number of target unspents to maintain in the wallet (currently defaulted to 8 by the server)
36
+ // validate: extra verification of the change addresses, which is always done server-side and is redundant client-side (defaults true)
37
+ // minUnspentSize: The minimum size in satoshis of unspent to use (to prevent spending unspents worth less than fee added). Defaults to 0.
38
+ // feeSingleKeySourceAddress: Use this single key address to pay fees
39
+ // feeSingleKeyWIF: Use the address based on this private key to pay fees
40
+ // unspentsFetchParams: Extra parameters to use for fetching unspents for this transaction
41
+ exports.createTransaction = function (params) {
42
+ const minConfirms = params.minConfirms || 0;
43
+ const validate = params.validate === undefined ? true : params.validate;
44
+ let recipients = [];
45
+ let opReturns = [];
46
+ let extraChangeAmounts = [];
47
+ let estTxSize;
48
+ let travelInfos;
49
+ // Sanity check the arguments passed in
50
+ if (!_.isObject(params.wallet) ||
51
+ (params.fee && !_.isNumber(params.fee)) ||
52
+ (params.feeRate && !_.isNumber(params.feeRate)) ||
53
+ !_.isInteger(minConfirms) ||
54
+ (params.forceChangeAtEnd && !_.isBoolean(params.forceChangeAtEnd)) ||
55
+ (params.changeAddress && !_.isString(params.changeAddress)) ||
56
+ (params.noSplitChange && !_.isBoolean(params.noSplitChange)) ||
57
+ (params.targetWalletUnspents && !_.isInteger(params.targetWalletUnspents)) ||
58
+ (validate && !_.isBoolean(validate)) ||
59
+ (params.enforceMinConfirmsForChange && !_.isBoolean(params.enforceMinConfirmsForChange)) ||
60
+ (params.minUnspentSize && !_.isNumber(params.minUnspentSize)) ||
61
+ (params.maxFeeRate && !_.isNumber(params.maxFeeRate)) ||
62
+ // this should be an array and its length must be at least 1
63
+ (params.unspents && (!Array.isArray(params.unspents) || params.unspents.length < 1)) ||
64
+ (params.feeTxConfirmTarget && !_.isInteger(params.feeTxConfirmTarget)) ||
65
+ (params.instant && !_.isBoolean(params.instant)) ||
66
+ (params.bitgoFee && !_.isObject(params.bitgoFee)) ||
67
+ (params.unspentsFetchParams && !_.isObject(params.unspentsFetchParams))) {
68
+ throw new Error('invalid argument');
69
+ }
70
+ const bitgo = params.wallet.bitgo;
71
+ const constants = bitgo.getConstants();
72
+ const network = sdk_core_1.getNetwork(sdk_core_1.common.Environments[bitgo.getEnv()].network);
73
+ // The user can specify a seperate, single-key wallet for the purposes of paying miner's fees
74
+ // When creating a transaction this can be specified as an input address or the private key in WIF
75
+ let feeSingleKeySourceAddress;
76
+ let feeSingleKeyInputAmount = 0;
77
+ if (params.feeSingleKeySourceAddress) {
78
+ try {
79
+ utxolib.address.fromBase58Check(params.feeSingleKeySourceAddress, network);
80
+ feeSingleKeySourceAddress = params.feeSingleKeySourceAddress;
81
+ }
82
+ catch (e) {
83
+ throw new Error('invalid bitcoin address: ' + params.feeSingleKeySourceAddress);
84
+ }
85
+ }
86
+ if (params.feeSingleKeyWIF) {
87
+ const feeSingleKey = utxolib.ECPair.fromWIF(params.feeSingleKeyWIF, network);
88
+ feeSingleKeySourceAddress = sdk_core_1.getAddressP2PKH(feeSingleKey);
89
+ // If the user specifies both, check to make sure the feeSingleKeySourceAddress corresponds to the address of feeSingleKeyWIF
90
+ if (params.feeSingleKeySourceAddress && params.feeSingleKeySourceAddress !== feeSingleKeySourceAddress) {
91
+ throw new Error('feeSingleKeySourceAddress: ' +
92
+ params.feeSingleKeySourceAddress +
93
+ ' did not correspond to address of feeSingleKeyWIF: ' +
94
+ feeSingleKeySourceAddress);
95
+ }
96
+ }
97
+ if (!_.isObject(params.recipients)) {
98
+ throw new Error('recipients must be array of { address: abc, amount: 100000 } objects');
99
+ }
100
+ let feeParamsDefined = 0;
101
+ if (!_.isUndefined(params.fee)) {
102
+ feeParamsDefined++;
103
+ }
104
+ if (!_.isUndefined(params.feeRate)) {
105
+ feeParamsDefined++;
106
+ }
107
+ if (!_.isUndefined(params.feeTxConfirmTarget)) {
108
+ feeParamsDefined++;
109
+ }
110
+ if (feeParamsDefined > 1) {
111
+ throw new Error('cannot specify more than one of fee, feeRate and feeTxConfirmTarget');
112
+ }
113
+ if (_.isUndefined(params.maxFeeRate)) {
114
+ params.maxFeeRate = constants.maxFeeRate;
115
+ }
116
+ // Convert the old format of params.recipients (dictionary of address:amount) to new format: { destinationAddress, amount }
117
+ if (!(params.recipients instanceof Array)) {
118
+ recipients = [];
119
+ Object.keys(params.recipients).forEach(function (destinationAddress) {
120
+ const amount = params.recipients[destinationAddress];
121
+ recipients.push({ address: destinationAddress, amount: amount });
122
+ });
123
+ }
124
+ else {
125
+ recipients = params.recipients;
126
+ }
127
+ if (params.opReturns) {
128
+ if (!(params.opReturns instanceof Array)) {
129
+ opReturns = [];
130
+ Object.keys(params.opReturns).forEach(function (message) {
131
+ const amount = params.opReturns[message];
132
+ opReturns.push({ message, amount });
133
+ });
134
+ }
135
+ else {
136
+ opReturns = params.opReturns;
137
+ }
138
+ }
139
+ if (recipients.length === 0 && opReturns.length === 0) {
140
+ throw new Error('must have at least one recipient');
141
+ }
142
+ let fee = params.fee;
143
+ let feeRate = params.feeRate;
144
+ // Flag indicating whether this class will compute the fee
145
+ const shouldComputeBestFee = _.isUndefined(fee);
146
+ let totalOutputAmount = 0;
147
+ recipients.forEach(function (recipient) {
148
+ if (_.isString(recipient.address)) {
149
+ try {
150
+ utxolib.address.fromBase58Check(recipient.address, network);
151
+ }
152
+ catch (e) {
153
+ throw new Error('invalid bitcoin address: ' + recipient.address);
154
+ }
155
+ if (!!recipient.script) {
156
+ // A script was provided as well - validate that the address corresponds to that
157
+ if (utxolib.address.toOutputScript(recipient.address, network).toString('hex') !== recipient.script) {
158
+ throw new Error('both script and address provided but they did not match: ' + recipient.address + ' ' + recipient.script);
159
+ }
160
+ }
161
+ }
162
+ if (!_.isInteger(recipient.amount) || recipient.amount < 0) {
163
+ throw new Error('invalid amount for ' + recipient.address + ': ' + recipient.amount);
164
+ }
165
+ totalOutputAmount += recipient.amount;
166
+ });
167
+ opReturns.forEach(function (opReturn) {
168
+ totalOutputAmount += opReturn.amount;
169
+ });
170
+ let bitgoFeeInfo = params.bitgoFee;
171
+ if (bitgoFeeInfo && (!_.isInteger(bitgoFeeInfo.amount) || !_.isString(bitgoFeeInfo.address))) {
172
+ throw new Error('invalid bitgoFeeInfo');
173
+ }
174
+ // The total amount needed for this transaction.
175
+ let totalAmount = totalOutputAmount + (fee || 0);
176
+ // The list of unspent transactions being used in this transaction.
177
+ let unspents;
178
+ // the total number of unspents on this wallet
179
+ let totalUnspentsCount;
180
+ // the number of unspents we fetched from the server, before filtering
181
+ let fetchedUnspentsCount;
182
+ // The list of unspent transactions being used with zero-confirmations
183
+ let zeroConfUnspentTxIds;
184
+ // The sum of the input values for this transaction.
185
+ let inputAmount;
186
+ let changeOutputs = [];
187
+ // The transaction.
188
+ let transaction = utxolib.bitgo.createTransactionBuilderForNetwork(network);
189
+ const getBitGoFee = function () {
190
+ return Bluebird.try(function () {
191
+ if (bitgoFeeInfo) {
192
+ return;
193
+ }
194
+ return params.wallet.getBitGoFee({ amount: totalOutputAmount, instant: params.instant }).then(function (result) {
195
+ if (result && result.fee > 0) {
196
+ bitgoFeeInfo = {
197
+ amount: result.fee,
198
+ };
199
+ }
200
+ });
201
+ }).then(function () {
202
+ if (bitgoFeeInfo && bitgoFeeInfo.amount > 0) {
203
+ totalAmount += bitgoFeeInfo.amount;
204
+ }
205
+ });
206
+ };
207
+ const getBitGoFeeAddress = function () {
208
+ return Bluebird.try(function () {
209
+ // If we don't have bitgoFeeInfo, or address is already set, don't get a new one
210
+ if (!bitgoFeeInfo || bitgoFeeInfo.address) {
211
+ return;
212
+ }
213
+ return bitgo.getBitGoFeeAddress().then(function (result) {
214
+ bitgoFeeInfo.address = result.address;
215
+ });
216
+ });
217
+ };
218
+ // Get a dynamic fee estimate from the BitGo server if feeTxConfirmTarget
219
+ // is specified or if no fee-related params are specified
220
+ const getDynamicFeeRateEstimate = function () {
221
+ if (params.feeTxConfirmTarget || !feeParamsDefined) {
222
+ return bitgo
223
+ .estimateFee({
224
+ numBlocks: params.feeTxConfirmTarget,
225
+ maxFee: params.maxFeeRate,
226
+ inputs: zeroConfUnspentTxIds,
227
+ txSize: estTxSize,
228
+ cpfpAware: true,
229
+ })
230
+ .then(function (result) {
231
+ const estimatedFeeRate = result.cpfpFeePerKb;
232
+ const minimum = params.instant
233
+ ? Math.max(constants.minFeeRate, constants.minInstantFeeRate)
234
+ : constants.minFeeRate;
235
+ // 5 satoshis per byte
236
+ // it is worth noting that the padding only applies when the threshold is crossed, but not when the delta is less than the padding
237
+ const padding = 5000;
238
+ if (estimatedFeeRate < minimum) {
239
+ console.log(new Date() +
240
+ ': Error when estimating fee for send from ' +
241
+ params.wallet.id() +
242
+ ', it was too low - ' +
243
+ estimatedFeeRate);
244
+ feeRate = minimum + padding;
245
+ }
246
+ else if (estimatedFeeRate > params.maxFeeRate) {
247
+ feeRate = params.maxFeeRate - padding;
248
+ }
249
+ else {
250
+ feeRate = estimatedFeeRate;
251
+ }
252
+ return feeRate;
253
+ })
254
+ .catch(function (e) {
255
+ // sanity check failed on tx size
256
+ if (_.includes(e.message, 'invalid txSize')) {
257
+ return Bluebird.reject(e);
258
+ }
259
+ else {
260
+ // couldn't estimate the fee, proceed using the default
261
+ feeRate = constants.fallbackFeeRate;
262
+ console.log('Error estimating fee for send from ' + params.wallet.id() + ': ' + e.message);
263
+ return Bluebird.resolve();
264
+ }
265
+ });
266
+ }
267
+ };
268
+ // Get the unspents for the sending wallet.
269
+ const getUnspents = function () {
270
+ if (params.unspents) {
271
+ // we just wanna use custom unspents
272
+ unspents = params.unspents;
273
+ return;
274
+ }
275
+ // Get enough unspents for the requested amount
276
+ const options = _.merge({}, params.unspentsFetchParams || {}, {
277
+ target: totalAmount,
278
+ minSize: params.minUnspentSize || 0,
279
+ instant: params.instant,
280
+ targetWalletUnspents: params.targetWalletUnspents,
281
+ });
282
+ if (params.instant) {
283
+ options.instant = params.instant; // insist on instant unspents only
284
+ }
285
+ return params.wallet.unspentsPaged(options).then(function (results) {
286
+ totalUnspentsCount = results.total;
287
+ fetchedUnspentsCount = results.count;
288
+ unspents = results.unspents.filter(function (u) {
289
+ const confirms = u.confirmations || 0;
290
+ if (!params.enforceMinConfirmsForChange && u.isChange) {
291
+ return true;
292
+ }
293
+ return confirms >= minConfirms;
294
+ });
295
+ // abort early if there's no viable unspents, because it won't be possible to create the txn later
296
+ if (unspents.length === 0) {
297
+ throw Error('0 unspents available for transaction creation');
298
+ }
299
+ // create array of unconfirmed unspent ID strings of the form "txHash:outputIndex"
300
+ zeroConfUnspentTxIds = _(results.unspents)
301
+ .filter(function (u) {
302
+ return !u.confirmations;
303
+ })
304
+ .map(function (u) {
305
+ return u.tx_hash + ':' + u.tx_output_n;
306
+ })
307
+ .value();
308
+ if (_.isEmpty(zeroConfUnspentTxIds)) {
309
+ // we don't want to pass an empty array of inputs to the server, because it assumes if the
310
+ // inputs arguments exists, it contains values
311
+ zeroConfUnspentTxIds = undefined;
312
+ }
313
+ // For backwards compatibility, respect the old splitChangeSize=0 parameter
314
+ if (!params.noSplitChange && params.splitChangeSize !== 0) {
315
+ extraChangeAmounts = results.extraChangeAmounts || [];
316
+ }
317
+ });
318
+ };
319
+ // Get the unspents for the single key fee address
320
+ let feeSingleKeyUnspents = [];
321
+ const getUnspentsForSingleKey = function () {
322
+ if (feeSingleKeySourceAddress) {
323
+ let feeTarget = 0.01e8;
324
+ if (params.instant) {
325
+ feeTarget += totalAmount * 0.001;
326
+ }
327
+ return bitgo
328
+ .get(bitgo.url('/address/' + feeSingleKeySourceAddress + '/unspents?target=' + feeTarget))
329
+ .then(function (response) {
330
+ if (response.body.total <= 0) {
331
+ throw new Error('No unspents available in single key fee source');
332
+ }
333
+ feeSingleKeyUnspents = response.body.unspents;
334
+ });
335
+ }
336
+ };
337
+ let minerFeeInfo = {};
338
+ let txInfo = {};
339
+ // Iterate unspents, sum the inputs, and save _inputs with the total
340
+ // input amount and final list of inputs to use with the transaction.
341
+ let feeSingleKeyUnspentsUsed = [];
342
+ const collectInputs = function () {
343
+ if (!unspents.length) {
344
+ throw new Error('no unspents available on wallet');
345
+ }
346
+ inputAmount = 0;
347
+ // Calculate the cost of spending a single input, i.e. the smallest economical unspent value
348
+ return Bluebird.try(function () {
349
+ if (_.isNumber(params.feeRate) || _.isNumber(params.originalFeeRate)) {
350
+ return !_.isUndefined(params.feeRate) ? params.feeRate : params.originalFeeRate;
351
+ }
352
+ else {
353
+ return bitgo
354
+ .estimateFee({
355
+ numBlocks: params.feeTxConfirmTarget,
356
+ maxFee: params.maxFeeRate,
357
+ })
358
+ .then(function (feeRateEstimate) {
359
+ return feeRateEstimate.feePerKb;
360
+ });
361
+ }
362
+ })
363
+ .then(function (feeRate) {
364
+ // Don't spend inputs that cannot pay for their own cost.
365
+ let minInputValue = 0;
366
+ if (_.isInteger(params.minUnspentSize)) {
367
+ minInputValue = params.minUnspentSize;
368
+ }
369
+ let prunedUnspentCount = 0;
370
+ const originalUnspentCount = unspents.length;
371
+ unspents = _.filter(unspents, function (unspent) {
372
+ const isSegwitInput = !!unspent.witnessScript;
373
+ const currentInputSize = isSegwitInput ? unspents_1.VirtualSizes.txP2shP2wshInputSize : unspents_1.VirtualSizes.txP2shInputSize;
374
+ const feeBasedMinInputValue = (feeRate * currentInputSize) / 1000;
375
+ const currentMinInputValue = Math.max(minInputValue, feeBasedMinInputValue);
376
+ if (currentMinInputValue > unspent.value) {
377
+ // pruning unspent
378
+ const pruneDetails = {
379
+ generalMinInputValue: minInputValue,
380
+ feeBasedMinInputValue,
381
+ currentMinInputValue,
382
+ feeRate,
383
+ inputSize: currentInputSize,
384
+ unspent: unspent,
385
+ };
386
+ console.log(`pruning unspent: ${JSON.stringify(pruneDetails, null, 4)}`);
387
+ prunedUnspentCount++;
388
+ return false;
389
+ }
390
+ return true;
391
+ });
392
+ if (prunedUnspentCount > 0) {
393
+ console.log(`pruned ${prunedUnspentCount} out of ${originalUnspentCount} unspents`);
394
+ }
395
+ if (unspents.length === 0) {
396
+ throw new Error('insufficient funds');
397
+ }
398
+ let segwitInputCount = 0;
399
+ unspents.every(function (unspent) {
400
+ if (unspent.witnessScript) {
401
+ segwitInputCount++;
402
+ }
403
+ inputAmount += unspent.value;
404
+ transaction.addInput(unspent.tx_hash, unspent.tx_output_n, 0xffffffff);
405
+ return inputAmount < (feeSingleKeySourceAddress ? totalOutputAmount : totalAmount);
406
+ });
407
+ // if paying fees from an external single key wallet, add the inputs
408
+ if (feeSingleKeySourceAddress) {
409
+ // collect the amount used in the fee inputs so we can get change later
410
+ feeSingleKeyInputAmount = 0;
411
+ feeSingleKeyUnspentsUsed = [];
412
+ feeSingleKeyUnspents.every(function (unspent) {
413
+ feeSingleKeyInputAmount += unspent.value;
414
+ inputAmount += unspent.value;
415
+ transaction.addInput(unspent.tx_hash, unspent.tx_output_n);
416
+ feeSingleKeyUnspentsUsed.push(unspent);
417
+ // use the fee wallet to pay miner fees and potentially instant fees
418
+ return feeSingleKeyInputAmount < fee + (bitgoFeeInfo ? bitgoFeeInfo.amount : 0);
419
+ });
420
+ }
421
+ txInfo = {
422
+ nP2shInputs: transaction.tx.ins.length - (feeSingleKeySourceAddress ? 1 : 0) - segwitInputCount,
423
+ nP2shP2wshInputs: segwitInputCount,
424
+ nP2pkhInputs: feeSingleKeySourceAddress ? 1 : 0,
425
+ // add single key source address change
426
+ nOutputs: recipients.length +
427
+ 1 + // recipients and change
428
+ extraChangeAmounts.length + // extra change splitting
429
+ (bitgoFeeInfo && bitgoFeeInfo.amount > 0 ? 1 : 0) + // add output for bitgo fee
430
+ (feeSingleKeySourceAddress ? 1 : 0),
431
+ };
432
+ estTxSize = estimateTransactionSize({
433
+ nP2shInputs: txInfo.nP2shInputs,
434
+ nP2shP2wshInputs: txInfo.nP2shP2wshInputs,
435
+ nP2pkhInputs: txInfo.nP2pkhInputs,
436
+ nOutputs: txInfo.nOutputs,
437
+ });
438
+ })
439
+ .then(getDynamicFeeRateEstimate)
440
+ .then(function () {
441
+ minerFeeInfo = exports.calculateMinerFeeInfo({
442
+ bitgo: params.wallet.bitgo,
443
+ feeRate: feeRate,
444
+ nP2shInputs: txInfo.nP2shInputs,
445
+ nP2shP2wshInputs: txInfo.nP2shP2wshInputs,
446
+ nP2pkhInputs: txInfo.nP2pkhInputs,
447
+ nOutputs: txInfo.nOutputs,
448
+ });
449
+ if (shouldComputeBestFee) {
450
+ const approximateFee = minerFeeInfo.fee;
451
+ const shouldRecurse = _.isUndefined(fee) || approximateFee > fee;
452
+ fee = approximateFee;
453
+ // Recompute totalAmount from scratch
454
+ totalAmount = fee + totalOutputAmount;
455
+ if (bitgoFeeInfo) {
456
+ totalAmount += bitgoFeeInfo.amount;
457
+ }
458
+ if (shouldRecurse) {
459
+ // if fee changed, re-collect inputs
460
+ inputAmount = 0;
461
+ transaction = utxolib.bitgo.createTransactionBuilderForNetwork(network);
462
+ return collectInputs();
463
+ }
464
+ }
465
+ const totalFee = fee + (bitgoFeeInfo ? bitgoFeeInfo.amount : 0);
466
+ if (feeSingleKeySourceAddress) {
467
+ const summedSingleKeyUnspents = _.sumBy(feeSingleKeyUnspents, 'value');
468
+ if (totalFee > summedSingleKeyUnspents) {
469
+ const err = new Error('Insufficient fee amount available in single key fee source: ' + summedSingleKeyUnspents);
470
+ err.result = {
471
+ fee: fee,
472
+ feeRate: feeRate,
473
+ estimatedSize: minerFeeInfo.size,
474
+ available: inputAmount,
475
+ bitgoFee: bitgoFeeInfo,
476
+ txInfo: txInfo,
477
+ };
478
+ return Bluebird.reject(err);
479
+ }
480
+ }
481
+ if (inputAmount < (feeSingleKeySourceAddress ? totalOutputAmount : totalAmount)) {
482
+ // The unspents we're using for inputs do not have sufficient value on them to
483
+ // satisfy the user's requested spend amount. That may be because the wallet's balance
484
+ // is simply too low, or it might be that the wallet's balance is sufficient but
485
+ // we didn't fetch enough unspents. Too few unspents could result from the wallet
486
+ // having many small unspents and we hit our limit on the number of inputs we can use
487
+ // in a txn, or it might have been that the filters the user passed in (like minConfirms)
488
+ // disqualified too many of the unspents
489
+ let err;
490
+ if (totalUnspentsCount === fetchedUnspentsCount) {
491
+ // we fetched every unspent the wallet had, but it still wasn't enough
492
+ err = new Error('Insufficient funds');
493
+ }
494
+ else {
495
+ // we weren't able to fetch all the unspents on the wallet
496
+ err = new Error(`Transaction size too large due to too many unspents. Can send only ${inputAmount} satoshis in this transaction`);
497
+ }
498
+ err.result = {
499
+ fee: fee,
500
+ feeRate: feeRate,
501
+ estimatedSize: minerFeeInfo.size,
502
+ available: inputAmount,
503
+ bitgoFee: bitgoFeeInfo,
504
+ txInfo: txInfo,
505
+ };
506
+ return Bluebird.reject(err);
507
+ }
508
+ });
509
+ };
510
+ // Add the outputs for this transaction.
511
+ const collectOutputs = function () {
512
+ if (minerFeeInfo.size >= 90000) {
513
+ throw new Error('transaction too large: estimated size ' + minerFeeInfo.size + ' bytes');
514
+ }
515
+ const outputs = [];
516
+ recipients.forEach(function (recipient) {
517
+ let script;
518
+ if (_.isString(recipient.address)) {
519
+ script = utxolib.address.toOutputScript(recipient.address, network);
520
+ }
521
+ else if (_.isObject(recipient.script)) {
522
+ script = recipient.script;
523
+ }
524
+ else {
525
+ throw new Error('neither recipient address nor script was provided');
526
+ }
527
+ // validate travelInfo if it exists
528
+ let travelInfo;
529
+ if (!_.isEmpty(recipient.travelInfo)) {
530
+ travelInfo = recipient.travelInfo;
531
+ // Better to avoid trouble now, before tx is created
532
+ bitgo.travelRule().validateTravelInfo(travelInfo);
533
+ }
534
+ outputs.push({
535
+ script: script,
536
+ amount: recipient.amount,
537
+ travelInfo: travelInfo,
538
+ });
539
+ });
540
+ opReturns.forEach(function ({ message, amount }) {
541
+ const script = utxolib.script.fromASM('OP_RETURN ' + Buffer.from(message).toString('hex'));
542
+ outputs.push({ script, amount });
543
+ });
544
+ const getChangeOutputs = function (changeAmount) {
545
+ if (changeAmount < 0) {
546
+ throw new Error('negative change amount: ' + changeAmount);
547
+ }
548
+ const result = [];
549
+ // if we paid fees from a single key wallet, return the fee change first
550
+ if (feeSingleKeySourceAddress) {
551
+ const feeSingleKeyWalletChangeAmount = feeSingleKeyInputAmount - (fee + (bitgoFeeInfo ? bitgoFeeInfo.amount : 0));
552
+ if (feeSingleKeyWalletChangeAmount >= constants.minOutputSize) {
553
+ result.push({ address: feeSingleKeySourceAddress, amount: feeSingleKeyWalletChangeAmount });
554
+ changeAmount = changeAmount - feeSingleKeyWalletChangeAmount;
555
+ }
556
+ }
557
+ if (changeAmount < constants.minOutputSize) {
558
+ // Give it to the miners
559
+ return result;
560
+ }
561
+ if (params.wallet.type() === 'safe') {
562
+ return params.wallet.addresses().then(function (response) {
563
+ result.push({ address: response.addresses[0].address, amount: changeAmount });
564
+ return result;
565
+ });
566
+ }
567
+ let extraChangeTotal = _.sum(extraChangeAmounts);
568
+ // Sanity check
569
+ if (extraChangeTotal > changeAmount) {
570
+ extraChangeAmounts = [];
571
+ extraChangeTotal = 0;
572
+ }
573
+ // copy and add remaining change amount
574
+ const allChangeAmounts = extraChangeAmounts.slice(0);
575
+ allChangeAmounts.push(changeAmount - extraChangeTotal);
576
+ // Recursive async func to add all change outputs
577
+ const addChangeOutputs = function () {
578
+ const thisAmount = allChangeAmounts.shift();
579
+ if (!thisAmount) {
580
+ return result;
581
+ }
582
+ return Bluebird.try(function () {
583
+ if (params.changeAddress) {
584
+ // If user passed a change address, use it for all outputs
585
+ return params.changeAddress;
586
+ }
587
+ else {
588
+ // Otherwise create a new address per output, for privacy
589
+ // determine if segwit or not
590
+ const changeChain = params.wallet.getChangeChain(params);
591
+ return params.wallet.createAddress({ chain: changeChain, validate: validate }).then(function (result) {
592
+ return result.address;
593
+ });
594
+ }
595
+ }).then(function (address) {
596
+ result.push({ address: address, amount: thisAmount });
597
+ return addChangeOutputs();
598
+ });
599
+ };
600
+ return addChangeOutputs();
601
+ };
602
+ // Add change output(s) and instant fee output if applicable
603
+ return Bluebird.try(function () {
604
+ return getChangeOutputs(inputAmount - totalAmount);
605
+ }).then(function (result) {
606
+ changeOutputs = result;
607
+ const extraOutputs = changeOutputs.concat([]); // copy the array
608
+ if (bitgoFeeInfo && bitgoFeeInfo.amount > 0) {
609
+ extraOutputs.push(bitgoFeeInfo);
610
+ }
611
+ extraOutputs.forEach(function (output) {
612
+ if (output.address) {
613
+ output.script = utxolib.address.toOutputScript(output.address, network);
614
+ }
615
+ // decide where to put the outputs - default is to randomize unless forced to end
616
+ const outputIndex = params.forceChangeAtEnd ? outputs.length : _.random(0, outputs.length);
617
+ outputs.splice(outputIndex, 0, output);
618
+ });
619
+ // Add all outputs to the transaction
620
+ outputs.forEach(function (output) {
621
+ transaction.addOutput(output.script, output.amount);
622
+ });
623
+ travelInfos = _(outputs)
624
+ .map(function (output, index) {
625
+ const result = output.travelInfo;
626
+ if (!result) {
627
+ return undefined;
628
+ }
629
+ result.outputIndex = index;
630
+ return result;
631
+ })
632
+ .filter()
633
+ .value();
634
+ });
635
+ };
636
+ // Serialize the transaction, returning what is needed to sign it
637
+ const serialize = function () {
638
+ // only need to return the unspents that were used and just the chainPath, redeemScript, and instant flag
639
+ const pickedUnspents = _.map(unspents, function (unspent) {
640
+ return _.pick(unspent, ['chainPath', 'redeemScript', 'instant', 'witnessScript', 'script', 'value']);
641
+ });
642
+ const prunedUnspents = _.slice(pickedUnspents, 0, transaction.tx.ins.length - feeSingleKeyUnspentsUsed.length);
643
+ _.each(feeSingleKeyUnspentsUsed, function (feeUnspent) {
644
+ prunedUnspents.push({ redeemScript: false, chainPath: false }); // mark as false to signify a non-multisig address
645
+ });
646
+ const result = {
647
+ transactionHex: transaction.buildIncomplete().toHex(),
648
+ unspents: prunedUnspents,
649
+ fee: fee,
650
+ changeAddresses: changeOutputs.map(function (co) {
651
+ return _.pick(co, ['address', 'path', 'amount']);
652
+ }),
653
+ walletId: params.wallet.id(),
654
+ walletKeychains: params.wallet.keychains,
655
+ feeRate: feeRate,
656
+ instant: params.instant,
657
+ bitgoFee: bitgoFeeInfo,
658
+ estimatedSize: minerFeeInfo.size,
659
+ txInfo: txInfo,
660
+ travelInfos: travelInfos,
661
+ };
662
+ // Add for backwards compatibility
663
+ if (result.instant && bitgoFeeInfo) {
664
+ result.instantFee = _.pick(bitgoFeeInfo, ['amount', 'address']);
665
+ }
666
+ return result;
667
+ };
668
+ return Bluebird.try(function () {
669
+ return getBitGoFee();
670
+ })
671
+ .then(function () {
672
+ return Bluebird.all([getBitGoFeeAddress(), getUnspents(), getUnspentsForSingleKey()]);
673
+ })
674
+ .then(collectInputs)
675
+ .then(collectOutputs)
676
+ .then(serialize);
677
+ };
678
+ /**
679
+ * Estimate the size of a transaction in bytes based on the number of
680
+ * inputs and outputs present.
681
+ * @params params {
682
+ * nP2shInputs: number of P2SH (multisig) inputs
683
+ * nP2pkhInputs: number of P2PKH (single sig) inputs
684
+ * nOutputs: number of outputs
685
+ * }
686
+ *
687
+ * @returns size: estimated size of the transaction in bytes
688
+ */
689
+ const estimateTransactionSize = function (params) {
690
+ if (!_.isInteger(params.nP2shInputs) || params.nP2shInputs < 0) {
691
+ throw new Error('expecting positive nP2shInputs');
692
+ }
693
+ if (!_.isInteger(params.nP2pkhInputs) || params.nP2pkhInputs < 0) {
694
+ throw new Error('expecting positive nP2pkhInputs to be numeric');
695
+ }
696
+ if (!_.isInteger(params.nP2shP2wshInputs) || params.nP2shP2wshInputs < 0) {
697
+ throw new Error('expecting positive nP2shP2wshInputs to be numeric');
698
+ }
699
+ if (params.nP2shInputs + params.nP2shP2wshInputs < 1) {
700
+ throw new Error('expecting at least one nP2shInputs or nP2shP2wshInputs');
701
+ }
702
+ if (!_.isInteger(params.nOutputs) || params.nOutputs < 1) {
703
+ throw new Error('expecting positive nOutputs');
704
+ }
705
+ const estimatedSize = unspents_1.VirtualSizes.txP2shInputSize * params.nP2shInputs +
706
+ unspents_1.VirtualSizes.txP2shP2wshInputSize * (params.nP2shP2wshInputs || 0) +
707
+ unspents_1.VirtualSizes.txP2pkhInputSizeUncompressedKey * (params.nP2pkhInputs || 0) +
708
+ unspents_1.VirtualSizes.txP2pkhOutputSize * params.nOutputs +
709
+ // if the tx contains at least one segwit input, the tx overhead is increased by 1
710
+ unspents_1.VirtualSizes.txOverheadSize +
711
+ (params.nP2shP2wshInputs > 0 ? 1 : 0);
712
+ return estimatedSize;
713
+ };
714
+ /**
715
+ * Calculate the fee and estimated size in bytes for a transaction.
716
+ * @params params {
717
+ * bitgo: bitgo object
718
+ * feeRate: satoshis per kilobyte
719
+ * nP2shInputs: number of P2SH (multisig) inputs
720
+ * nP2pkhInputs: number of P2PKH (single sig) inputs
721
+ * nOutputs: number of outputs
722
+ * }
723
+ *
724
+ * @returns {
725
+ * size: estimated size of the transaction in bytes
726
+ * fee: estimated fee in satoshis for the transaction
727
+ * feeRate: fee rate that was used to estimate the fee for the transaction
728
+ * }
729
+ */
730
+ exports.calculateMinerFeeInfo = function (params) {
731
+ const feeRateToUse = params.feeRate || params.bitgo.getConstants().fallbackFeeRate;
732
+ const estimatedSize = estimateTransactionSize(params);
733
+ return {
734
+ size: estimatedSize,
735
+ fee: Math.ceil((estimatedSize * feeRateToUse) / 1000),
736
+ feeRate: feeRateToUse,
737
+ };
738
+ };
739
+ /*
740
+ * Given a transaction hex, unspent information (chain path and redeem scripts), and the keychain xprv,
741
+ * perform key derivation and sign the inputs in the transaction based on the unspent information provided
742
+ *
743
+ * @params:
744
+ * transactionHex serialized form of the transaction in hex
745
+ * unspents array of unspent information, where each unspent is a chainPath and redeemScript with the same
746
+ * index as the inputs in the transactionHex
747
+ * keychain Keychain containing the xprv to sign with. For legacy support of safe wallets, keychain can
748
+ also be a WIF private key.
749
+ * signingKey private key in WIF for safe wallets, when keychain is unavailable
750
+ * validate client-side signature verification - can be disabled for improved performance (signatures
751
+ * are still validated server-side).
752
+ * feeSingleKeyWIF Use the address based on this private key to pay fees
753
+ * @returns {*}
754
+ */
755
+ exports.signTransaction = function (params) {
756
+ let keychain = params.keychain; // duplicate so as to not mutate below
757
+ const validate = params.validate === undefined ? true : params.validate;
758
+ let privKey;
759
+ if (!_.isString(params.transactionHex)) {
760
+ throw new Error('expecting the transaction hex as a string');
761
+ }
762
+ if (!Array.isArray(params.unspents)) {
763
+ throw new Error('expecting the unspents array');
764
+ }
765
+ if (!_.isBoolean(validate)) {
766
+ throw new Error('expecting validate to be a boolean');
767
+ }
768
+ let network = sdk_core_1.getNetwork();
769
+ const enableBCH = _.isBoolean(params.forceBCH) && params.forceBCH === true;
770
+ if (!_.isObject(keychain) || !_.isString(keychain.xprv)) {
771
+ if (_.isString(params.signingKey)) {
772
+ privKey = utxolib.ECPair.fromWIF(params.signingKey, network);
773
+ keychain = undefined;
774
+ }
775
+ else {
776
+ throw new Error('expecting the keychain object with xprv');
777
+ }
778
+ }
779
+ let feeSingleKey;
780
+ if (params.feeSingleKeyWIF) {
781
+ feeSingleKey = utxolib.ECPair.fromWIF(params.feeSingleKeyWIF, network);
782
+ }
783
+ debug('Network: %O', network);
784
+ if (enableBCH) {
785
+ debug('Enabling BCH…');
786
+ network = utxolib.networks.bitcoincash;
787
+ debug('New network: %O', network);
788
+ }
789
+ const transaction = utxolib.bitgo.createTransactionFromHex(params.transactionHex, network);
790
+ if (transaction.ins.length !== params.unspents.length) {
791
+ throw new Error('length of unspents array should equal to the number of transaction inputs');
792
+ }
793
+ // decorate transaction with input values for TransactionBuilder instantiation
794
+ const isUtxoTx = _.isObject(transaction) && Array.isArray(transaction.ins);
795
+ const areValidUnspents = _.isObject(params) && Array.isArray(params.unspents);
796
+ if (isUtxoTx && areValidUnspents) {
797
+ // extend the transaction inputs with the values
798
+ const inputValues = _.map(params.unspents, (u) => _.pick(u, 'value'));
799
+ transaction.ins.map((currentItem, index) => _.extend(currentItem, inputValues[index]));
800
+ }
801
+ let rootExtKey;
802
+ if (keychain) {
803
+ rootExtKey = utxo_lib_1.bip32.fromBase58(keychain.xprv);
804
+ }
805
+ const txb = utxolib.bitgo.createTransactionBuilderFromTransaction(transaction);
806
+ for (let index = 0; index < txb.tx.ins.length; ++index) {
807
+ const currentUnspent = params.unspents[index];
808
+ if (currentUnspent.redeemScript === false) {
809
+ // this is the input from a single key fee address
810
+ if (!feeSingleKey) {
811
+ throw new Error('single key address used in input but feeSingleKeyWIF not provided');
812
+ }
813
+ if (enableBCH) {
814
+ feeSingleKey.network = network;
815
+ }
816
+ txb.sign(index, feeSingleKey);
817
+ continue;
818
+ }
819
+ if (currentUnspent.witnessScript && enableBCH) {
820
+ throw new Error('BCH does not support segwit inputs');
821
+ }
822
+ const chainPath = currentUnspent.chainPath;
823
+ if (rootExtKey) {
824
+ const { walletSubPath = '/0/0' } = keychain;
825
+ const path = sdk_core_1.sanitizeLegacyPath(keychain.path + walletSubPath + chainPath);
826
+ debug('derived user key path "%s" using keychain path "%s", walletSubPath "%s", keychain walletSubPath "%s" and chainPath "%s"', path, keychain.path, walletSubPath, keychain.walletSubPath, chainPath);
827
+ privKey = rootExtKey.derivePath(path);
828
+ }
829
+ privKey.network = network;
830
+ // subscript is the part of the output script after the OP_CODESEPARATOR.
831
+ // Since we are only ever signing p2sh outputs, which do not have
832
+ // OP_CODESEPARATORS, it is always the output script.
833
+ const subscript = Buffer.from(currentUnspent.redeemScript, 'hex');
834
+ currentUnspent.validationScript = subscript;
835
+ // In order to sign with bitcoinjs-lib, we must use its transaction
836
+ // builder, confusingly named the same exact thing as our transaction
837
+ // builder, but with inequivalent behavior.
838
+ try {
839
+ const witnessScript = currentUnspent.witnessScript ? Buffer.from(currentUnspent.witnessScript, 'hex') : undefined;
840
+ const sigHash = utxolib.bitgo.getDefaultSigHash(network);
841
+ txb.sign(index, privKey, subscript, sigHash, currentUnspent.value, witnessScript);
842
+ }
843
+ catch (e) {
844
+ // try fallback derivation path (see BG-46497)
845
+ let fallbackSigningSuccessful = false;
846
+ try {
847
+ const fallbackPath = sdk_core_1.sanitizeLegacyPath(keychain.path + chainPath);
848
+ debug('derived fallback user key path "%s" using keychain path "%s" and chainPath "%s"', fallbackPath, keychain.path, chainPath);
849
+ privKey = rootExtKey.derivePath(fallbackPath);
850
+ const witnessScript = currentUnspent.witnessScript
851
+ ? Buffer.from(currentUnspent.witnessScript, 'hex')
852
+ : undefined;
853
+ const sigHash = utxolib.bitgo.getDefaultSigHash(network);
854
+ txb.sign(index, privKey, subscript, sigHash, currentUnspent.value, witnessScript);
855
+ fallbackSigningSuccessful = true;
856
+ }
857
+ catch (fallbackError) {
858
+ debug('input sign failed for fallback path: %s', fallbackError.message);
859
+ }
860
+ // we need to know what's causing this
861
+ if (!fallbackSigningSuccessful) {
862
+ e.result = {
863
+ unspent: currentUnspent,
864
+ };
865
+ e.message = `Failed to sign input #${index} - ${e.message} - ${JSON.stringify(e.result, null, 4)} - \n${e.stack}`;
866
+ debug('input sign failed: %s', e.message);
867
+ return Bluebird.reject(e);
868
+ }
869
+ }
870
+ }
871
+ const partialTransaction = txb.buildIncomplete();
872
+ if (validate) {
873
+ partialTransaction.ins.forEach((input, index) => {
874
+ const signatureCount = utxolib.bitgo
875
+ .getSignatureVerifications(partialTransaction, index, params.unspents[index].value)
876
+ .filter((v) => v.signedBy !== undefined).length;
877
+ if (signatureCount < 1) {
878
+ throw new Error('expected at least one valid signature');
879
+ }
880
+ if (params.fullLocalSigning && signatureCount < 2) {
881
+ throw new Error('fullLocalSigning set: expected at least two valid signatures');
882
+ }
883
+ });
884
+ }
885
+ return Bluebird.resolve({
886
+ transactionHex: partialTransaction.toHex(),
887
+ });
888
+ };
889
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3YxL3RyYW5zYWN0aW9uQnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7O0dBRUc7O0FBRUg7R0FDRztBQUNILEVBQUU7QUFDRixxQkFBcUI7QUFDckIsa0RBQWtEO0FBQ2xELEVBQUU7QUFDRixvREFBb0Q7QUFDcEQsRUFBRTtBQUVGLDhDQUF3QztBQUN4QyxxQ0FBcUM7QUFDckMsMkNBQTJDO0FBQzNDLDRCQUE0QjtBQUM1Qiw4Q0FBK0M7QUFDL0Msa0NBQW1DO0FBQ25DLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUN2Qyw4Q0FBMEY7QUF1QjFGLEVBQUU7QUFDRixxQkFBcUI7QUFDckIsV0FBVztBQUNYLDBDQUEwQztBQUMxQyw4TUFBOE07QUFDOU0sc0dBQXNHO0FBQ3RHLGtJQUFrSTtBQUNsSSw2SEFBNkg7QUFDN0gsdUdBQXVHO0FBQ3ZHLCtFQUErRTtBQUMvRSxxRUFBcUU7QUFDckUsNkVBQTZFO0FBQzdFLHdHQUF3RztBQUN4RyxpSUFBaUk7QUFDakksd0lBQXdJO0FBQ3hJLDRJQUE0STtBQUM1SSx1RUFBdUU7QUFDdkUsMkVBQTJFO0FBQzNFLDRGQUE0RjtBQUM1RixPQUFPLENBQUMsaUJBQWlCLEdBQUcsVUFBVSxNQUFNO0lBQzFDLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxXQUFXLElBQUksQ0FBQyxDQUFDO0lBQzVDLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7SUFDeEUsSUFBSSxVQUFVLEdBQTZFLEVBQUUsQ0FBQztJQUM5RixJQUFJLFNBQVMsR0FBMEMsRUFBRSxDQUFDO0lBQzFELElBQUksa0JBQWtCLEdBQWEsRUFBRSxDQUFDO0lBQ3RDLElB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RjtJQUVELE1BQU0sa0JBQWtCLEdBQUcsR0FBRyxDQUFDLGVBQWUsRUFBRSxDQUFDO0lBRWpELElBQUksUUFBUSxFQUFFO1FBQ1osa0JBQWtCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUM5QyxNQUFNLGNBQWMsR0FBRyxPQUFPLENBQUMsS0FBSztpQkFDakMseUJBQXlCLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDO2lCQUNsRixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEtBQUssU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDO1lBQ2xELElBQUksY0FBYyxHQUFHLENBQUMsRUFBRTtnQkFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO2FBQzFEO1lBQ0QsSUFBSSxNQUFNLENBQUMsZ0JBQWdCLElBQUksY0FBYyxHQUFHLENBQUMsRUFBRTtnQkFDakQsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO2FBQ2pGO1FBQ0gsQ0FBQyxDQUFDLENBQUM7S0FDSjtJQUVELE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQztRQUN0QixjQUFjLEVBQUUsa0JBQWtCLENBQUMsS0FBSyxFQUFFO0tBQzNDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGhpZGRlblxuICovXG5cbi8qKlxuICovXG4vL1xuLy8gVHJhbnNhY3Rpb25CdWlsZGVyXG4vLyBBIHV0aWxpdHkgZm9yIGJ1aWxkaW5nIGFuZCBzaWduaW5nIHRyYW5zYWN0aW9uc1xuLy9cbi8vIENvcHlyaWdodCAyMDE0LCBCaXRHbywgSW5jLiAgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbi8vXG5cbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIEJsdWViaXJkIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCAqIGFzIHV0eG9saWIgZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IFZpcnR1YWxTaXplcyB9IGZyb20gJ0BiaXRnby91bnNwZW50cyc7XG5pbXBvcnQgZGVidWdMaWIgPSByZXF1aXJlKCdkZWJ1ZycpO1xuY29uc3QgZGVidWcgPSBkZWJ1Z0xpYignYml0Z286djE6dHhiJyk7XG5pbXBvcnQgeyBjb21tb24sIGdldEFkZHJlc3NQMlBLSCwgZ2V0TmV0d29yaywgc2FuaXRpemVMZWdhY3lQYXRoIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcblxuaW50ZXJmYWNlIEJhc2VPdXRwdXQge1xuICBhbW91bnQ6IG51bWJlcjtcbiAgdHJhdmVsSW5mbz86IGFueTtcbn1cblxuaW50ZXJmYWNlIEFkZHJlc3NPdXRwdXQgZXh0ZW5kcyBCYXNlT3V0cHV0IHtcbiAgYWRkcmVzczogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgU2NyaXB0T3V0cHV0IGV4dGVuZHMgQmFzZU91dHB1dCB7XG4gIHNjcmlwdDogQnVmZmVyO1xufVxuXG50eXBlIE91dHB1dCA9IEFkZHJlc3NPdXRwdXQgfCBTY3JpcHRPdXRwdXQ7XG5cbmludGVyZmFjZSBCaXRHb1Vuc3BlbnQge1xuICB2YWx1ZTogbnVtYmVyO1xuICB0eF9oYXNoOiBCdWZmZXI7XG4gIHR4X291dHB1dF9uOiBudW1iZXI7XG59XG5cbi8vXG4vLyBUcmFuc2FjdGlvbkJ1aWxkZXJcbi8vIEBwYXJhbXM6XG4vLyAgIHdhbGxldDogIGEgd2FsbGV0IG9iamVjdCB0byBzZW5kIGZyb21cbi8vICAgcmVjaXBpZW50czogYXJyYXkgb2YgcmVjaXBpZW50IG9iamVjdHMgYW5kIHRoZSBhbW91bnQgdG8gc2VuZCB0byBlYWNoIGUuZy4gW3thZGRyZXNzOiAnMzhCS0ROWmJQY0xvZ3ZWYmN4MmVrSjlFNlZ2OTREcURxdycsIGFtb3VudDogMTUwMH0sIHthZGRyZXNzOiAnMzZlTDh5UXFDbjFITVJtVkZGbzQ5dDJQSjNwYWk4d1FhbScsIGFtb3VudDogMjAwMH1dXG4vLyAgIGZlZTogdGhlIGZlZSB0byB1c2Ugd2l0aCB0aGlzIHRyYW5zYWN0aW9uLiAgaWYgbm90IHByb3ZpZGVkLCBhIGRlZmF1bHQsIG1pbmltdW0gZmVlIHdpbGwgYmUgdXNlZC5cbi8vICAgZmVlUmF0ZTogdGhlIGFtb3VudCBvZiBmZWUgcGVyIGtpbG9ieXRlIC0gb3B0aW9uYWwgLSBzcGVjaWZ5IGVpdGhlciBmZWUsIGZlZVJhdGUsIG9yIGZlZVR4Q29uZmlybVRhcmdldCBidXQgbm90IG1vcmUgdGhhbiBvbmVcbi8vICAgZmVlVHhDb25maXJtVGFyZ2V0OiBjYWxjdWxhdGUgdGhlIGZlZXMgcGVyIGtpbG9ieXRlIHN1Y2ggdGhhdCB0aGUgdHJhbnNhY3Rpb24gd2lsbCBiZSBjb25maXJtZWQgaW4gdGhpcyBudW1iZXIgb2YgYmxvY2tzXG4vLyAgIG1heEZlZVJhdGU6IFRoZSBtYXhpbXVtIGZlZSBwZXIga2IgdG8gdXNlIGluIHNhdG9zaGlzLCBmb3Igc2FmZXR5IHB1cnBvc2VzIHdoZW4gdXNpbmcgZHluYW1pYyBmZWVzXG4vLyAgIG1pbkNvbmZpcm1zOiB0aGUgbWluaW11bSBjb25maXJtYXRpb25zIGFuIG91dHB1dCBtdXN0IGhhdmUgYmVmb3JlIHNwZW5kaW5nXG4vLyAgIGZvcmNlQ2hhbmdlQXRFbmQ6IGZvcmNlIHRoZSBjaGFuZ2UgYWRkcmVzcyB0byBiZSB0aGUgbGFzdCBvdXRwdXRcbi8vICAgY2hhbmdlQWRkcmVzczogc3BlY2lmeSB0aGUgY2hhbmdlIGFkZHJlc3MgcmF0aGVyIHRoYW4gZ2VuZXJhdGUgYSBuZXcgb25lXG4vLyAgIG5vU3BsaXRDaGFuZ2U6IHNldCB0byB0cnVlIHRvIGRpc2FibGUgYXV0b21hdGljIGNoYW5nZSBzcGxpdHRpbmcgZm9yIHB1cnBvc2VzIG9mIHVuc3BlbnQgbWFuYWdlbWVudFxuLy8gICB0YXJnZXRXYWxsZXRVbnNwZW50czogc3BlY2lmeSBhIG51bWJlciBvZiB0YXJnZXQgdW5zcGVudHMgdG8gbWFpbnRhaW4gaW4gdGhlIHdhbGxldCAoY3VycmVudGx5IGRlZmF1bHRlZCB0byA4IGJ5IHRoZSBzZXJ2ZXIpXG4vLyAgIHZhbGlkYXRlOiBleHRyYSB2ZXJpZmljYXRpb24gb2YgdGhlIGNoYW5nZSBhZGRyZXNzZXMsIHdoaWNoIGlzIGFsd2F5cyBkb25lIHNlcnZlci1zaWRlIGFuZCBpcyByZWR1bmRhbnQgY2xpZW50LXNpZGUgKGRlZmF1bHRzIHRydWUpXG4vLyAgIG1pblVuc3BlbnRTaXplOiBUaGUgbWluaW11bSBzaXplIGluIHNhdG9zaGlzIG9mIHVuc3BlbnQgdG8gdXNlICh0byBwcmV2ZW50IHNwZW5kaW5nIHVuc3BlbnRzIHdvcnRoIGxlc3MgdGhhbiBmZWUgYWRkZWQpLiBEZWZhdWx0cyB0byAwLlxuLy8gICBmZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzOiBVc2UgdGhpcyBzaW5nbGUga2V5IGFkZHJlc3MgdG8gcGF5IGZlZXNcbi8vICAgZmVlU2luZ2xlS2V5V0lGOiBVc2UgdGhlIGFkZHJlc3MgYmFzZWQgb24gdGhpcyBwcml2YXRlIGtleSB0byBwYXkgZmVlc1xuLy8gICB1bnNwZW50c0ZldGNoUGFyYW1zOiBFeHRyYSBwYXJhbWV0ZXJzIHRvIHVzZSBmb3IgZmV0Y2hpbmcgdW5zcGVudHMgZm9yIHRoaXMgdHJhbnNhY3Rpb25cbmV4cG9ydHMuY3JlYXRlVHJhbnNhY3Rpb24gPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gIGNvbnN0IG1pbkNvbmZpcm1zID0gcGFyYW1zLm1pbkNvbmZpcm1zIHx8IDA7XG4gIGNvbnN0IHZhbGlkYXRlID0gcGFyYW1zLnZhbGlkYXRlID09PSB1bmRlZmluZWQgPyB0cnVlIDogcGFyYW1zLnZhbGlkYXRlO1xuICBsZXQgcmVjaXBpZW50czogeyBhZGRyZXNzOiBzdHJpbmc7IGFtb3VudDogbnVtYmVyOyBzY3JpcHQ/OiBzdHJpbmc7IHRyYXZlbEluZm8/OiBhbnkgfVtdID0gW107XG4gIGxldCBvcFJldHVybnM6IHsgbWVzc2FnZTogc3RyaW5nOyBhbW91bnQ6IG51bWJlciB9W10gPSBbXTtcbiAgbGV0IGV4dHJhQ2hhbmdlQW1vdW50czogbnVtYmVyW10gPSBbXTtcbiAgbGV0IGVzdFR4U2l6ZTogbnVtYmVyO1xuICBsZXQgdHJhdmVsSW5mb3M7XG5cbiAgLy8gU2FuaXR5IGNoZWNrIHRoZSBhcmd1bWVudHMgcGFzc2VkIGluXG4gIGlmIChcbiAgICAhXy5pc09iamVjdChwYXJhbXMud2FsbGV0KSB8fFxuICAgIChwYXJhbXMuZmVlICYmICFfLmlzTnVtYmVyKHBhcmFtcy5mZWUpKSB8fFxuICAgIChwYXJhbXMuZmVlUmF0ZSAmJiAhXy5pc051bWJlcihwYXJhbXMuZmVlUmF0ZSkpIHx8XG4gICAgIV8uaXNJbnRlZ2VyKG1pbkNvbmZpcm1zKSB8fFxuICAgIChwYXJhbXMuZm9yY2VDaGFuZ2VBdEVuZCAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLmZvcmNlQ2hhbmdlQXRFbmQpKSB8fFxuICAgIChwYXJhbXMuY2hhbmdlQWRkcmVzcyAmJiAhXy5pc1N0cmluZyhwYXJhbXMuY2hhbmdlQWRkcmVzcykpIHx8XG4gICAgKHBhcmFtcy5ub1NwbGl0Q2hhbmdlICYmICFfLmlzQm9vbGVhbihwYXJhbXMubm9TcGxpdENoYW5nZSkpIHx8XG4gICAgKHBhcmFtcy50YXJnZXRXYWxsZXRVbnNwZW50cyAmJiAhXy5pc0ludGVnZXIocGFyYW1zLnRhcmdldFdhbGxldFVuc3BlbnRzKSkgfHxcbiAgICAodmFsaWRhdGUgJiYgIV8uaXNCb29sZWFuKHZhbGlkYXRlKSkgfHxcbiAgICAocGFyYW1zLmVuZm9yY2VNaW5Db25maXJtc0ZvckNoYW5nZSAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLmVuZm9yY2VNaW5Db25maXJtc0ZvckNoYW5nZSkpIHx8XG4gICAgKHBhcmFtcy5taW5VbnNwZW50U2l6ZSAmJiAhXy5pc051bWJlcihwYXJhbXMubWluVW5zcGVudFNpemUpKSB8fFxuICAgIChwYXJhbXMubWF4RmVlUmF0ZSAmJiAhXy5pc051bWJlcihwYXJhbXMubWF4RmVlUmF0ZSkpIHx8XG4gICAgLy8gdGhpcyBzaG91bGQgYmUgYW4gYXJyYXkgYW5kIGl0cyBsZW5ndGggbXVzdCBiZSBhdCBsZWFzdCAxXG4gICAgKHBhcmFtcy51bnNwZW50cyAmJiAoIUFycmF5LmlzQXJyYXkocGFyYW1zLnVuc3BlbnRzKSB8fCBwYXJhbXMudW5zcGVudHMubGVuZ3RoIDwgMSkpIHx8XG4gICAgKHBhcmFtcy5mZWVUeENvbmZpcm1UYXJnZXQgJiYgIV8uaXNJbnRlZ2VyKHBhcmFtcy5mZWVUeENvbmZpcm1UYXJnZXQpKSB8fFxuICAgIChwYXJhbXMuaW5zdGFudCAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLmluc3RhbnQpKSB8fFxuICAgIChwYXJhbXMuYml0Z29GZWUgJiYgIV8uaXNPYmplY3QocGFyYW1zLmJpdGdvRmVlKSkgfHxcbiAgICAocGFyYW1zLnVuc3BlbnRzRmV0Y2hQYXJhbXMgJiYgIV8uaXNPYmplY3QocGFyYW1zLnVuc3BlbnRzRmV0Y2hQYXJhbXMpKVxuICApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYXJndW1lbnQnKTtcbiAgfVxuXG4gIGNvbnN0IGJpdGdvID0gcGFyYW1zLndhbGxldC5iaXRnbztcbiAgY29uc3QgY29uc3RhbnRzID0gYml0Z28uZ2V0Q29uc3RhbnRzKCk7XG4gIGNvbnN0IG5ldHdvcmsgPSBnZXROZXR3b3JrKGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLm5ldHdvcmspO1xuXG4gIC8vIFRoZSB1c2VyIGNhbiBzcGVjaWZ5IGEgc2VwZXJhdGUsIHNpbmdsZS1rZXkgd2FsbGV0IGZvciB0aGUgcHVycG9zZXMgb2YgcGF5aW5nIG1pbmVyJ3MgZmVlc1xuICAvLyBXaGVuIGNyZWF0aW5nIGEgdHJhbnNhY3Rpb24gdGhpcyBjYW4gYmUgc3BlY2lmaWVkIGFzIGFuIGlucHV0IGFkZHJlc3Mgb3IgdGhlIHByaXZhdGUga2V5IGluIFdJRlxuICBsZXQgZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzcztcbiAgbGV0IGZlZVNpbmdsZUtleUlucHV0QW1vdW50ID0gMDtcbiAgaWYgKHBhcmFtcy5mZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzKSB7XG4gICAgdHJ5IHtcbiAgICAgIHV0eG9saWIuYWRkcmVzcy5mcm9tQmFzZTU4Q2hlY2socGFyYW1zLmZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3MsIG5ldHdvcmspO1xuICAgICAgZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzcyA9IHBhcmFtcy5mZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBiaXRjb2luIGFkZHJlc3M6ICcgKyBwYXJhbXMuZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzcyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHBhcmFtcy5mZWVTaW5nbGVLZXlXSUYpIHtcbiAgICBjb25zdCBmZWVTaW5nbGVLZXkgPSB1dHhvbGliLkVDUGFpci5mcm9tV0lGKHBhcmFtcy5mZWVTaW5nbGVLZXlXSUYsIG5ldHdvcmsgYXMgdXR4b2xpYi5CaXRjb2luSlNOZXR3b3JrKTtcbiAgICBmZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzID0gZ2V0QWRkcmVzc1AyUEtIKGZlZVNpbmdsZUtleSk7XG4gICAgLy8gSWYgdGhlIHVzZXIgc3BlY2lmaWVzIGJvdGgsIGNoZWNrIHRvIG1ha2Ugc3VyZSB0aGUgZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzcyBjb3JyZXNwb25kcyB0byB0aGUgYWRkcmVzcyBvZiBmZWVTaW5nbGVLZXlXSUZcbiAgICBpZiAocGFyYW1zLmZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3MgJiYgcGFyYW1zLmZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3MgIT09IGZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3MpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ2ZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3M6ICcgK1xuICAgICAgICAgIHBhcmFtcy5mZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzICtcbiAgICAgICAgICAnIGRpZCBub3QgY29ycmVzcG9uZCB0byBhZGRyZXNzIG9mIGZlZVNpbmdsZUtleVdJRjogJyArXG4gICAgICAgICAgZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzc1xuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpZiAoIV8uaXNPYmplY3QocGFyYW1zLnJlY2lwaWVudHMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdyZWNpcGllbnRzIG11c3QgYmUgYXJyYXkgb2YgeyBhZGRyZXNzOiBhYmMsIGFtb3VudDogMTAwMDAwIH0gb2JqZWN0cycpO1xuICB9XG5cbiAgbGV0IGZlZVBhcmFtc0RlZmluZWQgPSAwO1xuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmZlZSkpIHtcbiAgICBmZWVQYXJhbXNEZWZpbmVkKys7XG4gIH1cblxuICBpZiAoIV8uaXNVbmRlZmluZWQocGFyYW1zLmZlZVJhdGUpKSB7XG4gICAgZmVlUGFyYW1zRGVmaW5lZCsrO1xuICB9XG5cbiAgaWYgKCFfLmlzVW5kZWZpbmVkKHBhcmFtcy5mZWVUeENvbmZpcm1UYXJnZXQpKSB7XG4gICAgZmVlUGFyYW1zRGVmaW5lZCsrO1xuICB9XG5cbiAgaWYgKGZlZVBhcmFtc0RlZmluZWQgPiAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjYW5ub3Qgc3BlY2lmeSBtb3JlIHRoYW4gb25lIG9mIGZlZSwgZmVlUmF0ZSBhbmQgZmVlVHhDb25maXJtVGFyZ2V0Jyk7XG4gIH1cblxuICBpZiAoXy5pc1VuZGVmaW5lZChwYXJhbXMubWF4RmVlUmF0ZSkpIHtcbiAgICBwYXJhbXMubWF4RmVlUmF0ZSA9IGNvbnN0YW50cy5tYXhGZWVSYXRlO1xuICB9XG5cbiAgLy8gQ29udmVydCB0aGUgb2xkIGZvcm1hdCBvZiBwYXJhbXMucmVjaXBpZW50cyAoZGljdGlvbmFyeSBvZiBhZGRyZXNzOmFtb3VudCkgdG8gbmV3IGZvcm1hdDogeyBkZXN0aW5hdGlvbkFkZHJlc3MsIGFtb3VudCB9XG4gIGlmICghKHBhcmFtcy5yZWNpcGllbnRzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgcmVjaXBpZW50cyA9IFtdO1xuICAgIE9iamVjdC5rZXlzKHBhcmFtcy5yZWNpcGllbnRzKS5mb3JFYWNoKGZ1bmN0aW9uIChkZXN0aW5hdGlvbkFkZHJlc3MpIHtcbiAgICAgIGNvbnN0IGFtb3VudCA9IHBhcmFtcy5yZWNpcGllbnRzW2Rlc3RpbmF0aW9uQWRkcmVzc107XG4gICAgICByZWNpcGllbnRzLnB1c2goeyBhZGRyZXNzOiBkZXN0aW5hdGlvbkFkZHJlc3MsIGFtb3VudDogYW1vdW50IH0pO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJlY2lwaWVudHMgPSBwYXJhbXMucmVjaXBpZW50cztcbiAgfVxuXG4gIGlmIChwYXJhbXMub3BSZXR1cm5zKSB7XG4gICAgaWYgKCEocGFyYW1zLm9wUmV0dXJucyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgICAgb3BSZXR1cm5zID0gW107XG4gICAgICBPYmplY3Qua2V5cyhwYXJhbXMub3BSZXR1cm5zKS5mb3JFYWNoKGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gICAgICAgIGNvbnN0IGFtb3VudCA9IHBhcmFtcy5vcFJldHVybnNbbWVzc2FnZV07XG4gICAgICAgIG9wUmV0dXJucy5wdXNoKHsgbWVzc2FnZSwgYW1vdW50IH0pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wUmV0dXJucyA9IHBhcmFtcy5vcFJldHVybnM7XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlY2lwaWVudHMubGVuZ3RoID09PSAwICYmIG9wUmV0dXJucy5sZW5ndGggPT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ211c3QgaGF2ZSBhdCBsZWFzdCBvbmUgcmVjaXBpZW50Jyk7XG4gIH1cblxuICBsZXQgZmVlID0gcGFyYW1zLmZlZTtcbiAgbGV0IGZlZVJhdGUgPSBwYXJhbXMuZmVlUmF0ZTtcblxuICAvLyBGbGFnIGluZGljYXRpbmcgd2hldGhlciB0aGlzIGNsYXNzIHdpbGwgY29tcHV0ZSB0aGUgZmVlXG4gIGNvbnN0IHNob3VsZENvbXB1dGVCZXN0RmVlID0gXy5pc1VuZGVmaW5lZChmZWUpO1xuXG4gIGxldCB0b3RhbE91dHB1dEFtb3VudCA9IDA7XG5cbiAgcmVjaXBpZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChyZWNpcGllbnQpIHtcbiAgICBpZiAoXy5pc1N0cmluZyhyZWNpcGllbnQuYWRkcmVzcykpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHV0eG9saWIuYWRkcmVzcy5mcm9tQmFzZTU4Q2hlY2socmVjaXBpZW50LmFkZHJlc3MsIG5ldHdvcmspO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYml0Y29pbiBhZGRyZXNzOiAnICsgcmVjaXBpZW50LmFkZHJlc3MpO1xuICAgICAgfVxuICAgICAgaWYgKCEhcmVjaXBpZW50LnNjcmlwdCkge1xuICAgICAgICAvLyBBIHNjcmlwdCB3YXMgcHJvdmlkZWQgYXMgd2VsbCAtIHZhbGlkYXRlIHRoYXQgdGhlIGFkZHJlc3MgY29ycmVzcG9uZHMgdG8gdGhhdFxuICAgICAgICBpZiAodXR4b2xpYi5hZGRyZXNzLnRvT3V0cHV0U2NyaXB0KHJlY2lwaWVudC5hZGRyZXNzLCBuZXR3b3JrKS50b1N0cmluZygnaGV4JykgIT09IHJlY2lwaWVudC5zY3JpcHQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnYm90aCBzY3JpcHQgYW5kIGFkZHJlc3MgcHJvdmlkZWQgYnV0IHRoZXkgZGlkIG5vdCBtYXRjaDogJyArIHJlY2lwaWVudC5hZGRyZXNzICsgJyAnICsgcmVjaXBpZW50LnNjcmlwdFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFfLmlzSW50ZWdlcihyZWNpcGllbnQuYW1vdW50KSB8fCByZWNpcGllbnQuYW1vdW50IDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFtb3VudCBmb3IgJyArIHJlY2lwaWVudC5hZGRyZXNzICsgJzogJyArIHJlY2lwaWVudC5hbW91bnQpO1xuICAgIH1cbiAgICB0b3RhbE91dHB1dEFtb3VudCArPSByZWNpcGllbnQuYW1vdW50O1xuICB9KTtcblxuICBvcFJldHVybnMuZm9yRWFjaChmdW5jdGlvbiAob3BSZXR1cm4pIHtcbiAgICB0b3RhbE91dHB1dEFtb3VudCArPSBvcFJldHVybi5hbW91bnQ7XG4gIH0pO1xuXG4gIGxldCBiaXRnb0ZlZUluZm8gPSBwYXJhbXMuYml0Z29GZWU7XG4gIGlmIChiaXRnb0ZlZUluZm8gJiYgKCFfLmlzSW50ZWdlcihiaXRnb0ZlZUluZm8uYW1vdW50KSB8fCAhXy5pc1N0cmluZyhiaXRnb0ZlZUluZm8uYWRkcmVzcykpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJpdGdvRmVlSW5mbycpO1xuICB9XG5cbiAgLy8gVGhlIHRvdGFsIGFtb3VudCBuZWVkZWQgZm9yIHRoaXMgdHJhbnNhY3Rpb24uXG4gIGxldCB0b3RhbEFtb3VudCA9IHRvdGFsT3V0cHV0QW1vdW50ICsgKGZlZSB8fCAwKTtcblxuICAvLyBUaGUgbGlzdCBvZiB1bnNwZW50IHRyYW5zYWN0aW9ucyBiZWluZyB1c2VkIGluIHRoaXMgdHJhbnNhY3Rpb24uXG4gIGxldCB1bnNwZW50cztcblxuICAvLyB0aGUgdG90YWwgbnVtYmVyIG9mIHVuc3BlbnRzIG9uIHRoaXMgd2FsbGV0XG4gIGxldCB0b3RhbFVuc3BlbnRzQ291bnQ7XG5cbiAgLy8gdGhlIG51bWJlciBvZiB1bnNwZW50cyB3ZSBmZXRjaGVkIGZyb20gdGhlIHNlcnZlciwgYmVmb3JlIGZpbHRlcmluZ1xuICBsZXQgZmV0Y2hlZFVuc3BlbnRzQ291bnQ7XG5cbiAgLy8gVGhlIGxpc3Qgb2YgdW5zcGVudCB0cmFuc2FjdGlvbnMgYmVpbmcgdXNlZCB3aXRoIHplcm8tY29uZmlybWF0aW9uc1xuICBsZXQgemVyb0NvbmZVbnNwZW50VHhJZHM7XG5cbiAgLy8gVGhlIHN1bSBvZiB0aGUgaW5wdXQgdmFsdWVzIGZvciB0aGlzIHRyYW5zYWN0aW9uLlxuICBsZXQgaW5wdXRBbW91bnQ7XG5cbiAgbGV0IGNoYW5nZU91dHB1dHM6IE91dHB1dFtdID0gW107XG5cbiAgLy8gVGhlIHRyYW5zYWN0aW9uLlxuICBsZXQgdHJhbnNhY3Rpb24gPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uQnVpbGRlckZvck5ldHdvcmsobmV0d29yayk7XG5cbiAgY29uc3QgZ2V0Qml0R29GZWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIEJsdWViaXJkLnRyeShmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoYml0Z29GZWVJbmZvKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwYXJhbXMud2FsbGV0LmdldEJpdEdvRmVlKHsgYW1vdW50OiB0b3RhbE91dHB1dEFtb3VudCwgaW5zdGFudDogcGFyYW1zLmluc3RhbnQgfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgIGlmIChyZXN1bHQgJiYgcmVzdWx0LmZlZSA+IDApIHtcbiAgICAgICAgICBiaXRnb0ZlZUluZm8gPSB7XG4gICAgICAgICAgICBhbW91bnQ6IHJlc3VsdC5mZWUsXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoYml0Z29GZWVJbmZvICYmIGJpdGdvRmVlSW5mby5hbW91bnQgPiAwKSB7XG4gICAgICAgIHRvdGFsQW1vdW50ICs9IGJpdGdvRmVlSW5mby5hbW91bnQ7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgY29uc3QgZ2V0Qml0R29GZWVBZGRyZXNzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBCbHVlYmlyZC50cnkoZnVuY3Rpb24gKCkge1xuICAgICAgLy8gSWYgd2UgZG9uJ3QgaGF2ZSBiaXRnb0ZlZUluZm8sIG9yIGFkZHJlc3MgaXMgYWxyZWFkeSBzZXQsIGRvbid0IGdldCBhIG5ldyBvbmVcbiAgICAgIGlmICghYml0Z29GZWVJbmZvIHx8IGJpdGdvRmVlSW5mby5hZGRyZXNzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBiaXRnby5nZXRCaXRHb0ZlZUFkZHJlc3MoKS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgYml0Z29GZWVJbmZvLmFkZHJlc3MgPSByZXN1bHQuYWRkcmVzcztcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIEdldCBhIGR5bmFtaWMgZmVlIGVzdGltYXRlIGZyb20gdGhlIEJpdEdvIHNlcnZlciBpZiBmZWVUeENvbmZpcm1UYXJnZXRcbiAgLy8gaXMgc3BlY2lmaWVkIG9yIGlmIG5vIGZlZS1yZWxhdGVkIHBhcmFtcyBhcmUgc3BlY2lmaWVkXG4gIGNvbnN0IGdldER5bmFtaWNGZWVSYXRlRXN0aW1hdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHBhcmFtcy5mZWVUeENvbmZpcm1UYXJnZXQgfHwgIWZlZVBhcmFtc0RlZmluZWQpIHtcbiAgICAgIHJldHVybiBiaXRnb1xuICAgICAgICAuZXN0aW1hdGVGZWUoe1xuICAgICAgICAgIG51bUJsb2NrczogcGFyYW1zLmZlZVR4Q29uZmlybVRhcmdldCxcbiAgICAgICAgICBtYXhGZWU6IHBhcmFtcy5tYXhGZWVSYXRlLFxuICAgICAgICAgIGlucHV0czogemVyb0NvbmZVbnNwZW50VHhJZHMsXG4gICAgICAgICAgdHhTaXplOiBlc3RUeFNpemUsXG4gICAgICAgICAgY3BmcEF3YXJlOiB0cnVlLFxuICAgICAgICB9KVxuICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgY29uc3QgZXN0aW1hdGVkRmVlUmF0ZSA9IHJlc3VsdC5jcGZwRmVlUGVyS2I7XG4gICAgICAgICAgY29uc3QgbWluaW11bSA9IHBhcmFtcy5pbnN0YW50XG4gICAgICAgICAgICA/IE1hdGgubWF4KGNvbnN0YW50cy5taW5GZWVSYXRlLCBjb25zdGFudHMubWluSW5zdGFudEZlZVJhdGUpXG4gICAgICAgICAgICA6IGNvbnN0YW50cy5taW5GZWVSYXRlO1xuICAgICAgICAgIC8vIDUgc2F0b3NoaXMgcGVyIGJ5dGVcbiAgICAgICAgICAvLyBpdCBpcyB3b3J0aCBub3RpbmcgdGhhdCB0aGUgcGFkZGluZyBvbmx5IGFwcGxpZXMgd2hlbiB0aGUgdGhyZXNob2xkIGlzIGNyb3NzZWQsIGJ1dCBub3Qgd2hlbiB0aGUgZGVsdGEgaXMgbGVzcyB0aGFuIHRoZSBwYWRkaW5nXG4gICAgICAgICAgY29uc3QgcGFkZGluZyA9IDUwMDA7XG4gICAgICAgICAgaWYgKGVzdGltYXRlZEZlZVJhdGUgPCBtaW5pbXVtKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgbmV3IERhdGUoKSArXG4gICAgICAgICAgICAgICAgJzogRXJyb3Igd2hlbiBlc3RpbWF0aW5nIGZlZSBmb3Igc2VuZCBmcm9tICcgK1xuICAgICAgICAgICAgICAgIHBhcmFtcy53YWxsZXQuaWQoKSArXG4gICAgICAgICAgICAgICAgJywgaXQgd2FzIHRvbyBsb3cgLSAnICtcbiAgICAgICAgICAgICAgICBlc3RpbWF0ZWRGZWVSYXRlXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgZmVlUmF0ZSA9IG1pbmltdW0gKyBwYWRkaW5nO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZXN0aW1hdGVkRmVlUmF0ZSA+IHBhcmFtcy5tYXhGZWVSYXRlKSB7XG4gICAgICAgICAgICBmZWVSYXRlID0gcGFyYW1zLm1heEZlZVJhdGUgLSBwYWRkaW5nO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmZWVSYXRlID0gZXN0aW1hdGVkRmVlUmF0ZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZlZVJhdGU7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICAgIC8vIHNhbml0eSBjaGVjayBmYWlsZWQgb24gdHggc2l6ZVxuICAgICAgICAgIGlmIChfLmluY2x1ZGVzKGUubWVzc2FnZSwgJ2ludmFsaWQgdHhTaXplJykpIHtcbiAgICAgICAgICAgIHJldHVybiBCbHVlYmlyZC5yZWplY3QoZSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNvdWxkbid0IGVzdGltYXRlIHRoZSBmZWUsIHByb2NlZWQgdXNpbmcgdGhlIGRlZmF1bHRcbiAgICAgICAgICAgIGZlZVJhdGUgPSBjb25zdGFudHMuZmFsbGJhY2tGZWVSYXRlO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ0Vycm9yIGVzdGltYXRpbmcgZmVlIGZvciBzZW5kIGZyb20gJyArIHBhcmFtcy53YWxsZXQuaWQoKSArICc6ICcgKyBlLm1lc3NhZ2UpO1xuICAgICAgICAgICAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICAvLyBHZXQgdGhlIHVuc3BlbnRzIGZvciB0aGUgc2VuZGluZyB3YWxsZXQuXG4gIGNvbnN0IGdldFVuc3BlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIGlmIChwYXJhbXMudW5zcGVudHMpIHtcbiAgICAgIC8vIHdlIGp1c3Qgd2FubmEgdXNlIGN1c3RvbSB1bnNwZW50c1xuICAgICAgdW5zcGVudHMgPSBwYXJhbXMudW5zcGVudHM7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gR2V0IGVub3VnaCB1bnNwZW50cyBmb3IgdGhlIHJlcXVlc3RlZCBhbW91bnRcbiAgICBjb25zdCBvcHRpb25zID0gXy5tZXJnZSh7fSwgcGFyYW1zLnVuc3BlbnRzRmV0Y2hQYXJhbXMgfHwge30sIHtcbiAgICAgIHRhcmdldDogdG90YWxBbW91bnQsXG4gICAgICBtaW5TaXplOiBwYXJhbXMubWluVW5zcGVudFNpemUgfHwgMCxcbiAgICAgIGluc3RhbnQ6IHBhcmFtcy5pbnN0YW50LCAvLyBpbnNpc3Qgb24gaW5zdGFudCB1bnNwZW50cyBvbmx5XG4gICAgICB0YXJnZXRXYWxsZXRVbnNwZW50czogcGFyYW1zLnRhcmdldFdhbGxldFVuc3BlbnRzLFxuICAgIH0pO1xuICAgIGlmIChwYXJhbXMuaW5zdGFudCkge1xuICAgICAgb3B0aW9ucy5pbnN0YW50ID0gcGFyYW1zLmluc3RhbnQ7IC8vIGluc2lzdCBvbiBpbnN0YW50IHVuc3BlbnRzIG9ubHlcbiAgICB9XG5cbiAgICByZXR1cm4gcGFyYW1zLndhbGxldC51bnNwZW50c1BhZ2VkKG9wdGlvbnMpLnRoZW4oZnVuY3Rpb24gKHJlc3VsdHMpIHtcbiAgICAgIHRvdGFsVW5zcGVudHNDb3VudCA9IHJlc3VsdHMudG90YWw7XG4gICAgICBmZXRjaGVkVW5zcGVudHNDb3VudCA9IHJlc3VsdHMuY291bnQ7XG4gICAgICB1bnNwZW50cyA9IHJlc3VsdHMudW5zcGVudHMuZmlsdGVyKGZ1bmN0aW9uICh1KSB7XG4gICAgICAgIGNvbnN0IGNvbmZpcm1zID0gdS5jb25maXJtYXRpb25zIHx8IDA7XG4gICAgICAgIGlmICghcGFyYW1zLmVuZm9yY2VNaW5Db25maXJtc0ZvckNoYW5nZSAmJiB1LmlzQ2hhbmdlKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbmZpcm1zID49IG1pbkNvbmZpcm1zO1xuICAgICAgfSk7XG5cbiAgICAgIC8vIGFib3J0IGVhcmx5IGlmIHRoZXJlJ3Mgbm8gdmlhYmxlIHVuc3BlbnRzLCBiZWNhdXNlIGl0IHdvbid0IGJlIHBvc3NpYmxlIHRvIGNyZWF0ZSB0aGUgdHhuIGxhdGVyXG4gICAgICBpZiAodW5zcGVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRocm93IEVycm9yKCcwIHVuc3BlbnRzIGF2YWlsYWJsZSBmb3IgdHJhbnNhY3Rpb24gY3JlYXRpb24nKTtcbiAgICAgIH1cblxuICAgICAgLy8gY3JlYXRlIGFycmF5IG9mIHVuY29uZmlybWVkIHVuc3BlbnQgSUQgc3RyaW5ncyBvZiB0aGUgZm9ybSBcInR4SGFzaDpvdXRwdXRJbmRleFwiXG4gICAgICB6ZXJvQ29uZlVuc3BlbnRUeElkcyA9IF8ocmVzdWx0cy51bnNwZW50cylcbiAgICAgICAgLmZpbHRlcihmdW5jdGlvbiAodSkge1xuICAgICAgICAgIHJldHVybiAhdS5jb25maXJtYXRpb25zO1xuICAgICAgICB9KVxuICAgICAgICAubWFwKGZ1bmN0aW9uICh1KSB7XG4gICAgICAgICAgcmV0dXJuIHUudHhfaGFzaCArICc6JyArIHUudHhfb3V0cHV0X247XG4gICAgICAgIH0pXG4gICAgICAgIC52YWx1ZSgpO1xuICAgICAgaWYgKF8uaXNFbXB0eSh6ZXJvQ29uZlVuc3BlbnRUeElkcykpIHtcbiAgICAgICAgLy8gd2UgZG9uJ3Qgd2FudCB0byBwYXNzIGFuIGVtcHR5IGFycmF5IG9mIGlucHV0cyB0byB0aGUgc2VydmVyLCBiZWNhdXNlIGl0IGFzc3VtZXMgaWYgdGhlXG4gICAgICAgIC8vIGlucHV0cyBhcmd1bWVudHMgZXhpc3RzLCBpdCBjb250YWlucyB2YWx1ZXNcbiAgICAgICAgemVyb0NvbmZVbnNwZW50VHhJZHMgPSB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIC8vIEZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgcmVzcGVjdCB0aGUgb2xkIHNwbGl0Q2hhbmdlU2l6ZT0wIHBhcmFtZXRlclxuICAgICAgaWYgKCFwYXJhbXMubm9TcGxpdENoYW5nZSAmJiBwYXJhbXMuc3BsaXRDaGFuZ2VTaXplICE9PSAwKSB7XG4gICAgICAgIGV4dHJhQ2hhbmdlQW1vdW50cyA9IHJlc3VsdHMuZXh0cmFDaGFuZ2VBbW91bnRzIHx8IFtdO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIC8vIEdldCB0aGUgdW5zcGVudHMgZm9yIHRoZSBzaW5nbGUga2V5IGZlZSBhZGRyZXNzXG4gIGxldCBmZWVTaW5nbGVLZXlVbnNwZW50czogQml0R29VbnNwZW50W10gPSBbXTtcbiAgY29uc3QgZ2V0VW5zcGVudHNGb3JTaW5nbGVLZXkgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3MpIHtcbiAgICAgIGxldCBmZWVUYXJnZXQgPSAwLjAxZTg7XG4gICAgICBpZiAocGFyYW1zLmluc3RhbnQpIHtcbiAgICAgICAgZmVlVGFyZ2V0ICs9IHRvdGFsQW1vdW50ICogMC4wMDE7XG4gICAgICB9XG4gICAgICByZXR1cm4gYml0Z29cbiAgICAgICAgLmdldChiaXRnby51cmwoJy9hZGRyZXNzLycgKyBmZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzICsgJy91bnNwZW50cz90YXJnZXQ9JyArIGZlZVRhcmdldCkpXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgIGlmIChyZXNwb25zZS5ib2R5LnRvdGFsIDw9IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gdW5zcGVudHMgYXZhaWxhYmxlIGluIHNpbmdsZSBrZXkgZmVlIHNvdXJjZScpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmZWVTaW5nbGVLZXlVbnNwZW50cyA9IHJlc3BvbnNlLmJvZHkudW5zcGVudHM7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICBsZXQgbWluZXJGZWVJbmZvOiBhbnkgPSB7fTtcbiAgbGV0IHR4SW5mbzogYW55ID0ge307XG5cbiAgLy8gSXRlcmF0ZSB1bnNwZW50cywgc3VtIHRoZSBpbnB1dHMsIGFuZCBzYXZlIF9pbnB1dHMgd2l0aCB0aGUgdG90YWxcbiAgLy8gaW5wdXQgYW1vdW50IGFuZCBmaW5hbCBsaXN0IG9mIGlucHV0cyB0byB1c2Ugd2l0aCB0aGUgdHJhbnNhY3Rpb24uXG4gIGxldCBmZWVTaW5nbGVLZXlVbnNwZW50c1VzZWQ6IEJpdEdvVW5zcGVudFtdID0gW107XG5cbiAgY29uc3QgY29sbGVjdElucHV0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXVuc3BlbnRzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyB1bnNwZW50cyBhdmFpbGFibGUgb24gd2FsbGV0Jyk7XG4gICAgfVxuICAgIGlucHV0QW1vdW50ID0gMDtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgY29zdCBvZiBzcGVuZGluZyBhIHNpbmdsZSBpbnB1dCwgaS5lLiB0aGUgc21hbGxlc3QgZWNvbm9taWNhbCB1bnNwZW50IHZhbHVlXG4gICAgcmV0dXJuIEJsdWViaXJkLnRyeShmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoXy5pc051bWJlcihwYXJhbXMuZmVlUmF0ZSkgfHwgXy5pc051bWJlcihwYXJhbXMub3JpZ2luYWxGZWVSYXRlKSkge1xuICAgICAgICByZXR1cm4gIV8uaXNVbmRlZmluZWQocGFyYW1zLmZlZVJhdGUpID8gcGFyYW1zLmZlZVJhdGUgOiBwYXJhbXMub3JpZ2luYWxGZWVSYXRlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGJpdGdvXG4gICAgICAgICAgLmVzdGltYXRlRmVlKHtcbiAgICAgICAgICAgIG51bUJsb2NrczogcGFyYW1zLmZlZVR4Q29uZmlybVRhcmdldCxcbiAgICAgICAgICAgIG1heEZlZTogcGFyYW1zLm1heEZlZVJhdGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAudGhlbihmdW5jdGlvbiAoZmVlUmF0ZUVzdGltYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmVlUmF0ZUVzdGltYXRlLmZlZVBlcktiO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pXG4gICAgICAudGhlbihmdW5jdGlvbiAoZmVlUmF0ZSkge1xuICAgICAgICAvLyBEb24ndCBzcGVuZCBpbnB1dHMgdGhhdCBjYW5ub3QgcGF5IGZvciB0aGVpciBvd24gY29zdC5cbiAgICAgICAgbGV0IG1pbklucHV0VmFsdWUgPSAwO1xuICAgICAgICBpZiAoXy5pc0ludGVnZXIocGFyYW1zLm1pblVuc3BlbnRTaXplKSkge1xuICAgICAgICAgIG1pbklucHV0VmFsdWUgPSBwYXJhbXMubWluVW5zcGVudFNpemU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcHJ1bmVkVW5zcGVudENvdW50ID0gMDtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxVbnNwZW50Q291bnQgPSB1bnNwZW50cy5sZW5ndGg7XG4gICAgICAgIHVuc3BlbnRzID0gXy5maWx0ZXIodW5zcGVudHMsIGZ1bmN0aW9uICh1bnNwZW50KSB7XG4gICAgICAgICAgY29uc3QgaXNTZWd3aXRJbnB1dCA9ICEhdW5zcGVudC53aXRuZXNzU2NyaXB0O1xuICAgICAgICAgIGNvbnN0IGN1cnJlbnRJbnB1dFNpemUgPSBpc1NlZ3dpdElucHV0ID8gVmlydHVhbFNpemVzLnR4UDJzaFAyd3NoSW5wdXRTaXplIDogVmlydHVhbFNpemVzLnR4UDJzaElucHV0U2l6ZTtcbiAgICAgICAgICBjb25zdCBmZWVCYXNlZE1pbklucHV0VmFsdWUgPSAoZmVlUmF0ZSAqIGN1cnJlbnRJbnB1dFNpemUpIC8gMTAwMDtcbiAgICAgICAgICBjb25zdCBjdXJyZW50TWluSW5wdXRWYWx1ZSA9IE1hdGgubWF4KG1pbklucHV0VmFsdWUsIGZlZUJhc2VkTWluSW5wdXRWYWx1ZSk7XG4gICAgICAgICAgaWYgKGN1cnJlbnRNaW5JbnB1dFZhbHVlID4gdW5zcGVudC52YWx1ZSkge1xuICAgICAgICAgICAgLy8gcHJ1bmluZyB1bnNwZW50XG4gICAgICAgICAgICBjb25zdCBwcnVuZURldGFpbHMgPSB7XG4gICAgICAgICAgICAgIGdlbmVyYWxNaW5JbnB1dFZhbHVlOiBtaW5JbnB1dFZhbHVlLFxuICAgICAgICAgICAgICBmZWVCYXNlZE1pbklucHV0VmFsdWUsXG4gICAgICAgICAgICAgIGN1cnJlbnRNaW5JbnB1dFZhbHVlLFxuICAgICAgICAgICAgICBmZWVSYXRlLFxuICAgICAgICAgICAgICBpbnB1dFNpemU6IGN1cnJlbnRJbnB1dFNpemUsXG4gICAgICAgICAgICAgIHVuc3BlbnQ6IHVuc3BlbnQsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc29sZS5sb2coYHBydW5pbmcgdW5zcGVudDogJHtKU09OLnN0cmluZ2lmeShwcnVuZURldGFpbHMsIG51bGwsIDQpfWApO1xuICAgICAgICAgICAgcHJ1bmVkVW5zcGVudENvdW50Kys7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAocHJ1bmVkVW5zcGVudENvdW50ID4gMCkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGBwcnVuZWQgJHtwcnVuZWRVbnNwZW50Q291bnR9IG91dCBvZiAke29yaWdpbmFsVW5zcGVudENvdW50fSB1bnNwZW50c2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVuc3BlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW5zdWZmaWNpZW50IGZ1bmRzJyk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHNlZ3dpdElucHV0Q291bnQgPSAwO1xuICAgICAgICB1bnNwZW50cy5ldmVyeShmdW5jdGlvbiAodW5zcGVudCkge1xuICAgICAgICAgIGlmICh1bnNwZW50LndpdG5lc3NTY3JpcHQpIHtcbiAgICAgICAgICAgIHNlZ3dpdElucHV0Q291bnQrKztcbiAgICAgICAgICB9XG4gICAgICAgICAgaW5wdXRBbW91bnQgKz0gdW5zcGVudC52YWx1ZTtcbiAgICAgICAgICB0cmFuc2FjdGlvbi5hZGRJbnB1dCh1bnNwZW50LnR4X2hhc2gsIHVuc3BlbnQudHhfb3V0cHV0X24sIDB4ZmZmZmZmZmYpO1xuXG4gICAgICAgICAgcmV0dXJuIGlucHV0QW1vdW50IDwgKGZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3MgPyB0b3RhbE91dHB1dEFtb3VudCA6IHRvdGFsQW1vdW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gaWYgcGF5aW5nIGZlZXMgZnJvbSBhbiBleHRlcm5hbCBzaW5nbGUga2V5IHdhbGxldCwgYWRkIHRoZSBpbnB1dHNcbiAgICAgICAgaWYgKGZlZVNpbmdsZUtleVNvdXJjZUFkZHJlc3MpIHtcbiAgICAgICAgICAvLyBjb2xsZWN0IHRoZSBhbW91bnQgdXNlZCBpbiB0aGUgZmVlIGlucHV0cyBzbyB3ZSBjYW4gZ2V0IGNoYW5nZSBsYXRlclxuICAgICAgICAgIGZlZVNpbmdsZUtleUlucHV0QW1vdW50ID0gMDtcbiAgICAgICAgICBmZWVTaW5nbGVLZXlVbnNwZW50c1VzZWQgPSBbXTtcbiAgICAgICAgICBmZWVTaW5nbGVLZXlVbnNwZW50cy5ldmVyeShmdW5jdGlvbiAodW5zcGVudCkge1xuICAgICAgICAgICAgZmVlU2luZ2xlS2V5SW5wdXRBbW91bnQgKz0gdW5zcGVudC52YWx1ZTtcbiAgICAgICAgICAgIGlucHV0QW1vdW50ICs9IHVuc3BlbnQudmFsdWU7XG4gICAgICAgICAgICB0cmFuc2FjdGlvbi5hZGRJbnB1dCh1bnNwZW50LnR4X2hhc2gsIHVuc3BlbnQudHhfb3V0cHV0X24pO1xuICAgICAgICAgICAgZmVlU2luZ2xlS2V5VW5zcGVudHNVc2VkLnB1c2godW5zcGVudCk7XG4gICAgICAgICAgICAvLyB1c2UgdGhlIGZlZSB3YWxsZXQgdG8gcGF5IG1pbmVyIGZlZXMgYW5kIHBvdGVudGlhbGx5IGluc3RhbnQgZmVlc1xuICAgICAgICAgICAgcmV0dXJuIGZlZVNpbmdsZUtleUlucHV0QW1vdW50IDwgZmVlICsgKGJpdGdvRmVlSW5mbyA/IGJpdGdvRmVlSW5mby5hbW91bnQgOiAwKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHR4SW5mbyA9IHtcbiAgICAgICAgICBuUDJzaElucHV0czogdHJhbnNhY3Rpb24udHguaW5zLmxlbmd0aCAtIChmZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzID8gMSA6IDApIC0gc2Vnd2l0SW5wdXRDb3VudCxcbiAgICAgICAgICBuUDJzaFAyd3NoSW5wdXRzOiBzZWd3aXRJbnB1dENvdW50LFxuICAgICAgICAgIG5QMnBraElucHV0czogZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzcyA/IDEgOiAwLFxuICAgICAgICAgIC8vIGFkZCBzaW5nbGUga2V5IHNvdXJjZSBhZGRyZXNzIGNoYW5nZVxuICAgICAgICAgIG5PdXRwdXRzOlxuICAgICAgICAgICAgcmVjaXBpZW50cy5sZW5ndGggK1xuICAgICAgICAgICAgMSArIC8vIHJlY2lwaWVudHMgYW5kIGNoYW5nZVxuICAgICAgICAgICAgZXh0cmFDaGFuZ2VBbW91bnRzLmxlbmd0aCArIC8vIGV4dHJhIGNoYW5nZSBzcGxpdHRpbmdcbiAgICAgICAgICAgIChiaXRnb0ZlZUluZm8gJiYgYml0Z29GZWVJbmZvLmFtb3VudCA+IDAgPyAxIDogMCkgKyAvLyBhZGQgb3V0cHV0IGZvciBiaXRnbyBmZWVcbiAgICAgICAgICAgIChmZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzID8gMSA6IDApLFxuICAgICAgICB9O1xuXG4gICAgICAgIGVzdFR4U2l6ZSA9IGVzdGltYXRlVHJhbnNhY3Rpb25TaXplKHtcbiAgICAgICAgICBuUDJzaElucHV0czogdHhJbmZvLm5QMnNoSW5wdXRzLFxuICAgICAgICAgIG5QMnNoUDJ3c2hJbnB1dHM6IHR4SW5mby5uUDJzaFAyd3NoSW5wdXRzLFxuICAgICAgICAgIG5QMnBraElucHV0czogdHhJbmZvLm5QMnBraElucHV0cyxcbiAgICAgICAgICBuT3V0cHV0czogdHhJbmZvLm5PdXRwdXRzLFxuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbihnZXREeW5hbWljRmVlUmF0ZUVzdGltYXRlKVxuICAgICAgLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICBtaW5lckZlZUluZm8gPSBleHBvcnRzLmNhbGN1bGF0ZU1pbmVyRmVlSW5mbyh7XG4gICAgICAgICAgYml0Z286IHBhcmFtcy53YWxsZXQuYml0Z28sXG4gICAgICAgICAgZmVlUmF0ZTogZmVlUmF0ZSxcbiAgICAgICAgICBuUDJzaElucHV0czogdHhJbmZvLm5QMnNoSW5wdXRzLFxuICAgICAgICAgIG5QMnNoUDJ3c2hJbnB1dHM6IHR4SW5mby5uUDJzaFAyd3NoSW5wdXRzLFxuICAgICAgICAgIG5QMnBraElucHV0czogdHhJbmZvLm5QMnBraElucHV0cyxcbiAgICAgICAgICBuT3V0cHV0czogdHhJbmZvLm5PdXRwdXRzLFxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoc2hvdWxkQ29tcHV0ZUJlc3RGZWUpIHtcbiAgICAgICAgICBjb25zdCBhcHByb3hpbWF0ZUZlZSA9IG1pbmVyRmVlSW5mby5mZWU7XG4gICAgICAgICAgY29uc3Qgc2hvdWxkUmVjdXJzZSA9IF8uaXNVbmRlZmluZWQoZmVlKSB8fCBhcHByb3hpbWF0ZUZlZSA+IGZlZTtcbiAgICAgICAgICBmZWUgPSBhcHByb3hpbWF0ZUZlZTtcbiAgICAgICAgICAvLyBSZWNvbXB1dGUgdG90YWxBbW91bnQgZnJvbSBzY3JhdGNoXG4gICAgICAgICAgdG90YWxBbW91bnQgPSBmZWUgKyB0b3RhbE91dHB1dEFtb3VudDtcbiAgICAgICAgICBpZiAoYml0Z29GZWVJbmZvKSB7XG4gICAgICAgICAgICB0b3RhbEFtb3VudCArPSBiaXRnb0ZlZUluZm8uYW1vdW50O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoc2hvdWxkUmVjdXJzZSkge1xuICAgICAgICAgICAgLy8gaWYgZmVlIGNoYW5nZWQsIHJlLWNvbGxlY3QgaW5wdXRzXG4gICAgICAgICAgICBpbnB1dEFtb3VudCA9IDA7XG4gICAgICAgICAgICB0cmFuc2FjdGlvbiA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25CdWlsZGVyRm9yTmV0d29yayhuZXR3b3JrKTtcbiAgICAgICAgICAgIHJldHVybiBjb2xsZWN0SW5wdXRzKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdG90YWxGZWUgPSBmZWUgKyAoYml0Z29GZWVJbmZvID8gYml0Z29GZWVJbmZvLmFtb3VudCA6IDApO1xuXG4gICAgICAgIGlmIChmZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzKSB7XG4gICAgICAgICAgY29uc3Qgc3VtbWVkU2luZ2xlS2V5VW5zcGVudHMgPSBfLnN1bUJ5KGZlZVNpbmdsZUtleVVuc3BlbnRzLCAndmFsdWUnKTtcbiAgICAgICAgICBpZiAodG90YWxGZWUgPiBzdW1tZWRTaW5nbGVLZXlVbnNwZW50cykge1xuICAgICAgICAgICAgY29uc3QgZXJyOiBhbnkgPSBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICdJbnN1ZmZpY2llbnQgZmVlIGFtb3VudCBhdmFpbGFibGUgaW4gc2luZ2xlIGtleSBmZWUgc291cmNlOiAnICsgc3VtbWVkU2luZ2xlS2V5VW5zcGVudHNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBlcnIucmVzdWx0ID0ge1xuICAgICAgICAgICAgICBmZWU6IGZlZSxcbiAgICAgICAgICAgICAgZmVlUmF0ZTogZmVlUmF0ZSxcbiAgICAgICAgICAgICAgZXN0aW1hdGVkU2l6ZTogbWluZXJGZWVJbmZvLnNpemUsXG4gICAgICAgICAgICAgIGF2YWlsYWJsZTogaW5wdXRBbW91bnQsXG4gICAgICAgICAgICAgIGJpdGdvRmVlOiBiaXRnb0ZlZUluZm8sXG4gICAgICAgICAgICAgIHR4SW5mbzogdHhJbmZvLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiBCbHVlYmlyZC5yZWplY3QoZXJyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaW5wdXRBbW91bnQgPCAoZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzcyA/IHRvdGFsT3V0cHV0QW1vdW50IDogdG90YWxBbW91bnQpKSB7XG4gICAgICAgICAgLy8gVGhlIHVuc3BlbnRzIHdlJ3JlIHVzaW5nIGZvciBpbnB1dHMgZG8gbm90IGhhdmUgc3VmZmljaWVudCB2YWx1ZSBvbiB0aGVtIHRvXG4gICAgICAgICAgLy8gc2F0aXNmeSB0aGUgdXNlcidzIHJlcXVlc3RlZCBzcGVuZCBhbW91bnQuIFRoYXQgbWF5IGJlIGJlY2F1c2UgdGhlIHdhbGxldCdzIGJhbGFuY2VcbiAgICAgICAgICAvLyBpcyBzaW1wbHkgdG9vIGxvdywgb3IgaXQgbWlnaHQgYmUgdGhhdCB0aGUgd2FsbGV0J3MgYmFsYW5jZSBpcyBzdWZmaWNpZW50IGJ1dFxuICAgICAgICAgIC8vIHdlIGRpZG4ndCBmZXRjaCBlbm91Z2ggdW5zcGVudHMuIFRvbyBmZXcgdW5zcGVudHMgY291bGQgcmVzdWx0IGZyb20gdGhlIHdhbGxldFxuICAgICAgICAgIC8vIGhhdmluZyBtYW55IHNtYWxsIHVuc3BlbnRzIGFuZCB3ZSBoaXQgb3VyIGxpbWl0IG9uIHRoZSBudW1iZXIgb2YgaW5wdXRzIHdlIGNhbiB1c2VcbiAgICAgICAgICAvLyBpbiBhIHR4biwgb3IgaXQgbWlnaHQgaGF2ZSBiZWVuIHRoYXQgdGhlIGZpbHRlcnMgdGhlIHVzZXIgcGFzc2VkIGluIChsaWtlIG1pbkNvbmZpcm1zKVxuICAgICAgICAgIC8vIGRpc3F1YWxpZmllZCB0b28gbWFueSBvZiB0aGUgdW5zcGVudHNcbiAgICAgICAgICBsZXQgZXJyO1xuICAgICAgICAgIGlmICh0b3RhbFVuc3BlbnRzQ291bnQgPT09IGZldGNoZWRVbnNwZW50c0NvdW50KSB7XG4gICAgICAgICAgICAvLyB3ZSBmZXRjaGVkIGV2ZXJ5IHVuc3BlbnQgdGhlIHdhbGxldCBoYWQsIGJ1dCBpdCBzdGlsbCB3YXNuJ3QgZW5vdWdoXG4gICAgICAgICAgICBlcnIgPSBuZXcgRXJyb3IoJ0luc3VmZmljaWVudCBmdW5kcycpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyB3ZSB3ZXJlbid0IGFibGUgdG8gZmV0Y2ggYWxsIHRoZSB1bnNwZW50cyBvbiB0aGUgd2FsbGV0XG4gICAgICAgICAgICBlcnIgPSBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBUcmFuc2FjdGlvbiBzaXplIHRvbyBsYXJnZSBkdWUgdG8gdG9vIG1hbnkgdW5zcGVudHMuIENhbiBzZW5kIG9ubHkgJHtpbnB1dEFtb3VudH0gc2F0b3NoaXMgaW4gdGhpcyB0cmFuc2FjdGlvbmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVyci5yZXN1bHQgPSB7XG4gICAgICAgICAgICBmZWU6IGZlZSxcbiAgICAgICAgICAgIGZlZVJhdGU6IGZlZVJhdGUsXG4gICAgICAgICAgICBlc3RpbWF0ZWRTaXplOiBtaW5lckZlZUluZm8uc2l6ZSxcbiAgICAgICAgICAgIGF2YWlsYWJsZTogaW5wdXRBbW91bnQsXG4gICAgICAgICAgICBiaXRnb0ZlZTogYml0Z29GZWVJbmZvLFxuICAgICAgICAgICAgdHhJbmZvOiB0eEluZm8sXG4gICAgICAgICAgfTtcbiAgICAgICAgICByZXR1cm4gQmx1ZWJpcmQucmVqZWN0KGVycik7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9O1xuXG4gIC8vIEFkZCB0aGUgb3V0cHV0cyBmb3IgdGhpcyB0cmFuc2FjdGlvbi5cbiAgY29uc3QgY29sbGVjdE91dHB1dHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKG1pbmVyRmVlSW5mby5zaXplID49IDkwMDAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RyYW5zYWN0aW9uIHRvbyBsYXJnZTogZXN0aW1hdGVkIHNpemUgJyArIG1pbmVyRmVlSW5mby5zaXplICsgJyBieXRlcycpO1xuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dHM6IE91dHB1dFtdID0gW107XG5cbiAgICByZWNpcGllbnRzLmZvckVhY2goZnVuY3Rpb24gKHJlY2lwaWVudCkge1xuICAgICAgbGV0IHNjcmlwdDtcbiAgICAgIGlmIChfLmlzU3RyaW5nKHJlY2lwaWVudC5hZGRyZXNzKSkge1xuICAgICAgICBzY3JpcHQgPSB1dHhvbGliLmFkZHJlc3MudG9PdXRwdXRTY3JpcHQocmVjaXBpZW50LmFkZHJlc3MsIG5ldHdvcmspO1xuICAgICAgfSBlbHNlIGlmIChfLmlzT2JqZWN0KHJlY2lwaWVudC5zY3JpcHQpKSB7XG4gICAgICAgIHNjcmlwdCA9IHJlY2lwaWVudC5zY3JpcHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25laXRoZXIgcmVjaXBpZW50IGFkZHJlc3Mgbm9yIHNjcmlwdCB3YXMgcHJvdmlkZWQnKTtcbiAgICAgIH1cblxuICAgICAgLy8gdmFsaWRhdGUgdHJhdmVsSW5mbyBpZiBpdCBleGlzdHNcbiAgICAgIGxldCB0cmF2ZWxJbmZvO1xuICAgICAgaWYgKCFfLmlzRW1wdHkocmVjaXBpZW50LnRyYXZlbEluZm8pKSB7XG4gICAgICAgIHRyYXZlbEluZm8gPSByZWNpcGllbnQudHJhdmVsSW5mbztcbiAgICAgICAgLy8gQmV0dGVyIHRvIGF2b2lkIHRyb3VibGUgbm93LCBiZWZvcmUgdHggaXMgY3JlYXRlZFxuICAgICAgICBiaXRnby50cmF2ZWxSdWxlKCkudmFsaWRhdGVUcmF2ZWxJbmZvKHRyYXZlbEluZm8pO1xuICAgICAgfVxuXG4gICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICBzY3JpcHQ6IHNjcmlwdCxcbiAgICAgICAgYW1vdW50OiByZWNpcGllbnQuYW1vdW50LFxuICAgICAgICB0cmF2ZWxJbmZvOiB0cmF2ZWxJbmZvLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBvcFJldHVybnMuZm9yRWFjaChmdW5jdGlvbiAoeyBtZXNzYWdlLCBhbW91bnQgfSkge1xuICAgICAgY29uc3Qgc2NyaXB0ID0gdXR4b2xpYi5zY3JpcHQuZnJvbUFTTSgnT1BfUkVUVVJOICcgKyBCdWZmZXIuZnJvbShtZXNzYWdlKS50b1N0cmluZygnaGV4JykpO1xuICAgICAgb3V0cHV0cy5wdXNoKHsgc2NyaXB0LCBhbW91bnQgfSk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBnZXRDaGFuZ2VPdXRwdXRzID0gZnVuY3Rpb24gKGNoYW5nZUFtb3VudDogbnVtYmVyKTogT3V0cHV0W10gfCBCbHVlYmlyZDxPdXRwdXRbXT4ge1xuICAgICAgaWYgKGNoYW5nZUFtb3VudCA8IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCduZWdhdGl2ZSBjaGFuZ2UgYW1vdW50OiAnICsgY2hhbmdlQW1vdW50KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0OiBPdXRwdXRbXSA9IFtdO1xuICAgICAgLy8gaWYgd2UgcGFpZCBmZWVzIGZyb20gYSBzaW5nbGUga2V5IHdhbGxldCwgcmV0dXJuIHRoZSBmZWUgY2hhbmdlIGZpcnN0XG4gICAgICBpZiAoZmVlU2luZ2xlS2V5U291cmNlQWRkcmVzcykge1xuICAgICAgICBjb25zdCBmZWVTaW5nbGVLZXlXYWxsZXRDaGFuZ2VBbW91bnQgPVxuICAgICAgICAgIGZlZVNpbmdsZUtleUlucHV0QW1vdW50IC0gKGZlZSArIChiaXRnb0ZlZUluZm8gPyBiaXRnb0ZlZUluZm8uYW1vdW50IDogMCkpO1xuICAgICAgICBpZiAoZmVlU2luZ2xlS2V5V2FsbGV0Q2hhbmdlQW1vdW50ID49IGNvbnN0YW50cy5taW5PdXRwdXRTaXplKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2goeyBhZGRyZXNzOiBmZWVTaW5nbGVLZXlTb3VyY2VBZGRyZXNzLCBhbW91bnQ6IGZlZVNpbmdsZUtleVdhbGxldENoYW5nZUFtb3VudCB9KTtcbiAgICAgICAgICBjaGFuZ2VBbW91bnQgPSBjaGFuZ2VBbW91bnQgLSBmZWVTaW5nbGVLZXlXYWxsZXRDaGFuZ2VBbW91bnQ7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGNoYW5nZUFtb3VudCA8IGNvbnN0YW50cy5taW5PdXRwdXRTaXplKSB7XG4gICAgICAgIC8vIEdpdmUgaXQgdG8gdGhlIG1pbmVyc1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBpZiAocGFyYW1zLndhbGxldC50eXBlKCkgPT09ICdzYWZlJykge1xuICAgICAgICByZXR1cm4gcGFyYW1zLndhbGxldC5hZGRyZXNzZXMoKS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHsgYWRkcmVzczogcmVzcG9uc2UuYWRkcmVzc2VzWzBdLmFkZHJlc3MsIGFtb3VudDogY2hhbmdlQW1vdW50IH0pO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBsZXQgZXh0cmFDaGFuZ2VUb3RhbCA9IF8uc3VtKGV4dHJhQ2hhbmdlQW1vdW50cyk7XG4gICAgICAvLyBTYW5pdHkgY2hlY2tcbiAgICAgIGlmIChleHRyYUNoYW5nZVRvdGFsID4gY2hhbmdlQW1vdW50KSB7XG4gICAgICAgIGV4dHJhQ2hhbmdlQW1vdW50cyA9IFtdO1xuICAgICAgICBleHRyYUNoYW5nZVRvdGFsID0gMDtcbiAgICAgIH1cblxuICAgICAgLy8gY29weSBhbmQgYWRkIHJlbWFpbmluZyBjaGFuZ2UgYW1vdW50XG4gICAgICBjb25zdCBhbGxDaGFuZ2VBbW91bnRzID0gZXh0cmFDaGFuZ2VBbW91bnRzLnNsaWNlKDApO1xuICAgICAgYWxsQ2hhbmdlQW1vdW50cy5wdXNoKGNoYW5nZUFtb3VudCAtIGV4dHJhQ2hhbmdlVG90YWwpO1xuXG4gICAgICAvLyBSZWN1cnNpdmUgYXN5bmMgZnVuYyB0byBhZGQgYWxsIGNoYW5nZSBvdXRwdXRzXG4gICAgICBjb25zdCBhZGRDaGFuZ2VPdXRwdXRzID0gZnVuY3Rpb24gKCk6IE91dHB1dFtdIHwgQmx1ZWJpcmQ8T3V0cHV0W10+IHtcbiAgICAgICAgY29uc3QgdGhpc0Ftb3VudCA9IGFsbENoYW5nZUFtb3VudHMuc2hpZnQoKTtcbiAgICAgICAgaWYgKCF0aGlzQW1vdW50KSB7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQmx1ZWJpcmQudHJ5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAocGFyYW1zLmNoYW5nZUFkZHJlc3MpIHtcbiAgICAgICAgICAgIC8vIElmIHVzZXIgcGFzc2VkIGEgY2hhbmdlIGFkZHJlc3MsIHVzZSBpdCBmb3IgYWxsIG91dHB1dHNcbiAgICAgICAgICAgIHJldHVybiBwYXJhbXMuY2hhbmdlQWRkcmVzcztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGNyZWF0ZSBhIG5ldyBhZGRyZXNzIHBlciBvdXRwdXQsIGZvciBwcml2YWN5XG4gICAgICAgICAgICAvLyBkZXRlcm1pbmUgaWYgc2Vnd2l0IG9yIG5vdFxuICAgICAgICAgICAgY29uc3QgY2hhbmdlQ2hhaW4gPSBwYXJhbXMud2FsbGV0LmdldENoYW5nZUNoYWluKHBhcmFtcyk7XG4gICAgICAgICAgICByZXR1cm4gcGFyYW1zLndhbGxldC5jcmVhdGVBZGRyZXNzKHsgY2hhaW46IGNoYW5nZUNoYWluLCB2YWxpZGF0ZTogdmFsaWRhdGUgfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgIHJldHVybiByZXN1bHQuYWRkcmVzcztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSkudGhlbihmdW5jdGlvbiAoYWRkcmVzcykge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHsgYWRkcmVzczogYWRkcmVzcywgYW1vdW50OiB0aGlzQW1vdW50IH0pO1xuICAgICAgICAgIHJldHVybiBhZGRDaGFuZ2VPdXRwdXRzKCk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgcmV0dXJuIGFkZENoYW5nZU91dHB1dHMoKTtcbiAgICB9O1xuXG4gICAgLy8gQWRkIGNoYW5nZSBvdXRwdXQocykgYW5kIGluc3RhbnQgZmVlIG91dHB1dCBpZiBhcHBsaWNhYmxlXG4gICAgcmV0dXJuIEJsdWViaXJkLnRyeShmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gZ2V0Q2hhbmdlT3V0cHV0cyhpbnB1dEFtb3VudCAtIHRvdGFsQW1vdW50KTtcbiAgICB9KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgIGNoYW5nZU91dHB1dHMgPSByZXN1bHQ7XG4gICAgICBjb25zdCBleHRyYU91dHB1dHMgPSBjaGFuZ2VPdXRwdXRzLmNvbmNhdChbXSk7IC8vIGNvcHkgdGhlIGFycmF5XG4gICAgICBpZiAoYml0Z29GZWVJbmZvICYmIGJpdGdvRmVlSW5mby5hbW91bnQgPiAwKSB7XG4gICAgICAgIGV4dHJhT3V0cHV0cy5wdXNoKGJpdGdvRmVlSW5mbyk7XG4gICAgICB9XG4gICAgICBleHRyYU91dHB1dHMuZm9yRWFjaChmdW5jdGlvbiAob3V0cHV0KSB7XG4gICAgICAgIGlmICgob3V0cHV0IGFzIEFkZHJlc3NPdXRwdXQpLmFkZHJlc3MpIHtcbiAgICAgICAgICAob3V0cHV0IGFzIFNjcmlwdE91dHB1dCkuc2NyaXB0ID0gdXR4b2xpYi5hZGRyZXNzLnRvT3V0cHV0U2NyaXB0KChvdXRwdXQgYXMgQWRkcmVzc091dHB1dCkuYWRkcmVzcywgbmV0d29yayk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBkZWNpZGUgd2hlcmUgdG8gcHV0IHRoZSBvdXRwdXRzIC0gZGVmYXVsdCBpcyB0byByYW5kb21pemUgdW5sZXNzIGZvcmNlZCB0byBlbmRcbiAgICAgICAgY29uc3Qgb3V0cHV0SW5kZXggPSBwYXJhbXMuZm9yY2VDaGFuZ2VBdEVuZCA/IG91dHB1dHMubGVuZ3RoIDogXy5yYW5kb20oMCwgb3V0cHV0cy5sZW5ndGgpO1xuICAgICAgICBvdXRwdXRzLnNwbGljZShvdXRwdXRJbmRleCwgMCwgb3V0cHV0KTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBBZGQgYWxsIG91dHB1dHMgdG8gdGhlIHRyYW5zYWN0aW9uXG4gICAgICBvdXRwdXRzLmZvckVhY2goZnVuY3Rpb24gKG91dHB1dCkge1xuICAgICAgICB0cmFuc2FjdGlvbi5hZGRPdXRwdXQoKG91dHB1dCBhcyBTY3JpcHRPdXRwdXQpLnNjcmlwdCwgb3V0cHV0LmFtb3VudCk7XG4gICAgICB9KTtcblxuICAgICAgdHJhdmVsSW5mb3MgPSBfKG91dHB1dHMpXG4gICAgICAgIC5tYXAoZnVuY3Rpb24gKG91dHB1dCwgaW5kZXgpIHtcbiAgICAgICAgICBjb25zdCByZXN1bHQgPSBvdXRwdXQudHJhdmVsSW5mbztcbiAgICAgICAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzdWx0Lm91dHB1dEluZGV4ID0gaW5kZXg7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSlcbiAgICAgICAgLmZpbHRlcigpXG4gICAgICAgIC52YWx1ZSgpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIFNlcmlhbGl6ZSB0aGUgdHJhbnNhY3Rpb24sIHJldHVybmluZyB3aGF0IGlzIG5lZWRlZCB0byBzaWduIGl0XG4gIGNvbnN0IHNlcmlhbGl6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBvbmx5IG5lZWQgdG8gcmV0dXJuIHRoZSB1bnNwZW50cyB0aGF0IHdlcmUgdXNlZCBhbmQganVzdCB0aGUgY2hhaW5QYXRoLCByZWRlZW1TY3JpcHQsIGFuZCBpbnN0YW50IGZsYWdcbiAgICBjb25zdCBwaWNrZWRVbnNwZW50czogYW55ID0gXy5tYXAodW5zcGVudHMsIGZ1bmN0aW9uICh1bnNwZW50KSB7XG4gICAgICByZXR1cm4gXy5waWNrKHVuc3BlbnQsIFsnY2hhaW5QYXRoJywgJ3JlZGVlbVNjcmlwdCcsICdpbnN0YW50JywgJ3dpdG5lc3NTY3JpcHQnLCAnc2NyaXB0JywgJ3ZhbHVlJ10pO1xuICAgIH0pO1xuICAgIGNvbnN0IHBydW5lZFVuc3BlbnRzID0gXy5zbGljZShwaWNrZWRVbnNwZW50cywgMCwgdHJhbnNhY3Rpb24udHguaW5zLmxlbmd0aCAtIGZlZVNpbmdsZUtleVVuc3BlbnRzVXNlZC5sZW5ndGgpO1xuICAgIF8uZWFjaChmZWVTaW5nbGVLZXlVbnNwZW50c1VzZWQsIGZ1bmN0aW9uIChmZWVVbnNwZW50KSB7XG4gICAgICBwcnVuZWRVbnNwZW50cy5wdXNoKHsgcmVkZWVtU2NyaXB0OiBmYWxzZSwgY2hhaW5QYXRoOiBmYWxzZSB9KTsgLy8gbWFyayBhcyBmYWxzZSB0byBzaWduaWZ5IGEgbm9uLW11bHRpc2lnIGFkZHJlc3NcbiAgICB9KTtcbiAgICBjb25zdCByZXN1bHQ6IGFueSA9IHtcbiAgICAgIHRyYW5zYWN0aW9uSGV4OiB0cmFuc2FjdGlvbi5idWlsZEluY29tcGxldGUoKS50b0hleCgpLFxuICAgICAgdW5zcGVudHM6IHBydW5lZFVuc3BlbnRzLFxuICAgICAgZmVlOiBmZWUsXG4gICAgICBjaGFuZ2VBZGRyZXNzZXM6IGNoYW5nZU91dHB1dHMubWFwKGZ1bmN0aW9uIChjbykge1xuICAgICAgICByZXR1cm4gXy5waWNrKGNvLCBbJ2FkZHJlc3MnLCAncGF0aCcsICdhbW91bnQnXSk7XG4gICAgICB9KSxcbiAgICAgIHdhbGxldElkOiBwYXJhbXMud2FsbGV0LmlkKCksXG4gICAgICB3YWxsZXRLZXljaGFpbnM6IHBhcmFtcy53YWxsZXQua2V5Y2hhaW5zLFxuICAgICAgZmVlUmF0ZTogZmVlUmF0ZSxcbiAgICAgIGluc3RhbnQ6IHBhcmFtcy5pbnN0YW50LFxuICAgICAgYml0Z29GZWU6IGJpdGdvRmVlSW5mbyxcbiAgICAgIGVzdGltYXRlZFNpemU6IG1pbmVyRmVlSW5mby5zaXplLFxuICAgICAgdHhJbmZvOiB0eEluZm8sXG4gICAgICB0cmF2ZWxJbmZvczogdHJhdmVsSW5mb3MsXG4gICAgfTtcblxuICAgIC8vIEFkZCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgICBpZiAocmVzdWx0Lmluc3RhbnQgJiYgYml0Z29GZWVJbmZvKSB7XG4gICAgICByZXN1bHQuaW5zdGFudEZlZSA9IF8ucGljayhiaXRnb0ZlZUluZm8sIFsnYW1vdW50JywgJ2FkZHJlc3MnXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICByZXR1cm4gQmx1ZWJpcmQudHJ5KGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZ2V0Qml0R29GZWUoKTtcbiAgfSlcbiAgICAudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gQmx1ZWJpcmQuYWxsKFtnZXRCaXRHb0ZlZUFkZHJlc3MoKSwgZ2V0VW5zcGVudHMoKSwgZ2V0VW5zcGVudHNGb3JTaW5nbGVLZXkoKV0pO1xuICAgIH0pXG4gICAgLnRoZW4oY29sbGVjdElucHV0cylcbiAgICAudGhlbihjb2xsZWN0T3V0cHV0cylcbiAgICAudGhlbihzZXJpYWxpemUpO1xufTtcblxuLyoqXG4gKiBFc3RpbWF0ZSB0aGUgc2l6ZSBvZiBhIHRyYW5zYWN0aW9uIGluIGJ5dGVzIGJhc2VkIG9uIHRoZSBudW1iZXIgb2ZcbiAqIGlucHV0cyBhbmQgb3V0cHV0cyBwcmVzZW50LlxuICogQHBhcmFtcyBwYXJhbXMge1xuICogICBuUDJzaElucHV0czogbnVtYmVyIG9mIFAyU0ggKG11bHRpc2lnKSBpbnB1dHNcbiAqICAgblAycGtoSW5wdXRzOiBudW1iZXIgb2YgUDJQS0ggKHNpbmdsZSBzaWcpIGlucHV0c1xuICogICBuT3V0cHV0czogbnVtYmVyIG9mIG91dHB1dHNcbiAqIH1cbiAqXG4gKiBAcmV0dXJucyBzaXplOiBlc3RpbWF0ZWQgc2l6ZSBvZiB0aGUgdHJhbnNhY3Rpb24gaW4gYnl0ZXNcbiAqL1xuY29uc3QgZXN0aW1hdGVUcmFuc2FjdGlvblNpemUgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gIGlmICghXy5pc0ludGVnZXIocGFyYW1zLm5QMnNoSW5wdXRzKSB8fCBwYXJhbXMublAyc2hJbnB1dHMgPCAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RpbmcgcG9zaXRpdmUgblAyc2hJbnB1dHMnKTtcbiAgfVxuICBpZiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5uUDJwa2hJbnB1dHMpIHx8IHBhcmFtcy5uUDJwa2hJbnB1dHMgPCAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RpbmcgcG9zaXRpdmUgblAycGtoSW5wdXRzIHRvIGJlIG51bWVyaWMnKTtcbiAgfVxuICBpZiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5uUDJzaFAyd3NoSW5wdXRzKSB8fCBwYXJhbXMublAyc2hQMndzaElucHV0cyA8IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGluZyBwb3NpdGl2ZSBuUDJzaFAyd3NoSW5wdXRzIHRvIGJlIG51bWVyaWMnKTtcbiAgfVxuICBpZiAocGFyYW1zLm5QMnNoSW5wdXRzICsgcGFyYW1zLm5QMnNoUDJ3c2hJbnB1dHMgPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RpbmcgYXQgbGVhc3Qgb25lIG5QMnNoSW5wdXRzIG9yIG5QMnNoUDJ3c2hJbnB1dHMnKTtcbiAgfVxuICBpZiAoIV8uaXNJbnRlZ2VyKHBhcmFtcy5uT3V0cHV0cykgfHwgcGFyYW1zLm5PdXRwdXRzIDwgMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0aW5nIHBvc2l0aXZlIG5PdXRwdXRzJyk7XG4gIH1cblxuICBjb25zdCBlc3RpbWF0ZWRTaXplID1cbiAgICBWaXJ0dWFsU2l6ZXMudHhQMnNoSW5wdXRTaXplICogcGFyYW1zLm5QMnNoSW5wdXRzICtcbiAgICBWaXJ0dWFsU2l6ZXMudHhQMnNoUDJ3c2hJbnB1dFNpemUgKiAocGFyYW1zLm5QMnNoUDJ3c2hJbnB1dHMgfHwgMCkgK1xuICAgIFZpcnR1YWxTaXplcy50eFAycGtoSW5wdXRTaXplVW5jb21wcmVzc2VkS2V5ICogKHBhcmFtcy5uUDJwa2hJbnB1dHMgfHwgMCkgK1xuICAgIFZpcnR1YWxTaXplcy50eFAycGtoT3V0cHV0U2l6ZSAqIHBhcmFtcy5uT3V0cHV0cyArXG4gICAgLy8gaWYgdGhlIHR4IGNvbnRhaW5zIGF0IGxlYXN0IG9uZSBzZWd3aXQgaW5wdXQsIHRoZSB0eCBvdmVyaGVhZCBpcyBpbmNyZWFzZWQgYnkgMVxuICAgIFZpcnR1YWxTaXplcy50eE92ZXJoZWFkU2l6ZSArXG4gICAgKHBhcmFtcy5uUDJzaFAyd3NoSW5wdXRzID4gMCA/IDEgOiAwKTtcblxuICByZXR1cm4gZXN0aW1hdGVkU2l6ZTtcbn07XG5cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSBmZWUgYW5kIGVzdGltYXRlZCBzaXplIGluIGJ5dGVzIGZvciBhIHRyYW5zYWN0aW9uLlxuICogQHBhcmFtcyBwYXJhbXMge1xuICogICBiaXRnbzogYml0Z28gb2JqZWN0XG4gKiAgIGZlZVJhdGU6IHNhdG9zaGlzIHBlciBraWxvYnl0ZVxuICogICBuUDJzaElucHV0czogbnVtYmVyIG9mIFAyU0ggKG11bHRpc2lnKSBpbnB1dHNcbiAqICAgblAycGtoSW5wdXRzOiBudW1iZXIgb2YgUDJQS0ggKHNpbmdsZSBzaWcpIGlucHV0c1xuICogICBuT3V0cHV0czogbnVtYmVyIG9mIG91dHB1dHNcbiAqIH1cbiAqXG4gKiBAcmV0dXJucyB7XG4gKiAgIHNpemU6IGVzdGltYXRlZCBzaXplIG9mIHRoZSB0cmFuc2FjdGlvbiBpbiBieXRlc1xuICogICBmZWU6IGVzdGltYXRlZCBmZWUgaW4gc2F0b3NoaXMgZm9yIHRoZSB0cmFuc2FjdGlvblxuICogICBmZWVSYXRlOiBmZWUgcmF0ZSB0aGF0IHdhcyB1c2VkIHRvIGVzdGltYXRlIHRoZSBmZWUgZm9yIHRoZSB0cmFuc2FjdGlvblxuICogfVxuICovXG5leHBvcnRzLmNhbGN1bGF0ZU1pbmVyRmVlSW5mbyA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgY29uc3QgZmVlUmF0ZVRvVXNlID0gcGFyYW1zLmZlZVJhdGUgfHwgcGFyYW1zLmJpdGdvLmdldENvbnN0YW50cygpLmZhbGxiYWNrRmVlUmF0ZTtcbiAgY29uc3QgZXN0aW1hdGVkU2l6ZSA9IGVzdGltYXRlVHJhbnNhY3Rpb25TaXplKHBhcmFtcyk7XG5cbiAgcmV0dXJuIHtcbiAgICBzaXplOiBlc3RpbWF0ZWRTaXplLFxuICAgIGZlZTogTWF0aC5jZWlsKChlc3RpbWF0ZWRTaXplICogZmVlUmF0ZVRvVXNlKSAvIDEwMDApLFxuICAgIGZlZVJhdGU6IGZlZVJhdGVUb1VzZSxcbiAgfTtcbn07XG5cbi8qXG4gKiBHaXZlbiBhIHRyYW5zYWN0aW9uIGhleCwgdW5zcGVudCBpbmZvcm1hdGlvbiAoY2hhaW4gcGF0aCBhbmQgcmVkZWVtIHNjcmlwdHMpLCBhbmQgdGhlIGtleWNoYWluIHhwcnYsXG4gKiBwZXJmb3JtIGtleSBkZXJpdmF0aW9uIGFuZCBzaWduIHRoZSBpbnB1dHMgaW4gdGhlIHRyYW5zYWN0aW9uIGJhc2VkIG9uIHRoZSB1bnNwZW50IGluZm9ybWF0aW9uIHByb3ZpZGVkXG4gKlxuICogQHBhcmFtczpcbiAqICB0cmFuc2FjdGlvbkhleCBzZXJpYWxpemVkIGZvcm0gb2YgdGhlIHRyYW5zYWN0aW9uIGluIGhleFxuICogIHVuc3BlbnRzIGFycmF5IG9mIHVuc3BlbnQgaW5mb3JtYXRpb24sIHdoZXJlIGVhY2ggdW5zcGVudCBpcyBhIGNoYWluUGF0aCBhbmQgcmVkZWVtU2NyaXB0IHdpdGggdGhlIHNhbWVcbiAqICBpbmRleCBhcyB0aGUgaW5wdXRzIGluIHRoZSB0cmFuc2FjdGlvbkhleFxuICogIGtleWNoYWluIEtleWNoYWluIGNvbnRhaW5pbmcgdGhlIHhwcnYgdG8gc2lnbiB3aXRoLiBGb3IgbGVnYWN5IHN1cHBvcnQgb2Ygc2FmZSB3YWxsZXRzLCBrZXljaGFpbiBjYW5cbiBhbHNvIGJlIGEgV0lGIHByaXZhdGUga2V5LlxuICogIHNpZ25pbmdLZXkgcHJpdmF0ZSBrZXkgaW4gV0lGIGZvciBzYWZlIHdhbGxldHMsIHdoZW4ga2V5Y2hhaW4gaXMgdW5hdmFpbGFibGVcbiAqICB2YWxpZGF0ZSBjbGllbnQtc2lkZSBzaWduYXR1cmUgdmVyaWZpY2F0aW9uIC0gY2FuIGJlIGRpc2FibGVkIGZvciBpbXByb3ZlZCBwZXJmb3JtYW5jZSAoc2lnbmF0dXJlc1xuICogICAgICAgICAgIGFyZSBzdGlsbCB2YWxpZGF0ZWQgc2VydmVyLXNpZGUpLlxuICogIGZlZVNpbmdsZUtleVdJRiBVc2UgdGhlIGFkZHJlc3MgYmFzZWQgb24gdGhpcyBwcml2YXRlIGtleSB0byBwYXkgZmVlc1xuICogQHJldHVybnMgeyp9XG4gKi9cbmV4cG9ydHMuc2lnblRyYW5zYWN0aW9uID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICBsZXQga2V5Y2hhaW4gPSBwYXJhbXMua2V5Y2hhaW47IC8vIGR1cGxpY2F0ZSBzbyBhcyB0byBub3QgbXV0YXRlIGJlbG93XG5cbiAgY29uc3QgdmFsaWRhdGUgPSBwYXJhbXMudmFsaWRhdGUgPT09IHVuZGVmaW5lZCA/IHRydWUgOiBwYXJhbXMudmFsaWRhdGU7XG4gIGxldCBwcml2S2V5O1xuICBpZiAoIV8uaXNTdHJpbmcocGFyYW1zLnRyYW5zYWN0aW9uSGV4KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0aW5nIHRoZSB0cmFuc2FjdGlvbiBoZXggYXMgYSBzdHJpbmcnKTtcbiAgfVxuICBpZiAoIUFycmF5LmlzQXJyYXkocGFyYW1zLnVuc3BlbnRzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0aW5nIHRoZSB1bnNwZW50cyBhcnJheScpO1xuICB9XG4gIGlmICghXy5pc0Jvb2xlYW4odmFsaWRhdGUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RpbmcgdmFsaWRhdGUgdG8gYmUgYSBib29sZWFuJyk7XG4gIH1cbiAgbGV0IG5ldHdvcmsgPSBnZXROZXR3b3JrKCk7XG4gIGNvbnN0IGVuYWJsZUJDSCA9IF8uaXNCb29sZWFuKHBhcmFtcy5mb3JjZUJDSCkgJiYgcGFyYW1zLmZvcmNlQkNIID09PSB0cnVlO1xuXG4gIGlmICghXy5pc09iamVjdChrZXljaGFpbikgfHwgIV8uaXNTdHJpbmcoKGtleWNoYWluIGFzIGFueSkueHBydikpIHtcbiAgICBpZiAoXy5pc1N0cmluZyhwYXJhbXMuc2lnbmluZ0tleSkpIHtcbiAgICAgIHByaXZLZXkgPSB1dHhvbGliLkVDUGFpci5mcm9tV0lGKHBhcmFtcy5zaWduaW5nS2V5LCBuZXR3b3JrIGFzIHV0eG9saWIuQml0Y29pbkpTTmV0d29yayk7XG4gICAgICBrZXljaGFpbiA9IHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHBlY3RpbmcgdGhlIGtleWNoYWluIG9iamVjdCB3aXRoIHhwcnYnKTtcbiAgICB9XG4gIH1cblxuICBsZXQgZmVlU2luZ2xlS2V5O1xuICBpZiAocGFyYW1zLmZlZVNpbmdsZUtleVdJRikge1xuICAgIGZlZVNpbmdsZUtleSA9IHV0eG9saWIuRUNQYWlyLmZyb21XSUYocGFyYW1zLmZlZVNpbmdsZUtleVdJRiwgbmV0d29yayBhcyB1dHhvbGliLkJpdGNvaW5KU05ldHdvcmspO1xuICB9XG5cbiAgZGVidWcoJ05ldHdvcms6ICVPJywgbmV0d29yayk7XG5cbiAgaWYgKGVuYWJsZUJDSCkge1xuICAgIGRlYnVnKCdFbmFibGluZyBCQ0jigKYnKTtcbiAgICBuZXR3b3JrID0gdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luY2FzaDtcbiAgICBkZWJ1ZygnTmV3IG5ldHdvcms6ICVPJywgbmV0d29yayk7XG4gIH1cblxuICBjb25zdCB0cmFuc2FjdGlvbiA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4KHBhcmFtcy50cmFuc2FjdGlvbkhleCwgbmV0d29yayk7XG4gIGlmICh0cmFuc2FjdGlvbi5pbnMubGVuZ3RoICE9PSBwYXJhbXMudW5zcGVudHMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2YgdW5zcGVudHMgYXJyYXkgc2hvdWxkIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgdHJhbnNhY3Rpb24gaW5wdXRzJyk7XG4gIH1cblxuICAvLyBkZWNvcmF0ZSB0cmFuc2FjdGlvbiB3aXRoIGlucHV0IHZhbHVlcyBmb3IgVHJhbnNhY3Rpb25CdWlsZGVyIGluc3RhbnRpYXRpb25cbiAgY29uc3QgaXNVdHhvVHggPSBfLmlzT2JqZWN0KHRyYW5zYWN0aW9uKSAmJiBBcnJheS5pc0FycmF5KCh0cmFuc2FjdGlvbiBhcyBhbnkpLmlucyk7XG4gIGNvbnN0IGFyZVZhbGlkVW5zcGVudHMgPSBfLmlzT2JqZWN0KHBhcmFtcykgJiYgQXJyYXkuaXNBcnJheSgocGFyYW1zIGFzIGFueSkudW5zcGVudHMpO1xuICBpZiAoaXNVdHhvVHggJiYgYXJlVmFsaWRVbnNwZW50cykge1xuICAgIC8vIGV4dGVuZCB0aGUgdHJhbnNhY3Rpb24gaW5wdXRzIHdpdGggdGhlIHZhbHVlc1xuICAgIGNvbnN0IGlucHV0VmFsdWVzID0gXy5tYXAoKHBhcmFtcyBhcyBhbnkpLnVuc3BlbnRzLCAodSkgPT4gXy5waWNrKHUsICd2YWx1ZScpKTtcbiAgICB0cmFuc2FjdGlvbi5pbnMubWFwKChjdXJyZW50SXRlbSwgaW5kZXgpID0+IF8uZXh0ZW5kKGN1cnJlbnRJdGVtLCBpbnB1dFZhbHVlc1tpbmRleF0pKTtcbiAgfVxuXG4gIGxldCByb290RXh0S2V5O1xuICBpZiAoa2V5Y2hhaW4pIHtcbiAgICByb290RXh0S2V5ID0gYmlwMzIuZnJvbUJhc2U1OChrZXljaGFpbi54cHJ2KTtcbiAgfVxuXG4gIGNvbnN0IHR4YiA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25CdWlsZGVyRnJvbVRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKTtcblxuICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdHhiLnR4Lmlucy5sZW5ndGg7ICsraW5kZXgpIHtcbiAgICBjb25zdCBjdXJyZW50VW5zcGVudCA9IHBhcmFtcy51bnNwZW50c1tpbmRleF07XG4gICAgaWYgKGN1cnJlbnRVbnNwZW50LnJlZGVlbVNjcmlwdCA9PT0gZmFsc2UpIHtcbiAgICAgIC8vIHRoaXMgaXMgdGhlIGlucHV0IGZyb20gYSBzaW5nbGUga2V5IGZlZSBhZGRyZXNzXG4gICAgICBpZiAoIWZlZVNpbmdsZUtleSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NpbmdsZSBrZXkgYWRkcmVzcyB1c2VkIGluIGlucHV0IGJ1dCBmZWVTaW5nbGVLZXlXSUYgbm90IHByb3ZpZGVkJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChlbmFibGVCQ0gpIHtcbiAgICAgICAgZmVlU2luZ2xlS2V5Lm5ldHdvcmsgPSBuZXR3b3JrO1xuICAgICAgfVxuXG4gICAgICB0eGIuc2lnbihpbmRleCwgZmVlU2luZ2xlS2V5KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGlmIChjdXJyZW50VW5zcGVudC53aXRuZXNzU2NyaXB0ICYmIGVuYWJsZUJDSCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCQ0ggZG9lcyBub3Qgc3VwcG9ydCBzZWd3aXQgaW5wdXRzJyk7XG4gICAgfVxuXG4gICAgY29uc3QgY2hhaW5QYXRoID0gY3VycmVudFVuc3BlbnQuY2hhaW5QYXRoO1xuICAgIGlmIChyb290RXh0S2V5KSB7XG4gICAgICBjb25zdCB7IHdhbGxldFN1YlBhdGggPSAnLzAvMCcgfSA9IGtleWNoYWluO1xuICAgICAgY29uc3QgcGF0aCA9IHNhbml0aXplTGVnYWN5UGF0aChrZXljaGFpbi5wYXRoICsgd2FsbGV0U3ViUGF0aCArIGNoYWluUGF0aCk7XG4gICAgICBkZWJ1ZyhcbiAgICAgICAgJ2Rlcml2ZWQgdXNlciBrZXkgcGF0aCBcIiVzXCIgdXNpbmcga2V5Y2hhaW4gcGF0aCBcIiVzXCIsIHdhbGxldFN1YlBhdGggXCIlc1wiLCBrZXljaGFpbiB3YWxsZXRTdWJQYXRoIFwiJXNcIiBhbmQgY2hhaW5QYXRoIFwiJXNcIicsXG4gICAgICAgIHBhdGgsXG4gICAgICAgIGtleWNoYWluLnBhdGgsXG4gICAgICAgIHdhbGxldFN1YlBhdGgsXG4gICAgICAgIGtleWNoYWluLndhbGxldFN1YlBhdGgsXG4gICAgICAgIGNoYWluUGF0aFxuICAgICAgKTtcbiAgICAgIHByaXZLZXkgPSByb290RXh0S2V5LmRlcml2ZVBhdGgocGF0aCk7XG4gICAgfVxuXG4gICAgcHJpdktleS5uZXR3b3JrID0gbmV0d29yaztcblxuICAgIC8vIHN1YnNjcmlwdCBpcyB0aGUgcGFydCBvZiB0aGUgb3V0cHV0IHNjcmlwdCBhZnRlciB0aGUgT1BfQ09ERVNFUEFSQVRPUi5cbiAgICAvLyBTaW5jZSB3ZSBhcmUgb25seSBldmVyIHNpZ25pbmcgcDJzaCBvdXRwdXRzLCB3aGljaCBkbyBub3QgaGF2ZVxuICAgIC8vIE9QX0NPREVTRVBBUkFUT1JTLCBpdCBpcyBhbHdheXMgdGhlIG91dHB1dCBzY3JpcHQuXG4gICAgY29uc3Qgc3Vic2NyaXB0ID0gQnVmZmVyLmZyb20oY3VycmVudFVuc3BlbnQucmVkZWVtU2NyaXB0LCAnaGV4Jyk7XG4gICAgY3VycmVudFVuc3BlbnQudmFsaWRhdGlvblNjcmlwdCA9IHN1YnNjcmlwdDtcblxuICAgIC8vIEluIG9yZGVyIHRvIHNpZ24gd2l0aCBiaXRjb2luanMtbGliLCB3ZSBtdXN0IHVzZSBpdHMgdHJhbnNhY3Rpb25cbiAgICAvLyBidWlsZGVyLCBjb25mdXNpbmdseSBuYW1lZCB0aGUgc2FtZSBleGFjdCB0aGluZyBhcyBvdXIgdHJhbnNhY3Rpb25cbiAgICAvLyBidWlsZGVyLCBidXQgd2l0aCBpbmVxdWl2YWxlbnQgYmVoYXZpb3IuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHdpdG5lc3NTY3JpcHQgPSBjdXJyZW50VW5zcGVudC53aXRuZXNzU2NyaXB0ID8gQnVmZmVyLmZyb20oY3VycmVudFVuc3BlbnQud2l0bmVzc1NjcmlwdCwgJ2hleCcpIDogdW5kZWZpbmVkO1xuICAgICAgY29uc3Qgc2lnSGFzaCA9IHV0eG9saWIuYml0Z28uZ2V0RGVmYXVsdFNpZ0hhc2gobmV0d29yayk7XG4gICAgICB0eGIuc2lnbihpbmRleCwgcHJpdktleSwgc3Vic2NyaXB0LCBzaWdIYXNoLCBjdXJyZW50VW5zcGVudC52YWx1ZSwgd2l0bmVzc1NjcmlwdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gdHJ5IGZhbGxiYWNrIGRlcml2YXRpb24gcGF0aCAoc2VlIEJHLTQ2NDk3KVxuICAgICAgbGV0IGZhbGxiYWNrU2lnbmluZ1N1Y2Nlc3NmdWwgPSBmYWxzZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IGZhbGxiYWNrUGF0aCA9IHNhbml0aXplTGVnYWN5UGF0aChrZXljaGFpbi5wYXRoICsgY2hhaW5QYXRoKTtcbiAgICAgICAgZGVidWcoXG4gICAgICAgICAgJ2Rlcml2ZWQgZmFsbGJhY2sgdXNlciBrZXkgcGF0aCBcIiVzXCIgdXNpbmcga2V5Y2hhaW4gcGF0aCBcIiVzXCIgYW5kIGNoYWluUGF0aCBcIiVzXCInLFxuICAgICAgICAgIGZhbGxiYWNrUGF0aCxcbiAgICAgICAgICBrZXljaGFpbi5wYXRoLFxuICAgICAgICAgIGNoYWluUGF0aFxuICAgICAgICApO1xuICAgICAgICBwcml2S2V5ID0gcm9vdEV4dEtleS5kZXJpdmVQYXRoKGZhbGxiYWNrUGF0aCk7XG4gICAgICAgIGNvbnN0IHdpdG5lc3NTY3JpcHQgPSBjdXJyZW50VW5zcGVudC53aXRuZXNzU2NyaXB0XG4gICAgICAgICAgPyBCdWZmZXIuZnJvbShjdXJyZW50VW5zcGVudC53aXRuZXNzU2NyaXB0LCAnaGV4JylcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3Qgc2lnSGFzaCA9IHV0eG9saWIuYml0Z28uZ2V0RGVmYXVsdFNpZ0hhc2gobmV0d29yayk7XG4gICAgICAgIHR4Yi5zaWduKGluZGV4LCBwcml2S2V5LCBzdWJzY3JpcHQsIHNpZ0hhc2gsIGN1cnJlbnRVbnNwZW50LnZhbHVlLCB3aXRuZXNzU2NyaXB0KTtcbiAgICAgICAgZmFsbGJhY2tTaWduaW5nU3VjY2Vzc2Z1bCA9IHRydWU7XG4gICAgICB9IGNhdGNoIChmYWxsYmFja0Vycm9yKSB7XG4gICAgICAgIGRlYnVnKCdpbnB1dCBzaWduIGZhaWxlZCBmb3IgZmFsbGJhY2sgcGF0aDogJXMnLCBmYWxsYmFja0Vycm9yLm1lc3NhZ2UpO1xuICAgICAgfVxuICAgICAgLy8gd2UgbmVlZCB0byBrbm93IHdoYXQncyBjYXVzaW5nIHRoaXNcbiAgICAgIGlmICghZmFsbGJhY2tTaWduaW5nU3VjY2Vzc2Z1bCkge1xuICAgICAgICBlLnJlc3VsdCA9IHtcbiAgICAgICAgICB1bnNwZW50OiBjdXJyZW50VW5zcGVudCxcbiAgICAgICAgfTtcbiAgICAgICAgZS5tZXNzYWdlID0gYEZhaWxlZCB0byBzaWduIGlucHV0ICMke2luZGV4fSAtICR7ZS5tZXNzYWdlfSAtICR7SlNPTi5zdHJpbmdpZnkoZS5yZXN1bHQsIG51bGwsIDQpfSAtIFxcbiR7XG4gICAgICAgICAgZS5zdGFja1xuICAgICAgICB9YDtcbiAgICAgICAgZGVidWcoJ2lucHV0IHNpZ24gZmFpbGVkOiAlcycsIGUubWVzc2FnZSk7XG4gICAgICAgIHJldHVybiBCbHVlYmlyZC5yZWplY3QoZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY29uc3QgcGFydGlhbFRyYW5zYWN0aW9uID0gdHhiLmJ1aWxkSW5jb21wbGV0ZSgpO1xuXG4gIGlmICh2YWxpZGF0ZSkge1xuICAgIHBhcnRpYWxUcmFuc2FjdGlvbi5pbnMuZm9yRWFjaCgoaW5wdXQsIGluZGV4KSA9PiB7XG4gICAgICBjb25zdCBzaWduYXR1cmVDb3VudCA9IHV0eG9saWIuYml0Z29cbiAgICAgICAgLmdldFNpZ25hdHVyZVZlcmlmaWNhdGlvbnMocGFydGlhbFRyYW5zYWN0aW9uLCBpbmRleCwgcGFyYW1zLnVuc3BlbnRzW2luZGV4XS52YWx1ZSlcbiAgICAgICAgLmZpbHRlcigodikgPT4gdi5zaWduZWRCeSAhPT0gdW5kZWZpbmVkKS5sZW5ndGg7XG4gICAgICBpZiAoc2lnbmF0dXJlQ291bnQgPCAxKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0ZWQgYXQgbGVhc3Qgb25lIHZhbGlkIHNpZ25hdHVyZScpO1xuICAgICAgfVxuICAgICAgaWYgKHBhcmFtcy5mdWxsTG9jYWxTaWduaW5nICYmIHNpZ25hdHVyZUNvdW50IDwgMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Z1bGxMb2NhbFNpZ25pbmcgc2V0OiBleHBlY3RlZCBhdCBsZWFzdCB0d28gdmFsaWQgc2lnbmF0dXJlcycpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIEJsdWViaXJkLnJlc29sdmUoe1xuICAgIHRyYW5zYWN0aW9uSGV4OiBwYXJ0aWFsVHJhbnNhY3Rpb24udG9IZXgoKSxcbiAgfSk7XG59O1xuIl19