@atomicfinance/bitcoin-dlc-provider 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,38 +1,41 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const bitcoin_networks_1 = require("@atomicfinance/bitcoin-networks");
7
- const provider_1 = __importDefault(require("@atomicfinance/provider"));
8
- const types_1 = require("@atomicfinance/types");
9
- const utils_1 = require("@liquality/utils");
10
- const core_1 = require("@node-dlc/core");
11
- const messaging_1 = require("@node-dlc/messaging");
12
- const bitcoin_1 = require("@node-lightning/bitcoin");
13
- const bufio_1 = require("@node-lightning/bufio");
14
- const crypto_1 = require("@node-lightning/crypto");
15
- const assert_1 = __importDefault(require("assert"));
16
- const bignumber_js_1 = __importDefault(require("bignumber.js"));
17
- const bitcoinjs_lib_1 = require("bitcoinjs-lib");
18
- const Utils_1 = require("./utils/Utils");
1
+ Object.defineProperty(exports, "__esModule", {
2
+ value: true
3
+ });
4
+ exports.default = void 0;
5
+ var _bitcoinNetworks = require("@atomicfinance/bitcoin-networks");
6
+ var _provider = _interopRequireDefault(require("@atomicfinance/provider"));
7
+ var _types = require("@atomicfinance/types");
8
+ var _utils = require("@liquality/utils");
9
+ var _core = require("@node-dlc/core");
10
+ var _messaging = require("@node-dlc/messaging");
11
+ var _bitcoin = require("@node-lightning/bitcoin");
12
+ var _bufio = require("@node-lightning/bufio");
13
+ var _crypto = require("@node-lightning/crypto");
14
+ var _assert = _interopRequireDefault(require("assert"));
15
+ var _bignumberJs = _interopRequireDefault(require("bignumber.js"));
16
+ var _bitcoinjsLib = require("bitcoinjs-lib");
17
+ var _utils1 = require("./utils/Utils");
18
+ function _interopRequireDefault(obj) {
19
+ return obj && obj.__esModule ? obj : {
20
+ default: obj
21
+ };
22
+ }
19
23
  const ESTIMATED_SIZE = 312;
20
- class BitcoinDlcProvider extends provider_1.default {
21
- constructor(network, cfdDlcJs) {
22
- super();
23
- this._network = network;
24
- this._cfdDlcJs = cfdDlcJs;
25
- }
24
+ let BitcoinDlcProvider = class BitcoinDlcProvider extends _provider.default {
26
25
  async CfdLoaded() {
27
- while (!this._cfdDlcJs) {
28
- await utils_1.sleep(10);
26
+ while(!this._cfdDlcJs){
27
+ await (0, _utils).sleep(10);
29
28
  }
30
29
  }
31
30
  async GetPrivKeysForInputs(inputs) {
32
31
  const privKeys = [];
33
- for (let i = 0; i < inputs.length; i++) {
32
+ for(let i = 0; i < inputs.length; i++){
34
33
  const input = inputs[i];
35
- const keyPair = await this.getMethod('keyPair')(input.derivationPath);
34
+ let derivationPath = input.derivationPath;
35
+ if (!derivationPath) {
36
+ derivationPath = (await this.getMethod('getWalletAddress')(input.address)).derivationPath;
37
+ }
38
+ const keyPair = await this.getMethod('keyPair')(derivationPath);
36
39
  const privKey = Buffer.from(keyPair.__D).toString('hex');
37
40
  privKeys.push(privKey);
38
41
  }
@@ -40,7 +43,7 @@ class BitcoinDlcProvider extends provider_1.default {
40
43
  }
41
44
  async GetCfdNetwork() {
42
45
  const network = await this.getConnectedNetwork();
43
- switch (network.name) {
46
+ switch(network.name){
44
47
  case 'bitcoin_testnet':
45
48
  return 'testnet';
46
49
  case 'bitcoin_regtest':
@@ -50,24 +53,21 @@ class BitcoinDlcProvider extends provider_1.default {
50
53
  }
51
54
  }
52
55
  async GetInputsForAmount(amount, feeRatePerVb, fixedInputs = []) {
53
- if (amount === BigInt(0))
54
- return [];
56
+ if (amount === BigInt(0)) return [];
55
57
  const targets = [
56
58
  {
57
59
  address: BurnAddress,
58
- value: Number(amount) + ESTIMATED_SIZE * (Number(feeRatePerVb) - 1),
59
- },
60
+ value: Number(amount) + ESTIMATED_SIZE * (Number(feeRatePerVb) - 1)
61
+ },
60
62
  ];
61
63
  let inputs;
62
64
  try {
63
65
  const inputsForAmount = await this.getMethod('getInputsForAmount')(targets, Number(feeRatePerVb), fixedInputs);
64
66
  inputs = inputsForAmount.inputs;
65
- }
66
- catch (e) {
67
+ } catch (e) {
67
68
  if (fixedInputs.length === 0) {
68
69
  throw Error('Not enough balance getInputsForAmount');
69
- }
70
- else {
70
+ } else {
71
71
  inputs = fixedInputs;
72
72
  }
73
73
  }
@@ -76,113 +76,156 @@ class BitcoinDlcProvider extends provider_1.default {
76
76
  async Initialize(collateral, feeRatePerVb, fixedInputs) {
77
77
  const network = await this.getConnectedNetwork();
78
78
  const payoutAddress = await this.client.wallet.getUnusedAddress(false);
79
- const payoutSPK = bitcoinjs_lib_1.address.toOutputScript(payoutAddress.address, network);
79
+ const payoutSPK = _bitcoinjsLib.address.toOutputScript(payoutAddress.address, network);
80
80
  const changeAddress = await this.client.wallet.getUnusedAddress(true);
81
- const changeSPK = bitcoinjs_lib_1.address.toOutputScript(changeAddress.address, network);
81
+ const changeSPK = _bitcoinjsLib.address.toOutputScript(changeAddress.address, network);
82
82
  const fundingAddress = await this.client.wallet.getUnusedAddress(false);
83
83
  const fundingPubKey = Buffer.from(fundingAddress.publicKey, 'hex');
84
- if (fundingAddress.address === payoutAddress.address)
85
- throw Error('Address reuse');
84
+ if (fundingAddress.address === payoutAddress.address) throw Error('Address reuse');
86
85
  const inputs = await this.GetInputsForAmount(collateral, feeRatePerVb, fixedInputs);
87
- const fundingInputs = await Promise.all(inputs.map(async (input) => {
86
+ const fundingInputs = await Promise.all(inputs.map(async (input)=>{
88
87
  return this.inputToFundingInput(input);
89
88
  }));
90
- const payoutSerialId = Utils_1.generateSerialId();
91
- const changeSerialId = Utils_1.generateSerialId();
89
+ const payoutSerialId = (0, _utils1).generateSerialId();
90
+ const changeSerialId = (0, _utils1).generateSerialId();
92
91
  return {
93
92
  fundingPubKey,
94
93
  payoutSPK,
95
94
  payoutSerialId,
96
95
  fundingInputs,
97
96
  changeSPK,
98
- changeSerialId,
97
+ changeSerialId
99
98
  };
100
99
  }
101
100
  /**
102
- * TODO: Add GetPayoutFromOutcomes
103
- *
104
- * private GetPayoutsFromOutcomes(
105
- * contractDescriptor: ContractDescriptorV0,
106
- * totalCollateral: bigint,
107
- * ): PayoutRequest[] {}
108
- */
109
- GetPayoutsFromPayoutFunction(_dlcOffer, contractDescriptor, oracleInfo, totalCollateral) {
110
- if (_dlcOffer.type !== messaging_1.MessageType.DlcOfferV0)
111
- throw Error('DlcOffer must be V0');
101
+ * TODO: Add GetPayoutFromOutcomes
102
+ *
103
+ * private GetPayoutsFromOutcomes(
104
+ * contractDescriptor: ContractDescriptorV0,
105
+ * totalCollateral: bigint,
106
+ * ): PayoutRequest[] {}
107
+ */ GetPayoutsFromPayoutFunction(_dlcOffer, contractDescriptor, oracleInfo, totalCollateral) {
108
+ if (_dlcOffer.type !== _messaging.MessageType.DlcOfferV0) throw Error('DlcOffer must be V0');
112
109
  const dlcOffer = _dlcOffer;
113
- if (contractDescriptor.payoutFunction.type !== messaging_1.MessageType.PayoutFunctionV0)
114
- throw Error('PayoutFunction must be V0');
110
+ if (contractDescriptor.payoutFunction.type !== _messaging.MessageType.PayoutFunctionV0) throw Error('PayoutFunction must be V0');
115
111
  const payoutFunction = contractDescriptor.payoutFunction;
116
- if (payoutFunction.pieces.length === 0)
117
- throw Error('PayoutFunction must have at least once PayoutCurvePiece');
118
- if (payoutFunction.pieces.length > 1)
119
- throw Error('More than one PayoutCurvePiece not supported');
120
- const payoutCurvePiece = payoutFunction.pieces[0]
121
- .payoutCurvePiece;
122
- if (payoutCurvePiece.type !== messaging_1.MessageType.HyperbolaPayoutCurvePiece &&
123
- payoutCurvePiece.type !== messaging_1.MessageType.OldHyperbolaPayoutCurvePiece)
124
- throw Error('Must be HyperbolaPayoutCurvePiece');
125
- if (payoutCurvePiece.b !== BigInt(0) || payoutCurvePiece.c !== BigInt(0))
126
- throw Error('b and c HyperbolaPayoutCurvePiece values must be 0');
127
- const eventDescriptor = oracleInfo.announcement.oracleEvent
128
- .eventDescriptor;
129
- if (eventDescriptor.type !== messaging_1.MessageType.DigitDecompositionEventDescriptorV0)
130
- throw Error('Only DigitDecomposition Oracle Events supported');
112
+ if (payoutFunction.pieces.length === 0) throw Error('PayoutFunction must have at least once PayoutCurvePiece');
113
+ if (payoutFunction.pieces.length > 1) throw Error('More than one PayoutCurvePiece not supported');
114
+ const payoutCurvePiece = payoutFunction.pieces[0].payoutCurvePiece;
115
+ if (payoutCurvePiece.type !== _messaging.MessageType.HyperbolaPayoutCurvePiece && payoutCurvePiece.type !== _messaging.MessageType.OldHyperbolaPayoutCurvePiece) throw Error('Must be HyperbolaPayoutCurvePiece');
116
+ if (payoutCurvePiece.b !== BigInt(0) || payoutCurvePiece.c !== BigInt(0)) throw Error('b and c HyperbolaPayoutCurvePiece values must be 0');
117
+ const eventDescriptor = oracleInfo.announcement.oracleEvent.eventDescriptor;
118
+ if (eventDescriptor.type !== _messaging.MessageType.DigitDecompositionEventDescriptorV0) throw Error('Only DigitDecomposition Oracle Events supported');
131
119
  const roundingIntervals = contractDescriptor.roundingIntervals;
132
- const cetPayouts = core_1.HyperbolaPayoutCurve.computePayouts(payoutFunction, totalCollateral, roundingIntervals);
120
+ const cetPayouts = _core.HyperbolaPayoutCurve.computePayouts(payoutFunction, totalCollateral, roundingIntervals);
133
121
  const payoutGroups = [];
134
- cetPayouts.forEach((p) => {
122
+ cetPayouts.forEach((p)=>{
135
123
  payoutGroups.push({
136
124
  payout: p.payout,
137
- groups: core_1.groupByIgnoringDigits(p.indexFrom, p.indexTo, eventDescriptor.base, contractDescriptor.numDigits),
125
+ groups: (0, _core).groupByIgnoringDigits(p.indexFrom, p.indexTo, eventDescriptor.base, contractDescriptor.numDigits)
138
126
  });
139
127
  });
140
128
  const rValuesMessagesList = this.GenerateMessages(oracleInfo);
141
- const { payouts, messagesList } = Utils_1.outputsToPayouts(payoutGroups, rValuesMessagesList, dlcOffer.offerCollateralSatoshis, dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis, true);
142
- return { payouts, payoutGroups, messagesList };
129
+ const { payouts , messagesList } = (0, _utils1).outputsToPayouts(payoutGroups, rValuesMessagesList, dlcOffer.offerCollateralSatoshis, dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis, true);
130
+ return {
131
+ payouts,
132
+ payoutGroups,
133
+ messagesList
134
+ };
135
+ }
136
+ GetPayoutsFromPolynomialPayoutFunction(_dlcOffer, contractDescriptor, oracleInfo, totalCollateral) {
137
+ if (_dlcOffer.type !== _messaging.MessageType.DlcOfferV0) throw Error('DlcOffer must be V0');
138
+ const dlcOffer = _dlcOffer;
139
+ if (contractDescriptor.payoutFunction.type !== _messaging.MessageType.PayoutFunctionV0) throw Error('PayoutFunction must be V0');
140
+ const payoutFunction = contractDescriptor.payoutFunction;
141
+ if (payoutFunction.pieces.length === 0) throw Error('PayoutFunction must have at least once PayoutCurvePiece');
142
+ for (const piece of payoutFunction.pieces){
143
+ if (piece.payoutCurvePiece.type !== _messaging.MessageType.PolynomialPayoutCurvePiece) throw Error('Must be PolynomialPayoutCurvePiece');
144
+ }
145
+ const eventDescriptor = oracleInfo.announcement.oracleEvent.eventDescriptor;
146
+ if (eventDescriptor.type !== _messaging.MessageType.DigitDecompositionEventDescriptorV0) throw Error('Only DigitDecomposition Oracle Events supported');
147
+ const roundingIntervals = contractDescriptor.roundingIntervals;
148
+ const cetPayouts = _core.PolynomialPayoutCurve.computePayouts(payoutFunction, totalCollateral, roundingIntervals);
149
+ const payoutGroups = [];
150
+ cetPayouts.forEach((p)=>{
151
+ payoutGroups.push({
152
+ payout: p.payout,
153
+ groups: (0, _core).groupByIgnoringDigits(p.indexFrom, p.indexTo, eventDescriptor.base, contractDescriptor.numDigits)
154
+ });
155
+ });
156
+ const rValuesMessagesList = this.GenerateMessages(oracleInfo);
157
+ const { payouts , messagesList } = (0, _utils1).outputsToPayouts(payoutGroups, rValuesMessagesList, dlcOffer.offerCollateralSatoshis, dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis, true);
158
+ return {
159
+ payouts,
160
+ payoutGroups,
161
+ messagesList
162
+ };
143
163
  }
144
164
  GetPayouts(_dlcOffer) {
145
- const { dlcOffer } = Utils_1.checkTypes({ _dlcOffer });
165
+ const { dlcOffer } = (0, _utils1).checkTypes({
166
+ _dlcOffer
167
+ });
146
168
  const contractInfo = dlcOffer.contractInfo;
147
169
  const totalCollateral = contractInfo.totalCollateral;
148
170
  const contractOraclePairs = this.GetContractOraclePairs(contractInfo);
149
- const payoutResponses = contractOraclePairs.map(({ contractDescriptor, oracleInfo }) => this.GetPayoutsFromContractDescriptor(dlcOffer, contractDescriptor, oracleInfo, totalCollateral));
171
+ const payoutResponses = contractOraclePairs.map(({ contractDescriptor , oracleInfo })=>this.GetPayoutsFromContractDescriptor(dlcOffer, contractDescriptor, oracleInfo, totalCollateral)
172
+ );
150
173
  return payoutResponses;
151
174
  }
152
175
  FlattenPayouts(payoutResponses) {
153
- return payoutResponses.reduce((acc, { payouts, payoutGroups, messagesList }) => {
176
+ return payoutResponses.reduce((acc, { payouts , payoutGroups , messagesList })=>{
154
177
  return {
155
178
  payouts: acc.payouts.concat(payouts),
156
179
  payoutGroups: acc.payoutGroups.concat(payoutGroups),
157
- messagesList: acc.messagesList.concat(messagesList),
180
+ messagesList: acc.messagesList.concat(messagesList)
158
181
  };
159
182
  });
160
183
  }
161
184
  GetIndicesFromPayouts(payoutResponses) {
162
- return payoutResponses.reduce((prev, acc) => {
185
+ return payoutResponses.reduce((prev, acc)=>{
163
186
  return prev.concat({
164
- startingMessagesIndex: prev[prev.length - 1].startingMessagesIndex +
165
- acc.messagesList.length,
166
- startingPayoutGroupsIndex: prev[prev.length - 1].startingPayoutGroupsIndex +
167
- acc.payoutGroups.length,
187
+ startingMessagesIndex: prev[prev.length - 1].startingMessagesIndex + acc.messagesList.length,
188
+ startingPayoutGroupsIndex: prev[prev.length - 1].startingPayoutGroupsIndex + acc.payoutGroups.length
168
189
  });
169
- }, [{ startingMessagesIndex: 0, startingPayoutGroupsIndex: 0 }]);
190
+ }, [
191
+ {
192
+ startingMessagesIndex: 0,
193
+ startingPayoutGroupsIndex: 0
194
+ }
195
+ ]);
170
196
  }
171
197
  GetPayoutsFromContractDescriptor(dlcOffer, contractDescriptor, oracleInfo, totalCollateral) {
172
- switch (contractDescriptor.type) {
173
- case messaging_1.MessageType.ContractDescriptorV0:
174
- throw Error('ContractDescriptorV0 not yet supported');
175
- case messaging_1.MessageType.ContractDescriptorV1:
176
- // eslint-disable-next-line no-case-declarations
177
- return this.GetPayoutsFromPayoutFunction(dlcOffer, contractDescriptor, oracleInfo, totalCollateral);
198
+ switch(contractDescriptor.type){
199
+ case _messaging.MessageType.ContractDescriptorV0:
200
+ {
201
+ throw Error('ContractDescriptorV0 not yet supported');
202
+ }
203
+ case _messaging.MessageType.ContractDescriptorV1:
204
+ {
205
+ const contractDescriptorV1 = contractDescriptor;
206
+ const payoutFunction = contractDescriptorV1.payoutFunction;
207
+ // TODO: add a better check for this
208
+ const payoutCurvePiece = payoutFunction.pieces[0].payoutCurvePiece;
209
+ switch(payoutCurvePiece.type){
210
+ case _messaging.MessageType.HyperbolaPayoutCurvePiece:
211
+ return this.GetPayoutsFromPayoutFunction(dlcOffer, contractDescriptor, oracleInfo, totalCollateral);
212
+ case _messaging.MessageType.OldHyperbolaPayoutCurvePiece:
213
+ return this.GetPayoutsFromPayoutFunction(dlcOffer, contractDescriptor, oracleInfo, totalCollateral);
214
+ case _messaging.MessageType.PolynomialPayoutCurvePiece:
215
+ return this.GetPayoutsFromPolynomialPayoutFunction(dlcOffer, contractDescriptor, oracleInfo, totalCollateral);
216
+ }
217
+ }
218
+ break;
178
219
  default:
179
- throw Error('ContractDescriptor must be V0 or V1');
220
+ {
221
+ throw Error('ContractDescriptor must be V0 or V1');
222
+ }
180
223
  }
181
224
  }
182
225
  async createDlcTxs(_dlcOffer, _dlcAccept) {
183
- const { dlcOffer, dlcAccept } = Utils_1.checkTypes({
226
+ const { dlcOffer , dlcAccept } = (0, _utils1).checkTypes({
184
227
  _dlcOffer,
185
- _dlcAccept,
228
+ _dlcAccept
186
229
  });
187
230
  const localFundPubkey = dlcOffer.fundingPubKey.toString('hex');
188
231
  const remoteFundPubkey = dlcAccept.fundingPubKey.toString('hex');
@@ -190,18 +233,20 @@ class BitcoinDlcProvider extends provider_1.default {
190
233
  const remoteFinalScriptPubkey = dlcAccept.payoutSPK.toString('hex');
191
234
  const localChangeScriptPubkey = dlcOffer.changeSPK.toString('hex');
192
235
  const remoteChangeScriptPubkey = dlcAccept.changeSPK.toString('hex');
193
- const localInputs = await Promise.all(dlcOffer.fundingInputs.map(async (fundingInput) => {
236
+ const localInputs = await Promise.all(dlcOffer.fundingInputs.map(async (fundingInput)=>{
194
237
  const input = await this.fundingInputToInput(fundingInput, false);
195
238
  return input.toUtxo();
196
239
  }));
197
- const remoteInputs = await Promise.all(dlcAccept.fundingInputs.map(async (fundingInput) => {
240
+ const remoteInputs = await Promise.all(dlcAccept.fundingInputs.map(async (fundingInput)=>{
198
241
  const input = await this.fundingInputToInput(fundingInput, false);
199
242
  return input.toUtxo();
200
243
  }));
201
- const localInputAmount = localInputs.reduce((prev, cur) => prev + cur.amount.GetSatoshiAmount(), 0);
202
- const remoteInputAmount = remoteInputs.reduce((prev, cur) => prev + cur.amount.GetSatoshiAmount(), 0);
244
+ const localInputAmount = localInputs.reduce((prev, cur)=>prev + cur.amount.GetSatoshiAmount()
245
+ , 0);
246
+ const remoteInputAmount = remoteInputs.reduce((prev, cur)=>prev + cur.amount.GetSatoshiAmount()
247
+ , 0);
203
248
  const payoutResponses = this.GetPayouts(dlcOffer);
204
- const { payouts, messagesList } = this.FlattenPayouts(payoutResponses);
249
+ const { payouts , messagesList } = this.FlattenPayouts(payoutResponses);
205
250
  const dlcTxRequest = {
206
251
  payouts,
207
252
  localFundPubkey,
@@ -223,23 +268,26 @@ class BitcoinDlcProvider extends provider_1.default {
223
268
  remoteChangeScriptPubkey,
224
269
  feeRate: Number(dlcOffer.feeRatePerVb),
225
270
  cetLockTime: dlcOffer.cetLocktime,
226
- fundOutputSerialId: dlcOffer.fundOutputSerialId,
271
+ fundOutputSerialId: dlcOffer.fundOutputSerialId
227
272
  };
228
273
  const dlcTxs = await this.CreateDlcTransactions(dlcTxRequest);
229
- const dlcTransactions = new messaging_1.DlcTransactionsV0();
230
- dlcTransactions.fundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(dlcTxs.fundTxHex));
274
+ const dlcTransactions = new _messaging.DlcTransactionsV0();
275
+ dlcTransactions.fundTx = _bitcoin.Tx.decode(_bufio.StreamReader.fromHex(dlcTxs.fundTxHex));
231
276
  dlcTransactions.fundTxVout = [
232
277
  BigInt(dlcOffer.changeSerialId),
233
278
  BigInt(dlcAccept.changeSerialId),
234
- BigInt(dlcTxRequest.fundOutputSerialId),
235
- ]
236
- .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
237
- .findIndex((i) => BigInt(i) === BigInt(dlcTxRequest.fundOutputSerialId));
238
- dlcTransactions.refundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(dlcTxs.refundTxHex));
239
- dlcTransactions.cets = dlcTxs.cetsHex.map((cetHex) => {
240
- return bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(cetHex));
279
+ BigInt(dlcTxRequest.fundOutputSerialId),
280
+ ].sort((a, b)=>a < b ? -1 : a > b ? 1 : 0
281
+ ).findIndex((i)=>BigInt(i) === BigInt(dlcTxRequest.fundOutputSerialId)
282
+ );
283
+ dlcTransactions.refundTx = _bitcoin.Tx.decode(_bufio.StreamReader.fromHex(dlcTxs.refundTxHex));
284
+ dlcTransactions.cets = dlcTxs.cetsHex.map((cetHex)=>{
285
+ return _bitcoin.Tx.decode(_bufio.StreamReader.fromHex(cetHex));
241
286
  });
242
- return { dlcTransactions, messagesList };
287
+ return {
288
+ dlcTransactions,
289
+ messagesList
290
+ };
243
291
  }
244
292
  GenerateEnumMessages(oracleEvent) {
245
293
  throw Error('Only DigitDecomposition Oracle Events supported');
@@ -248,73 +296,76 @@ class BitcoinDlcProvider extends provider_1.default {
248
296
  const oracleNonces = oracleEvent.oracleNonces;
249
297
  const eventDescriptor = oracleEvent.eventDescriptor;
250
298
  const messagesList = [];
251
- oracleNonces.forEach(() => {
299
+ oracleNonces.forEach(()=>{
252
300
  const messages = [];
253
- for (let i = 0; i < eventDescriptor.base; i++) {
301
+ for(let i = 0; i < eventDescriptor.base; i++){
254
302
  const m = i.toString();
255
303
  messages.push(m);
256
304
  }
257
- messagesList.push({ messages });
305
+ messagesList.push({
306
+ messages
307
+ });
258
308
  });
259
309
  return messagesList;
260
310
  }
261
311
  GenerateMessages(oracleInfo) {
262
312
  const oracleEvent = oracleInfo.announcement.oracleEvent;
263
- switch (oracleEvent.eventDescriptor.type) {
264
- case messaging_1.MessageType.EnumEventDescriptorV0:
313
+ switch(oracleEvent.eventDescriptor.type){
314
+ case _messaging.MessageType.EnumEventDescriptorV0:
265
315
  return this.GenerateEnumMessages(oracleEvent);
266
- case messaging_1.MessageType.DigitDecompositionEventDescriptorV0:
316
+ case _messaging.MessageType.DigitDecompositionEventDescriptorV0:
267
317
  return this.GenerateDigitDecompositionMessages(oracleEvent);
268
318
  default:
269
319
  throw Error('EventDescriptor must be Enum or DigitDecomposition');
270
320
  }
271
321
  }
272
322
  GetContractOraclePairs(_contractInfo) {
273
- switch (_contractInfo.type) {
274
- case messaging_1.MessageType.ContractInfoV0: {
275
- const contractInfo = _contractInfo;
276
- return [
277
- {
278
- contractDescriptor: contractInfo.contractDescriptor,
279
- oracleInfo: contractInfo.oracleInfo,
280
- },
281
- ];
282
- }
283
- case messaging_1.MessageType.ContractInfoV1: {
284
- return _contractInfo.contractOraclePairs;
285
- }
323
+ switch(_contractInfo.type){
324
+ case _messaging.MessageType.ContractInfoV0:
325
+ {
326
+ const contractInfo = _contractInfo;
327
+ return [
328
+ {
329
+ contractDescriptor: contractInfo.contractDescriptor,
330
+ oracleInfo: contractInfo.oracleInfo
331
+ },
332
+ ];
333
+ }
334
+ case _messaging.MessageType.ContractInfoV1:
335
+ {
336
+ return _contractInfo.contractOraclePairs;
337
+ }
286
338
  default:
287
339
  throw Error('ContractInfo must be V0 or V1');
288
340
  }
289
341
  }
290
342
  async CreateCetAdaptorAndRefundSigs(_dlcOffer, _dlcAccept, _dlcTxs, messagesList, isOfferer) {
291
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
343
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
292
344
  _dlcOffer,
293
345
  _dlcAccept,
294
- _dlcTxs,
346
+ _dlcTxs
295
347
  });
296
348
  const network = await this.getConnectedNetwork();
297
- const cetsHex = dlcTxs.cets.map((cet) => cet.serialize().toString('hex'));
298
- const fundingSPK = bitcoin_1.Script.p2wpkhLock(crypto_1.hash160(isOfferer ? dlcOffer.fundingPubKey : dlcAccept.fundingPubKey))
299
- .serialize()
300
- .slice(1);
301
- const fundingAddress = bitcoinjs_lib_1.address.fromOutputScript(fundingSPK, network);
302
- const { derivationPath } = await this.getMethod('findAddress')([
303
- fundingAddress,
349
+ const cetsHex = dlcTxs.cets.map((cet)=>cet.serialize().toString('hex')
350
+ );
351
+ const fundingSPK = _bitcoin.Script.p2wpkhLock((0, _crypto).hash160(isOfferer ? dlcOffer.fundingPubKey : dlcAccept.fundingPubKey)).serialize().slice(1);
352
+ const fundingAddress = _bitcoinjsLib.address.fromOutputScript(fundingSPK, network);
353
+ const { derivationPath , } = await this.client.financewallet.quickFindAddress([
354
+ fundingAddress
304
355
  ]);
305
356
  const fundPrivateKeyPair = await this.getMethod('keyPair')(derivationPath);
306
357
  const fundPrivateKey = Buffer.from(fundPrivateKeyPair.__D).toString('hex');
307
358
  const contractOraclePairs = this.GetContractOraclePairs(dlcOffer.contractInfo);
308
359
  const indices = this.GetIndicesFromPayouts(this.GetPayouts(_dlcOffer));
309
360
  const sigs = [];
310
- for (const [index, { oracleInfo }] of contractOraclePairs.entries()) {
361
+ for (const [index, { oracleInfo }] of contractOraclePairs.entries()){
311
362
  const oracleAnnouncement = oracleInfo.announcement;
312
363
  const startingIndex = indices[index].startingMessagesIndex, endingIndex = indices[index + 1].startingMessagesIndex;
313
364
  const oracleEventMessagesList = messagesList.slice(startingIndex, endingIndex);
314
365
  const oracleEventCetsHex = cetsHex.slice(startingIndex, endingIndex);
315
366
  const chunk = 100;
316
367
  const adaptorSigRequestPromises = [];
317
- for (let i = 0, j = oracleEventMessagesList.length; i < j; i += chunk) {
368
+ for(let i = 0, j = oracleEventMessagesList.length; i < j; i += chunk){
318
369
  const tempMessagesList = oracleEventMessagesList.slice(i, i + chunk);
319
370
  const tempCetsHex = oracleEventCetsHex.slice(i, i + chunk);
320
371
  const cetSignRequest = {
@@ -327,18 +378,19 @@ class BitcoinDlcProvider extends provider_1.default {
327
378
  remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
328
379
  fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
329
380
  oraclePubkey: oracleAnnouncement.oraclePubkey.toString('hex'),
330
- oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce) => nonce.toString('hex')),
381
+ oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce)=>nonce.toString('hex')
382
+ )
331
383
  };
332
- adaptorSigRequestPromises.push((async () => {
384
+ adaptorSigRequestPromises.push((async ()=>{
333
385
  const response = await this.CreateCetAdaptorSignatures(cetSignRequest);
334
386
  return response.adaptorPairs;
335
387
  })());
336
388
  }
337
389
  const adaptorPairs = (await Promise.all(adaptorSigRequestPromises)).flat();
338
- sigs.push(adaptorPairs.map((adaptorPair) => {
390
+ sigs.push(adaptorPairs.map((adaptorPair)=>{
339
391
  return {
340
392
  encryptedSig: Buffer.from(adaptorPair.signature, 'hex'),
341
- dleqProof: Buffer.from(adaptorPair.proof, 'hex'),
393
+ dleqProof: Buffer.from(adaptorPair.proof, 'hex')
342
394
  };
343
395
  }));
344
396
  }
@@ -349,175 +401,174 @@ class BitcoinDlcProvider extends provider_1.default {
349
401
  fundVout: dlcTxs.fundTxVout,
350
402
  localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
351
403
  remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
352
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
404
+ fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats
353
405
  };
354
406
  const refundSignature = Buffer.from((await this.GetRawRefundTxSignature(refundSignRequest)).hex, 'hex');
355
- const cetSignatures = new messaging_1.CetAdaptorSignaturesV0();
407
+ const cetSignatures = new _messaging.CetAdaptorSignaturesV0();
356
408
  cetSignatures.sigs = sigs.flat();
357
- return { cetSignatures, refundSignature };
409
+ return {
410
+ cetSignatures,
411
+ refundSignature
412
+ };
358
413
  }
359
414
  async VerifyCetAdaptorAndRefundSigs(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, messagesList, isOfferer) {
360
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = Utils_1.checkTypes({
415
+ const { dlcOffer , dlcAccept , dlcSign , dlcTxs } = (0, _utils1).checkTypes({
361
416
  _dlcOffer,
362
417
  _dlcAccept,
363
418
  _dlcSign,
364
- _dlcTxs,
419
+ _dlcTxs
365
420
  });
366
- const cetsHex = dlcTxs.cets.map((cet) => cet.serialize().toString('hex'));
421
+ const cetsHex = dlcTxs.cets.map((cet)=>cet.serialize().toString('hex')
422
+ );
367
423
  const chunk = 100;
368
424
  const contractOraclePairs = this.GetContractOraclePairs(dlcOffer.contractInfo);
369
425
  const indices = this.GetIndicesFromPayouts(this.GetPayouts(_dlcOffer));
370
- for (const [index, { oracleInfo }] of contractOraclePairs.entries()) {
426
+ for (const [index, { oracleInfo }] of contractOraclePairs.entries()){
371
427
  const oracleAnnouncement = oracleInfo.announcement;
372
428
  const startingIndex = indices[index].startingMessagesIndex, endingIndex = indices[index + 1].startingMessagesIndex;
373
429
  const oracleEventMessagesList = messagesList.slice(startingIndex, endingIndex);
374
430
  const oracleEventCetsHex = cetsHex.slice(startingIndex, endingIndex);
375
- const oracleEventSigs = (isOfferer
376
- ? dlcAccept.cetSignatures.sigs
377
- : dlcSign.cetSignatures.sigs).slice(startingIndex, endingIndex);
431
+ const oracleEventSigs = (isOfferer ? dlcAccept.cetSignatures.sigs : dlcSign.cetSignatures.sigs).slice(startingIndex, endingIndex);
378
432
  const sigsValidity = [];
379
- for (let i = 0, j = oracleEventMessagesList.length; i < j; i += chunk) {
433
+ for(let i = 0, j = oracleEventMessagesList.length; i < j; i += chunk){
380
434
  const tempMessagesList = oracleEventMessagesList.slice(i, i + chunk);
381
435
  const tempCetsHex = oracleEventCetsHex.slice(i, i + chunk);
382
436
  const tempSigs = oracleEventSigs.slice(i, i + chunk);
383
- const tempAdaptorPairs = tempSigs.map((sig) => {
437
+ const tempAdaptorPairs = tempSigs.map((sig)=>{
384
438
  return {
385
439
  signature: sig.encryptedSig.toString('hex'),
386
- proof: sig.dleqProof.toString('hex'),
440
+ proof: sig.dleqProof.toString('hex')
387
441
  };
388
442
  });
389
443
  const verifyCetAdaptorSignaturesRequest = {
390
444
  cetsHex: tempCetsHex,
391
445
  messagesList: tempMessagesList,
392
446
  oraclePubkey: oracleAnnouncement.oraclePubkey.toString('hex'),
393
- oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce) => nonce.toString('hex')),
447
+ oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce)=>nonce.toString('hex')
448
+ ),
394
449
  adaptorPairs: tempAdaptorPairs,
395
450
  localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
396
451
  remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
397
452
  fundTxId: dlcTxs.fundTx.txId.toString(),
398
453
  fundVout: dlcTxs.fundTxVout,
399
454
  fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
400
- verifyRemote: isOfferer,
455
+ verifyRemote: isOfferer
401
456
  };
402
- sigsValidity.push((async () => {
457
+ sigsValidity.push((async ()=>{
403
458
  const response = await this.VerifyCetAdaptorSignatures(verifyCetAdaptorSignaturesRequest);
404
459
  return response.valid;
405
460
  })());
406
461
  }
407
- let areSigsValid = (await Promise.all(sigsValidity)).every((b) => b);
462
+ let areSigsValid = (await Promise.all(sigsValidity)).every((b)=>b
463
+ );
408
464
  const verifyRefundSigRequest = {
409
465
  refundTxHex: dlcTxs.refundTx.serialize().toString('hex'),
410
- signature: isOfferer
411
- ? dlcAccept.refundSignature.toString('hex')
412
- : dlcSign.refundSignature.toString('hex'),
466
+ signature: isOfferer ? dlcAccept.refundSignature.toString('hex') : dlcSign.refundSignature.toString('hex'),
413
467
  localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
414
468
  remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
415
469
  fundTxId: dlcTxs.fundTx.txId.toString(),
416
470
  fundVout: dlcTxs.fundTxVout,
417
471
  fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
418
- verifyRemote: isOfferer,
472
+ verifyRemote: isOfferer
419
473
  };
420
- areSigsValid =
421
- areSigsValid &&
422
- (await this.VerifyRefundTxSignature(verifyRefundSigRequest)).valid;
474
+ areSigsValid = areSigsValid && (await this.VerifyRefundTxSignature(verifyRefundSigRequest)).valid;
423
475
  if (!areSigsValid) {
424
476
  throw new Error('Invalid signatures received');
425
477
  }
426
478
  }
427
479
  }
428
480
  async CreateFundingSigs(_dlcOffer, _dlcAccept, _dlcTxs, isOfferer) {
429
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
481
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
430
482
  _dlcOffer,
431
483
  _dlcAccept,
432
- _dlcTxs,
484
+ _dlcTxs
433
485
  });
434
- const fundingInputs = isOfferer
435
- ? dlcOffer.fundingInputs
436
- : dlcAccept.fundingInputs;
437
- const inputs = await Promise.all(fundingInputs.map(async (fundingInput) => {
486
+ const fundingInputs = isOfferer ? dlcOffer.fundingInputs : dlcAccept.fundingInputs;
487
+ const inputs = await Promise.all(fundingInputs.map(async (fundingInput)=>{
438
488
  return this.fundingInputToInput(fundingInput);
439
489
  }));
440
490
  const inputPrivKeys = await this.GetPrivKeysForInputs(inputs);
441
- const fundTxSigs = await Promise.all(inputs.map(async (input, index) => {
491
+ const fundTxSigs = await Promise.all(inputs.map(async (input, index)=>{
442
492
  const fundTxSignRequest = {
443
493
  fundTxHex: dlcTxs.fundTx.serialize().toString('hex'),
444
494
  privkey: inputPrivKeys[index],
445
495
  prevTxId: input.txid,
446
496
  prevVout: input.vout,
447
- amount: input.value,
497
+ amount: input.value
448
498
  };
449
499
  return (await this.GetRawFundTxSignature(fundTxSignRequest)).hex;
450
500
  }));
451
- const inputPubKeys = await Promise.all(inputPrivKeys.map(async (privkey) => {
501
+ const inputPubKeys = await Promise.all(inputPrivKeys.map(async (privkey)=>{
452
502
  const reqPrivKey = {
453
503
  privkey,
454
- isCompressed: true,
504
+ isCompressed: true
455
505
  };
456
- return (await this.getMethod('GetPubkeyFromPrivkey')(reqPrivKey))
457
- .pubkey;
506
+ return (await this.getMethod('GetPubkeyFromPrivkey')(reqPrivKey)).pubkey;
458
507
  }));
459
508
  const witnessElements = [];
460
- for (let i = 0; i < fundTxSigs.length; i++) {
461
- const sigWitness = new messaging_1.ScriptWitnessV0();
509
+ for(let i = 0; i < fundTxSigs.length; i++){
510
+ const sigWitness = new _messaging.ScriptWitnessV0();
462
511
  sigWitness.witness = Buffer.from(fundTxSigs[i], 'hex');
463
- const pubKeyWitness = new messaging_1.ScriptWitnessV0();
512
+ const pubKeyWitness = new _messaging.ScriptWitnessV0();
464
513
  pubKeyWitness.witness = Buffer.from(inputPubKeys[i], 'hex');
465
- witnessElements.push([sigWitness, pubKeyWitness]);
514
+ witnessElements.push([
515
+ sigWitness,
516
+ pubKeyWitness
517
+ ]);
466
518
  }
467
- const fundingSignatures = new messaging_1.FundingSignaturesV0();
519
+ const fundingSignatures = new _messaging.FundingSignaturesV0();
468
520
  fundingSignatures.witnessElements = witnessElements;
469
521
  return fundingSignatures;
470
522
  }
471
523
  async VerifyFundingSigs(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, isOfferer) {
472
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = Utils_1.checkTypes({
524
+ const { dlcOffer , dlcAccept , dlcSign , dlcTxs } = (0, _utils1).checkTypes({
473
525
  _dlcOffer,
474
526
  _dlcAccept,
475
527
  _dlcSign,
476
- _dlcTxs,
528
+ _dlcTxs
477
529
  });
478
530
  const sigsValidity = [];
479
- for (let i = 0; i < dlcSign.fundingSignatures.witnessElements.length; i++) {
531
+ for(let i = 0; i < dlcSign.fundingSignatures.witnessElements.length; i++){
480
532
  const witnessElement = dlcSign.fundingSignatures.witnessElements[i];
481
533
  const signature = witnessElement[0].witness.toString('hex');
482
534
  const pubkey = witnessElement[1].witness.toString('hex');
483
- const fundingInput = isOfferer
484
- ? dlcAccept.fundingInputs[i]
485
- : dlcOffer.fundingInputs[i];
535
+ const fundingInput = isOfferer ? dlcAccept.fundingInputs[i] : dlcOffer.fundingInputs[i];
486
536
  const verifyFundSigRequest = {
487
537
  fundTxHex: dlcTxs.fundTx.serialize().toString('hex'),
488
538
  signature,
489
539
  pubkey,
490
540
  prevTxId: fundingInput.prevTx.txId.toString(),
491
541
  prevVout: fundingInput.prevTxVout,
492
- fundInputAmount: fundingInput.prevTx.outputs[fundingInput.prevTxVout].value.sats,
542
+ fundInputAmount: fundingInput.prevTx.outputs[fundingInput.prevTxVout].value.sats
493
543
  };
494
- sigsValidity.push((async () => {
544
+ sigsValidity.push((async ()=>{
495
545
  const response = await this.VerifyFundTxSignature(verifyFundSigRequest);
496
546
  return response.valid;
497
547
  })());
498
548
  }
499
- const areSigsValid = (await Promise.all(sigsValidity)).every((b) => b);
549
+ const areSigsValid = (await Promise.all(sigsValidity)).every((b)=>b
550
+ );
500
551
  if (!areSigsValid) {
501
552
  throw new Error('Invalid signatures received');
502
553
  }
503
554
  }
504
555
  async CreateFundingTx(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, fundingSignatures) {
505
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = Utils_1.checkTypes({
556
+ const { dlcOffer , dlcAccept , dlcSign , dlcTxs } = (0, _utils1).checkTypes({
506
557
  _dlcOffer,
507
558
  _dlcAccept,
508
559
  _dlcSign,
509
- _dlcTxs,
560
+ _dlcTxs
510
561
  });
511
562
  const witnessElements = [
512
563
  ...dlcSign.fundingSignatures.witnessElements,
513
- ...fundingSignatures.witnessElements,
564
+ ...fundingSignatures.witnessElements,
514
565
  ];
515
566
  const fundingInputs = [
516
567
  ...dlcOffer.fundingInputs,
517
- ...dlcAccept.fundingInputs,
568
+ ...dlcAccept.fundingInputs,
518
569
  ];
519
570
  let fundTxHex = dlcTxs.fundTx.serialize().toString('hex');
520
- await Utils_1.asyncForEach(witnessElements, async (witnessElement, i) => {
571
+ await (0, _utils1).asyncForEach(witnessElements, async (witnessElement, i)=>{
521
572
  const signature = witnessElement[0].witness.toString('hex');
522
573
  const pubkey = witnessElement[1].witness.toString('hex');
523
574
  const fundingInput = fundingInputs[i];
@@ -526,133 +577,185 @@ class BitcoinDlcProvider extends provider_1.default {
526
577
  signature,
527
578
  prevTxId: fundingInput.prevTx.txId.toString(),
528
579
  prevVout: fundingInput.prevTxVout,
529
- pubkey,
580
+ pubkey
530
581
  };
531
- fundTxHex = (await this.AddSignatureToFundTransaction(addSignRequest))
532
- .hex;
582
+ fundTxHex = (await this.AddSignatureToFundTransaction(addSignRequest)).hex;
533
583
  });
534
- const fundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(fundTxHex));
584
+ const fundTx = _bitcoin.Tx.decode(_bufio.StreamReader.fromHex(fundTxHex));
535
585
  return fundTx;
536
586
  }
537
- async FindOutcomeIndexFromHyperbolaPayoutCurvePiece(_dlcOffer, contractDescriptor, contractOraclePairIndex, hyperbolaPayoutCurvePiece, oracleAttestation, outcome) {
538
- const { dlcOffer } = Utils_1.checkTypes({ _dlcOffer });
539
- const hyperbolaCurve = core_1.HyperbolaPayoutCurve.fromPayoutCurvePiece(hyperbolaPayoutCurvePiece);
540
- const clampBN = (val) => bignumber_js_1.default.max(0, bignumber_js_1.default.min(val, dlcOffer.contractInfo.totalCollateral.toString()));
541
- const payout = clampBN(hyperbolaCurve.getPayout(outcome));
587
+ async FindOutcomeIndexFromPolynomialPayoutCurvePiece(_dlcOffer, contractDescriptor, contractOraclePairIndex, polynomialPayoutCurvePiece, oracleAttestation, outcome1) {
588
+ const { dlcOffer } = (0, _utils1).checkTypes({
589
+ _dlcOffer
590
+ });
591
+ const polynomialCurve = _core.PolynomialPayoutCurve.fromPayoutCurvePiece(polynomialPayoutCurvePiece);
592
+ const clampBN = (val)=>_bignumberJs.default.max(0, _bignumberJs.default.min(val, dlcOffer.contractInfo.totalCollateral.toString()))
593
+ ;
594
+ const payout = clampBN(polynomialCurve.getPayout(outcome1));
542
595
  const payoutResponses = this.GetPayouts(dlcOffer);
543
596
  const payoutIndexOffset = this.GetIndicesFromPayouts(payoutResponses)[contractOraclePairIndex].startingMessagesIndex;
544
- const { payoutGroups } = payoutResponses[contractOraclePairIndex];
597
+ const { payoutGroups } = payoutResponses[contractOraclePairIndex];
545
598
  const intervalsSorted = [
546
- ...contractDescriptor.roundingIntervals.intervals,
547
- ].sort((a, b) => Number(b.beginInterval) - Number(a.beginInterval));
548
- const interval = intervalsSorted.find((interval) => Number(outcome) >= Number(interval.beginInterval));
549
- const roundedPayout = BigInt(clampBN(new bignumber_js_1.default(core_1.roundPayout(payout, interval.roundingMod).toString())).toString());
550
- const outcomesFormatted = oracleAttestation.outcomes.map((outcome) => parseInt(outcome));
599
+ ...contractDescriptor.roundingIntervals.intervals,
600
+ ].sort((a, b)=>Number(b.beginInterval) - Number(a.beginInterval)
601
+ );
602
+ const interval1 = intervalsSorted.find((interval)=>Number(outcome1) >= Number(interval.beginInterval)
603
+ );
604
+ const roundedPayout = BigInt(clampBN(new _bignumberJs.default((0, _core).roundPayout(payout, interval1.roundingMod).toString())).toString());
605
+ const outcomesFormatted = oracleAttestation.outcomes.map((outcome)=>parseInt(outcome)
606
+ );
551
607
  let index = 0;
552
608
  let groupIndex = -1;
553
609
  let groupLength = 0;
554
- for (const payoutGroup of payoutGroups) {
610
+ for (const payoutGroup of payoutGroups){
555
611
  if (payoutGroup.payout === roundedPayout) {
556
- groupIndex = payoutGroup.groups.findIndex((group) => {
557
- return group.every((msg, i) => msg === outcomesFormatted[i]);
612
+ groupIndex = payoutGroup.groups.findIndex((group)=>{
613
+ return group.every((msg, i)=>msg === outcomesFormatted[i]
614
+ );
558
615
  });
559
- if (groupIndex === -1)
560
- throw Error('Failed to Find OutcomeIndex From HyperbolaPayoutCurvePiece. \
616
+ if (groupIndex === -1) throw Error('Failed to Find OutcomeIndex From PolynomialPayoutCurvePiece. \
561
617
  Payout Group found but incorrect group index');
562
618
  index += groupIndex;
563
619
  groupLength = payoutGroup.groups[groupIndex].length;
564
620
  break;
621
+ } else {
622
+ index += payoutGroup.groups.length;
565
623
  }
566
- else {
624
+ }
625
+ if (groupIndex === -1) throw Error('Failed to Find OutcomeIndex From PolynomialPayoutCurvePiece. \
626
+ Payout Group not found');
627
+ return {
628
+ index: payoutIndexOffset + index,
629
+ groupLength
630
+ };
631
+ }
632
+ async FindOutcomeIndexFromHyperbolaPayoutCurvePiece(_dlcOffer, contractDescriptor, contractOraclePairIndex, hyperbolaPayoutCurvePiece, oracleAttestation, outcome2) {
633
+ const { dlcOffer } = (0, _utils1).checkTypes({
634
+ _dlcOffer
635
+ });
636
+ const hyperbolaCurve = _core.HyperbolaPayoutCurve.fromPayoutCurvePiece(hyperbolaPayoutCurvePiece);
637
+ const clampBN = (val)=>_bignumberJs.default.max(0, _bignumberJs.default.min(val, dlcOffer.contractInfo.totalCollateral.toString()))
638
+ ;
639
+ const payout = clampBN(hyperbolaCurve.getPayout(outcome2));
640
+ const payoutResponses = this.GetPayouts(dlcOffer);
641
+ const payoutIndexOffset = this.GetIndicesFromPayouts(payoutResponses)[contractOraclePairIndex].startingMessagesIndex;
642
+ const { payoutGroups } = payoutResponses[contractOraclePairIndex];
643
+ const intervalsSorted = [
644
+ ...contractDescriptor.roundingIntervals.intervals,
645
+ ].sort((a, b)=>Number(b.beginInterval) - Number(a.beginInterval)
646
+ );
647
+ const interval2 = intervalsSorted.find((interval)=>Number(outcome2) >= Number(interval.beginInterval)
648
+ );
649
+ const roundedPayout = BigInt(clampBN(new _bignumberJs.default((0, _core).roundPayout(payout, interval2.roundingMod).toString())).toString());
650
+ const outcomesFormatted = oracleAttestation.outcomes.map((outcome)=>parseInt(outcome)
651
+ );
652
+ let index = 0;
653
+ let groupIndex = -1;
654
+ let groupLength = 0;
655
+ for (const payoutGroup of payoutGroups){
656
+ if (payoutGroup.payout === roundedPayout) {
657
+ groupIndex = payoutGroup.groups.findIndex((group)=>{
658
+ return group.every((msg, i)=>msg === outcomesFormatted[i]
659
+ );
660
+ });
661
+ if (groupIndex === -1) throw Error('Failed to Find OutcomeIndex From HyperbolaPayoutCurvePiece. \
662
+ Payout Group found but incorrect group index');
663
+ index += groupIndex;
664
+ groupLength = payoutGroup.groups[groupIndex].length;
665
+ break;
666
+ } else {
567
667
  index += payoutGroup.groups.length;
568
668
  }
569
669
  }
570
- if (groupIndex === -1)
571
- throw Error('Failed to Find OutcomeIndex From HyperbolaPayoutCurvePiece. \
670
+ if (groupIndex === -1) throw Error('Failed to Find OutcomeIndex From HyperbolaPayoutCurvePiece. \
572
671
  Payout Group not found');
573
- return { index: payoutIndexOffset + index, groupLength };
672
+ return {
673
+ index: payoutIndexOffset + index,
674
+ groupLength
675
+ };
574
676
  }
575
677
  async FindOutcomeIndex(_dlcOffer, oracleAttestation) {
576
- const { dlcOffer } = Utils_1.checkTypes({ _dlcOffer });
678
+ const { dlcOffer } = (0, _utils1).checkTypes({
679
+ _dlcOffer
680
+ });
577
681
  const contractOraclePairs = this.GetContractOraclePairs(dlcOffer.contractInfo);
578
- const contractOraclePairIndex = contractOraclePairs.findIndex(({ oracleInfo }) => oracleInfo.announcement.oracleEvent.eventId ===
579
- oracleAttestation.eventId);
580
- assert_1.default(contractOraclePairIndex !== -1, 'OracleAttestation must be for an existing OracleEvent');
682
+ const contractOraclePairIndex = contractOraclePairs.findIndex(({ oracleInfo })=>oracleInfo.announcement.oracleEvent.eventId === oracleAttestation.eventId
683
+ );
684
+ (0, _assert).default(contractOraclePairIndex !== -1, 'OracleAttestation must be for an existing OracleEvent');
581
685
  const contractOraclePair = contractOraclePairs[contractOraclePairIndex];
582
- const { contractDescriptor: _contractDescriptor, oracleInfo, } = contractOraclePair;
583
- assert_1.default(_contractDescriptor.type === messaging_1.MessageType.ContractDescriptorV1, 'ContractDescriptor must be V1');
686
+ const { contractDescriptor: _contractDescriptor , oracleInfo: oracleInfo1 , } = contractOraclePair;
687
+ (0, _assert).default(_contractDescriptor.type === _messaging.MessageType.ContractDescriptorV1, 'ContractDescriptor must be V1');
584
688
  const contractDescriptor = _contractDescriptor;
585
689
  const _payoutFunction = contractDescriptor.payoutFunction;
586
- assert_1.default(_payoutFunction.type === messaging_1.MessageType.PayoutFunctionV0, 'PayoutFunction must be V0');
587
- const eventDescriptor = oracleInfo.announcement.oracleEvent
588
- .eventDescriptor;
690
+ (0, _assert).default(_payoutFunction.type === _messaging.MessageType.PayoutFunctionV0, 'PayoutFunction must be V0');
691
+ const eventDescriptor = oracleInfo1.announcement.oracleEvent.eventDescriptor;
589
692
  const payoutFunction = _payoutFunction;
590
693
  const base = eventDescriptor.base;
591
- const outcome = [...oracleAttestation.outcomes]
592
- .reverse()
593
- .reduce((acc, val, i) => acc + Number(val) * base ** i, 0);
594
- const piecesSorted = payoutFunction.pieces.sort((a, b) => Number(b.endpoint) - Number(a.endpoint));
595
- const piece = piecesSorted.find((piece) => outcome < piece.endpoint);
596
- switch (piece.payoutCurvePiece.type) {
597
- case messaging_1.MessageType.PolynomialPayoutCurvePiece:
598
- throw Error('Polynomial Curve Piece not yet supported');
599
- case messaging_1.MessageType.HyperbolaPayoutCurvePiece:
600
- return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece.payoutCurvePiece, oracleAttestation, BigInt(outcome));
601
- case messaging_1.MessageType.OldHyperbolaPayoutCurvePiece:
602
- return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece.payoutCurvePiece, oracleAttestation, BigInt(outcome));
694
+ const outcome = [
695
+ ...oracleAttestation.outcomes
696
+ ].reverse().reduce((acc, val, i)=>acc + Number(val) * base ** i
697
+ , 0);
698
+ const piecesSorted = payoutFunction.pieces.sort((a, b)=>Number(a.endpoint) - Number(b.endpoint)
699
+ );
700
+ const piece1 = piecesSorted.find((piece)=>outcome < piece.endpoint
701
+ );
702
+ switch(piece1.payoutCurvePiece.type){
703
+ case _messaging.MessageType.PolynomialPayoutCurvePiece:
704
+ return this.FindOutcomeIndexFromPolynomialPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece1.payoutCurvePiece, oracleAttestation, BigInt(outcome));
705
+ case _messaging.MessageType.HyperbolaPayoutCurvePiece:
706
+ return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece1.payoutCurvePiece, oracleAttestation, BigInt(outcome));
707
+ case _messaging.MessageType.OldHyperbolaPayoutCurvePiece:
708
+ return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece1.payoutCurvePiece, oracleAttestation, BigInt(outcome));
603
709
  default:
604
710
  throw Error('Must be Hyperbola or Polynomial curve piece');
605
711
  }
606
712
  }
607
713
  ValidateEvent(_dlcOffer, oracleAttestation) {
608
- const { dlcOffer } = Utils_1.checkTypes({
609
- _dlcOffer,
714
+ const { dlcOffer } = (0, _utils1).checkTypes({
715
+ _dlcOffer
610
716
  });
611
- switch (dlcOffer.contractInfo.type) {
612
- case messaging_1.MessageType.ContractInfoV0: {
613
- const contractInfo = dlcOffer.contractInfo;
614
- switch (contractInfo.contractDescriptor.type) {
615
- case messaging_1.MessageType.ContractDescriptorV0:
616
- throw Error('ContractDescriptorV0 not yet supported');
617
- case messaging_1.MessageType.ContractDescriptorV1: {
618
- const oracleInfo = contractInfo.oracleInfo;
619
- if (oracleInfo.announcement.oracleEvent.eventId !==
620
- oracleAttestation.eventId)
621
- throw Error('Incorrect Oracle Attestation. Event Id must match.');
622
- break;
717
+ switch(dlcOffer.contractInfo.type){
718
+ case _messaging.MessageType.ContractInfoV0:
719
+ {
720
+ const contractInfo = dlcOffer.contractInfo;
721
+ switch(contractInfo.contractDescriptor.type){
722
+ case _messaging.MessageType.ContractDescriptorV0:
723
+ throw Error('ContractDescriptorV0 not yet supported');
724
+ case _messaging.MessageType.ContractDescriptorV1:
725
+ {
726
+ const oracleInfo = contractInfo.oracleInfo;
727
+ if (oracleInfo.announcement.oracleEvent.eventId !== oracleAttestation.eventId) throw Error('Incorrect Oracle Attestation. Event Id must match.');
728
+ break;
729
+ }
730
+ default:
731
+ throw Error('ConractDescriptor must be V0 or V1');
623
732
  }
624
- default:
625
- throw Error('ConractDescriptor must be V0 or V1');
733
+ break;
734
+ }
735
+ case _messaging.MessageType.ContractInfoV1:
736
+ {
737
+ const contractInfo = dlcOffer.contractInfo;
738
+ const attestedOracleEvent = contractInfo.contractOraclePairs.find(({ oracleInfo })=>oracleInfo.announcement.oracleEvent.eventId === oracleAttestation.eventId
739
+ );
740
+ if (!attestedOracleEvent) throw Error('Oracle event of attestation not found.');
741
+ break;
626
742
  }
627
- break;
628
- }
629
- case messaging_1.MessageType.ContractInfoV1: {
630
- const contractInfo = dlcOffer.contractInfo;
631
- const attestedOracleEvent = contractInfo.contractOraclePairs.find(({ oracleInfo }) => oracleInfo.announcement.oracleEvent.eventId ===
632
- oracleAttestation.eventId);
633
- if (!attestedOracleEvent)
634
- throw Error('Oracle event of attestation not found.');
635
- break;
636
- }
637
743
  default:
638
744
  throw Error('ContractInfo must be V0 or V1');
639
745
  }
640
746
  }
641
747
  async FindAndSignCet(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, oracleAttestation, isOfferer) {
642
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = Utils_1.checkTypes({
748
+ const { dlcOffer , dlcAccept , dlcSign , dlcTxs } = (0, _utils1).checkTypes({
643
749
  _dlcOffer,
644
750
  _dlcAccept,
645
751
  _dlcSign,
646
- _dlcTxs,
752
+ _dlcTxs
647
753
  });
648
- if (isOfferer === undefined)
649
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
650
- const { index: outcomeIndex, groupLength } = await this.FindOutcomeIndex(dlcOffer, oracleAttestation);
754
+ if (isOfferer === undefined) isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
755
+ const { index: outcomeIndex , groupLength } = await this.FindOutcomeIndex(dlcOffer, oracleAttestation);
651
756
  const fundPrivateKey = await this.GetFundPrivateKey(dlcOffer, dlcAccept, isOfferer);
652
757
  const sliceIndex = -(oracleAttestation.signatures.length - groupLength);
653
- const oracleSignatures = sliceIndex === 0
654
- ? oracleAttestation.signatures
655
- : oracleAttestation.signatures.slice(0, sliceIndex);
758
+ const oracleSignatures = sliceIndex === 0 ? oracleAttestation.signatures : oracleAttestation.signatures.slice(0, sliceIndex);
656
759
  const signCetRequest = {
657
760
  cetHex: dlcTxs.cets[outcomeIndex].serialize().toString('hex'),
658
761
  fundPrivkey: fundPrivateKey,
@@ -660,26 +763,23 @@ Payout Group not found');
660
763
  fundVout: dlcTxs.fundTxVout,
661
764
  localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
662
765
  remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
663
- oracleSignatures: oracleSignatures.map((sig) => sig.toString('hex')),
766
+ oracleSignatures: oracleSignatures.map((sig)=>sig.toString('hex')
767
+ ),
664
768
  fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
665
- adaptorSignature: isOfferer
666
- ? dlcAccept.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex')
667
- : dlcSign.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex'),
769
+ adaptorSignature: isOfferer ? dlcAccept.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex') : dlcSign.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex')
668
770
  };
669
771
  const finalCet = (await this.SignCet(signCetRequest)).hex;
670
- return bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(finalCet));
772
+ return _bitcoin.Tx.decode(_bufio.StreamReader.fromHex(finalCet));
671
773
  }
672
774
  async GetFundAddress(dlcOffer, dlcAccept, isOfferer) {
673
775
  const network = await this.getConnectedNetwork();
674
- const fundingSPK = bitcoin_1.Script.p2wpkhLock(crypto_1.hash160(isOfferer ? dlcOffer.fundingPubKey : dlcAccept.fundingPubKey))
675
- .serialize()
676
- .slice(1);
677
- const fundingAddress = bitcoinjs_lib_1.address.fromOutputScript(fundingSPK, network);
776
+ const fundingSPK = _bitcoin.Script.p2wpkhLock((0, _crypto).hash160(isOfferer ? dlcOffer.fundingPubKey : dlcAccept.fundingPubKey)).serialize().slice(1);
777
+ const fundingAddress = _bitcoinjsLib.address.fromOutputScript(fundingSPK, network);
678
778
  return fundingAddress;
679
779
  }
680
780
  async GetFundKeyPair(dlcOffer, dlcAccept, isOfferer) {
681
781
  const fundingAddress = await this.GetFundAddress(dlcOffer, dlcAccept, isOfferer);
682
- const { derivationPath } = await this.getMethod('getWalletAddress')(fundingAddress);
782
+ const { derivationPath } = await this.getMethod('getWalletAddress')(fundingAddress);
683
783
  const keyPair = await this.getMethod('keyPair')(derivationPath);
684
784
  return keyPair;
685
785
  }
@@ -688,57 +788,49 @@ Payout Group not found');
688
788
  return Buffer.from(fundPrivateKeyPair.privateKey).toString('hex');
689
789
  }
690
790
  async CreateCloseRawTxs(_dlcOffer, _dlcAccept, _dlcTxs, closeInputAmount, isOfferer, _dlcCloses = [], fundingInputs, initiatorPayouts) {
691
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
791
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
692
792
  _dlcOffer,
693
793
  _dlcAccept,
694
- _dlcTxs,
794
+ _dlcTxs
695
795
  });
696
796
  const network = await this.getConnectedNetwork();
697
797
  let finalizer;
698
798
  if (_dlcCloses.length === 0) {
699
- finalizer = new core_1.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
799
+ finalizer = new _core.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
700
800
  }
701
801
  const rawTransactionRequestPromises = [];
702
802
  const rawCloseTxs = [];
703
803
  const numPayouts = _dlcCloses.length === 0 ? initiatorPayouts.length : _dlcCloses.length;
704
- for (let i = 0; i < numPayouts; i++) {
804
+ for(let i = 0; i < numPayouts; i++){
705
805
  let offerPayoutValue = BigInt(0);
706
806
  let acceptPayoutValue = BigInt(0);
707
807
  if (_dlcCloses.length === 0) {
708
808
  const payout = initiatorPayouts[i];
709
- const payoutMinusOfferFees = finalizer.offerInitiatorFees > payout
710
- ? BigInt(0)
711
- : payout - finalizer.offerInitiatorFees;
712
- const collateralMinusPayout = payout > dlcOffer.contractInfo.totalCollateral
713
- ? BigInt(0)
714
- : dlcOffer.contractInfo.totalCollateral - payout;
715
- offerPayoutValue = isOfferer
716
- ? closeInputAmount + payoutMinusOfferFees
717
- : collateralMinusPayout;
718
- acceptPayoutValue = isOfferer
719
- ? collateralMinusPayout
720
- : closeInputAmount + payoutMinusOfferFees;
721
- }
722
- else {
723
- const dlcClose = Utils_1.checkTypes({ _dlcClose: _dlcCloses[i] }).dlcClose;
809
+ const payoutMinusOfferFees = finalizer.offerInitiatorFees > payout ? BigInt(0) : payout - finalizer.offerInitiatorFees;
810
+ const collateralMinusPayout = payout > dlcOffer.contractInfo.totalCollateral ? BigInt(0) : dlcOffer.contractInfo.totalCollateral - payout;
811
+ offerPayoutValue = isOfferer ? closeInputAmount + payoutMinusOfferFees : collateralMinusPayout;
812
+ acceptPayoutValue = isOfferer ? collateralMinusPayout : closeInputAmount + payoutMinusOfferFees;
813
+ } else {
814
+ const dlcClose = (0, _utils1).checkTypes({
815
+ _dlcClose: _dlcCloses[i]
816
+ }).dlcClose;
724
817
  offerPayoutValue = dlcClose.offerPayoutSatoshis;
725
818
  acceptPayoutValue = dlcClose.acceptPayoutSatoshis;
726
819
  }
727
820
  const txOuts = [];
728
821
  if (Number(offerPayoutValue) > 0) {
729
822
  txOuts.push({
730
- address: bitcoinjs_lib_1.address.fromOutputScript(dlcOffer.payoutSPK, network),
731
- amount: Number(offerPayoutValue),
823
+ address: _bitcoinjsLib.address.fromOutputScript(dlcOffer.payoutSPK, network),
824
+ amount: Number(offerPayoutValue)
732
825
  });
733
826
  }
734
827
  if (Number(acceptPayoutValue) > 0) {
735
828
  txOuts.push({
736
- address: bitcoinjs_lib_1.address.fromOutputScript(dlcAccept.payoutSPK, network),
737
- amount: Number(acceptPayoutValue),
829
+ address: _bitcoinjsLib.address.fromOutputScript(dlcAccept.payoutSPK, network),
830
+ amount: Number(acceptPayoutValue)
738
831
  });
739
832
  }
740
- if (dlcOffer.payoutSerialId > dlcAccept.payoutSerialId)
741
- txOuts.reverse();
833
+ if (dlcOffer.payoutSerialId > dlcAccept.payoutSerialId) txOuts.reverse();
742
834
  const rawTransactionRequest = {
743
835
  version: 2,
744
836
  locktime: 0,
@@ -746,12 +838,12 @@ Payout Group not found');
746
838
  {
747
839
  txid: dlcTxs.fundTx.txId.serialize().reverse().toString('hex'),
748
840
  vout: dlcTxs.fundTxVout,
749
- sequence: 0,
750
- },
841
+ sequence: 0
842
+ },
751
843
  ],
752
- txouts: txOuts,
844
+ txouts: txOuts
753
845
  };
754
- rawTransactionRequestPromises.push((async () => {
846
+ rawTransactionRequestPromises.push((async ()=>{
755
847
  const response = await this.getMethod('CreateRawTransaction')(rawTransactionRequest);
756
848
  return response.hex;
757
849
  })());
@@ -761,27 +853,31 @@ Payout Group not found');
761
853
  return rawCloseTxs.flat();
762
854
  }
763
855
  async CreateSignatureHashes(_dlcOffer, _dlcAccept, _dlcTxs, rawCloseTxs) {
764
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
856
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
765
857
  _dlcOffer,
766
858
  _dlcAccept,
767
- _dlcTxs,
859
+ _dlcTxs
768
860
  });
769
861
  const network = await this.getConnectedNetwork();
770
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
771
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
772
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
773
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
862
+ const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1 ? [
863
+ dlcOffer.fundingPubKey,
864
+ dlcAccept.fundingPubKey
865
+ ] : [
866
+ dlcAccept.fundingPubKey,
867
+ dlcOffer.fundingPubKey
868
+ ];
869
+ const p2ms = _bitcoinjsLib.payments.p2ms({
774
870
  m: 2,
775
871
  pubkeys: fundingPubKeys,
776
- network,
872
+ network
777
873
  });
778
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
874
+ const paymentVariant = _bitcoinjsLib.payments.p2wsh({
779
875
  redeem: p2ms,
780
- network,
876
+ network
781
877
  });
782
878
  const sigHashRequestPromises = [];
783
879
  const sigHashes = [];
784
- for (let i = 0; i < rawCloseTxs.length; i++) {
880
+ for(let i = 0; i < rawCloseTxs.length; i++){
785
881
  const rawTx = rawCloseTxs[i];
786
882
  const sigHashRequest = {
787
883
  tx: rawTx,
@@ -790,15 +886,15 @@ Payout Group not found');
790
886
  vout: dlcTxs.fundTxVout,
791
887
  keyData: {
792
888
  hex: paymentVariant.redeem.output.toString('hex'),
793
- type: 'redeem_script',
889
+ type: 'redeem_script'
794
890
  },
795
891
  amount: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
796
892
  hashType: 'p2wsh',
797
893
  sighashType: 'all',
798
- sighashAnyoneCanPay: false,
799
- },
894
+ sighashAnyoneCanPay: false
895
+ }
800
896
  };
801
- sigHashRequestPromises.push((async () => {
897
+ sigHashRequestPromises.push((async ()=>{
802
898
  const response = await this.getMethod('CreateSignatureHash')(sigHashRequest);
803
899
  return response.sighash;
804
900
  })());
@@ -810,18 +906,18 @@ Payout Group not found');
810
906
  async CalculateEcSignatureHashes(sigHashes, privKey) {
811
907
  const cfdNetwork = await this.GetCfdNetwork();
812
908
  const sigsRequestPromises = [];
813
- for (let i = 0; i < sigHashes.length; i++) {
909
+ for(let i = 0; i < sigHashes.length; i++){
814
910
  const sigHash = sigHashes[i];
815
911
  const calculateEcSignatureRequest = {
816
912
  sighash: sigHash,
817
913
  privkeyData: {
818
914
  privkey: privKey,
819
915
  wif: false,
820
- network: cfdNetwork,
916
+ network: cfdNetwork
821
917
  },
822
- isGrindR: true,
918
+ isGrindR: true
823
919
  };
824
- sigsRequestPromises.push((async () => {
920
+ sigsRequestPromises.push((async ()=>{
825
921
  const response = await this.getMethod('CalculateEcSignature')(calculateEcSignatureRequest);
826
922
  return response.signature;
827
923
  })());
@@ -830,28 +926,35 @@ Payout Group not found');
830
926
  return sigs.flat();
831
927
  }
832
928
  async VerifySignatures(_dlcOffer, _dlcAccept, _dlcTxs, _dlcCloses, rawCloseTxs, isOfferer) {
833
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
929
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
834
930
  _dlcOffer,
835
931
  _dlcAccept,
836
- _dlcTxs,
932
+ _dlcTxs
837
933
  });
838
- const dlcCloses = _dlcCloses.map((_dlcClose) => Utils_1.checkTypes({ _dlcClose }).dlcClose);
934
+ const dlcCloses = _dlcCloses.map((_dlcClose)=>(0, _utils1).checkTypes({
935
+ _dlcClose
936
+ }).dlcClose
937
+ );
839
938
  const network = await this.getConnectedNetwork();
840
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
841
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
842
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
843
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
939
+ const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1 ? [
940
+ dlcOffer.fundingPubKey,
941
+ dlcAccept.fundingPubKey
942
+ ] : [
943
+ dlcAccept.fundingPubKey,
944
+ dlcOffer.fundingPubKey
945
+ ];
946
+ const p2ms = _bitcoinjsLib.payments.p2ms({
844
947
  m: 2,
845
948
  pubkeys: fundingPubKeys,
846
- network,
949
+ network
847
950
  });
848
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
951
+ const paymentVariant = _bitcoinjsLib.payments.p2wsh({
849
952
  redeem: p2ms,
850
- network,
953
+ network
851
954
  });
852
955
  const pubkey = isOfferer ? dlcAccept.fundingPubKey : dlcOffer.fundingPubKey;
853
956
  const sigsValidity = [];
854
- for (let i = 0; i < rawCloseTxs.length; i++) {
957
+ for(let i = 0; i < rawCloseTxs.length; i++){
855
958
  const rawTx = rawCloseTxs[i];
856
959
  const dlcClose = dlcCloses[i];
857
960
  const verifySignatureRequest = {
@@ -865,67 +968,64 @@ Payout Group not found');
865
968
  hashType: 'p2wsh',
866
969
  sighashType: 'all',
867
970
  sighashAnyoneCanPay: false,
868
- amount: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
869
- },
971
+ amount: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats)
972
+ }
870
973
  };
871
- sigsValidity.push((async () => {
974
+ sigsValidity.push((async ()=>{
872
975
  const response = await this.getMethod('VerifySignature')(verifySignatureRequest);
873
976
  return response.success;
874
977
  })());
875
978
  }
876
- const areSigsValid = (await Promise.all(sigsValidity)).every((b) => b);
979
+ const areSigsValid = (await Promise.all(sigsValidity)).every((b)=>b
980
+ );
877
981
  return areSigsValid;
878
982
  }
879
983
  /**
880
- * Check whether wallet is offerer of DlcOffer or DlcAccept
881
- * @param dlcOffer Dlc Offer Message
882
- * @param dlcAccept Dlc Accept Message
883
- * @returns {Promise<boolean>}
884
- */
885
- async isOfferer(_dlcOffer, _dlcAccept) {
886
- const { dlcOffer, dlcAccept } = Utils_1.checkTypes({
984
+ * Check whether wallet is offerer of DlcOffer or DlcAccept
985
+ * @param dlcOffer Dlc Offer Message
986
+ * @param dlcAccept Dlc Accept Message
987
+ * @returns {Promise<boolean>}
988
+ */ async isOfferer(_dlcOffer, _dlcAccept) {
989
+ const { dlcOffer , dlcAccept } = (0, _utils1).checkTypes({
887
990
  _dlcOffer,
888
- _dlcAccept,
991
+ _dlcAccept
889
992
  });
890
993
  const network = await this.getConnectedNetwork();
891
- const offerFundingSPK = bitcoin_1.Script.p2wpkhLock(crypto_1.hash160(dlcOffer.fundingPubKey))
892
- .serialize()
893
- .slice(1);
894
- const acceptFundingSPK = bitcoin_1.Script.p2wpkhLock(crypto_1.hash160(dlcAccept.fundingPubKey))
895
- .serialize()
896
- .slice(1);
897
- const offerFundingAddress = bitcoinjs_lib_1.address.fromOutputScript(offerFundingSPK, network);
898
- const acceptFundingAddress = bitcoinjs_lib_1.address.fromOutputScript(acceptFundingSPK, network);
899
- let walletAddress = await this.getMethod('findAddress')([
900
- offerFundingAddress,
994
+ const offerFundingSPK = _bitcoin.Script.p2wpkhLock((0, _crypto).hash160(dlcOffer.fundingPubKey)).serialize().slice(1);
995
+ const acceptFundingSPK = _bitcoin.Script.p2wpkhLock((0, _crypto).hash160(dlcAccept.fundingPubKey)).serialize().slice(1);
996
+ const offerFundingAddress = _bitcoinjsLib.address.fromOutputScript(offerFundingSPK, network);
997
+ const acceptFundingAddress = _bitcoinjsLib.address.fromOutputScript(acceptFundingSPK, network);
998
+ let walletAddress = await this.client.financewallet.quickFindAddress([
999
+ offerFundingAddress
1000
+ ]);
1001
+ if (walletAddress) return true;
1002
+ walletAddress = await this.client.financewallet.quickFindAddress([
1003
+ acceptFundingAddress,
901
1004
  ]);
902
- if (walletAddress)
903
- return true;
904
- walletAddress = await this.getMethod('findAddress')([acceptFundingAddress]);
905
- if (walletAddress)
906
- return false;
1005
+ if (walletAddress) return false;
907
1006
  throw Error('Wallet Address not found for DlcOffer or DlcAccept');
908
1007
  }
909
1008
  /**
910
- * Create DLC Offer Message
911
- * @param contractInfo ContractInfo TLV (V0 or V1)
912
- * @param offerCollateralSatoshis Amount DLC Initiator is putting into the contract
913
- * @param feeRatePerVb Fee rate in satoshi per virtual byte that both sides use to compute fees in funding tx
914
- * @param cetLocktime The nLockTime to be put on CETs
915
- * @param refundLocktime The nLockTime to be put on the refund transaction
916
- * @returns {Promise<DlcOffer>}
917
- */
918
- async createDlcOffer(contractInfo, offerCollateralSatoshis, feeRatePerVb, cetLocktime, refundLocktime, fixedInputs) {
1009
+ * Create DLC Offer Message
1010
+ * @param contractInfo ContractInfo TLV (V0 or V1)
1011
+ * @param offerCollateralSatoshis Amount DLC Initiator is putting into the contract
1012
+ * @param feeRatePerVb Fee rate in satoshi per virtual byte that both sides use to compute fees in funding tx
1013
+ * @param cetLocktime The nLockTime to be put on CETs
1014
+ * @param refundLocktime The nLockTime to be put on the refund transaction
1015
+ * @returns {Promise<DlcOffer>}
1016
+ */ async createDlcOffer(contractInfo, offerCollateralSatoshis, feeRatePerVb, cetLocktime, refundLocktime, fixedInputs) {
919
1017
  contractInfo.validate();
920
1018
  const network = await this.getConnectedNetwork();
921
- const dlcOffer = new messaging_1.DlcOfferV0();
922
- const { fundingPubKey, payoutSPK, payoutSerialId, fundingInputs: _fundingInputs, changeSPK, changeSerialId, } = await this.Initialize(offerCollateralSatoshis, feeRatePerVb, fixedInputs);
923
- _fundingInputs.forEach((input) => assert_1.default(input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0'));
924
- const fundingInputs = _fundingInputs.map((input) => input);
925
- const fundOutputSerialId = Utils_1.generateSerialId();
926
- assert_1.default(changeSerialId !== fundOutputSerialId, 'changeSerialId cannot equal the fundOutputSerialId');
1019
+ const dlcOffer = new _messaging.DlcOfferV0();
1020
+ const { fundingPubKey , payoutSPK , payoutSerialId , fundingInputs: _fundingInputs , changeSPK , changeSerialId , } = await this.Initialize(offerCollateralSatoshis, feeRatePerVb, fixedInputs);
1021
+ _fundingInputs.forEach((input)=>(0, _assert).default(input.type === _messaging.MessageType.FundingInputV0, 'FundingInput must be V0')
1022
+ );
1023
+ const fundingInputs = _fundingInputs.map((input)=>input
1024
+ );
1025
+ const fundOutputSerialId = (0, _utils1).generateSerialId();
1026
+ (0, _assert).default(changeSerialId !== fundOutputSerialId, 'changeSerialId cannot equal the fundOutputSerialId');
927
1027
  dlcOffer.contractFlags = Buffer.from('00', 'hex');
928
- dlcOffer.chainHash = bitcoin_networks_1.chainHashFromNetwork(network);
1028
+ dlcOffer.chainHash = (0, _bitcoinNetworks).chainHashFromNetwork(network);
929
1029
  dlcOffer.contractInfo = contractInfo;
930
1030
  dlcOffer.fundingPubKey = fundingPubKey;
931
1031
  dlcOffer.payoutSPK = payoutSPK;
@@ -938,9 +1038,9 @@ Payout Group not found');
938
1038
  dlcOffer.feeRatePerVb = feeRatePerVb;
939
1039
  dlcOffer.cetLocktime = cetLocktime;
940
1040
  dlcOffer.refundLocktime = refundLocktime;
941
- assert_1.default((() => {
942
- const finalizer = new core_1.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, null, null, null, dlcOffer.feeRatePerVb);
943
- const funding = fundingInputs.reduce((total, input) => {
1041
+ (0, _assert).default((()=>{
1042
+ const finalizer = new _core.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, null, null, null, dlcOffer.feeRatePerVb);
1043
+ const funding = fundingInputs.reduce((total, input)=>{
944
1044
  return total + input.prevTx.outputs[input.prevTxVout].value.sats;
945
1045
  }, BigInt(0));
946
1046
  return funding >= offerCollateralSatoshis + finalizer.offerFees;
@@ -949,24 +1049,25 @@ Payout Group not found');
949
1049
  return dlcOffer;
950
1050
  }
951
1051
  /**
952
- * Accept DLC Offer
953
- * @param _dlcOffer Dlc Offer Message
954
- * @param fixedInputs Optional inputs to use for Funding Inputs
955
- * @returns {Promise<AcceptDlcOfferResponse}
956
- */
957
- async acceptDlcOffer(_dlcOffer, fixedInputs) {
958
- const { dlcOffer } = Utils_1.checkTypes({ _dlcOffer });
1052
+ * Accept DLC Offer
1053
+ * @param _dlcOffer Dlc Offer Message
1054
+ * @param fixedInputs Optional inputs to use for Funding Inputs
1055
+ * @returns {Promise<AcceptDlcOfferResponse}
1056
+ */ async acceptDlcOffer(_dlcOffer, fixedInputs) {
1057
+ const { dlcOffer } = (0, _utils1).checkTypes({
1058
+ _dlcOffer
1059
+ });
959
1060
  dlcOffer.validate();
960
1061
  const acceptCollateralSatoshis = dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis;
961
- assert_1.default(acceptCollateralSatoshis ===
962
- dlcOffer.contractInfo.totalCollateral -
963
- dlcOffer.offerCollateralSatoshis, 'acceptCollaterialSatoshis should equal totalCollateral - offerCollateralSatoshis');
964
- const { fundingPubKey, payoutSPK, payoutSerialId, fundingInputs: _fundingInputs, changeSPK, changeSerialId, } = await this.Initialize(acceptCollateralSatoshis, dlcOffer.feeRatePerVb, fixedInputs);
965
- assert_1.default(Buffer.compare(dlcOffer.fundingPubKey, fundingPubKey) !== 0, 'DlcOffer and DlcAccept FundingPubKey cannot be the same');
966
- _fundingInputs.forEach((input) => assert_1.default(input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0'));
967
- const fundingInputs = _fundingInputs.map((input) => input);
968
- const dlcAccept = new messaging_1.DlcAcceptV0();
969
- dlcAccept.tempContractId = crypto_1.sha256(dlcOffer.serialize());
1062
+ (0, _assert).default(acceptCollateralSatoshis === dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis, 'acceptCollaterialSatoshis should equal totalCollateral - offerCollateralSatoshis');
1063
+ const { fundingPubKey , payoutSPK , payoutSerialId , fundingInputs: _fundingInputs , changeSPK , changeSerialId , } = await this.Initialize(acceptCollateralSatoshis, dlcOffer.feeRatePerVb, fixedInputs);
1064
+ (0, _assert).default(Buffer.compare(dlcOffer.fundingPubKey, fundingPubKey) !== 0, 'DlcOffer and DlcAccept FundingPubKey cannot be the same');
1065
+ _fundingInputs.forEach((input)=>(0, _assert).default(input.type === _messaging.MessageType.FundingInputV0, 'FundingInput must be V0')
1066
+ );
1067
+ const fundingInputs = _fundingInputs.map((input)=>input
1068
+ );
1069
+ const dlcAccept = new _messaging.DlcAcceptV0();
1070
+ dlcAccept.tempContractId = (0, _crypto).sha256(dlcOffer.serialize());
970
1071
  dlcAccept.acceptCollateralSatoshis = acceptCollateralSatoshis;
971
1072
  dlcAccept.fundingPubKey = fundingPubKey;
972
1073
  dlcAccept.payoutSPK = payoutSPK;
@@ -974,81 +1075,85 @@ Payout Group not found');
974
1075
  dlcAccept.fundingInputs = fundingInputs;
975
1076
  dlcAccept.changeSPK = changeSPK;
976
1077
  dlcAccept.changeSerialId = dlcAccept.changeSerialId = changeSerialId;
977
- assert_1.default(dlcAccept.changeSerialId !== dlcOffer.fundOutputSerialId, 'changeSerialId cannot equal the fundOutputSerialId');
978
- assert_1.default(dlcOffer.payoutSerialId !== dlcAccept.payoutSerialId, 'offer.payoutSerialId cannot equal accept.payoutSerialId');
979
- assert_1.default((() => {
1078
+ (0, _assert).default(dlcAccept.changeSerialId !== dlcOffer.fundOutputSerialId, 'changeSerialId cannot equal the fundOutputSerialId');
1079
+ (0, _assert).default(dlcOffer.payoutSerialId !== dlcAccept.payoutSerialId, 'offer.payoutSerialId cannot equal accept.payoutSerialId');
1080
+ (0, _assert).default((()=>{
980
1081
  const ids = [
981
1082
  dlcOffer.changeSerialId,
982
1083
  dlcAccept.changeSerialId,
983
- dlcOffer.fundOutputSerialId,
1084
+ dlcOffer.fundOutputSerialId,
984
1085
  ];
985
1086
  return new Set(ids).size === ids.length;
986
1087
  })(), 'offer.changeSerialID, accept.changeSerialId and fundOutputSerialId must be unique');
987
1088
  dlcAccept.validate();
988
- assert_1.default((() => {
989
- const finalizer = new core_1.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, dlcAccept.fundingInputs, dlcAccept.payoutSPK, dlcAccept.changeSPK, dlcOffer.feeRatePerVb);
990
- const funding = fundingInputs.reduce((total, input) => {
1089
+ (0, _assert).default((()=>{
1090
+ const finalizer = new _core.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, dlcAccept.fundingInputs, dlcAccept.payoutSPK, dlcAccept.changeSPK, dlcOffer.feeRatePerVb);
1091
+ const funding = fundingInputs.reduce((total, input)=>{
991
1092
  return total + input.prevTx.outputs[input.prevTxVout].value.sats;
992
1093
  }, BigInt(0));
993
1094
  return funding >= acceptCollateralSatoshis + finalizer.acceptFees;
994
1095
  })(), 'fundingInputs for dlcAccept must be greater than acceptCollateralSatoshis plus acceptFees');
995
- const { dlcTransactions, messagesList } = await this.createDlcTxs(dlcOffer, dlcAccept);
996
- const { cetSignatures, refundSignature, } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, false);
997
- assert_1.default(dlcTransactions.type === messaging_1.MessageType.DlcTransactionsV0, 'DlcTransactions must be V0');
1096
+ const { dlcTransactions , messagesList } = await this.createDlcTxs(dlcOffer, dlcAccept);
1097
+ const { cetSignatures , refundSignature , } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, false);
1098
+ (0, _assert).default(dlcTransactions.type === _messaging.MessageType.DlcTransactionsV0, 'DlcTransactions must be V0');
998
1099
  const _dlcTransactions = dlcTransactions;
999
- const contractId = crypto_1.xor(_dlcTransactions.fundTx.txId.serialize(), dlcAccept.tempContractId);
1100
+ const contractId = (0, _crypto).xor(_dlcTransactions.fundTx.txId.serialize(), dlcAccept.tempContractId);
1000
1101
  _dlcTransactions.contractId = contractId;
1001
1102
  dlcAccept.cetSignatures = cetSignatures;
1002
1103
  dlcAccept.refundSignature = refundSignature;
1003
- dlcAccept.negotiationFields = new messaging_1.NegotiationFieldsV0();
1004
- return { dlcAccept, dlcTransactions: _dlcTransactions };
1104
+ dlcAccept.negotiationFields = new _messaging.NegotiationFieldsV0();
1105
+ return {
1106
+ dlcAccept,
1107
+ dlcTransactions: _dlcTransactions
1108
+ };
1005
1109
  }
1006
1110
  /**
1007
- * Sign Dlc Accept Message
1008
- * @param _dlcOffer Dlc Offer Message
1009
- * @param _dlcAccept Dlc Accept Message
1010
- * @returns {Promise<SignDlcAcceptResponse}
1011
- */
1012
- async signDlcAccept(_dlcOffer, _dlcAccept) {
1013
- const { dlcOffer, dlcAccept } = Utils_1.checkTypes({
1111
+ * Sign Dlc Accept Message
1112
+ * @param _dlcOffer Dlc Offer Message
1113
+ * @param _dlcAccept Dlc Accept Message
1114
+ * @returns {Promise<SignDlcAcceptResponse}
1115
+ */ async signDlcAccept(_dlcOffer, _dlcAccept) {
1116
+ const { dlcOffer , dlcAccept } = (0, _utils1).checkTypes({
1014
1117
  _dlcOffer,
1015
- _dlcAccept,
1118
+ _dlcAccept
1016
1119
  });
1017
1120
  dlcOffer.validate();
1018
1121
  dlcAccept.validate();
1019
- assert_1.default(Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) !== 0, 'DlcOffer and DlcAccept FundingPubKey cannot be the same');
1020
- const dlcSign = new messaging_1.DlcSignV0();
1021
- const { dlcTransactions, messagesList } = await this.createDlcTxs(dlcOffer, dlcAccept);
1122
+ (0, _assert).default(Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) !== 0, 'DlcOffer and DlcAccept FundingPubKey cannot be the same');
1123
+ const dlcSign = new _messaging.DlcSignV0();
1124
+ const { dlcTransactions , messagesList } = await this.createDlcTxs(dlcOffer, dlcAccept);
1022
1125
  await this.VerifyCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcSign, dlcTransactions, messagesList, true);
1023
- const { cetSignatures, refundSignature, } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, true);
1126
+ const { cetSignatures , refundSignature , } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, true);
1024
1127
  const fundingSignatures = await this.CreateFundingSigs(dlcOffer, dlcAccept, dlcTransactions, true);
1025
1128
  const dlcTxs = dlcTransactions;
1026
- const contractId = crypto_1.xor(dlcTxs.fundTx.txId.serialize(), dlcAccept.tempContractId);
1027
- assert_1.default(Buffer.compare(contractId, crypto_1.xor(dlcTxs.fundTx.txId.serialize(), dlcAccept.tempContractId)) === 0, 'contractId must be the xor of funding txid, fundingOutputIndex and the tempContractId');
1129
+ const contractId = (0, _crypto).xor(dlcTxs.fundTx.txId.serialize(), dlcAccept.tempContractId);
1130
+ (0, _assert).default(Buffer.compare(contractId, (0, _crypto).xor(dlcTxs.fundTx.txId.serialize(), dlcAccept.tempContractId)) === 0, 'contractId must be the xor of funding txid, fundingOutputIndex and the tempContractId');
1028
1131
  dlcTxs.contractId = contractId;
1029
1132
  dlcSign.contractId = contractId;
1030
1133
  dlcSign.cetSignatures = cetSignatures;
1031
1134
  dlcSign.refundSignature = refundSignature;
1032
1135
  dlcSign.fundingSignatures = fundingSignatures;
1033
- return { dlcSign, dlcTransactions: dlcTxs };
1136
+ return {
1137
+ dlcSign,
1138
+ dlcTransactions: dlcTxs
1139
+ };
1034
1140
  }
1035
1141
  /**
1036
- * Finalize Dlc Sign
1037
- * @param _dlcOffer Dlc Offer Message
1038
- * @param _dlcAccept Dlc Accept Message
1039
- * @param _dlcSign Dlc Sign Message
1040
- * @param _dlcTxs Dlc Transactions Message
1041
- * @returns {Promise<Tx>}
1042
- */
1043
- async finalizeDlcSign(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs) {
1044
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = Utils_1.checkTypes({
1142
+ * Finalize Dlc Sign
1143
+ * @param _dlcOffer Dlc Offer Message
1144
+ * @param _dlcAccept Dlc Accept Message
1145
+ * @param _dlcSign Dlc Sign Message
1146
+ * @param _dlcTxs Dlc Transactions Message
1147
+ * @returns {Promise<Tx>}
1148
+ */ async finalizeDlcSign(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs) {
1149
+ const { dlcOffer , dlcAccept , dlcSign , dlcTxs } = (0, _utils1).checkTypes({
1045
1150
  _dlcOffer,
1046
1151
  _dlcAccept,
1047
1152
  _dlcSign,
1048
- _dlcTxs,
1153
+ _dlcTxs
1049
1154
  });
1050
1155
  const payoutResponses = this.GetPayouts(dlcOffer);
1051
- const { messagesList } = this.FlattenPayouts(payoutResponses);
1156
+ const { messagesList } = this.FlattenPayouts(payoutResponses);
1052
1157
  await this.VerifyCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcSign, dlcTxs, messagesList, false);
1053
1158
  await this.VerifyFundingSigs(dlcOffer, dlcAccept, dlcSign, dlcTxs, false);
1054
1159
  const fundingSignatures = await this.CreateFundingSigs(dlcOffer, dlcAccept, dlcTxs, false);
@@ -1056,99 +1161,97 @@ Payout Group not found');
1056
1161
  return fundTx;
1057
1162
  }
1058
1163
  /**
1059
- * Execute DLC
1060
- * @param _dlcOffer Dlc Offer Message
1061
- * @param _dlcAccept Dlc Accept Message
1062
- * @param _dlcSign Dlc Sign Message
1063
- * @param _dlcTxs Dlc Transactions Message
1064
- * @param oracleAttestation Oracle Attestations TLV (V0)
1065
- * @param isOfferer Whether party is Dlc Offerer
1066
- * @returns {Promise<Tx>}
1067
- */
1068
- async execute(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, oracleAttestation, isOfferer) {
1069
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = Utils_1.checkTypes({
1164
+ * Execute DLC
1165
+ * @param _dlcOffer Dlc Offer Message
1166
+ * @param _dlcAccept Dlc Accept Message
1167
+ * @param _dlcSign Dlc Sign Message
1168
+ * @param _dlcTxs Dlc Transactions Message
1169
+ * @param oracleAttestation Oracle Attestations TLV (V0)
1170
+ * @param isOfferer Whether party is Dlc Offerer
1171
+ * @returns {Promise<Tx>}
1172
+ */ async execute(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, oracleAttestation, isOfferer) {
1173
+ const { dlcOffer , dlcAccept , dlcSign , dlcTxs } = (0, _utils1).checkTypes({
1070
1174
  _dlcOffer,
1071
1175
  _dlcAccept,
1072
1176
  _dlcSign,
1073
- _dlcTxs,
1177
+ _dlcTxs
1074
1178
  });
1075
- if (isOfferer === undefined)
1076
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1179
+ if (isOfferer === undefined) isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1077
1180
  this.ValidateEvent(dlcOffer, oracleAttestation);
1078
1181
  return this.FindAndSignCet(dlcOffer, dlcAccept, dlcSign, dlcTxs, oracleAttestation, isOfferer);
1079
1182
  }
1080
1183
  /**
1081
- * Refund DLC
1082
- * @param _dlcOffer Dlc Offer Message
1083
- * @param _dlcAccept Dlc Accept Message
1084
- * @param _dlcSign Dlc Sign Message
1085
- * @param _dlcTxs Dlc Transactions message
1086
- * @returns {Promise<Tx>}
1087
- */
1088
- async refund(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs) {
1089
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = Utils_1.checkTypes({
1184
+ * Refund DLC
1185
+ * @param _dlcOffer Dlc Offer Message
1186
+ * @param _dlcAccept Dlc Accept Message
1187
+ * @param _dlcSign Dlc Sign Message
1188
+ * @param _dlcTxs Dlc Transactions message
1189
+ * @returns {Promise<Tx>}
1190
+ */ async refund(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs) {
1191
+ const { dlcOffer , dlcAccept , dlcSign , dlcTxs } = (0, _utils1).checkTypes({
1090
1192
  _dlcOffer,
1091
1193
  _dlcAccept,
1092
1194
  _dlcSign,
1093
- _dlcTxs,
1195
+ _dlcTxs
1094
1196
  });
1095
- const signatures = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1096
- ? [
1097
- dlcSign.refundSignature.toString('hex'),
1098
- dlcAccept.refundSignature.toString('hex'),
1099
- ]
1100
- : [
1101
- dlcAccept.refundSignature.toString('hex'),
1102
- dlcSign.refundSignature.toString('hex'),
1103
- ];
1197
+ const signatures = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1 ? [
1198
+ dlcSign.refundSignature.toString('hex'),
1199
+ dlcAccept.refundSignature.toString('hex'),
1200
+ ] : [
1201
+ dlcAccept.refundSignature.toString('hex'),
1202
+ dlcSign.refundSignature.toString('hex'),
1203
+ ];
1104
1204
  const addSigsToRefundTxRequest = {
1105
1205
  refundTxHex: dlcTxs.refundTx.serialize().toString('hex'),
1106
1206
  signatures,
1107
1207
  fundTxId: dlcTxs.fundTx.txId.toString(),
1108
1208
  fundVout: dlcTxs.fundTxVout,
1109
1209
  localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
1110
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
1210
+ remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex')
1111
1211
  };
1112
1212
  const refundHex = (await this.AddSignaturesToRefundTx(addSigsToRefundTxRequest)).hex;
1113
- return bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(refundHex));
1213
+ return _bitcoin.Tx.decode(_bufio.StreamReader.fromHex(refundHex));
1114
1214
  }
1115
1215
  /**
1116
- * Goal of createDlcClose is for alice (the initiator) to
1117
- * 1. take dlcoffer, accept, and sign messages. Create a dlcClose message.
1118
- * 2. Build a close tx, sign.
1119
- * 3. return dlcClose message (no psbt)
1120
- */
1121
- /**
1122
- * Generate DlcClose messagetype for closing DLC with Mutual Consent
1123
- * @param _dlcOffer DlcOffer TLV (V0)
1124
- * @param _dlcAccept DlcAccept TLV (V0)
1125
- * @param _dlcTxs DlcTransactions TLV (V0)
1126
- * @param initiatorPayoutSatoshis Amount initiator expects as a payout
1127
- * @param isOfferer Whether offerer or not
1128
- * @param _inputs Optionally specified closing inputs
1129
- * @returns {Promise<DlcClose>}
1130
- */
1131
- async createDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, initiatorPayoutSatoshis, isOfferer, _inputs) {
1132
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
1216
+ * Goal of createDlcClose is for alice (the initiator) to
1217
+ * 1. take dlcoffer, accept, and sign messages. Create a dlcClose message.
1218
+ * 2. Build a close tx, sign.
1219
+ * 3. return dlcClose message (no psbt)
1220
+ */ /**
1221
+ * Generate DlcClose messagetype for closing DLC with Mutual Consent
1222
+ * @param _dlcOffer DlcOffer TLV (V0)
1223
+ * @param _dlcAccept DlcAccept TLV (V0)
1224
+ * @param _dlcTxs DlcTransactions TLV (V0)
1225
+ * @param initiatorPayoutSatoshis Amount initiator expects as a payout
1226
+ * @param isOfferer Whether offerer or not
1227
+ * @param _inputs Optionally specified closing inputs
1228
+ * @returns {Promise<DlcClose>}
1229
+ */ async createDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, initiatorPayoutSatoshis, isOfferer, _inputs) {
1230
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
1133
1231
  _dlcOffer,
1134
1232
  _dlcAccept,
1135
- _dlcTxs,
1233
+ _dlcTxs
1136
1234
  });
1137
- if (isOfferer === undefined)
1138
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1235
+ if (isOfferer === undefined) isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1139
1236
  const network = await this.getConnectedNetwork();
1140
- const psbt = new bitcoinjs_lib_1.Psbt({ network });
1141
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1142
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
1143
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
1144
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
1237
+ const psbt = new _bitcoinjsLib.Psbt({
1238
+ network
1239
+ });
1240
+ const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1 ? [
1241
+ dlcOffer.fundingPubKey,
1242
+ dlcAccept.fundingPubKey
1243
+ ] : [
1244
+ dlcAccept.fundingPubKey,
1245
+ dlcOffer.fundingPubKey
1246
+ ];
1247
+ const p2ms = _bitcoinjsLib.payments.p2ms({
1145
1248
  m: 2,
1146
1249
  pubkeys: fundingPubKeys,
1147
- network,
1250
+ network
1148
1251
  });
1149
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
1252
+ const paymentVariant1 = _bitcoinjsLib.payments.p2wsh({
1150
1253
  redeem: p2ms,
1151
- network,
1254
+ network
1152
1255
  });
1153
1256
  // Initiate and build PSBT
1154
1257
  let inputs = _inputs;
@@ -1156,18 +1259,18 @@ Payout Group not found');
1156
1259
  const tempInputs = await this.GetInputsForAmount(BigInt(20000), dlcOffer.feeRatePerVb, _inputs);
1157
1260
  _inputs = tempInputs;
1158
1261
  }
1159
- inputs = _inputs.map((input) => {
1262
+ inputs = _inputs.map((input)=>{
1160
1263
  return {
1161
1264
  ...input,
1162
- inputSerialId: input.inputSerialId || Utils_1.generateSerialId(),
1163
- toUtxo: input.toUtxo,
1265
+ inputSerialId: input.inputSerialId || (0, _utils1).generateSerialId(),
1266
+ toUtxo: input.toUtxo
1164
1267
  };
1165
1268
  });
1166
- const pubkeys = await Promise.all(inputs.map(async (input) => {
1269
+ const pubkeys = await Promise.all(inputs.map(async (input)=>{
1167
1270
  const address = await this.getMethod('getWalletAddress')(input.address);
1168
1271
  return Buffer.from(address.publicKey, 'hex');
1169
1272
  }));
1170
- const fundingInputSerialId = Utils_1.generateSerialId();
1273
+ const fundingInputSerialId = (0, _utils1).generateSerialId();
1171
1274
  // Make temporary array to hold all inputs and then sort them
1172
1275
  // this method can be improved later
1173
1276
  const psbtInputs = [];
@@ -1176,69 +1279,67 @@ Payout Group not found');
1176
1279
  index: dlcTxs.fundTxVout,
1177
1280
  sequence: 0,
1178
1281
  witnessUtxo: {
1179
- script: paymentVariant.output,
1180
- value: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
1282
+ script: paymentVariant1.output,
1283
+ value: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats)
1181
1284
  },
1182
- witnessScript: paymentVariant.redeem.output,
1285
+ witnessScript: paymentVariant1.redeem.output,
1183
1286
  inputSerialId: fundingInputSerialId,
1184
- derivationPath: null,
1287
+ derivationPath: null
1185
1288
  });
1186
1289
  // add all dlc close inputs
1187
- inputs.forEach((input, i) => {
1188
- const paymentVariant = bitcoinjs_lib_1.payments.p2wpkh({ pubkey: pubkeys[i], network });
1290
+ inputs.forEach((input, i)=>{
1291
+ const paymentVariant = _bitcoinjsLib.payments.p2wpkh({
1292
+ pubkey: pubkeys[i],
1293
+ network
1294
+ });
1189
1295
  psbtInputs.push({
1190
1296
  hash: input.txid,
1191
1297
  index: input.vout,
1192
1298
  sequence: 0,
1193
1299
  witnessUtxo: {
1194
1300
  script: paymentVariant.output,
1195
- value: input.value,
1301
+ value: input.value
1196
1302
  },
1197
1303
  inputSerialId: input.inputSerialId,
1198
- derivationPath: input.derivationPath,
1304
+ derivationPath: input.derivationPath
1199
1305
  });
1200
1306
  });
1201
1307
  // sort all inputs in ascending order by serial ID
1202
1308
  // The only reason we are doing this is for privacy. If the fundingInput is
1203
1309
  // always first, it is very obvious. Hence, a serialId is randomly generated
1204
1310
  // and the inputs are sorted by that instead.
1205
- const sortedPsbtInputs = psbtInputs.sort((a, b) => Number(a.inputSerialId - b.inputSerialId));
1311
+ const sortedPsbtInputs = psbtInputs.sort((a, b)=>Number(a.inputSerialId - b.inputSerialId)
1312
+ );
1206
1313
  // Get index of fundingInput
1207
- const fundingInputIndex = sortedPsbtInputs.findIndex((input) => input.inputSerialId === fundingInputSerialId);
1314
+ const fundingInputIndex = sortedPsbtInputs.findIndex((input)=>input.inputSerialId === fundingInputSerialId
1315
+ );
1208
1316
  // add to psbt
1209
- sortedPsbtInputs.forEach((input, i) => psbt.addInput(input));
1210
- const fundingInputs = await Promise.all(inputs.map(async (input) => {
1317
+ sortedPsbtInputs.forEach((input, i)=>psbt.addInput(input)
1318
+ );
1319
+ const fundingInputs = await Promise.all(inputs.map(async (input)=>{
1211
1320
  return this.inputToFundingInput(input);
1212
1321
  }));
1213
- const finalizer = new core_1.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
1214
- const closeInputAmount = BigInt(inputs.reduce((acc, val) => acc + val.value, 0));
1215
- const offerPayoutValue = isOfferer
1216
- ? closeInputAmount +
1217
- initiatorPayoutSatoshis -
1218
- finalizer.offerInitiatorFees
1219
- : dlcOffer.contractInfo.totalCollateral - initiatorPayoutSatoshis;
1220
- const acceptPayoutValue = isOfferer
1221
- ? dlcOffer.contractInfo.totalCollateral - initiatorPayoutSatoshis
1222
- : closeInputAmount +
1223
- initiatorPayoutSatoshis -
1224
- finalizer.offerInitiatorFees;
1322
+ const finalizer = new _core.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
1323
+ const closeInputAmount = BigInt(inputs.reduce((acc, val)=>acc + val.value
1324
+ , 0));
1325
+ const offerPayoutValue = isOfferer ? closeInputAmount + initiatorPayoutSatoshis - finalizer.offerInitiatorFees : dlcOffer.contractInfo.totalCollateral - initiatorPayoutSatoshis;
1326
+ const acceptPayoutValue = isOfferer ? dlcOffer.contractInfo.totalCollateral - initiatorPayoutSatoshis : closeInputAmount + initiatorPayoutSatoshis - finalizer.offerInitiatorFees;
1225
1327
  const offerFirst = dlcOffer.payoutSerialId < dlcAccept.payoutSerialId;
1226
1328
  psbt.addOutput({
1227
1329
  value: Number(offerFirst ? offerPayoutValue : acceptPayoutValue),
1228
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcOffer.payoutSPK : dlcAccept.payoutSPK, network),
1330
+ address: _bitcoinjsLib.address.fromOutputScript(offerFirst ? dlcOffer.payoutSPK : dlcAccept.payoutSPK, network)
1229
1331
  });
1230
1332
  psbt.addOutput({
1231
1333
  value: Number(offerFirst ? acceptPayoutValue : offerPayoutValue),
1232
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcAccept.payoutSPK : dlcOffer.payoutSPK, network),
1334
+ address: _bitcoinjsLib.address.fromOutputScript(offerFirst ? dlcAccept.payoutSPK : dlcOffer.payoutSPK, network)
1233
1335
  });
1234
1336
  // Generate keypair to sign inputs
1235
1337
  const fundPrivateKeyPair = await this.GetFundKeyPair(dlcOffer, dlcAccept, isOfferer);
1236
1338
  // Sign dlc fundinginput
1237
1339
  psbt.signInput(fundingInputIndex, fundPrivateKeyPair);
1238
1340
  // Sign dlcclose inputs
1239
- await Promise.all(sortedPsbtInputs.map(async (input, i) => {
1240
- if (i === fundingInputIndex)
1241
- return;
1341
+ await Promise.all(sortedPsbtInputs.map(async (input, i)=>{
1342
+ if (i === fundingInputIndex) return;
1242
1343
  // derive keypair
1243
1344
  const keyPair = await this.getMethod('keyPair')(input.derivationPath);
1244
1345
  psbt.signInput(i, keyPair);
@@ -1246,24 +1347,27 @@ Payout Group not found');
1246
1347
  // Validate signatures
1247
1348
  psbt.validateSignaturesOfAllInputs();
1248
1349
  // Extract close signature from psbt and decode it to only extract r and s values
1249
- const closeSignature = await bitcoinjs_lib_1.script.signature.decode(psbt.data.inputs[fundingInputIndex].partialSig[0].signature).signature;
1350
+ const closeSignature = await _bitcoinjsLib.script.signature.decode(psbt.data.inputs[fundingInputIndex].partialSig[0].signature).signature;
1250
1351
  // Extract funding signatures from psbt
1251
- const inputSigs = psbt.data.inputs
1252
- .filter((input) => input !== fundingInputIndex)
1253
- .map((input) => input.partialSig[0]);
1352
+ const inputSigs = psbt.data.inputs.filter((input)=>input !== fundingInputIndex
1353
+ ).map((input)=>input.partialSig[0]
1354
+ );
1254
1355
  // create fundingSignatures
1255
1356
  const witnessElements = [];
1256
- for (let i = 0; i < inputSigs.length; i++) {
1257
- const sigWitness = new messaging_1.ScriptWitnessV0();
1258
- sigWitness.witness = inputSigs[i].signature;
1259
- const pubKeyWitness = new messaging_1.ScriptWitnessV0();
1260
- pubKeyWitness.witness = inputSigs[i].pubkey;
1261
- witnessElements.push([sigWitness, pubKeyWitness]);
1357
+ for(let i1 = 0; i1 < inputSigs.length; i1++){
1358
+ const sigWitness = new _messaging.ScriptWitnessV0();
1359
+ sigWitness.witness = inputSigs[i1].signature;
1360
+ const pubKeyWitness = new _messaging.ScriptWitnessV0();
1361
+ pubKeyWitness.witness = inputSigs[i1].pubkey;
1362
+ witnessElements.push([
1363
+ sigWitness,
1364
+ pubKeyWitness
1365
+ ]);
1262
1366
  }
1263
- const fundingSignatures = new messaging_1.FundingSignaturesV0();
1367
+ const fundingSignatures = new _messaging.FundingSignaturesV0();
1264
1368
  fundingSignatures.witnessElements = witnessElements;
1265
1369
  // Create DlcClose
1266
- const dlcClose = new messaging_1.DlcCloseV0();
1370
+ const dlcClose = new _messaging.DlcCloseV0();
1267
1371
  dlcClose.contractId = dlcTxs.contractId;
1268
1372
  dlcClose.offerPayoutSatoshis = BigInt(psbt.txOutputs[offerFirst ? 0 : 1].value); // You give collateral back to users
1269
1373
  dlcClose.acceptPayoutSatoshis = BigInt(psbt.txOutputs[offerFirst ? 1 : 0].value); // give collateral back to users
@@ -1275,28 +1379,25 @@ Payout Group not found');
1275
1379
  return dlcClose;
1276
1380
  }
1277
1381
  /**
1278
- * Generate multiple DlcClose messagetypes for closing DLC with Mutual Consent
1279
- * @param _dlcOffer DlcOffer TLV (V0)
1280
- * @param _dlcAccept DlcAccept TLV (V0)
1281
- * @param _dlcTxs DlcTransactions TLV (V0)
1282
- * @param initiatorPayouts Array of amounts initiator expects as payouts
1283
- * @param isOfferer Whether offerer or not
1284
- * @param _inputs Optionally specified closing inputs
1285
- * @returns {Promise<DlcClose[]>}
1286
- */
1287
- async createBatchDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, initiatorPayouts, isOfferer, _inputs) {
1288
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
1382
+ * Generate multiple DlcClose messagetypes for closing DLC with Mutual Consent
1383
+ * @param _dlcOffer DlcOffer TLV (V0)
1384
+ * @param _dlcAccept DlcAccept TLV (V0)
1385
+ * @param _dlcTxs DlcTransactions TLV (V0)
1386
+ * @param initiatorPayouts Array of amounts initiator expects as payouts
1387
+ * @param isOfferer Whether offerer or not
1388
+ * @param _inputs Optionally specified closing inputs
1389
+ * @returns {Promise<DlcClose[]>}
1390
+ */ async createBatchDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, initiatorPayouts, isOfferer, _inputs) {
1391
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
1289
1392
  _dlcOffer,
1290
1393
  _dlcAccept,
1291
- _dlcTxs,
1394
+ _dlcTxs
1292
1395
  });
1293
- if (isOfferer === undefined)
1294
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1295
- if (_inputs && _inputs.length > 0)
1296
- throw Error('funding inputs not supported on BatchDlcClose'); // TODO support multiple funding inputs
1297
- const fundingInputSerialId = Utils_1.generateSerialId();
1396
+ if (isOfferer === undefined) isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1397
+ if (_inputs && _inputs.length > 0) throw Error('funding inputs not supported on BatchDlcClose'); // TODO support multiple funding inputs
1398
+ const fundingInputSerialId = (0, _utils1).generateSerialId();
1298
1399
  const fundingInputs = []; // TODO: support multiple funding inputs
1299
- const finalizer = new core_1.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
1400
+ const finalizer = new _core.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
1300
1401
  // Generate keypair to sign inputs
1301
1402
  const fundPrivateKeyPair = await this.GetFundKeyPair(dlcOffer, dlcAccept, isOfferer);
1302
1403
  const closeInputAmount = BigInt(0); // TODO support multiple funding inputs
@@ -1305,22 +1406,14 @@ Payout Group not found');
1305
1406
  const sigHashes = await this.CreateSignatureHashes(dlcOffer, dlcAccept, dlcTxs, rawCloseTxs);
1306
1407
  const signatures = await this.CalculateEcSignatureHashes(sigHashes, privKey);
1307
1408
  const dlcCloses = [];
1308
- signatures.forEach((sig, i) => {
1409
+ signatures.forEach((sig, i)=>{
1309
1410
  const payout = initiatorPayouts[i];
1310
- const payoutMinusOfferFees = finalizer.offerInitiatorFees > payout
1311
- ? BigInt(0)
1312
- : payout - finalizer.offerInitiatorFees;
1313
- const collateralMinusPayout = payout > dlcOffer.contractInfo.totalCollateral
1314
- ? BigInt(0)
1315
- : dlcOffer.contractInfo.totalCollateral - payout;
1316
- const offerPayoutValue = isOfferer
1317
- ? closeInputAmount + payoutMinusOfferFees
1318
- : collateralMinusPayout;
1319
- const acceptPayoutValue = isOfferer
1320
- ? collateralMinusPayout
1321
- : closeInputAmount + payoutMinusOfferFees;
1322
- const fundingSignatures = new messaging_1.FundingSignaturesV0();
1323
- const dlcClose = new messaging_1.DlcCloseV0();
1411
+ const payoutMinusOfferFees = finalizer.offerInitiatorFees > payout ? BigInt(0) : payout - finalizer.offerInitiatorFees;
1412
+ const collateralMinusPayout = payout > dlcOffer.contractInfo.totalCollateral ? BigInt(0) : dlcOffer.contractInfo.totalCollateral - payout;
1413
+ const offerPayoutValue = isOfferer ? closeInputAmount + payoutMinusOfferFees : collateralMinusPayout;
1414
+ const acceptPayoutValue = isOfferer ? collateralMinusPayout : closeInputAmount + payoutMinusOfferFees;
1415
+ const fundingSignatures = new _messaging.FundingSignaturesV0();
1416
+ const dlcClose = new _messaging.DlcCloseV0();
1324
1417
  dlcClose.contractId = dlcTxs.contractId;
1325
1418
  dlcClose.offerPayoutSatoshis = offerPayoutValue;
1326
1419
  dlcClose.acceptPayoutSatoshis = acceptPayoutValue;
@@ -1333,71 +1426,77 @@ Payout Group not found');
1333
1426
  return dlcCloses;
1334
1427
  }
1335
1428
  async verifyBatchDlcCloseUsingMetadata(dlcCloseMetadata, _dlcCloses, isOfferer) {
1336
- const { dlcOffer, dlcAccept, dlcTxs } = dlcCloseMetadata.toDlcMessages();
1429
+ const { dlcOffer , dlcAccept , dlcTxs } = dlcCloseMetadata.toDlcMessages();
1337
1430
  await this.verifyBatchDlcClose(dlcOffer, dlcAccept, dlcTxs, _dlcCloses, isOfferer);
1338
1431
  }
1339
1432
  /**
1340
- * Verify multiple DlcClose messagetypes for closing DLC with Mutual Consent
1341
- * @param _dlcOffer DlcOffer TLV (V0)
1342
- * @param _dlcAccept DlcAccept TLV (V0)
1343
- * @param _dlcTxs DlcTransactions TLV (V0)
1344
- * @param _dlcCloses DlcClose[] TLV (V0)
1345
- * @param isOfferer Whether offerer or not
1346
- * @returns {Promise<void>}
1347
- */
1348
- async verifyBatchDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, _dlcCloses, isOfferer) {
1349
- const { dlcOffer, dlcAccept, dlcTxs } = Utils_1.checkTypes({
1433
+ * Verify multiple DlcClose messagetypes for closing DLC with Mutual Consent
1434
+ * @param _dlcOffer DlcOffer TLV (V0)
1435
+ * @param _dlcAccept DlcAccept TLV (V0)
1436
+ * @param _dlcTxs DlcTransactions TLV (V0)
1437
+ * @param _dlcCloses DlcClose[] TLV (V0)
1438
+ * @param isOfferer Whether offerer or not
1439
+ * @returns {Promise<void>}
1440
+ */ async verifyBatchDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, _dlcCloses, isOfferer) {
1441
+ const { dlcOffer , dlcAccept , dlcTxs } = (0, _utils1).checkTypes({
1350
1442
  _dlcOffer,
1351
1443
  _dlcAccept,
1352
- _dlcTxs,
1444
+ _dlcTxs
1353
1445
  });
1354
- const dlcCloses = _dlcCloses.map((_dlcClose) => Utils_1.checkTypes({ _dlcClose }).dlcClose);
1355
- if (isOfferer === undefined)
1356
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1357
- assert_1.default(dlcCloses.every((dlcClose) => dlcClose.fundingInputs.length === 0), 'funding inputs not supported on verify BatchDlcClose'); // TODO support multiple funding inputs
1446
+ const dlcCloses = _dlcCloses.map((_dlcClose)=>(0, _utils1).checkTypes({
1447
+ _dlcClose
1448
+ }).dlcClose
1449
+ );
1450
+ if (isOfferer === undefined) isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1451
+ (0, _assert).default(dlcCloses.every((dlcClose)=>dlcClose.fundingInputs.length === 0
1452
+ ), 'funding inputs not supported on verify BatchDlcClose'); // TODO support multiple funding inputs
1358
1453
  const closeInputAmount = BigInt(0); // TODO support multiple funding inputs
1359
1454
  const rawCloseTxs = await this.CreateCloseRawTxs(dlcOffer, dlcAccept, dlcTxs, closeInputAmount, isOfferer, dlcCloses);
1360
1455
  const areSigsValid = await this.VerifySignatures(dlcOffer, dlcAccept, dlcTxs, dlcCloses, rawCloseTxs, isOfferer);
1361
- assert_1.default(areSigsValid, 'Signatures invalid in Verify Batch DlcClose');
1456
+ (0, _assert).default(areSigsValid, 'Signatures invalid in Verify Batch DlcClose');
1362
1457
  }
1363
1458
  /**
1364
- * Goal of finalize Dlc Close is for bob to
1365
- * 1. take the dlcClose created by alice using createDlcClose,
1366
- * 2. Build a psbt using Alice's dlcClose message
1367
- * 3. Sign psbt with bob's privkey
1368
- * 4. return a tx ready to be broadcast
1369
- */
1370
- /**
1371
- * Finalize Dlc Close
1372
- * @param _dlcOffer Dlc Offer Message
1373
- * @param _dlcAccept Dlc Accept Message
1374
- * @param _dlcClose Dlc Close Message
1375
- * @param _dlcTxs Dlc Transactions Message
1376
- * @returns {Promise<Tx>}
1377
- */
1378
- async finalizeDlcClose(_dlcOffer, _dlcAccept, _dlcClose, _dlcTxs) {
1379
- const { dlcOffer, dlcAccept, dlcClose, dlcTxs } = Utils_1.checkTypes({
1459
+ * Goal of finalize Dlc Close is for bob to
1460
+ * 1. take the dlcClose created by alice using createDlcClose,
1461
+ * 2. Build a psbt using Alice's dlcClose message
1462
+ * 3. Sign psbt with bob's privkey
1463
+ * 4. return a tx ready to be broadcast
1464
+ */ /**
1465
+ * Finalize Dlc Close
1466
+ * @param _dlcOffer Dlc Offer Message
1467
+ * @param _dlcAccept Dlc Accept Message
1468
+ * @param _dlcClose Dlc Close Message
1469
+ * @param _dlcTxs Dlc Transactions Message
1470
+ * @returns {Promise<Tx>}
1471
+ */ async finalizeDlcClose(_dlcOffer, _dlcAccept, _dlcClose, _dlcTxs) {
1472
+ const { dlcOffer , dlcAccept , dlcClose , dlcTxs } = (0, _utils1).checkTypes({
1380
1473
  _dlcOffer,
1381
1474
  _dlcAccept,
1382
1475
  _dlcClose,
1383
- _dlcTxs,
1476
+ _dlcTxs
1384
1477
  });
1385
1478
  dlcOffer.validate();
1386
1479
  dlcAccept.validate();
1387
1480
  dlcClose.validate();
1388
1481
  const network = await this.getConnectedNetwork();
1389
- const psbt = new bitcoinjs_lib_1.Psbt({ network });
1390
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1391
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
1392
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
1393
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
1482
+ const psbt = new _bitcoinjsLib.Psbt({
1483
+ network
1484
+ });
1485
+ const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1 ? [
1486
+ dlcOffer.fundingPubKey,
1487
+ dlcAccept.fundingPubKey
1488
+ ] : [
1489
+ dlcAccept.fundingPubKey,
1490
+ dlcOffer.fundingPubKey
1491
+ ];
1492
+ const p2ms = _bitcoinjsLib.payments.p2ms({
1394
1493
  m: 2,
1395
1494
  pubkeys: fundingPubKeys,
1396
- network,
1495
+ network
1397
1496
  });
1398
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
1497
+ const paymentVariant = _bitcoinjsLib.payments.p2wsh({
1399
1498
  redeem: p2ms,
1400
- network,
1499
+ network
1401
1500
  });
1402
1501
  // Make temporary array to hold all inputs and then sort them
1403
1502
  // this method can be improved later
@@ -1408,48 +1507,45 @@ Payout Group not found');
1408
1507
  sequence: 0,
1409
1508
  witnessUtxo: {
1410
1509
  script: paymentVariant.output,
1411
- value: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
1510
+ value: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats)
1412
1511
  },
1413
1512
  witnessScript: paymentVariant.redeem.output,
1414
- inputSerialId: dlcClose.fundInputSerialId,
1513
+ inputSerialId: dlcClose.fundInputSerialId
1415
1514
  });
1416
1515
  // add all dlc close inputs
1417
- dlcClose.fundingInputs.forEach((input, i) => {
1516
+ dlcClose.fundingInputs.forEach((input, i)=>{
1418
1517
  psbtInputs.push({
1419
1518
  hash: input.prevTx.txId.serialize(),
1420
1519
  index: input.prevTxVout,
1421
1520
  sequence: 0,
1422
1521
  witnessUtxo: {
1423
- script: input.prevTx.outputs[input.prevTxVout].scriptPubKey
1424
- .serialize()
1425
- .slice(1),
1426
- value: Number(input.prevTx.outputs[input.prevTxVout].value.sats),
1522
+ script: input.prevTx.outputs[input.prevTxVout].scriptPubKey.serialize().slice(1),
1523
+ value: Number(input.prevTx.outputs[input.prevTxVout].value.sats)
1427
1524
  },
1428
- inputSerialId: input.inputSerialId,
1525
+ inputSerialId: input.inputSerialId
1429
1526
  });
1430
1527
  });
1431
1528
  // sort all inputs in ascending order by serial ID
1432
1529
  // The only reason we are doing this is for privacy. If the fundingInput is
1433
1530
  // always first, it is very obvious. Hence, a serialId is randomly generated
1434
1531
  // and the inputs are sorted by that instead.
1435
- const sortedPsbtInputs = psbtInputs.sort((a, b) => Number(a.inputSerialId - b.inputSerialId));
1532
+ const sortedPsbtInputs = psbtInputs.sort((a, b)=>Number(a.inputSerialId - b.inputSerialId)
1533
+ );
1436
1534
  // Get index of fundingInput
1437
- const fundingInputIndex = sortedPsbtInputs.findIndex((input) => input.inputSerialId === dlcClose.fundInputSerialId);
1535
+ const fundingInputIndex = sortedPsbtInputs.findIndex((input)=>input.inputSerialId === dlcClose.fundInputSerialId
1536
+ );
1438
1537
  const offerFirst = dlcOffer.payoutSerialId < dlcAccept.payoutSerialId;
1439
1538
  psbt.addOutput({
1440
- value: Number(offerFirst
1441
- ? dlcClose.offerPayoutSatoshis
1442
- : dlcClose.acceptPayoutSatoshis),
1443
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcOffer.payoutSPK : dlcAccept.payoutSPK, network),
1539
+ value: Number(offerFirst ? dlcClose.offerPayoutSatoshis : dlcClose.acceptPayoutSatoshis),
1540
+ address: _bitcoinjsLib.address.fromOutputScript(offerFirst ? dlcOffer.payoutSPK : dlcAccept.payoutSPK, network)
1444
1541
  });
1445
1542
  psbt.addOutput({
1446
- value: Number(offerFirst
1447
- ? dlcClose.acceptPayoutSatoshis
1448
- : dlcClose.offerPayoutSatoshis),
1449
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcAccept.payoutSPK : dlcOffer.payoutSPK, network),
1543
+ value: Number(offerFirst ? dlcClose.acceptPayoutSatoshis : dlcClose.offerPayoutSatoshis),
1544
+ address: _bitcoinjsLib.address.fromOutputScript(offerFirst ? dlcAccept.payoutSPK : dlcOffer.payoutSPK, network)
1450
1545
  });
1451
1546
  // add to psbt
1452
- sortedPsbtInputs.forEach((input, i) => psbt.addInput(input));
1547
+ sortedPsbtInputs.forEach((input, i)=>psbt.addInput(input)
1548
+ );
1453
1549
  const offerer = await this.isOfferer(dlcOffer, dlcAccept);
1454
1550
  // Generate keypair to sign inputs
1455
1551
  const fundPrivateKeyPair = await this.GetFundKeyPair(dlcOffer, dlcAccept, offerer);
@@ -1458,23 +1554,26 @@ Payout Group not found');
1458
1554
  const partialSig = [
1459
1555
  {
1460
1556
  pubkey: offerer ? dlcAccept.fundingPubKey : dlcOffer.fundingPubKey,
1461
- signature: await bitcoinjs_lib_1.script.signature.encode(dlcClose.closeSignature, 1),
1462
- },
1557
+ signature: await _bitcoinjsLib.script.signature.encode(dlcClose.closeSignature, 1)
1558
+ },
1463
1559
  ];
1464
- psbt.updateInput(fundingInputIndex, { partialSig });
1465
- for (let i = 0; i < psbt.data.inputs.length; ++i) {
1466
- if (i === fundingInputIndex)
1467
- continue;
1468
- if (!psbt.data.inputs[i].partialSig)
1469
- psbt.data.inputs[i].partialSig = [];
1470
- const witnessI = dlcClose.fundingSignatures.witnessElements.findIndex((el) => Buffer.compare(bitcoin_1.Script.p2wpkhLock(crypto_1.hash160(el[1].witness)).serialize().slice(1), psbt.data.inputs[i].witnessUtxo.script) === 0);
1560
+ psbt.updateInput(fundingInputIndex, {
1561
+ partialSig
1562
+ });
1563
+ for(let i = 0; i < psbt.data.inputs.length; ++i){
1564
+ if (i === fundingInputIndex) continue;
1565
+ if (!psbt.data.inputs[i].partialSig) psbt.data.inputs[i].partialSig = [];
1566
+ const witnessI = dlcClose.fundingSignatures.witnessElements.findIndex((el)=>Buffer.compare(_bitcoin.Script.p2wpkhLock((0, _crypto).hash160(el[1].witness)).serialize().slice(1), psbt.data.inputs[i].witnessUtxo.script) === 0
1567
+ );
1471
1568
  const partialSig = [
1472
1569
  {
1473
1570
  pubkey: dlcClose.fundingSignatures.witnessElements[witnessI][1].witness,
1474
- signature: dlcClose.fundingSignatures.witnessElements[witnessI][0].witness,
1475
- },
1571
+ signature: dlcClose.fundingSignatures.witnessElements[witnessI][0].witness
1572
+ },
1476
1573
  ];
1477
- psbt.updateInput(i, { partialSig });
1574
+ psbt.updateInput(i, {
1575
+ partialSig
1576
+ });
1478
1577
  }
1479
1578
  psbt.validateSignaturesOfAllInputs();
1480
1579
  psbt.finalizeAllInputs();
@@ -1545,16 +1644,18 @@ Payout Group not found');
1545
1644
  return this._cfdDlcJs.VerifyRefundTxSignature(jsonObject);
1546
1645
  }
1547
1646
  async fundingInputToInput(_input, findDerivationPath = true) {
1548
- assert_1.default(_input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0');
1647
+ (0, _assert).default(_input.type === _messaging.MessageType.FundingInputV0, 'FundingInput must be V0');
1549
1648
  const network = await this.getConnectedNetwork();
1550
1649
  const input = _input;
1551
1650
  const prevTx = input.prevTx;
1552
1651
  const prevTxOut = prevTx.outputs[input.prevTxVout];
1553
1652
  const scriptPubKey = prevTxOut.scriptPubKey.serialize().slice(1);
1554
- const _address = bitcoinjs_lib_1.address.fromOutputScript(scriptPubKey, network);
1653
+ const _address = _bitcoinjsLib.address.fromOutputScript(scriptPubKey, network);
1555
1654
  let derivationPath;
1556
1655
  if (findDerivationPath) {
1557
- const inputAddress = await this.client.financewallet.quickFindAddress([_address]);
1656
+ const inputAddress = await this.client.financewallet.quickFindAddress([
1657
+ _address
1658
+ ]);
1558
1659
  if (inputAddress) {
1559
1660
  derivationPath = inputAddress.derivationPath;
1560
1661
  }
@@ -1567,48 +1668,43 @@ Payout Group not found');
1567
1668
  value: Number(prevTxOut.value.sats),
1568
1669
  derivationPath,
1569
1670
  maxWitnessLength: input.maxWitnessLen,
1570
- redeemScript: input.redeemScript
1571
- ? input.redeemScript.toString('hex')
1572
- : '',
1671
+ redeemScript: input.redeemScript ? input.redeemScript.toString('hex') : '',
1573
1672
  scriptPubKey: scriptPubKey.toString('hex'),
1574
1673
  inputSerialId: input.inputSerialId,
1575
- toUtxo: types_1.Input.prototype.toUtxo,
1674
+ toUtxo: _types.Input.prototype.toUtxo
1576
1675
  };
1577
1676
  }
1578
1677
  async inputToFundingInput(input) {
1579
- const fundingInput = new messaging_1.FundingInputV0();
1678
+ const fundingInput = new _messaging.FundingInputV0();
1580
1679
  fundingInput.prevTxVout = input.vout;
1581
1680
  let txRaw = '';
1582
1681
  try {
1583
1682
  txRaw = await this.getMethod('getRawTransactionByHash')(input.txid);
1584
- }
1585
- catch (e) {
1683
+ } catch (e) {
1586
1684
  try {
1587
- txRaw = (await this.getMethod('jsonrpc')('gettransaction', input.txid))
1588
- .hex;
1589
- }
1590
- catch (e) {
1685
+ txRaw = (await this.getMethod('jsonrpc')('gettransaction', input.txid)).hex;
1686
+ } catch (e) {
1591
1687
  throw Error(`Cannot find tx ${input.txid} in inputToFundingInput using getrawtransactionbyhash or gettransaction`);
1592
1688
  }
1593
1689
  }
1594
- const tx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(txRaw));
1690
+ const tx = _bitcoin.Tx.decode(_bufio.StreamReader.fromHex(txRaw));
1595
1691
  fundingInput.prevTx = tx;
1596
- fundingInput.sequence = bitcoin_1.Sequence.default();
1597
- fundingInput.maxWitnessLen = input.maxWitnessLength
1598
- ? input.maxWitnessLength
1599
- : 108;
1600
- fundingInput.redeemScript = input.redeemScript
1601
- ? Buffer.from(input.redeemScript, 'hex')
1602
- : Buffer.from('', 'hex');
1603
- fundingInput.inputSerialId = input.inputSerialId
1604
- ? input.inputSerialId
1605
- : Utils_1.generateSerialId();
1692
+ fundingInput.sequence = _bitcoin.Sequence.default();
1693
+ fundingInput.maxWitnessLen = input.maxWitnessLength ? input.maxWitnessLength : 108;
1694
+ fundingInput.redeemScript = input.redeemScript ? Buffer.from(input.redeemScript, 'hex') : Buffer.from('', 'hex');
1695
+ fundingInput.inputSerialId = input.inputSerialId ? input.inputSerialId : (0, _utils1).generateSerialId();
1606
1696
  return fundingInput;
1607
1697
  }
1608
1698
  async getConnectedNetwork() {
1609
1699
  return this._network;
1610
1700
  }
1611
- }
1612
- exports.default = BitcoinDlcProvider;
1701
+ constructor(network, cfdDlcJs){
1702
+ super();
1703
+ this._network = network;
1704
+ this._cfdDlcJs = cfdDlcJs;
1705
+ }
1706
+ };
1613
1707
  const BurnAddress = 'bcrt1qxcjufgh2jarkp2qkx68azh08w9v5gah8u6es8s';
1614
- //# sourceMappingURL=BitcoinDlcProvider.js.map
1708
+ exports.default = BitcoinDlcProvider;
1709
+
1710
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9CaXRjb2luRGxjUHJvdmlkZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY2hhaW5IYXNoRnJvbU5ldHdvcmsgfSBmcm9tICdAYXRvbWljZmluYW5jZS9iaXRjb2luLW5ldHdvcmtzJztcbmltcG9ydCBQcm92aWRlciBmcm9tICdAYXRvbWljZmluYW5jZS9wcm92aWRlcic7XG5pbXBvcnQge1xuICBBZGFwdG9yUGFpcixcbiAgQWRkU2lnbmF0dXJlc1RvUmVmdW5kVHhSZXF1ZXN0LFxuICBBZGRTaWduYXR1cmVzVG9SZWZ1bmRUeFJlc3BvbnNlLFxuICBBZGRTaWduYXR1cmVUb0Z1bmRUcmFuc2FjdGlvblJlcXVlc3QsXG4gIEFkZFNpZ25hdHVyZVRvRnVuZFRyYW5zYWN0aW9uUmVzcG9uc2UsXG4gIENhbGN1bGF0ZUVjU2lnbmF0dXJlUmVxdWVzdCxcbiAgQ3JlYXRlQ2V0QWRhcHRvclNpZ25hdHVyZVJlcXVlc3QsXG4gIENyZWF0ZUNldEFkYXB0b3JTaWduYXR1cmVSZXNwb25zZSxcbiAgQ3JlYXRlQ2V0QWRhcHRvclNpZ25hdHVyZXNSZXF1ZXN0LFxuICBDcmVhdGVDZXRBZGFwdG9yU2lnbmF0dXJlc1Jlc3BvbnNlLFxuICBDcmVhdGVDZXRSZXF1ZXN0LFxuICBDcmVhdGVDZXRSZXNwb25zZSxcbiAgQ3JlYXRlRGxjVHJhbnNhY3Rpb25zUmVxdWVzdCxcbiAgQ3JlYXRlRGxjVHJhbnNhY3Rpb25zUmVzcG9uc2UsXG4gIENyZWF0ZUZ1bmRUcmFuc2FjdGlvblJlcXVlc3QsXG4gIENyZWF0ZUZ1bmRUcmFuc2FjdGlvblJlc3BvbnNlLFxuICBDcmVhdGVSYXdUcmFuc2FjdGlvblJlcXVlc3QsXG4gIENyZWF0ZVJlZnVuZFRyYW5zYWN0aW9uUmVxdWVzdCxcbiAgQ3JlYXRlUmVmdW5kVHJhbnNhY3Rpb25SZXNwb25zZSxcbiAgQ3JlYXRlU2lnbmF0dXJlSGFzaFJlcXVlc3QsXG4gIERsY1Byb3ZpZGVyLFxuICBHZXRSYXdGdW5kVHhTaWduYXR1cmVSZXF1ZXN0LFxuICBHZXRSYXdGdW5kVHhTaWduYXR1cmVSZXNwb25zZSxcbiAgR2V0UmF3UmVmdW5kVHhTaWduYXR1cmVSZXF1ZXN0LFxuICBHZXRSYXdSZWZ1bmRUeFNpZ25hdHVyZVJlc3BvbnNlLFxuICBJbnB1dCxcbiAgTWVzc2FnZXMsXG4gIFBheW91dFJlcXVlc3QsXG4gIFNpZ25DZXRSZXF1ZXN0LFxuICBTaWduQ2V0UmVzcG9uc2UsXG4gIFNpZ25GdW5kVHJhbnNhY3Rpb25SZXF1ZXN0LFxuICBTaWduRnVuZFRyYW5zYWN0aW9uUmVzcG9uc2UsXG4gIFV0eG8sXG4gIFZlcmlmeUNldEFkYXB0b3JTaWduYXR1cmVSZXF1ZXN0LFxuICBWZXJpZnlDZXRBZGFwdG9yU2lnbmF0dXJlUmVzcG9uc2UsXG4gIFZlcmlmeUNldEFkYXB0b3JTaWduYXR1cmVzUmVxdWVzdCxcbiAgVmVyaWZ5Q2V0QWRhcHRvclNpZ25hdHVyZXNSZXNwb25zZSxcbiAgVmVyaWZ5RnVuZFR4U2lnbmF0dXJlUmVxdWVzdCxcbiAgVmVyaWZ5RnVuZFR4U2lnbmF0dXJlUmVzcG9uc2UsXG4gIFZlcmlmeVJlZnVuZFR4U2lnbmF0dXJlUmVxdWVzdCxcbiAgVmVyaWZ5UmVmdW5kVHhTaWduYXR1cmVSZXNwb25zZSxcbiAgVmVyaWZ5U2lnbmF0dXJlUmVxdWVzdCxcbn0gZnJvbSAnQGF0b21pY2ZpbmFuY2UvdHlwZXMnO1xuaW1wb3J0IHsgQml0Y29pbk5ldHdvcmsgfSBmcm9tICdAbGlxdWFsaXR5L2JpdGNvaW4tbmV0d29ya3MnO1xuaW1wb3J0IHsgQWRkcmVzcywgYml0Y29pbiB9IGZyb20gJ0BsaXF1YWxpdHkvdHlwZXMnO1xuaW1wb3J0IHsgc2xlZXAgfSBmcm9tICdAbGlxdWFsaXR5L3V0aWxzJztcbmltcG9ydCB7XG4gIER1YWxDbG9zaW5nVHhGaW5hbGl6ZXIsXG4gIER1YWxGdW5kaW5nVHhGaW5hbGl6ZXIsXG4gIGdyb3VwQnlJZ25vcmluZ0RpZ2l0cyxcbiAgSHlwZXJib2xhUGF5b3V0Q3VydmUsXG4gIFBvbHlub21pYWxQYXlvdXRDdXJ2ZSxcbiAgcm91bmRQYXlvdXQsXG59IGZyb20gJ0Bub2RlLWRsYy9jb3JlJztcbmltcG9ydCB7XG4gIENldEFkYXB0b3JTaWduYXR1cmVzVjAsXG4gIENvbnRyYWN0RGVzY3JpcHRvcixcbiAgQ29udHJhY3REZXNjcmlwdG9yVjEsXG4gIENvbnRyYWN0SW5mbyxcbiAgQ29udHJhY3RJbmZvVjAsXG4gIENvbnRyYWN0SW5mb1YxLFxuICBEaWdpdERlY29tcG9zaXRpb25FdmVudERlc2NyaXB0b3JWMCxcbiAgRGxjQWNjZXB0LFxuICBEbGNBY2NlcHRWMCxcbiAgRGxjQ2xvc2UsXG4gIERsY0Nsb3NlTWV0YWRhdGEsXG4gIERsY0Nsb3NlVjAsXG4gIERsY09mZmVyLFxuICBEbGNPZmZlclYwLFxuICBEbGNTaWduLFxuICBEbGNTaWduVjAsXG4gIERsY1RyYW5zYWN0aW9ucyxcbiAgRGxjVHJhbnNhY3Rpb25zVjAsXG4gIEZ1bmRpbmdJbnB1dCxcbiAgRnVuZGluZ0lucHV0VjAsXG4gIEZ1bmRpbmdTaWduYXR1cmVzVjAsXG4gIEh5cGVyYm9sYVBheW91dEN1cnZlUGllY2UsXG4gIE1lc3NhZ2VUeXBlLFxuICBOZWdvdGlhdGlvbkZpZWxkc1YwLFxuICBPcmFjbGVBdHRlc3RhdGlvblYwLFxuICBPcmFjbGVFdmVudFYwLFxuICBPcmFjbGVJbmZvVjAsXG4gIFBheW91dEZ1bmN0aW9uVjAsXG4gIFBvbHlub21pYWxQYXlvdXRDdXJ2ZVBpZWNlLFxuICBTY3JpcHRXaXRuZXNzVjAsXG59IGZyb20gJ0Bub2RlLWRsYy9tZXNzYWdpbmcnO1xuaW1wb3J0IHsgU2NyaXB0LCBTZXF1ZW5jZSwgVHggfSBmcm9tICdAbm9kZS1saWdodG5pbmcvYml0Y29pbic7XG5pbXBvcnQgeyBTdHJlYW1SZWFkZXIgfSBmcm9tICdAbm9kZS1saWdodG5pbmcvYnVmaW8nO1xuaW1wb3J0IHsgaGFzaDE2MCwgc2hhMjU2LCB4b3IgfSBmcm9tICdAbm9kZS1saWdodG5pbmcvY3J5cHRvJztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7XG4gIGFkZHJlc3MsXG4gIEVDUGFpckludGVyZmFjZSxcbiAgcGF5bWVudHMsXG4gIFBzYnQsXG4gIHNjcmlwdCxcbn0gZnJvbSAnYml0Y29pbmpzLWxpYic7XG5cbmltcG9ydCB7XG4gIGFzeW5jRm9yRWFjaCxcbiAgY2hlY2tUeXBlcyxcbiAgZ2VuZXJhdGVTZXJpYWxJZCxcbiAgb3V0cHV0c1RvUGF5b3V0cyxcbn0gZnJvbSAnLi91dGlscy9VdGlscyc7XG5cbmNvbnN0IEVTVElNQVRFRF9TSVpFID0gMzEyO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCaXRjb2luRGxjUHJvdmlkZXJcbiAgZXh0ZW5kcyBQcm92aWRlclxuICBpbXBsZW1lbnRzIFBhcnRpYWw8RGxjUHJvdmlkZXI+IHtcbiAgX25ldHdvcms6IEJpdGNvaW5OZXR3b3JrO1xuICBfY2ZkRGxjSnM6IGFueTtcblxuICBjb25zdHJ1Y3RvcihuZXR3b3JrOiBCaXRjb2luTmV0d29yaywgY2ZkRGxjSnM/OiBhbnkpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fbmV0d29yayA9IG5ldHdvcms7XG4gICAgdGhpcy5fY2ZkRGxjSnMgPSBjZmREbGNKcztcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgQ2ZkTG9hZGVkKCkge1xuICAgIHdoaWxlICghdGhpcy5fY2ZkRGxjSnMpIHtcbiAgICAgIGF3YWl0IHNsZWVwKDEwKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIEdldFByaXZLZXlzRm9ySW5wdXRzKGlucHV0czogSW5wdXRbXSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCBwcml2S2V5czogc3RyaW5nW10gPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBpbnB1dCA9IGlucHV0c1tpXTtcbiAgICAgIGxldCBkZXJpdmF0aW9uUGF0aCA9IGlucHV0LmRlcml2YXRpb25QYXRoO1xuXG4gICAgICBpZiAoIWRlcml2YXRpb25QYXRoKSB7XG4gICAgICAgIGRlcml2YXRpb25QYXRoID0gKFxuICAgICAgICAgIGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdnZXRXYWxsZXRBZGRyZXNzJykoaW5wdXQuYWRkcmVzcylcbiAgICAgICAgKS5kZXJpdmF0aW9uUGF0aDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qga2V5UGFpciA9IGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdrZXlQYWlyJykoZGVyaXZhdGlvblBhdGgpO1xuICAgICAgY29uc3QgcHJpdktleSA9IEJ1ZmZlci5mcm9tKGtleVBhaXIuX19EKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBwcml2S2V5cy5wdXNoKHByaXZLZXkpO1xuICAgIH1cblxuICAgIHJldHVybiBwcml2S2V5cztcbiAgfVxuXG4gIGFzeW5jIEdldENmZE5ldHdvcmsoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBuZXR3b3JrID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWROZXR3b3JrKCk7XG5cbiAgICBzd2l0Y2ggKG5ldHdvcmsubmFtZSkge1xuICAgICAgY2FzZSAnYml0Y29pbl90ZXN0bmV0JzpcbiAgICAgICAgcmV0dXJuICd0ZXN0bmV0JztcbiAgICAgIGNhc2UgJ2JpdGNvaW5fcmVndGVzdCc6XG4gICAgICAgIHJldHVybiAncmVndGVzdCc7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gJ2JpdGNvaW4nO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIEdldElucHV0c0ZvckFtb3VudChcbiAgICBhbW91bnQ6IGJpZ2ludCxcbiAgICBmZWVSYXRlUGVyVmI6IGJpZ2ludCxcbiAgICBmaXhlZElucHV0czogSW5wdXRbXSA9IFtdLFxuICApOiBQcm9taXNlPElucHV0W10+IHtcbiAgICBpZiAoYW1vdW50ID09PSBCaWdJbnQoMCkpIHJldHVybiBbXTtcbiAgICBjb25zdCB0YXJnZXRzOiBiaXRjb2luLk91dHB1dFRhcmdldFtdID0gW1xuICAgICAge1xuICAgICAgICBhZGRyZXNzOiBCdXJuQWRkcmVzcyxcbiAgICAgICAgdmFsdWU6IE51bWJlcihhbW91bnQpICsgRVNUSU1BVEVEX1NJWkUgKiAoTnVtYmVyKGZlZVJhdGVQZXJWYikgLSAxKSxcbiAgICAgIH0sXG4gICAgXTtcbiAgICBsZXQgaW5wdXRzOiBJbnB1dFtdO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbnB1dHNGb3JBbW91bnQ6IElucHV0c0ZvckFtb3VudFJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXRNZXRob2QoXG4gICAgICAgICdnZXRJbnB1dHNGb3JBbW91bnQnLFxuICAgICAgKSh0YXJnZXRzLCBOdW1iZXIoZmVlUmF0ZVBlclZiKSwgZml4ZWRJbnB1dHMpO1xuICAgICAgaW5wdXRzID0gaW5wdXRzRm9yQW1vdW50LmlucHV0cztcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoZml4ZWRJbnB1dHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRocm93IEVycm9yKCdOb3QgZW5vdWdoIGJhbGFuY2UgZ2V0SW5wdXRzRm9yQW1vdW50Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbnB1dHMgPSBmaXhlZElucHV0cztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaW5wdXRzO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBJbml0aWFsaXplKFxuICAgIGNvbGxhdGVyYWw6IGJpZ2ludCxcbiAgICBmZWVSYXRlUGVyVmI6IGJpZ2ludCxcbiAgICBmaXhlZElucHV0czogSW5wdXRbXSxcbiAgKTogUHJvbWlzZTxJbml0aWFsaXplUmVzcG9uc2U+IHtcbiAgICBjb25zdCBuZXR3b3JrID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWROZXR3b3JrKCk7XG4gICAgY29uc3QgcGF5b3V0QWRkcmVzczogQWRkcmVzcyA9IGF3YWl0IHRoaXMuY2xpZW50LndhbGxldC5nZXRVbnVzZWRBZGRyZXNzKFxuICAgICAgZmFsc2UsXG4gICAgKTtcbiAgICBjb25zdCBwYXlvdXRTUEs6IEJ1ZmZlciA9IGFkZHJlc3MudG9PdXRwdXRTY3JpcHQoXG4gICAgICBwYXlvdXRBZGRyZXNzLmFkZHJlc3MsXG4gICAgICBuZXR3b3JrLFxuICAgICk7XG4gICAgY29uc3QgY2hhbmdlQWRkcmVzczogQWRkcmVzcyA9IGF3YWl0IHRoaXMuY2xpZW50LndhbGxldC5nZXRVbnVzZWRBZGRyZXNzKFxuICAgICAgdHJ1ZSxcbiAgICApO1xuICAgIGNvbnN0IGNoYW5nZVNQSzogQnVmZmVyID0gYWRkcmVzcy50b091dHB1dFNjcmlwdChcbiAgICAgIGNoYW5nZUFkZHJlc3MuYWRkcmVzcyxcbiAgICAgIG5ldHdvcmssXG4gICAgKTtcblxuICAgIGNvbnN0IGZ1bmRpbmdBZGRyZXNzOiBBZGRyZXNzID0gYXdhaXQgdGhpcy5jbGllbnQud2FsbGV0LmdldFVudXNlZEFkZHJlc3MoXG4gICAgICBmYWxzZSxcbiAgICApO1xuICAgIGNvbnN0IGZ1bmRpbmdQdWJLZXk6IEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGZ1bmRpbmdBZGRyZXNzLnB1YmxpY0tleSwgJ2hleCcpO1xuXG4gICAgaWYgKGZ1bmRpbmdBZGRyZXNzLmFkZHJlc3MgPT09IHBheW91dEFkZHJlc3MuYWRkcmVzcylcbiAgICAgIHRocm93IEVycm9yKCdBZGRyZXNzIHJldXNlJyk7XG5cbiAgICBjb25zdCBpbnB1dHM6IElucHV0W10gPSBhd2FpdCB0aGlzLkdldElucHV0c0ZvckFtb3VudChcbiAgICAgIGNvbGxhdGVyYWwsXG4gICAgICBmZWVSYXRlUGVyVmIsXG4gICAgICBmaXhlZElucHV0cyxcbiAgICApO1xuICAgIGNvbnN0IGZ1bmRpbmdJbnB1dHM6IEZ1bmRpbmdJbnB1dFtdID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBpbnB1dHMubWFwKGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5pbnB1dFRvRnVuZGluZ0lucHV0KGlucHV0KTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBjb25zdCBwYXlvdXRTZXJpYWxJZDogYmlnaW50ID0gZ2VuZXJhdGVTZXJpYWxJZCgpO1xuICAgIGNvbnN0IGNoYW5nZVNlcmlhbElkOiBiaWdpbnQgPSBnZW5lcmF0ZVNlcmlhbElkKCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZnVuZGluZ1B1YktleSxcbiAgICAgIHBheW91dFNQSyxcbiAgICAgIHBheW91dFNlcmlhbElkLFxuICAgICAgZnVuZGluZ0lucHV0cyxcbiAgICAgIGNoYW5nZVNQSyxcbiAgICAgIGNoYW5nZVNlcmlhbElkLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVE9ETzogQWRkIEdldFBheW91dEZyb21PdXRjb21lc1xuICAgKlxuICAgKiBwcml2YXRlIEdldFBheW91dHNGcm9tT3V0Y29tZXMoXG4gICAqICAgY29udHJhY3REZXNjcmlwdG9yOiBDb250cmFjdERlc2NyaXB0b3JWMCxcbiAgICogICB0b3RhbENvbGxhdGVyYWw6IGJpZ2ludCxcbiAgICogKTogUGF5b3V0UmVxdWVzdFtdIHt9XG4gICAqL1xuXG4gIHByaXZhdGUgR2V0UGF5b3V0c0Zyb21QYXlvdXRGdW5jdGlvbihcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIGNvbnRyYWN0RGVzY3JpcHRvcjogQ29udHJhY3REZXNjcmlwdG9yVjEsXG4gICAgb3JhY2xlSW5mbzogT3JhY2xlSW5mb1YwLFxuICAgIHRvdGFsQ29sbGF0ZXJhbDogYmlnaW50LFxuICApOiBHZXRQYXlvdXRzUmVzcG9uc2Uge1xuICAgIGlmIChfZGxjT2ZmZXIudHlwZSAhPT0gTWVzc2FnZVR5cGUuRGxjT2ZmZXJWMClcbiAgICAgIHRocm93IEVycm9yKCdEbGNPZmZlciBtdXN0IGJlIFYwJyk7XG4gICAgY29uc3QgZGxjT2ZmZXIgPSBfZGxjT2ZmZXIgYXMgRGxjT2ZmZXJWMDtcbiAgICBpZiAoY29udHJhY3REZXNjcmlwdG9yLnBheW91dEZ1bmN0aW9uLnR5cGUgIT09IE1lc3NhZ2VUeXBlLlBheW91dEZ1bmN0aW9uVjApXG4gICAgICB0aHJvdyBFcnJvcignUGF5b3V0RnVuY3Rpb24gbXVzdCBiZSBWMCcpO1xuICAgIGNvbnN0IHBheW91dEZ1bmN0aW9uID0gY29udHJhY3REZXNjcmlwdG9yLnBheW91dEZ1bmN0aW9uIGFzIFBheW91dEZ1bmN0aW9uVjA7XG4gICAgaWYgKHBheW91dEZ1bmN0aW9uLnBpZWNlcy5sZW5ndGggPT09IDApXG4gICAgICB0aHJvdyBFcnJvcignUGF5b3V0RnVuY3Rpb24gbXVzdCBoYXZlIGF0IGxlYXN0IG9uY2UgUGF5b3V0Q3VydmVQaWVjZScpO1xuICAgIGlmIChwYXlvdXRGdW5jdGlvbi5waWVjZXMubGVuZ3RoID4gMSlcbiAgICAgIHRocm93IEVycm9yKCdNb3JlIHRoYW4gb25lIFBheW91dEN1cnZlUGllY2Ugbm90IHN1cHBvcnRlZCcpO1xuICAgIGNvbnN0IHBheW91dEN1cnZlUGllY2UgPSBwYXlvdXRGdW5jdGlvbi5waWVjZXNbMF1cbiAgICAgIC5wYXlvdXRDdXJ2ZVBpZWNlIGFzIEh5cGVyYm9sYVBheW91dEN1cnZlUGllY2U7XG4gICAgaWYgKFxuICAgICAgcGF5b3V0Q3VydmVQaWVjZS50eXBlICE9PSBNZXNzYWdlVHlwZS5IeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlICYmXG4gICAgICBwYXlvdXRDdXJ2ZVBpZWNlLnR5cGUgIT09IE1lc3NhZ2VUeXBlLk9sZEh5cGVyYm9sYVBheW91dEN1cnZlUGllY2VcbiAgICApXG4gICAgICB0aHJvdyBFcnJvcignTXVzdCBiZSBIeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlJyk7XG4gICAgaWYgKHBheW91dEN1cnZlUGllY2UuYiAhPT0gQmlnSW50KDApIHx8IHBheW91dEN1cnZlUGllY2UuYyAhPT0gQmlnSW50KDApKVxuICAgICAgdGhyb3cgRXJyb3IoJ2IgYW5kIGMgSHlwZXJib2xhUGF5b3V0Q3VydmVQaWVjZSB2YWx1ZXMgbXVzdCBiZSAwJyk7XG4gICAgY29uc3QgZXZlbnREZXNjcmlwdG9yID0gb3JhY2xlSW5mby5hbm5vdW5jZW1lbnQub3JhY2xlRXZlbnRcbiAgICAgIC5ldmVudERlc2NyaXB0b3IgYXMgRGlnaXREZWNvbXBvc2l0aW9uRXZlbnREZXNjcmlwdG9yVjA7XG4gICAgaWYgKFxuICAgICAgZXZlbnREZXNjcmlwdG9yLnR5cGUgIT09IE1lc3NhZ2VUeXBlLkRpZ2l0RGVjb21wb3NpdGlvbkV2ZW50RGVzY3JpcHRvclYwXG4gICAgKVxuICAgICAgdGhyb3cgRXJyb3IoJ09ubHkgRGlnaXREZWNvbXBvc2l0aW9uIE9yYWNsZSBFdmVudHMgc3VwcG9ydGVkJyk7XG5cbiAgICBjb25zdCByb3VuZGluZ0ludGVydmFscyA9IGNvbnRyYWN0RGVzY3JpcHRvci5yb3VuZGluZ0ludGVydmFscztcbiAgICBjb25zdCBjZXRQYXlvdXRzID0gSHlwZXJib2xhUGF5b3V0Q3VydmUuY29tcHV0ZVBheW91dHMoXG4gICAgICBwYXlvdXRGdW5jdGlvbixcbiAgICAgIHRvdGFsQ29sbGF0ZXJhbCxcbiAgICAgIHJvdW5kaW5nSW50ZXJ2YWxzLFxuICAgICk7XG5cbiAgICBjb25zdCBwYXlvdXRHcm91cHM6IFBheW91dEdyb3VwW10gPSBbXTtcbiAgICBjZXRQYXlvdXRzLmZvckVhY2goKHApID0+IHtcbiAgICAgIHBheW91dEdyb3Vwcy5wdXNoKHtcbiAgICAgICAgcGF5b3V0OiBwLnBheW91dCxcbiAgICAgICAgZ3JvdXBzOiBncm91cEJ5SWdub3JpbmdEaWdpdHMoXG4gICAgICAgICAgcC5pbmRleEZyb20sXG4gICAgICAgICAgcC5pbmRleFRvLFxuICAgICAgICAgIGV2ZW50RGVzY3JpcHRvci5iYXNlLFxuICAgICAgICAgIGNvbnRyYWN0RGVzY3JpcHRvci5udW1EaWdpdHMsXG4gICAgICAgICksXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHJWYWx1ZXNNZXNzYWdlc0xpc3QgPSB0aGlzLkdlbmVyYXRlTWVzc2FnZXMob3JhY2xlSW5mbyk7XG5cbiAgICBjb25zdCB7IHBheW91dHMsIG1lc3NhZ2VzTGlzdCB9ID0gb3V0cHV0c1RvUGF5b3V0cyhcbiAgICAgIHBheW91dEdyb3VwcyxcbiAgICAgIHJWYWx1ZXNNZXNzYWdlc0xpc3QsXG4gICAgICBkbGNPZmZlci5vZmZlckNvbGxhdGVyYWxTYXRvc2hpcyxcbiAgICAgIGRsY09mZmVyLmNvbnRyYWN0SW5mby50b3RhbENvbGxhdGVyYWwgLSBkbGNPZmZlci5vZmZlckNvbGxhdGVyYWxTYXRvc2hpcyxcbiAgICAgIHRydWUsXG4gICAgKTtcblxuICAgIHJldHVybiB7IHBheW91dHMsIHBheW91dEdyb3VwcywgbWVzc2FnZXNMaXN0IH07XG4gIH1cblxuICBwcml2YXRlIEdldFBheW91dHNGcm9tUG9seW5vbWlhbFBheW91dEZ1bmN0aW9uKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgY29udHJhY3REZXNjcmlwdG9yOiBDb250cmFjdERlc2NyaXB0b3JWMSxcbiAgICBvcmFjbGVJbmZvOiBPcmFjbGVJbmZvVjAsXG4gICAgdG90YWxDb2xsYXRlcmFsOiBiaWdpbnQsXG4gICk6IEdldFBheW91dHNSZXNwb25zZSB7XG4gICAgaWYgKF9kbGNPZmZlci50eXBlICE9PSBNZXNzYWdlVHlwZS5EbGNPZmZlclYwKVxuICAgICAgdGhyb3cgRXJyb3IoJ0RsY09mZmVyIG11c3QgYmUgVjAnKTtcbiAgICBjb25zdCBkbGNPZmZlciA9IF9kbGNPZmZlciBhcyBEbGNPZmZlclYwO1xuICAgIGlmIChjb250cmFjdERlc2NyaXB0b3IucGF5b3V0RnVuY3Rpb24udHlwZSAhPT0gTWVzc2FnZVR5cGUuUGF5b3V0RnVuY3Rpb25WMClcbiAgICAgIHRocm93IEVycm9yKCdQYXlvdXRGdW5jdGlvbiBtdXN0IGJlIFYwJyk7XG4gICAgY29uc3QgcGF5b3V0RnVuY3Rpb24gPSBjb250cmFjdERlc2NyaXB0b3IucGF5b3V0RnVuY3Rpb24gYXMgUGF5b3V0RnVuY3Rpb25WMDtcbiAgICBpZiAocGF5b3V0RnVuY3Rpb24ucGllY2VzLmxlbmd0aCA9PT0gMClcbiAgICAgIHRocm93IEVycm9yKCdQYXlvdXRGdW5jdGlvbiBtdXN0IGhhdmUgYXQgbGVhc3Qgb25jZSBQYXlvdXRDdXJ2ZVBpZWNlJyk7XG4gICAgZm9yIChjb25zdCBwaWVjZSBvZiBwYXlvdXRGdW5jdGlvbi5waWVjZXMpIHtcbiAgICAgIGlmIChcbiAgICAgICAgcGllY2UucGF5b3V0Q3VydmVQaWVjZS50eXBlICE9PSBNZXNzYWdlVHlwZS5Qb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZVxuICAgICAgKVxuICAgICAgICB0aHJvdyBFcnJvcignTXVzdCBiZSBQb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZScpO1xuICAgIH1cbiAgICBjb25zdCBldmVudERlc2NyaXB0b3IgPSBvcmFjbGVJbmZvLmFubm91bmNlbWVudC5vcmFjbGVFdmVudFxuICAgICAgLmV2ZW50RGVzY3JpcHRvciBhcyBEaWdpdERlY29tcG9zaXRpb25FdmVudERlc2NyaXB0b3JWMDtcbiAgICBpZiAoXG4gICAgICBldmVudERlc2NyaXB0b3IudHlwZSAhPT0gTWVzc2FnZVR5cGUuRGlnaXREZWNvbXBvc2l0aW9uRXZlbnREZXNjcmlwdG9yVjBcbiAgICApXG4gICAgICB0aHJvdyBFcnJvcignT25seSBEaWdpdERlY29tcG9zaXRpb24gT3JhY2xlIEV2ZW50cyBzdXBwb3J0ZWQnKTtcblxuICAgIGNvbnN0IHJvdW5kaW5nSW50ZXJ2YWxzID0gY29udHJhY3REZXNjcmlwdG9yLnJvdW5kaW5nSW50ZXJ2YWxzO1xuICAgIGNvbnN0IGNldFBheW91dHMgPSBQb2x5bm9taWFsUGF5b3V0Q3VydmUuY29tcHV0ZVBheW91dHMoXG4gICAgICBwYXlvdXRGdW5jdGlvbixcbiAgICAgIHRvdGFsQ29sbGF0ZXJhbCxcbiAgICAgIHJvdW5kaW5nSW50ZXJ2YWxzLFxuICAgICk7XG5cbiAgICBjb25zdCBwYXlvdXRHcm91cHM6IFBheW91dEdyb3VwW10gPSBbXTtcbiAgICBjZXRQYXlvdXRzLmZvckVhY2goKHApID0+IHtcbiAgICAgIHBheW91dEdyb3Vwcy5wdXNoKHtcbiAgICAgICAgcGF5b3V0OiBwLnBheW91dCxcbiAgICAgICAgZ3JvdXBzOiBncm91cEJ5SWdub3JpbmdEaWdpdHMoXG4gICAgICAgICAgcC5pbmRleEZyb20sXG4gICAgICAgICAgcC5pbmRleFRvLFxuICAgICAgICAgIGV2ZW50RGVzY3JpcHRvci5iYXNlLFxuICAgICAgICAgIGNvbnRyYWN0RGVzY3JpcHRvci5udW1EaWdpdHMsXG4gICAgICAgICksXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHJWYWx1ZXNNZXNzYWdlc0xpc3QgPSB0aGlzLkdlbmVyYXRlTWVzc2FnZXMob3JhY2xlSW5mbyk7XG5cbiAgICBjb25zdCB7IHBheW91dHMsIG1lc3NhZ2VzTGlzdCB9ID0gb3V0cHV0c1RvUGF5b3V0cyhcbiAgICAgIHBheW91dEdyb3VwcyxcbiAgICAgIHJWYWx1ZXNNZXNzYWdlc0xpc3QsXG4gICAgICBkbGNPZmZlci5vZmZlckNvbGxhdGVyYWxTYXRvc2hpcyxcbiAgICAgIGRsY09mZmVyLmNvbnRyYWN0SW5mby50b3RhbENvbGxhdGVyYWwgLSBkbGNPZmZlci5vZmZlckNvbGxhdGVyYWxTYXRvc2hpcyxcbiAgICAgIHRydWUsXG4gICAgKTtcblxuICAgIHJldHVybiB7IHBheW91dHMsIHBheW91dEdyb3VwcywgbWVzc2FnZXNMaXN0IH07XG4gIH1cblxuICBwcml2YXRlIEdldFBheW91dHMoX2RsY09mZmVyOiBEbGNPZmZlcik6IEdldFBheW91dHNSZXNwb25zZVtdIHtcbiAgICBjb25zdCB7IGRsY09mZmVyIH0gPSBjaGVja1R5cGVzKHsgX2RsY09mZmVyIH0pO1xuXG4gICAgY29uc3QgY29udHJhY3RJbmZvID0gZGxjT2ZmZXIuY29udHJhY3RJbmZvO1xuICAgIGNvbnN0IHRvdGFsQ29sbGF0ZXJhbCA9IGNvbnRyYWN0SW5mby50b3RhbENvbGxhdGVyYWw7XG4gICAgY29uc3QgY29udHJhY3RPcmFjbGVQYWlycyA9IHRoaXMuR2V0Q29udHJhY3RPcmFjbGVQYWlycyhjb250cmFjdEluZm8pO1xuXG4gICAgY29uc3QgcGF5b3V0UmVzcG9uc2VzID0gY29udHJhY3RPcmFjbGVQYWlycy5tYXAoXG4gICAgICAoeyBjb250cmFjdERlc2NyaXB0b3IsIG9yYWNsZUluZm8gfSkgPT5cbiAgICAgICAgdGhpcy5HZXRQYXlvdXRzRnJvbUNvbnRyYWN0RGVzY3JpcHRvcihcbiAgICAgICAgICBkbGNPZmZlcixcbiAgICAgICAgICBjb250cmFjdERlc2NyaXB0b3IsXG4gICAgICAgICAgb3JhY2xlSW5mbyxcbiAgICAgICAgICB0b3RhbENvbGxhdGVyYWwsXG4gICAgICAgICksXG4gICAgKTtcblxuICAgIHJldHVybiBwYXlvdXRSZXNwb25zZXM7XG4gIH1cblxuICBwcml2YXRlIEZsYXR0ZW5QYXlvdXRzKHBheW91dFJlc3BvbnNlczogR2V0UGF5b3V0c1Jlc3BvbnNlW10pIHtcbiAgICByZXR1cm4gcGF5b3V0UmVzcG9uc2VzLnJlZHVjZShcbiAgICAgIChhY2MsIHsgcGF5b3V0cywgcGF5b3V0R3JvdXBzLCBtZXNzYWdlc0xpc3QgfSkgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHBheW91dHM6IGFjYy5wYXlvdXRzLmNvbmNhdChwYXlvdXRzKSxcbiAgICAgICAgICBwYXlvdXRHcm91cHM6IGFjYy5wYXlvdXRHcm91cHMuY29uY2F0KHBheW91dEdyb3VwcyksXG4gICAgICAgICAgbWVzc2FnZXNMaXN0OiBhY2MubWVzc2FnZXNMaXN0LmNvbmNhdChtZXNzYWdlc0xpc3QpLFxuICAgICAgICB9O1xuICAgICAgfSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBHZXRJbmRpY2VzRnJvbVBheW91dHMocGF5b3V0UmVzcG9uc2VzOiBHZXRQYXlvdXRzUmVzcG9uc2VbXSkge1xuICAgIHJldHVybiBwYXlvdXRSZXNwb25zZXMucmVkdWNlKFxuICAgICAgKHByZXYsIGFjYykgPT4ge1xuICAgICAgICByZXR1cm4gcHJldi5jb25jYXQoe1xuICAgICAgICAgIHN0YXJ0aW5nTWVzc2FnZXNJbmRleDpcbiAgICAgICAgICAgIHByZXZbcHJldi5sZW5ndGggLSAxXS5zdGFydGluZ01lc3NhZ2VzSW5kZXggK1xuICAgICAgICAgICAgYWNjLm1lc3NhZ2VzTGlzdC5sZW5ndGgsXG4gICAgICAgICAgc3RhcnRpbmdQYXlvdXRHcm91cHNJbmRleDpcbiAgICAgICAgICAgIHByZXZbcHJldi5sZW5ndGggLSAxXS5zdGFydGluZ1BheW91dEdyb3Vwc0luZGV4ICtcbiAgICAgICAgICAgIGFjYy5wYXlvdXRHcm91cHMubGVuZ3RoLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICBbeyBzdGFydGluZ01lc3NhZ2VzSW5kZXg6IDAsIHN0YXJ0aW5nUGF5b3V0R3JvdXBzSW5kZXg6IDAgfV0sXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgR2V0UGF5b3V0c0Zyb21Db250cmFjdERlc2NyaXB0b3IoXG4gICAgZGxjT2ZmZXI6IERsY09mZmVyVjAsXG4gICAgY29udHJhY3REZXNjcmlwdG9yOiBDb250cmFjdERlc2NyaXB0b3IsXG4gICAgb3JhY2xlSW5mbzogT3JhY2xlSW5mb1YwLFxuICAgIHRvdGFsQ29sbGF0ZXJhbDogYmlnaW50LFxuICApIHtcbiAgICBzd2l0Y2ggKGNvbnRyYWN0RGVzY3JpcHRvci50eXBlKSB7XG4gICAgICBjYXNlIE1lc3NhZ2VUeXBlLkNvbnRyYWN0RGVzY3JpcHRvclYwOiB7XG4gICAgICAgIHRocm93IEVycm9yKCdDb250cmFjdERlc2NyaXB0b3JWMCBub3QgeWV0IHN1cHBvcnRlZCcpO1xuICAgICAgfVxuICAgICAgY2FzZSBNZXNzYWdlVHlwZS5Db250cmFjdERlc2NyaXB0b3JWMTpcbiAgICAgICAge1xuICAgICAgICAgIGNvbnN0IGNvbnRyYWN0RGVzY3JpcHRvclYxID0gY29udHJhY3REZXNjcmlwdG9yIGFzIENvbnRyYWN0RGVzY3JpcHRvclYxO1xuICAgICAgICAgIGNvbnN0IHBheW91dEZ1bmN0aW9uID0gY29udHJhY3REZXNjcmlwdG9yVjEucGF5b3V0RnVuY3Rpb24gYXMgUGF5b3V0RnVuY3Rpb25WMDtcblxuICAgICAgICAgIC8vIFRPRE86IGFkZCBhIGJldHRlciBjaGVjayBmb3IgdGhpc1xuICAgICAgICAgIGNvbnN0IHBheW91dEN1cnZlUGllY2UgPSBwYXlvdXRGdW5jdGlvbi5waWVjZXNbMF0ucGF5b3V0Q3VydmVQaWVjZTtcblxuICAgICAgICAgIHN3aXRjaCAocGF5b3V0Q3VydmVQaWVjZS50eXBlKSB7XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VUeXBlLkh5cGVyYm9sYVBheW91dEN1cnZlUGllY2U6XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLkdldFBheW91dHNGcm9tUGF5b3V0RnVuY3Rpb24oXG4gICAgICAgICAgICAgICAgZGxjT2ZmZXIsXG4gICAgICAgICAgICAgICAgY29udHJhY3REZXNjcmlwdG9yIGFzIENvbnRyYWN0RGVzY3JpcHRvclYxLFxuICAgICAgICAgICAgICAgIG9yYWNsZUluZm8sXG4gICAgICAgICAgICAgICAgdG90YWxDb2xsYXRlcmFsLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgY2FzZSBNZXNzYWdlVHlwZS5PbGRIeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlOlxuICAgICAgICAgICAgICByZXR1cm4gdGhpcy5HZXRQYXlvdXRzRnJvbVBheW91dEZ1bmN0aW9uKFxuICAgICAgICAgICAgICAgIGRsY09mZmVyLFxuICAgICAgICAgICAgICAgIGNvbnRyYWN0RGVzY3JpcHRvciBhcyBDb250cmFjdERlc2NyaXB0b3JWMSxcbiAgICAgICAgICAgICAgICBvcmFjbGVJbmZvLFxuICAgICAgICAgICAgICAgIHRvdGFsQ29sbGF0ZXJhbCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZVR5cGUuUG9seW5vbWlhbFBheW91dEN1cnZlUGllY2U6XG4gICAgICAgICAgICAgIHJldHVybiB0aGlzLkdldFBheW91dHNGcm9tUG9seW5vbWlhbFBheW91dEZ1bmN0aW9uKFxuICAgICAgICAgICAgICAgIGRsY09mZmVyLFxuICAgICAgICAgICAgICAgIGNvbnRyYWN0RGVzY3JpcHRvciBhcyBDb250cmFjdERlc2NyaXB0b3JWMSxcbiAgICAgICAgICAgICAgICBvcmFjbGVJbmZvLFxuICAgICAgICAgICAgICAgIHRvdGFsQ29sbGF0ZXJhbCxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIHRocm93IEVycm9yKCdDb250cmFjdERlc2NyaXB0b3IgbXVzdCBiZSBWMCBvciBWMScpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjcmVhdGVEbGNUeHMoXG4gICAgX2RsY09mZmVyOiBEbGNPZmZlcixcbiAgICBfZGxjQWNjZXB0OiBEbGNBY2NlcHQsXG4gICk6IFByb21pc2U8Q3JlYXRlRGxjVHhzUmVzcG9uc2U+IHtcbiAgICBjb25zdCB7IGRsY09mZmVyLCBkbGNBY2NlcHQgfSA9IGNoZWNrVHlwZXMoe1xuICAgICAgX2RsY09mZmVyLFxuICAgICAgX2RsY0FjY2VwdCxcbiAgICB9KTtcblxuICAgIGNvbnN0IGxvY2FsRnVuZFB1YmtleSA9IGRsY09mZmVyLmZ1bmRpbmdQdWJLZXkudG9TdHJpbmcoJ2hleCcpO1xuICAgIGNvbnN0IHJlbW90ZUZ1bmRQdWJrZXkgPSBkbGNBY2NlcHQuZnVuZGluZ1B1YktleS50b1N0cmluZygnaGV4Jyk7XG4gICAgY29uc3QgbG9jYWxGaW5hbFNjcmlwdFB1YmtleSA9IGRsY09mZmVyLnBheW91dFNQSy50b1N0cmluZygnaGV4Jyk7XG4gICAgY29uc3QgcmVtb3RlRmluYWxTY3JpcHRQdWJrZXkgPSBkbGNBY2NlcHQucGF5b3V0U1BLLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBsb2NhbENoYW5nZVNjcmlwdFB1YmtleSA9IGRsY09mZmVyLmNoYW5nZVNQSy50b1N0cmluZygnaGV4Jyk7XG4gICAgY29uc3QgcmVtb3RlQ2hhbmdlU2NyaXB0UHVia2V5ID0gZGxjQWNjZXB0LmNoYW5nZVNQSy50b1N0cmluZygnaGV4Jyk7XG5cbiAgICBjb25zdCBsb2NhbElucHV0czogVXR4b1tdID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBkbGNPZmZlci5mdW5kaW5nSW5wdXRzLm1hcChhc3luYyAoZnVuZGluZ0lucHV0KSA9PiB7XG4gICAgICAgIGNvbnN0IGlucHV0ID0gYXdhaXQgdGhpcy5mdW5kaW5nSW5wdXRUb0lucHV0KGZ1bmRpbmdJbnB1dCwgZmFsc2UpO1xuICAgICAgICByZXR1cm4gaW5wdXQudG9VdHhvKCk7XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgY29uc3QgcmVtb3RlSW5wdXRzOiBVdHhvW10gPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGRsY0FjY2VwdC5mdW5kaW5nSW5wdXRzLm1hcChhc3luYyAoZnVuZGluZ0lucHV0KSA9PiB7XG4gICAgICAgIGNvbnN0IGlucHV0ID0gYXdhaXQgdGhpcy5mdW5kaW5nSW5wdXRUb0lucHV0KGZ1bmRpbmdJbnB1dCwgZmFsc2UpO1xuICAgICAgICByZXR1cm4gaW5wdXQudG9VdHhvKCk7XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgY29uc3QgbG9jYWxJbnB1dEFtb3VudCA9IGxvY2FsSW5wdXRzLnJlZHVjZTxudW1iZXI+KFxuICAgICAgKHByZXYsIGN1cikgPT4gcHJldiArIGN1ci5hbW91bnQuR2V0U2F0b3NoaUFtb3VudCgpLFxuICAgICAgMCxcbiAgICApO1xuXG4gICAgY29uc3QgcmVtb3RlSW5wdXRBbW91bnQgPSByZW1vdGVJbnB1dHMucmVkdWNlPG51bWJlcj4oXG4gICAgICAocHJldiwgY3VyKSA9PiBwcmV2ICsgY3VyLmFtb3VudC5HZXRTYXRvc2hpQW1vdW50KCksXG4gICAgICAwLFxuICAgICk7XG5cbiAgICBjb25zdCBwYXlvdXRSZXNwb25zZXMgPSB0aGlzLkdldFBheW91dHMoZGxjT2ZmZXIpO1xuICAgIGNvbnN0IHsgcGF5b3V0cywgbWVzc2FnZXNMaXN0IH0gPSB0aGlzLkZsYXR0ZW5QYXlvdXRzKHBheW91dFJlc3BvbnNlcyk7XG5cbiAgICBjb25zdCBkbGNUeFJlcXVlc3Q6IENyZWF0ZURsY1RyYW5zYWN0aW9uc1JlcXVlc3QgPSB7XG4gICAgICBwYXlvdXRzLFxuICAgICAgbG9jYWxGdW5kUHVia2V5LFxuICAgICAgbG9jYWxGaW5hbFNjcmlwdFB1YmtleSxcbiAgICAgIHJlbW90ZUZ1bmRQdWJrZXksXG4gICAgICByZW1vdGVGaW5hbFNjcmlwdFB1YmtleSxcbiAgICAgIGxvY2FsSW5wdXRBbW91bnQsXG4gICAgICBsb2NhbENvbGxhdGVyYWxBbW91bnQ6IGRsY09mZmVyLm9mZmVyQ29sbGF0ZXJhbFNhdG9zaGlzLFxuICAgICAgbG9jYWxQYXlvdXRTZXJpYWxJZDogZGxjT2ZmZXIucGF5b3V0U2VyaWFsSWQsXG4gICAgICBsb2NhbENoYW5nZVNlcmlhbElkOiBkbGNPZmZlci5jaGFuZ2VTZXJpYWxJZCxcbiAgICAgIHJlbW90ZUlucHV0QW1vdW50LFxuICAgICAgcmVtb3RlQ29sbGF0ZXJhbEFtb3VudDogZGxjQWNjZXB0LmFjY2VwdENvbGxhdGVyYWxTYXRvc2hpcyxcbiAgICAgIHJlbW90ZVBheW91dFNlcmlhbElkOiBkbGNBY2NlcHQucGF5b3V0U2VyaWFsSWQsXG4gICAgICByZW1vdGVDaGFuZ2VTZXJpYWxJZDogZGxjQWNjZXB0LmNoYW5nZVNlcmlhbElkLFxuICAgICAgcmVmdW5kTG9ja3RpbWU6IGRsY09mZmVyLnJlZnVuZExvY2t0aW1lLFxuICAgICAgbG9jYWxJbnB1dHMsXG4gICAgICByZW1vdGVJbnB1dHMsXG4gICAgICBsb2NhbENoYW5nZVNjcmlwdFB1YmtleSxcbiAgICAgIHJlbW90ZUNoYW5nZVNjcmlwdFB1YmtleSxcbiAgICAgIGZlZVJhdGU6IE51bWJlcihkbGNPZmZlci5mZWVSYXRlUGVyVmIpLFxuICAgICAgY2V0TG9ja1RpbWU6IGRsY09mZmVyLmNldExvY2t0aW1lLFxuICAgICAgZnVuZE91dHB1dFNlcmlhbElkOiBkbGNPZmZlci5mdW5kT3V0cHV0U2VyaWFsSWQsXG4gICAgfTtcblxuICAgIGNvbnN0IGRsY1R4cyA9IGF3YWl0IHRoaXMuQ3JlYXRlRGxjVHJhbnNhY3Rpb25zKGRsY1R4UmVxdWVzdCk7XG5cbiAgICBjb25zdCBkbGNUcmFuc2FjdGlvbnMgPSBuZXcgRGxjVHJhbnNhY3Rpb25zVjAoKTtcbiAgICBkbGNUcmFuc2FjdGlvbnMuZnVuZFR4ID0gVHguZGVjb2RlKFN0cmVhbVJlYWRlci5mcm9tSGV4KGRsY1R4cy5mdW5kVHhIZXgpKTtcbiAgICBkbGNUcmFuc2FjdGlvbnMuZnVuZFR4Vm91dCA9IFtcbiAgICAgIEJpZ0ludChkbGNPZmZlci5jaGFuZ2VTZXJpYWxJZCksXG4gICAgICBCaWdJbnQoZGxjQWNjZXB0LmNoYW5nZVNlcmlhbElkKSxcbiAgICAgIEJpZ0ludChkbGNUeFJlcXVlc3QuZnVuZE91dHB1dFNlcmlhbElkKSxcbiAgICBdXG4gICAgICAuc29ydCgoYSwgYikgPT4gKGEgPCBiID8gLTEgOiBhID4gYiA/IDEgOiAwKSlcbiAgICAgIC5maW5kSW5kZXgoKGkpID0+IEJpZ0ludChpKSA9PT0gQmlnSW50KGRsY1R4UmVxdWVzdC5mdW5kT3V0cHV0U2VyaWFsSWQpKTtcbiAgICBkbGNUcmFuc2FjdGlvbnMucmVmdW5kVHggPSBUeC5kZWNvZGUoXG4gICAgICBTdHJlYW1SZWFkZXIuZnJvbUhleChkbGNUeHMucmVmdW5kVHhIZXgpLFxuICAgICk7XG4gICAgZGxjVHJhbnNhY3Rpb25zLmNldHMgPSBkbGNUeHMuY2V0c0hleC5tYXAoKGNldEhleCkgPT4ge1xuICAgICAgcmV0dXJuIFR4LmRlY29kZShTdHJlYW1SZWFkZXIuZnJvbUhleChjZXRIZXgpKTtcbiAgICB9KTtcblxuICAgIHJldHVybiB7IGRsY1RyYW5zYWN0aW9ucywgbWVzc2FnZXNMaXN0IH07XG4gIH1cblxuICBwcml2YXRlIEdlbmVyYXRlRW51bU1lc3NhZ2VzKG9yYWNsZUV2ZW50OiBPcmFjbGVFdmVudFYwKTogTWVzc2FnZXNbXSB7XG4gICAgdGhyb3cgRXJyb3IoJ09ubHkgRGlnaXREZWNvbXBvc2l0aW9uIE9yYWNsZSBFdmVudHMgc3VwcG9ydGVkJyk7XG4gIH1cblxuICBwcml2YXRlIEdlbmVyYXRlRGlnaXREZWNvbXBvc2l0aW9uTWVzc2FnZXMoXG4gICAgb3JhY2xlRXZlbnQ6IE9yYWNsZUV2ZW50VjAsXG4gICk6IE1lc3NhZ2VzW10ge1xuICAgIGNvbnN0IG9yYWNsZU5vbmNlcyA9IG9yYWNsZUV2ZW50Lm9yYWNsZU5vbmNlcztcbiAgICBjb25zdCBldmVudERlc2NyaXB0b3IgPSBvcmFjbGVFdmVudC5ldmVudERlc2NyaXB0b3IgYXMgRGlnaXREZWNvbXBvc2l0aW9uRXZlbnREZXNjcmlwdG9yVjA7XG5cbiAgICBjb25zdCBtZXNzYWdlc0xpc3Q6IE1lc3NhZ2VzW10gPSBbXTtcbiAgICBvcmFjbGVOb25jZXMuZm9yRWFjaCgoKSA9PiB7XG4gICAgICBjb25zdCBtZXNzYWdlcyA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBldmVudERlc2NyaXB0b3IuYmFzZTsgaSsrKSB7XG4gICAgICAgIGNvbnN0IG0gPSBpLnRvU3RyaW5nKCk7XG4gICAgICAgIG1lc3NhZ2VzLnB1c2gobSk7XG4gICAgICB9XG4gICAgICBtZXNzYWdlc0xpc3QucHVzaCh7IG1lc3NhZ2VzIH0pO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIG1lc3NhZ2VzTGlzdDtcbiAgfVxuXG4gIHByaXZhdGUgR2VuZXJhdGVNZXNzYWdlcyhvcmFjbGVJbmZvOiBPcmFjbGVJbmZvVjApOiBNZXNzYWdlc1tdIHtcbiAgICBjb25zdCBvcmFjbGVFdmVudCA9IG9yYWNsZUluZm8uYW5ub3VuY2VtZW50Lm9yYWNsZUV2ZW50O1xuXG4gICAgc3dpdGNoIChvcmFjbGVFdmVudC5ldmVudERlc2NyaXB0b3IudHlwZSkge1xuICAgICAgY2FzZSBNZXNzYWdlVHlwZS5FbnVtRXZlbnREZXNjcmlwdG9yVjA6XG4gICAgICAgIHJldHVybiB0aGlzLkdlbmVyYXRlRW51bU1lc3NhZ2VzKG9yYWNsZUV2ZW50KTtcbiAgICAgIGNhc2UgTWVzc2FnZVR5cGUuRGlnaXREZWNvbXBvc2l0aW9uRXZlbnREZXNjcmlwdG9yVjA6XG4gICAgICAgIHJldHVybiB0aGlzLkdlbmVyYXRlRGlnaXREZWNvbXBvc2l0aW9uTWVzc2FnZXMob3JhY2xlRXZlbnQpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgRXJyb3IoJ0V2ZW50RGVzY3JpcHRvciBtdXN0IGJlIEVudW0gb3IgRGlnaXREZWNvbXBvc2l0aW9uJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBHZXRDb250cmFjdE9yYWNsZVBhaXJzKFxuICAgIF9jb250cmFjdEluZm86IENvbnRyYWN0SW5mbyxcbiAgKTogeyBjb250cmFjdERlc2NyaXB0b3I6IENvbnRyYWN0RGVzY3JpcHRvcjsgb3JhY2xlSW5mbzogT3JhY2xlSW5mb1YwIH1bXSB7XG4gICAgc3dpdGNoIChfY29udHJhY3RJbmZvLnR5cGUpIHtcbiAgICAgIGNhc2UgTWVzc2FnZVR5cGUuQ29udHJhY3RJbmZvVjA6IHtcbiAgICAgICAgY29uc3QgY29udHJhY3RJbmZvID0gX2NvbnRyYWN0SW5mbyBhcyBDb250cmFjdEluZm9WMDtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBjb250cmFjdERlc2NyaXB0b3I6IGNvbnRyYWN0SW5mby5jb250cmFjdERlc2NyaXB0b3IsXG4gICAgICAgICAgICBvcmFjbGVJbmZvOiBjb250cmFjdEluZm8ub3JhY2xlSW5mbyxcbiAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgICAgfVxuICAgICAgY2FzZSBNZXNzYWdlVHlwZS5Db250cmFjdEluZm9WMToge1xuICAgICAgICByZXR1cm4gKF9jb250cmFjdEluZm8gYXMgQ29udHJhY3RJbmZvVjEpLmNvbnRyYWN0T3JhY2xlUGFpcnM7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBFcnJvcignQ29udHJhY3RJbmZvIG11c3QgYmUgVjAgb3IgVjEnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIENyZWF0ZUNldEFkYXB0b3JBbmRSZWZ1bmRTaWdzKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgICBtZXNzYWdlc0xpc3Q6IE1lc3NhZ2VzW10sXG4gICAgaXNPZmZlcmVyOiBib29sZWFuLFxuICApOiBQcm9taXNlPENyZWF0ZUNldEFkYXB0b3JBbmRSZWZ1bmRTaWdzUmVzcG9uc2U+IHtcbiAgICBjb25zdCB7IGRsY09mZmVyLCBkbGNBY2NlcHQsIGRsY1R4cyB9ID0gY2hlY2tUeXBlcyh7XG4gICAgICBfZGxjT2ZmZXIsXG4gICAgICBfZGxjQWNjZXB0LFxuICAgICAgX2RsY1R4cyxcbiAgICB9KTtcbiAgICBjb25zdCBuZXR3b3JrID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWROZXR3b3JrKCk7XG5cbiAgICBjb25zdCBjZXRzSGV4ID0gZGxjVHhzLmNldHMubWFwKChjZXQpID0+IGNldC5zZXJpYWxpemUoKS50b1N0cmluZygnaGV4JykpO1xuXG4gICAgY29uc3QgZnVuZGluZ1NQSyA9IFNjcmlwdC5wMndwa2hMb2NrKFxuICAgICAgaGFzaDE2MChpc09mZmVyZXIgPyBkbGNPZmZlci5mdW5kaW5nUHViS2V5IDogZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkpLFxuICAgIClcbiAgICAgIC5zZXJpYWxpemUoKVxuICAgICAgLnNsaWNlKDEpO1xuXG4gICAgY29uc3QgZnVuZGluZ0FkZHJlc3M6IHN0cmluZyA9IGFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdChcbiAgICAgIGZ1bmRpbmdTUEssXG4gICAgICBuZXR3b3JrLFxuICAgICk7XG5cbiAgICBjb25zdCB7XG4gICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICB9ID0gYXdhaXQgdGhpcy5jbGllbnQuZmluYW5jZXdhbGxldC5xdWlja0ZpbmRBZGRyZXNzKFtmdW5kaW5nQWRkcmVzc10pO1xuXG4gICAgY29uc3QgZnVuZFByaXZhdGVLZXlQYWlyID0gYXdhaXQgdGhpcy5nZXRNZXRob2QoJ2tleVBhaXInKShkZXJpdmF0aW9uUGF0aCk7XG4gICAgY29uc3QgZnVuZFByaXZhdGVLZXkgPSBCdWZmZXIuZnJvbShmdW5kUHJpdmF0ZUtleVBhaXIuX19EKS50b1N0cmluZygnaGV4Jyk7XG5cbiAgICBjb25zdCBjb250cmFjdE9yYWNsZVBhaXJzID0gdGhpcy5HZXRDb250cmFjdE9yYWNsZVBhaXJzKFxuICAgICAgZGxjT2ZmZXIuY29udHJhY3RJbmZvLFxuICAgICk7XG5cbiAgICBjb25zdCBpbmRpY2VzID0gdGhpcy5HZXRJbmRpY2VzRnJvbVBheW91dHModGhpcy5HZXRQYXlvdXRzKF9kbGNPZmZlcikpO1xuICAgIGNvbnN0IHNpZ3M6IElTaWdbXVtdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IFtpbmRleCwgeyBvcmFjbGVJbmZvIH1dIG9mIGNvbnRyYWN0T3JhY2xlUGFpcnMuZW50cmllcygpKSB7XG4gICAgICBjb25zdCBvcmFjbGVBbm5vdW5jZW1lbnQgPSBvcmFjbGVJbmZvLmFubm91bmNlbWVudDtcblxuICAgICAgY29uc3Qgc3RhcnRpbmdJbmRleCA9IGluZGljZXNbaW5kZXhdLnN0YXJ0aW5nTWVzc2FnZXNJbmRleCxcbiAgICAgICAgZW5kaW5nSW5kZXggPSBpbmRpY2VzW2luZGV4ICsgMV0uc3RhcnRpbmdNZXNzYWdlc0luZGV4O1xuXG4gICAgICBjb25zdCBvcmFjbGVFdmVudE1lc3NhZ2VzTGlzdCA9IG1lc3NhZ2VzTGlzdC5zbGljZShcbiAgICAgICAgc3RhcnRpbmdJbmRleCxcbiAgICAgICAgZW5kaW5nSW5kZXgsXG4gICAgICApO1xuICAgICAgY29uc3Qgb3JhY2xlRXZlbnRDZXRzSGV4ID0gY2V0c0hleC5zbGljZShzdGFydGluZ0luZGV4LCBlbmRpbmdJbmRleCk7XG5cbiAgICAgIGNvbnN0IGNodW5rID0gMTAwO1xuICAgICAgY29uc3QgYWRhcHRvclNpZ1JlcXVlc3RQcm9taXNlczogUHJvbWlzZTxBZGFwdG9yUGFpcltdPltdID0gW107XG5cbiAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gb3JhY2xlRXZlbnRNZXNzYWdlc0xpc3QubGVuZ3RoOyBpIDwgajsgaSArPSBjaHVuaykge1xuICAgICAgICBjb25zdCB0ZW1wTWVzc2FnZXNMaXN0ID0gb3JhY2xlRXZlbnRNZXNzYWdlc0xpc3Quc2xpY2UoaSwgaSArIGNodW5rKTtcbiAgICAgICAgY29uc3QgdGVtcENldHNIZXggPSBvcmFjbGVFdmVudENldHNIZXguc2xpY2UoaSwgaSArIGNodW5rKTtcblxuICAgICAgICBjb25zdCBjZXRTaWduUmVxdWVzdDogQ3JlYXRlQ2V0QWRhcHRvclNpZ25hdHVyZXNSZXF1ZXN0ID0ge1xuICAgICAgICAgIG1lc3NhZ2VzTGlzdDogdGVtcE1lc3NhZ2VzTGlzdCxcbiAgICAgICAgICBjZXRzSGV4OiB0ZW1wQ2V0c0hleCxcbiAgICAgICAgICBwcml2a2V5OiBmdW5kUHJpdmF0ZUtleSxcbiAgICAgICAgICBmdW5kVHhJZDogZGxjVHhzLmZ1bmRUeC50eElkLnRvU3RyaW5nKCksXG4gICAgICAgICAgZnVuZFZvdXQ6IGRsY1R4cy5mdW5kVHhWb3V0LFxuICAgICAgICAgIGxvY2FsRnVuZFB1YmtleTogZGxjT2ZmZXIuZnVuZGluZ1B1YktleS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgcmVtb3RlRnVuZFB1YmtleTogZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIGZ1bmRJbnB1dEFtb3VudDogZGxjVHhzLmZ1bmRUeC5vdXRwdXRzW2RsY1R4cy5mdW5kVHhWb3V0XS52YWx1ZS5zYXRzLFxuICAgICAgICAgIG9yYWNsZVB1YmtleTogb3JhY2xlQW5ub3VuY2VtZW50Lm9yYWNsZVB1YmtleS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgb3JhY2xlUlZhbHVlczogb3JhY2xlQW5ub3VuY2VtZW50Lm9yYWNsZUV2ZW50Lm9yYWNsZU5vbmNlcy5tYXAoXG4gICAgICAgICAgICAobm9uY2UpID0+IG5vbmNlLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgICApLFxuICAgICAgICB9O1xuXG4gICAgICAgIGFkYXB0b3JTaWdSZXF1ZXN0UHJvbWlzZXMucHVzaChcbiAgICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLkNyZWF0ZUNldEFkYXB0b3JTaWduYXR1cmVzKFxuICAgICAgICAgICAgICBjZXRTaWduUmVxdWVzdCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuYWRhcHRvclBhaXJzO1xuICAgICAgICAgIH0pKCksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFkYXB0b3JQYWlyczogQWRhcHRvclBhaXJbXSA9IChcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoYWRhcHRvclNpZ1JlcXVlc3RQcm9taXNlcylcbiAgICAgICkuZmxhdCgpO1xuXG4gICAgICBzaWdzLnB1c2goXG4gICAgICAgIGFkYXB0b3JQYWlycy5tYXAoKGFkYXB0b3JQYWlyKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGVuY3J5cHRlZFNpZzogQnVmZmVyLmZyb20oYWRhcHRvclBhaXIuc2lnbmF0dXJlLCAnaGV4JyksXG4gICAgICAgICAgICBkbGVxUHJvb2Y6IEJ1ZmZlci5mcm9tKGFkYXB0b3JQYWlyLnByb29mLCAnaGV4JyksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlZnVuZFNpZ25SZXF1ZXN0OiBHZXRSYXdSZWZ1bmRUeFNpZ25hdHVyZVJlcXVlc3QgPSB7XG4gICAgICByZWZ1bmRUeEhleDogZGxjVHhzLnJlZnVuZFR4LnNlcmlhbGl6ZSgpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIHByaXZrZXk6IGZ1bmRQcml2YXRlS2V5LFxuICAgICAgZnVuZFR4SWQ6IGRsY1R4cy5mdW5kVHgudHhJZC50b1N0cmluZygpLFxuICAgICAgZnVuZFZvdXQ6IGRsY1R4cy5mdW5kVHhWb3V0LFxuICAgICAgbG9jYWxGdW5kUHVia2V5OiBkbGNPZmZlci5mdW5kaW5nUHViS2V5LnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIHJlbW90ZUZ1bmRQdWJrZXk6IGRsY0FjY2VwdC5mdW5kaW5nUHViS2V5LnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIGZ1bmRJbnB1dEFtb3VudDogZGxjVHhzLmZ1bmRUeC5vdXRwdXRzW2RsY1R4cy5mdW5kVHhWb3V0XS52YWx1ZS5zYXRzLFxuICAgIH07XG5cbiAgICBjb25zdCByZWZ1bmRTaWduYXR1cmUgPSBCdWZmZXIuZnJvbShcbiAgICAgIChhd2FpdCB0aGlzLkdldFJhd1JlZnVuZFR4U2lnbmF0dXJlKHJlZnVuZFNpZ25SZXF1ZXN0KSkuaGV4LFxuICAgICAgJ2hleCcsXG4gICAgKTtcblxuICAgIGNvbnN0IGNldFNpZ25hdHVyZXMgPSBuZXcgQ2V0QWRhcHRvclNpZ25hdHVyZXNWMCgpO1xuICAgIGNldFNpZ25hdHVyZXMuc2lncyA9IHNpZ3MuZmxhdCgpO1xuXG4gICAgcmV0dXJuIHsgY2V0U2lnbmF0dXJlcywgcmVmdW5kU2lnbmF0dXJlIH07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIFZlcmlmeUNldEFkYXB0b3JBbmRSZWZ1bmRTaWdzKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNTaWduOiBEbGNTaWduLFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgICBtZXNzYWdlc0xpc3Q6IE1lc3NhZ2VzW10sXG4gICAgaXNPZmZlcmVyOiBib29sZWFuLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGRsY09mZmVyLCBkbGNBY2NlcHQsIGRsY1NpZ24sIGRsY1R4cyB9ID0gY2hlY2tUeXBlcyh7XG4gICAgICBfZGxjT2ZmZXIsXG4gICAgICBfZGxjQWNjZXB0LFxuICAgICAgX2RsY1NpZ24sXG4gICAgICBfZGxjVHhzLFxuICAgIH0pO1xuXG4gICAgY29uc3QgY2V0c0hleCA9IGRsY1R4cy5jZXRzLm1hcCgoY2V0KSA9PiBjZXQuc2VyaWFsaXplKCkudG9TdHJpbmcoJ2hleCcpKTtcblxuICAgIGNvbnN0IGNodW5rID0gMTAwO1xuXG4gICAgY29uc3QgY29udHJhY3RPcmFjbGVQYWlycyA9IHRoaXMuR2V0Q29udHJhY3RPcmFjbGVQYWlycyhcbiAgICAgIGRsY09mZmVyLmNvbnRyYWN0SW5mbyxcbiAgICApO1xuXG4gICAgY29uc3QgaW5kaWNlcyA9IHRoaXMuR2V0SW5kaWNlc0Zyb21QYXlvdXRzKHRoaXMuR2V0UGF5b3V0cyhfZGxjT2ZmZXIpKTtcblxuICAgIGZvciAoY29uc3QgW2luZGV4LCB7IG9yYWNsZUluZm8gfV0gb2YgY29udHJhY3RPcmFjbGVQYWlycy5lbnRyaWVzKCkpIHtcbiAgICAgIGNvbnN0IG9yYWNsZUFubm91bmNlbWVudCA9IG9yYWNsZUluZm8uYW5ub3VuY2VtZW50O1xuXG4gICAgICBjb25zdCBzdGFydGluZ0luZGV4ID0gaW5kaWNlc1tpbmRleF0uc3RhcnRpbmdNZXNzYWdlc0luZGV4LFxuICAgICAgICBlbmRpbmdJbmRleCA9IGluZGljZXNbaW5kZXggKyAxXS5zdGFydGluZ01lc3NhZ2VzSW5kZXg7XG5cbiAgICAgIGNvbnN0IG9yYWNsZUV2ZW50TWVzc2FnZXNMaXN0ID0gbWVzc2FnZXNMaXN0LnNsaWNlKFxuICAgICAgICBzdGFydGluZ0luZGV4LFxuICAgICAgICBlbmRpbmdJbmRleCxcbiAgICAgICk7XG4gICAgICBjb25zdCBvcmFjbGVFdmVudENldHNIZXggPSBjZXRzSGV4LnNsaWNlKHN0YXJ0aW5nSW5kZXgsIGVuZGluZ0luZGV4KTtcbiAgICAgIGNvbnN0IG9yYWNsZUV2ZW50U2lncyA9IChpc09mZmVyZXJcbiAgICAgICAgPyBkbGNBY2NlcHQuY2V0U2lnbmF0dXJlcy5zaWdzXG4gICAgICAgIDogZGxjU2lnbi5jZXRTaWduYXR1cmVzLnNpZ3NcbiAgICAgICkuc2xpY2Uoc3RhcnRpbmdJbmRleCwgZW5kaW5nSW5kZXgpO1xuXG4gICAgICBjb25zdCBzaWdzVmFsaWRpdHk6IFByb21pc2U8Ym9vbGVhbj5bXSA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBpID0gMCwgaiA9IG9yYWNsZUV2ZW50TWVzc2FnZXNMaXN0Lmxlbmd0aDsgaSA8IGo7IGkgKz0gY2h1bmspIHtcbiAgICAgICAgY29uc3QgdGVtcE1lc3NhZ2VzTGlzdCA9IG9yYWNsZUV2ZW50TWVzc2FnZXNMaXN0LnNsaWNlKGksIGkgKyBjaHVuayk7XG4gICAgICAgIGNvbnN0IHRlbXBDZXRzSGV4ID0gb3JhY2xlRXZlbnRDZXRzSGV4LnNsaWNlKGksIGkgKyBjaHVuayk7XG4gICAgICAgIGNvbnN0IHRlbXBTaWdzID0gb3JhY2xlRXZlbnRTaWdzLnNsaWNlKGksIGkgKyBjaHVuayk7XG4gICAgICAgIGNvbnN0IHRlbXBBZGFwdG9yUGFpcnMgPSB0ZW1wU2lncy5tYXAoKHNpZykgPT4ge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzaWduYXR1cmU6IHNpZy5lbmNyeXB0ZWRTaWcudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgICAgcHJvb2Y6IHNpZy5kbGVxUHJvb2YudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IHZlcmlmeUNldEFkYXB0b3JTaWduYXR1cmVzUmVxdWVzdDogVmVyaWZ5Q2V0QWRhcHRvclNpZ25hdHVyZXNSZXF1ZXN0ID0ge1xuICAgICAgICAgIGNldHNIZXg6IHRlbXBDZXRzSGV4LFxuICAgICAgICAgIG1lc3NhZ2VzTGlzdDogdGVtcE1lc3NhZ2VzTGlzdCxcbiAgICAgICAgICBvcmFjbGVQdWJrZXk6IG9yYWNsZUFubm91bmNlbWVudC5vcmFjbGVQdWJrZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIG9yYWNsZVJWYWx1ZXM6IG9yYWNsZUFubm91bmNlbWVudC5vcmFjbGVFdmVudC5vcmFjbGVOb25jZXMubWFwKFxuICAgICAgICAgICAgKG5vbmNlKSA9PiBub25jZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgKSxcbiAgICAgICAgICBhZGFwdG9yUGFpcnM6IHRlbXBBZGFwdG9yUGFpcnMsXG4gICAgICAgICAgbG9jYWxGdW5kUHVia2V5OiBkbGNPZmZlci5mdW5kaW5nUHViS2V5LnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgICByZW1vdGVGdW5kUHVia2V5OiBkbGNBY2NlcHQuZnVuZGluZ1B1YktleS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgZnVuZFR4SWQ6IGRsY1R4cy5mdW5kVHgudHhJZC50b1N0cmluZygpLFxuICAgICAgICAgIGZ1bmRWb3V0OiBkbGNUeHMuZnVuZFR4Vm91dCxcbiAgICAgICAgICBmdW5kSW5wdXRBbW91bnQ6IGRsY1R4cy5mdW5kVHgub3V0cHV0c1tkbGNUeHMuZnVuZFR4Vm91dF0udmFsdWUuc2F0cyxcbiAgICAgICAgICB2ZXJpZnlSZW1vdGU6IGlzT2ZmZXJlcixcbiAgICAgICAgfTtcblxuICAgICAgICBzaWdzVmFsaWRpdHkucHVzaChcbiAgICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLlZlcmlmeUNldEFkYXB0b3JTaWduYXR1cmVzKFxuICAgICAgICAgICAgICB2ZXJpZnlDZXRBZGFwdG9yU2lnbmF0dXJlc1JlcXVlc3QsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnZhbGlkO1xuICAgICAgICAgIH0pKCksXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGxldCBhcmVTaWdzVmFsaWQgPSAoYXdhaXQgUHJvbWlzZS5hbGwoc2lnc1ZhbGlkaXR5KSkuZXZlcnkoKGIpID0+IGIpO1xuXG4gICAgICBjb25zdCB2ZXJpZnlSZWZ1bmRTaWdSZXF1ZXN0OiBWZXJpZnlSZWZ1bmRUeFNpZ25hdHVyZVJlcXVlc3QgPSB7XG4gICAgICAgIHJlZnVuZFR4SGV4OiBkbGNUeHMucmVmdW5kVHguc2VyaWFsaXplKCkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICBzaWduYXR1cmU6IGlzT2ZmZXJlclxuICAgICAgICAgID8gZGxjQWNjZXB0LnJlZnVuZFNpZ25hdHVyZS50b1N0cmluZygnaGV4JylcbiAgICAgICAgICA6IGRsY1NpZ24ucmVmdW5kU2lnbmF0dXJlLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgbG9jYWxGdW5kUHVia2V5OiBkbGNPZmZlci5mdW5kaW5nUHViS2V5LnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgcmVtb3RlRnVuZFB1YmtleTogZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICBmdW5kVHhJZDogZGxjVHhzLmZ1bmRUeC50eElkLnRvU3RyaW5nKCksXG4gICAgICAgIGZ1bmRWb3V0OiBkbGNUeHMuZnVuZFR4Vm91dCxcbiAgICAgICAgZnVuZElucHV0QW1vdW50OiBkbGNUeHMuZnVuZFR4Lm91dHB1dHNbZGxjVHhzLmZ1bmRUeFZvdXRdLnZhbHVlLnNhdHMsXG4gICAgICAgIHZlcmlmeVJlbW90ZTogaXNPZmZlcmVyLFxuICAgICAgfTtcblxuICAgICAgYXJlU2lnc1ZhbGlkID1cbiAgICAgICAgYXJlU2lnc1ZhbGlkICYmXG4gICAgICAgIChhd2FpdCB0aGlzLlZlcmlmeVJlZnVuZFR4U2lnbmF0dXJlKHZlcmlmeVJlZnVuZFNpZ1JlcXVlc3QpKS52YWxpZDtcblxuICAgICAgaWYgKCFhcmVTaWdzVmFsaWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpZ25hdHVyZXMgcmVjZWl2ZWQnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIENyZWF0ZUZ1bmRpbmdTaWdzKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgICBpc09mZmVyZXI6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8RnVuZGluZ1NpZ25hdHVyZXNWMD4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjVHhzIH0gPSBjaGVja1R5cGVzKHtcbiAgICAgIF9kbGNPZmZlcixcbiAgICAgIF9kbGNBY2NlcHQsXG4gICAgICBfZGxjVHhzLFxuICAgIH0pO1xuXG4gICAgY29uc3QgZnVuZGluZ0lucHV0cyA9IGlzT2ZmZXJlclxuICAgICAgPyBkbGNPZmZlci5mdW5kaW5nSW5wdXRzXG4gICAgICA6IGRsY0FjY2VwdC5mdW5kaW5nSW5wdXRzO1xuXG4gICAgY29uc3QgaW5wdXRzOiBJbnB1dFtdID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBmdW5kaW5nSW5wdXRzLm1hcChhc3luYyAoZnVuZGluZ0lucHV0KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmZ1bmRpbmdJbnB1dFRvSW5wdXQoZnVuZGluZ0lucHV0KTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBjb25zdCBpbnB1dFByaXZLZXlzID0gYXdhaXQgdGhpcy5HZXRQcml2S2V5c0ZvcklucHV0cyhpbnB1dHMpO1xuXG4gICAgY29uc3QgZnVuZFR4U2lncyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaW5wdXRzLm1hcChhc3luYyAoaW5wdXQsIGluZGV4KSA9PiB7XG4gICAgICAgIGNvbnN0IGZ1bmRUeFNpZ25SZXF1ZXN0OiBHZXRSYXdGdW5kVHhTaWduYXR1cmVSZXF1ZXN0ID0ge1xuICAgICAgICAgIGZ1bmRUeEhleDogZGxjVHhzLmZ1bmRUeC5zZXJpYWxpemUoKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgcHJpdmtleTogaW5wdXRQcml2S2V5c1tpbmRleF0sXG4gICAgICAgICAgcHJldlR4SWQ6IGlucHV0LnR4aWQsXG4gICAgICAgICAgcHJldlZvdXQ6IGlucHV0LnZvdXQsXG4gICAgICAgICAgYW1vdW50OiBpbnB1dC52YWx1ZSxcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gKGF3YWl0IHRoaXMuR2V0UmF3RnVuZFR4U2lnbmF0dXJlKGZ1bmRUeFNpZ25SZXF1ZXN0KSkuaGV4O1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IGlucHV0UHViS2V5cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaW5wdXRQcml2S2V5cy5tYXAoYXN5bmMgKHByaXZrZXkpID0+IHtcbiAgICAgICAgY29uc3QgcmVxUHJpdktleSA9IHtcbiAgICAgICAgICBwcml2a2V5LFxuICAgICAgICAgIGlzQ29tcHJlc3NlZDogdHJ1ZSxcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gKGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdHZXRQdWJrZXlGcm9tUHJpdmtleScpKHJlcVByaXZLZXkpKVxuICAgICAgICAgIC5wdWJrZXk7XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgY29uc3Qgd2l0bmVzc0VsZW1lbnRzOiBTY3JpcHRXaXRuZXNzVjBbXVtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmdW5kVHhTaWdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBzaWdXaXRuZXNzID0gbmV3IFNjcmlwdFdpdG5lc3NWMCgpO1xuICAgICAgc2lnV2l0bmVzcy53aXRuZXNzID0gQnVmZmVyLmZyb20oZnVuZFR4U2lnc1tpXSwgJ2hleCcpO1xuICAgICAgY29uc3QgcHViS2V5V2l0bmVzcyA9IG5ldyBTY3JpcHRXaXRuZXNzVjAoKTtcbiAgICAgIHB1YktleVdpdG5lc3Mud2l0bmVzcyA9IEJ1ZmZlci5mcm9tKGlucHV0UHViS2V5c1tpXSwgJ2hleCcpO1xuICAgICAgd2l0bmVzc0VsZW1lbnRzLnB1c2goW3NpZ1dpdG5lc3MsIHB1YktleVdpdG5lc3NdKTtcbiAgICB9XG5cbiAgICBjb25zdCBmdW5kaW5nU2lnbmF0dXJlcyA9IG5ldyBGdW5kaW5nU2lnbmF0dXJlc1YwKCk7XG4gICAgZnVuZGluZ1NpZ25hdHVyZXMud2l0bmVzc0VsZW1lbnRzID0gd2l0bmVzc0VsZW1lbnRzO1xuXG4gICAgcmV0dXJuIGZ1bmRpbmdTaWduYXR1cmVzO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBWZXJpZnlGdW5kaW5nU2lncyhcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIF9kbGNBY2NlcHQ6IERsY0FjY2VwdCxcbiAgICBfZGxjU2lnbjogRGxjU2lnbixcbiAgICBfZGxjVHhzOiBEbGNUcmFuc2FjdGlvbnMsXG4gICAgaXNPZmZlcmVyOiBib29sZWFuLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGRsY09mZmVyLCBkbGNBY2NlcHQsIGRsY1NpZ24sIGRsY1R4cyB9ID0gY2hlY2tUeXBlcyh7XG4gICAgICBfZGxjT2ZmZXIsXG4gICAgICBfZGxjQWNjZXB0LFxuICAgICAgX2RsY1NpZ24sXG4gICAgICBfZGxjVHhzLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc2lnc1ZhbGlkaXR5OiBQcm9taXNlPGJvb2xlYW4+W10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRsY1NpZ24uZnVuZGluZ1NpZ25hdHVyZXMud2l0bmVzc0VsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCB3aXRuZXNzRWxlbWVudCA9IGRsY1NpZ24uZnVuZGluZ1NpZ25hdHVyZXMud2l0bmVzc0VsZW1lbnRzW2ldO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gd2l0bmVzc0VsZW1lbnRbMF0ud2l0bmVzcy50b1N0cmluZygnaGV4Jyk7XG4gICAgICBjb25zdCBwdWJrZXkgPSB3aXRuZXNzRWxlbWVudFsxXS53aXRuZXNzLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgY29uc3QgZnVuZGluZ0lucHV0ID0gaXNPZmZlcmVyXG4gICAgICAgID8gKGRsY0FjY2VwdC5mdW5kaW5nSW5wdXRzW2ldIGFzIEZ1bmRpbmdJbnB1dFYwKVxuICAgICAgICA6IChkbGNPZmZlci5mdW5kaW5nSW5wdXRzW2ldIGFzIEZ1bmRpbmdJbnB1dFYwKTtcblxuICAgICAgY29uc3QgdmVyaWZ5RnVuZFNpZ1JlcXVlc3Q6IFZlcmlmeUZ1bmRUeFNpZ25hdHVyZVJlcXVlc3QgPSB7XG4gICAgICAgIGZ1bmRUeEhleDogZGxjVHhzLmZ1bmRUeC5zZXJpYWxpemUoKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIHNpZ25hdHVyZSxcbiAgICAgICAgcHVia2V5LFxuICAgICAgICBwcmV2VHhJZDogZnVuZGluZ0lucHV0LnByZXZUeC50eElkLnRvU3RyaW5nKCksXG4gICAgICAgIHByZXZWb3V0OiBmdW5kaW5nSW5wdXQucHJldlR4Vm91dCxcbiAgICAgICAgZnVuZElucHV0QW1vdW50OlxuICAgICAgICAgIGZ1bmRpbmdJbnB1dC5wcmV2VHgub3V0cHV0c1tmdW5kaW5nSW5wdXQucHJldlR4Vm91dF0udmFsdWUuc2F0cyxcbiAgICAgIH07XG5cbiAgICAgIHNpZ3NWYWxpZGl0eS5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5WZXJpZnlGdW5kVHhTaWduYXR1cmUoXG4gICAgICAgICAgICB2ZXJpZnlGdW5kU2lnUmVxdWVzdCxcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS52YWxpZDtcbiAgICAgICAgfSkoKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgYXJlU2lnc1ZhbGlkID0gKGF3YWl0IFByb21pc2UuYWxsKHNpZ3NWYWxpZGl0eSkpLmV2ZXJ5KChiKSA9PiBiKTtcblxuICAgIGlmICghYXJlU2lnc1ZhbGlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlcyByZWNlaXZlZCcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgQ3JlYXRlRnVuZGluZ1R4KFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNTaWduOiBEbGNTaWduLFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgICBmdW5kaW5nU2lnbmF0dXJlczogRnVuZGluZ1NpZ25hdHVyZXNWMCxcbiAgKTogUHJvbWlzZTxUeD4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjU2lnbiwgZGxjVHhzIH0gPSBjaGVja1R5cGVzKHtcbiAgICAgIF9kbGNPZmZlcixcbiAgICAgIF9kbGNBY2NlcHQsXG4gICAgICBfZGxjU2lnbixcbiAgICAgIF9kbGNUeHMsXG4gICAgfSk7XG5cbiAgICBjb25zdCB3aXRuZXNzRWxlbWVudHMgPSBbXG4gICAgICAuLi5kbGNTaWduLmZ1bmRpbmdTaWduYXR1cmVzLndpdG5lc3NFbGVtZW50cyxcbiAgICAgIC4uLmZ1bmRpbmdTaWduYXR1cmVzLndpdG5lc3NFbGVtZW50cyxcbiAgICBdO1xuICAgIGNvbnN0IGZ1bmRpbmdJbnB1dHMgPSBbXG4gICAgICAuLi5kbGNPZmZlci5mdW5kaW5nSW5wdXRzLFxuICAgICAgLi4uZGxjQWNjZXB0LmZ1bmRpbmdJbnB1dHMsXG4gICAgXTtcblxuICAgIGxldCBmdW5kVHhIZXggPSBkbGNUeHMuZnVuZFR4LnNlcmlhbGl6ZSgpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgIGF3YWl0IGFzeW5jRm9yRWFjaChcbiAgICAgIHdpdG5lc3NFbGVtZW50cyxcbiAgICAgIGFzeW5jICh3aXRuZXNzRWxlbWVudDogU2NyaXB0V2l0bmVzc1YwLCBpOiBudW1iZXIpID0+IHtcbiAgICAgICAgY29uc3Qgc2lnbmF0dXJlID0gd2l0bmVzc0VsZW1lbnRbMF0ud2l0bmVzcy50b1N0cmluZygnaGV4Jyk7XG4gICAgICAgIGNvbnN0IHB1YmtleSA9IHdpdG5lc3NFbGVtZW50WzFdLndpdG5lc3MudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgICAgIGNvbnN0IGZ1bmRpbmdJbnB1dCA9IGZ1bmRpbmdJbnB1dHNbaV0gYXMgRnVuZGluZ0lucHV0VjA7XG5cbiAgICAgICAgY29uc3QgYWRkU2lnblJlcXVlc3Q6IEFkZFNpZ25hdHVyZVRvRnVuZFRyYW5zYWN0aW9uUmVxdWVzdCA9IHtcbiAgICAgICAgICBmdW5kVHhIZXgsXG4gICAgICAgICAgc2lnbmF0dXJlLFxuICAgICAgICAgIHByZXZUeElkOiBmdW5kaW5nSW5wdXQucHJldlR4LnR4SWQudG9TdHJpbmcoKSxcbiAgICAgICAgICBwcmV2Vm91dDogZnVuZGluZ0lucHV0LnByZXZUeFZvdXQsXG4gICAgICAgICAgcHVia2V5LFxuICAgICAgICB9O1xuICAgICAgICBmdW5kVHhIZXggPSAoYXdhaXQgdGhpcy5BZGRTaWduYXR1cmVUb0Z1bmRUcmFuc2FjdGlvbihhZGRTaWduUmVxdWVzdCkpXG4gICAgICAgICAgLmhleDtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGNvbnN0IGZ1bmRUeCA9IFR4LmRlY29kZShTdHJlYW1SZWFkZXIuZnJvbUhleChmdW5kVHhIZXgpKTtcblxuICAgIHJldHVybiBmdW5kVHg7XG4gIH1cblxuICBhc3luYyBGaW5kT3V0Y29tZUluZGV4RnJvbVBvbHlub21pYWxQYXlvdXRDdXJ2ZVBpZWNlKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgY29udHJhY3REZXNjcmlwdG9yOiBDb250cmFjdERlc2NyaXB0b3JWMSxcbiAgICBjb250cmFjdE9yYWNsZVBhaXJJbmRleDogbnVtYmVyLFxuICAgIHBvbHlub21pYWxQYXlvdXRDdXJ2ZVBpZWNlOiBQb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZSxcbiAgICBvcmFjbGVBdHRlc3RhdGlvbjogT3JhY2xlQXR0ZXN0YXRpb25WMCxcbiAgICBvdXRjb21lOiBiaWdpbnQsXG4gICk6IFByb21pc2U8RmluZE91dGNvbWVSZXNwb25zZT4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIgfSA9IGNoZWNrVHlwZXMoeyBfZGxjT2ZmZXIgfSk7XG5cbiAgICBjb25zdCBwb2x5bm9taWFsQ3VydmUgPSBQb2x5bm9taWFsUGF5b3V0Q3VydmUuZnJvbVBheW91dEN1cnZlUGllY2UoXG4gICAgICBwb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZSxcbiAgICApO1xuXG4gICAgY29uc3QgY2xhbXBCTiA9ICh2YWw6IEJpZ051bWJlcikgPT5cbiAgICAgIEJpZ051bWJlci5tYXgoXG4gICAgICAgIDAsXG4gICAgICAgIEJpZ051bWJlci5taW4odmFsLCBkbGNPZmZlci5jb250cmFjdEluZm8udG90YWxDb2xsYXRlcmFsLnRvU3RyaW5nKCkpLFxuICAgICAgKTtcblxuICAgIGNvbnN0IHBheW91dCA9IGNsYW1wQk4ocG9seW5vbWlhbEN1cnZlLmdldFBheW91dChvdXRjb21lKSk7XG5cbiAgICBjb25zdCBwYXlvdXRSZXNwb25zZXMgPSB0aGlzLkdldFBheW91dHMoZGxjT2ZmZXIpO1xuICAgIGNvbnN0IHBheW91dEluZGV4T2Zmc2V0ID0gdGhpcy5HZXRJbmRpY2VzRnJvbVBheW91dHMocGF5b3V0UmVzcG9uc2VzKVtcbiAgICAgIGNvbnRyYWN0T3JhY2xlUGFpckluZGV4XG4gICAgXS5zdGFydGluZ01lc3NhZ2VzSW5kZXg7XG5cbiAgICBjb25zdCB7IHBheW91dEdyb3VwcyB9ID0gcGF5b3V0UmVzcG9uc2VzW2NvbnRyYWN0T3JhY2xlUGFpckluZGV4XTtcblxuICAgIGNvbnN0IGludGVydmFsc1NvcnRlZCA9IFtcbiAgICAgIC4uLmNvbnRyYWN0RGVzY3JpcHRvci5yb3VuZGluZ0ludGVydmFscy5pbnRlcnZhbHMsXG4gICAgXS5zb3J0KChhLCBiKSA9PiBOdW1iZXIoYi5iZWdpbkludGVydmFsKSAtIE51bWJlcihhLmJlZ2luSW50ZXJ2YWwpKTtcblxuICAgIGNvbnN0IGludGVydmFsID0gaW50ZXJ2YWxzU29ydGVkLmZpbmQoXG4gICAgICAoaW50ZXJ2YWwpID0+IE51bWJlcihvdXRjb21lKSA+PSBOdW1iZXIoaW50ZXJ2YWwuYmVnaW5JbnRlcnZhbCksXG4gICAgKTtcblxuICAgIGNvbnN0IHJvdW5kZWRQYXlvdXQgPSBCaWdJbnQoXG4gICAgICBjbGFtcEJOKFxuICAgICAgICBuZXcgQmlnTnVtYmVyKHJvdW5kUGF5b3V0KHBheW91dCwgaW50ZXJ2YWwucm91bmRpbmdNb2QpLnRvU3RyaW5nKCkpLFxuICAgICAgKS50b1N0cmluZygpLFxuICAgICk7XG5cbiAgICBjb25zdCBvdXRjb21lc0Zvcm1hdHRlZCA9IG9yYWNsZUF0dGVzdGF0aW9uLm91dGNvbWVzLm1hcCgob3V0Y29tZSkgPT5cbiAgICAgIHBhcnNlSW50KG91dGNvbWUpLFxuICAgICk7XG5cbiAgICBsZXQgaW5kZXggPSAwO1xuICAgIGxldCBncm91cEluZGV4ID0gLTE7XG4gICAgbGV0IGdyb3VwTGVuZ3RoID0gMDtcblxuICAgIGZvciAoY29uc3QgcGF5b3V0R3JvdXAgb2YgcGF5b3V0R3JvdXBzKSB7XG4gICAgICBpZiAocGF5b3V0R3JvdXAucGF5b3V0ID09PSByb3VuZGVkUGF5b3V0KSB7XG4gICAgICAgIGdyb3VwSW5kZXggPSBwYXlvdXRHcm91cC5ncm91cHMuZmluZEluZGV4KChncm91cCkgPT4ge1xuICAgICAgICAgIHJldHVybiBncm91cC5ldmVyeSgobXNnLCBpKSA9PiBtc2cgPT09IG91dGNvbWVzRm9ybWF0dGVkW2ldKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChncm91cEluZGV4ID09PSAtMSlcbiAgICAgICAgICB0aHJvdyBFcnJvcihcbiAgICAgICAgICAgICdGYWlsZWQgdG8gRmluZCBPdXRjb21lSW5kZXggRnJvbSBQb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZS4gXFxcblBheW91dCBHcm91cCBmb3VuZCBidXQgaW5jb3JyZWN0IGdyb3VwIGluZGV4JyxcbiAgICAgICAgICApO1xuICAgICAgICBpbmRleCArPSBncm91cEluZGV4O1xuICAgICAgICBncm91cExlbmd0aCA9IHBheW91dEdyb3VwLmdyb3Vwc1tncm91cEluZGV4XS5sZW5ndGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5kZXggKz0gcGF5b3V0R3JvdXAuZ3JvdXBzLmxlbmd0aDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZ3JvdXBJbmRleCA9PT0gLTEpXG4gICAgICB0aHJvdyBFcnJvcihcbiAgICAgICAgJ0ZhaWxlZCB0byBGaW5kIE91dGNvbWVJbmRleCBGcm9tIFBvbHlub21pYWxQYXlvdXRDdXJ2ZVBpZWNlLiBcXFxuUGF5b3V0IEdyb3VwIG5vdCBmb3VuZCcsXG4gICAgICApO1xuXG4gICAgcmV0dXJuIHsgaW5kZXg6IHBheW91dEluZGV4T2Zmc2V0ICsgaW5kZXgsIGdyb3VwTGVuZ3RoIH07XG4gIH1cblxuICBhc3luYyBGaW5kT3V0Y29tZUluZGV4RnJvbUh5cGVyYm9sYVBheW91dEN1cnZlUGllY2UoXG4gICAgX2RsY09mZmVyOiBEbGNPZmZlcixcbiAgICBjb250cmFjdERlc2NyaXB0b3I6IENvbnRyYWN0RGVzY3JpcHRvclYxLFxuICAgIGNvbnRyYWN0T3JhY2xlUGFpckluZGV4OiBudW1iZXIsXG4gICAgaHlwZXJib2xhUGF5b3V0Q3VydmVQaWVjZTogSHlwZXJib2xhUGF5b3V0Q3VydmVQaWVjZSxcbiAgICBvcmFjbGVBdHRlc3RhdGlvbjogT3JhY2xlQXR0ZXN0YXRpb25WMCxcbiAgICBvdXRjb21lOiBiaWdpbnQsXG4gICk6IFByb21pc2U8RmluZE91dGNvbWVSZXNwb25zZT4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIgfSA9IGNoZWNrVHlwZXMoeyBfZGxjT2ZmZXIgfSk7XG5cbiAgICBjb25zdCBoeXBlcmJvbGFDdXJ2ZSA9IEh5cGVyYm9sYVBheW91dEN1cnZlLmZyb21QYXlvdXRDdXJ2ZVBpZWNlKFxuICAgICAgaHlwZXJib2xhUGF5b3V0Q3VydmVQaWVjZSxcbiAgICApO1xuXG4gICAgY29uc3QgY2xhbXBCTiA9ICh2YWw6IEJpZ051bWJlcikgPT5cbiAgICAgIEJpZ051bWJlci5tYXgoXG4gICAgICAgIDAsXG4gICAgICAgIEJpZ051bWJlci5taW4odmFsLCBkbGNPZmZlci5jb250cmFjdEluZm8udG90YWxDb2xsYXRlcmFsLnRvU3RyaW5nKCkpLFxuICAgICAgKTtcblxuICAgIGNvbnN0IHBheW91dCA9IGNsYW1wQk4oaHlwZXJib2xhQ3VydmUuZ2V0UGF5b3V0KG91dGNvbWUpKTtcblxuICAgIGNvbnN0IHBheW91dFJlc3BvbnNlcyA9IHRoaXMuR2V0UGF5b3V0cyhkbGNPZmZlcik7XG4gICAgY29uc3QgcGF5b3V0SW5kZXhPZmZzZXQgPSB0aGlzLkdldEluZGljZXNGcm9tUGF5b3V0cyhwYXlvdXRSZXNwb25zZXMpW1xuICAgICAgY29udHJhY3RPcmFjbGVQYWlySW5kZXhcbiAgICBdLnN0YXJ0aW5nTWVzc2FnZXNJbmRleDtcblxuICAgIGNvbnN0IHsgcGF5b3V0R3JvdXBzIH0gPSBwYXlvdXRSZXNwb25zZXNbY29udHJhY3RPcmFjbGVQYWlySW5kZXhdO1xuXG4gICAgY29uc3QgaW50ZXJ2YWxzU29ydGVkID0gW1xuICAgICAgLi4uY29udHJhY3REZXNjcmlwdG9yLnJvdW5kaW5nSW50ZXJ2YWxzLmludGVydmFscyxcbiAgICBdLnNvcnQoKGEsIGIpID0+IE51bWJlcihiLmJlZ2luSW50ZXJ2YWwpIC0gTnVtYmVyKGEuYmVnaW5JbnRlcnZhbCkpO1xuXG4gICAgY29uc3QgaW50ZXJ2YWwgPSBpbnRlcnZhbHNTb3J0ZWQuZmluZChcbiAgICAgIChpbnRlcnZhbCkgPT4gTnVtYmVyKG91dGNvbWUpID49IE51bWJlcihpbnRlcnZhbC5iZWdpbkludGVydmFsKSxcbiAgICApO1xuXG4gICAgY29uc3Qgcm91bmRlZFBheW91dCA9IEJpZ0ludChcbiAgICAgIGNsYW1wQk4oXG4gICAgICAgIG5ldyBCaWdOdW1iZXIocm91bmRQYXlvdXQocGF5b3V0LCBpbnRlcnZhbC5yb3VuZGluZ01vZCkudG9TdHJpbmcoKSksXG4gICAgICApLnRvU3RyaW5nKCksXG4gICAgKTtcblxuICAgIGNvbnN0IG91dGNvbWVzRm9ybWF0dGVkID0gb3JhY2xlQXR0ZXN0YXRpb24ub3V0Y29tZXMubWFwKChvdXRjb21lKSA9PlxuICAgICAgcGFyc2VJbnQob3V0Y29tZSksXG4gICAgKTtcblxuICAgIGxldCBpbmRleCA9IDA7XG4gICAgbGV0IGdyb3VwSW5kZXggPSAtMTtcbiAgICBsZXQgZ3JvdXBMZW5ndGggPSAwO1xuXG4gICAgZm9yIChjb25zdCBwYXlvdXRHcm91cCBvZiBwYXlvdXRHcm91cHMpIHtcbiAgICAgIGlmIChwYXlvdXRHcm91cC5wYXlvdXQgPT09IHJvdW5kZWRQYXlvdXQpIHtcbiAgICAgICAgZ3JvdXBJbmRleCA9IHBheW91dEdyb3VwLmdyb3Vwcy5maW5kSW5kZXgoKGdyb3VwKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGdyb3VwLmV2ZXJ5KChtc2csIGkpID0+IG1zZyA9PT0gb3V0Y29tZXNGb3JtYXR0ZWRbaV0pO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGdyb3VwSW5kZXggPT09IC0xKVxuICAgICAgICAgIHRocm93IEVycm9yKFxuICAgICAgICAgICAgJ0ZhaWxlZCB0byBGaW5kIE91dGNvbWVJbmRleCBGcm9tIEh5cGVyYm9sYVBheW91dEN1cnZlUGllY2UuIFxcXG5QYXlvdXQgR3JvdXAgZm91bmQgYnV0IGluY29ycmVjdCBncm91cCBpbmRleCcsXG4gICAgICAgICAgKTtcbiAgICAgICAgaW5kZXggKz0gZ3JvdXBJbmRleDtcbiAgICAgICAgZ3JvdXBMZW5ndGggPSBwYXlvdXRHcm91cC5ncm91cHNbZ3JvdXBJbmRleF0ubGVuZ3RoO1xuICAgICAgICBicmVhaztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGluZGV4ICs9IHBheW91dEdyb3VwLmdyb3Vwcy5sZW5ndGg7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGdyb3VwSW5kZXggPT09IC0xKVxuICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgICdGYWlsZWQgdG8gRmluZCBPdXRjb21lSW5kZXggRnJvbSBIeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlLiBcXFxuUGF5b3V0IEdyb3VwIG5vdCBmb3VuZCcsXG4gICAgICApO1xuXG4gICAgcmV0dXJuIHsgaW5kZXg6IHBheW91dEluZGV4T2Zmc2V0ICsgaW5kZXgsIGdyb3VwTGVuZ3RoIH07XG4gIH1cblxuICBhc3luYyBGaW5kT3V0Y29tZUluZGV4KFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgb3JhY2xlQXR0ZXN0YXRpb246IE9yYWNsZUF0dGVzdGF0aW9uVjAsXG4gICk6IFByb21pc2U8RmluZE91dGNvbWVSZXNwb25zZT4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIgfSA9IGNoZWNrVHlwZXMoeyBfZGxjT2ZmZXIgfSk7XG5cbiAgICBjb25zdCBjb250cmFjdE9yYWNsZVBhaXJzID0gdGhpcy5HZXRDb250cmFjdE9yYWNsZVBhaXJzKFxuICAgICAgZGxjT2ZmZXIuY29udHJhY3RJbmZvLFxuICAgICk7XG5cbiAgICBjb25zdCBjb250cmFjdE9yYWNsZVBhaXJJbmRleCA9IGNvbnRyYWN0T3JhY2xlUGFpcnMuZmluZEluZGV4KFxuICAgICAgKHsgb3JhY2xlSW5mbyB9KSA9PlxuICAgICAgICBvcmFjbGVJbmZvLmFubm91bmNlbWVudC5vcmFjbGVFdmVudC5ldmVudElkID09PVxuICAgICAgICBvcmFjbGVBdHRlc3RhdGlvbi5ldmVudElkLFxuICAgICk7XG5cbiAgICBhc3NlcnQoXG4gICAgICBjb250cmFjdE9yYWNsZVBhaXJJbmRleCAhPT0gLTEsXG4gICAgICAnT3JhY2xlQXR0ZXN0YXRpb24gbXVzdCBiZSBmb3IgYW4gZXhpc3RpbmcgT3JhY2xlRXZlbnQnLFxuICAgICk7XG5cbiAgICBjb25zdCBjb250cmFjdE9yYWNsZVBhaXIgPSBjb250cmFjdE9yYWNsZVBhaXJzW2NvbnRyYWN0T3JhY2xlUGFpckluZGV4XTtcblxuICAgIGNvbnN0IHtcbiAgICAgIGNvbnRyYWN0RGVzY3JpcHRvcjogX2NvbnRyYWN0RGVzY3JpcHRvcixcbiAgICAgIG9yYWNsZUluZm8sXG4gICAgfSA9IGNvbnRyYWN0T3JhY2xlUGFpcjtcblxuICAgIGFzc2VydChcbiAgICAgIF9jb250cmFjdERlc2NyaXB0b3IudHlwZSA9PT0gTWVzc2FnZVR5cGUuQ29udHJhY3REZXNjcmlwdG9yVjEsXG4gICAgICAnQ29udHJhY3REZXNjcmlwdG9yIG11c3QgYmUgVjEnLFxuICAgICk7XG5cbiAgICBjb25zdCBjb250cmFjdERlc2NyaXB0b3IgPSBfY29udHJhY3REZXNjcmlwdG9yIGFzIENvbnRyYWN0RGVzY3JpcHRvclYxO1xuICAgIGNvbnN0IF9wYXlvdXRGdW5jdGlvbiA9IGNvbnRyYWN0RGVzY3JpcHRvci5wYXlvdXRGdW5jdGlvbjtcblxuICAgIGFzc2VydChcbiAgICAgIF9wYXlvdXRGdW5jdGlvbi50eXBlID09PSBNZXNzYWdlVHlwZS5QYXlvdXRGdW5jdGlvblYwLFxuICAgICAgJ1BheW91dEZ1bmN0aW9uIG11c3QgYmUgVjAnLFxuICAgICk7XG5cbiAgICBjb25zdCBldmVudERlc2NyaXB0b3IgPSBvcmFjbGVJbmZvLmFubm91bmNlbWVudC5vcmFjbGVFdmVudFxuICAgICAgLmV2ZW50RGVzY3JpcHRvciBhcyBEaWdpdERlY29tcG9zaXRpb25FdmVudERlc2NyaXB0b3JWMDtcbiAgICBjb25zdCBwYXlvdXRGdW5jdGlvbiA9IF9wYXlvdXRGdW5jdGlvbiBhcyBQYXlvdXRGdW5jdGlvblYwO1xuXG4gICAgY29uc3QgYmFzZSA9IGV2ZW50RGVzY3JpcHRvci5iYXNlO1xuXG4gICAgY29uc3Qgb3V0Y29tZTogbnVtYmVyID0gWy4uLm9yYWNsZUF0dGVzdGF0aW9uLm91dGNvbWVzXVxuICAgICAgLnJldmVyc2UoKVxuICAgICAgLnJlZHVjZSgoYWNjLCB2YWwsIGkpID0+IGFjYyArIE51bWJlcih2YWwpICogYmFzZSAqKiBpLCAwKTtcblxuICAgIGNvbnN0IHBpZWNlc1NvcnRlZCA9IHBheW91dEZ1bmN0aW9uLnBpZWNlcy5zb3J0KFxuICAgICAgKGEsIGIpID0+IE51bWJlcihhLmVuZHBvaW50KSAtIE51bWJlcihiLmVuZHBvaW50KSxcbiAgICApO1xuXG4gICAgY29uc3QgcGllY2UgPSBwaWVjZXNTb3J0ZWQuZmluZCgocGllY2UpID0+IG91dGNvbWUgPCBwaWVjZS5lbmRwb2ludCk7XG5cbiAgICBzd2l0Y2ggKHBpZWNlLnBheW91dEN1cnZlUGllY2UudHlwZSkge1xuICAgICAgY2FzZSBNZXNzYWdlVHlwZS5Qb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZTpcbiAgICAgICAgcmV0dXJuIHRoaXMuRmluZE91dGNvbWVJbmRleEZyb21Qb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZShcbiAgICAgICAgICBkbGNPZmZlcixcbiAgICAgICAgICBjb250cmFjdERlc2NyaXB0b3IsXG4gICAgICAgICAgY29udHJhY3RPcmFjbGVQYWlySW5kZXgsXG4gICAgICAgICAgcGllY2UucGF5b3V0Q3VydmVQaWVjZSBhcyBQb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZSxcbiAgICAgICAgICBvcmFjbGVBdHRlc3RhdGlvbixcbiAgICAgICAgICBCaWdJbnQob3V0Y29tZSksXG4gICAgICAgICk7XG4gICAgICBjYXNlIE1lc3NhZ2VUeXBlLkh5cGVyYm9sYVBheW91dEN1cnZlUGllY2U6XG4gICAgICAgIHJldHVybiB0aGlzLkZpbmRPdXRjb21lSW5kZXhGcm9tSHlwZXJib2xhUGF5b3V0Q3VydmVQaWVjZShcbiAgICAgICAgICBkbGNPZmZlcixcbiAgICAgICAgICBjb250cmFjdERlc2NyaXB0b3IsXG4gICAgICAgICAgY29udHJhY3RPcmFjbGVQYWlySW5kZXgsXG4gICAgICAgICAgcGllY2UucGF5b3V0Q3VydmVQaWVjZSBhcyBIeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlLFxuICAgICAgICAgIG9yYWNsZUF0dGVzdGF0aW9uLFxuICAgICAgICAgIEJpZ0ludChvdXRjb21lKSxcbiAgICAgICAgKTtcbiAgICAgIGNhc2UgTWVzc2FnZVR5cGUuT2xkSHlwZXJib2xhUGF5b3V0Q3VydmVQaWVjZTpcbiAgICAgICAgcmV0dXJuIHRoaXMuRmluZE91dGNvbWVJbmRleEZyb21IeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlKFxuICAgICAgICAgIGRsY09mZmVyLFxuICAgICAgICAgIGNvbnRyYWN0RGVzY3JpcHRvcixcbiAgICAgICAgICBjb250cmFjdE9yYWNsZVBhaXJJbmRleCxcbiAgICAgICAgICBwaWVjZS5wYXlvdXRDdXJ2ZVBpZWNlIGFzIEh5cGVyYm9sYVBheW91dEN1cnZlUGllY2UsXG4gICAgICAgICAgb3JhY2xlQXR0ZXN0YXRpb24sXG4gICAgICAgICAgQmlnSW50KG91dGNvbWUpLFxuICAgICAgICApO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgRXJyb3IoJ011c3QgYmUgSHlwZXJib2xhIG9yIFBvbHlub21pYWwgY3VydmUgcGllY2UnKTtcbiAgICB9XG4gIH1cblxuICBWYWxpZGF0ZUV2ZW50KFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgb3JhY2xlQXR0ZXN0YXRpb246IE9yYWNsZUF0dGVzdGF0aW9uVjAsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIgfSA9IGNoZWNrVHlwZXMoe1xuICAgICAgX2RsY09mZmVyLFxuICAgIH0pO1xuXG4gICAgc3dpdGNoIChkbGNPZmZlci5jb250cmFjdEluZm8udHlwZSkge1xuICAgICAgY2FzZSBNZXNzYWdlVHlwZS5Db250cmFjdEluZm9WMDoge1xuICAgICAgICBjb25zdCBjb250cmFjdEluZm8gPSBkbGNPZmZlci5jb250cmFjdEluZm8gYXMgQ29udHJhY3RJbmZvVjA7XG4gICAgICAgIHN3aXRjaCAoY29udHJhY3RJbmZvLmNvbnRyYWN0RGVzY3JpcHRvci50eXBlKSB7XG4gICAgICAgICAgY2FzZSBNZXNzYWdlVHlwZS5Db250cmFjdERlc2NyaXB0b3JWMDpcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdDb250cmFjdERlc2NyaXB0b3JWMCBub3QgeWV0IHN1cHBvcnRlZCcpO1xuICAgICAgICAgIGNhc2UgTWVzc2FnZVR5cGUuQ29udHJhY3REZXNjcmlwdG9yVjE6IHtcbiAgICAgICAgICAgIGNvbnN0IG9yYWNsZUluZm8gPSBjb250cmFjdEluZm8ub3JhY2xlSW5mbztcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgb3JhY2xlSW5mby5hbm5vdW5jZW1lbnQub3JhY2xlRXZlbnQuZXZlbnRJZCAhPT1cbiAgICAgICAgICAgICAgb3JhY2xlQXR0ZXN0YXRpb24uZXZlbnRJZFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgICB0aHJvdyBFcnJvcignSW5jb3JyZWN0IE9yYWNsZSBBdHRlc3RhdGlvbi4gRXZlbnQgSWQgbXVzdCBtYXRjaC4nKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgRXJyb3IoJ0NvbnJhY3REZXNjcmlwdG9yIG11c3QgYmUgVjAgb3IgVjEnKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgTWVzc2FnZVR5cGUuQ29udHJhY3RJbmZvVjE6IHtcbiAgICAgICAgY29uc3QgY29udHJhY3RJbmZvID0gZGxjT2ZmZXIuY29udHJhY3RJbmZvIGFzIENvbnRyYWN0SW5mb1YxO1xuICAgICAgICBjb25zdCBhdHRlc3RlZE9yYWNsZUV2ZW50ID0gY29udHJhY3RJbmZvLmNvbnRyYWN0T3JhY2xlUGFpcnMuZmluZChcbiAgICAgICAgICAoeyBvcmFjbGVJbmZvIH0pID0+XG4gICAgICAgICAgICBvcmFjbGVJbmZvLmFubm91bmNlbWVudC5vcmFjbGVFdmVudC5ldmVudElkID09PVxuICAgICAgICAgICAgb3JhY2xlQXR0ZXN0YXRpb24uZXZlbnRJZCxcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIWF0dGVzdGVkT3JhY2xlRXZlbnQpXG4gICAgICAgICAgdGhyb3cgRXJyb3IoJ09yYWNsZSBldmVudCBvZiBhdHRlc3RhdGlvbiBub3QgZm91bmQuJyk7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBFcnJvcignQ29udHJhY3RJbmZvIG11c3QgYmUgVjAgb3IgVjEnKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBGaW5kQW5kU2lnbkNldChcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIF9kbGNBY2NlcHQ6IERsY0FjY2VwdCxcbiAgICBfZGxjU2lnbjogRGxjU2lnbixcbiAgICBfZGxjVHhzOiBEbGNUcmFuc2FjdGlvbnMsXG4gICAgb3JhY2xlQXR0ZXN0YXRpb246IE9yYWNsZUF0dGVzdGF0aW9uVjAsXG4gICAgaXNPZmZlcmVyPzogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxUeD4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjU2lnbiwgZGxjVHhzIH0gPSBjaGVja1R5cGVzKHtcbiAgICAgIF9kbGNPZmZlcixcbiAgICAgIF9kbGNBY2NlcHQsXG4gICAgICBfZGxjU2lnbixcbiAgICAgIF9kbGNUeHMsXG4gICAgfSk7XG5cbiAgICBpZiAoaXNPZmZlcmVyID09PSB1bmRlZmluZWQpXG4gICAgICBpc09mZmVyZXIgPSBhd2FpdCB0aGlzLmlzT2ZmZXJlcihkbGNPZmZlciwgZGxjQWNjZXB0KTtcblxuICAgIGNvbnN0IHsgaW5kZXg6IG91dGNvbWVJbmRleCwgZ3JvdXBMZW5ndGggfSA9IGF3YWl0IHRoaXMuRmluZE91dGNvbWVJbmRleChcbiAgICAgIGRsY09mZmVyLFxuICAgICAgb3JhY2xlQXR0ZXN0YXRpb24sXG4gICAgKTtcblxuICAgIGNvbnN0IGZ1bmRQcml2YXRlS2V5ID0gYXdhaXQgdGhpcy5HZXRGdW5kUHJpdmF0ZUtleShcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgaXNPZmZlcmVyLFxuICAgICk7XG5cbiAgICBjb25zdCBzbGljZUluZGV4ID0gLShvcmFjbGVBdHRlc3RhdGlvbi5zaWduYXR1cmVzLmxlbmd0aCAtIGdyb3VwTGVuZ3RoKTtcblxuICAgIGNvbnN0IG9yYWNsZVNpZ25hdHVyZXMgPVxuICAgICAgc2xpY2VJbmRleCA9PT0gMFxuICAgICAgICA/IG9yYWNsZUF0dGVzdGF0aW9uLnNpZ25hdHVyZXNcbiAgICAgICAgOiBvcmFjbGVBdHRlc3RhdGlvbi5zaWduYXR1cmVzLnNsaWNlKDAsIHNsaWNlSW5kZXgpO1xuXG4gICAgY29uc3Qgc2lnbkNldFJlcXVlc3Q6IFNpZ25DZXRSZXF1ZXN0ID0ge1xuICAgICAgY2V0SGV4OiBkbGNUeHMuY2V0c1tvdXRjb21lSW5kZXhdLnNlcmlhbGl6ZSgpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIGZ1bmRQcml2a2V5OiBmdW5kUHJpdmF0ZUtleSxcbiAgICAgIGZ1bmRUeElkOiBkbGNUeHMuZnVuZFR4LnR4SWQudG9TdHJpbmcoKSxcbiAgICAgIGZ1bmRWb3V0OiBkbGNUeHMuZnVuZFR4Vm91dCxcbiAgICAgIGxvY2FsRnVuZFB1YmtleTogZGxjT2ZmZXIuZnVuZGluZ1B1YktleS50b1N0cmluZygnaGV4JyksXG4gICAgICByZW1vdGVGdW5kUHVia2V5OiBkbGNBY2NlcHQuZnVuZGluZ1B1YktleS50b1N0cmluZygnaGV4JyksXG4gICAgICBvcmFjbGVTaWduYXR1cmVzOiBvcmFjbGVTaWduYXR1cmVzLm1hcCgoc2lnKSA9PiBzaWcudG9TdHJpbmcoJ2hleCcpKSxcbiAgICAgIGZ1bmRJbnB1dEFtb3VudDogZGxjVHhzLmZ1bmRUeC5vdXRwdXRzW2RsY1R4cy5mdW5kVHhWb3V0XS52YWx1ZS5zYXRzLFxuICAgICAgYWRhcHRvclNpZ25hdHVyZTogaXNPZmZlcmVyXG4gICAgICAgID8gZGxjQWNjZXB0LmNldFNpZ25hdHVyZXMuc2lnc1tvdXRjb21lSW5kZXhdLmVuY3J5cHRlZFNpZy50b1N0cmluZyhcbiAgICAgICAgICAgICdoZXgnLFxuICAgICAgICAgIClcbiAgICAgICAgOiBkbGNTaWduLmNldFNpZ25hdHVyZXMuc2lnc1tvdXRjb21lSW5kZXhdLmVuY3J5cHRlZFNpZy50b1N0cmluZygnaGV4JyksXG4gICAgfTtcblxuICAgIGNvbnN0IGZpbmFsQ2V0ID0gKGF3YWl0IHRoaXMuU2lnbkNldChzaWduQ2V0UmVxdWVzdCkpLmhleDtcblxuICAgIHJldHVybiBUeC5kZWNvZGUoU3RyZWFtUmVhZGVyLmZyb21IZXgoZmluYWxDZXQpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgR2V0RnVuZEFkZHJlc3MoXG4gICAgZGxjT2ZmZXI6IERsY09mZmVyVjAsXG4gICAgZGxjQWNjZXB0OiBEbGNBY2NlcHRWMCxcbiAgICBpc09mZmVyZXI6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgY29uc3QgbmV0d29yayA9IGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGVkTmV0d29yaygpO1xuXG4gICAgY29uc3QgZnVuZGluZ1NQSyA9IFNjcmlwdC5wMndwa2hMb2NrKFxuICAgICAgaGFzaDE2MChpc09mZmVyZXIgPyBkbGNPZmZlci5mdW5kaW5nUHViS2V5IDogZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkpLFxuICAgIClcbiAgICAgIC5zZXJpYWxpemUoKVxuICAgICAgLnNsaWNlKDEpO1xuXG4gICAgY29uc3QgZnVuZGluZ0FkZHJlc3M6IHN0cmluZyA9IGFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdChcbiAgICAgIGZ1bmRpbmdTUEssXG4gICAgICBuZXR3b3JrLFxuICAgICk7XG5cbiAgICByZXR1cm4gZnVuZGluZ0FkZHJlc3M7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIEdldEZ1bmRLZXlQYWlyKFxuICAgIGRsY09mZmVyOiBEbGNPZmZlclYwLFxuICAgIGRsY0FjY2VwdDogRGxjQWNjZXB0VjAsXG4gICAgaXNPZmZlcmVyOiBib29sZWFuLFxuICApOiBQcm9taXNlPEVDUGFpckludGVyZmFjZT4ge1xuICAgIGNvbnN0IGZ1bmRpbmdBZGRyZXNzID0gYXdhaXQgdGhpcy5HZXRGdW5kQWRkcmVzcyhcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgaXNPZmZlcmVyLFxuICAgICk7XG5cbiAgICBjb25zdCB7IGRlcml2YXRpb25QYXRoIH0gPSBhd2FpdCB0aGlzLmdldE1ldGhvZCgnZ2V0V2FsbGV0QWRkcmVzcycpKFxuICAgICAgZnVuZGluZ0FkZHJlc3MsXG4gICAgKTtcbiAgICBjb25zdCBrZXlQYWlyOiBFQ1BhaXJJbnRlcmZhY2UgPSBhd2FpdCB0aGlzLmdldE1ldGhvZCgna2V5UGFpcicpKFxuICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgKTtcblxuICAgIHJldHVybiBrZXlQYWlyO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBHZXRGdW5kUHJpdmF0ZUtleShcbiAgICBkbGNPZmZlcjogRGxjT2ZmZXJWMCxcbiAgICBkbGNBY2NlcHQ6IERsY0FjY2VwdFYwLFxuICAgIGlzT2ZmZXJlcjogYm9vbGVhbixcbiAgKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBmdW5kUHJpdmF0ZUtleVBhaXI6IEVDUGFpckludGVyZmFjZSA9IGF3YWl0IHRoaXMuR2V0RnVuZEtleVBhaXIoXG4gICAgICBkbGNPZmZlcixcbiAgICAgIGRsY0FjY2VwdCxcbiAgICAgIGlzT2ZmZXJlcixcbiAgICApO1xuXG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGZ1bmRQcml2YXRlS2V5UGFpci5wcml2YXRlS2V5KS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICBhc3luYyBDcmVhdGVDbG9zZVJhd1R4cyhcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIF9kbGNBY2NlcHQ6IERsY0FjY2VwdCxcbiAgICBfZGxjVHhzOiBEbGNUcmFuc2FjdGlvbnMsXG4gICAgY2xvc2VJbnB1dEFtb3VudDogYmlnaW50LFxuICAgIGlzT2ZmZXJlcjogYm9vbGVhbixcbiAgICBfZGxjQ2xvc2VzOiBEbGNDbG9zZVtdID0gW10sXG4gICAgZnVuZGluZ0lucHV0cz86IEZ1bmRpbmdJbnB1dFtdLFxuICAgIGluaXRpYXRvclBheW91dHM/OiBiaWdpbnRbXSxcbiAgKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjVHhzIH0gPSBjaGVja1R5cGVzKHtcbiAgICAgIF9kbGNPZmZlcixcbiAgICAgIF9kbGNBY2NlcHQsXG4gICAgICBfZGxjVHhzLFxuICAgIH0pO1xuICAgIGNvbnN0IG5ldHdvcmsgPSBhd2FpdCB0aGlzLmdldENvbm5lY3RlZE5ldHdvcmsoKTtcblxuICAgIGxldCBmaW5hbGl6ZXI6IER1YWxDbG9zaW5nVHhGaW5hbGl6ZXI7XG4gICAgaWYgKF9kbGNDbG9zZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBmaW5hbGl6ZXIgPSBuZXcgRHVhbENsb3NpbmdUeEZpbmFsaXplcihcbiAgICAgICAgZnVuZGluZ0lucHV0cyxcbiAgICAgICAgZGxjT2ZmZXIucGF5b3V0U1BLLFxuICAgICAgICBkbGNBY2NlcHQucGF5b3V0U1BLLFxuICAgICAgICBkbGNPZmZlci5mZWVSYXRlUGVyVmIsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHJhd1RyYW5zYWN0aW9uUmVxdWVzdFByb21pc2VzOiBQcm9taXNlPHN0cmluZz5bXSA9IFtdO1xuICAgIGNvbnN0IHJhd0Nsb3NlVHhzID0gW107XG5cbiAgICBjb25zdCBudW1QYXlvdXRzID1cbiAgICAgIF9kbGNDbG9zZXMubGVuZ3RoID09PSAwID8gaW5pdGlhdG9yUGF5b3V0cy5sZW5ndGggOiBfZGxjQ2xvc2VzLmxlbmd0aDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtUGF5b3V0czsgaSsrKSB7XG4gICAgICBsZXQgb2ZmZXJQYXlvdXRWYWx1ZSA9IEJpZ0ludCgwKTtcbiAgICAgIGxldCBhY2NlcHRQYXlvdXRWYWx1ZSA9IEJpZ0ludCgwKTtcblxuICAgICAgaWYgKF9kbGNDbG9zZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnN0IHBheW91dCA9IGluaXRpYXRvclBheW91dHNbaV07XG4gICAgICAgIGNvbnN0IHBheW91dE1pbnVzT2ZmZXJGZWVzID1cbiAgICAgICAgICBmaW5hbGl6ZXIub2ZmZXJJbml0aWF0b3JGZWVzID4gcGF5b3V0XG4gICAgICAgICAgICA/IEJpZ0ludCgwKVxuICAgICAgICAgICAgOiBwYXlvdXQgLSBmaW5hbGl6ZXIub2ZmZXJJbml0aWF0b3JGZWVzO1xuICAgICAgICBjb25zdCBjb2xsYXRlcmFsTWludXNQYXlvdXQgPVxuICAgICAgICAgIHBheW91dCA+IGRsY09mZmVyLmNvbnRyYWN0SW5mby50b3RhbENvbGxhdGVyYWxcbiAgICAgICAgICAgID8gQmlnSW50KDApXG4gICAgICAgICAgICA6IGRsY09mZmVyLmNvbnRyYWN0SW5mby50b3RhbENvbGxhdGVyYWwgLSBwYXlvdXQ7XG5cbiAgICAgICAgb2ZmZXJQYXlvdXRWYWx1ZSA9IGlzT2ZmZXJlclxuICAgICAgICAgID8gY2xvc2VJbnB1dEFtb3VudCArIHBheW91dE1pbnVzT2ZmZXJGZWVzXG4gICAgICAgICAgOiBjb2xsYXRlcmFsTWludXNQYXlvdXQ7XG5cbiAgICAgICAgYWNjZXB0UGF5b3V0VmFsdWUgPSBpc09mZmVyZXJcbiAgICAgICAgICA/IGNvbGxhdGVyYWxNaW51c1BheW91dFxuICAgICAgICAgIDogY2xvc2VJbnB1dEFtb3VudCArIHBheW91dE1pbnVzT2ZmZXJGZWVzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgZGxjQ2xvc2UgPSBjaGVja1R5cGVzKHsgX2RsY0Nsb3NlOiBfZGxjQ2xvc2VzW2ldIH0pLmRsY0Nsb3NlO1xuXG4gICAgICAgIG9mZmVyUGF5b3V0VmFsdWUgPSBkbGNDbG9zZS5vZmZlclBheW91dFNhdG9zaGlzO1xuICAgICAgICBhY2NlcHRQYXlvdXRWYWx1ZSA9IGRsY0Nsb3NlLmFjY2VwdFBheW91dFNhdG9zaGlzO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0eE91dHMgPSBbXTtcblxuICAgICAgaWYgKE51bWJlcihvZmZlclBheW91dFZhbHVlKSA+IDApIHtcbiAgICAgICAgdHhPdXRzLnB1c2goe1xuICAgICAgICAgIGFkZHJlc3M6IGFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdChkbGNPZmZlci5wYXlvdXRTUEssIG5ldHdvcmspLFxuICAgICAgICAgIGFtb3VudDogTnVtYmVyKG9mZmVyUGF5b3V0VmFsdWUpLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKE51bWJlcihhY2NlcHRQYXlvdXRWYWx1ZSkgPiAwKSB7XG4gICAgICAgIHR4T3V0cy5wdXNoKHtcbiAgICAgICAgICBhZGRyZXNzOiBhZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoZGxjQWNjZXB0LnBheW91dFNQSywgbmV0d29yayksXG4gICAgICAgICAgYW1vdW50OiBOdW1iZXIoYWNjZXB0UGF5b3V0VmFsdWUpLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGRsY09mZmVyLnBheW91dFNlcmlhbElkID4gZGxjQWNjZXB0LnBheW91dFNlcmlhbElkKSB0eE91dHMucmV2ZXJzZSgpO1xuXG4gICAgICBjb25zdCByYXdUcmFuc2FjdGlvblJlcXVlc3Q6IENyZWF0ZVJhd1RyYW5zYWN0aW9uUmVxdWVzdCA9IHtcbiAgICAgICAgdmVyc2lvbjogMixcbiAgICAgICAgbG9ja3RpbWU6IDAsXG4gICAgICAgIHR4aW5zOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgdHhpZDogZGxjVHhzLmZ1bmRUeC50eElkLnNlcmlhbGl6ZSgpLnJldmVyc2UoKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgICB2b3V0OiBkbGNUeHMuZnVuZFR4Vm91dCxcbiAgICAgICAgICAgIHNlcXVlbmNlOiAwLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHR4b3V0czogdHhPdXRzLFxuICAgICAgfTtcblxuICAgICAgcmF3VHJhbnNhY3Rpb25SZXF1ZXN0UHJvbWlzZXMucHVzaChcbiAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdDcmVhdGVSYXdUcmFuc2FjdGlvbicpKFxuICAgICAgICAgICAgcmF3VHJhbnNhY3Rpb25SZXF1ZXN0LFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmhleDtcbiAgICAgICAgfSkoKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgaGV4czogc3RyaW5nW10gPSBhd2FpdCBQcm9taXNlLmFsbChyYXdUcmFuc2FjdGlvblJlcXVlc3RQcm9taXNlcyk7XG5cbiAgICByYXdDbG9zZVR4cy5wdXNoKGhleHMpO1xuXG4gICAgcmV0dXJuIHJhd0Nsb3NlVHhzLmZsYXQoKTtcbiAgfVxuXG4gIGFzeW5jIENyZWF0ZVNpZ25hdHVyZUhhc2hlcyhcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIF9kbGNBY2NlcHQ6IERsY0FjY2VwdCxcbiAgICBfZGxjVHhzOiBEbGNUcmFuc2FjdGlvbnMsXG4gICAgcmF3Q2xvc2VUeHM6IHN0cmluZ1tdLFxuICApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgeyBkbGNPZmZlciwgZGxjQWNjZXB0LCBkbGNUeHMgfSA9IGNoZWNrVHlwZXMoe1xuICAgICAgX2RsY09mZmVyLFxuICAgICAgX2RsY0FjY2VwdCxcbiAgICAgIF9kbGNUeHMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBuZXR3b3JrID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWROZXR3b3JrKCk7XG5cbiAgICBjb25zdCBmdW5kaW5nUHViS2V5cyA9XG4gICAgICBCdWZmZXIuY29tcGFyZShkbGNPZmZlci5mdW5kaW5nUHViS2V5LCBkbGNBY2NlcHQuZnVuZGluZ1B1YktleSkgPT09IC0xXG4gICAgICAgID8gW2RsY09mZmVyLmZ1bmRpbmdQdWJLZXksIGRsY0FjY2VwdC5mdW5kaW5nUHViS2V5XVxuICAgICAgICA6IFtkbGNBY2NlcHQuZnVuZGluZ1B1YktleSwgZGxjT2ZmZXIuZnVuZGluZ1B1YktleV07XG5cbiAgICBjb25zdCBwMm1zID0gcGF5bWVudHMucDJtcyh7XG4gICAgICBtOiAyLFxuICAgICAgcHVia2V5czogZnVuZGluZ1B1YktleXMsXG4gICAgICBuZXR3b3JrLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcGF5bWVudFZhcmlhbnQgPSBwYXltZW50cy5wMndzaCh7XG4gICAgICByZWRlZW06IHAybXMsXG4gICAgICBuZXR3b3JrLFxuICAgIH0pO1xuXG4gICAgY29uc3Qgc2lnSGFzaFJlcXVlc3RQcm9taXNlczogUHJvbWlzZTxzdHJpbmc+W10gPSBbXTtcbiAgICBjb25zdCBzaWdIYXNoZXMgPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmF3Q2xvc2VUeHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHJhd1R4ID0gcmF3Q2xvc2VUeHNbaV07XG5cbiAgICAgIGNvbnN0IHNpZ0hhc2hSZXF1ZXN0OiBDcmVhdGVTaWduYXR1cmVIYXNoUmVxdWVzdCA9IHtcbiAgICAgICAgdHg6IHJhd1R4LFxuICAgICAgICB0eGluOiB7XG4gICAgICAgICAgdHhpZDogZGxjVHhzLmZ1bmRUeC50eElkLnNlcmlhbGl6ZSgpLnJldmVyc2UoKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgdm91dDogZGxjVHhzLmZ1bmRUeFZvdXQsXG4gICAgICAgICAga2V5RGF0YToge1xuICAgICAgICAgICAgaGV4OiBwYXltZW50VmFyaWFudC5yZWRlZW0ub3V0cHV0LnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgICAgIHR5cGU6ICdyZWRlZW1fc2NyaXB0JyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGFtb3VudDogTnVtYmVyKGRsY1R4cy5mdW5kVHgub3V0cHV0c1tkbGNUeHMuZnVuZFR4Vm91dF0udmFsdWUuc2F0cyksXG4gICAgICAgICAgaGFzaFR5cGU6ICdwMndzaCcsXG4gICAgICAgICAgc2lnaGFzaFR5cGU6ICdhbGwnLFxuICAgICAgICAgIHNpZ2hhc2hBbnlvbmVDYW5QYXk6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgc2lnSGFzaFJlcXVlc3RQcm9taXNlcy5wdXNoKFxuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5nZXRNZXRob2QoJ0NyZWF0ZVNpZ25hdHVyZUhhc2gnKShcbiAgICAgICAgICAgIHNpZ0hhc2hSZXF1ZXN0LFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnNpZ2hhc2g7XG4gICAgICAgIH0pKCksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHNpZ2hhc2hlczogc3RyaW5nW10gPSBhd2FpdCBQcm9taXNlLmFsbChzaWdIYXNoUmVxdWVzdFByb21pc2VzKTtcblxuICAgIHNpZ0hhc2hlcy5wdXNoKHNpZ2hhc2hlcyk7XG5cbiAgICByZXR1cm4gc2lnSGFzaGVzLmZsYXQoKTtcbiAgfVxuXG4gIGFzeW5jIENhbGN1bGF0ZUVjU2lnbmF0dXJlSGFzaGVzKFxuICAgIHNpZ0hhc2hlczogc3RyaW5nW10sXG4gICAgcHJpdktleTogc3RyaW5nLFxuICApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3QgY2ZkTmV0d29yayA9IGF3YWl0IHRoaXMuR2V0Q2ZkTmV0d29yaygpO1xuXG4gICAgY29uc3Qgc2lnc1JlcXVlc3RQcm9taXNlczogUHJvbWlzZTxzdHJpbmc+W10gPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2lnSGFzaGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBzaWdIYXNoID0gc2lnSGFzaGVzW2ldO1xuXG4gICAgICBjb25zdCBjYWxjdWxhdGVFY1NpZ25hdHVyZVJlcXVlc3Q6IENhbGN1bGF0ZUVjU2lnbmF0dXJlUmVxdWVzdCA9IHtcbiAgICAgICAgc2lnaGFzaDogc2lnSGFzaCxcbiAgICAgICAgcHJpdmtleURhdGE6IHtcbiAgICAgICAgICBwcml2a2V5OiBwcml2S2V5LFxuICAgICAgICAgIHdpZjogZmFsc2UsXG4gICAgICAgICAgbmV0d29yazogY2ZkTmV0d29yayxcbiAgICAgICAgfSxcbiAgICAgICAgaXNHcmluZFI6IHRydWUsXG4gICAgICB9O1xuXG4gICAgICBzaWdzUmVxdWVzdFByb21pc2VzLnB1c2goXG4gICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmdldE1ldGhvZCgnQ2FsY3VsYXRlRWNTaWduYXR1cmUnKShcbiAgICAgICAgICAgIGNhbGN1bGF0ZUVjU2lnbmF0dXJlUmVxdWVzdCxcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5zaWduYXR1cmU7XG4gICAgICAgIH0pKCksXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHNpZ3M6IHN0cmluZ1tdID0gYXdhaXQgUHJvbWlzZS5hbGwoc2lnc1JlcXVlc3RQcm9taXNlcyk7XG5cbiAgICByZXR1cm4gc2lncy5mbGF0KCk7XG4gIH1cblxuICBhc3luYyBWZXJpZnlTaWduYXR1cmVzKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgICBfZGxjQ2xvc2VzOiBEbGNDbG9zZVtdLFxuICAgIHJhd0Nsb3NlVHhzOiBzdHJpbmdbXSxcbiAgICBpc09mZmVyZXI6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjVHhzIH0gPSBjaGVja1R5cGVzKHtcbiAgICAgIF9kbGNPZmZlcixcbiAgICAgIF9kbGNBY2NlcHQsXG4gICAgICBfZGxjVHhzLFxuICAgIH0pO1xuXG4gICAgY29uc3QgZGxjQ2xvc2VzID0gX2RsY0Nsb3Nlcy5tYXAoXG4gICAgICAoX2RsY0Nsb3NlKSA9PiBjaGVja1R5cGVzKHsgX2RsY0Nsb3NlIH0pLmRsY0Nsb3NlLFxuICAgICk7XG5cbiAgICBjb25zdCBuZXR3b3JrID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWROZXR3b3JrKCk7XG5cbiAgICBjb25zdCBmdW5kaW5nUHViS2V5cyA9XG4gICAgICBCdWZmZXIuY29tcGFyZShkbGNPZmZlci5mdW5kaW5nUHViS2V5LCBkbGNBY2NlcHQuZnVuZGluZ1B1YktleSkgPT09IC0xXG4gICAgICAgID8gW2RsY09mZmVyLmZ1bmRpbmdQdWJLZXksIGRsY0FjY2VwdC5mdW5kaW5nUHViS2V5XVxuICAgICAgICA6IFtkbGNBY2NlcHQuZnVuZGluZ1B1YktleSwgZGxjT2ZmZXIuZnVuZGluZ1B1YktleV07XG5cbiAgICBjb25zdCBwMm1zID0gcGF5bWVudHMucDJtcyh7XG4gICAgICBtOiAyLFxuICAgICAgcHVia2V5czogZnVuZGluZ1B1YktleXMsXG4gICAgICBuZXR3b3JrLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcGF5bWVudFZhcmlhbnQgPSBwYXltZW50cy5wMndzaCh7XG4gICAgICByZWRlZW06IHAybXMsXG4gICAgICBuZXR3b3JrLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcHVia2V5ID0gaXNPZmZlcmVyID8gZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkgOiBkbGNPZmZlci5mdW5kaW5nUHViS2V5O1xuXG4gICAgY29uc3Qgc2lnc1ZhbGlkaXR5OiBQcm9taXNlPGJvb2xlYW4+W10gPSBbXTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmF3Q2xvc2VUeHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHJhd1R4ID0gcmF3Q2xvc2VUeHNbaV07XG4gICAgICBjb25zdCBkbGNDbG9zZSA9IGRsY0Nsb3Nlc1tpXTtcblxuICAgICAgY29uc3QgdmVyaWZ5U2lnbmF0dXJlUmVxdWVzdDogVmVyaWZ5U2lnbmF0dXJlUmVxdWVzdCA9IHtcbiAgICAgICAgdHg6IHJhd1R4LFxuICAgICAgICB0eGluOiB7XG4gICAgICAgICAgdHhpZDogZGxjVHhzLmZ1bmRUeC50eElkLnNlcmlhbGl6ZSgpLnJldmVyc2UoKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgdm91dDogZGxjVHhzLmZ1bmRUeFZvdXQsXG4gICAgICAgICAgc2lnbmF0dXJlOiBkbGNDbG9zZS5jbG9zZVNpZ25hdHVyZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgcHVia2V5OiBwdWJrZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAgIHJlZGVlbVNjcmlwdDogcGF5bWVudFZhcmlhbnQucmVkZWVtLm91dHB1dC50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgaGFzaFR5cGU6ICdwMndzaCcsXG4gICAgICAgICAgc2lnaGFzaFR5cGU6ICdhbGwnLFxuICAgICAgICAgIHNpZ2hhc2hBbnlvbmVDYW5QYXk6IGZhbHNlLFxuICAgICAgICAgIGFtb3VudDogTnVtYmVyKGRsY1R4cy5mdW5kVHgub3V0cHV0c1tkbGNUeHMuZnVuZFR4Vm91dF0udmFsdWUuc2F0cyksXG4gICAgICAgIH0sXG4gICAgICB9O1xuXG4gICAgICBzaWdzVmFsaWRpdHkucHVzaChcbiAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdWZXJpZnlTaWduYXR1cmUnKShcbiAgICAgICAgICAgIHZlcmlmeVNpZ25hdHVyZVJlcXVlc3QsXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2Uuc3VjY2VzcztcbiAgICAgICAgfSkoKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgYXJlU2lnc1ZhbGlkID0gKGF3YWl0IFByb21pc2UuYWxsKHNpZ3NWYWxpZGl0eSkpLmV2ZXJ5KChiKSA9PiBiKTtcbiAgICByZXR1cm4gYXJlU2lnc1ZhbGlkO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIHdoZXRoZXIgd2FsbGV0IGlzIG9mZmVyZXIgb2YgRGxjT2ZmZXIgb3IgRGxjQWNjZXB0XG4gICAqIEBwYXJhbSBkbGNPZmZlciBEbGMgT2ZmZXIgTWVzc2FnZVxuICAgKiBAcGFyYW0gZGxjQWNjZXB0IERsYyBBY2NlcHQgTWVzc2FnZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn1cbiAgICovXG4gIGFzeW5jIGlzT2ZmZXJlcihcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIF9kbGNBY2NlcHQ6IERsY0FjY2VwdCxcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgeyBkbGNPZmZlciwgZGxjQWNjZXB0IH0gPSBjaGVja1R5cGVzKHtcbiAgICAgIF9kbGNPZmZlcixcbiAgICAgIF9kbGNBY2NlcHQsXG4gICAgfSk7XG4gICAgY29uc3QgbmV0d29yayA9IGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGVkTmV0d29yaygpO1xuXG4gICAgY29uc3Qgb2ZmZXJGdW5kaW5nU1BLID0gU2NyaXB0LnAyd3BraExvY2soaGFzaDE2MChkbGNPZmZlci5mdW5kaW5nUHViS2V5KSlcbiAgICAgIC5zZXJpYWxpemUoKVxuICAgICAgLnNsaWNlKDEpO1xuICAgIGNvbnN0IGFjY2VwdEZ1bmRpbmdTUEsgPSBTY3JpcHQucDJ3cGtoTG9jayhoYXNoMTYwKGRsY0FjY2VwdC5mdW5kaW5nUHViS2V5KSlcbiAgICAgIC5zZXJpYWxpemUoKVxuICAgICAgLnNsaWNlKDEpO1xuXG4gICAgY29uc3Qgb2ZmZXJGdW5kaW5nQWRkcmVzczogc3RyaW5nID0gYWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0KFxuICAgICAgb2ZmZXJGdW5kaW5nU1BLLFxuICAgICAgbmV0d29yayxcbiAgICApO1xuXG4gICAgY29uc3QgYWNjZXB0RnVuZGluZ0FkZHJlc3M6IHN0cmluZyA9IGFkZHJlc3MuZnJvbU91dHB1dFNjcmlwdChcbiAgICAgIGFjY2VwdEZ1bmRpbmdTUEssXG4gICAgICBuZXR3b3JrLFxuICAgICk7XG5cbiAgICBsZXQgd2FsbGV0QWRkcmVzczogQWRkcmVzcyA9IGF3YWl0IHRoaXMuY2xpZW50LmZpbmFuY2V3YWxsZXQucXVpY2tGaW5kQWRkcmVzcyhcbiAgICAgIFtvZmZlckZ1bmRpbmdBZGRyZXNzXSxcbiAgICApO1xuICAgIGlmICh3YWxsZXRBZGRyZXNzKSByZXR1cm4gdHJ1ZTtcbiAgICB3YWxsZXRBZGRyZXNzID0gYXdhaXQgdGhpcy5jbGllbnQuZmluYW5jZXdhbGxldC5xdWlja0ZpbmRBZGRyZXNzKFtcbiAgICAgIGFjY2VwdEZ1bmRpbmdBZGRyZXNzLFxuICAgIF0pO1xuICAgIGlmICh3YWxsZXRBZGRyZXNzKSByZXR1cm4gZmFsc2U7XG5cbiAgICB0aHJvdyBFcnJvcignV2FsbGV0IEFkZHJlc3Mgbm90IGZvdW5kIGZvciBEbGNPZmZlciBvciBEbGNBY2NlcHQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgRExDIE9mZmVyIE1lc3NhZ2VcbiAgICogQHBhcmFtIGNvbnRyYWN0SW5mbyBDb250cmFjdEluZm8gVExWIChWMCBvciBWMSlcbiAgICogQHBhcmFtIG9mZmVyQ29sbGF0ZXJhbFNhdG9zaGlzIEFtb3VudCBETEMgSW5pdGlhdG9yIGlzIHB1dHRpbmcgaW50byB0aGUgY29udHJhY3RcbiAgICogQHBhcmFtIGZlZVJhdGVQZXJWYiBGZWUgcmF0ZSBpbiBzYXRvc2hpIHBlciB2aXJ0dWFsIGJ5dGUgdGhhdCBib3RoIHNpZGVzIHVzZSB0byBjb21wdXRlIGZlZXMgaW4gZnVuZGluZyB0eFxuICAgKiBAcGFyYW0gY2V0TG9ja3RpbWUgVGhlIG5Mb2NrVGltZSB0byBiZSBwdXQgb24gQ0VUc1xuICAgKiBAcGFyYW0gcmVmdW5kTG9ja3RpbWUgVGhlIG5Mb2NrVGltZSB0byBiZSBwdXQgb24gdGhlIHJlZnVuZCB0cmFuc2FjdGlvblxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxEbGNPZmZlcj59XG4gICAqL1xuICBhc3luYyBjcmVhdGVEbGNPZmZlcihcbiAgICBjb250cmFjdEluZm86IENvbnRyYWN0SW5mbyxcbiAgICBvZmZlckNvbGxhdGVyYWxTYXRvc2hpczogYmlnaW50LFxuICAgIGZlZVJhdGVQZXJWYjogYmlnaW50LFxuICAgIGNldExvY2t0aW1lOiBudW1iZXIsXG4gICAgcmVmdW5kTG9ja3RpbWU6IG51bWJlcixcbiAgICBmaXhlZElucHV0cz86IElucHV0W10sXG4gICk6IFByb21pc2U8RGxjT2ZmZXI+IHtcbiAgICBjb250cmFjdEluZm8udmFsaWRhdGUoKTtcbiAgICBjb25zdCBuZXR3b3JrID0gYXdhaXQgdGhpcy5nZXRDb25uZWN0ZWROZXR3b3JrKCk7XG5cbiAgICBjb25zdCBkbGNPZmZlciA9IG5ldyBEbGNPZmZlclYwKCk7XG5cbiAgICBjb25zdCB7XG4gICAgICBmdW5kaW5nUHViS2V5LFxuICAgICAgcGF5b3V0U1BLLFxuICAgICAgcGF5b3V0U2VyaWFsSWQsXG4gICAgICBmdW5kaW5nSW5wdXRzOiBfZnVuZGluZ0lucHV0cyxcbiAgICAgIGNoYW5nZVNQSyxcbiAgICAgIGNoYW5nZVNlcmlhbElkLFxuICAgIH0gPSBhd2FpdCB0aGlzLkluaXRpYWxpemUoXG4gICAgICBvZmZlckNvbGxhdGVyYWxTYXRvc2hpcyxcbiAgICAgIGZlZVJhdGVQZXJWYixcbiAgICAgIGZpeGVkSW5wdXRzLFxuICAgICk7XG5cbiAgICBfZnVuZGluZ0lucHV0cy5mb3JFYWNoKChpbnB1dCkgPT5cbiAgICAgIGFzc2VydChcbiAgICAgICAgaW5wdXQudHlwZSA9PT0gTWVzc2FnZVR5cGUuRnVuZGluZ0lucHV0VjAsXG4gICAgICAgICdGdW5kaW5nSW5wdXQgbXVzdCBiZSBWMCcsXG4gICAgICApLFxuICAgICk7XG5cbiAgICBjb25zdCBmdW5kaW5nSW5wdXRzOiBGdW5kaW5nSW5wdXRWMFtdID0gX2Z1bmRpbmdJbnB1dHMubWFwKFxuICAgICAgKGlucHV0KSA9PiBpbnB1dCBhcyBGdW5kaW5nSW5wdXRWMCxcbiAgICApO1xuXG4gICAgY29uc3QgZnVuZE91dHB1dFNlcmlhbElkID0gZ2VuZXJhdGVTZXJpYWxJZCgpO1xuXG4gICAgYXNzZXJ0KFxuICAgICAgY2hhbmdlU2VyaWFsSWQgIT09IGZ1bmRPdXRwdXRTZXJpYWxJZCxcbiAgICAgICdjaGFuZ2VTZXJpYWxJZCBjYW5ub3QgZXF1YWwgdGhlIGZ1bmRPdXRwdXRTZXJpYWxJZCcsXG4gICAgKTtcblxuICAgIGRsY09mZmVyLmNvbnRyYWN0RmxhZ3MgPSBCdWZmZXIuZnJvbSgnMDAnLCAnaGV4Jyk7XG4gICAgZGxjT2ZmZXIuY2hhaW5IYXNoID0gY2hhaW5IYXNoRnJvbU5ldHdvcmsobmV0d29yayk7XG4gICAgZGxjT2ZmZXIuY29udHJhY3RJbmZvID0gY29udHJhY3RJbmZvO1xuICAgIGRsY09mZmVyLmZ1bmRpbmdQdWJLZXkgPSBmdW5kaW5nUHViS2V5O1xuICAgIGRsY09mZmVyLnBheW91dFNQSyA9IHBheW91dFNQSztcbiAgICBkbGNPZmZlci5wYXlvdXRTZXJpYWxJZCA9IHBheW91dFNlcmlhbElkO1xuICAgIGRsY09mZmVyLm9mZmVyQ29sbGF0ZXJhbFNhdG9zaGlzID0gb2ZmZXJDb2xsYXRlcmFsU2F0b3NoaXM7XG4gICAgZGxjT2ZmZXIuZnVuZGluZ0lucHV0cyA9IGZ1bmRpbmdJbnB1dHM7XG4gICAgZGxjT2ZmZXIuY2hhbmdlU1BLID0gY2hhbmdlU1BLO1xuICAgIGRsY09mZmVyLmNoYW5nZVNlcmlhbElkID0gY2hhbmdlU2VyaWFsSWQ7XG4gICAgZGxjT2ZmZXIuZnVuZE91dHB1dFNlcmlhbElkID0gZGxjT2ZmZXIuZnVuZE91dHB1dFNlcmlhbElkID0gZnVuZE91dHB1dFNlcmlhbElkO1xuICAgIGRsY09mZmVyLmZlZVJhdGVQZXJWYiA9IGZlZVJhdGVQZXJWYjtcbiAgICBkbGNPZmZlci5jZXRMb2NrdGltZSA9IGNldExvY2t0aW1lO1xuICAgIGRsY09mZmVyLnJlZnVuZExvY2t0aW1lID0gcmVmdW5kTG9ja3RpbWU7XG5cbiAgICBhc3NlcnQoXG4gICAgICAoKCkgPT4ge1xuICAgICAgICBjb25zdCBmaW5hbGl6ZXIgPSBuZXcgRHVhbEZ1bmRpbmdUeEZpbmFsaXplcihcbiAgICAgICAgICBkbGNPZmZlci5mdW5kaW5nSW5wdXRzLFxuICAgICAgICAgIGRsY09mZmVyLnBheW91dFNQSyxcbiAgICAgICAgICBkbGNPZmZlci5jaGFuZ2VTUEssXG4gICAgICAgICAgbnVsbCxcbiAgICAgICAgICBudWxsLFxuICAgICAgICAgIG51bGwsXG4gICAgICAgICAgZGxjT2ZmZXIuZmVlUmF0ZVBlclZiLFxuICAgICAgICApO1xuICAgICAgICBjb25zdCBmdW5kaW5nID0gZnVuZGluZ0lucHV0cy5yZWR1Y2UoKHRvdGFsLCBpbnB1dCkgPT4ge1xuICAgICAgICAgIHJldHVybiB0b3RhbCArIGlucHV0LnByZXZUeC5vdXRwdXRzW2lucHV0LnByZXZUeFZvdXRdLnZhbHVlLnNhdHM7XG4gICAgICAgIH0sIEJpZ0ludCgwKSk7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmRpbmcgPj0gb2ZmZXJDb2xsYXRlcmFsU2F0b3NoaXMgKyBmaW5hbGl6ZXIub2ZmZXJGZWVzO1xuICAgICAgfSkoKSxcbiAgICAgICdmdW5kaW5nSW5wdXRzIGZvciBkbGNPZmZlciBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBvZmZlckNvbGxhdGVyYWxTYXRvc2hpcyBwbHVzIG9mZmVyRmVlcycsXG4gICAgKTtcblxuICAgIGRsY09mZmVyLnZhbGlkYXRlKCk7XG5cbiAgICByZXR1cm4gZGxjT2ZmZXI7XG4gIH1cblxuICAvKipcbiAgICogQWNjZXB0IERMQyBPZmZlclxuICAgKiBAcGFyYW0gX2RsY09mZmVyIERsYyBPZmZlciBNZXNzYWdlXG4gICAqIEBwYXJhbSBmaXhlZElucHV0cyBPcHRpb25hbCBpbnB1dHMgdG8gdXNlIGZvciBGdW5kaW5nIElucHV0c1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBY2NlcHREbGNPZmZlclJlc3BvbnNlfVxuICAgKi9cbiAgYXN5bmMgYWNjZXB0RGxjT2ZmZXIoXG4gICAgX2RsY09mZmVyOiBEbGNPZmZlcixcbiAgICBmaXhlZElucHV0cz86IElucHV0W10sXG4gICk6IFByb21pc2U8QWNjZXB0RGxjT2ZmZXJSZXNwb25zZT4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIgfSA9IGNoZWNrVHlwZXMoeyBfZGxjT2ZmZXIgfSk7XG4gICAgZGxjT2ZmZXIudmFsaWRhdGUoKTtcblxuICAgIGNvbnN0IGFjY2VwdENvbGxhdGVyYWxTYXRvc2hpcyA9XG4gICAgICBkbGNPZmZlci5jb250cmFjdEluZm8udG90YWxDb2xsYXRlcmFsIC0gZGxjT2ZmZXIub2ZmZXJDb2xsYXRlcmFsU2F0b3NoaXM7XG5cbiAgICBhc3NlcnQoXG4gICAgICBhY2NlcHRDb2xsYXRlcmFsU2F0b3NoaXMgPT09XG4gICAgICAgIGRsY09mZmVyLmNvbnRyYWN0SW5mby50b3RhbENvbGxhdGVyYWwgLVxuICAgICAgICAgIGRsY09mZmVyLm9mZmVyQ29sbGF0ZXJhbFNhdG9zaGlzLFxuICAgICAgJ2FjY2VwdENvbGxhdGVyaWFsU2F0b3NoaXMgc2hvdWxkIGVxdWFsIHRvdGFsQ29sbGF0ZXJhbCAtIG9mZmVyQ29sbGF0ZXJhbFNhdG9zaGlzJyxcbiAgICApO1xuXG4gICAgY29uc3Qge1xuICAgICAgZnVuZGluZ1B1YktleSxcbiAgICAgIHBheW91dFNQSyxcbiAgICAgIHBheW91dFNlcmlhbElkLFxuICAgICAgZnVuZGluZ0lucHV0czogX2Z1bmRpbmdJbnB1dHMsXG4gICAgICBjaGFuZ2VTUEssXG4gICAgICBjaGFuZ2VTZXJpYWxJZCxcbiAgICB9ID0gYXdhaXQgdGhpcy5Jbml0aWFsaXplKFxuICAgICAgYWNjZXB0Q29sbGF0ZXJhbFNhdG9zaGlzLFxuICAgICAgZGxjT2ZmZXIuZmVlUmF0ZVBlclZiLFxuICAgICAgZml4ZWRJbnB1dHMsXG4gICAgKTtcblxuICAgIGFzc2VydChcbiAgICAgIEJ1ZmZlci5jb21wYXJlKGRsY09mZmVyLmZ1bmRpbmdQdWJLZXksIGZ1bmRpbmdQdWJLZXkpICE9PSAwLFxuICAgICAgJ0RsY09mZmVyIGFuZCBEbGNBY2NlcHQgRnVuZGluZ1B1YktleSBjYW5ub3QgYmUgdGhlIHNhbWUnLFxuICAgICk7XG5cbiAgICBfZnVuZGluZ0lucHV0cy5mb3JFYWNoKChpbnB1dCkgPT5cbiAgICAgIGFzc2VydChcbiAgICAgICAgaW5wdXQudHlwZSA9PT0gTWVzc2FnZVR5cGUuRnVuZGluZ0lucHV0VjAsXG4gICAgICAgICdGdW5kaW5nSW5wdXQgbXVzdCBiZSBWMCcsXG4gICAgICApLFxuICAgICk7XG5cbiAgICBjb25zdCBmdW5kaW5nSW5wdXRzOiBGdW5kaW5nSW5wdXRWMFtdID0gX2Z1bmRpbmdJbnB1dHMubWFwKFxuICAgICAgKGlucHV0KSA9PiBpbnB1dCBhcyBGdW5kaW5nSW5wdXRWMCxcbiAgICApO1xuXG4gICAgY29uc3QgZGxjQWNjZXB0ID0gbmV3IERsY0FjY2VwdFYwKCk7XG5cbiAgICBkbGNBY2NlcHQudGVtcENvbnRyYWN0SWQgPSBzaGEyNTYoZGxjT2ZmZXIuc2VyaWFsaXplKCkpO1xuICAgIGRsY0FjY2VwdC5hY2NlcHRDb2xsYXRlcmFsU2F0b3NoaXMgPSBhY2NlcHRDb2xsYXRlcmFsU2F0b3NoaXM7XG4gICAgZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkgPSBmdW5kaW5nUHViS2V5O1xuICAgIGRsY0FjY2VwdC5wYXlvdXRTUEsgPSBwYXlvdXRTUEs7XG4gICAgZGxjQWNjZXB0LnBheW91dFNlcmlhbElkID0gZGxjQWNjZXB0LnBheW91dFNlcmlhbElkID0gcGF5b3V0U2VyaWFsSWQ7XG4gICAgZGxjQWNjZXB0LmZ1bmRpbmdJbnB1dHMgPSBmdW5kaW5nSW5wdXRzO1xuICAgIGRsY0FjY2VwdC5jaGFuZ2VTUEsgPSBjaGFuZ2VTUEs7XG4gICAgZGxjQWNjZXB0LmNoYW5nZVNlcmlhbElkID0gZGxjQWNjZXB0LmNoYW5nZVNlcmlhbElkID0gY2hhbmdlU2VyaWFsSWQ7XG5cbiAgICBhc3NlcnQoXG4gICAgICBkbGNBY2NlcHQuY2hhbmdlU2VyaWFsSWQgIT09IGRsY09mZmVyLmZ1bmRPdXRwdXRTZXJpYWxJZCxcbiAgICAgICdjaGFuZ2VTZXJpYWxJZCBjYW5ub3QgZXF1YWwgdGhlIGZ1bmRPdXRwdXRTZXJpYWxJZCcsXG4gICAgKTtcblxuICAgIGFzc2VydChcbiAgICAgIGRsY09mZmVyLnBheW91dFNlcmlhbElkICE9PSBkbGNBY2NlcHQucGF5b3V0U2VyaWFsSWQsXG4gICAgICAnb2ZmZXIucGF5b3V0U2VyaWFsSWQgY2Fubm90IGVxdWFsIGFjY2VwdC5wYXlvdXRTZXJpYWxJZCcsXG4gICAgKTtcblxuICAgIGFzc2VydChcbiAgICAgICgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGlkcyA9IFtcbiAgICAgICAgICBkbGNPZmZlci5jaGFuZ2VTZXJpYWxJZCxcbiAgICAgICAgICBkbGNBY2NlcHQuY2hhbmdlU2VyaWFsSWQsXG4gICAgICAgICAgZGxjT2ZmZXIuZnVuZE91dHB1dFNlcmlhbElkLFxuICAgICAgICBdO1xuICAgICAgICByZXR1cm4gbmV3IFNldChpZHMpLnNpemUgPT09IGlkcy5sZW5ndGg7XG4gICAgICB9KSgpLFxuICAgICAgJ29mZmVyLmNoYW5nZVNlcmlhbElELCBhY2NlcHQuY2hhbmdlU2VyaWFsSWQgYW5kIGZ1bmRPdXRwdXRTZXJpYWxJZCBtdXN0IGJlIHVuaXF1ZScsXG4gICAgKTtcblxuICAgIGRsY0FjY2VwdC52YWxpZGF0ZSgpO1xuXG4gICAgYXNzZXJ0KFxuICAgICAgKCgpID0+IHtcbiAgICAgICAgY29uc3QgZmluYWxpemVyID0gbmV3IER1YWxGdW5kaW5nVHhGaW5hbGl6ZXIoXG4gICAgICAgICAgZGxjT2ZmZXIuZnVuZGluZ0lucHV0cyxcbiAgICAgICAgICBkbGNPZmZlci5wYXlvdXRTUEssXG4gICAgICAgICAgZGxjT2ZmZXIuY2hhbmdlU1BLLFxuICAgICAgICAgIGRsY0FjY2VwdC5mdW5kaW5nSW5wdXRzLFxuICAgICAgICAgIGRsY0FjY2VwdC5wYXlvdXRTUEssXG4gICAgICAgICAgZGxjQWNjZXB0LmNoYW5nZVNQSyxcbiAgICAgICAgICBkbGNPZmZlci5mZWVSYXRlUGVyVmIsXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGZ1bmRpbmcgPSBmdW5kaW5nSW5wdXRzLnJlZHVjZSgodG90YWwsIGlucHV0KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRvdGFsICsgaW5wdXQucHJldlR4Lm91dHB1dHNbaW5wdXQucHJldlR4Vm91dF0udmFsdWUuc2F0cztcbiAgICAgICAgfSwgQmlnSW50KDApKTtcblxuICAgICAgICByZXR1cm4gZnVuZGluZyA+PSBhY2NlcHRDb2xsYXRlcmFsU2F0b3NoaXMgKyBmaW5hbGl6ZXIuYWNjZXB0RmVlcztcbiAgICAgIH0pKCksXG4gICAgICAnZnVuZGluZ0lucHV0cyBmb3IgZGxjQWNjZXB0IG11c3QgYmUgZ3JlYXRlciB0aGFuIGFjY2VwdENvbGxhdGVyYWxTYXRvc2hpcyBwbHVzIGFjY2VwdEZlZXMnLFxuICAgICk7XG5cbiAgICBjb25zdCB7IGRsY1RyYW5zYWN0aW9ucywgbWVzc2FnZXNMaXN0IH0gPSBhd2FpdCB0aGlzLmNyZWF0ZURsY1R4cyhcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICk7XG5cbiAgICBjb25zdCB7XG4gICAgICBjZXRTaWduYXR1cmVzLFxuICAgICAgcmVmdW5kU2lnbmF0dXJlLFxuICAgIH0gPSBhd2FpdCB0aGlzLkNyZWF0ZUNldEFkYXB0b3JBbmRSZWZ1bmRTaWdzKFxuICAgICAgZGxjT2ZmZXIsXG4gICAgICBkbGNBY2NlcHQsXG4gICAgICBkbGNUcmFuc2FjdGlvbnMsXG4gICAgICBtZXNzYWdlc0xpc3QsXG4gICAgICBmYWxzZSxcbiAgICApO1xuXG4gICAgYXNzZXJ0KFxuICAgICAgZGxjVHJhbnNhY3Rpb25zLnR5cGUgPT09IE1lc3NhZ2VUeXBlLkRsY1RyYW5zYWN0aW9uc1YwLFxuICAgICAgJ0RsY1RyYW5zYWN0aW9ucyBtdXN0IGJlIFYwJyxcbiAgICApO1xuICAgIGNvbnN0IF9kbGNUcmFuc2FjdGlvbnMgPSBkbGNUcmFuc2FjdGlvbnMgYXMgRGxjVHJhbnNhY3Rpb25zVjA7XG5cbiAgICBjb25zdCBjb250cmFjdElkID0geG9yKFxuICAgICAgX2RsY1RyYW5zYWN0aW9ucy5mdW5kVHgudHhJZC5zZXJpYWxpemUoKSxcbiAgICAgIGRsY0FjY2VwdC50ZW1wQ29udHJhY3RJZCxcbiAgICApO1xuICAgIF9kbGNUcmFuc2FjdGlvbnMuY29udHJhY3RJZCA9IGNvbnRyYWN0SWQ7XG5cbiAgICBkbGNBY2NlcHQuY2V0U2lnbmF0dXJlcyA9IGNldFNpZ25hdHVyZXM7XG4gICAgZGxjQWNjZXB0LnJlZnVuZFNpZ25hdHVyZSA9IHJlZnVuZFNpZ25hdHVyZTtcbiAgICBkbGNBY2NlcHQubmVnb3RpYXRpb25GaWVsZHMgPSBuZXcgTmVnb3RpYXRpb25GaWVsZHNWMCgpO1xuXG4gICAgcmV0dXJuIHsgZGxjQWNjZXB0LCBkbGNUcmFuc2FjdGlvbnM6IF9kbGNUcmFuc2FjdGlvbnMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduIERsYyBBY2NlcHQgTWVzc2FnZVxuICAgKiBAcGFyYW0gX2RsY09mZmVyIERsYyBPZmZlciBNZXNzYWdlXG4gICAqIEBwYXJhbSBfZGxjQWNjZXB0IERsYyBBY2NlcHQgTWVzc2FnZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTaWduRGxjQWNjZXB0UmVzcG9uc2V9XG4gICAqL1xuICBhc3luYyBzaWduRGxjQWNjZXB0KFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICApOiBQcm9taXNlPFNpZ25EbGNBY2NlcHRSZXNwb25zZT4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCB9ID0gY2hlY2tUeXBlcyh7XG4gICAgICBfZGxjT2ZmZXIsXG4gICAgICBfZGxjQWNjZXB0LFxuICAgIH0pO1xuICAgIGRsY09mZmVyLnZhbGlkYXRlKCk7XG4gICAgZGxjQWNjZXB0LnZhbGlkYXRlKCk7XG5cbiAgICBhc3NlcnQoXG4gICAgICBCdWZmZXIuY29tcGFyZShkbGNPZmZlci5mdW5kaW5nUHViS2V5LCBkbGNBY2NlcHQuZnVuZGluZ1B1YktleSkgIT09IDAsXG4gICAgICAnRGxjT2ZmZXIgYW5kIERsY0FjY2VwdCBGdW5kaW5nUHViS2V5IGNhbm5vdCBiZSB0aGUgc2FtZScsXG4gICAgKTtcblxuICAgIGNvbnN0IGRsY1NpZ24gPSBuZXcgRGxjU2lnblYwKCk7XG5cbiAgICBjb25zdCB7IGRsY1RyYW5zYWN0aW9ucywgbWVzc2FnZXNMaXN0IH0gPSBhd2FpdCB0aGlzLmNyZWF0ZURsY1R4cyhcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICk7XG5cbiAgICBhd2FpdCB0aGlzLlZlcmlmeUNldEFkYXB0b3JBbmRSZWZ1bmRTaWdzKFxuICAgICAgZGxjT2ZmZXIsXG4gICAgICBkbGNBY2NlcHQsXG4gICAgICBkbGNTaWduLFxuICAgICAgZGxjVHJhbnNhY3Rpb25zLFxuICAgICAgbWVzc2FnZXNMaXN0LFxuICAgICAgdHJ1ZSxcbiAgICApO1xuXG4gICAgY29uc3Qge1xuICAgICAgY2V0U2lnbmF0dXJlcyxcbiAgICAgIHJlZnVuZFNpZ25hdHVyZSxcbiAgICB9ID0gYXdhaXQgdGhpcy5DcmVhdGVDZXRBZGFwdG9yQW5kUmVmdW5kU2lncyhcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgZGxjVHJhbnNhY3Rpb25zLFxuICAgICAgbWVzc2FnZXNMaXN0LFxuICAgICAgdHJ1ZSxcbiAgICApO1xuXG4gICAgY29uc3QgZnVuZGluZ1NpZ25hdHVyZXMgPSBhd2FpdCB0aGlzLkNyZWF0ZUZ1bmRpbmdTaWdzKFxuICAgICAgZGxjT2ZmZXIsXG4gICAgICBkbGNBY2NlcHQsXG4gICAgICBkbGNUcmFuc2FjdGlvbnMsXG4gICAgICB0cnVlLFxuICAgICk7XG5cbiAgICBjb25zdCBkbGNUeHMgPSBkbGNUcmFuc2FjdGlvbnMgYXMgRGxjVHJhbnNhY3Rpb25zVjA7XG5cbiAgICBjb25zdCBjb250cmFjdElkID0geG9yKFxuICAgICAgZGxjVHhzLmZ1bmRUeC50eElkLnNlcmlhbGl6ZSgpLFxuICAgICAgZGxjQWNjZXB0LnRlbXBDb250cmFjdElkLFxuICAgICk7XG5cbiAgICBhc3NlcnQoXG4gICAgICBCdWZmZXIuY29tcGFyZShcbiAgICAgICAgY29udHJhY3RJZCxcbiAgICAgICAgeG9yKGRsY1R4cy5mdW5kVHgudHhJZC5zZXJpYWxpemUoKSwgZGxjQWNjZXB0LnRlbXBDb250cmFjdElkKSxcbiAgICAgICkgPT09IDAsXG4gICAgICAnY29udHJhY3RJZCBtdXN0IGJlIHRoZSB4b3Igb2YgZnVuZGluZyB0eGlkLCBmdW5kaW5nT3V0cHV0SW5kZXggYW5kIHRoZSB0ZW1wQ29udHJhY3RJZCcsXG4gICAgKTtcblxuICAgIGRsY1R4cy5jb250cmFjdElkID0gY29udHJhY3RJZDtcblxuICAgIGRsY1NpZ24uY29udHJhY3RJZCA9IGNvbnRyYWN0SWQ7XG4gICAgZGxjU2lnbi5jZXRTaWduYXR1cmVzID0gY2V0U2lnbmF0dXJlcztcbiAgICBkbGNTaWduLnJlZnVuZFNpZ25hdHVyZSA9IHJlZnVuZFNpZ25hdHVyZTtcbiAgICBkbGNTaWduLmZ1bmRpbmdTaWduYXR1cmVzID0gZnVuZGluZ1NpZ25hdHVyZXM7XG5cbiAgICByZXR1cm4geyBkbGNTaWduLCBkbGNUcmFuc2FjdGlvbnM6IGRsY1R4cyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmFsaXplIERsYyBTaWduXG4gICAqIEBwYXJhbSBfZGxjT2ZmZXIgRGxjIE9mZmVyIE1lc3NhZ2VcbiAgICogQHBhcmFtIF9kbGNBY2NlcHQgRGxjIEFjY2VwdCBNZXNzYWdlXG4gICAqIEBwYXJhbSBfZGxjU2lnbiBEbGMgU2lnbiBNZXNzYWdlXG4gICAqIEBwYXJhbSBfZGxjVHhzIERsYyBUcmFuc2FjdGlvbnMgTWVzc2FnZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUeD59XG4gICAqL1xuICBhc3luYyBmaW5hbGl6ZURsY1NpZ24oXG4gICAgX2RsY09mZmVyOiBEbGNPZmZlcixcbiAgICBfZGxjQWNjZXB0OiBEbGNBY2NlcHQsXG4gICAgX2RsY1NpZ246IERsY1NpZ24sXG4gICAgX2RsY1R4czogRGxjVHJhbnNhY3Rpb25zLFxuICApOiBQcm9taXNlPFR4PiB7XG4gICAgY29uc3QgeyBkbGNPZmZlciwgZGxjQWNjZXB0LCBkbGNTaWduLCBkbGNUeHMgfSA9IGNoZWNrVHlwZXMoe1xuICAgICAgX2RsY09mZmVyLFxuICAgICAgX2RsY0FjY2VwdCxcbiAgICAgIF9kbGNTaWduLFxuICAgICAgX2RsY1R4cyxcbiAgICB9KTtcblxuICAgIGNvbnN0IHBheW91dFJlc3BvbnNlcyA9IHRoaXMuR2V0UGF5b3V0cyhkbGNPZmZlcik7XG4gICAgY29uc3QgeyBtZXNzYWdlc0xpc3QgfSA9IHRoaXMuRmxhdHRlblBheW91dHMocGF5b3V0UmVzcG9uc2VzKTtcblxuICAgIGF3YWl0IHRoaXMuVmVyaWZ5Q2V0QWRhcHRvckFuZFJlZnVuZFNpZ3MoXG4gICAgICBkbGNPZmZlcixcbiAgICAgIGRsY0FjY2VwdCxcbiAgICAgIGRsY1NpZ24sXG4gICAgICBkbGNUeHMsXG4gICAgICBtZXNzYWdlc0xpc3QsXG4gICAgICBmYWxzZSxcbiAgICApO1xuXG4gICAgYXdhaXQgdGhpcy5WZXJpZnlGdW5kaW5nU2lncyhkbGNPZmZlciwgZGxjQWNjZXB0LCBkbGNTaWduLCBkbGNUeHMsIGZhbHNlKTtcblxuICAgIGNvbnN0IGZ1bmRpbmdTaWduYXR1cmVzID0gYXdhaXQgdGhpcy5DcmVhdGVGdW5kaW5nU2lncyhcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgZGxjVHhzLFxuICAgICAgZmFsc2UsXG4gICAgKTtcblxuICAgIGNvbnN0IGZ1bmRUeCA9IGF3YWl0IHRoaXMuQ3JlYXRlRnVuZGluZ1R4KFxuICAgICAgZGxjT2ZmZXIsXG4gICAgICBkbGNBY2NlcHQsXG4gICAgICBkbGNTaWduLFxuICAgICAgZGxjVHhzLFxuICAgICAgZnVuZGluZ1NpZ25hdHVyZXMsXG4gICAgKTtcblxuICAgIHJldHVybiBmdW5kVHg7XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZSBETENcbiAgICogQHBhcmFtIF9kbGNPZmZlciBEbGMgT2ZmZXIgTWVzc2FnZVxuICAgKiBAcGFyYW0gX2RsY0FjY2VwdCBEbGMgQWNjZXB0IE1lc3NhZ2VcbiAgICogQHBhcmFtIF9kbGNTaWduIERsYyBTaWduIE1lc3NhZ2VcbiAgICogQHBhcmFtIF9kbGNUeHMgRGxjIFRyYW5zYWN0aW9ucyBNZXNzYWdlXG4gICAqIEBwYXJhbSBvcmFjbGVBdHRlc3RhdGlvbiBPcmFjbGUgQXR0ZXN0YXRpb25zIFRMViAoVjApXG4gICAqIEBwYXJhbSBpc09mZmVyZXIgV2hldGhlciBwYXJ0eSBpcyBEbGMgT2ZmZXJlclxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUeD59XG4gICAqL1xuICBhc3luYyBleGVjdXRlKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNTaWduOiBEbGNTaWduLFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgICBvcmFjbGVBdHRlc3RhdGlvbjogT3JhY2xlQXR0ZXN0YXRpb25WMCxcbiAgICBpc09mZmVyZXI/OiBib29sZWFuLFxuICApOiBQcm9taXNlPFR4PiB7XG4gICAgY29uc3QgeyBkbGNPZmZlciwgZGxjQWNjZXB0LCBkbGNTaWduLCBkbGNUeHMgfSA9IGNoZWNrVHlwZXMoe1xuICAgICAgX2RsY09mZmVyLFxuICAgICAgX2RsY0FjY2VwdCxcbiAgICAgIF9kbGNTaWduLFxuICAgICAgX2RsY1R4cyxcbiAgICB9KTtcblxuICAgIGlmIChpc09mZmVyZXIgPT09IHVuZGVmaW5lZClcbiAgICAgIGlzT2ZmZXJlciA9IGF3YWl0IHRoaXMuaXNPZmZlcmVyKGRsY09mZmVyLCBkbGNBY2NlcHQpO1xuXG4gICAgdGhpcy5WYWxpZGF0ZUV2ZW50KGRsY09mZmVyLCBvcmFjbGVBdHRlc3RhdGlvbik7XG5cbiAgICByZXR1cm4gdGhpcy5GaW5kQW5kU2lnbkNldChcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgZGxjU2lnbixcbiAgICAgIGRsY1R4cyxcbiAgICAgIG9yYWNsZUF0dGVzdGF0aW9uLFxuICAgICAgaXNPZmZlcmVyLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmVmdW5kIERMQ1xuICAgKiBAcGFyYW0gX2RsY09mZmVyIERsYyBPZmZlciBNZXNzYWdlXG4gICAqIEBwYXJhbSBfZGxjQWNjZXB0IERsYyBBY2NlcHQgTWVzc2FnZVxuICAgKiBAcGFyYW0gX2RsY1NpZ24gRGxjIFNpZ24gTWVzc2FnZVxuICAgKiBAcGFyYW0gX2RsY1R4cyBEbGMgVHJhbnNhY3Rpb25zIG1lc3NhZ2VcbiAgICogQHJldHVybnMge1Byb21pc2U8VHg+fVxuICAgKi9cbiAgYXN5bmMgcmVmdW5kKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNTaWduOiBEbGNTaWduLFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgKTogUHJvbWlzZTxUeD4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjU2lnbiwgZGxjVHhzIH0gPSBjaGVja1R5cGVzKHtcbiAgICAgIF9kbGNPZmZlcixcbiAgICAgIF9kbGNBY2NlcHQsXG4gICAgICBfZGxjU2lnbixcbiAgICAgIF9kbGNUeHMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBzaWduYXR1cmVzID1cbiAgICAgIEJ1ZmZlci5jb21wYXJlKGRsY09mZmVyLmZ1bmRpbmdQdWJLZXksIGRsY0FjY2VwdC5mdW5kaW5nUHViS2V5KSA9PT0gLTFcbiAgICAgICAgPyBbXG4gICAgICAgICAgICBkbGNTaWduLnJlZnVuZFNpZ25hdHVyZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgICBkbGNBY2NlcHQucmVmdW5kU2lnbmF0dXJlLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgICBdXG4gICAgICAgIDogW1xuICAgICAgICAgICAgZGxjQWNjZXB0LnJlZnVuZFNpZ25hdHVyZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgICBkbGNTaWduLnJlZnVuZFNpZ25hdHVyZS50b1N0cmluZygnaGV4JyksXG4gICAgICAgICAgXTtcblxuICAgIGNvbnN0IGFkZFNpZ3NUb1JlZnVuZFR4UmVxdWVzdDogQWRkU2lnbmF0dXJlc1RvUmVmdW5kVHhSZXF1ZXN0ID0ge1xuICAgICAgcmVmdW5kVHhIZXg6IGRsY1R4cy5yZWZ1bmRUeC5zZXJpYWxpemUoKS50b1N0cmluZygnaGV4JyksXG4gICAgICBzaWduYXR1cmVzLFxuICAgICAgZnVuZFR4SWQ6IGRsY1R4cy5mdW5kVHgudHhJZC50b1N0cmluZygpLFxuICAgICAgZnVuZFZvdXQ6IGRsY1R4cy5mdW5kVHhWb3V0LFxuICAgICAgbG9jYWxGdW5kUHVia2V5OiBkbGNPZmZlci5mdW5kaW5nUHViS2V5LnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIHJlbW90ZUZ1bmRQdWJrZXk6IGRsY0FjY2VwdC5mdW5kaW5nUHViS2V5LnRvU3RyaW5nKCdoZXgnKSxcbiAgICB9O1xuXG4gICAgY29uc3QgcmVmdW5kSGV4ID0gKFxuICAgICAgYXdhaXQgdGhpcy5BZGRTaWduYXR1cmVzVG9SZWZ1bmRUeChhZGRTaWdzVG9SZWZ1bmRUeFJlcXVlc3QpXG4gICAgKS5oZXg7XG5cbiAgICByZXR1cm4gVHguZGVjb2RlKFN0cmVhbVJlYWRlci5mcm9tSGV4KHJlZnVuZEhleCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdvYWwgb2YgY3JlYXRlRGxjQ2xvc2UgaXMgZm9yIGFsaWNlICh0aGUgaW5pdGlhdG9yKSB0b1xuICAgKiAxLiB0YWtlIGRsY29mZmVyLCBhY2NlcHQsIGFuZCBzaWduIG1lc3NhZ2VzLiBDcmVhdGUgYSBkbGNDbG9zZSBtZXNzYWdlLlxuICAgKiAyLiBCdWlsZCBhIGNsb3NlIHR4LCBzaWduLlxuICAgKiAzLiByZXR1cm4gZGxjQ2xvc2UgbWVzc2FnZSAobm8gcHNidClcbiAgICovXG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIERsY0Nsb3NlIG1lc3NhZ2V0eXBlIGZvciBjbG9zaW5nIERMQyB3aXRoIE11dHVhbCBDb25zZW50XG4gICAqIEBwYXJhbSBfZGxjT2ZmZXIgRGxjT2ZmZXIgVExWIChWMClcbiAgICogQHBhcmFtIF9kbGNBY2NlcHQgRGxjQWNjZXB0IFRMViAoVjApXG4gICAqIEBwYXJhbSBfZGxjVHhzIERsY1RyYW5zYWN0aW9ucyBUTFYgKFYwKVxuICAgKiBAcGFyYW0gaW5pdGlhdG9yUGF5b3V0U2F0b3NoaXMgQW1vdW50IGluaXRpYXRvciBleHBlY3RzIGFzIGEgcGF5b3V0XG4gICAqIEBwYXJhbSBpc09mZmVyZXIgV2hldGhlciBvZmZlcmVyIG9yIG5vdFxuICAgKiBAcGFyYW0gX2lucHV0cyBPcHRpb25hbGx5IHNwZWNpZmllZCBjbG9zaW5nIGlucHV0c1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxEbGNDbG9zZT59XG4gICAqL1xuICBhc3luYyBjcmVhdGVEbGNDbG9zZShcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIF9kbGNBY2NlcHQ6IERsY0FjY2VwdCxcbiAgICBfZGxjVHhzOiBEbGNUcmFuc2FjdGlvbnMsXG4gICAgaW5pdGlhdG9yUGF5b3V0U2F0b3NoaXM6IGJpZ2ludCxcbiAgICBpc09mZmVyZXI/OiBib29sZWFuLFxuICAgIF9pbnB1dHM/OiBJbnB1dFtdLFxuICApOiBQcm9taXNlPERsY0Nsb3NlPiB7XG4gICAgY29uc3QgeyBkbGNPZmZlciwgZGxjQWNjZXB0LCBkbGNUeHMgfSA9IGNoZWNrVHlwZXMoe1xuICAgICAgX2RsY09mZmVyLFxuICAgICAgX2RsY0FjY2VwdCxcbiAgICAgIF9kbGNUeHMsXG4gICAgfSk7XG5cbiAgICBpZiAoaXNPZmZlcmVyID09PSB1bmRlZmluZWQpXG4gICAgICBpc09mZmVyZXIgPSBhd2FpdCB0aGlzLmlzT2ZmZXJlcihkbGNPZmZlciwgZGxjQWNjZXB0KTtcblxuICAgIGNvbnN0IG5ldHdvcmsgPSBhd2FpdCB0aGlzLmdldENvbm5lY3RlZE5ldHdvcmsoKTtcbiAgICBjb25zdCBwc2J0ID0gbmV3IFBzYnQoeyBuZXR3b3JrIH0pO1xuXG4gICAgY29uc3QgZnVuZGluZ1B1YktleXMgPVxuICAgICAgQnVmZmVyLmNvbXBhcmUoZGxjT2ZmZXIuZnVuZGluZ1B1YktleSwgZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkpID09PSAtMVxuICAgICAgICA/IFtkbGNPZmZlci5mdW5kaW5nUHViS2V5LCBkbGNBY2NlcHQuZnVuZGluZ1B1YktleV1cbiAgICAgICAgOiBbZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXksIGRsY09mZmVyLmZ1bmRpbmdQdWJLZXldO1xuXG4gICAgY29uc3QgcDJtcyA9IHBheW1lbnRzLnAybXMoe1xuICAgICAgbTogMixcbiAgICAgIHB1YmtleXM6IGZ1bmRpbmdQdWJLZXlzLFxuICAgICAgbmV0d29yayxcbiAgICB9KTtcblxuICAgIGNvbnN0IHBheW1lbnRWYXJpYW50ID0gcGF5bWVudHMucDJ3c2goe1xuICAgICAgcmVkZWVtOiBwMm1zLFxuICAgICAgbmV0d29yayxcbiAgICB9KTtcblxuICAgIC8vIEluaXRpYXRlIGFuZCBidWlsZCBQU0JUXG4gICAgbGV0IGlucHV0czogSW5wdXRbXSA9IF9pbnB1dHM7XG4gICAgaWYgKCFfaW5wdXRzKSB7XG4gICAgICBjb25zdCB0ZW1wSW5wdXRzID0gYXdhaXQgdGhpcy5HZXRJbnB1dHNGb3JBbW91bnQoXG4gICAgICAgIEJpZ0ludCgyMDAwMCksXG4gICAgICAgIGRsY09mZmVyLmZlZVJhdGVQZXJWYixcbiAgICAgICAgX2lucHV0cyxcbiAgICAgICk7XG4gICAgICBfaW5wdXRzID0gdGVtcElucHV0cztcbiAgICB9XG4gICAgaW5wdXRzID0gX2lucHV0cy5tYXAoKGlucHV0KSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5pbnB1dCxcbiAgICAgICAgaW5wdXRTZXJpYWxJZDogaW5wdXQuaW5wdXRTZXJpYWxJZCB8fCBnZW5lcmF0ZVNlcmlhbElkKCksXG4gICAgICAgIHRvVXR4bzogaW5wdXQudG9VdHhvLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHB1YmtleXM6IEJ1ZmZlcltdID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBpbnB1dHMubWFwKGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgICBjb25zdCBhZGRyZXNzOiBBZGRyZXNzID0gYXdhaXQgdGhpcy5nZXRNZXRob2QoJ2dldFdhbGxldEFkZHJlc3MnKShcbiAgICAgICAgICBpbnB1dC5hZGRyZXNzLFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gQnVmZmVyLmZyb20oYWRkcmVzcy5wdWJsaWNLZXksICdoZXgnKTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBjb25zdCBmdW5kaW5nSW5wdXRTZXJpYWxJZCA9IGdlbmVyYXRlU2VyaWFsSWQoKTtcblxuICAgIC8vIE1ha2UgdGVtcG9yYXJ5IGFycmF5IHRvIGhvbGQgYWxsIGlucHV0cyBhbmQgdGhlbiBzb3J0IHRoZW1cbiAgICAvLyB0aGlzIG1ldGhvZCBjYW4gYmUgaW1wcm92ZWQgbGF0ZXJcbiAgICBjb25zdCBwc2J0SW5wdXRzID0gW107XG4gICAgcHNidElucHV0cy5wdXNoKHtcbiAgICAgIGhhc2g6IGRsY1R4cy5mdW5kVHgudHhJZC5zZXJpYWxpemUoKSxcbiAgICAgIGluZGV4OiBkbGNUeHMuZnVuZFR4Vm91dCxcbiAgICAgIHNlcXVlbmNlOiAwLFxuICAgICAgd2l0bmVzc1V0eG86IHtcbiAgICAgICAgc2NyaXB0OiBwYXltZW50VmFyaWFudC5vdXRwdXQsXG4gICAgICAgIHZhbHVlOiBOdW1iZXIoZGxjVHhzLmZ1bmRUeC5vdXRwdXRzW2RsY1R4cy5mdW5kVHhWb3V0XS52YWx1ZS5zYXRzKSxcbiAgICAgIH0sXG4gICAgICB3aXRuZXNzU2NyaXB0OiBwYXltZW50VmFyaWFudC5yZWRlZW0ub3V0cHV0LFxuICAgICAgaW5wdXRTZXJpYWxJZDogZnVuZGluZ0lucHV0U2VyaWFsSWQsXG4gICAgICBkZXJpdmF0aW9uUGF0aDogbnVsbCxcbiAgICB9KTtcblxuICAgIC8vIGFkZCBhbGwgZGxjIGNsb3NlIGlucHV0c1xuICAgIGlucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgICAgY29uc3QgcGF5bWVudFZhcmlhbnQgPSBwYXltZW50cy5wMndwa2goeyBwdWJrZXk6IHB1YmtleXNbaV0sIG5ldHdvcmsgfSk7XG5cbiAgICAgIHBzYnRJbnB1dHMucHVzaCh7XG4gICAgICAgIGhhc2g6IGlucHV0LnR4aWQsXG4gICAgICAgIGluZGV4OiBpbnB1dC52b3V0LFxuICAgICAgICBzZXF1ZW5jZTogMCxcbiAgICAgICAgd2l0bmVzc1V0eG86IHtcbiAgICAgICAgICBzY3JpcHQ6IHBheW1lbnRWYXJpYW50Lm91dHB1dCxcbiAgICAgICAgICB2YWx1ZTogaW5wdXQudmFsdWUsXG4gICAgICAgIH0sXG4gICAgICAgIGlucHV0U2VyaWFsSWQ6IGlucHV0LmlucHV0U2VyaWFsSWQsXG4gICAgICAgIGRlcml2YXRpb25QYXRoOiBpbnB1dC5kZXJpdmF0aW9uUGF0aCxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gc29ydCBhbGwgaW5wdXRzIGluIGFzY2VuZGluZyBvcmRlciBieSBzZXJpYWwgSURcbiAgICAvLyBUaGUgb25seSByZWFzb24gd2UgYXJlIGRvaW5nIHRoaXMgaXMgZm9yIHByaXZhY3kuIElmIHRoZSBmdW5kaW5nSW5wdXQgaXNcbiAgICAvLyBhbHdheXMgZmlyc3QsIGl0IGlzIHZlcnkgb2J2aW91cy4gSGVuY2UsIGEgc2VyaWFsSWQgaXMgcmFuZG9tbHkgZ2VuZXJhdGVkXG4gICAgLy8gYW5kIHRoZSBpbnB1dHMgYXJlIHNvcnRlZCBieSB0aGF0IGluc3RlYWQuXG4gICAgY29uc3Qgc29ydGVkUHNidElucHV0cyA9IHBzYnRJbnB1dHMuc29ydCgoYSwgYikgPT5cbiAgICAgIE51bWJlcihhLmlucHV0U2VyaWFsSWQgLSBiLmlucHV0U2VyaWFsSWQpLFxuICAgICk7XG5cbiAgICAvLyBHZXQgaW5kZXggb2YgZnVuZGluZ0lucHV0XG4gICAgY29uc3QgZnVuZGluZ0lucHV0SW5kZXggPSBzb3J0ZWRQc2J0SW5wdXRzLmZpbmRJbmRleChcbiAgICAgIChpbnB1dCkgPT4gaW5wdXQuaW5wdXRTZXJpYWxJZCA9PT0gZnVuZGluZ0lucHV0U2VyaWFsSWQsXG4gICAgKTtcblxuICAgIC8vIGFkZCB0byBwc2J0XG4gICAgc29ydGVkUHNidElucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4gcHNidC5hZGRJbnB1dChpbnB1dCkpO1xuXG4gICAgY29uc3QgZnVuZGluZ0lucHV0czogRnVuZGluZ0lucHV0W10gPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGlucHV0cy5tYXAoYXN5bmMgKGlucHV0KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmlucHV0VG9GdW5kaW5nSW5wdXQoaW5wdXQpO1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IGZpbmFsaXplciA9IG5ldyBEdWFsQ2xvc2luZ1R4RmluYWxpemVyKFxuICAgICAgZnVuZGluZ0lucHV0cyxcbiAgICAgIGRsY09mZmVyLnBheW91dFNQSyxcbiAgICAgIGRsY0FjY2VwdC5wYXlvdXRTUEssXG4gICAgICBkbGNPZmZlci5mZWVSYXRlUGVyVmIsXG4gICAgKTtcblxuICAgIGNvbnN0IGNsb3NlSW5wdXRBbW91bnQgPSBCaWdJbnQoXG4gICAgICBpbnB1dHMucmVkdWNlKChhY2MsIHZhbCkgPT4gYWNjICsgdmFsLnZhbHVlLCAwKSxcbiAgICApO1xuXG4gICAgY29uc3Qgb2ZmZXJQYXlvdXRWYWx1ZTogYmlnaW50ID0gaXNPZmZlcmVyXG4gICAgICA/IGNsb3NlSW5wdXRBbW91bnQgK1xuICAgICAgICBpbml0aWF0b3JQYXlvdXRTYXRvc2hpcyAtXG4gICAgICAgIGZpbmFsaXplci5vZmZlckluaXRpYXRvckZlZXNcbiAgICAgIDogZGxjT2ZmZXIuY29udHJhY3RJbmZvLnRvdGFsQ29sbGF0ZXJhbCAtIGluaXRpYXRvclBheW91dFNhdG9zaGlzO1xuXG4gICAgY29uc3QgYWNjZXB0UGF5b3V0VmFsdWU6IGJpZ2ludCA9IGlzT2ZmZXJlclxuICAgICAgPyBkbGNPZmZlci5jb250cmFjdEluZm8udG90YWxDb2xsYXRlcmFsIC0gaW5pdGlhdG9yUGF5b3V0U2F0b3NoaXNcbiAgICAgIDogY2xvc2VJbnB1dEFtb3VudCArXG4gICAgICAgIGluaXRpYXRvclBheW91dFNhdG9zaGlzIC1cbiAgICAgICAgZmluYWxpemVyLm9mZmVySW5pdGlhdG9yRmVlcztcblxuICAgIGNvbnN0IG9mZmVyRmlyc3QgPSBkbGNPZmZlci5wYXlvdXRTZXJpYWxJZCA8IGRsY0FjY2VwdC5wYXlvdXRTZXJpYWxJZDtcblxuICAgIHBzYnQuYWRkT3V0cHV0KHtcbiAgICAgIHZhbHVlOiBOdW1iZXIob2ZmZXJGaXJzdCA/IG9mZmVyUGF5b3V0VmFsdWUgOiBhY2NlcHRQYXlvdXRWYWx1ZSksXG4gICAgICBhZGRyZXNzOiBhZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoXG4gICAgICAgIG9mZmVyRmlyc3QgPyBkbGNPZmZlci5wYXlvdXRTUEsgOiBkbGNBY2NlcHQucGF5b3V0U1BLLFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgKSxcbiAgICB9KTtcblxuICAgIHBzYnQuYWRkT3V0cHV0KHtcbiAgICAgIHZhbHVlOiBOdW1iZXIob2ZmZXJGaXJzdCA/IGFjY2VwdFBheW91dFZhbHVlIDogb2ZmZXJQYXlvdXRWYWx1ZSksXG4gICAgICBhZGRyZXNzOiBhZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoXG4gICAgICAgIG9mZmVyRmlyc3QgPyBkbGNBY2NlcHQucGF5b3V0U1BLIDogZGxjT2ZmZXIucGF5b3V0U1BLLFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgKSxcbiAgICB9KTtcblxuICAgIC8vIEdlbmVyYXRlIGtleXBhaXIgdG8gc2lnbiBpbnB1dHNcbiAgICBjb25zdCBmdW5kUHJpdmF0ZUtleVBhaXIgPSBhd2FpdCB0aGlzLkdldEZ1bmRLZXlQYWlyKFxuICAgICAgZGxjT2ZmZXIsXG4gICAgICBkbGNBY2NlcHQsXG4gICAgICBpc09mZmVyZXIsXG4gICAgKTtcblxuICAgIC8vIFNpZ24gZGxjIGZ1bmRpbmdpbnB1dFxuICAgIHBzYnQuc2lnbklucHV0KGZ1bmRpbmdJbnB1dEluZGV4LCBmdW5kUHJpdmF0ZUtleVBhaXIpO1xuXG4gICAgLy8gU2lnbiBkbGNjbG9zZSBpbnB1dHNcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHNvcnRlZFBzYnRJbnB1dHMubWFwKGFzeW5jIChpbnB1dCwgaSkgPT4ge1xuICAgICAgICBpZiAoaSA9PT0gZnVuZGluZ0lucHV0SW5kZXgpIHJldHVybjtcblxuICAgICAgICAvLyBkZXJpdmUga2V5cGFpclxuICAgICAgICBjb25zdCBrZXlQYWlyID0gYXdhaXQgdGhpcy5nZXRNZXRob2QoJ2tleVBhaXInKShpbnB1dC5kZXJpdmF0aW9uUGF0aCk7XG4gICAgICAgIHBzYnQuc2lnbklucHV0KGksIGtleVBhaXIpO1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIC8vIFZhbGlkYXRlIHNpZ25hdHVyZXNcbiAgICBwc2J0LnZhbGlkYXRlU2lnbmF0dXJlc09mQWxsSW5wdXRzKCk7XG5cbiAgICAvLyBFeHRyYWN0IGNsb3NlIHNpZ25hdHVyZSBmcm9tIHBzYnQgYW5kIGRlY29kZSBpdCB0byBvbmx5IGV4dHJhY3QgciBhbmQgcyB2YWx1ZXNcbiAgICBjb25zdCBjbG9zZVNpZ25hdHVyZSA9IGF3YWl0IHNjcmlwdC5zaWduYXR1cmUuZGVjb2RlKFxuICAgICAgcHNidC5kYXRhLmlucHV0c1tmdW5kaW5nSW5wdXRJbmRleF0ucGFydGlhbFNpZ1swXS5zaWduYXR1cmUsXG4gICAgKS5zaWduYXR1cmU7XG5cbiAgICAvLyBFeHRyYWN0IGZ1bmRpbmcgc2lnbmF0dXJlcyBmcm9tIHBzYnRcbiAgICBjb25zdCBpbnB1dFNpZ3MgPSBwc2J0LmRhdGEuaW5wdXRzXG4gICAgICAuZmlsdGVyKChpbnB1dCkgPT4gaW5wdXQgIT09IGZ1bmRpbmdJbnB1dEluZGV4KVxuICAgICAgLm1hcCgoaW5wdXQpID0+IGlucHV0LnBhcnRpYWxTaWdbMF0pO1xuXG4gICAgLy8gY3JlYXRlIGZ1bmRpbmdTaWduYXR1cmVzXG4gICAgY29uc3Qgd2l0bmVzc0VsZW1lbnRzOiBTY3JpcHRXaXRuZXNzVjBbXVtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNpZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHNpZ1dpdG5lc3MgPSBuZXcgU2NyaXB0V2l0bmVzc1YwKCk7XG4gICAgICBzaWdXaXRuZXNzLndpdG5lc3MgPSBpbnB1dFNpZ3NbaV0uc2lnbmF0dXJlO1xuICAgICAgY29uc3QgcHViS2V5V2l0bmVzcyA9IG5ldyBTY3JpcHRXaXRuZXNzVjAoKTtcbiAgICAgIHB1YktleVdpdG5lc3Mud2l0bmVzcyA9IGlucHV0U2lnc1tpXS5wdWJrZXk7XG4gICAgICB3aXRuZXNzRWxlbWVudHMucHVzaChbc2lnV2l0bmVzcywgcHViS2V5V2l0bmVzc10pO1xuICAgIH1cbiAgICBjb25zdCBmdW5kaW5nU2lnbmF0dXJlcyA9IG5ldyBGdW5kaW5nU2lnbmF0dXJlc1YwKCk7XG4gICAgZnVuZGluZ1NpZ25hdHVyZXMud2l0bmVzc0VsZW1lbnRzID0gd2l0bmVzc0VsZW1lbnRzO1xuXG4gICAgLy8gQ3JlYXRlIERsY0Nsb3NlXG4gICAgY29uc3QgZGxjQ2xvc2UgPSBuZXcgRGxjQ2xvc2VWMCgpO1xuICAgIGRsY0Nsb3NlLmNvbnRyYWN0SWQgPSBkbGNUeHMuY29udHJhY3RJZDtcbiAgICBkbGNDbG9zZS5vZmZlclBheW91dFNhdG9zaGlzID0gQmlnSW50KFxuICAgICAgcHNidC50eE91dHB1dHNbb2ZmZXJGaXJzdCA/IDAgOiAxXS52YWx1ZSxcbiAgICApOyAvLyBZb3UgZ2l2ZSBjb2xsYXRlcmFsIGJhY2sgdG8gdXNlcnNcbiAgICBkbGNDbG9zZS5hY2NlcHRQYXlvdXRTYXRvc2hpcyA9IEJpZ0ludChcbiAgICAgIHBzYnQudHhPdXRwdXRzW29mZmVyRmlyc3QgPyAxIDogMF0udmFsdWUsXG4gICAgKTsgLy8gZ2l2ZSBjb2xsYXRlcmFsIGJhY2sgdG8gdXNlcnNcbiAgICBkbGNDbG9zZS5mdW5kSW5wdXRTZXJpYWxJZCA9IGZ1bmRpbmdJbnB1dFNlcmlhbElkOyAvLyByYW5kb21seSBnZW5lcmF0ZWQgc2VyaWFsIGlkXG4gICAgZGxjQ2xvc2UuY2xvc2VTaWduYXR1cmUgPSBjbG9zZVNpZ25hdHVyZTtcbiAgICBkbGNDbG9zZS5mdW5kaW5nU2lnbmF0dXJlcyA9IGZ1bmRpbmdTaWduYXR1cmVzO1xuICAgIGRsY0Nsb3NlLmZ1bmRpbmdJbnB1dHMgPSBmdW5kaW5nSW5wdXRzIGFzIEZ1bmRpbmdJbnB1dFYwW107XG4gICAgZGxjQ2xvc2UudmFsaWRhdGUoKTtcblxuICAgIHJldHVybiBkbGNDbG9zZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBtdWx0aXBsZSBEbGNDbG9zZSBtZXNzYWdldHlwZXMgZm9yIGNsb3NpbmcgRExDIHdpdGggTXV0dWFsIENvbnNlbnRcbiAgICogQHBhcmFtIF9kbGNPZmZlciBEbGNPZmZlciBUTFYgKFYwKVxuICAgKiBAcGFyYW0gX2RsY0FjY2VwdCBEbGNBY2NlcHQgVExWIChWMClcbiAgICogQHBhcmFtIF9kbGNUeHMgRGxjVHJhbnNhY3Rpb25zIFRMViAoVjApXG4gICAqIEBwYXJhbSBpbml0aWF0b3JQYXlvdXRzIEFycmF5IG9mIGFtb3VudHMgaW5pdGlhdG9yIGV4cGVjdHMgYXMgcGF5b3V0c1xuICAgKiBAcGFyYW0gaXNPZmZlcmVyIFdoZXRoZXIgb2ZmZXJlciBvciBub3RcbiAgICogQHBhcmFtIF9pbnB1dHMgT3B0aW9uYWxseSBzcGVjaWZpZWQgY2xvc2luZyBpbnB1dHNcbiAgICogQHJldHVybnMge1Byb21pc2U8RGxjQ2xvc2VbXT59XG4gICAqL1xuICBhc3luYyBjcmVhdGVCYXRjaERsY0Nsb3NlKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNUeHM6IERsY1RyYW5zYWN0aW9ucyxcbiAgICBpbml0aWF0b3JQYXlvdXRzOiBiaWdpbnRbXSxcbiAgICBpc09mZmVyZXI/OiBib29sZWFuLFxuICAgIF9pbnB1dHM/OiBJbnB1dFtdLFxuICApOiBQcm9taXNlPERsY0Nsb3NlW10+IHtcbiAgICBjb25zdCB7IGRsY09mZmVyLCBkbGNBY2NlcHQsIGRsY1R4cyB9ID0gY2hlY2tUeXBlcyh7XG4gICAgICBfZGxjT2ZmZXIsXG4gICAgICBfZGxjQWNjZXB0LFxuICAgICAgX2RsY1R4cyxcbiAgICB9KTtcblxuICAgIGlmIChpc09mZmVyZXIgPT09IHVuZGVmaW5lZClcbiAgICAgIGlzT2ZmZXJlciA9IGF3YWl0IHRoaXMuaXNPZmZlcmVyKGRsY09mZmVyLCBkbGNBY2NlcHQpO1xuXG4gICAgaWYgKF9pbnB1dHMgJiYgX2lucHV0cy5sZW5ndGggPiAwKVxuICAgICAgdGhyb3cgRXJyb3IoJ2Z1bmRpbmcgaW5wdXRzIG5vdCBzdXBwb3J0ZWQgb24gQmF0Y2hEbGNDbG9zZScpOyAvLyBUT0RPIHN1cHBvcnQgbXVsdGlwbGUgZnVuZGluZyBpbnB1dHNcblxuICAgIGNvbnN0IGZ1bmRpbmdJbnB1dFNlcmlhbElkID0gZ2VuZXJhdGVTZXJpYWxJZCgpO1xuXG4gICAgY29uc3QgZnVuZGluZ0lucHV0czogRnVuZGluZ0lucHV0W10gPSBbXTsgLy8gVE9ETzogc3VwcG9ydCBtdWx0aXBsZSBmdW5kaW5nIGlucHV0c1xuXG4gICAgY29uc3QgZmluYWxpemVyID0gbmV3IER1YWxDbG9zaW5nVHhGaW5hbGl6ZXIoXG4gICAgICBmdW5kaW5nSW5wdXRzLFxuICAgICAgZGxjT2ZmZXIucGF5b3V0U1BLLFxuICAgICAgZGxjQWNjZXB0LnBheW91dFNQSyxcbiAgICAgIGRsY09mZmVyLmZlZVJhdGVQZXJWYixcbiAgICApO1xuXG4gICAgLy8gR2VuZXJhdGUga2V5cGFpciB0byBzaWduIGlucHV0c1xuICAgIGNvbnN0IGZ1bmRQcml2YXRlS2V5UGFpciA9IGF3YWl0IHRoaXMuR2V0RnVuZEtleVBhaXIoXG4gICAgICBkbGNPZmZlcixcbiAgICAgIGRsY0FjY2VwdCxcbiAgICAgIGlzT2ZmZXJlcixcbiAgICApO1xuXG4gICAgY29uc3QgY2xvc2VJbnB1dEFtb3VudCA9IEJpZ0ludCgwKTsgLy8gVE9ETyBzdXBwb3J0IG11bHRpcGxlIGZ1bmRpbmcgaW5wdXRzXG5cbiAgICBjb25zdCBwcml2S2V5ID0gQnVmZmVyLmZyb20oZnVuZFByaXZhdGVLZXlQYWlyLnByaXZhdGVLZXkpLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgIGNvbnN0IHJhd0Nsb3NlVHhzID0gYXdhaXQgdGhpcy5DcmVhdGVDbG9zZVJhd1R4cyhcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgZGxjVHhzLFxuICAgICAgY2xvc2VJbnB1dEFtb3VudCxcbiAgICAgIGlzT2ZmZXJlcixcbiAgICAgIFtdLFxuICAgICAgZnVuZGluZ0lucHV0cyxcbiAgICAgIGluaXRpYXRvclBheW91dHMsXG4gICAgKTtcblxuICAgIGNvbnN0IHNpZ0hhc2hlcyA9IGF3YWl0IHRoaXMuQ3JlYXRlU2lnbmF0dXJlSGFzaGVzKFxuICAgICAgZGxjT2ZmZXIsXG4gICAgICBkbGNBY2NlcHQsXG4gICAgICBkbGNUeHMsXG4gICAgICByYXdDbG9zZVR4cyxcbiAgICApO1xuXG4gICAgY29uc3Qgc2lnbmF0dXJlcyA9IGF3YWl0IHRoaXMuQ2FsY3VsYXRlRWNTaWduYXR1cmVIYXNoZXMoXG4gICAgICBzaWdIYXNoZXMsXG4gICAgICBwcml2S2V5LFxuICAgICk7XG5cbiAgICBjb25zdCBkbGNDbG9zZXMgPSBbXTtcblxuICAgIHNpZ25hdHVyZXMuZm9yRWFjaCgoc2lnLCBpKSA9PiB7XG4gICAgICBjb25zdCBwYXlvdXQgPSBpbml0aWF0b3JQYXlvdXRzW2ldO1xuICAgICAgY29uc3QgcGF5b3V0TWludXNPZmZlckZlZXMgPVxuICAgICAgICBmaW5hbGl6ZXIub2ZmZXJJbml0aWF0b3JGZWVzID4gcGF5b3V0XG4gICAgICAgICAgPyBCaWdJbnQoMClcbiAgICAgICAgICA6IHBheW91dCAtIGZpbmFsaXplci5vZmZlckluaXRpYXRvckZlZXM7XG4gICAgICBjb25zdCBjb2xsYXRlcmFsTWludXNQYXlvdXQgPVxuICAgICAgICBwYXlvdXQgPiBkbGNPZmZlci5jb250cmFjdEluZm8udG90YWxDb2xsYXRlcmFsXG4gICAgICAgICAgPyBCaWdJbnQoMClcbiAgICAgICAgICA6IGRsY09mZmVyLmNvbnRyYWN0SW5mby50b3RhbENvbGxhdGVyYWwgLSBwYXlvdXQ7XG5cbiAgICAgIGNvbnN0IG9mZmVyUGF5b3V0VmFsdWU6IGJpZ2ludCA9IGlzT2ZmZXJlclxuICAgICAgICA/IGNsb3NlSW5wdXRBbW91bnQgKyBwYXlvdXRNaW51c09mZmVyRmVlc1xuICAgICAgICA6IGNvbGxhdGVyYWxNaW51c1BheW91dDtcblxuICAgICAgY29uc3QgYWNjZXB0UGF5b3V0VmFsdWU6IGJpZ2ludCA9IGlzT2ZmZXJlclxuICAgICAgICA/IGNvbGxhdGVyYWxNaW51c1BheW91dFxuICAgICAgICA6IGNsb3NlSW5wdXRBbW91bnQgKyBwYXlvdXRNaW51c09mZmVyRmVlcztcblxuICAgICAgY29uc3QgZnVuZGluZ1NpZ25hdHVyZXMgPSBuZXcgRnVuZGluZ1NpZ25hdHVyZXNWMCgpO1xuXG4gICAgICBjb25zdCBkbGNDbG9zZSA9IG5ldyBEbGNDbG9zZVYwKCk7XG4gICAgICBkbGNDbG9zZS5jb250cmFjdElkID0gZGxjVHhzLmNvbnRyYWN0SWQ7XG4gICAgICBkbGNDbG9zZS5vZmZlclBheW91dFNhdG9zaGlzID0gb2ZmZXJQYXlvdXRWYWx1ZTtcbiAgICAgIGRsY0Nsb3NlLmFjY2VwdFBheW91dFNhdG9zaGlzID0gYWNjZXB0UGF5b3V0VmFsdWU7XG4gICAgICBkbGNDbG9zZS5mdW5kSW5wdXRTZXJpYWxJZCA9IGZ1bmRpbmdJbnB1dFNlcmlhbElkO1xuICAgICAgZGxjQ2xvc2UuY2xvc2VTaWduYXR1cmUgPSBCdWZmZXIuZnJvbShzaWcsICdoZXgnKTtcbiAgICAgIGRsY0Nsb3NlLmZ1bmRpbmdTaWduYXR1cmVzID0gZnVuZGluZ1NpZ25hdHVyZXM7XG4gICAgICBkbGNDbG9zZS52YWxpZGF0ZSgpO1xuXG4gICAgICBkbGNDbG9zZXMucHVzaChkbGNDbG9zZSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gZGxjQ2xvc2VzO1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5QmF0Y2hEbGNDbG9zZVVzaW5nTWV0YWRhdGEoXG4gICAgZGxjQ2xvc2VNZXRhZGF0YTogRGxjQ2xvc2VNZXRhZGF0YSxcbiAgICBfZGxjQ2xvc2VzOiBEbGNDbG9zZVtdLFxuICAgIGlzT2ZmZXJlcj86IGJvb2xlYW4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjVHhzIH0gPSBkbGNDbG9zZU1ldGFkYXRhLnRvRGxjTWVzc2FnZXMoKTtcblxuICAgIGF3YWl0IHRoaXMudmVyaWZ5QmF0Y2hEbGNDbG9zZShcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgZGxjVHhzLFxuICAgICAgX2RsY0Nsb3NlcyxcbiAgICAgIGlzT2ZmZXJlcixcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmeSBtdWx0aXBsZSBEbGNDbG9zZSBtZXNzYWdldHlwZXMgZm9yIGNsb3NpbmcgRExDIHdpdGggTXV0dWFsIENvbnNlbnRcbiAgICogQHBhcmFtIF9kbGNPZmZlciBEbGNPZmZlciBUTFYgKFYwKVxuICAgKiBAcGFyYW0gX2RsY0FjY2VwdCBEbGNBY2NlcHQgVExWIChWMClcbiAgICogQHBhcmFtIF9kbGNUeHMgRGxjVHJhbnNhY3Rpb25zIFRMViAoVjApXG4gICAqIEBwYXJhbSBfZGxjQ2xvc2VzIERsY0Nsb3NlW10gVExWIChWMClcbiAgICogQHBhcmFtIGlzT2ZmZXJlciBXaGV0aGVyIG9mZmVyZXIgb3Igbm90XG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgYXN5bmMgdmVyaWZ5QmF0Y2hEbGNDbG9zZShcbiAgICBfZGxjT2ZmZXI6IERsY09mZmVyLFxuICAgIF9kbGNBY2NlcHQ6IERsY0FjY2VwdCxcbiAgICBfZGxjVHhzOiBEbGNUcmFuc2FjdGlvbnMsXG4gICAgX2RsY0Nsb3NlczogRGxjQ2xvc2VbXSxcbiAgICBpc09mZmVyZXI/OiBib29sZWFuLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB7IGRsY09mZmVyLCBkbGNBY2NlcHQsIGRsY1R4cyB9ID0gY2hlY2tUeXBlcyh7XG4gICAgICBfZGxjT2ZmZXIsXG4gICAgICBfZGxjQWNjZXB0LFxuICAgICAgX2RsY1R4cyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRsY0Nsb3NlcyA9IF9kbGNDbG9zZXMubWFwKFxuICAgICAgKF9kbGNDbG9zZSkgPT4gY2hlY2tUeXBlcyh7IF9kbGNDbG9zZSB9KS5kbGNDbG9zZSxcbiAgICApO1xuXG4gICAgaWYgKGlzT2ZmZXJlciA9PT0gdW5kZWZpbmVkKVxuICAgICAgaXNPZmZlcmVyID0gYXdhaXQgdGhpcy5pc09mZmVyZXIoZGxjT2ZmZXIsIGRsY0FjY2VwdCk7XG5cbiAgICBhc3NlcnQoXG4gICAgICBkbGNDbG9zZXMuZXZlcnkoKGRsY0Nsb3NlKSA9PiBkbGNDbG9zZS5mdW5kaW5nSW5wdXRzLmxlbmd0aCA9PT0gMCksXG4gICAgICAnZnVuZGluZyBpbnB1dHMgbm90IHN1cHBvcnRlZCBvbiB2ZXJpZnkgQmF0Y2hEbGNDbG9zZScsXG4gICAgKTsgLy8gVE9ETyBzdXBwb3J0IG11bHRpcGxlIGZ1bmRpbmcgaW5wdXRzXG5cbiAgICBjb25zdCBjbG9zZUlucHV0QW1vdW50ID0gQmlnSW50KDApOyAvLyBUT0RPIHN1cHBvcnQgbXVsdGlwbGUgZnVuZGluZyBpbnB1dHNcblxuICAgIGNvbnN0IHJhd0Nsb3NlVHhzID0gYXdhaXQgdGhpcy5DcmVhdGVDbG9zZVJhd1R4cyhcbiAgICAgIGRsY09mZmVyLFxuICAgICAgZGxjQWNjZXB0LFxuICAgICAgZGxjVHhzLFxuICAgICAgY2xvc2VJbnB1dEFtb3VudCxcbiAgICAgIGlzT2ZmZXJlcixcbiAgICAgIGRsY0Nsb3NlcyxcbiAgICApO1xuXG4gICAgY29uc3QgYXJlU2lnc1ZhbGlkID0gYXdhaXQgdGhpcy5WZXJpZnlTaWduYXR1cmVzKFxuICAgICAgZGxjT2ZmZXIsXG4gICAgICBkbGNBY2NlcHQsXG4gICAgICBkbGNUeHMsXG4gICAgICBkbGNDbG9zZXMsXG4gICAgICByYXdDbG9zZVR4cyxcbiAgICAgIGlzT2ZmZXJlcixcbiAgICApO1xuXG4gICAgYXNzZXJ0KGFyZVNpZ3NWYWxpZCwgJ1NpZ25hdHVyZXMgaW52YWxpZCBpbiBWZXJpZnkgQmF0Y2ggRGxjQ2xvc2UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHb2FsIG9mIGZpbmFsaXplIERsYyBDbG9zZSBpcyBmb3IgYm9iIHRvXG4gICAqIDEuIHRha2UgdGhlIGRsY0Nsb3NlIGNyZWF0ZWQgYnkgYWxpY2UgdXNpbmcgY3JlYXRlRGxjQ2xvc2UsXG4gICAqIDIuIEJ1aWxkIGEgcHNidCB1c2luZyBBbGljZSdzIGRsY0Nsb3NlIG1lc3NhZ2VcbiAgICogMy4gU2lnbiBwc2J0IHdpdGggYm9iJ3MgcHJpdmtleVxuICAgKiA0LiByZXR1cm4gYSB0eCByZWFkeSB0byBiZSBicm9hZGNhc3RcbiAgICovXG5cbiAgLyoqXG4gICAqIEZpbmFsaXplIERsYyBDbG9zZVxuICAgKiBAcGFyYW0gX2RsY09mZmVyIERsYyBPZmZlciBNZXNzYWdlXG4gICAqIEBwYXJhbSBfZGxjQWNjZXB0IERsYyBBY2NlcHQgTWVzc2FnZVxuICAgKiBAcGFyYW0gX2RsY0Nsb3NlIERsYyBDbG9zZSBNZXNzYWdlXG4gICAqIEBwYXJhbSBfZGxjVHhzIERsYyBUcmFuc2FjdGlvbnMgTWVzc2FnZVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUeD59XG4gICAqL1xuICBhc3luYyBmaW5hbGl6ZURsY0Nsb3NlKFxuICAgIF9kbGNPZmZlcjogRGxjT2ZmZXIsXG4gICAgX2RsY0FjY2VwdDogRGxjQWNjZXB0LFxuICAgIF9kbGNDbG9zZTogRGxjQ2xvc2UsXG4gICAgX2RsY1R4czogRGxjVHJhbnNhY3Rpb25zLFxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHsgZGxjT2ZmZXIsIGRsY0FjY2VwdCwgZGxjQ2xvc2UsIGRsY1R4cyB9ID0gY2hlY2tUeXBlcyh7XG4gICAgICBfZGxjT2ZmZXIsXG4gICAgICBfZGxjQWNjZXB0LFxuICAgICAgX2RsY0Nsb3NlLFxuICAgICAgX2RsY1R4cyxcbiAgICB9KTtcblxuICAgIGRsY09mZmVyLnZhbGlkYXRlKCk7XG4gICAgZGxjQWNjZXB0LnZhbGlkYXRlKCk7XG4gICAgZGxjQ2xvc2UudmFsaWRhdGUoKTtcblxuICAgIGNvbnN0IG5ldHdvcmsgPSBhd2FpdCB0aGlzLmdldENvbm5lY3RlZE5ldHdvcmsoKTtcbiAgICBjb25zdCBwc2J0ID0gbmV3IFBzYnQoeyBuZXR3b3JrIH0pO1xuXG4gICAgY29uc3QgZnVuZGluZ1B1YktleXMgPVxuICAgICAgQnVmZmVyLmNvbXBhcmUoZGxjT2ZmZXIuZnVuZGluZ1B1YktleSwgZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkpID09PSAtMVxuICAgICAgICA/IFtkbGNPZmZlci5mdW5kaW5nUHViS2V5LCBkbGNBY2NlcHQuZnVuZGluZ1B1YktleV1cbiAgICAgICAgOiBbZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXksIGRsY09mZmVyLmZ1bmRpbmdQdWJLZXldO1xuXG4gICAgY29uc3QgcDJtcyA9IHBheW1lbnRzLnAybXMoe1xuICAgICAgbTogMixcbiAgICAgIHB1YmtleXM6IGZ1bmRpbmdQdWJLZXlzLFxuICAgICAgbmV0d29yayxcbiAgICB9KTtcblxuICAgIGNvbnN0IHBheW1lbnRWYXJpYW50ID0gcGF5bWVudHMucDJ3c2goe1xuICAgICAgcmVkZWVtOiBwMm1zLFxuICAgICAgbmV0d29yayxcbiAgICB9KTtcblxuICAgIC8vIE1ha2UgdGVtcG9yYXJ5IGFycmF5IHRvIGhvbGQgYWxsIGlucHV0cyBhbmQgdGhlbiBzb3J0IHRoZW1cbiAgICAvLyB0aGlzIG1ldGhvZCBjYW4gYmUgaW1wcm92ZWQgbGF0ZXJcbiAgICBjb25zdCBwc2J0SW5wdXRzID0gW107XG4gICAgcHNidElucHV0cy5wdXNoKHtcbiAgICAgIGhhc2g6IGRsY1R4cy5mdW5kVHgudHhJZC5zZXJpYWxpemUoKSxcbiAgICAgIGluZGV4OiBkbGNUeHMuZnVuZFR4Vm91dCxcbiAgICAgIHNlcXVlbmNlOiAwLFxuICAgICAgd2l0bmVzc1V0eG86IHtcbiAgICAgICAgc2NyaXB0OiBwYXltZW50VmFyaWFudC5vdXRwdXQsXG4gICAgICAgIHZhbHVlOiBOdW1iZXIoZGxjVHhzLmZ1bmRUeC5vdXRwdXRzW2RsY1R4cy5mdW5kVHhWb3V0XS52YWx1ZS5zYXRzKSxcbiAgICAgIH0sXG4gICAgICB3aXRuZXNzU2NyaXB0OiBwYXltZW50VmFyaWFudC5yZWRlZW0ub3V0cHV0LFxuICAgICAgaW5wdXRTZXJpYWxJZDogZGxjQ2xvc2UuZnVuZElucHV0U2VyaWFsSWQsXG4gICAgfSk7XG5cbiAgICAvLyBhZGQgYWxsIGRsYyBjbG9zZSBpbnB1dHNcbiAgICBkbGNDbG9zZS5mdW5kaW5nSW5wdXRzLmZvckVhY2goKGlucHV0LCBpKSA9PiB7XG4gICAgICBwc2J0SW5wdXRzLnB1c2goe1xuICAgICAgICBoYXNoOiBpbnB1dC5wcmV2VHgudHhJZC5zZXJpYWxpemUoKSxcbiAgICAgICAgaW5kZXg6IGlucHV0LnByZXZUeFZvdXQsXG4gICAgICAgIHNlcXVlbmNlOiAwLFxuICAgICAgICB3aXRuZXNzVXR4bzoge1xuICAgICAgICAgIHNjcmlwdDogaW5wdXQucHJldlR4Lm91dHB1dHNbaW5wdXQucHJldlR4Vm91dF0uc2NyaXB0UHViS2V5XG4gICAgICAgICAgICAuc2VyaWFsaXplKClcbiAgICAgICAgICAgIC5zbGljZSgxKSxcbiAgICAgICAgICB2YWx1ZTogTnVtYmVyKGlucHV0LnByZXZUeC5vdXRwdXRzW2lucHV0LnByZXZUeFZvdXRdLnZhbHVlLnNhdHMpLFxuICAgICAgICB9LFxuICAgICAgICBpbnB1dFNlcmlhbElkOiBpbnB1dC5pbnB1dFNlcmlhbElkLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBzb3J0IGFsbCBpbnB1dHMgaW4gYXNjZW5kaW5nIG9yZGVyIGJ5IHNlcmlhbCBJRFxuICAgIC8vIFRoZSBvbmx5IHJlYXNvbiB3ZSBhcmUgZG9pbmcgdGhpcyBpcyBmb3IgcHJpdmFjeS4gSWYgdGhlIGZ1bmRpbmdJbnB1dCBpc1xuICAgIC8vIGFsd2F5cyBmaXJzdCwgaXQgaXMgdmVyeSBvYnZpb3VzLiBIZW5jZSwgYSBzZXJpYWxJZCBpcyByYW5kb21seSBnZW5lcmF0ZWRcbiAgICAvLyBhbmQgdGhlIGlucHV0cyBhcmUgc29ydGVkIGJ5IHRoYXQgaW5zdGVhZC5cbiAgICBjb25zdCBzb3J0ZWRQc2J0SW5wdXRzID0gcHNidElucHV0cy5zb3J0KChhLCBiKSA9PlxuICAgICAgTnVtYmVyKGEuaW5wdXRTZXJpYWxJZCAtIGIuaW5wdXRTZXJpYWxJZCksXG4gICAgKTtcblxuICAgIC8vIEdldCBpbmRleCBvZiBmdW5kaW5nSW5wdXRcbiAgICBjb25zdCBmdW5kaW5nSW5wdXRJbmRleCA9IHNvcnRlZFBzYnRJbnB1dHMuZmluZEluZGV4KFxuICAgICAgKGlucHV0KSA9PiBpbnB1dC5pbnB1dFNlcmlhbElkID09PSBkbGNDbG9zZS5mdW5kSW5wdXRTZXJpYWxJZCxcbiAgICApO1xuXG4gICAgY29uc3Qgb2ZmZXJGaXJzdCA9IGRsY09mZmVyLnBheW91dFNlcmlhbElkIDwgZGxjQWNjZXB0LnBheW91dFNlcmlhbElkO1xuXG4gICAgcHNidC5hZGRPdXRwdXQoe1xuICAgICAgdmFsdWU6IE51bWJlcihcbiAgICAgICAgb2ZmZXJGaXJzdFxuICAgICAgICAgID8gZGxjQ2xvc2Uub2ZmZXJQYXlvdXRTYXRvc2hpc1xuICAgICAgICAgIDogZGxjQ2xvc2UuYWNjZXB0UGF5b3V0U2F0b3NoaXMsXG4gICAgICApLFxuICAgICAgYWRkcmVzczogYWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0KFxuICAgICAgICBvZmZlckZpcnN0ID8gZGxjT2ZmZXIucGF5b3V0U1BLIDogZGxjQWNjZXB0LnBheW91dFNQSyxcbiAgICAgICAgbmV0d29yayxcbiAgICAgICksXG4gICAgfSk7XG5cbiAgICBwc2J0LmFkZE91dHB1dCh7XG4gICAgICB2YWx1ZTogTnVtYmVyKFxuICAgICAgICBvZmZlckZpcnN0XG4gICAgICAgICAgPyBkbGNDbG9zZS5hY2NlcHRQYXlvdXRTYXRvc2hpc1xuICAgICAgICAgIDogZGxjQ2xvc2Uub2ZmZXJQYXlvdXRTYXRvc2hpcyxcbiAgICAgICksXG4gICAgICBhZGRyZXNzOiBhZGRyZXNzLmZyb21PdXRwdXRTY3JpcHQoXG4gICAgICAgIG9mZmVyRmlyc3QgPyBkbGNBY2NlcHQucGF5b3V0U1BLIDogZGxjT2ZmZXIucGF5b3V0U1BLLFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgKSxcbiAgICB9KTtcblxuICAgIC8vIGFkZCB0byBwc2J0XG4gICAgc29ydGVkUHNidElucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4gcHNidC5hZGRJbnB1dChpbnB1dCkpO1xuXG4gICAgY29uc3Qgb2ZmZXJlciA9IGF3YWl0IHRoaXMuaXNPZmZlcmVyKGRsY09mZmVyLCBkbGNBY2NlcHQpO1xuXG4gICAgLy8gR2VuZXJhdGUga2V5cGFpciB0byBzaWduIGlucHV0c1xuICAgIGNvbnN0IGZ1bmRQcml2YXRlS2V5UGFpciA9IGF3YWl0IHRoaXMuR2V0RnVuZEtleVBhaXIoXG4gICAgICBkbGNPZmZlcixcbiAgICAgIGRsY0FjY2VwdCxcbiAgICAgIG9mZmVyZXIsXG4gICAgKTtcblxuICAgIC8vIFNpZ24gZGxjIGZ1bmRpbmdpbnB1dFxuICAgIHBzYnQuc2lnbklucHV0KGZ1bmRpbmdJbnB1dEluZGV4LCBmdW5kUHJpdmF0ZUtleVBhaXIpO1xuXG4gICAgY29uc3QgcGFydGlhbFNpZyA9IFtcbiAgICAgIHtcbiAgICAgICAgcHVia2V5OiBvZmZlcmVyID8gZGxjQWNjZXB0LmZ1bmRpbmdQdWJLZXkgOiBkbGNPZmZlci5mdW5kaW5nUHViS2V5LFxuICAgICAgICBzaWduYXR1cmU6IGF3YWl0IHNjcmlwdC5zaWduYXR1cmUuZW5jb2RlKGRsY0Nsb3NlLmNsb3NlU2lnbmF0dXJlLCAxKSwgLy8gZW5jb2RlIHVzaW5nIFNJR0hBU0hfQUxMXG4gICAgICB9LFxuICAgIF07XG4gICAgcHNidC51cGRhdGVJbnB1dChmdW5kaW5nSW5wdXRJbmRleCwgeyBwYXJ0aWFsU2lnIH0pO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwc2J0LmRhdGEuaW5wdXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAoaSA9PT0gZnVuZGluZ0lucHV0SW5kZXgpIGNvbnRpbnVlO1xuICAgICAgaWYgKCFwc2J0LmRhdGEuaW5wdXRzW2ldLnBhcnRpYWxTaWcpIHBzYnQuZGF0YS5pbnB1dHNbaV0ucGFydGlhbFNpZyA9IFtdO1xuXG4gICAgICBjb25zdCB3aXRuZXNzSSA9IGRsY0Nsb3NlLmZ1bmRpbmdTaWduYXR1cmVzLndpdG5lc3NFbGVtZW50cy5maW5kSW5kZXgoXG4gICAgICAgIChlbCkgPT5cbiAgICAgICAgICBCdWZmZXIuY29tcGFyZShcbiAgICAgICAgICAgIFNjcmlwdC5wMndwa2hMb2NrKGhhc2gxNjAoZWxbMV0ud2l0bmVzcykpLnNlcmlhbGl6ZSgpLnNsaWNlKDEpLFxuICAgICAgICAgICAgcHNidC5kYXRhLmlucHV0c1tpXS53aXRuZXNzVXR4by5zY3JpcHQsXG4gICAgICAgICAgKSA9PT0gMCxcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHBhcnRpYWxTaWcgPSBbXG4gICAgICAgIHtcbiAgICAgICAgICBwdWJrZXk6XG4gICAgICAgICAgICBkbGNDbG9zZS5mdW5kaW5nU2lnbmF0dXJlcy53aXRuZXNzRWxlbWVudHNbd2l0bmVzc0ldWzFdLndpdG5lc3MsXG4gICAgICAgICAgc2lnbmF0dXJlOlxuICAgICAgICAgICAgZGxjQ2xvc2UuZnVuZGluZ1NpZ25hdHVyZXMud2l0bmVzc0VsZW1lbnRzW3dpdG5lc3NJXVswXS53aXRuZXNzLFxuICAgICAgICB9LFxuICAgICAgXTtcblxuICAgICAgcHNidC51cGRhdGVJbnB1dChpLCB7IHBhcnRpYWxTaWcgfSk7XG4gICAgfVxuXG4gICAgcHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZkFsbElucHV0cygpO1xuICAgIHBzYnQuZmluYWxpemVBbGxJbnB1dHMoKTtcblxuICAgIHJldHVybiBwc2J0LmV4dHJhY3RUcmFuc2FjdGlvbigpLnRvSGV4KCk7XG4gIH1cblxuICBhc3luYyBBZGRTaWduYXR1cmVUb0Z1bmRUcmFuc2FjdGlvbihcbiAgICBqc29uT2JqZWN0OiBBZGRTaWduYXR1cmVUb0Z1bmRUcmFuc2FjdGlvblJlcXVlc3QsXG4gICk6IFByb21pc2U8QWRkU2lnbmF0dXJlVG9GdW5kVHJhbnNhY3Rpb25SZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuQWRkU2lnbmF0dXJlVG9GdW5kVHJhbnNhY3Rpb24oanNvbk9iamVjdCk7XG4gIH1cblxuICBhc3luYyBDcmVhdGVDZXRBZGFwdG9yU2lnbmF0dXJlKFxuICAgIGpzb25PYmplY3Q6IENyZWF0ZUNldEFkYXB0b3JTaWduYXR1cmVSZXF1ZXN0LFxuICApOiBQcm9taXNlPENyZWF0ZUNldEFkYXB0b3JTaWduYXR1cmVSZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuQ3JlYXRlQ2V0QWRhcHRvclNpZ25hdHVyZShqc29uT2JqZWN0KTtcbiAgfVxuXG4gIGFzeW5jIENyZWF0ZUNldEFkYXB0b3JTaWduYXR1cmVzKFxuICAgIGpzb25PYmplY3Q6IENyZWF0ZUNldEFkYXB0b3JTaWduYXR1cmVzUmVxdWVzdCxcbiAgKTogUHJvbWlzZTxDcmVhdGVDZXRBZGFwdG9yU2lnbmF0dXJlc1Jlc3BvbnNlPiB7XG4gICAgYXdhaXQgdGhpcy5DZmRMb2FkZWQoKTtcblxuICAgIHJldHVybiB0aGlzLl9jZmREbGNKcy5DcmVhdGVDZXRBZGFwdG9yU2lnbmF0dXJlcyhqc29uT2JqZWN0KTtcbiAgfVxuXG4gIGFzeW5jIEFkZFNpZ25hdHVyZXNUb1JlZnVuZFR4KFxuICAgIGpzb25PYmplY3Q6IEFkZFNpZ25hdHVyZXNUb1JlZnVuZFR4UmVxdWVzdCxcbiAgKTogUHJvbWlzZTxBZGRTaWduYXR1cmVzVG9SZWZ1bmRUeFJlc3BvbnNlPiB7XG4gICAgYXdhaXQgdGhpcy5DZmRMb2FkZWQoKTtcblxuICAgIHJldHVybiB0aGlzLl9jZmREbGNKcy5BZGRTaWduYXR1cmVzVG9SZWZ1bmRUeChqc29uT2JqZWN0KTtcbiAgfVxuXG4gIGFzeW5jIENyZWF0ZUNldChqc29uT2JqZWN0OiBDcmVhdGVDZXRSZXF1ZXN0KTogUHJvbWlzZTxDcmVhdGVDZXRSZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuQ3JlYXRlQ2V0KGpzb25PYmplY3QpO1xuICB9XG5cbiAgYXN5bmMgQ3JlYXRlRGxjVHJhbnNhY3Rpb25zKFxuICAgIGpzb25PYmplY3Q6IENyZWF0ZURsY1RyYW5zYWN0aW9uc1JlcXVlc3QsXG4gICk6IFByb21pc2U8Q3JlYXRlRGxjVHJhbnNhY3Rpb25zUmVzcG9uc2U+IHtcbiAgICBhd2FpdCB0aGlzLkNmZExvYWRlZCgpO1xuXG4gICAgcmV0dXJuIHRoaXMuX2NmZERsY0pzLkNyZWF0ZURsY1RyYW5zYWN0aW9ucyhqc29uT2JqZWN0KTtcbiAgfVxuXG4gIGFzeW5jIENyZWF0ZUZ1bmRUcmFuc2FjdGlvbihcbiAgICBqc29uT2JqZWN0OiBDcmVhdGVGdW5kVHJhbnNhY3Rpb25SZXF1ZXN0LFxuICApOiBQcm9taXNlPENyZWF0ZUZ1bmRUcmFuc2FjdGlvblJlc3BvbnNlPiB7XG4gICAgYXdhaXQgdGhpcy5DZmRMb2FkZWQoKTtcblxuICAgIHJldHVybiB0aGlzLl9jZmREbGNKcy5DcmVhdGVGdW5kVHJhbnNhY3Rpb24oanNvbk9iamVjdCk7XG4gIH1cblxuICBhc3luYyBDcmVhdGVSZWZ1bmRUcmFuc2FjdGlvbihcbiAgICBqc29uT2JqZWN0OiBDcmVhdGVSZWZ1bmRUcmFuc2FjdGlvblJlcXVlc3QsXG4gICk6IFByb21pc2U8Q3JlYXRlUmVmdW5kVHJhbnNhY3Rpb25SZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuQ3JlYXRlUmVmdW5kVHJhbnNhY3Rpb24oanNvbk9iamVjdCk7XG4gIH1cblxuICBhc3luYyBHZXRSYXdGdW5kVHhTaWduYXR1cmUoXG4gICAganNvbk9iamVjdDogR2V0UmF3RnVuZFR4U2lnbmF0dXJlUmVxdWVzdCxcbiAgKTogUHJvbWlzZTxHZXRSYXdGdW5kVHhTaWduYXR1cmVSZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuR2V0UmF3RnVuZFR4U2lnbmF0dXJlKGpzb25PYmplY3QpO1xuICB9XG5cbiAgYXN5bmMgR2V0UmF3UmVmdW5kVHhTaWduYXR1cmUoXG4gICAganNvbk9iamVjdDogR2V0UmF3UmVmdW5kVHhTaWduYXR1cmVSZXF1ZXN0LFxuICApOiBQcm9taXNlPEdldFJhd1JlZnVuZFR4U2lnbmF0dXJlUmVzcG9uc2U+IHtcbiAgICBhd2FpdCB0aGlzLkNmZExvYWRlZCgpO1xuXG4gICAgcmV0dXJuIHRoaXMuX2NmZERsY0pzLkdldFJhd1JlZnVuZFR4U2lnbmF0dXJlKGpzb25PYmplY3QpO1xuICB9XG5cbiAgYXN5bmMgU2lnbkNldChqc29uT2JqZWN0OiBTaWduQ2V0UmVxdWVzdCk6IFByb21pc2U8U2lnbkNldFJlc3BvbnNlPiB7XG4gICAgYXdhaXQgdGhpcy5DZmRMb2FkZWQoKTtcblxuICAgIHJldHVybiB0aGlzLl9jZmREbGNKcy5TaWduQ2V0KGpzb25PYmplY3QpO1xuICB9XG5cbiAgYXN5bmMgVmVyaWZ5Q2V0QWRhcHRvclNpZ25hdHVyZShcbiAgICBqc29uT2JqZWN0OiBWZXJpZnlDZXRBZGFwdG9yU2lnbmF0dXJlUmVxdWVzdCxcbiAgKTogUHJvbWlzZTxWZXJpZnlDZXRBZGFwdG9yU2lnbmF0dXJlUmVzcG9uc2U+IHtcbiAgICBhd2FpdCB0aGlzLkNmZExvYWRlZCgpO1xuXG4gICAgcmV0dXJuIHRoaXMuX2NmZERsY0pzLlZlcmlmeUNldEFkYXB0b3JTaWduYXR1cmUoanNvbk9iamVjdCk7XG4gIH1cblxuICBhc3luYyBWZXJpZnlDZXRBZGFwdG9yU2lnbmF0dXJlcyhcbiAgICBqc29uT2JqZWN0OiBWZXJpZnlDZXRBZGFwdG9yU2lnbmF0dXJlc1JlcXVlc3QsXG4gICk6IFByb21pc2U8VmVyaWZ5Q2V0QWRhcHRvclNpZ25hdHVyZXNSZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuVmVyaWZ5Q2V0QWRhcHRvclNpZ25hdHVyZXMoanNvbk9iamVjdCk7XG4gIH1cblxuICBhc3luYyBTaWduRnVuZFRyYW5zYWN0aW9uKFxuICAgIGpzb25PYmplY3Q6IFNpZ25GdW5kVHJhbnNhY3Rpb25SZXF1ZXN0LFxuICApOiBQcm9taXNlPFNpZ25GdW5kVHJhbnNhY3Rpb25SZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuU2lnbkZ1bmRUcmFuc2FjdGlvbihqc29uT2JqZWN0KTtcbiAgfVxuXG4gIGFzeW5jIFZlcmlmeUZ1bmRUeFNpZ25hdHVyZShcbiAgICBqc29uT2JqZWN0OiBWZXJpZnlGdW5kVHhTaWduYXR1cmVSZXF1ZXN0LFxuICApOiBQcm9taXNlPFZlcmlmeUZ1bmRUeFNpZ25hdHVyZVJlc3BvbnNlPiB7XG4gICAgYXdhaXQgdGhpcy5DZmRMb2FkZWQoKTtcblxuICAgIHJldHVybiB0aGlzLl9jZmREbGNKcy5WZXJpZnlGdW5kVHhTaWduYXR1cmUoanNvbk9iamVjdCk7XG4gIH1cblxuICBhc3luYyBWZXJpZnlSZWZ1bmRUeFNpZ25hdHVyZShcbiAgICBqc29uT2JqZWN0OiBWZXJpZnlSZWZ1bmRUeFNpZ25hdHVyZVJlcXVlc3QsXG4gICk6IFByb21pc2U8VmVyaWZ5UmVmdW5kVHhTaWduYXR1cmVSZXNwb25zZT4ge1xuICAgIGF3YWl0IHRoaXMuQ2ZkTG9hZGVkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fY2ZkRGxjSnMuVmVyaWZ5UmVmdW5kVHhTaWduYXR1cmUoanNvbk9iamVjdCk7XG4gIH1cblxuICBhc3luYyBmdW5kaW5nSW5wdXRUb0lucHV0KFxuICAgIF9pbnB1dDogRnVuZGluZ0lucHV0LFxuICAgIGZpbmREZXJpdmF0aW9uUGF0aCA9IHRydWUsXG4gICk6IFByb21pc2U8SW5wdXQ+IHtcbiAgICBhc3NlcnQoXG4gICAgICBfaW5wdXQudHlwZSA9PT0gTWVzc2FnZVR5cGUuRnVuZGluZ0lucHV0VjAsXG4gICAgICAnRnVuZGluZ0lucHV0IG11c3QgYmUgVjAnLFxuICAgICk7XG4gICAgY29uc3QgbmV0d29yayA9IGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGVkTmV0d29yaygpO1xuICAgIGNvbnN0IGlucHV0ID0gX2lucHV0IGFzIEZ1bmRpbmdJbnB1dFYwO1xuICAgIGNvbnN0IHByZXZUeCA9IGlucHV0LnByZXZUeDtcbiAgICBjb25zdCBwcmV2VHhPdXQgPSBwcmV2VHgub3V0cHV0c1tpbnB1dC5wcmV2VHhWb3V0XTtcbiAgICBjb25zdCBzY3JpcHRQdWJLZXkgPSBwcmV2VHhPdXQuc2NyaXB0UHViS2V5LnNlcmlhbGl6ZSgpLnNsaWNlKDEpO1xuICAgIGNvbnN0IF9hZGRyZXNzID0gYWRkcmVzcy5mcm9tT3V0cHV0U2NyaXB0KHNjcmlwdFB1YktleSwgbmV0d29yayk7XG4gICAgbGV0IGRlcml2YXRpb25QYXRoOiBzdHJpbmc7XG5cbiAgICBpZiAoZmluZERlcml2YXRpb25QYXRoKSB7XG4gICAgICBjb25zdCBpbnB1dEFkZHJlc3M6IEFkZHJlc3MgPSBhd2FpdCB0aGlzLmNsaWVudC5maW5hbmNld2FsbGV0LnF1aWNrRmluZEFkZHJlc3MoXG4gICAgICAgIFtfYWRkcmVzc10sXG4gICAgICApO1xuICAgICAgaWYgKGlucHV0QWRkcmVzcykge1xuICAgICAgICBkZXJpdmF0aW9uUGF0aCA9IGlucHV0QWRkcmVzcy5kZXJpdmF0aW9uUGF0aDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHhpZDogcHJldlR4LnR4SWQudG9TdHJpbmcoKSxcbiAgICAgIHZvdXQ6IGlucHV0LnByZXZUeFZvdXQsXG4gICAgICBhZGRyZXNzOiBfYWRkcmVzcyxcbiAgICAgIGFtb3VudDogcHJldlR4T3V0LnZhbHVlLmJpdGNvaW4sXG4gICAgICB2YWx1ZTogTnVtYmVyKHByZXZUeE91dC52YWx1ZS5zYXRzKSxcbiAgICAgIGRlcml2YXRpb25QYXRoLFxuICAgICAgbWF4V2l0bmVzc0xlbmd0aDogaW5wdXQubWF4V2l0bmVzc0xlbixcbiAgICAgIHJlZGVlbVNjcmlwdDogaW5wdXQucmVkZWVtU2NyaXB0XG4gICAgICAgID8gaW5wdXQucmVkZWVtU2NyaXB0LnRvU3RyaW5nKCdoZXgnKVxuICAgICAgICA6ICcnLFxuICAgICAgc2NyaXB0UHViS2V5OiBzY3JpcHRQdWJLZXkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgaW5wdXRTZXJpYWxJZDogaW5wdXQuaW5wdXRTZXJpYWxJZCxcbiAgICAgIHRvVXR4bzogSW5wdXQucHJvdG90eXBlLnRvVXR4byxcbiAgICB9O1xuICB9XG5cbiAgYXN5bmMgaW5wdXRUb0Z1bmRpbmdJbnB1dChpbnB1dDogSW5wdXQpOiBQcm9taXNlPEZ1bmRpbmdJbnB1dD4ge1xuICAgIGNvbnN0IGZ1bmRpbmdJbnB1dCA9IG5ldyBGdW5kaW5nSW5wdXRWMCgpO1xuICAgIGZ1bmRpbmdJbnB1dC5wcmV2VHhWb3V0ID0gaW5wdXQudm91dDtcblxuICAgIGxldCB0eFJhdyA9ICcnO1xuICAgIHRyeSB7XG4gICAgICB0eFJhdyA9IGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdnZXRSYXdUcmFuc2FjdGlvbkJ5SGFzaCcpKGlucHV0LnR4aWQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHR4UmF3ID0gKGF3YWl0IHRoaXMuZ2V0TWV0aG9kKCdqc29ucnBjJykoJ2dldHRyYW5zYWN0aW9uJywgaW5wdXQudHhpZCkpXG4gICAgICAgICAgLmhleDtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoXG4gICAgICAgICAgYENhbm5vdCBmaW5kIHR4ICR7aW5wdXQudHhpZH0gaW4gaW5wdXRUb0Z1bmRpbmdJbnB1dCB1c2luZyBnZXRyYXd0cmFuc2FjdGlvbmJ5aGFzaCBvciBnZXR0cmFuc2FjdGlvbmAsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHR4ID0gVHguZGVjb2RlKFN0cmVhbVJlYWRlci5mcm9tSGV4KHR4UmF3KSk7XG5cbiAgICBmdW5kaW5nSW5wdXQucHJldlR4ID0gdHg7XG4gICAgZnVuZGluZ0lucHV0LnNlcXVlbmNlID0gU2VxdWVuY2UuZGVmYXVsdCgpO1xuICAgIGZ1bmRpbmdJbnB1dC5tYXhXaXRuZXNzTGVuID0gaW5wdXQubWF4V2l0bmVzc0xlbmd0aFxuICAgICAgPyBpbnB1dC5tYXhXaXRuZXNzTGVuZ3RoXG4gICAgICA6IDEwODtcbiAgICBmdW5kaW5nSW5wdXQucmVkZWVtU2NyaXB0ID0gaW5wdXQucmVkZWVtU2NyaXB0XG4gICAgICA/IEJ1ZmZlci5mcm9tKGlucHV0LnJlZGVlbVNjcmlwdCwgJ2hleCcpXG4gICAgICA6IEJ1ZmZlci5mcm9tKCcnLCAnaGV4Jyk7XG4gICAgZnVuZGluZ0lucHV0LmlucHV0U2VyaWFsSWQgPSBpbnB1dC5pbnB1dFNlcmlhbElkXG4gICAgICA/IGlucHV0LmlucHV0U2VyaWFsSWRcbiAgICAgIDogZ2VuZXJhdGVTZXJpYWxJZCgpO1xuXG4gICAgcmV0dXJuIGZ1bmRpbmdJbnB1dDtcbiAgfVxuXG4gIGFzeW5jIGdldENvbm5lY3RlZE5ldHdvcmsoKTogUHJvbWlzZTxCaXRjb2luTmV0d29yaz4ge1xuICAgIHJldHVybiB0aGlzLl9uZXR3b3JrO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5pdGlhbGl6ZVJlc3BvbnNlIHtcbiAgZnVuZGluZ1B1YktleTogQnVmZmVyO1xuICBwYXlvdXRTUEs6IEJ1ZmZlcjtcbiAgcGF5b3V0U2VyaWFsSWQ6IGJpZ2ludDtcbiAgZnVuZGluZ0lucHV0czogRnVuZGluZ0lucHV0W107XG4gIGNoYW5nZVNQSzogQnVmZmVyO1xuICBjaGFuZ2VTZXJpYWxJZDogYmlnaW50O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFjY2VwdERsY09mZmVyUmVzcG9uc2Uge1xuICBkbGNBY2NlcHQ6IERsY0FjY2VwdDtcbiAgZGxjVHJhbnNhY3Rpb25zOiBEbGNUcmFuc2FjdGlvbnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2lnbkRsY0FjY2VwdFJlc3BvbnNlIHtcbiAgZGxjU2lnbjogRGxjU2lnbjtcbiAgZGxjVHJhbnNhY3Rpb25zOiBEbGNUcmFuc2FjdGlvbnM7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0UGF5b3V0c1Jlc3BvbnNlIHtcbiAgcGF5b3V0czogUGF5b3V0UmVxdWVzdFtdO1xuICBwYXlvdXRHcm91cHM6IFBheW91dEdyb3VwW107XG4gIG1lc3NhZ2VzTGlzdDogTWVzc2FnZXNbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVEbGNUeHNSZXNwb25zZSB7XG4gIGRsY1RyYW5zYWN0aW9uczogRGxjVHJhbnNhY3Rpb25zO1xuICBtZXNzYWdlc0xpc3Q6IE1lc3NhZ2VzW107XG59XG5cbmludGVyZmFjZSBJU2lnIHtcbiAgZW5jcnlwdGVkU2lnOiBCdWZmZXI7XG4gIGRsZXFQcm9vZjogQnVmZmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZUNldEFkYXB0b3JBbmRSZWZ1bmRTaWdzUmVzcG9uc2Uge1xuICBjZXRTaWduYXR1cmVzOiBDZXRBZGFwdG9yU2lnbmF0dXJlc1YwO1xuICByZWZ1bmRTaWduYXR1cmU6IEJ1ZmZlcjtcbn1cblxuaW50ZXJmYWNlIFBheW91dEdyb3VwIHtcbiAgcGF5b3V0OiBiaWdpbnQ7XG4gIGdyb3VwczogbnVtYmVyW11bXTtcbn1cblxuaW50ZXJmYWNlIEZpbmRPdXRjb21lUmVzcG9uc2Uge1xuICBpbmRleDogbnVtYmVyO1xuICBncm91cExlbmd0aDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENoYW5nZSB7XG4gIHZhbHVlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3V0cHV0IHtcbiAgdmFsdWU6IG51bWJlcjtcbiAgaWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSW5wdXRzRm9yQW1vdW50UmVzcG9uc2Uge1xuICBpbnB1dHM6IElucHV0W107XG4gIGNoYW5nZTogQ2hhbmdlO1xuICBvdXRwdXRzOiBPdXRwdXRbXTtcbiAgZmVlOiBudW1iZXI7XG59XG5cbmNvbnN0IEJ1cm5BZGRyZXNzID0gJ2JjcnQxcXhjanVmZ2gyamFya3AycWt4NjhhemgwOHc5djVnYWg4dTZlczhzJztcbiJdLCJuYW1lcyI6WyJFU1RJTUFURURfU0laRSIsIkJpdGNvaW5EbGNQcm92aWRlciIsIlByb3ZpZGVyIiwiQ2ZkTG9hZGVkIiwiX2NmZERsY0pzIiwic2xlZXAiLCJHZXRQcml2S2V5c0ZvcklucHV0cyIsImlucHV0cyIsInByaXZLZXlzIiwiaSIsImxlbmd0aCIsImlucHV0IiwiZGVyaXZhdGlvblBhdGgiLCJnZXRNZXRob2QiLCJhZGRyZXNzIiwia2V5UGFpciIsInByaXZLZXkiLCJCdWZmZXIiLCJmcm9tIiwiX19EIiwidG9TdHJpbmciLCJwdXNoIiwiR2V0Q2ZkTmV0d29yayIsIm5ldHdvcmsiLCJnZXRDb25uZWN0ZWROZXR3b3JrIiwibmFtZSIsIkdldElucHV0c0ZvckFtb3VudCIsImFtb3VudCIsImZlZVJhdGVQZXJWYiIsImZpeGVkSW5wdXRzIiwiQmlnSW50IiwidGFyZ2V0cyIsIkJ1cm5BZGRyZXNzIiwidmFsdWUiLCJOdW1iZXIiLCJpbnB1dHNGb3JBbW91bnQiLCJlIiwiRXJyb3IiLCJJbml0aWFsaXplIiwiY29sbGF0ZXJhbCIsInBheW91dEFkZHJlc3MiLCJjbGllbnQiLCJ3YWxsZXQiLCJnZXRVbnVzZWRBZGRyZXNzIiwicGF5b3V0U1BLIiwidG9PdXRwdXRTY3JpcHQiLCJjaGFuZ2VBZGRyZXNzIiwiY2hhbmdlU1BLIiwiZnVuZGluZ0FkZHJlc3MiLCJmdW5kaW5nUHViS2V5IiwicHVibGljS2V5IiwiZnVuZGluZ0lucHV0cyIsIlByb21pc2UiLCJhbGwiLCJtYXAiLCJpbnB1dFRvRnVuZGluZ0lucHV0IiwicGF5b3V0U2VyaWFsSWQiLCJnZW5lcmF0ZVNlcmlhbElkIiwiY2hhbmdlU2VyaWFsSWQiLCJHZXRQYXlvdXRzRnJvbVBheW91dEZ1bmN0aW9uIiwiX2RsY09mZmVyIiwiY29udHJhY3REZXNjcmlwdG9yIiwib3JhY2xlSW5mbyIsInRvdGFsQ29sbGF0ZXJhbCIsInR5cGUiLCJNZXNzYWdlVHlwZSIsIkRsY09mZmVyVjAiLCJkbGNPZmZlciIsInBheW91dEZ1bmN0aW9uIiwiUGF5b3V0RnVuY3Rpb25WMCIsInBpZWNlcyIsInBheW91dEN1cnZlUGllY2UiLCJIeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlIiwiT2xkSHlwZXJib2xhUGF5b3V0Q3VydmVQaWVjZSIsImIiLCJjIiwiZXZlbnREZXNjcmlwdG9yIiwiYW5ub3VuY2VtZW50Iiwib3JhY2xlRXZlbnQiLCJEaWdpdERlY29tcG9zaXRpb25FdmVudERlc2NyaXB0b3JWMCIsInJvdW5kaW5nSW50ZXJ2YWxzIiwiY2V0UGF5b3V0cyIsIkh5cGVyYm9sYVBheW91dEN1cnZlIiwiY29tcHV0ZVBheW91dHMiLCJwYXlvdXRHcm91cHMiLCJmb3JFYWNoIiwicCIsInBheW91dCIsImdyb3VwcyIsImdyb3VwQnlJZ25vcmluZ0RpZ2l0cyIsImluZGV4RnJvbSIsImluZGV4VG8iLCJiYXNlIiwibnVtRGlnaXRzIiwiclZhbHVlc01lc3NhZ2VzTGlzdCIsIkdlbmVyYXRlTWVzc2FnZXMiLCJwYXlvdXRzIiwibWVzc2FnZXNMaXN0Iiwib3V0cHV0c1RvUGF5b3V0cyIsIm9mZmVyQ29sbGF0ZXJhbFNhdG9zaGlzIiwiY29udHJhY3RJbmZvIiwiR2V0UGF5b3V0c0Zyb21Qb2x5bm9taWFsUGF5b3V0RnVuY3Rpb24iLCJwaWVjZSIsIlBvbHlub21pYWxQYXlvdXRDdXJ2ZVBpZWNlIiwiUG9seW5vbWlhbFBheW91dEN1cnZlIiwiR2V0UGF5b3V0cyIsImNoZWNrVHlwZXMiLCJjb250cmFjdE9yYWNsZVBhaXJzIiwiR2V0Q29udHJhY3RPcmFjbGVQYWlycyIsInBheW91dFJlc3BvbnNlcyIsIkdldFBheW91dHNGcm9tQ29udHJhY3REZXNjcmlwdG9yIiwiRmxhdHRlblBheW91dHMiLCJyZWR1Y2UiLCJhY2MiLCJjb25jYXQiLCJHZXRJbmRpY2VzRnJvbVBheW91dHMiLCJwcmV2Iiwic3RhcnRpbmdNZXNzYWdlc0luZGV4Iiwic3RhcnRpbmdQYXlvdXRHcm91cHNJbmRleCIsIkNvbnRyYWN0RGVzY3JpcHRvclYwIiwiQ29udHJhY3REZXNjcmlwdG9yVjEiLCJjb250cmFjdERlc2NyaXB0b3JWMSIsImNyZWF0ZURsY1R4cyIsIl9kbGNBY2NlcHQiLCJkbGNBY2NlcHQiLCJsb2NhbEZ1bmRQdWJrZXkiLCJyZW1vdGVGdW5kUHVia2V5IiwibG9jYWxGaW5hbFNjcmlwdFB1YmtleSIsInJlbW90ZUZpbmFsU2NyaXB0UHVia2V5IiwibG9jYWxDaGFuZ2VTY3JpcHRQdWJrZXkiLCJyZW1vdGVDaGFuZ2VTY3JpcHRQdWJrZXkiLCJsb2NhbElucHV0cyIsImZ1bmRpbmdJbnB1dCIsImZ1bmRpbmdJbnB1dFRvSW5wdXQiLCJ0b1V0eG8iLCJyZW1vdGVJbnB1dHMiLCJsb2NhbElucHV0QW1vdW50IiwiY3VyIiwiR2V0U2F0b3NoaUFtb3VudCIsInJlbW90ZUlucHV0QW1vdW50IiwiZGxjVHhSZXF1ZXN0IiwibG9jYWxDb2xsYXRlcmFsQW1vdW50IiwibG9jYWxQYXlvdXRTZXJpYWxJZCIsImxvY2FsQ2hhbmdlU2VyaWFsSWQiLCJyZW1vdGVDb2xsYXRlcmFsQW1vdW50IiwiYWNjZXB0Q29sbGF0ZXJhbFNhdG9zaGlzIiwicmVtb3RlUGF5b3V0U2VyaWFsSWQiLCJyZW1vdGVDaGFuZ2VTZXJpYWxJZCIsInJlZnVuZExvY2t0aW1lIiwiZmVlUmF0ZSIsImNldExvY2tUaW1lIiwiY2V0TG9ja3RpbWUiLCJmdW5kT3V0cHV0U2VyaWFsSWQiLCJkbGNUeHMiLCJDcmVhdGVEbGNUcmFuc2FjdGlvbnMiLCJkbGNUcmFuc2FjdGlvbnMiLCJEbGNUcmFuc2FjdGlvbnNWMCIsImZ1bmRUeCIsIlR4IiwiZGVjb2RlIiwiU3RyZWFtUmVhZGVyIiwiZnJvbUhleCIsImZ1bmRUeEhleCIsImZ1bmRUeFZvdXQiLCJzb3J0IiwiYSIsImZpbmRJbmRleCIsInJlZnVuZFR4IiwicmVmdW5kVHhIZXgiLCJjZXRzIiwiY2V0c0hleCIsImNldEhleCIsIkdlbmVyYXRlRW51bU1lc3NhZ2VzIiwiR2VuZXJhdGVEaWdpdERlY29tcG9zaXRpb25NZXNzYWdlcyIsIm9yYWNsZU5vbmNlcyIsIm1lc3NhZ2VzIiwibSIsIkVudW1FdmVudERlc2NyaXB0b3JWMCIsIl9jb250cmFjdEluZm8iLCJDb250cmFjdEluZm9WMCIsIkNvbnRyYWN0SW5mb1YxIiwiQ3JlYXRlQ2V0QWRhcHRvckFuZFJlZnVuZFNpZ3MiLCJfZGxjVHhzIiwiaXNPZmZlcmVyIiwiY2V0Iiwic2VyaWFsaXplIiwiZnVuZGluZ1NQSyIsIlNjcmlwdCIsInAyd3BraExvY2siLCJoYXNoMTYwIiwic2xpY2UiLCJmcm9tT3V0cHV0U2NyaXB0IiwiZmluYW5jZXdhbGxldCIsInF1aWNrRmluZEFkZHJlc3MiLCJmdW5kUHJpdmF0ZUtleVBhaXIiLCJmdW5kUHJpdmF0ZUtleSIsImluZGljZXMiLCJzaWdzIiwiaW5kZXgiLCJlbnRyaWVzIiwib3JhY2xlQW5ub3VuY2VtZW50Iiwic3RhcnRpbmdJbmRleCIsImVuZGluZ0luZGV4Iiwib3JhY2xlRXZlbnRNZXNzYWdlc0xpc3QiLCJvcmFjbGVFdmVudENldHNIZXgiLCJjaHVuayIsImFkYXB0b3JTaWdSZXF1ZXN0UHJvbWlzZXMiLCJqIiwidGVtcE1lc3NhZ2VzTGlzdCIsInRlbXBDZXRzSGV4IiwiY2V0U2lnblJlcXVlc3QiLCJwcml2a2V5IiwiZnVuZFR4SWQiLCJ0eElkIiwiZnVuZFZvdXQiLCJmdW5kSW5wdXRBbW91bnQiLCJvdXRwdXRzIiwic2F0cyIsIm9yYWNsZVB1YmtleSIsIm9yYWNsZVJWYWx1ZXMiLCJub25jZSIsInJlc3BvbnNlIiwiQ3JlYXRlQ2V0QWRhcHRvclNpZ25hdHVyZXMiLCJhZGFwdG9yUGFpcnMiLCJmbGF0IiwiYWRhcHRvclBhaXIiLCJlbmNyeXB0ZWRTaWciLCJzaWduYXR1cmUiLCJkbGVxUHJvb2YiLCJwcm9vZiIsInJlZnVuZFNpZ25SZXF1ZXN0IiwicmVmdW5kU2lnbmF0dXJlIiwiR2V0UmF3UmVmdW5kVHhTaWduYXR1cmUiLCJoZXgiLCJjZXRTaWduYXR1cmVzIiwiQ2V0QWRhcHRvclNpZ25hdHVyZXNWMCIsIlZlcmlmeUNldEFkYXB0b3JBbmRSZWZ1bmRTaWdzIiwiX2RsY1NpZ24iLCJkbGNTaWduIiwib3JhY2xlRXZlbnRTaWdzIiwic2lnc1ZhbGlkaXR5IiwidGVtcFNpZ3MiLCJ0ZW1wQWRhcHRvclBhaXJzIiwic2lnIiwidmVyaWZ5Q2V0QWRhcHRvclNpZ25hdHVyZXNSZXF1ZXN0IiwidmVyaWZ5UmVtb3RlIiwiVmVyaWZ5Q2V0QWRhcHRvclNpZ25hdHVyZXMiLCJ2YWxpZCIsImFyZVNpZ3NWYWxpZCIsImV2ZXJ5IiwidmVyaWZ5UmVmdW5kU2lnUmVxdWVzdCIsIlZlcmlmeVJlZnVuZFR4U2lnbmF0dXJlIiwiQ3JlYXRlRnVuZGluZ1NpZ3MiLCJpbnB1dFByaXZLZXlzIiwiZnVuZFR4U2lncyIsImZ1bmRUeFNpZ25SZXF1ZXN0IiwicHJldlR4SWQiLCJ0eGlkIiwicHJldlZvdXQiLCJ2b3V0IiwiR2V0UmF3RnVuZFR4U2lnbmF0dXJlIiwiaW5wdXRQdWJLZXlzIiwicmVxUHJpdktleSIsImlzQ29tcHJlc3NlZCIsInB1YmtleSIsIndpdG5lc3NFbGVtZW50cyIsInNpZ1dpdG5lc3MiLCJTY3JpcHRXaXRuZXNzVjAiLCJ3aXRuZXNzIiwicHViS2V5V2l0bmVzcyIsImZ1bmRpbmdTaWduYXR1cmVzIiwiRnVuZGluZ1NpZ25hdHVyZXNWMCIsIlZlcmlmeUZ1bmRpbmdTaWdzIiwid2l0bmVzc0VsZW1lbnQiLCJ2ZXJpZnlGdW5kU2lnUmVxdWVzdCIsInByZXZUeCIsInByZXZUeFZvdXQiLCJWZXJpZnlGdW5kVHhTaWduYXR1cmUiLCJDcmVhdGVGdW5kaW5nVHgiLCJhc3luY0ZvckVhY2giLCJhZGRTaWduUmVxdWVzdCIsIkFkZFNpZ25hdHVyZVRvRnVuZFRyYW5zYWN0aW9uIiwiRmluZE91dGNvbWVJbmRleEZyb21Qb2x5bm9taWFsUGF5b3V0Q3VydmVQaWVjZSIsImNvbnRyYWN0T3JhY2xlUGFpckluZGV4IiwicG9seW5vbWlhbFBheW91dEN1cnZlUGllY2UiLCJvcmFjbGVBdHRlc3RhdGlvbiIsIm91dGNvbWUiLCJwb2x5bm9taWFsQ3VydmUiLCJmcm9tUGF5b3V0Q3VydmVQaWVjZSIsImNsYW1wQk4iLCJ2YWwiLCJCaWdOdW1iZXIiLCJtYXgiLCJtaW4iLCJnZXRQYXlvdXQiLCJwYXlvdXRJbmRleE9mZnNldCIsImludGVydmFsc1NvcnRlZCIsImludGVydmFscyIsImJlZ2luSW50ZXJ2YWwiLCJpbnRlcnZhbCIsImZpbmQiLCJyb3VuZGVkUGF5b3V0Iiwicm91bmRQYXlvdXQiLCJyb3VuZGluZ01vZCIsIm91dGNvbWVzRm9ybWF0dGVkIiwib3V0Y29tZXMiLCJwYXJzZUludCIsImdyb3VwSW5kZXgiLCJncm91cExlbmd0aCIsInBheW91dEdyb3VwIiwiZ3JvdXAiLCJtc2ciLCJGaW5kT3V0Y29tZUluZGV4RnJvbUh5cGVyYm9sYVBheW91dEN1cnZlUGllY2UiLCJoeXBlcmJvbGFQYXlvdXRDdXJ2ZVBpZWNlIiwiaHlwZXJib2xhQ3VydmUiLCJGaW5kT3V0Y29tZUluZGV4IiwiZXZlbnRJZCIsImFzc2VydCIsImNvbnRyYWN0T3JhY2xlUGFpciIsIl9jb250cmFjdERlc2NyaXB0b3IiLCJfcGF5b3V0RnVuY3Rpb24iLCJyZXZlcnNlIiwicGllY2VzU29ydGVkIiwiZW5kcG9pbnQiLCJWYWxpZGF0ZUV2ZW50IiwiYXR0ZXN0ZWRPcmFjbGVFdmVudCIsIkZpbmRBbmRTaWduQ2V0IiwidW5kZWZpbmVkIiwib3V0Y29tZUluZGV4IiwiR2V0RnVuZFByaXZhdGVLZXkiLCJzbGljZUluZGV4Iiwic2lnbmF0dXJlcyIsIm9yYWNsZVNpZ25hdHVyZXMiLCJzaWduQ2V0UmVxdWVzdCIsImZ1bmRQcml2a2V5IiwiYWRhcHRvclNpZ25hdHVyZSIsImZpbmFsQ2V0IiwiU2lnbkNldCIsIkdldEZ1bmRBZGRyZXNzIiwiR2V0RnVuZEtleVBhaXIiLCJwcml2YXRlS2V5IiwiQ3JlYXRlQ2xvc2VSYXdUeHMiLCJjbG9zZUlucHV0QW1vdW50IiwiX2RsY0Nsb3NlcyIsImluaXRpYXRvclBheW91dHMiLCJmaW5hbGl6ZXIiLCJEdWFsQ2xvc2luZ1R4RmluYWxpemVyIiwicmF3VHJhbnNhY3Rpb25SZXF1ZXN0UHJvbWlzZXMiLCJyYXdDbG9zZVR4cyIsIm51bVBheW91dHMiLCJvZmZlclBheW91dFZhbHVlIiwiYWNjZXB0UGF5b3V0VmFsdWUiLCJwYXlvdXRNaW51c09mZmVyRmVlcyIsIm9mZmVySW5pdGlhdG9yRmVlcyIsImNvbGxhdGVyYWxNaW51c1BheW91dCIsImRsY0Nsb3NlIiwiX2RsY0Nsb3NlIiwib2ZmZXJQYXlvdXRTYXRvc2hpcyIsImFjY2VwdFBheW91dFNhdG9zaGlzIiwidHhPdXRzIiwicmF3VHJhbnNhY3Rpb25SZXF1ZXN0IiwidmVyc2lvbiIsImxvY2t0aW1lIiwidHhpbnMiLCJzZXF1ZW5jZSIsInR4b3V0cyIsImhleHMiLCJDcmVhdGVTaWduYXR1cmVIYXNoZXMiLCJmdW5kaW5nUHViS2V5cyIsImNvbXBhcmUiLCJwMm1zIiwicGF5bWVudHMiLCJwdWJrZXlzIiwicGF5bWVudFZhcmlhbnQiLCJwMndzaCIsInJlZGVlbSIsInNpZ0hhc2hSZXF1ZXN0UHJvbWlzZXMiLCJzaWdIYXNoZXMiLCJyYXdUeCIsInNpZ0hhc2hSZXF1ZXN0IiwidHgiLCJ0eGluIiwia2V5RGF0YSIsIm91dHB1dCIsImhhc2hUeXBlIiwic2lnaGFzaFR5cGUiLCJzaWdoYXNoQW55b25lQ2FuUGF5Iiwic2lnaGFzaCIsInNpZ2hhc2hlcyIsIkNhbGN1bGF0ZUVjU2lnbmF0dXJlSGFzaGVzIiwiY2ZkTmV0d29yayIsInNpZ3NSZXF1ZXN0UHJvbWlzZXMiLCJzaWdIYXNoIiwiY2FsY3VsYXRlRWNTaWduYXR1cmVSZXF1ZXN0IiwicHJpdmtleURhdGEiLCJ3aWYiLCJpc0dyaW5kUiIsIlZlcmlmeVNpZ25hdHVyZXMiLCJkbGNDbG9zZXMiLCJ2ZXJpZnlTaWduYXR1cmVSZXF1ZXN0IiwiY2xvc2VTaWduYXR1cmUiLCJyZWRlZW1TY3JpcHQiLCJzdWNjZXNzIiwib2ZmZXJGdW5kaW5nU1BLIiwiYWNjZXB0RnVuZGluZ1NQSyIsIm9mZmVyRnVuZGluZ0FkZHJlc3MiLCJhY2NlcHRGdW5kaW5nQWRkcmVzcyIsIndhbGxldEFkZHJlc3MiLCJjcmVhdGVEbGNPZmZlciIsInZhbGlkYXRlIiwiX2Z1bmRpbmdJbnB1dHMiLCJGdW5kaW5nSW5wdXRWMCIsImNvbnRyYWN0RmxhZ3MiLCJjaGFpbkhhc2giLCJjaGFpbkhhc2hGcm9tTmV0d29yayIsIkR1YWxGdW5kaW5nVHhGaW5hbGl6ZXIiLCJmdW5kaW5nIiwidG90YWwiLCJvZmZlckZlZXMiLCJhY2NlcHREbGNPZmZlciIsIkRsY0FjY2VwdFYwIiwidGVtcENvbnRyYWN0SWQiLCJzaGEyNTYiLCJpZHMiLCJTZXQiLCJzaXplIiwiYWNjZXB0RmVlcyIsIl9kbGNUcmFuc2FjdGlvbnMiLCJjb250cmFjdElkIiwieG9yIiwibmVnb3RpYXRpb25GaWVsZHMiLCJOZWdvdGlhdGlvbkZpZWxkc1YwIiwic2lnbkRsY0FjY2VwdCIsIkRsY1NpZ25WMCIsImZpbmFsaXplRGxjU2lnbiIsImV4ZWN1dGUiLCJyZWZ1bmQiLCJhZGRTaWdzVG9SZWZ1bmRUeFJlcXVlc3QiLCJyZWZ1bmRIZXgiLCJBZGRTaWduYXR1cmVzVG9SZWZ1bmRUeCIsImNyZWF0ZURsY0Nsb3NlIiwiaW5pdGlhdG9yUGF5b3V0U2F0b3NoaXMiLCJfaW5wdXRzIiwicHNidCIsIlBzYnQiLCJ0ZW1wSW5wdXRzIiwiaW5wdXRTZXJpYWxJZCIsImZ1bmRpbmdJbnB1dFNlcmlhbElkIiwicHNidElucHV0cyIsImhhc2giLCJ3aXRuZXNzVXR4byIsInNjcmlwdCIsIndpdG5lc3NTY3JpcHQiLCJwMndwa2giLCJzb3J0ZWRQc2J0SW5wdXRzIiwiZnVuZGluZ0lucHV0SW5kZXgiLCJhZGRJbnB1dCIsIm9mZmVyRmlyc3QiLCJhZGRPdXRwdXQiLCJzaWduSW5wdXQiLCJ2YWxpZGF0ZVNpZ25hdHVyZXNPZkFsbElucHV0cyIsImRhdGEiLCJwYXJ0aWFsU2lnIiwiaW5wdXRTaWdzIiwiZmlsdGVyIiwiRGxjQ2xvc2VWMCIsInR4T3V0cHV0cyIsImZ1bmRJbnB1dFNlcmlhbElkIiwiY3JlYXRlQmF0Y2hEbGNDbG9zZSIsInZlcmlmeUJhdGNoRGxjQ2xvc2VVc2luZ01ldGFkYXRhIiwiZGxjQ2xvc2VNZXRhZGF0YSIsInRvRGxjTWVzc2FnZXMiLCJ2ZXJpZnlCYXRjaERsY0Nsb3NlIiwiZmluYWxpemVEbGNDbG9zZSIsInNjcmlwdFB1YktleSIsIm9mZmVyZXIiLCJlbmNvZGUiLCJ1cGRhdGVJbnB1dCIsIndpdG5lc3NJIiwiZWwiLCJmaW5hbGl6ZUFsbElucHV0cyIsImV4dHJhY3RUcmFuc2FjdGlvbiIsInRvSGV4IiwianNvbk9iamVjdCIsIkNyZWF0ZUNldEFkYXB0b3JTaWduYXR1cmUiLCJDcmVhdGVDZXQiLCJDcmVhdGVGdW5kVHJhbnNhY3Rpb24iLCJDcmVhdGVSZWZ1bmRUcmFuc2FjdGlvbiIsIlZlcmlmeUNldEFkYXB0b3JTaWduYXR1cmUiLCJTaWduRnVuZFRyYW5zYWN0aW9uIiwiX2lucHV0IiwiZmluZERlcml2YXRpb25QYXRoIiwicHJldlR4T3V0IiwiX2FkZHJlc3MiLCJpbnB1dEFkZHJlc3MiLCJiaXRjb2luIiwibWF4V2l0bmVzc0xlbmd0aCIsIm1heFdpdG5lc3NMZW4iLCJJbnB1dCIsInByb3RvdHlwZSIsInR4UmF3IiwiU2VxdWVuY2UiLCJkZWZhdWx0IiwiX25ldHdvcmsiLCJjb25zdHJ1Y3RvciIsImNmZERsY0pzIl0sIm1hcHBpbmdzIjoiQUFBQTs7OztBQUFxQyxJQUFBLGdCQUFpQyxXQUFqQyxpQ0FBaUMsQ0FBQTtBQUNqRCxJQUFBLFNBQXlCLGtDQUF6Qix5QkFBeUIsRUFBQTtBQTRDdkMsSUFBQSxNQUFzQixXQUF0QixzQkFBc0IsQ0FBQTtBQUdQLElBQUEsTUFBa0IsV0FBbEIsa0JBQWtCLENBQUE7QUFRakMsSUFBQSxLQUFnQixXQUFoQixnQkFBZ0IsQ0FBQTtBQWdDaEIsSUFBQSxVQUFxQixXQUFyQixxQkFBcUIsQ0FBQTtBQUNTLElBQUEsUUFBeUIsV0FBekIseUJBQXlCLENBQUE7QUFDakMsSUFBQSxNQUF1QixXQUF2Qix1QkFBdUIsQ0FBQTtBQUNmLElBQUEsT0FBd0IsV0FBeEIsd0JBQXdCLENBQUE7QUFDMUMsSUFBQSxPQUFRLGtDQUFSLFFBQVEsRUFBQTtBQUNMLElBQUEsWUFBYyxrQ0FBZCxjQUFjLEVBQUE7QUFPN0IsSUFBQSxhQUFlLFdBQWYsZUFBZSxDQUFBO0FBT2YsSUFBQSxPQUFlLFdBQWYsZUFBZSxDQUFBOzs7Ozs7QUFFdEIsTUFBTUEsY0FBYyxHQUFHLEdBQUcsQUFBQztBQUVaLElBQUEsQUFBTUMsa0JBQWtCLEdBQXhCLE1BQU1BLGtCQUFrQixTQUM3QkMsU0FBUSxRQUFBO0lBWWhCLE1BQWNDLFNBQVMsR0FBRztRQUN4QixNQUFPLENBQUMsSUFBSSxDQUFDQyxTQUFTLENBQUU7WUFDdEIsTUFBTUMsQ0FBQUEsR0FBQUEsTUFBSyxBQUFJLENBQUEsTUFBSixDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ2pCO0tBQ0Y7SUFFRCxN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