@bitgo-beta/sdk-api 1.10.1-beta.1224 → 1.10.1-beta.1225

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