@bitgo-beta/abstract-utxo 1.1.1-beta.1813 → 1.1.1-beta.1815
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/dist/cjs/src/abstractUtxoCoin.d.ts +1 -0
- package/dist/cjs/src/abstractUtxoCoin.d.ts.map +1 -1
- package/dist/cjs/src/abstractUtxoCoin.js +2 -2
- package/dist/cjs/src/address/fixedScript.d.ts +1 -5
- package/dist/cjs/src/address/fixedScript.d.ts.map +1 -1
- package/dist/cjs/src/address/fixedScript.js +3 -5
- package/dist/cjs/src/recovery/backupKeyRecovery.d.ts +3 -3
- package/dist/cjs/src/recovery/backupKeyRecovery.d.ts.map +1 -1
- package/dist/cjs/src/recovery/backupKeyRecovery.js +31 -69
- package/dist/cjs/src/recovery/crossChainRecovery.d.ts +5 -5
- package/dist/cjs/src/recovery/crossChainRecovery.d.ts.map +1 -1
- package/dist/cjs/src/recovery/crossChainRecovery.js +22 -121
- package/dist/cjs/src/recovery/psbt.d.ts +8 -31
- package/dist/cjs/src/recovery/psbt.d.ts.map +1 -1
- package/dist/cjs/src/recovery/psbt.js +14 -126
- package/dist/cjs/src/transaction/fixedScript/parseOutput.d.ts.map +1 -1
- package/dist/cjs/src/transaction/fixedScript/parseOutput.js +6 -11
- package/dist/cjs/src/transaction/fixedScript/signPsbtUtxolib.d.ts +1 -1
- package/dist/cjs/src/transaction/fixedScript/signPsbtUtxolib.d.ts.map +1 -1
- package/dist/cjs/src/transaction/fixedScript/signPsbtUtxolib.js +1 -1
- package/dist/cjs/src/transaction/fixedScript/signPsbtWasm.d.ts +2 -2
- package/dist/cjs/src/transaction/fixedScript/signPsbtWasm.d.ts.map +1 -1
- package/dist/cjs/src/transaction/fixedScript/signPsbtWasm.js +1 -1
- package/dist/cjs/src/transaction/fixedScript/signTransaction.d.ts +4 -4
- package/dist/cjs/src/transaction/fixedScript/signTransaction.d.ts.map +1 -1
- package/dist/cjs/src/transaction/fixedScript/signTransaction.js +41 -6
- package/dist/cjs/src/unspent.d.ts +7 -0
- package/dist/cjs/src/unspent.d.ts.map +1 -1
- package/dist/cjs/src/unspent.js +10 -1
- package/dist/cjs/test/unit/prebuildAndSign.d.ts +0 -4
- package/dist/cjs/test/unit/prebuildAndSign.d.ts.map +1 -1
- package/dist/cjs/test/unit/prebuildAndSign.js +12 -32
- package/dist/cjs/test/unit/recovery/backupKeyRecovery.js +17 -14
- package/dist/cjs/test/unit/recovery/crossChainRecovery.js +13 -4
- package/dist/cjs/test/unit/signTransaction.d.ts +2 -0
- package/dist/cjs/test/unit/signTransaction.d.ts.map +1 -0
- package/dist/cjs/test/unit/signTransaction.js +244 -0
- package/dist/cjs/test/unit/transaction.js +4 -224
- package/dist/cjs/test/unit/util/transaction.d.ts +3 -0
- package/dist/cjs/test/unit/util/transaction.d.ts.map +1 -1
- package/dist/cjs/test/unit/util/transaction.js +19 -1
- package/dist/cjs/test/unit/util/utxoCoins.d.ts +13 -0
- package/dist/cjs/test/unit/util/utxoCoins.d.ts.map +1 -1
- package/dist/cjs/test/unit/util/utxoCoins.js +33 -2
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/abstractUtxoCoin.d.ts +1 -0
- package/dist/esm/abstractUtxoCoin.d.ts.map +1 -1
- package/dist/esm/abstractUtxoCoin.js +2 -2
- package/dist/esm/address/fixedScript.d.ts +1 -5
- package/dist/esm/address/fixedScript.d.ts.map +1 -1
- package/dist/esm/address/fixedScript.js +3 -5
- package/dist/esm/recovery/backupKeyRecovery.d.ts +3 -3
- package/dist/esm/recovery/backupKeyRecovery.d.ts.map +1 -1
- package/dist/esm/recovery/backupKeyRecovery.js +34 -39
- package/dist/esm/recovery/crossChainRecovery.d.ts +5 -5
- package/dist/esm/recovery/crossChainRecovery.d.ts.map +1 -1
- package/dist/esm/recovery/crossChainRecovery.js +24 -90
- package/dist/esm/recovery/psbt.d.ts +8 -31
- package/dist/esm/recovery/psbt.d.ts.map +1 -1
- package/dist/esm/recovery/psbt.js +14 -91
- package/dist/esm/transaction/fixedScript/parseOutput.d.ts.map +1 -1
- package/dist/esm/transaction/fixedScript/parseOutput.js +6 -11
- package/dist/esm/transaction/fixedScript/signPsbtUtxolib.d.ts +1 -1
- package/dist/esm/transaction/fixedScript/signPsbtUtxolib.d.ts.map +1 -1
- package/dist/esm/transaction/fixedScript/signPsbtUtxolib.js +1 -1
- package/dist/esm/transaction/fixedScript/signPsbtWasm.d.ts +2 -2
- package/dist/esm/transaction/fixedScript/signPsbtWasm.d.ts.map +1 -1
- package/dist/esm/transaction/fixedScript/signPsbtWasm.js +1 -1
- package/dist/esm/transaction/fixedScript/signTransaction.d.ts +4 -4
- package/dist/esm/transaction/fixedScript/signTransaction.d.ts.map +1 -1
- package/dist/esm/transaction/fixedScript/signTransaction.js +9 -7
- package/dist/esm/unspent.d.ts +7 -0
- package/dist/esm/unspent.d.ts.map +1 -1
- package/dist/esm/unspent.js +8 -2
- package/package.json +9 -10
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
require("mocha");
|
|
37
|
+
const assert = __importStar(require("assert"));
|
|
38
|
+
const utxolib = __importStar(require("@bitgo-beta/utxo-lib"));
|
|
39
|
+
const nock = require("nock");
|
|
40
|
+
const utxo_lib_1 = require("@bitgo-beta/utxo-lib");
|
|
41
|
+
const sdk_core_1 = require("@bitgo-beta/sdk-core");
|
|
42
|
+
const src_1 = require("../../src");
|
|
43
|
+
const util_1 = require("./util");
|
|
44
|
+
describe('signTransaction', function () {
|
|
45
|
+
const bgUrl = sdk_core_1.common.Environments[util_1.defaultBitGo.getEnv()].uri;
|
|
46
|
+
const coin = (0, util_1.getUtxoCoin)('btc');
|
|
47
|
+
const wallet = (0, util_1.getUtxoWallet)(coin, { id: '5b34252f1bf349930e34020a00000000', coin: coin.getChain() });
|
|
48
|
+
const rootWalletKeys = (0, util_1.getDefaultWalletKeys)();
|
|
49
|
+
const userPrv = rootWalletKeys.user.toBase58();
|
|
50
|
+
const pubs = util_1.keychainsBase58.map((v) => v.pub);
|
|
51
|
+
function validatePsbt(txHex, targetSigCount, targetNonceCount) {
|
|
52
|
+
const psbt = utxolib.bitgo.createPsbtFromHex(txHex, coin.network);
|
|
53
|
+
psbt.data.inputs.forEach((input, index) => {
|
|
54
|
+
const parsed = utxolib.bitgo.parsePsbtInput(input);
|
|
55
|
+
if (parsed.scriptType === 'taprootKeyPathSpend') {
|
|
56
|
+
assert.ok(targetNonceCount);
|
|
57
|
+
const nonce = psbt.getProprietaryKeyVals(index, {
|
|
58
|
+
identifier: utxolib.bitgo.PSBT_PROPRIETARY_IDENTIFIER,
|
|
59
|
+
subtype: utxolib.bitgo.ProprietaryKeySubtype.MUSIG2_PUB_NONCE,
|
|
60
|
+
});
|
|
61
|
+
assert.strictEqual(nonce.length, targetNonceCount);
|
|
62
|
+
}
|
|
63
|
+
const expectedSigCount = parsed.scriptType === 'p2shP2pk' || targetSigCount === 0 ? undefined : 1;
|
|
64
|
+
assert.strictEqual(parsed.signatures?.length, expectedSigCount);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function validateTx(txHex, unspents, targetSigCount) {
|
|
68
|
+
const tx = utxolib.bitgo.createTransactionFromHex(txHex, coin.network);
|
|
69
|
+
unspents.forEach((u, i) => {
|
|
70
|
+
const sigCount = utxolib.bitgo.getStrictSignatureCount(tx.ins[i]);
|
|
71
|
+
const expectedSigCount = utxolib.bitgo.isWalletUnspent(u) && !!targetSigCount ? 1 : 0;
|
|
72
|
+
assert.strictEqual(sigCount, expectedSigCount);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async function signTransaction(tx, useSigningSteps, unspents) {
|
|
76
|
+
const isPsbt = tx instanceof utxolib.bitgo.UtxoPsbt;
|
|
77
|
+
const isTxWithTaprootKeyPathSpend = isPsbt && utxolib.bitgo.isTransactionWithKeyPathSpendInput(tx);
|
|
78
|
+
const txHex = tx.toHex();
|
|
79
|
+
function nockSignPsbt(psbtHex) {
|
|
80
|
+
const psbt = utxolib.bitgo.createPsbtFromHex(psbtHex, coin.network);
|
|
81
|
+
return nock(bgUrl)
|
|
82
|
+
.post(`/api/v2/${wallet.coin()}/wallet/${wallet.id()}/tx/signpsbt`, (body) => body.psbt)
|
|
83
|
+
.reply(200, { psbt: psbt.setAllInputsMusig2NonceHD(rootWalletKeys.bitgo).toHex() });
|
|
84
|
+
}
|
|
85
|
+
if (!useSigningSteps) {
|
|
86
|
+
let scope;
|
|
87
|
+
if (tx instanceof utxolib.bitgo.UtxoPsbt && isTxWithTaprootKeyPathSpend) {
|
|
88
|
+
scope = nockSignPsbt(tx.clone().setAllInputsMusig2NonceHD(rootWalletKeys.bitgo).toHex());
|
|
89
|
+
}
|
|
90
|
+
const psbt = await coin.signTransaction({
|
|
91
|
+
txPrebuild: {
|
|
92
|
+
txHex,
|
|
93
|
+
txInfo: isPsbt ? undefined : { unspents },
|
|
94
|
+
walletId: isTxWithTaprootKeyPathSpend ? wallet.id() : undefined,
|
|
95
|
+
},
|
|
96
|
+
prv: userPrv,
|
|
97
|
+
pubs: isPsbt ? undefined : pubs,
|
|
98
|
+
});
|
|
99
|
+
assert.ok('txHex' in psbt);
|
|
100
|
+
if (isPsbt) {
|
|
101
|
+
validatePsbt(psbt.txHex, 1, 2);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
assert.ok(unspents);
|
|
105
|
+
validateTx(psbt.txHex, unspents, 1);
|
|
106
|
+
}
|
|
107
|
+
if (scope) {
|
|
108
|
+
assert.strictEqual(scope.isDone(), true);
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const signerNoncePsbt = await coin.signTransaction({
|
|
113
|
+
txPrebuild: { txHex },
|
|
114
|
+
prv: userPrv,
|
|
115
|
+
signingStep: 'signerNonce',
|
|
116
|
+
});
|
|
117
|
+
assert.ok('txHex' in signerNoncePsbt);
|
|
118
|
+
if (isPsbt) {
|
|
119
|
+
validatePsbt(signerNoncePsbt.txHex, 0, isTxWithTaprootKeyPathSpend ? 1 : undefined);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
assert.ok(unspents);
|
|
123
|
+
validateTx(signerNoncePsbt.txHex, unspents, 0);
|
|
124
|
+
}
|
|
125
|
+
let scope;
|
|
126
|
+
if (isTxWithTaprootKeyPathSpend) {
|
|
127
|
+
scope = nockSignPsbt(signerNoncePsbt.txHex);
|
|
128
|
+
}
|
|
129
|
+
const cosignerNoncePsbt = await coin.signTransaction({
|
|
130
|
+
txPrebuild: { ...signerNoncePsbt, walletId: wallet.id() },
|
|
131
|
+
signingStep: 'cosignerNonce',
|
|
132
|
+
});
|
|
133
|
+
assert.ok('txHex' in cosignerNoncePsbt);
|
|
134
|
+
if (isPsbt) {
|
|
135
|
+
validatePsbt(cosignerNoncePsbt.txHex, 0, isTxWithTaprootKeyPathSpend ? 2 : undefined);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
assert.ok(unspents);
|
|
139
|
+
validateTx(cosignerNoncePsbt.txHex, unspents, 0);
|
|
140
|
+
}
|
|
141
|
+
if (scope) {
|
|
142
|
+
assert.strictEqual(scope.isDone(), true);
|
|
143
|
+
}
|
|
144
|
+
const signerSigPsbt = await coin.signTransaction({
|
|
145
|
+
txPrebuild: { ...cosignerNoncePsbt, txInfo: isPsbt ? undefined : { unspents } },
|
|
146
|
+
prv: userPrv,
|
|
147
|
+
pubs: isPsbt ? undefined : pubs,
|
|
148
|
+
signingStep: 'signerSignature',
|
|
149
|
+
});
|
|
150
|
+
assert.ok('txHex' in signerSigPsbt);
|
|
151
|
+
if (isPsbt) {
|
|
152
|
+
validatePsbt(signerSigPsbt.txHex, 1, isTxWithTaprootKeyPathSpend ? 2 : undefined);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
assert.ok(unspents);
|
|
156
|
+
validateTx(signerSigPsbt.txHex, unspents, 1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
it('customSigningFunction flow - PSBT with taprootKeyPathSpend inputs', async function () {
|
|
160
|
+
const inputs = utxo_lib_1.testutil.inputScriptTypes.map((scriptType) => ({
|
|
161
|
+
scriptType,
|
|
162
|
+
value: BigInt(1000),
|
|
163
|
+
}));
|
|
164
|
+
const unspentSum = inputs.reduce((prev, curr) => prev + curr.value, BigInt(0));
|
|
165
|
+
const outputs = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }];
|
|
166
|
+
const psbt = utxo_lib_1.testutil.constructPsbt(inputs, outputs, coin.network, rootWalletKeys, 'unsigned', {
|
|
167
|
+
p2shP2pkKey: (0, src_1.getReplayProtectionPubkeys)(coin.name)[0],
|
|
168
|
+
});
|
|
169
|
+
for (const v of [false, true]) {
|
|
170
|
+
await signTransaction(psbt, v);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
it('customSigningFunction flow - PSBT without taprootKeyPathSpend inputs', async function () {
|
|
174
|
+
const inputs = utxo_lib_1.testutil.inputScriptTypes
|
|
175
|
+
.filter((v) => v !== 'taprootKeyPathSpend')
|
|
176
|
+
.map((scriptType) => ({
|
|
177
|
+
scriptType,
|
|
178
|
+
value: BigInt(1000),
|
|
179
|
+
}));
|
|
180
|
+
const unspentSum = inputs.reduce((prev, cur) => prev + cur.value, BigInt(0));
|
|
181
|
+
const outputs = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }];
|
|
182
|
+
const psbt = utxo_lib_1.testutil.constructPsbt(inputs, outputs, coin.network, rootWalletKeys, 'unsigned');
|
|
183
|
+
for (const v of [false, true]) {
|
|
184
|
+
await signTransaction(psbt, v);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
it('customSigningFunction flow - Network Tx', async function () {
|
|
188
|
+
const inputs = utxo_lib_1.testutil.txnInputScriptTypes
|
|
189
|
+
.filter((v) => v !== 'p2shP2pk')
|
|
190
|
+
.map((scriptType) => ({
|
|
191
|
+
scriptType,
|
|
192
|
+
value: BigInt(1000),
|
|
193
|
+
}));
|
|
194
|
+
const unspentSum = inputs.reduce((prev, curr) => prev + curr.value, BigInt(0));
|
|
195
|
+
const outputs = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }];
|
|
196
|
+
const txBuilder = utxo_lib_1.testutil.constructTxnBuilder(inputs, outputs, coin.network, rootWalletKeys, 'unsigned');
|
|
197
|
+
const unspents = inputs.map((v, i) => utxo_lib_1.testutil.toTxnUnspent(v, i, coin.network, rootWalletKeys));
|
|
198
|
+
for (const v of [false, true]) {
|
|
199
|
+
await signTransaction(txBuilder.buildIncomplete(), v, unspents);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
it('fails on PSBT cache miss', async function () {
|
|
203
|
+
const inputs = [{ scriptType: 'taprootKeyPathSpend', value: BigInt(1000) }];
|
|
204
|
+
const unspentSum = inputs.reduce((prev, curr) => prev + curr.value, BigInt(0));
|
|
205
|
+
const outputs = [{ scriptType: 'p2sh', value: unspentSum - BigInt(1000) }];
|
|
206
|
+
const psbt = utxo_lib_1.testutil.constructPsbt(inputs, outputs, coin.network, rootWalletKeys, 'unsigned');
|
|
207
|
+
await assert.rejects(async () => {
|
|
208
|
+
await coin.signTransaction({
|
|
209
|
+
txPrebuild: { txHex: psbt.toHex() },
|
|
210
|
+
prv: userPrv,
|
|
211
|
+
signingStep: 'signerSignature',
|
|
212
|
+
});
|
|
213
|
+
}, {
|
|
214
|
+
message: `Psbt is missing from txCache (cache size 0).
|
|
215
|
+
This may be due to the request being routed to a different BitGo-Express instance that for signing step 'signerNonce'.`,
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
it('fails on unsupported locking script', async function () {
|
|
219
|
+
const inputs = [
|
|
220
|
+
{ scriptType: 'p2wsh', value: BigInt(1000) },
|
|
221
|
+
{ scriptType: 'p2trMusig2', value: BigInt(1000) },
|
|
222
|
+
];
|
|
223
|
+
const unspentSum = inputs.reduce((prev, curr) => prev + curr.value, BigInt(0));
|
|
224
|
+
const outputs = [{ scriptType: 'p2sh', value: unspentSum - BigInt(500) }];
|
|
225
|
+
const psbt = utxo_lib_1.testutil.constructPsbt(inputs, outputs, coin.network, rootWalletKeys, 'unsigned');
|
|
226
|
+
// override the 1st PSBT input with unsupported 2 of 2 multi-sig locking script.
|
|
227
|
+
const unspent = utxo_lib_1.testutil.toUnspent(inputs[0], 0, coin.network, rootWalletKeys);
|
|
228
|
+
if (!utxolib.bitgo.isWalletUnspent(unspent)) {
|
|
229
|
+
throw new Error('invalid unspent');
|
|
230
|
+
}
|
|
231
|
+
const { publicKeys } = rootWalletKeys.deriveForChainAndIndex(unspent.chain, unspent.index);
|
|
232
|
+
const script2Of2 = utxolib.payments.p2ms({ m: 2, pubkeys: [publicKeys[0], publicKeys[1]] });
|
|
233
|
+
psbt.data.inputs[0].witnessScript = script2Of2.output;
|
|
234
|
+
await assert.rejects(async () => {
|
|
235
|
+
await coin.signTransaction({
|
|
236
|
+
txPrebuild: { txHex: psbt.toHex() },
|
|
237
|
+
prv: userPrv,
|
|
238
|
+
});
|
|
239
|
+
}, {
|
|
240
|
+
message: `length mismatch`,
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnblRyYW5zYWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3NpZ25UcmFuc2FjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlCQUFlO0FBQ2YsK0NBQWlDO0FBRWpDLDhEQUFnRDtBQUNoRCw2QkFBOEI7QUFDOUIsbURBQWdEO0FBQ2hELG1EQUFzRDtBQUV0RCxtQ0FBdUQ7QUFHdkQsaUNBQXlHO0FBRXpHLFFBQVEsQ0FBQyxpQkFBaUIsRUFBRTtJQUMxQixNQUFNLEtBQUssR0FBRyxpQkFBTSxDQUFDLFlBQVksQ0FBQyxtQkFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDO0lBRTdELE1BQU0sSUFBSSxHQUFHLElBQUEsa0JBQVcsRUFBQyxLQUFLLENBQUMsQ0FBQztJQUNoQyxNQUFNLE1BQU0sR0FBRyxJQUFBLG9CQUFhLEVBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLGtDQUFrQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLE1BQU0sY0FBYyxHQUFHLElBQUEsMkJBQW9CLEdBQUUsQ0FBQztJQUM5QyxNQUFNLE9BQU8sR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQy9DLE1BQU0sSUFBSSxHQUFHLHNCQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFtQixDQUFDO0lBRWpFLFNBQVMsWUFBWSxDQUFDLEtBQWEsRUFBRSxjQUFxQixFQUFFLGdCQUF3QjtRQUNsRixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLElB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LENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICdtb2NoYSc7XG5pbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcblxuaW1wb3J0ICogYXMgdXR4b2xpYiBmcm9tICdAYml0Z28tYmV0YS91dHhvLWxpYic7XG5pbXBvcnQgbm9jayA9IHJlcXVpcmUoJ25vY2snKTtcbmltcG9ydCB7IHRlc3R1dGlsIH0gZnJvbSAnQGJpdGdvLWJldGEvdXR4by1saWInO1xuaW1wb3J0IHsgY29tbW9uLCBUcmlwbGUgfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5cbmltcG9ydCB7IGdldFJlcGxheVByb3RlY3Rpb25QdWJrZXlzIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB0eXBlIHsgVW5zcGVudCB9IGZyb20gJy4uLy4uL3NyYy91bnNwZW50JztcblxuaW1wb3J0IHsgZ2V0VXR4b1dhbGxldCwgZ2V0RGVmYXVsdFdhbGxldEtleXMsIGdldFV0eG9Db2luLCBrZXljaGFpbnNCYXNlNTgsIGRlZmF1bHRCaXRHbyB9IGZyb20gJy4vdXRpbCc7XG5cbmRlc2NyaWJlKCdzaWduVHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tkZWZhdWx0Qml0R28uZ2V0RW52KCldLnVyaTtcblxuICBjb25zdCBjb2luID0gZ2V0VXR4b0NvaW4oJ2J0YycpO1xuICBjb25zdCB3YWxsZXQgPSBnZXRVdHhvV2FsbGV0KGNvaW4sIHsgaWQ6ICc1YjM0MjUyZjFiZjM0OTkzMGUzNDAyMGEwMDAwMDAwMCcsIGNvaW46IGNvaW4uZ2V0Q2hhaW4oKSB9KTtcbiAgY29uc3Qgcm9vdFdhbGxldEtleXMgPSBnZXREZWZhdWx0V2FsbGV0S2V5cygpO1xuICBjb25zdCB1c2VyUHJ2ID0gcm9vdFdhbGxldEtleXMudXNlci50b0Jhc2U1OCgpO1xuICBjb25zdCBwdWJzID0ga2V5Y2hhaW5zQmFzZTU4Lm1hcCgodikgPT4gdi5wdWIpIGFzIFRyaXBsZTxzdHJpbmc+O1xuXG4gIGZ1bmN0aW9uIHZhbGlkYXRlUHNidCh0eEhleDogc3RyaW5nLCB0YXJnZXRTaWdDb3VudDogMCB8IDEsIHRhcmdldE5vbmNlQ291bnQ/OiAxIHwgMikge1xuICAgIGNvbnN0IHBzYnQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVBzYnRGcm9tSGV4KHR4SGV4LCBjb2luLm5ldHdvcmspO1xuICAgIHBzYnQuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGluZGV4KSA9PiB7XG4gICAgICBjb25zdCBwYXJzZWQgPSB1dHhvbGliLmJpdGdvLnBhcnNlUHNidElucHV0KGlucHV0KTtcbiAgICAgIGlmIChwYXJzZWQuc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnKSB7XG4gICAgICAgIGFzc2VydC5vayh0YXJnZXROb25jZUNvdW50KTtcbiAgICAgICAgY29uc3Qgbm9uY2UgPSBwc2J0LmdldFByb3ByaWV0YXJ5S2V5VmFscyhpbmRleCwge1xuICAgICAgICAgIGlkZW50aWZpZXI6IHV0eG9saWIuYml0Z28uUFNCVF9QUk9QUklFVEFSWV9JREVOVElGSUVSLFxuICAgICAgICAgIHN1YnR5cGU6IHV0eG9saWIuYml0Z28uUHJvcHJpZXRhcnlLZXlTdWJ0eXBlLk1VU0lHMl9QVUJfTk9OQ0UsXG4gICAgICAgIH0pO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwobm9uY2UubGVuZ3RoLCB0YXJnZXROb25jZUNvdW50KTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGV4cGVjdGVkU2lnQ291bnQgPSBwYXJzZWQuc2NyaXB0VHlwZSA9PT0gJ3Ayc2hQMnBrJyB8fCB0YXJnZXRTaWdDb3VudCA9PT0gMCA/IHVuZGVmaW5lZCA6IDE7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnNpZ25hdHVyZXM/Lmxlbmd0aCwgZXhwZWN0ZWRTaWdDb3VudCk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiB2YWxpZGF0ZVR4KHR4SGV4OiBzdHJpbmcsIHVuc3BlbnRzOiBVbnNwZW50PGJpZ2ludD5bXSwgdGFyZ2V0U2lnQ291bnQ6IDAgfCAxKSB7XG4gICAgY29uc3QgdHggPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleCh0eEhleCwgY29pbi5uZXR3b3JrKTtcbiAgICB1bnNwZW50cy5mb3JFYWNoKCh1LCBpKSA9PiB7XG4gICAgICBjb25zdCBzaWdDb3VudCA9IHV0eG9saWIuYml0Z28uZ2V0U3RyaWN0U2lnbmF0dXJlQ291bnQodHguaW5zW2ldKTtcbiAgICAgIGNvbnN0IGV4cGVjdGVkU2lnQ291bnQgPSB1dHhvbGliLmJpdGdvLmlzV2FsbGV0VW5zcGVudCh1KSAmJiAhIXRhcmdldFNpZ0NvdW50ID8gMSA6IDA7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2lnQ291bnQsIGV4cGVjdGVkU2lnQ291bnQpO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gc2lnblRyYW5zYWN0aW9uKFxuICAgIHR4OiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0IHwgdXR4b2xpYi5iaXRnby5VdHhvVHJhbnNhY3Rpb248YmlnaW50PixcbiAgICB1c2VTaWduaW5nU3RlcHM6IGJvb2xlYW4sXG4gICAgdW5zcGVudHM/OiBVbnNwZW50PGJpZ2ludD5bXVxuICApIHtcbiAgICBjb25zdCBpc1BzYnQgPSB0eCBpbnN0YW5jZW9mIHV0eG9saWIuYml0Z28uVXR4b1BzYnQ7XG4gICAgY29uc3QgaXNUeFdpdGhUYXByb290S2V5UGF0aFNwZW5kID0gaXNQc2J0ICYmIHV0eG9saWIuYml0Z28uaXNUcmFuc2FjdGlvbldpdGhLZXlQYXRoU3BlbmRJbnB1dCh0eCk7XG4gICAgY29uc3QgdHhIZXggPSB0eC50b0hleCgpO1xuXG4gICAgZnVuY3Rpb24gbm9ja1NpZ25Qc2J0KHBzYnRIZXg6IHN0cmluZyk6IG5vY2suU2NvcGUge1xuICAgICAgY29uc3QgcHNidCA9IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgocHNidEhleCwgY29pbi5uZXR3b3JrKTtcbiAgICAgIHJldHVybiBub2NrKGJnVXJsKVxuICAgICAgICAucG9zdChgL2FwaS92Mi8ke3dhbGxldC5jb2luKCl9L3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC9zaWducHNidGAsIChib2R5KSA9PiBib2R5LnBzYnQpXG4gICAgICAgIC5yZXBseSgyMDAsIHsgcHNidDogcHNidC5zZXRBbGxJbnB1dHNNdXNpZzJOb25jZUhEKHJvb3RXYWxsZXRLZXlzLmJpdGdvKS50b0hleCgpIH0pO1xuICAgIH1cblxuICAgIGlmICghdXNlU2lnbmluZ1N0ZXBzKSB7XG4gICAgICBsZXQgc2NvcGU6IG5vY2suU2NvcGUgfCB1bmRlZmluZWQ7XG4gICAgICBpZiAodHggaW5zdGFuY2VvZiB1dHhvbGliLmJpdGdvLlV0eG9Qc2J0ICYmIGlzVHhXaXRoVGFwcm9vdEtleVBhdGhTcGVuZCkge1xuICAgICAgICBzY29wZSA9IG5vY2tTaWduUHNidCh0eC5jbG9uZSgpLnNldEFsbElucHV0c011c2lnMk5vbmNlSEQocm9vdFdhbGxldEtleXMuYml0Z28pLnRvSGV4KCkpO1xuICAgICAgfVxuICAgICAgY29uc3QgcHNidCA9IGF3YWl0IGNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHR4SGV4LFxuICAgICAgICAgIHR4SW5mbzogaXNQc2J0ID8gdW5kZWZpbmVkIDogeyB1bnNwZW50cyB9LFxuICAgICAgICAgIHdhbGxldElkOiBpc1R4V2l0aFRhcHJvb3RLZXlQYXRoU3BlbmQgPyB3YWxsZXQuaWQoKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgfSxcbiAgICAgICAgcHJ2OiB1c2VyUHJ2LFxuICAgICAgICBwdWJzOiBpc1BzYnQgPyB1bmRlZmluZWQgOiBwdWJzLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQub2soJ3R4SGV4JyBpbiBwc2J0KTtcbiAgICAgIGlmIChpc1BzYnQpIHtcbiAgICAgICAgdmFsaWRhdGVQc2J0KHBzYnQudHhIZXgsIDEsIDIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXNzZXJ0Lm9rKHVuc3BlbnRzKTtcbiAgICAgICAgdmFsaWRhdGVUeChwc2J0LnR4SGV4LCB1bnNwZW50cywgMSk7XG4gICAgICB9XG4gICAgICBpZiAoc2NvcGUpIHtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHNjb3BlLmlzRG9uZSgpLCB0cnVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzaWduZXJOb25jZVBzYnQgPSBhd2FpdCBjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4IH0sXG4gICAgICBwcnY6IHVzZXJQcnYsXG4gICAgICBzaWduaW5nU3RlcDogJ3NpZ25lck5vbmNlJyxcbiAgICB9KTtcbiAgICBhc3NlcnQub2soJ3R4SGV4JyBpbiBzaWduZXJOb25jZVBzYnQpO1xuICAgIGlmIChpc1BzYnQpIHtcbiAgICAgIHZhbGlkYXRlUHNidChzaWduZXJOb25jZVBzYnQudHhIZXgsIDAsIGlzVHhXaXRoVGFwcm9vdEtleVBhdGhTcGVuZCA/IDEgOiB1bmRlZmluZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhc3NlcnQub2sodW5zcGVudHMpO1xuICAgICAgdmFsaWRhdGVUeChzaWduZXJOb25jZVBzYnQudHhIZXgsIHVuc3BlbnRzLCAwKTtcbiAgICB9XG5cbiAgICBsZXQgc2NvcGU6IG5vY2suU2NvcGUgfCB1bmRlZmluZWQ7XG4gICAgaWYgKGlzVHhXaXRoVGFwcm9vdEtleVBhdGhTcGVuZCkge1xuICAgICAgc2NvcGUgPSBub2NrU2lnblBzYnQoc2lnbmVyTm9uY2VQc2J0LnR4SGV4KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb3NpZ25lck5vbmNlUHNidCA9IGF3YWl0IGNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UHJlYnVpbGQ6IHsgLi4uc2lnbmVyTm9uY2VQc2J0LCB3YWxsZXRJZDogd2FsbGV0LmlkKCkgfSxcbiAgICAgIHNpZ25pbmdTdGVwOiAnY29zaWduZXJOb25jZScsXG4gICAgfSk7XG4gICAgYXNzZXJ0Lm9rKCd0eEhleCcgaW4gY29zaWduZXJOb25jZVBzYnQpO1xuICAgIGlmIChpc1BzYnQpIHtcbiAgICAgIHZhbGlkYXRlUHNidChjb3NpZ25lck5vbmNlUHNidC50eEhleCwgMCwgaXNUeFdpdGhUYXByb290S2V5UGF0aFNwZW5kID8gMiA6IHVuZGVmaW5lZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2VydC5vayh1bnNwZW50cyk7XG4gICAgICB2YWxpZGF0ZVR4KGNvc2lnbmVyTm9uY2VQc2J0LnR4SGV4LCB1bnNwZW50cywgMCk7XG4gICAgfVxuXG4gICAgaWYgKHNjb3BlKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoc2NvcGUuaXNEb25lKCksIHRydWUpO1xuICAgIH1cblxuICAgIGNvbnN0IHNpZ25lclNpZ1BzYnQgPSBhd2FpdCBjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICB0eFByZWJ1aWxkOiB7IC4uLmNvc2lnbmVyTm9uY2VQc2J0LCB0eEluZm86IGlzUHNidCA/IHVuZGVmaW5lZCA6IHsgdW5zcGVudHMgfSB9LFxuICAgICAgcHJ2OiB1c2VyUHJ2LFxuICAgICAgcHViczogaXNQc2J0ID8gdW5kZWZpbmVkIDogcHVicyxcbiAgICAgIHNpZ25pbmdTdGVwOiAnc2lnbmVyU2lnbmF0dXJlJyxcbiAgICB9KTtcbiAgICBhc3NlcnQub2soJ3R4SGV4JyBpbiBzaWduZXJTaWdQc2J0KTtcbiAgICBpZiAoaXNQc2J0KSB7XG4gICAgICB2YWxpZGF0ZVBzYnQoc2lnbmVyU2lnUHNidC50eEhleCwgMSwgaXNUeFdpdGhUYXByb290S2V5UGF0aFNwZW5kID8gMiA6IHVuZGVmaW5lZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFzc2VydC5vayh1bnNwZW50cyk7XG4gICAgICB2YWxpZGF0ZVR4KHNpZ25lclNpZ1BzYnQudHhIZXgsIHVuc3BlbnRzLCAxKTtcbiAgICB9XG4gIH1cblxuICBpdCgnY3VzdG9tU2lnbmluZ0Z1bmN0aW9uIGZsb3cgLSBQU0JUIHdpdGggdGFwcm9vdEtleVBhdGhTcGVuZCBpbnB1dHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgaW5wdXRzOiB0ZXN0dXRpbC5JbnB1dFtdID0gdGVzdHV0aWwuaW5wdXRTY3JpcHRUeXBlcy5tYXAoKHNjcmlwdFR5cGUpID0+ICh7XG4gICAgICBzY3JpcHRUeXBlLFxuICAgICAgdmFsdWU6IEJpZ0ludCgxMDAwKSxcbiAgICB9KSk7XG4gICAgY29uc3QgdW5zcGVudFN1bSA9IGlucHV0cy5yZWR1Y2UoKHByZXY6IGJpZ2ludCwgY3VycikgPT4gcHJldiArIGN1cnIudmFsdWUsIEJpZ0ludCgwKSk7XG4gICAgY29uc3Qgb3V0cHV0czogdGVzdHV0aWwuT3V0cHV0W10gPSBbeyBzY3JpcHRUeXBlOiAncDJzaCcsIHZhbHVlOiB1bnNwZW50U3VtIC0gQmlnSW50KDEwMDApIH1dO1xuICAgIGNvbnN0IHBzYnQgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KGlucHV0cywgb3V0cHV0cywgY29pbi5uZXR3b3JrLCByb290V2FsbGV0S2V5cywgJ3Vuc2lnbmVkJywge1xuICAgICAgcDJzaFAycGtLZXk6IGdldFJlcGxheVByb3RlY3Rpb25QdWJrZXlzKGNvaW4ubmFtZSlbMF0sXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IHYgb2YgW2ZhbHNlLCB0cnVlXSkge1xuICAgICAgYXdhaXQgc2lnblRyYW5zYWN0aW9uKHBzYnQsIHYpO1xuICAgIH1cbiAgfSk7XG5cbiAgaXQoJ2N1c3RvbVNpZ25pbmdGdW5jdGlvbiBmbG93IC0gUFNCVCB3aXRob3V0IHRhcHJvb3RLZXlQYXRoU3BlbmQgaW5wdXRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGlucHV0czogdGVzdHV0aWwuSW5wdXRbXSA9IHRlc3R1dGlsLmlucHV0U2NyaXB0VHlwZXNcbiAgICAgIC5maWx0ZXIoKHYpID0+IHYgIT09ICd0YXByb290S2V5UGF0aFNwZW5kJylcbiAgICAgIC5tYXAoKHNjcmlwdFR5cGUpID0+ICh7XG4gICAgICAgIHNjcmlwdFR5cGUsXG4gICAgICAgIHZhbHVlOiBCaWdJbnQoMTAwMCksXG4gICAgICB9KSk7XG4gICAgY29uc3QgdW5zcGVudFN1bSA9IGlucHV0cy5yZWR1Y2UoKHByZXY6IGJpZ2ludCwgY3VyKSA9PiBwcmV2ICsgY3VyLnZhbHVlLCBCaWdJbnQoMCkpO1xuICAgIGNvbnN0IG91dHB1dHM6IHRlc3R1dGlsLk91dHB1dFtdID0gW3sgc2NyaXB0VHlwZTogJ3Ayc2gnLCB2YWx1ZTogdW5zcGVudFN1bSAtIEJpZ0ludCgxMDAwKSB9XTtcbiAgICBjb25zdCBwc2J0ID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChpbnB1dHMsIG91dHB1dHMsIGNvaW4ubmV0d29yaywgcm9vdFdhbGxldEtleXMsICd1bnNpZ25lZCcpO1xuXG4gICAgZm9yIChjb25zdCB2IG9mIFtmYWxzZSwgdHJ1ZV0pIHtcbiAgICAgIGF3YWl0IHNpZ25UcmFuc2FjdGlvbihwc2J0LCB2KTtcbiAgICB9XG4gIH0pO1xuXG4gIGl0KCdjdXN0b21TaWduaW5nRnVuY3Rpb24gZmxvdyAtIE5ldHdvcmsgVHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgaW5wdXRzOiB0ZXN0dXRpbC5UeG5JbnB1dDxiaWdpbnQ+W10gPSB0ZXN0dXRpbC50eG5JbnB1dFNjcmlwdFR5cGVzXG4gICAgICAuZmlsdGVyKCh2KSA9PiB2ICE9PSAncDJzaFAycGsnKVxuICAgICAgLm1hcCgoc2NyaXB0VHlwZSkgPT4gKHtcbiAgICAgICAgc2NyaXB0VHlwZSxcbiAgICAgICAgdmFsdWU6IEJpZ0ludCgxMDAwKSxcbiAgICAgIH0pKTtcbiAgICBjb25zdCB1bnNwZW50U3VtID0gaW5wdXRzLnJlZHVjZSgocHJldjogYmlnaW50LCBjdXJyKSA9PiBwcmV2ICsgY3Vyci52YWx1ZSwgQmlnSW50KDApKTtcbiAgICBjb25zdCBvdXRwdXRzOiB0ZXN0dXRpbC5UeG5PdXRwdXQ8YmlnaW50PltdID0gW3sgc2NyaXB0VHlwZTogJ3Ayc2gnLCB2YWx1ZTogdW5zcGVudFN1bSAtIEJpZ0ludCgxMDAwKSB9XTtcbiAgICBjb25zdCB0eEJ1aWxkZXIgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RUeG5CdWlsZGVyKGlucHV0cywgb3V0cHV0cywgY29pbi5uZXR3b3JrLCByb290V2FsbGV0S2V5cywgJ3Vuc2lnbmVkJyk7XG4gICAgY29uc3QgdW5zcGVudHMgPSBpbnB1dHMubWFwKCh2LCBpKSA9PiB0ZXN0dXRpbC50b1R4blVuc3BlbnQodiwgaSwgY29pbi5uZXR3b3JrLCByb290V2FsbGV0S2V5cykpO1xuXG4gICAgZm9yIChjb25zdCB2IG9mIFtmYWxzZSwgdHJ1ZV0pIHtcbiAgICAgIGF3YWl0IHNpZ25UcmFuc2FjdGlvbih0eEJ1aWxkZXIuYnVpbGRJbmNvbXBsZXRlKCksIHYsIHVuc3BlbnRzKTtcbiAgICB9XG4gIH0pO1xuXG4gIGl0KCdmYWlscyBvbiBQU0JUIGNhY2hlIG1pc3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgaW5wdXRzOiB0ZXN0dXRpbC5JbnB1dFtdID0gW3sgc2NyaXB0VHlwZTogJ3RhcHJvb3RLZXlQYXRoU3BlbmQnLCB2YWx1ZTogQmlnSW50KDEwMDApIH1dO1xuICAgIGNvbnN0IHVuc3BlbnRTdW0gPSBpbnB1dHMucmVkdWNlKChwcmV2OiBiaWdpbnQsIGN1cnIpID0+IHByZXYgKyBjdXJyLnZhbHVlLCBCaWdJbnQoMCkpO1xuICAgIGNvbnN0IG91dHB1dHM6IHRlc3R1dGlsLk91dHB1dFtdID0gW3sgc2NyaXB0VHlwZTogJ3Ayc2gnLCB2YWx1ZTogdW5zcGVudFN1bSAtIEJpZ0ludCgxMDAwKSB9XTtcbiAgICBjb25zdCBwc2J0ID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChpbnB1dHMsIG91dHB1dHMsIGNvaW4ubmV0d29yaywgcm9vdFdhbGxldEtleXMsICd1bnNpZ25lZCcpO1xuXG4gICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IGNvaW4uc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgICB0eFByZWJ1aWxkOiB7IHR4SGV4OiBwc2J0LnRvSGV4KCkgfSxcbiAgICAgICAgICBwcnY6IHVzZXJQcnYsXG4gICAgICAgICAgc2lnbmluZ1N0ZXA6ICdzaWduZXJTaWduYXR1cmUnLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6IGBQc2J0IGlzIG1pc3NpbmcgZnJvbSB0eENhY2hlIChjYWNoZSBzaXplIDApLlxuICAgICAgICAgICAgVGhpcyBtYXkgYmUgZHVlIHRvIHRoZSByZXF1ZXN0IGJlaW5nIHJvdXRlZCB0byBhIGRpZmZlcmVudCBCaXRHby1FeHByZXNzIGluc3RhbmNlIHRoYXQgZm9yIHNpZ25pbmcgc3RlcCAnc2lnbmVyTm9uY2UnLmAsXG4gICAgICB9XG4gICAgKTtcbiAgfSk7XG5cbiAgaXQoJ2ZhaWxzIG9uIHVuc3VwcG9ydGVkIGxvY2tpbmcgc2NyaXB0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGlucHV0czogdGVzdHV0aWwuSW5wdXRbXSA9IFtcbiAgICAgIHsgc2NyaXB0VHlwZTogJ3Ayd3NoJywgdmFsdWU6IEJpZ0ludCgxMDAwKSB9LFxuICAgICAgeyBzY3JpcHRUeXBlOiAncDJ0ck11c2lnMicsIHZhbHVlOiBCaWdJbnQoMTAwMCkgfSxcbiAgICBdO1xuICAgIGNvbnN0IHVuc3BlbnRTdW0gPSBpbnB1dHMucmVkdWNlKChwcmV2OiBiaWdpbnQsIGN1cnIpID0+IHByZXYgKyBjdXJyLnZhbHVlLCBCaWdJbnQoMCkpO1xuICAgIGNvbnN0IG91dHB1dHM6IHRlc3R1dGlsLk91dHB1dFtdID0gW3sgc2NyaXB0VHlwZTogJ3Ayc2gnLCB2YWx1ZTogdW5zcGVudFN1bSAtIEJpZ0ludCg1MDApIH1dO1xuICAgIGNvbnN0IHBzYnQgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KGlucHV0cywgb3V0cHV0cywgY29pbi5uZXR3b3JrLCByb290V2FsbGV0S2V5cywgJ3Vuc2lnbmVkJyk7XG5cbiAgICAvLyBvdmVycmlkZSB0aGUgMXN0IFBTQlQgaW5wdXQgd2l0aCB1bnN1cHBvcnRlZCAyIG9mIDIgbXVsdGktc2lnIGxvY2tpbmcgc2NyaXB0LlxuICAgIGNvbnN0IHVuc3BlbnQgPSB0ZXN0dXRpbC50b1Vuc3BlbnQoaW5wdXRzWzBdLCAwLCBjb2luLm5ldHdvcmssIHJvb3RXYWxsZXRLZXlzKTtcbiAgICBpZiAoIXV0eG9saWIuYml0Z28uaXNXYWxsZXRVbnNwZW50KHVuc3BlbnQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgdW5zcGVudCcpO1xuICAgIH1cbiAgICBjb25zdCB7IHB1YmxpY0tleXMgfSA9IHJvb3RXYWxsZXRLZXlzLmRlcml2ZUZvckNoYWluQW5kSW5kZXgodW5zcGVudC5jaGFpbiwgdW5zcGVudC5pbmRleCk7XG4gICAgY29uc3Qgc2NyaXB0Mk9mMiA9IHV0eG9saWIucGF5bWVudHMucDJtcyh7IG06IDIsIHB1YmtleXM6IFtwdWJsaWNLZXlzWzBdLCBwdWJsaWNLZXlzWzFdXSB9KTtcbiAgICBwc2J0LmRhdGEuaW5wdXRzWzBdLndpdG5lc3NTY3JpcHQgPSBzY3JpcHQyT2YyLm91dHB1dDtcblxuICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKFxuICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICBhd2FpdCBjb2luLnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHhQcmVidWlsZDogeyB0eEhleDogcHNidC50b0hleCgpIH0sXG4gICAgICAgICAgcHJ2OiB1c2VyUHJ2LFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIG1lc3NhZ2U6IGBsZW5ndGggbWlzbWF0Y2hgLFxuICAgICAgfVxuICAgICk7XG4gIH0pO1xufSk7XG4iXX0=
|