UNPKG

42.6 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const tslib_1 = require("tslib");
4const client_common_1 = require("@neo-one/client-common");
5const node_core_1 = require("@neo-one/node-core");
6const bn_js_1 = require("bn.js");
7const lodash_1 = tslib_1.__importDefault(require("lodash"));
8const ValidatorCache_1 = require("./ValidatorCache");
9const processOutput = async (blockchain, cache, output, negative) => {
10 let { value } = output;
11 if (negative) {
12 value = value.neg();
13 }
14 const [account] = await Promise.all([
15 cache.getAccount(output.address),
16 cache.updateAccountBalance(output.address, output.asset, value),
17 ]);
18 if (client_common_1.common.uInt256Equal(output.asset, blockchain.settings.governingToken.hash) && account.votes.length > 0) {
19 await Promise.all([
20 Promise.all(account.votes.map(async (publicKey) => cache.updateValidatorVotes(publicKey, value))),
21 cache.updateValidatorsCountVotes(account.votes.length - 1, value),
22 ]);
23 }
24};
25const processTransaction = async (blockchain, cache, transaction) => {
26 let allOutputs = await Promise.all(transaction.inputs.map(async (input) => {
27 const output = await blockchain.output.get(input);
28 return { output, negative: true };
29 }));
30 allOutputs = allOutputs.concat(transaction.outputs.map((output) => ({ output, negative: false })));
31 await Promise.all(allOutputs.map(async ({ output, negative }) => processOutput(blockchain, cache, output, negative)));
32 const accountHashes = [...new Set(allOutputs.map(({ output }) => client_common_1.common.uInt160ToHex(output.address)))].map((hash) => client_common_1.common.hexToUInt160(hash));
33 const touchedValidators = await Promise.all(accountHashes.map(async (hash) => {
34 const account = await cache.getAccount(hash);
35 return account.votes;
36 }));
37 const touchedValidatorsSet = [
38 ...new Set(touchedValidators.reduce((acc, votes) => acc.concat(votes.map((vote) => client_common_1.common.ecPointToHex(vote))), [])),
39 ].map((publicKey) => client_common_1.common.hexToECPoint(publicKey));
40 await Promise.all(touchedValidatorsSet.map(async (publicKey) => {
41 const validator = await cache.getValidator(publicKey);
42 if (!validator.registered && validator.votes.eq(node_core_1.utils.ZERO)) {
43 await cache.deleteValidator(publicKey);
44 }
45 }));
46};
47exports.getDescriptorChanges = async ({ transactions, getAccount, governingTokenHash, }) => {
48 const accountChanges = {};
49 const validatorVotesChanges = {};
50 const validatorRegisteredChanges = {};
51 const validatorsCountChanges = [];
52 const allDescriptors = transactions.reduce((acc, transaction) => acc.concat(transaction.descriptors), []);
53 const accountDescriptors = allDescriptors.filter((descriptor) => descriptor.type === 0x40);
54 const groupedAccountDescriptors = Object.entries(lodash_1.default.groupBy(accountDescriptors, (descriptor) => client_common_1.common.uInt160ToHex(client_common_1.common.bufferToUInt160(descriptor.key))));
55 await Promise.all(groupedAccountDescriptors.map(async ([hash, descriptors]) => {
56 const account = await getAccount(client_common_1.common.hexToUInt160(hash));
57 const balance = account.getBalance(governingTokenHash);
58 for (const vote of account.votes) {
59 const voteHex = client_common_1.common.ecPointToHex(vote);
60 validatorVotesChanges[voteHex] = (validatorVotesChanges[voteHex] === undefined
61 ? node_core_1.utils.ZERO
62 : validatorVotesChanges[voteHex]).sub(balance);
63 }
64 const descriptor = descriptors[descriptors.length - 1];
65 const reader = new node_core_1.BinaryReader(descriptor.value);
66 const votes = reader.readArray(() => reader.readECPoint());
67 if (votes.length !== account.votes.length) {
68 if (account.votes.length > 0) {
69 validatorsCountChanges[account.votes.length - 1] = (validatorsCountChanges[account.votes.length - 1] === undefined
70 ? node_core_1.utils.ZERO
71 : validatorsCountChanges[account.votes.length - 1]).sub(balance);
72 }
73 if (votes.length > 0) {
74 validatorsCountChanges[votes.length - 1] = (validatorsCountChanges[votes.length - 1] ===
75 undefined
76 ? node_core_1.utils.ZERO
77 : validatorsCountChanges[votes.length - 1]).add(balance);
78 }
79 }
80 accountChanges[hash] = votes;
81 for (const vote of votes) {
82 const voteHex = client_common_1.common.ecPointToHex(vote);
83 validatorVotesChanges[voteHex] = (validatorVotesChanges[voteHex] === undefined
84 ? node_core_1.utils.ZERO
85 : validatorVotesChanges[voteHex]).add(balance);
86 }
87 }));
88 const validatorDescriptors = allDescriptors.filter((descriptor) => descriptor.type === 0x48);
89 for (const descriptor of validatorDescriptors) {
90 const publicKey = client_common_1.common.bufferToECPoint(descriptor.key);
91 validatorRegisteredChanges[client_common_1.common.ecPointToHex(publicKey)] = descriptor.value.some((byte) => byte !== 0);
92 }
93 const validatorChanges = {};
94 for (const [publicKey, votes] of Object.entries(validatorVotesChanges)) {
95 validatorChanges[publicKey] = { votes };
96 }
97 for (const [publicKey, registered] of Object.entries(validatorRegisteredChanges)) {
98 const current = validatorChanges[publicKey] === undefined ? {} : validatorChanges[publicKey];
99 validatorChanges[publicKey] = {
100 registered,
101 votes: current.votes,
102 };
103 }
104 return {
105 accountChanges,
106 validatorChanges,
107 validatorsCountChanges,
108 };
109};
110exports.processStateTransaction = async ({ validatorChanges, validatorsCountChanges, tryGetValidatorsCount, addValidatorsCount, updateValidatorsCount, tryGetValidator, addValidator, deleteValidator, updateValidator, }) => {
111 const validatorsCount = await tryGetValidatorsCount();
112 const mutableValidatorsCountVotes = validatorsCount === undefined ? [] : [...validatorsCount.votes];
113 [...validatorsCountChanges.entries()].forEach(([index, value]) => {
114 mutableValidatorsCountVotes[index] = value;
115 });
116 await Promise.all([
117 Promise.all(Object.entries(validatorChanges).map(async ([publicKeyHex, { registered, votes }]) => {
118 const publicKey = client_common_1.common.hexToECPoint(publicKeyHex);
119 const validator = await tryGetValidator({ publicKey });
120 if (validator === undefined) {
121 await addValidator(new node_core_1.Validator({
122 publicKey,
123 registered,
124 votes,
125 }));
126 }
127 else if (((registered !== undefined && !registered) || (registered === undefined && !validator.registered)) &&
128 ((votes !== undefined && votes.eq(node_core_1.utils.ZERO)) || (votes === undefined && validator.votes.eq(node_core_1.utils.ZERO)))) {
129 await deleteValidator({ publicKey: validator.publicKey });
130 }
131 else {
132 await updateValidator(validator, { votes, registered });
133 }
134 })),
135 validatorsCount === undefined
136 ? addValidatorsCount(new node_core_1.ValidatorsCount({
137 votes: mutableValidatorsCountVotes,
138 }))
139 : updateValidatorsCount(validatorsCount, {
140 votes: mutableValidatorsCountVotes,
141 }),
142 ]);
143};
144exports.getValidators = async (blockchain, transactions) => {
145 const cache = new ValidatorCache_1.ValidatorCache(blockchain);
146 await Promise.all(transactions.map(async (transaction) => processTransaction(blockchain, cache, transaction)));
147 const { validatorChanges, validatorsCountChanges } = await exports.getDescriptorChanges({
148 transactions: transactions.filter((transaction) => transaction.type === node_core_1.TransactionType.State && transaction instanceof node_core_1.StateTransaction),
149 getAccount: async (hash) => cache.getAccount(hash),
150 governingTokenHash: blockchain.settings.governingToken.hashHex,
151 });
152 await exports.processStateTransaction({
153 validatorChanges,
154 validatorsCountChanges,
155 tryGetValidatorsCount: async () => cache.getValidatorsCount(),
156 addValidatorsCount: async (value) => cache.addValidatorsCount(value),
157 updateValidatorsCount: async (update) => {
158 await cache.updateValidatorsCount(update);
159 },
160 tryGetValidator: async (key) => cache.getValidator(key.publicKey),
161 addValidator: async (validator) => cache.addValidator(validator),
162 deleteValidator: async (key) => cache.deleteValidator(key.publicKey),
163 updateValidator: async (value, update) => cache.updateValidator(value.publicKey, update),
164 });
165 const [validatorsCount, validators] = await Promise.all([cache.getValidatorsCount(), cache.getAllValidators()]);
166 const numValidators = Math.max(node_core_1.utils.weightedAverage(node_core_1.utils
167 .weightedFilter(validatorsCount.votes
168 .map((votes, count) => ({ count, votes: votes === undefined ? node_core_1.utils.ZERO : votes }))
169 .filter(({ votes }) => votes.gt(node_core_1.utils.ZERO)), 0.25, 0.75, ({ count }) => new bn_js_1.BN(count))
170 .map(([{ count }, weight]) => ({ value: count, weight }))), blockchain.settings.standbyValidators.length);
171 const standbyValidatorsSet = new Set(blockchain.settings.standbyValidators.map((publicKey) => client_common_1.common.ecPointToHex(publicKey)));
172 const validatorsPublicKeySet = new Set(lodash_1.default.take(validators
173 .filter((validator) => (validator.registered && validator.votes.gt(node_core_1.utils.ZERO)) ||
174 standbyValidatorsSet.has(client_common_1.common.ecPointToHex(validator.publicKey)))
175 .sort((aValidator, bValidator) => aValidator.votes.eq(bValidator.votes)
176 ? client_common_1.common.ecPointCompare(aValidator.publicKey, bValidator.publicKey)
177 : -aValidator.votes.cmp(bValidator.votes))
178 .map((validator) => client_common_1.common.ecPointToHex(validator.publicKey)), numValidators));
179 const standbyValidatorsArray = [...standbyValidatorsSet];
180 for (let i = 0; i < standbyValidatorsArray.length && validatorsPublicKeySet.size < numValidators; i += 1) {
181 validatorsPublicKeySet.add(standbyValidatorsArray[i]);
182 }
183 const validatorsPublicKeys = [...validatorsPublicKeySet].map((hex) => client_common_1.common.hexToECPoint(hex));
184 return validatorsPublicKeys.sort((aKey, bKey) => client_common_1.common.ecPointCompare(aKey, bKey));
185};
186
187//# sourceMappingURL=data:application/json;charset=utf8;base64,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by1vbmUtbm9kZS1ibG9ja2NoYWluL3NyYy9nZXRWYWxpZGF0b3JzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdHNsaW50OmRpc2FibGUgbm8tb2JqZWN0LW11dGF0aW9uIG5vLWFycmF5LW11dGF0aW9uIG5vLWxvb3Atc3RhdGVtZW50XG5pbXBvcnQgeyBjb21tb24sIEVDUG9pbnQsIFVJbnQxNjAsIFVJbnQyNTZIZXggfSBmcm9tICdAbmVvLW9uZS9jbGllbnQtY29tbW9uJztcbmltcG9ydCB7XG4gIEFjY291bnQsXG4gIEJpbmFyeVJlYWRlcixcbiAgT3V0cHV0LFxuICBTdGF0ZURlc2NyaXB0b3IsXG4gIFN0YXRlVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uLFxuICBUcmFuc2FjdGlvblR5cGUsXG4gIHV0aWxzLFxuICBWYWxpZGF0b3IsXG4gIFZhbGlkYXRvcktleSxcbiAgVmFsaWRhdG9yc0NvdW50LFxuICBWYWxpZGF0b3JzQ291bnRVcGRhdGUsXG4gIFZhbGlkYXRvclVwZGF0ZSxcbn0gZnJvbSAnQG5lby1vbmUvbm9kZS1jb3JlJztcbmltcG9ydCB7IEJOIH0gZnJvbSAnYm4uanMnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEJsb2NrY2hhaW4gfSBmcm9tICcuL0Jsb2NrY2hhaW4nO1xuaW1wb3J0IHsgVmFsaWRhdG9yQ2FjaGUgfSBmcm9tICcuL1ZhbGlkYXRvckNhY2hlJztcblxuY29uc3QgcHJvY2Vzc091dHB1dCA9IGFzeW5jIChcbiAgYmxvY2tjaGFpbjogQmxvY2tjaGFpbixcbiAgY2FjaGU6IFZhbGlkYXRvckNhY2hlLFxuICBvdXRwdXQ6IE91dHB1dCxcbiAgbmVnYXRpdmU6IGJvb2xlYW4sXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgbGV0IHsgdmFsdWUgfSA9IG91dHB1dDtcbiAgaWYgKG5lZ2F0aXZlKSB7XG4gICAgdmFsdWUgPSB2YWx1ZS5uZWcoKTtcbiAgfVxuICBjb25zdCBbYWNjb3VudF0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgY2FjaGUuZ2V0QWNjb3VudChvdXRwdXQuYWRkcmVzcyksXG4gICAgY2FjaGUudXBkYXRlQWNjb3VudEJhbGFuY2Uob3V0cHV0LmFkZHJlc3MsIG91dHB1dC5hc3NldCwgdmFsdWUpLFxuICBdKTtcblxuICBpZiAoY29tbW9uLnVJbnQyNTZFcXVhbChvdXRwdXQuYXNzZXQsIGJsb2NrY2hhaW4uc2V0dGluZ3MuZ292ZXJuaW5nVG9rZW4uaGFzaCkgJiYgYWNjb3VudC52b3Rlcy5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgUHJvbWlzZS5hbGwoYWNjb3VudC52b3Rlcy5tYXAoYXN5bmMgKHB1YmxpY0tleSkgPT4gY2FjaGUudXBkYXRlVmFsaWRhdG9yVm90ZXMocHVibGljS2V5LCB2YWx1ZSkpKSxcblxuICAgICAgY2FjaGUudXBkYXRlVmFsaWRhdG9yc0NvdW50Vm90ZXMoYWNjb3VudC52b3Rlcy5sZW5ndGggLSAxLCB2YWx1ZSksXG4gICAgXSk7XG4gIH1cbn07XG5cbmNvbnN0IHByb2Nlc3NUcmFuc2FjdGlvbiA9IGFzeW5jIChcbiAgYmxvY2tjaGFpbjogQmxvY2tjaGFpbixcbiAgY2FjaGU6IFZhbGlkYXRvckNhY2hlLFxuICB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24sXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgbGV0IGFsbE91dHB1dHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICB0cmFuc2FjdGlvbi5pbnB1dHMubWFwKGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgYmxvY2tjaGFpbi5vdXRwdXQuZ2V0KGlucHV0KTtcblxuICAgICAgcmV0dXJuIHsgb3V0cHV0LCBuZWdhdGl2ZTogdHJ1ZSB9O1xuICAgIH0pLFxuICApO1xuXG4gIGFsbE91dHB1dHMgPSBhbGxPdXRwdXRzLmNvbmNhdCh0cmFuc2FjdGlvbi5vdXRwdXRzLm1hcCgob3V0cHV0KSA9PiAoeyBvdXRwdXQsIG5lZ2F0aXZlOiBmYWxzZSB9KSkpO1xuXG4gIGF3YWl0IFByb21pc2UuYWxsKGFsbE91dHB1dHMubWFwKGFzeW5jICh7IG91dHB1dCwgbmVnYXRpdmUgfSkgPT4gcHJvY2Vzc091dHB1dChibG9ja2NoYWluLCBjYWNoZSwgb3V0cHV0LCBuZWdhdGl2ZSkpKTtcblxuICBjb25zdCBhY2NvdW50SGFzaGVzID0gWy4uLm5ldyBTZXQoYWxsT3V0cHV0cy5tYXAoKHsgb3V0cHV0IH0pID0+IGNvbW1vbi51SW50MTYwVG9IZXgob3V0cHV0LmFkZHJlc3MpKSldLm1hcCgoaGFzaCkgPT5cbiAgICBjb21tb24uaGV4VG9VSW50MTYwKGhhc2gpLFxuICApO1xuICBjb25zdCB0b3VjaGVkVmFsaWRhdG9ycyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGFjY291bnRIYXNoZXMubWFwKGFzeW5jIChoYXNoKSA9PiB7XG4gICAgICBjb25zdCBhY2NvdW50ID0gYXdhaXQgY2FjaGUuZ2V0QWNjb3VudChoYXNoKTtcblxuICAgICAgcmV0dXJuIGFjY291bnQudm90ZXM7XG4gICAgfSksXG4gICk7XG5cbiAgY29uc3QgdG91Y2hlZFZhbGlkYXRvcnNTZXQgPSBbXG4gICAgLi4ubmV3IFNldChcbiAgICAgIHRvdWNoZWRWYWxpZGF0b3JzLnJlZHVjZTxyZWFkb25seSBzdHJpbmdbXT4oXG4gICAgICAgIChhY2MsIHZvdGVzKSA9PiBhY2MuY29uY2F0KHZvdGVzLm1hcCgodm90ZSkgPT4gY29tbW9uLmVjUG9pbnRUb0hleCh2b3RlKSkpLFxuICAgICAgICBbXSxcbiAgICAgICksXG4gICAgKSxcbiAgXS5tYXAoKHB1YmxpY0tleSkgPT4gY29tbW9uLmhleFRvRUNQb2ludChwdWJsaWNLZXkpKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgdG91Y2hlZFZhbGlkYXRvcnNTZXQubWFwKGFzeW5jIChwdWJsaWNLZXkpID0+IHtcbiAgICAgIGNvbnN0IHZhbGlkYXRvciA9IGF3YWl0IGNhY2hlLmdldFZhbGlkYXRvcihwdWJsaWNLZXkpO1xuICAgICAgaWYgKCF2YWxpZGF0b3IucmVnaXN0ZXJlZCAmJiB2YWxpZGF0b3Iudm90ZXMuZXEodXRpbHMuWkVSTykpIHtcbiAgICAgICAgYXdhaXQgY2FjaGUuZGVsZXRlVmFsaWRhdG9yKHB1YmxpY0tleSk7XG4gICAgICB9XG4gICAgfSksXG4gICk7XG59O1xuXG4vLyB0c2xpbnQ6ZGlzYWJsZSByZWFkb25seS1rZXl3b3JkIHJlYWRvbmx5LWFycmF5XG5leHBvcnQgaW50ZXJmYWNlIEFjY291bnRDaGFuZ2VzIHtcbiAgW2hhc2g6IHN0cmluZ106IHJlYWRvbmx5IEVDUG9pbnRbXTtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgVmFsaWRhdG9yVm90ZXNDaGFuZ2VzIHtcbiAgW2hhc2g6IHN0cmluZ106IEJOO1xufVxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0b3JSZWdpc3RlcmVkQ2hhbmdlcyB7XG4gIFtoYXNoOiBzdHJpbmddOiBib29sZWFuO1xufVxuaW50ZXJmYWNlIFZhbGlkYXRvckNoYW5nZSB7XG4gIHJlYWRvbmx5IHJlZ2lzdGVyZWQ/OiBib29sZWFuO1xuICByZWFkb25seSB2b3Rlcz86IEJOO1xufVxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0b3JDaGFuZ2VzIHtcbiAgW2hhc2g6IHN0cmluZ106IFZhbGlkYXRvckNoYW5nZTtcbn1cbmV4cG9ydCB0eXBlIFZhbGlkYXRvcnNDb3VudENoYW5nZXMgPSBCTltdO1xuLy8gdHNsaW50OmVuYWJsZSByZWFkb25seS1rZXl3b3JkIHJlYWRvbmx5LWFycmF5XG5cbmV4cG9ydCBjb25zdCBnZXREZXNjcmlwdG9yQ2hhbmdlcyA9IGFzeW5jICh7XG4gIHRyYW5zYWN0aW9ucyxcbiAgZ2V0QWNjb3VudCxcbiAgZ292ZXJuaW5nVG9rZW5IYXNoLFxufToge1xuICByZWFkb25seSB0cmFuc2FjdGlvbnM6IHJlYWRvbmx5IFN0YXRlVHJhbnNhY3Rpb25bXTtcbiAgcmVhZG9ubHkgZ2V0QWNjb3VudDogKGhhc2g6IFVJbnQxNjApID0+IFByb21pc2U8QWNjb3VudD47XG4gIHJlYWRvbmx5IGdvdmVybmluZ1Rva2VuSGFzaDogVUludDI1NkhleDtcbn0pOiBQcm9taXNlPHtcbiAgcmVhZG9ubHkgYWNjb3VudENoYW5nZXM6IEFjY291bnRDaGFuZ2VzO1xuICByZWFkb25seSB2YWxpZGF0b3JDaGFuZ2VzOiBWYWxpZGF0b3JDaGFuZ2VzO1xuICByZWFkb25seSB2YWxpZGF0b3JzQ291bnRDaGFuZ2VzOiBWYWxpZGF0b3JzQ291bnRDaGFuZ2VzO1xufT4gPT4ge1xuICBjb25zdCBhY2NvdW50Q2hhbmdlczogQWNjb3VudENoYW5nZXMgPSB7fTtcbiAgY29uc3QgdmFsaWRhdG9yVm90ZXNDaGFuZ2VzOiBWYWxpZGF0b3JWb3Rlc0NoYW5nZXMgPSB7fTtcbiAgY29uc3QgdmFsaWRhdG9yUmVnaXN0ZXJlZENoYW5nZXM6IFZhbGlkYXRvclJlZ2lzdGVyZWRDaGFuZ2VzID0ge307XG4gIGNvbnN0IHZhbGlkYXRvcnNDb3VudENoYW5nZXM6IFZhbGlkYXRvcnNDb3VudENoYW5nZXMgPSBbXTtcbiAgY29uc3QgYWxsRGVzY3JpcHRvcnMgPSB0cmFuc2FjdGlvbnMucmVkdWNlPHJlYWRvbmx5IFN0YXRlRGVzY3JpcHRvcltdPihcbiAgICAoYWNjLCB0cmFuc2FjdGlvbikgPT4gYWNjLmNvbmNhdCh0cmFuc2FjdGlvbi5kZXNjcmlwdG9ycyksXG4gICAgW10sXG4gICk7XG5cbiAgY29uc3QgYWNjb3VudERlc2NyaXB0b3JzID0gYWxsRGVzY3JpcHRvcnMuZmlsdGVyKChkZXNjcmlwdG9yKSA9PiBkZXNjcmlwdG9yLnR5cGUgPT09IDB4NDApO1xuXG4gIGNvbnN0IGdyb3VwZWRBY2NvdW50RGVzY3JpcHRvcnMgPSBPYmplY3QuZW50cmllcyhcbiAgICBfLmdyb3VwQnkoYWNjb3VudERlc2NyaXB0b3JzLCAoZGVzY3JpcHRvcikgPT4gY29tbW9uLnVJbnQxNjBUb0hleChjb21tb24uYnVmZmVyVG9VSW50MTYwKGRlc2NyaXB0b3Iua2V5KSkpLFxuICApO1xuXG4gIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGdyb3VwZWRBY2NvdW50RGVzY3JpcHRvcnMubWFwKGFzeW5jIChbaGFzaCwgZGVzY3JpcHRvcnNdKSA9PiB7XG4gICAgICBjb25zdCBhY2NvdW50ID0gYXdhaXQgZ2V0QWNjb3VudChjb21tb24uaGV4VG9VSW50MTYwKGhhc2gpKTtcbiAgICAgIGNvbnN0IGJhbGFuY2UgPSBhY2NvdW50LmdldEJhbGFuY2UoZ292ZXJuaW5nVG9rZW5IYXNoKTtcblxuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gICAgICBmb3IgKGNvbnN0IHZvdGUgb2YgYWNjb3VudC52b3Rlcykge1xuICAgICAgICBjb25zdCB2b3RlSGV4ID0gY29tbW9uLmVjUG9pbnRUb0hleCh2b3RlKTtcbiAgICAgICAgdmFsaWRhdG9yVm90ZXNDaGFuZ2VzW3ZvdGVIZXhdID0gKCh2YWxpZGF0b3JWb3Rlc0NoYW5nZXNbdm90ZUhleF0gYXMgQk4gfCB1bmRlZmluZWQpID09PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHV0aWxzLlpFUk9cbiAgICAgICAgICA6IHZhbGlkYXRvclZvdGVzQ2hhbmdlc1t2b3RlSGV4XVxuICAgICAgICApLnN1YihiYWxhbmNlKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JzW2Rlc2NyaXB0b3JzLmxlbmd0aCAtIDFdO1xuICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEJpbmFyeVJlYWRlcihkZXNjcmlwdG9yLnZhbHVlKTtcbiAgICAgIGNvbnN0IHZvdGVzID0gcmVhZGVyLnJlYWRBcnJheSgoKSA9PiByZWFkZXIucmVhZEVDUG9pbnQoKSk7XG4gICAgICBpZiAodm90ZXMubGVuZ3RoICE9PSBhY2NvdW50LnZvdGVzLmxlbmd0aCkge1xuICAgICAgICBpZiAoYWNjb3VudC52b3Rlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdmFsaWRhdG9yc0NvdW50Q2hhbmdlc1thY2NvdW50LnZvdGVzLmxlbmd0aCAtIDFdID0gKCh2YWxpZGF0b3JzQ291bnRDaGFuZ2VzW2FjY291bnQudm90ZXMubGVuZ3RoIC0gMV0gYXNcbiAgICAgICAgICAgIHwgQk5cbiAgICAgICAgICAgIHwgdW5kZWZpbmVkKSA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IHV0aWxzLlpFUk9cbiAgICAgICAgICAgIDogdmFsaWRhdG9yc0NvdW50Q2hhbmdlc1thY2NvdW50LnZvdGVzLmxlbmd0aCAtIDFdXG4gICAgICAgICAgKS5zdWIoYmFsYW5jZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodm90ZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHZhbGlkYXRvcnNDb3VudENoYW5nZXNbdm90ZXMubGVuZ3RoIC0gMV0gPSAoKHZhbGlkYXRvcnNDb3VudENoYW5nZXNbdm90ZXMubGVuZ3RoIC0gMV0gYXMgQk4gfCB1bmRlZmluZWQpID09PVxuICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgPyB1dGlscy5aRVJPXG4gICAgICAgICAgICA6IHZhbGlkYXRvcnNDb3VudENoYW5nZXNbdm90ZXMubGVuZ3RoIC0gMV1cbiAgICAgICAgICApLmFkZChiYWxhbmNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhY2NvdW50Q2hhbmdlc1toYXNoXSA9IHZvdGVzO1xuICAgICAgZm9yIChjb25zdCB2b3RlIG9mIHZvdGVzKSB7XG4gICAgICAgIGNvbnN0IHZvdGVIZXggPSBjb21tb24uZWNQb2ludFRvSGV4KHZvdGUpO1xuICAgICAgICB2YWxpZGF0b3JWb3Rlc0NoYW5nZXNbdm90ZUhleF0gPSAoKHZhbGlkYXRvclZvdGVzQ2hhbmdlc1t2b3RlSGV4XSBhcyBCTiB8IHVuZGVmaW5lZCkgPT09IHVuZGVmaW5lZFxuICAgICAgICAgID8gdXRpbHMuWkVST1xuICAgICAgICAgIDogdmFsaWRhdG9yVm90ZXNDaGFuZ2VzW3ZvdGVIZXhdXG4gICAgICAgICkuYWRkKGJhbGFuY2UpO1xuICAgICAgfVxuICAgIH0pLFxuICApO1xuXG4gIGNvbnN0IHZhbGlkYXRvckRlc2NyaXB0b3JzID0gYWxsRGVzY3JpcHRvcnMuZmlsdGVyKChkZXNjcmlwdG9yKSA9PiBkZXNjcmlwdG9yLnR5cGUgPT09IDB4NDgpO1xuXG4gIGZvciAoY29uc3QgZGVzY3JpcHRvciBvZiB2YWxpZGF0b3JEZXNjcmlwdG9ycykge1xuICAgIGNvbnN0IHB1YmxpY0tleSA9IGNvbW1vbi5idWZmZXJUb0VDUG9pbnQoZGVzY3JpcHRvci5rZXkpO1xuICAgIHZhbGlkYXRvclJlZ2lzdGVyZWRDaGFuZ2VzW2NvbW1vbi5lY1BvaW50VG9IZXgocHVibGljS2V5KV0gPSBkZXNjcmlwdG9yLnZhbHVlLnNvbWUoKGJ5dGUpID0+IGJ5dGUgIT09IDApO1xuICB9XG5cbiAgY29uc3QgdmFsaWRhdG9yQ2hhbmdlczogVmFsaWRhdG9yQ2hhbmdlcyA9IHt9O1xuICBmb3IgKGNvbnN0IFtwdWJsaWNLZXksIHZvdGVzXSBvZiBPYmplY3QuZW50cmllcyh2YWxpZGF0b3JWb3Rlc0NoYW5nZXMpKSB7XG4gICAgdmFsaWRhdG9yQ2hhbmdlc1twdWJsaWNLZXldID0geyB2b3RlcyB9O1xuICB9XG5cbiAgZm9yIChjb25zdCBbcHVibGljS2V5LCByZWdpc3RlcmVkXSBvZiBPYmplY3QuZW50cmllcyh2YWxpZGF0b3JSZWdpc3RlcmVkQ2hhbmdlcykpIHtcbiAgICBjb25zdCBjdXJyZW50ID1cbiAgICAgICh2YWxpZGF0b3JDaGFuZ2VzW3B1YmxpY0tleV0gYXMgVmFsaWRhdG9yQ2hhbmdlIHwgdW5kZWZpbmVkKSA9PT0gdW5kZWZpbmVkID8ge30gOiB2YWxpZGF0b3JDaGFuZ2VzW3B1YmxpY0tleV07XG4gICAgdmFsaWRhdG9yQ2hhbmdlc1twdWJsaWNLZXldID0ge1xuICAgICAgcmVnaXN0ZXJlZCxcbiAgICAgIHZvdGVzOiBjdXJyZW50LnZvdGVzLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFjY291bnRDaGFuZ2VzLFxuICAgIHZhbGlkYXRvckNoYW5nZXMsXG4gICAgdmFsaWRhdG9yc0NvdW50Q2hhbmdlcyxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwcm9jZXNzU3RhdGVUcmFuc2FjdGlvbiA9IGFzeW5jICh7XG4gIHZhbGlkYXRvckNoYW5nZXMsXG4gIHZhbGlkYXRvcnNDb3VudENoYW5nZXMsXG4gIHRyeUdldFZhbGlkYXRvcnNDb3VudCxcbiAgYWRkVmFsaWRhdG9yc0NvdW50LFxuICB1cGRhdGVWYWxpZGF0b3JzQ291bnQsXG4gIHRyeUdldFZhbGlkYXRvcixcbiAgYWRkVmFsaWRhdG9yLFxuICBkZWxldGVWYWxpZGF0b3IsXG4gIHVwZGF0ZVZhbGlkYXRvcixcbn06IHtcbiAgcmVhZG9ubHkgdmFsaWRhdG9yQ2hhbmdlczogVmFsaWRhdG9yQ2hhbmdlcztcbiAgcmVhZG9ubHkgdmFsaWRhdG9yc0NvdW50Q2hhbmdlczogVmFsaWRhdG9yc0NvdW50Q2hhbmdlcztcbiAgcmVhZG9ubHkgdHJ5R2V0VmFsaWRhdG9yc0NvdW50OiAoKSA9PiBQcm9taXNlPFZhbGlkYXRvcnNDb3VudCB8IHVuZGVmaW5lZD47XG4gIHJlYWRvbmx5IGFkZFZhbGlkYXRvcnNDb3VudDogKHZhbGlkYXRvcnNDb3VudDogVmFsaWRhdG9yc0NvdW50KSA9PiBQcm9taXNlPHZvaWQ+O1xuICByZWFkb25seSB1cGRhdGVWYWxpZGF0b3JzQ291bnQ6ICh2YWxpZGF0b3JzQ291bnQ6IFZhbGlkYXRvcnNDb3VudCwgdXBkYXRlOiBWYWxpZGF0b3JzQ291bnRVcGRhdGUpID0+IFByb21pc2U8dm9pZD47XG5cbiAgcmVhZG9ubHkgdHJ5R2V0VmFsaWRhdG9yOiAoa2V5OiBWYWxpZGF0b3JLZXkpID0+IFByb21pc2U8VmFsaWRhdG9yIHwgdW5kZWZpbmVkPjtcbiAgcmVhZG9ubHkgYWRkVmFsaWRhdG9yOiAodmFsaWRhdG9yOiBWYWxpZGF0b3IpID0+IFByb21pc2U8dm9pZD47XG4gIHJlYWRvbmx5IGRlbGV0ZVZhbGlkYXRvcjogKGtleTogVmFsaWRhdG9yS2V5KSA9PiBQcm9taXNlPHZvaWQ+O1xuICByZWFkb25seSB1cGRhdGVWYWxpZGF0b3I6ICh2YWxpZGF0b3I6IFZhbGlkYXRvciwgdXBkYXRlOiBWYWxpZGF0b3JVcGRhdGUpID0+IFByb21pc2U8VmFsaWRhdG9yPjtcbn0pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc3QgdmFsaWRhdG9yc0NvdW50ID0gYXdhaXQgdHJ5R2V0VmFsaWRhdG9yc0NvdW50KCk7XG4gIGNvbnN0IG11dGFibGVWYWxpZGF0b3JzQ291bnRWb3RlcyA9IHZhbGlkYXRvcnNDb3VudCA9PT0gdW5kZWZpbmVkID8gW10gOiBbLi4udmFsaWRhdG9yc0NvdW50LnZvdGVzXTtcbiAgWy4uLnZhbGlkYXRvcnNDb3VudENoYW5nZXMuZW50cmllcygpXS5mb3JFYWNoKChbaW5kZXgsIHZhbHVlXSkgPT4ge1xuICAgIG11dGFibGVWYWxpZGF0b3JzQ291bnRWb3Rlc1tpbmRleF0gPSB2YWx1ZTtcbiAgfSk7XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIFByb21pc2UuYWxsKFxuICAgICAgT2JqZWN0LmVudHJpZXModmFsaWRhdG9yQ2hhbmdlcykubWFwKGFzeW5jIChbcHVibGljS2V5SGV4LCB7IHJlZ2lzdGVyZWQsIHZvdGVzIH1dKSA9PiB7XG4gICAgICAgIGNvbnN0IHB1YmxpY0tleSA9IGNvbW1vbi5oZXhUb0VDUG9pbnQocHVibGljS2V5SGV4KTtcbiAgICAgICAgY29uc3QgdmFsaWRhdG9yID0gYXdhaXQgdHJ5R2V0VmFsaWRhdG9yKHsgcHVibGljS2V5IH0pO1xuICAgICAgICBpZiAodmFsaWRhdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBhd2FpdCBhZGRWYWxpZGF0b3IoXG4gICAgICAgICAgICBuZXcgVmFsaWRhdG9yKHtcbiAgICAgICAgICAgICAgcHVibGljS2V5LFxuICAgICAgICAgICAgICByZWdpc3RlcmVkLFxuICAgICAgICAgICAgICB2b3RlcyxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgKChyZWdpc3RlcmVkICE9PSB1bmRlZmluZWQgJiYgIXJlZ2lzdGVyZWQpIHx8IChyZWdpc3RlcmVkID09PSB1bmRlZmluZWQgJiYgIXZhbGlkYXRvci5yZWdpc3RlcmVkKSkgJiZcbiAgICAgICAgICAoKHZvdGVzICE9PSB1bmRlZmluZWQgJiYgdm90ZXMuZXEodXRpbHMuWkVSTykpIHx8ICh2b3RlcyA9PT0gdW5kZWZpbmVkICYmIHZhbGlkYXRvci52b3Rlcy5lcSh1dGlscy5aRVJPKSkpXG4gICAgICAgICkge1xuICAgICAgICAgIGF3YWl0IGRlbGV0ZVZhbGlkYXRvcih7IHB1YmxpY0tleTogdmFsaWRhdG9yLnB1YmxpY0tleSB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhd2FpdCB1cGRhdGVWYWxpZGF0b3IodmFsaWRhdG9yLCB7IHZvdGVzLCByZWdpc3RlcmVkIH0pO1xuICAgICAgICB9XG4gICAgICB9KSxcbiAgICApLFxuICAgIHZhbGlkYXRvcnNDb3VudCA9PT0gdW5kZWZpbmVkXG4gICAgICA/IGFkZFZhbGlkYXRvcnNDb3VudChcbiAgICAgICAgICBuZXcgVmFsaWRhdG9yc0NvdW50KHtcbiAgICAgICAgICAgIHZvdGVzOiBtdXRhYmxlVmFsaWRhdG9yc0NvdW50Vm90ZXMsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgIDogdXBkYXRlVmFsaWRhdG9yc0NvdW50KHZhbGlkYXRvcnNDb3VudCwge1xuICAgICAgICAgIHZvdGVzOiBtdXRhYmxlVmFsaWRhdG9yc0NvdW50Vm90ZXMsXG4gICAgICAgIH0pLFxuICBdKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRWYWxpZGF0b3JzID0gYXN5bmMgKFxuICBibG9ja2NoYWluOiBCbG9ja2NoYWluLFxuICB0cmFuc2FjdGlvbnM6IHJlYWRvbmx5IFRyYW5zYWN0aW9uW10sXG4pOiBQcm9taXNlPHJlYWRvbmx5IEVDUG9pbnRbXT4gPT4ge1xuICBjb25zdCBjYWNoZSA9IG5ldyBWYWxpZGF0b3JDYWNoZShibG9ja2NoYWluKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwodHJhbnNhY3Rpb25zLm1hcChhc3luYyAodHJhbnNhY3Rpb24pID0+IHByb2Nlc3NUcmFuc2FjdGlvbihibG9ja2NoYWluLCBjYWNoZSwgdHJhbnNhY3Rpb24pKSk7XG5cbiAgY29uc3QgeyB2YWxpZGF0b3JDaGFuZ2VzLCB2YWxpZGF0b3JzQ291bnRDaGFuZ2VzIH0gPSBhd2FpdCBnZXREZXNjcmlwdG9yQ2hhbmdlcyh7XG4gICAgdHJhbnNhY3Rpb25zOiB0cmFuc2FjdGlvbnMuZmlsdGVyKFxuICAgICAgKHRyYW5zYWN0aW9uKTogdHJhbnNhY3Rpb24gaXMgU3RhdGVUcmFuc2FjdGlvbiA9PlxuICAgICAgICB0cmFuc2FjdGlvbi50eXBlID09PSBUcmFuc2FjdGlvblR5cGUuU3RhdGUgJiYgdHJhbnNhY3Rpb24gaW5zdGFuY2VvZiBTdGF0ZVRyYW5zYWN0aW9uLFxuICAgICksXG5cbiAgICBnZXRBY2NvdW50OiBhc3luYyAoaGFzaCkgPT4gY2FjaGUuZ2V0QWNjb3VudChoYXNoKSxcbiAgICBnb3Zlcm5pbmdUb2tlbkhhc2g6IGJsb2NrY2hhaW4uc2V0dGluZ3MuZ292ZXJuaW5nVG9rZW4uaGFzaEhleCxcbiAgfSk7XG5cbiAgYXdhaXQgcHJvY2Vzc1N0YXRlVHJhbnNhY3Rpb24oe1xuICAgIHZhbGlkYXRvckNoYW5nZXMsXG4gICAgdmFsaWRhdG9yc0NvdW50Q2hhbmdlcyxcbiAgICB0cnlHZXRWYWxpZGF0b3JzQ291bnQ6IGFzeW5jICgpID0+IGNhY2hlLmdldFZhbGlkYXRvcnNDb3VudCgpLFxuICAgIGFkZFZhbGlkYXRvcnNDb3VudDogYXN5bmMgKHZhbHVlKSA9PiBjYWNoZS5hZGRWYWxpZGF0b3JzQ291bnQodmFsdWUpLFxuICAgIHVwZGF0ZVZhbGlkYXRvcnNDb3VudDogYXN5bmMgKHVwZGF0ZSkgPT4ge1xuICAgICAgYXdhaXQgY2FjaGUudXBkYXRlVmFsaWRhdG9yc0NvdW50KHVwZGF0ZSk7XG4gICAgfSxcbiAgICB0cnlHZXRWYWxpZGF0b3I6IGFzeW5jIChrZXkpID0+IGNhY2hlLmdldFZhbGlkYXRvcihrZXkucHVibGljS2V5KSxcbiAgICBhZGRWYWxpZGF0b3I6IGFzeW5jICh2YWxpZGF0b3IpID0+IGNhY2hlLmFkZFZhbGlkYXRvcih2YWxpZGF0b3IpLFxuICAgIGRlbGV0ZVZhbGlkYXRvcjogYXN5bmMgKGtleSkgPT4gY2FjaGUuZGVsZXRlVmFsaWRhdG9yKGtleS5wdWJsaWNLZXkpLFxuICAgIHVwZGF0ZVZhbGlkYXRvcjogYXN5bmMgKHZhbHVlLCB1cGRhdGUpID0+IGNhY2hlLnVwZGF0ZVZhbGlkYXRvcih2YWx1ZS5wdWJsaWNLZXksIHVwZGF0ZSksXG4gIH0pO1xuXG4gIGNvbnN0IFt2YWxpZGF0b3JzQ291bnQsIHZhbGlkYXRvcnNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW2NhY2hlLmdldFZhbGlkYXRvcnNDb3VudCgpLCBjYWNoZS5nZXRBbGxWYWxpZGF0b3JzKCldKTtcblxuICBjb25zdCBudW1WYWxpZGF0b3JzID0gTWF0aC5tYXgoXG4gICAgdXRpbHMud2VpZ2h0ZWRBdmVyYWdlKFxuICAgICAgdXRpbHNcbiAgICAgICAgLndlaWdodGVkRmlsdGVyKFxuICAgICAgICAgIHZhbGlkYXRvcnNDb3VudC52b3Rlc1xuICAgICAgICAgICAgLm1hcCgodm90ZXMsIGNvdW50KSA9PiAoeyBjb3VudCwgdm90ZXM6IHZvdGVzID09PSB1bmRlZmluZWQgPyB1dGlscy5aRVJPIDogdm90ZXMgfSkpXG4gICAgICAgICAgICAuZmlsdGVyKCh7IHZvdGVzIH0pID0+IHZvdGVzLmd0KHV0aWxzLlpFUk8pKSxcbiAgICAgICAgICAwLjI1LFxuICAgICAgICAgIDAuNzUsXG4gICAgICAgICAgKHsgY291bnQgfSkgPT4gbmV3IEJOKGNvdW50KSxcbiAgICAgICAgKVxuICAgICAgICAubWFwKChbeyBjb3VudCB9LCB3ZWlnaHRdKSA9PiAoeyB2YWx1ZTogY291bnQsIHdlaWdodCB9KSksXG4gICAgKSxcblxuICAgIGJsb2NrY2hhaW4uc2V0dGluZ3Muc3RhbmRieVZhbGlkYXRvcnMubGVuZ3RoLFxuICApO1xuXG4gIGNvbnN0IHN0YW5kYnlWYWxpZGF0b3JzU2V0ID0gbmV3IFNldChcbiAgICBibG9ja2NoYWluLnNldHRpbmdzLnN0YW5kYnlWYWxpZGF0b3JzLm1hcCgocHVibGljS2V5KSA9PiBjb21tb24uZWNQb2ludFRvSGV4KHB1YmxpY0tleSkpLFxuICApO1xuXG4gIGNvbnN0IHZhbGlkYXRvcnNQdWJsaWNLZXlTZXQgPSBuZXcgU2V0KFxuICAgIF8udGFrZShcbiAgICAgIHZhbGlkYXRvcnNcbiAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAodmFsaWRhdG9yKSA9PlxuICAgICAgICAgICAgKHZhbGlkYXRvci5yZWdpc3RlcmVkICYmIHZhbGlkYXRvci52b3Rlcy5ndCh1dGlscy5aRVJPKSkgfHxcbiAgICAgICAgICAgIHN0YW5kYnlWYWxpZGF0b3JzU2V0Lmhhcyhjb21tb24uZWNQb2ludFRvSGV4KHZhbGlkYXRvci5wdWJsaWNLZXkpKSxcbiAgICAgICAgKVxuICAgICAgICAuc29ydCgoYVZhbGlkYXRvciwgYlZhbGlkYXRvcikgPT5cbiAgICAgICAgICBhVmFsaWRhdG9yLnZvdGVzLmVxKGJWYWxpZGF0b3Iudm90ZXMpXG4gICAgICAgICAgICA/IGNvbW1vbi5lY1BvaW50Q29tcGFyZShhVmFsaWRhdG9yLnB1YmxpY0tleSwgYlZhbGlkYXRvci5wdWJsaWNLZXkpXG4gICAgICAgICAgICA6IC1hVmFsaWRhdG9yLnZvdGVzLmNtcChiVmFsaWRhdG9yLnZvdGVzKSxcbiAgICAgICAgKVxuICAgICAgICAubWFwKCh2YWxpZGF0b3IpID0+IGNvbW1vbi5lY1BvaW50VG9IZXgodmFsaWRhdG9yLnB1YmxpY0tleSkpLFxuICAgICAgbnVtVmFsaWRhdG9ycyxcbiAgICApLFxuICApO1xuXG4gIGNvbnN0IHN0YW5kYnlWYWxpZGF0b3JzQXJyYXkgPSBbLi4uc3RhbmRieVZhbGlkYXRvcnNTZXRdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0YW5kYnlWYWxpZGF0b3JzQXJyYXkubGVuZ3RoICYmIHZhbGlkYXRvcnNQdWJsaWNLZXlTZXQuc2l6ZSA8IG51bVZhbGlkYXRvcnM7IGkgKz0gMSkge1xuICAgIHZhbGlkYXRvcnNQdWJsaWNLZXlTZXQuYWRkKHN0YW5kYnlWYWxpZGF0b3JzQXJyYXlbaV0pO1xuICB9XG5cbiAgY29uc3QgdmFsaWRhdG9yc1B1YmxpY0tleXMgPSBbLi4udmFsaWRhdG9yc1B1YmxpY0tleVNldF0ubWFwKChoZXgpID0+IGNvbW1vbi5oZXhUb0VDUG9pbnQoaGV4KSk7XG5cbiAgcmV0dXJuIHZhbGlkYXRvcnNQdWJsaWNLZXlzLnNvcnQoKGFLZXksIGJLZXkpID0+IGNvbW1vbi5lY1BvaW50Q29tcGFyZShhS2V5LCBiS2V5KSk7XG59O1xuIl19