@bitgo-beta/sdk-coin-eth 4.4.1-beta.202 → 4.4.1-beta.2021

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 (122) hide show
  1. package/dist/src/erc20Token.d.ts +1 -1
  2. package/dist/src/erc20Token.d.ts.map +1 -1
  3. package/dist/src/erc20Token.js +49 -28
  4. package/dist/src/erc721Token.d.ts +60 -0
  5. package/dist/src/erc721Token.d.ts.map +1 -0
  6. package/dist/src/erc721Token.js +334 -0
  7. package/dist/src/erc7984Token.d.ts +187 -0
  8. package/dist/src/erc7984Token.d.ts.map +1 -0
  9. package/dist/src/erc7984Token.js +946 -0
  10. package/dist/src/eth.d.ts +10 -8
  11. package/dist/src/eth.d.ts.map +1 -1
  12. package/dist/src/eth.js +54 -39
  13. package/dist/src/index.d.ts +3 -0
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/index.js +9 -2
  16. package/dist/src/lib/index.d.ts +1 -0
  17. package/dist/src/lib/index.d.ts.map +1 -1
  18. package/dist/src/lib/index.js +7 -2
  19. package/dist/src/lib/messages/index.d.ts +3 -0
  20. package/dist/src/lib/messages/index.d.ts.map +1 -0
  21. package/dist/src/lib/messages/index.js +6 -0
  22. package/dist/src/lib/transactionBuilder.d.ts +10 -5
  23. package/dist/src/lib/transactionBuilder.d.ts.map +1 -1
  24. package/dist/src/lib/transactionBuilder.js +17 -7
  25. package/dist/src/lib/transferBuilders/index.d.ts +2 -2
  26. package/dist/src/lib/transferBuilders/index.d.ts.map +1 -1
  27. package/dist/src/lib/transferBuilders/index.js +3 -2
  28. package/dist/src/register.d.ts +2 -0
  29. package/dist/src/register.d.ts.map +1 -1
  30. package/dist/src/register.js +39 -2
  31. package/dist/src/sepeth.d.ts +8 -0
  32. package/dist/src/sepeth.d.ts.map +1 -0
  33. package/dist/src/sepeth.js +14 -0
  34. package/dist/test/fixtures/eth.d.ts +39 -0
  35. package/dist/test/fixtures/eth.d.ts.map +1 -0
  36. package/dist/test/fixtures/eth.js +262 -0
  37. package/dist/test/resources/erc1155Abi.d.ts +40 -0
  38. package/dist/test/resources/erc1155Abi.d.ts.map +1 -0
  39. package/dist/test/resources/erc1155Abi.js +329 -0
  40. package/dist/test/resources/erc721Abi.d.ts +12 -0
  41. package/dist/test/resources/erc721Abi.d.ts.map +1 -0
  42. package/dist/test/resources/erc721Abi.js +34 -0
  43. package/dist/test/resources/eth.d.ts +51 -0
  44. package/dist/test/resources/eth.d.ts.map +1 -0
  45. package/dist/test/resources/eth.js +72 -0
  46. package/dist/test/resources/nftEncodings.d.ts +4 -0
  47. package/dist/test/resources/nftEncodings.d.ts.map +1 -0
  48. package/dist/test/resources/nftEncodings.js +7 -0
  49. package/dist/test/resources/walletSimpleAbi.d.ts +12 -0
  50. package/dist/test/resources/walletSimpleAbi.d.ts.map +1 -0
  51. package/dist/test/resources/walletSimpleAbi.js +44 -0
  52. package/dist/test/unit/erc7984Token.d.ts +2 -0
  53. package/dist/test/unit/erc7984Token.d.ts.map +1 -0
  54. package/dist/test/unit/erc7984Token.js +1589 -0
  55. package/dist/test/unit/eth.d.ts +2 -0
  56. package/dist/test/unit/eth.d.ts.map +1 -0
  57. package/dist/test/unit/eth.js +2701 -0
  58. package/dist/test/unit/ethWallet.d.ts +2 -0
  59. package/dist/test/unit/ethWallet.d.ts.map +1 -0
  60. package/dist/test/unit/ethWallet.js +552 -0
  61. package/dist/test/unit/fixtures/ethMultiSigBackupKey.d.ts +4 -0
  62. package/dist/test/unit/fixtures/ethMultiSigBackupKey.d.ts.map +1 -0
  63. package/dist/test/unit/fixtures/ethMultiSigBackupKey.js +10 -0
  64. package/dist/test/unit/fixtures/ethTssBackupKey.d.ts +5 -0
  65. package/dist/test/unit/fixtures/ethTssBackupKey.d.ts.map +1 -0
  66. package/dist/test/unit/fixtures/ethTssBackupKey.js +25 -0
  67. package/dist/test/unit/getBuilder.d.ts +3 -0
  68. package/dist/test/unit/getBuilder.d.ts.map +1 -0
  69. package/dist/test/unit/getBuilder.js +10 -0
  70. package/dist/test/unit/keyPair.d.ts +2 -0
  71. package/dist/test/unit/keyPair.d.ts.map +1 -0
  72. package/dist/test/unit/keyPair.js +175 -0
  73. package/dist/test/unit/register.d.ts +2 -0
  74. package/dist/test/unit/register.d.ts.map +1 -0
  75. package/dist/test/unit/register.js +75 -0
  76. package/dist/test/unit/transaction.d.ts +2 -0
  77. package/dist/test/unit/transaction.d.ts.map +1 -0
  78. package/dist/test/unit/transaction.js +117 -0
  79. package/dist/test/unit/transactionBuilder/addressInitialization.d.ts +2 -0
  80. package/dist/test/unit/transactionBuilder/addressInitialization.d.ts.map +1 -0
  81. package/dist/test/unit/transactionBuilder/addressInitialization.js +101 -0
  82. package/dist/test/unit/transactionBuilder/contractCall.d.ts +2 -0
  83. package/dist/test/unit/transactionBuilder/contractCall.d.ts.map +1 -0
  84. package/dist/test/unit/transactionBuilder/contractCall.js +101 -0
  85. package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts +2 -0
  86. package/dist/test/unit/transactionBuilder/decryptionDelegation.d.ts.map +1 -0
  87. package/dist/test/unit/transactionBuilder/decryptionDelegation.js +59 -0
  88. package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.d.ts +2 -0
  89. package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.d.ts.map +1 -0
  90. package/dist/test/unit/transactionBuilder/decryptionDelegationTxBuilder.js +136 -0
  91. package/dist/test/unit/transactionBuilder/flushCoins.d.ts +2 -0
  92. package/dist/test/unit/transactionBuilder/flushCoins.d.ts.map +1 -0
  93. package/dist/test/unit/transactionBuilder/flushCoins.js +133 -0
  94. package/dist/test/unit/transactionBuilder/flushTokens.d.ts +2 -0
  95. package/dist/test/unit/transactionBuilder/flushTokens.d.ts.map +1 -0
  96. package/dist/test/unit/transactionBuilder/flushTokens.js +298 -0
  97. package/dist/test/unit/transactionBuilder/send.d.ts +2 -0
  98. package/dist/test/unit/transactionBuilder/send.d.ts.map +1 -0
  99. package/dist/test/unit/transactionBuilder/send.js +331 -0
  100. package/dist/test/unit/transactionBuilder/sendERC7984Token.d.ts +2 -0
  101. package/dist/test/unit/transactionBuilder/sendERC7984Token.d.ts.map +1 -0
  102. package/dist/test/unit/transactionBuilder/sendERC7984Token.js +361 -0
  103. package/dist/test/unit/transactionBuilder/sendNFT.d.ts +2 -0
  104. package/dist/test/unit/transactionBuilder/sendNFT.d.ts.map +1 -0
  105. package/dist/test/unit/transactionBuilder/sendNFT.js +295 -0
  106. package/dist/test/unit/transactionBuilder/singleSigSend.d.ts +2 -0
  107. package/dist/test/unit/transactionBuilder/singleSigSend.d.ts.map +1 -0
  108. package/dist/test/unit/transactionBuilder/singleSigSend.js +196 -0
  109. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts +2 -0
  110. package/dist/test/unit/transactionBuilder/walletInitialization.d.ts.map +1 -0
  111. package/dist/test/unit/transactionBuilder/walletInitialization.js +436 -0
  112. package/dist/test/unit/transferBuilder.d.ts +2 -0
  113. package/dist/test/unit/transferBuilder.d.ts.map +1 -0
  114. package/dist/test/unit/transferBuilder.js +124 -0
  115. package/dist/test/unit/utils.d.ts +2 -0
  116. package/dist/test/unit/utils.d.ts.map +1 -0
  117. package/dist/test/unit/utils.js +74 -0
  118. package/dist/tsconfig.tsbuildinfo +1 -0
  119. package/package.json +17 -13
  120. package/.eslintignore +0 -5
  121. package/.mocharc.yml +0 -8
  122. package/CHANGELOG.md +0 -771
