@bitgo-beta/sdk-api 1.10.1-beta.203 → 1.10.1-beta.2030

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.
Files changed (91) hide show
  1. package/dist/package.json +23 -27
  2. package/dist/src/api.d.ts +8 -5
  3. package/dist/src/api.d.ts.map +1 -1
  4. package/dist/src/api.js +134 -72
  5. package/dist/src/bitgoAPI.d.ts +115 -31
  6. package/dist/src/bitgoAPI.d.ts.map +1 -1
  7. package/dist/src/bitgoAPI.js +705 -342
  8. package/dist/src/decryptV1.d.ts +60 -0
  9. package/dist/src/decryptV1.d.ts.map +1 -0
  10. package/dist/src/decryptV1.js +140 -0
  11. package/dist/src/encrypt.d.ts +37 -6
  12. package/dist/src/encrypt.d.ts.map +1 -1
  13. package/dist/src/encrypt.js +171 -15
  14. package/dist/src/encryptV2.d.ts +67 -0
  15. package/dist/src/encryptV2.d.ts.map +1 -0
  16. package/dist/src/encryptV2.js +234 -0
  17. package/dist/src/encryptionSession.d.ts +63 -0
  18. package/dist/src/encryptionSession.d.ts.map +1 -0
  19. package/dist/src/encryptionSession.js +140 -0
  20. package/dist/src/index.d.ts +3 -0
  21. package/dist/src/index.d.ts.map +1 -1
  22. package/dist/src/index.js +9 -2
  23. package/dist/src/types.d.ts +70 -43
  24. package/dist/src/types.d.ts.map +1 -1
  25. package/dist/src/types.js +4 -2
  26. package/dist/src/util.d.ts +12 -0
  27. package/dist/src/util.d.ts.map +1 -1
  28. package/dist/src/util.js +57 -4
  29. package/dist/src/v1/blockchain.js +25 -12
  30. package/dist/src/v1/keychains.js +39 -26
  31. package/dist/src/v1/markets.js +10 -5
  32. package/dist/src/v1/pendingapproval.d.ts.map +1 -1
  33. package/dist/src/v1/pendingapproval.js +57 -18
  34. package/dist/src/v1/pendingapprovals.d.ts.map +1 -1
  35. package/dist/src/v1/pendingapprovals.js +41 -7
  36. package/dist/src/v1/signPsbt.d.ts +14 -0
  37. package/dist/src/v1/signPsbt.d.ts.map +1 -0
  38. package/dist/src/v1/signPsbt.js +69 -0
  39. package/dist/src/v1/transactionBuilder.js +221 -91
  40. package/dist/src/v1/travelRule.js +125 -66
  41. package/dist/src/v1/verifyAddress.d.ts +6 -0
  42. package/dist/src/v1/verifyAddress.d.ts.map +1 -0
  43. package/dist/src/v1/verifyAddress.js +50 -0
  44. package/dist/src/v1/wallet.d.ts.map +1 -1
  45. package/dist/src/v1/wallet.js +498 -230
  46. package/dist/src/v1/wallets.js +118 -53
  47. package/dist/test/unit/api.d.ts +2 -0
  48. package/dist/test/unit/api.d.ts.map +1 -0
  49. package/dist/test/unit/api.js +307 -0
  50. package/dist/test/unit/bitgoAPI.d.ts +2 -0
  51. package/dist/test/unit/bitgoAPI.d.ts.map +1 -0
  52. package/dist/test/unit/bitgoAPI.js +1117 -0
  53. package/dist/test/unit/decryptV1.browser.d.ts +2 -0
  54. package/dist/test/unit/decryptV1.browser.d.ts.map +1 -0
  55. package/dist/test/unit/decryptV1.browser.js +133 -0
  56. package/dist/test/unit/decryptV1.d.ts +2 -0
  57. package/dist/test/unit/decryptV1.d.ts.map +1 -0
  58. package/dist/test/unit/decryptV1.js +230 -0
  59. package/dist/test/unit/encrypt.d.ts +2 -0
  60. package/dist/test/unit/encrypt.d.ts.map +1 -0
  61. package/dist/test/unit/encrypt.js +544 -0
  62. package/dist/test/unit/fixtures/keycard.d.ts +25 -0
  63. package/dist/test/unit/fixtures/keycard.d.ts.map +1 -0
  64. package/dist/test/unit/fixtures/keycard.js +28 -0
  65. package/dist/test/unit/hmacStrategy.d.ts +2 -0
  66. package/dist/test/unit/hmacStrategy.d.ts.map +1 -0
  67. package/dist/test/unit/hmacStrategy.js +136 -0
  68. package/dist/test/unit/utils.d.ts +2 -0
  69. package/dist/test/unit/utils.d.ts.map +1 -0
  70. package/dist/test/unit/utils.js +65 -0
  71. package/dist/test/unit/v1/fixtures/accelerate-tx.d.ts +4 -0
  72. package/dist/test/unit/v1/fixtures/accelerate-tx.d.ts.map +1 -0
  73. package/dist/test/unit/v1/fixtures/accelerate-tx.js +53 -0
  74. package/dist/test/unit/v1/fixtures/index.d.ts +3 -0
  75. package/dist/test/unit/v1/fixtures/index.d.ts.map +1 -0
  76. package/dist/test/unit/v1/fixtures/index.js +24 -0
  77. package/dist/test/unit/v1/signPsbt.d.ts +2 -0
  78. package/dist/test/unit/v1/signPsbt.d.ts.map +1 -0
  79. package/dist/test/unit/v1/signPsbt.js +53 -0
  80. package/dist/test/unit/v1/travelRule.d.ts +2 -0
  81. package/dist/test/unit/v1/travelRule.d.ts.map +1 -0
  82. package/dist/test/unit/v1/travelRule.js +125 -0
  83. package/dist/test/unit/v1/wallet.d.ts +2 -0
  84. package/dist/test/unit/v1/wallet.d.ts.map +1 -0
  85. package/dist/test/unit/v1/wallet.js +1717 -0
  86. package/dist/tsconfig.tsbuildinfo +1 -0
  87. package/package.json +23 -27
  88. package/.eslintignore +0 -5
  89. package/CHANGELOG.md +0 -605
  90. package/dist/web/main.js +0 -2
  91. package/dist/web/main.js.LICENSE.txt +0 -110
@@ -0,0 +1,1717 @@
1
+ "use strict";
2
+ //
3
+ // Tests for Wallet
4
+ //
5
+ // Copyright 2014, BitGo, Inc. All Rights Reserved.
6
+ //
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ const fixtures_1 = require("./fixtures");
45
+ const Wallet = require('../../../src/v1/wallet');
46
+ const bitgoAPI_1 = require("../../../src/bitgoAPI");
47
+ const _ = __importStar(require("lodash"));
48
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
49
+ const utxolib = __importStar(require("@bitgo-beta/utxo-lib"));
50
+ const should = __importStar(require("should"));
51
+ const nock_1 = __importDefault(require("nock"));
52
+ const sinon = __importStar(require("sinon"));
53
+ const accelerate_tx_1 = require("./fixtures/accelerate-tx");
54
+ nock_1.default.disableNetConnect();
55
+ const TestBitGo = {
56
+ TEST_WALLET1_PASSCODE: 'iVWeATjqLS1jJShrPpETti0b',
57
+ };
58
+ describe('Wallet Prototype Methods', function () {
59
+ const fixtures = (0, accelerate_tx_1.getFixtures)();
60
+ let bitgo = new bitgoAPI_1.BitGoAPI({ env: 'test', clientConstants: { constants: {} } });
61
+ // bitgo.initializeTestVars();
62
+ const userKeypair = {
63
+ xprv: 'xprv9s21ZrQH143K2fJ91S4BRsupcYrE6mmY96fcX5HkhoTrrwmwjd16Cn87cWinJjByrfpojjx7ezsJLx7TAKLT8m8hM5Kax9YcoxnBeJZ3t2k',
64
+ xpub: 'xpub661MyMwAqRbcF9Nc7TbBo1rZAagiWEVPWKbDKThNG8zqjk76HAKLkaSbTn6dK2dQPfuD7xjicxCZVWvj67fP5nQ9W7QURmoMVAX8m6jZsGp',
65
+ rawPub: '02c103ac74481874b5ef0f385d12725e4f14aedc9e00bc814ce96f47f62ce7adf2',
66
+ rawPrv: '936c5af3f8af81f75cdad1b08f29e7d9c01e598e2db2d7be18b9e5a8646e87c6',
67
+ path: 'm',
68
+ walletSubPath: '/0/0',
69
+ };
70
+ const backupKeypair = {
71
+ xprv: 'xprv9s21ZrQH143K47sEkLkykgYmq1xF5ZWrPYhUZcmBpPFMQojvGUmEcr5jFXYGfr8CpFdpTvhQ7L9NN2rLtsBFjSix3BAjwJcBj6U3D5hxTPc',
72
+ xpub: 'xpub661MyMwAqRbcGbwhrNHz7pVWP3njV2Ehkmd5N1AoNinLHc54p25VAeQD6q2oTS3uuDMDnfnXnthbS9ufC8JVYpNnWU5Rn3pYaNuLCNywkw1',
73
+ rawPub: '03bbcb73997977068d9e36666bbd5cd37579acae8e2bd5ce9d0a6e5c150a423bc3',
74
+ rawPrv: '77a15f14796f4001d1092ae84f766bd869e9bee6bffae6547def5045b96fa943',
75
+ path: 'm',
76
+ walletSubPath: '/0/0',
77
+ };
78
+ const bitgoKey = {
79
+ xpub: 'xpub661MyMwAqRbcGQcVFiwcrtc7c3vopsX96jsJUYPcFMREcRTqAqsqbv2ZRyCJAPLm5NMHCy85E3ZwpT4EAUw9WGU7vMhG6z83hDeKXBWn6Lf',
80
+ path: 'm',
81
+ walletSubPath: '/0/0',
82
+ };
83
+ const fakeWallet = new Wallet(bitgo, {
84
+ id: '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4',
85
+ private: { keychains: [userKeypair, backupKeypair, bitgoKey] },
86
+ });
87
+ describe('Generate Address', function () {
88
+ before(() => nock_1.default.pendingMocks().should.be.empty());
89
+ it('generate first address', function () {
90
+ const idAddress = fakeWallet.generateAddress({ path: '/0/0', segwit: false });
91
+ idAddress.address.should.equal(fakeWallet.id());
92
+ idAddress.chain.should.equal(0);
93
+ idAddress.index.should.equal(0);
94
+ idAddress.chainPath.should.equal('/0/0');
95
+ idAddress.path.should.equal('/0/0');
96
+ idAddress.outputScript.should.equal('a914d682476e9bd54454a885f9dff1e604e99cef43dc87');
97
+ idAddress.redeemScript.should.equal('522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae');
98
+ idAddress.wallet.should.equal(fakeWallet.id());
99
+ });
100
+ it('generate second address', function () {
101
+ const p2shAddress = fakeWallet.generateAddress({ path: '/0/1', segwit: false });
102
+ p2shAddress.address.should.equal('2N5y5RLVqdZi7qp5PmzMdPR6YvQzUqBQFWK');
103
+ p2shAddress.chain.should.equal(0);
104
+ p2shAddress.index.should.equal(1);
105
+ p2shAddress.chainPath.should.equal('/0/1');
106
+ p2shAddress.path.should.equal('/0/1');
107
+ p2shAddress.outputScript.should.equal('a9148b8bd3da68ef0f2465523146bd2de33c86b9c87187');
108
+ p2shAddress.redeemScript.should.equal('522102709edb6a2198d364c485a76b981d12065eabde8aa2d85bd7e7a035f7ecb3579b2102a724efed499c05fdb4da1e139700951fae00c006b3283888bdfd1b46979292242102b32abe44d61986ff57b835e3bd16293d93f303d0d8fb0454e2c9cceda5c4929853ae');
109
+ p2shAddress.wallet.should.equal(fakeWallet.id());
110
+ });
111
+ it('generate change address', function () {
112
+ const p2shAddress = fakeWallet.generateAddress({ path: '/1/0', segwit: false });
113
+ p2shAddress.address.should.equal('2NFj9JrpZc5MyYnCouyREtzNY4eoyKWDfgP');
114
+ p2shAddress.chain.should.equal(1);
115
+ p2shAddress.index.should.equal(0);
116
+ p2shAddress.chainPath.should.equal('/1/0');
117
+ p2shAddress.path.should.equal('/1/0');
118
+ p2shAddress.outputScript.should.equal('a914f69a81fad75ea65ad166da76515291679a4f1ad887');
119
+ p2shAddress.redeemScript.should.equal('5221020b4c4f891a5520f5a0b6818d8d53919552a0d4d806b5fa05c97708079d83737e2102c5cc49bf0331eb0b0890a7e7d87f7e9e0dea515438280dc76834c21d198efe08210370e52cf741ebf4513749d028839d696891eb789ba7a58592cfbc857cdc0a9de753ae');
120
+ p2shAddress.wallet.should.equal(fakeWallet.id());
121
+ });
122
+ it('generate segwit address', function () {
123
+ const segwitAddress = fakeWallet.generateAddress({ path: '/10/0', segwit: true });
124
+ segwitAddress.address.should.equal('2N5EVegRPWnmed2PpqDggZPw7DcNDguRYv8');
125
+ segwitAddress.chain.should.equal(10);
126
+ segwitAddress.index.should.equal(0);
127
+ segwitAddress.chainPath.should.equal('/10/0');
128
+ segwitAddress.path.should.equal('/10/0');
129
+ segwitAddress.outputScript.should.equal('a914837e2adcb6f6386fea3c5d40316b282ccf39121d87');
130
+ segwitAddress.redeemScript.should.equal('0020a62afee1d211c5adb9739f81ed4e36330e6cda651c7bdd314e32ccc465ec2203');
131
+ segwitAddress.witnessScript.should.equal('5221027b30505777a4ed8947b069fcb0116e287995d97278d84da4db6c613270649d3d21034c30e51f1e614cad667815c91d041404c18225d0b2f79e2c0bcb63fd2604316b2103b65ddfc06159b691693390761e75a0b8cc7a65b6ff305d094f3ad972f17953fe53ae');
132
+ segwitAddress.wallet.should.equal(fakeWallet.id());
133
+ });
134
+ });
135
+ describe('Create Transaction', function () {
136
+ let bgUrl, bgUrlTest;
137
+ let fakeProdWallet;
138
+ before(function () {
139
+ nock_1.default.pendingMocks().should.be.empty();
140
+ const prodBitgo = new bitgoAPI_1.BitGoAPI({ env: 'prod', clientConstants: { constants: {} } });
141
+ // prodBitgo.initializeTestVars();
142
+ bgUrl = sdk_core_1.common.Environments[prodBitgo.getEnv()].uri;
143
+ fakeProdWallet = new Wallet(prodBitgo, {
144
+ id: '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4',
145
+ private: { keychains: [userKeypair, backupKeypair, bitgoKey] },
146
+ });
147
+ bgUrlTest = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
148
+ });
149
+ it('extra unspent fetch params', async function () {
150
+ const billingAddress = '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy';
151
+ const customUnspentsFetchParams = { test: 123 };
152
+ const sendAmount = 1e5;
153
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: billingAddress });
154
+ const scope = (0, nock_1.default)(bgUrl)
155
+ .get(`/api/v1/wallet/${fakeProdWallet.id()}/unspents`)
156
+ .query(_.merge(customUnspentsFetchParams, {
157
+ segwit: true,
158
+ target: sendAmount,
159
+ minSize: 0,
160
+ }))
161
+ .reply(200, { unspents: [] });
162
+ await fakeProdWallet
163
+ .createTransaction({
164
+ unspentsFetchParams: customUnspentsFetchParams,
165
+ recipients: { [billingAddress]: sendAmount },
166
+ feeRate: 10000,
167
+ bitgoFee: {
168
+ amount: 0,
169
+ address: '',
170
+ },
171
+ })
172
+ .should.be.rejectedWith('0 unspents available for transaction creation');
173
+ scope.isDone().should.be.true();
174
+ });
175
+ it('forwards recipient addresses to the billing/fee endpoint (dict-form recipients)', async function () {
176
+ // Regression test: sendCoins builds recipients as a dict ({ [address]: amount }), not an
177
+ // array. getBitGoFee must forward the recipient addresses to /billing/fee so the server can
178
+ // waive the PayGo fee on v1->v2 migration transfers. A previous bug read params.recipients
179
+ // (the dict) and called .map on it, which threw for the dict form and never sent recipients.
180
+ const recipientAddress = '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy';
181
+ const sendAmount = 1e5;
182
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
183
+ const unspent = {
184
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
185
+ value_int: 504422,
186
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
187
+ n: 1,
188
+ script_pub_key: {
189
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
190
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
191
+ },
192
+ req_sigs: 1,
193
+ type: 'scripthash',
194
+ confirmations: 9,
195
+ id: 61330229,
196
+ };
197
+ _.extend(unspent, p2shAddress);
198
+ unspent.value = unspent.value_int;
199
+ unspent.tx_hash = unspent.txid;
200
+ unspent.tx_output_n = unspent.n;
201
+ unspent.script = unspent.outputScript;
202
+ let capturedQuery;
203
+ const billingScope = (0, nock_1.default)(bgUrl)
204
+ .get(`/api/v1/wallet/${fakeProdWallet.id()}/billing/fee`)
205
+ .query((actualQuery) => {
206
+ capturedQuery = actualQuery;
207
+ return true;
208
+ })
209
+ // fee: 0 exercises the v1->v2 PayGo waiver path (no bitgoFee output added)
210
+ .reply(200, { fee: 0 });
211
+ // No bitgoFee passed in, so getBitGoFee must hit /billing/fee.
212
+ const transaction = (await fakeProdWallet.createTransaction({
213
+ changeAddress: p2shAddress.address,
214
+ unspents: [unspent],
215
+ recipients: { [recipientAddress]: sendAmount },
216
+ noSplitChange: true,
217
+ forceChangeAtEnd: true,
218
+ feeRate: 10000,
219
+ usePsbt: false,
220
+ }));
221
+ // The recipient address must have reached /billing/fee (this is what the fix restores).
222
+ billingScope.isDone().should.be.true();
223
+ should.exist(capturedQuery);
224
+ const forwardedRecipients = [].concat(capturedQuery['recipients[]'] || []);
225
+ forwardedRecipients.should.deepEqual([recipientAddress]);
226
+ capturedQuery.amount.should.equal(String(sendAmount));
227
+ // fee: 0 => no PayGo fee output added; the tx builds successfully.
228
+ should.exist(transaction.transactionHex);
229
+ should.not.exist(transaction.bitgoFee);
230
+ const tx = utxolib.bitgo.createTransactionFromHex(transaction.transactionHex, utxolib.networks.bitcoin);
231
+ // recipient output + change output, no extra fee output
232
+ tx.outs.length.should.equal(2);
233
+ });
234
+ it('default p2sh', async function () {
235
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
236
+ const unspent = {
237
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
238
+ value: '0.00504422',
239
+ value_int: 504422,
240
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
241
+ n: 1,
242
+ script_pub_key: {
243
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
244
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
245
+ },
246
+ req_sigs: 1,
247
+ type: 'scripthash',
248
+ confirmations: 9,
249
+ id: 61330229,
250
+ };
251
+ _.extend(unspent, p2shAddress);
252
+ unspent.value = unspent.value_int;
253
+ unspent.tx_hash = unspent.txid;
254
+ unspent.tx_output_n = unspent.n;
255
+ unspent.script = unspent.outputScript;
256
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
257
+ const transaction = (await fakeProdWallet.createTransaction({
258
+ changeAddress: p2shAddress.address,
259
+ unspents: [unspent],
260
+ recipients: {},
261
+ noSplitChange: true,
262
+ forceChangeAtEnd: true,
263
+ feeRate: 10000,
264
+ bitgoFee: {
265
+ amount: 0,
266
+ address: '',
267
+ },
268
+ opReturns: { 'BitGo p2sh test': 1000 },
269
+ usePsbt: false,
270
+ }));
271
+ transaction.transactionHex.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b80100000000ffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
272
+ // add first signature
273
+ transaction.keychain = userKeypair;
274
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
275
+ signature1.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000b600473044022021fa73d5fe61ac8942cd70ff4507c574677ce747de5bc46c3dd2e38ec2448fce022047906d2c0154337ab96041e8fb58c243b9bce5f8818fa991643c1260a1859ad80100004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
276
+ // add second signature
277
+ transaction.transactionHex = signature1.tx;
278
+ transaction.keychain = backupKeypair;
279
+ transaction.fullLocalSigning = true;
280
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
281
+ // This transaction has actually worked: https://testnet.smartbit.com.au/tx/a8ccb928169032d6e1f37bf81dfd9ab6d90362a4f84e577397fa690aa711550c
282
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
283
+ // changed, changing the output amounts and thus the tx hex.
284
+ signature2.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000fdfd0000473044022021fa73d5fe61ac8942cd70ff4507c574677ce747de5bc46c3dd2e38ec2448fce022047906d2c0154337ab96041e8fb58c243b9bce5f8818fa991643c1260a1859ad80147304402202ae01f01b5ae0c3fa7d67ac73db81932cb5aca10db16a99063fef45e3f1398cd022055001ba7e163cb350910fc7321ecd7eb6359b321d4c04887484d9c7284b78c4701004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
285
+ });
286
+ it('p2sh PSBT produces same unsigned tx as legacy', async function () {
287
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
288
+ const unspent = {
289
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
290
+ value: '0.00504422',
291
+ value_int: 504422,
292
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
293
+ n: 1,
294
+ script_pub_key: {
295
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
296
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
297
+ },
298
+ req_sigs: 1,
299
+ type: 'scripthash',
300
+ confirmations: 9,
301
+ id: 61330229,
302
+ };
303
+ _.extend(unspent, p2shAddress);
304
+ unspent.value = unspent.value_int;
305
+ unspent.tx_hash = unspent.txid;
306
+ unspent.tx_output_n = unspent.n;
307
+ unspent.script = unspent.outputScript;
308
+ const txParams = {
309
+ changeAddress: p2shAddress.address,
310
+ unspents: [unspent],
311
+ recipients: {},
312
+ noSplitChange: true,
313
+ forceChangeAtEnd: true,
314
+ feeRate: 10000,
315
+ bitgoFee: {
316
+ amount: 0,
317
+ address: '',
318
+ },
319
+ opReturns: { 'BitGo p2sh test': 1000 },
320
+ };
321
+ // Create legacy transaction
322
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
323
+ const legacyTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: false }));
324
+ // Create PSBT transaction (explicitly)
325
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
326
+ const psbtTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: true }));
327
+ // Extract unsigned tx from PSBT and compare
328
+ const psbt = utxolib.bitgo.createPsbtFromHex(psbtTx.transactionHex, utxolib.networks.bitcoin);
329
+ const unsignedTxFromPsbt = psbt.getUnsignedTx().toHex();
330
+ // The unsigned transaction hex should be identical
331
+ legacyTx.transactionHex.should.equal(unsignedTxFromPsbt);
332
+ // Fees should also match
333
+ legacyTx.fee.should.equal(psbtTx.fee);
334
+ // Clean up nock mocks to avoid interference with other tests
335
+ nock_1.default.cleanAll();
336
+ });
337
+ it('segwit PSBT produces same unsigned tx as legacy', async function () {
338
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
339
+ const unspent = {
340
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
341
+ value: '0.18750000',
342
+ value_int: 18750000,
343
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
344
+ n: 0,
345
+ script_pub_key: {
346
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
347
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
348
+ },
349
+ req_sigs: 1,
350
+ type: 'scripthash',
351
+ confirmations: 0,
352
+ id: 61331617,
353
+ };
354
+ _.extend(unspent, segwitAddress);
355
+ unspent.value = unspent.value_int;
356
+ unspent.tx_hash = unspent.txid;
357
+ unspent.tx_output_n = unspent.n;
358
+ unspent.script = unspent.outputScript;
359
+ const txParams = {
360
+ changeAddress: segwitAddress.address,
361
+ unspents: [unspent],
362
+ recipients: {},
363
+ noSplitChange: true,
364
+ forceChangeAtEnd: true,
365
+ feeRate: 10000,
366
+ bitgoFee: {
367
+ amount: 0,
368
+ address: '',
369
+ },
370
+ opReturns: { 'BitGo segwit test': 1000 },
371
+ };
372
+ // Create legacy transaction
373
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
374
+ const legacyTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: false }));
375
+ // Create PSBT transaction (explicitly)
376
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
377
+ const psbtTx = (await fakeProdWallet.createTransaction({ ...txParams, usePsbt: true }));
378
+ // Extract unsigned tx from PSBT and compare
379
+ const psbt = utxolib.bitgo.createPsbtFromHex(psbtTx.transactionHex, utxolib.networks.bitcoin);
380
+ const unsignedTxFromPsbt = psbt.getUnsignedTx().toHex();
381
+ // The unsigned transaction hex should be identical
382
+ legacyTx.transactionHex.should.equal(unsignedTxFromPsbt);
383
+ // Fees should also match
384
+ legacyTx.fee.should.equal(psbtTx.fee);
385
+ // Clean up nock mocks to avoid interference with other tests
386
+ nock_1.default.cleanAll();
387
+ });
388
+ it('p2sh with PSBT format', async function () {
389
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
390
+ const unspent = {
391
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
392
+ value: '0.00504422',
393
+ value_int: 504422,
394
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
395
+ n: 1,
396
+ script_pub_key: {
397
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
398
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
399
+ },
400
+ req_sigs: 1,
401
+ type: 'scripthash',
402
+ confirmations: 9,
403
+ id: 61330229,
404
+ };
405
+ _.extend(unspent, p2shAddress);
406
+ unspent.value = unspent.value_int;
407
+ unspent.tx_hash = unspent.txid;
408
+ unspent.tx_output_n = unspent.n;
409
+ unspent.script = unspent.outputScript;
410
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
411
+ const transaction = (await fakeProdWallet.createTransaction({
412
+ changeAddress: p2shAddress.address,
413
+ unspents: [unspent],
414
+ recipients: {},
415
+ noSplitChange: true,
416
+ forceChangeAtEnd: true,
417
+ feeRate: 10000,
418
+ bitgoFee: {
419
+ amount: 0,
420
+ address: '',
421
+ },
422
+ opReturns: { 'BitGo p2sh test': 1000 },
423
+ usePsbt: true, // Explicitly request PSBT format
424
+ }));
425
+ // Verify PSBT format is returned in transactionHex
426
+ should.exist(transaction.transactionHex);
427
+ should.ok(utxolib.bitgo.isPsbt(transaction.transactionHex));
428
+ should.not.exist(transaction.unspents);
429
+ // Parse and validate the PSBT
430
+ const psbt = utxolib.bitgo.createPsbtFromHex(transaction.transactionHex, utxolib.networks.bitcoin);
431
+ psbt.data.inputs.length.should.equal(1);
432
+ psbt.data.outputs.length.should.equal(2); // OP_RETURN + change
433
+ // Verify input has required PSBT metadata
434
+ const input = psbt.data.inputs[0];
435
+ should.exist(input.witnessUtxo);
436
+ should.exist(input.redeemScript);
437
+ should.exist(input.bip32Derivation);
438
+ input.bip32Derivation.length.should.equal(3); // user, backup, bitgo
439
+ // Verify globalXpubs are set
440
+ should.exist(psbt.data.globalMap.globalXpub);
441
+ psbt.data.globalMap.globalXpub.length.should.equal(3);
442
+ // Sign with user key - auto-detects PSBT in transactionHex
443
+ const signedResult = (await fakeProdWallet.signTransaction({
444
+ transactionHex: transaction.transactionHex,
445
+ keychain: userKeypair,
446
+ }));
447
+ should.exist(signedResult.tx);
448
+ // Parse signed PSBT and verify signature
449
+ const signedPsbt = utxolib.bitgo.createPsbtFromHex(signedResult.tx, utxolib.networks.bitcoin);
450
+ should.ok(signedPsbt.validateSignaturesOfInputHD(0, utxolib.bip32.fromBase58(userKeypair.xpub)));
451
+ });
452
+ it('segwit with PSBT format', async function () {
453
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
454
+ const unspent = {
455
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
456
+ value: '0.18750000',
457
+ value_int: 18750000,
458
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
459
+ n: 0,
460
+ script_pub_key: {
461
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
462
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
463
+ },
464
+ req_sigs: 1,
465
+ type: 'scripthash',
466
+ confirmations: 0,
467
+ id: 61331617,
468
+ };
469
+ _.extend(unspent, segwitAddress);
470
+ unspent.value = unspent.value_int;
471
+ unspent.tx_hash = unspent.txid;
472
+ unspent.tx_output_n = unspent.n;
473
+ unspent.script = unspent.outputScript;
474
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
475
+ const transaction = (await fakeProdWallet.createTransaction({
476
+ changeAddress: segwitAddress.address,
477
+ unspents: [unspent],
478
+ recipients: {},
479
+ noSplitChange: true,
480
+ forceChangeAtEnd: true,
481
+ feeRate: 10000,
482
+ bitgoFee: {
483
+ amount: 0,
484
+ address: '',
485
+ },
486
+ opReturns: { 'BitGo segwit test': 1000 },
487
+ usePsbt: true, // Explicitly request PSBT format
488
+ }));
489
+ // Verify PSBT format is returned in transactionHex
490
+ should.exist(transaction.transactionHex);
491
+ should.ok(utxolib.bitgo.isPsbt(transaction.transactionHex));
492
+ // Parse and validate the PSBT
493
+ const psbt = utxolib.bitgo.createPsbtFromHex(transaction.transactionHex, utxolib.networks.bitcoin);
494
+ psbt.data.inputs.length.should.equal(1);
495
+ // Verify input has segwit PSBT metadata
496
+ const input = psbt.data.inputs[0];
497
+ should.exist(input.witnessUtxo);
498
+ should.exist(input.witnessScript);
499
+ should.exist(input.redeemScript);
500
+ should.exist(input.bip32Derivation);
501
+ // Sign with user key - auto-detects PSBT in transactionHex
502
+ const signedResult = (await fakeProdWallet.signTransaction({
503
+ transactionHex: transaction.transactionHex,
504
+ keychain: userKeypair,
505
+ }));
506
+ should.exist(signedResult.tx);
507
+ // Parse signed PSBT and verify signature
508
+ const signedPsbt = utxolib.bitgo.createPsbtFromHex(signedResult.tx, utxolib.networks.bitcoin);
509
+ should.ok(signedPsbt.validateSignaturesOfInputHD(0, utxolib.bip32.fromBase58(userKeypair.xpub)));
510
+ });
511
+ it('BCH p2sh', async function () {
512
+ const p2shAddress = fakeProdWallet.generateAddress({ path: '/0/13', segwit: false });
513
+ const unspent = {
514
+ addresses: ['2NCEDmmKNNnqKvnWw7pE3RLzuFe5aHHVy1X'],
515
+ value: '0.00504422',
516
+ value_int: 504422,
517
+ txid: 'b816ded89c3d8d5021b01097f4a3129a6a68a5cb7c886e97945f4205cba5de44',
518
+ n: 1,
519
+ script_pub_key: {
520
+ asm: 'OP_HASH160 d039cb3344294a5a384a5508a006444c420cbc11 OP_EQUAL',
521
+ hex: 'a914d039cb3344294a5a384a5508a006444c420cbc1187',
522
+ },
523
+ req_sigs: 1,
524
+ type: 'scripthash',
525
+ confirmations: 9,
526
+ id: 61330229,
527
+ };
528
+ _.extend(unspent, p2shAddress);
529
+ unspent.value = unspent.value_int;
530
+ unspent.tx_hash = unspent.txid;
531
+ unspent.tx_output_n = unspent.n;
532
+ unspent.script = unspent.outputScript;
533
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
534
+ const transaction = (await fakeProdWallet.createTransaction({
535
+ changeAddress: p2shAddress.address,
536
+ unspents: [unspent],
537
+ recipients: {},
538
+ noSplitChange: true,
539
+ forceChangeAtEnd: true,
540
+ feeRate: 10000,
541
+ bitgoFee: {
542
+ amount: 0,
543
+ address: '',
544
+ },
545
+ opReturns: { 'BitGo p2sh test': 1000 },
546
+ usePsbt: false,
547
+ }));
548
+ transaction.transactionHex.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b80100000000ffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
549
+ // add first signature
550
+ transaction.keychain = userKeypair;
551
+ transaction.forceBCH = true;
552
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
553
+ signature1.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000b60047304402206221a97f081d87e02e3b14988a64861811a6a8de4f11f74f5aaea45981cf612e022077a08a5bd7d781e79838afbb126af2e48802fefad660afdbd8805f5e598ed5884100004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
554
+ // add second signature
555
+ transaction.transactionHex = signature1.tx;
556
+ transaction.keychain = backupKeypair;
557
+ transaction.fullLocalSigning = true;
558
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
559
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/a8ccb928169032d6e1f37bf81dfd9ab6d90362a4f84e577397fa690aa711550c
560
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
561
+ // changed, changing the output amounts and thus the tx hex.
562
+ signature2.tx.should.equal('010000000144dea5cb05425f94976e887ccba5686a9a12a3f49710b021508d3d9cd8de16b801000000fdfe000047304402206221a97f081d87e02e3b14988a64861811a6a8de4f11f74f5aaea45981cf612e022077a08a5bd7d781e79838afbb126af2e48802fefad660afdbd8805f5e598ed5884148304502210082bc546293858459f3895db24c85ccf37505c56f8faf4bb8f78cf40135bc2f2b02203dc1c78d7c7ceaf6b924eca3c39b95e8a227b069a07047581273136b47ca7ac441004c695221031cd227e40ad61b4e137109cb2845eb6f5a584ed5c67d9d3135cdaa5045a842ea2103a2e7b54c7b2da0992555353b8e26c6acff4248f4351f08787bf3e2efc94b658321025c2a6cde33c2d73ccf12eecf64c54f08f722c2f073824498950695e9883b141253aeffffffff02e803000000000000116a0f426974476f2070327368207465737422a107000000000017a914d039cb3344294a5a384a5508a006444c420cbc118700000000');
563
+ });
564
+ it('default segwit', async function () {
565
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
566
+ const unspent = {
567
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
568
+ value: '0.18750000',
569
+ value_int: 18750000,
570
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
571
+ n: 0,
572
+ script_pub_key: {
573
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
574
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
575
+ },
576
+ req_sigs: 1,
577
+ type: 'scripthash',
578
+ confirmations: 0,
579
+ id: 61331617,
580
+ };
581
+ _.extend(unspent, segwitAddress);
582
+ unspent.value = unspent.value_int;
583
+ unspent.tx_hash = unspent.txid;
584
+ unspent.tx_output_n = unspent.n;
585
+ unspent.script = unspent.outputScript;
586
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
587
+ const transaction = (await fakeProdWallet.createTransaction({
588
+ changeAddress: segwitAddress.address,
589
+ unspents: [unspent],
590
+ recipients: {},
591
+ noSplitChange: true,
592
+ forceChangeAtEnd: true,
593
+ feeRate: 10000,
594
+ bitgoFee: {
595
+ amount: 0,
596
+ address: '',
597
+ },
598
+ opReturns: { 'BitGo segwit test': 1000 },
599
+ usePsbt: false,
600
+ }));
601
+ transaction.transactionHex.should.equal('01000000011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000000ffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a8700000000');
602
+ // add first signature
603
+ transaction.keychain = userKeypair;
604
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
605
+ signature1.tx.should.equal('010000000001011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000023220020440e858228b753544b4c57e300296b55717f811053883f9be9b6a712eacd931cffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a870500483045022100bf3a8914a1bfe92661f27ca37c0d6b5c0b3c7353614c955646929f2e7eb89ffe02202d556b0ffab37c104bae67406ca16f8859cfa37c6a40f2013d89afcecd5594f3010000695221032c505fc8a1e4b56811b27366a371e61c9faf565dd2fabaff7a70eac19c32157c210251160b583bd5dc0f0d48096505131c4347ab65b4f21ed57d76c38157499c003d2102679712d62a2560917cc43fd2cc3a1b9b61f528c88bc64905bae6ee079e60609f53ae00000000');
606
+ // add second signature
607
+ transaction.transactionHex = signature1.tx;
608
+ transaction.keychain = backupKeypair;
609
+ transaction.fullLocalSigning = true;
610
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
611
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/d67266f1de905baaee750011fa4b3d88a8e3a1758d5173a659c67709488dde07
612
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
613
+ // changed, changing the output amounts and thus the tx hex.
614
+ signature2.tx.should.equal('010000000001011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000023220020440e858228b753544b4c57e300296b55717f811053883f9be9b6a712eacd931cffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a870500483045022100bf3a8914a1bfe92661f27ca37c0d6b5c0b3c7353614c955646929f2e7eb89ffe02202d556b0ffab37c104bae67406ca16f8859cfa37c6a40f2013d89afcecd5594f30147304402205cf8d2f2be6ce083d35654bdc3fa85d7e71b227d457e9245bb603b21e7b5165102203ea686226db8320e08c26bfb304048b3a9473d0e05797d3658dacb2f09a2b51c0100695221032c505fc8a1e4b56811b27366a371e61c9faf565dd2fabaff7a70eac19c32157c210251160b583bd5dc0f0d48096505131c4347ab65b4f21ed57d76c38157499c003d2102679712d62a2560917cc43fd2cc3a1b9b61f528c88bc64905bae6ee079e60609f53ae00000000');
615
+ });
616
+ it('creates an unsigned tx made of uncompressed public keys of v1 safe wallet', async function () {
617
+ const { address, redeemScript, scriptPubKey } = await (0, fixtures_1.getFixture)(`${__dirname}/fixtures/sign-transaction.json`);
618
+ const testBitgo = new bitgoAPI_1.BitGoAPI({ env: 'test', clientConstants: { constants: {} } });
619
+ const fakeTestV1SafeWallet = new Wallet(testBitgo, {
620
+ id: address,
621
+ private: { safe: { redeemScript } },
622
+ });
623
+ const unspentsToSpend = [
624
+ {
625
+ value: 100000,
626
+ redeemScript,
627
+ script: scriptPubKey,
628
+ tx_hash: 'a55d11dc8b701bd19601fbfe711a1e465fc8f128ec4474e78e1fd087e808e5fe',
629
+ tx_output_n: 0,
630
+ confirmations: 1,
631
+ },
632
+ {
633
+ value: 100000,
634
+ redeemScript,
635
+ script: scriptPubKey,
636
+ tx_hash: '48fb879cec879356045a331937023aed859f5dc5db955a1dc8a5ccf29f49d108',
637
+ tx_output_n: 0,
638
+ confirmations: 1,
639
+ },
640
+ ];
641
+ const recipients = {
642
+ '2MyGxrhLC4kRfuVjLqCVYFtC7DchhgMCiNz': 191340, // purposely set to simulate a sweep transaction
643
+ };
644
+ const scope = (0, nock_1.default)(bgUrlTest)
645
+ .post('/api/v1/billing/address')
646
+ .reply(200, { address: '2N3L9cu9WN2Df7Xvb1Y8owokuDVj5Hdyv4i' });
647
+ const result = await fakeTestV1SafeWallet.createTransaction({
648
+ recipients,
649
+ unspents: unspentsToSpend,
650
+ feeRate: 10000, // 10 sat/byte
651
+ bitgoFee: {
652
+ amount: 0,
653
+ address: '',
654
+ },
655
+ usePsbt: false,
656
+ });
657
+ scope.isDone().should.be.true();
658
+ result.estimatedSize.should.equal(866);
659
+ result.fee.should.equal(8660);
660
+ // This should equal to 1 because this is a sweep transaction but due to hardcoded addition of
661
+ // 1 change output in transactionBuilder, it is 2.
662
+ // Because of this the estimated size of the transactions is more than what it actually is in the hex.
663
+ result.txInfo.nOutputs.should.equal(2);
664
+ });
665
+ it('signs an unsigned tx made of uncompressed public keys of v1 safe wallet & verifies signatures', async function () {
666
+ const { address, redeemScript, scriptPubKey, userKeyWIF: userSigningKey, bitgoKeyWIF: bitgoSigningKey, unsignedTxHex, halfSignedTxHex, fullSignedTxHex, } = await (0, fixtures_1.getFixture)(`${__dirname}/fixtures/sign-transaction.json`);
667
+ const testBitgo = new bitgoAPI_1.BitGoAPI({ env: 'test', clientConstants: { constants: {} } });
668
+ const fakeTestV1SafeWallet = new Wallet(testBitgo, {
669
+ id: address,
670
+ private: { safe: { redeemScript } },
671
+ });
672
+ const unspentsToSpend = [
673
+ { value: 100000, redeemScript, script: scriptPubKey },
674
+ { value: 100000, redeemScript, script: scriptPubKey },
675
+ ];
676
+ const halfSignedTx = await fakeTestV1SafeWallet.signTransaction({
677
+ transactionHex: unsignedTxHex,
678
+ signingKey: userSigningKey,
679
+ unspents: unspentsToSpend,
680
+ validate: true,
681
+ });
682
+ halfSignedTx.tx.should.equal(halfSignedTxHex);
683
+ const fullSignedTx = await fakeTestV1SafeWallet.signTransaction({
684
+ transactionHex: halfSignedTxHex,
685
+ signingKey: bitgoSigningKey,
686
+ unspents: unspentsToSpend,
687
+ validate: true,
688
+ fullLocalSigning: true,
689
+ });
690
+ // Upon calling txb.build() instead after getting 2 valid signatures, we get a valid full signed tx that was broadcast
691
+ // and confirmed on testnet here: https://mempool.space/testnet/tx/bde09f1bd5e6661c28d90e4c96291853e21ba15ab42f3e4a30719decb73e791b
692
+ // It's present in the fullSignedTxHexBuildComplete property of the fixture.
693
+ fullSignedTx.tx.should.equal(fullSignedTxHex);
694
+ });
695
+ it('BCH segwit should fail', async function () {
696
+ const segwitAddress = fakeProdWallet.generateAddress({ path: '/10/13', segwit: true });
697
+ const unspent = {
698
+ addresses: ['2MxKkH8yB3S9YWmTQRbvmborYQyQnH5petP'],
699
+ value: '0.18750000',
700
+ value_int: 18750000,
701
+ txid: '7d282878a85daee5d46e043827daed57596d75d1aa6e04fd0c09a36f9130881f',
702
+ n: 0,
703
+ script_pub_key: {
704
+ asm: 'OP_HASH160 37b393fce627a0ec634eb543dda1e608e2d1c78a OP_EQUAL',
705
+ hex: 'a91437b393fce627a0ec634eb543dda1e608e2d1c78a87',
706
+ },
707
+ req_sigs: 1,
708
+ type: 'scripthash',
709
+ confirmations: 0,
710
+ id: 61331617,
711
+ };
712
+ _.extend(unspent, segwitAddress);
713
+ unspent.value = unspent.value_int;
714
+ unspent.tx_hash = unspent.txid;
715
+ unspent.tx_output_n = unspent.n;
716
+ unspent.script = unspent.outputScript;
717
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, { address: '2MswQjkvN6oWYdE7L2brJ5cAAMjPmG59oco' });
718
+ const transaction = (await fakeProdWallet.createTransaction({
719
+ changeAddress: segwitAddress.address,
720
+ unspents: [unspent],
721
+ recipients: {},
722
+ noSplitChange: true,
723
+ forceChangeAtEnd: true,
724
+ feeRate: 10000,
725
+ bitgoFee: {
726
+ amount: 0,
727
+ address: '',
728
+ },
729
+ opReturns: { 'BitGo segwit test': 1000 },
730
+ usePsbt: false,
731
+ }));
732
+ transaction.transactionHex.should.equal('01000000011f8830916fa3090cfd046eaad1756d5957edda2738046ed4e5ae5da87828287d0000000000ffffffff02e803000000000000136a11426974476f2073656777697420746573740e0f1e010000000017a91437b393fce627a0ec634eb543dda1e608e2d1c78a8700000000');
733
+ // add first signature
734
+ transaction.keychain = userKeypair;
735
+ transaction.forceBCH = true;
736
+ (() => fakeProdWallet.signTransaction(transaction)).should.throw('BCH does not support segwit inputs');
737
+ });
738
+ it('mixed p2sh & segwit', async function () {
739
+ const p2shAddress = fakeWallet.generateAddress({ path: '/0/14', segwit: false });
740
+ const segwitAddress = fakeWallet.generateAddress({ path: '/10/14', segwit: true });
741
+ const p2shUnspent = {
742
+ addresses: ['2N533fqgyPYKVD892nBRaYmFHbbTykhYSEw'],
743
+ value: '2.99996610',
744
+ value_int: 299996610,
745
+ txid: 'f654ce0a5be3f12df7fecf4ee777b6d86b5aa8c710ef6946ec121206b4f8757c',
746
+ n: 1,
747
+ script_pub_key: {
748
+ asm: 'OP_HASH160 8153e7a35508088b6cf599226792c7de2dbff252 OP_EQUAL',
749
+ hex: 'a9148153e7a35508088b6cf599226792c7de2dbff25287',
750
+ },
751
+ req_sigs: 1,
752
+ type: 'scripthash',
753
+ confirmations: 0,
754
+ id: 61331263,
755
+ };
756
+ const segwitUnspent = {
757
+ addresses: ['2NBtpXcDruf3zRutmF4AbCMFNQHXsGNP6kT'],
758
+ value: '1.50000000',
759
+ value_int: 150000000,
760
+ txid: 'a4409c3f042fae67b890ac3df40ef0db03539c67331fd7e9260511893b4f9f24',
761
+ n: 0,
762
+ script_pub_key: {
763
+ asm: 'OP_HASH160 cc8e7cbf481389d3183a590acfa6aa66eb97c8e1 OP_EQUAL',
764
+ hex: 'a914cc8e7cbf481389d3183a590acfa6aa66eb97c8e187',
765
+ },
766
+ req_sigs: 1,
767
+ type: 'scripthash',
768
+ confirmations: 0,
769
+ id: 61330882,
770
+ };
771
+ const addresses = [p2shAddress, segwitAddress];
772
+ const unspents = [p2shUnspent, segwitUnspent].map((unspent, index) => {
773
+ const address = addresses[index];
774
+ _.extend(unspent, address);
775
+ unspent.value = unspent.value_int;
776
+ unspent.tx_hash = unspent.txid;
777
+ unspent.tx_output_n = unspent.n;
778
+ unspent.script = unspent.outputScript;
779
+ return unspent;
780
+ });
781
+ const transaction = (await fakeWallet.createTransaction({
782
+ changeAddress: p2shAddress.address,
783
+ unspents: unspents,
784
+ recipients: {},
785
+ noSplitChange: true,
786
+ forceChangeAtEnd: true,
787
+ feeRate: 10000,
788
+ opReturns: { 'BitGo mixed p2sh & segwit test': 400000000 },
789
+ bitgoFee: {
790
+ amount: 81760,
791
+ address: '2ND7jQR5itjGTbh3DKgbpZWSY9ungDrwcwb',
792
+ },
793
+ usePsbt: false,
794
+ }));
795
+ transaction.transactionHex.should.equal('01000000027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f60100000000ffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a40000000000ffffffff030084d71700000000206a1e426974476f206d6978656420703273682026207365677769742074657374b08ff9020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700000000');
796
+ // add first signature
797
+ transaction.keychain = userKeypair;
798
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
799
+ signature1.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000b700483045022100ffc45d93cbaf4c1c850e21f277c5b311d3e3957f1338955cb165d72a768a054c022052020593b36781eea00a9f8dcbeb76608f920c7a933a9088318ab2f70c11e1d90100004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff030084d71700000000206a1e426974476f206d6978656420703273682026207365677769742074657374b08ff9020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700050047304402205898bee711467c09a5e22e1dcb1a11fce1a0d6ea129d911f813f87c7d45e067b02202f69fb118bbf0b072ed26d72cf8073e7acd66c205419a4a00f86a7ba0f6e3dd6010000695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
800
+ // add second signature
801
+ transaction.transactionHex = signature1.tx;
802
+ transaction.keychain = backupKeypair;
803
+ transaction.fullLocalSigning = true;
804
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
805
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/e2f696bcba91a376c36bb525df8c367938f6e2fd6344c90587bf12802091124c
806
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
807
+ // changed, changing the output amounts and thus the tx hex.
808
+ signature2.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000fdff0000483045022100ffc45d93cbaf4c1c850e21f277c5b311d3e3957f1338955cb165d72a768a054c022052020593b36781eea00a9f8dcbeb76608f920c7a933a9088318ab2f70c11e1d9014830450221008254d100401a3a831ed019e1662dbd90b96c6c4072b81ce640d152bc29295c10022013f86c5af5716234999a7bd6e94fc8f428f7697cc3138b3649d0ec4dd8681bc701004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff030084d71700000000206a1e426974476f206d6978656420703273682026207365677769742074657374b08ff9020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700050047304402205898bee711467c09a5e22e1dcb1a11fce1a0d6ea129d911f813f87c7d45e067b02202f69fb118bbf0b072ed26d72cf8073e7acd66c205419a4a00f86a7ba0f6e3dd60147304402207713d671b45989688e2665c2b11ab7e5ea8d57eb14f9da233c095dabe441308d022069521b5aeb071b07a70a7197a0c2bbc40a23ae63a04160cf3627250c4ba4c40f0100695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
809
+ });
810
+ it('should send to bech32 recipient', async function () {
811
+ const p2shAddress = fakeWallet.generateAddress({ path: '/0/14', segwit: false });
812
+ const segwitAddress = fakeWallet.generateAddress({ path: '/10/14', segwit: true });
813
+ const p2shUnspent = {
814
+ addresses: ['2N533fqgyPYKVD892nBRaYmFHbbTykhYSEw'],
815
+ value: '2.99996610',
816
+ value_int: 299996610,
817
+ txid: 'f654ce0a5be3f12df7fecf4ee777b6d86b5aa8c710ef6946ec121206b4f8757c',
818
+ n: 1,
819
+ script_pub_key: {
820
+ asm: 'OP_HASH160 8153e7a35508088b6cf599226792c7de2dbff252 OP_EQUAL',
821
+ hex: 'a9148153e7a35508088b6cf599226792c7de2dbff25287',
822
+ },
823
+ req_sigs: 1,
824
+ type: 'scripthash',
825
+ confirmations: 0,
826
+ id: 61331263,
827
+ };
828
+ const segwitUnspent = {
829
+ addresses: ['2NBtpXcDruf3zRutmF4AbCMFNQHXsGNP6kT'],
830
+ value: '1.50000000',
831
+ value_int: 150000000,
832
+ txid: 'a4409c3f042fae67b890ac3df40ef0db03539c67331fd7e9260511893b4f9f24',
833
+ n: 0,
834
+ script_pub_key: {
835
+ asm: 'OP_HASH160 cc8e7cbf481389d3183a590acfa6aa66eb97c8e1 OP_EQUAL',
836
+ hex: 'a914cc8e7cbf481389d3183a590acfa6aa66eb97c8e187',
837
+ },
838
+ req_sigs: 1,
839
+ type: 'scripthash',
840
+ confirmations: 0,
841
+ id: 61330882,
842
+ };
843
+ const addresses = [p2shAddress, segwitAddress];
844
+ const unspents = [p2shUnspent, segwitUnspent].map((unspent, index) => {
845
+ const address = addresses[index];
846
+ _.extend(unspent, address);
847
+ unspent.value = unspent.value_int;
848
+ unspent.tx_hash = unspent.txid;
849
+ unspent.tx_output_n = unspent.n;
850
+ unspent.script = unspent.outputScript;
851
+ return unspent;
852
+ });
853
+ const transaction = (await fakeWallet.createTransaction({
854
+ changeAddress: p2shAddress.address,
855
+ unspents: unspents,
856
+ recipients: { tb1qguzyk4w6kaqtpsczs5aj0w8r7598jq36egm8e98wqph3rwmex68seslgsg: 300000 },
857
+ noSplitChange: true,
858
+ forceChangeAtEnd: true,
859
+ feeRate: 10000,
860
+ opReturns: { 'BitGo mixed p2sh & segwit test': 400000000 },
861
+ bitgoFee: {
862
+ amount: 81760,
863
+ address: '2ND7jQR5itjGTbh3DKgbpZWSY9ungDrwcwb',
864
+ },
865
+ usePsbt: false,
866
+ }));
867
+ transaction.transactionHex.should.equal('01000000027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f60100000000ffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a40000000000ffffffff04e09304000000000022002047044b55dab740b0c302853b27b8e3f50a79023aca367c94ee006f11bb79368f0084d71700000000206a1e426974476f206d69786564207032736820262073656777697420746573747cfaf4020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba98700000000');
868
+ // add first signature
869
+ transaction.keychain = userKeypair;
870
+ const signature1 = (await fakeProdWallet.signTransaction(transaction));
871
+ signature1.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000b7004830450221008809377634e667d6e19f38a138a55b2b6370312af76a5ca3b776df61fc719617022021d90347b9085ab71a76c8400f984e322c15451ecc673dd37de30887436d37b40100004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff04e09304000000000022002047044b55dab740b0c302853b27b8e3f50a79023aca367c94ee006f11bb79368f0084d71700000000206a1e426974476f206d69786564207032736820262073656777697420746573747cfaf4020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba9870005004830450221008b95ac83e44c727b79ffbf4571171925d06f883a05c122b3b33c055f0bffa70102207b5ee3412ea8a5cec4a5c386f1b464ab68d531c6c697077bc462c05eb44a2832010000695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
872
+ // add second signature
873
+ transaction.transactionHex = signature1.tx;
874
+ transaction.keychain = backupKeypair;
875
+ transaction.fullLocalSigning = true;
876
+ const signature2 = (await fakeProdWallet.signTransaction(transaction));
877
+ console.log('signature1 ' + JSON.stringify(signature2));
878
+ // this transaction has actually worked: https://testnet.smartbit.com.au/tx/e2f696bcba91a376c36bb525df8c367938f6e2fd6344c90587bf12802091124c
879
+ // Note that the tx hex below no longer corresponds to the above transaction because our fee estimation has
880
+ // changed, changing the output amounts and thus the tx hex.
881
+ signature2.tx.should.equal('010000000001027c75f8b4061212ec4669ef10c7a85a6bd8b677e74ecffef72df1e35b0ace54f601000000fdfe00004830450221008809377634e667d6e19f38a138a55b2b6370312af76a5ca3b776df61fc719617022021d90347b9085ab71a76c8400f984e322c15451ecc673dd37de30887436d37b40147304402205a58e602042b8e8a5da509d19ce31050147dd0ffcfbe2bb337c23d4c88f4cc41022075bfa455d1f74e30fbd9c786cd4811a1defe54310f235b4193ce4ffa0e8309a101004c69522103da95b28a13aa2d4bb490d70628e2e5d912461d375fef381aadd89dc1256220752103121287a510c5f32e8ba72d2479e90eb52ba44a467173df339feb0ff215f100e32102977cdfbee76066ae739db72d55371ad49dc6712fb8f2f3f69bb1a4c2422b0b1a53aeffffffff249f4f3b89110526e9d71f33679c5303dbf00ef43dac90b867ae2f043f9c40a400000000232200208b91aa03eb0f7f31e3917088084168ba5282a915e7cde0a5a934b7ea02eb057bffffffff04e09304000000000022002047044b55dab740b0c302853b27b8e3f50a79023aca367c94ee006f11bb79368f0084d71700000000206a1e426974476f206d69786564207032736820262073656777697420746573747cfaf4020000000017a9148153e7a35508088b6cf599226792c7de2dbff25287603f01000000000017a914d9f7be47975c036f94228b0bfd70701912758ba9870005004830450221008b95ac83e44c727b79ffbf4571171925d06f883a05c122b3b33c055f0bffa70102207b5ee3412ea8a5cec4a5c386f1b464ab68d531c6c697077bc462c05eb44a283201473044022053690234582a6911a28cae9f534c980b7d7918749a7413c1c59327debf16ff0b022056175f5c27a363416b2ce4791aefc3d55545cacbd0527202e869e1127fc2f24d0100695221030780186c0be5df0d2d62cf54cc2f3d2c09911e377aa95b5fe875fa352aed0a592103f3237edd2d87010e8fe9f43f34e8c63de6384283de909795d62af4ddb4d579542102ad03de5504ef947e4e6ee2fa6b15d150d553c21275f49f2ce2359d9fdedb9ade53ae00000000');
882
+ });
883
+ });
884
+ describe('Send Many', function () {
885
+ it('responds with proper fee and fee rate', async function () {
886
+ const params = {
887
+ recipients: [
888
+ {
889
+ address: '2MutpXVYs8Lyk74pVDn3eAG7xnK4Wc2kjTQ',
890
+ amount: 300000,
891
+ },
892
+ ],
893
+ };
894
+ const unspents = [
895
+ {
896
+ value: 8170,
897
+ },
898
+ {
899
+ value: 800000,
900
+ },
901
+ ];
902
+ const createAndSignResponse = {
903
+ bitgoFee: 0,
904
+ travelInfos: [],
905
+ unspents,
906
+ tx: 'halfsignedhex',
907
+ };
908
+ sinon.stub(fakeWallet, 'createAndSignTransaction').returns(Promise.resolve(createAndSignResponse));
909
+ const getSendTxResponse = () => ({
910
+ status: 'accepted',
911
+ tx: '0100000000010228b5c3e2789d4770fc397ec79fa7255f86235297c5a04def678b481b8b09e81b0100000023220020b3bbe067960be39501f365b8999d53f2a8285d8d9836f61fad020e6a4a9e26fdffffffff1510e90411a86c49f2a52546a32a03febde2bc604741f0e85dc47adec33f515900000000fdfd0000483045022100a44bbf97b155c57703862be69d2b20c4b2ab9e94f402595880bf74402ccc87e202200a4aaf98f939b65c98ca08eb96074c222ecb1fc37e359b1d67a05f1c56dedfc001473044022003f3989a14284f132bbb550118c20256d4ea737704123a29955acc1d03ea6eb7022017223da7edcf73076d89875aa33360aa6a12141807f683c6c1b9a5a0d3ff6019014c695221025789857cc8be110ff4cbf354b52dd0e7e9326c6bfe0aee6c30c1ee69660c3dc02102f58f1b1516d05814ae688ca701856695e27050e3e16d3a2351284d7af84498882102385c7bcec3f38c13e87b558aebf2f20a8928e7ecbe11e7c3a47792bc8e33fe8853aeffffffff02e09304000000000017a9141d0c791cec3af1f37808d42f04593095d6fdea268705bc07000000000017a914d8c720f646c7c56c5467248e47c72dc0b2d30bbc87040047304402201eaa1359fffd3bdec5b48268bd2f15193a299c22b1970356f390883473324651022074186232f02245af9c0977031448c2c99e7b7e2b05b2ba4b32c3227d8ca1494e01483045022100bd61b37051c28533ea0b00dda75b1c4f1dee1b683bb7351b2d8dd720f6dfbe1102203acc4cf9d2dd44b294aa25812e99e7d8eb3730e4ff6f889d3cdcd525195750b8016952210219d093c18c27cb547737b4a49dddac9c3412b10e9f880eb30053c3eba81928542103747118892cac1b4da11526fc4ebeebe168dae0907cefb1a1812541cd46b07602210339f73b6750f8f91efd484b5aa2974321a6cc2776d5bd78b9cfb5fe18e3b2d66253ae005a9e1600',
912
+ hash: 'f8df43c2c650b3bb11277aee4531db99a715fa3b9dfd3d45a8d171342c1bf780',
913
+ instant: false,
914
+ });
915
+ const expectedResult = Object.assign({
916
+ fee: 1285,
917
+ feeRate: 2519.607843137255,
918
+ }, getSendTxResponse());
919
+ sinon.stub(fakeWallet, 'sendTransaction').resolves(getSendTxResponse());
920
+ const result = (await fakeWallet.sendMany(params));
921
+ result.tx.should.equal(expectedResult.tx);
922
+ result.fee.should.equal(expectedResult.fee);
923
+ result.feeRate.should.equal(expectedResult.feeRate);
924
+ });
925
+ });
926
+ describe('Accelerate Transaction (server mocked)', function accelerateTxMockedDescribe() {
927
+ let wallet;
928
+ let bgUrl;
929
+ let explorerUrl;
930
+ let minChangeSize;
931
+ let parentTxId = '6a74b74df4991d93c32d751336c85b5f2d1ee544a2dfbae2e5f4beb4f914e5e0';
932
+ const outputIdx = 0;
933
+ const outputAddress = '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4';
934
+ const unrelatedTxId = '08f5e0b4acb5ab8245229dfe161ce4ca0da1ec983e7a34b09e72f56979a467df';
935
+ const walletId = '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4';
936
+ /**
937
+ * Helper function to get the parent transaction ID from a transaction input
938
+ *
939
+ * This function converts `hash` (which is a Buffer object) to a usable txid string.
940
+ * The issue is that the bytes are stored in reverse order in the buffer, so
941
+ * the simple approach of just comparing the hex strings doesn't work.
942
+ * Instead, the Buffer is copied to a new Buffer object, the new Buffer
943
+ * object is reversed in-place, and then the new Buffer is converted to a
944
+ * hex string. After this, the result is a hex string which is the parent txid
945
+ *
946
+ * @param hash a bitcoinjs-lib transaction object's input hash
947
+ */
948
+ function inputParentTxId({ hash }) {
949
+ return Buffer.from(hash).reverse().toString('hex');
950
+ }
951
+ before(function accelerateTxMockedBefore() {
952
+ nock_1.default.pendingMocks().should.be.empty();
953
+ bitgo = new bitgoAPI_1.BitGoAPI({ env: 'mock', clientConstants: { constants: {} } });
954
+ // bitgo.initializeTestVars();
955
+ bitgo.setValidate(false);
956
+ wallet = new Wallet(bitgo, { id: walletId, private: { keychains: [userKeypair, backupKeypair, bitgoKey] } });
957
+ wallet.bitgo = bitgo;
958
+ bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
959
+ explorerUrl = sdk_core_1.common.Environments[bitgo.getEnv()].btcExplorerBaseUrl;
960
+ // try to get the min change size from the server, otherwise default to 0.1 BTC
961
+ // TODO: minChangeSize is not currently a constant defined on the client and should be added
962
+ minChangeSize = 1e7;
963
+ });
964
+ after(function accelerateTxMockedAfter() {
965
+ // make sure all nocks are cleared or consumed after the tests are complete
966
+ nock_1.default.pendingMocks().should.be.empty();
967
+ });
968
+ it('arguments', async () => {
969
+ await wallet.accelerateTransaction({ feeRate: 123 }).should.be.rejectedWith(/^Missing parameter: transactionID$/);
970
+ await wallet
971
+ .accelerateTransaction({ transactionID: 123, feeRate: 123 })
972
+ .should.be.rejectedWith(/^Expecting parameter string: transactionID but found number$/);
973
+ await wallet
974
+ .accelerateTransaction({ transactionID: '123' })
975
+ .should.be.rejectedWith(/^Missing parameter: feeRate$/);
976
+ const feeRatesParams = ['123', 0, -10, -Infinity, Infinity, NaN];
977
+ for (const feeRate of feeRatesParams) {
978
+ await wallet
979
+ .accelerateTransaction({ transactionID: '123', feeRate })
980
+ .should.be.rejectedWith(/^Expecting positive finite number for parameter: feeRate$/);
981
+ }
982
+ });
983
+ describe('bad input', function badInputDescribe() {
984
+ after(() => {
985
+ // make sure all nocks are cleared or consumed after the tests are complete
986
+ nock_1.default.pendingMocks().should.be.empty();
987
+ });
988
+ it('non existent transaction ID', async () => {
989
+ (0, nock_1.default)(bgUrl)
990
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
991
+ .reply(404, 'transaction not found on this wallet');
992
+ await wallet
993
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 123 })
994
+ .should.be.rejectedWith(/^404\ntransaction not found on this wallet$/);
995
+ });
996
+ it('confirmed transaction', async () => {
997
+ (0, nock_1.default)(bgUrl).get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`).reply(200, {
998
+ confirmations: 6,
999
+ });
1000
+ await wallet
1001
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1002
+ .should.be.rejectedWith(/^Transaction [0-9a-f]+ is already confirmed and cannot be accelerated$/);
1003
+ });
1004
+ it('no outputs to wallet', async () => {
1005
+ (0, nock_1.default)(bgUrl)
1006
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1007
+ .reply(200, {
1008
+ outputs: [
1009
+ {
1010
+ account: outputAddress,
1011
+ value: 1890000,
1012
+ vout: 0,
1013
+ chain: 0,
1014
+ },
1015
+ ],
1016
+ confirmations: 0,
1017
+ });
1018
+ await wallet
1019
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1020
+ .should.be.rejectedWith(/^Transaction [0-9a-f]+ contains no outputs to this wallet, and thus cannot be accelerated$/);
1021
+ });
1022
+ /*
1023
+ * This test covers the case where a failure occurs during the process of
1024
+ * converting an output from the parent transaction into an unspent which
1025
+ * can be used to chain the child tx to the parent.
1026
+ *
1027
+ * This should never happen, but it is possible (for example, in the case
1028
+ * of an attempted double spend of the output from the parent, or a race
1029
+ * between finding the parent output, and retrieving the corresponding unspent).
1030
+ */
1031
+ it('cannot find correct unspent to use', async () => {
1032
+ (0, nock_1.default)(bgUrl)
1033
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1034
+ .reply(200, {
1035
+ outputs: [
1036
+ {
1037
+ account: outputAddress,
1038
+ value: 50 * 1e4,
1039
+ vout: outputIdx,
1040
+ isMine: true,
1041
+ chain: 0,
1042
+ },
1043
+ ],
1044
+ confirmations: 0,
1045
+ hex: parentTxId,
1046
+ fee: 10,
1047
+ });
1048
+ (0, nock_1.default)(bgUrl).get(`/api/v1/wallet/${wallet.id()}/unspents`).query(true).reply(200, {
1049
+ count: 0,
1050
+ unspents: [],
1051
+ });
1052
+ await wallet
1053
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1054
+ .should.be.rejectedWith(/^Could not find unspent output from parent tx to use as child input$/);
1055
+ });
1056
+ it('Detects when an incorrect tx hex is returned by the external service', async () => {
1057
+ (0, nock_1.default)(bgUrl)
1058
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1059
+ .reply(200, {
1060
+ outputs: [
1061
+ {
1062
+ account: outputAddress,
1063
+ value: 10,
1064
+ vout: outputIdx,
1065
+ isMine: true,
1066
+ chain: 0,
1067
+ },
1068
+ ],
1069
+ confirmations: 0,
1070
+ hex: fixtures[parentTxId],
1071
+ fee: 10,
1072
+ });
1073
+ (0, nock_1.default)(bgUrl)
1074
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1075
+ .query(true)
1076
+ .reply(200, {
1077
+ count: 1,
1078
+ unspents: [
1079
+ {
1080
+ tx_hash: parentTxId,
1081
+ tx_output_n: outputIdx,
1082
+ },
1083
+ ],
1084
+ });
1085
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[unrelatedTxId]);
1086
+ await wallet
1087
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1088
+ .should.be.rejectedWith(/^Decoded transaction id is [0-9a-f]+, which does not match given txid [0-9a-f]+$/);
1089
+ });
1090
+ it('cannot cover child fee with one parent output and one wallet unspent', async () => {
1091
+ (0, nock_1.default)(bgUrl)
1092
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1093
+ .reply(200, {
1094
+ outputs: [
1095
+ {
1096
+ account: outputAddress,
1097
+ value: 10,
1098
+ vout: outputIdx,
1099
+ isMine: true,
1100
+ chain: 0,
1101
+ },
1102
+ ],
1103
+ confirmations: 0,
1104
+ hex: fixtures[parentTxId],
1105
+ fee: 10,
1106
+ });
1107
+ (0, nock_1.default)(bgUrl)
1108
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1109
+ .query(true)
1110
+ .reply(200, {
1111
+ count: 1,
1112
+ unspents: [
1113
+ {
1114
+ tx_hash: parentTxId,
1115
+ tx_output_n: outputIdx,
1116
+ },
1117
+ ],
1118
+ });
1119
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1120
+ (0, nock_1.default)(bgUrl).get(`/api/v1/wallet/${wallet.id()}/unspents`).query(true).reply(200, {
1121
+ count: 0,
1122
+ unspents: [],
1123
+ });
1124
+ await wallet
1125
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1126
+ .should.be.rejectedWith(/^Insufficient confirmed unspents available to cover the child fee$/);
1127
+ });
1128
+ it('cannot lower fee rate', async () => {
1129
+ (0, nock_1.default)(bgUrl)
1130
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1131
+ .reply(200, {
1132
+ outputs: [
1133
+ {
1134
+ account: outputAddress,
1135
+ value: 10,
1136
+ vout: outputIdx,
1137
+ isMine: true,
1138
+ chain: 11,
1139
+ },
1140
+ ],
1141
+ confirmations: 0,
1142
+ hex: fixtures[parentTxId],
1143
+ fee: 10000, // large fee, and thus fee rate, for parent
1144
+ });
1145
+ (0, nock_1.default)(bgUrl)
1146
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1147
+ .query(true)
1148
+ .reply(200, {
1149
+ count: 1,
1150
+ unspents: [
1151
+ {
1152
+ tx_hash: parentTxId,
1153
+ tx_output_n: outputIdx,
1154
+ },
1155
+ ],
1156
+ });
1157
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1158
+ await wallet
1159
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2000 })
1160
+ .should.be.rejectedWith(/^Cannot lower fee rate! \(Parent tx fee rate is \d+\.?\d* sat\/kB, and requested fee rate was \d+\.?\d* sat\/kB\)$/);
1161
+ });
1162
+ it('cannot break maximum fee limit for combined transaction', async () => {
1163
+ (0, nock_1.default)(bgUrl)
1164
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1165
+ .reply(200, {
1166
+ outputs: [
1167
+ {
1168
+ account: outputAddress,
1169
+ value: 3e7,
1170
+ vout: outputIdx,
1171
+ isMine: true,
1172
+ chain: 11,
1173
+ },
1174
+ ],
1175
+ confirmations: 0,
1176
+ hex: fixtures[parentTxId],
1177
+ fee: 1000,
1178
+ });
1179
+ (0, nock_1.default)(bgUrl)
1180
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1181
+ .query(true)
1182
+ .reply(200, {
1183
+ count: 1,
1184
+ unspents: [
1185
+ {
1186
+ tx_hash: parentTxId,
1187
+ tx_output_n: outputIdx,
1188
+ },
1189
+ ],
1190
+ });
1191
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1192
+ await wallet
1193
+ .accelerateTransaction({ transactionID: parentTxId, feeRate: 2e6 })
1194
+ .should.be.rejectedWith(/^Transaction cannot be accelerated\. Combined fee rate of \d+\.?\d* sat\/kB exceeds maximum fee rate of \d+\.?\d* sat\/kB$/);
1195
+ });
1196
+ });
1197
+ describe('successful tx acceleration', function successfulTxDescribe() {
1198
+ const feeRate = 20000;
1199
+ beforeEach(async () => {
1200
+ (0, nock_1.default)(bgUrl).post(`/api/v1/wallet/${wallet.id()}/address/1`).reply(200, {
1201
+ address: '2NCYjG8Q56yr8tx9jazNoYnGKxjgB2MQSfY',
1202
+ });
1203
+ (0, nock_1.default)(bgUrl).post('/api/v1/billing/address').reply(200, {
1204
+ address: '2NFbvo2HK4eXZm1aqDcSDGGqD64FPt7T6d8',
1205
+ });
1206
+ (0, nock_1.default)(bgUrl).get('/api/v1/tx/fee').query(true).reply(200, {
1207
+ feePerKb: 0,
1208
+ });
1209
+ (0, nock_1.default)(bgUrl)
1210
+ .post(`/api/v1/keychain/${userKeypair.xpub}`, {})
1211
+ .reply(200, {
1212
+ encryptedXprv: await bitgo.encrypt({ input: userKeypair.xprv, password: TestBitGo.TEST_WALLET1_PASSCODE }),
1213
+ path: userKeypair.path + userKeypair.walletSubPath,
1214
+ });
1215
+ });
1216
+ it('accelerates a stuck tx without additional unspents', async () => {
1217
+ parentTxId = '75cfc5a7b214c4b73c92c7b02608cde70b226767a9576f84c04407e43fd385bd';
1218
+ (0, nock_1.default)(bgUrl)
1219
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1220
+ .reply(200, {
1221
+ fee: 434,
1222
+ outputs: [
1223
+ {
1224
+ vout: 0,
1225
+ value: 10348500,
1226
+ isMine: true,
1227
+ chain: 1,
1228
+ },
1229
+ {
1230
+ vout: 1,
1231
+ value: 10000,
1232
+ isMine: true,
1233
+ chain: 11,
1234
+ },
1235
+ ],
1236
+ });
1237
+ (0, nock_1.default)(bgUrl)
1238
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1239
+ .query(true)
1240
+ .reply(200, {
1241
+ unspents: [
1242
+ {
1243
+ tx_hash: parentTxId,
1244
+ tx_output_n: 0,
1245
+ value: 10348500,
1246
+ redeemScript: '0020f7b58d455351b7b8ddd7c8986d98244f6a95f0746720091537323b967800f744',
1247
+ chainPath: '/11/160',
1248
+ witnessScript: '5221027f0b45bb4155ea532e3b4312fe0be80166f297d1e0753d2d4a9118c073ad6514210310aa9d68c98831625f329b7826b6c3e3b53e16736b1994b8902442bdcd6653d121026e0ca414f2488b0ab572b99e0ae5442911ab4e0821b2709d885175a527fd552b53ae',
1249
+ },
1250
+ ],
1251
+ });
1252
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1253
+ (0, nock_1.default)(bgUrl)
1254
+ .post('/api/v1/tx/send', (body) => {
1255
+ return !body.ignoreMaxFeeRate;
1256
+ })
1257
+ .reply(200, function (_, body) {
1258
+ return {
1259
+ transaction: body.tx,
1260
+ };
1261
+ });
1262
+ const childTx = await wallet.accelerateTransaction({
1263
+ transactionID: parentTxId,
1264
+ feeRate,
1265
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1266
+ });
1267
+ should.exist(childTx);
1268
+ childTx.should.have.property('status', 'accepted');
1269
+ childTx.should.have.property('tx');
1270
+ // assert the following:
1271
+ // 0) The child tx has exactly one input
1272
+ // 1) The parent tx output is an input
1273
+ // 2) The child tx has exactly one output
1274
+ // 3) The child tx output meets the minimum change threshold
1275
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1276
+ decodedChild.ins.length.should.equal(1);
1277
+ decodedChild.outs.length.should.equal(1);
1278
+ const childInput = decodedChild.ins[0];
1279
+ childInput.should.have.property('index', 0);
1280
+ childInput.should.have.property('hash');
1281
+ const inputTxId = inputParentTxId(childInput);
1282
+ inputTxId.should.equal(parentTxId);
1283
+ const childOutput = decodedChild.outs[0];
1284
+ childOutput.should.have.property('value');
1285
+ childOutput.value.should.be.above(minChangeSize);
1286
+ });
1287
+ it('accelerates a stuck tx with one additional segwit unspent', async () => {
1288
+ parentTxId = '8815f202c8654b6c8b295749545c711878cd845a14cb1ea982394d0c14945c33';
1289
+ const additionalUnspentTxId = '07d6ee57b024ce2b6108f67847454a0a79a4fcfb98ab255553a2993a1a170b87';
1290
+ (0, nock_1.default)(bgUrl)
1291
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1292
+ .reply(200, {
1293
+ fee: 1336,
1294
+ outputs: [
1295
+ {
1296
+ vout: 0,
1297
+ value: 10000,
1298
+ isMine: true,
1299
+ chain: 11,
1300
+ },
1301
+ {
1302
+ vout: 1,
1303
+ value: 8664,
1304
+ isMine: true,
1305
+ chain: 1,
1306
+ },
1307
+ ],
1308
+ confirmations: 0,
1309
+ });
1310
+ (0, nock_1.default)(bgUrl)
1311
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1312
+ .query(true)
1313
+ .reply(200, {
1314
+ unspents: [
1315
+ {
1316
+ tx_hash: parentTxId,
1317
+ tx_output_n: 0,
1318
+ value: 10000,
1319
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1320
+ chainPath: '/0/0',
1321
+ },
1322
+ ],
1323
+ });
1324
+ (0, nock_1.default)(bgUrl)
1325
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1326
+ .query(true)
1327
+ .reply(200, {
1328
+ unspents: [
1329
+ {
1330
+ tx_hash: additionalUnspentTxId,
1331
+ tx_output_n: 0,
1332
+ value: 19935526,
1333
+ redeemScript: '0020d34ef6dd34ef2a4fbea67c541c1c796749a60afe4a97fee8ec7ded188bd749da',
1334
+ chainPath: '/11/155',
1335
+ witnessScript: '522102219d2aa8417633f0bce3911374a1604c1b64161f83a3c2ee409c27c42355f08e2102c9734920dc4da06c289fe69171dfcd75e3b9b4f190d0cbc3d5d0ff3f5fdeeaae2103ccd68d7fa8dc0d02dd45dad165557a48582eda4435fae7377b3c31e08ad065c953ae',
1336
+ },
1337
+ ],
1338
+ });
1339
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1340
+ (0, nock_1.default)(bgUrl)
1341
+ .post('/api/v1/tx/send', (body) => {
1342
+ return !body.ignoreMaxFeeRate;
1343
+ })
1344
+ .reply(200, function (_, body) {
1345
+ return {
1346
+ transaction: body.tx,
1347
+ };
1348
+ });
1349
+ const childTx = await wallet.accelerateTransaction({
1350
+ transactionID: parentTxId,
1351
+ feeRate,
1352
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1353
+ });
1354
+ should.exist(childTx);
1355
+ childTx.should.have.property('status', 'accepted');
1356
+ childTx.should.have.property('tx');
1357
+ // assert the following:
1358
+ // 0) The child tx has exactly two inputs
1359
+ // 1) The parent tx output is an input
1360
+ // 2) The additional unspent output is an input
1361
+ // 3) The child tx has exactly one output
1362
+ // 4) The child tx output meets the minimum change threshold
1363
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1364
+ decodedChild.ins.length.should.equal(2);
1365
+ decodedChild.outs.length.should.equal(1);
1366
+ let inputFromParent = undefined;
1367
+ let additionalInput = undefined;
1368
+ _.forEach(decodedChild.ins, (input) => {
1369
+ input.should.have.property('hash');
1370
+ input.should.have.property('index');
1371
+ const inputTxId = inputParentTxId(input);
1372
+ if (inputTxId === parentTxId) {
1373
+ inputFromParent = input;
1374
+ }
1375
+ else {
1376
+ additionalInput = input;
1377
+ }
1378
+ });
1379
+ should.exist(inputFromParent);
1380
+ const inputFromParentHash = inputParentTxId(inputFromParent);
1381
+ inputFromParentHash.should.equal(parentTxId);
1382
+ inputFromParent.index.should.equal(0);
1383
+ should.exist(additionalInput);
1384
+ const additionalInputHash = inputParentTxId(additionalInput);
1385
+ additionalInputHash.should.equal(additionalUnspentTxId);
1386
+ additionalInput.index.should.equal(0);
1387
+ const childOutput = decodedChild.outs[0];
1388
+ childOutput.should.have.property('value');
1389
+ childOutput.value.should.be.above(minChangeSize);
1390
+ });
1391
+ it('accelerates a stuck tx with one additional P2SH unspent', async () => {
1392
+ parentTxId = '8815f202c8654b6c8b295749545c711878cd845a14cb1ea982394d0c14945c33';
1393
+ const additionalUnspentTxId = 'e190310f2f3f71aa8846f1161cbce1533c24a857dd24e4501b131feb400aad58';
1394
+ (0, nock_1.default)(bgUrl)
1395
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1396
+ .reply(200, {
1397
+ fee: 1336,
1398
+ outputs: [
1399
+ {
1400
+ vout: 0,
1401
+ value: 10000,
1402
+ isMine: true,
1403
+ chain: 11,
1404
+ },
1405
+ {
1406
+ vout: 1,
1407
+ value: 8664,
1408
+ isMine: true,
1409
+ chain: 1,
1410
+ },
1411
+ ],
1412
+ confirmations: 0,
1413
+ });
1414
+ (0, nock_1.default)(bgUrl)
1415
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1416
+ .query(true)
1417
+ .reply(200, {
1418
+ unspents: [
1419
+ {
1420
+ tx_hash: parentTxId,
1421
+ tx_output_n: 0,
1422
+ value: 10000,
1423
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1424
+ chainPath: '/0/0',
1425
+ },
1426
+ ],
1427
+ });
1428
+ (0, nock_1.default)(bgUrl)
1429
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1430
+ .query(true)
1431
+ .reply(200, {
1432
+ unspents: [
1433
+ {
1434
+ tx_hash: additionalUnspentTxId,
1435
+ tx_output_n: 1,
1436
+ value: 20000000,
1437
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1438
+ chainPath: '/0/0',
1439
+ },
1440
+ ],
1441
+ });
1442
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1443
+ (0, nock_1.default)(bgUrl)
1444
+ .post('/api/v1/tx/send', (body) => {
1445
+ return !body.ignoreMaxFeeRate;
1446
+ })
1447
+ .reply(200, function (_, body) {
1448
+ return {
1449
+ transaction: body.tx,
1450
+ };
1451
+ });
1452
+ const childTx = await wallet.accelerateTransaction({
1453
+ transactionID: parentTxId,
1454
+ feeRate,
1455
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1456
+ });
1457
+ should.exist(childTx);
1458
+ childTx.should.have.property('status', 'accepted');
1459
+ childTx.should.have.property('tx');
1460
+ // assert the following:
1461
+ // 0) The child tx has exactly two inputs
1462
+ // 1) The parent tx output is an input
1463
+ // 2) The additional unspent output is an input
1464
+ // 3) The child tx has exactly one output
1465
+ // 4) The child tx output meets the minimum change threshold
1466
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1467
+ decodedChild.ins.length.should.equal(2);
1468
+ decodedChild.outs.length.should.equal(1);
1469
+ let inputFromParent = undefined;
1470
+ let additionalInput = undefined;
1471
+ _.forEach(decodedChild.ins, (input) => {
1472
+ input.should.have.property('hash');
1473
+ input.should.have.property('index');
1474
+ const inputHash = inputParentTxId(input);
1475
+ if (inputHash === parentTxId) {
1476
+ inputFromParent = input;
1477
+ }
1478
+ else {
1479
+ additionalInput = input;
1480
+ }
1481
+ });
1482
+ should.exist(inputFromParent);
1483
+ const inputFromParentHash = inputParentTxId(inputFromParent);
1484
+ inputFromParentHash.should.equal(parentTxId);
1485
+ inputFromParent.index.should.equal(0);
1486
+ should.exist(additionalInput);
1487
+ const additionalInputHash = inputParentTxId(additionalInput);
1488
+ additionalInputHash.should.equal(additionalUnspentTxId);
1489
+ additionalInput.index.should.equal(1);
1490
+ const childOutput = decodedChild.outs[0];
1491
+ childOutput.should.have.property('value');
1492
+ childOutput.value.should.be.above(minChangeSize);
1493
+ });
1494
+ it('accelerates a stuck tx with two additional unspents (segwit and P2SH)', async () => {
1495
+ parentTxId = '8815f202c8654b6c8b295749545c711878cd845a14cb1ea982394d0c14945c33';
1496
+ (0, nock_1.default)(bgUrl)
1497
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1498
+ .reply(200, {
1499
+ fee: 1336,
1500
+ outputs: [
1501
+ {
1502
+ vout: 0,
1503
+ value: 10000,
1504
+ isMine: true,
1505
+ chain: 11,
1506
+ },
1507
+ {
1508
+ vout: 1,
1509
+ value: 8664,
1510
+ isMine: true,
1511
+ chain: 1,
1512
+ },
1513
+ ],
1514
+ confirmations: 0,
1515
+ });
1516
+ (0, nock_1.default)(bgUrl)
1517
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1518
+ .query(true)
1519
+ .reply(200, {
1520
+ unspents: [
1521
+ {
1522
+ tx_hash: parentTxId,
1523
+ tx_output_n: 0,
1524
+ value: 10000,
1525
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1526
+ chainPath: '/0/0',
1527
+ },
1528
+ ],
1529
+ });
1530
+ (0, nock_1.default)(bgUrl)
1531
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1532
+ .query(true)
1533
+ .reply(200, {
1534
+ unspents: [
1535
+ {
1536
+ tx_hash: 'e190310f2f3f71aa8846f1161cbce1533c24a857dd24e4501b131feb400aad58',
1537
+ tx_output_n: 1,
1538
+ value: 800000,
1539
+ redeemScript: '522102cd3c8e6006a4627705021d1d016d097c2944d98100a47bf2da67a5fe15aeeb342102ee1fa9e812e779356aa3c31ebf317d0cffebab92864cfe38bab223e0820f98bc21026ba05752baa6eafd5c5659da62b7f0ac51fd2886b65c241d0afef1c4fdfa1cbc53ae',
1540
+ chainPath: '/0/0',
1541
+ },
1542
+ {
1543
+ tx_hash: '07d6ee57b024ce2b6108f67847454a0a79a4fcfb98ab255553a2993a1a170b87',
1544
+ tx_output_n: 0,
1545
+ value: 20006284,
1546
+ redeemScript: '0020d34ef6dd34ef2a4fbea67c541c1c796749a60afe4a97fee8ec7ded188bd749da',
1547
+ chainPath: '/11/155',
1548
+ witnessScript: '522102219d2aa8417633f0bce3911374a1604c1b64161f83a3c2ee409c27c42355f08e2102c9734920dc4da06c289fe69171dfcd75e3b9b4f190d0cbc3d5d0ff3f5fdeeaae2103ccd68d7fa8dc0d02dd45dad165557a48582eda4435fae7377b3c31e08ad065c953ae',
1549
+ },
1550
+ ],
1551
+ });
1552
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1553
+ (0, nock_1.default)(bgUrl)
1554
+ .post('/api/v1/tx/send', (body) => {
1555
+ return !body.ignoreMaxFeeRate;
1556
+ })
1557
+ .reply(200, function (_, body) {
1558
+ return {
1559
+ transaction: body.tx,
1560
+ };
1561
+ });
1562
+ const childTx = await wallet.accelerateTransaction({
1563
+ transactionID: parentTxId,
1564
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1565
+ feeRate,
1566
+ });
1567
+ should.exist(childTx);
1568
+ childTx.should.have.property('status', 'accepted');
1569
+ childTx.should.have.property('tx');
1570
+ // assert the following:
1571
+ // 0) The child tx has exactly three inputs
1572
+ // 1) The parent tx output is an input
1573
+ // 2) The child tx has exactly one output
1574
+ // 3) The child tx output meets the minimum change threshold
1575
+ const decodedChild = utxolib.bitgo.createTransactionFromHex(childTx.tx, utxolib.networks.bitcoin);
1576
+ decodedChild.ins.length.should.equal(3);
1577
+ decodedChild.outs.length.should.equal(1);
1578
+ let inputFromParent = undefined;
1579
+ const additionalInputs = [];
1580
+ _.forEach(decodedChild.ins, (input) => {
1581
+ input.should.have.property('hash');
1582
+ input.should.have.property('index');
1583
+ const inputHash = inputParentTxId(input);
1584
+ if (inputHash === parentTxId) {
1585
+ inputFromParent = input;
1586
+ }
1587
+ else {
1588
+ additionalInputs.push(input);
1589
+ }
1590
+ });
1591
+ should.exist(inputFromParent);
1592
+ const inputFromParentHash = inputParentTxId(inputFromParent);
1593
+ inputFromParentHash.should.equal(parentTxId);
1594
+ inputFromParent.index.should.equal(0);
1595
+ additionalInputs.length.should.equal(2);
1596
+ const childOutput = decodedChild.outs[0];
1597
+ childOutput.should.have.property('value');
1598
+ childOutput.value.should.be.above(minChangeSize);
1599
+ });
1600
+ it('correctly uses the ignoreMaxFeeRate parameter only when necessary', async () => {
1601
+ parentTxId = '75cfc5a7b214c4b73c92c7b02608cde70b226767a9576f84c04407e43fd385bd';
1602
+ (0, nock_1.default)(bgUrl)
1603
+ .get(`/api/v1/wallet/${wallet.id()}/tx/${parentTxId}`)
1604
+ .reply(200, {
1605
+ fee: 434,
1606
+ outputs: [
1607
+ {
1608
+ vout: 0,
1609
+ value: 10348500,
1610
+ isMine: true,
1611
+ chain: 0,
1612
+ },
1613
+ {
1614
+ vout: 1,
1615
+ value: 10000,
1616
+ isMine: true,
1617
+ chain: 11,
1618
+ },
1619
+ ],
1620
+ });
1621
+ (0, nock_1.default)(bgUrl)
1622
+ .get(`/api/v1/wallet/${wallet.id()}/unspents`)
1623
+ .query(true)
1624
+ .reply(200, {
1625
+ unspents: [
1626
+ {
1627
+ tx_hash: parentTxId,
1628
+ tx_output_n: 0,
1629
+ value: 10348500,
1630
+ redeemScript: '0020f7b58d455351b7b8ddd7c8986d98244f6a95f0746720091537323b967800f744',
1631
+ chainPath: '/11/160',
1632
+ witnessScript: '5221027f0b45bb4155ea532e3b4312fe0be80166f297d1e0753d2d4a9118c073ad6514210310aa9d68c98831625f329b7826b6c3e3b53e16736b1994b8902442bdcd6653d121026e0ca414f2488b0ab572b99e0ae5442911ab4e0821b2709d885175a527fd552b53ae',
1633
+ },
1634
+ ],
1635
+ });
1636
+ (0, nock_1.default)(explorerUrl).get(`/tx/${parentTxId}/hex`).reply(200, fixtures[parentTxId]);
1637
+ (0, nock_1.default)(bgUrl)
1638
+ .post('/api/v1/tx/send', (body) => {
1639
+ // ignore max fee rate must be set for this test
1640
+ return body.ignoreMaxFeeRate;
1641
+ })
1642
+ .reply(200);
1643
+ // monkey patch the bitgo getConstants() function
1644
+ const oldGetConstants = bitgo.__proto__.getConstants;
1645
+ bitgo.__proto__.getConstants = () => ({
1646
+ // child fee rate in this test is 31378 sat/kb
1647
+ // so set the max fee rate just below that limit,
1648
+ // but above the combined fee rate of 20000
1649
+ maxFeeRate: 30000,
1650
+ });
1651
+ await wallet.accelerateTransaction({
1652
+ transactionID: parentTxId,
1653
+ feeRate,
1654
+ walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE,
1655
+ });
1656
+ nock_1.default.pendingMocks().should.be.empty();
1657
+ bitgo.__proto__.getConstants = oldGetConstants;
1658
+ });
1659
+ });
1660
+ });
1661
+ describe('getBitGoFee', function () {
1662
+ let bgUrl;
1663
+ let wallet;
1664
+ before(function () {
1665
+ nock_1.default.pendingMocks().should.be.empty();
1666
+ const prodBitgo = new bitgoAPI_1.BitGoAPI({ env: 'prod', clientConstants: { constants: {} } });
1667
+ bgUrl = sdk_core_1.common.Environments[prodBitgo.getEnv()].uri;
1668
+ wallet = new Wallet(prodBitgo, {
1669
+ id: '2NCoSfHH6Ls4CdTS5QahgC9k7x9RfXeSwY4',
1670
+ private: { keychains: [userKeypair, backupKeypair, bitgoKey] },
1671
+ });
1672
+ });
1673
+ afterEach(function () {
1674
+ nock_1.default.cleanAll();
1675
+ });
1676
+ it('sends amount and instant without recipients when recipients array is empty', async function () {
1677
+ const scope = (0, nock_1.default)(bgUrl)
1678
+ .get(`/api/v1/wallet/${wallet.id()}/billing/fee`)
1679
+ .query({ amount: '100000', instant: 'false' })
1680
+ .reply(200, { fee: 1000 });
1681
+ const result = await wallet.getBitGoFee({ amount: 100000, instant: false });
1682
+ result.fee.should.equal(1000);
1683
+ scope.isDone().should.be.true();
1684
+ });
1685
+ it('sends recipients[] query params when recipients are provided', async function () {
1686
+ const addr1 = '3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy';
1687
+ const addr2 = '3FZbgi29cpjq2GjdwV8eyHuJJnkLtktZc5';
1688
+ const scope = (0, nock_1.default)(bgUrl)
1689
+ .get(`/api/v1/wallet/${wallet.id()}/billing/fee`)
1690
+ .query((query) => {
1691
+ const recipientsParam = query['recipients[]'];
1692
+ const recipientsList = Array.isArray(recipientsParam) ? recipientsParam : [recipientsParam];
1693
+ return query.amount === '100000' && recipientsList.includes(addr1) && recipientsList.includes(addr2);
1694
+ })
1695
+ .reply(200, { fee: 0 });
1696
+ const result = await wallet.getBitGoFee({ amount: 100000, recipients: [addr1, addr2] });
1697
+ result.fee.should.equal(0);
1698
+ scope.isDone().should.be.true();
1699
+ });
1700
+ it('omits recipients[] when recipients array is empty', async function () {
1701
+ const scope = (0, nock_1.default)(bgUrl)
1702
+ .get(`/api/v1/wallet/${wallet.id()}/billing/fee`)
1703
+ .query((query) => query.amount === '200000' && !('recipients[]' in query))
1704
+ .reply(200, { fee: 500 });
1705
+ const result = await wallet.getBitGoFee({ amount: 200000, recipients: [] });
1706
+ result.fee.should.equal(500);
1707
+ scope.isDone().should.be.true();
1708
+ });
1709
+ it('throws when amount is not a number', function () {
1710
+ (() => wallet.getBitGoFee({ amount: 'bad' })).should.throw('invalid amount argument');
1711
+ });
1712
+ it('throws when instant is not a boolean', function () {
1713
+ (() => wallet.getBitGoFee({ amount: 100, instant: 'yes' })).should.throw('invalid instant argument');
1714
+ });
1715
+ });
1716
+ });
1717
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FsbGV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L3YxL3dhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsRUFBRTtBQUNGLG1CQUFtQjtBQUNuQixFQUFFO0FBQ0Ysb0RBQW9EO0FBQ3BELEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUYseUNBQXdDO0FBRXhDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBQ2pELG9EQUFpRDtBQUNqRCwwQ0FBNEI7QUFDNUIsbURBQThDO0FBQzlDLDhEQUFnRDtBQUNoRCwrQ0FBaUM7QUFDakMsZ0RBQXdCO0FBQ3hCLDZDQUErQjtBQUUvQiw0REFBdUQ7QUFFdkQsY0FBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7QUFFekIsTUFBTSxTQUFTLEdBQUc7SUFDaEIscUJBQXFCLEVBQUUsMEJBQTBCO0NBQ2xELENBQUM7QUFDRixRQUFRLENBQUMsMEJBQTBCLEVBQUU7SUFDbkMsTUFBTSxRQUFRLEdBQUcsSUFBQSwyQkFBVyxHQUFFLENBQUM7SUFFL0IsSUFBSSxLQUFLLEdBQUcsSUFBSSxtQkFBUSxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzlFLDhCQUE4QjtJQUU5QixNQUFNLFdBQVcsR0FBRztRQUNsQixJQUFJLEVBQUUsaUhBQWlIO1FBQ3ZILElBQUksRUFBRSxpSEFBaUg7UUFDdkgsTUFBTSxFQUFFLG9FQUFvRTtRQUM1RSxNQUFNLEVBQUUsa0VBQWtFO1FBQzFFLElBQUksRUFBRSxHQUFHO1FBQ1QsYUFBYSxFQUFFLE1BQU07S0FDdEIsQ0FBQztJQUNGLE1BQU0sYUFBYSxHQUFHO1FBQ3BCLElBQUksRUFBRSxpSEFBaUg7UUFDdkgsSUFBSSxFQUFFLGlIQUFpSDtRQUN2SCxNQUFNLEVBQUUsb0VBQW9FO1FBQzVFLE1BQU0sRUFBRSxrRUFBa0U7UUFDMUUsSUFBSSxFQUFFLEdBQUc7UUFDVCxhQUFhLEVBQUUsTUFBTTtLQUN0QixDQUFDO0lBQ0YsTUFBTSxRQUFRLEdBQUc7UUFDZixJQUFJLEVBQUUsaUhBQWlIO1FBQ3ZILElBQUksRUFBRSxHQUFHO1FBQ1QsYUFBYSxFQUFFLE1BQU07S0FDdEIsQ0FBQztJQUVGLE1BQU0sVUFBVSxHQUFHLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRTtRQUNuQyxFQUFFLEVBQUUscUNBQXFDO1FBQ3pDLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsUUFBUSxDQUFDLEVBQUU7S0FDL0QsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGtCQUFrQixFQUFFO1FBQzNCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxjQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBRXBELEVBQUUsQ0FBQyx3QkFBd0IsRUFBRTtZQUMzQixNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUM5RSxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDaEQsU0FBUyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNoQyxTQUFTLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDekMsU0FBUyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3BDLFNBQVMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1lBQ3RGLFNBQVMsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDakMsb05BQW9OLENBQ3JOLENBQUM7WUFDRixTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseUJBQXlCLEVBQUU7WUFDNUIsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDaEYsV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7WUFDeEUsV0FBVyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLFdBQVcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsQyxXQUFXLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0MsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RDLFdBQVcsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1lBQ3hGLFdBQVcsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDbkMsb05BQW9OLENBQ3JOLENBQUM7WUFDRixXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDbkQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseUJBQXlCLEVBQUU7WUFDNUIsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDaEYsV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7WUFDeEUsV0FBVyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLFdBQVcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsQyxXQUFXLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDM0MsV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3RDLFdBQVcsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1lBQ3hGLFdBQVcsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDbkMsb05BQW9OLENBQ3JOLENBQUM7WUFDRixXQUFXLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDbkQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseUJBQXlCLEVBQUU7WUFDNUIsTUFBTSxhQUFhLEdBQUcsVUFBVSxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDbEYsYUFBYSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7WUFDMUUsYUFBYSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3JDLGFBQWEsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNwQyxhQUFhLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDOUMsYUFBYSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ3pDLGFBQWEsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFDO1lBQzFGLGFBQWEsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxzRUFBc0UsQ0FBQyxDQUFDO1lBQ2hILGFBQWEsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDdEMsb05BQW9OLENBQ3JOLENBQUM7WUFDRixhQUFhLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDckQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxvQkFBb0IsRUFBRTtRQUM3QixJQUFJLEtBQUssRUFBRSxTQUFTLENBQUM7UUFDckIsSUFBSSxjQUFjLENBQUM7UUFFbkIsTUFBTSxDQUFDO1lBQ0wsY0FBSSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDdEMsTUFBTSxTQUFTLEdBQUcsSUFBSSxtQkFBUSxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3BGLGtDQUFrQztZQUNsQyxLQUFLLEdBQUcsaUJBQU0sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQ3BELGNBQWMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUU7Z0JBQ3JDLEVBQUUsRUFBRSxxQ0FBcUM7Z0JBQ3pDLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsUUFBUSxDQUFDLEVBQUU7YUFDL0QsQ0FBQyxDQUFDO1lBQ0gsU0FBUyxHQUFHLGlCQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUN0RCxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw0QkFBNEIsRUFBRSxLQUFLO1lBQ3BDLE1BQU0sY0FBYyxHQUFHLG9DQUFvQyxDQUFDO1lBQzVELE1BQU0seUJBQXlCLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFDaEQsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDO1lBRXZCLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQztZQUVwRixNQUFNLEtBQUssR0FBRyxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7aUJBQ3RCLEdBQUcsQ0FBQyxrQkFBa0IsY0FBYyxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUM7aUJBQ3JELEtBQUssQ0FDSixDQUFDLENBQUMsS0FBSyxDQUFDLHlCQUF5QixFQUFFO2dCQUNqQyxNQUFNLEVBQUUsSUFBSTtnQkFDWixNQUFNLEVBQUUsVUFBVTtnQkFDbEIsT0FBTyxFQUFFLENBQUM7YUFDWCxDQUFDLENBQ0g7aUJBQ0EsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLFFBQVEsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBRWhDLE1BQU0sY0FBYztpQkFDakIsaUJBQWlCLENBQUM7Z0JBQ2pCLG1CQUFtQixFQUFFLHlCQUF5QjtnQkFDOUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxVQUFVLEVBQUU7Z0JBQzVDLE9BQU8sRUFBRSxLQUFLO2dCQUNkLFFBQVEsRUFBRTtvQkFDUixNQUFNLEVBQUUsQ0FBQztvQkFDVCxPQUFPLEVBQUUsRUFBRTtpQkFDWjthQUNGLENBQUM7aUJBQ0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsK0NBQStDLENBQUMsQ0FBQztZQUUzRSxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxpRkFBaUYsRUFBRSxLQUFLO1lBQ3pGLHlGQUF5RjtZQUN6Riw0RkFBNEY7WUFDNUYsMkZBQTJGO1lBQzNGLDZGQUE2RjtZQUM3RixNQUFNLGdCQUFnQixHQUFHLG9DQUFvQyxDQUFDO1lBQzlELE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQztZQUV2QixNQUFNLFdBQVcsR0FBRyxjQUFjLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUNyRixNQUFNLE9BQU8sR0FBUTtnQkFDbkIsU0FBUyxFQUFFLENBQUMscUNBQXFDLENBQUM7Z0JBQ2xELFNBQVMsRUFBRSxNQUFNO2dCQUNqQixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxDQUFDLEVBQUUsQ0FBQztnQkFDSixjQUFjLEVBQUU7b0JBQ2QsR0FBRyxFQUFFLDhEQUE4RDtvQkFDbkUsR0FBRyxFQUFFLGdEQUFnRDtpQkFDdEQ7Z0JBQ0QsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUM7WUFDRixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztZQUMvQixPQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDbEMsT0FBTyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQy9CLE9BQU8sQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoQyxPQUFPLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFFdEMsSUFBSSxhQUFrQixDQUFDO1lBQ3ZCLE1BQU0sWUFBWSxHQUFHLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQztpQkFDN0IsR0FBRyxDQUFDLGtCQUFrQixjQUFjLENBQUMsRUFBRSxFQUFFLGNBQWMsQ0FBQztpQkFDeEQsS0FBSyxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUU7Z0JBQ3JCLGFBQWEsR0FBRyxXQUFXLENBQUM7Z0JBQzVCLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQyxDQUFDO2dCQUNGLDJFQUEyRTtpQkFDMUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBRTFCLCtEQUErRDtZQUMvRCxNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGlCQUFpQixDQUFDO2dCQUMxRCxhQUFhLEVBQUUsV0FBVyxDQUFDLE9BQU87Z0JBQ2xDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQztnQkFDbkIsVUFBVSxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLFVBQVUsRUFBRTtnQkFDOUMsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLE9BQU8sRUFBRSxLQUFLO2dCQUNkLE9BQU8sRUFBRSxLQUFLO2FBQ2YsQ0FBQyxDQUFRLENBQUM7WUFFWCx3RkFBd0Y7WUFDeEYsWUFBWSxDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDdkMsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM1QixNQUFNLG1CQUFtQixHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzNFLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7WUFDekQsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBRXRELG1FQUFtRTtZQUNuRSxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDdkMsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDeEcsd0RBQXdEO1lBQ3hELEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsY0FBYyxFQUFFLEtBQUs7WUFDdEIsTUFBTSxXQUFXLEdBQUcsY0FBYyxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDckYsTUFBTSxPQUFPLEdBQVE7Z0JBQ25CLFNBQVMsRUFBRSxDQUFDLHFDQUFxQyxDQUFDO2dCQUNsRCxLQUFLLEVBQUUsWUFBWTtnQkFDbkIsU0FBUyxFQUFFLE1BQU07Z0JBQ2pCLElBQUksRUFBRSxrRUFBa0U7Z0JBQ3hFLENBQUMsRUFBRSxDQUFDO2dCQUNKLGNBQWMsRUFBRTtvQkFDZCxHQUFHLEVBQUUsOERBQThEO29CQUNuRSxHQUFHLEVBQUUsZ0RBQWdEO2lCQUN0RDtnQkFDRCxRQUFRLEVBQUUsQ0FBQztnQkFDWCxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsYUFBYSxFQUFFLENBQUM7Z0JBQ2hCLEVBQUUsRUFBRSxRQUFRO2FBQ2IsQ0FBQztZQUNGLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQy9CLE9BQU8sQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztZQUNsQyxPQUFPLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDL0IsT0FBTyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQztZQUV0QyxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLHFDQUFxQyxFQUFFLENBQUMsQ0FBQztZQUUzRyxNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGlCQUFpQixDQUFDO2dCQUMxRCxhQUFhLEVBQUUsV0FBVyxDQUFDLE9BQU87Z0JBQ2xDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQztnQkFDbkIsVUFBVSxFQUFFLEVBQUU7Z0JBQ2QsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLE9BQU8sRUFBRSxLQUFLO2dCQUNkLFFBQVEsRUFBRTtvQkFDUixNQUFNLEVBQUUsQ0FBQztvQkFDVCxPQUFPLEVBQUUsRUFBRTtpQkFDWjtnQkFDRCxTQUFTLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxJQUFJLEVBQUU7Z0JBQ3RDLE9BQU8sRUFBRSxLQUFLO2FBQ2YsQ0FBQyxDQUFRLENBQUM7WUFDWCxXQUFXLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3JDLDROQUE0TixDQUM3TixDQUFDO1lBRUYsc0JBQXNCO1lBQ3RCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO1lBQ25DLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFRLENBQUM7WUFDOUUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUN4Qix3a0JBQXdrQixDQUN6a0IsQ0FBQztZQUVGLHVCQUF1QjtZQUN2QixXQUFXLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDM0MsV0FBVyxDQUFDLFFBQVEsR0FBRyxhQUFhLENBQUM7WUFDckMsV0FBVyxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztZQUNwQyxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBUSxDQUFDO1lBQzlFLDRJQUE0STtZQUM1SSwyR0FBMkc7WUFDM0csNERBQTREO1lBQzVELFVBQVUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDeEIsMHRCQUEwdEIsQ0FDM3RCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywrQ0FBK0MsRUFBRSxLQUFLO1lBQ3ZELE1BQU0sV0FBVyxHQUFHLGNBQWMsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ3JGLE1BQU0sT0FBTyxHQUFRO2dCQUNuQixTQUFTLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQztnQkFDbEQsS0FBSyxFQUFFLFlBQVk7Z0JBQ25CLFNBQVMsRUFBRSxNQUFNO2dCQUNqQixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxDQUFDLEVBQUUsQ0FBQztnQkFDSixjQUFjLEVBQUU7b0JBQ2QsR0FBRyxFQUFFLDhEQUE4RDtvQkFDbkUsR0FBRyxFQUFFLGdEQUFnRDtpQkFDdEQ7Z0JBQ0QsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUM7WUFDRixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztZQUMvQixPQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDbEMsT0FBTyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQy9CLE9BQU8sQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoQyxPQUFPLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFFdEMsTUFBTSxRQUFRLEdBQUc7Z0JBQ2YsYUFBYSxFQUFFLFdBQVcsQ0FBQyxPQUFPO2dCQUNsQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUM7Z0JBQ25CLFVBQVUsRUFBRSxFQUFFO2dCQUNkLGFBQWEsRUFBRSxJQUFJO2dCQUNuQixnQkFBZ0IsRUFBRSxJQUFJO2dCQUN0QixPQUFPLEVBQUUsS0FBSztnQkFDZCxRQUFRLEVBQUU7b0JBQ1IsTUFBTSxFQUFFLENBQUM7b0JBQ1QsT0FBTyxFQUFFLEVBQUU7aUJBQ1o7Z0JBQ0QsU0FBUyxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFO2FBQ3ZDLENBQUM7WUFFRiw0QkFBNEI7WUFDNUIsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxxQ0FBcUMsRUFBRSxDQUFDLENBQUM7WUFDM0csTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFRLENBQUM7WUFFbEcsdUNBQXVDO1lBQ3ZDLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUscUNBQXFDLEVBQUUsQ0FBQyxDQUFDO1lBQzNHLE1BQU0sTUFBTSxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsaUJBQWlCLENBQUMsRUFBRSxHQUFHLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBUSxDQUFDO1lBRS9GLDRDQUE0QztZQUM1QyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5RixNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUV4RCxtREFBbUQ7WUFDbkQsUUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFFekQseUJBQXlCO1lBQ3pCLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFdEMsNkRBQTZEO1lBQzdELGNBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNsQixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxpREFBaUQsRUFBRSxLQUFLO1lBQ3pELE1BQU0sYUFBYSxHQUFHLGNBQWMsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZGLE1BQU0sT0FBTyxHQUFRO2dCQUNuQixTQUFTLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQztnQkFDbEQsS0FBSyxFQUFFLFlBQVk7Z0JBQ25CLFNBQVMsRUFBRSxRQUFRO2dCQUNuQixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxDQUFDLEVBQUUsQ0FBQztnQkFDSixjQUFjLEVBQUU7b0JBQ2QsR0FBRyxFQUFFLDhEQUE4RDtvQkFDbkUsR0FBRyxFQUFFLGdEQUFnRDtpQkFDdEQ7Z0JBQ0QsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUM7WUFDRixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQztZQUNqQyxPQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDbEMsT0FBTyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQy9CLE9BQU8sQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoQyxPQUFPLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFFdEMsTUFBTSxRQUFRLEdBQUc7Z0JBQ2YsYUFBYSxFQUFFLGFBQWEsQ0FBQyxPQUFPO2dCQUNwQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUM7Z0JBQ25CLFVBQVUsRUFBRSxFQUFFO2dCQUNkLGFBQWEsRUFBRSxJQUFJO2dCQUNuQixnQkFBZ0IsRUFBRSxJQUFJO2dCQUN0QixPQUFPLEVBQUUsS0FBSztnQkFDZCxRQUFRLEVBQUU7b0JBQ1IsTUFBTSxFQUFFLENBQUM7b0JBQ1QsT0FBTyxFQUFFLEVBQUU7aUJBQ1o7Z0JBQ0QsU0FBUyxFQUFFLEVBQUUsbUJBQW1CLEVBQUUsSUFBSSxFQUFFO2FBQ3pDLENBQUM7WUFFRiw0QkFBNEI7WUFDNUIsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxxQ0FBcUMsRUFBRSxDQUFDLENBQUM7WUFDM0csTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLEdBQUcsUUFBUSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFRLENBQUM7WUFFbEcsdUNBQXVDO1lBQ3ZDLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUscUNBQXFDLEVBQUUsQ0FBQyxDQUFDO1lBQzNHLE1BQU0sTUFBTSxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsaUJBQWlCLENBQUMsRUFBRSxHQUFHLFFBQVEsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBUSxDQUFDO1lBRS9GLDRDQUE0QztZQUM1QyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5RixNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUV4RCxtREFBbUQ7WUFDbkQsUUFBUSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFFekQseUJBQXlCO1lBQ3pCLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFdEMsNkRBQTZEO1lBQzdELGNBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNsQixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLO1lBQy9CLE1BQU0sV0FBVyxHQUFHLGNBQWMsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ3JGLE1BQU0sT0FBTyxHQUFRO2dCQUNuQixTQUFTLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQztnQkFDbEQsS0FBSyxFQUFFLFlBQVk7Z0JBQ25CLFNBQVMsRUFBRSxNQUFNO2dCQUNqQixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxDQUFDLEVBQUUsQ0FBQztnQkFDSixjQUFjLEVBQUU7b0JBQ2QsR0FBRyxFQUFFLDhEQUE4RDtvQkFDbkUsR0FBRyxFQUFFLGdEQUFnRDtpQkFDdEQ7Z0JBQ0QsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUM7WUFDRixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztZQUMvQixPQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDbEMsT0FBTyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQy9CLE9BQU8sQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUNoQyxPQUFPLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7WUFFdEMsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxxQ0FBcUMsRUFBRSxDQUFDLENBQUM7WUFFM0csTUFBTSxXQUFXLEdBQUcsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDMUQsYUFBYSxFQUFFLFdBQVcsQ0FBQyxPQUFPO2dCQUNsQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUM7Z0JBQ25CLFVBQVUsRUFBRSxFQUFFO2dCQUNkLGFBQWEsRUFBRSxJQUFJO2dCQUNuQixnQkFBZ0IsRUFBRSxJQUFJO2dCQUN0QixPQUFPLEVBQUUsS0FBSztnQkFDZCxRQUFRLEVBQUU7b0JBQ1IsTUFBTSxFQUFFLENBQUM7b0JBQ1QsT0FBTyxFQUFFLEVBQUU7aUJBQ1o7Z0JBQ0QsU0FBUyxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFO2dCQUN0QyxPQUFPLEVBQUUsSUFBSSxFQUFFLGlDQUFpQzthQUNqRCxDQUFDLENBQVEsQ0FBQztZQUVYLG1EQUFtRDtZQUNuRCxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1lBQzVELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUV2Qyw4QkFBOEI7WUFDOUIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbkcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxxQkFBcUI7WUFFL0QsMENBQTBDO1lBQzFDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2hDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2pDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ3BDLEtBQUssQ0FBQyxlQUFnQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsc0JBQXNCO1lBRXJFLDZCQUE2QjtZQUM3QixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQzdDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUV2RCwyREFBMkQ7WUFDM0QsTUFBTSxZQUFZLEdBQUcsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxlQUFlLENBQUM7Z0JBQ3pELGNBQWMsRUFBRSxXQUFXLENBQUMsY0FBYztnQkFDMUMsUUFBUSxFQUFFLFdBQVc7YUFDdEIsQ0FBQyxDQUFRLENBQUM7WUFFWCxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUU5Qix5Q0FBeUM7WUFDekMsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDOUYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsMkJBQTJCLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkcsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseUJBQXlCLEVBQUUsS0FBSztZQUNqQyxNQUFNLGFBQWEsR0FBRyxjQUFjLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUN2RixNQUFNLE9BQU8sR0FBUTtnQkFDbkIsU0FBUyxFQUFFLENBQUMscUNBQXFDLENBQUM7Z0JBQ2xELEtBQUssRUFBRSxZQUFZO2dCQUNuQixTQUFTLEVBQUUsUUFBUTtnQkFDbkIsSUFBSSxFQUFFLGtFQUFrRTtnQkFDeEUsQ0FBQyxFQUFFLENBQUM7Z0JBQ0osY0FBYyxFQUFFO29CQUNkLEdBQUcsRUFBRSw4REFBOEQ7b0JBQ25FLEdBQUcsRUFBRSxnREFBZ0Q7aUJBQ3REO2dCQUNELFFBQVEsRUFBRSxDQUFDO2dCQUNYLElBQUksRUFBRSxZQUFZO2dCQUNsQixhQUFhLEVBQUUsQ0FBQztnQkFDaEIsRUFBRSxFQUFFLFFBQVE7YUFDYixDQUFDO1lBQ0YsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDakMsT0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ2xDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztZQUMvQixPQUFPLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDaEMsT0FBTyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO1lBRXRDLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUscUNBQXFDLEVBQUUsQ0FBQyxDQUFDO1lBRTNHLE1BQU0sV0FBVyxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsaUJBQWlCLENBQUM7Z0JBQzFELGFBQWEsRUFBRSxhQUFhLENBQUMsT0FBTztnQkFDcEMsUUFBUSxFQUFFLENBQUMsT0FBTyxDQUFDO2dCQUNuQixVQUFVLEVBQUUsRUFBRTtnQkFDZCxhQUFhLEVBQUUsSUFBSTtnQkFDbkIsZ0JBQWdCLEVBQUUsSUFBSTtnQkFDdEIsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsUUFBUSxFQUFFO29CQUNSLE1BQU0sRUFBRSxDQUFDO29CQUNULE9BQU8sRUFBRSxFQUFFO2lCQUNaO2dCQUNELFNBQVMsRUFBRSxFQUFFLG1CQUFtQixFQUFFLElBQUksRUFBRTtnQkFDeEMsT0FBTyxFQUFFLElBQUksRUFBRSxpQ0FBaUM7YUFDakQsQ0FBQyxDQUFRLENBQUM7WUFFWCxtREFBbUQ7WUFDbkQsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDekMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztZQUU1RCw4QkFBOEI7WUFDOUIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbkcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFeEMsd0NBQXdDO1lBQ3hDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2hDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ2xDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2pDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRXBDLDJEQUEyRDtZQUMzRCxNQUFNLFlBQVksR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGVBQWUsQ0FBQztnQkFDekQsY0FBYyxFQUFFLFdBQVcsQ0FBQyxjQUFjO2dCQUMxQyxRQUFRLEVBQUUsV0FBVzthQUN0QixDQUFDLENBQVEsQ0FBQztZQUVYLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBRTlCLHlDQUF5QztZQUN6QyxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5RixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxVQUFVLEVBQUUsS0FBSztZQUNsQixNQUFNLFdBQVcsR0FBRyxjQUFjLENBQUMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUNyRixNQUFNLE9BQU8sR0FBUTtnQkFDbkIsU0FBUyxFQUFFLENBQUMscUNBQXFDLENBQUM7Z0JBQ2xELEtBQUssRUFBRSxZQUFZO2dCQUNuQixTQUFTLEVBQUUsTUFBTTtnQkFDakIsSUFBSSxFQUFFLGtFQUFrRTtnQkFDeEUsQ0FBQyxFQUFFLENBQUM7Z0JBQ0osY0FBYyxFQUFFO29CQUNkLEdBQUcsRUFBRSw4REFBOEQ7b0JBQ25FLEdBQUcsRUFBRSxnREFBZ0Q7aUJBQ3REO2dCQUNELFFBQVEsRUFBRSxDQUFDO2dCQUNYLElBQUksRUFBRSxZQUFZO2dCQUNsQixhQUFhLEVBQUUsQ0FBQztnQkFDaEIsRUFBRSxFQUFFLFFBQVE7YUFDYixDQUFDO1lBQ0YsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFDL0IsT0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDO1lBQ2xDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztZQUMvQixPQUFPLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDaEMsT0FBTyxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDO1lBRXRDLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUscUNBQXFDLEVBQUUsQ0FBQyxDQUFDO1lBRTNHLE1BQU0sV0FBVyxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsaUJBQWlCLENBQUM7Z0JBQzFELGFBQWEsRUFBRSxXQUFXLENBQUMsT0FBTztnQkFDbEMsUUFBUSxFQUFFLENBQUMsT0FBTyxDQUFDO2dCQUNuQixVQUFVLEVBQUUsRUFBRTtnQkFDZCxhQUFhLEVBQUUsSUFBSTtnQkFDbkIsZ0JBQWdCLEVBQUUsSUFBSTtnQkFDdEIsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsUUFBUSxFQUFFO29CQUNSLE1BQU0sRUFBRSxDQUFDO29CQUNULE9BQU8sRUFBRSxFQUFFO2lCQUNaO2dCQUNELFNBQVMsRUFBRSxFQUFFLGlCQUFpQixFQUFFLElBQUksRUFBRTtnQkFDdEMsT0FBTyxFQUFFLEtBQUs7YUFDZixDQUFDLENBQVEsQ0FBQztZQUNYLFdBQVcsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDckMsNE5BQTROLENBQzdOLENBQUM7WUFFRixzQkFBc0I7WUFDdEIsV0FBVyxDQUFDLFFBQVEsR0FBRyxXQUFXLENBQUM7WUFDbkMsV0FBVyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDNUIsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQVEsQ0FBQztZQUM5RSxVQUFVLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3hCLHdrQkFBd2tCLENBQ3prQixDQUFDO1lBQ0YsdUJBQXVCO1lBQ3ZCLFdBQVcsQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUMzQyxXQUFXLENBQUMsUUFBUSxHQUFHLGFBQWEsQ0FBQztZQUNyQyxXQUFXLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1lBQ3BDLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFRLENBQUM7WUFDOUUsNElBQTRJO1lBQzVJLDJHQUEyRztZQUMzRyw0REFBNEQ7WUFDNUQsVUFBVSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUN4Qiw0dEJBQTR0QixDQUM3dEIsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLGdCQUFnQixFQUFFLEtBQUs7WUFDeEIsTUFBTSxhQUFhLEdBQUcsY0FBYyxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDdkYsTUFBTSxPQUFPLEdBQVE7Z0JBQ25CLFNBQVMsRUFBRSxDQUFDLHFDQUFxQyxDQUFDO2dCQUNsRCxLQUFLLEVBQUUsWUFBWTtnQkFDbkIsU0FBUyxFQUFFLFFBQVE7Z0JBQ25CLElBQUksRUFBRSxrRUFBa0U7Z0JBQ3hFLENBQUMsRUFBRSxDQUFDO2dCQUNKLGNBQWMsRUFBRTtvQkFDZCxHQUFHLEVBQUUsOERBQThEO29CQUNuRSxHQUFHLEVBQUUsZ0RBQWdEO2lCQUN0RDtnQkFDRCxRQUFRLEVBQUUsQ0FBQztnQkFDWCxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsYUFBYSxFQUFFLENBQUM7Z0JBQ2hCLEVBQUUsRUFBRSxRQUFRO2FBQ2IsQ0FBQztZQUNGLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQ2pDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztZQUNsQyxPQUFPLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDL0IsT0FBTyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQztZQUV0QyxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLHFDQUFxQyxFQUFFLENBQUMsQ0FBQztZQUUzRyxNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGlCQUFpQixDQUFDO2dCQUMxRCxhQUFhLEVBQUUsYUFBYSxDQUFDLE9BQU87Z0JBQ3BDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQztnQkFDbkIsVUFBVSxFQUFFLEVBQUU7Z0JBQ2QsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLE9BQU8sRUFBRSxLQUFLO2dCQUNkLFFBQVEsRUFBRTtvQkFDUixNQUFNLEVBQUUsQ0FBQztvQkFDVCxPQUFPLEVBQUUsRUFBRTtpQkFDWjtnQkFDRCxTQUFTLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUU7Z0JBQ3hDLE9BQU8sRUFBRSxLQUFLO2FBQ2YsQ0FBQyxDQUFRLENBQUM7WUFDWCxXQUFXLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3JDLGdPQUFnTyxDQUNqTyxDQUFDO1lBRUYsc0JBQXNCO1lBQ3RCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO1lBQ25DLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFRLENBQUM7WUFDOUUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUN4Qix3cEJBQXdwQixDQUN6cEIsQ0FBQztZQUVGLHVCQUF1QjtZQUN2QixXQUFXLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDM0MsV0FBVyxDQUFDLFFBQVEsR0FBRyxhQUFhLENBQUM7WUFDckMsV0FBVyxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztZQUNwQyxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBUSxDQUFDO1lBQzlFLDRJQUE0STtZQUM1SSwyR0FBMkc7WUFDM0csNERBQTREO1lBQzVELFVBQVUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDeEIsc3lCQUFzeUIsQ0FDdnlCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywyRUFBMkUsRUFBRSxLQUFLO1lBQ25GLE1BQU0sRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxHQUFHLE1BQU0sSUFBQSxxQkFBVSxFQUM5RCxHQUFHLFNBQVMsaUNBQWlDLENBQzlDLENBQUM7WUFDRixNQUFNLFNBQVMsR0FBRyxJQUFJLG1CQUFRLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDcEYsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUU7Z0JBQ2pELEVBQUUsRUFBRSxPQUFPO2dCQUNYLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLFlBQVksRUFBRSxFQUFFO2FBQ3BDLENBQUMsQ0FBQztZQUNILE1BQU0sZUFBZSxHQUFHO2dCQUN0QjtvQkFDRSxLQUFLLEVBQUUsTUFBTTtvQkFDYixZQUFZO29CQUNaLE1BQU0sRUFBRSxZQUFZO29CQUNwQixPQUFPLEVBQUUsa0VBQWtFO29CQUMzRSxXQUFXLEVBQUUsQ0FBQztvQkFDZCxhQUFhLEVBQUUsQ0FBQztpQkFDakI7Z0JBQ0Q7b0JBQ0UsS0FBSyxFQUFFLE1BQU07b0JBQ2IsWUFBWTtvQkFDWixNQUFNLEVBQUUsWUFBWTtvQkFDcEIsT0FBTyxFQUFFLGtFQUFrRTtvQkFDM0UsV0FBVyxFQUFFLENBQUM7b0JBQ2QsYUFBYSxFQUFFLENBQUM7aUJBQ2pCO2FBQ0YsQ0FBQztZQUNGLE1BQU0sVUFBVSxHQUFHO2dCQUNqQixxQ0FBcUMsRUFBRSxNQUFNLEVBQUUsZ0RBQWdEO2FBQ2hHLENBQUM7WUFFRixNQUFNLEtBQUssR0FBRyxJQUFBLGNBQUksRUFBQyxTQUFTLENBQUM7aUJBQzFCLElBQUksQ0FBQyx5QkFBeUIsQ0FBQztpQkFDL0IsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBRSxxQ0FBcUMsRUFBRSxDQUFDLENBQUM7WUFFbEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxvQkFBb0IsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDMUQsVUFBVTtnQkFDVixRQUFRLEVBQUUsZUFBZTtnQkFDekIsT0FBTyxFQUFFLEtBQUssRUFBRSxjQUFjO2dCQUM5QixRQUFRLEVBQUU7b0JBQ1IsTUFBTSxFQUFFLENBQUM7b0JBQ1QsT0FBTyxFQUFFLEVBQUU7aUJBQ1o7Z0JBQ0QsT0FBTyxFQUFFLEtBQUs7YUFDZixDQUFDLENBQUM7WUFFSCxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUVoQyxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzlCLDhGQUE4RjtZQUM5RixrREFBa0Q7WUFDbEQsc0dBQXNHO1lBQ3RHLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsK0ZBQStGLEVBQUUsS0FBSztZQUN2RyxNQUFNLEVBQ0osT0FBTyxFQUNQLFlBQVksRUFDWixZQUFZLEVBQ1osVUFBVSxFQUFFLGNBQWMsRUFDMUIsV0FBVyxFQUFFLGVBQWUsRUFDNUIsYUFBYSxFQUNiLGVBQWUsRUFDZixlQUFlLEdBQ2hCLEdBQUcsTUFBTSxJQUFBLHFCQUFVLEVBQTBCLEdBQUcsU0FBUyxpQ0FBaUMsQ0FBQyxDQUFDO1lBQzdGLE1BQU0sU0FBUyxHQUFHLElBQUksbUJBQVEsQ0FBQyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsZUFBZSxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNwRixNQUFNLG9CQUFvQixHQUFHLElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRTtnQkFDakQsRUFBRSxFQUFFLE9BQU87Z0JBQ1gsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUU7YUFDcEMsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxlQUFlLEdBQUc7Z0JBQ3RCLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRTtnQkFDckQsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFO2FBQ3RELENBQUM7WUFDRixNQUFNLFlBQVksR0FBRyxNQUFNLG9CQUFvQixDQUFDLGVBQWUsQ0FBQztnQkFDOUQsY0FBYyxFQUFFLGFBQWE7Z0JBQzdCLFVBQVUsRUFBRSxjQUFjO2dCQUMxQixRQUFRLEVBQUUsZUFBZTtnQkFDekIsUUFBUSxFQUFFLElBQUk7YUFDZixDQUFDLENBQUM7WUFDSCxZQUFZLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7WUFFOUMsTUFBTSxZQUFZLEdBQUcsTUFBTSxvQkFBb0IsQ0FBQyxlQUFlLENBQUM7Z0JBQzlELGNBQWMsRUFBRSxlQUFlO2dCQUMvQixVQUFVLEVBQUUsZUFBZTtnQkFDM0IsUUFBUSxFQUFFLGVBQWU7Z0JBQ3pCLFFBQVEsRUFBRSxJQUFJO2dCQUNkLGdCQUFnQixFQUFFLElBQUk7YUFDdkIsQ0FBQyxDQUFDO1lBQ0gsc0hBQXNIO1lBQ3RILG1JQUFtSTtZQUNuSSw0RUFBNEU7WUFDNUUsWUFBWSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ2hELENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLHdCQUF3QixFQUFFLEtBQUs7WUFDaEMsTUFBTSxhQUFhLEdBQUcsY0FBYyxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDdkYsTUFBTSxPQUFPLEdBQVE7Z0JBQ25CLFNBQVMsRUFBRSxDQUFDLHFDQUFxQyxDQUFDO2dCQUNsRCxLQUFLLEVBQUUsWUFBWTtnQkFDbkIsU0FBUyxFQUFFLFFBQVE7Z0JBQ25CLElBQUksRUFBRSxrRUFBa0U7Z0JBQ3hFLENBQUMsRUFBRSxDQUFDO2dCQUNKLGNBQWMsRUFBRTtvQkFDZCxHQUFHLEVBQUUsOERBQThEO29CQUNuRSxHQUFHLEVBQUUsZ0RBQWdEO2lCQUN0RDtnQkFDRCxRQUFRLEVBQUUsQ0FBQztnQkFDWCxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsYUFBYSxFQUFFLENBQUM7Z0JBQ2hCLEVBQUUsRUFBRSxRQUFRO2FBQ2IsQ0FBQztZQUNGLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQ2pDLE9BQU8sQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztZQUNsQyxPQUFPLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDL0IsT0FBTyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQztZQUV0QyxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLHFDQUFxQyxFQUFFLENBQUMsQ0FBQztZQUUzRyxNQUFNLFdBQVcsR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGlCQUFpQixDQUFDO2dCQUMxRCxhQUFhLEVBQUUsYUFBYSxDQUFDLE9BQU87Z0JBQ3BDLFFBQVEsRUFBRSxDQUFDLE9BQU8sQ0FBQztnQkFDbkIsVUFBVSxFQUFFLEVBQUU7Z0JBQ2QsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLE9BQU8sRUFBRSxLQUFLO2dCQUNkLFFBQVEsRUFBRTtvQkFDUixNQUFNLEVBQUUsQ0FBQztvQkFDVCxPQUFPLEVBQUUsRUFBRTtpQkFDWjtnQkFDRCxTQUFTLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUU7Z0JBQ3hDLE9BQU8sRUFBRSxLQUFLO2FBQ2YsQ0FBQyxDQUFRLENBQUM7WUFDWCxXQUFXLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3JDLGdPQUFnTyxDQUNqTyxDQUFDO1lBRUYsc0JBQXNCO1lBQ3RCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO1lBQ25DLFdBQVcsQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1lBQzVCLENBQUMsR0FBRyxFQUFFLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUN6RyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxLQUFLO1lBQzdCLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ2pGLE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ25GLE1BQU0sV0FBVyxHQUFHO2dCQUNsQixTQUFTLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQztnQkFDbEQsS0FBSyxFQUFFLFlBQVk7Z0JBQ25CLFNBQVMsRUFBRSxTQUFTO2dCQUNwQixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxDQUFDLEVBQUUsQ0FBQztnQkFDSixjQUFjLEVBQUU7b0JBQ2QsR0FBRyxFQUFFLDhEQUE4RDtvQkFDbkUsR0FBRyxFQUFFLGdEQUFnRDtpQkFDdEQ7Z0JBQ0QsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUM7WUFDRixNQUFNLGFBQWEsR0FBRztnQkFDcEIsU0FBUyxFQUFFLENBQUMscUNBQXFDLENBQUM7Z0JBQ2xELEtBQUssRUFBRSxZQUFZO2dCQUNuQixTQUFTLEVBQUUsU0FBUztnQkFDcEIsSUFBSSxFQUFFLGtFQUFrRTtnQkFDeEUsQ0FBQyxFQUFFLENBQUM7Z0JBQ0osY0FBYyxFQUFFO29CQUNkLEdBQUcsRUFBRSw4REFBOEQ7b0JBQ25FLEdBQUcsRUFBRSxnREFBZ0Q7aUJBQ3REO2dCQUNELFFBQVEsRUFBRSxDQUFDO2dCQUNYLElBQUksRUFBRSxZQUFZO2dCQUNsQixhQUFhLEVBQUUsQ0FBQztnQkFDaEIsRUFBRSxFQUFFLFFBQVE7YUFDYixDQUFDO1lBQ0YsTUFBTSxTQUFTLEdBQUcsQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDL0MsTUFBTSxRQUFRLEdBQUcsQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBWSxFQUFFLEtBQUssRUFBRSxFQUFFO2dCQUN4RSxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2pDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUMzQixPQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7Z0JBQ2xDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDL0IsT0FBTyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUNoQyxPQUFPLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7Z0JBQ3RDLE9BQU8sT0FBTyxDQUFDO1lBQ2pCLENBQUMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxXQUFXLEdBQUcsQ0FBQyxNQUFNLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDdEQsYUFBYSxFQUFFLFdBQVcsQ0FBQyxPQUFPO2dCQUNsQyxRQUFRLEVBQUUsUUFBUTtnQkFDbEIsVUFBVSxFQUFFLEVBQUU7Z0JBQ2QsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLGdCQUFnQixFQUFFLElBQUk7Z0JBQ3RCLE9BQU8sRUFBRSxLQUFLO2dCQUNkLFNBQVMsRUFBRSxFQUFFLGdDQUFnQyxFQUFFLFNBQVMsRUFBRTtnQkFDMUQsUUFBUSxFQUFFO29CQUNSLE1BQU0sRUFBRSxLQUFLO29CQUNiLE9BQU8sRUFBRSxxQ0FBcUM7aUJBQy9DO2dCQUNELE9BQU8sRUFBRSxLQUFLO2FBQ2YsQ0FBQyxDQUFRLENBQUM7WUFDWCxXQUFXLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3JDLDRZQUE0WSxDQUM3WSxDQUFDO1lBRUYsc0JBQXNCO1lBQ3RCLFdBQVcsQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO1lBQ25DLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFRLENBQUM7WUFDOUUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUN4QixrckNBQWtyQyxDQUNuckMsQ0FBQztZQUVGLHVCQUF1QjtZQUN2QixXQUFXLENBQUMsY0FBYyxHQUFHLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDM0MsV0FBVyxDQUFDLFFBQVEsR0FBRyxhQUFhLENBQUM7WUFDckMsV0FBVyxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztZQUNwQyxNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQU0sY0FBYyxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsQ0FBUSxDQUFDO1lBQzlFLDRJQUE0STtZQUM1SSwyR0FBMkc7WUFDM0csNERBQTREO1lBQzVELFVBQVUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDeEIsbzlDQUFvOUMsQ0FDcjlDLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxpQ0FBaUMsRUFBRSxLQUFLO1lBQ3pDLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQ2pGLE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ25GLE1BQU0sV0FBVyxHQUFHO2dCQUNsQixTQUFTLEVBQUUsQ0FBQyxxQ0FBcUMsQ0FBQztnQkFDbEQsS0FBSyxFQUFFLFlBQVk7Z0JBQ25CLFNBQVMsRUFBRSxTQUFTO2dCQUNwQixJQUFJLEVBQUUsa0VBQWtFO2dCQUN4RSxDQUFDLEVBQUUsQ0FBQztnQkFDSixjQUFjLEVBQUU7b0JBQ2QsR0FBRyxFQUFFLDhEQUE4RDtvQkFDbkUsR0FBRyxFQUFFLGdEQUFnRDtpQkFDdEQ7Z0JBQ0QsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixFQUFFLEVBQUUsUUFBUTthQUNiLENBQUM7WUFDRixNQUFNLGFBQWEsR0FBRztnQkFDcEIsU0FBUyxFQUFFLENBQUMscUNBQXFDLENBQUM7Z0JBQ2xELEtBQUssRUFBRSxZQUFZO2dCQUNuQixTQUFTLEVBQUUsU0FBUztnQkFDcEIsSUFBSSxFQUFFLGtFQUFrRTtnQkFDeEUsQ0FBQyxFQUFFLENBQUM7Z0JBQ0osY0FBYyxFQUFFO29CQUNkLEdBQUcsRUFBRSw4REFBOEQ7b0JBQ25FLEdBQUcsRUFBRSxnREFBZ0Q7aUJBQ3REO2dCQUNELFFBQVEsRUFBRSxDQUFDO2dCQUNYLElBQUksRUFBRSxZQUFZO2dCQUNsQixhQUFhLEVBQUUsQ0FBQztnQkFDaEIsRUFBRSxFQUFFLFFBQVE7YUFDYixDQUFDO1lBQ0YsTUFBTSxTQUFTLEdBQUcsQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDL0MsTUFBTSxRQUFRLEdBQUcsQ0FBQyxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBWSxFQUFFLEtBQUssRUFBRSxFQUFFO2dCQUN4RSxNQUFNLE9BQU8sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2pDLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUMzQixPQUFPLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7Z0JBQ2xDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDL0IsT0FBTyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUNoQyxPQUFPLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUM7Z0JBQ3RDLE9BQU8sT0FBTyxDQUFDO1lBQ2pCLENBQUMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxXQUFXLEdBQUcsQ0FBQyxNQUFNLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQztnQkFDdEQsYUFBYSxFQUFFLFdBQVcsQ0FBQyxPQUFPO2dCQUNsQyxRQUFRLEVBQUUsUUFBUTtnQkFDbEIsVUFBVSxFQUFFLEVBQUUsOERBQThELEVBQUUsTUFBTSxFQUFFO2dCQUN0RixhQUFhLEVBQUUsSUFBSTtnQkFDbkIsZ0JBQWdCLEVBQUUsSUFBSTtnQkFDdEIsT0FBTyxFQUFFLEtBQUs7Z0JBQ2QsU0FBUyxFQUFFLEVBQUUsZ0NBQWdDLEVBQUUsU0FBUyxFQUFFO2dCQUMxRCxRQUFRLEVBQUU7b0JBQ1IsTUFBTSxFQUFFLEtBQUs7b0JBQ2IsT0FBTyxFQUFFLHFDQUFxQztpQkFDL0M7Z0JBQ0QsT0FBTyxFQUFFLEtBQUs7YUFDZixDQUFDLENBQVEsQ0FBQztZQUNYLFdBQVcsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDckMsa2VBQWtlLENBQ25lLENBQUM7WUFFRixzQkFBc0I7WUFDdEIsV0FBVyxDQUFDLFFBQVEsR0FBRyxXQUFXLENBQUM7WUFDbkMsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQVEsQ0FBQztZQUM5RSxVQUFVLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQ3hCLDB3Q0FBMHdDLENBQzN3QyxDQUFDO1lBRUYsdUJBQXVCO1lBQ3ZCLFdBQVcsQ0FBQyxjQUFjLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQztZQUMzQyxXQUFXLENBQUMsUUFBUSxHQUFHLGFBQWEsQ0FBQztZQUNyQyxXQUFXLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1lBQ3BDLE1BQU0sVUFBVSxHQUFHLENBQUMsTUFBTSxjQUFjLENBQUMsZUFBZSxDQUFDLFdBQVcsQ0FBQyxDQUFRLENBQUM7WUFDOUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1lBQ3hELDRJQUE0STtZQUM1SSwyR0FBMkc7WUFDM0csNERBQTREO1lBQzVELFVBQVUsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDeEIsMGlEQUEwaUQsQ0FDM2lELENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLFdBQVcsRUFBRTtRQUNwQixFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSztZQUMvQyxNQUFNLE1BQU0sR0FBRztnQkFDYixVQUFVLEVBQUU7b0JBQ1Y7d0JBQ0UsT0FBTyxFQUFFLHFDQUFxQzt3QkFDOUMsTUFBTSxFQUFFLE1BQU07cUJBQ2Y7aUJBQ0Y7YUFDRixDQUFDO1lBQ0YsTUFBTSxRQUFRLEdBQUc7Z0JBQ2Y7b0JBQ0UsS0FBSyxFQUFFLElBQUk7aUJBQ1o7Z0JBQ0Q7b0JBQ0UsS0FBSyxFQUFFLE1BQU07aUJBQ2Q7YUFDRixDQUFDO1lBQ0YsTUFBTSxxQkFBcUIsR0FBRztnQkFDNUIsUUFBUSxFQUFFLENBQUM7Z0JBQ1gsV0FBVyxFQUFFLEVBQUU7Z0JBQ2YsUUFBUTtnQkFDUixFQUFFLEVBQUUsZUFBZTthQUNwQixDQUFDO1lBQ0YsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsMEJBQTBCLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7WUFDbkcsTUFBTSxpQkFBaUIsR0FBRyxHQUFHLEVBQUUsQ0FBQyxDQUFDO2dCQUMvQixNQUFNLEVBQUUsVUFBVTtnQkFDbEIsRUFBRSxFQUFFLDgzQ0FBODNDO2dCQUNsNEMsSUFBSSxFQUFFLGtFQUFrRTtnQkFDeEUsT0FBTyxFQUFFLEtBQUs7YUFDZixDQUFDLENBQUM7WUFDSCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUNsQztnQkFDRSxHQUFHLEVBQUUsSUFBSTtnQkFDVCxPQUFPLEVBQUUsaUJBQWlCO2FBQzNCLEVBQ0QsaUJBQWlCLEVBQUUsQ0FDcEIsQ0FBQztZQUNGLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLGlCQUFpQixDQUFDLENBQUMsUUFBUSxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztZQUN4RSxNQUFNLE1BQU0sR0FBRyxDQUFDLE1BQU0sVUFBVSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBUSxDQUFDO1lBQzFELE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDMUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM1QyxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3RELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsd0NBQXdDLEVBQUUsU0FBUywwQkFBMEI7UUFDcEYsSUFBSSxNQUFNLENBQUM7UUFDWCxJQUFJLEtBQUssQ0FBQztRQUNWLElBQUksV0FBVyxDQUFDO1FBQ2hCLElBQUksYUFBYSxDQUFDO1FBRWxCLElBQUksVUFBVSxHQUFHLGtFQUFrRSxDQUFDO1FBQ3BGLE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBQztRQUNwQixNQUFNLGFBQWEsR0FBRyxxQ0FBcUMsQ0FBQztRQUM1RCxNQUFNLGFBQWEsR0FBRyxrRUFBa0UsQ0FBQztRQUN6RixNQUFNLFFBQVEsR0FBRyxxQ0FBcUMsQ0FBQztRQUV2RDs7Ozs7Ozs7Ozs7V0FXRztRQUNILFNBQVMsZUFBZSxDQUFDLEVBQUUsSUFBSSxFQUFFO1lBQy9CLE9BQVEsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQWEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUVELE1BQU0sQ0FBQyxTQUFTLHdCQUF3QjtZQUN0QyxjQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUV0QyxLQUFLLEdBQUcsSUFBSSxtQkFBUSxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzFFLDhCQUE4QjtZQUM5QixLQUFLLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pCLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsUUFBUSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDNUcsTUFBYyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7WUFDOUIsS0FBSyxHQUFHLGlCQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUNoRCxXQUFXLEdBQUcsaUJBQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsa0JBQWtCLENBQUM7WUFFckUsK0VBQStFO1lBQy9FLDRGQUE0RjtZQUM1RixhQUFhLEdBQUcsR0FBRyxDQUFDO1FBQ3RCLENBQUMsQ0FBQyxDQUFDO1FBRUgsS0FBSyxDQUFDLFNBQVMsdUJBQXVCO1lBQ3BDLDJFQUEyRTtZQUMzRSxjQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN4QyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxXQUFXLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDekIsTUFBTSxNQUFNLENBQUMscUJBQXFCLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO1lBRWxILE1BQU0sTUFBTTtpQkFDVCxxQkFBcUIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDO2lCQUMzRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyw4REFBOEQsQ0FBQyxDQUFDO1lBRTFGLE1BQU0sTUFBTTtpQkFDVCxxQkFBcUIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsQ0FBQztpQkFDL0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsOEJBQThCLENBQUMsQ0FBQztZQUUxRCxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ2pFLEtBQUssTUFBTSxPQUFPLElBQUksY0FBYyxFQUFFLENBQUM7Z0JBQ3JDLE1BQU0sTUFBTTtxQkFDVCxxQkFBcUIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUM7cUJBQ3hELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLDJEQUEyRCxDQUFDLENBQUM7WUFDekYsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsUUFBUSxDQUFDLFdBQVcsRUFBRSxTQUFTLGdCQUFnQjtZQUM3QyxLQUFLLENBQUMsR0FBRyxFQUFFO2dCQUNULDJFQUEyRTtnQkFDM0UsY0FBSSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDeEMsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQzNDLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQztxQkFDUixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsT0FBTyxVQUFVLEVBQUUsQ0FBQztxQkFDckQsS0FBSyxDQUFDLEdBQUcsRUFBRSxzQ0FBc0MsQ0FBQyxDQUFDO2dCQUV0RCxNQUFNLE1BQU07cUJBQ1QscUJBQXFCLENBQUMsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQztxQkFDbEUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsNkNBQTZDLENBQUMsQ0FBQztZQUMzRSxDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDckMsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sVUFBVSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUMzRSxhQUFhLEVBQUUsQ0FBQztpQkFDakIsQ0FBQyxDQUFDO2dCQUVILE1BQU0sTUFBTTtxQkFDVCxxQkFBcUIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDO3FCQUNuRSxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyx3RUFBd0UsQ0FBQyxDQUFDO1lBQ3RHLENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLHNCQUFzQixFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNwQyxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sVUFBVSxFQUFFLENBQUM7cUJBQ3JELEtBQUssQ0FBQyxHQUFHLEVBQUU7b0JBQ1YsT0FBTyxFQUFFO3dCQUNQOzRCQUNFLE9BQU8sRUFBRSxhQUFhOzRCQUN0QixLQUFLLEVBQUUsT0FBTzs0QkFDZCxJQUFJLEVBQUUsQ0FBQzs0QkFDUCxLQUFLLEVBQUUsQ0FBQzt5QkFDVDtxQkFDRjtvQkFDRCxhQUFhLEVBQUUsQ0FBQztpQkFDakIsQ0FBQyxDQUFDO2dCQUVMLE1BQU0sTUFBTTtxQkFDVCxxQkFBcUIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxDQUFDO3FCQUNuRSxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FDckIsNEZBQTRGLENBQzdGLENBQUM7WUFDTixDQUFDLENBQUMsQ0FBQztZQUVIOzs7Ozs7OztlQVFHO1lBQ0gsRUFBRSxDQUFDLG9DQUFvQyxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNsRCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sVUFBVSxFQUFFLENBQUM7cUJBQ3JELEtBQUssQ0FBQyxHQUFHLEVBQUU7b0JBQ1YsT0FBTyxFQUFFO3dCQUNQOzRCQUNFLE9BQU8sRUFBRSxhQUFhOzRCQUN0QixLQUFLLEVBQUUsRUFBRSxHQUFHLEdBQUc7NEJBQ2YsSUFBSSxFQUFFLFNBQVM7NEJBQ2YsTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLENBQUM7eUJBQ1Q7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFLENBQUM7b0JBQ2hCLEdBQUcsRUFBRSxVQUFVO29CQUNmLEdBQUcsRUFBRSxFQUFFO2lCQUNSLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7b0JBQy9FLEtBQUssRUFBRSxDQUFDO29CQUNSLFFBQVEsRUFBRSxFQUFFO2lCQUNiLENBQUMsQ0FBQztnQkFFSCxNQUFNLE1BQU07cUJBQ1QscUJBQXFCLENBQUMsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztxQkFDbkUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsc0VBQXNFLENBQUMsQ0FBQztZQUNwRyxDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyxzRUFBc0UsRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDcEYsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLFVBQVUsRUFBRSxDQUFDO3FCQUNyRCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLE9BQU8sRUFBRTt3QkFDUDs0QkFDRSxPQUFPLEVBQUUsYUFBYTs0QkFDdEIsS0FBSyxFQUFFLEVBQUU7NEJBQ1QsSUFBSSxFQUFFLFNBQVM7NEJBQ2YsTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLENBQUM7eUJBQ1Q7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFLENBQUM7b0JBQ2hCLEdBQUcsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDO29CQUN6QixHQUFHLEVBQUUsRUFBRTtpQkFDUixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUM7cUJBQzdDLEtBQUssQ0FBQyxJQUFJLENBQUM7cUJBQ1gsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixLQUFLLEVBQUUsQ0FBQztvQkFDUixRQUFRLEVBQUU7d0JBQ1I7NEJBQ0UsT0FBTyxFQUFFLFVBQVU7NEJBQ25CLFdBQVcsRUFBRSxTQUFTO3lCQUN2QjtxQkFDRjtpQkFDRixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sVUFBVSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO2dCQUVuRixNQUFNLE1BQU07cUJBQ1QscUJBQXFCLENBQUMsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztxQkFDbkUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsa0ZBQWtGLENBQUMsQ0FBQztZQUNoSCxDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyxzRUFBc0UsRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDcEYsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLFVBQVUsRUFBRSxDQUFDO3FCQUNyRCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLE9BQU8sRUFBRTt3QkFDUDs0QkFDRSxPQUFPLEVBQUUsYUFBYTs0QkFDdEIsS0FBSyxFQUFFLEVBQUU7NEJBQ1QsSUFBSSxFQUFFLFNBQVM7NEJBQ2YsTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLENBQUM7eUJBQ1Q7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFLENBQUM7b0JBQ2hCLEdBQUcsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDO29CQUN6QixHQUFHLEVBQUUsRUFBRTtpQkFDUixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUM7cUJBQzdDLEtBQUssQ0FBQyxJQUFJLENBQUM7cUJBQ1gsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixLQUFLLEVBQUUsQ0FBQztvQkFDUixRQUFRLEVBQUU7d0JBQ1I7NEJBQ0UsT0FBTyxFQUFFLFVBQVU7NEJBQ25CLFdBQVcsRUFBRSxTQUFTO3lCQUN2QjtxQkFDRjtpQkFDRixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sVUFBVSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO2dCQUVoRixJQUFBLGNBQUksRUFBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7b0JBQy9FLEtBQUssRUFBRSxDQUFDO29CQUNSLFFBQVEsRUFBRSxFQUFFO2lCQUNiLENBQUMsQ0FBQztnQkFFSCxNQUFNLE1BQU07cUJBQ1QscUJBQXFCLENBQUMsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztxQkFDbkUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsb0VBQW9FLENBQUMsQ0FBQztZQUNsRyxDQUFDLENBQUMsQ0FBQztZQUVILEVBQUUsQ0FBQyx1QkFBdUIsRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDckMsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLFVBQVUsRUFBRSxDQUFDO3FCQUNyRCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLE9BQU8sRUFBRTt3QkFDUDs0QkFDRSxPQUFPLEVBQUUsYUFBYTs0QkFDdEIsS0FBSyxFQUFFLEVBQUU7NEJBQ1QsSUFBSSxFQUFFLFNBQVM7NEJBQ2YsTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLEVBQUU7eUJBQ1Y7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFLENBQUM7b0JBQ2hCLEdBQUcsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDO29CQUN6QixHQUFHLEVBQUUsS0FBSyxFQUFFLDJDQUEyQztpQkFDeEQsQ0FBQyxDQUFDO2dCQUVMLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQztxQkFDUixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsV0FBVyxDQUFDO3FCQUM3QyxLQUFLLENBQUMsSUFBSSxDQUFDO3FCQUNYLEtBQUssQ0FBQyxHQUFHLEVBQUU7b0JBQ1YsS0FBSyxFQUFFLENBQUM7b0JBQ1IsUUFBUSxFQUFFO3dCQUNSOzRCQUNFLE9BQU8sRUFBRSxVQUFVOzRCQUNuQixXQUFXLEVBQUUsU0FBUzt5QkFDdkI7cUJBQ0Y7aUJBQ0YsQ0FBQyxDQUFDO2dCQUVMLElBQUEsY0FBSSxFQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLFVBQVUsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztnQkFFaEYsTUFBTSxNQUFNO3FCQUNULHFCQUFxQixDQUFDLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7cUJBQ25FLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUNyQixvSEFBb0gsQ0FDckgsQ0FBQztZQUNOLENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLHlEQUF5RCxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUN2RSxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLE9BQU8sVUFBVSxFQUFFLENBQUM7cUJBQ3JELEtBQUssQ0FBQyxHQUFHLEVBQUU7b0JBQ1YsT0FBTyxFQUFFO3dCQUNQOzRCQUNFLE9BQU8sRUFBRSxhQUFhOzRCQUN0QixLQUFLLEVBQUUsR0FBRzs0QkFDVixJQUFJLEVBQUUsU0FBUzs0QkFDZixNQUFNLEVBQUUsSUFBSTs0QkFDWixLQUFLLEVBQUUsRUFBRTt5QkFDVjtxQkFDRjtvQkFDRCxhQUFhLEVBQUUsQ0FBQztvQkFDaEIsR0FBRyxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUM7b0JBQ3pCLEdBQUcsRUFBRSxJQUFJO2lCQUNWLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQztxQkFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQztxQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLEtBQUssRUFBRSxDQUFDO29CQUNSLFFBQVEsRUFBRTt3QkFDUjs0QkFDRSxPQUFPLEVBQUUsVUFBVTs0QkFDbkIsV0FBVyxFQUFFLFNBQVM7eUJBQ3ZCO3FCQUNGO2lCQUNGLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxVQUFVLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7Z0JBRWhGLE1BQU0sTUFBTTtxQkFDVCxxQkFBcUIsQ0FBQyxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDO3FCQUNsRSxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FDckIsNEhBQTRILENBQzdILENBQUM7WUFDTixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsUUFBUSxDQUFDLDRCQUE0QixFQUFFLFNBQVMsb0JBQW9CO1lBQ2xFLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQztZQUV0QixVQUFVLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ3BCLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxZQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNyRSxPQUFPLEVBQUUscUNBQXFDO2lCQUMvQyxDQUFDLENBQUM7Z0JBRUgsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDckQsT0FBTyxFQUFFLHFDQUFxQztpQkFDL0MsQ0FBQyxDQUFDO2dCQUVILElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUN2RCxRQUFRLEVBQUUsQ0FBQztpQkFDWixDQUFDLENBQUM7Z0JBRUgsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLElBQUksQ0FBQyxvQkFBb0IsV0FBVyxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQztxQkFDaEQsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixhQUFhLEVBQUUsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLFdBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO29CQUMxRyxJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUksR0FBRyxXQUFXLENBQUMsYUFBYTtpQkFDbkQsQ0FBQyxDQUFDO1lBQ1AsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsb0RBQW9ELEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ2xFLFVBQVUsR0FBRyxrRUFBa0UsQ0FBQztnQkFDaEYsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLFVBQVUsRUFBRSxDQUFDO3FCQUNyRCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLEdBQUcsRUFBRSxHQUFHO29CQUNSLE9BQU8sRUFBRTt3QkFDUDs0QkFDRSxJQUFJLEVBQUUsQ0FBQzs0QkFDUCxLQUFLLEVBQUUsUUFBUTs0QkFDZixNQUFNLEVBQUUsSUFBSTs0QkFDWixLQUFLLEVBQUUsQ0FBQzt5QkFDVDt3QkFDRDs0QkFDRSxJQUFJLEVBQUUsQ0FBQzs0QkFDUCxLQUFLLEVBQUUsS0FBSzs0QkFDWixNQUFNLEVBQUUsSUFBSTs0QkFDWixLQUFLLEVBQUUsRUFBRTt5QkFDVjtxQkFDRjtpQkFDRixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUM7cUJBQzdDLEtBQUssQ0FBQyxJQUFJLENBQUM7cUJBQ1gsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixRQUFRLEVBQUU7d0JBQ1I7NEJBQ0UsT0FBTyxFQUFFLFVBQVU7NEJBQ25CLFdBQVcsRUFBRSxDQUFDOzRCQUNkLEtBQUssRUFBRSxRQUFROzRCQUNmLFlBQVksRUFBRSxzRUFBc0U7NEJBQ3BGLFNBQVMsRUFBRSxTQUFTOzRCQUNwQixhQUFhLEVBQ1gsb05BQW9OO3lCQUN2TjtxQkFDRjtpQkFDRixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sVUFBVSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO2dCQUVoRixJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUU7b0JBQ2hDLE9BQU8sQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7Z0JBQ2hDLENBQUMsQ0FBQztxQkFDRCxLQUFLLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxFQUFFLElBQUk7b0JBQzNCLE9BQU87d0JBQ0wsV0FBVyxFQUFHLElBQVksQ0FBQyxFQUFFO3FCQUM5QixDQUFDO2dCQUNKLENBQUMsQ0FBQyxDQUFDO2dCQUVMLE1BQU0sT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLHFCQUFxQixDQUFDO29CQUNqRCxhQUFhLEVBQUUsVUFBVTtvQkFDekIsT0FBTztvQkFDUCxnQkFBZ0IsRUFBRSxTQUFTLENBQUMscUJBQXFCO2lCQUNsRCxDQUFDLENBQUM7Z0JBRUgsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDdEIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDbkQsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUVuQyx3QkFBd0I7Z0JBQ3hCLHdDQUF3QztnQkFDeEMsc0NBQXNDO2dCQUN0Qyx5Q0FBeUM7Z0JBQ3pDLDREQUE0RDtnQkFDNUQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2xHLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRXpDLE1BQU0sVUFBVSxHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQzVDLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFFeEMsTUFBTSxTQUFTLEdBQUcsZUFBZSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUM5QyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFFbkMsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDekMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUMxQyxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ25ELENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLDJEQUEyRCxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUN6RSxVQUFVLEdBQUcsa0VBQWtFLENBQUM7Z0JBQ2hGLE1BQU0scUJBQXFCLEdBQUcsa0VBQWtFLENBQUM7Z0JBQ2pHLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQztxQkFDUixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsT0FBTyxVQUFVLEVBQUUsQ0FBQztxQkFDckQsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixHQUFHLEVBQUUsSUFBSTtvQkFDVCxPQUFPLEVBQUU7d0JBQ1A7NEJBQ0UsSUFBSSxFQUFFLENBQUM7NEJBQ1AsS0FBSyxFQUFFLEtBQUs7NEJBQ1osTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLEVBQUU7eUJBQ1Y7d0JBQ0Q7NEJBQ0UsSUFBSSxFQUFFLENBQUM7NEJBQ1AsS0FBSyxFQUFFLElBQUk7NEJBQ1gsTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLENBQUM7eUJBQ1Q7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFLENBQUM7aUJBQ2pCLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQztxQkFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQztxQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLFFBQVEsRUFBRTt3QkFDUjs0QkFDRSxPQUFPLEVBQUUsVUFBVTs0QkFDbkIsV0FBVyxFQUFFLENBQUM7NEJBQ2QsS0FBSyxFQUFFLEtBQUs7NEJBQ1osWUFBWSxFQUNWLG9OQUFvTjs0QkFDdE4sU0FBUyxFQUFFLE1BQU07eUJBQ2xCO3FCQUNGO2lCQUNGLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQztxQkFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQztxQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLFFBQVEsRUFBRTt3QkFDUjs0QkFDRSxPQUFPLEVBQUUscUJBQXFCOzRCQUM5QixXQUFXLEVBQUUsQ0FBQzs0QkFDZCxLQUFLLEVBQUUsUUFBUTs0QkFDZixZQUFZLEVBQUUsc0VBQXNFOzRCQUNwRixTQUFTLEVBQUUsU0FBUzs0QkFDcEIsYUFBYSxFQUNYLG9OQUFvTjt5QkFDdk47cUJBQ0Y7aUJBQ0YsQ0FBQyxDQUFDO2dCQUVMLElBQUEsY0FBSSxFQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLFVBQVUsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztnQkFFaEYsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFO29CQUNoQyxPQUFPLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDO2dCQUNoQyxDQUFDLENBQUM7cUJBQ0QsS0FBSyxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsRUFBRSxJQUFJO29CQUMzQixPQUFPO3dCQUNMLFdBQVcsRUFBRyxJQUFZLENBQUMsRUFBRTtxQkFDOUIsQ0FBQztnQkFDSixDQUFDLENBQUMsQ0FBQztnQkFFTCxNQUFNLE9BQU8sR0FBRyxNQUFNLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQztvQkFDakQsYUFBYSxFQUFFLFVBQVU7b0JBQ3pCLE9BQU87b0JBQ1AsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLHFCQUFxQjtpQkFDbEQsQ0FBQyxDQUFDO2dCQUVILE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ25ELE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFbkMsd0JBQXdCO2dCQUN4Qix5Q0FBeUM7Z0JBQ3pDLHNDQUFzQztnQkFDdEMsK0NBQStDO2dCQUMvQyx5Q0FBeUM7Z0JBQ3pDLDREQUE0RDtnQkFDNUQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2xHLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRXpDLElBQUksZUFBZSxHQUFRLFNBQVMsQ0FBQztnQkFDckMsSUFBSSxlQUFlLEdBQVEsU0FBUyxDQUFDO2dCQUVyQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtvQkFDcEMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUNuQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBRXBDLE1BQU0sU0FBUyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFFekMsSUFBSSxTQUFTLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQzdCLGVBQWUsR0FBRyxLQUFLLENBQUM7b0JBQzFCLENBQUM7eUJBQU0sQ0FBQzt3QkFDTixlQUFlLEdBQUcsS0FBSyxDQUFDO29CQUMxQixDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUVILE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7Z0JBQzlCLE1BQU0sbUJBQW1CLEdBQUcsZUFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUM3RCxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUM3QyxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRXRDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7Z0JBQzlCLE1BQU0sbUJBQW1CLEdBQUcsZUFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUM3RCxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQ3hELGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFFdEMsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDekMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUMxQyxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ25ELENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLHlEQUF5RCxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUN2RSxVQUFVLEdBQUcsa0VBQWtFLENBQUM7Z0JBQ2hGLE1BQU0scUJBQXFCLEdBQUcsa0VBQWtFLENBQUM7Z0JBQ2pHLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQztxQkFDUixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsT0FBTyxVQUFVLEVBQUUsQ0FBQztxQkFDckQsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixHQUFHLEVBQUUsSUFBSTtvQkFDVCxPQUFPLEVBQUU7d0JBQ1A7NEJBQ0UsSUFBSSxFQUFFLENBQUM7NEJBQ1AsS0FBSyxFQUFFLEtBQUs7NEJBQ1osTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLEVBQUU7eUJBQ1Y7d0JBQ0Q7NEJBQ0UsSUFBSSxFQUFFLENBQUM7NEJBQ1AsS0FBSyxFQUFFLElBQUk7NEJBQ1gsTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLENBQUM7eUJBQ1Q7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFLENBQUM7aUJBQ2pCLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQztxQkFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQztxQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLFFBQVEsRUFBRTt3QkFDUjs0QkFDRSxPQUFPLEVBQUUsVUFBVTs0QkFDbkIsV0FBVyxFQUFFLENBQUM7NEJBQ2QsS0FBSyxFQUFFLEtBQUs7NEJBQ1osWUFBWSxFQUNWLG9OQUFvTjs0QkFDdE4sU0FBUyxFQUFFLE1BQU07eUJBQ2xCO3FCQUNGO2lCQUNGLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQztxQkFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQztxQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLFFBQVEsRUFBRTt3QkFDUjs0QkFDRSxPQUFPLEVBQUUscUJBQXFCOzRCQUM5QixXQUFXLEVBQUUsQ0FBQzs0QkFDZCxLQUFLLEVBQUUsUUFBUTs0QkFDZixZQUFZLEVBQ1Ysb05BQW9OOzRCQUN0TixTQUFTLEVBQUUsTUFBTTt5QkFDbEI7cUJBQ0Y7aUJBQ0YsQ0FBQyxDQUFDO2dCQUVMLElBQUEsY0FBSSxFQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLFVBQVUsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztnQkFFaEYsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFO29CQUNoQyxPQUFPLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDO2dCQUNoQyxDQUFDLENBQUM7cUJBQ0QsS0FBSyxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsRUFBRSxJQUFJO29CQUMzQixPQUFPO3dCQUNMLFdBQVcsRUFBRyxJQUFZLENBQUMsRUFBRTtxQkFDOUIsQ0FBQztnQkFDSixDQUFDLENBQUMsQ0FBQztnQkFFTCxNQUFNLE9BQU8sR0FBRyxNQUFNLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQztvQkFDakQsYUFBYSxFQUFFLFVBQVU7b0JBQ3pCLE9BQU87b0JBQ1AsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLHFCQUFxQjtpQkFDbEQsQ0FBQyxDQUFDO2dCQUVILE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3RCLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ25ELE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFbkMsd0JBQXdCO2dCQUN4Qix5Q0FBeUM7Z0JBQ3pDLHNDQUFzQztnQkFDdEMsK0NBQStDO2dCQUMvQyx5Q0FBeUM7Z0JBQ3pDLDREQUE0RDtnQkFDNUQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2xHLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRXpDLElBQUksZUFBZSxHQUFRLFNBQVMsQ0FBQztnQkFDckMsSUFBSSxlQUFlLEdBQVEsU0FBUyxDQUFDO2dCQUVyQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtvQkFDcEMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUNuQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBRXBDLE1BQU0sU0FBUyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFFekMsSUFBSSxTQUFTLEtBQUssVUFBVSxFQUFFLENBQUM7d0JBQzdCLGVBQWUsR0FBRyxLQUFLLENBQUM7b0JBQzFCLENBQUM7eUJBQU0sQ0FBQzt3QkFDTixlQUFlLEdBQUcsS0FBSyxDQUFDO29CQUMxQixDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUVILE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7Z0JBQzlCLE1BQU0sbUJBQW1CLEdBQUcsZUFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUM3RCxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUM3QyxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRXRDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7Z0JBQzlCLE1BQU0sbUJBQW1CLEdBQUcsZUFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUM3RCxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7Z0JBQ3hELGVBQWUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFFdEMsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDekMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUMxQyxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ25ELENBQUMsQ0FBQyxDQUFDO1lBRUgsRUFBRSxDQUFDLHVFQUF1RSxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNyRixVQUFVLEdBQUcsa0VBQWtFLENBQUM7Z0JBQ2hGLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQztxQkFDUixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsT0FBTyxVQUFVLEVBQUUsQ0FBQztxQkFDckQsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixHQUFHLEVBQUUsSUFBSTtvQkFDVCxPQUFPLEVBQUU7d0JBQ1A7NEJBQ0UsSUFBSSxFQUFFLENBQUM7NEJBQ1AsS0FBSyxFQUFFLEtBQUs7NEJBQ1osTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLEVBQUU7eUJBQ1Y7d0JBQ0Q7NEJBQ0UsSUFBSSxFQUFFLENBQUM7NEJBQ1AsS0FBSyxFQUFFLElBQUk7NEJBQ1gsTUFBTSxFQUFFLElBQUk7NEJBQ1osS0FBSyxFQUFFLENBQUM7eUJBQ1Q7cUJBQ0Y7b0JBQ0QsYUFBYSxFQUFFLENBQUM7aUJBQ2pCLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQztxQkFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQztxQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLFFBQVEsRUFBRTt3QkFDUjs0QkFDRSxPQUFPLEVBQUUsVUFBVTs0QkFDbkIsV0FBVyxFQUFFLENBQUM7NEJBQ2QsS0FBSyxFQUFFLEtBQUs7NEJBQ1osWUFBWSxFQUNWLG9OQUFvTjs0QkFDdE4sU0FBUyxFQUFFLE1BQU07eUJBQ2xCO3FCQUNGO2lCQUNGLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsR0FBRyxDQUFDLGtCQUFrQixNQUFNLENBQUMsRUFBRSxFQUFFLFdBQVcsQ0FBQztxQkFDN0MsS0FBSyxDQUFDLElBQUksQ0FBQztxQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLFFBQVEsRUFBRTt3QkFDUjs0QkFDRSxPQUFPLEVBQUUsa0VBQWtFOzRCQUMzRSxXQUFXLEVBQUUsQ0FBQzs0QkFDZCxLQUFLLEVBQUUsTUFBTTs0QkFDYixZQUFZLEVBQ1Ysb05BQW9OOzRCQUN0TixTQUFTLEVBQUUsTUFBTTt5QkFDbEI7d0JBQ0Q7NEJBQ0UsT0FBTyxFQUFFLGtFQUFrRTs0QkFDM0UsV0FBVyxFQUFFLENBQUM7NEJBQ2QsS0FBSyxFQUFFLFFBQVE7NEJBQ2YsWUFBWSxFQUFFLHNFQUFzRTs0QkFDcEYsU0FBUyxFQUFFLFNBQVM7NEJBQ3BCLGFBQWEsRUFDWCxvTkFBb047eUJBQ3ZOO3FCQUNGO2lCQUNGLENBQUMsQ0FBQztnQkFFTCxJQUFBLGNBQUksRUFBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxVQUFVLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7Z0JBRWhGLElBQUEsY0FBSSxFQUFDLEtBQUssQ0FBQztxQkFDUixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRTtvQkFDaEMsT0FBTyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztnQkFDaEMsQ0FBQyxDQUFDO3FCQUNELEtBQUssQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLEVBQUUsSUFBSTtvQkFDM0IsT0FBTzt3QkFDTCxXQUFXLEVBQUcsSUFBWSxDQUFDLEVBQUU7cUJBQzlCLENBQUM7Z0JBQ0osQ0FBQyxDQUFDLENBQUM7Z0JBRUwsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMscUJBQXFCLENBQUM7b0JBQ2pELGFBQWEsRUFBRSxVQUFVO29CQUN6QixnQkFBZ0IsRUFBRSxTQUFTLENBQUMscUJBQXFCO29CQUNqRCxPQUFPO2lCQUNSLENBQUMsQ0FBQztnQkFFSCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUN0QixPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO2dCQUNuRCxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRW5DLHdCQUF3QjtnQkFDeEIsMkNBQTJDO2dCQUMzQyxzQ0FBc0M7Z0JBQ3RDLHlDQUF5QztnQkFDekMsNERBQTREO2dCQUM1RCxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLHdCQUF3QixDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDbEcsWUFBWSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDeEMsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFFekMsSUFBSSxlQUFlLEdBQVEsU0FBUyxDQUFDO2dCQUNyQyxNQUFNLGdCQUFnQixHQUFVLEVBQUUsQ0FBQztnQkFFbkMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7b0JBQ3BDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDbkMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO29CQUVwQyxNQUFNLFNBQVMsR0FBRyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBRXpDLElBQUksU0FBUyxLQUFLLFVBQVUsRUFBRSxDQUFDO3dCQUM3QixlQUFlLEdBQUcsS0FBSyxDQUFDO29CQUMxQixDQUFDO3lCQUFNLENBQUM7d0JBQ04sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUMvQixDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO2dCQUVILE1BQU0sQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLENBQUM7Z0JBQzlCLE1BQU0sbUJBQW1CLEdBQUcsZUFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUM3RCxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUM3QyxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBRXRDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUV4QyxNQUFNLFdBQVcsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN6QyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDbkQsQ0FBQyxDQUFDLENBQUM7WUFFSCxFQUFFLENBQUMsbUVBQW1FLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ2pGLFVBQVUsR0FBRyxrRUFBa0UsQ0FBQztnQkFDaEYsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLFVBQVUsRUFBRSxDQUFDO3FCQUNyRCxLQUFLLENBQUMsR0FBRyxFQUFFO29CQUNWLEdBQUcsRUFBRSxHQUFHO29CQUNSLE9BQU8sRUFBRTt3QkFDUDs0QkFDRSxJQUFJLEVBQUUsQ0FBQzs0QkFDUCxLQUFLLEVBQUUsUUFBUTs0QkFDZixNQUFNLEVBQUUsSUFBSTs0QkFDWixLQUFLLEVBQUUsQ0FBQzt5QkFDVDt3QkFDRDs0QkFDRSxJQUFJLEVBQUUsQ0FBQzs0QkFDUCxLQUFLLEVBQUUsS0FBSzs0QkFDWixNQUFNLEVBQUUsSUFBSTs0QkFDWixLQUFLLEVBQUUsRUFBRTt5QkFDVjtxQkFDRjtpQkFDRixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO3FCQUNSLEdBQUcsQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxXQUFXLENBQUM7cUJBQzdDLEtBQUssQ0FBQyxJQUFJLENBQUM7cUJBQ1gsS0FBSyxDQUFDLEdBQUcsRUFBRTtvQkFDVixRQUFRLEVBQUU7d0JBQ1I7NEJBQ0UsT0FBTyxFQUFFLFVBQVU7NEJBQ25CLFdBQVcsRUFBRSxDQUFDOzRCQUNkLEtBQUssRUFBRSxRQUFROzRCQUNmLFlBQVksRUFBRSxzRUFBc0U7NEJBQ3BGLFNBQVMsRUFBRSxTQUFTOzRCQUNwQixhQUFhLEVBQ1gsb05BQW9OO3lCQUN2TjtxQkFDRjtpQkFDRixDQUFDLENBQUM7Z0JBRUwsSUFBQSxjQUFJLEVBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sVUFBVSxNQUFNLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO2dCQUVoRixJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7cUJBQ1IsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUU7b0JBQ2hDLGdEQUFnRDtvQkFDaEQsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7Z0JBQy9CLENBQUMsQ0FBQztxQkFDRCxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBRWQsaURBQWlEO2dCQUNqRCxNQUFNLGVBQWUsR0FBSSxLQUFhLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQztnQkFDN0QsS0FBYSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQztvQkFDN0MsOENBQThDO29CQUM5QyxpREFBaUQ7b0JBQ2pELDJDQUEyQztvQkFDM0MsVUFBVSxFQUFFLEtBQUs7aUJBQ2xCLENBQUMsQ0FBQztnQkFFSCxNQUFNLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQztvQkFDakMsYUFBYSxFQUFFLFVBQVU7b0JBQ3pCLE9BQU87b0JBQ1AsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLHFCQUFxQjtpQkFDbEQsQ0FBQyxDQUFDO2dCQUNILGNBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUVyQyxLQUFhLENBQUMsU0FBUyxDQUFDLFlBQVksR0FBRyxlQUFlLENBQUM7WUFDMUQsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLGFBQWEsRUFBRTtRQUN0QixJQUFJLEtBQWEsQ0FBQztRQUNsQixJQUFJLE1BQVcsQ0FBQztRQUVoQixNQUFNLENBQUM7WUFDTCxjQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN0QyxNQUFNLFNBQVMsR0FBRyxJQUFJLG1CQUFRLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDcEYsS0FBSyxHQUFHLGlCQUFNLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUNwRCxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsU0FBUyxFQUFFO2dCQUM3QixFQUFFLEVBQUUscUNBQXFDO2dCQUN6QyxPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLFFBQVEsQ0FBQyxFQUFFO2FBQy9ELENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsU0FBUyxDQUFDO1lBQ1IsY0FBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2xCLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDRFQUE0RSxFQUFFLEtBQUs7WUFDcEYsTUFBTSxLQUFLLEdBQUcsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO2lCQUN0QixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsY0FBYyxDQUFDO2lCQUNoRCxLQUFLLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztpQkFDN0MsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBRTdCLE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDNUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzlCLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDhEQUE4RCxFQUFFLEtBQUs7WUFDdEUsTUFBTSxLQUFLLEdBQUcsb0NBQW9DLENBQUM7WUFDbkQsTUFBTSxLQUFLLEdBQUcsb0NBQW9DLENBQUM7WUFFbkQsTUFBTSxLQUFLLEdBQUcsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO2lCQUN0QixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsY0FBYyxDQUFDO2lCQUNoRCxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDZixNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBQzlDLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDNUYsT0FBTyxLQUFLLENBQUMsTUFBTSxLQUFLLFFBQVEsSUFBSSxjQUFjLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLGNBQWMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkcsQ0FBQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUUxQixNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEYsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNCLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2xDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLG1EQUFtRCxFQUFFLEtBQUs7WUFDM0QsTUFBTSxLQUFLLEdBQUcsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO2lCQUN0QixHQUFHLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxFQUFFLEVBQUUsY0FBYyxDQUFDO2lCQUNoRCxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxjQUFjLElBQUksS0FBSyxDQUFDLENBQUM7aUJBQ3pFLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUU1QixNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzVFLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM3QixLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsQyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxvQ0FBb0MsRUFBRTtZQUN2QyxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUN4RixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxzQ0FBc0MsRUFBRTtZQUN6QyxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ3ZHLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vXG4vLyBUZXN0cyBmb3IgV2FsbGV0XG4vL1xuLy8gQ29weXJpZ2h0IDIwMTQsIEJpdEdvLCBJbmMuICBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy9cblxuaW1wb3J0IHsgZ2V0Rml4dHVyZSB9IGZyb20gJy4vZml4dHVyZXMnO1xuXG5jb25zdCBXYWxsZXQgPSByZXF1aXJlKCcuLi8uLi8uLi9zcmMvdjEvd2FsbGV0Jyk7XG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJy4uLy4uLy4uL3NyYy9iaXRnb0FQSSc7XG5pbXBvcnQgKiBhcyBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgeyBjb21tb24gfSBmcm9tICdAYml0Z28tYmV0YS9zZGstY29yZSc7XG5pbXBvcnQgKiBhcyB1dHhvbGliIGZyb20gJ0BiaXRnby1iZXRhL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIHNob3VsZCBmcm9tICdzaG91bGQnO1xuaW1wb3J0IG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5cbmltcG9ydCB7IGdldEZpeHR1cmVzIH0gZnJvbSAnLi9maXh0dXJlcy9hY2NlbGVyYXRlLXR4Jztcblxubm9jay5kaXNhYmxlTmV0Q29ubmVjdCgpO1xuXG5jb25zdCBUZXN0Qml0R28gPSB7XG4gIFRFU1RfV0FMTEVUMV9QQVNTQ09ERTogJ2lWV2VBVGpxTFMxakpTaHJQcEVUdGkwYicsXG59O1xuZGVzY3JpYmUoJ1dhbGxldCBQcm90b3R5cGUgTWV0aG9kcycsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgZml4dHVyZXMgPSBnZXRGaXh0dXJlcygpO1xuXG4gIGxldCBiaXRnbyA9IG5ldyBCaXRHb0FQSSh7IGVudjogJ3Rlc3QnLCBjbGllbnRDb25zdGFudHM6IHsgY29uc3RhbnRzOiB7fSB9IH0pO1xuICAvLyBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcblxuICBjb25zdCB1c2VyS2V5cGFpciA9IHtcbiAgICB4cHJ2OiAneHBydjlzMjFaclFIMTQzSzJmSjkxUzRCUnN1cGNZckU2bW1ZOTZmY1g1SGtob1Rycndtd2pkMTZDbjg3Y1dpbkpqQnlyZnBvamp4N2V6c0pMeDdUQUtMVDhtOGhNNUtheDlZY294bkJlSlozdDJrJyxcbiAgICB4cHViOiAneHB1YjY2MU15TXdBcVJiY0Y5TmM3VGJCbzFyWkFhZ2lXRVZQV0tiREtUaE5HOHpxams3NkhBS0xrYVNiVG42ZEsyZFFQZnVEN3hqaWN4Q1pWV3ZqNjdmUDVuUTlXN1FVUm1vTVZBWDhtNmpac0dwJyxcbiAgICByYXdQdWI6ICcwMmMxMDNhYzc0NDgxODc0YjVlZjBmMzg1ZDEyNzI1ZTRmMTRhZWRjOWUwMGJjODE0Y2U5NmY0N2Y2MmNlN2FkZjInLFxuICAgIHJhd1BydjogJzkzNmM1YWYzZjhhZjgxZjc1Y2RhZDFiMDhmMjllN2Q5YzAxZTU5OGUyZGIyZDdiZTE4YjllNWE4NjQ2ZTg3YzYnLFxuICAgIHBhdGg6ICdtJyxcbiAgICB3YWxsZXRTdWJQYXRoOiAnLzAvMCcsXG4gIH07XG4gIGNvbnN0IGJhY2t1cEtleXBhaXIgPSB7XG4gICAgeHBydjogJ3hwcnY5czIxWnJRSDE0M0s0N3NFa0xreWtnWW1xMXhGNVpXclBZaFVaY21CcFBGTVFvanZHVW1FY3I1akZYWUdmcjhDcEZkcFR2aFE3TDlOTjJyTHRzQkZqU2l4M0JBandKY0JqNlUzRDVoeFRQYycsXG4gICAgeHB1YjogJ3hwdWI2NjFNeU13QXFSYmNHYndock5IejdwVldQM25qVjJFaGttZDVOMUFvTmluTEhjNTRwMjVWQWVRRDZxMm9UUzN1dURNRG5mblhudGhiUzl1ZkM4SlZZcE5uV1U1Um4zcFlhTnVMQ055d2t3MScsXG4gICAgcmF3UHViOiAnMDNiYmNiNzM5OTc5NzcwNjhkOWUzNjY2NmJiZDVjZDM3NTc5YWNhZThlMmJkNWNlOWQwYTZlNWMxNTBhNDIzYmMzJyxcbiAgICByYXdQcnY6ICc3N2ExNWYxNDc5NmY0MDAxZDEwOTJhZTg0Zjc2NmJkODY5ZTliZWU2YmZmYWU2NTQ3ZGVmNTA0NWI5NmZhOTQzJyxcbiAgICBwYXRoOiAnbScsXG4gICAgd2FsbGV0U3ViUGF0aDogJy8wLzAnLFxuICB9O1xuICBjb25zdCBiaXRnb0tleSA9IHtcbiAgICB4cHViOiAneHB1YjY2MU15TXdBcVJiY0dRY1ZGaXdjcnRjN2Mzdm9wc1g5NmpzSlVZUGNGTVJFY1JUcUFxc3FidjJaUnlDSkFQTG01Tk1IQ3k4NUUzWndwVDRFQVV3OVdHVTd2TWhHNno4M2hEZUtYQlduNkxmJyxcbiAgICBwYXRoOiAnbScsXG4gICAgd2FsbGV0U3ViUGF0aDogJy8wLzAnLFxuICB9O1xuXG4gIGNvbnN0IGZha2VXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCB7XG4gICAgaWQ6ICcyTkNvU2ZISDZMczRDZFRTNVFhaGdDOWs3eDlSZlhlU3dZNCcsXG4gICAgcHJpdmF0ZTogeyBrZXljaGFpbnM6IFt1c2VyS2V5cGFpciwgYmFja3VwS2V5cGFpciwgYml0Z29LZXldIH0sXG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdHZW5lcmF0ZSBBZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgIGJlZm9yZSgoKSA9PiBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpKTtcblxuICAgIGl0KCdnZW5lcmF0ZSBmaXJzdCBhZGRyZXNzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaWRBZGRyZXNzID0gZmFrZVdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzAvMCcsIHNlZ3dpdDogZmFsc2UgfSk7XG4gICAgICBpZEFkZHJlc3MuYWRkcmVzcy5zaG91bGQuZXF1YWwoZmFrZVdhbGxldC5pZCgpKTtcbiAgICAgIGlkQWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBpZEFkZHJlc3MuaW5kZXguc2hvdWxkLmVxdWFsKDApO1xuICAgICAgaWRBZGRyZXNzLmNoYWluUGF0aC5zaG91bGQuZXF1YWwoJy8wLzAnKTtcbiAgICAgIGlkQWRkcmVzcy5wYXRoLnNob3VsZC5lcXVhbCgnLzAvMCcpO1xuICAgICAgaWRBZGRyZXNzLm91dHB1dFNjcmlwdC5zaG91bGQuZXF1YWwoJ2E5MTRkNjgyNDc2ZTliZDU0NDU0YTg4NWY5ZGZmMWU2MDRlOTljZWY0M2RjODcnKTtcbiAgICAgIGlkQWRkcmVzcy5yZWRlZW1TY3JpcHQuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnNTIyMTAyY2QzYzhlNjAwNmE0NjI3NzA1MDIxZDFkMDE2ZDA5N2MyOTQ0ZDk4MTAwYTQ3YmYyZGE2N2E1ZmUxNWFlZWIzNDIxMDJlZTFmYTllODEyZTc3OTM1NmFhM2MzMWViZjMxN2QwY2ZmZWJhYjkyODY0Y2ZlMzhiYWIyMjNlMDgyMGY5OGJjMjEwMjZiYTA1NzUyYmFhNmVhZmQ1YzU2NTlkYTYyYjdmMGFjNTFmZDI4ODZiNjVjMjQxZDBhZmVmMWM0ZmRmYTFjYmM1M2FlJ1xuICAgICAgKTtcbiAgICAgIGlkQWRkcmVzcy53YWxsZXQuc2hvdWxkLmVxdWFsKGZha2VXYWxsZXQuaWQoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGUgc2Vjb25kIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8wLzEnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgcDJzaEFkZHJlc3MuYWRkcmVzcy5zaG91bGQuZXF1YWwoJzJONXk1UkxWcWRaaTdxcDVQbXpNZFBSNll2UXpVcUJRRldLJyk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBwMnNoQWRkcmVzcy5pbmRleC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpblBhdGguc2hvdWxkLmVxdWFsKCcvMC8xJyk7XG4gICAgICBwMnNoQWRkcmVzcy5wYXRoLnNob3VsZC5lcXVhbCgnLzAvMScpO1xuICAgICAgcDJzaEFkZHJlc3Mub3V0cHV0U2NyaXB0LnNob3VsZC5lcXVhbCgnYTkxNDhiOGJkM2RhNjhlZjBmMjQ2NTUyMzE0NmJkMmRlMzNjODZiOWM4NzE4NycpO1xuICAgICAgcDJzaEFkZHJlc3MucmVkZWVtU2NyaXB0LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzUyMjEwMjcwOWVkYjZhMjE5OGQzNjRjNDg1YTc2Yjk4MWQxMjA2NWVhYmRlOGFhMmQ4NWJkN2U3YTAzNWY3ZWNiMzU3OWIyMTAyYTcyNGVmZWQ0OTljMDVmZGI0ZGExZTEzOTcwMDk1MWZhZTAwYzAwNmIzMjgzODg4YmRmZDFiNDY5NzkyOTIyNDIxMDJiMzJhYmU0NGQ2MTk4NmZmNTdiODM1ZTNiZDE2MjkzZDkzZjMwM2QwZDhmYjA0NTRlMmM5Y2NlZGE1YzQ5Mjk4NTNhZSdcbiAgICAgICk7XG4gICAgICBwMnNoQWRkcmVzcy53YWxsZXQuc2hvdWxkLmVxdWFsKGZha2VXYWxsZXQuaWQoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGUgY2hhbmdlIGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8xLzAnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgcDJzaEFkZHJlc3MuYWRkcmVzcy5zaG91bGQuZXF1YWwoJzJORmo5SnJwWmM1TXlZbkNvdXlSRXR6Tlk0ZW95S1dEZmdQJyk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMSk7XG4gICAgICBwMnNoQWRkcmVzcy5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBwMnNoQWRkcmVzcy5jaGFpblBhdGguc2hvdWxkLmVxdWFsKCcvMS8wJyk7XG4gICAgICBwMnNoQWRkcmVzcy5wYXRoLnNob3VsZC5lcXVhbCgnLzEvMCcpO1xuICAgICAgcDJzaEFkZHJlc3Mub3V0cHV0U2NyaXB0LnNob3VsZC5lcXVhbCgnYTkxNGY2OWE4MWZhZDc1ZWE2NWFkMTY2ZGE3NjUxNTI5MTY3OWE0ZjFhZDg4NycpO1xuICAgICAgcDJzaEFkZHJlc3MucmVkZWVtU2NyaXB0LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzUyMjEwMjBiNGM0Zjg5MWE1NTIwZjVhMGI2ODE4ZDhkNTM5MTk1NTJhMGQ0ZDgwNmI1ZmEwNWM5NzcwODA3OWQ4MzczN2UyMTAyYzVjYzQ5YmYwMzMxZWIwYjA4OTBhN2U3ZDg3ZjdlOWUwZGVhNTE1NDM4MjgwZGM3NjgzNGMyMWQxOThlZmUwODIxMDM3MGU1MmNmNzQxZWJmNDUxMzc0OWQwMjg4MzlkNjk2ODkxZWI3ODliYTdhNTg1OTJjZmJjODU3Y2RjMGE5ZGU3NTNhZSdcbiAgICAgICk7XG4gICAgICBwMnNoQWRkcmVzcy53YWxsZXQuc2hvdWxkLmVxdWFsKGZha2VXYWxsZXQuaWQoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnZ2VuZXJhdGUgc2Vnd2l0IGFkZHJlc3MnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzZWd3aXRBZGRyZXNzID0gZmFrZVdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzEwLzAnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBzZWd3aXRBZGRyZXNzLmFkZHJlc3Muc2hvdWxkLmVxdWFsKCcyTjVFVmVnUlBXbm1lZDJQcHFEZ2daUHc3RGNORGd1Ull2OCcpO1xuICAgICAgc2Vnd2l0QWRkcmVzcy5jaGFpbi5zaG91bGQuZXF1YWwoMTApO1xuICAgICAgc2Vnd2l0QWRkcmVzcy5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG4gICAgICBzZWd3aXRBZGRyZXNzLmNoYWluUGF0aC5zaG91bGQuZXF1YWwoJy8xMC8wJyk7XG4gICAgICBzZWd3aXRBZGRyZXNzLnBhdGguc2hvdWxkLmVxdWFsKCcvMTAvMCcpO1xuICAgICAgc2Vnd2l0QWRkcmVzcy5vdXRwdXRTY3JpcHQuc2hvdWxkLmVxdWFsKCdhOTE0ODM3ZTJhZGNiNmY2Mzg2ZmVhM2M1ZDQwMzE2YjI4MmNjZjM5MTIxZDg3Jyk7XG4gICAgICBzZWd3aXRBZGRyZXNzLnJlZGVlbVNjcmlwdC5zaG91bGQuZXF1YWwoJzAwMjBhNjJhZmVlMWQyMTFjNWFkYjk3MzlmODFlZDRlMzYzMzBlNmNkYTY1MWM3YmRkMzE0ZTMyY2NjNDY1ZWMyMjAzJyk7XG4gICAgICBzZWd3aXRBZGRyZXNzLndpdG5lc3NTY3JpcHQuc2hvdWxkLmVxdWFsKFxuICAgICAgICAnNTIyMTAyN2IzMDUwNTc3N2E0ZWQ4OTQ3YjA2OWZjYjAxMTZlMjg3OTk1ZDk3Mjc4ZDg0ZGE0ZGI2YzYxMzI3MDY0OWQzZDIxMDM0YzMwZTUxZjFlNjE0Y2FkNjY3ODE1YzkxZDA0MTQwNGMxODIyNWQwYjJmNzllMmMwYmNiNjNmZDI2MDQzMTZiMjEwM2I2NWRkZmMwNjE1OWI2OTE2OTMzOTA3NjFlNzVhMGI4Y2M3YTY1YjZmZjMwNWQwOTRmM2FkOTcyZjE3OTUzZmU1M2FlJ1xuICAgICAgKTtcbiAgICAgIHNlZ3dpdEFkZHJlc3Mud2FsbGV0LnNob3VsZC5lcXVhbChmYWtlV2FsbGV0LmlkKCkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnQ3JlYXRlIFRyYW5zYWN0aW9uJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBiZ1VybCwgYmdVcmxUZXN0O1xuICAgIGxldCBmYWtlUHJvZFdhbGxldDtcblxuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgICAgY29uc3QgcHJvZEJpdGdvID0gbmV3IEJpdEdvQVBJKHsgZW52OiAncHJvZCcsIGNsaWVudENvbnN0YW50czogeyBjb25zdGFudHM6IHt9IH0gfSk7XG4gICAgICAvLyBwcm9kQml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgICBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbcHJvZEJpdGdvLmdldEVudigpXS51cmk7XG4gICAgICBmYWtlUHJvZFdhbGxldCA9IG5ldyBXYWxsZXQocHJvZEJpdGdvLCB7XG4gICAgICAgIGlkOiAnMk5Db1NmSEg2THM0Q2RUUzVRYWhnQzlrN3g5UmZYZVN3WTQnLFxuICAgICAgICBwcml2YXRlOiB7IGtleWNoYWluczogW3VzZXJLZXlwYWlyLCBiYWNrdXBLZXlwYWlyLCBiaXRnb0tleV0gfSxcbiAgICAgIH0pO1xuICAgICAgYmdVcmxUZXN0ID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2V4dHJhIHVuc3BlbnQgZmV0Y2ggcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYmlsbGluZ0FkZHJlc3MgPSAnM0o5OHQxV3BFWjczQ05tUXZpZWNybnlpV3JucVJoV05MeSc7XG4gICAgICBjb25zdCBjdXN0b21VbnNwZW50c0ZldGNoUGFyYW1zID0geyB0ZXN0OiAxMjMgfTtcbiAgICAgIGNvbnN0IHNlbmRBbW91bnQgPSAxZTU7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6IGJpbGxpbmdBZGRyZXNzIH0pO1xuXG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7ZmFrZVByb2RXYWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAucXVlcnkoXG4gICAgICAgICAgXy5tZXJnZShjdXN0b21VbnNwZW50c0ZldGNoUGFyYW1zLCB7XG4gICAgICAgICAgICBzZWd3aXQ6IHRydWUsXG4gICAgICAgICAgICB0YXJnZXQ6IHNlbmRBbW91bnQsXG4gICAgICAgICAgICBtaW5TaXplOiAwLFxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgICAgLnJlcGx5KDIwMCwgeyB1bnNwZW50czogW10gfSk7XG5cbiAgICAgIGF3YWl0IGZha2VQcm9kV2FsbGV0XG4gICAgICAgIC5jcmVhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdW5zcGVudHNGZXRjaFBhcmFtczogY3VzdG9tVW5zcGVudHNGZXRjaFBhcmFtcyxcbiAgICAgICAgICByZWNpcGllbnRzOiB7IFtiaWxsaW5nQWRkcmVzc106IHNlbmRBbW91bnQgfSxcbiAgICAgICAgICBmZWVSYXRlOiAxMDAwMCxcbiAgICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgICAgYWRkcmVzczogJycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJzAgdW5zcGVudHMgYXZhaWxhYmxlIGZvciB0cmFuc2FjdGlvbiBjcmVhdGlvbicpO1xuXG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ2ZvcndhcmRzIHJlY2lwaWVudCBhZGRyZXNzZXMgdG8gdGhlIGJpbGxpbmcvZmVlIGVuZHBvaW50IChkaWN0LWZvcm0gcmVjaXBpZW50cyknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBSZWdyZXNzaW9uIHRlc3Q6IHNlbmRDb2lucyBidWlsZHMgcmVjaXBpZW50cyBhcyBhIGRpY3QgKHsgW2FkZHJlc3NdOiBhbW91bnQgfSksIG5vdCBhblxuICAgICAgLy8gYXJyYXkuIGdldEJpdEdvRmVlIG11c3QgZm9yd2FyZCB0aGUgcmVjaXBpZW50IGFkZHJlc3NlcyB0byAvYmlsbGluZy9mZWUgc28gdGhlIHNlcnZlciBjYW5cbiAgICAgIC8vIHdhaXZlIHRoZSBQYXlHbyBmZWUgb24gdjEtPnYyIG1pZ3JhdGlvbiB0cmFuc2ZlcnMuIEEgcHJldmlvdXMgYnVnIHJlYWQgcGFyYW1zLnJlY2lwaWVudHNcbiAgICAgIC8vICh0aGUgZGljdCkgYW5kIGNhbGxlZCAubWFwIG9uIGl0LCB3aGljaCB0aHJldyBmb3IgdGhlIGRpY3QgZm9ybSBhbmQgbmV2ZXIgc2VudCByZWNpcGllbnRzLlxuICAgICAgY29uc3QgcmVjaXBpZW50QWRkcmVzcyA9ICczSjk4dDFXcEVaNzNDTm1RdmllY3JueWlXcm5xUmhXTkx5JztcbiAgICAgIGNvbnN0IHNlbmRBbW91bnQgPSAxZTU7XG5cbiAgICAgIGNvbnN0IHAyc2hBZGRyZXNzID0gZmFrZVByb2RXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8wLzEzJywgc2Vnd2l0OiBmYWxzZSB9KTtcbiAgICAgIGNvbnN0IHVuc3BlbnQ6IGFueSA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJOQ0VEbW1LTk5ucUt2bld3N3BFM1JMenVGZTVhSEhWeTFYJ10sXG4gICAgICAgIHZhbHVlX2ludDogNTA0NDIyLFxuICAgICAgICB0eGlkOiAnYjgxNmRlZDg5YzNkOGQ1MDIxYjAxMDk3ZjRhMzEyOWE2YTY4YTVjYjdjODg2ZTk3OTQ1ZjQyMDVjYmE1ZGU0NCcsXG4gICAgICAgIG46IDEsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCBkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogOSxcbiAgICAgICAgaWQ6IDYxMzMwMjI5LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIHAyc2hBZGRyZXNzKTtcbiAgICAgIHVuc3BlbnQudmFsdWUgPSB1bnNwZW50LnZhbHVlX2ludDtcbiAgICAgIHVuc3BlbnQudHhfaGFzaCA9IHVuc3BlbnQudHhpZDtcbiAgICAgIHVuc3BlbnQudHhfb3V0cHV0X24gPSB1bnNwZW50Lm47XG4gICAgICB1bnNwZW50LnNjcmlwdCA9IHVuc3BlbnQub3V0cHV0U2NyaXB0O1xuXG4gICAgICBsZXQgY2FwdHVyZWRRdWVyeTogYW55O1xuICAgICAgY29uc3QgYmlsbGluZ1Njb3BlID0gbm9jayhiZ1VybClcbiAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHtmYWtlUHJvZFdhbGxldC5pZCgpfS9iaWxsaW5nL2ZlZWApXG4gICAgICAgIC5xdWVyeSgoYWN0dWFsUXVlcnkpID0+IHtcbiAgICAgICAgICBjYXB0dXJlZFF1ZXJ5ID0gYWN0dWFsUXVlcnk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pXG4gICAgICAgIC8vIGZlZTogMCBleGVyY2lzZXMgdGhlIHYxLT52MiBQYXlHbyB3YWl2ZXIgcGF0aCAobm8gYml0Z29GZWUgb3V0cHV0IGFkZGVkKVxuICAgICAgICAucmVwbHkoMjAwLCB7IGZlZTogMCB9KTtcblxuICAgICAgLy8gTm8gYml0Z29GZWUgcGFzc2VkIGluLCBzbyBnZXRCaXRHb0ZlZSBtdXN0IGhpdCAvYmlsbGluZy9mZWUuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5jcmVhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgIGNoYW5nZUFkZHJlc3M6IHAyc2hBZGRyZXNzLmFkZHJlc3MsXG4gICAgICAgIHVuc3BlbnRzOiBbdW5zcGVudF0sXG4gICAgICAgIHJlY2lwaWVudHM6IHsgW3JlY2lwaWVudEFkZHJlc3NdOiBzZW5kQW1vdW50IH0sXG4gICAgICAgIG5vU3BsaXRDaGFuZ2U6IHRydWUsXG4gICAgICAgIGZvcmNlQ2hhbmdlQXRFbmQ6IHRydWUsXG4gICAgICAgIGZlZVJhdGU6IDEwMDAwLFxuICAgICAgICB1c2VQc2J0OiBmYWxzZSxcbiAgICAgIH0pKSBhcyBhbnk7XG5cbiAgICAgIC8vIFRoZSByZWNpcGllbnQgYWRkcmVzcyBtdXN0IGhhdmUgcmVhY2hlZCAvYmlsbGluZy9mZWUgKHRoaXMgaXMgd2hhdCB0aGUgZml4IHJlc3RvcmVzKS5cbiAgICAgIGJpbGxpbmdTY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgICAgc2hvdWxkLmV4aXN0KGNhcHR1cmVkUXVlcnkpO1xuICAgICAgY29uc3QgZm9yd2FyZGVkUmVjaXBpZW50cyA9IFtdLmNvbmNhdChjYXB0dXJlZFF1ZXJ5WydyZWNpcGllbnRzW10nXSB8fCBbXSk7XG4gICAgICBmb3J3YXJkZWRSZWNpcGllbnRzLnNob3VsZC5kZWVwRXF1YWwoW3JlY2lwaWVudEFkZHJlc3NdKTtcbiAgICAgIGNhcHR1cmVkUXVlcnkuYW1vdW50LnNob3VsZC5lcXVhbChTdHJpbmcoc2VuZEFtb3VudCkpO1xuXG4gICAgICAvLyBmZWU6IDAgPT4gbm8gUGF5R28gZmVlIG91dHB1dCBhZGRlZDsgdGhlIHR4IGJ1aWxkcyBzdWNjZXNzZnVsbHkuXG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXgpO1xuICAgICAgc2hvdWxkLm5vdC5leGlzdCh0cmFuc2FjdGlvbi5iaXRnb0ZlZSk7XG4gICAgICBjb25zdCB0eCA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4KHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgLy8gcmVjaXBpZW50IG91dHB1dCArIGNoYW5nZSBvdXRwdXQsIG5vIGV4dHJhIGZlZSBvdXRwdXRcbiAgICAgIHR4Lm91dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgyKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZWZhdWx0IHAyc2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VQcm9kV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMC8xMycsIHNlZ3dpdDogZmFsc2UgfSk7XG4gICAgICBjb25zdCB1bnNwZW50OiBhbnkgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTkNFRG1tS05ObnFLdm5XdzdwRTNSTHp1RmU1YUhIVnkxWCddLFxuICAgICAgICB2YWx1ZTogJzAuMDA1MDQ0MjInLFxuICAgICAgICB2YWx1ZV9pbnQ6IDUwNDQyMixcbiAgICAgICAgdHhpZDogJ2I4MTZkZWQ4OWMzZDhkNTAyMWIwMTA5N2Y0YTMxMjlhNmE2OGE1Y2I3Yzg4NmU5Nzk0NWY0MjA1Y2JhNWRlNDQnLFxuICAgICAgICBuOiAxLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMSBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTE4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDksXG4gICAgICAgIGlkOiA2MTMzMDIyOSxcbiAgICAgIH07XG4gICAgICBfLmV4dGVuZCh1bnNwZW50LCBwMnNoQWRkcmVzcyk7XG4gICAgICB1bnNwZW50LnZhbHVlID0gdW5zcGVudC52YWx1ZV9pbnQ7XG4gICAgICB1bnNwZW50LnR4X2hhc2ggPSB1bnNwZW50LnR4aWQ7XG4gICAgICB1bnNwZW50LnR4X291dHB1dF9uID0gdW5zcGVudC5uO1xuICAgICAgdW5zcGVudC5zY3JpcHQgPSB1bnNwZW50Lm91dHB1dFNjcmlwdDtcblxuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS9iaWxsaW5nL2FkZHJlc3MnKS5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJNc3dRamt2TjZvV1lkRTdMMmJySjVjQUFNalBtRzU5b2NvJyB9KTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICBjaGFuZ2VBZGRyZXNzOiBwMnNoQWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHAyc2ggdGVzdCc6IDEwMDAgfSxcbiAgICAgICAgdXNlUHNidDogZmFsc2UsXG4gICAgICB9KSkgYXMgYW55O1xuICAgICAgdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMTQ0ZGVhNWNiMDU0MjVmOTQ5NzZlODg3Y2NiYTU2ODZhOWExMmEzZjQ5NzEwYjAyMTUwOGQzZDljZDhkZTE2YjgwMTAwMDAwMDAwZmZmZmZmZmYwMmU4MDMwMDAwMDAwMDAwMDAxMTZhMGY0MjY5NzQ0NzZmMjA3MDMyNzM2ODIwNzQ2NTczNzQyMmExMDcwMDAwMDAwMDAwMTdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3MDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgZmlyc3Qgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IHVzZXJLZXlwYWlyO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMSA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICBzaWduYXR1cmUxLnR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDE0NGRlYTVjYjA1NDI1Zjk0OTc2ZTg4N2NjYmE1Njg2YTlhMTJhM2Y0OTcxMGIwMjE1MDhkM2Q5Y2Q4ZGUxNmI4MDEwMDAwMDBiNjAwNDczMDQ0MDIyMDIxZmE3M2Q1ZmU2MWFjODk0MmNkNzBmZjQ1MDdjNTc0Njc3Y2U3NDdkZTViYzQ2YzNkZDJlMzhlYzI0NDhmY2UwMjIwNDc5MDZkMmMwMTU0MzM3YWI5NjA0MWU4ZmI1OGMyNDNiOWJjZTVmODgxOGZhOTkxNjQzYzEyNjBhMTg1OWFkODAxMDAwMDRjNjk1MjIxMDMxY2QyMjdlNDBhZDYxYjRlMTM3MTA5Y2IyODQ1ZWI2ZjVhNTg0ZWQ1YzY3ZDlkMzEzNWNkYWE1MDQ1YTg0MmVhMjEwM2EyZTdiNTRjN2IyZGEwOTkyNTU1MzUzYjhlMjZjNmFjZmY0MjQ4ZjQzNTFmMDg3ODdiZjNlMmVmYzk0YjY1ODMyMTAyNWMyYTZjZGUzM2MyZDczY2NmMTJlZWNmNjRjNTRmMDhmNzIyYzJmMDczODI0NDk4OTUwNjk1ZTk4ODNiMTQxMjUzYWVmZmZmZmZmZjAyZTgwMzAwMDAwMDAwMDAwMDExNmEwZjQyNjk3NDQ3NmYyMDcwMzI3MzY4MjA3NDY1NzM3NDIyYTEwNzAwMDAwMDAwMDAxN2E5MTRkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExODcwMDAwMDAwMCdcbiAgICAgICk7XG5cbiAgICAgIC8vIGFkZCBzZWNvbmQgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCA9IHNpZ25hdHVyZTEudHg7XG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IGJhY2t1cEtleXBhaXI7XG4gICAgICB0cmFuc2FjdGlvbi5mdWxsTG9jYWxTaWduaW5nID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZTIgPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkgYXMgYW55O1xuICAgICAgLy8gVGhpcyB0cmFuc2FjdGlvbiBoYXMgYWN0dWFsbHkgd29ya2VkOiBodHRwczovL3Rlc3RuZXQuc21hcnRiaXQuY29tLmF1L3R4L2E4Y2NiOTI4MTY5MDMyZDZlMWYzN2JmODFkZmQ5YWI2ZDkwMzYyYTRmODRlNTc3Mzk3ZmE2OTBhYTcxMTU1MGNcbiAgICAgIC8vIE5vdGUgdGhhdCB0aGUgdHggaGV4IGJlbG93IG5vIGxvbmdlciBjb3JyZXNwb25kcyB0byB0aGUgYWJvdmUgdHJhbnNhY3Rpb24gYmVjYXVzZSBvdXIgZmVlIGVzdGltYXRpb24gaGFzXG4gICAgICAvLyBjaGFuZ2VkLCBjaGFuZ2luZyB0aGUgb3V0cHV0IGFtb3VudHMgYW5kIHRodXMgdGhlIHR4IGhleC5cbiAgICAgIHNpZ25hdHVyZTIudHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMTQ0ZGVhNWNiMDU0MjVmOTQ5NzZlODg3Y2NiYTU2ODZhOWExMmEzZjQ5NzEwYjAyMTUwOGQzZDljZDhkZTE2YjgwMTAwMDAwMGZkZmQwMDAwNDczMDQ0MDIyMDIxZmE3M2Q1ZmU2MWFjODk0MmNkNzBmZjQ1MDdjNTc0Njc3Y2U3NDdkZTViYzQ2YzNkZDJlMzhlYzI0NDhmY2UwMjIwNDc5MDZkMmMwMTU0MzM3YWI5NjA0MWU4ZmI1OGMyNDNiOWJjZTVmODgxOGZhOTkxNjQzYzEyNjBhMTg1OWFkODAxNDczMDQ0MDIyMDJhZTAxZjAxYjVhZTBjM2ZhN2Q2N2FjNzNkYjgxOTMyY2I1YWNhMTBkYjE2YTk5MDYzZmVmNDVlM2YxMzk4Y2QwMjIwNTUwMDFiYTdlMTYzY2IzNTA5MTBmYzczMjFlY2Q3ZWI2MzU5YjMyMWQ0YzA0ODg3NDg0ZDljNzI4NGI3OGM0NzAxMDA0YzY5NTIyMTAzMWNkMjI3ZTQwYWQ2MWI0ZTEzNzEwOWNiMjg0NWViNmY1YTU4NGVkNWM2N2Q5ZDMxMzVjZGFhNTA0NWE4NDJlYTIxMDNhMmU3YjU0YzdiMmRhMDk5MjU1NTM1M2I4ZTI2YzZhY2ZmNDI0OGY0MzUxZjA4Nzg3YmYzZTJlZmM5NGI2NTgzMjEwMjVjMmE2Y2RlMzNjMmQ3M2NjZjEyZWVjZjY0YzU0ZjA4ZjcyMmMyZjA3MzgyNDQ5ODk1MDY5NWU5ODgzYjE0MTI1M2FlZmZmZmZmZmYwMmU4MDMwMDAwMDAwMDAwMDAxMTZhMGY0MjY5NzQ0NzZmMjA3MDMyNzM2ODIwNzQ2NTczNzQyMmExMDcwMDAwMDAwMDAwMTdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3MDAwMDAwMDAnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Ayc2ggUFNCVCBwcm9kdWNlcyBzYW1lIHVuc2lnbmVkIHR4IGFzIGxlZ2FjeScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHAyc2hBZGRyZXNzID0gZmFrZVByb2RXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8wLzEzJywgc2Vnd2l0OiBmYWxzZSB9KTtcbiAgICAgIGNvbnN0IHVuc3BlbnQ6IGFueSA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJOQ0VEbW1LTk5ucUt2bld3N3BFM1JMenVGZTVhSEhWeTFYJ10sXG4gICAgICAgIHZhbHVlOiAnMC4wMDUwNDQyMicsXG4gICAgICAgIHZhbHVlX2ludDogNTA0NDIyLFxuICAgICAgICB0eGlkOiAnYjgxNmRlZDg5YzNkOGQ1MDIxYjAxMDk3ZjRhMzEyOWE2YTY4YTVjYjdjODg2ZTk3OTQ1ZjQyMDVjYmE1ZGU0NCcsXG4gICAgICAgIG46IDEsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCBkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogOSxcbiAgICAgICAgaWQ6IDYxMzMwMjI5LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIHAyc2hBZGRyZXNzKTtcbiAgICAgIHVuc3BlbnQudmFsdWUgPSB1bnNwZW50LnZhbHVlX2ludDtcbiAgICAgIHVuc3BlbnQudHhfaGFzaCA9IHVuc3BlbnQudHhpZDtcbiAgICAgIHVuc3BlbnQudHhfb3V0cHV0X24gPSB1bnNwZW50Lm47XG4gICAgICB1bnNwZW50LnNjcmlwdCA9IHVuc3BlbnQub3V0cHV0U2NyaXB0O1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogcDJzaEFkZHJlc3MuYWRkcmVzcyxcbiAgICAgICAgdW5zcGVudHM6IFt1bnNwZW50XSxcbiAgICAgICAgcmVjaXBpZW50czoge30sXG4gICAgICAgIG5vU3BsaXRDaGFuZ2U6IHRydWUsXG4gICAgICAgIGZvcmNlQ2hhbmdlQXRFbmQ6IHRydWUsXG4gICAgICAgIGZlZVJhdGU6IDEwMDAwLFxuICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgICBhZGRyZXNzOiAnJyxcbiAgICAgICAgfSxcbiAgICAgICAgb3BSZXR1cm5zOiB7ICdCaXRHbyBwMnNoIHRlc3QnOiAxMDAwIH0sXG4gICAgICB9O1xuXG4gICAgICAvLyBDcmVhdGUgbGVnYWN5IHRyYW5zYWN0aW9uXG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpLnJlcGx5KDIwMCwgeyBhZGRyZXNzOiAnMk1zd1Fqa3ZONm9XWWRFN0wyYnJKNWNBQU1qUG1HNTlvY28nIH0pO1xuICAgICAgY29uc3QgbGVnYWN5VHggPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oeyAuLi50eFBhcmFtcywgdXNlUHNidDogZmFsc2UgfSkpIGFzIGFueTtcblxuICAgICAgLy8gQ3JlYXRlIFBTQlQgdHJhbnNhY3Rpb24gKGV4cGxpY2l0bHkpXG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpLnJlcGx5KDIwMCwgeyBhZGRyZXNzOiAnMk1zd1Fqa3ZONm9XWWRFN0wyYnJKNWNBQU1qUG1HNTlvY28nIH0pO1xuICAgICAgY29uc3QgcHNidFR4ID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHsgLi4udHhQYXJhbXMsIHVzZVBzYnQ6IHRydWUgfSkpIGFzIGFueTtcblxuICAgICAgLy8gRXh0cmFjdCB1bnNpZ25lZCB0eCBmcm9tIFBTQlQgYW5kIGNvbXBhcmVcbiAgICAgIGNvbnN0IHBzYnQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVBzYnRGcm9tSGV4KHBzYnRUeC50cmFuc2FjdGlvbkhleCwgdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luKTtcbiAgICAgIGNvbnN0IHVuc2lnbmVkVHhGcm9tUHNidCA9IHBzYnQuZ2V0VW5zaWduZWRUeCgpLnRvSGV4KCk7XG5cbiAgICAgIC8vIFRoZSB1bnNpZ25lZCB0cmFuc2FjdGlvbiBoZXggc2hvdWxkIGJlIGlkZW50aWNhbFxuICAgICAgbGVnYWN5VHgudHJhbnNhY3Rpb25IZXguc2hvdWxkLmVxdWFsKHVuc2lnbmVkVHhGcm9tUHNidCk7XG5cbiAgICAgIC8vIEZlZXMgc2hvdWxkIGFsc28gbWF0Y2hcbiAgICAgIGxlZ2FjeVR4LmZlZS5zaG91bGQuZXF1YWwocHNidFR4LmZlZSk7XG5cbiAgICAgIC8vIENsZWFuIHVwIG5vY2sgbW9ja3MgdG8gYXZvaWQgaW50ZXJmZXJlbmNlIHdpdGggb3RoZXIgdGVzdHNcbiAgICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzZWd3aXQgUFNCVCBwcm9kdWNlcyBzYW1lIHVuc2lnbmVkIHR4IGFzIGxlZ2FjeScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNlZ3dpdEFkZHJlc3MgPSBmYWtlUHJvZFdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzEwLzEzJywgc2Vnd2l0OiB0cnVlIH0pO1xuICAgICAgY29uc3QgdW5zcGVudDogYW55ID0ge1xuICAgICAgICBhZGRyZXNzZXM6IFsnMk14S2tIOHlCM1M5WVdtVFFSYnZtYm9yWVF5UW5INXBldFAnXSxcbiAgICAgICAgdmFsdWU6ICcwLjE4NzUwMDAwJyxcbiAgICAgICAgdmFsdWVfaW50OiAxODc1MDAwMCxcbiAgICAgICAgdHhpZDogJzdkMjgyODc4YTg1ZGFlZTVkNDZlMDQzODI3ZGFlZDU3NTk2ZDc1ZDFhYTZlMDRmZDBjMDlhMzZmOTEzMDg4MWYnLFxuICAgICAgICBuOiAwLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgMzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YSBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNDM3YjM5M2ZjZTYyN2EwZWM2MzRlYjU0M2RkYTFlNjA4ZTJkMWM3OGE4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgIGlkOiA2MTMzMTYxNyxcbiAgICAgIH07XG4gICAgICBfLmV4dGVuZCh1bnNwZW50LCBzZWd3aXRBZGRyZXNzKTtcbiAgICAgIHVuc3BlbnQudmFsdWUgPSB1bnNwZW50LnZhbHVlX2ludDtcbiAgICAgIHVuc3BlbnQudHhfaGFzaCA9IHVuc3BlbnQudHhpZDtcbiAgICAgIHVuc3BlbnQudHhfb3V0cHV0X24gPSB1bnNwZW50Lm47XG4gICAgICB1bnNwZW50LnNjcmlwdCA9IHVuc3BlbnQub3V0cHV0U2NyaXB0O1xuXG4gICAgICBjb25zdCB0eFBhcmFtcyA9IHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogc2Vnd2l0QWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHNlZ3dpdCB0ZXN0JzogMTAwMCB9LFxuICAgICAgfTtcblxuICAgICAgLy8gQ3JlYXRlIGxlZ2FjeSB0cmFuc2FjdGlvblxuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS9iaWxsaW5nL2FkZHJlc3MnKS5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJNc3dRamt2TjZvV1lkRTdMMmJySjVjQUFNalBtRzU5b2NvJyB9KTtcbiAgICAgIGNvbnN0IGxlZ2FjeVR4ID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHsgLi4udHhQYXJhbXMsIHVzZVBzYnQ6IGZhbHNlIH0pKSBhcyBhbnk7XG5cbiAgICAgIC8vIENyZWF0ZSBQU0JUIHRyYW5zYWN0aW9uIChleHBsaWNpdGx5KVxuICAgICAgbm9jayhiZ1VybCkucG9zdCgnL2FwaS92MS9iaWxsaW5nL2FkZHJlc3MnKS5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJNc3dRamt2TjZvV1lkRTdMMmJySjVjQUFNalBtRzU5b2NvJyB9KTtcbiAgICAgIGNvbnN0IHBzYnRUeCA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5jcmVhdGVUcmFuc2FjdGlvbih7IC4uLnR4UGFyYW1zLCB1c2VQc2J0OiB0cnVlIH0pKSBhcyBhbnk7XG5cbiAgICAgIC8vIEV4dHJhY3QgdW5zaWduZWQgdHggZnJvbSBQU0JUIGFuZCBjb21wYXJlXG4gICAgICBjb25zdCBwc2J0ID0gdXR4b2xpYi5iaXRnby5jcmVhdGVQc2J0RnJvbUhleChwc2J0VHgudHJhbnNhY3Rpb25IZXgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICBjb25zdCB1bnNpZ25lZFR4RnJvbVBzYnQgPSBwc2J0LmdldFVuc2lnbmVkVHgoKS50b0hleCgpO1xuXG4gICAgICAvLyBUaGUgdW5zaWduZWQgdHJhbnNhY3Rpb24gaGV4IHNob3VsZCBiZSBpZGVudGljYWxcbiAgICAgIGxlZ2FjeVR4LnRyYW5zYWN0aW9uSGV4LnNob3VsZC5lcXVhbCh1bnNpZ25lZFR4RnJvbVBzYnQpO1xuXG4gICAgICAvLyBGZWVzIHNob3VsZCBhbHNvIG1hdGNoXG4gICAgICBsZWdhY3lUeC5mZWUuc2hvdWxkLmVxdWFsKHBzYnRUeC5mZWUpO1xuXG4gICAgICAvLyBDbGVhbiB1cCBub2NrIG1vY2tzIHRvIGF2b2lkIGludGVyZmVyZW5jZSB3aXRoIG90aGVyIHRlc3RzXG4gICAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgfSk7XG5cbiAgICBpdCgncDJzaCB3aXRoIFBTQlQgZm9ybWF0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcDJzaEFkZHJlc3MgPSBmYWtlUHJvZFdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzAvMTMnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgY29uc3QgdW5zcGVudDogYW55ID0ge1xuICAgICAgICBhZGRyZXNzZXM6IFsnMk5DRURtbUtOTm5xS3ZuV3c3cEUzUkx6dUZlNWFISFZ5MVgnXSxcbiAgICAgICAgdmFsdWU6ICcwLjAwNTA0NDIyJyxcbiAgICAgICAgdmFsdWVfaW50OiA1MDQ0MjIsXG4gICAgICAgIHR4aWQ6ICdiODE2ZGVkODljM2Q4ZDUwMjFiMDEwOTdmNGEzMTI5YTZhNjhhNWNiN2M4ODZlOTc5NDVmNDIwNWNiYTVkZTQ0JyxcbiAgICAgICAgbjogMSxcbiAgICAgICAgc2NyaXB0X3B1Yl9rZXk6IHtcbiAgICAgICAgICBhc206ICdPUF9IQVNIMTYwIGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTEgT1BfRVFVQUwnLFxuICAgICAgICAgIGhleDogJ2E5MTRkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExODcnLFxuICAgICAgICB9LFxuICAgICAgICByZXFfc2lnczogMSxcbiAgICAgICAgdHlwZTogJ3NjcmlwdGhhc2gnLFxuICAgICAgICBjb25maXJtYXRpb25zOiA5LFxuICAgICAgICBpZDogNjEzMzAyMjksXG4gICAgICB9O1xuICAgICAgXy5leHRlbmQodW5zcGVudCwgcDJzaEFkZHJlc3MpO1xuICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6ICcyTXN3UWprdk42b1dZZEU3TDJicko1Y0FBTWpQbUc1OW9jbycgfSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogcDJzaEFkZHJlc3MuYWRkcmVzcyxcbiAgICAgICAgdW5zcGVudHM6IFt1bnNwZW50XSxcbiAgICAgICAgcmVjaXBpZW50czoge30sXG4gICAgICAgIG5vU3BsaXRDaGFuZ2U6IHRydWUsXG4gICAgICAgIGZvcmNlQ2hhbmdlQXRFbmQ6IHRydWUsXG4gICAgICAgIGZlZVJhdGU6IDEwMDAwLFxuICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgICBhZGRyZXNzOiAnJyxcbiAgICAgICAgfSxcbiAgICAgICAgb3BSZXR1cm5zOiB7ICdCaXRHbyBwMnNoIHRlc3QnOiAxMDAwIH0sXG4gICAgICAgIHVzZVBzYnQ6IHRydWUsIC8vIEV4cGxpY2l0bHkgcmVxdWVzdCBQU0JUIGZvcm1hdFxuICAgICAgfSkpIGFzIGFueTtcblxuICAgICAgLy8gVmVyaWZ5IFBTQlQgZm9ybWF0IGlzIHJldHVybmVkIGluIHRyYW5zYWN0aW9uSGV4XG4gICAgICBzaG91bGQuZXhpc3QodHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXgpO1xuICAgICAgc2hvdWxkLm9rKHV0eG9saWIuYml0Z28uaXNQc2J0KHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4KSk7XG4gICAgICBzaG91bGQubm90LmV4aXN0KHRyYW5zYWN0aW9uLnVuc3BlbnRzKTtcblxuICAgICAgLy8gUGFyc2UgYW5kIHZhbGlkYXRlIHRoZSBQU0JUXG4gICAgICBjb25zdCBwc2J0ID0gdXR4b2xpYi5iaXRnby5jcmVhdGVQc2J0RnJvbUhleCh0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCwgdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luKTtcbiAgICAgIHBzYnQuZGF0YS5pbnB1dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcbiAgICAgIHBzYnQuZGF0YS5vdXRwdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7IC8vIE9QX1JFVFVSTiArIGNoYW5nZVxuXG4gICAgICAvLyBWZXJpZnkgaW5wdXQgaGFzIHJlcXVpcmVkIFBTQlQgbWV0YWRhdGFcbiAgICAgIGNvbnN0IGlucHV0ID0gcHNidC5kYXRhLmlucHV0c1swXTtcbiAgICAgIHNob3VsZC5leGlzdChpbnB1dC53aXRuZXNzVXR4byk7XG4gICAgICBzaG91bGQuZXhpc3QoaW5wdXQucmVkZWVtU2NyaXB0KTtcbiAgICAgIHNob3VsZC5leGlzdChpbnB1dC5iaXAzMkRlcml2YXRpb24pO1xuICAgICAgaW5wdXQuYmlwMzJEZXJpdmF0aW9uIS5sZW5ndGguc2hvdWxkLmVxdWFsKDMpOyAvLyB1c2VyLCBiYWNrdXAsIGJpdGdvXG5cbiAgICAgIC8vIFZlcmlmeSBnbG9iYWxYcHVicyBhcmUgc2V0XG4gICAgICBzaG91bGQuZXhpc3QocHNidC5kYXRhLmdsb2JhbE1hcC5nbG9iYWxYcHViKTtcbiAgICAgIHBzYnQuZGF0YS5nbG9iYWxNYXAuZ2xvYmFsWHB1YiEubGVuZ3RoLnNob3VsZC5lcXVhbCgzKTtcblxuICAgICAgLy8gU2lnbiB3aXRoIHVzZXIga2V5IC0gYXV0by1kZXRlY3RzIFBTQlQgaW4gdHJhbnNhY3Rpb25IZXhcbiAgICAgIGNvbnN0IHNpZ25lZFJlc3VsdCA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICB0cmFuc2FjdGlvbkhleDogdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXgsXG4gICAgICAgIGtleWNoYWluOiB1c2VyS2V5cGFpcixcbiAgICAgIH0pKSBhcyBhbnk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzaWduZWRSZXN1bHQudHgpO1xuXG4gICAgICAvLyBQYXJzZSBzaWduZWQgUFNCVCBhbmQgdmVyaWZ5IHNpZ25hdHVyZVxuICAgICAgY29uc3Qgc2lnbmVkUHNidCA9IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgoc2lnbmVkUmVzdWx0LnR4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgc2hvdWxkLm9rKHNpZ25lZFBzYnQudmFsaWRhdGVTaWduYXR1cmVzT2ZJbnB1dEhEKDAsIHV0eG9saWIuYmlwMzIuZnJvbUJhc2U1OCh1c2VyS2V5cGFpci54cHViKSkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NlZ3dpdCB3aXRoIFBTQlQgZm9ybWF0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2Vnd2l0QWRkcmVzcyA9IGZha2VQcm9kV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMTAvMTMnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBjb25zdCB1bnNwZW50OiBhbnkgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTXhLa0g4eUIzUzlZV21UUVJidm1ib3JZUXlRbkg1cGV0UCddLFxuICAgICAgICB2YWx1ZTogJzAuMTg3NTAwMDAnLFxuICAgICAgICB2YWx1ZV9pbnQ6IDE4NzUwMDAwLFxuICAgICAgICB0eGlkOiAnN2QyODI4NzhhODVkYWVlNWQ0NmUwNDM4MjdkYWVkNTc1OTZkNzVkMWFhNmUwNGZkMGMwOWEzNmY5MTMwODgxZicsXG4gICAgICAgIG46IDAsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCAzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0MzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgaWQ6IDYxMzMxNjE3LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIHNlZ3dpdEFkZHJlc3MpO1xuICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6ICcyTXN3UWprdk42b1dZZEU3TDJicko1Y0FBTWpQbUc1OW9jbycgfSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogc2Vnd2l0QWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHNlZ3dpdCB0ZXN0JzogMTAwMCB9LFxuICAgICAgICB1c2VQc2J0OiB0cnVlLCAvLyBFeHBsaWNpdGx5IHJlcXVlc3QgUFNCVCBmb3JtYXRcbiAgICAgIH0pKSBhcyBhbnk7XG5cbiAgICAgIC8vIFZlcmlmeSBQU0JUIGZvcm1hdCBpcyByZXR1cm5lZCBpbiB0cmFuc2FjdGlvbkhleFxuICAgICAgc2hvdWxkLmV4aXN0KHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4KTtcbiAgICAgIHNob3VsZC5vayh1dHhvbGliLmJpdGdvLmlzUHNidCh0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCkpO1xuXG4gICAgICAvLyBQYXJzZSBhbmQgdmFsaWRhdGUgdGhlIFBTQlRcbiAgICAgIGNvbnN0IHBzYnQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVBzYnRGcm9tSGV4KHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgcHNidC5kYXRhLmlucHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICAvLyBWZXJpZnkgaW5wdXQgaGFzIHNlZ3dpdCBQU0JUIG1ldGFkYXRhXG4gICAgICBjb25zdCBpbnB1dCA9IHBzYnQuZGF0YS5pbnB1dHNbMF07XG4gICAgICBzaG91bGQuZXhpc3QoaW5wdXQud2l0bmVzc1V0eG8pO1xuICAgICAgc2hvdWxkLmV4aXN0KGlucHV0LndpdG5lc3NTY3JpcHQpO1xuICAgICAgc2hvdWxkLmV4aXN0KGlucHV0LnJlZGVlbVNjcmlwdCk7XG4gICAgICBzaG91bGQuZXhpc3QoaW5wdXQuYmlwMzJEZXJpdmF0aW9uKTtcblxuICAgICAgLy8gU2lnbiB3aXRoIHVzZXIga2V5IC0gYXV0by1kZXRlY3RzIFBTQlQgaW4gdHJhbnNhY3Rpb25IZXhcbiAgICAgIGNvbnN0IHNpZ25lZFJlc3VsdCA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgICB0cmFuc2FjdGlvbkhleDogdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXgsXG4gICAgICAgIGtleWNoYWluOiB1c2VyS2V5cGFpcixcbiAgICAgIH0pKSBhcyBhbnk7XG5cbiAgICAgIHNob3VsZC5leGlzdChzaWduZWRSZXN1bHQudHgpO1xuXG4gICAgICAvLyBQYXJzZSBzaWduZWQgUFNCVCBhbmQgdmVyaWZ5IHNpZ25hdHVyZVxuICAgICAgY29uc3Qgc2lnbmVkUHNidCA9IHV0eG9saWIuYml0Z28uY3JlYXRlUHNidEZyb21IZXgoc2lnbmVkUmVzdWx0LnR4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgc2hvdWxkLm9rKHNpZ25lZFBzYnQudmFsaWRhdGVTaWduYXR1cmVzT2ZJbnB1dEhEKDAsIHV0eG9saWIuYmlwMzIuZnJvbUJhc2U1OCh1c2VyS2V5cGFpci54cHViKSkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ0JDSCBwMnNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcDJzaEFkZHJlc3MgPSBmYWtlUHJvZFdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzAvMTMnLCBzZWd3aXQ6IGZhbHNlIH0pO1xuICAgICAgY29uc3QgdW5zcGVudDogYW55ID0ge1xuICAgICAgICBhZGRyZXNzZXM6IFsnMk5DRURtbUtOTm5xS3ZuV3c3cEUzUkx6dUZlNWFISFZ5MVgnXSxcbiAgICAgICAgdmFsdWU6ICcwLjAwNTA0NDIyJyxcbiAgICAgICAgdmFsdWVfaW50OiA1MDQ0MjIsXG4gICAgICAgIHR4aWQ6ICdiODE2ZGVkODljM2Q4ZDUwMjFiMDEwOTdmNGEzMTI5YTZhNjhhNWNiN2M4ODZlOTc5NDVmNDIwNWNiYTVkZTQ0JyxcbiAgICAgICAgbjogMSxcbiAgICAgICAgc2NyaXB0X3B1Yl9rZXk6IHtcbiAgICAgICAgICBhc206ICdPUF9IQVNIMTYwIGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTEgT1BfRVFVQUwnLFxuICAgICAgICAgIGhleDogJ2E5MTRkMDM5Y2IzMzQ0Mjk0YTVhMzg0YTU1MDhhMDA2NDQ0YzQyMGNiYzExODcnLFxuICAgICAgICB9LFxuICAgICAgICByZXFfc2lnczogMSxcbiAgICAgICAgdHlwZTogJ3NjcmlwdGhhc2gnLFxuICAgICAgICBjb25maXJtYXRpb25zOiA5LFxuICAgICAgICBpZDogNjEzMzAyMjksXG4gICAgICB9O1xuICAgICAgXy5leHRlbmQodW5zcGVudCwgcDJzaEFkZHJlc3MpO1xuICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6ICcyTXN3UWprdk42b1dZZEU3TDJicko1Y0FBTWpQbUc1OW9jbycgfSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogcDJzaEFkZHJlc3MuYWRkcmVzcyxcbiAgICAgICAgdW5zcGVudHM6IFt1bnNwZW50XSxcbiAgICAgICAgcmVjaXBpZW50czoge30sXG4gICAgICAgIG5vU3BsaXRDaGFuZ2U6IHRydWUsXG4gICAgICAgIGZvcmNlQ2hhbmdlQXRFbmQ6IHRydWUsXG4gICAgICAgIGZlZVJhdGU6IDEwMDAwLFxuICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgICBhZGRyZXNzOiAnJyxcbiAgICAgICAgfSxcbiAgICAgICAgb3BSZXR1cm5zOiB7ICdCaXRHbyBwMnNoIHRlc3QnOiAxMDAwIH0sXG4gICAgICAgIHVzZVBzYnQ6IGZhbHNlLFxuICAgICAgfSkpIGFzIGFueTtcbiAgICAgIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDE0NGRlYTVjYjA1NDI1Zjk0OTc2ZTg4N2NjYmE1Njg2YTlhMTJhM2Y0OTcxMGIwMjE1MDhkM2Q5Y2Q4ZGUxNmI4MDEwMDAwMDAwMGZmZmZmZmZmMDJlODAzMDAwMDAwMDAwMDAwMTE2YTBmNDI2OTc0NDc2ZjIwNzAzMjczNjgyMDc0NjU3Mzc0MjJhMTA3MDAwMDAwMDAwMDE3YTkxNGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTE4NzAwMDAwMDAwJ1xuICAgICAgKTtcblxuICAgICAgLy8gYWRkIGZpcnN0IHNpZ25hdHVyZVxuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSB1c2VyS2V5cGFpcjtcbiAgICAgIHRyYW5zYWN0aW9uLmZvcmNlQkNIID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZTEgPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkgYXMgYW55O1xuICAgICAgc2lnbmF0dXJlMS50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAxNDRkZWE1Y2IwNTQyNWY5NDk3NmU4ODdjY2JhNTY4NmE5YTEyYTNmNDk3MTBiMDIxNTA4ZDNkOWNkOGRlMTZiODAxMDAwMDAwYjYwMDQ3MzA0NDAyMjA2MjIxYTk3ZjA4MWQ4N2UwMmUzYjE0OTg4YTY0ODYxODExYTZhOGRlNGYxMWY3NGY1YWFlYTQ1OTgxY2Y2MTJlMDIyMDc3YTA4YTViZDdkNzgxZTc5ODM4YWZiYjEyNmFmMmU0ODgwMmZlZmFkNjYwYWZkYmQ4ODA1ZjVlNTk4ZWQ1ODg0MTAwMDA0YzY5NTIyMTAzMWNkMjI3ZTQwYWQ2MWI0ZTEzNzEwOWNiMjg0NWViNmY1YTU4NGVkNWM2N2Q5ZDMxMzVjZGFhNTA0NWE4NDJlYTIxMDNhMmU3YjU0YzdiMmRhMDk5MjU1NTM1M2I4ZTI2YzZhY2ZmNDI0OGY0MzUxZjA4Nzg3YmYzZTJlZmM5NGI2NTgzMjEwMjVjMmE2Y2RlMzNjMmQ3M2NjZjEyZWVjZjY0YzU0ZjA4ZjcyMmMyZjA3MzgyNDQ5ODk1MDY5NWU5ODgzYjE0MTI1M2FlZmZmZmZmZmYwMmU4MDMwMDAwMDAwMDAwMDAxMTZhMGY0MjY5NzQ0NzZmMjA3MDMyNzM2ODIwNzQ2NTczNzQyMmExMDcwMDAwMDAwMDAwMTdhOTE0ZDAzOWNiMzM0NDI5NGE1YTM4NGE1NTA4YTAwNjQ0NGM0MjBjYmMxMTg3MDAwMDAwMDAnXG4gICAgICApO1xuICAgICAgLy8gYWRkIHNlY29uZCBzaWduYXR1cmVcbiAgICAgIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4ID0gc2lnbmF0dXJlMS50eDtcbiAgICAgIHRyYW5zYWN0aW9uLmtleWNoYWluID0gYmFja3VwS2V5cGFpcjtcbiAgICAgIHRyYW5zYWN0aW9uLmZ1bGxMb2NhbFNpZ25pbmcgPSB0cnVlO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMiA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICAvLyB0aGlzIHRyYW5zYWN0aW9uIGhhcyBhY3R1YWxseSB3b3JrZWQ6IGh0dHBzOi8vdGVzdG5ldC5zbWFydGJpdC5jb20uYXUvdHgvYThjY2I5MjgxNjkwMzJkNmUxZjM3YmY4MWRmZDlhYjZkOTAzNjJhNGY4NGU1NzczOTdmYTY5MGFhNzExNTUwY1xuICAgICAgLy8gTm90ZSB0aGF0IHRoZSB0eCBoZXggYmVsb3cgbm8gbG9uZ2VyIGNvcnJlc3BvbmRzIHRvIHRoZSBhYm92ZSB0cmFuc2FjdGlvbiBiZWNhdXNlIG91ciBmZWUgZXN0aW1hdGlvbiBoYXNcbiAgICAgIC8vIGNoYW5nZWQsIGNoYW5naW5nIHRoZSBvdXRwdXQgYW1vdW50cyBhbmQgdGh1cyB0aGUgdHggaGV4LlxuICAgICAgc2lnbmF0dXJlMi50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAxNDRkZWE1Y2IwNTQyNWY5NDk3NmU4ODdjY2JhNTY4NmE5YTEyYTNmNDk3MTBiMDIxNTA4ZDNkOWNkOGRlMTZiODAxMDAwMDAwZmRmZTAwMDA0NzMwNDQwMjIwNjIyMWE5N2YwODFkODdlMDJlM2IxNDk4OGE2NDg2MTgxMWE2YThkZTRmMTFmNzRmNWFhZWE0NTk4MWNmNjEyZTAyMjA3N2EwOGE1YmQ3ZDc4MWU3OTgzOGFmYmIxMjZhZjJlNDg4MDJmZWZhZDY2MGFmZGJkODgwNWY1ZTU5OGVkNTg4NDE0ODMwNDUwMjIxMDA4MmJjNTQ2MjkzODU4NDU5ZjM4OTVkYjI0Yzg1Y2NmMzc1MDVjNTZmOGZhZjRiYjhmNzhjZjQwMTM1YmMyZjJiMDIyMDNkYzFjNzhkN2M3Y2VhZjZiOTI0ZWNhM2MzOWI5NWU4YTIyN2IwNjlhMDcwNDc1ODEyNzMxMzZiNDdjYTdhYzQ0MTAwNGM2OTUyMjEwMzFjZDIyN2U0MGFkNjFiNGUxMzcxMDljYjI4NDVlYjZmNWE1ODRlZDVjNjdkOWQzMTM1Y2RhYTUwNDVhODQyZWEyMTAzYTJlN2I1NGM3YjJkYTA5OTI1NTUzNTNiOGUyNmM2YWNmZjQyNDhmNDM1MWYwODc4N2JmM2UyZWZjOTRiNjU4MzIxMDI1YzJhNmNkZTMzYzJkNzNjY2YxMmVlY2Y2NGM1NGYwOGY3MjJjMmYwNzM4MjQ0OTg5NTA2OTVlOTg4M2IxNDEyNTNhZWZmZmZmZmZmMDJlODAzMDAwMDAwMDAwMDAwMTE2YTBmNDI2OTc0NDc2ZjIwNzAzMjczNjgyMDc0NjU3Mzc0MjJhMTA3MDAwMDAwMDAwMDE3YTkxNGQwMzljYjMzNDQyOTRhNWEzODRhNTUwOGEwMDY0NDRjNDIwY2JjMTE4NzAwMDAwMDAwJ1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdkZWZhdWx0IHNlZ3dpdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNlZ3dpdEFkZHJlc3MgPSBmYWtlUHJvZFdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzEwLzEzJywgc2Vnd2l0OiB0cnVlIH0pO1xuICAgICAgY29uc3QgdW5zcGVudDogYW55ID0ge1xuICAgICAgICBhZGRyZXNzZXM6IFsnMk14S2tIOHlCM1M5WVdtVFFSYnZtYm9yWVF5UW5INXBldFAnXSxcbiAgICAgICAgdmFsdWU6ICcwLjE4NzUwMDAwJyxcbiAgICAgICAgdmFsdWVfaW50OiAxODc1MDAwMCxcbiAgICAgICAgdHhpZDogJzdkMjgyODc4YTg1ZGFlZTVkNDZlMDQzODI3ZGFlZDU3NTk2ZDc1ZDFhYTZlMDRmZDBjMDlhMzZmOTEzMDg4MWYnLFxuICAgICAgICBuOiAwLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgMzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YSBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNDM3YjM5M2ZjZTYyN2EwZWM2MzRlYjU0M2RkYTFlNjA4ZTJkMWM3OGE4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgIGlkOiA2MTMzMTYxNyxcbiAgICAgIH07XG4gICAgICBfLmV4dGVuZCh1bnNwZW50LCBzZWd3aXRBZGRyZXNzKTtcbiAgICAgIHVuc3BlbnQudmFsdWUgPSB1bnNwZW50LnZhbHVlX2ludDtcbiAgICAgIHVuc3BlbnQudHhfaGFzaCA9IHVuc3BlbnQudHhpZDtcbiAgICAgIHVuc3BlbnQudHhfb3V0cHV0X24gPSB1bnNwZW50Lm47XG4gICAgICB1bnNwZW50LnNjcmlwdCA9IHVuc3BlbnQub3V0cHV0U2NyaXB0O1xuXG4gICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpLnJlcGx5KDIwMCwgeyBhZGRyZXNzOiAnMk1zd1Fqa3ZONm9XWWRFN0wyYnJKNWNBQU1qUG1HNTlvY28nIH0pO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5jcmVhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgIGNoYW5nZUFkZHJlc3M6IHNlZ3dpdEFkZHJlc3MuYWRkcmVzcyxcbiAgICAgICAgdW5zcGVudHM6IFt1bnNwZW50XSxcbiAgICAgICAgcmVjaXBpZW50czoge30sXG4gICAgICAgIG5vU3BsaXRDaGFuZ2U6IHRydWUsXG4gICAgICAgIGZvcmNlQ2hhbmdlQXRFbmQ6IHRydWUsXG4gICAgICAgIGZlZVJhdGU6IDEwMDAwLFxuICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgICBhZGRyZXNzOiAnJyxcbiAgICAgICAgfSxcbiAgICAgICAgb3BSZXR1cm5zOiB7ICdCaXRHbyBzZWd3aXQgdGVzdCc6IDEwMDAgfSxcbiAgICAgICAgdXNlUHNidDogZmFsc2UsXG4gICAgICB9KSkgYXMgYW55O1xuICAgICAgdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMTFmODgzMDkxNmZhMzA5MGNmZDA0NmVhYWQxNzU2ZDU5NTdlZGRhMjczODA0NmVkNGU1YWU1ZGE4NzgyODI4N2QwMDAwMDAwMDAwZmZmZmZmZmYwMmU4MDMwMDAwMDAwMDAwMDAxMzZhMTE0MjY5NzQ0NzZmMjA3MzY1Njc3NzY5NzQyMDc0NjU3Mzc0MGUwZjFlMDEwMDAwMDAwMDE3YTkxNDM3YjM5M2ZjZTYyN2EwZWM2MzRlYjU0M2RkYTFlNjA4ZTJkMWM3OGE4NzAwMDAwMDAwJ1xuICAgICAgKTtcblxuICAgICAgLy8gYWRkIGZpcnN0IHNpZ25hdHVyZVxuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSB1c2VyS2V5cGFpcjtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZTEgPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkgYXMgYW55O1xuICAgICAgc2lnbmF0dXJlMS50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAwMDEwMTFmODgzMDkxNmZhMzA5MGNmZDA0NmVhYWQxNzU2ZDU5NTdlZGRhMjczODA0NmVkNGU1YWU1ZGE4NzgyODI4N2QwMDAwMDAwMDIzMjIwMDIwNDQwZTg1ODIyOGI3NTM1NDRiNGM1N2UzMDAyOTZiNTU3MTdmODExMDUzODgzZjliZTliNmE3MTJlYWNkOTMxY2ZmZmZmZmZmMDJlODAzMDAwMDAwMDAwMDAwMTM2YTExNDI2OTc0NDc2ZjIwNzM2NTY3Nzc2OTc0MjA3NDY1NzM3NDBlMGYxZTAxMDAwMDAwMDAxN2E5MTQzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhODcwNTAwNDgzMDQ1MDIyMTAwYmYzYTg5MTRhMWJmZTkyNjYxZjI3Y2EzN2MwZDZiNWMwYjNjNzM1MzYxNGM5NTU2NDY5MjlmMmU3ZWI4OWZmZTAyMjAyZDU1NmIwZmZhYjM3YzEwNGJhZTY3NDA2Y2ExNmY4ODU5Y2ZhMzdjNmE0MGYyMDEzZDg5YWZjZWNkNTU5NGYzMDEwMDAwNjk1MjIxMDMyYzUwNWZjOGExZTRiNTY4MTFiMjczNjZhMzcxZTYxYzlmYWY1NjVkZDJmYWJhZmY3YTcwZWFjMTljMzIxNTdjMjEwMjUxMTYwYjU4M2JkNWRjMGYwZDQ4MDk2NTA1MTMxYzQzNDdhYjY1YjRmMjFlZDU3ZDc2YzM4MTU3NDk5YzAwM2QyMTAyNjc5NzEyZDYyYTI1NjA5MTdjYzQzZmQyY2MzYTFiOWI2MWY1MjhjODhiYzY0OTA1YmFlNmVlMDc5ZTYwNjA5ZjUzYWUwMDAwMDAwMCdcbiAgICAgICk7XG5cbiAgICAgIC8vIGFkZCBzZWNvbmQgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleCA9IHNpZ25hdHVyZTEudHg7XG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IGJhY2t1cEtleXBhaXI7XG4gICAgICB0cmFuc2FjdGlvbi5mdWxsTG9jYWxTaWduaW5nID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZTIgPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkgYXMgYW55O1xuICAgICAgLy8gdGhpcyB0cmFuc2FjdGlvbiBoYXMgYWN0dWFsbHkgd29ya2VkOiBodHRwczovL3Rlc3RuZXQuc21hcnRiaXQuY29tLmF1L3R4L2Q2NzI2NmYxZGU5MDViYWFlZTc1MDAxMWZhNGIzZDg4YThlM2ExNzU4ZDUxNzNhNjU5YzY3NzA5NDg4ZGRlMDdcbiAgICAgIC8vIE5vdGUgdGhhdCB0aGUgdHggaGV4IGJlbG93IG5vIGxvbmdlciBjb3JyZXNwb25kcyB0byB0aGUgYWJvdmUgdHJhbnNhY3Rpb24gYmVjYXVzZSBvdXIgZmVlIGVzdGltYXRpb24gaGFzXG4gICAgICAvLyBjaGFuZ2VkLCBjaGFuZ2luZyB0aGUgb3V0cHV0IGFtb3VudHMgYW5kIHRodXMgdGhlIHR4IGhleC5cbiAgICAgIHNpZ25hdHVyZTIudHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMDAxMDExZjg4MzA5MTZmYTMwOTBjZmQwNDZlYWFkMTc1NmQ1OTU3ZWRkYTI3MzgwNDZlZDRlNWFlNWRhODc4MjgyODdkMDAwMDAwMDAyMzIyMDAyMDQ0MGU4NTgyMjhiNzUzNTQ0YjRjNTdlMzAwMjk2YjU1NzE3ZjgxMTA1Mzg4M2Y5YmU5YjZhNzEyZWFjZDkzMWNmZmZmZmZmZjAyZTgwMzAwMDAwMDAwMDAwMDEzNmExMTQyNjk3NDQ3NmYyMDczNjU2Nzc3Njk3NDIwNzQ2NTczNzQwZTBmMWUwMTAwMDAwMDAwMTdhOTE0MzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YTg3MDUwMDQ4MzA0NTAyMjEwMGJmM2E4OTE0YTFiZmU5MjY2MWYyN2NhMzdjMGQ2YjVjMGIzYzczNTM2MTRjOTU1NjQ2OTI5ZjJlN2ViODlmZmUwMjIwMmQ1NTZiMGZmYWIzN2MxMDRiYWU2NzQwNmNhMTZmODg1OWNmYTM3YzZhNDBmMjAxM2Q4OWFmY2VjZDU1OTRmMzAxNDczMDQ0MDIyMDVjZjhkMmYyYmU2Y2UwODNkMzU2NTRiZGMzZmE4NWQ3ZTcxYjIyN2Q0NTdlOTI0NWJiNjAzYjIxZTdiNTE2NTEwMjIwM2VhNjg2MjI2ZGI4MzIwZTA4YzI2YmZiMzA0MDQ4YjNhOTQ3M2QwZTA1Nzk3ZDM2NThkYWNiMmYwOWEyYjUxYzAxMDA2OTUyMjEwMzJjNTA1ZmM4YTFlNGI1NjgxMWIyNzM2NmEzNzFlNjFjOWZhZjU2NWRkMmZhYmFmZjdhNzBlYWMxOWMzMjE1N2MyMTAyNTExNjBiNTgzYmQ1ZGMwZjBkNDgwOTY1MDUxMzFjNDM0N2FiNjViNGYyMWVkNTdkNzZjMzgxNTc0OTljMDAzZDIxMDI2Nzk3MTJkNjJhMjU2MDkxN2NjNDNmZDJjYzNhMWI5YjYxZjUyOGM4OGJjNjQ5MDViYWU2ZWUwNzllNjA2MDlmNTNhZTAwMDAwMDAwJ1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdjcmVhdGVzIGFuIHVuc2lnbmVkIHR4IG1hZGUgb2YgdW5jb21wcmVzc2VkIHB1YmxpYyBrZXlzIG9mIHYxIHNhZmUgd2FsbGV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgeyBhZGRyZXNzLCByZWRlZW1TY3JpcHQsIHNjcmlwdFB1YktleSB9ID0gYXdhaXQgZ2V0Rml4dHVyZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgICAgIGAke19fZGlybmFtZX0vZml4dHVyZXMvc2lnbi10cmFuc2FjdGlvbi5qc29uYFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHRlc3RCaXRnbyA9IG5ldyBCaXRHb0FQSSh7IGVudjogJ3Rlc3QnLCBjbGllbnRDb25zdGFudHM6IHsgY29uc3RhbnRzOiB7fSB9IH0pO1xuICAgICAgY29uc3QgZmFrZVRlc3RWMVNhZmVXYWxsZXQgPSBuZXcgV2FsbGV0KHRlc3RCaXRnbywge1xuICAgICAgICBpZDogYWRkcmVzcyxcbiAgICAgICAgcHJpdmF0ZTogeyBzYWZlOiB7IHJlZGVlbVNjcmlwdCB9IH0sXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHVuc3BlbnRzVG9TcGVuZCA9IFtcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiAxMDAwMDAsXG4gICAgICAgICAgcmVkZWVtU2NyaXB0LFxuICAgICAgICAgIHNjcmlwdDogc2NyaXB0UHViS2V5LFxuICAgICAgICAgIHR4X2hhc2g6ICdhNTVkMTFkYzhiNzAxYmQxOTYwMWZiZmU3MTFhMWU0NjVmYzhmMTI4ZWM0NDc0ZTc4ZTFmZDA4N2U4MDhlNWZlJyxcbiAgICAgICAgICB0eF9vdXRwdXRfbjogMCxcbiAgICAgICAgICBjb25maXJtYXRpb25zOiAxLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgdmFsdWU6IDEwMDAwMCxcbiAgICAgICAgICByZWRlZW1TY3JpcHQsXG4gICAgICAgICAgc2NyaXB0OiBzY3JpcHRQdWJLZXksXG4gICAgICAgICAgdHhfaGFzaDogJzQ4ZmI4NzljZWM4NzkzNTYwNDVhMzMxOTM3MDIzYWVkODU5ZjVkYzVkYjk1NWExZGM4YTVjY2YyOWY0OWQxMDgnLFxuICAgICAgICAgIHR4X291dHB1dF9uOiAwLFxuICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDEsXG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgICAgY29uc3QgcmVjaXBpZW50cyA9IHtcbiAgICAgICAgJzJNeUd4cmhMQzRrUmZ1VmpMcUNWWUZ0QzdEY2hoZ01DaU56JzogMTkxMzQwLCAvLyBwdXJwb3NlbHkgc2V0IHRvIHNpbXVsYXRlIGEgc3dlZXAgdHJhbnNhY3Rpb25cbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IHNjb3BlID0gbm9jayhiZ1VybFRlc3QpXG4gICAgICAgIC5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpXG4gICAgICAgIC5yZXBseSgyMDAsIHsgYWRkcmVzczogJzJOM0w5Y3U5V04yRGY3WHZiMVk4b3dva3VEVmo1SGR5djRpJyB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZmFrZVRlc3RWMVNhZmVXYWxsZXQuY3JlYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICByZWNpcGllbnRzLFxuICAgICAgICB1bnNwZW50czogdW5zcGVudHNUb1NwZW5kLFxuICAgICAgICBmZWVSYXRlOiAxMDAwMCwgLy8gMTAgc2F0L2J5dGVcbiAgICAgICAgYml0Z29GZWU6IHtcbiAgICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgICAgYWRkcmVzczogJycsXG4gICAgICAgIH0sXG4gICAgICAgIHVzZVBzYnQ6IGZhbHNlLFxuICAgICAgfSk7XG5cbiAgICAgIHNjb3BlLmlzRG9uZSgpLnNob3VsZC5iZS50cnVlKCk7XG5cbiAgICAgIHJlc3VsdC5lc3RpbWF0ZWRTaXplLnNob3VsZC5lcXVhbCg4NjYpO1xuICAgICAgcmVzdWx0LmZlZS5zaG91bGQuZXF1YWwoODY2MCk7XG4gICAgICAvLyBUaGlzIHNob3VsZCBlcXVhbCB0byAxIGJlY2F1c2UgdGhpcyBpcyBhIHN3ZWVwIHRyYW5zYWN0aW9uIGJ1dCBkdWUgdG8gaGFyZGNvZGVkIGFkZGl0aW9uIG9mXG4gICAgICAvLyAxIGNoYW5nZSBvdXRwdXQgaW4gdHJhbnNhY3Rpb25CdWlsZGVyLCBpdCBpcyAyLlxuICAgICAgLy8gQmVjYXVzZSBvZiB0aGlzIHRoZSBlc3RpbWF0ZWQgc2l6ZSBvZiB0aGUgdHJhbnNhY3Rpb25zIGlzIG1vcmUgdGhhbiB3aGF0IGl0IGFjdHVhbGx5IGlzIGluIHRoZSBoZXguXG4gICAgICByZXN1bHQudHhJbmZvLm5PdXRwdXRzLnNob3VsZC5lcXVhbCgyKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWducyBhbiB1bnNpZ25lZCB0eCBtYWRlIG9mIHVuY29tcHJlc3NlZCBwdWJsaWMga2V5cyBvZiB2MSBzYWZlIHdhbGxldCAmIHZlcmlmaWVzIHNpZ25hdHVyZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGFkZHJlc3MsXG4gICAgICAgIHJlZGVlbVNjcmlwdCxcbiAgICAgICAgc2NyaXB0UHViS2V5LFxuICAgICAgICB1c2VyS2V5V0lGOiB1c2VyU2lnbmluZ0tleSxcbiAgICAgICAgYml0Z29LZXlXSUY6IGJpdGdvU2lnbmluZ0tleSxcbiAgICAgICAgdW5zaWduZWRUeEhleCxcbiAgICAgICAgaGFsZlNpZ25lZFR4SGV4LFxuICAgICAgICBmdWxsU2lnbmVkVHhIZXgsXG4gICAgICB9ID0gYXdhaXQgZ2V0Rml4dHVyZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oYCR7X19kaXJuYW1lfS9maXh0dXJlcy9zaWduLXRyYW5zYWN0aW9uLmpzb25gKTtcbiAgICAgIGNvbnN0IHRlc3RCaXRnbyA9IG5ldyBCaXRHb0FQSSh7IGVudjogJ3Rlc3QnLCBjbGllbnRDb25zdGFudHM6IHsgY29uc3RhbnRzOiB7fSB9IH0pO1xuICAgICAgY29uc3QgZmFrZVRlc3RWMVNhZmVXYWxsZXQgPSBuZXcgV2FsbGV0KHRlc3RCaXRnbywge1xuICAgICAgICBpZDogYWRkcmVzcyxcbiAgICAgICAgcHJpdmF0ZTogeyBzYWZlOiB7IHJlZGVlbVNjcmlwdCB9IH0sXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHVuc3BlbnRzVG9TcGVuZCA9IFtcbiAgICAgICAgeyB2YWx1ZTogMTAwMDAwLCByZWRlZW1TY3JpcHQsIHNjcmlwdDogc2NyaXB0UHViS2V5IH0sXG4gICAgICAgIHsgdmFsdWU6IDEwMDAwMCwgcmVkZWVtU2NyaXB0LCBzY3JpcHQ6IHNjcmlwdFB1YktleSB9LFxuICAgICAgXTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRUeCA9IGF3YWl0IGZha2VUZXN0VjFTYWZlV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih7XG4gICAgICAgIHRyYW5zYWN0aW9uSGV4OiB1bnNpZ25lZFR4SGV4LFxuICAgICAgICBzaWduaW5nS2V5OiB1c2VyU2lnbmluZ0tleSxcbiAgICAgICAgdW5zcGVudHM6IHVuc3BlbnRzVG9TcGVuZCxcbiAgICAgICAgdmFsaWRhdGU6IHRydWUsXG4gICAgICB9KTtcbiAgICAgIGhhbGZTaWduZWRUeC50eC5zaG91bGQuZXF1YWwoaGFsZlNpZ25lZFR4SGV4KTtcblxuICAgICAgY29uc3QgZnVsbFNpZ25lZFR4ID0gYXdhaXQgZmFrZVRlc3RWMVNhZmVXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgICAgdHJhbnNhY3Rpb25IZXg6IGhhbGZTaWduZWRUeEhleCxcbiAgICAgICAgc2lnbmluZ0tleTogYml0Z29TaWduaW5nS2V5LFxuICAgICAgICB1bnNwZW50czogdW5zcGVudHNUb1NwZW5kLFxuICAgICAgICB2YWxpZGF0ZTogdHJ1ZSxcbiAgICAgICAgZnVsbExvY2FsU2lnbmluZzogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgLy8gVXBvbiBjYWxsaW5nIHR4Yi5idWlsZCgpIGluc3RlYWQgYWZ0ZXIgZ2V0dGluZyAyIHZhbGlkIHNpZ25hdHVyZXMsIHdlIGdldCBhIHZhbGlkIGZ1bGwgc2lnbmVkIHR4IHRoYXQgd2FzIGJyb2FkY2FzdFxuICAgICAgLy8gYW5kIGNvbmZpcm1lZCBvbiB0ZXN0bmV0IGhlcmU6IGh0dHBzOi8vbWVtcG9vbC5zcGFjZS90ZXN0bmV0L3R4L2JkZTA5ZjFiZDVlNjY2MWMyOGQ5MGU0Yzk2MjkxODUzZTIxYmExNWFiNDJmM2U0YTMwNzE5ZGVjYjczZTc5MWJcbiAgICAgIC8vIEl0J3MgcHJlc2VudCBpbiB0aGUgZnVsbFNpZ25lZFR4SGV4QnVpbGRDb21wbGV0ZSBwcm9wZXJ0eSBvZiB0aGUgZml4dHVyZS5cbiAgICAgIGZ1bGxTaWduZWRUeC50eC5zaG91bGQuZXF1YWwoZnVsbFNpZ25lZFR4SGV4KTtcbiAgICB9KTtcblxuICAgIGl0KCdCQ0ggc2Vnd2l0IHNob3VsZCBmYWlsJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2Vnd2l0QWRkcmVzcyA9IGZha2VQcm9kV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMTAvMTMnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBjb25zdCB1bnNwZW50OiBhbnkgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTXhLa0g4eUIzUzlZV21UUVJidm1ib3JZUXlRbkg1cGV0UCddLFxuICAgICAgICB2YWx1ZTogJzAuMTg3NTAwMDAnLFxuICAgICAgICB2YWx1ZV9pbnQ6IDE4NzUwMDAwLFxuICAgICAgICB0eGlkOiAnN2QyODI4NzhhODVkYWVlNWQ0NmUwNDM4MjdkYWVkNTc1OTZkNzVkMWFhNmUwNGZkMGMwOWEzNmY5MTMwODgxZicsXG4gICAgICAgIG46IDAsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCAzN2IzOTNmY2U2MjdhMGVjNjM0ZWI1NDNkZGExZTYwOGUyZDFjNzhhIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0MzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YTg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgaWQ6IDYxMzMxNjE3LFxuICAgICAgfTtcbiAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIHNlZ3dpdEFkZHJlc3MpO1xuICAgICAgdW5zcGVudC52YWx1ZSA9IHVuc3BlbnQudmFsdWVfaW50O1xuICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgIHVuc3BlbnQuc2NyaXB0ID0gdW5zcGVudC5vdXRwdXRTY3JpcHQ7XG5cbiAgICAgIG5vY2soYmdVcmwpLnBvc3QoJy9hcGkvdjEvYmlsbGluZy9hZGRyZXNzJykucmVwbHkoMjAwLCB7IGFkZHJlc3M6ICcyTXN3UWprdk42b1dZZEU3TDJicko1Y0FBTWpQbUc1OW9jbycgfSk7XG5cbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9uID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogc2Vnd2l0QWRkcmVzcy5hZGRyZXNzLFxuICAgICAgICB1bnNwZW50czogW3Vuc3BlbnRdLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGFkZHJlc3M6ICcnLFxuICAgICAgICB9LFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIHNlZ3dpdCB0ZXN0JzogMTAwMCB9LFxuICAgICAgICB1c2VQc2J0OiBmYWxzZSxcbiAgICAgIH0pKSBhcyBhbnk7XG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAxMWY4ODMwOTE2ZmEzMDkwY2ZkMDQ2ZWFhZDE3NTZkNTk1N2VkZGEyNzM4MDQ2ZWQ0ZTVhZTVkYTg3ODI4Mjg3ZDAwMDAwMDAwMDBmZmZmZmZmZjAyZTgwMzAwMDAwMDAwMDAwMDEzNmExMTQyNjk3NDQ3NmYyMDczNjU2Nzc3Njk3NDIwNzQ2NTczNzQwZTBmMWUwMTAwMDAwMDAwMTdhOTE0MzdiMzkzZmNlNjI3YTBlYzYzNGViNTQzZGRhMWU2MDhlMmQxYzc4YTg3MDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgZmlyc3Qgc2lnbmF0dXJlXG4gICAgICB0cmFuc2FjdGlvbi5rZXljaGFpbiA9IHVzZXJLZXlwYWlyO1xuICAgICAgdHJhbnNhY3Rpb24uZm9yY2VCQ0ggPSB0cnVlO1xuICAgICAgKCgpID0+IGZha2VQcm9kV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih0cmFuc2FjdGlvbikpLnNob3VsZC50aHJvdygnQkNIIGRvZXMgbm90IHN1cHBvcnQgc2Vnd2l0IGlucHV0cycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ21peGVkIHAyc2ggJiBzZWd3aXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwMnNoQWRkcmVzcyA9IGZha2VXYWxsZXQuZ2VuZXJhdGVBZGRyZXNzKHsgcGF0aDogJy8wLzE0Jywgc2Vnd2l0OiBmYWxzZSB9KTtcbiAgICAgIGNvbnN0IHNlZ3dpdEFkZHJlc3MgPSBmYWtlV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMTAvMTQnLCBzZWd3aXQ6IHRydWUgfSk7XG4gICAgICBjb25zdCBwMnNoVW5zcGVudCA9IHtcbiAgICAgICAgYWRkcmVzc2VzOiBbJzJONTMzZnFneVBZS1ZEODkybkJSYVltRkhiYlR5a2hZU0V3J10sXG4gICAgICAgIHZhbHVlOiAnMi45OTk5NjYxMCcsXG4gICAgICAgIHZhbHVlX2ludDogMjk5OTk2NjEwLFxuICAgICAgICB0eGlkOiAnZjY1NGNlMGE1YmUzZjEyZGY3ZmVjZjRlZTc3N2I2ZDg2YjVhYThjNzEwZWY2OTQ2ZWMxMjEyMDZiNGY4NzU3YycsXG4gICAgICAgIG46IDEsXG4gICAgICAgIHNjcmlwdF9wdWJfa2V5OiB7XG4gICAgICAgICAgYXNtOiAnT1BfSEFTSDE2MCA4MTUzZTdhMzU1MDgwODhiNmNmNTk5MjI2NzkyYzdkZTJkYmZmMjUyIE9QX0VRVUFMJyxcbiAgICAgICAgICBoZXg6ICdhOTE0ODE1M2U3YTM1NTA4MDg4YjZjZjU5OTIyNjc5MmM3ZGUyZGJmZjI1Mjg3JyxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxX3NpZ3M6IDEsXG4gICAgICAgIHR5cGU6ICdzY3JpcHRoYXNoJyxcbiAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgaWQ6IDYxMzMxMjYzLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHNlZ3dpdFVuc3BlbnQgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTkJ0cFhjRHJ1ZjN6UnV0bUY0QWJDTUZOUUhYc0dOUDZrVCddLFxuICAgICAgICB2YWx1ZTogJzEuNTAwMDAwMDAnLFxuICAgICAgICB2YWx1ZV9pbnQ6IDE1MDAwMDAwMCxcbiAgICAgICAgdHhpZDogJ2E0NDA5YzNmMDQyZmFlNjdiODkwYWMzZGY0MGVmMGRiMDM1MzljNjczMzFmZDdlOTI2MDUxMTg5M2I0ZjlmMjQnLFxuICAgICAgICBuOiAwLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgY2M4ZTdjYmY0ODEzODlkMzE4M2E1OTBhY2ZhNmFhNjZlYjk3YzhlMSBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNGNjOGU3Y2JmNDgxMzg5ZDMxODNhNTkwYWNmYTZhYTY2ZWI5N2M4ZTE4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgIGlkOiA2MTMzMDg4MixcbiAgICAgIH07XG4gICAgICBjb25zdCBhZGRyZXNzZXMgPSBbcDJzaEFkZHJlc3MsIHNlZ3dpdEFkZHJlc3NdO1xuICAgICAgY29uc3QgdW5zcGVudHMgPSBbcDJzaFVuc3BlbnQsIHNlZ3dpdFVuc3BlbnRdLm1hcCgodW5zcGVudDogYW55LCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBhZGRyZXNzID0gYWRkcmVzc2VzW2luZGV4XTtcbiAgICAgICAgXy5leHRlbmQodW5zcGVudCwgYWRkcmVzcyk7XG4gICAgICAgIHVuc3BlbnQudmFsdWUgPSB1bnNwZW50LnZhbHVlX2ludDtcbiAgICAgICAgdW5zcGVudC50eF9oYXNoID0gdW5zcGVudC50eGlkO1xuICAgICAgICB1bnNwZW50LnR4X291dHB1dF9uID0gdW5zcGVudC5uO1xuICAgICAgICB1bnNwZW50LnNjcmlwdCA9IHVuc3BlbnQub3V0cHV0U2NyaXB0O1xuICAgICAgICByZXR1cm4gdW5zcGVudDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCB0cmFuc2FjdGlvbiA9IChhd2FpdCBmYWtlV2FsbGV0LmNyZWF0ZVRyYW5zYWN0aW9uKHtcbiAgICAgICAgY2hhbmdlQWRkcmVzczogcDJzaEFkZHJlc3MuYWRkcmVzcyxcbiAgICAgICAgdW5zcGVudHM6IHVuc3BlbnRzLFxuICAgICAgICByZWNpcGllbnRzOiB7fSxcbiAgICAgICAgbm9TcGxpdENoYW5nZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VDaGFuZ2VBdEVuZDogdHJ1ZSxcbiAgICAgICAgZmVlUmF0ZTogMTAwMDAsXG4gICAgICAgIG9wUmV0dXJuczogeyAnQml0R28gbWl4ZWQgcDJzaCAmIHNlZ3dpdCB0ZXN0JzogNDAwMDAwMDAwIH0sXG4gICAgICAgIGJpdGdvRmVlOiB7XG4gICAgICAgICAgYW1vdW50OiA4MTc2MCxcbiAgICAgICAgICBhZGRyZXNzOiAnMk5EN2pRUjVpdGpHVGJoM0RLZ2JwWldTWTl1bmdEcndjd2InLFxuICAgICAgICB9LFxuICAgICAgICB1c2VQc2J0OiBmYWxzZSxcbiAgICAgIH0pKSBhcyBhbnk7XG4gICAgICB0cmFuc2FjdGlvbi50cmFuc2FjdGlvbkhleC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAyN2M3NWY4YjQwNjEyMTJlYzQ2NjllZjEwYzdhODVhNmJkOGI2NzdlNzRlY2ZmZWY3MmRmMWUzNWIwYWNlNTRmNjAxMDAwMDAwMDBmZmZmZmZmZjI0OWY0ZjNiODkxMTA1MjZlOWQ3MWYzMzY3OWM1MzAzZGJmMDBlZjQzZGFjOTBiODY3YWUyZjA0M2Y5YzQwYTQwMDAwMDAwMDAwZmZmZmZmZmYwMzAwODRkNzE3MDAwMDAwMDAyMDZhMWU0MjY5NzQ0NzZmMjA2ZDY5Nzg2NTY0MjA3MDMyNzM2ODIwMjYyMDczNjU2Nzc3Njk3NDIwNzQ2NTczNzRiMDhmZjkwMjAwMDAwMDAwMTdhOTE0ODE1M2U3YTM1NTA4MDg4YjZjZjU5OTIyNjc5MmM3ZGUyZGJmZjI1Mjg3NjAzZjAxMDAwMDAwMDAwMDE3YTkxNGQ5ZjdiZTQ3OTc1YzAzNmY5NDIyOGIwYmZkNzA3MDE5MTI3NThiYTk4NzAwMDAwMDAwJ1xuICAgICAgKTtcblxuICAgICAgLy8gYWRkIGZpcnN0IHNpZ25hdHVyZVxuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSB1c2VyS2V5cGFpcjtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZTEgPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkgYXMgYW55O1xuICAgICAgc2lnbmF0dXJlMS50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAwMDEwMjdjNzVmOGI0MDYxMjEyZWM0NjY5ZWYxMGM3YTg1YTZiZDhiNjc3ZTc0ZWNmZmVmNzJkZjFlMzViMGFjZTU0ZjYwMTAwMDAwMGI3MDA0ODMwNDUwMjIxMDBmZmM0NWQ5M2NiYWY0YzFjODUwZTIxZjI3N2M1YjMxMWQzZTM5NTdmMTMzODk1NWNiMTY1ZDcyYTc2OGEwNTRjMDIyMDUyMDIwNTkzYjM2NzgxZWVhMDBhOWY4ZGNiZWI3NjYwOGY5MjBjN2E5MzNhOTA4ODMxOGFiMmY3MGMxMWUxZDkwMTAwMDA0YzY5NTIyMTAzZGE5NWIyOGExM2FhMmQ0YmI0OTBkNzA2MjhlMmU1ZDkxMjQ2MWQzNzVmZWYzODFhYWRkODlkYzEyNTYyMjA3NTIxMDMxMjEyODdhNTEwYzVmMzJlOGJhNzJkMjQ3OWU5MGViNTJiYTQ0YTQ2NzE3M2RmMzM5ZmViMGZmMjE1ZjEwMGUzMjEwMjk3N2NkZmJlZTc2MDY2YWU3MzlkYjcyZDU1MzcxYWQ0OWRjNjcxMmZiOGYyZjNmNjliYjFhNGMyNDIyYjBiMWE1M2FlZmZmZmZmZmYyNDlmNGYzYjg5MTEwNTI2ZTlkNzFmMzM2NzljNTMwM2RiZjAwZWY0M2RhYzkwYjg2N2FlMmYwNDNmOWM0MGE0MDAwMDAwMDAyMzIyMDAyMDhiOTFhYTAzZWIwZjdmMzFlMzkxNzA4ODA4NDE2OGJhNTI4MmE5MTVlN2NkZTBhNWE5MzRiN2VhMDJlYjA1N2JmZmZmZmZmZjAzMDA4NGQ3MTcwMDAwMDAwMDIwNmExZTQyNjk3NDQ3NmYyMDZkNjk3ODY1NjQyMDcwMzI3MzY4MjAyNjIwNzM2NTY3Nzc2OTc0MjA3NDY1NzM3NGIwOGZmOTAyMDAwMDAwMDAxN2E5MTQ4MTUzZTdhMzU1MDgwODhiNmNmNTk5MjI2NzkyYzdkZTJkYmZmMjUyODc2MDNmMDEwMDAwMDAwMDAwMTdhOTE0ZDlmN2JlNDc5NzVjMDM2Zjk0MjI4YjBiZmQ3MDcwMTkxMjc1OGJhOTg3MDAwNTAwNDczMDQ0MDIyMDU4OThiZWU3MTE0NjdjMDlhNWUyMmUxZGNiMWExMWZjZTFhMGQ2ZWExMjlkOTExZjgxM2Y4N2M3ZDQ1ZTA2N2IwMjIwMmY2OWZiMTE4YmJmMGIwNzJlZDI2ZDcyY2Y4MDczZTdhY2Q2NmMyMDU0MTlhNGEwMGY4NmE3YmEwZjZlM2RkNjAxMDAwMDY5NTIyMTAzMDc4MDE4NmMwYmU1ZGYwZDJkNjJjZjU0Y2MyZjNkMmMwOTkxMWUzNzdhYTk1YjVmZTg3NWZhMzUyYWVkMGE1OTIxMDNmMzIzN2VkZDJkODcwMTBlOGZlOWY0M2YzNGU4YzYzZGU2Mzg0MjgzZGU5MDk3OTVkNjJhZjRkZGI0ZDU3OTU0MjEwMmFkMDNkZTU1MDRlZjk0N2U0ZTZlZTJmYTZiMTVkMTUwZDU1M2MyMTI3NWY0OWYyY2UyMzU5ZDlmZGVkYjlhZGU1M2FlMDAwMDAwMDAnXG4gICAgICApO1xuXG4gICAgICAvLyBhZGQgc2Vjb25kIHNpZ25hdHVyZVxuICAgICAgdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXggPSBzaWduYXR1cmUxLnR4O1xuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSBiYWNrdXBLZXlwYWlyO1xuICAgICAgdHJhbnNhY3Rpb24uZnVsbExvY2FsU2lnbmluZyA9IHRydWU7XG4gICAgICBjb25zdCBzaWduYXR1cmUyID0gKGF3YWl0IGZha2VQcm9kV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih0cmFuc2FjdGlvbikpIGFzIGFueTtcbiAgICAgIC8vIHRoaXMgdHJhbnNhY3Rpb24gaGFzIGFjdHVhbGx5IHdvcmtlZDogaHR0cHM6Ly90ZXN0bmV0LnNtYXJ0Yml0LmNvbS5hdS90eC9lMmY2OTZiY2JhOTFhMzc2YzM2YmI1MjVkZjhjMzY3OTM4ZjZlMmZkNjM0NGM5MDU4N2JmMTI4MDIwOTExMjRjXG4gICAgICAvLyBOb3RlIHRoYXQgdGhlIHR4IGhleCBiZWxvdyBubyBsb25nZXIgY29ycmVzcG9uZHMgdG8gdGhlIGFib3ZlIHRyYW5zYWN0aW9uIGJlY2F1c2Ugb3VyIGZlZSBlc3RpbWF0aW9uIGhhc1xuICAgICAgLy8gY2hhbmdlZCwgY2hhbmdpbmcgdGhlIG91dHB1dCBhbW91bnRzIGFuZCB0aHVzIHRoZSB0eCBoZXguXG4gICAgICBzaWduYXR1cmUyLnR4LnNob3VsZC5lcXVhbChcbiAgICAgICAgJzAxMDAwMDAwMDAwMTAyN2M3NWY4YjQwNjEyMTJlYzQ2NjllZjEwYzdhODVhNmJkOGI2NzdlNzRlY2ZmZWY3MmRmMWUzNWIwYWNlNTRmNjAxMDAwMDAwZmRmZjAwMDA0ODMwNDUwMjIxMDBmZmM0NWQ5M2NiYWY0YzFjODUwZTIxZjI3N2M1YjMxMWQzZTM5NTdmMTMzODk1NWNiMTY1ZDcyYTc2OGEwNTRjMDIyMDUyMDIwNTkzYjM2NzgxZWVhMDBhOWY4ZGNiZWI3NjYwOGY5MjBjN2E5MzNhOTA4ODMxOGFiMmY3MGMxMWUxZDkwMTQ4MzA0NTAyMjEwMDgyNTRkMTAwNDAxYTNhODMxZWQwMTllMTY2MmRiZDkwYjk2YzZjNDA3MmI4MWNlNjQwZDE1MmJjMjkyOTVjMTAwMjIwMTNmODZjNWFmNTcxNjIzNDk5OWE3YmQ2ZTk0ZmM4ZjQyOGY3Njk3Y2MzMTM4YjM2NDlkMGVjNGRkODY4MWJjNzAxMDA0YzY5NTIyMTAzZGE5NWIyOGExM2FhMmQ0YmI0OTBkNzA2MjhlMmU1ZDkxMjQ2MWQzNzVmZWYzODFhYWRkODlkYzEyNTYyMjA3NTIxMDMxMjEyODdhNTEwYzVmMzJlOGJhNzJkMjQ3OWU5MGViNTJiYTQ0YTQ2NzE3M2RmMzM5ZmViMGZmMjE1ZjEwMGUzMjEwMjk3N2NkZmJlZTc2MDY2YWU3MzlkYjcyZDU1MzcxYWQ0OWRjNjcxMmZiOGYyZjNmNjliYjFhNGMyNDIyYjBiMWE1M2FlZmZmZmZmZmYyNDlmNGYzYjg5MTEwNTI2ZTlkNzFmMzM2NzljNTMwM2RiZjAwZWY0M2RhYzkwYjg2N2FlMmYwNDNmOWM0MGE0MDAwMDAwMDAyMzIyMDAyMDhiOTFhYTAzZWIwZjdmMzFlMzkxNzA4ODA4NDE2OGJhNTI4MmE5MTVlN2NkZTBhNWE5MzRiN2VhMDJlYjA1N2JmZmZmZmZmZjAzMDA4NGQ3MTcwMDAwMDAwMDIwNmExZTQyNjk3NDQ3NmYyMDZkNjk3ODY1NjQyMDcwMzI3MzY4MjAyNjIwNzM2NTY3Nzc2OTc0MjA3NDY1NzM3NGIwOGZmOTAyMDAwMDAwMDAxN2E5MTQ4MTUzZTdhMzU1MDgwODhiNmNmNTk5MjI2NzkyYzdkZTJkYmZmMjUyODc2MDNmMDEwMDAwMDAwMDAwMTdhOTE0ZDlmN2JlNDc5NzVjMDM2Zjk0MjI4YjBiZmQ3MDcwMTkxMjc1OGJhOTg3MDAwNTAwNDczMDQ0MDIyMDU4OThiZWU3MTE0NjdjMDlhNWUyMmUxZGNiMWExMWZjZTFhMGQ2ZWExMjlkOTExZjgxM2Y4N2M3ZDQ1ZTA2N2IwMjIwMmY2OWZiMTE4YmJmMGIwNzJlZDI2ZDcyY2Y4MDczZTdhY2Q2NmMyMDU0MTlhNGEwMGY4NmE3YmEwZjZlM2RkNjAxNDczMDQ0MDIyMDc3MTNkNjcxYjQ1OTg5Njg4ZTI2NjVjMmIxMWFiN2U1ZWE4ZDU3ZWIxNGY5ZGEyMzNjMDk1ZGFiZTQ0MTMwOGQwMjIwNjk1MjFiNWFlYjA3MWIwN2E3MGE3MTk3YTBjMmJiYzQwYTIzYWU2M2EwNDE2MGNmMzYyNzI1MGM0YmE0YzQwZjAxMDA2OTUyMjEwMzA3ODAxODZjMGJlNWRmMGQyZDYyY2Y1NGNjMmYzZDJjMDk5MTFlMzc3YWE5NWI1ZmU4NzVmYTM1MmFlZDBhNTkyMTAzZjMyMzdlZGQyZDg3MDEwZThmZTlmNDNmMzRlOGM2M2RlNjM4NDI4M2RlOTA5Nzk1ZDYyYWY0ZGRiNGQ1Nzk1NDIxMDJhZDAzZGU1NTA0ZWY5NDdlNGU2ZWUyZmE2YjE1ZDE1MGQ1NTNjMjEyNzVmNDlmMmNlMjM1OWQ5ZmRlZGI5YWRlNTNhZTAwMDAwMDAwJ1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2VuZCB0byBiZWNoMzIgcmVjaXBpZW50JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcDJzaEFkZHJlc3MgPSBmYWtlV2FsbGV0LmdlbmVyYXRlQWRkcmVzcyh7IHBhdGg6ICcvMC8xNCcsIHNlZ3dpdDogZmFsc2UgfSk7XG4gICAgICBjb25zdCBzZWd3aXRBZGRyZXNzID0gZmFrZVdhbGxldC5nZW5lcmF0ZUFkZHJlc3MoeyBwYXRoOiAnLzEwLzE0Jywgc2Vnd2l0OiB0cnVlIH0pO1xuICAgICAgY29uc3QgcDJzaFVuc3BlbnQgPSB7XG4gICAgICAgIGFkZHJlc3NlczogWycyTjUzM2ZxZ3lQWUtWRDg5Mm5CUmFZbUZIYmJUeWtoWVNFdyddLFxuICAgICAgICB2YWx1ZTogJzIuOTk5OTY2MTAnLFxuICAgICAgICB2YWx1ZV9pbnQ6IDI5OTk5NjYxMCxcbiAgICAgICAgdHhpZDogJ2Y2NTRjZTBhNWJlM2YxMmRmN2ZlY2Y0ZWU3NzdiNmQ4NmI1YWE4YzcxMGVmNjk0NmVjMTIxMjA2YjRmODc1N2MnLFxuICAgICAgICBuOiAxLFxuICAgICAgICBzY3JpcHRfcHViX2tleToge1xuICAgICAgICAgIGFzbTogJ09QX0hBU0gxNjAgODE1M2U3YTM1NTA4MDg4YjZjZjU5OTIyNjc5MmM3ZGUyZGJmZjI1MiBPUF9FUVVBTCcsXG4gICAgICAgICAgaGV4OiAnYTkxNDgxNTNlN2EzNTUwODA4OGI2Y2Y1OTkyMjY3OTJjN2RlMmRiZmYyNTI4NycsXG4gICAgICAgIH0sXG4gICAgICAgIHJlcV9zaWdzOiAxLFxuICAgICAgICB0eXBlOiAnc2NyaXB0aGFzaCcsXG4gICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgIGlkOiA2MTMzMTI2MyxcbiAgICAgIH07XG4gICAgICBjb25zdCBzZWd3aXRVbnNwZW50ID0ge1xuICAgICAgICBhZGRyZXNzZXM6IFsnMk5CdHBYY0RydWYzelJ1dG1GNEFiQ01GTlFIWHNHTlA2a1QnXSxcbiAgICAgICAgdmFsdWU6ICcxLjUwMDAwMDAwJyxcbiAgICAgICAgdmFsdWVfaW50OiAxNTAwMDAwMDAsXG4gICAgICAgIHR4aWQ6ICdhNDQwOWMzZjA0MmZhZTY3Yjg5MGFjM2RmNDBlZjBkYjAzNTM5YzY3MzMxZmQ3ZTkyNjA1MTE4OTNiNGY5ZjI0JyxcbiAgICAgICAgbjogMCxcbiAgICAgICAgc2NyaXB0X3B1Yl9rZXk6IHtcbiAgICAgICAgICBhc206ICdPUF9IQVNIMTYwIGNjOGU3Y2JmNDgxMzg5ZDMxODNhNTkwYWNmYTZhYTY2ZWI5N2M4ZTEgT1BfRVFVQUwnLFxuICAgICAgICAgIGhleDogJ2E5MTRjYzhlN2NiZjQ4MTM4OWQzMTgzYTU5MGFjZmE2YWE2NmViOTdjOGUxODcnLFxuICAgICAgICB9LFxuICAgICAgICByZXFfc2lnczogMSxcbiAgICAgICAgdHlwZTogJ3NjcmlwdGhhc2gnLFxuICAgICAgICBjb25maXJtYXRpb25zOiAwLFxuICAgICAgICBpZDogNjEzMzA4ODIsXG4gICAgICB9O1xuICAgICAgY29uc3QgYWRkcmVzc2VzID0gW3Ayc2hBZGRyZXNzLCBzZWd3aXRBZGRyZXNzXTtcbiAgICAgIGNvbnN0IHVuc3BlbnRzID0gW3Ayc2hVbnNwZW50LCBzZWd3aXRVbnNwZW50XS5tYXAoKHVuc3BlbnQ6IGFueSwgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgYWRkcmVzcyA9IGFkZHJlc3Nlc1tpbmRleF07XG4gICAgICAgIF8uZXh0ZW5kKHVuc3BlbnQsIGFkZHJlc3MpO1xuICAgICAgICB1bnNwZW50LnZhbHVlID0gdW5zcGVudC52YWx1ZV9pbnQ7XG4gICAgICAgIHVuc3BlbnQudHhfaGFzaCA9IHVuc3BlbnQudHhpZDtcbiAgICAgICAgdW5zcGVudC50eF9vdXRwdXRfbiA9IHVuc3BlbnQubjtcbiAgICAgICAgdW5zcGVudC5zY3JpcHQgPSB1bnNwZW50Lm91dHB1dFNjcmlwdDtcbiAgICAgICAgcmV0dXJuIHVuc3BlbnQ7XG4gICAgICB9KTtcblxuICAgICAgY29uc3QgdHJhbnNhY3Rpb24gPSAoYXdhaXQgZmFrZVdhbGxldC5jcmVhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgIGNoYW5nZUFkZHJlc3M6IHAyc2hBZGRyZXNzLmFkZHJlc3MsXG4gICAgICAgIHVuc3BlbnRzOiB1bnNwZW50cyxcbiAgICAgICAgcmVjaXBpZW50czogeyB0YjFxZ3V6eWs0dzZrYXF0cHNjenM1YWowdzhyNzU5OGpxMzZlZ204ZTk4d3FwaDNyd21leDY4c2VzbGdzZzogMzAwMDAwIH0sXG4gICAgICAgIG5vU3BsaXRDaGFuZ2U6IHRydWUsXG4gICAgICAgIGZvcmNlQ2hhbmdlQXRFbmQ6IHRydWUsXG4gICAgICAgIGZlZVJhdGU6IDEwMDAwLFxuICAgICAgICBvcFJldHVybnM6IHsgJ0JpdEdvIG1peGVkIHAyc2ggJiBzZWd3aXQgdGVzdCc6IDQwMDAwMDAwMCB9LFxuICAgICAgICBiaXRnb0ZlZToge1xuICAgICAgICAgIGFtb3VudDogODE3NjAsXG4gICAgICAgICAgYWRkcmVzczogJzJORDdqUVI1aXRqR1RiaDNES2dicFpXU1k5dW5nRHJ3Y3diJyxcbiAgICAgICAgfSxcbiAgICAgICAgdXNlUHNidDogZmFsc2UsXG4gICAgICB9KSkgYXMgYW55O1xuICAgICAgdHJhbnNhY3Rpb24udHJhbnNhY3Rpb25IZXguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMjdjNzVmOGI0MDYxMjEyZWM0NjY5ZWYxMGM3YTg1YTZiZDhiNjc3ZTc0ZWNmZmVmNzJkZjFlMzViMGFjZTU0ZjYwMTAwMDAwMDAwZmZmZmZmZmYyNDlmNGYzYjg5MTEwNTI2ZTlkNzFmMzM2NzljNTMwM2RiZjAwZWY0M2RhYzkwYjg2N2FlMmYwNDNmOWM0MGE0MDAwMDAwMDAwMGZmZmZmZmZmMDRlMDkzMDQwMDAwMDAwMDAwMjIwMDIwNDcwNDRiNTVkYWI3NDBiMGMzMDI4NTNiMjdiOGUzZjUwYTc5MDIzYWNhMzY3Yzk0ZWUwMDZmMTFiYjc5MzY4ZjAwODRkNzE3MDAwMDAwMDAyMDZhMWU0MjY5NzQ0NzZmMjA2ZDY5Nzg2NTY0MjA3MDMyNzM2ODIwMjYyMDczNjU2Nzc3Njk3NDIwNzQ2NTczNzQ3Y2ZhZjQwMjAwMDAwMDAwMTdhOTE0ODE1M2U3YTM1NTA4MDg4YjZjZjU5OTIyNjc5MmM3ZGUyZGJmZjI1Mjg3NjAzZjAxMDAwMDAwMDAwMDE3YTkxNGQ5ZjdiZTQ3OTc1YzAzNmY5NDIyOGIwYmZkNzA3MDE5MTI3NThiYTk4NzAwMDAwMDAwJ1xuICAgICAgKTtcblxuICAgICAgLy8gYWRkIGZpcnN0IHNpZ25hdHVyZVxuICAgICAgdHJhbnNhY3Rpb24ua2V5Y2hhaW4gPSB1c2VyS2V5cGFpcjtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZTEgPSAoYXdhaXQgZmFrZVByb2RXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHRyYW5zYWN0aW9uKSkgYXMgYW55O1xuICAgICAgc2lnbmF0dXJlMS50eC5zaG91bGQuZXF1YWwoXG4gICAgICAgICcwMTAwMDAwMDAwMDEwMjdjNzVmOGI0MDYxMjEyZWM0NjY5ZWYxMGM3YTg1YTZiZDhiNjc3ZTc0ZWNmZmVmNzJkZjFlMzViMGFjZTU0ZjYwMTAwMDAwMGI3MDA0ODMwNDUwMjIxMDA4ODA5Mzc3NjM0ZTY2N2Q2ZTE5ZjM4YTEzOGE1NWIyYjYzNzAzMTJhZjc2YTVjYTNiNzc2ZGY2MWZjNzE5NjE3MDIyMDIxZDkwMzQ3YjkwODVhYjcxYTc2Yzg0MDBmOTg0ZTMyMmMxNTQ1MWVjYzY3M2RkMzdkZTMwODg3NDM2ZDM3YjQwMTAwMDA0YzY5NTIyMTAzZGE5NWIyOGExM2FhMmQ0YmI0OTBkNzA2MjhlMmU1ZDkxMjQ2MWQzNzVmZWYzODFhYWRkODlkYzEyNTYyMjA3NTIxMDMxMjEyODdhNTEwYzVmMzJlOGJhNzJkMjQ3OWU5MGViNTJiYTQ0YTQ2NzE3M2RmMzM5ZmViMGZmMjE1ZjEwMGUzMjEwMjk3N2NkZmJlZTc2MDY2YWU3MzlkYjcyZDU1MzcxYWQ0OWRjNjcxMmZiOGYyZjNmNjliYjFhNGMyNDIyYjBiMWE1M2FlZmZmZmZmZmYyNDlmNGYzYjg5MTEwNTI2ZTlkNzFmMzM2NzljNTMwM2RiZjAwZWY0M2RhYzkwYjg2N2FlMmYwNDNmOWM0MGE0MDAwMDAwMDAyMzIyMDAyMDhiOTFhYTAzZWIwZjdmMzFlMzkxNzA4ODA4NDE2OGJhNTI4MmE5MTVlN2NkZTBhNWE5MzRiN2VhMDJlYjA1N2JmZmZmZmZmZjA0ZTA5MzA0MDAwMDAwMDAwMDIyMDAyMDQ3MDQ0YjU1ZGFiNzQwYjBjMzAyODUzYjI3YjhlM2Y1MGE3OTAyM2FjYTM2N2M5NGVlMDA2ZjExYmI3OTM2OGYwMDg0ZDcxNzAwMDAwMDAwMjA2YTFlNDI2OTc0NDc2ZjIwNmQ2OTc4NjU2NDIwNzAzMjczNjgyMDI2MjA3MzY1Njc3NzY5NzQyMDc0NjU3Mzc0N2NmYWY0MDIwMDAwMDAwMDE3YTkxNDgxNTNlN2EzNTUwODA4OGI2Y2Y1OTkyMjY3OTJjN2RlMmRiZmYyNTI4NzYwM2YwMTAwMDAwMDAwMDAxN2E5MTRkOWY3YmU0Nzk3NWMwMzZmOTQyMjhiMGJmZDcwNzAxOTEyNzU4YmE5ODcwMDA1MDA0ODMwNDUwMjIxMDA4Yjk1YWM4M2U0NGM3MjdiNzlmZmJmNDU3MTE3MTkyNWQwNmY4ODNhMDVjMTIyYjNiMzNjMDU1ZjBiZmZhNzAxMDIyMDdiNWVlMzQxMmVhOGE1Y2VjNGE1YzM4NmYxYjQ2NGFiNjhkNTMxYzZjNjk3MDc3YmM0NjJjMDVlYjQ0YTI4MzIwMTAwMDA2OTUyMjEwMzA3ODAxODZjMGJlNWRmMGQyZDYyY2Y1NGNjMmYzZDJjMDk5MTFlMzc3YWE5NWI1ZmU4NzVmYTM1MmFlZDBhNTkyMTAzZjMyMzdlZGQyZDg3MDEwZThmZTlmNDNmMzRlOGM2M2RlNjM4NDI4M2RlOTA5Nzk1ZDYyYWY0ZGRiNGQ1Nzk1NDIxMDJhZDAzZGU1NTA0ZWY5NDdlNGU2ZWUyZmE2YjE1ZDE1MGQ1NTNjMjEyNzVmNDlmMmNlMjM1OWQ5ZmRlZGI5YWRlNTNhZTAwMDAwMDAwJ1xuICAgICAgKTtcblxuICAgICAgLy8gYWRkIHNlY29uZCBzaWduYXR1cmVcbiAgICAgIHRyYW5zYWN0aW9uLnRyYW5zYWN0aW9uSGV4ID0gc2lnbmF0dXJlMS50eDtcbiAgICAgIHRyYW5zYWN0aW9uLmtleWNoYWluID0gYmFja3VwS2V5cGFpcjtcbiAgICAgIHRyYW5zYWN0aW9uLmZ1bGxMb2NhbFNpZ25pbmcgPSB0cnVlO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlMiA9IChhd2FpdCBmYWtlUHJvZFdhbGxldC5zaWduVHJhbnNhY3Rpb24odHJhbnNhY3Rpb24pKSBhcyBhbnk7XG4gICAgICBjb25zb2xlLmxvZygnc2lnbmF0dXJlMSAnICsgSlNPTi5zdHJpbmdpZnkoc2lnbmF0dXJlMikpO1xuICAgICAgLy8gdGhpcyB0cmFuc2FjdGlvbiBoYXMgYWN0dWFsbHkgd29ya2VkOiBodHRwczovL3Rlc3RuZXQuc21hcnRiaXQuY29tLmF1L3R4L2UyZjY5NmJjYmE5MWEzNzZjMzZiYjUyNWRmOGMzNjc5MzhmNmUyZmQ2MzQ0YzkwNTg3YmYxMjgwMjA5MTEyNGNcbiAgICAgIC8vIE5vdGUgdGhhdCB0aGUgdHggaGV4IGJlbG93IG5vIGxvbmdlciBjb3JyZXNwb25kcyB0byB0aGUgYWJvdmUgdHJhbnNhY3Rpb24gYmVjYXVzZSBvdXIgZmVlIGVzdGltYXRpb24gaGFzXG4gICAgICAvLyBjaGFuZ2VkLCBjaGFuZ2luZyB0aGUgb3V0cHV0IGFtb3VudHMgYW5kIHRodXMgdGhlIHR4IGhleC5cbiAgICAgIHNpZ25hdHVyZTIudHguc2hvdWxkLmVxdWFsKFxuICAgICAgICAnMDEwMDAwMDAwMDAxMDI3Yzc1ZjhiNDA2MTIxMmVjNDY2OWVmMTBjN2E4NWE2YmQ4YjY3N2U3NGVjZmZlZjcyZGYxZTM1YjBhY2U1NGY2MDEwMDAwMDBmZGZlMDAwMDQ4MzA0NTAyMjEwMDg4MDkzNzc2MzRlNjY3ZDZlMTlmMzhhMTM4YTU1YjJiNjM3MDMxMmFmNzZhNWNhM2I3NzZkZjYxZmM3MTk2MTcwMjIwMjFkOTAzNDdiOTA4NWFiNzFhNzZjODQwMGY5ODRlMzIyYzE1NDUxZWNjNjczZGQzN2RlMzA4ODc0MzZkMzdiNDAxNDczMDQ0MDIyMDVhNThlNjAyMDQyYjhlOGE1ZGE1MDlkMTljZTMxMDUwMTQ3ZGQwZmZjZmJlMmJiMzM3YzIzZDRjODhmNGNjNDEwMjIwNzViZmE0NTVkMWY3NGUzMGZiZDljNzg2Y2Q0ODExYTFkZWZlNTQzMTBmMjM1YjQxOTNjZTRmZmEwZTgzMDlhMTAxMDA0YzY5NTIyMTAzZGE5NWIyOGExM2FhMmQ0YmI0OTBkNzA2MjhlMmU1ZDkxMjQ2MWQzNzVmZWYzODFhYWRkODlkYzEyNTYyMjA3NTIxMDMxMjEyODdhNTEwYzVmMzJlOGJhNzJkMjQ3OWU5MGViNTJiYTQ0YTQ2NzE3M2RmMzM5ZmViMGZmMjE1ZjEwMGUzMjEwMjk3N2NkZmJlZTc2MDY2YWU3MzlkYjcyZDU1MzcxYWQ0OWRjNjcxMmZiOGYyZjNmNjliYjFhNGMyNDIyYjBiMWE1M2FlZmZmZmZmZmYyNDlmNGYzYjg5MTEwNTI2ZTlkNzFmMzM2NzljNTMwM2RiZjAwZWY0M2RhYzkwYjg2N2FlMmYwNDNmOWM0MGE0MDAwMDAwMDAyMzIyMDAyMDhiOTFhYTAzZWIwZjdmMzFlMzkxNzA4ODA4NDE2OGJhNTI4MmE5MTVlN2NkZTBhNWE5MzRiN2VhMDJlYjA1N2JmZmZmZmZmZjA0ZTA5MzA0MDAwMDAwMDAwMDIyMDAyMDQ3MDQ0YjU1ZGFiNzQwYjBjMzAyODUzYjI3YjhlM2Y1MGE3OTAyM2FjYTM2N2M5NGVlMDA2ZjExYmI3OTM2OGYwMDg0ZDcxNzAwMDAwMDAwMjA2YTFlNDI2OTc0NDc2ZjIwNmQ2OTc4NjU2NDIwNzAzMjczNjgyMDI2MjA3MzY1Njc3NzY5NzQyMDc0NjU3Mzc0N2NmYWY0MDIwMDAwMDAwMDE3YTkxNDgxNTNlN2EzNTUwODA4OGI2Y2Y1OTkyMjY3OTJjN2RlMmRiZmYyNTI4NzYwM2YwMTAwMDAwMDAwMDAxN2E5MTRkOWY3YmU0Nzk3NWMwMzZmOTQyMjhiMGJmZDcwNzAxOTEyNzU4YmE5ODcwMDA1MDA0ODMwNDUwMjIxMDA4Yjk1YWM4M2U0NGM3MjdiNzlmZmJmNDU3MTE3MTkyNWQwNmY4ODNhMDVjMTIyYjNiMzNjMDU1ZjBiZmZhNzAxMDIyMDdiNWVlMzQxMmVhOGE1Y2VjNGE1YzM4NmYxYjQ2NGFiNjhkNTMxYzZjNjk3MDc3YmM0NjJjMDVlYjQ0YTI4MzIwMTQ3MzA0NDAyMjA1MzY5MDIzNDU4MmE2OTExYTI4Y2FlOWY1MzRjOTgwYjdkNzkxODc0OWE3NDEzYzFjNTkzMjdkZWJmMTZmZjBiMDIyMDU2MTc1ZjVjMjdhMzYzNDE2YjJjZTQ3OTFhZWZjM2Q1NTU0NWNhY2JkMDUyNzIwMmU4NjllMTEyN2ZjMmYyNGQwMTAwNjk1MjIxMDMwNzgwMTg2YzBiZTVkZjBkMmQ2MmNmNTRjYzJmM2QyYzA5OTExZTM3N2FhOTViNWZlODc1ZmEzNTJhZWQwYTU5MjEwM2YzMjM3ZWRkMmQ4NzAxMGU4ZmU5ZjQzZjM0ZThjNjNkZTYzODQyODNkZTkwOTc5NWQ2MmFmNGRkYjRkNTc5NTQyMTAyYWQwM2RlNTUwNGVmOTQ3ZTRlNmVlMmZhNmIxNWQxNTBkNTUzYzIxMjc1ZjQ5ZjJjZTIzNTlkOWZkZWRiOWFkZTUzYWUwMDAwMDAwMCdcbiAgICAgICk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdTZW5kIE1hbnknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Jlc3BvbmRzIHdpdGggcHJvcGVyIGZlZSBhbmQgZmVlIHJhdGUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiAnMk11dHBYVllzOEx5azc0cFZEbjNlQUc3eG5LNFdjMmtqVFEnLFxuICAgICAgICAgICAgYW1vdW50OiAzMDAwMDAsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgICBjb25zdCB1bnNwZW50cyA9IFtcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlOiA4MTcwLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgdmFsdWU6IDgwMDAwMCxcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgICBjb25zdCBjcmVhdGVBbmRTaWduUmVzcG9uc2UgPSB7XG4gICAgICAgIGJpdGdvRmVlOiAwLFxuICAgICAgICB0cmF2ZWxJbmZvczogW10sXG4gICAgICAgIHVuc3BlbnRzLFxuICAgICAgICB0eDogJ2hhbGZzaWduZWRoZXgnLFxuICAgICAgfTtcbiAgICAgIHNpbm9uLnN0dWIoZmFrZVdhbGxldCwgJ2NyZWF0ZUFuZFNpZ25UcmFuc2FjdGlvbicpLnJldHVybnMoUHJvbWlzZS5yZXNvbHZlKGNyZWF0ZUFuZFNpZ25SZXNwb25zZSkpO1xuICAgICAgY29uc3QgZ2V0U2VuZFR4UmVzcG9uc2UgPSAoKSA9PiAoe1xuICAgICAgICBzdGF0dXM6ICdhY2NlcHRlZCcsXG4gICAgICAgIHR4OiAnMDEwMDAwMDAwMDAxMDIyOGI1YzNlMjc4OWQ0NzcwZmMzOTdlYzc5ZmE3MjU1Zjg2MjM1Mjk3YzVhMDRkZWY2NzhiNDgxYjhiMDllODFiMDEwMDAwMDAyMzIyMDAyMGIzYmJlMDY3OTYwYmUzOTUwMWYzNjViODk5OWQ1M2YyYTgyODVkOGQ5ODM2ZjYxZmFkMDIwZTZhNGE5ZTI2ZmRmZmZmZmZmZjE1MTBlOTA0MTFhODZjNDlmMmE1MjU0NmEzMmEwM2ZlYmRlMmJjNjA0NzQxZjBlODVkYzQ3YWRlYzMzZjUxNTkwMDAwMDAwMGZkZmQwMDAwNDgzMDQ1MDIyMTAwYTQ0YmJmOTdiMTU1YzU3NzAzODYyYmU2OWQyYjIwYzRiMmFiOWU5NGY0MDI1OTU4ODBiZjc0NDAyY2NjODdlMjAyMjAwYTRhYWY5OGY5MzliNjVjOThjYTA4ZWI5NjA3NGMyMjJlY2IxZmMzN2UzNTliMWQ2N2EwNWYxYzU2ZGVkZmMwMDE0NzMwNDQwMjIwMDNmMzk4OWExNDI4NGYxMzJiYmI1NTAxMThjMjAyNTZkNGVhNzM3NzA0MTIzYTI5OTU1YWNjMWQwM2VhNmViNzAyMjAxNzIyM2RhN2VkY2Y3MzA3NmQ4OTg3NWFhMzMzNjBhYTZhMTIxNDE4MDdmNjgzYzZjMWI5YTVhMGQzZmY2MDE5MDE0YzY5NTIyMTAyNTc4OTg1N2NjOGJlMTEwZmY0Y2JmMzU0YjUyZGQwZTdlOTMyNmM2YmZlMGFlZTZjMzBjMWVlNjk2NjBjM2RjMDIxMDJmNThmMWIxNTE2ZDA1ODE0YWU2ODhjYTcwMTg1NjY5NWUyNzA1MGUzZTE2ZDNhMjM1MTI4NGQ3YWY4NDQ5ODg4MjEwMjM4NWM3YmNlYzNmMzhjMTNlODdiNTU4YWViZjJmMjBhODkyOGU3ZWNiZTExZTdjM2E0Nzc5MmJjOGUzM2ZlODg1M2FlZmZmZmZmZmYwMmUwOTMwNDAwMDAwMDAwMDAxN2E5MTQxZDBjNzkxY2VjM2FmMWYzNzgwOGQ0MmYwNDU5MzA5NWQ2ZmRlYTI2ODcwNWJjMDcwMDAwMDAwMDAwMTdhOTE0ZDhjNzIwZjY0NmM3YzU2YzU0NjcyNDhlNDdjNzJkYzBiMmQzMGJiYzg3MDQwMDQ3MzA0NDAyMjAxZWFhMTM1OWZmZmQzYmRlYzViNDgyNjhiZDJmMTUxOTNhMjk5YzIyYjE5NzAzNTZmMzkwODgzNDczMzI0NjUxMDIyMDc0MTg2MjMyZjAyMjQ1YWY5YzA5NzcwMzE0NDhjMmM5OWU3YjdlMmIwNWIyYmE0YjMyYzMyMjdkOGNhMTQ5NGUwMTQ4MzA0NTAyMjEwMGJkNjFiMzcwNTFjMjg1MzNlYTBiMDBkZGE3NWIxYzRmMWRlZTFiNjgzYmI3MzUxYjJkOGRkNzIwZjZkZmJlMTEwMjIwM2FjYzRjZjlkMmRkNDRiMjk0YWEyNTgxMmU5OWU3ZDhlYjM3MzBlNGZmNmY4ODlkM2NkY2Q1MjUxOTU3NTBiODAxNjk1MjIxMDIxOWQwOTNjMThjMjdjYjU0NzczN2I0YTQ5ZGRkYWM5YzM0MTJiMTBlOWY4ODBlYjMwMDUzYzNlYmE4MTkyODU0MjEwMzc0NzExODg5MmNhYzFiNGRhMTE1MjZmYzRlYmVlYmUxNjhkYWUwOTA3Y2VmYjFhMTgxMjU0MWNkNDZiMDc2MDIyMTAzMzlmNzNiNjc1MGY4ZjkxZWZkNDg0YjVhYTI5NzQzMjFhNmNjMjc3NmQ1YmQ3OGI5Y2ZiNWZlMThlM2IyZDY2MjUzYWUwMDVhOWUxNjAwJyxcbiAgICAgICAgaGFzaDogJ2Y4ZGY0M2MyYzY1MGIzYmIxMTI3N2FlZTQ1MzFkYjk5YTcxNWZhM2I5ZGZkM2Q0NWE4ZDE3MTM0MmMxYmY3ODAnLFxuICAgICAgICBpbnN0YW50OiBmYWxzZSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZXhwZWN0ZWRSZXN1bHQgPSBPYmplY3QuYXNzaWduKFxuICAgICAgICB7XG4gICAgICAgICAgZmVlOiAxMjg1LFxuICAgICAgICAgIGZlZVJhdGU6IDI1MTkuNjA3ODQzMTM3MjU1LFxuICAgICAgICB9LFxuICAgICAgICBnZXRTZW5kVHhSZXNwb25zZSgpXG4gICAgICApO1xuICAgICAgc2lub24uc3R1YihmYWtlV2FsbGV0LCAnc2VuZFRyYW5zYWN0aW9uJykucmVzb2x2ZXMoZ2V0U2VuZFR4UmVzcG9uc2UoKSk7XG4gICAgICBjb25zdCByZXN1bHQgPSAoYXdhaXQgZmFrZVdhbGxldC5zZW5kTWFueShwYXJhbXMpKSBhcyBhbnk7XG4gICAgICByZXN1bHQudHguc2hvdWxkLmVxdWFsKGV4cGVjdGVkUmVzdWx0LnR4KTtcbiAgICAgIHJlc3VsdC5mZWUuc2hvdWxkLmVxdWFsKGV4cGVjdGVkUmVzdWx0LmZlZSk7XG4gICAgICByZXN1bHQuZmVlUmF0ZS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRSZXN1bHQuZmVlUmF0ZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdBY2NlbGVyYXRlIFRyYW5zYWN0aW9uIChzZXJ2ZXIgbW9ja2VkKScsIGZ1bmN0aW9uIGFjY2VsZXJhdGVUeE1vY2tlZERlc2NyaWJlKCkge1xuICAgIGxldCB3YWxsZXQ7XG4gICAgbGV0IGJnVXJsO1xuICAgIGxldCBleHBsb3JlclVybDtcbiAgICBsZXQgbWluQ2hhbmdlU2l6ZTtcblxuICAgIGxldCBwYXJlbnRUeElkID0gJzZhNzRiNzRkZjQ5OTFkOTNjMzJkNzUxMzM2Yzg1YjVmMmQxZWU1NDRhMmRmYmFlMmU1ZjRiZWI0ZjkxNGU1ZTAnO1xuICAgIGNvbnN0IG91dHB1dElkeCA9IDA7XG4gICAgY29uc3Qgb3V0cHV0QWRkcmVzcyA9ICcyTkNvU2ZISDZMczRDZFRTNVFhaGdDOWs3eDlSZlhlU3dZNCc7XG4gICAgY29uc3QgdW5yZWxhdGVkVHhJZCA9ICcwOGY1ZTBiNGFjYjVhYjgyNDUyMjlkZmUxNjFjZTRjYTBkYTFlYzk4M2U3YTM0YjA5ZTcyZjU2OTc5YTQ2N2RmJztcbiAgICBjb25zdCB3YWxsZXRJZCA9ICcyTkNvU2ZISDZMczRDZFRTNVFhaGdDOWs3eDlSZlhlU3dZNCc7XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gZ2V0IHRoZSBwYXJlbnQgdHJhbnNhY3Rpb24gSUQgZnJvbSBhIHRyYW5zYWN0aW9uIGlucHV0XG4gICAgICpcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGNvbnZlcnRzIGBoYXNoYCAod2hpY2ggaXMgYSBCdWZmZXIgb2JqZWN0KSB0byBhIHVzYWJsZSB0eGlkIHN0cmluZy5cbiAgICAgKiBUaGUgaXNzdWUgaXMgdGhhdCB0aGUgYnl0ZXMgYXJlIHN0b3JlZCBpbiByZXZlcnNlIG9yZGVyIGluIHRoZSBidWZmZXIsIHNvXG4gICAgICogdGhlIHNpbXBsZSBhcHByb2FjaCBvZiBqdXN0IGNvbXBhcmluZyB0aGUgaGV4IHN0cmluZ3MgZG9lc24ndCB3b3JrLlxuICAgICAqIEluc3RlYWQsIHRoZSBCdWZmZXIgaXMgY29waWVkIHRvIGEgbmV3IEJ1ZmZlciBvYmplY3QsIHRoZSBuZXcgQnVmZmVyXG4gICAgICogb2JqZWN0IGlzIHJldmVyc2VkIGluLXBsYWNlLCBhbmQgdGhlbiB0aGUgbmV3IEJ1ZmZlciBpcyBjb252ZXJ0ZWQgdG8gYVxuICAgICAqIGhleCBzdHJpbmcuIEFmdGVyIHRoaXMsIHRoZSByZXN1bHQgaXMgYSBoZXggc3RyaW5nIHdoaWNoIGlzIHRoZSBwYXJlbnQgdHhpZFxuICAgICAqXG4gICAgICogQHBhcmFtIGhhc2ggYSBiaXRjb2luanMtbGliIHRyYW5zYWN0aW9uIG9iamVjdCdzIGlucHV0IGhhc2hcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbnB1dFBhcmVudFR4SWQoeyBoYXNoIH0pOiBzdHJpbmcge1xuICAgICAgcmV0dXJuIChCdWZmZXIuZnJvbShoYXNoKS5yZXZlcnNlKCkgYXMgQnVmZmVyKS50b1N0cmluZygnaGV4Jyk7XG4gICAgfVxuXG4gICAgYmVmb3JlKGZ1bmN0aW9uIGFjY2VsZXJhdGVUeE1vY2tlZEJlZm9yZSgpIHtcbiAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG5cbiAgICAgIGJpdGdvID0gbmV3IEJpdEdvQVBJKHsgZW52OiAnbW9jaycsIGNsaWVudENvbnN0YW50czogeyBjb25zdGFudHM6IHt9IH0gfSk7XG4gICAgICAvLyBiaXRnby5pbml0aWFsaXplVGVzdFZhcnMoKTtcbiAgICAgIGJpdGdvLnNldFZhbGlkYXRlKGZhbHNlKTtcbiAgICAgIHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIHsgaWQ6IHdhbGxldElkLCBwcml2YXRlOiB7IGtleWNoYWluczogW3VzZXJLZXlwYWlyLCBiYWNrdXBLZXlwYWlyLCBiaXRnb0tleV0gfSB9KTtcbiAgICAgICh3YWxsZXQgYXMgYW55KS5iaXRnbyA9IGJpdGdvO1xuICAgICAgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG4gICAgICBleHBsb3JlclVybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbYml0Z28uZ2V0RW52KCldLmJ0Y0V4cGxvcmVyQmFzZVVybDtcblxuICAgICAgLy8gdHJ5IHRvIGdldCB0aGUgbWluIGNoYW5nZSBzaXplIGZyb20gdGhlIHNlcnZlciwgb3RoZXJ3aXNlIGRlZmF1bHQgdG8gMC4xIEJUQ1xuICAgICAgLy8gVE9ETzogbWluQ2hhbmdlU2l6ZSBpcyBub3QgY3VycmVudGx5IGEgY29uc3RhbnQgZGVmaW5lZCBvbiB0aGUgY2xpZW50IGFuZCBzaG91bGQgYmUgYWRkZWRcbiAgICAgIG1pbkNoYW5nZVNpemUgPSAxZTc7XG4gICAgfSk7XG5cbiAgICBhZnRlcihmdW5jdGlvbiBhY2NlbGVyYXRlVHhNb2NrZWRBZnRlcigpIHtcbiAgICAgIC8vIG1ha2Ugc3VyZSBhbGwgbm9ja3MgYXJlIGNsZWFyZWQgb3IgY29uc3VtZWQgYWZ0ZXIgdGhlIHRlc3RzIGFyZSBjb21wbGV0ZVxuICAgICAgbm9jay5wZW5kaW5nTW9ja3MoKS5zaG91bGQuYmUuZW1wdHkoKTtcbiAgICB9KTtcblxuICAgIGl0KCdhcmd1bWVudHMnLCBhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB3YWxsZXQuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgZmVlUmF0ZTogMTIzIH0pLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL15NaXNzaW5nIHBhcmFtZXRlcjogdHJhbnNhY3Rpb25JRCQvKTtcblxuICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgIC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyB0cmFuc2FjdGlvbklEOiAxMjMsIGZlZVJhdGU6IDEyMyB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvXkV4cGVjdGluZyBwYXJhbWV0ZXIgc3RyaW5nOiB0cmFuc2FjdGlvbklEIGJ1dCBmb3VuZCBudW1iZXIkLyk7XG5cbiAgICAgIGF3YWl0IHdhbGxldFxuICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogJzEyMycgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL15NaXNzaW5nIHBhcmFtZXRlcjogZmVlUmF0ZSQvKTtcblxuICAgICAgY29uc3QgZmVlUmF0ZXNQYXJhbXMgPSBbJzEyMycsIDAsIC0xMCwgLUluZmluaXR5LCBJbmZpbml0eSwgTmFOXTtcbiAgICAgIGZvciAoY29uc3QgZmVlUmF0ZSBvZiBmZWVSYXRlc1BhcmFtcykge1xuICAgICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogJzEyMycsIGZlZVJhdGUgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvXkV4cGVjdGluZyBwb3NpdGl2ZSBmaW5pdGUgbnVtYmVyIGZvciBwYXJhbWV0ZXI6IGZlZVJhdGUkLyk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBkZXNjcmliZSgnYmFkIGlucHV0JywgZnVuY3Rpb24gYmFkSW5wdXREZXNjcmliZSgpIHtcbiAgICAgIGFmdGVyKCgpID0+IHtcbiAgICAgICAgLy8gbWFrZSBzdXJlIGFsbCBub2NrcyBhcmUgY2xlYXJlZCBvciBjb25zdW1lZCBhZnRlciB0aGUgdGVzdHMgYXJlIGNvbXBsZXRlXG4gICAgICAgIG5vY2sucGVuZGluZ01vY2tzKCkuc2hvdWxkLmJlLmVtcHR5KCk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ25vbiBleGlzdGVudCB0cmFuc2FjdGlvbiBJRCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoNDA0LCAndHJhbnNhY3Rpb24gbm90IGZvdW5kIG9uIHRoaXMgd2FsbGV0Jyk7XG5cbiAgICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgICAgLmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7IHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsIGZlZVJhdGU6IDEyMyB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9eNDA0XFxudHJhbnNhY3Rpb24gbm90IGZvdW5kIG9uIHRoaXMgd2FsbGV0JC8pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdjb25maXJtZWQgdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDYsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGF3YWl0IHdhbGxldFxuICAgICAgICAgIC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyB0cmFuc2FjdGlvbklEOiBwYXJlbnRUeElkLCBmZWVSYXRlOiAyMDAwIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL15UcmFuc2FjdGlvbiBbMC05YS1mXSsgaXMgYWxyZWFkeSBjb25maXJtZWQgYW5kIGNhbm5vdCBiZSBhY2NlbGVyYXRlZCQvKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnbm8gb3V0cHV0cyB0byB3YWxsZXQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWNjb3VudDogb3V0cHV0QWRkcmVzcyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTg5MDAwMCxcbiAgICAgICAgICAgICAgICB2b3V0OiAwLFxuICAgICAgICAgICAgICAgIGNoYWluOiAwLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgICAgLmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7IHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsIGZlZVJhdGU6IDIwMDAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAgIC9eVHJhbnNhY3Rpb24gWzAtOWEtZl0rIGNvbnRhaW5zIG5vIG91dHB1dHMgdG8gdGhpcyB3YWxsZXQsIGFuZCB0aHVzIGNhbm5vdCBiZSBhY2NlbGVyYXRlZCQvXG4gICAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICAvKlxuICAgICAgICogVGhpcyB0ZXN0IGNvdmVycyB0aGUgY2FzZSB3aGVyZSBhIGZhaWx1cmUgb2NjdXJzIGR1cmluZyB0aGUgcHJvY2VzcyBvZlxuICAgICAgICogY29udmVydGluZyBhbiBvdXRwdXQgZnJvbSB0aGUgcGFyZW50IHRyYW5zYWN0aW9uIGludG8gYW4gdW5zcGVudCB3aGljaFxuICAgICAgICogY2FuIGJlIHVzZWQgdG8gY2hhaW4gdGhlIGNoaWxkIHR4IHRvIHRoZSBwYXJlbnQuXG4gICAgICAgKlxuICAgICAgICogVGhpcyBzaG91bGQgbmV2ZXIgaGFwcGVuLCBidXQgaXQgaXMgcG9zc2libGUgKGZvciBleGFtcGxlLCBpbiB0aGUgY2FzZVxuICAgICAgICogb2YgYW4gYXR0ZW1wdGVkIGRvdWJsZSBzcGVuZCBvZiB0aGUgb3V0cHV0IGZyb20gdGhlIHBhcmVudCwgb3IgYSByYWNlXG4gICAgICAgKiBiZXR3ZWVuIGZpbmRpbmcgdGhlIHBhcmVudCBvdXRwdXQsIGFuZCByZXRyaWV2aW5nIHRoZSBjb3JyZXNwb25kaW5nIHVuc3BlbnQpLlxuICAgICAgICovXG4gICAgICBpdCgnY2Fubm90IGZpbmQgY29ycmVjdCB1bnNwZW50IHRvIHVzZScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhY2NvdW50OiBvdXRwdXRBZGRyZXNzLFxuICAgICAgICAgICAgICAgIHZhbHVlOiA1MCAqIDFlNCxcbiAgICAgICAgICAgICAgICB2b3V0OiBvdXRwdXRJZHgsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAwLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgICBoZXg6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICBmZWU6IDEwLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKS5xdWVyeSh0cnVlKS5yZXBseSgyMDAsIHtcbiAgICAgICAgICBjb3VudDogMCxcbiAgICAgICAgICB1bnNwZW50czogW10sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGF3YWl0IHdhbGxldFxuICAgICAgICAgIC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oeyB0cmFuc2FjdGlvbklEOiBwYXJlbnRUeElkLCBmZWVSYXRlOiAyMDAwIH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL15Db3VsZCBub3QgZmluZCB1bnNwZW50IG91dHB1dCBmcm9tIHBhcmVudCB0eCB0byB1c2UgYXMgY2hpbGQgaW5wdXQkLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ0RldGVjdHMgd2hlbiBhbiBpbmNvcnJlY3QgdHggaGV4IGlzIHJldHVybmVkIGJ5IHRoZSBleHRlcm5hbCBzZXJ2aWNlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4LyR7cGFyZW50VHhJZH1gKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFjY291bnQ6IG91dHB1dEFkZHJlc3MsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwLFxuICAgICAgICAgICAgICAgIHZvdXQ6IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY29uZmlybWF0aW9uczogMCxcbiAgICAgICAgICAgIGhleDogZml4dHVyZXNbcGFyZW50VHhJZF0sXG4gICAgICAgICAgICBmZWU6IDEwLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIGNvdW50OiAxLFxuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhleHBsb3JlclVybCkuZ2V0KGAvdHgvJHtwYXJlbnRUeElkfS9oZXhgKS5yZXBseSgyMDAsIGZpeHR1cmVzW3VucmVsYXRlZFR4SWRdKTtcblxuICAgICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCwgZmVlUmF0ZTogMjAwMCB9KVxuICAgICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKC9eRGVjb2RlZCB0cmFuc2FjdGlvbiBpZCBpcyBbMC05YS1mXSssIHdoaWNoIGRvZXMgbm90IG1hdGNoIGdpdmVuIHR4aWQgWzAtOWEtZl0rJC8pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdjYW5ub3QgY292ZXIgY2hpbGQgZmVlIHdpdGggb25lIHBhcmVudCBvdXRwdXQgYW5kIG9uZSB3YWxsZXQgdW5zcGVudCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhY2NvdW50OiBvdXRwdXRBZGRyZXNzLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMCxcbiAgICAgICAgICAgICAgICB2b3V0OiBvdXRwdXRJZHgsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAwLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgICBoZXg6IGZpeHR1cmVzW3BhcmVudFR4SWRdLFxuICAgICAgICAgICAgZmVlOiAxMCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBjb3VudDogMSxcbiAgICAgICAgICAgIHVuc3BlbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiBwYXJlbnRUeElkLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiBvdXRwdXRJZHgsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soZXhwbG9yZXJVcmwpLmdldChgL3R4LyR7cGFyZW50VHhJZH0vaGV4YCkucmVwbHkoMjAwLCBmaXh0dXJlc1twYXJlbnRUeElkXSk7XG5cbiAgICAgICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApLnF1ZXJ5KHRydWUpLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGNvdW50OiAwLFxuICAgICAgICAgIHVuc3BlbnRzOiBbXSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgICAgLmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7IHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsIGZlZVJhdGU6IDIwMDAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvXkluc3VmZmljaWVudCBjb25maXJtZWQgdW5zcGVudHMgYXZhaWxhYmxlIHRvIGNvdmVyIHRoZSBjaGlsZCBmZWUkLyk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2Nhbm5vdCBsb3dlciBmZWUgcmF0ZScsIGFzeW5jICgpID0+IHtcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhY2NvdW50OiBvdXRwdXRBZGRyZXNzLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMCxcbiAgICAgICAgICAgICAgICB2b3V0OiBvdXRwdXRJZHgsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxMSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBjb25maXJtYXRpb25zOiAwLFxuICAgICAgICAgICAgaGV4OiBmaXh0dXJlc1twYXJlbnRUeElkXSxcbiAgICAgICAgICAgIGZlZTogMTAwMDAsIC8vIGxhcmdlIGZlZSwgYW5kIHRodXMgZmVlIHJhdGUsIGZvciBwYXJlbnRcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBjb3VudDogMSxcbiAgICAgICAgICAgIHVuc3BlbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiBwYXJlbnRUeElkLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiBvdXRwdXRJZHgsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soZXhwbG9yZXJVcmwpLmdldChgL3R4LyR7cGFyZW50VHhJZH0vaGV4YCkucmVwbHkoMjAwLCBmaXh0dXJlc1twYXJlbnRUeElkXSk7XG5cbiAgICAgICAgYXdhaXQgd2FsbGV0XG4gICAgICAgICAgLmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7IHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsIGZlZVJhdGU6IDIwMDAgfSlcbiAgICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICAgIC9eQ2Fubm90IGxvd2VyIGZlZSByYXRlISBcXChQYXJlbnQgdHggZmVlIHJhdGUgaXMgXFxkK1xcLj9cXGQqIHNhdFxcL2tCLCBhbmQgcmVxdWVzdGVkIGZlZSByYXRlIHdhcyBcXGQrXFwuP1xcZCogc2F0XFwva0JcXCkkL1xuICAgICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ2Nhbm5vdCBicmVhayBtYXhpbXVtIGZlZSBsaW1pdCBmb3IgY29tYmluZWQgdHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWNjb3VudDogb3V0cHV0QWRkcmVzcyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogM2U3LFxuICAgICAgICAgICAgICAgIHZvdXQ6IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDExLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgICBoZXg6IGZpeHR1cmVzW3BhcmVudFR4SWRdLFxuICAgICAgICAgICAgZmVlOiAxMDAwLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIGNvdW50OiAxLFxuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IG91dHB1dElkeCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhleHBsb3JlclVybCkuZ2V0KGAvdHgvJHtwYXJlbnRUeElkfS9oZXhgKS5yZXBseSgyMDAsIGZpeHR1cmVzW3BhcmVudFR4SWRdKTtcblxuICAgICAgICBhd2FpdCB3YWxsZXRcbiAgICAgICAgICAuYWNjZWxlcmF0ZVRyYW5zYWN0aW9uKHsgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCwgZmVlUmF0ZTogMmU2IH0pXG4gICAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgICAvXlRyYW5zYWN0aW9uIGNhbm5vdCBiZSBhY2NlbGVyYXRlZFxcLiBDb21iaW5lZCBmZWUgcmF0ZSBvZiBcXGQrXFwuP1xcZCogc2F0XFwva0IgZXhjZWVkcyBtYXhpbXVtIGZlZSByYXRlIG9mIFxcZCtcXC4/XFxkKiBzYXRcXC9rQiQvXG4gICAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgZGVzY3JpYmUoJ3N1Y2Nlc3NmdWwgdHggYWNjZWxlcmF0aW9uJywgZnVuY3Rpb24gc3VjY2Vzc2Z1bFR4RGVzY3JpYmUoKSB7XG4gICAgICBjb25zdCBmZWVSYXRlID0gMjAwMDA7XG5cbiAgICAgIGJlZm9yZUVhY2goYXN5bmMgKCkgPT4ge1xuICAgICAgICBub2NrKGJnVXJsKS5wb3N0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS9hZGRyZXNzLzFgKS5yZXBseSgyMDAsIHtcbiAgICAgICAgICBhZGRyZXNzOiAnMk5DWWpHOFE1NnlyOHR4OWphek5vWW5HS3hqZ0IyTVFTZlknLFxuICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKS5wb3N0KCcvYXBpL3YxL2JpbGxpbmcvYWRkcmVzcycpLnJlcGx5KDIwMCwge1xuICAgICAgICAgIGFkZHJlc3M6ICcyTkZidm8ySEs0ZVhabTFhcURjU0RHR3FENjRGUHQ3VDZkOCcsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpLmdldCgnL2FwaS92MS90eC9mZWUnKS5xdWVyeSh0cnVlKS5yZXBseSgyMDAsIHtcbiAgICAgICAgICBmZWVQZXJLYjogMCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAucG9zdChgL2FwaS92MS9rZXljaGFpbi8ke3VzZXJLZXlwYWlyLnhwdWJ9YCwge30pXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgZW5jcnlwdGVkWHBydjogYXdhaXQgYml0Z28uZW5jcnlwdCh7IGlucHV0OiB1c2VyS2V5cGFpci54cHJ2LCBwYXNzd29yZDogVGVzdEJpdEdvLlRFU1RfV0FMTEVUMV9QQVNTQ09ERSB9KSxcbiAgICAgICAgICAgIHBhdGg6IHVzZXJLZXlwYWlyLnBhdGggKyB1c2VyS2V5cGFpci53YWxsZXRTdWJQYXRoLFxuICAgICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdhY2NlbGVyYXRlcyBhIHN0dWNrIHR4IHdpdGhvdXQgYWRkaXRpb25hbCB1bnNwZW50cycsIGFzeW5jICgpID0+IHtcbiAgICAgICAgcGFyZW50VHhJZCA9ICc3NWNmYzVhN2IyMTRjNGI3M2M5MmM3YjAyNjA4Y2RlNzBiMjI2NzY3YTk1NzZmODRjMDQ0MDdlNDNmZDM4NWJkJztcbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS90eC8ke3BhcmVudFR4SWR9YClcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICBmZWU6IDQzNCxcbiAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMzQ4NTAwLFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDEsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwLFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMTEsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIHVuc3BlbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiBwYXJlbnRUeElkLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMDM0ODUwMCxcbiAgICAgICAgICAgICAgICByZWRlZW1TY3JpcHQ6ICcwMDIwZjdiNThkNDU1MzUxYjdiOGRkZDdjODk4NmQ5ODI0NGY2YTk1ZjA3NDY3MjAwOTE1MzczMjNiOTY3ODAwZjc0NCcsXG4gICAgICAgICAgICAgICAgY2hhaW5QYXRoOiAnLzExLzE2MCcsXG4gICAgICAgICAgICAgICAgd2l0bmVzc1NjcmlwdDpcbiAgICAgICAgICAgICAgICAgICc1MjIxMDI3ZjBiNDViYjQxNTVlYTUzMmUzYjQzMTJmZTBiZTgwMTY2ZjI5N2QxZTA3NTNkMmQ0YTkxMThjMDczYWQ2NTE0MjEwMzEwYWE5ZDY4Yzk4ODMxNjI1ZjMyOWI3ODI2YjZjM2UzYjUzZTE2NzM2YjE5OTRiODkwMjQ0MmJkY2Q2NjUzZDEyMTAyNmUwY2E0MTRmMjQ4OGIwYWI1NzJiOTllMGFlNTQ0MjkxMWFiNGUwODIxYjI3MDlkODg1MTc1YTUyN2ZkNTUyYjUzYWUnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGV4cGxvcmVyVXJsKS5nZXQoYC90eC8ke3BhcmVudFR4SWR9L2hleGApLnJlcGx5KDIwMCwgZml4dHVyZXNbcGFyZW50VHhJZF0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjEvdHgvc2VuZCcsIChib2R5KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gIWJvZHkuaWdub3JlTWF4RmVlUmF0ZTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5yZXBseSgyMDAsIGZ1bmN0aW9uIChfLCBib2R5KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICB0cmFuc2FjdGlvbjogKGJvZHkgYXMgYW55KS50eCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgY2hpbGRUeCA9IGF3YWl0IHdhbGxldC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsXG4gICAgICAgICAgZmVlUmF0ZSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBUZXN0Qml0R28uVEVTVF9XQUxMRVQxX1BBU1NDT0RFLFxuICAgICAgICB9KTtcblxuICAgICAgICBzaG91bGQuZXhpc3QoY2hpbGRUeCk7XG4gICAgICAgIGNoaWxkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXR1cycsICdhY2NlcHRlZCcpO1xuICAgICAgICBjaGlsZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuXG4gICAgICAgIC8vIGFzc2VydCB0aGUgZm9sbG93aW5nOlxuICAgICAgICAvLyAwKSBUaGUgY2hpbGQgdHggaGFzIGV4YWN0bHkgb25lIGlucHV0XG4gICAgICAgIC8vIDEpIFRoZSBwYXJlbnQgdHggb3V0cHV0IGlzIGFuIGlucHV0XG4gICAgICAgIC8vIDIpIFRoZSBjaGlsZCB0eCBoYXMgZXhhY3RseSBvbmUgb3V0cHV0XG4gICAgICAgIC8vIDMpIFRoZSBjaGlsZCB0eCBvdXRwdXQgbWVldHMgdGhlIG1pbmltdW0gY2hhbmdlIHRocmVzaG9sZFxuICAgICAgICBjb25zdCBkZWNvZGVkQ2hpbGQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleChjaGlsZFR4LnR4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgICBkZWNvZGVkQ2hpbGQuaW5zLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG4gICAgICAgIGRlY29kZWRDaGlsZC5vdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgY29uc3QgY2hpbGRJbnB1dCA9IGRlY29kZWRDaGlsZC5pbnNbMF07XG4gICAgICAgIGNoaWxkSW5wdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2luZGV4JywgMCk7XG4gICAgICAgIGNoaWxkSW5wdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2hhc2gnKTtcblxuICAgICAgICBjb25zdCBpbnB1dFR4SWQgPSBpbnB1dFBhcmVudFR4SWQoY2hpbGRJbnB1dCk7XG4gICAgICAgIGlucHV0VHhJZC5zaG91bGQuZXF1YWwocGFyZW50VHhJZCk7XG5cbiAgICAgICAgY29uc3QgY2hpbGRPdXRwdXQgPSBkZWNvZGVkQ2hpbGQub3V0c1swXTtcbiAgICAgICAgY2hpbGRPdXRwdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbHVlJyk7XG4gICAgICAgIGNoaWxkT3V0cHV0LnZhbHVlLnNob3VsZC5iZS5hYm92ZShtaW5DaGFuZ2VTaXplKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnYWNjZWxlcmF0ZXMgYSBzdHVjayB0eCB3aXRoIG9uZSBhZGRpdGlvbmFsIHNlZ3dpdCB1bnNwZW50JywgYXN5bmMgKCkgPT4ge1xuICAgICAgICBwYXJlbnRUeElkID0gJzg4MTVmMjAyYzg2NTRiNmM4YjI5NTc0OTU0NWM3MTE4NzhjZDg0NWExNGNiMWVhOTgyMzk0ZDBjMTQ5NDVjMzMnO1xuICAgICAgICBjb25zdCBhZGRpdGlvbmFsVW5zcGVudFR4SWQgPSAnMDdkNmVlNTdiMDI0Y2UyYjYxMDhmNjc4NDc0NTRhMGE3OWE0ZmNmYjk4YWIyNTU1NTNhMjk5M2ExYTE3MGI4Nyc7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgZmVlOiAxMzM2LFxuICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdm91dDogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAwMDAsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxMSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDEsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDg2NjQsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApXG4gICAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwLFxuICAgICAgICAgICAgICAgIHJlZGVlbVNjcmlwdDpcbiAgICAgICAgICAgICAgICAgICc1MjIxMDJjZDNjOGU2MDA2YTQ2Mjc3MDUwMjFkMWQwMTZkMDk3YzI5NDRkOTgxMDBhNDdiZjJkYTY3YTVmZTE1YWVlYjM0MjEwMmVlMWZhOWU4MTJlNzc5MzU2YWEzYzMxZWJmMzE3ZDBjZmZlYmFiOTI4NjRjZmUzOGJhYjIyM2UwODIwZjk4YmMyMTAyNmJhMDU3NTJiYWE2ZWFmZDVjNTY1OWRhNjJiN2YwYWM1MWZkMjg4NmI2NWMyNDFkMGFmZWYxYzRmZGZhMWNiYzUzYWUnLFxuICAgICAgICAgICAgICAgIGNoYWluUGF0aDogJy8wLzAnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogYWRkaXRpb25hbFVuc3BlbnRUeElkLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxOTkzNTUyNixcbiAgICAgICAgICAgICAgICByZWRlZW1TY3JpcHQ6ICcwMDIwZDM0ZWY2ZGQzNGVmMmE0ZmJlYTY3YzU0MWMxYzc5Njc0OWE2MGFmZTRhOTdmZWU4ZWM3ZGVkMTg4YmQ3NDlkYScsXG4gICAgICAgICAgICAgICAgY2hhaW5QYXRoOiAnLzExLzE1NScsXG4gICAgICAgICAgICAgICAgd2l0bmVzc1NjcmlwdDpcbiAgICAgICAgICAgICAgICAgICc1MjIxMDIyMTlkMmFhODQxNzYzM2YwYmNlMzkxMTM3NGExNjA0YzFiNjQxNjFmODNhM2MyZWU0MDljMjdjNDIzNTVmMDhlMjEwMmM5NzM0OTIwZGM0ZGEwNmMyODlmZTY5MTcxZGZjZDc1ZTNiOWI0ZjE5MGQwY2JjM2Q1ZDBmZjNmNWZkZWVhYWUyMTAzY2NkNjhkN2ZhOGRjMGQwMmRkNDVkYWQxNjU1NTdhNDg1ODJlZGE0NDM1ZmFlNzM3N2IzYzMxZTA4YWQwNjVjOTUzYWUnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGV4cGxvcmVyVXJsKS5nZXQoYC90eC8ke3BhcmVudFR4SWR9L2hleGApLnJlcGx5KDIwMCwgZml4dHVyZXNbcGFyZW50VHhJZF0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLnBvc3QoJy9hcGkvdjEvdHgvc2VuZCcsIChib2R5KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gIWJvZHkuaWdub3JlTWF4RmVlUmF0ZTtcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5yZXBseSgyMDAsIGZ1bmN0aW9uIChfLCBib2R5KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICB0cmFuc2FjdGlvbjogKGJvZHkgYXMgYW55KS50eCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgY2hpbGRUeCA9IGF3YWl0IHdhbGxldC5hY2NlbGVyYXRlVHJhbnNhY3Rpb24oe1xuICAgICAgICAgIHRyYW5zYWN0aW9uSUQ6IHBhcmVudFR4SWQsXG4gICAgICAgICAgZmVlUmF0ZSxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBUZXN0Qml0R28uVEVTVF9XQUxMRVQxX1BBU1NDT0RFLFxuICAgICAgICB9KTtcblxuICAgICAgICBzaG91bGQuZXhpc3QoY2hpbGRUeCk7XG4gICAgICAgIGNoaWxkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3N0YXR1cycsICdhY2NlcHRlZCcpO1xuICAgICAgICBjaGlsZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eCcpO1xuXG4gICAgICAgIC8vIGFzc2VydCB0aGUgZm9sbG93aW5nOlxuICAgICAgICAvLyAwKSBUaGUgY2hpbGQgdHggaGFzIGV4YWN0bHkgdHdvIGlucHV0c1xuICAgICAgICAvLyAxKSBUaGUgcGFyZW50IHR4IG91dHB1dCBpcyBhbiBpbnB1dFxuICAgICAgICAvLyAyKSBUaGUgYWRkaXRpb25hbCB1bnNwZW50IG91dHB1dCBpcyBhbiBpbnB1dFxuICAgICAgICAvLyAzKSBUaGUgY2hpbGQgdHggaGFzIGV4YWN0bHkgb25lIG91dHB1dFxuICAgICAgICAvLyA0KSBUaGUgY2hpbGQgdHggb3V0cHV0IG1lZXRzIHRoZSBtaW5pbXVtIGNoYW5nZSB0aHJlc2hvbGRcbiAgICAgICAgY29uc3QgZGVjb2RlZENoaWxkID0gdXR4b2xpYi5iaXRnby5jcmVhdGVUcmFuc2FjdGlvbkZyb21IZXgoY2hpbGRUeC50eCwgdXR4b2xpYi5uZXR3b3Jrcy5iaXRjb2luKTtcbiAgICAgICAgZGVjb2RlZENoaWxkLmlucy5sZW5ndGguc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgICBkZWNvZGVkQ2hpbGQub3V0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuXG4gICAgICAgIGxldCBpbnB1dEZyb21QYXJlbnQ6IGFueSA9IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IGFkZGl0aW9uYWxJbnB1dDogYW55ID0gdW5kZWZpbmVkO1xuXG4gICAgICAgIF8uZm9yRWFjaChkZWNvZGVkQ2hpbGQuaW5zLCAoaW5wdXQpID0+IHtcbiAgICAgICAgICBpbnB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaGFzaCcpO1xuICAgICAgICAgIGlucHV0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdpbmRleCcpO1xuXG4gICAgICAgICAgY29uc3QgaW5wdXRUeElkID0gaW5wdXRQYXJlbnRUeElkKGlucHV0KTtcblxuICAgICAgICAgIGlmIChpbnB1dFR4SWQgPT09IHBhcmVudFR4SWQpIHtcbiAgICAgICAgICAgIGlucHV0RnJvbVBhcmVudCA9IGlucHV0O1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhZGRpdGlvbmFsSW5wdXQgPSBpbnB1dDtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNob3VsZC5leGlzdChpbnB1dEZyb21QYXJlbnQpO1xuICAgICAgICBjb25zdCBpbnB1dEZyb21QYXJlbnRIYXNoID0gaW5wdXRQYXJlbnRUeElkKGlucHV0RnJvbVBhcmVudCk7XG4gICAgICAgIGlucHV0RnJvbVBhcmVudEhhc2guc2hvdWxkLmVxdWFsKHBhcmVudFR4SWQpO1xuICAgICAgICBpbnB1dEZyb21QYXJlbnQuaW5kZXguc2hvdWxkLmVxdWFsKDApO1xuXG4gICAgICAgIHNob3VsZC5leGlzdChhZGRpdGlvbmFsSW5wdXQpO1xuICAgICAgICBjb25zdCBhZGRpdGlvbmFsSW5wdXRIYXNoID0gaW5wdXRQYXJlbnRUeElkKGFkZGl0aW9uYWxJbnB1dCk7XG4gICAgICAgIGFkZGl0aW9uYWxJbnB1dEhhc2guc2hvdWxkLmVxdWFsKGFkZGl0aW9uYWxVbnNwZW50VHhJZCk7XG4gICAgICAgIGFkZGl0aW9uYWxJbnB1dC5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgICAgY29uc3QgY2hpbGRPdXRwdXQgPSBkZWNvZGVkQ2hpbGQub3V0c1swXTtcbiAgICAgICAgY2hpbGRPdXRwdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbHVlJyk7XG4gICAgICAgIGNoaWxkT3V0cHV0LnZhbHVlLnNob3VsZC5iZS5hYm92ZShtaW5DaGFuZ2VTaXplKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnYWNjZWxlcmF0ZXMgYSBzdHVjayB0eCB3aXRoIG9uZSBhZGRpdGlvbmFsIFAyU0ggdW5zcGVudCcsIGFzeW5jICgpID0+IHtcbiAgICAgICAgcGFyZW50VHhJZCA9ICc4ODE1ZjIwMmM4NjU0YjZjOGIyOTU3NDk1NDVjNzExODc4Y2Q4NDVhMTRjYjFlYTk4MjM5NGQwYzE0OTQ1YzMzJztcbiAgICAgICAgY29uc3QgYWRkaXRpb25hbFVuc3BlbnRUeElkID0gJ2UxOTAzMTBmMmYzZjcxYWE4ODQ2ZjExNjFjYmNlMTUzM2MyNGE4NTdkZDI0ZTQ1MDFiMTMxZmViNDAwYWFkNTgnO1xuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3R4LyR7cGFyZW50VHhJZH1gKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIGZlZTogMTMzNixcbiAgICAgICAgICAgIG91dHB1dHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwLFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMTEsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2b3V0OiAxLFxuICAgICAgICAgICAgICAgIHZhbHVlOiA4NjY0LFxuICAgICAgICAgICAgICAgIGlzTWluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjaGFpbjogMSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBjb25maXJtYXRpb25zOiAwLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdW5zcGVudHNgKVxuICAgICAgICAgIC5xdWVyeSh0cnVlKVxuICAgICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICAgIHVuc3BlbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiBwYXJlbnRUeElkLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMDAwMCxcbiAgICAgICAgICAgICAgICByZWRlZW1TY3JpcHQ6XG4gICAgICAgICAgICAgICAgICAnNTIyMTAyY2QzYzhlNjAwNmE0NjI3NzA1MDIxZDFkMDE2ZDA5N2MyOTQ0ZDk4MTAwYTQ3YmYyZGE2N2E1ZmUxNWFlZWIzNDIxMDJlZTFmYTllODEyZTc3OTM1NmFhM2MzMWViZjMxN2QwY2ZmZWJhYjkyODY0Y2ZlMzhiYWIyMjNlMDgyMGY5OGJjMjEwMjZiYTA1NzUyYmFhNmVhZmQ1YzU2NTlkYTYyYjdmMGFjNTFmZDI4ODZiNjVjMjQxZDBhZmVmMWM0ZmRmYTFjYmM1M2FlJyxcbiAgICAgICAgICAgICAgICBjaGFpblBhdGg6ICcvMC8wJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApXG4gICAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IGFkZGl0aW9uYWxVbnNwZW50VHhJZCxcbiAgICAgICAgICAgICAgICB0eF9vdXRwdXRfbjogMSxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMjAwMDAwMDAsXG4gICAgICAgICAgICAgICAgcmVkZWVtU2NyaXB0OlxuICAgICAgICAgICAgICAgICAgJzUyMjEwMmNkM2M4ZTYwMDZhNDYyNzcwNTAyMWQxZDAxNmQwOTdjMjk0NGQ5ODEwMGE0N2JmMmRhNjdhNWZlMTVhZWViMzQyMTAyZWUxZmE5ZTgxMmU3NzkzNTZhYTNjMzFlYmYzMTdkMGNmZmViYWI5Mjg2NGNmZTM4YmFiMjIzZTA4MjBmOThiYzIxMDI2YmEwNTc1MmJhYTZlYWZkNWM1NjU5ZGE2MmI3ZjBhYzUxZmQyODg2YjY1YzI0MWQwYWZlZjFjNGZkZmExY2JjNTNhZScsXG4gICAgICAgICAgICAgICAgY2hhaW5QYXRoOiAnLzAvMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soZXhwbG9yZXJVcmwpLmdldChgL3R4LyR7cGFyZW50VHhJZH0vaGV4YCkucmVwbHkoMjAwLCBmaXh0dXJlc1twYXJlbnRUeElkXSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAucG9zdCgnL2FwaS92MS90eC9zZW5kJywgKGJvZHkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiAhYm9keS5pZ25vcmVNYXhGZWVSYXRlO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnJlcGx5KDIwMCwgZnVuY3Rpb24gKF8sIGJvZHkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHRyYW5zYWN0aW9uOiAoYm9keSBhcyBhbnkpLnR4LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBjaGlsZFR4ID0gYXdhaXQgd2FsbGV0LmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCxcbiAgICAgICAgICBmZWVSYXRlLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFRlc3RCaXRHby5URVNUX1dBTExFVDFfUEFTU0NPREUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNob3VsZC5leGlzdChjaGlsZFR4KTtcbiAgICAgICAgY2hpbGRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhdHVzJywgJ2FjY2VwdGVkJyk7XG4gICAgICAgIGNoaWxkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG5cbiAgICAgICAgLy8gYXNzZXJ0IHRoZSBmb2xsb3dpbmc6XG4gICAgICAgIC8vIDApIFRoZSBjaGlsZCB0eCBoYXMgZXhhY3RseSB0d28gaW5wdXRzXG4gICAgICAgIC8vIDEpIFRoZSBwYXJlbnQgdHggb3V0cHV0IGlzIGFuIGlucHV0XG4gICAgICAgIC8vIDIpIFRoZSBhZGRpdGlvbmFsIHVuc3BlbnQgb3V0cHV0IGlzIGFuIGlucHV0XG4gICAgICAgIC8vIDMpIFRoZSBjaGlsZCB0eCBoYXMgZXhhY3RseSBvbmUgb3V0cHV0XG4gICAgICAgIC8vIDQpIFRoZSBjaGlsZCB0eCBvdXRwdXQgbWVldHMgdGhlIG1pbmltdW0gY2hhbmdlIHRocmVzaG9sZFxuICAgICAgICBjb25zdCBkZWNvZGVkQ2hpbGQgPSB1dHhvbGliLmJpdGdvLmNyZWF0ZVRyYW5zYWN0aW9uRnJvbUhleChjaGlsZFR4LnR4LCB1dHhvbGliLm5ldHdvcmtzLmJpdGNvaW4pO1xuICAgICAgICBkZWNvZGVkQ2hpbGQuaW5zLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgICAgIGRlY29kZWRDaGlsZC5vdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMSk7XG5cbiAgICAgICAgbGV0IGlucHV0RnJvbVBhcmVudDogYW55ID0gdW5kZWZpbmVkO1xuICAgICAgICBsZXQgYWRkaXRpb25hbElucHV0OiBhbnkgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgXy5mb3JFYWNoKGRlY29kZWRDaGlsZC5pbnMsIChpbnB1dCkgPT4ge1xuICAgICAgICAgIGlucHV0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdoYXNoJyk7XG4gICAgICAgICAgaW5wdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2luZGV4Jyk7XG5cbiAgICAgICAgICBjb25zdCBpbnB1dEhhc2ggPSBpbnB1dFBhcmVudFR4SWQoaW5wdXQpO1xuXG4gICAgICAgICAgaWYgKGlucHV0SGFzaCA9PT0gcGFyZW50VHhJZCkge1xuICAgICAgICAgICAgaW5wdXRGcm9tUGFyZW50ID0gaW5wdXQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFkZGl0aW9uYWxJbnB1dCA9IGlucHV0O1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2hvdWxkLmV4aXN0KGlucHV0RnJvbVBhcmVudCk7XG4gICAgICAgIGNvbnN0IGlucHV0RnJvbVBhcmVudEhhc2ggPSBpbnB1dFBhcmVudFR4SWQoaW5wdXRGcm9tUGFyZW50KTtcbiAgICAgICAgaW5wdXRGcm9tUGFyZW50SGFzaC5zaG91bGQuZXF1YWwocGFyZW50VHhJZCk7XG4gICAgICAgIGlucHV0RnJvbVBhcmVudC5pbmRleC5zaG91bGQuZXF1YWwoMCk7XG5cbiAgICAgICAgc2hvdWxkLmV4aXN0KGFkZGl0aW9uYWxJbnB1dCk7XG4gICAgICAgIGNvbnN0IGFkZGl0aW9uYWxJbnB1dEhhc2ggPSBpbnB1dFBhcmVudFR4SWQoYWRkaXRpb25hbElucHV0KTtcbiAgICAgICAgYWRkaXRpb25hbElucHV0SGFzaC5zaG91bGQuZXF1YWwoYWRkaXRpb25hbFVuc3BlbnRUeElkKTtcbiAgICAgICAgYWRkaXRpb25hbElucHV0LmluZGV4LnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICBjb25zdCBjaGlsZE91dHB1dCA9IGRlY29kZWRDaGlsZC5vdXRzWzBdO1xuICAgICAgICBjaGlsZE91dHB1dC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndmFsdWUnKTtcbiAgICAgICAgY2hpbGRPdXRwdXQudmFsdWUuc2hvdWxkLmJlLmFib3ZlKG1pbkNoYW5nZVNpemUpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdhY2NlbGVyYXRlcyBhIHN0dWNrIHR4IHdpdGggdHdvIGFkZGl0aW9uYWwgdW5zcGVudHMgKHNlZ3dpdCBhbmQgUDJTSCknLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHBhcmVudFR4SWQgPSAnODgxNWYyMDJjODY1NGI2YzhiMjk1NzQ5NTQ1YzcxMTg3OGNkODQ1YTE0Y2IxZWE5ODIzOTRkMGMxNDk0NWMzMyc7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgZmVlOiAxMzM2LFxuICAgICAgICAgICAgb3V0cHV0czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdm91dDogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAwMDAsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxMSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZvdXQ6IDEsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDg2NjQsXG4gICAgICAgICAgICAgICAgaXNNaW5lOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNoYWluOiAxLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGNvbmZpcm1hdGlvbnM6IDAsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS91bnNwZW50c2ApXG4gICAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgdW5zcGVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHR4X2hhc2g6IHBhcmVudFR4SWQsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDEwMDAwLFxuICAgICAgICAgICAgICAgIHJlZGVlbVNjcmlwdDpcbiAgICAgICAgICAgICAgICAgICc1MjIxMDJjZDNjOGU2MDA2YTQ2Mjc3MDUwMjFkMWQwMTZkMDk3YzI5NDRkOTgxMDBhNDdiZjJkYTY3YTVmZTE1YWVlYjM0MjEwMmVlMWZhOWU4MTJlNzc5MzU2YWEzYzMxZWJmMzE3ZDBjZmZlYmFiOTI4NjRjZmUzOGJhYjIyM2UwODIwZjk4YmMyMTAyNmJhMDU3NTJiYWE2ZWFmZDVjNTY1OWRhNjJiN2YwYWM1MWZkMjg4NmI2NWMyNDFkMGFmZWYxYzRmZGZhMWNiYzUzYWUnLFxuICAgICAgICAgICAgICAgIGNoYWluUGF0aDogJy8wLzAnLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogJ2UxOTAzMTBmMmYzZjcxYWE4ODQ2ZjExNjFjYmNlMTUzM2MyNGE4NTdkZDI0ZTQ1MDFiMTMxZmViNDAwYWFkNTgnLFxuICAgICAgICAgICAgICAgIHR4X291dHB1dF9uOiAxLFxuICAgICAgICAgICAgICAgIHZhbHVlOiA4MDAwMDAsXG4gICAgICAgICAgICAgICAgcmVkZWVtU2NyaXB0OlxuICAgICAgICAgICAgICAgICAgJzUyMjEwMmNkM2M4ZTYwMDZhNDYyNzcwNTAyMWQxZDAxNmQwOTdjMjk0NGQ5ODEwMGE0N2JmMmRhNjdhNWZlMTVhZWViMzQyMTAyZWUxZmE5ZTgxMmU3NzkzNTZhYTNjMzFlYmYzMTdkMGNmZmViYWI5Mjg2NGNmZTM4YmFiMjIzZTA4MjBmOThiYzIxMDI2YmEwNTc1MmJhYTZlYWZkNWM1NjU5ZGE2MmI3ZjBhYzUxZmQyODg2YjY1YzI0MWQwYWZlZjFjNGZkZmExY2JjNTNhZScsXG4gICAgICAgICAgICAgICAgY2hhaW5QYXRoOiAnLzAvMCcsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eF9oYXNoOiAnMDdkNmVlNTdiMDI0Y2UyYjYxMDhmNjc4NDc0NTRhMGE3OWE0ZmNmYjk4YWIyNTU1NTNhMjk5M2ExYTE3MGI4NycsXG4gICAgICAgICAgICAgICAgdHhfb3V0cHV0X246IDAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IDIwMDA2Mjg0LFxuICAgICAgICAgICAgICAgIHJlZGVlbVNjcmlwdDogJzAwMjBkMzRlZjZkZDM0ZWYyYTRmYmVhNjdjNTQxYzFjNzk2NzQ5YTYwYWZlNGE5N2ZlZThlYzdkZWQxODhiZDc0OWRhJyxcbiAgICAgICAgICAgICAgICBjaGFpblBhdGg6ICcvMTEvMTU1JyxcbiAgICAgICAgICAgICAgICB3aXRuZXNzU2NyaXB0OlxuICAgICAgICAgICAgICAgICAgJzUyMjEwMjIxOWQyYWE4NDE3NjMzZjBiY2UzOTExMzc0YTE2MDRjMWI2NDE2MWY4M2EzYzJlZTQwOWMyN2M0MjM1NWYwOGUyMTAyYzk3MzQ5MjBkYzRkYTA2YzI4OWZlNjkxNzFkZmNkNzVlM2I5YjRmMTkwZDBjYmMzZDVkMGZmM2Y1ZmRlZWFhZTIxMDNjY2Q2OGQ3ZmE4ZGMwZDAyZGQ0NWRhZDE2NTU1N2E0ODU4MmVkYTQ0MzVmYWU3Mzc3YjNjMzFlMDhhZDA2NWM5NTNhZScsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgIG5vY2soZXhwbG9yZXJVcmwpLmdldChgL3R4LyR7cGFyZW50VHhJZH0vaGV4YCkucmVwbHkoMjAwLCBmaXh0dXJlc1twYXJlbnRUeElkXSk7XG5cbiAgICAgICAgbm9jayhiZ1VybClcbiAgICAgICAgICAucG9zdCgnL2FwaS92MS90eC9zZW5kJywgKGJvZHkpID0+IHtcbiAgICAgICAgICAgIHJldHVybiAhYm9keS5pZ25vcmVNYXhGZWVSYXRlO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnJlcGx5KDIwMCwgZnVuY3Rpb24gKF8sIGJvZHkpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIHRyYW5zYWN0aW9uOiAoYm9keSBhcyBhbnkpLnR4LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBjaGlsZFR4ID0gYXdhaXQgd2FsbGV0LmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCxcbiAgICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBUZXN0Qml0R28uVEVTVF9XQUxMRVQxX1BBU1NDT0RFLFxuICAgICAgICAgIGZlZVJhdGUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNob3VsZC5leGlzdChjaGlsZFR4KTtcbiAgICAgICAgY2hpbGRUeC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc3RhdHVzJywgJ2FjY2VwdGVkJyk7XG4gICAgICAgIGNoaWxkVHguc2hvdWxkLmhhdmUucHJvcGVydHkoJ3R4Jyk7XG5cbiAgICAgICAgLy8gYXNzZXJ0IHRoZSBmb2xsb3dpbmc6XG4gICAgICAgIC8vIDApIFRoZSBjaGlsZCB0eCBoYXMgZXhhY3RseSB0aHJlZSBpbnB1dHNcbiAgICAgICAgLy8gMSkgVGhlIHBhcmVudCB0eCBvdXRwdXQgaXMgYW4gaW5wdXRcbiAgICAgICAgLy8gMikgVGhlIGNoaWxkIHR4IGhhcyBleGFjdGx5IG9uZSBvdXRwdXRcbiAgICAgICAgLy8gMykgVGhlIGNoaWxkIHR4IG91dHB1dCBtZWV0cyB0aGUgbWluaW11bSBjaGFuZ2UgdGhyZXNob2xkXG4gICAgICAgIGNvbnN0IGRlY29kZWRDaGlsZCA9IHV0eG9saWIuYml0Z28uY3JlYXRlVHJhbnNhY3Rpb25Gcm9tSGV4KGNoaWxkVHgudHgsIHV0eG9saWIubmV0d29ya3MuYml0Y29pbik7XG4gICAgICAgIGRlY29kZWRDaGlsZC5pbnMubGVuZ3RoLnNob3VsZC5lcXVhbCgzKTtcbiAgICAgICAgZGVjb2RlZENoaWxkLm91dHMubGVuZ3RoLnNob3VsZC5lcXVhbCgxKTtcblxuICAgICAgICBsZXQgaW5wdXRGcm9tUGFyZW50OiBhbnkgPSB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGFkZGl0aW9uYWxJbnB1dHM6IGFueVtdID0gW107XG5cbiAgICAgICAgXy5mb3JFYWNoKGRlY29kZWRDaGlsZC5pbnMsIChpbnB1dCkgPT4ge1xuICAgICAgICAgIGlucHV0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdoYXNoJyk7XG4gICAgICAgICAgaW5wdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2luZGV4Jyk7XG5cbiAgICAgICAgICBjb25zdCBpbnB1dEhhc2ggPSBpbnB1dFBhcmVudFR4SWQoaW5wdXQpO1xuXG4gICAgICAgICAgaWYgKGlucHV0SGFzaCA9PT0gcGFyZW50VHhJZCkge1xuICAgICAgICAgICAgaW5wdXRGcm9tUGFyZW50ID0gaW5wdXQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFkZGl0aW9uYWxJbnB1dHMucHVzaChpbnB1dCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBzaG91bGQuZXhpc3QoaW5wdXRGcm9tUGFyZW50KTtcbiAgICAgICAgY29uc3QgaW5wdXRGcm9tUGFyZW50SGFzaCA9IGlucHV0UGFyZW50VHhJZChpbnB1dEZyb21QYXJlbnQpO1xuICAgICAgICBpbnB1dEZyb21QYXJlbnRIYXNoLnNob3VsZC5lcXVhbChwYXJlbnRUeElkKTtcbiAgICAgICAgaW5wdXRGcm9tUGFyZW50LmluZGV4LnNob3VsZC5lcXVhbCgwKTtcblxuICAgICAgICBhZGRpdGlvbmFsSW5wdXRzLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG5cbiAgICAgICAgY29uc3QgY2hpbGRPdXRwdXQgPSBkZWNvZGVkQ2hpbGQub3V0c1swXTtcbiAgICAgICAgY2hpbGRPdXRwdXQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3ZhbHVlJyk7XG4gICAgICAgIGNoaWxkT3V0cHV0LnZhbHVlLnNob3VsZC5iZS5hYm92ZShtaW5DaGFuZ2VTaXplKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnY29ycmVjdGx5IHVzZXMgdGhlIGlnbm9yZU1heEZlZVJhdGUgcGFyYW1ldGVyIG9ubHkgd2hlbiBuZWNlc3NhcnknLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHBhcmVudFR4SWQgPSAnNzVjZmM1YTdiMjE0YzRiNzNjOTJjN2IwMjYwOGNkZTcwYjIyNjc2N2E5NTc2Zjg0YzA0NDA3ZTQzZmQzODViZCc7XG4gICAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vdHgvJHtwYXJlbnRUeElkfWApXG4gICAgICAgICAgLnJlcGx5KDIwMCwge1xuICAgICAgICAgICAgZmVlOiA0MzQsXG4gICAgICAgICAgICBvdXRwdXRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2b3V0OiAwLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMDM0ODUwMCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDAsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2b3V0OiAxLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAxMDAwMCxcbiAgICAgICAgICAgICAgICBpc01pbmU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2hhaW46IDExLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L3Vuc3BlbnRzYClcbiAgICAgICAgICAucXVlcnkodHJ1ZSlcbiAgICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgICB1bnNwZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHhfaGFzaDogcGFyZW50VHhJZCxcbiAgICAgICAgICAgICAgICB0eF9vdXRwdXRfbjogMCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogMTAzNDg1MDAsXG4gICAgICAgICAgICAgICAgcmVkZWVtU2NyaXB0OiAnMDAyMGY3YjU4ZDQ1NTM1MWI3YjhkZGQ3Yzg5ODZkOTgyNDRmNmE5NWYwNzQ2NzIwMDkxNTM3MzIzYjk2NzgwMGY3NDQnLFxuICAgICAgICAgICAgICAgIGNoYWluUGF0aDogJy8xMS8xNjAnLFxuICAgICAgICAgICAgICAgIHdpdG5lc3NTY3JpcHQ6XG4gICAgICAgICAgICAgICAgICAnNTIyMTAyN2YwYjQ1YmI0MTU1ZWE1MzJlM2I0MzEyZmUwYmU4MDE2NmYyOTdkMWUwNzUzZDJkNGE5MTE4YzA3M2FkNjUxNDIxMDMxMGFhOWQ2OGM5ODgzMTYyNWYzMjliNzgyNmI2YzNlM2I1M2UxNjczNmIxOTk0Yjg5MDI0NDJiZGNkNjY1M2QxMjEwMjZlMGNhNDE0ZjI0ODhiMGFiNTcyYjk5ZTBhZTU0NDI5MTFhYjRlMDgyMWIyNzA5ZDg4NTE3NWE1MjdmZDU1MmI1M2FlJyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgbm9jayhleHBsb3JlclVybCkuZ2V0KGAvdHgvJHtwYXJlbnRUeElkfS9oZXhgKS5yZXBseSgyMDAsIGZpeHR1cmVzW3BhcmVudFR4SWRdKTtcblxuICAgICAgICBub2NrKGJnVXJsKVxuICAgICAgICAgIC5wb3N0KCcvYXBpL3YxL3R4L3NlbmQnLCAoYm9keSkgPT4ge1xuICAgICAgICAgICAgLy8gaWdub3JlIG1heCBmZWUgcmF0ZSBtdXN0IGJlIHNldCBmb3IgdGhpcyB0ZXN0XG4gICAgICAgICAgICByZXR1cm4gYm9keS5pZ25vcmVNYXhGZWVSYXRlO1xuICAgICAgICAgIH0pXG4gICAgICAgICAgLnJlcGx5KDIwMCk7XG5cbiAgICAgICAgLy8gbW9ua2V5IHBhdGNoIHRoZSBiaXRnbyBnZXRDb25zdGFudHMoKSBmdW5jdGlvblxuICAgICAgICBjb25zdCBvbGRHZXRDb25zdGFudHMgPSAoYml0Z28gYXMgYW55KS5fX3Byb3RvX18uZ2V0Q29uc3RhbnRzO1xuICAgICAgICAoYml0Z28gYXMgYW55KS5fX3Byb3RvX18uZ2V0Q29uc3RhbnRzID0gKCkgPT4gKHtcbiAgICAgICAgICAvLyBjaGlsZCBmZWUgcmF0ZSBpbiB0aGlzIHRlc3QgaXMgMzEzNzggc2F0L2tiXG4gICAgICAgICAgLy8gc28gc2V0IHRoZSBtYXggZmVlIHJhdGUganVzdCBiZWxvdyB0aGF0IGxpbWl0LFxuICAgICAgICAgIC8vIGJ1dCBhYm92ZSB0aGUgY29tYmluZWQgZmVlIHJhdGUgb2YgMjAwMDBcbiAgICAgICAgICBtYXhGZWVSYXRlOiAzMDAwMCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgd2FsbGV0LmFjY2VsZXJhdGVUcmFuc2FjdGlvbih7XG4gICAgICAgICAgdHJhbnNhY3Rpb25JRDogcGFyZW50VHhJZCxcbiAgICAgICAgICBmZWVSYXRlLFxuICAgICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IFRlc3RCaXRHby5URVNUX1dBTExFVDFfUEFTU0NPREUsXG4gICAgICAgIH0pO1xuICAgICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuXG4gICAgICAgIChiaXRnbyBhcyBhbnkpLl9fcHJvdG9fXy5nZXRDb25zdGFudHMgPSBvbGRHZXRDb25zdGFudHM7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldEJpdEdvRmVlJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBiZ1VybDogc3RyaW5nO1xuICAgIGxldCB3YWxsZXQ6IGFueTtcblxuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrLnBlbmRpbmdNb2NrcygpLnNob3VsZC5iZS5lbXB0eSgpO1xuICAgICAgY29uc3QgcHJvZEJpdGdvID0gbmV3IEJpdEdvQVBJKHsgZW52OiAncHJvZCcsIGNsaWVudENvbnN0YW50czogeyBjb25zdGFudHM6IHt9IH0gfSk7XG4gICAgICBiZ1VybCA9IGNvbW1vbi5FbnZpcm9ubWVudHNbcHJvZEJpdGdvLmdldEVudigpXS51cmk7XG4gICAgICB3YWxsZXQgPSBuZXcgV2FsbGV0KHByb2RCaXRnbywge1xuICAgICAgICBpZDogJzJOQ29TZkhINkxzNENkVFM1UWFoZ0M5azd4OVJmWGVTd1k0JyxcbiAgICAgICAgcHJpdmF0ZTogeyBrZXljaGFpbnM6IFt1c2VyS2V5cGFpciwgYmFja3VwS2V5cGFpciwgYml0Z29LZXldIH0sXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2VuZHMgYW1vdW50IGFuZCBpbnN0YW50IHdpdGhvdXQgcmVjaXBpZW50cyB3aGVuIHJlY2lwaWVudHMgYXJyYXkgaXMgZW1wdHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzY29wZSA9IG5vY2soYmdVcmwpXG4gICAgICAgIC5nZXQoYC9hcGkvdjEvd2FsbGV0LyR7d2FsbGV0LmlkKCl9L2JpbGxpbmcvZmVlYClcbiAgICAgICAgLnF1ZXJ5KHsgYW1vdW50OiAnMTAwMDAwJywgaW5zdGFudDogJ2ZhbHNlJyB9KVxuICAgICAgICAucmVwbHkoMjAwLCB7IGZlZTogMTAwMCB9KTtcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgd2FsbGV0LmdldEJpdEdvRmVlKHsgYW1vdW50OiAxMDAwMDAsIGluc3RhbnQ6IGZhbHNlIH0pO1xuICAgICAgcmVzdWx0LmZlZS5zaG91bGQuZXF1YWwoMTAwMCk7XG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NlbmRzIHJlY2lwaWVudHNbXSBxdWVyeSBwYXJhbXMgd2hlbiByZWNpcGllbnRzIGFyZSBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGFkZHIxID0gJzNKOTh0MVdwRVo3M0NObVF2aWVjcm55aVdybnFSaFdOTHknO1xuICAgICAgY29uc3QgYWRkcjIgPSAnM0ZaYmdpMjljcGpxMkdqZHdWOGV5SHVKSm5rTHRrdFpjNSc7XG5cbiAgICAgIGNvbnN0IHNjb3BlID0gbm9jayhiZ1VybClcbiAgICAgICAgLmdldChgL2FwaS92MS93YWxsZXQvJHt3YWxsZXQuaWQoKX0vYmlsbGluZy9mZWVgKVxuICAgICAgICAucXVlcnkoKHF1ZXJ5KSA9PiB7XG4gICAgICAgICAgY29uc3QgcmVjaXBpZW50c1BhcmFtID0gcXVlcnlbJ3JlY2lwaWVudHNbXSddO1xuICAgICAgICAgIGNvbnN0IHJlY2lwaWVudHNMaXN0ID0gQXJyYXkuaXNBcnJheShyZWNpcGllbnRzUGFyYW0pID8gcmVjaXBpZW50c1BhcmFtIDogW3JlY2lwaWVudHNQYXJhbV07XG4gICAgICAgICAgcmV0dXJuIHF1ZXJ5LmFtb3VudCA9PT0gJzEwMDAwMCcgJiYgcmVjaXBpZW50c0xpc3QuaW5jbHVkZXMoYWRkcjEpICYmIHJlY2lwaWVudHNMaXN0LmluY2x1ZGVzKGFkZHIyKTtcbiAgICAgICAgfSlcbiAgICAgICAgLnJlcGx5KDIwMCwgeyBmZWU6IDAgfSk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdhbGxldC5nZXRCaXRHb0ZlZSh7IGFtb3VudDogMTAwMDAwLCByZWNpcGllbnRzOiBbYWRkcjEsIGFkZHIyXSB9KTtcbiAgICAgIHJlc3VsdC5mZWUuc2hvdWxkLmVxdWFsKDApO1xuICAgICAgc2NvcGUuaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdvbWl0cyByZWNpcGllbnRzW10gd2hlbiByZWNpcGllbnRzIGFycmF5IGlzIGVtcHR5JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2NvcGUgPSBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KGAvYXBpL3YxL3dhbGxldC8ke3dhbGxldC5pZCgpfS9iaWxsaW5nL2ZlZWApXG4gICAgICAgIC5xdWVyeSgocXVlcnkpID0+IHF1ZXJ5LmFtb3VudCA9PT0gJzIwMDAwMCcgJiYgISgncmVjaXBpZW50c1tdJyBpbiBxdWVyeSkpXG4gICAgICAgIC5yZXBseSgyMDAsIHsgZmVlOiA1MDAgfSk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHdhbGxldC5nZXRCaXRHb0ZlZSh7IGFtb3VudDogMjAwMDAwLCByZWNpcGllbnRzOiBbXSB9KTtcbiAgICAgIHJlc3VsdC5mZWUuc2hvdWxkLmVxdWFsKDUwMCk7XG4gICAgICBzY29wZS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyB3aGVuIGFtb3VudCBpcyBub3QgYSBudW1iZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAoKCkgPT4gd2FsbGV0LmdldEJpdEdvRmVlKHsgYW1vdW50OiAnYmFkJyB9KSkuc2hvdWxkLnRocm93KCdpbnZhbGlkIGFtb3VudCBhcmd1bWVudCcpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyB3aGVuIGluc3RhbnQgaXMgbm90IGEgYm9vbGVhbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICgoKSA9PiB3YWxsZXQuZ2V0Qml0R29GZWUoeyBhbW91bnQ6IDEwMCwgaW5zdGFudDogJ3llcycgfSkpLnNob3VsZC50aHJvdygnaW52YWxpZCBpbnN0YW50IGFyZ3VtZW50Jyk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG4iXX0=