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