@bitgo-beta/sdk-core 8.2.1-beta.1813 → 8.2.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/src/bitgo/keychain/iKeychains.d.ts +2 -0
- package/dist/src/bitgo/keychain/iKeychains.d.ts.map +1 -1
- package/dist/src/bitgo/keychain/iKeychains.js +1 -1
- package/dist/src/bitgo/utils/mpcUtils.d.ts.map +1 -1
- package/dist/src/bitgo/utils/mpcUtils.js +8 -3
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.d.ts +2 -2
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsa.js +19 -17
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/ecdsa/ecdsaMPCv2.js +17 -16
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.d.ts +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/eddsa.js +15 -13
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.d.ts.map +1 -1
- package/dist/src/bitgo/utils/tss/eddsa/eddsaMPCv2.js +17 -16
- package/dist/src/bitgo/wallet/iWallets.d.ts +22 -0
- package/dist/src/bitgo/wallet/iWallets.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/iWallets.js +1 -1
- package/dist/src/bitgo/wallet/wallet.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/wallet.js +28 -1
- package/dist/src/bitgo/wallet/wallets.d.ts +10 -1
- package/dist/src/bitgo/wallet/wallets.d.ts.map +1 -1
- package/dist/src/bitgo/wallet/wallets.js +149 -1
- package/dist/test/unit/bitgo/wallet/walletsExternalSigner.d.ts +2 -0
- package/dist/test/unit/bitgo/wallet/walletsExternalSigner.d.ts.map +1 -0
- package/dist/test/unit/bitgo/wallet/walletsExternalSigner.js +310 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walletsExternalSigner.d.ts","sourceRoot":"","sources":["../../../../../test/unit/bitgo/wallet/walletsExternalSigner.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,CAAC"}
|
|
@@ -0,0 +1,310 @@
|
|
|
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
|
+
const assert = __importStar(require("assert"));
|
|
37
|
+
const sinon = __importStar(require("sinon"));
|
|
38
|
+
require("should");
|
|
39
|
+
const wallets_1 = require("../../../../src/bitgo/wallet/wallets");
|
|
40
|
+
const wallet_1 = require("../../../../src/bitgo/wallet/wallet");
|
|
41
|
+
describe('Wallets - external signer onchain wallet generation', function () {
|
|
42
|
+
let wallets;
|
|
43
|
+
let mockBitGo;
|
|
44
|
+
let mockBaseCoin;
|
|
45
|
+
let mockKeychains;
|
|
46
|
+
let createKeychainCallback;
|
|
47
|
+
let sendStub;
|
|
48
|
+
const userPub = 'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8';
|
|
49
|
+
const backupPub = 'xpub661MyMwAqRbcGczjuMoRm6dXaLDEhW1u34gKenbeYqAix21mdUKJyuyu5F1rzYGVxyL6tmgBUAEPrEz92mBXjByMRiJdba9wpnN37RLLAXa';
|
|
50
|
+
const bitgoPub = 'xpub661MyMwAqRbcEYS8w7XLSVeEsBXy79zSzH1J8vCdxAZningWLdN3zgtU6LBpB85b3D2yc8sfvZU521AAwdZafEz7mnzBBsz4wKY5fTtTQBm';
|
|
51
|
+
beforeEach(function () {
|
|
52
|
+
createKeychainCallback = sinon.stub();
|
|
53
|
+
createKeychainCallback.withArgs({ source: 'user', coin: 'tbtc' }).resolves({
|
|
54
|
+
pub: userPub,
|
|
55
|
+
type: 'independent',
|
|
56
|
+
source: 'user',
|
|
57
|
+
});
|
|
58
|
+
createKeychainCallback.withArgs({ source: 'backup', coin: 'tbtc' }).resolves({
|
|
59
|
+
pub: backupPub,
|
|
60
|
+
type: 'independent',
|
|
61
|
+
source: 'backup',
|
|
62
|
+
});
|
|
63
|
+
mockKeychains = {
|
|
64
|
+
add: sinon.stub().callsFake(async (params) => ({
|
|
65
|
+
id: `${params.source}-key-id`,
|
|
66
|
+
pub: params.pub,
|
|
67
|
+
source: params.source,
|
|
68
|
+
})),
|
|
69
|
+
createBitGo: sinon.stub().resolves({ id: 'bitgo-key-id', pub: bitgoPub }),
|
|
70
|
+
};
|
|
71
|
+
const mockWalletData = { id: 'wallet-id', keys: ['user-key-id', 'backup-key-id', 'bitgo-key-id'] };
|
|
72
|
+
sendStub = sinon.stub().returns({
|
|
73
|
+
result: sinon.stub().resolves(mockWalletData),
|
|
74
|
+
});
|
|
75
|
+
mockBitGo = {
|
|
76
|
+
post: sinon.stub().returns({ send: sendStub }),
|
|
77
|
+
setRequestTracer: sinon.stub(),
|
|
78
|
+
};
|
|
79
|
+
mockBaseCoin = {
|
|
80
|
+
isEVM: sinon.stub().returns(false),
|
|
81
|
+
supportsTss: sinon.stub().returns(true),
|
|
82
|
+
getFamily: sinon.stub().returns('btc'),
|
|
83
|
+
getChain: sinon.stub().returns('tbtc'),
|
|
84
|
+
getDefaultMultisigType: sinon.stub().returns('onchain'),
|
|
85
|
+
keychains: sinon.stub().returns(mockKeychains),
|
|
86
|
+
url: sinon.stub().returns('/api/v2/tbtc/wallet/add'),
|
|
87
|
+
getConfig: sinon.stub().returns({ features: [] }),
|
|
88
|
+
supplementGenerateWallet: sinon.stub().callsFake((walletParams) => Promise.resolve(walletParams)),
|
|
89
|
+
isValidPub: sinon.stub().returns(true),
|
|
90
|
+
};
|
|
91
|
+
wallets = new wallets_1.Wallets(mockBitGo, mockBaseCoin);
|
|
92
|
+
});
|
|
93
|
+
afterEach(function () {
|
|
94
|
+
sinon.restore();
|
|
95
|
+
});
|
|
96
|
+
describe('generateWalletWithExternalSigner', function () {
|
|
97
|
+
it('should create user and backup keys via callback and create wallet', async function () {
|
|
98
|
+
const result = await wallets.generateWalletWithExternalSigner({
|
|
99
|
+
label: 'External Signer Wallet',
|
|
100
|
+
enterprise: 'enterprise-id',
|
|
101
|
+
createKeychainCallback,
|
|
102
|
+
});
|
|
103
|
+
assert.strictEqual(createKeychainCallback.callCount, 2);
|
|
104
|
+
assert.strictEqual(mockKeychains.add.callCount, 2);
|
|
105
|
+
assert.strictEqual(mockKeychains.createBitGo.calledOnce, true);
|
|
106
|
+
assert.strictEqual(mockBitGo.post.calledOnce, true);
|
|
107
|
+
const addUserParams = mockKeychains.add.getCall(0).args[0];
|
|
108
|
+
addUserParams.should.have.property('pub', userPub);
|
|
109
|
+
addUserParams.should.have.property('keyType', 'independent');
|
|
110
|
+
addUserParams.should.have.property('source', 'user');
|
|
111
|
+
const walletBody = sendStub.firstCall.args[0];
|
|
112
|
+
walletBody.keys.should.deepEqual(['user-key-id', 'backup-key-id', 'bitgo-key-id']);
|
|
113
|
+
walletBody.label.should.equal('External Signer Wallet');
|
|
114
|
+
walletBody.enterprise.should.equal('enterprise-id');
|
|
115
|
+
result.responseType.should.equal('WalletWithKeychains');
|
|
116
|
+
assert.strictEqual(result.userKeychain.pub, userPub);
|
|
117
|
+
assert.strictEqual(result.backupKeychain.pub, backupPub);
|
|
118
|
+
assert.strictEqual(result.bitgoKeychain.pub, bitgoPub);
|
|
119
|
+
});
|
|
120
|
+
it('should reject when callback source does not match requested source', async function () {
|
|
121
|
+
createKeychainCallback.withArgs({ source: 'user', coin: 'tbtc' }).resolves({
|
|
122
|
+
pub: userPub,
|
|
123
|
+
type: 'independent',
|
|
124
|
+
source: 'backup',
|
|
125
|
+
});
|
|
126
|
+
await wallets
|
|
127
|
+
.generateWalletWithExternalSigner({
|
|
128
|
+
label: 'External Signer Wallet',
|
|
129
|
+
createKeychainCallback,
|
|
130
|
+
})
|
|
131
|
+
.should.be.rejectedWith('Failed to create user keychain: createKeychainCallback returned source backup, expected user');
|
|
132
|
+
});
|
|
133
|
+
it('should reject invalid type from callback', async function () {
|
|
134
|
+
const badTypeCallback = sinon.stub();
|
|
135
|
+
badTypeCallback.withArgs({ source: 'user', coin: 'tbtc' }).resolves({
|
|
136
|
+
pub: userPub,
|
|
137
|
+
type: 'tss',
|
|
138
|
+
source: 'user',
|
|
139
|
+
});
|
|
140
|
+
badTypeCallback.withArgs({ source: 'backup', coin: 'tbtc' }).resolves({
|
|
141
|
+
pub: backupPub,
|
|
142
|
+
type: 'independent',
|
|
143
|
+
source: 'backup',
|
|
144
|
+
});
|
|
145
|
+
await wallets
|
|
146
|
+
.generateWalletWithExternalSigner({
|
|
147
|
+
label: 'External Signer Wallet',
|
|
148
|
+
createKeychainCallback: badTypeCallback,
|
|
149
|
+
})
|
|
150
|
+
.should.be.rejectedWith("Failed to create user keychain: createKeychainCallback returned invalid type tss, expected 'independent' for onchain multisig");
|
|
151
|
+
});
|
|
152
|
+
it('should reject TSS multisig type', async function () {
|
|
153
|
+
await wallets
|
|
154
|
+
.generateWalletWithExternalSigner({
|
|
155
|
+
label: 'TSS Wallet',
|
|
156
|
+
multisigType: 'tss',
|
|
157
|
+
createKeychainCallback,
|
|
158
|
+
})
|
|
159
|
+
.should.be.rejectedWith('external signer wallet generation is only supported for onchain multisig wallets');
|
|
160
|
+
});
|
|
161
|
+
it('should reject custodial wallet type', async function () {
|
|
162
|
+
await wallets
|
|
163
|
+
.generateWalletWithExternalSigner({
|
|
164
|
+
label: 'Custodial Wallet',
|
|
165
|
+
type: 'custodial',
|
|
166
|
+
createKeychainCallback,
|
|
167
|
+
})
|
|
168
|
+
.should.be.rejectedWith('external signer wallet generation is not supported for custodial onchain wallets');
|
|
169
|
+
});
|
|
170
|
+
it('should reject passcodeEncryptionCode', async function () {
|
|
171
|
+
await wallets
|
|
172
|
+
.generateWalletWithExternalSigner({
|
|
173
|
+
label: 'Wallet',
|
|
174
|
+
passcodeEncryptionCode: 'some-code',
|
|
175
|
+
createKeychainCallback,
|
|
176
|
+
})
|
|
177
|
+
.should.be.rejectedWith('passcodeEncryptionCode is not supported for external signer wallet generation');
|
|
178
|
+
});
|
|
179
|
+
it('should reject webauthnInfo', async function () {
|
|
180
|
+
await wallets
|
|
181
|
+
.generateWalletWithExternalSigner({
|
|
182
|
+
label: 'Wallet',
|
|
183
|
+
webauthnInfo: { otpDeviceId: 'dev-id', prfSalt: 'salt', passphrase: 'pass' },
|
|
184
|
+
createKeychainCallback,
|
|
185
|
+
})
|
|
186
|
+
.should.be.rejectedWith('webauthnInfo is not supported for external signer wallet generation');
|
|
187
|
+
});
|
|
188
|
+
it('should reject isDistributedCustody without enterprise', async function () {
|
|
189
|
+
await wallets
|
|
190
|
+
.generateWalletWithExternalSigner({
|
|
191
|
+
label: 'DC Wallet',
|
|
192
|
+
type: 'cold',
|
|
193
|
+
isDistributedCustody: true,
|
|
194
|
+
createKeychainCallback,
|
|
195
|
+
})
|
|
196
|
+
.should.be.rejectedWith('must provide enterprise when creating distributed custody wallet');
|
|
197
|
+
});
|
|
198
|
+
it('should reject isDistributedCustody with non-cold type', async function () {
|
|
199
|
+
await wallets
|
|
200
|
+
.generateWalletWithExternalSigner({
|
|
201
|
+
label: 'DC Wallet',
|
|
202
|
+
type: 'hot',
|
|
203
|
+
isDistributedCustody: true,
|
|
204
|
+
enterprise: 'enterprise-id',
|
|
205
|
+
createKeychainCallback,
|
|
206
|
+
})
|
|
207
|
+
.should.be.rejectedWith('distributed custody wallets must be type: cold');
|
|
208
|
+
});
|
|
209
|
+
it('should reject when callback returns invalid pub for coin', async function () {
|
|
210
|
+
// only invalidate user pub so the rejection source is deterministic
|
|
211
|
+
mockBaseCoin.isValidPub.callsFake((pub) => pub !== userPub);
|
|
212
|
+
await wallets
|
|
213
|
+
.generateWalletWithExternalSigner({
|
|
214
|
+
label: 'External Signer Wallet',
|
|
215
|
+
createKeychainCallback,
|
|
216
|
+
})
|
|
217
|
+
.should.be.rejectedWith('Failed to create user keychain: createKeychainCallback returned invalid pub for user key on tbtc');
|
|
218
|
+
});
|
|
219
|
+
it('should wrap error when callback throws', async function () {
|
|
220
|
+
createKeychainCallback.withArgs({ source: 'user', coin: 'tbtc' }).rejects(new Error('HSM unreachable'));
|
|
221
|
+
await wallets
|
|
222
|
+
.generateWalletWithExternalSigner({
|
|
223
|
+
label: 'External Signer Wallet',
|
|
224
|
+
createKeychainCallback,
|
|
225
|
+
})
|
|
226
|
+
.should.be.rejectedWith('Failed to create user keychain: HSM unreachable');
|
|
227
|
+
});
|
|
228
|
+
it('should reject with backup keychain error when backup callback throws', async function () {
|
|
229
|
+
createKeychainCallback.withArgs({ source: 'backup', coin: 'tbtc' }).rejects(new Error('HSM unreachable'));
|
|
230
|
+
await wallets
|
|
231
|
+
.generateWalletWithExternalSigner({
|
|
232
|
+
label: 'External Signer Wallet',
|
|
233
|
+
createKeychainCallback,
|
|
234
|
+
})
|
|
235
|
+
.should.be.rejectedWith('Failed to create backup keychain: HSM unreachable');
|
|
236
|
+
assert.strictEqual(mockBitGo.post.callCount, 0);
|
|
237
|
+
});
|
|
238
|
+
it('should wrap non-Error thrown by callback', async function () {
|
|
239
|
+
createKeychainCallback
|
|
240
|
+
.withArgs({ source: 'user', coin: 'tbtc' })
|
|
241
|
+
.returns(Promise.reject('plain string rejection'));
|
|
242
|
+
await wallets
|
|
243
|
+
.generateWalletWithExternalSigner({
|
|
244
|
+
label: 'External Signer Wallet',
|
|
245
|
+
createKeychainCallback,
|
|
246
|
+
})
|
|
247
|
+
.should.be.rejectedWith('Failed to create user keychain: plain string rejection');
|
|
248
|
+
});
|
|
249
|
+
it('should forward keySignatures to wallet params when provided', async function () {
|
|
250
|
+
const keySignatures = {
|
|
251
|
+
backup: 'deadbeef01',
|
|
252
|
+
bitgo: 'deadbeef02',
|
|
253
|
+
};
|
|
254
|
+
await wallets.generateWalletWithExternalSigner({
|
|
255
|
+
label: 'External Signer Wallet',
|
|
256
|
+
enterprise: 'enterprise-id',
|
|
257
|
+
createKeychainCallback,
|
|
258
|
+
keySignatures,
|
|
259
|
+
});
|
|
260
|
+
const walletBody = sendStub.firstCall.args[0];
|
|
261
|
+
walletBody.should.have.property('keySignatures');
|
|
262
|
+
walletBody.keySignatures.should.deepEqual(keySignatures);
|
|
263
|
+
});
|
|
264
|
+
it('should not include keySignatures in wallet params when not provided', async function () {
|
|
265
|
+
await wallets.generateWalletWithExternalSigner({
|
|
266
|
+
label: 'External Signer Wallet',
|
|
267
|
+
enterprise: 'enterprise-id',
|
|
268
|
+
createKeychainCallback,
|
|
269
|
+
});
|
|
270
|
+
const walletBody = sendStub.firstCall.args[0];
|
|
271
|
+
walletBody.should.not.have.property('keySignatures');
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
describe('generateWallet with createKeychainCallback', function () {
|
|
275
|
+
it('should delegate to generateWalletWithExternalSigner', async function () {
|
|
276
|
+
const generateWalletWithExternalSignerStub = sinon.stub(wallets, 'generateWalletWithExternalSigner').resolves({
|
|
277
|
+
responseType: 'WalletWithKeychains',
|
|
278
|
+
wallet: sinon.createStubInstance(wallet_1.Wallet),
|
|
279
|
+
userKeychain: { id: 'user-key-id', pub: userPub, type: 'independent' },
|
|
280
|
+
backupKeychain: { id: 'backup-key-id', pub: backupPub, type: 'independent' },
|
|
281
|
+
bitgoKeychain: { id: 'bitgo-key-id', pub: bitgoPub, type: 'independent' },
|
|
282
|
+
});
|
|
283
|
+
await wallets.generateWallet({
|
|
284
|
+
label: 'Delegated Wallet',
|
|
285
|
+
createKeychainCallback,
|
|
286
|
+
});
|
|
287
|
+
assert.strictEqual(generateWalletWithExternalSignerStub.calledOnce, true);
|
|
288
|
+
generateWalletWithExternalSignerStub.firstCall.args[0].label.should.equal('Delegated Wallet');
|
|
289
|
+
});
|
|
290
|
+
it('should reject when createKeychainCallback is combined with passphrase', async function () {
|
|
291
|
+
await wallets
|
|
292
|
+
.generateWallet({
|
|
293
|
+
label: 'Invalid Wallet',
|
|
294
|
+
passphrase: 'secret',
|
|
295
|
+
createKeychainCallback,
|
|
296
|
+
})
|
|
297
|
+
.should.be.rejectedWith('createKeychainCallback cannot be used with passphrase');
|
|
298
|
+
});
|
|
299
|
+
it('should reject when createKeychainCallback is combined with userKey', async function () {
|
|
300
|
+
await wallets
|
|
301
|
+
.generateWallet({
|
|
302
|
+
label: 'Invalid Wallet',
|
|
303
|
+
userKey: 'xpub...',
|
|
304
|
+
createKeychainCallback,
|
|
305
|
+
})
|
|
306
|
+
.should.be.rejectedWith('createKeychainCallback cannot be used with userKey');
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FsbGV0c0V4dGVybmFsU2lnbmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGVzdC91bml0L2JpdGdvL3dhbGxldC93YWxsZXRzRXh0ZXJuYWxTaWduZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBaUM7QUFDakMsNkNBQStCO0FBQy9CLGtCQUFnQjtBQUVoQixrRUFBK0Q7QUFFL0QsZ0VBQTZEO0FBRTdELFFBQVEsQ0FBQyxxREFBcUQsRUFBRTtJQUM5RCxJQUFJLE9BQWdCLENBQUM7SUFDckIsSUFBSSxTQUFjLENBQUM7SUFDbkIsSUFBSSxZQUFpQixDQUFDO0lBQ3RCLElBQUksYUFBa0IsQ0FBQztJQUN2QixJQUFJLHNCQUErRyxDQUFDO0lBQ3BILElBQUksUUFBeUIsQ0FBQztJQUU5QixNQUFNLE9BQU8sR0FDWCxpSEFBaUgsQ0FBQztJQUNwSCxNQUFNLFNBQVMsR0FDYixpSEFBaUgsQ0FBQztJQUNwSCxNQUFNLFFBQVEsR0FDWixpSEFBaUgsQ0FBQztJQUVwSCxVQUFVLENBQUM7UUFDVCxzQkFBc0IsR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEMsc0JBQXNCLENBQUMsUUFBUSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUM7WUFDekUsR0FBRyxFQUFFLE9BQU87WUFDWixJQUFJLEVBQUUsYUFBYTtZQUNuQixNQUFNLEVBQUUsTUFBTTtTQUNmLENBQUMsQ0FBQztRQUNILHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDO1lBQzNFLEdBQUcsRUFBRSxTQUFTO1lBQ2QsSUFBSSxFQUFFLGFBQWE7WUFDbkIsTUFBTSxFQUFFLFFBQVE7U0FDakIsQ0FBQyxDQUFDO1FBRUgsYUFBYSxHQUFHO1lBQ2QsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLE1BQXVDLEVBQUUsRUFBRSxDQUFDLENBQUM7Z0JBQzlFLEVBQUUsRUFBRSxHQUFHLE1BQU0sQ0FBQyxNQUFNLFNBQVM7Z0JBQzdCLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztnQkFDZixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07YUFDdEIsQ0FBQyxDQUFDO1lBQ0gsV0FBVyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQztTQUMxRSxDQUFDO1FBRUYsTUFBTSxjQUFjLEdBQUcsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxDQUFDLGFBQWEsRUFBRSxlQUFlLEVBQUUsY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUVuRyxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQztZQUM5QixNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7U0FDOUMsQ0FBQyxDQUFDO1FBQ0gsU0FBUyxHQUFHO1lBQ1YsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUM7WUFDOUMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRTtTQUMvQixDQUFDO1FBRUYsWUFBWSxHQUFHO1lBQ2IsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1lBQ2xDLFdBQVcsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztZQUN2QyxTQUFTLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDdEMsUUFBUSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1lBQ3RDLHNCQUFzQixFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ3ZELFNBQVMsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQztZQUM5QyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQztZQUNwRCxTQUFTLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsQ0FBQztZQUNqRCx3QkFBd0IsRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsWUFBcUIsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUMxRyxVQUFVLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7U0FDdkMsQ0FBQztRQUVGLE9BQU8sR0FBRyxJQUFJLGlCQUFPLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBRUgsU0FBUyxDQUFDO1FBQ1IsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGtDQUFrQyxFQUFFO1FBQzNDLEVBQUUsQ0FBQyxtRUFBbUUsRUFBRSxLQUFLO1lBQzNFLE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLGdDQUFnQyxDQUFDO2dCQUM1RCxLQUFLLEVBQUUsd0JBQXdCO2dCQUMvQixVQUFVLEVBQUUsZUFBZTtnQkFDM0Isc0JBQXNCO2FBQ3ZCLENBQUMsQ0FBQztZQUVILE1BQU0sQ0FBQyxXQUFXLENBQUMsc0JBQXNCLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUMvRCxNQUFNLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBRXBELE1BQU0sYUFBYSxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMzRCxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ25ELGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDN0QsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUVyRCxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5QyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxhQUFhLEVBQUUsZUFBZSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDbkYsVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7WUFDeEQsVUFBVSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRXBELE1BQU0sQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDckQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUN6RCxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3pELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLG9FQUFvRSxFQUFFLEtBQUs7WUFDNUUsc0JBQXNCLENBQUMsUUFBUSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUM7Z0JBQ3pFLEdBQUcsRUFBRSxPQUFPO2dCQUNaLElBQUksRUFBRSxhQUFhO2dCQUNuQixNQUFNLEVBQUUsUUFBUTthQUNqQixDQUFDLENBQUM7WUFFSCxNQUFNLE9BQU87aUJBQ1YsZ0NBQWdDLENBQUM7Z0JBQ2hDLEtBQUssRUFBRSx3QkFBd0I7Z0JBQy9CLHNCQUFzQjthQUN2QixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUNyQiw4RkFBOEYsQ0FDL0YsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDBDQUEwQyxFQUFFLEtBQUs7WUFDbEQsTUFBTSxlQUFlLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3JDLGVBQWUsQ0FBQyxRQUFRLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQztnQkFDbEUsR0FBRyxFQUFFLE9BQU87Z0JBQ1osSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsTUFBTSxFQUFFLE1BQU07YUFDZixDQUFDLENBQUM7WUFDSCxlQUFlLENBQUMsUUFBUSxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUM7Z0JBQ3BFLEdBQUcsRUFBRSxTQUFTO2dCQUNkLElBQUksRUFBRSxhQUFhO2dCQUNuQixNQUFNLEVBQUUsUUFBUTthQUNqQixDQUFDLENBQUM7WUFFSCxNQUFNLE9BQU87aUJBQ1YsZ0NBQWdDLENBQUM7Z0JBQ2hDLEtBQUssRUFBRSx3QkFBd0I7Z0JBQy9CLHNCQUFzQixFQUFFLGVBQWU7YUFDeEMsQ0FBQztpQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FDckIsK0hBQStILENBQ2hJLENBQUM7UUFDTixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxpQ0FBaUMsRUFBRSxLQUFLO1lBQ3pDLE1BQU0sT0FBTztpQkFDVixnQ0FBZ0MsQ0FBQztnQkFDaEMsS0FBSyxFQUFFLFlBQVk7Z0JBQ25CLFlBQVksRUFBRSxLQUFLO2dCQUNuQixzQkFBc0I7YUFDdkIsQ0FBQztpQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxrRkFBa0YsQ0FBQyxDQUFDO1FBQ2hILENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHFDQUFxQyxFQUFFLEtBQUs7WUFDN0MsTUFBTSxPQUFPO2lCQUNWLGdDQUFnQyxDQUFDO2dCQUNoQyxLQUFLLEVBQUUsa0JBQWtCO2dCQUN6QixJQUFJLEVBQUUsV0FBVztnQkFDakIsc0JBQXNCO2FBQ3ZCLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsa0ZBQWtGLENBQUMsQ0FBQztRQUNoSCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLO1lBQzlDLE1BQU0sT0FBTztpQkFDVixnQ0FBZ0MsQ0FBQztnQkFDaEMsS0FBSyxFQUFFLFFBQVE7Z0JBQ2Ysc0JBQXNCLEVBQUUsV0FBVztnQkFDbkMsc0JBQXNCO2FBQ3ZCLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsK0VBQStFLENBQUMsQ0FBQztRQUM3RyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxLQUFLO1lBQ3BDLE1BQU0sT0FBTztpQkFDVixnQ0FBZ0MsQ0FBQztnQkFDaEMsS0FBSyxFQUFFLFFBQVE7Z0JBQ2YsWUFBWSxFQUFFLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7Z0JBQzVFLHNCQUFzQjthQUN2QixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLHFFQUFxRSxDQUFDLENBQUM7UUFDbkcsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsdURBQXVELEVBQUUsS0FBSztZQUMvRCxNQUFNLE9BQU87aUJBQ1YsZ0NBQWdDLENBQUM7Z0JBQ2hDLEtBQUssRUFBRSxXQUFXO2dCQUNsQixJQUFJLEVBQUUsTUFBTTtnQkFDWixvQkFBb0IsRUFBRSxJQUFJO2dCQUMxQixzQkFBc0I7YUFDdkIsQ0FBQztpQkFDRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxrRUFBa0UsQ0FBQyxDQUFDO1FBQ2hHLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHVEQUF1RCxFQUFFLEtBQUs7WUFDL0QsTUFBTSxPQUFPO2lCQUNWLGdDQUFnQyxDQUFDO2dCQUNoQyxLQUFLLEVBQUUsV0FBVztnQkFDbEIsSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsb0JBQW9CLEVBQUUsSUFBSTtnQkFDMUIsVUFBVSxFQUFFLGVBQWU7Z0JBQzNCLHNCQUFzQjthQUN2QixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGdEQUFnRCxDQUFDLENBQUM7UUFDOUUsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsMERBQTBELEVBQUUsS0FBSztZQUNsRSxvRUFBb0U7WUFDcEUsWUFBWSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxPQUFPLENBQUMsQ0FBQztZQUVwRSxNQUFNLE9BQU87aUJBQ1YsZ0NBQWdDLENBQUM7Z0JBQ2hDLEtBQUssRUFBRSx3QkFBd0I7Z0JBQy9CLHNCQUFzQjthQUN2QixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUNyQixrR0FBa0csQ0FDbkcsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHdDQUF3QyxFQUFFLEtBQUs7WUFDaEQsc0JBQXNCLENBQUMsUUFBUSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO1lBRXhHLE1BQU0sT0FBTztpQkFDVixnQ0FBZ0MsQ0FBQztnQkFDaEMsS0FBSyxFQUFFLHdCQUF3QjtnQkFDL0Isc0JBQXNCO2FBQ3ZCLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsaURBQWlELENBQUMsQ0FBQztRQUMvRSxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxzRUFBc0UsRUFBRSxLQUFLO1lBQzlFLHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztZQUUxRyxNQUFNLE9BQU87aUJBQ1YsZ0NBQWdDLENBQUM7Z0JBQ2hDLEtBQUssRUFBRSx3QkFBd0I7Z0JBQy9CLHNCQUFzQjthQUN2QixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLG1EQUFtRCxDQUFDLENBQUM7WUFFL0UsTUFBTSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNsRCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywwQ0FBMEMsRUFBRSxLQUFLO1lBQ2xELHNCQUFzQjtpQkFDbkIsUUFBUSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7aUJBQzFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQztZQUVyRCxNQUFNLE9BQU87aUJBQ1YsZ0NBQWdDLENBQUM7Z0JBQ2hDLEtBQUssRUFBRSx3QkFBd0I7Z0JBQy9CLHNCQUFzQjthQUN2QixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLHdEQUF3RCxDQUFDLENBQUM7UUFDdEYsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkRBQTZELEVBQUUsS0FBSztZQUNyRSxNQUFNLGFBQWEsR0FBRztnQkFDcEIsTUFBTSxFQUFFLFlBQVk7Z0JBQ3BCLEtBQUssRUFBRSxZQUFZO2FBQ3BCLENBQUM7WUFFRixNQUFNLE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBQztnQkFDN0MsS0FBSyxFQUFFLHdCQUF3QjtnQkFDL0IsVUFBVSxFQUFFLGVBQWU7Z0JBQzNCLHNCQUFzQjtnQkFDdEIsYUFBYTthQUNkLENBQUMsQ0FBQztZQUVILE1BQU0sVUFBVSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNqRCxVQUFVLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDM0QsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMscUVBQXFFLEVBQUUsS0FBSztZQUM3RSxNQUFNLE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBQztnQkFDN0MsS0FBSyxFQUFFLHdCQUF3QjtnQkFDL0IsVUFBVSxFQUFFLGVBQWU7Z0JBQzNCLHNCQUFzQjthQUN2QixDQUFDLENBQUM7WUFFSCxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5QyxVQUFVLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3ZELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsNENBQTRDLEVBQUU7UUFDckQsRUFBRSxDQUFDLHFEQUFxRCxFQUFFLEtBQUs7WUFDN0QsTUFBTSxvQ0FBb0MsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxrQ0FBa0MsQ0FBQyxDQUFDLFFBQVEsQ0FBQztnQkFDNUcsWUFBWSxFQUFFLHFCQUFxQjtnQkFDbkMsTUFBTSxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxlQUFNLENBQUM7Z0JBQ3hDLFlBQVksRUFBRSxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsYUFBc0IsRUFBRTtnQkFDL0UsY0FBYyxFQUFFLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxhQUFzQixFQUFFO2dCQUNyRixhQUFhLEVBQUUsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLGFBQXNCLEVBQUU7YUFDbkYsQ0FBQyxDQUFDO1lBRUgsTUFBTSxPQUFPLENBQUMsY0FBYyxDQUFDO2dCQUMzQixLQUFLLEVBQUUsa0JBQWtCO2dCQUN6QixzQkFBc0I7YUFDdkIsQ0FBQyxDQUFDO1lBRUgsTUFBTSxDQUFDLFdBQVcsQ0FBQyxvQ0FBb0MsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDMUUsb0NBQW9DLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ2hHLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHVFQUF1RSxFQUFFLEtBQUs7WUFDL0UsTUFBTSxPQUFPO2lCQUNWLGNBQWMsQ0FBQztnQkFDZCxLQUFLLEVBQUUsZ0JBQWdCO2dCQUN2QixVQUFVLEVBQUUsUUFBUTtnQkFDcEIsc0JBQXNCO2FBQ3ZCLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsdURBQXVELENBQUMsQ0FBQztRQUNyRixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxvRUFBb0UsRUFBRSxLQUFLO1lBQzVFLE1BQU0sT0FBTztpQkFDVixjQUFjLENBQUM7Z0JBQ2QsS0FBSyxFQUFFLGdCQUFnQjtnQkFDdkIsT0FBTyxFQUFFLFNBQVM7Z0JBQ2xCLHNCQUFzQjthQUN2QixDQUFDO2lCQUNELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLG9EQUFvRCxDQUFDLENBQUM7UUFDbEYsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgJ3Nob3VsZCc7XG5cbmltcG9ydCB7IFdhbGxldHMgfSBmcm9tICcuLi8uLi8uLi8uLi9zcmMvYml0Z28vd2FsbGV0L3dhbGxldHMnO1xuaW1wb3J0IHsgQ3JlYXRlS2V5Y2hhaW5DYWxsYmFjayB9IGZyb20gJy4uLy4uLy4uLy4uL3NyYy9iaXRnby93YWxsZXQvaVdhbGxldHMnO1xuaW1wb3J0IHsgV2FsbGV0IH0gZnJvbSAnLi4vLi4vLi4vLi4vc3JjL2JpdGdvL3dhbGxldC93YWxsZXQnO1xuXG5kZXNjcmliZSgnV2FsbGV0cyAtIGV4dGVybmFsIHNpZ25lciBvbmNoYWluIHdhbGxldCBnZW5lcmF0aW9uJywgZnVuY3Rpb24gKCkge1xuICBsZXQgd2FsbGV0czogV2FsbGV0cztcbiAgbGV0IG1vY2tCaXRHbzogYW55O1xuICBsZXQgbW9ja0Jhc2VDb2luOiBhbnk7XG4gIGxldCBtb2NrS2V5Y2hhaW5zOiBhbnk7XG4gIGxldCBjcmVhdGVLZXljaGFpbkNhbGxiYWNrOiBzaW5vbi5TaW5vblN0dWI8UGFyYW1ldGVyczxDcmVhdGVLZXljaGFpbkNhbGxiYWNrPiwgUmV0dXJuVHlwZTxDcmVhdGVLZXljaGFpbkNhbGxiYWNrPj47XG4gIGxldCBzZW5kU3R1Yjogc2lub24uU2lub25TdHViO1xuXG4gIGNvbnN0IHVzZXJQdWIgPVxuICAgICd4cHViNjYxTXlNd0FxUmJjRnRYZ1M1c1lKQUJxcUc5WUxtQzRRMVJkYXA5Z1NFOE5xdHd5YkdoZVBZMmdaMjlFU0ZqcUpvQ3UxUnVwamU4WXRHcXNlZkQyNjVUTWc3dXNVREZkcDZXMUVHTWNldDgnO1xuICBjb25zdCBiYWNrdXBQdWIgPVxuICAgICd4cHViNjYxTXlNd0FxUmJjR2N6anVNb1JtNmRYYUxERWhXMXUzNGdLZW5iZVlxQWl4MjFtZFVLSnl1eXU1RjFyellHVnh5TDZ0bWdCVUFFUHJFejkybUJYakJ5TVJpSmRiYTl3cG5OMzdSTExBWGEnO1xuICBjb25zdCBiaXRnb1B1YiA9XG4gICAgJ3hwdWI2NjFNeU13QXFSYmNFWVM4dzdYTFNWZUVzQlh5Nzl6U3pIMUo4dkNkeEFabmluZ1dMZE4zemd0VTZMQnBCODViM0QyeWM4c2Z2WlU1MjFBQXdkWmFmRXo3bW56QkJzejR3S1k1ZlR0VFFCbSc7XG5cbiAgYmVmb3JlRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayA9IHNpbm9uLnN0dWIoKTtcbiAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLndpdGhBcmdzKHsgc291cmNlOiAndXNlcicsIGNvaW46ICd0YnRjJyB9KS5yZXNvbHZlcyh7XG4gICAgICBwdWI6IHVzZXJQdWIsXG4gICAgICB0eXBlOiAnaW5kZXBlbmRlbnQnLFxuICAgICAgc291cmNlOiAndXNlcicsXG4gICAgfSk7XG4gICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjay53aXRoQXJncyh7IHNvdXJjZTogJ2JhY2t1cCcsIGNvaW46ICd0YnRjJyB9KS5yZXNvbHZlcyh7XG4gICAgICBwdWI6IGJhY2t1cFB1YixcbiAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICBzb3VyY2U6ICdiYWNrdXAnLFxuICAgIH0pO1xuXG4gICAgbW9ja0tleWNoYWlucyA9IHtcbiAgICAgIGFkZDogc2lub24uc3R1YigpLmNhbGxzRmFrZShhc3luYyAocGFyYW1zOiB7IHB1Yjogc3RyaW5nOyBzb3VyY2U6IHN0cmluZyB9KSA9PiAoe1xuICAgICAgICBpZDogYCR7cGFyYW1zLnNvdXJjZX0ta2V5LWlkYCxcbiAgICAgICAgcHViOiBwYXJhbXMucHViLFxuICAgICAgICBzb3VyY2U6IHBhcmFtcy5zb3VyY2UsXG4gICAgICB9KSksXG4gICAgICBjcmVhdGVCaXRHbzogc2lub24uc3R1YigpLnJlc29sdmVzKHsgaWQ6ICdiaXRnby1rZXktaWQnLCBwdWI6IGJpdGdvUHViIH0pLFxuICAgIH07XG5cbiAgICBjb25zdCBtb2NrV2FsbGV0RGF0YSA9IHsgaWQ6ICd3YWxsZXQtaWQnLCBrZXlzOiBbJ3VzZXIta2V5LWlkJywgJ2JhY2t1cC1rZXktaWQnLCAnYml0Z28ta2V5LWlkJ10gfTtcblxuICAgIHNlbmRTdHViID0gc2lub24uc3R1YigpLnJldHVybnMoe1xuICAgICAgcmVzdWx0OiBzaW5vbi5zdHViKCkucmVzb2x2ZXMobW9ja1dhbGxldERhdGEpLFxuICAgIH0pO1xuICAgIG1vY2tCaXRHbyA9IHtcbiAgICAgIHBvc3Q6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKHsgc2VuZDogc2VuZFN0dWIgfSksXG4gICAgICBzZXRSZXF1ZXN0VHJhY2VyOiBzaW5vbi5zdHViKCksXG4gICAgfTtcblxuICAgIG1vY2tCYXNlQ29pbiA9IHtcbiAgICAgIGlzRVZNOiBzaW5vbi5zdHViKCkucmV0dXJucyhmYWxzZSksXG4gICAgICBzdXBwb3J0c1Rzczogc2lub24uc3R1YigpLnJldHVybnModHJ1ZSksXG4gICAgICBnZXRGYW1pbHk6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKCdidGMnKSxcbiAgICAgIGdldENoYWluOiBzaW5vbi5zdHViKCkucmV0dXJucygndGJ0YycpLFxuICAgICAgZ2V0RGVmYXVsdE11bHRpc2lnVHlwZTogc2lub24uc3R1YigpLnJldHVybnMoJ29uY2hhaW4nKSxcbiAgICAgIGtleWNoYWluczogc2lub24uc3R1YigpLnJldHVybnMobW9ja0tleWNoYWlucyksXG4gICAgICB1cmw6IHNpbm9uLnN0dWIoKS5yZXR1cm5zKCcvYXBpL3YyL3RidGMvd2FsbGV0L2FkZCcpLFxuICAgICAgZ2V0Q29uZmlnOiBzaW5vbi5zdHViKCkucmV0dXJucyh7IGZlYXR1cmVzOiBbXSB9KSxcbiAgICAgIHN1cHBsZW1lbnRHZW5lcmF0ZVdhbGxldDogc2lub24uc3R1YigpLmNhbGxzRmFrZSgod2FsbGV0UGFyYW1zOiB1bmtub3duKSA9PiBQcm9taXNlLnJlc29sdmUod2FsbGV0UGFyYW1zKSksXG4gICAgICBpc1ZhbGlkUHViOiBzaW5vbi5zdHViKCkucmV0dXJucyh0cnVlKSxcbiAgICB9O1xuXG4gICAgd2FsbGV0cyA9IG5ldyBXYWxsZXRzKG1vY2tCaXRHbywgbW9ja0Jhc2VDb2luKTtcbiAgfSk7XG5cbiAgYWZ0ZXJFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZW5lcmF0ZVdhbGxldFdpdGhFeHRlcm5hbFNpZ25lcicsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSB1c2VyIGFuZCBiYWNrdXAga2V5cyB2aWEgY2FsbGJhY2sgYW5kIGNyZWF0ZSB3YWxsZXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB3YWxsZXRzLmdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyKHtcbiAgICAgICAgbGFiZWw6ICdFeHRlcm5hbCBTaWduZXIgV2FsbGV0JyxcbiAgICAgICAgZW50ZXJwcmlzZTogJ2VudGVycHJpc2UtaWQnLFxuICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgfSk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChjcmVhdGVLZXljaGFpbkNhbGxiYWNrLmNhbGxDb3VudCwgMik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwobW9ja0tleWNoYWlucy5hZGQuY2FsbENvdW50LCAyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChtb2NrS2V5Y2hhaW5zLmNyZWF0ZUJpdEdvLmNhbGxlZE9uY2UsIHRydWUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG1vY2tCaXRHby5wb3N0LmNhbGxlZE9uY2UsIHRydWUpO1xuXG4gICAgICBjb25zdCBhZGRVc2VyUGFyYW1zID0gbW9ja0tleWNoYWlucy5hZGQuZ2V0Q2FsbCgwKS5hcmdzWzBdO1xuICAgICAgYWRkVXNlclBhcmFtcy5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgncHViJywgdXNlclB1Yik7XG4gICAgICBhZGRVc2VyUGFyYW1zLnNob3VsZC5oYXZlLnByb3BlcnR5KCdrZXlUeXBlJywgJ2luZGVwZW5kZW50Jyk7XG4gICAgICBhZGRVc2VyUGFyYW1zLnNob3VsZC5oYXZlLnByb3BlcnR5KCdzb3VyY2UnLCAndXNlcicpO1xuXG4gICAgICBjb25zdCB3YWxsZXRCb2R5ID0gc2VuZFN0dWIuZmlyc3RDYWxsLmFyZ3NbMF07XG4gICAgICB3YWxsZXRCb2R5LmtleXMuc2hvdWxkLmRlZXBFcXVhbChbJ3VzZXIta2V5LWlkJywgJ2JhY2t1cC1rZXktaWQnLCAnYml0Z28ta2V5LWlkJ10pO1xuICAgICAgd2FsbGV0Qm9keS5sYWJlbC5zaG91bGQuZXF1YWwoJ0V4dGVybmFsIFNpZ25lciBXYWxsZXQnKTtcbiAgICAgIHdhbGxldEJvZHkuZW50ZXJwcmlzZS5zaG91bGQuZXF1YWwoJ2VudGVycHJpc2UtaWQnKTtcblxuICAgICAgcmVzdWx0LnJlc3BvbnNlVHlwZS5zaG91bGQuZXF1YWwoJ1dhbGxldFdpdGhLZXljaGFpbnMnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQudXNlcktleWNoYWluLnB1YiwgdXNlclB1Yik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LmJhY2t1cEtleWNoYWluLnB1YiwgYmFja3VwUHViKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQuYml0Z29LZXljaGFpbi5wdWIsIGJpdGdvUHViKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IHdoZW4gY2FsbGJhY2sgc291cmNlIGRvZXMgbm90IG1hdGNoIHJlcXVlc3RlZCBzb3VyY2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLndpdGhBcmdzKHsgc291cmNlOiAndXNlcicsIGNvaW46ICd0YnRjJyB9KS5yZXNvbHZlcyh7XG4gICAgICAgIHB1YjogdXNlclB1YixcbiAgICAgICAgdHlwZTogJ2luZGVwZW5kZW50JyxcbiAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldFdpdGhFeHRlcm5hbFNpZ25lcih7XG4gICAgICAgICAgbGFiZWw6ICdFeHRlcm5hbCBTaWduZXIgV2FsbGV0JyxcbiAgICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAnRmFpbGVkIHRvIGNyZWF0ZSB1c2VyIGtleWNoYWluOiBjcmVhdGVLZXljaGFpbkNhbGxiYWNrIHJldHVybmVkIHNvdXJjZSBiYWNrdXAsIGV4cGVjdGVkIHVzZXInXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBpbnZhbGlkIHR5cGUgZnJvbSBjYWxsYmFjaycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJhZFR5cGVDYWxsYmFjayA9IHNpbm9uLnN0dWIoKTtcbiAgICAgIGJhZFR5cGVDYWxsYmFjay53aXRoQXJncyh7IHNvdXJjZTogJ3VzZXInLCBjb2luOiAndGJ0YycgfSkucmVzb2x2ZXMoe1xuICAgICAgICBwdWI6IHVzZXJQdWIsXG4gICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgIH0pO1xuICAgICAgYmFkVHlwZUNhbGxiYWNrLndpdGhBcmdzKHsgc291cmNlOiAnYmFja3VwJywgY29pbjogJ3RidGMnIH0pLnJlc29sdmVzKHtcbiAgICAgICAgcHViOiBiYWNrdXBQdWIsXG4gICAgICAgIHR5cGU6ICdpbmRlcGVuZGVudCcsXG4gICAgICAgIHNvdXJjZTogJ2JhY2t1cCcsXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgd2FsbGV0c1xuICAgICAgICAuZ2VuZXJhdGVXYWxsZXRXaXRoRXh0ZXJuYWxTaWduZXIoe1xuICAgICAgICAgIGxhYmVsOiAnRXh0ZXJuYWwgU2lnbmVyIFdhbGxldCcsXG4gICAgICAgICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjazogYmFkVHlwZUNhbGxiYWNrLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICBcIkZhaWxlZCB0byBjcmVhdGUgdXNlciBrZXljaGFpbjogY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayByZXR1cm5lZCBpbnZhbGlkIHR5cGUgdHNzLCBleHBlY3RlZCAnaW5kZXBlbmRlbnQnIGZvciBvbmNoYWluIG11bHRpc2lnXCJcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IFRTUyBtdWx0aXNpZyB0eXBlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgYXdhaXQgd2FsbGV0c1xuICAgICAgICAuZ2VuZXJhdGVXYWxsZXRXaXRoRXh0ZXJuYWxTaWduZXIoe1xuICAgICAgICAgIGxhYmVsOiAnVFNTIFdhbGxldCcsXG4gICAgICAgICAgbXVsdGlzaWdUeXBlOiAndHNzJyxcbiAgICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnZXh0ZXJuYWwgc2lnbmVyIHdhbGxldCBnZW5lcmF0aW9uIGlzIG9ubHkgc3VwcG9ydGVkIGZvciBvbmNoYWluIG11bHRpc2lnIHdhbGxldHMnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGN1c3RvZGlhbCB3YWxsZXQgdHlwZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyKHtcbiAgICAgICAgICBsYWJlbDogJ0N1c3RvZGlhbCBXYWxsZXQnLFxuICAgICAgICAgIHR5cGU6ICdjdXN0b2RpYWwnLFxuICAgICAgICAgIGNyZWF0ZUtleWNoYWluQ2FsbGJhY2ssXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdleHRlcm5hbCBzaWduZXIgd2FsbGV0IGdlbmVyYXRpb24gaXMgbm90IHN1cHBvcnRlZCBmb3IgY3VzdG9kaWFsIG9uY2hhaW4gd2FsbGV0cycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3QgcGFzc2NvZGVFbmNyeXB0aW9uQ29kZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyKHtcbiAgICAgICAgICBsYWJlbDogJ1dhbGxldCcsXG4gICAgICAgICAgcGFzc2NvZGVFbmNyeXB0aW9uQ29kZTogJ3NvbWUtY29kZScsXG4gICAgICAgICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3Bhc3Njb2RlRW5jcnlwdGlvbkNvZGUgaXMgbm90IHN1cHBvcnRlZCBmb3IgZXh0ZXJuYWwgc2lnbmVyIHdhbGxldCBnZW5lcmF0aW9uJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCB3ZWJhdXRobkluZm8nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldFdpdGhFeHRlcm5hbFNpZ25lcih7XG4gICAgICAgICAgbGFiZWw6ICdXYWxsZXQnLFxuICAgICAgICAgIHdlYmF1dGhuSW5mbzogeyBvdHBEZXZpY2VJZDogJ2Rldi1pZCcsIHByZlNhbHQ6ICdzYWx0JywgcGFzc3BocmFzZTogJ3Bhc3MnIH0sXG4gICAgICAgICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3dlYmF1dGhuSW5mbyBpcyBub3Qgc3VwcG9ydGVkIGZvciBleHRlcm5hbCBzaWduZXIgd2FsbGV0IGdlbmVyYXRpb24nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IGlzRGlzdHJpYnV0ZWRDdXN0b2R5IHdpdGhvdXQgZW50ZXJwcmlzZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyKHtcbiAgICAgICAgICBsYWJlbDogJ0RDIFdhbGxldCcsXG4gICAgICAgICAgdHlwZTogJ2NvbGQnLFxuICAgICAgICAgIGlzRGlzdHJpYnV0ZWRDdXN0b2R5OiB0cnVlLFxuICAgICAgICAgIGNyZWF0ZUtleWNoYWluQ2FsbGJhY2ssXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdtdXN0IHByb3ZpZGUgZW50ZXJwcmlzZSB3aGVuIGNyZWF0aW5nIGRpc3RyaWJ1dGVkIGN1c3RvZHkgd2FsbGV0Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJlamVjdCBpc0Rpc3RyaWJ1dGVkQ3VzdG9keSB3aXRoIG5vbi1jb2xkIHR5cGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldFdpdGhFeHRlcm5hbFNpZ25lcih7XG4gICAgICAgICAgbGFiZWw6ICdEQyBXYWxsZXQnLFxuICAgICAgICAgIHR5cGU6ICdob3QnLFxuICAgICAgICAgIGlzRGlzdHJpYnV0ZWRDdXN0b2R5OiB0cnVlLFxuICAgICAgICAgIGVudGVycHJpc2U6ICdlbnRlcnByaXNlLWlkJyxcbiAgICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnZGlzdHJpYnV0ZWQgY3VzdG9keSB3YWxsZXRzIG11c3QgYmUgdHlwZTogY29sZCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3Qgd2hlbiBjYWxsYmFjayByZXR1cm5zIGludmFsaWQgcHViIGZvciBjb2luJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gb25seSBpbnZhbGlkYXRlIHVzZXIgcHViIHNvIHRoZSByZWplY3Rpb24gc291cmNlIGlzIGRldGVybWluaXN0aWNcbiAgICAgIG1vY2tCYXNlQ29pbi5pc1ZhbGlkUHViLmNhbGxzRmFrZSgocHViOiBzdHJpbmcpID0+IHB1YiAhPT0gdXNlclB1Yik7XG5cbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyKHtcbiAgICAgICAgICBsYWJlbDogJ0V4dGVybmFsIFNpZ25lciBXYWxsZXQnLFxuICAgICAgICAgIGNyZWF0ZUtleWNoYWluQ2FsbGJhY2ssXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgICdGYWlsZWQgdG8gY3JlYXRlIHVzZXIga2V5Y2hhaW46IGNyZWF0ZUtleWNoYWluQ2FsbGJhY2sgcmV0dXJuZWQgaW52YWxpZCBwdWIgZm9yIHVzZXIga2V5IG9uIHRidGMnXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHdyYXAgZXJyb3Igd2hlbiBjYWxsYmFjayB0aHJvd3MnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLndpdGhBcmdzKHsgc291cmNlOiAndXNlcicsIGNvaW46ICd0YnRjJyB9KS5yZWplY3RzKG5ldyBFcnJvcignSFNNIHVucmVhY2hhYmxlJykpO1xuXG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldFdpdGhFeHRlcm5hbFNpZ25lcih7XG4gICAgICAgICAgbGFiZWw6ICdFeHRlcm5hbCBTaWduZXIgV2FsbGV0JyxcbiAgICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnRmFpbGVkIHRvIGNyZWF0ZSB1c2VyIGtleWNoYWluOiBIU00gdW5yZWFjaGFibGUnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IHdpdGggYmFja3VwIGtleWNoYWluIGVycm9yIHdoZW4gYmFja3VwIGNhbGxiYWNrIHRocm93cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNyZWF0ZUtleWNoYWluQ2FsbGJhY2sud2l0aEFyZ3MoeyBzb3VyY2U6ICdiYWNrdXAnLCBjb2luOiAndGJ0YycgfSkucmVqZWN0cyhuZXcgRXJyb3IoJ0hTTSB1bnJlYWNoYWJsZScpKTtcblxuICAgICAgYXdhaXQgd2FsbGV0c1xuICAgICAgICAuZ2VuZXJhdGVXYWxsZXRXaXRoRXh0ZXJuYWxTaWduZXIoe1xuICAgICAgICAgIGxhYmVsOiAnRXh0ZXJuYWwgU2lnbmVyIFdhbGxldCcsXG4gICAgICAgICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ZhaWxlZCB0byBjcmVhdGUgYmFja3VwIGtleWNoYWluOiBIU00gdW5yZWFjaGFibGUnKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKG1vY2tCaXRHby5wb3N0LmNhbGxDb3VudCwgMCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHdyYXAgbm9uLUVycm9yIHRocm93biBieSBjYWxsYmFjaycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNyZWF0ZUtleWNoYWluQ2FsbGJhY2tcbiAgICAgICAgLndpdGhBcmdzKHsgc291cmNlOiAndXNlcicsIGNvaW46ICd0YnRjJyB9KVxuICAgICAgICAucmV0dXJucyhQcm9taXNlLnJlamVjdCgncGxhaW4gc3RyaW5nIHJlamVjdGlvbicpKTtcblxuICAgICAgYXdhaXQgd2FsbGV0c1xuICAgICAgICAuZ2VuZXJhdGVXYWxsZXRXaXRoRXh0ZXJuYWxTaWduZXIoe1xuICAgICAgICAgIGxhYmVsOiAnRXh0ZXJuYWwgU2lnbmVyIFdhbGxldCcsXG4gICAgICAgICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ZhaWxlZCB0byBjcmVhdGUgdXNlciBrZXljaGFpbjogcGxhaW4gc3RyaW5nIHJlamVjdGlvbicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmb3J3YXJkIGtleVNpZ25hdHVyZXMgdG8gd2FsbGV0IHBhcmFtcyB3aGVuIHByb3ZpZGVkJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qga2V5U2lnbmF0dXJlcyA9IHtcbiAgICAgICAgYmFja3VwOiAnZGVhZGJlZWYwMScsXG4gICAgICAgIGJpdGdvOiAnZGVhZGJlZWYwMicsXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCB3YWxsZXRzLmdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyKHtcbiAgICAgICAgbGFiZWw6ICdFeHRlcm5hbCBTaWduZXIgV2FsbGV0JyxcbiAgICAgICAgZW50ZXJwcmlzZTogJ2VudGVycHJpc2UtaWQnLFxuICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgICBrZXlTaWduYXR1cmVzLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHdhbGxldEJvZHkgPSBzZW5kU3R1Yi5maXJzdENhbGwuYXJnc1swXTtcbiAgICAgIHdhbGxldEJvZHkuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2tleVNpZ25hdHVyZXMnKTtcbiAgICAgIHdhbGxldEJvZHkua2V5U2lnbmF0dXJlcy5zaG91bGQuZGVlcEVxdWFsKGtleVNpZ25hdHVyZXMpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBub3QgaW5jbHVkZSBrZXlTaWduYXR1cmVzIGluIHdhbGxldCBwYXJhbXMgd2hlbiBub3QgcHJvdmlkZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCB3YWxsZXRzLmdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyKHtcbiAgICAgICAgbGFiZWw6ICdFeHRlcm5hbCBTaWduZXIgV2FsbGV0JyxcbiAgICAgICAgZW50ZXJwcmlzZTogJ2VudGVycHJpc2UtaWQnLFxuICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHdhbGxldEJvZHkgPSBzZW5kU3R1Yi5maXJzdENhbGwuYXJnc1swXTtcbiAgICAgIHdhbGxldEJvZHkuc2hvdWxkLm5vdC5oYXZlLnByb3BlcnR5KCdrZXlTaWduYXR1cmVzJyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdnZW5lcmF0ZVdhbGxldCB3aXRoIGNyZWF0ZUtleWNoYWluQ2FsbGJhY2snLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBkZWxlZ2F0ZSB0byBnZW5lcmF0ZVdhbGxldFdpdGhFeHRlcm5hbFNpZ25lcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGdlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyU3R1YiA9IHNpbm9uLnN0dWIod2FsbGV0cywgJ2dlbmVyYXRlV2FsbGV0V2l0aEV4dGVybmFsU2lnbmVyJykucmVzb2x2ZXMoe1xuICAgICAgICByZXNwb25zZVR5cGU6ICdXYWxsZXRXaXRoS2V5Y2hhaW5zJyxcbiAgICAgICAgd2FsbGV0OiBzaW5vbi5jcmVhdGVTdHViSW5zdGFuY2UoV2FsbGV0KSxcbiAgICAgICAgdXNlcktleWNoYWluOiB7IGlkOiAndXNlci1rZXktaWQnLCBwdWI6IHVzZXJQdWIsIHR5cGU6ICdpbmRlcGVuZGVudCcgYXMgY29uc3QgfSxcbiAgICAgICAgYmFja3VwS2V5Y2hhaW46IHsgaWQ6ICdiYWNrdXAta2V5LWlkJywgcHViOiBiYWNrdXBQdWIsIHR5cGU6ICdpbmRlcGVuZGVudCcgYXMgY29uc3QgfSxcbiAgICAgICAgYml0Z29LZXljaGFpbjogeyBpZDogJ2JpdGdvLWtleS1pZCcsIHB1YjogYml0Z29QdWIsIHR5cGU6ICdpbmRlcGVuZGVudCcgYXMgY29uc3QgfSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB3YWxsZXRzLmdlbmVyYXRlV2FsbGV0KHtcbiAgICAgICAgbGFiZWw6ICdEZWxlZ2F0ZWQgV2FsbGV0JyxcbiAgICAgICAgY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayxcbiAgICAgIH0pO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZ2VuZXJhdGVXYWxsZXRXaXRoRXh0ZXJuYWxTaWduZXJTdHViLmNhbGxlZE9uY2UsIHRydWUpO1xuICAgICAgZ2VuZXJhdGVXYWxsZXRXaXRoRXh0ZXJuYWxTaWduZXJTdHViLmZpcnN0Q2FsbC5hcmdzWzBdLmxhYmVsLnNob3VsZC5lcXVhbCgnRGVsZWdhdGVkIFdhbGxldCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCByZWplY3Qgd2hlbiBjcmVhdGVLZXljaGFpbkNhbGxiYWNrIGlzIGNvbWJpbmVkIHdpdGggcGFzc3BocmFzZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IHdhbGxldHNcbiAgICAgICAgLmdlbmVyYXRlV2FsbGV0KHtcbiAgICAgICAgICBsYWJlbDogJ0ludmFsaWQgV2FsbGV0JyxcbiAgICAgICAgICBwYXNzcGhyYXNlOiAnc2VjcmV0JyxcbiAgICAgICAgICBjcmVhdGVLZXljaGFpbkNhbGxiYWNrLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayBjYW5ub3QgYmUgdXNlZCB3aXRoIHBhc3NwaHJhc2UnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmVqZWN0IHdoZW4gY3JlYXRlS2V5Y2hhaW5DYWxsYmFjayBpcyBjb21iaW5lZCB3aXRoIHVzZXJLZXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhd2FpdCB3YWxsZXRzXG4gICAgICAgIC5nZW5lcmF0ZVdhbGxldCh7XG4gICAgICAgICAgbGFiZWw6ICdJbnZhbGlkIFdhbGxldCcsXG4gICAgICAgICAgdXNlcktleTogJ3hwdWIuLi4nLFxuICAgICAgICAgIGNyZWF0ZUtleWNoYWluQ2FsbGJhY2ssXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdjcmVhdGVLZXljaGFpbkNhbGxiYWNrIGNhbm5vdCBiZSB1c2VkIHdpdGggdXNlcktleScpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|