@bitgo-beta/sdk-api 1.10.1-beta.209 → 1.10.1-beta.2090
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/package.json +23 -27
- package/dist/src/api.d.ts +18 -6
- package/dist/src/api.d.ts.map +1 -1
- package/dist/src/api.js +151 -72
- package/dist/src/bitgoAPI.d.ts +123 -30
- package/dist/src/bitgoAPI.d.ts.map +1 -1
- package/dist/src/bitgoAPI.js +794 -339
- package/dist/src/decryptV1.d.ts +60 -0
- package/dist/src/decryptV1.d.ts.map +1 -0
- package/dist/src/decryptV1.js +140 -0
- package/dist/src/encrypt.d.ts +37 -6
- package/dist/src/encrypt.d.ts.map +1 -1
- package/dist/src/encrypt.js +171 -15
- package/dist/src/encryptV2.d.ts +67 -0
- package/dist/src/encryptV2.d.ts.map +1 -0
- package/dist/src/encryptV2.js +234 -0
- package/dist/src/encryptionSession.d.ts +63 -0
- package/dist/src/encryptionSession.d.ts.map +1 -0
- package/dist/src/encryptionSession.js +140 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -2
- package/dist/src/types.d.ts +87 -43
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +4 -2
- package/dist/src/util.d.ts +12 -0
- package/dist/src/util.d.ts.map +1 -1
- package/dist/src/util.js +57 -4
- package/dist/src/v1/blockchain.js +25 -12
- package/dist/src/v1/keychains.js +52 -26
- package/dist/src/v1/markets.js +10 -5
- package/dist/src/v1/pendingapproval.d.ts.map +1 -1
- package/dist/src/v1/pendingapproval.js +57 -18
- package/dist/src/v1/pendingapprovals.d.ts.map +1 -1
- package/dist/src/v1/pendingapprovals.js +41 -7
- package/dist/src/v1/signPsbt.d.ts +14 -0
- package/dist/src/v1/signPsbt.d.ts.map +1 -0
- package/dist/src/v1/signPsbt.js +69 -0
- package/dist/src/v1/transactionBuilder.js +221 -91
- package/dist/src/v1/travelRule.js +125 -66
- package/dist/src/v1/verifyAddress.d.ts +6 -0
- package/dist/src/v1/verifyAddress.d.ts.map +1 -0
- package/dist/src/v1/verifyAddress.js +50 -0
- package/dist/src/v1/wallet.d.ts.map +1 -1
- package/dist/src/v1/wallet.js +498 -230
- package/dist/src/v1/wallets.js +118 -53
- package/dist/test/unit/api.d.ts +2 -0
- package/dist/test/unit/api.d.ts.map +1 -0
- package/dist/test/unit/api.js +331 -0
- package/dist/test/unit/bitgoAPI.d.ts +2 -0
- package/dist/test/unit/bitgoAPI.d.ts.map +1 -0
- package/dist/test/unit/bitgoAPI.js +1339 -0
- package/dist/test/unit/decryptV1.browser.d.ts +2 -0
- package/dist/test/unit/decryptV1.browser.d.ts.map +1 -0
- package/dist/test/unit/decryptV1.browser.js +133 -0
- package/dist/test/unit/decryptV1.d.ts +2 -0
- package/dist/test/unit/decryptV1.d.ts.map +1 -0
- package/dist/test/unit/decryptV1.js +230 -0
- package/dist/test/unit/encrypt.d.ts +2 -0
- package/dist/test/unit/encrypt.d.ts.map +1 -0
- package/dist/test/unit/encrypt.js +544 -0
- package/dist/test/unit/fixtures/keycard.d.ts +25 -0
- package/dist/test/unit/fixtures/keycard.d.ts.map +1 -0
- package/dist/test/unit/fixtures/keycard.js +28 -0
- package/dist/test/unit/hmacStrategy.d.ts +2 -0
- package/dist/test/unit/hmacStrategy.d.ts.map +1 -0
- package/dist/test/unit/hmacStrategy.js +136 -0
- package/dist/test/unit/serializeRequestDataIntegration.d.ts +2 -0
- package/dist/test/unit/serializeRequestDataIntegration.d.ts.map +1 -0
- package/dist/test/unit/serializeRequestDataIntegration.js +115 -0
- package/dist/test/unit/utils.d.ts +2 -0
- package/dist/test/unit/utils.d.ts.map +1 -0
- package/dist/test/unit/utils.js +65 -0
- package/dist/test/unit/v1/fixtures/accelerate-tx.d.ts +4 -0
- package/dist/test/unit/v1/fixtures/accelerate-tx.d.ts.map +1 -0
- package/dist/test/unit/v1/fixtures/accelerate-tx.js +53 -0
- package/dist/test/unit/v1/fixtures/index.d.ts +3 -0
- package/dist/test/unit/v1/fixtures/index.d.ts.map +1 -0
- package/dist/test/unit/v1/fixtures/index.js +24 -0
- package/dist/test/unit/v1/keychains.d.ts +2 -0
- package/dist/test/unit/v1/keychains.d.ts.map +1 -0
- package/dist/test/unit/v1/keychains.js +114 -0
- package/dist/test/unit/v1/signPsbt.d.ts +2 -0
- package/dist/test/unit/v1/signPsbt.d.ts.map +1 -0
- package/dist/test/unit/v1/signPsbt.js +53 -0
- package/dist/test/unit/v1/travelRule.d.ts +2 -0
- package/dist/test/unit/v1/travelRule.d.ts.map +1 -0
- package/dist/test/unit/v1/travelRule.js +125 -0
- package/dist/test/unit/v1/wallet.d.ts +2 -0
- package/dist/test/unit/v1/wallet.d.ts.map +1 -0
- package/dist/test/unit/v1/wallet.js +1717 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +23 -27
- package/.eslintignore +0 -5
- package/CHANGELOG.md +0 -639
- package/dist/web/main.js +0 -2
- package/dist/web/main.js.LICENSE.txt +0 -110
|
@@ -0,0 +1,544 @@
|
|
|
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 assert_1 = __importDefault(require("assert"));
|
|
7
|
+
const crypto_1 = require("crypto");
|
|
8
|
+
const src_1 = require("../../src");
|
|
9
|
+
const bitgoAPI_1 = require("../../src/bitgoAPI");
|
|
10
|
+
const subtle = globalThis.crypto?.subtle ?? crypto_1.webcrypto.subtle;
|
|
11
|
+
/**
|
|
12
|
+
* Build an HKDF-only v2 envelope independently of the SDK. Nothing in the SDK emits this
|
|
13
|
+
* shape yet -- senders start doing so in WCN-2504 -- so the wire format is pinned here.
|
|
14
|
+
* The info string must stay in sync with HKDF_ONLY_INFO in encryptV2.ts.
|
|
15
|
+
*/
|
|
16
|
+
async function makeHkdfOnlyEnvelope(password, plaintext, opts = {}) {
|
|
17
|
+
const hkdfSalt = opts.hkdfSalt ?? new Uint8Array((0, crypto_1.randomBytes)(32));
|
|
18
|
+
const iv = new Uint8Array((0, crypto_1.randomBytes)(12));
|
|
19
|
+
const ikm = await subtle.importKey('raw', new TextEncoder().encode(password), 'HKDF', false, ['deriveKey']);
|
|
20
|
+
const aesKey = await subtle.deriveKey({ name: 'HKDF', hash: 'SHA-256', salt: hkdfSalt, info: new TextEncoder().encode('bitgo-v2-hkdf') }, ikm, { name: 'AES-GCM', length: 256 }, false, ['encrypt']);
|
|
21
|
+
const params = { name: 'AES-GCM', iv, tagLength: 128 };
|
|
22
|
+
if (opts.adata)
|
|
23
|
+
params.additionalData = new TextEncoder().encode(opts.adata);
|
|
24
|
+
const ct = await subtle.encrypt(params, aesKey, new TextEncoder().encode(plaintext));
|
|
25
|
+
const envelope = {
|
|
26
|
+
v: 2,
|
|
27
|
+
hkdfSalt: Buffer.from(hkdfSalt).toString('base64'),
|
|
28
|
+
iv: Buffer.from(iv).toString('base64'),
|
|
29
|
+
ct: Buffer.from(new Uint8Array(ct)).toString('base64'),
|
|
30
|
+
};
|
|
31
|
+
if (opts.adata)
|
|
32
|
+
envelope.adata = opts.adata;
|
|
33
|
+
return JSON.stringify(envelope);
|
|
34
|
+
}
|
|
35
|
+
describe('encryption methods tests', () => {
|
|
36
|
+
describe('encrypt (async, default v2)', () => {
|
|
37
|
+
const password = 'myPassword';
|
|
38
|
+
const plaintext = 'Hello, World!';
|
|
39
|
+
it('encrypts the plaintext with the given password', async () => {
|
|
40
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext);
|
|
41
|
+
(0, assert_1.default)(ciphertext !== plaintext, 'ciphertext should not be equal to plaintext');
|
|
42
|
+
});
|
|
43
|
+
it('produces a v2 envelope by default', async () => {
|
|
44
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext);
|
|
45
|
+
const envelope = JSON.parse(ciphertext);
|
|
46
|
+
assert_1.default.strictEqual(envelope.v, 2);
|
|
47
|
+
});
|
|
48
|
+
it('returns a different ciphertext for the same plaintext and password', async () => {
|
|
49
|
+
const ciphertext1 = await (0, src_1.encrypt)(password, plaintext);
|
|
50
|
+
const ciphertext2 = await (0, src_1.encrypt)(password, plaintext);
|
|
51
|
+
(0, assert_1.default)(ciphertext1 !== ciphertext2, 'ciphertexts should not be equal');
|
|
52
|
+
});
|
|
53
|
+
it('forwards adata to the v2 envelope', async () => {
|
|
54
|
+
const adata = 'txhash:m/0/1';
|
|
55
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext, { adata });
|
|
56
|
+
const envelope = JSON.parse(ciphertext);
|
|
57
|
+
assert_1.default.strictEqual(envelope.adata, adata);
|
|
58
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ciphertext), plaintext);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('encrypt with encryptionVersion: 1 (legacy v1)', () => {
|
|
62
|
+
const password = 'myPassword';
|
|
63
|
+
const plaintext = 'Hello, World!';
|
|
64
|
+
it('produces a v1 envelope that decrypts back via decrypt', async () => {
|
|
65
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
66
|
+
const envelope = JSON.parse(ciphertext);
|
|
67
|
+
assert_1.default.notStrictEqual(envelope.v, 2, 'encryptionVersion 1 should not produce a v2 envelope');
|
|
68
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ciphertext), plaintext);
|
|
69
|
+
});
|
|
70
|
+
it('throws an error if the salt length is not 8 bytes', async () => {
|
|
71
|
+
await assert_1.default.rejects(() => (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1, salt: (0, crypto_1.randomBytes)(4) }), /salt must be 8 bytes/);
|
|
72
|
+
});
|
|
73
|
+
it('throws an error if the iv length is not 16 bytes', async () => {
|
|
74
|
+
await assert_1.default.rejects(() => (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1, iv: (0, crypto_1.randomBytes)(4) }), /iv must be 16 bytes/);
|
|
75
|
+
});
|
|
76
|
+
it('forwards salt and iv options for deterministic v1 output', async () => {
|
|
77
|
+
const salt = (0, crypto_1.randomBytes)(8);
|
|
78
|
+
const iv = (0, crypto_1.randomBytes)(16);
|
|
79
|
+
const ct1 = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1, salt, iv });
|
|
80
|
+
const ct2 = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1, salt, iv });
|
|
81
|
+
assert_1.default.strictEqual(ct1, ct2);
|
|
82
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ct1), plaintext);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('decrypt (auto-detect v1/v2)', () => {
|
|
86
|
+
const password = 'myPassword';
|
|
87
|
+
const plaintext = 'Hello, World!';
|
|
88
|
+
it('decrypts default v2 data', async () => {
|
|
89
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext);
|
|
90
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ciphertext), plaintext);
|
|
91
|
+
});
|
|
92
|
+
it('decrypts legacy v1 data', async () => {
|
|
93
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
94
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ciphertext), plaintext);
|
|
95
|
+
});
|
|
96
|
+
it('throws on wrong password for v1', async () => {
|
|
97
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
98
|
+
await assert_1.default.rejects(() => (0, src_1.decrypt)('wrongPassword', ciphertext));
|
|
99
|
+
});
|
|
100
|
+
it('throws on wrong password for v2', async () => {
|
|
101
|
+
const ciphertext = await (0, src_1.encrypt)(password, plaintext);
|
|
102
|
+
await assert_1.default.rejects(() => (0, src_1.decrypt)('wrongPassword', ciphertext));
|
|
103
|
+
});
|
|
104
|
+
it('throws on invalid JSON input', async () => {
|
|
105
|
+
await assert_1.default.rejects(() => (0, src_1.decrypt)(password, 'not-json'), /ciphertext is not valid JSON/);
|
|
106
|
+
});
|
|
107
|
+
it('wrong password on v2 data does not fall through to v1 decrypt', async () => {
|
|
108
|
+
const v2ct = await (0, src_1.encryptV2)(password, plaintext, { memorySize: 1024, iterations: 1, parallelism: 1 });
|
|
109
|
+
let caughtError;
|
|
110
|
+
try {
|
|
111
|
+
await (0, src_1.decrypt)('wrong', v2ct);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
caughtError = e;
|
|
115
|
+
}
|
|
116
|
+
assert_1.default.ok(caughtError, 'should have thrown');
|
|
117
|
+
assert_1.default.ok(!caughtError.message?.includes('sjcl'), 'error must not be from SJCL');
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe('v2 encrypt/decrypt (Argon2id + AES-256-GCM)', () => {
|
|
121
|
+
const password = 'myPassword';
|
|
122
|
+
const plaintext = 'Hello, World!';
|
|
123
|
+
it('encrypts and decrypts round-trip', async () => {
|
|
124
|
+
const ciphertext = await (0, src_1.encryptV2)(password, plaintext);
|
|
125
|
+
const decrypted = await (0, src_1.decryptV2)(password, ciphertext);
|
|
126
|
+
assert_1.default.strictEqual(decrypted, plaintext);
|
|
127
|
+
});
|
|
128
|
+
it('produces a valid v2 envelope', async () => {
|
|
129
|
+
const ciphertext = await (0, src_1.encryptV2)(password, plaintext);
|
|
130
|
+
const envelope = JSON.parse(ciphertext);
|
|
131
|
+
assert_1.default.strictEqual(envelope.v, 2);
|
|
132
|
+
assert_1.default.strictEqual(envelope.m, 65536);
|
|
133
|
+
assert_1.default.strictEqual(envelope.t, 3);
|
|
134
|
+
assert_1.default.strictEqual(envelope.p, 4);
|
|
135
|
+
assert_1.default.ok(envelope.salt, 'envelope must have salt');
|
|
136
|
+
assert_1.default.ok(envelope.iv, 'envelope must have iv');
|
|
137
|
+
assert_1.default.ok(envelope.ct, 'envelope must have ct');
|
|
138
|
+
});
|
|
139
|
+
it('returns different ciphertext for the same plaintext and password', async () => {
|
|
140
|
+
const ct1 = await (0, src_1.encryptV2)(password, plaintext);
|
|
141
|
+
const ct2 = await (0, src_1.encryptV2)(password, plaintext);
|
|
142
|
+
assert_1.default.notStrictEqual(ct1, ct2);
|
|
143
|
+
});
|
|
144
|
+
it('decrypts with custom Argon2id parameters', async () => {
|
|
145
|
+
const ciphertext = await (0, src_1.encryptV2)(password, plaintext, {
|
|
146
|
+
memorySize: 1024,
|
|
147
|
+
iterations: 1,
|
|
148
|
+
parallelism: 1,
|
|
149
|
+
});
|
|
150
|
+
const envelope = JSON.parse(ciphertext);
|
|
151
|
+
assert_1.default.strictEqual(envelope.m, 1024);
|
|
152
|
+
assert_1.default.strictEqual(envelope.t, 1);
|
|
153
|
+
assert_1.default.strictEqual(envelope.p, 1);
|
|
154
|
+
const decrypted = await (0, src_1.decryptV2)(password, ciphertext);
|
|
155
|
+
assert_1.default.strictEqual(decrypted, plaintext);
|
|
156
|
+
});
|
|
157
|
+
it('throws on wrong password', async () => {
|
|
158
|
+
const ciphertext = await (0, src_1.encryptV2)(password, plaintext);
|
|
159
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)('wrongPassword', ciphertext));
|
|
160
|
+
});
|
|
161
|
+
it('throws on invalid JSON', async () => {
|
|
162
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, 'not-json'), /invalid JSON envelope/);
|
|
163
|
+
});
|
|
164
|
+
it('throws on wrong envelope version', async () => {
|
|
165
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify({ v: 99 })), /invalid envelope/);
|
|
166
|
+
});
|
|
167
|
+
it('throws on invalid salt length', async () => {
|
|
168
|
+
await assert_1.default.rejects(() => (0, src_1.encryptV2)(password, plaintext, { salt: new Uint8Array(8) }), /salt must be 16 bytes/);
|
|
169
|
+
});
|
|
170
|
+
it('throws on invalid iv length', async () => {
|
|
171
|
+
await assert_1.default.rejects(() => (0, src_1.encryptV2)(password, plaintext, { iv: new Uint8Array(8) }), /iv must be 12 bytes/);
|
|
172
|
+
});
|
|
173
|
+
it('encrypts and decrypts with adata (AAD)', async () => {
|
|
174
|
+
const adata = 'txhash:m/0/1';
|
|
175
|
+
const ciphertext = await (0, src_1.encryptV2)(password, plaintext, { adata });
|
|
176
|
+
const envelope = JSON.parse(ciphertext);
|
|
177
|
+
assert_1.default.strictEqual(envelope.adata, adata);
|
|
178
|
+
const decrypted = await (0, src_1.decryptV2)(password, ciphertext);
|
|
179
|
+
assert_1.default.strictEqual(decrypted, plaintext);
|
|
180
|
+
});
|
|
181
|
+
it('adata mismatch causes GCM decryption failure', async () => {
|
|
182
|
+
const ciphertext = await (0, src_1.encryptV2)(password, plaintext, { adata: 'context-A' });
|
|
183
|
+
const envelope = JSON.parse(ciphertext);
|
|
184
|
+
envelope.adata = 'context-B';
|
|
185
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify(envelope)), /operation-specific reason|incorrect/i);
|
|
186
|
+
});
|
|
187
|
+
it('adata: undefined is equivalent to omitting adata', async () => {
|
|
188
|
+
const fixedOpts = {
|
|
189
|
+
memorySize: 1024,
|
|
190
|
+
iterations: 1,
|
|
191
|
+
parallelism: 1,
|
|
192
|
+
salt: new Uint8Array(16).fill(0xaa),
|
|
193
|
+
iv: new Uint8Array(12).fill(0xbb),
|
|
194
|
+
};
|
|
195
|
+
const withUndefined = await (0, src_1.encryptV2)(password, plaintext, { ...fixedOpts, adata: undefined });
|
|
196
|
+
const withOmitted = await (0, src_1.encryptV2)(password, plaintext, fixedOpts);
|
|
197
|
+
assert_1.default.strictEqual(withUndefined, withOmitted);
|
|
198
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV2)(password, withUndefined), plaintext);
|
|
199
|
+
});
|
|
200
|
+
it('ciphertext bound to enterprise-A cannot be re-attributed to enterprise-B', async () => {
|
|
201
|
+
const prv = 'xprv-private-key-bytes';
|
|
202
|
+
const prfKey = 'prf-derived-key';
|
|
203
|
+
const ct = await (0, src_1.encryptV2)(prfKey, prv, { adata: 'enterprise-A' });
|
|
204
|
+
// Attacker moves blob to enterprise-B by altering the stored adata field
|
|
205
|
+
const envelope = JSON.parse(ct);
|
|
206
|
+
envelope.adata = 'enterprise-B';
|
|
207
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(prfKey, JSON.stringify(envelope)));
|
|
208
|
+
});
|
|
209
|
+
it('v1 and v2 are independent (v1 data does not decrypt with v2)', async () => {
|
|
210
|
+
const v1ct = await (0, src_1.encrypt)(password, plaintext, { encryptionVersion: 1 });
|
|
211
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, v1ct), /invalid envelope/);
|
|
212
|
+
});
|
|
213
|
+
it('rejects envelope with memorySize exceeding max', async () => {
|
|
214
|
+
const envelope = { v: 2, m: 999999999, t: 3, p: 4, salt: 'AAAA', iv: 'AAAA', ct: 'AAAA' };
|
|
215
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify(envelope)), /invalid envelope/);
|
|
216
|
+
});
|
|
217
|
+
it('rejects envelope with iterations exceeding max', async () => {
|
|
218
|
+
const envelope = { v: 2, m: 65536, t: 100, p: 4, salt: 'AAAA', iv: 'AAAA', ct: 'AAAA' };
|
|
219
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify(envelope)), /invalid envelope/);
|
|
220
|
+
});
|
|
221
|
+
it('rejects envelope with parallelism exceeding max', async () => {
|
|
222
|
+
const envelope = { v: 2, m: 65536, t: 3, p: 100, salt: 'AAAA', iv: 'AAAA', ct: 'AAAA' };
|
|
223
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify(envelope)), /invalid envelope/);
|
|
224
|
+
});
|
|
225
|
+
it('rejects envelope with zero-valued parameters', async () => {
|
|
226
|
+
const envelope = { v: 2, m: 0, t: 3, p: 4, salt: 'AAAA', iv: 'AAAA', ct: 'AAAA' };
|
|
227
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify(envelope)), /invalid envelope/);
|
|
228
|
+
});
|
|
229
|
+
it('rejects envelope with non-numeric parameter types', async () => {
|
|
230
|
+
const envelope = { v: 2, m: '65536', t: 3, p: 4, salt: 'AAAA', iv: 'AAAA', ct: 'AAAA' };
|
|
231
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify(envelope)), /invalid envelope/);
|
|
232
|
+
});
|
|
233
|
+
it('rejects envelope with empty salt', async () => {
|
|
234
|
+
const envelope = { v: 2, m: 65536, t: 3, p: 4, salt: '', iv: 'AAAA', ct: 'AAAA' };
|
|
235
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(password, JSON.stringify(envelope)), /invalid envelope/);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
describe('v2 HKDF-only decrypt (high-entropy IKM, no Argon2)', () => {
|
|
239
|
+
// ECDH-shaped input: 256-bit secret as hex, matching encryptPrvForUser.
|
|
240
|
+
const highEntropyPassword = Buffer.alloc(32, 0xab).toString('hex');
|
|
241
|
+
const plaintext = 'shared-wallet-prv';
|
|
242
|
+
it('decrypts an HKDF-only envelope via decryptV2', async () => {
|
|
243
|
+
const ciphertext = await makeHkdfOnlyEnvelope(highEntropyPassword, plaintext);
|
|
244
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV2)(highEntropyPassword, ciphertext), plaintext);
|
|
245
|
+
});
|
|
246
|
+
it('decrypts an HKDF-only envelope via decrypt auto-detect', async () => {
|
|
247
|
+
const ciphertext = await makeHkdfOnlyEnvelope(highEntropyPassword, plaintext);
|
|
248
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(highEntropyPassword, ciphertext), plaintext);
|
|
249
|
+
});
|
|
250
|
+
it('decrypts a fixed HKDF-only envelope (wire format is pinned)', async () => {
|
|
251
|
+
const ciphertext = await makeHkdfOnlyEnvelope(highEntropyPassword, plaintext, {
|
|
252
|
+
hkdfSalt: new Uint8Array(32).fill(0xcd),
|
|
253
|
+
});
|
|
254
|
+
const envelope = JSON.parse(ciphertext);
|
|
255
|
+
assert_1.default.strictEqual(envelope.v, 2);
|
|
256
|
+
assert_1.default.ok(envelope.hkdfSalt, 'must have hkdf salt');
|
|
257
|
+
assert_1.default.strictEqual(envelope.m, undefined);
|
|
258
|
+
assert_1.default.strictEqual(envelope.t, undefined);
|
|
259
|
+
assert_1.default.strictEqual(envelope.p, undefined);
|
|
260
|
+
assert_1.default.strictEqual(envelope.salt, undefined);
|
|
261
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV2)(highEntropyPassword, ciphertext), plaintext);
|
|
262
|
+
});
|
|
263
|
+
it('throws on wrong password', async () => {
|
|
264
|
+
const ciphertext = await makeHkdfOnlyEnvelope(highEntropyPassword, plaintext);
|
|
265
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)('wrong-password', ciphertext));
|
|
266
|
+
});
|
|
267
|
+
it('decrypts an HKDF-only envelope carrying adata', async () => {
|
|
268
|
+
const adata = 'wallet-share';
|
|
269
|
+
const ciphertext = await makeHkdfOnlyEnvelope(highEntropyPassword, plaintext, { adata });
|
|
270
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV2)(highEntropyPassword, ciphertext), plaintext);
|
|
271
|
+
});
|
|
272
|
+
it('adata mismatch causes GCM decryption failure', async () => {
|
|
273
|
+
const ciphertext = await makeHkdfOnlyEnvelope(highEntropyPassword, plaintext, { adata: 'context-A' });
|
|
274
|
+
const envelope = JSON.parse(ciphertext);
|
|
275
|
+
envelope.adata = 'context-B';
|
|
276
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(highEntropyPassword, JSON.stringify(envelope)), /operation-specific reason|incorrect/i);
|
|
277
|
+
});
|
|
278
|
+
it('rejects mixed envelopes (hkdfSalt plus incomplete Argon2 params)', async () => {
|
|
279
|
+
const envelope = { v: 2, m: 1024, hkdfSalt: 'AAAA', iv: 'AAAA', ct: 'AAAA' };
|
|
280
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(highEntropyPassword, JSON.stringify(envelope)), /invalid envelope/);
|
|
281
|
+
});
|
|
282
|
+
it('rejects envelopes with neither Argon2 params nor hkdfSalt', async () => {
|
|
283
|
+
const envelope = { v: 2, iv: 'AAAA', ct: 'AAAA' };
|
|
284
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)(highEntropyPassword, JSON.stringify(envelope)), /invalid envelope/);
|
|
285
|
+
});
|
|
286
|
+
it('Argon2 and HKDF-only envelopes stay distinguishable and both decrypt', async () => {
|
|
287
|
+
const argon2ct = await (0, src_1.encryptV2)(highEntropyPassword, plaintext, {
|
|
288
|
+
memorySize: 1024,
|
|
289
|
+
iterations: 1,
|
|
290
|
+
parallelism: 1,
|
|
291
|
+
});
|
|
292
|
+
const hkdfct = await makeHkdfOnlyEnvelope(highEntropyPassword, plaintext);
|
|
293
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV2)(highEntropyPassword, argon2ct), plaintext);
|
|
294
|
+
assert_1.default.strictEqual(await (0, src_1.decryptV2)(highEntropyPassword, hkdfct), plaintext);
|
|
295
|
+
const argon2env = JSON.parse(argon2ct);
|
|
296
|
+
const hkdfenv = JSON.parse(hkdfct);
|
|
297
|
+
assert_1.default.ok(argon2env.salt);
|
|
298
|
+
assert_1.default.ok(hkdfenv.hkdfSalt);
|
|
299
|
+
assert_1.default.strictEqual(argon2env.hkdfSalt, undefined);
|
|
300
|
+
assert_1.default.strictEqual(hkdfenv.salt, undefined);
|
|
301
|
+
});
|
|
302
|
+
it('no SDK encrypt path emits HKDF-only envelopes yet', async () => {
|
|
303
|
+
const fromEncrypt = JSON.parse(await (0, src_1.encrypt)(highEntropyPassword, plaintext));
|
|
304
|
+
const fromEncryptV2 = JSON.parse(await (0, src_1.encryptV2)(highEntropyPassword, plaintext));
|
|
305
|
+
for (const envelope of [fromEncrypt, fromEncryptV2]) {
|
|
306
|
+
assert_1.default.strictEqual(envelope.v, 2);
|
|
307
|
+
assert_1.default.ok(envelope.m, 'must still emit Argon2 params');
|
|
308
|
+
assert_1.default.ok(envelope.t);
|
|
309
|
+
assert_1.default.ok(envelope.p);
|
|
310
|
+
assert_1.default.ok(envelope.salt);
|
|
311
|
+
assert_1.default.strictEqual(envelope.hkdfSalt, undefined);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
describe('EncryptionSession (HKDF caching)', () => {
|
|
316
|
+
const opts = { memorySize: 1024, iterations: 1, parallelism: 1 };
|
|
317
|
+
const password = 'test-password';
|
|
318
|
+
const plaintext = 'hello session';
|
|
319
|
+
it('session-produced envelope contains salt and hkdfSalt', async () => {
|
|
320
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
321
|
+
const ct = await session.encrypt(plaintext);
|
|
322
|
+
session.destroy();
|
|
323
|
+
const envelope = JSON.parse(ct);
|
|
324
|
+
assert_1.default.strictEqual(envelope.v, 2);
|
|
325
|
+
assert_1.default.ok(envelope.salt, 'must have argon2 salt');
|
|
326
|
+
assert_1.default.ok(envelope.hkdfSalt, 'must have hkdf salt');
|
|
327
|
+
assert_1.default.ok(envelope.iv, 'must have iv');
|
|
328
|
+
assert_1.default.ok(envelope.ct, 'must have ciphertext');
|
|
329
|
+
});
|
|
330
|
+
it('session round-trip via session.decrypt', async () => {
|
|
331
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
332
|
+
const ct = await session.encrypt(plaintext);
|
|
333
|
+
const result = await session.decrypt(ct);
|
|
334
|
+
session.destroy();
|
|
335
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
336
|
+
});
|
|
337
|
+
it('session envelope can be decrypted standalone via decryptV2', async () => {
|
|
338
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
339
|
+
const ct = await session.encrypt(plaintext);
|
|
340
|
+
session.destroy();
|
|
341
|
+
const result = await (0, src_1.decryptV2)(password, ct);
|
|
342
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
343
|
+
});
|
|
344
|
+
it('session envelope can be decrypted via decrypt', async () => {
|
|
345
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
346
|
+
const ct = await session.encrypt(plaintext);
|
|
347
|
+
session.destroy();
|
|
348
|
+
const result = await (0, src_1.decrypt)(password, ct);
|
|
349
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
350
|
+
});
|
|
351
|
+
it('multiple encrypts produce different hkdfSalt values', async () => {
|
|
352
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
353
|
+
const ct1 = await session.encrypt(plaintext);
|
|
354
|
+
const ct2 = await session.encrypt(plaintext);
|
|
355
|
+
session.destroy();
|
|
356
|
+
const e1 = JSON.parse(ct1);
|
|
357
|
+
const e2 = JSON.parse(ct2);
|
|
358
|
+
assert_1.default.notStrictEqual(e1.hkdfSalt, e2.hkdfSalt);
|
|
359
|
+
});
|
|
360
|
+
it('all session encrypts share the same argon2 salt', async () => {
|
|
361
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
362
|
+
const ct1 = await session.encrypt(plaintext);
|
|
363
|
+
const ct2 = await session.encrypt(plaintext);
|
|
364
|
+
session.destroy();
|
|
365
|
+
const e1 = JSON.parse(ct1);
|
|
366
|
+
const e2 = JSON.parse(ct2);
|
|
367
|
+
assert_1.default.strictEqual(e1.salt, e2.salt);
|
|
368
|
+
});
|
|
369
|
+
it('wrong password rejected by decryptV2', async () => {
|
|
370
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
371
|
+
const ct = await session.encrypt(plaintext);
|
|
372
|
+
session.destroy();
|
|
373
|
+
await assert_1.default.rejects(() => (0, src_1.decryptV2)('wrong-password', ct));
|
|
374
|
+
});
|
|
375
|
+
it('destroy prevents further encrypt calls', async () => {
|
|
376
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
377
|
+
session.destroy();
|
|
378
|
+
await assert_1.default.rejects(() => session.encrypt(plaintext), /destroyed/);
|
|
379
|
+
});
|
|
380
|
+
it('destroy prevents further decrypt calls', async () => {
|
|
381
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
382
|
+
const ct = await session.encrypt(plaintext);
|
|
383
|
+
session.destroy();
|
|
384
|
+
await assert_1.default.rejects(() => session.decrypt(ct), /destroyed/);
|
|
385
|
+
});
|
|
386
|
+
it('session rejects envelopes from a different session', async () => {
|
|
387
|
+
const session1 = await (0, src_1.createEncryptionSession)(password, opts);
|
|
388
|
+
const session2 = await (0, src_1.createEncryptionSession)(password, opts);
|
|
389
|
+
const ct = await session1.encrypt(plaintext);
|
|
390
|
+
await assert_1.default.rejects(() => session2.decrypt(ct), /not encrypted with this session/);
|
|
391
|
+
session1.destroy();
|
|
392
|
+
session2.destroy();
|
|
393
|
+
});
|
|
394
|
+
it('session encrypt with adata round-trip', async () => {
|
|
395
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
396
|
+
const adata = 'txhash:m/0/1:round1';
|
|
397
|
+
const ct = await session.encrypt(plaintext, adata);
|
|
398
|
+
const envelope = JSON.parse(ct);
|
|
399
|
+
assert_1.default.strictEqual(envelope.adata, adata);
|
|
400
|
+
const result = await session.decrypt(ct);
|
|
401
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
402
|
+
session.destroy();
|
|
403
|
+
});
|
|
404
|
+
it('session encrypt with adata is decryptable via decryptV2', async () => {
|
|
405
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
406
|
+
const ct = await session.encrypt(plaintext, 'context-binding');
|
|
407
|
+
session.destroy();
|
|
408
|
+
const result = await (0, src_1.decryptV2)(password, ct);
|
|
409
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
410
|
+
});
|
|
411
|
+
it('session adata mismatch causes GCM failure', async () => {
|
|
412
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
413
|
+
const ct = await session.encrypt(plaintext, 'original-context');
|
|
414
|
+
const envelope = JSON.parse(ct);
|
|
415
|
+
envelope.adata = 'tampered-context';
|
|
416
|
+
await assert_1.default.rejects(() => session.decrypt(JSON.stringify(envelope)), /operation-specific reason|incorrect/i);
|
|
417
|
+
session.destroy();
|
|
418
|
+
});
|
|
419
|
+
it('session rejects standard v2 envelopes (no hkdfSalt)', async () => {
|
|
420
|
+
const v2ct = await (0, src_1.encryptV2)(password, plaintext, opts);
|
|
421
|
+
const session = await (0, src_1.createEncryptionSession)(password, opts);
|
|
422
|
+
await assert_1.default.rejects(() => session.decrypt(v2ct), /use decryptV2/);
|
|
423
|
+
session.destroy();
|
|
424
|
+
});
|
|
425
|
+
it('Argon2id params are stored in envelope', async () => {
|
|
426
|
+
const session = await (0, src_1.createEncryptionSession)(password, { memorySize: 2048, iterations: 2, parallelism: 2 });
|
|
427
|
+
const ct = await session.encrypt(plaintext);
|
|
428
|
+
session.destroy();
|
|
429
|
+
const envelope = JSON.parse(ct);
|
|
430
|
+
assert_1.default.strictEqual(envelope.m, 2048);
|
|
431
|
+
assert_1.default.strictEqual(envelope.t, 2);
|
|
432
|
+
assert_1.default.strictEqual(envelope.p, 2);
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
describe('createEncryptionSession with encryptionVersion=1 (v1 shim)', () => {
|
|
436
|
+
const password = 'v1-shim-password';
|
|
437
|
+
const plaintext = 'legacy consumer data';
|
|
438
|
+
it('produces v1 (SJCL) envelopes', async () => {
|
|
439
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
440
|
+
const ct = await session.encrypt(plaintext);
|
|
441
|
+
const envelope = JSON.parse(ct);
|
|
442
|
+
// v1 SJCL envelopes carry iter/mode/ks fields; no hkdfSalt/argon2 params
|
|
443
|
+
assert_1.default.ok(envelope.iter, 'v1 envelope must have iter');
|
|
444
|
+
assert_1.default.ok(envelope.mode, 'v1 envelope must have mode');
|
|
445
|
+
assert_1.default.notStrictEqual(envelope.v, 2);
|
|
446
|
+
assert_1.default.strictEqual(envelope.hkdfSalt, undefined);
|
|
447
|
+
session.destroy();
|
|
448
|
+
});
|
|
449
|
+
it('round-trips via session.decrypt', async () => {
|
|
450
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
451
|
+
const ct = await session.encrypt(plaintext);
|
|
452
|
+
const rt = await session.decrypt(ct);
|
|
453
|
+
assert_1.default.strictEqual(rt, plaintext);
|
|
454
|
+
session.destroy();
|
|
455
|
+
});
|
|
456
|
+
it('produced envelopes decrypt via the standard decrypt() with the same password', async () => {
|
|
457
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
458
|
+
const ct = await session.encrypt(plaintext);
|
|
459
|
+
session.destroy();
|
|
460
|
+
const rt = await (0, src_1.decrypt)(password, ct);
|
|
461
|
+
assert_1.default.strictEqual(rt, plaintext);
|
|
462
|
+
});
|
|
463
|
+
it('multiple encrypts produce distinct ciphertexts (per-call SJCL salt/iv)', async () => {
|
|
464
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
465
|
+
const ct1 = await session.encrypt(plaintext);
|
|
466
|
+
const ct2 = await session.encrypt(plaintext);
|
|
467
|
+
assert_1.default.notStrictEqual(ct1, ct2);
|
|
468
|
+
const e1 = JSON.parse(ct1);
|
|
469
|
+
const e2 = JSON.parse(ct2);
|
|
470
|
+
// v1 salts are per-call, so they must differ across envelopes even under same password
|
|
471
|
+
assert_1.default.notStrictEqual(e1.salt, e2.salt);
|
|
472
|
+
session.destroy();
|
|
473
|
+
});
|
|
474
|
+
it('forwards adata to the v1 envelope', async () => {
|
|
475
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
476
|
+
const ct = await session.encrypt(plaintext, 'enterprise-id-42');
|
|
477
|
+
const envelope = JSON.parse(ct);
|
|
478
|
+
assert_1.default.strictEqual(envelope.adata, 'enterprise-id-42');
|
|
479
|
+
session.destroy();
|
|
480
|
+
});
|
|
481
|
+
it('destroy blocks further encrypt calls', async () => {
|
|
482
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
483
|
+
session.destroy();
|
|
484
|
+
await assert_1.default.rejects(() => session.encrypt(plaintext), /destroyed/);
|
|
485
|
+
});
|
|
486
|
+
it('destroy blocks further decrypt calls', async () => {
|
|
487
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
488
|
+
const ct = await session.encrypt(plaintext);
|
|
489
|
+
session.destroy();
|
|
490
|
+
await assert_1.default.rejects(() => session.decrypt(ct), /destroyed/);
|
|
491
|
+
});
|
|
492
|
+
it('destroy is idempotent', async () => {
|
|
493
|
+
const session = await (0, src_1.createEncryptionSession)(password, { encryptionVersion: 1 });
|
|
494
|
+
session.destroy();
|
|
495
|
+
session.destroy();
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
describe('BitGoAPI.encrypt', () => {
|
|
499
|
+
let bitgo;
|
|
500
|
+
const password = 'test-password';
|
|
501
|
+
const plaintext = 'hello encrypt';
|
|
502
|
+
before(() => {
|
|
503
|
+
bitgo = new bitgoAPI_1.BitGoAPI({ env: 'test' });
|
|
504
|
+
});
|
|
505
|
+
it('produces a v2 envelope by default and output is decryptable via decrypt', async () => {
|
|
506
|
+
const ct = await bitgo.encrypt({ input: plaintext, password });
|
|
507
|
+
const envelope = JSON.parse(ct);
|
|
508
|
+
assert_1.default.strictEqual(envelope.v, 2);
|
|
509
|
+
assert_1.default.ok(envelope.salt, 'public encrypt must still emit Argon2 params');
|
|
510
|
+
assert_1.default.strictEqual(envelope.hkdfSalt, undefined);
|
|
511
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ct), plaintext);
|
|
512
|
+
});
|
|
513
|
+
it('produces a v1 envelope when encryptionVersion: 1', async () => {
|
|
514
|
+
const ct = await bitgo.encrypt({ input: plaintext, password, encryptionVersion: 1 });
|
|
515
|
+
const envelope = JSON.parse(ct);
|
|
516
|
+
assert_1.default.notStrictEqual(envelope.v, 2);
|
|
517
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ct), plaintext);
|
|
518
|
+
});
|
|
519
|
+
it('forwards adata to v2 envelope', async () => {
|
|
520
|
+
const adata = 'txhash:m/0/1';
|
|
521
|
+
const ct = await bitgo.encrypt({ input: plaintext, password, adata });
|
|
522
|
+
const envelope = JSON.parse(ct);
|
|
523
|
+
assert_1.default.strictEqual(envelope.adata, adata);
|
|
524
|
+
assert_1.default.strictEqual(await (0, src_1.decrypt)(password, ct), plaintext);
|
|
525
|
+
});
|
|
526
|
+
});
|
|
527
|
+
describe('BitGoAPI.createEncryptionSession', () => {
|
|
528
|
+
let bitgo;
|
|
529
|
+
const password = 'test-password';
|
|
530
|
+
const plaintext = 'hello session';
|
|
531
|
+
before(() => {
|
|
532
|
+
bitgo = new bitgoAPI_1.BitGoAPI({ env: 'test' });
|
|
533
|
+
});
|
|
534
|
+
it('returns working session (encrypt/decrypt/destroy)', async () => {
|
|
535
|
+
const session = await bitgo.createEncryptionSession(password);
|
|
536
|
+
const ct = await session.encrypt(plaintext);
|
|
537
|
+
const result = await session.decrypt(ct);
|
|
538
|
+
assert_1.default.strictEqual(result, plaintext);
|
|
539
|
+
session.destroy();
|
|
540
|
+
await assert_1.default.rejects(() => session.encrypt(plaintext), /destroyed/);
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5jcnlwdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rlc3QvdW5pdC9lbmNyeXB0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsb0RBQTRCO0FBQzVCLG1DQUFnRDtBQUVoRCxtQ0FBd0c7QUFDeEcsaURBQThDO0FBRTlDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxJQUFJLGtCQUFTLENBQUMsTUFBTSxDQUFDO0FBRTdEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsb0JBQW9CLENBQ2pDLFFBQWdCLEVBQ2hCLFNBQWlCLEVBQ2pCLE9BQWtELEVBQUU7SUFFcEQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLFVBQVUsQ0FBQyxJQUFBLG9CQUFXLEVBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRSxNQUFNLEVBQUUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFBLG9CQUFXLEVBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzQyxNQUFNLEdBQUcsR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDO0lBQzVHLE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLFNBQVMsQ0FDbkMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLEVBQUUsRUFDbEcsR0FBRyxFQUNILEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQ2hDLEtBQUssRUFDTCxDQUFDLFNBQVMsQ0FBQyxDQUNaLENBQUM7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QUMsUUFBUSxDQUFDLENBQUM7WUFDOUQsTUFBTSxFQUFFLEdBQUcsTUFBTSxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQzVDLE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN6QyxnQkFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDdEMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLE1BQU0sZ0JBQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUN0RSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyByYW5kb21CeXRlcywgd2ViY3J5cHRvIH0gZnJvbSAnY3J5cHRvJztcblxuaW1wb3J0IHsgZGVjcnlwdCwgZGVjcnlwdFYyLCBlbmNyeXB0LCBlbmNyeXB0VjIsIFYyRW52ZWxvcGUsIGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7IEJpdEdvQVBJIH0gZnJvbSAnLi4vLi4vc3JjL2JpdGdvQVBJJztcblxuY29uc3Qgc3VidGxlID0gZ2xvYmFsVGhpcy5jcnlwdG8/LnN1YnRsZSA/PyB3ZWJjcnlwdG8uc3VidGxlO1xuXG4vKipcbiAqIEJ1aWxkIGFuIEhLREYtb25seSB2MiBlbnZlbG9wZSBpbmRlcGVuZGVudGx5IG9mIHRoZSBTREsuIE5vdGhpbmcgaW4gdGhlIFNESyBlbWl0cyB0aGlzXG4gKiBzaGFwZSB5ZXQgLS0gc2VuZGVycyBzdGFydCBkb2luZyBzbyBpbiBXQ04tMjUwNCAtLSBzbyB0aGUgd2lyZSBmb3JtYXQgaXMgcGlubmVkIGhlcmUuXG4gKiBUaGUgaW5mbyBzdHJpbmcgbXVzdCBzdGF5IGluIHN5bmMgd2l0aCBIS0RGX09OTFlfSU5GTyBpbiBlbmNyeXB0VjIudHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIG1ha2VIa2RmT25seUVudmVsb3BlKFxuICBwYXNzd29yZDogc3RyaW5nLFxuICBwbGFpbnRleHQ6IHN0cmluZyxcbiAgb3B0czogeyBhZGF0YT86IHN0cmluZzsgaGtkZlNhbHQ/OiBVaW50OEFycmF5IH0gPSB7fVxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3QgaGtkZlNhbHQgPSBvcHRzLmhrZGZTYWx0ID8/IG5ldyBVaW50OEFycmF5KHJhbmRvbUJ5dGVzKDMyKSk7XG4gIGNvbnN0IGl2ID0gbmV3IFVpbnQ4QXJyYXkocmFuZG9tQnl0ZXMoMTIpKTtcbiAgY29uc3QgaWttID0gYXdhaXQgc3VidGxlLmltcG9ydEtleSgncmF3JywgbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHBhc3N3b3JkKSwgJ0hLREYnLCBmYWxzZSwgWydkZXJpdmVLZXknXSk7XG4gIGNvbnN0IGFlc0tleSA9IGF3YWl0IHN1YnRsZS5kZXJpdmVLZXkoXG4gICAgeyBuYW1lOiAnSEtERicsIGhhc2g6ICdTSEEtMjU2Jywgc2FsdDogaGtkZlNhbHQsIGluZm86IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZSgnYml0Z28tdjItaGtkZicpIH0sXG4gICAgaWttLFxuICAgIHsgbmFtZTogJ0FFUy1HQ00nLCBsZW5ndGg6IDI1NiB9LFxuICAgIGZhbHNlLFxuICAgIFsnZW5jcnlwdCddXG4gICk7XG4gIGNvbnN0IHBhcmFtczogQWVzR2NtUGFyYW1zID0geyBuYW1lOiAnQUVTLUdDTScsIGl2LCB0YWdMZW5ndGg6IDEyOCB9O1xuICBpZiAob3B0cy5hZGF0YSkgcGFyYW1zLmFkZGl0aW9uYWxEYXRhID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKG9wdHMuYWRhdGEpO1xuICBjb25zdCBjdCA9IGF3YWl0IHN1YnRsZS5lbmNyeXB0KHBhcmFtcywgYWVzS2V5LCBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUocGxhaW50ZXh0KSk7XG5cbiAgY29uc3QgZW52ZWxvcGU6IFYyRW52ZWxvcGUgPSB7XG4gICAgdjogMixcbiAgICBoa2RmU2FsdDogQnVmZmVyLmZyb20oaGtkZlNhbHQpLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICBpdjogQnVmZmVyLmZyb20oaXYpLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICBjdDogQnVmZmVyLmZyb20obmV3IFVpbnQ4QXJyYXkoY3QpKS50b1N0cmluZygnYmFzZTY0JyksXG4gIH07XG4gIGlmIChvcHRzLmFkYXRhKSBlbnZlbG9wZS5hZGF0YSA9IG9wdHMuYWRhdGE7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShlbnZlbG9wZSk7XG59XG5cbmRlc2NyaWJlKCdlbmNyeXB0aW9uIG1ldGhvZHMgdGVzdHMnLCAoKSA9PiB7XG4gIGRlc2NyaWJlKCdlbmNyeXB0IChhc3luYywgZGVmYXVsdCB2MiknLCAoKSA9PiB7XG4gICAgY29uc3QgcGFzc3dvcmQgPSAnbXlQYXNzd29yZCc7XG4gICAgY29uc3QgcGxhaW50ZXh0ID0gJ0hlbGxvLCBXb3JsZCEnO1xuXG4gICAgaXQoJ2VuY3J5cHRzIHRoZSBwbGFpbnRleHQgd2l0aCB0aGUgZ2l2ZW4gcGFzc3dvcmQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0KTtcbiAgICAgIGFzc2VydChjaXBoZXJ0ZXh0ICE9PSBwbGFpbnRleHQsICdjaXBoZXJ0ZXh0IHNob3VsZCBub3QgYmUgZXF1YWwgdG8gcGxhaW50ZXh0Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgncHJvZHVjZXMgYSB2MiBlbnZlbG9wZSBieSBkZWZhdWx0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY2lwaGVydGV4dCA9IGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCk7XG4gICAgICBjb25zdCBlbnZlbG9wZTogVjJFbnZlbG9wZSA9IEpTT04ucGFyc2UoY2lwaGVydGV4dCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUudiwgMik7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBhIGRpZmZlcmVudCBjaXBoZXJ0ZXh0IGZvciB0aGUgc2FtZSBwbGFpbnRleHQgYW5kIHBhc3N3b3JkJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY2lwaGVydGV4dDEgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQpO1xuICAgICAgY29uc3QgY2lwaGVydGV4dDIgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQpO1xuICAgICAgYXNzZXJ0KGNpcGhlcnRleHQxICE9PSBjaXBoZXJ0ZXh0MiwgJ2NpcGhlcnRleHRzIHNob3VsZCBub3QgYmUgZXF1YWwnKTtcbiAgICB9KTtcblxuICAgIGl0KCdmb3J3YXJkcyBhZGF0YSB0byB0aGUgdjIgZW52ZWxvcGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBhZGF0YSA9ICd0eGhhc2g6bS8wLzEnO1xuICAgICAgY29uc3QgY2lwaGVydGV4dCA9IGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBhZGF0YSB9KTtcbiAgICAgIGNvbnN0IGVudmVsb3BlOiBWMkVudmVsb3BlID0gSlNPTi5wYXJzZShjaXBoZXJ0ZXh0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS5hZGF0YSwgYWRhdGEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IGRlY3J5cHQocGFzc3dvcmQsIGNpcGhlcnRleHQpLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZW5jcnlwdCB3aXRoIGVuY3J5cHRpb25WZXJzaW9uOiAxIChsZWdhY3kgdjEpJywgKCkgPT4ge1xuICAgIGNvbnN0IHBhc3N3b3JkID0gJ215UGFzc3dvcmQnO1xuICAgIGNvbnN0IHBsYWludGV4dCA9ICdIZWxsbywgV29ybGQhJztcblxuICAgIGl0KCdwcm9kdWNlcyBhIHYxIGVudmVsb3BlIHRoYXQgZGVjcnlwdHMgYmFjayB2aWEgZGVjcnlwdCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IEpTT04ucGFyc2UoY2lwaGVydGV4dCk7XG4gICAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwoZW52ZWxvcGUudiwgMiwgJ2VuY3J5cHRpb25WZXJzaW9uIDEgc2hvdWxkIG5vdCBwcm9kdWNlIGEgdjIgZW52ZWxvcGUnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhd2FpdCBkZWNyeXB0KHBhc3N3b3JkLCBjaXBoZXJ0ZXh0KSwgcGxhaW50ZXh0KTtcbiAgICB9KTtcblxuICAgIGl0KCd0aHJvd3MgYW4gZXJyb3IgaWYgdGhlIHNhbHQgbGVuZ3RoIGlzIG5vdCA4IGJ5dGVzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICgpID0+IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSwgc2FsdDogcmFuZG9tQnl0ZXMoNCkgfSksXG4gICAgICAgIC9zYWx0IG11c3QgYmUgOCBieXRlcy9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIGFuIGVycm9yIGlmIHRoZSBpdiBsZW5ndGggaXMgbm90IDE2IGJ5dGVzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoXG4gICAgICAgICgpID0+IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSwgaXY6IHJhbmRvbUJ5dGVzKDQpIH0pLFxuICAgICAgICAvaXYgbXVzdCBiZSAxNiBieXRlcy9cbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnZm9yd2FyZHMgc2FsdCBhbmQgaXYgb3B0aW9ucyBmb3IgZGV0ZXJtaW5pc3RpYyB2MSBvdXRwdXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzYWx0ID0gcmFuZG9tQnl0ZXMoOCk7XG4gICAgICBjb25zdCBpdiA9IHJhbmRvbUJ5dGVzKDE2KTtcbiAgICAgIGNvbnN0IGN0MSA9IGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSwgc2FsdCwgaXYgfSk7XG4gICAgICBjb25zdCBjdDIgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEsIHNhbHQsIGl2IH0pO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGN0MSwgY3QyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhd2FpdCBkZWNyeXB0KHBhc3N3b3JkLCBjdDEpLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZGVjcnlwdCAoYXV0by1kZXRlY3QgdjEvdjIpJywgKCkgPT4ge1xuICAgIGNvbnN0IHBhc3N3b3JkID0gJ215UGFzc3dvcmQnO1xuICAgIGNvbnN0IHBsYWludGV4dCA9ICdIZWxsbywgV29ybGQhJztcblxuICAgIGl0KCdkZWNyeXB0cyBkZWZhdWx0IHYyIGRhdGEnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhd2FpdCBkZWNyeXB0KHBhc3N3b3JkLCBjaXBoZXJ0ZXh0KSwgcGxhaW50ZXh0KTtcbiAgICB9KTtcblxuICAgIGl0KCdkZWNyeXB0cyBsZWdhY3kgdjEgZGF0YScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdChwYXNzd29yZCwgY2lwaGVydGV4dCksIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIG9uIHdyb25nIHBhc3N3b3JkIGZvciB2MScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBlbmNyeXB0KHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0KCd3cm9uZ1Bhc3N3b3JkJywgY2lwaGVydGV4dCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyBvbiB3cm9uZyBwYXNzd29yZCBmb3IgdjInLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgZW5jcnlwdChwYXNzd29yZCwgcGxhaW50ZXh0KTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHQoJ3dyb25nUGFzc3dvcmQnLCBjaXBoZXJ0ZXh0KSk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIG9uIGludmFsaWQgSlNPTiBpbnB1dCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHQocGFzc3dvcmQsICdub3QtanNvbicpLCAvY2lwaGVydGV4dCBpcyBub3QgdmFsaWQgSlNPTi8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3dyb25nIHBhc3N3b3JkIG9uIHYyIGRhdGEgZG9lcyBub3QgZmFsbCB0aHJvdWdoIHRvIHYxIGRlY3J5cHQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB2MmN0ID0gYXdhaXQgZW5jcnlwdFYyKHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgbWVtb3J5U2l6ZTogMTAyNCwgaXRlcmF0aW9uczogMSwgcGFyYWxsZWxpc206IDEgfSk7XG4gICAgICBsZXQgY2F1Z2h0RXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZGVjcnlwdCgnd3JvbmcnLCB2MmN0KTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2F1Z2h0RXJyb3IgPSBlIGFzIEVycm9yO1xuICAgICAgfVxuICAgICAgYXNzZXJ0Lm9rKGNhdWdodEVycm9yLCAnc2hvdWxkIGhhdmUgdGhyb3duJyk7XG4gICAgICBhc3NlcnQub2soIWNhdWdodEVycm9yLm1lc3NhZ2U/LmluY2x1ZGVzKCdzamNsJyksICdlcnJvciBtdXN0IG5vdCBiZSBmcm9tIFNKQ0wnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3YyIGVuY3J5cHQvZGVjcnlwdCAoQXJnb24yaWQgKyBBRVMtMjU2LUdDTSknLCAoKSA9PiB7XG4gICAgY29uc3QgcGFzc3dvcmQgPSAnbXlQYXNzd29yZCc7XG4gICAgY29uc3QgcGxhaW50ZXh0ID0gJ0hlbGxvLCBXb3JsZCEnO1xuXG4gICAgaXQoJ2VuY3J5cHRzIGFuZCBkZWNyeXB0cyByb3VuZC10cmlwJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY2lwaGVydGV4dCA9IGF3YWl0IGVuY3J5cHRWMihwYXNzd29yZCwgcGxhaW50ZXh0KTtcbiAgICAgIGNvbnN0IGRlY3J5cHRlZCA9IGF3YWl0IGRlY3J5cHRWMihwYXNzd29yZCwgY2lwaGVydGV4dCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZGVjcnlwdGVkLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Byb2R1Y2VzIGEgdmFsaWQgdjIgZW52ZWxvcGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgZW5jcnlwdFYyKHBhc3N3b3JkLCBwbGFpbnRleHQpO1xuICAgICAgY29uc3QgZW52ZWxvcGU6IFYyRW52ZWxvcGUgPSBKU09OLnBhcnNlKGNpcGhlcnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLnYsIDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLm0sIDY1NTM2KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS50LCAzKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS5wLCA0KTtcbiAgICAgIGFzc2VydC5vayhlbnZlbG9wZS5zYWx0LCAnZW52ZWxvcGUgbXVzdCBoYXZlIHNhbHQnKTtcbiAgICAgIGFzc2VydC5vayhlbnZlbG9wZS5pdiwgJ2VudmVsb3BlIG11c3QgaGF2ZSBpdicpO1xuICAgICAgYXNzZXJ0Lm9rKGVudmVsb3BlLmN0LCAnZW52ZWxvcGUgbXVzdCBoYXZlIGN0Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgncmV0dXJucyBkaWZmZXJlbnQgY2lwaGVydGV4dCBmb3IgdGhlIHNhbWUgcGxhaW50ZXh0IGFuZCBwYXNzd29yZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGN0MSA9IGF3YWl0IGVuY3J5cHRWMihwYXNzd29yZCwgcGxhaW50ZXh0KTtcbiAgICAgIGNvbnN0IGN0MiA9IGF3YWl0IGVuY3J5cHRWMihwYXNzd29yZCwgcGxhaW50ZXh0KTtcbiAgICAgIGFzc2VydC5ub3RTdHJpY3RFcXVhbChjdDEsIGN0Mik7XG4gICAgfSk7XG5cbiAgICBpdCgnZGVjcnlwdHMgd2l0aCBjdXN0b20gQXJnb24yaWQgcGFyYW1ldGVycycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBlbmNyeXB0VjIocGFzc3dvcmQsIHBsYWludGV4dCwge1xuICAgICAgICBtZW1vcnlTaXplOiAxMDI0LFxuICAgICAgICBpdGVyYXRpb25zOiAxLFxuICAgICAgICBwYXJhbGxlbGlzbTogMSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZW52ZWxvcGU6IFYyRW52ZWxvcGUgPSBKU09OLnBhcnNlKGNpcGhlcnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLm0sIDEwMjQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLnQsIDEpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLnAsIDEpO1xuXG4gICAgICBjb25zdCBkZWNyeXB0ZWQgPSBhd2FpdCBkZWNyeXB0VjIocGFzc3dvcmQsIGNpcGhlcnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGRlY3J5cHRlZCwgcGxhaW50ZXh0KTtcbiAgICB9KTtcblxuICAgIGl0KCd0aHJvd3Mgb24gd3JvbmcgcGFzc3dvcmQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgZW5jcnlwdFYyKHBhc3N3b3JkLCBwbGFpbnRleHQpO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYyKCd3cm9uZ1Bhc3N3b3JkJywgY2lwaGVydGV4dCkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyBvbiBpbnZhbGlkIEpTT04nLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjIocGFzc3dvcmQsICdub3QtanNvbicpLCAvaW52YWxpZCBKU09OIGVudmVsb3BlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgndGhyb3dzIG9uIHdyb25nIGVudmVsb3BlIHZlcnNpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjIocGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KHsgdjogOTkgfSkpLCAvaW52YWxpZCBlbnZlbG9wZS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyBvbiBpbnZhbGlkIHNhbHQgbGVuZ3RoJywgYXN5bmMgKCkgPT4ge1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZW5jcnlwdFYyKHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgc2FsdDogbmV3IFVpbnQ4QXJyYXkoOCkgfSksIC9zYWx0IG11c3QgYmUgMTYgYnl0ZXMvKTtcbiAgICB9KTtcblxuICAgIGl0KCd0aHJvd3Mgb24gaW52YWxpZCBpdiBsZW5ndGgnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBlbmNyeXB0VjIocGFzc3dvcmQsIHBsYWludGV4dCwgeyBpdjogbmV3IFVpbnQ4QXJyYXkoOCkgfSksIC9pdiBtdXN0IGJlIDEyIGJ5dGVzLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnZW5jcnlwdHMgYW5kIGRlY3J5cHRzIHdpdGggYWRhdGEgKEFBRCknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBhZGF0YSA9ICd0eGhhc2g6bS8wLzEnO1xuICAgICAgY29uc3QgY2lwaGVydGV4dCA9IGF3YWl0IGVuY3J5cHRWMihwYXNzd29yZCwgcGxhaW50ZXh0LCB7IGFkYXRhIH0pO1xuICAgICAgY29uc3QgZW52ZWxvcGU6IFYyRW52ZWxvcGUgPSBKU09OLnBhcnNlKGNpcGhlcnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLmFkYXRhLCBhZGF0YSk7XG4gICAgICBjb25zdCBkZWNyeXB0ZWQgPSBhd2FpdCBkZWNyeXB0VjIocGFzc3dvcmQsIGNpcGhlcnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGRlY3J5cHRlZCwgcGxhaW50ZXh0KTtcbiAgICB9KTtcblxuICAgIGl0KCdhZGF0YSBtaXNtYXRjaCBjYXVzZXMgR0NNIGRlY3J5cHRpb24gZmFpbHVyZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBlbmNyeXB0VjIocGFzc3dvcmQsIHBsYWludGV4dCwgeyBhZGF0YTogJ2NvbnRleHQtQScgfSk7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IEpTT04ucGFyc2UoY2lwaGVydGV4dCk7XG4gICAgICBlbnZlbG9wZS5hZGF0YSA9ICdjb250ZXh0LUInO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYyKHBhc3N3b3JkLCBKU09OLnN0cmluZ2lmeShlbnZlbG9wZSkpLCAvb3BlcmF0aW9uLXNwZWNpZmljIHJlYXNvbnxpbmNvcnJlY3QvaSk7XG4gICAgfSk7XG5cbiAgICBpdCgnYWRhdGE6IHVuZGVmaW5lZCBpcyBlcXVpdmFsZW50IHRvIG9taXR0aW5nIGFkYXRhJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZml4ZWRPcHRzID0ge1xuICAgICAgICBtZW1vcnlTaXplOiAxMDI0LFxuICAgICAgICBpdGVyYXRpb25zOiAxLFxuICAgICAgICBwYXJhbGxlbGlzbTogMSxcbiAgICAgICAgc2FsdDogbmV3IFVpbnQ4QXJyYXkoMTYpLmZpbGwoMHhhYSksXG4gICAgICAgIGl2OiBuZXcgVWludDhBcnJheSgxMikuZmlsbCgweGJiKSxcbiAgICAgIH07XG4gICAgICBjb25zdCB3aXRoVW5kZWZpbmVkID0gYXdhaXQgZW5jcnlwdFYyKHBhc3N3b3JkLCBwbGFpbnRleHQsIHsgLi4uZml4ZWRPcHRzLCBhZGF0YTogdW5kZWZpbmVkIH0pO1xuICAgICAgY29uc3Qgd2l0aE9taXR0ZWQgPSBhd2FpdCBlbmNyeXB0VjIocGFzc3dvcmQsIHBsYWludGV4dCwgZml4ZWRPcHRzKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh3aXRoVW5kZWZpbmVkLCB3aXRoT21pdHRlZCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdFYyKHBhc3N3b3JkLCB3aXRoVW5kZWZpbmVkKSwgcGxhaW50ZXh0KTtcbiAgICB9KTtcblxuICAgIGl0KCdjaXBoZXJ0ZXh0IGJvdW5kIHRvIGVudGVycHJpc2UtQSBjYW5ub3QgYmUgcmUtYXR0cmlidXRlZCB0byBlbnRlcnByaXNlLUInLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBwcnYgPSAneHBydi1wcml2YXRlLWtleS1ieXRlcyc7XG4gICAgICBjb25zdCBwcmZLZXkgPSAncHJmLWRlcml2ZWQta2V5JztcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgZW5jcnlwdFYyKHByZktleSwgcHJ2LCB7IGFkYXRhOiAnZW50ZXJwcmlzZS1BJyB9KTtcbiAgICAgIC8vIEF0dGFja2VyIG1vdmVzIGJsb2IgdG8gZW50ZXJwcmlzZS1CIGJ5IGFsdGVyaW5nIHRoZSBzdG9yZWQgYWRhdGEgZmllbGRcbiAgICAgIGNvbnN0IGVudmVsb3BlID0gSlNPTi5wYXJzZShjdCk7XG4gICAgICBlbnZlbG9wZS5hZGF0YSA9ICdlbnRlcnByaXNlLUInO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYyKHByZktleSwgSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpKSk7XG4gICAgfSk7XG5cbiAgICBpdCgndjEgYW5kIHYyIGFyZSBpbmRlcGVuZGVudCAodjEgZGF0YSBkb2VzIG5vdCBkZWNyeXB0IHdpdGggdjIpJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdjFjdCA9IGF3YWl0IGVuY3J5cHQocGFzc3dvcmQsIHBsYWludGV4dCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHRWMihwYXNzd29yZCwgdjFjdCksIC9pbnZhbGlkIGVudmVsb3BlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyBlbnZlbG9wZSB3aXRoIG1lbW9yeVNpemUgZXhjZWVkaW5nIG1heCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0geyB2OiAyLCBtOiA5OTk5OTk5OTksIHQ6IDMsIHA6IDQsIHNhbHQ6ICdBQUFBJywgaXY6ICdBQUFBJywgY3Q6ICdBQUFBJyB9O1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYyKHBhc3N3b3JkLCBKU09OLnN0cmluZ2lmeShlbnZlbG9wZSkpLCAvaW52YWxpZCBlbnZlbG9wZS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JlamVjdHMgZW52ZWxvcGUgd2l0aCBpdGVyYXRpb25zIGV4Y2VlZGluZyBtYXgnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IHsgdjogMiwgbTogNjU1MzYsIHQ6IDEwMCwgcDogNCwgc2FsdDogJ0FBQUEnLCBpdjogJ0FBQUEnLCBjdDogJ0FBQUEnIH07XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjIocGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksIC9pbnZhbGlkIGVudmVsb3BlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyBlbnZlbG9wZSB3aXRoIHBhcmFsbGVsaXNtIGV4Y2VlZGluZyBtYXgnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IHsgdjogMiwgbTogNjU1MzYsIHQ6IDMsIHA6IDEwMCwgc2FsdDogJ0FBQUEnLCBpdjogJ0FBQUEnLCBjdDogJ0FBQUEnIH07XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjIocGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksIC9pbnZhbGlkIGVudmVsb3BlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyBlbnZlbG9wZSB3aXRoIHplcm8tdmFsdWVkIHBhcmFtZXRlcnMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IHsgdjogMiwgbTogMCwgdDogMywgcDogNCwgc2FsdDogJ0FBQUEnLCBpdjogJ0FBQUEnLCBjdDogJ0FBQUEnIH07XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjIocGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksIC9pbnZhbGlkIGVudmVsb3BlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyBlbnZlbG9wZSB3aXRoIG5vbi1udW1lcmljIHBhcmFtZXRlciB0eXBlcycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0geyB2OiAyLCBtOiAnNjU1MzYnLCB0OiAzLCBwOiA0LCBzYWx0OiAnQUFBQScsIGl2OiAnQUFBQScsIGN0OiAnQUFBQScgfTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHRWMihwYXNzd29yZCwgSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpKSwgL2ludmFsaWQgZW52ZWxvcGUvKTtcbiAgICB9KTtcblxuICAgIGl0KCdyZWplY3RzIGVudmVsb3BlIHdpdGggZW1wdHkgc2FsdCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0geyB2OiAyLCBtOiA2NTUzNiwgdDogMywgcDogNCwgc2FsdDogJycsIGl2OiAnQUFBQScsIGN0OiAnQUFBQScgfTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHRWMihwYXNzd29yZCwgSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpKSwgL2ludmFsaWQgZW52ZWxvcGUvKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3YyIEhLREYtb25seSBkZWNyeXB0IChoaWdoLWVudHJvcHkgSUtNLCBubyBBcmdvbjIpJywgKCkgPT4ge1xuICAgIC8vIEVDREgtc2hhcGVkIGlucHV0OiAyNTYtYml0IHNlY3JldCBhcyBoZXgsIG1hdGNoaW5nIGVuY3J5cHRQcnZGb3JVc2VyLlxuICAgIGNvbnN0IGhpZ2hFbnRyb3B5UGFzc3dvcmQgPSBCdWZmZXIuYWxsb2MoMzIsIDB4YWIpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBwbGFpbnRleHQgPSAnc2hhcmVkLXdhbGxldC1wcnYnO1xuXG4gICAgaXQoJ2RlY3J5cHRzIGFuIEhLREYtb25seSBlbnZlbG9wZSB2aWEgZGVjcnlwdFYyJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgY2lwaGVydGV4dCA9IGF3YWl0IG1ha2VIa2RmT25seUVudmVsb3BlKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIHBsYWludGV4dCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdFYyKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIGNpcGhlcnRleHQpLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2RlY3J5cHRzIGFuIEhLREYtb25seSBlbnZlbG9wZSB2aWEgZGVjcnlwdCBhdXRvLWRldGVjdCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBtYWtlSGtkZk9ubHlFbnZlbG9wZShoaWdoRW50cm9weVBhc3N3b3JkLCBwbGFpbnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IGRlY3J5cHQoaGlnaEVudHJvcHlQYXNzd29yZCwgY2lwaGVydGV4dCksIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGVjcnlwdHMgYSBmaXhlZCBIS0RGLW9ubHkgZW52ZWxvcGUgKHdpcmUgZm9ybWF0IGlzIHBpbm5lZCknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgbWFrZUhrZGZPbmx5RW52ZWxvcGUoaGlnaEVudHJvcHlQYXNzd29yZCwgcGxhaW50ZXh0LCB7XG4gICAgICAgIGhrZGZTYWx0OiBuZXcgVWludDhBcnJheSgzMikuZmlsbCgweGNkKSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZW52ZWxvcGU6IFYyRW52ZWxvcGUgPSBKU09OLnBhcnNlKGNpcGhlcnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLnYsIDIpO1xuICAgICAgYXNzZXJ0Lm9rKGVudmVsb3BlLmhrZGZTYWx0LCAnbXVzdCBoYXZlIGhrZGYgc2FsdCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLm0sIHVuZGVmaW5lZCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUudCwgdW5kZWZpbmVkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS5wLCB1bmRlZmluZWQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLnNhbHQsIHVuZGVmaW5lZCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdFYyKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIGNpcGhlcnRleHQpLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyBvbiB3cm9uZyBwYXNzd29yZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGNpcGhlcnRleHQgPSBhd2FpdCBtYWtlSGtkZk9ubHlFbnZlbG9wZShoaWdoRW50cm9weVBhc3N3b3JkLCBwbGFpbnRleHQpO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYyKCd3cm9uZy1wYXNzd29yZCcsIGNpcGhlcnRleHQpKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZWNyeXB0cyBhbiBIS0RGLW9ubHkgZW52ZWxvcGUgY2FycnlpbmcgYWRhdGEnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBhZGF0YSA9ICd3YWxsZXQtc2hhcmUnO1xuICAgICAgY29uc3QgY2lwaGVydGV4dCA9IGF3YWl0IG1ha2VIa2RmT25seUVudmVsb3BlKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIHBsYWludGV4dCwgeyBhZGF0YSB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhd2FpdCBkZWNyeXB0VjIoaGlnaEVudHJvcHlQYXNzd29yZCwgY2lwaGVydGV4dCksIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnYWRhdGEgbWlzbWF0Y2ggY2F1c2VzIEdDTSBkZWNyeXB0aW9uIGZhaWx1cmUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjaXBoZXJ0ZXh0ID0gYXdhaXQgbWFrZUhrZGZPbmx5RW52ZWxvcGUoaGlnaEVudHJvcHlQYXNzd29yZCwgcGxhaW50ZXh0LCB7IGFkYXRhOiAnY29udGV4dC1BJyB9KTtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0gSlNPTi5wYXJzZShjaXBoZXJ0ZXh0KTtcbiAgICAgIGVudmVsb3BlLmFkYXRhID0gJ2NvbnRleHQtQic7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhcbiAgICAgICAgKCkgPT4gZGVjcnlwdFYyKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksXG4gICAgICAgIC9vcGVyYXRpb24tc3BlY2lmaWMgcmVhc29ufGluY29ycmVjdC9pXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JlamVjdHMgbWl4ZWQgZW52ZWxvcGVzIChoa2RmU2FsdCBwbHVzIGluY29tcGxldGUgQXJnb24yIHBhcmFtcyknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBlbnZlbG9wZSA9IHsgdjogMiwgbTogMTAyNCwgaGtkZlNhbHQ6ICdBQUFBJywgaXY6ICdBQUFBJywgY3Q6ICdBQUFBJyB9O1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gZGVjcnlwdFYyKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksIC9pbnZhbGlkIGVudmVsb3BlLyk7XG4gICAgfSk7XG5cbiAgICBpdCgncmVqZWN0cyBlbnZlbG9wZXMgd2l0aCBuZWl0aGVyIEFyZ29uMiBwYXJhbXMgbm9yIGhrZGZTYWx0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgZW52ZWxvcGUgPSB7IHY6IDIsIGl2OiAnQUFBQScsIGN0OiAnQUFBQScgfTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IGRlY3J5cHRWMihoaWdoRW50cm9weVBhc3N3b3JkLCBKU09OLnN0cmluZ2lmeShlbnZlbG9wZSkpLCAvaW52YWxpZCBlbnZlbG9wZS8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ0FyZ29uMiBhbmQgSEtERi1vbmx5IGVudmVsb3BlcyBzdGF5IGRpc3Rpbmd1aXNoYWJsZSBhbmQgYm90aCBkZWNyeXB0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYXJnb24yY3QgPSBhd2FpdCBlbmNyeXB0VjIoaGlnaEVudHJvcHlQYXNzd29yZCwgcGxhaW50ZXh0LCB7XG4gICAgICAgIG1lbW9yeVNpemU6IDEwMjQsXG4gICAgICAgIGl0ZXJhdGlvbnM6IDEsXG4gICAgICAgIHBhcmFsbGVsaXNtOiAxLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBoa2RmY3QgPSBhd2FpdCBtYWtlSGtkZk9ubHlFbnZlbG9wZShoaWdoRW50cm9weVBhc3N3b3JkLCBwbGFpbnRleHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGF3YWl0IGRlY3J5cHRWMihoaWdoRW50cm9weVBhc3N3b3JkLCBhcmdvbjJjdCksIHBsYWludGV4dCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdFYyKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIGhrZGZjdCksIHBsYWludGV4dCk7XG4gICAgICBjb25zdCBhcmdvbjJlbnYgPSBKU09OLnBhcnNlKGFyZ29uMmN0KTtcbiAgICAgIGNvbnN0IGhrZGZlbnYgPSBKU09OLnBhcnNlKGhrZGZjdCk7XG4gICAgICBhc3NlcnQub2soYXJnb24yZW52LnNhbHQpO1xuICAgICAgYXNzZXJ0Lm9rKGhrZGZlbnYuaGtkZlNhbHQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGFyZ29uMmVudi5oa2RmU2FsdCwgdW5kZWZpbmVkKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChoa2RmZW52LnNhbHQsIHVuZGVmaW5lZCk7XG4gICAgfSk7XG5cbiAgICBpdCgnbm8gU0RLIGVuY3J5cHQgcGF0aCBlbWl0cyBIS0RGLW9ubHkgZW52ZWxvcGVzIHlldCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGZyb21FbmNyeXB0OiBWMkVudmVsb3BlID0gSlNPTi5wYXJzZShhd2FpdCBlbmNyeXB0KGhpZ2hFbnRyb3B5UGFzc3dvcmQsIHBsYWludGV4dCkpO1xuICAgICAgY29uc3QgZnJvbUVuY3J5cHRWMjogVjJFbnZlbG9wZSA9IEpTT04ucGFyc2UoYXdhaXQgZW5jcnlwdFYyKGhpZ2hFbnRyb3B5UGFzc3dvcmQsIHBsYWludGV4dCkpO1xuICAgICAgZm9yIChjb25zdCBlbnZlbG9wZSBvZiBbZnJvbUVuY3J5cHQsIGZyb21FbmNyeXB0VjJdKSB7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS52LCAyKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGVudmVsb3BlLm0sICdtdXN0IHN0aWxsIGVtaXQgQXJnb24yIHBhcmFtcycpO1xuICAgICAgICBhc3NlcnQub2soZW52ZWxvcGUudCk7XG4gICAgICAgIGFzc2VydC5vayhlbnZlbG9wZS5wKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGVudmVsb3BlLnNhbHQpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUuaGtkZlNhbHQsIHVuZGVmaW5lZCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdFbmNyeXB0aW9uU2Vzc2lvbiAoSEtERiBjYWNoaW5nKScsICgpID0+IHtcbiAgICBjb25zdCBvcHRzID0geyBtZW1vcnlTaXplOiAxMDI0LCBpdGVyYXRpb25zOiAxLCBwYXJhbGxlbGlzbTogMSB9O1xuICAgIGNvbnN0IHBhc3N3b3JkID0gJ3Rlc3QtcGFzc3dvcmQnO1xuICAgIGNvbnN0IHBsYWludGV4dCA9ICdoZWxsbyBzZXNzaW9uJztcblxuICAgIGl0KCdzZXNzaW9uLXByb2R1Y2VkIGVudmVsb3BlIGNvbnRhaW5zIHNhbHQgYW5kIGhrZGZTYWx0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uKHBhc3N3b3JkLCBvcHRzKTtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgc2Vzc2lvbi5lbmNyeXB0KHBsYWludGV4dCk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcblxuICAgICAgY29uc3QgZW52ZWxvcGU6IFYyRW52ZWxvcGUgPSBKU09OLnBhcnNlKGN0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS52LCAyKTtcbiAgICAgIGFzc2VydC5vayhlbnZlbG9wZS5zYWx0LCAnbXVzdCBoYXZlIGFyZ29uMiBzYWx0Jyk7XG4gICAgICBhc3NlcnQub2soZW52ZWxvcGUuaGtkZlNhbHQsICdtdXN0IGhhdmUgaGtkZiBzYWx0Jyk7XG4gICAgICBhc3NlcnQub2soZW52ZWxvcGUuaXYsICdtdXN0IGhhdmUgaXYnKTtcbiAgICAgIGFzc2VydC5vayhlbnZlbG9wZS5jdCwgJ211c3QgaGF2ZSBjaXBoZXJ0ZXh0Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2Vzc2lvbiByb3VuZC10cmlwIHZpYSBzZXNzaW9uLmRlY3J5cHQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIG9wdHMpO1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlc3Npb24uZGVjcnlwdChjdCk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2Vzc2lvbiBlbnZlbG9wZSBjYW4gYmUgZGVjcnlwdGVkIHN0YW5kYWxvbmUgdmlhIGRlY3J5cHRWMicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgb3B0cyk7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkZWNyeXB0VjIocGFzc3dvcmQsIGN0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2Vzc2lvbiBlbnZlbG9wZSBjYW4gYmUgZGVjcnlwdGVkIHZpYSBkZWNyeXB0JywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uKHBhc3N3b3JkLCBvcHRzKTtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgc2Vzc2lvbi5lbmNyeXB0KHBsYWludGV4dCk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGRlY3J5cHQocGFzc3dvcmQsIGN0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnbXVsdGlwbGUgZW5jcnlwdHMgcHJvZHVjZSBkaWZmZXJlbnQgaGtkZlNhbHQgdmFsdWVzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uKHBhc3N3b3JkLCBvcHRzKTtcbiAgICAgIGNvbnN0IGN0MSA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgY29uc3QgY3QyID0gYXdhaXQgc2Vzc2lvbi5lbmNyeXB0KHBsYWludGV4dCk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgIGNvbnN0IGUxOiBWMkVudmVsb3BlID0gSlNPTi5wYXJzZShjdDEpO1xuICAgICAgY29uc3QgZTI6IFYyRW52ZWxvcGUgPSBKU09OLnBhcnNlKGN0Mik7XG4gICAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwoZTEuaGtkZlNhbHQsIGUyLmhrZGZTYWx0KTtcbiAgICB9KTtcblxuICAgIGl0KCdhbGwgc2Vzc2lvbiBlbmNyeXB0cyBzaGFyZSB0aGUgc2FtZSBhcmdvbjIgc2FsdCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgb3B0cyk7XG4gICAgICBjb25zdCBjdDEgPSBhd2FpdCBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0KTtcbiAgICAgIGNvbnN0IGN0MiA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgICBjb25zdCBlMTogVjJFbnZlbG9wZSA9IEpTT04ucGFyc2UoY3QxKTtcbiAgICAgIGNvbnN0IGUyOiBWMkVudmVsb3BlID0gSlNPTi5wYXJzZShjdDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGUxLnNhbHQsIGUyLnNhbHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3dyb25nIHBhc3N3b3JkIHJlamVjdGVkIGJ5IGRlY3J5cHRWMicsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgb3B0cyk7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBkZWNyeXB0VjIoJ3dyb25nLXBhc3N3b3JkJywgY3QpKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZXN0cm95IHByZXZlbnRzIGZ1cnRoZXIgZW5jcnlwdCBjYWxscycsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgb3B0cyk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpLCAvZGVzdHJveWVkLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGVzdHJveSBwcmV2ZW50cyBmdXJ0aGVyIGRlY3J5cHQgY2FsbHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIG9wdHMpO1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0KTtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gc2Vzc2lvbi5kZWNyeXB0KGN0KSwgL2Rlc3Ryb3llZC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nlc3Npb24gcmVqZWN0cyBlbnZlbG9wZXMgZnJvbSBhIGRpZmZlcmVudCBzZXNzaW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2Vzc2lvbjEgPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgb3B0cyk7XG4gICAgICBjb25zdCBzZXNzaW9uMiA9IGF3YWl0IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uKHBhc3N3b3JkLCBvcHRzKTtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgc2Vzc2lvbjEuZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gc2Vzc2lvbjIuZGVjcnlwdChjdCksIC9ub3QgZW5jcnlwdGVkIHdpdGggdGhpcyBzZXNzaW9uLyk7XG4gICAgICBzZXNzaW9uMS5kZXN0cm95KCk7XG4gICAgICBzZXNzaW9uMi5kZXN0cm95KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2Vzc2lvbiBlbmNyeXB0IHdpdGggYWRhdGEgcm91bmQtdHJpcCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgb3B0cyk7XG4gICAgICBjb25zdCBhZGF0YSA9ICd0eGhhc2g6bS8wLzE6cm91bmQxJztcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgc2Vzc2lvbi5lbmNyeXB0KHBsYWludGV4dCwgYWRhdGEpO1xuICAgICAgY29uc3QgZW52ZWxvcGU6IFYyRW52ZWxvcGUgPSBKU09OLnBhcnNlKGN0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS5hZGF0YSwgYWRhdGEpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2Vzc2lvbi5kZWNyeXB0KGN0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHBsYWludGV4dCk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgIGl0KCdzZXNzaW9uIGVuY3J5cHQgd2l0aCBhZGF0YSBpcyBkZWNyeXB0YWJsZSB2aWEgZGVjcnlwdFYyJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uKHBhc3N3b3JkLCBvcHRzKTtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgc2Vzc2lvbi5lbmNyeXB0KHBsYWludGV4dCwgJ2NvbnRleHQtYmluZGluZycpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBkZWNyeXB0VjIocGFzc3dvcmQsIGN0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQsIHBsYWludGV4dCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2Vzc2lvbiBhZGF0YSBtaXNtYXRjaCBjYXVzZXMgR0NNIGZhaWx1cmUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIG9wdHMpO1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0LCAnb3JpZ2luYWwtY29udGV4dCcpO1xuICAgICAgY29uc3QgZW52ZWxvcGUgPSBKU09OLnBhcnNlKGN0KTtcbiAgICAgIGVudmVsb3BlLmFkYXRhID0gJ3RhbXBlcmVkLWNvbnRleHQnO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gc2Vzc2lvbi5kZWNyeXB0KEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSksIC9vcGVyYXRpb24tc3BlY2lmaWMgcmVhc29ufGluY29ycmVjdC9pKTtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nlc3Npb24gcmVqZWN0cyBzdGFuZGFyZCB2MiBlbnZlbG9wZXMgKG5vIGhrZGZTYWx0KScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHYyY3QgPSBhd2FpdCBlbmNyeXB0VjIocGFzc3dvcmQsIHBsYWludGV4dCwgb3B0cyk7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIG9wdHMpO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gc2Vzc2lvbi5kZWNyeXB0KHYyY3QpLCAvdXNlIGRlY3J5cHRWMi8pO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgfSk7XG5cbiAgICBpdCgnQXJnb24yaWQgcGFyYW1zIGFyZSBzdG9yZWQgaW4gZW52ZWxvcGUnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIHsgbWVtb3J5U2l6ZTogMjA0OCwgaXRlcmF0aW9uczogMiwgcGFyYWxsZWxpc206IDIgfSk7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgICBjb25zdCBlbnZlbG9wZTogVjJFbnZlbG9wZSA9IEpTT04ucGFyc2UoY3QpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLm0sIDIwNDgpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLnQsIDIpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGVudmVsb3BlLnAsIDIpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlRW5jcnlwdGlvblNlc3Npb24gd2l0aCBlbmNyeXB0aW9uVmVyc2lvbj0xICh2MSBzaGltKScsICgpID0+IHtcbiAgICBjb25zdCBwYXNzd29yZCA9ICd2MS1zaGltLXBhc3N3b3JkJztcbiAgICBjb25zdCBwbGFpbnRleHQgPSAnbGVnYWN5IGNvbnN1bWVyIGRhdGEnO1xuXG4gICAgaXQoJ3Byb2R1Y2VzIHYxIChTSkNMKSBlbnZlbG9wZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgY29uc3QgZW52ZWxvcGUgPSBKU09OLnBhcnNlKGN0KTtcbiAgICAgIC8vIHYxIFNKQ0wgZW52ZWxvcGVzIGNhcnJ5IGl0ZXIvbW9kZS9rcyBmaWVsZHM7IG5vIGhrZGZTYWx0L2FyZ29uMiBwYXJhbXNcbiAgICAgIGFzc2VydC5vayhlbnZlbG9wZS5pdGVyLCAndjEgZW52ZWxvcGUgbXVzdCBoYXZlIGl0ZXInKTtcbiAgICAgIGFzc2VydC5vayhlbnZlbG9wZS5tb2RlLCAndjEgZW52ZWxvcGUgbXVzdCBoYXZlIG1vZGUnKTtcbiAgICAgIGFzc2VydC5ub3RTdHJpY3RFcXVhbChlbnZlbG9wZS52LCAyKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChlbnZlbG9wZS5oa2RmU2FsdCwgdW5kZWZpbmVkKTtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JvdW5kLXRyaXBzIHZpYSBzZXNzaW9uLmRlY3J5cHQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgY29uc3QgcnQgPSBhd2FpdCBzZXNzaW9uLmRlY3J5cHQoY3QpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJ0LCBwbGFpbnRleHQpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgfSk7XG5cbiAgICBpdCgncHJvZHVjZWQgZW52ZWxvcGVzIGRlY3J5cHQgdmlhIHRoZSBzdGFuZGFyZCBkZWNyeXB0KCkgd2l0aCB0aGUgc2FtZSBwYXNzd29yZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KTtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgc2Vzc2lvbi5lbmNyeXB0KHBsYWludGV4dCk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgIGNvbnN0IHJ0ID0gYXdhaXQgZGVjcnlwdChwYXNzd29yZCwgY3QpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJ0LCBwbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ211bHRpcGxlIGVuY3J5cHRzIHByb2R1Y2UgZGlzdGluY3QgY2lwaGVydGV4dHMgKHBlci1jYWxsIFNKQ0wgc2FsdC9pdiknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBjb25zdCBjdDEgPSBhd2FpdCBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0KTtcbiAgICAgIGNvbnN0IGN0MiA9IGF3YWl0IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpO1xuICAgICAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKGN0MSwgY3QyKTtcbiAgICAgIGNvbnN0IGUxID0gSlNPTi5wYXJzZShjdDEpO1xuICAgICAgY29uc3QgZTIgPSBKU09OLnBhcnNlKGN0Mik7XG4gICAgICAvLyB2MSBzYWx0cyBhcmUgcGVyLWNhbGwsIHNvIHRoZXkgbXVzdCBkaWZmZXIgYWNyb3NzIGVudmVsb3BlcyBldmVuIHVuZGVyIHNhbWUgcGFzc3dvcmRcbiAgICAgIGFzc2VydC5ub3RTdHJpY3RFcXVhbChlMS5zYWx0LCBlMi5zYWx0KTtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2ZvcndhcmRzIGFkYXRhIHRvIHRoZSB2MSBlbnZlbG9wZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KTtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgc2Vzc2lvbi5lbmNyeXB0KHBsYWludGV4dCwgJ2VudGVycHJpc2UtaWQtNDInKTtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0gSlNPTi5wYXJzZShjdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUuYWRhdGEsICdlbnRlcnByaXNlLWlkLTQyJyk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZXN0cm95IGJsb2NrcyBmdXJ0aGVyIGVuY3J5cHQgY2FsbHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQsIHsgZW5jcnlwdGlvblZlcnNpb246IDEgfSk7XG4gICAgICBzZXNzaW9uLmRlc3Ryb3koKTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKCgpID0+IHNlc3Npb24uZW5jcnlwdChwbGFpbnRleHQpLCAvZGVzdHJveWVkLyk7XG4gICAgfSk7XG5cbiAgICBpdCgnZGVzdHJveSBibG9ja3MgZnVydGhlciBkZWNyeXB0IGNhbGxzJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgc2Vzc2lvbiA9IGF3YWl0IGNyZWF0ZUVuY3J5cHRpb25TZXNzaW9uKHBhc3N3b3JkLCB7IGVuY3J5cHRpb25WZXJzaW9uOiAxIH0pO1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0KTtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoKCkgPT4gc2Vzc2lvbi5kZWNyeXB0KGN0KSwgL2Rlc3Ryb3llZC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ2Rlc3Ryb3kgaXMgaWRlbXBvdGVudCcsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbihwYXNzd29yZCwgeyBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KTtcbiAgICAgIHNlc3Npb24uZGVzdHJveSgpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCaXRHb0FQSS5lbmNyeXB0JywgKCkgPT4ge1xuICAgIGxldCBiaXRnbzogQml0R29BUEk7XG4gICAgY29uc3QgcGFzc3dvcmQgPSAndGVzdC1wYXNzd29yZCc7XG4gICAgY29uc3QgcGxhaW50ZXh0ID0gJ2hlbGxvIGVuY3J5cHQnO1xuXG4gICAgYmVmb3JlKCgpID0+IHtcbiAgICAgIGJpdGdvID0gbmV3IEJpdEdvQVBJKHsgZW52OiAndGVzdCcgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgncHJvZHVjZXMgYSB2MiBlbnZlbG9wZSBieSBkZWZhdWx0IGFuZCBvdXRwdXQgaXMgZGVjcnlwdGFibGUgdmlhIGRlY3J5cHQnLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBjdCA9IGF3YWl0IGJpdGdvLmVuY3J5cHQoeyBpbnB1dDogcGxhaW50ZXh0LCBwYXNzd29yZCB9KTtcbiAgICAgIGNvbnN0IGVudmVsb3BlOiBWMkVudmVsb3BlID0gSlNPTi5wYXJzZShjdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUudiwgMik7XG4gICAgICBhc3NlcnQub2soZW52ZWxvcGUuc2FsdCwgJ3B1YmxpYyBlbmNyeXB0IG11c3Qgc3RpbGwgZW1pdCBBcmdvbjIgcGFyYW1zJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUuaGtkZlNhbHQsIHVuZGVmaW5lZCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdChwYXNzd29yZCwgY3QpLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Byb2R1Y2VzIGEgdjEgZW52ZWxvcGUgd2hlbiBlbmNyeXB0aW9uVmVyc2lvbjogMScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiBwbGFpbnRleHQsIHBhc3N3b3JkLCBlbmNyeXB0aW9uVmVyc2lvbjogMSB9KTtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0gSlNPTi5wYXJzZShjdCk7XG4gICAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwoZW52ZWxvcGUudiwgMik7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYXdhaXQgZGVjcnlwdChwYXNzd29yZCwgY3QpLCBwbGFpbnRleHQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2ZvcndhcmRzIGFkYXRhIHRvIHYyIGVudmVsb3BlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgYWRhdGEgPSAndHhoYXNoOm0vMC8xJztcbiAgICAgIGNvbnN0IGN0ID0gYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiBwbGFpbnRleHQsIHBhc3N3b3JkLCBhZGF0YSB9KTtcbiAgICAgIGNvbnN0IGVudmVsb3BlOiBWMkVudmVsb3BlID0gSlNPTi5wYXJzZShjdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoZW52ZWxvcGUuYWRhdGEsIGFkYXRhKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChhd2FpdCBkZWNyeXB0KHBhc3N3b3JkLCBjdCksIHBsYWludGV4dCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdCaXRHb0FQSS5jcmVhdGVFbmNyeXB0aW9uU2Vzc2lvbicsICgpID0+IHtcbiAgICBsZXQgYml0Z286IEJpdEdvQVBJO1xuICAgIGNvbnN0IHBhc3N3b3JkID0gJ3Rlc3QtcGFzc3dvcmQnO1xuICAgIGNvbnN0IHBsYWludGV4dCA9ICdoZWxsbyBzZXNzaW9uJztcblxuICAgIGJlZm9yZSgoKSA9PiB7XG4gICAgICBiaXRnbyA9IG5ldyBCaXRHb0FQSSh7IGVudjogJ3Rlc3QnIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3JldHVybnMgd29ya2luZyBzZXNzaW9uIChlbmNyeXB0L2RlY3J5cHQvZGVzdHJveSknLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgYml0Z28uY3JlYXRlRW5jcnlwdGlvblNlc3Npb24ocGFzc3dvcmQpO1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNlc3Npb24uZGVjcnlwdChjdCk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwocmVzdWx0LCBwbGFpbnRleHQpO1xuICAgICAgc2Vzc2lvbi5kZXN0cm95KCk7XG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cygoKSA9PiBzZXNzaW9uLmVuY3J5cHQocGxhaW50ZXh0KSwgL2Rlc3Ryb3llZC8pO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19
|