@@ -0,0 +1,552 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const should_1 = __importDefault(require("should"));
40
+ const secp256k1_1 = require("@bitgo-beta/secp256k1");
41
+ const secp256k1 = __importStar(require("secp256k1"));
42
+ const nock_1 = __importDefault(require("nock"));
43
+ const sinon_1 = __importDefault(require("sinon"));
44
+ const sdk_core_1 = require("@bitgo-beta/sdk-core");
45
+ const sdk_test_1 = require("@bitgo-beta/sdk-test");
46
+ const tx_1 = require("@ethereumjs/tx");
47
+ const fixtures = require('../fixtures/eth');
48
+ const sdk_api_1 = require("@bitgo-beta/sdk-api");
49
+ const src_1 = require("../../src");
50
+ const getBuilder_1 = require("./getBuilder");
51
+ describe('Sign ETH Transaction', async function () {
52
+ let bitgo;
53
+ let ethWallet;
54
+ let recipients;
55
+ let tx;
56
+ before(function () {
57
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
58
+ bitgo.initializeTestVars();
59
+ bitgo.safeRegister('teth', src_1.Teth.createInstance);
60
+ const coin = bitgo.coin('teth');
61
+ ethWallet = coin.newWalletObject({});
62
+ recipients = [
63
+ {
64
+ address: '0xe59dfe5c67114b39a5662cc856be536c614124c0',
65
+ amount: '100000',
66
+ },
67
+ ];
68
+ tx = { recipients, nextContractSequenceId: 0 };
69
+ });
70
+ it('should read transaction recipients from txPrebuild even if none are specified as top-level params', async function () {
71
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
72
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
73
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
74
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild: tx, prv: 'my_user_prv' }));
75
+ halfSigned.should.have.property('recipients', recipients);
76
+ sinon_1.default.restore();
77
+ });
78
+ it('should throw an error if no recipients are in the txPrebuild and none are specified as params', async function () {
79
+ await ethWallet
80
+ .signTransaction({ txPrebuild: {}, prv: 'my_user_prv' })
81
+ .should.be.rejectedWith('recipients missing or not array');
82
+ });
83
+ it('should throw an error if the recipients param is not an array', async function () {
84
+ await ethWallet
85
+ .signTransaction({ txPrebuild: { recipients: 'not-array' }, prv: 'my_user_prv' })
86
+ .should.be.rejectedWith('recipients missing or not array');
87
+ });
88
+ it('should set isBatch to false if single recipient', async function () {
89
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
90
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
91
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
92
+ const singleRecipientsTx = { recipients: recipients, nextContractSequenceId: 0, isBatch: false };
93
+ const { halfSigned } = (await ethWallet.signTransaction({
94
+ txPrebuild: singleRecipientsTx,
95
+ prv: 'my_user_prv',
96
+ }));
97
+ halfSigned.should.have.property('recipients', recipients);
98
+ halfSigned.should.have.property('isBatch', false);
99
+ sinon_1.default.restore();
100
+ });
101
+ it('should set isBatch to true if multiple recipients', async function () {
102
+ const multipleRecipients = [
103
+ {
104
+ address: '0x0c7f3bc5d2b2c0dbee1b45536b82569f41b54331',
105
+ amount: '200',
106
+ data: '0xcf4c58e2000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000431745b89e73230b3bc8a19e019194efb4b99efd000000000000000000000000431745b89e73230b3bc8a19e019194efb4b99efd000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064',
107
+ },
108
+ ];
109
+ const multipleRecipientsTx = { recipients: multipleRecipients, nextContractSequenceId: 0, isBatch: true };
110
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
111
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
112
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
113
+ const { halfSigned } = (await ethWallet.signTransaction({
114
+ txPrebuild: multipleRecipientsTx,
115
+ prv: 'my_user_prv',
116
+ }));
117
+ halfSigned.should.have.property('isBatch', true);
118
+ sinon_1.default.restore();
119
+ });
120
+ });
121
+ describe('Sign ETH Transaction – txInfo fallback', async function () {
122
+ let bitgo;
123
+ let ethWallet;
124
+ const recipients = [{ address: '0xe59dfe5c67114b39a5662cc856be536c614124c0', amount: '100000' }];
125
+ before(function () {
126
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
127
+ bitgo.initializeTestVars();
128
+ bitgo.safeRegister('teth', src_1.Teth.createInstance);
129
+ const coin = bitgo.coin('teth');
130
+ ethWallet = coin.newWalletObject({});
131
+ });
132
+ afterEach(function () {
133
+ sinon_1.default.restore();
134
+ });
135
+ it('should read recipients from txPrebuild.txInfo.recipients when txPrebuild.recipients is absent', async function () {
136
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
137
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
138
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
139
+ const txPrebuild = { txInfo: { recipients, nextContractSequenceId: 1 } };
140
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild, prv: 'my_user_prv' }));
141
+ halfSigned.should.have.property('recipients', recipients);
142
+ });
143
+ it('should prefer txPrebuild.recipients over txPrebuild.txInfo.recipients', async function () {
144
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
145
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
146
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
147
+ const txInfoRecipients = [{ address: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef', amount: '1' }];
148
+ const txPrebuild = { recipients, nextContractSequenceId: 0, txInfo: { recipients: txInfoRecipients } };
149
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild, prv: 'my_user_prv' }));
150
+ halfSigned.should.have.property('recipients', recipients);
151
+ });
152
+ it('should use txPrebuild.txInfo.nextContractSequenceId when nextContractSequenceId is absent', async function () {
153
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
154
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
155
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
156
+ const txPrebuild = { recipients, txInfo: { nextContractSequenceId: 5 } };
157
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild, prv: 'my_user_prv' }));
158
+ halfSigned.should.have.property('contractSequenceId', 5);
159
+ });
160
+ it('should throw when nextContractSequenceId is absent from both txPrebuild and txInfo', async function () {
161
+ await ethWallet
162
+ .signTransaction({ txPrebuild: { recipients }, prv: 'my_user_prv' })
163
+ .should.be.rejectedWith('transaction prebuild missing required property nextContractSequenceId');
164
+ });
165
+ it('should use txPrebuild.txInfo.eip1559 when txPrebuild.eip1559 is absent', async function () {
166
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
167
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
168
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
169
+ const eip1559 = { maxFeePerGas: '100', maxPriorityFeePerGas: '10' };
170
+ const txPrebuild = { recipients, nextContractSequenceId: 0, txInfo: { eip1559 } };
171
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild, prv: 'my_user_prv' }));
172
+ halfSigned.should.have.property('eip1559', eip1559);
173
+ });
174
+ it('should prefer txPrebuild.eip1559 over txPrebuild.txInfo.eip1559', async function () {
175
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
176
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
177
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
178
+ const eip1559 = { maxFeePerGas: '200', maxPriorityFeePerGas: '20' };
179
+ const txInfoEip1559 = { maxFeePerGas: '999', maxPriorityFeePerGas: '99' };
180
+ const txPrebuild = { recipients, nextContractSequenceId: 0, eip1559, txInfo: { eip1559: txInfoEip1559 } };
181
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild, prv: 'my_user_prv' }));
182
+ halfSigned.should.have.property('eip1559', eip1559);
183
+ });
184
+ it('should use txPrebuild.txInfo.isBatch when txPrebuild.isBatch is absent', async function () {
185
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
186
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
187
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
188
+ const txPrebuild = { recipients, nextContractSequenceId: 0, txInfo: { isBatch: true } };
189
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild, prv: 'my_user_prv' }));
190
+ halfSigned.should.have.property('isBatch', true);
191
+ });
192
+ it('should prefer txPrebuild.isBatch over txPrebuild.txInfo.isBatch', async function () {
193
+ sinon_1.default.stub(sdk_core_1.Util, 'xprvToEthPrivateKey');
194
+ sinon_1.default.stub(sdk_core_1.Util, 'ethSignMsgHash');
195
+ sinon_1.default.stub(ethWallet.getOperationSha3ForExecuteAndConfirm);
196
+ const txPrebuild = { recipients, nextContractSequenceId: 0, isBatch: false, txInfo: { isBatch: true } };
197
+ const { halfSigned } = (await ethWallet.signTransaction({ txPrebuild, prv: 'my_user_prv' }));
198
+ halfSigned.should.have.property('isBatch', false);
199
+ });
200
+ });
201
+ describe('Ethereum Hop Transactions', function () {
202
+ let bitgo;
203
+ let ethWallet;
204
+ let tx;
205
+ let txid;
206
+ let bitgoSignature;
207
+ let bitgoKeyXprv;
208
+ let bgUrl;
209
+ let env;
210
+ const userKeypair = {
211
+ xprv: 'xprv9s21ZrQH143K2fJ91S4BRsupcYrE6mmY96fcX5HkhoTrrwmwjd16Cn87cWinJjByrfpojjx7ezsJLx7TAKLT8m8hM5Kax9YcoxnBeJZ3t2k',
212
+ xpub: 'xpub661MyMwAqRbcF9Nc7TbBo1rZAagiWEVPWKbDKThNG8zqjk76HAKLkaSbTn6dK2dQPfuD7xjicxCZVWvj67fP5nQ9W7QURmoMVAX8m6jZsGp',
213
+ rawPub: '02c103ac74481874b5ef0f385d12725e4f14aedc9e00bc814ce96f47f62ce7adf2',
214
+ rawPrv: '936c5af3f8af81f75cdad1b08f29e7d9c01e598e2db2d7be18b9e5a8646e87c6',
215
+ path: 'm',
216
+ walletSubPath: '/0/0',
217
+ };
218
+ before(function () {
219
+ tx =
220
+ '0xf86c82015285012a05f200825208945208d8e80c6d1aef9be37b4bd19a9cf75ed93dc886b5e620f480008026a00e13f9e0e11337b2b0227e3412211d3625e43f1083fda399cc361dd4bf89083ba06c801a761e0aa3bc8db0ac2568d575b0fb306a1f04f4d5ba82ba3cc0ea0a83bd';
221
+ txid = '0x0ac669c5fef8294443c75a31e32c44b97bbc9e43a18ea8beabcc2a3b45eb6ffa';
222
+ bitgoKeyXprv =
223
+ 'xprv9s21ZrQH143K3tpWBHWe31sLoXNRQ9AvRYJgitkKxQ4ATFQMwvr7hHNqYRUnS7PsjzB7aK1VxqHLuNQjj1sckJ2Jwo2qxmsvejwECSpFMfC';
224
+ const bitgoKey = secp256k1_1.bip32.fromBase58(bitgoKeyXprv);
225
+ if (!bitgoKey.privateKey) {
226
+ throw new Error('no privateKey');
227
+ }
228
+ const bitgoXpub = bitgoKey.neutered().toBase58();
229
+ bitgoSignature =
230
+ '0xaa' +
231
+ Buffer.from(secp256k1.ecdsaSign(Buffer.from(txid.slice(2), 'hex'), bitgoKey.privateKey).signature).toString('hex');
232
+ env = 'test';
233
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env });
234
+ bitgo.safeRegister('teth', src_1.Teth.createInstance);
235
+ sdk_core_1.common.Environments[env].hsmXpub = bitgoXpub;
236
+ bitgo.initializeTestVars();
237
+ bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
238
+ const coin = bitgo.coin('teth');
239
+ ethWallet = coin.newWalletObject({ keys: ['user', 'backup', 'bitgo'] });
240
+ });
241
+ describe('Verify HSM Hop prebuild', function () {
242
+ let prebuild;
243
+ let buildParams;
244
+ let finalRecipient;
245
+ let sendAmount;
246
+ before(function () {
247
+ finalRecipient = '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8';
248
+ sendAmount = '200000000000000';
249
+ prebuild = {
250
+ tx,
251
+ id: txid,
252
+ signature: bitgoSignature,
253
+ };
254
+ buildParams = {
255
+ recipients: [
256
+ {
257
+ address: finalRecipient,
258
+ amount: sendAmount,
259
+ },
260
+ ],
261
+ };
262
+ });
263
+ it('should accept a valid hop prebuild', async function () {
264
+ await ethWallet.baseCoin.validateHopPrebuild(ethWallet, prebuild, buildParams).should.be.resolved();
265
+ });
266
+ it('should fail if the HSM prebuild recipient is wrong', async function () {
267
+ const badBuildParams = JSON.parse(JSON.stringify(buildParams));
268
+ badBuildParams.recipients[0].address = '0x54bf1609aeed804aa231f08c53dbb18f7d374615';
269
+ await ethWallet.baseCoin
270
+ .validateHopPrebuild(ethWallet, prebuild, badBuildParams)
271
+ .should.be.rejectedWith(/does not equal original recipient/);
272
+ });
273
+ it('should fail if the HSM prebuild tx amount is wrong', async function () {
274
+ const badBuildParams = JSON.parse(JSON.stringify(buildParams));
275
+ badBuildParams.recipients[0].amount = '50000000';
276
+ await ethWallet.baseCoin
277
+ .validateHopPrebuild(ethWallet, prebuild, badBuildParams)
278
+ .should.be.rejectedWith(/does not equal original amount/);
279
+ });
280
+ it('should fail if the HSM signature is invalid', async function () {
281
+ // Mocking a different BitGo key means the signing key should be wrong (it maps to a different address than this xpub)
282
+ const goodXpub = sdk_core_1.common.Environments[env].hsmXpub;
283
+ sdk_core_1.common.Environments[env].hsmXpub =
284
+ 'xpub661MyMwAqRbcErFqVXGiUFv9YeoPbhN72UiNCUdj9nj3T6M8h7iKNmbCYpMVWVZP7LA2ma3HWcPngz1gRTm4FPdtm9mHfrNvU93MCoszsGL';
285
+ await ethWallet.baseCoin
286
+ .validateHopPrebuild(ethWallet, prebuild, buildParams)
287
+ .should.be.rejectedWith(/Hop txid signature invalid/);
288
+ sdk_core_1.common.Environments[env].hsmXpub = goodXpub;
289
+ });
290
+ it('should fail if the HSM signature signed the wrong HSM commitment digest', async function () {
291
+ const badTxid = '0xb4b3827a529c9166786e796528017889ac5027255b65b3fa2a3d3ad91244a12b';
292
+ const badTxidBuffer = Buffer.from(badTxid.slice(2), 'hex');
293
+ const xprvNode = secp256k1_1.bip32.fromBase58(bitgoKeyXprv);
294
+ if (!xprvNode.privateKey) {
295
+ throw new Error('no privateKey');
296
+ }
297
+ const badSignature = '0xaa' + Buffer.from(secp256k1.ecdsaSign(badTxidBuffer, xprvNode.privateKey).signature).toString('hex');
298
+ const badPrebuild = JSON.parse(JSON.stringify(prebuild));
299
+ badPrebuild.signature = badSignature;
300
+ await ethWallet.baseCoin
301
+ .validateHopPrebuild(ethWallet, badPrebuild, buildParams)
302
+ .should.be.rejectedWith(/Hop txid signature invalid/);
303
+ });
304
+ });
305
+ describe('Prebuild hop transaction', function () {
306
+ let prebuild;
307
+ let buildParams;
308
+ let finalRecipient;
309
+ let sendAmount;
310
+ let gasLimitEstimate;
311
+ let gasPrice;
312
+ const nockUserKey = async function () {
313
+ (0, nock_1.default)(bgUrl)
314
+ .get(`/api/v2/teth/key/user`)
315
+ .reply(200, {
316
+ encryptedPrv: await bitgo.encrypt({ input: userKeypair.xprv, password: sdk_test_1.TestBitGo.TEST_WALLET1_PASSCODE }),
317
+ path: userKeypair.path + userKeypair.walletSubPath,
318
+ });
319
+ };
320
+ const nockFees = function () {
321
+ const scope = (0, nock_1.default)(bgUrl)
322
+ .get('/api/v2/teth/tx/fee')
323
+ .query(true)
324
+ .reply(200, {
325
+ gasLimitEstimate: gasLimitEstimate,
326
+ feeEstimate: gasLimitEstimate * gasPrice,
327
+ });
328
+ return scope;
329
+ };
330
+ const nockBuild = function (walletId) {
331
+ (0, nock_1.default)(bgUrl)
332
+ .post('/api/v2/teth/wallet/' + walletId + '/tx/build')
333
+ .reply(200, { hopTransaction: prebuild, buildParams });
334
+ };
335
+ before(function () {
336
+ gasLimitEstimate = 100000;
337
+ gasPrice = 50000000;
338
+ finalRecipient = '0x5208d8e80c6d1aef9be37b4bd19a9cf75ed93dc8';
339
+ sendAmount = '200000000000000';
340
+ prebuild = {
341
+ tx,
342
+ id: txid,
343
+ signature: bitgoSignature,
344
+ };
345
+ buildParams = {
346
+ recipients: [
347
+ {
348
+ address: finalRecipient,
349
+ amount: sendAmount,
350
+ },
351
+ ],
352
+ hop: true,
353
+ walletPassphrase: sdk_test_1.TestBitGo.TEST_WALLET1_PASSCODE,
354
+ };
355
+ });
356
+ it('should prebuild a hop transaction if given the correct args', async function () {
357
+ await nockUserKey();
358
+ const feeScope = nockFees();
359
+ nockBuild(ethWallet.id());
360
+ const res = (await ethWallet.prebuildTransaction(buildParams));
361
+ should_1.default.exist(res.hopTransaction);
362
+ should_1.default.exist(res.hopTransaction.tx);
363
+ should_1.default.exist(res.hopTransaction.tx);
364
+ should_1.default.exist(res.hopTransaction.id);
365
+ should_1.default.exist(res.hopTransaction.signature);
366
+ should_1.default.not.exist(res.wallet);
367
+ should_1.default.not.exist(res.buildParams);
368
+ feeScope.isDone().should.equal(true);
369
+ const feeReq = feeScope.interceptors[0].req;
370
+ feeReq.path.should.containEql('hop=true');
371
+ feeReq.path.should.containEql('recipient=' + finalRecipient);
372
+ feeReq.path.should.containEql('amount=' + sendAmount);
373
+ });
374
+ });
375
+ });
376
+ describe('Add final signature to ETH tx from offline vault', function () {
377
+ let paramsFromVault, expectedResult, bitgo, coin;
378
+ before(function () {
379
+ const vals = fixtures.getHalfSignedTethFromVault();
380
+ paramsFromVault = vals.paramsFromVault;
381
+ expectedResult = vals.expectedResult;
382
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
383
+ coin = bitgo.coin('teth');
384
+ });
385
+ it('should successfully fully sign a half-signed transaction from the offline vault', async function () {
386
+ const response = (await coin.signTransaction(paramsFromVault));
387
+ const expectedTx = tx_1.Transaction.fromSerializedTx(Buffer.from(expectedResult.txHex, 'hex'));
388
+ const actualTx = tx_1.Transaction.fromSerializedTx(Buffer.from(response.txHex, 'hex'));
389
+ actualTx.nonce.toString().should.deepEqual(expectedTx.nonce.toString());
390
+ should_1.default.exist(actualTx.to);
391
+ actualTx.to?.should.deepEqual(expectedTx.to);
392
+ actualTx.value.should.deepEqual(expectedTx.value);
393
+ actualTx.data.should.deepEqual(expectedTx.data);
394
+ actualTx.isSigned().should.equal(true);
395
+ actualTx.supports(tx_1.Capability.EIP155ReplayProtection).should.equal(false);
396
+ actualTx.verifySignature().should.equal(true);
397
+ should_1.default.exist(actualTx.v);
398
+ actualTx?.v?.toString().should.deepEqual(expectedTx?.v?.toString());
399
+ actualTx?.r?.toString().should.deepEqual(expectedTx?.r?.toString());
400
+ actualTx?.s?.toString().should.deepEqual(expectedTx?.s?.toString());
401
+ actualTx.gasPrice.toString().should.deepEqual(expectedTx.gasPrice.toString());
402
+ actualTx.gasLimit.toString().should.deepEqual(expectedTx.gasLimit.toString());
403
+ response.txHex.toString().should.equal(expectedResult.txHex.toString());
404
+ });
405
+ });
406
+ describe('Add signature to EIP1559 tx from offline vault', function () {
407
+ let bitgo;
408
+ let paramsFromVault, expectedResult, coin;
409
+ before(function () {
410
+ const vals = fixtures.getUnsignedEip1559TethFromVault();
411
+ paramsFromVault = vals.paramsFromVault;
412
+ expectedResult = vals.expectedResult;
413
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
414
+ bitgo.safeRegister('teth', src_1.Teth.createInstance);
415
+ coin = bitgo.coin('teth');
416
+ });
417
+ it('should successfully sign an unsigned transaction from the offline vault', async function* () {
418
+ const response = await coin.signTransaction(paramsFromVault);
419
+ should_1.default.exist(response.halfSigned);
420
+ response.halfSigned.eip1559.should.deepEqual(expectedResult.halfSigned.eip1559);
421
+ response.halfSigned.recipients.should.deepEqual(expectedResult.halfSigned.recipients);
422
+ });
423
+ });
424
+ describe('prebuildTransaction', function () {
425
+ let bitgo;
426
+ let ethWallet;
427
+ let recipients;
428
+ let bgUrl;
429
+ let gasLimit;
430
+ before(function () {
431
+ bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
432
+ src_1.Erc20Token.createTokenConstructors().forEach(({ name, coinConstructor }) => {
433
+ bitgo.safeRegister(name, coinConstructor);
434
+ });
435
+ bitgo.safeRegister('teth', src_1.Teth.createInstance);
436
+ bitgo.initializeTestVars();
437
+ const coin = bitgo.coin('teth');
438
+ ethWallet = coin.newWalletObject({});
439
+ gasLimit = 2100000;
440
+ recipients = [
441
+ {
442
+ address: '0xe59dfe5c67114b39a5662cc856be536c614124c0',
443
+ amount: '100000',
444
+ },
445
+ ];
446
+ bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
447
+ });
448
+ it('should successfully accept gasLimit as a param', async function () {
449
+ const scope = (0, nock_1.default)(bgUrl)
450
+ .post('/api/v2/teth/wallet/' + ethWallet.id() + '/tx/build', {
451
+ recipients,
452
+ gasLimit,
453
+ })
454
+ .reply(200, { success: true });
455
+ const prebuild = await ethWallet.prebuildTransaction({ recipients, gasLimit });
456
+ scope.isDone().should.equal(true);
457
+ prebuild.success.should.equal(true);
458
+ });
459
+ it('should reject hop param for an erc20 token build', async function () {
460
+ const token = bitgo.coin('terc');
461
+ const tokenWallet = token.newWalletObject({});
462
+ recipients = [
463
+ {
464
+ address: '0xe59dfe5c67114b39a5662cc856be536c614124c0',
465
+ amount: '100',
466
+ },
467
+ ];
468
+ await tokenWallet
469
+ .prebuildTransaction({ recipients, hop: true, walletPassphrase: 'hi' })
470
+ .should.be.rejectedWith(`Hop transactions are not enabled for ERC-20 tokens, nor are they necessary. Please remove the 'hop' parameter and try again.`);
471
+ });
472
+ });
473
+ describe('final-sign transaction from WRW', function () {
474
+ it('should add a second signature to unsigned sweep for teth', async function () {
475
+ const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
476
+ const basecoin = bitgo.coin('teth');
477
+ const gasPrice = 200000000000;
478
+ const gasLimit = 500000;
479
+ const prv = 'xprv9s21ZrQH143K3D8TXfvAJgHVfTEeQNW5Ys9wZtnUZkqPzFzSjbEJrWC1vZ4GnXCvR7rQL2UFX3RSuYeU9MrERm1XBvACow7c36vnz5iYyj2'; // placeholder test prv
480
+ const tx = {
481
+ txPrebuild: fixtures.WRWUnsignedSweepETHTx,
482
+ prv,
483
+ };
484
+ // sign transaction once
485
+ const halfSigned = await basecoin.signTransaction(tx);
486
+ const wrapper = {};
487
+ wrapper.txPrebuild = halfSigned;
488
+ wrapper.txPrebuild.recipients = halfSigned.halfSigned.recipients;
489
+ wrapper.txPrebuild.gasPrice = gasPrice.toString();
490
+ wrapper.txPrebuild.gasLimit = gasLimit.toString();
491
+ wrapper.isLastSignature = true;
492
+ wrapper.walletContractAddress = fixtures.WRWUnsignedSweepETHTx.walletContractAddress;
493
+ wrapper.prv = prv;
494
+ // sign transaction twice with the "isLastSignature" flag
495
+ const finalSignedTx = await basecoin.signTransaction(wrapper);
496
+ finalSignedTx.should.have.property('txHex');
497
+ const txBuilder = (0, getBuilder_1.getBuilder)('eth');
498
+ txBuilder.from('0x' + finalSignedTx.txHex); // add a 0x in front of this txhex
499
+ const rebuiltTx = await txBuilder.build();
500
+ const outputs = rebuiltTx.outputs.map((output) => {
501
+ return {
502
+ address: output.address,
503
+ amount: output.value,
504
+ };
505
+ });
506
+ rebuiltTx.signature.length.should.equal(2);
507
+ outputs.length.should.equal(1);
508
+ outputs[0].address.should.equal(fixtures.WRWUnsignedSweepETHTx.recipient.address);
509
+ outputs[0].amount.should.equal(fixtures.WRWUnsignedSweepETHTx.recipient.amount);
510
+ });
511
+ it('should add a second signature to unsigned sweep for erc20 token', async function () {
512
+ const bitgo = sdk_test_1.TestBitGo.decorate(sdk_api_1.BitGoAPI, { env: 'test' });
513
+ src_1.Erc20Token.createTokenConstructors().forEach(({ name, coinConstructor }) => {
514
+ bitgo.safeRegister(name, coinConstructor);
515
+ });
516
+ const basecoin = bitgo.coin('tdai');
517
+ const gasPrice = 200000000000;
518
+ const gasLimit = 500000;
519
+ const prv = 'xprv9s21ZrQH143K3399QBVvbmhs4RB5QzXD8XiW3NwtaeTem93QGd5VNjukUnwJQ94nUgugHSVzSVVe3RP16Urv1ZyijpYdyDamsxf2Shbq4w1'; // placeholder test prv
520
+ const tx = {
521
+ txPrebuild: fixtures.WRWUnsignedSweepERC20Tx,
522
+ prv,
523
+ };
524
+ // sign transaction once
525
+ const halfSigned = await basecoin.signTransaction(tx);
526
+ const wrapper = {};
527
+ wrapper.txPrebuild = halfSigned;
528
+ wrapper.txPrebuild.recipients = halfSigned.halfSigned.recipients;
529
+ wrapper.txPrebuild.gasPrice = gasPrice.toString();
530
+ wrapper.txPrebuild.gasLimit = gasLimit.toString();
531
+ wrapper.isLastSignature = true;
532
+ wrapper.walletContractAddress = fixtures.WRWUnsignedSweepERC20Tx.walletContractAddress;
533
+ wrapper.prv = prv;
534
+ // sign transaction twice with the "isLastSignature" flag
535
+ const finalSignedTx = await basecoin.signTransaction(wrapper);
536
+ finalSignedTx.should.have.property('txHex');
537
+ const txBuilder = (0, getBuilder_1.getBuilder)('eth');
538
+ txBuilder.from('0x' + finalSignedTx.txHex); // add a 0x in front of this txhex
539
+ const rebuiltTx = await txBuilder.build();
540
+ const outputs = rebuiltTx.outputs.map((output) => {
541
+ return {
542
+ address: output.address,
543
+ amount: output.value,
544
+ };
545
+ });
546
+ rebuiltTx.signature.length.should.equal(2);
547
+ outputs.length.should.equal(1);
548
+ outputs[0].address.should.equal(fixtures.WRWUnsignedSweepERC20Tx.recipient.address);
549
+ outputs[0].amount.should.equal(fixtures.WRWUnsignedSweepERC20Tx.recipient.amount);
550
+ });
551
+ });
552
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXRoV2FsbGV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdGVzdC91bml0L2V0aFdhbGxldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG9EQUE0QjtBQUM1QixxREFBOEM7QUFDOUMscURBQXVDO0FBQ3ZDLGdEQUF3QjtBQUN4QixrREFBMEI7QUFDMUIsbURBQW9EO0FBRXBELG1EQUErRDtBQUUvRCx1Q0FBa0U7QUFDbEUsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7QUFFNUMsaURBQStDO0FBQy9DLG1DQUFxRTtBQUNyRSw2Q0FBMEM7QUFFMUMsUUFBUSxDQUFDLHNCQUFzQixFQUFFLEtBQUs7SUFDcEMsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksU0FBUyxDQUFDO0lBQ2QsSUFBSSxVQUFVLENBQUM7SUFDZixJQUFJLEVBQUUsQ0FBQztJQUVQLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsVUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2hELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEMsU0FBUyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDckMsVUFBVSxHQUFHO1lBQ1g7Z0JBQ0UsT0FBTyxFQUFFLDRDQUE0QztnQkFDckQsTUFBTSxFQUFFLFFBQVE7YUFDakI7U0FDRixDQUFDO1FBQ0YsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLHNCQUFzQixFQUFFLENBQUMsRUFBRSxDQUFDO0lBQ2pELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLG1HQUFtRyxFQUFFLEtBQUs7UUFDM0csZUFBSyxDQUFDLElBQUksQ0FBQyxlQUFJLEVBQUUscUJBQXFCLENBQUMsQ0FBQztRQUN4QyxlQUFLLENBQUMsSUFBSSxDQUFDLGVBQUksRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ25DLGVBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7UUFFM0QsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxTQUFTLENBQUMsZUFBZSxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBUSxDQUFDO1FBQ3hHLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDMUQsZUFBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLCtGQUErRixFQUFFLEtBQUs7UUFDdkcsTUFBTSxTQUFTO2FBQ1osZUFBZSxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLENBQUM7YUFDdkQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsaUNBQWlDLENBQUMsQ0FBQztJQUMvRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQywrREFBK0QsRUFBRSxLQUFLO1FBQ3ZFLE1BQU0sU0FBUzthQUNaLGVBQWUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLENBQUM7YUFDaEYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsaUNBQWlDLENBQUMsQ0FBQztJQUMvRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxpREFBaUQsRUFBRSxLQUFLO1FBQ3pELGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFDeEMsZUFBSyxDQUFDLElBQUksQ0FBQyxlQUFJLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNuQyxlQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO1FBQzNELE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLHNCQUFzQixFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDakcsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxTQUFTLENBQUMsZUFBZSxDQUFDO1lBQ3RELFVBQVUsRUFBRSxrQkFBa0I7WUFDOUIsR0FBRyxFQUFFLGFBQWE7U0FDbkIsQ0FBQyxDQUFRLENBQUM7UUFDWCxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQzFELFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDbEQsZUFBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLG1EQUFtRCxFQUFFLEtBQUs7UUFDM0QsTUFBTSxrQkFBa0IsR0FBRztZQUN6QjtnQkFDRSxPQUFPLEVBQUUsNENBQTRDO2dCQUNyRCxNQUFNLEVBQUUsS0FBSztnQkFDYixJQUFJLEVBQUUsNGdCQUE0Z0I7YUFDbmhCO1NBQ0YsQ0FBQztRQUVGLE1BQU0sb0JBQW9CLEdBQUcsRUFBRSxVQUFVLEVBQUUsa0JBQWtCLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUUxRyxlQUFLLENBQUMsSUFBSSxDQUFDLGVBQUksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hDLGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDbkMsZUFBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUMzRCxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxlQUFlLENBQUM7WUFDdEQsVUFBVSxFQUFFLG9CQUFvQjtZQUNoQyxHQUFHLEVBQUUsYUFBYTtTQUNuQixDQUFDLENBQVEsQ0FBQztRQUNYLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDakQsZUFBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsd0NBQXdDLEVBQUUsS0FBSztJQUN0RCxJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxTQUFTLENBQUM7SUFDZCxNQUFNLFVBQVUsR0FBRyxDQUFDLEVBQUUsT0FBTyxFQUFFLDRDQUE0QyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBRWpHLE1BQU0sQ0FBQztRQUNMLEtBQUssR0FBRyxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDdEQsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDM0IsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsVUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ2hELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEMsU0FBUyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkMsQ0FBQyxDQUFDLENBQUM7SUFFSCxTQUFTLENBQUM7UUFDUixlQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbEIsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsK0ZBQStGLEVBQUUsS0FBSztRQUN2RyxlQUFLLENBQUMsSUFBSSxDQUFDLGVBQUksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hDLGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDbkMsZUFBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUUzRCxNQUFNLFVBQVUsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLFVBQVUsRUFBRSxzQkFBc0IsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3pFLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxDQUFDLE1BQU0sU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBUSxDQUFDO1FBQ3BHLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDNUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdUVBQXVFLEVBQUUsS0FBSztRQUMvRSxlQUFLLENBQUMsSUFBSSxDQUFDLGVBQUksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hDLGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDbkMsZUFBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUUzRCxNQUFNLGdCQUFnQixHQUFHLENBQUMsRUFBRSxPQUFPLEVBQUUsNENBQTRDLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDbEcsTUFBTSxVQUFVLEdBQUcsRUFBRSxVQUFVLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLFVBQVUsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLENBQUM7UUFDdkcsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxTQUFTLENBQUMsZUFBZSxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFRLENBQUM7UUFDcEcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxVQUFVLENBQUMsQ0FBQztJQUM1RCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQywyRkFBMkYsRUFBRSxLQUFLO1FBQ25HLGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFDeEMsZUFBSyxDQUFDLElBQUksQ0FBQyxlQUFJLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNuQyxlQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO1FBRTNELE1BQU0sVUFBVSxHQUFHLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUFFLHNCQUFzQixFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDekUsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxTQUFTLENBQUMsZUFBZSxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFRLENBQUM7UUFDcEcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLG9CQUFvQixFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLG9GQUFvRixFQUFFLEtBQUs7UUFDNUYsTUFBTSxTQUFTO2FBQ1osZUFBZSxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsVUFBVSxFQUFFLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxDQUFDO2FBQ25FLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLHVFQUF1RSxDQUFDLENBQUM7SUFDckcsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsd0VBQXdFLEVBQUUsS0FBSztRQUNoRixlQUFLLENBQUMsSUFBSSxDQUFDLGVBQUksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hDLGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDbkMsZUFBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUUzRCxNQUFNLE9BQU8sR0FBRyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDcEUsTUFBTSxVQUFVLEdBQUcsRUFBRSxVQUFVLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxFQUFFLENBQUM7UUFDbEYsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxTQUFTLENBQUMsZUFBZSxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFRLENBQUM7UUFDcEcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN0RCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxpRUFBaUUsRUFBRSxLQUFLO1FBQ3pFLGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFDeEMsZUFBSyxDQUFDLElBQUksQ0FBQyxlQUFJLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUNuQyxlQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxvQ0FBb0MsQ0FBQyxDQUFDO1FBRTNELE1BQU0sT0FBTyxHQUFHLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxvQkFBb0IsRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUNwRSxNQUFNLGFBQWEsR0FBRyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsb0JBQW9CLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFDMUUsTUFBTSxVQUFVLEdBQUcsRUFBRSxVQUFVLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLEVBQUUsQ0FBQztRQUMxRyxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxlQUFlLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQVEsQ0FBQztRQUNwRyxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3RELENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLHdFQUF3RSxFQUFFLEtBQUs7UUFDaEYsZUFBSyxDQUFDLElBQUksQ0FBQyxlQUFJLEVBQUUscUJBQXFCLENBQUMsQ0FBQztRQUN4QyxlQUFLLENBQUMsSUFBSSxDQUFDLGVBQUksRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ25DLGVBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7UUFFM0QsTUFBTSxVQUFVLEdBQUcsRUFBRSxVQUFVLEVBQUUsc0JBQXNCLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ3hGLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxDQUFDLE1BQU0sU0FBUyxDQUFDLGVBQWUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBUSxDQUFDO1FBQ3BHLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsaUVBQWlFLEVBQUUsS0FBSztRQUN6RSxlQUFLLENBQUMsSUFBSSxDQUFDLGVBQUksRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQ3hDLGVBQUssQ0FBQyxJQUFJLENBQUMsZUFBSSxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDbkMsZUFBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsb0NBQW9DLENBQUMsQ0FBQztRQUUzRCxNQUFNLFVBQVUsR0FBRyxFQUFFLFVBQVUsRUFBRSxzQkFBc0IsRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztRQUN4RyxNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxlQUFlLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQVEsQ0FBQztRQUNwRyxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3BELENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUM7QUFFSCxRQUFRLENBQUMsMkJBQTJCLEVBQUU7SUFDcEMsSUFBSSxLQUFtQixDQUFDO0lBQ3hCLElBQUksU0FBUyxDQUFDO0lBQ2QsSUFBSSxFQUFFLENBQUM7SUFDUCxJQUFJLElBQUksQ0FBQztJQUNULElBQUksY0FBYyxDQUFDO0lBQ25CLElBQUksWUFBWSxDQUFDO0lBQ2pCLElBQUksS0FBSyxDQUFDO0lBQ1YsSUFBSSxHQUFHLENBQUM7SUFFUixNQUFNLFdBQVcsR0FBRztRQUNsQixJQUFJLEVBQUUsaUhBQWlIO1FBQ3ZILElBQUksRUFBRSxpSEFBaUg7UUFDdkgsTUFBTSxFQUFFLG9FQUFvRTtRQUM1RSxNQUFNLEVBQUUsa0VBQWtFO1FBQzFFLElBQUksRUFBRSxHQUFHO1FBQ1QsYUFBYSxFQUFFLE1BQU07S0FDdEIsQ0FBQztJQUVGLE1BQU0sQ0FBQztRQUNMLEVBQUU7WUFDQSxnT0FBZ08sQ0FBQztRQUNuTyxJQUFJLEdBQUcsb0VBQW9FLENBQUM7UUFDNUUsWUFBWTtZQUNWLGlIQUFpSCxDQUFDO1FBQ3BILE1BQU0sUUFBUSxHQUFHLGlCQUFLLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDekIsTUFBTSxJQUFJLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNuQyxDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQUcsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2pELGNBQWM7WUFDWixNQUFNO2dCQUNOLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsQ0FDekcsS0FBSyxDQUNOLENBQUM7UUFFSixHQUFHLEdBQUcsTUFBTSxDQUFDO1FBQ2IsS0FBSyxHQUFHLG9CQUFTLENBQUMsUUFBUSxDQUFDLGtCQUFRLEVBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQzlDLEtBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxFQUFFLFVBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNoRCxpQkFBTSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDO1FBQzdDLEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzNCLEtBQUssR0FBRyxpQkFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDaEQsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzFFLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLHlCQUF5QixFQUFFO1FBQ2xDLElBQUksUUFBUSxDQUFDO1FBQ2IsSUFBSSxXQUFXLENBQUM7UUFDaEIsSUFBSSxjQUFjLENBQUM7UUFDbkIsSUFBSSxVQUFVLENBQUM7UUFFZixNQUFNLENBQUM7WUFDTCxjQUFjLEdBQUcsNENBQTRDLENBQUM7WUFDOUQsVUFBVSxHQUFHLGlCQUFpQixDQUFDO1lBQy9CLFFBQVEsR0FBRztnQkFDVCxFQUFFO2dCQUNGLEVBQUUsRUFBRSxJQUFJO2dCQUNSLFNBQVMsRUFBRSxjQUFjO2FBQzFCLENBQUM7WUFDRixXQUFXLEdBQUc7Z0JBQ1osVUFBVSxFQUFFO29CQUNWO3dCQUNFLE9BQU8sRUFBRSxjQUFjO3dCQUN2QixNQUFNLEVBQUUsVUFBVTtxQkFDbkI7aUJBQ0Y7YUFDRixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsb0NBQW9DLEVBQUUsS0FBSztZQUM1QyxNQUFNLFNBQVMsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3RHLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLG9EQUFvRCxFQUFFLEtBQUs7WUFDNUQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7WUFDL0QsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsNENBQTRDLENBQUM7WUFFcEYsTUFBTSxTQUFTLENBQUMsUUFBUTtpQkFDckIsbUJBQW1CLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxjQUFjLENBQUM7aUJBQ3hELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLG1DQUFtQyxDQUFDLENBQUM7UUFDakUsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsb0RBQW9ELEVBQUUsS0FBSztZQUM1RCxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztZQUMvRCxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUM7WUFFakQsTUFBTSxTQUFTLENBQUMsUUFBUTtpQkFDckIsbUJBQW1CLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxjQUFjLENBQUM7aUJBQ3hELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLGdDQUFnQyxDQUFDLENBQUM7UUFDOUQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkNBQTZDLEVBQUUsS0FBSztZQUNyRCxzSEFBc0g7WUFDdEgsTUFBTSxRQUFRLEdBQUcsaUJBQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDO1lBQ2xELGlCQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU87Z0JBQzlCLGlIQUFpSCxDQUFDO1lBRXBILE1BQU0sU0FBUyxDQUFDLFFBQVE7aUJBQ3JCLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxRQUFRLEVBQUUsV0FBVyxDQUFDO2lCQUNyRCxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO1lBQ3hELGlCQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMseUVBQXlFLEVBQUUsS0FBSztZQUNqRixNQUFNLE9BQU8sR0FBRyxvRUFBb0UsQ0FBQztZQUNyRixNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDM0QsTUFBTSxRQUFRLEdBQUcsaUJBQUssQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDaEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDekIsTUFBTSxJQUFJLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNuQyxDQUFDO1lBQ0QsTUFBTSxZQUFZLEdBQ2hCLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDMUcsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDekQsV0FBVyxDQUFDLFNBQVMsR0FBRyxZQUFZLENBQUM7WUFFckMsTUFBTSxTQUFTLENBQUMsUUFBUTtpQkFDckIsbUJBQW1CLENBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxXQUFXLENBQUM7aUJBQ3hELE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLDRCQUE0QixDQUFDLENBQUM7UUFDMUQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQywwQkFBMEIsRUFBRTtRQUNuQyxJQUFJLFFBQVEsQ0FBQztRQUNiLElBQUksV0FBVyxDQUFDO1FBQ2hCLElBQUksY0FBYyxDQUFDO1FBQ25CLElBQUksVUFBVSxDQUFDO1FBQ2YsSUFBSSxnQkFBZ0IsQ0FBQztRQUNyQixJQUFJLFFBQVEsQ0FBQztRQUViLE1BQU0sV0FBVyxHQUFHLEtBQUs7WUFDdkIsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO2lCQUNSLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQztpQkFDNUIsS0FBSyxDQUFDLEdBQUcsRUFBRTtnQkFDVixZQUFZLEVBQUUsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLFdBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLG9CQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQztnQkFDekcsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJLEdBQUcsV0FBVyxDQUFDLGFBQWE7YUFDbkQsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxRQUFRLEdBQUc7WUFDZixNQUFNLEtBQUssR0FBRyxJQUFBLGNBQUksRUFBQyxLQUFLLENBQUM7aUJBQ3RCLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQztpQkFDMUIsS0FBSyxDQUFDLElBQUksQ0FBQztpQkFDWCxLQUFLLENBQUMsR0FBRyxFQUFFO2dCQUNWLGdCQUFnQixFQUFFLGdCQUFnQjtnQkFDbEMsV0FBVyxFQUFFLGdCQUFnQixHQUFHLFFBQVE7YUFDekMsQ0FBQyxDQUFDO1lBQ0wsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDLENBQUM7UUFFRixNQUFNLFNBQVMsR0FBRyxVQUFVLFFBQVE7WUFDbEMsSUFBQSxjQUFJLEVBQUMsS0FBSyxDQUFDO2lCQUNSLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxRQUFRLEdBQUcsV0FBVyxDQUFDO2lCQUNyRCxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQzNELENBQUMsQ0FBQztRQUVGLE1BQU0sQ0FBQztZQUNMLGdCQUFnQixHQUFHLE1BQU0sQ0FBQztZQUMxQixRQUFRLEdBQUcsUUFBUSxDQUFDO1lBQ3BCLGNBQWMsR0FBRyw0Q0FBNEMsQ0FBQztZQUM5RCxVQUFVLEdBQUcsaUJBQWlCLENBQUM7WUFDL0IsUUFBUSxHQUFHO2dCQUNULEVBQUU7Z0JBQ0YsRUFBRSxFQUFFLElBQUk7Z0JBQ1IsU0FBUyxFQUFFLGNBQWM7YUFDMUIsQ0FBQztZQUNGLFdBQVcsR0FBRztnQkFDWixVQUFVLEVBQUU7b0JBQ1Y7d0JBQ0UsT0FBTyxFQUFFLGNBQWM7d0JBQ3ZCLE1BQU0sRUFBRSxVQUFVO3FCQUNuQjtpQkFDRjtnQkFDRCxHQUFHLEVBQUUsSUFBSTtnQkFDVCxnQkFBZ0IsRUFBRSxvQkFBUyxDQUFDLHFCQUFxQjthQUNsRCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkRBQTZELEVBQUUsS0FBSztZQUNyRSxNQUFNLFdBQVcsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sUUFBUSxHQUFHLFFBQVEsRUFBRSxDQUFDO1lBQzVCLFNBQVMsQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMxQixNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sU0FBUyxDQUFDLG1CQUFtQixDQUFDLFdBQVcsQ0FBQyxDQUFRLENBQUM7WUFDdEUsZ0JBQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ2pDLGdCQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEMsZ0JBQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNwQyxnQkFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3BDLGdCQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDM0MsZ0JBQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUM3QixnQkFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2xDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3JDLE1BQU0sTUFBTSxHQUFJLFFBQWdCLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUNyRCxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDMUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFlBQVksR0FBRyxjQUFjLENBQUMsQ0FBQztZQUM3RCxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsU0FBUyxHQUFHLFVBQVUsQ0FBQyxDQUFDO1FBQ3hELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQUVILFFBQVEsQ0FBQyxrREFBa0QsRUFBRTtJQUMzRCxJQUFJLGVBQWUsRUFBRSxjQUFjLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQztJQUNqRCxNQUFNLENBQUM7UUFDTCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUNuRCxlQUFlLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQztRQUN2QyxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUNyQyxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsa0JBQVEsRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzVCLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGlGQUFpRixFQUFFLEtBQUs7UUFDekYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsZUFBZSxDQUFDLENBQVEsQ0FBQztRQUN0RSxNQUFNLFVBQVUsR0FBRyxnQkFBSyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3BGLE1BQU0sUUFBUSxHQUFHLGdCQUFLLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDNUUsUUFBUSxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUN4RSxnQkFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMUIsUUFBUSxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QyxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xELFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEQsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxlQUFVLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3pFLFFBQVEsQ0FBQyxlQUFlLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzlDLGdCQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6QixRQUFRLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ3BFLFFBQVEsRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDcEUsUUFBUSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUNwRSxRQUFRLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVB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ZXNDb250ZW50IjpbImltcG9ydCBzaG91bGQgZnJvbSAnc2hvdWxkJztcbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvLWJldGEvc2VjcDI1NmsxJztcbmltcG9ydCAqIGFzIHNlY3AyNTZrMSBmcm9tICdzZWNwMjU2azEnO1xuaW1wb3J0IG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgc2lub24gZnJvbSAnc2lub24nO1xuaW1wb3J0IHsgY29tbW9uLCBVdGlsIH0gZnJvbSAnQGJpdGdvLWJldGEvc2RrLWNvcmUnO1xuXG5pbXBvcnQgeyBUZXN0Qml0R28sIFRlc3RCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay10ZXN0JztcblxuaW1wb3J0IHsgQ2FwYWJpbGl0eSwgVHJhbnNhY3Rpb24gYXMgRXRoVHggfSBmcm9tICdAZXRoZXJldW1qcy90eCc7XG5jb25zdCBmaXh0dXJlcyA9IHJlcXVpcmUoJy4uL2ZpeHR1cmVzL2V0aCcpO1xuXG5pbXBvcnQgeyBCaXRHb0FQSSB9IGZyb20gJ0BiaXRnby1iZXRhL3Nkay1hcGknO1xuaW1wb3J0IHsgRXJjMjBUb2tlbiwgU2lnblRyYW5zYWN0aW9uT3B0aW9ucywgVGV0aCB9IGZyb20gJy4uLy4uL3NyYyc7XG5pbXBvcnQgeyBnZXRCdWlsZGVyIH0gZnJvbSAnLi9nZXRCdWlsZGVyJztcblxuZGVzY3JpYmUoJ1NpZ24gRVRIIFRyYW5zYWN0aW9uJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGV0aFdhbGxldDtcbiAgbGV0IHJlY2lwaWVudHM7XG4gIGxldCB0eDtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGJpdGdvLnNhZmVSZWdpc3RlcigndGV0aCcsIFRldGguY3JlYXRlSW5zdGFuY2UpO1xuICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJyk7XG4gICAgZXRoV2FsbGV0ID0gY29pbi5uZXdXYWxsZXRPYmplY3Qoe30pO1xuICAgIHJlY2lwaWVudHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6ICcweGU1OWRmZTVjNjcxMTRiMzlhNTY2MmNjODU2YmU1MzZjNjE0MTI0YzAnLFxuICAgICAgICBhbW91bnQ6ICcxMDAwMDAnLFxuICAgICAgfSxcbiAgICBdO1xuICAgIHR4ID0geyByZWNpcGllbnRzLCBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwIH07XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVhZCB0cmFuc2FjdGlvbiByZWNpcGllbnRzIGZyb20gdHhQcmVidWlsZCBldmVuIGlmIG5vbmUgYXJlIHNwZWNpZmllZCBhcyB0b3AtbGV2ZWwgcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIHNpbm9uLnN0dWIoVXRpbCwgJ3hwcnZUb0V0aFByaXZhdGVLZXknKTtcbiAgICBzaW5vbi5zdHViKFV0aWwsICdldGhTaWduTXNnSGFzaCcpO1xuICAgIHNpbm9uLnN0dWIoZXRoV2FsbGV0LmdldE9wZXJhdGlvblNoYTNGb3JFeGVjdXRlQW5kQ29uZmlybSk7XG5cbiAgICBjb25zdCB7IGhhbGZTaWduZWQgfSA9IChhd2FpdCBldGhXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHsgdHhQcmVidWlsZDogdHgsIHBydjogJ215X3VzZXJfcHJ2JyB9KSkgYXMgYW55O1xuICAgIGhhbGZTaWduZWQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnLCByZWNpcGllbnRzKTtcbiAgICBzaW5vbi5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdGhyb3cgYW4gZXJyb3IgaWYgbm8gcmVjaXBpZW50cyBhcmUgaW4gdGhlIHR4UHJlYnVpbGQgYW5kIG5vbmUgYXJlIHNwZWNpZmllZCBhcyBwYXJhbXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYXdhaXQgZXRoV2FsbGV0XG4gICAgICAuc2lnblRyYW5zYWN0aW9uKHsgdHhQcmVidWlsZDoge30sIHBydjogJ215X3VzZXJfcHJ2JyB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3JlY2lwaWVudHMgbWlzc2luZyBvciBub3QgYXJyYXknKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyBhbiBlcnJvciBpZiB0aGUgcmVjaXBpZW50cyBwYXJhbSBpcyBub3QgYW4gYXJyYXknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYXdhaXQgZXRoV2FsbGV0XG4gICAgICAuc2lnblRyYW5zYWN0aW9uKHsgdHhQcmVidWlsZDogeyByZWNpcGllbnRzOiAnbm90LWFycmF5JyB9LCBwcnY6ICdteV91c2VyX3BydicgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdyZWNpcGllbnRzIG1pc3Npbmcgb3Igbm90IGFycmF5Jyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgc2V0IGlzQmF0Y2ggdG8gZmFsc2UgaWYgc2luZ2xlIHJlY2lwaWVudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5zdHViKFV0aWwsICd4cHJ2VG9FdGhQcml2YXRlS2V5Jyk7XG4gICAgc2lub24uc3R1YihVdGlsLCAnZXRoU2lnbk1zZ0hhc2gnKTtcbiAgICBzaW5vbi5zdHViKGV0aFdhbGxldC5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0pO1xuICAgIGNvbnN0IHNpbmdsZVJlY2lwaWVudHNUeCA9IHsgcmVjaXBpZW50czogcmVjaXBpZW50cywgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCwgaXNCYXRjaDogZmFsc2UgfTtcbiAgICBjb25zdCB7IGhhbGZTaWduZWQgfSA9IChhd2FpdCBldGhXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHtcbiAgICAgIHR4UHJlYnVpbGQ6IHNpbmdsZVJlY2lwaWVudHNUeCxcbiAgICAgIHBydjogJ215X3VzZXJfcHJ2JyxcbiAgICB9KSkgYXMgYW55O1xuICAgIGhhbGZTaWduZWQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3JlY2lwaWVudHMnLCByZWNpcGllbnRzKTtcbiAgICBoYWxmU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpc0JhdGNoJywgZmFsc2UpO1xuICAgIHNpbm9uLnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBzZXQgaXNCYXRjaCB0byB0cnVlIGlmIG11bHRpcGxlIHJlY2lwaWVudHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgbXVsdGlwbGVSZWNpcGllbnRzID0gW1xuICAgICAge1xuICAgICAgICBhZGRyZXNzOiAnMHgwYzdmM2JjNWQyYjJjMGRiZWUxYjQ1NTM2YjgyNTY5ZjQxYjU0MzMxJyxcbiAgICAgICAgYW1vdW50OiAnMjAwJyxcbiAgICAgICAgZGF0YTogJzB4Y2Y0YzU4ZTIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBhMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA0MzE3NDViODllNzMyMzBiM2JjOGExOWUwMTkxOTRlZmI0Yjk5ZWZkMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDMxNzQ1Yjg5ZTczMjMwYjNiYzhhMTllMDE5MTk0ZWZiNGI5OWVmZDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDY0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA2NCcsXG4gICAgICB9LFxuICAgIF07XG5cbiAgICBjb25zdCBtdWx0aXBsZVJlY2lwaWVudHNUeCA9IHsgcmVjaXBpZW50czogbXVsdGlwbGVSZWNpcGllbnRzLCBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLCBpc0JhdGNoOiB0cnVlIH07XG5cbiAgICBzaW5vbi5zdHViKFV0aWwsICd4cHJ2VG9FdGhQcml2YXRlS2V5Jyk7XG4gICAgc2lub24uc3R1YihVdGlsLCAnZXRoU2lnbk1zZ0hhc2gnKTtcbiAgICBzaW5vbi5zdHViKGV0aFdhbGxldC5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0pO1xuICAgIGNvbnN0IHsgaGFsZlNpZ25lZCB9ID0gKGF3YWl0IGV0aFdhbGxldC5zaWduVHJhbnNhY3Rpb24oe1xuICAgICAgdHhQcmVidWlsZDogbXVsdGlwbGVSZWNpcGllbnRzVHgsXG4gICAgICBwcnY6ICdteV91c2VyX3BydicsXG4gICAgfSkpIGFzIGFueTtcbiAgICBoYWxmU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpc0JhdGNoJywgdHJ1ZSk7XG4gICAgc2lub24ucmVzdG9yZSgpO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnU2lnbiBFVEggVHJhbnNhY3Rpb24g4oCTIHR4SW5mbyBmYWxsYmFjaycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBldGhXYWxsZXQ7XG4gIGNvbnN0IHJlY2lwaWVudHMgPSBbeyBhZGRyZXNzOiAnMHhlNTlkZmU1YzY3MTE0YjM5YTU2NjJjYzg1NmJlNTM2YzYxNDEyNGMwJywgYW1vdW50OiAnMTAwMDAwJyB9XTtcblxuICBiZWZvcmUoZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuICAgIGJpdGdvLnNhZmVSZWdpc3RlcigndGV0aCcsIFRldGguY3JlYXRlSW5zdGFuY2UpO1xuICAgIGNvbnN0IGNvaW4gPSBiaXRnby5jb2luKCd0ZXRoJyk7XG4gICAgZXRoV2FsbGV0ID0gY29pbi5uZXdXYWxsZXRPYmplY3Qoe30pO1xuICB9KTtcblxuICBhZnRlckVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNpbm9uLnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWFkIHJlY2lwaWVudHMgZnJvbSB0eFByZWJ1aWxkLnR4SW5mby5yZWNpcGllbnRzIHdoZW4gdHhQcmVidWlsZC5yZWNpcGllbnRzIGlzIGFic2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5zdHViKFV0aWwsICd4cHJ2VG9FdGhQcml2YXRlS2V5Jyk7XG4gICAgc2lub24uc3R1YihVdGlsLCAnZXRoU2lnbk1zZ0hhc2gnKTtcbiAgICBzaW5vbi5zdHViKGV0aFdhbGxldC5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0pO1xuXG4gICAgY29uc3QgdHhQcmVidWlsZCA9IHsgdHhJbmZvOiB7IHJlY2lwaWVudHMsIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDEgfSB9O1xuICAgIGNvbnN0IHsgaGFsZlNpZ25lZCB9ID0gKGF3YWl0IGV0aFdhbGxldC5zaWduVHJhbnNhY3Rpb24oeyB0eFByZWJ1aWxkLCBwcnY6ICdteV91c2VyX3BydicgfSkpIGFzIGFueTtcbiAgICBoYWxmU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCdyZWNpcGllbnRzJywgcmVjaXBpZW50cyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcHJlZmVyIHR4UHJlYnVpbGQucmVjaXBpZW50cyBvdmVyIHR4UHJlYnVpbGQudHhJbmZvLnJlY2lwaWVudHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgc2lub24uc3R1YihVdGlsLCAneHBydlRvRXRoUHJpdmF0ZUtleScpO1xuICAgIHNpbm9uLnN0dWIoVXRpbCwgJ2V0aFNpZ25Nc2dIYXNoJyk7XG4gICAgc2lub24uc3R1YihldGhXYWxsZXQuZ2V0T3BlcmF0aW9uU2hhM0ZvckV4ZWN1dGVBbmRDb25maXJtKTtcblxuICAgIGNvbnN0IHR4SW5mb1JlY2lwaWVudHMgPSBbeyBhZGRyZXNzOiAnMHhkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmJywgYW1vdW50OiAnMScgfV07XG4gICAgY29uc3QgdHhQcmVidWlsZCA9IHsgcmVjaXBpZW50cywgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCwgdHhJbmZvOiB7IHJlY2lwaWVudHM6IHR4SW5mb1JlY2lwaWVudHMgfSB9O1xuICAgIGNvbnN0IHsgaGFsZlNpZ25lZCB9ID0gKGF3YWl0IGV0aFdhbGxldC5zaWduVHJhbnNhY3Rpb24oeyB0eFByZWJ1aWxkLCBwcnY6ICdteV91c2VyX3BydicgfSkpIGFzIGFueTtcbiAgICBoYWxmU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCdyZWNpcGllbnRzJywgcmVjaXBpZW50cyk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgdXNlIHR4UHJlYnVpbGQudHhJbmZvLm5leHRDb250cmFjdFNlcXVlbmNlSWQgd2hlbiBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkIGlzIGFic2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5zdHViKFV0aWwsICd4cHJ2VG9FdGhQcml2YXRlS2V5Jyk7XG4gICAgc2lub24uc3R1YihVdGlsLCAnZXRoU2lnbk1zZ0hhc2gnKTtcbiAgICBzaW5vbi5zdHViKGV0aFdhbGxldC5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0pO1xuXG4gICAgY29uc3QgdHhQcmVidWlsZCA9IHsgcmVjaXBpZW50cywgdHhJbmZvOiB7IG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDUgfSB9O1xuICAgIGNvbnN0IHsgaGFsZlNpZ25lZCB9ID0gKGF3YWl0IGV0aFdhbGxldC5zaWduVHJhbnNhY3Rpb24oeyB0eFByZWJ1aWxkLCBwcnY6ICdteV91c2VyX3BydicgfSkpIGFzIGFueTtcbiAgICBoYWxmU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCdjb250cmFjdFNlcXVlbmNlSWQnLCA1KTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCB0aHJvdyB3aGVuIG5leHRDb250cmFjdFNlcXVlbmNlSWQgaXMgYWJzZW50IGZyb20gYm90aCB0eFByZWJ1aWxkIGFuZCB0eEluZm8nLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgYXdhaXQgZXRoV2FsbGV0XG4gICAgICAuc2lnblRyYW5zYWN0aW9uKHsgdHhQcmVidWlsZDogeyByZWNpcGllbnRzIH0sIHBydjogJ215X3VzZXJfcHJ2JyB9KVxuICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ3RyYW5zYWN0aW9uIHByZWJ1aWxkIG1pc3NpbmcgcmVxdWlyZWQgcHJvcGVydHkgbmV4dENvbnRyYWN0U2VxdWVuY2VJZCcpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHVzZSB0eFByZWJ1aWxkLnR4SW5mby5laXAxNTU5IHdoZW4gdHhQcmVidWlsZC5laXAxNTU5IGlzIGFic2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5zdHViKFV0aWwsICd4cHJ2VG9FdGhQcml2YXRlS2V5Jyk7XG4gICAgc2lub24uc3R1YihVdGlsLCAnZXRoU2lnbk1zZ0hhc2gnKTtcbiAgICBzaW5vbi5zdHViKGV0aFdhbGxldC5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0pO1xuXG4gICAgY29uc3QgZWlwMTU1OSA9IHsgbWF4RmVlUGVyR2FzOiAnMTAwJywgbWF4UHJpb3JpdHlGZWVQZXJHYXM6ICcxMCcgfTtcbiAgICBjb25zdCB0eFByZWJ1aWxkID0geyByZWNpcGllbnRzLCBuZXh0Q29udHJhY3RTZXF1ZW5jZUlkOiAwLCB0eEluZm86IHsgZWlwMTU1OSB9IH07XG4gICAgY29uc3QgeyBoYWxmU2lnbmVkIH0gPSAoYXdhaXQgZXRoV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih7IHR4UHJlYnVpbGQsIHBydjogJ215X3VzZXJfcHJ2JyB9KSkgYXMgYW55O1xuICAgIGhhbGZTaWduZWQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2VpcDE1NTknLCBlaXAxNTU5KTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBwcmVmZXIgdHhQcmVidWlsZC5laXAxNTU5IG92ZXIgdHhQcmVidWlsZC50eEluZm8uZWlwMTU1OScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5zdHViKFV0aWwsICd4cHJ2VG9FdGhQcml2YXRlS2V5Jyk7XG4gICAgc2lub24uc3R1YihVdGlsLCAnZXRoU2lnbk1zZ0hhc2gnKTtcbiAgICBzaW5vbi5zdHViKGV0aFdhbGxldC5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0pO1xuXG4gICAgY29uc3QgZWlwMTU1OSA9IHsgbWF4RmVlUGVyR2FzOiAnMjAwJywgbWF4UHJpb3JpdHlGZWVQZXJHYXM6ICcyMCcgfTtcbiAgICBjb25zdCB0eEluZm9FaXAxNTU5ID0geyBtYXhGZWVQZXJHYXM6ICc5OTknLCBtYXhQcmlvcml0eUZlZVBlckdhczogJzk5JyB9O1xuICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7IHJlY2lwaWVudHMsIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsIGVpcDE1NTksIHR4SW5mbzogeyBlaXAxNTU5OiB0eEluZm9FaXAxNTU5IH0gfTtcbiAgICBjb25zdCB7IGhhbGZTaWduZWQgfSA9IChhd2FpdCBldGhXYWxsZXQuc2lnblRyYW5zYWN0aW9uKHsgdHhQcmVidWlsZCwgcHJ2OiAnbXlfdXNlcl9wcnYnIH0pKSBhcyBhbnk7XG4gICAgaGFsZlNpZ25lZC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZWlwMTU1OScsIGVpcDE1NTkpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHVzZSB0eFByZWJ1aWxkLnR4SW5mby5pc0JhdGNoIHdoZW4gdHhQcmVidWlsZC5pc0JhdGNoIGlzIGFic2VudCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBzaW5vbi5zdHViKFV0aWwsICd4cHJ2VG9FdGhQcml2YXRlS2V5Jyk7XG4gICAgc2lub24uc3R1YihVdGlsLCAnZXRoU2lnbk1zZ0hhc2gnKTtcbiAgICBzaW5vbi5zdHViKGV0aFdhbGxldC5nZXRPcGVyYXRpb25TaGEzRm9yRXhlY3V0ZUFuZENvbmZpcm0pO1xuXG4gICAgY29uc3QgdHhQcmVidWlsZCA9IHsgcmVjaXBpZW50cywgbmV4dENvbnRyYWN0U2VxdWVuY2VJZDogMCwgdHhJbmZvOiB7IGlzQmF0Y2g6IHRydWUgfSB9O1xuICAgIGNvbnN0IHsgaGFsZlNpZ25lZCB9ID0gKGF3YWl0IGV0aFdhbGxldC5zaWduVHJhbnNhY3Rpb24oeyB0eFByZWJ1aWxkLCBwcnY6ICdteV91c2VyX3BydicgfSkpIGFzIGFueTtcbiAgICBoYWxmU2lnbmVkLnNob3VsZC5oYXZlLnByb3BlcnR5KCdpc0JhdGNoJywgdHJ1ZSk7XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcHJlZmVyIHR4UHJlYnVpbGQuaXNCYXRjaCBvdmVyIHR4UHJlYnVpbGQudHhJbmZvLmlzQmF0Y2gnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgc2lub24uc3R1YihVdGlsLCAneHBydlRvRXRoUHJpdmF0ZUtleScpO1xuICAgIHNpbm9uLnN0dWIoVXRpbCwgJ2V0aFNpZ25Nc2dIYXNoJyk7XG4gICAgc2lub24uc3R1YihldGhXYWxsZXQuZ2V0T3BlcmF0aW9uU2hhM0ZvckV4ZWN1dGVBbmRDb25maXJtKTtcblxuICAgIGNvbnN0IHR4UHJlYnVpbGQgPSB7IHJlY2lwaWVudHMsIG5leHRDb250cmFjdFNlcXVlbmNlSWQ6IDAsIGlzQmF0Y2g6IGZhbHNlLCB0eEluZm86IHsgaXNCYXRjaDogdHJ1ZSB9IH07XG4gICAgY29uc3QgeyBoYWxmU2lnbmVkIH0gPSAoYXdhaXQgZXRoV2FsbGV0LnNpZ25UcmFuc2FjdGlvbih7IHR4UHJlYnVpbGQsIHBydjogJ215X3VzZXJfcHJ2JyB9KSkgYXMgYW55O1xuICAgIGhhbGZTaWduZWQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2lzQmF0Y2gnLCBmYWxzZSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdFdGhlcmV1bSBIb3AgVHJhbnNhY3Rpb25zJywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IGV0aFdhbGxldDtcbiAgbGV0IHR4O1xuICBsZXQgdHhpZDtcbiAgbGV0IGJpdGdvU2lnbmF0dXJlO1xuICBsZXQgYml0Z29LZXlYcHJ2O1xuICBsZXQgYmdVcmw7XG4gIGxldCBlbnY7XG5cbiAgY29uc3QgdXNlcktleXBhaXIgPSB7XG4gICAgeHBydjogJ3hwcnY5czIxWnJRSDE0M0syZko5MVM0QlJzdXBjWXJFNm1tWTk2ZmNYNUhraG9UcnJ3bXdqZDE2Q244N2NXaW5KakJ5cmZwb2pqeDdlenNKTHg3VEFLTFQ4bThoTTVLYXg5WWNveG5CZUpaM3QyaycsXG4gICAgeHB1YjogJ3hwdWI2NjFNeU13QXFSYmNGOU5jN1RiQm8xclpBYWdpV0VWUFdLYkRLVGhORzh6cWprNzZIQUtMa2FTYlRuNmRLMmRRUGZ1RDd4amljeENaVld2ajY3ZlA1blE5VzdRVVJtb01WQVg4bTZqWnNHcCcsXG4gICAgcmF3UHViOiAnMDJjMTAzYWM3NDQ4MTg3NGI1ZWYwZjM4NWQxMjcyNWU0ZjE0YWVkYzllMDBiYzgxNGNlOTZmNDdmNjJjZTdhZGYyJyxcbiAgICByYXdQcnY6ICc5MzZjNWFmM2Y4YWY4MWY3NWNkYWQxYjA4ZjI5ZTdkOWMwMWU1OThlMmRiMmQ3YmUxOGI5ZTVhODY0NmU4N2M2JyxcbiAgICBwYXRoOiAnbScsXG4gICAgd2FsbGV0U3ViUGF0aDogJy8wLzAnLFxuICB9O1xuXG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgdHggPVxuICAgICAgJzB4Zjg2YzgyMDE1Mjg1MDEyYTA1ZjIwMDgyNTIwODk0NTIwOGQ4ZTgwYzZkMWFlZjliZTM3YjRiZDE5YTljZjc1ZWQ5M2RjODg2YjVlNjIwZjQ4MDAwODAyNmEwMGUxM2Y5ZTBlMTEzMzdiMmIwMjI3ZTM0MTIyMTFkMzYyNWU0M2YxMDgzZmRhMzk5Y2MzNjFkZDRiZjg5MDgzYmEwNmM4MDFhNzYxZTBhYTNiYzhkYjBhYzI1NjhkNTc1YjBmYjMwNmExZjA0ZjRkNWJhODJiYTNjYzBlYTBhODNiZCc7XG4gICAgdHhpZCA9ICcweDBhYzY2OWM1ZmVmODI5NDQ0M2M3NWEzMWUzMmM0NGI5N2JiYzllNDNhMThlYThiZWFiY2MyYTNiNDVlYjZmZmEnO1xuICAgIGJpdGdvS2V5WHBydiA9XG4gICAgICAneHBydjlzMjFaclFIMTQzSzN0cFdCSFdlMzFzTG9YTlJROUF2UllKZ2l0a0t4UTRBVEZRTXd2cjdoSE5xWVJVblM3UHNqekI3YUsxVnhxSEx1TlFqajFzY2tKMkp3bzJxeG1zdmVqd0VDU3BGTWZDJztcbiAgICBjb25zdCBiaXRnb0tleSA9IGJpcDMyLmZyb21CYXNlNTgoYml0Z29LZXlYcHJ2KTtcbiAgICBpZiAoIWJpdGdvS2V5LnByaXZhdGVLZXkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbm8gcHJpdmF0ZUtleScpO1xuICAgIH1cbiAgICBjb25zdCBiaXRnb1hwdWIgPSBiaXRnb0tleS5uZXV0ZXJlZCgpLnRvQmFzZTU4KCk7XG4gICAgYml0Z29TaWduYXR1cmUgPVxuICAgICAgJzB4YWEnICtcbiAgICAgIEJ1ZmZlci5mcm9tKHNlY3AyNTZrMS5lY2RzYVNpZ24oQnVmZmVyLmZyb20odHhpZC5zbGljZSgyKSwgJ2hleCcpLCBiaXRnb0tleS5wcml2YXRlS2V5KS5zaWduYXR1cmUpLnRvU3RyaW5nKFxuICAgICAgICAnaGV4J1xuICAgICAgKTtcblxuICAgIGVudiA9ICd0ZXN0JztcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnYgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0ZXRoJywgVGV0aC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgY29tbW9uLkVudmlyb25tZW50c1tlbnZdLmhzbVhwdWIgPSBiaXRnb1hwdWI7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG4gICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKTtcbiAgICBldGhXYWxsZXQgPSBjb2luLm5ld1dhbGxldE9iamVjdCh7IGtleXM6IFsndXNlcicsICdiYWNrdXAnLCAnYml0Z28nXSB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ1ZlcmlmeSBIU00gSG9wIHByZWJ1aWxkJywgZnVuY3Rpb24gKCkge1xuICAgIGxldCBwcmVidWlsZDtcbiAgICBsZXQgYnVpbGRQYXJhbXM7XG4gICAgbGV0IGZpbmFsUmVjaXBpZW50O1xuICAgIGxldCBzZW5kQW1vdW50O1xuXG4gICAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICAgIGZpbmFsUmVjaXBpZW50ID0gJzB4NTIwOGQ4ZTgwYzZkMWFlZjliZTM3YjRiZDE5YTljZjc1ZWQ5M2RjOCc7XG4gICAgICBzZW5kQW1vdW50ID0gJzIwMDAwMDAwMDAwMDAwMCc7XG4gICAgICBwcmVidWlsZCA9IHtcbiAgICAgICAgdHgsXG4gICAgICAgIGlkOiB0eGlkLFxuICAgICAgICBzaWduYXR1cmU6IGJpdGdvU2lnbmF0dXJlLFxuICAgICAgfTtcbiAgICAgIGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogZmluYWxSZWNpcGllbnQsXG4gICAgICAgICAgICBhbW91bnQ6IHNlbmRBbW91bnQsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGFjY2VwdCBhIHZhbGlkIGhvcCBwcmVidWlsZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IGV0aFdhbGxldC5iYXNlQ29pbi52YWxpZGF0ZUhvcFByZWJ1aWxkKGV0aFdhbGxldCwgcHJlYnVpbGQsIGJ1aWxkUGFyYW1zKS5zaG91bGQuYmUucmVzb2x2ZWQoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCBpZiB0aGUgSFNNIHByZWJ1aWxkIHJlY2lwaWVudCBpcyB3cm9uZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJhZEJ1aWxkUGFyYW1zID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShidWlsZFBhcmFtcykpO1xuICAgICAgYmFkQnVpbGRQYXJhbXMucmVjaXBpZW50c1swXS5hZGRyZXNzID0gJzB4NTRiZjE2MDlhZWVkODA0YWEyMzFmMDhjNTNkYmIxOGY3ZDM3NDYxNSc7XG5cbiAgICAgIGF3YWl0IGV0aFdhbGxldC5iYXNlQ29pblxuICAgICAgICAudmFsaWRhdGVIb3BQcmVidWlsZChldGhXYWxsZXQsIHByZWJ1aWxkLCBiYWRCdWlsZFBhcmFtcylcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2RvZXMgbm90IGVxdWFsIG9yaWdpbmFsIHJlY2lwaWVudC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGlmIHRoZSBIU00gcHJlYnVpbGQgdHggYW1vdW50IGlzIHdyb25nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYmFkQnVpbGRQYXJhbXMgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGJ1aWxkUGFyYW1zKSk7XG4gICAgICBiYWRCdWlsZFBhcmFtcy5yZWNpcGllbnRzWzBdLmFtb3VudCA9ICc1MDAwMDAwMCc7XG5cbiAgICAgIGF3YWl0IGV0aFdhbGxldC5iYXNlQ29pblxuICAgICAgICAudmFsaWRhdGVIb3BQcmVidWlsZChldGhXYWxsZXQsIHByZWJ1aWxkLCBiYWRCdWlsZFBhcmFtcylcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL2RvZXMgbm90IGVxdWFsIG9yaWdpbmFsIGFtb3VudC8pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGlmIHRoZSBIU00gc2lnbmF0dXJlIGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBNb2NraW5nIGEgZGlmZmVyZW50IEJpdEdvIGtleSBtZWFucyB0aGUgc2lnbmluZyBrZXkgc2hvdWxkIGJlIHdyb25nIChpdCBtYXBzIHRvIGEgZGlmZmVyZW50IGFkZHJlc3MgdGhhbiB0aGlzIHhwdWIpXG4gICAgICBjb25zdCBnb29kWHB1YiA9IGNvbW1vbi5FbnZpcm9ubWVudHNbZW52XS5oc21YcHViO1xuICAgICAgY29tbW9uLkVudmlyb25tZW50c1tlbnZdLmhzbVhwdWIgPVxuICAgICAgICAneHB1YjY2MU15TXdBcVJiY0VyRnFWWEdpVUZ2OVllb1BiaE43MlVpTkNVZGo5bmozVDZNOGg3aUtObWJDWXBNVldWWlA3TEEybWEzSFdjUG5nejFnUlRtNEZQZHRtOW1IZnJOdlU5M01Db3N6c0dMJztcblxuICAgICAgYXdhaXQgZXRoV2FsbGV0LmJhc2VDb2luXG4gICAgICAgIC52YWxpZGF0ZUhvcFByZWJ1aWxkKGV0aFdhbGxldCwgcHJlYnVpbGQsIGJ1aWxkUGFyYW1zKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgvSG9wIHR4aWQgc2lnbmF0dXJlIGludmFsaWQvKTtcbiAgICAgIGNvbW1vbi5FbnZpcm9ubWVudHNbZW52XS5oc21YcHViID0gZ29vZFhwdWI7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgaWYgdGhlIEhTTSBzaWduYXR1cmUgc2lnbmVkIHRoZSB3cm9uZyBIU00gY29tbWl0bWVudCBkaWdlc3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiYWRUeGlkID0gJzB4YjRiMzgyN2E1MjljOTE2Njc4NmU3OTY1MjgwMTc4ODlhYzUwMjcyNTViNjViM2ZhMmEzZDNhZDkxMjQ0YTEyYic7XG4gICAgICBjb25zdCBiYWRUeGlkQnVmZmVyID0gQnVmZmVyLmZyb20oYmFkVHhpZC5zbGljZSgyKSwgJ2hleCcpO1xuICAgICAgY29uc3QgeHBydk5vZGUgPSBiaXAzMi5mcm9tQmFzZTU4KGJpdGdvS2V5WHBydik7XG4gICAgICBpZiAoIXhwcnZOb2RlLnByaXZhdGVLZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBwcml2YXRlS2V5Jyk7XG4gICAgICB9XG4gICAgICBjb25zdCBiYWRTaWduYXR1cmUgPVxuICAgICAgICAnMHhhYScgKyBCdWZmZXIuZnJvbShzZWNwMjU2azEuZWNkc2FTaWduKGJhZFR4aWRCdWZmZXIsIHhwcnZOb2RlLnByaXZhdGVLZXkpLnNpZ25hdHVyZSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgY29uc3QgYmFkUHJlYnVpbGQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHByZWJ1aWxkKSk7XG4gICAgICBiYWRQcmVidWlsZC5zaWduYXR1cmUgPSBiYWRTaWduYXR1cmU7XG5cbiAgICAgIGF3YWl0IGV0aFdhbGxldC5iYXNlQ29pblxuICAgICAgICAudmFsaWRhdGVIb3BQcmVidWlsZChldGhXYWxsZXQsIGJhZFByZWJ1aWxkLCBidWlsZFBhcmFtcylcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoL0hvcCB0eGlkIHNpZ25hdHVyZSBpbnZhbGlkLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdQcmVidWlsZCBob3AgdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IHByZWJ1aWxkO1xuICAgIGxldCBidWlsZFBhcmFtcztcbiAgICBsZXQgZmluYWxSZWNpcGllbnQ7XG4gICAgbGV0IHNlbmRBbW91bnQ7XG4gICAgbGV0IGdhc0xpbWl0RXN0aW1hdGU7XG4gICAgbGV0IGdhc1ByaWNlO1xuXG4gICAgY29uc3Qgbm9ja1VzZXJLZXkgPSBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KGAvYXBpL3YyL3RldGgva2V5L3VzZXJgKVxuICAgICAgICAucmVwbHkoMjAwLCB7XG4gICAgICAgICAgZW5jcnlwdGVkUHJ2OiBhd2FpdCBiaXRnby5lbmNyeXB0KHsgaW5wdXQ6IHVzZXJLZXlwYWlyLnhwcnYsIHBhc3N3b3JkOiBUZXN0Qml0R28uVEVTVF9XQUxMRVQxX1BBU1NDT0RFIH0pLFxuICAgICAgICAgIHBhdGg6IHVzZXJLZXlwYWlyLnBhdGggKyB1c2VyS2V5cGFpci53YWxsZXRTdWJQYXRoLFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IG5vY2tGZWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2NvcGUgPSBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YyL3RldGgvdHgvZmVlJylcbiAgICAgICAgLnF1ZXJ5KHRydWUpXG4gICAgICAgIC5yZXBseSgyMDAsIHtcbiAgICAgICAgICBnYXNMaW1pdEVzdGltYXRlOiBnYXNMaW1pdEVzdGltYXRlLFxuICAgICAgICAgIGZlZUVzdGltYXRlOiBnYXNMaW1pdEVzdGltYXRlICogZ2FzUHJpY2UsXG4gICAgICAgIH0pO1xuICAgICAgcmV0dXJuIHNjb3BlO1xuICAgIH07XG5cbiAgICBjb25zdCBub2NrQnVpbGQgPSBmdW5jdGlvbiAod2FsbGV0SWQpIHtcbiAgICAgIG5vY2soYmdVcmwpXG4gICAgICAgIC5wb3N0KCcvYXBpL3YyL3RldGgvd2FsbGV0LycgKyB3YWxsZXRJZCArICcvdHgvYnVpbGQnKVxuICAgICAgICAucmVwbHkoMjAwLCB7IGhvcFRyYW5zYWN0aW9uOiBwcmVidWlsZCwgYnVpbGRQYXJhbXMgfSk7XG4gICAgfTtcblxuICAgIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgICBnYXNMaW1pdEVzdGltYXRlID0gMTAwMDAwO1xuICAgICAgZ2FzUHJpY2UgPSA1MDAwMDAwMDtcbiAgICAgIGZpbmFsUmVjaXBpZW50ID0gJzB4NTIwOGQ4ZTgwYzZkMWFlZjliZTM3YjRiZDE5YTljZjc1ZWQ5M2RjOCc7XG4gICAgICBzZW5kQW1vdW50ID0gJzIwMDAwMDAwMDAwMDAwMCc7XG4gICAgICBwcmVidWlsZCA9IHtcbiAgICAgICAgdHgsXG4gICAgICAgIGlkOiB0eGlkLFxuICAgICAgICBzaWduYXR1cmU6IGJpdGdvU2lnbmF0dXJlLFxuICAgICAgfTtcbiAgICAgIGJ1aWxkUGFyYW1zID0ge1xuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogZmluYWxSZWNpcGllbnQsXG4gICAgICAgICAgICBhbW91bnQ6IHNlbmRBbW91bnQsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgaG9wOiB0cnVlLFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBUZXN0Qml0R28uVEVTVF9XQUxMRVQxX1BBU1NDT0RFLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcHJlYnVpbGQgYSBob3AgdHJhbnNhY3Rpb24gaWYgZ2l2ZW4gdGhlIGNvcnJlY3QgYXJncycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IG5vY2tVc2VyS2V5KCk7XG4gICAgICBjb25zdCBmZWVTY29wZSA9IG5vY2tGZWVzKCk7XG4gICAgICBub2NrQnVpbGQoZXRoV2FsbGV0LmlkKCkpO1xuICAgICAgY29uc3QgcmVzID0gKGF3YWl0IGV0aFdhbGxldC5wcmVidWlsZFRyYW5zYWN0aW9uKGJ1aWxkUGFyYW1zKSkgYXMgYW55O1xuICAgICAgc2hvdWxkLmV4aXN0KHJlcy5ob3BUcmFuc2FjdGlvbik7XG4gICAgICBzaG91bGQuZXhpc3QocmVzLmhvcFRyYW5zYWN0aW9uLnR4KTtcbiAgICAgIHNob3VsZC5leGlzdChyZXMuaG9wVHJhbnNhY3Rpb24udHgpO1xuICAgICAgc2hvdWxkLmV4aXN0KHJlcy5ob3BUcmFuc2FjdGlvbi5pZCk7XG4gICAgICBzaG91bGQuZXhpc3QocmVzLmhvcFRyYW5zYWN0aW9uLnNpZ25hdHVyZSk7XG4gICAgICBzaG91bGQubm90LmV4aXN0KHJlcy53YWxsZXQpO1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChyZXMuYnVpbGRQYXJhbXMpO1xuICAgICAgZmVlU2NvcGUuaXNEb25lKCkuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgY29uc3QgZmVlUmVxID0gKGZlZVNjb3BlIGFzIGFueSkuaW50ZXJjZXB0b3JzWzBdLnJlcTtcbiAgICAgIGZlZVJlcS5wYXRoLnNob3VsZC5jb250YWluRXFsKCdob3A9dHJ1ZScpO1xuICAgICAgZmVlUmVxLnBhdGguc2hvdWxkLmNvbnRhaW5FcWwoJ3JlY2lwaWVudD0nICsgZmluYWxSZWNpcGllbnQpO1xuICAgICAgZmVlUmVxLnBhdGguc2hvdWxkLmNvbnRhaW5FcWwoJ2Ftb3VudD0nICsgc2VuZEFtb3VudCk7XG4gICAgfSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdBZGQgZmluYWwgc2lnbmF0dXJlIHRvIEVUSCB0eCBmcm9tIG9mZmxpbmUgdmF1bHQnLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBwYXJhbXNGcm9tVmF1bHQsIGV4cGVjdGVkUmVzdWx0LCBiaXRnbywgY29pbjtcbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB2YWxzID0gZml4dHVyZXMuZ2V0SGFsZlNpZ25lZFRldGhGcm9tVmF1bHQoKTtcbiAgICBwYXJhbXNGcm9tVmF1bHQgPSB2YWxzLnBhcmFtc0Zyb21WYXVsdDtcbiAgICBleHBlY3RlZFJlc3VsdCA9IHZhbHMuZXhwZWN0ZWRSZXN1bHQ7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBzdWNjZXNzZnVsbHkgZnVsbHkgc2lnbiBhIGhhbGYtc2lnbmVkIHRyYW5zYWN0aW9uIGZyb20gdGhlIG9mZmxpbmUgdmF1bHQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSAoYXdhaXQgY29pbi5zaWduVHJhbnNhY3Rpb24ocGFyYW1zRnJvbVZhdWx0KSkgYXMgYW55O1xuICAgIGNvbnN0IGV4cGVjdGVkVHggPSBFdGhUeC5mcm9tU2VyaWFsaXplZFR4KEJ1ZmZlci5mcm9tKGV4cGVjdGVkUmVzdWx0LnR4SGV4LCAnaGV4JykpO1xuICAgIGNvbnN0IGFjdHVhbFR4ID0gRXRoVHguZnJvbVNlcmlhbGl6ZWRUeChCdWZmZXIuZnJvbShyZXNwb25zZS50eEhleCwgJ2hleCcpKTtcbiAgICBhY3R1YWxUeC5ub25jZS50b1N0cmluZygpLnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWRUeC5ub25jZS50b1N0cmluZygpKTtcbiAgICBzaG91bGQuZXhpc3QoYWN0dWFsVHgudG8pO1xuICAgIGFjdHVhbFR4LnRvPy5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkVHgudG8pO1xuICAgIGFjdHVhbFR4LnZhbHVlLnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWRUeC52YWx1ZSk7XG4gICAgYWN0dWFsVHguZGF0YS5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkVHguZGF0YSk7XG4gICAgYWN0dWFsVHguaXNTaWduZWQoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgYWN0dWFsVHguc3VwcG9ydHMoQ2FwYWJpbGl0eS5FSVAxNTVSZXBsYXlQcm90ZWN0aW9uKS5zaG91bGQuZXF1YWwoZmFsc2UpO1xuICAgIGFjdHVhbFR4LnZlcmlmeVNpZ25hdHVyZSgpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICBzaG91bGQuZXhpc3QoYWN0dWFsVHgudik7XG4gICAgYWN0dWFsVHg/LnY/LnRvU3RyaW5nKCkuc2hvdWxkLmRlZXBFcXVhbChleHBlY3RlZFR4Py52Py50b1N0cmluZygpKTtcbiAgICBhY3R1YWxUeD8ucj8udG9TdHJpbmcoKS5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkVHg/LnI/LnRvU3RyaW5nKCkpO1xuICAgIGFjdHVhbFR4Py5zPy50b1N0cmluZygpLnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWRUeD8ucz8udG9TdHJpbmcoKSk7XG4gICAgYWN0dWFsVHguZ2FzUHJpY2UudG9TdHJpbmcoKS5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkVHguZ2FzUHJpY2UudG9TdHJpbmcoKSk7XG4gICAgYWN0dWFsVHguZ2FzTGltaXQudG9TdHJpbmcoKS5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkVHguZ2FzTGltaXQudG9TdHJpbmcoKSk7XG4gICAgcmVzcG9uc2UudHhIZXgudG9TdHJpbmcoKS5zaG91bGQuZXF1YWwoZXhwZWN0ZWRSZXN1bHQudHhIZXgudG9TdHJpbmcoKSk7XG4gIH0pO1xufSk7XG5cbmRlc2NyaWJlKCdBZGQgc2lnbmF0dXJlIHRvIEVJUDE1NTkgdHggZnJvbSBvZmZsaW5lIHZhdWx0JywgZnVuY3Rpb24gKCkge1xuICBsZXQgYml0Z286IFRlc3RCaXRHb0FQSTtcbiAgbGV0IHBhcmFtc0Zyb21WYXVsdCwgZXhwZWN0ZWRSZXN1bHQsIGNvaW47XG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdmFscyA9IGZpeHR1cmVzLmdldFVuc2lnbmVkRWlwMTU1OVRldGhGcm9tVmF1bHQoKTtcbiAgICBwYXJhbXNGcm9tVmF1bHQgPSB2YWxzLnBhcmFtc0Zyb21WYXVsdDtcbiAgICBleHBlY3RlZFJlc3VsdCA9IHZhbHMuZXhwZWN0ZWRSZXN1bHQ7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R29BUEksIHsgZW52OiAndGVzdCcgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0ZXRoJywgVGV0aC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBzdWNjZXNzZnVsbHkgc2lnbiBhbiB1bnNpZ25lZCB0cmFuc2FjdGlvbiBmcm9tIHRoZSBvZmZsaW5lIHZhdWx0JywgYXN5bmMgZnVuY3Rpb24qICgpIHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNvaW4uc2lnblRyYW5zYWN0aW9uKHBhcmFtc0Zyb21WYXVsdCk7XG4gICAgc2hvdWxkLmV4aXN0KHJlc3BvbnNlLmhhbGZTaWduZWQpO1xuICAgIHJlc3BvbnNlLmhhbGZTaWduZWQuZWlwMTU1OS5zaG91bGQuZGVlcEVxdWFsKGV4cGVjdGVkUmVzdWx0LmhhbGZTaWduZWQuZWlwMTU1OSk7XG4gICAgcmVzcG9uc2UuaGFsZlNpZ25lZC5yZWNpcGllbnRzLnNob3VsZC5kZWVwRXF1YWwoZXhwZWN0ZWRSZXN1bHQuaGFsZlNpZ25lZC5yZWNpcGllbnRzKTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ3ByZWJ1aWxkVHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gIGxldCBiaXRnbzogVGVzdEJpdEdvQVBJO1xuICBsZXQgZXRoV2FsbGV0O1xuICBsZXQgcmVjaXBpZW50cztcbiAgbGV0IGJnVXJsO1xuICBsZXQgZ2FzTGltaXQ7XG5cbiAgYmVmb3JlKGZ1bmN0aW9uICgpIHtcbiAgICBiaXRnbyA9IFRlc3RCaXRHby5kZWNvcmF0ZShCaXRHb0FQSSwgeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBFcmMyMFRva2VuLmNyZWF0ZVRva2VuQ29uc3RydWN0b3JzKCkuZm9yRWFjaCgoeyBuYW1lLCBjb2luQ29uc3RydWN0b3IgfSkgPT4ge1xuICAgICAgYml0Z28uc2FmZVJlZ2lzdGVyKG5hbWUsIGNvaW5Db25zdHJ1Y3Rvcik7XG4gICAgfSk7XG4gICAgYml0Z28uc2FmZVJlZ2lzdGVyKCd0ZXRoJywgVGV0aC5jcmVhdGVJbnN0YW5jZSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgY29uc3QgY29pbiA9IGJpdGdvLmNvaW4oJ3RldGgnKTtcbiAgICBldGhXYWxsZXQgPSBjb2luLm5ld1dhbGxldE9iamVjdCh7fSk7XG4gICAgZ2FzTGltaXQgPSAyMTAwMDAwO1xuICAgIHJlY2lwaWVudHMgPSBbXG4gICAgICB7XG4gICAgICAgIGFkZHJlc3M6ICcweGU1OWRmZTVjNjcxMTRiMzlhNTY2MmNjODU2YmU1MzZjNjE0MTI0YzAnLFxuICAgICAgICBhbW91bnQ6ICcxMDAwMDAnLFxuICAgICAgfSxcbiAgICBdO1xuICAgIGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHN1Y2Nlc3NmdWxseSBhY2NlcHQgZ2FzTGltaXQgYXMgYSBwYXJhbScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBzY29wZSA9IG5vY2soYmdVcmwpXG4gICAgICAucG9zdCgnL2FwaS92Mi90ZXRoL3dhbGxldC8nICsgZXRoV2FsbGV0LmlkKCkgKyAnL3R4L2J1aWxkJywge1xuICAgICAgICByZWNpcGllbnRzLFxuICAgICAgICBnYXNMaW1pdCxcbiAgICAgIH0pXG4gICAgICAucmVwbHkoMjAwLCB7IHN1Y2Nlc3M6IHRydWUgfSk7XG4gICAgY29uc3QgcHJlYnVpbGQgPSBhd2FpdCBldGhXYWxsZXQucHJlYnVpbGRUcmFuc2FjdGlvbih7IHJlY2lwaWVudHMsIGdhc0xpbWl0IH0pO1xuICAgIHNjb3BlLmlzRG9uZSgpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICBwcmVidWlsZC5zdWNjZXNzLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWplY3QgaG9wIHBhcmFtIGZvciBhbiBlcmMyMCB0b2tlbiBidWlsZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0b2tlbiA9IGJpdGdvLmNvaW4oJ3RlcmMnKTtcbiAgICBjb25zdCB0b2tlbldhbGxldCA9IHRva2VuLm5ld1dhbGxldE9iamVjdCh7fSk7XG4gICAgcmVjaXBpZW50cyA9IFtcbiAgICAgIHtcbiAgICAgICAgYWRkcmVzczogJzB4ZTU5ZGZlNWM2NzExNGIzOWE1NjYyY2M4NTZiZTUzNmM2MTQxMjRjMCcsXG4gICAgICAgIGFtb3VudDogJzEwMCcsXG4gICAgICB9LFxuICAgIF07XG4gICAgYXdhaXQgdG9rZW5XYWxsZXRcbiAgICAgIC5wcmVidWlsZFRyYW5zYWN0aW9uKHsgcmVjaXBpZW50cywgaG9wOiB0cnVlLCB3YWxsZXRQYXNzcGhyYXNlOiAnaGknIH0pXG4gICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgYEhvcCB0cmFuc2FjdGlvbnMgYXJlIG5vdCBlbmFibGVkIGZvciBFUkMtMjAgdG9rZW5zLCBub3IgYXJlIHRoZXkgbmVjZXNzYXJ5LiBQbGVhc2UgcmVtb3ZlIHRoZSAnaG9wJyBwYXJhbWV0ZXIgYW5kIHRyeSBhZ2Fpbi5gXG4gICAgICApO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnZmluYWwtc2lnbiB0cmFuc2FjdGlvbiBmcm9tIFdSVycsIGZ1bmN0aW9uICgpIHtcbiAgaXQoJ3Nob3VsZCBhZGQgYSBzZWNvbmQgc2lnbmF0dXJlIHRvIHVuc2lnbmVkIHN3ZWVwIGZvciB0ZXRoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuXG4gICAgY29uc3QgYmFzZWNvaW46IGFueSA9IGJpdGdvLmNvaW4oJ3RldGgnKTtcbiAgICBjb25zdCBnYXNQcmljZSA9IDIwMDAwMDAwMDAwMDtcbiAgICBjb25zdCBnYXNMaW1pdCA9IDUwMDAwMDtcbiAgICBjb25zdCBwcnYgPVxuICAgICAgJ3hwcnY5czIxWnJRSDE0M0szRDhUWGZ2QUpnSFZmVEVlUU5XNVlzOXdadG5VWmtxUHpGelNqYkVKcldDMXZaNEduWEN2UjdyUUwyVUZYM1JTdVllVTlNckVSbTFYQnZBQ293N2MzNnZuejVpWXlqMic7IC8vIHBsYWNlaG9sZGVyIHRlc3QgcHJ2XG4gICAgY29uc3QgdHggPSB7XG4gICAgICB0eFByZWJ1aWxkOiBmaXh0dXJlcy5XUldVbnNpZ25lZFN3ZWVwRVRIVHgsXG4gICAgICBwcnYsXG4gICAgfTtcbiAgICAvLyBzaWduIHRyYW5zYWN0aW9uIG9uY2VcbiAgICBjb25zdCBoYWxmU2lnbmVkID0gYXdhaXQgYmFzZWNvaW4uc2lnblRyYW5zYWN0aW9uKHR4KTtcblxuICAgIGNvbnN0IHdyYXBwZXIgPSB7fSBhcyBTaWduVHJhbnNhY3Rpb25PcHRpb25zO1xuICAgIHdyYXBwZXIudHhQcmVidWlsZCA9IGhhbGZTaWduZWQ7XG4gICAgd3JhcHBlci50eFByZWJ1aWxkLnJlY2lwaWVudHMgPSBoYWxmU2lnbmVkLmhhbGZTaWduZWQucmVjaXBpZW50cztcbiAgICB3cmFwcGVyLnR4UHJlYnVpbGQuZ2FzUHJpY2UgPSBnYXNQcmljZS50b1N0cmluZygpO1xuICAgIHdyYXBwZXIudHhQcmVidWlsZC5nYXNMaW1pdCA9IGdhc0xpbWl0LnRvU3RyaW5nKCk7XG4gICAgd3JhcHBlci5pc0xhc3RTaWduYXR1cmUgPSB0cnVlO1xuICAgIHdyYXBwZXIud2FsbGV0Q29udHJhY3RBZGRyZXNzID0gZml4dHVyZXMuV1JXVW5zaWduZWRTd2VlcEVUSFR4LndhbGxldENvbnRyYWN0QWRkcmVzcztcbiAgICB3cmFwcGVyLnBydiA9IHBydjtcblxuICAgIC8vIHNpZ24gdHJhbnNhY3Rpb24gdHdpY2Ugd2l0aCB0aGUgXCJpc0xhc3RTaWduYXR1cmVcIiBmbGFnXG4gICAgY29uc3QgZmluYWxTaWduZWRUeCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih3cmFwcGVyKTtcbiAgICBmaW5hbFNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eEhleCcpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2V0aCcpO1xuICAgIHR4QnVpbGRlci5mcm9tKCcweCcgKyBmaW5hbFNpZ25lZFR4LnR4SGV4KTsgLy8gYWRkIGEgMHggaW4gZnJvbnQgb2YgdGhpcyB0eGhleFxuICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGNvbnN0IG91dHB1dHMgPSByZWJ1aWx0VHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkcmVzczogb3V0cHV0LmFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogb3V0cHV0LnZhbHVlLFxuICAgICAgfTtcbiAgICB9KTtcbiAgICByZWJ1aWx0VHguc2lnbmF0dXJlLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgb3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgIG91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoZml4dHVyZXMuV1JXVW5zaWduZWRTd2VlcEVUSFR4LnJlY2lwaWVudC5hZGRyZXNzKTtcbiAgICBvdXRwdXRzWzBdLmFtb3VudC5zaG91bGQuZXF1YWwoZml4dHVyZXMuV1JXVW5zaWduZWRTd2VlcEVUSFR4LnJlY2lwaWVudC5hbW91bnQpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGFkZCBhIHNlY29uZCBzaWduYXR1cmUgdG8gdW5zaWduZWQgc3dlZXAgZm9yIGVyYzIwIHRva2VuJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvQVBJLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIEVyYzIwVG9rZW4uY3JlYXRlVG9rZW5Db25zdHJ1Y3RvcnMoKS5mb3JFYWNoKCh7IG5hbWUsIGNvaW5Db25zdHJ1Y3RvciB9KSA9PiB7XG4gICAgICBiaXRnby5zYWZlUmVnaXN0ZXIobmFtZSwgY29pbkNvbnN0cnVjdG9yKTtcbiAgICB9KTtcbiAgICBjb25zdCBiYXNlY29pbjogYW55ID0gYml0Z28uY29pbigndGRhaScpO1xuICAgIGNvbnN0IGdhc1ByaWNlID0gMjAwMDAwMDAwMDAwO1xuICAgIGNvbnN0IGdhc0xpbWl0ID0gNTAwMDAwO1xuICAgIGNvbnN0IHBydiA9XG4gICAgICAneHBydjlzMjFaclFIMTQzSzMzOTlRQlZ2Ym1oczRSQjVRelhEOFhpVzNOd3RhZVRlbTkzUUdkNVZOanVrVW53SlE5NG5VZ3VnSFNWelNWVmUzUlAxNlVydjFaeWlqcFlkeURhbXN4ZjJTaGJxNHcxJzsgLy8gcGxhY2Vob2xkZXIgdGVzdCBwcnZcbiAgICBjb25zdCB0eCA9IHtcbiAgICAgIHR4UHJlYnVpbGQ6IGZpeHR1cmVzLldSV1Vuc2lnbmVkU3dlZXBFUkMyMFR4LFxuICAgICAgcHJ2LFxuICAgIH07XG4gICAgLy8gc2lnbiB0cmFuc2FjdGlvbiBvbmNlXG4gICAgY29uc3QgaGFsZlNpZ25lZCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih0eCk7XG5cbiAgICBjb25zdCB3cmFwcGVyID0ge30gYXMgU2lnblRyYW5zYWN0aW9uT3B0aW9ucztcbiAgICB3cmFwcGVyLnR4UHJlYnVpbGQgPSBoYWxmU2lnbmVkO1xuICAgIHdyYXBwZXIudHhQcmVidWlsZC5yZWNpcGllbnRzID0gaGFsZlNpZ25lZC5oYWxmU2lnbmVkLnJlY2lwaWVudHM7XG4gICAgd3JhcHBlci50eFByZWJ1aWxkLmdhc1ByaWNlID0gZ2FzUHJpY2UudG9TdHJpbmcoKTtcbiAgICB3cmFwcGVyLnR4UHJlYnVpbGQuZ2FzTGltaXQgPSBnYXNMaW1pdC50b1N0cmluZygpO1xuICAgIHdyYXBwZXIuaXNMYXN0U2lnbmF0dXJlID0gdHJ1ZTtcbiAgICB3cmFwcGVyLndhbGxldENvbnRyYWN0QWRkcmVzcyA9IGZpeHR1cmVzLldSV1Vuc2lnbmVkU3dlZXBFUkMyMFR4LndhbGxldENvbnRyYWN0QWRkcmVzcztcbiAgICB3cmFwcGVyLnBydiA9IHBydjtcblxuICAgIC8vIHNpZ24gdHJhbnNhY3Rpb24gdHdpY2Ugd2l0aCB0aGUgXCJpc0xhc3RTaWduYXR1cmVcIiBmbGFnXG4gICAgY29uc3QgZmluYWxTaWduZWRUeCA9IGF3YWl0IGJhc2Vjb2luLnNpZ25UcmFuc2FjdGlvbih3cmFwcGVyKTtcbiAgICBmaW5hbFNpZ25lZFR4LnNob3VsZC5oYXZlLnByb3BlcnR5KCd0eEhleCcpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGdldEJ1aWxkZXIoJ2V0aCcpO1xuICAgIHR4QnVpbGRlci5mcm9tKCcweCcgKyBmaW5hbFNpZ25lZFR4LnR4SGV4KTsgLy8gYWRkIGEgMHggaW4gZnJvbnQgb2YgdGhpcyB0eGhleFxuICAgIGNvbnN0IHJlYnVpbHRUeCA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGNvbnN0IG91dHB1dHMgPSByZWJ1aWx0VHgub3V0cHV0cy5tYXAoKG91dHB1dCkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYWRkcmVzczogb3V0cHV0LmFkZHJlc3MsXG4gICAgICAgIGFtb3VudDogb3V0cHV0LnZhbHVlLFxuICAgICAgfTtcbiAgICB9KTtcbiAgICByZWJ1aWx0VHguc2lnbmF0dXJlLmxlbmd0aC5zaG91bGQuZXF1YWwoMik7XG4gICAgb3V0cHV0cy5sZW5ndGguc2hvdWxkLmVxdWFsKDEpO1xuICAgIG91dHB1dHNbMF0uYWRkcmVzcy5zaG91bGQuZXF1YWwoZml4dHVyZXMuV1JXVW5zaWduZWRTd2VlcEVSQzIwVHgucmVjaXBpZW50LmFkZHJlc3MpO1xuICAgIG91dHB1dHNbMF0uYW1vdW50LnNob3VsZC5lcXVhbChmaXh0dXJlcy5XUldVbnNpZ25lZFN3ZWVwRVJDMjBUeC5yZWNpcGllbnQuYW1vdW50KTtcbiAgfSk7XG59KTtcbiJdfQ==