@neo-one/node-blockchain-esnext-cjs
Version:
NEO•ONE NEO blockchain implementation.
178 lines (176 loc) • 47.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const take_1 = tslib_1.__importDefault(require("lodash/take"));
const groupBy_1 = tslib_1.__importDefault(require("lodash/groupBy"));
// tslint:disable no-object-mutation no-array-mutation no-loop-statement
const client_core_1 = require("@neo-one/client-core-esnext-cjs");
const node_core_1 = require("@neo-one/node-core-esnext-cjs");
const bn_js_1 = require("bn.js");
const ValidatorCache_1 = require("./ValidatorCache");
const processOutput = async (blockchain, cache, output, negative) => {
let { value } = output;
if (negative) {
value = value.neg();
}
const [account] = await Promise.all([cache.getAccount(output.address), cache.updateAccountBalance(output.address, output.asset, value)]);
if (client_core_1.common.uInt256Equal(output.asset, blockchain.settings.governingToken.hash) && account.votes.length > 0) {
await Promise.all([Promise.all(account.votes.map(async (publicKey) => cache.updateValidatorVotes(publicKey, value))), cache.updateValidatorsCountVotes(account.votes.length - 1, value)]);
}
};
const processTransaction = async (blockchain, cache, transaction) => {
let allOutputs = await Promise.all(transaction.inputs.map(async (input) => {
const output = await blockchain.output.get(input);
return {
output,
negative: true
};
}));
allOutputs = allOutputs.concat(transaction.outputs.map(output => ({
output,
negative: false
})));
await Promise.all(allOutputs.map(async ({ output, negative }) => processOutput(blockchain, cache, output, negative)));
const accountHashes = [...new Set(allOutputs.map(({ output }) => client_core_1.common.uInt160ToHex(output.address)))].map(hash => client_core_1.common.hexToUInt160(hash));
const touchedValidators = await Promise.all(accountHashes.map(async (hash) => {
const account = await cache.getAccount(hash);
return account.votes;
}));
const touchedValidatorsSet = [...new Set(touchedValidators.reduce((acc, votes) => acc.concat(votes.map(vote => client_core_1.common.ecPointToHex(vote))), []))].map(publicKey => client_core_1.common.hexToECPoint(publicKey));
await Promise.all(touchedValidatorsSet.map(async (publicKey) => {
const validator = await cache.getValidator(publicKey);
if (!validator.registered && validator.votes.eq(client_core_1.utils.ZERO)) {
await cache.deleteValidator(publicKey);
}
}));
}; // tslint:disable readonly-keyword readonly-array
exports.getDescriptorChanges = async ({ transactions, getAccount, governingTokenHash }) => {
const accountChanges = {};
const validatorVotesChanges = {};
const validatorRegisteredChanges = {};
const validatorsCountChanges = [];
const allDescriptors = transactions.reduce((acc, transaction) => acc.concat(transaction.descriptors), []);
const accountDescriptors = allDescriptors.filter(descriptor => descriptor.type === 0x40);
const groupedAccountDescriptors = Object.entries(groupBy_1.default(accountDescriptors, descriptor => client_core_1.common.uInt160ToHex(client_core_1.common.bufferToUInt160(descriptor.key))));
await Promise.all(groupedAccountDescriptors.map(async ([hash, descriptors]) => {
const account = await getAccount(client_core_1.common.hexToUInt160(hash));
const balance = account.getBalance(governingTokenHash); // tslint:disable-next-line no-loop-statement
for (const vote of account.votes) {
const voteHex = client_core_1.common.ecPointToHex(vote);
validatorVotesChanges[voteHex] = (validatorVotesChanges[voteHex] === undefined ? client_core_1.utils.ZERO : validatorVotesChanges[voteHex]).sub(balance);
}
const descriptor = descriptors[descriptors.length - 1];
const reader = new client_core_1.BinaryReader(descriptor.value);
const votes = reader.readArray(() => reader.readECPoint());
if (votes.length !== account.votes.length) {
if (account.votes.length > 0) {
validatorsCountChanges[account.votes.length - 1] = (validatorsCountChanges[account.votes.length - 1] === undefined ? client_core_1.utils.ZERO : validatorsCountChanges[account.votes.length - 1]).sub(balance);
}
if (votes.length > 0) {
validatorsCountChanges[votes.length - 1] = (validatorsCountChanges[votes.length - 1] === undefined ? client_core_1.utils.ZERO : validatorsCountChanges[votes.length - 1]).add(balance);
}
}
accountChanges[hash] = votes;
for (const vote of votes) {
const voteHex = client_core_1.common.ecPointToHex(vote);
validatorVotesChanges[voteHex] = (validatorVotesChanges[voteHex] === undefined ? client_core_1.utils.ZERO : validatorVotesChanges[voteHex]).add(balance);
}
}));
const validatorDescriptors = allDescriptors.filter(descriptor => descriptor.type === 0x48);
for (const descriptor of validatorDescriptors) {
const publicKey = client_core_1.common.bufferToECPoint(descriptor.key);
validatorRegisteredChanges[client_core_1.common.ecPointToHex(publicKey)] = descriptor.value.some(byte => byte !== 0);
}
const validatorChanges = {};
for (const [publicKey, votes] of Object.entries(validatorVotesChanges)) {
validatorChanges[publicKey] = {
votes
};
}
for (const [publicKey, registered] of Object.entries(validatorRegisteredChanges)) {
const current = validatorChanges[publicKey] === undefined ? {} : validatorChanges[publicKey];
validatorChanges[publicKey] = {
registered,
votes: current.votes
};
}
return {
accountChanges,
validatorChanges,
validatorsCountChanges
};
};
exports.processStateTransaction = async ({ validatorChanges, validatorsCountChanges, tryGetValidatorsCount, addValidatorsCount, updateValidatorsCount, tryGetValidator, addValidator, deleteValidator, updateValidator }) => {
const validatorsCount = await tryGetValidatorsCount();
const mutableValidatorsCountVotes = validatorsCount === undefined ? [] : [...validatorsCount.votes];
[...validatorsCountChanges.entries()].forEach(([index, value]) => {
mutableValidatorsCountVotes[index] = value;
});
await Promise.all([Promise.all(Object.entries(validatorChanges).map(async ([publicKeyHex, { registered, votes }]) => {
const publicKey = client_core_1.common.hexToECPoint(publicKeyHex);
const validator = await tryGetValidator({
publicKey
});
if (validator === undefined) {
await addValidator(new client_core_1.Validator({
publicKey,
registered,
votes
}));
}
else if ((registered !== undefined && !registered || registered === undefined && !validator.registered) && (votes !== undefined && votes.eq(client_core_1.utils.ZERO) || votes === undefined && validator.votes.eq(client_core_1.utils.ZERO))) {
await deleteValidator({
publicKey: validator.publicKey
});
}
else {
await updateValidator(validator, {
votes,
registered
});
}
})), validatorsCount === undefined ? addValidatorsCount(new node_core_1.ValidatorsCount({
votes: mutableValidatorsCountVotes
})) : updateValidatorsCount(validatorsCount, {
votes: mutableValidatorsCountVotes
})]);
};
exports.getValidators = async (blockchain, transactions) => {
const cache = new ValidatorCache_1.ValidatorCache(blockchain);
await Promise.all(transactions.map(async (transaction) => processTransaction(blockchain, cache, transaction)));
const { validatorChanges, validatorsCountChanges } = await exports.getDescriptorChanges({
transactions: transactions.filter((transaction) => transaction.type === client_core_1.TransactionType.State && transaction instanceof client_core_1.StateTransaction),
getAccount: async (hash) => cache.getAccount(hash),
governingTokenHash: blockchain.settings.governingToken.hashHex
});
await exports.processStateTransaction({
validatorChanges,
validatorsCountChanges,
tryGetValidatorsCount: async () => cache.getValidatorsCount(),
addValidatorsCount: async (value) => cache.addValidatorsCount(value),
updateValidatorsCount: async (update) => {
await cache.updateValidatorsCount(update);
},
tryGetValidator: async (key) => cache.getValidator(key.publicKey),
addValidator: async (validator) => cache.addValidator(validator),
deleteValidator: async (key) => cache.deleteValidator(key.publicKey),
updateValidator: async (value, update) => cache.updateValidator(value.publicKey, update)
});
const [validatorsCount, validators] = await Promise.all([cache.getValidatorsCount(), cache.getAllValidators()]);
const numValidators = Math.max(client_core_1.utils.weightedAverage(client_core_1.utils.weightedFilter(validatorsCount.votes.map((votes, count) => ({
count,
votes: votes === undefined ? client_core_1.utils.ZERO : votes
})).filter(({ votes }) => votes.gt(client_core_1.utils.ZERO)), 0.25, 0.75, ({ count }) => new bn_js_1.BN(count)).map(([{ count }, weight]) => ({
value: count,
weight
}))), blockchain.settings.standbyValidators.length);
const standbyValidatorsSet = new Set(blockchain.settings.standbyValidators.map(publicKey => client_core_1.common.ecPointToHex(publicKey)));
const validatorsPublicKeySet = new Set(take_1.default(validators.filter(validator => validator.registered && validator.votes.gt(client_core_1.utils.ZERO) || standbyValidatorsSet.has(client_core_1.common.ecPointToHex(validator.publicKey))).sort((aValidator, bValidator) => aValidator.votes.eq(bValidator.votes) ? client_core_1.common.ecPointCompare(aValidator.publicKey, bValidator.publicKey) : -aValidator.votes.cmp(bValidator.votes)).map(validator => client_core_1.common.ecPointToHex(validator.publicKey)), numValidators));
const standbyValidatorsArray = [...standbyValidatorsSet];
for (let i = 0; i < standbyValidatorsArray.length && validatorsPublicKeySet.size < numValidators; i += 1) {
validatorsPublicKeySet.add(standbyValidatorsArray[i]);
}
const validatorsPublicKeys = [...validatorsPublicKeySet].map(hex => client_core_1.common.hexToECPoint(hex));
return validatorsPublicKeys.sort((aKey, bKey) => client_core_1.common.ecPointCompare(aKey, bKey));
};
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImdldFZhbGlkYXRvcnMudHMiXSwibmFtZXMiOlsicHJvY2Vzc091dHB1dCIsImJsb2NrY2hhaW4iLCJjYWNoZSIsIm91dHB1dCIsIm5lZ2F0aXZlIiwidmFsdWUiLCJuZWciLCJhY2NvdW50IiwiUHJvbWlzZSIsImFsbCIsImdldEFjY291bnQiLCJhZGRyZXNzIiwidXBkYXRlQWNjb3VudEJhbGFuY2UiLCJhc3NldCIsImNvbW1vbiIsInVJbnQyNTZFcXVhbCIsInNldHRpbmdzIiwiZ292ZXJuaW5nVG9rZW4iLCJoYXNoIiwidm90ZXMiLCJsZW5ndGgiLCJtYXAiLCJwdWJsaWNLZXkiLCJ1cGRhdGVWYWxpZGF0b3JWb3RlcyIsInVwZGF0ZVZhbGlkYXRvcnNDb3VudFZvdGVzIiwicHJvY2Vzc1RyYW5zYWN0aW9uIiwidHJhbnNhY3Rpb24iLCJhbGxPdXRwdXRzIiwiaW5wdXRzIiwiaW5wdXQiLCJnZXQiLCJjb25jYXQiLCJvdXRwdXRzIiwiYWNjb3VudEhhc2hlcyIsIlNldCIsInVJbnQxNjBUb0hleCIsImhleFRvVUludDE2MCIsInRvdWNoZWRWYWxpZGF0b3JzIiwidG91Y2hlZFZhbGlkYXRvcnNTZXQiLCJyZWR1Y2UiLCJhY2MiLCJ2b3RlIiwiZWNQb2ludFRvSGV4IiwiaGV4VG9FQ1BvaW50IiwidmFsaWRhdG9yIiwiZ2V0VmFsaWRhdG9yIiwicmVnaXN0ZXJlZCIsImVxIiwidXRpbHMiLCJaRVJPIiwiZGVsZXRlVmFsaWRhdG9yIiwiZ2V0RGVzY3JpcHRvckNoYW5nZXMiLCJ0cmFuc2FjdGlvbnMiLCJnb3Zlcm5pbmdUb2tlbkhhc2giLCJhY2NvdW50Q2hhbmdlcyIsInZhbGlkYXRvclZvdGVzQ2hhbmdlcyIsInZhbGlkYXRvclJlZ2lzdGVyZWRDaGFuZ2VzIiwidmFsaWRhdG9yc0NvdW50Q2hhbmdlcyIsImFsbERlc2NyaXB0b3JzIiwiZGVzY3JpcHRvcnMiLCJhY2NvdW50RGVzY3JpcHRvcnMiLCJmaWx0ZXIiLCJkZXNjcmlwdG9yIiwidHlwZSIsImdyb3VwZWRBY2NvdW50RGVzY3JpcHRvcnMiLCJPYmplY3QiLCJlbnRyaWVzIiwiYnVmZmVyVG9VSW50MTYwIiwia2V5IiwiYmFsYW5jZSIsImdldEJhbGFuY2UiLCJ2b3RlSGV4IiwidW5kZWZpbmVkIiwic3ViIiwicmVhZGVyIiwiQmluYXJ5UmVhZGVyIiwicmVhZEFycmF5IiwicmVhZEVDUG9pbnQiLCJhZGQiLCJ2YWxpZGF0b3JEZXNjcmlwdG9ycyIsImJ1ZmZlclRvRUNQb2ludCIsInNvbWUiLCJieXRlIiwidmFsaWRhdG9yQ2hhbmdlcyIsImN1cnJlbnQiLCJwcm9jZXNzU3RhdGVUcmFuc2FjdGlvbiIsInRyeUdldFZhbGlkYXRvcnNDb3VudCIsImFkZFZhbGlkYXRvcnNDb3VudCIsInVwZGF0ZVZhbGlkYXRvcnNDb3VudCIsInRyeUdldFZhbGlkYXRvciIsImFkZFZhbGlkYXRvciIsInVwZGF0ZVZhbGlkYXRvciIsInZhbGlkYXRvcnNDb3VudCIsIm11dGFibGVWYWxpZGF0b3JzQ291bnRWb3RlcyIsImZvckVhY2giLCJpbmRleCIsInB1YmxpY0tleUhleCIsIlZhbGlkYXRvciIsIlZhbGlkYXRvcnNDb3VudCIsImdldFZhbGlkYXRvcnMiLCJWYWxpZGF0b3JDYWNoZSIsIlRyYW5zYWN0aW9uVHlwZSIsIlN0YXRlIiwiU3RhdGVUcmFuc2FjdGlvbiIsImhhc2hIZXgiLCJnZXRWYWxpZGF0b3JzQ291bnQiLCJ1cGRhdGUiLCJ2YWxpZGF0b3JzIiwiZ2V0QWxsVmFsaWRhdG9ycyIsIm51bVZhbGlkYXRvcnMiLCJNYXRoIiwibWF4Iiwid2VpZ2h0ZWRBdmVyYWdlIiwid2VpZ2h0ZWRGaWx0ZXIiLCJjb3VudCIsImd0IiwiQk4iLCJ3ZWlnaHQiLCJzdGFuZGJ5VmFsaWRhdG9ycyIsInN0YW5kYnlWYWxpZGF0b3JzU2V0IiwidmFsaWRhdG9yc1B1YmxpY0tleVNldCIsImhhcyIsInNvcnQiLCJhVmFsaWRhdG9yIiwiYlZhbGlkYXRvciIsImVjUG9pbnRDb21wYXJlIiwiY21wIiwic3RhbmRieVZhbGlkYXRvcnNBcnJheSIsImkiLCJzaXplIiwidmFsaWRhdG9yc1B1YmxpY0tleXMiLCJoZXgiLCJhS2V5IiwiYktleSJdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0RBQWdDO0FBQ2hDLHFFQUFzQztBQUR0Qyx3RUFBQTtBQUNBLHNEQUFBO0FBaUJBLGtEQUFBO0FBQ0EsaUNBQUE7QUFHQSxxREFBQTtBQUVBLE1BQU1BLGFBQUFBLEdBQWdCLEtBQUEsRUFDcEJDLFVBRG9CLEVBRXBCQyxLQUZvQixFQUdwQkMsTUFIb0IsRUFJcEJDLFFBSm9CLEVBQUEsRUFBQTtJQU1wQixJQUFJLEVBQUVDLEtBQUFBLEVBQUYsR0FBWUYsTUFBaEIsQ0FBQTtJQUNBLElBQUlDLFFBQUosRUFBYztRQUNaQyxLQUFBQSxHQUFRQSxLQUFBQSxDQUFNQyxHQUFOLEVBQVIsQ0FBQTtLQUNEO0lBQ0QsTUFBTSxDQUFDQyxPQUFELENBQUEsR0FBWSxNQUFNQyxPQUFBQSxDQUFRQyxHQUFSLENBQVksQ0FDbENQLEtBQUFBLENBQU1RLFVBQU4sQ0FBaUJQLE1BQUFBLENBQU9RLE9BQXhCLENBRGtDLEVBRWxDVCxLQUFBQSxDQUFNVSxvQkFBTixDQUEyQlQsTUFBQUEsQ0FBT1EsT0FBbEMsRUFBMkNSLE1BQUFBLENBQU9VLEtBQWxELEVBQXlEUixLQUF6RCxDQUZrQyxDQUFaLENBQXhCLENBQUE7SUFLQSxJQUFJUyxvQkFBQUEsQ0FBT0MsWUFBUCxDQUFvQlosTUFBQUEsQ0FBT1UsS0FBM0IsRUFBa0NaLFVBQUFBLENBQVdlLFFBQVgsQ0FBb0JDLGNBQXBCLENBQW1DQyxJQUFyRSxDQUFBLElBQThFWCxPQUFBQSxDQUFRWSxLQUFSLENBQWNDLE1BQWQsR0FBdUIsQ0FBekcsRUFBNEc7UUFDMUcsTUFBTVosT0FBQUEsQ0FBUUMsR0FBUixDQUFZLENBQ2hCRCxPQUFBQSxDQUFRQyxHQUFSLENBQVlGLE9BQUFBLENBQVFZLEtBQVIsQ0FBY0UsR0FBZCxDQUFrQixLQUFBLEVBQU9DLFNBQVAsRUFBQSxFQUFBLENBQXFCcEIsS0FBQUEsQ0FB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LFlBQVAsQ0FBb0JFLFNBQUFBLENBQVV0QixTQUE5QixDQVp0QixDQURGLEVBY0V1RixhQWRGLENBRDZCLENBQS9CLENBQUE7SUFtQkEsTUFBTWtCLHNCQUFBQSxHQUF5QixDQUFDLEdBQUdSLG9CQUFKLENBQS9CLENBQUE7SUFDQSxLQUFLLElBQUlTLENBQUFBLEdBQUksQ0FBYixFQUFnQkEsQ0FBQUEsR0FBSUQsc0JBQUFBLENBQXVCM0csTUFBM0IsSUFBcUNvRyxzQkFBQUEsQ0FBdUJTLElBQXZCLEdBQThCcEIsYUFBbkYsRUFBa0dtQixDQUFBQSxJQUFLLENBQXZHLEVBQTBHO1FBQ3hHUixzQkFBQUEsQ0FBdUIxQyxHQUF2QixDQUEyQmlELHNCQUFBQSxDQUF1QkMsQ0FBdkIsQ0FBM0IsQ0FBQSxDQUFBO0tBQ0Q7SUFFRCxNQUFNRSxvQkFBQUEsR0FBdUIsQ0FBQyxHQUFHVixzQkFBSixDQUFBLENBQTRCbkcsR0FBNUIsQ0FBaUM4RyxHQUFELENBQUEsRUFBQSxDQUFTckgsb0JBQUFBLENBQU82QixZQUFQLENBQW9Cd0YsR0FBcEIsQ0FBekMsQ0FBN0IsQ0FBQTtJQUVBLE9BQU9ELG9CQUFBQSxDQUFxQlIsSUFBckIsQ0FBMEIsQ0FBQ1UsSUFBRCxFQUFPQyxJQUFQLEVBQUEsRUFBQSxDQUFnQnZILG9CQUFBQSxDQUFPK0csY0FBUCxDQUFzQk8sSUFBdEIsRUFBNEJDLElBQTVCLENBQTFDLENBQVAsQ0FBQTtBQUNELENBakZNLENBQUEiLCJmaWxlIjoibmVvLW9uZS1ub2RlLWJsb2NrY2hhaW4vc3JjL2dldFZhbGlkYXRvcnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0c2xpbnQ6ZGlzYWJsZSBuby1vYmplY3QtbXV0YXRpb24gbm8tYXJyYXktbXV0YXRpb24gbm8tbG9vcC1zdGF0ZW1lbnRcbmltcG9ydCB7XG4gIEFjY291bnQsXG4gIEJpbmFyeVJlYWRlcixcbiAgY29tbW9uLFxuICBFQ1BvaW50LFxuICBPdXRwdXQsXG4gIFN0YXRlRGVzY3JpcHRvcixcbiAgU3RhdGVUcmFuc2FjdGlvbixcbiAgVHJhbnNhY3Rpb24sXG4gIFRyYW5zYWN0aW9uVHlwZSxcbiAgVUludDE2MCxcbiAgVUludDI1NkhleCxcbiAgdXRpbHMsXG4gIFZhbGlkYXRvcixcbiAgVmFsaWRhdG9yS2V5LFxuICBWYWxpZGF0b3JVcGRhdGUsXG59IGZyb20gJ0BuZW8tb25lL2NsaWVudC1jb3JlJztcbmltcG9ydCB7IFZhbGlkYXRvcnNDb3VudCwgVmFsaWRhdG9yc0NvdW50VXBkYXRlIH0gZnJvbSAnQG5lby1vbmUvbm9kZS1jb3JlJztcbmltcG9ydCB7IEJOIH0gZnJvbSAnYm4uanMnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IEJsb2NrY2hhaW4gfSBmcm9tICcuL0Jsb2NrY2hhaW4nO1xuaW1wb3J0IHsgVmFsaWRhdG9yQ2FjaGUgfSBmcm9tICcuL1ZhbGlkYXRvckNhY2hlJztcblxuY29uc3QgcHJvY2Vzc091dHB1dCA9IGFzeW5jIChcbiAgYmxvY2tjaGFpbjogQmxvY2tjaGFpbixcbiAgY2FjaGU6IFZhbGlkYXRvckNhY2hlLFxuICBvdXRwdXQ6IE91dHB1dCxcbiAgbmVnYXRpdmU6IGJvb2xlYW4sXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgbGV0IHsgdmFsdWUgfSA9IG91dHB1dDtcbiAgaWYgKG5lZ2F0aXZlKSB7XG4gICAgdmFsdWUgPSB2YWx1ZS5uZWcoKTtcbiAgfVxuICBjb25zdCBbYWNjb3VudF0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgY2FjaGUuZ2V0QWNjb3VudChvdXRwdXQuYWRkcmVzcyksXG4gICAgY2FjaGUudXBkYXRlQWNjb3VudEJhbGFuY2Uob3V0cHV0LmFkZHJlc3MsIG91dHB1dC5hc3NldCwgdmFsdWUpLFxuICBdKTtcblxuICBpZiAoY29tbW9uLnVJbnQyNTZFcXVhbChvdXRwdXQuYXNzZXQsIGJsb2NrY2hhaW4uc2V0dGluZ3MuZ292ZXJuaW5nVG9rZW4uaGFzaCkgJiYgYWNjb3VudC52b3Rlcy5sZW5ndGggPiAwKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgUHJvbWlzZS5hbGwoYWNjb3VudC52b3Rlcy5tYXAoYXN5bmMgKHB1YmxpY0tleSkgPT4gY2FjaGUudXBkYXRlVmFsaWRhdG9yVm90ZXMocHVibGljS2V5LCB2YWx1ZSkpKSxcblxuICAgICAgY2FjaGUudXBkYXRlVmFsaWRhdG9yc0NvdW50Vm90ZXMoYWNjb3VudC52b3Rlcy5sZW5ndGggLSAxLCB2YWx1ZSksXG4gICAgXSk7XG4gIH1cbn07XG5cbmNvbnN0IHByb2Nlc3NUcmFuc2FjdGlvbiA9IGFzeW5jIChcbiAgYmxvY2tjaGFpbjogQmxvY2tjaGFpbixcbiAgY2FjaGU6IFZhbGlkYXRvckNhY2hlLFxuICB0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24sXG4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgbGV0IGFsbE91dHB1dHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICB0cmFuc2FjdGlvbi5pbnB1dHMubWFwKGFzeW5jIChpbnB1dCkgPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgYmxvY2tjaGFpbi5vdXRwdXQuZ2V0KGlucHV0KTtcblxuICAgICAgcmV0dXJuIHsgb3V0cHV0LCBuZWdhdGl2ZTogdHJ1ZSB9O1xuICAgIH0pLFxuICApO1xuXG4gIGFsbE91dHB1dHMgPSBhbGxPdXRwdXRzLmNvbmNhdCh0cmFuc2FjdGlvbi5vdXRwdXRzLm1hcCgob3V0cHV0KSA9PiAoeyBvdXRwdXQsIG5lZ2F0aXZlOiBmYWxzZSB9KSkpO1xuXG4gIGF3YWl0IFByb21pc2UuYWxsKGFsbE91dHB1dHMubWFwKGFzeW5jICh7IG91dHB1dCwgbmVnYXRpdmUgfSkgPT4gcHJvY2Vzc091dHB1dChibG9ja2NoYWluLCBjYWNoZSwgb3V0cHV0LCBuZWdhdGl2ZSkpKTtcblxuICBjb25zdCBhY2NvdW50SGFzaGVzID0gWy4uLm5ldyBTZXQoYWxsT3V0cHV0cy5tYXAoKHsgb3V0cHV0IH0pID0+IGNvbW1vbi51SW50MTYwVG9IZXgob3V0cHV0LmFkZHJlc3MpKSldLm1hcCgoaGFzaCkgPT5cbiAgICBjb21tb24uaGV4VG9VSW50MTYwKGhhc2gpLFxuICApO1xuICBjb25zdCB0b3VjaGVkVmFsaWRhdG9ycyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGFjY291bnRIYXNoZXMubWFwKGFzeW5jIChoYXNoKSA9PiB7XG4gICAgICBjb25zdCBhY2NvdW50ID0gYXdhaXQgY2FjaGUuZ2V0QWNjb3VudChoYXNoKTtcblxuICAgICAgcmV0dXJuIGFjY291bnQudm90ZXM7XG4gICAgfSksXG4gICk7XG5cbiAgY29uc3QgdG91Y2hlZFZhbGlkYXRvcnNTZXQgPSBbXG4gICAgLi4ubmV3IFNldChcbiAgICAgIHRvdWNoZWRWYWxpZGF0b3JzLnJlZHVjZTxSZWFkb25seUFycmF5PHN0cmluZz4+KFxuICAgICAgICAoYWNjLCB2b3RlcykgPT4gYWNjLmNvbmNhdCh2b3Rlcy5tYXAoKHZvdGUpID0+IGNvbW1vbi5lY1BvaW50VG9IZXgodm90ZSkpKSxcbiAgICAgICAgW10sXG4gICAgICApLFxuICAgICksXG4gIF0ubWFwKChwdWJsaWNLZXkpID0+IGNvbW1vbi5oZXhUb0VDUG9pbnQocHVibGljS2V5KSk7XG4gIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIHRvdWNoZWRWYWxpZGF0b3JzU2V0Lm1hcChhc3luYyAocHVibGljS2V5KSA9PiB7XG4gICAgICBjb25zdCB2YWxpZGF0b3IgPSBhd2FpdCBjYWNoZS5nZXRWYWxpZGF0b3IocHVibGljS2V5KTtcbiAgICAgIGlmICghdmFsaWRhdG9yLnJlZ2lzdGVyZWQgJiYgdmFsaWRhdG9yLnZvdGVzLmVxKHV0aWxzLlpFUk8pKSB7XG4gICAgICAgIGF3YWl0IGNhY2hlLmRlbGV0ZVZhbGlkYXRvcihwdWJsaWNLZXkpO1xuICAgICAgfVxuICAgIH0pLFxuICApO1xufTtcblxuLy8gdHNsaW50OmRpc2FibGUgcmVhZG9ubHkta2V5d29yZCByZWFkb25seS1hcnJheVxuZXhwb3J0IGludGVyZmFjZSBBY2NvdW50Q2hhbmdlcyB7XG4gIFtoYXNoOiBzdHJpbmddOiBSZWFkb25seUFycmF5PEVDUG9pbnQ+O1xufVxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0b3JWb3Rlc0NoYW5nZXMge1xuICBbaGFzaDogc3RyaW5nXTogQk47XG59XG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRvclJlZ2lzdGVyZWRDaGFuZ2VzIHtcbiAgW2hhc2g6IHN0cmluZ106IGJvb2xlYW47XG59XG5pbnRlcmZhY2UgVmFsaWRhdG9yQ2hhbmdlIHtcbiAgcmVhZG9ubHkgcmVnaXN0ZXJlZD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHZvdGVzPzogQk47XG59XG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRvckNoYW5nZXMge1xuICBbaGFzaDogc3RyaW5nXTogVmFsaWRhdG9yQ2hhbmdlO1xufVxuZXhwb3J0IHR5cGUgVmFsaWRhdG9yc0NvdW50Q2hhbmdlcyA9IEJOW107XG4vLyB0c2xpbnQ6ZW5hYmxlIHJlYWRvbmx5LWtleXdvcmQgcmVhZG9ubHktYXJyYXlcblxuZXhwb3J0IGNvbnN0IGdldERlc2NyaXB0b3JDaGFuZ2VzID0gYXN5bmMgKHtcbiAgdHJhbnNhY3Rpb25zLFxuICBnZXRBY2NvdW50LFxuICBnb3Zlcm5pbmdUb2tlbkhhc2gsXG59OiB7XG4gIHJlYWRvbmx5IHRyYW5zYWN0aW9uczogUmVhZG9ubHlBcnJheTxTdGF0ZVRyYW5zYWN0aW9uPjtcbiAgcmVhZG9ubHkgZ2V0QWNjb3VudDogKChoYXNoOiBVSW50MTYwKSA9PiBQcm9taXNlPEFjY291bnQ+KTtcbiAgcmVhZG9ubHkgZ292ZXJuaW5nVG9rZW5IYXNoOiBVSW50MjU2SGV4O1xufSk6IFByb21pc2U8e1xuICByZWFkb25seSBhY2NvdW50Q2hhbmdlczogQWNjb3VudENoYW5nZXM7XG4gIHJlYWRvbmx5IHZhbGlkYXRvckNoYW5nZXM6IFZhbGlkYXRvckNoYW5nZXM7XG4gIHJlYWRvbmx5IHZhbGlkYXRvcnNDb3VudENoYW5nZXM6IFZhbGlkYXRvcnNDb3VudENoYW5nZXM7XG59PiA9PiB7XG4gIGNvbnN0IGFjY291bnRDaGFuZ2VzOiBBY2NvdW50Q2hhbmdlcyA9IHt9O1xuICBjb25zdCB2YWxpZGF0b3JWb3Rlc0NoYW5nZXM6IFZhbGlkYXRvclZvdGVzQ2hhbmdlcyA9IHt9O1xuICBjb25zdCB2YWxpZGF0b3JSZWdpc3RlcmVkQ2hhbmdlczogVmFsaWRhdG9yUmVnaXN0ZXJlZENoYW5nZXMgPSB7fTtcbiAgY29uc3QgdmFsaWRhdG9yc0NvdW50Q2hhbmdlczogVmFsaWRhdG9yc0NvdW50Q2hhbmdlcyA9IFtdO1xuICBjb25zdCBhbGxEZXNjcmlwdG9ycyA9IHRyYW5zYWN0aW9ucy5yZWR1Y2U8UmVhZG9ubHlBcnJheTxTdGF0ZURlc2NyaXB0b3I+PihcbiAgICAoYWNjLCB0cmFuc2FjdGlvbikgPT4gYWNjLmNvbmNhdCh0cmFuc2FjdGlvbi5kZXNjcmlwdG9ycyksXG4gICAgW10sXG4gICk7XG5cbiAgY29uc3QgYWNjb3VudERlc2NyaXB0b3JzID0gYWxsRGVzY3JpcHRvcnMuZmlsdGVyKChkZXNjcmlwdG9yKSA9PiBkZXNjcmlwdG9yLnR5cGUgPT09IDB4NDApO1xuXG4gIGNvbnN0IGdyb3VwZWRBY2NvdW50RGVzY3JpcHRvcnMgPSBPYmplY3QuZW50cmllcyhcbiAgICBfLmdyb3VwQnkoYWNjb3VudERlc2NyaXB0b3JzLCAoZGVzY3JpcHRvcikgPT4gY29tbW9uLnVJbnQxNjBUb0hleChjb21tb24uYnVmZmVyVG9VSW50MTYwKGRlc2NyaXB0b3Iua2V5KSkpLFxuICApO1xuXG4gIGF3YWl0IFByb21pc2UuYWxsKFxuICAgIGdyb3VwZWRBY2NvdW50RGVzY3JpcHRvcnMubWFwKGFzeW5jIChbaGFzaCwgZGVzY3JpcHRvcnNdKSA9PiB7XG4gICAgICBjb25zdCBhY2NvdW50ID0gYXdhaXQgZ2V0QWNjb3VudChjb21tb24uaGV4VG9VSW50MTYwKGhhc2gpKTtcbiAgICAgIGNvbnN0IGJhbGFuY2UgPSBhY2NvdW50LmdldEJhbGFuY2UoZ292ZXJuaW5nVG9rZW5IYXNoKTtcblxuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWxvb3Atc3RhdGVtZW50XG4gICAgICBmb3IgKGNvbnN0IHZvdGUgb2YgYWNjb3VudC52b3Rlcykge1xuICAgICAgICBjb25zdCB2b3RlSGV4ID0gY29tbW9uLmVjUG9pbnRUb0hleCh2b3RlKTtcbiAgICAgICAgdmFsaWRhdG9yVm90ZXNDaGFuZ2VzW3ZvdGVIZXhdID0gKCh2YWxpZGF0b3JWb3Rlc0NoYW5nZXNbdm90ZUhleF0gYXMgQk4gfCB1bmRlZmluZWQpID09PSB1bmRlZmluZWRcbiAgICAgICAgICA/IHV0aWxzLlpFUk9cbiAgICAgICAgICA6IHZhbGlkYXRvclZvdGVzQ2hhbmdlc1t2b3RlSGV4XVxuICAgICAgICApLnN1YihiYWxhbmNlKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGVzY3JpcHRvciA9IGRlc2NyaXB0b3JzW2Rlc2NyaXB0b3JzLmxlbmd0aCAtIDFdO1xuICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEJpbmFyeVJlYWRlcihkZXNjcmlwdG9yLnZhbHVlKTtcbiAgICAgIGNvbnN0IHZvdGVzID0gcmVhZGVyLnJlYWRBcnJheSgoKSA9PiByZWFkZXIucmVhZEVDUG9pbnQoKSk7XG4gICAgICBpZiAodm90ZXMubGVuZ3RoICE9PSBhY2NvdW50LnZvdGVzLmxlbmd0aCkge1xuICAgICAgICBpZiAoYWNjb3VudC52b3Rlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdmFsaWRhdG9yc0NvdW50Q2hhbmdlc1thY2NvdW50LnZvdGVzLmxlbmd0aCAtIDFdID0gKCh2YWxpZGF0b3JzQ291bnRDaGFuZ2VzW2FjY291bnQudm90ZXMubGVuZ3RoIC0gMV0gYXNcbiAgICAgICAgICAgIHwgQk5cbiAgICAgICAgICAgIHwgdW5kZWZpbmVkKSA9PT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IHV0aWxzLlpFUk9cbiAgICAgICAgICAgIDogdmFsaWRhdG9yc0NvdW50Q2hhbmdlc1thY2NvdW50LnZvdGVzLmxlbmd0aCAtIDFdXG4gICAgICAgICAgKS5zdWIoYmFsYW5jZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodm90ZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHZhbGlkYXRvcnNDb3VudENoYW5nZXNbdm90ZXMubGVuZ3RoIC0gMV0gPSAoKHZhbGlkYXRvcnNDb3VudENoYW5nZXNbdm90ZXMubGVuZ3RoIC0gMV0gYXMgQk4gfCB1bmRlZmluZWQpID09PVxuICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgICAgICAgPyB1dGlscy5aRVJPXG4gICAgICAgICAgICA6IHZhbGlkYXRvcnNDb3VudENoYW5nZXNbdm90ZXMubGVuZ3RoIC0gMV1cbiAgICAgICAgICApLmFkZChiYWxhbmNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBhY2NvdW50Q2hhbmdlc1toYXNoXSA9IHZvdGVzO1xuICAgICAgZm9yIChjb25zdCB2b3RlIG9mIHZvdGVzKSB7XG4gICAgICAgIGNvbnN0IHZvdGVIZXggPSBjb21tb24uZWNQb2ludFRvSGV4KHZvdGUpO1xuICAgICAgICB2YWxpZGF0b3JWb3Rlc0NoYW5nZXNbdm90ZUhleF0gPSAoKHZhbGlkYXRvclZvdGVzQ2hhbmdlc1t2b3RlSGV4XSBhcyBCTiB8IHVuZGVmaW5lZCkgPT09IHVuZGVmaW5lZFxuICAgICAgICAgID8gdXRpbHMuWkVST1xuICAgICAgICAgIDogdmFsaWRhdG9yVm90ZXNDaGFuZ2VzW3ZvdGVIZXhdXG4gICAgICAgICkuYWRkKGJhbGFuY2UpO1xuICAgICAgfVxuICAgIH0pLFxuICApO1xuXG4gIGNvbnN0IHZhbGlkYXRvckRlc2NyaXB0b3JzID0gYWxsRGVzY3JpcHRvcnMuZmlsdGVyKChkZXNjcmlwdG9yKSA9PiBkZXNjcmlwdG9yLnR5cGUgPT09IDB4NDgpO1xuXG4gIGZvciAoY29uc3QgZGVzY3JpcHRvciBvZiB2YWxpZGF0b3JEZXNjcmlwdG9ycykge1xuICAgIGNvbnN0IHB1YmxpY0tleSA9IGNvbW1vbi5idWZmZXJUb0VDUG9pbnQoZGVzY3JpcHRvci5rZXkpO1xuICAgIHZhbGlkYXRvclJlZ2lzdGVyZWRDaGFuZ2VzW2NvbW1vbi5lY1BvaW50VG9IZXgocHVibGljS2V5KV0gPSBkZXNjcmlwdG9yLnZhbHVlLnNvbWUoKGJ5dGUpID0+IGJ5dGUgIT09IDApO1xuICB9XG5cbiAgY29uc3QgdmFsaWRhdG9yQ2hhbmdlczogVmFsaWRhdG9yQ2hhbmdlcyA9IHt9O1xuICBmb3IgKGNvbnN0IFtwdWJsaWNLZXksIHZvdGVzXSBvZiBPYmplY3QuZW50cmllcyh2YWxpZGF0b3JWb3Rlc0NoYW5nZXMpKSB7XG4gICAgdmFsaWRhdG9yQ2hhbmdlc1twdWJsaWNLZXldID0geyB2b3RlcyB9O1xuICB9XG5cbiAgZm9yIChjb25zdCBbcHVibGljS2V5LCByZWdpc3RlcmVkXSBvZiBPYmplY3QuZW50cmllcyh2YWxpZGF0b3JSZWdpc3RlcmVkQ2hhbmdlcykpIHtcbiAgICBjb25zdCBjdXJyZW50ID1cbiAgICAgICh2YWxpZGF0b3JDaGFuZ2VzW3B1YmxpY0tleV0gYXMgVmFsaWRhdG9yQ2hhbmdlIHwgdW5kZWZpbmVkKSA9PT0gdW5kZWZpbmVkID8ge30gOiB2YWxpZGF0b3JDaGFuZ2VzW3B1YmxpY0tleV07XG4gICAgdmFsaWRhdG9yQ2hhbmdlc1twdWJsaWNLZXldID0ge1xuICAgICAgcmVnaXN0ZXJlZCxcbiAgICAgIHZvdGVzOiBjdXJyZW50LnZvdGVzLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFjY291bnRDaGFuZ2VzLFxuICAgIHZhbGlkYXRvckNoYW5nZXMsXG4gICAgdmFsaWRhdG9yc0NvdW50Q2hhbmdlcyxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBwcm9jZXNzU3RhdGVUcmFuc2FjdGlvbiA9IGFzeW5jICh7XG4gIHZhbGlkYXRvckNoYW5nZXMsXG4gIHZhbGlkYXRvcnNDb3VudENoYW5nZXMsXG4gIHRyeUdldFZhbGlkYXRvcnNDb3VudCxcbiAgYWRkVmFsaWRhdG9yc0NvdW50LFxuICB1cGRhdGVWYWxpZGF0b3JzQ291bnQsXG4gIHRyeUdldFZhbGlkYXRvcixcbiAgYWRkVmFsaWRhdG9yLFxuICBkZWxldGVWYWxpZGF0b3IsXG4gIHVwZGF0ZVZhbGlkYXRvcixcbn06IHtcbiAgcmVhZG9ubHkgdmFsaWRhdG9yQ2hhbmdlczogVmFsaWRhdG9yQ2hhbmdlcztcbiAgcmVhZG9ubHkgdmFsaWRhdG9yc0NvdW50Q2hhbmdlczogVmFsaWRhdG9yc0NvdW50Q2hhbmdlcztcbiAgcmVhZG9ubHkgdHJ5R2V0VmFsaWRhdG9yc0NvdW50OiAoKCkgPT4gUHJvbWlzZTxWYWxpZGF0b3JzQ291bnQgfCB1bmRlZmluZWQ+KTtcbiAgcmVhZG9ubHkgYWRkVmFsaWRhdG9yc0NvdW50OiAoKHZhbGlkYXRvcnNDb3VudDogVmFsaWRhdG9yc0NvdW50KSA9PiBQcm9taXNlPHZvaWQ+KTtcbiAgcmVhZG9ubHkgdXBkYXRlVmFsaWRhdG9yc0NvdW50OiAoKHZhbGlkYXRvcnNDb3VudDogVmFsaWRhdG9yc0NvdW50LCB1cGRhdGU6IFZhbGlkYXRvcnNDb3VudFVwZGF0ZSkgPT4gUHJvbWlzZTx2b2lkPik7XG5cbiAgcmVhZG9ubHkgdHJ5R2V0VmFsaWRhdG9yOiAoKGtleTogVmFsaWRhdG9yS2V5KSA9PiBQcm9taXNlPFZhbGlkYXRvciB8IHVuZGVmaW5lZD4pO1xuICByZWFkb25seSBhZGRWYWxpZGF0b3I6ICgodmFsaWRhdG9yOiBWYWxpZGF0b3IpID0+IFByb21pc2U8dm9pZD4pO1xuICByZWFkb25seSBkZWxldGVWYWxpZGF0b3I6ICgoa2V5OiBWYWxpZGF0b3JLZXkpID0+IFByb21pc2U8dm9pZD4pO1xuICByZWFkb25seSB1cGRhdGVWYWxpZGF0b3I6ICgodmFsaWRhdG9yOiBWYWxpZGF0b3IsIHVwZGF0ZTogVmFsaWRhdG9yVXBkYXRlKSA9PiBQcm9taXNlPFZhbGlkYXRvcj4pO1xufSk6IFByb21pc2U8dm9pZD4gPT4ge1xuICBjb25zdCB2YWxpZGF0b3JzQ291bnQgPSBhd2FpdCB0cnlHZXRWYWxpZGF0b3JzQ291bnQoKTtcbiAgY29uc3QgbXV0YWJsZVZhbGlkYXRvcnNDb3VudFZvdGVzID0gdmFsaWRhdG9yc0NvdW50ID09PSB1bmRlZmluZWQgPyBbXSA6IFsuLi52YWxpZGF0b3JzQ291bnQudm90ZXNdO1xuICBbLi4udmFsaWRhdG9yc0NvdW50Q2hhbmdlcy5lbnRyaWVzKCldLmZvckVhY2goKFtpbmRleCwgdmFsdWVdKSA9PiB7XG4gICAgbXV0YWJsZVZhbGlkYXRvcnNDb3VudFZvdGVzW2luZGV4XSA9IHZhbHVlO1xuICB9KTtcblxuICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgUHJvbWlzZS5hbGwoXG4gICAgICBPYmplY3QuZW50cmllcyh2YWxpZGF0b3JDaGFuZ2VzKS5tYXAoYXN5bmMgKFtwdWJsaWNLZXlIZXgsIHsgcmVnaXN0ZXJlZCwgdm90ZXMgfV0pID0+IHtcbiAgICAgICAgY29uc3QgcHVibGljS2V5ID0gY29tbW9uLmhleFRvRUNQb2ludChwdWJsaWNLZXlIZXgpO1xuICAgICAgICBjb25zdCB2YWxpZGF0b3IgPSBhd2FpdCB0cnlHZXRWYWxpZGF0b3IoeyBwdWJsaWNLZXkgfSk7XG4gICAgICAgIGlmICh2YWxpZGF0b3IgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGF3YWl0IGFkZFZhbGlkYXRvcihcbiAgICAgICAgICAgIG5ldyBWYWxpZGF0b3Ioe1xuICAgICAgICAgICAgICBwdWJsaWNLZXksXG4gICAgICAgICAgICAgIHJlZ2lzdGVyZWQsXG4gICAgICAgICAgICAgIHZvdGVzLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAoKHJlZ2lzdGVyZWQgIT09IHVuZGVmaW5lZCAmJiAhcmVnaXN0ZXJlZCkgfHwgKHJlZ2lzdGVyZWQgPT09IHVuZGVmaW5lZCAmJiAhdmFsaWRhdG9yLnJlZ2lzdGVyZWQpKSAmJlxuICAgICAgICAgICgodm90ZXMgIT09IHVuZGVmaW5lZCAmJiB2b3Rlcy5lcSh1dGlscy5aRVJPKSkgfHwgKHZvdGVzID09PSB1bmRlZmluZWQgJiYgdmFsaWRhdG9yLnZvdGVzLmVxKHV0aWxzLlpFUk8pKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgYXdhaXQgZGVsZXRlVmFsaWRhdG9yKHsgcHVibGljS2V5OiB2YWxpZGF0b3IucHVibGljS2V5IH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGF3YWl0IHVwZGF0ZVZhbGlkYXRvcih2YWxpZGF0b3IsIHsgdm90ZXMsIHJlZ2lzdGVyZWQgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pLFxuICAgICksXG4gICAgdmFsaWRhdG9yc0NvdW50ID09PSB1bmRlZmluZWRcbiAgICAgID8gYWRkVmFsaWRhdG9yc0NvdW50KFxuICAgICAgICAgIG5ldyBWYWxpZGF0b3JzQ291bnQoe1xuICAgICAgICAgICAgdm90ZXM6IG11dGFibGVWYWxpZGF0b3JzQ291bnRWb3RlcyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgOiB1cGRhdGVWYWxpZGF0b3JzQ291bnQodmFsaWRhdG9yc0NvdW50LCB7XG4gICAgICAgICAgdm90ZXM6IG11dGFibGVWYWxpZGF0b3JzQ291bnRWb3RlcyxcbiAgICAgICAgfSksXG4gIF0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFZhbGlkYXRvcnMgPSBhc3luYyAoXG4gIGJsb2NrY2hhaW46IEJsb2NrY2hhaW4sXG4gIHRyYW5zYWN0aW9uczogUmVhZG9ubHlBcnJheTxUcmFuc2FjdGlvbj4sXG4pOiBQcm9taXNlPFJlYWRvbmx5QXJyYXk8RUNQb2ludD4+ID0+IHtcbiAgY29uc3QgY2FjaGUgPSBuZXcgVmFsaWRhdG9yQ2FjaGUoYmxvY2tjaGFpbik7XG4gIGF3YWl0IFByb21pc2UuYWxsKHRyYW5zYWN0aW9ucy5tYXAoYXN5bmMgKHRyYW5zYWN0aW9uKSA9PiBwcm9jZXNzVHJhbnNhY3Rpb24oYmxvY2tjaGFpbiwgY2FjaGUsIHRyYW5zYWN0aW9uKSkpO1xuXG4gIGNvbnN0IHsgdmFsaWRhdG9yQ2hhbmdlcywgdmFsaWRhdG9yc0NvdW50Q2hhbmdlcyB9ID0gYXdhaXQgZ2V0RGVzY3JpcHRvckNoYW5nZXMoe1xuICAgIHRyYW5zYWN0aW9uczogdHJhbnNhY3Rpb25zLmZpbHRlcihcbiAgICAgICh0cmFuc2FjdGlvbik6IHRyYW5zYWN0aW9uIGlzIFN0YXRlVHJhbnNhY3Rpb24gPT5cbiAgICAgICAgdHJhbnNhY3Rpb24udHlwZSA9PT0gVHJhbnNhY3Rpb25UeXBlLlN0YXRlICYmIHRyYW5zYWN0aW9uIGluc3RhbmNlb2YgU3RhdGVUcmFuc2FjdGlvbixcbiAgICApLFxuXG4gICAgZ2V0QWNjb3VudDogYXN5bmMgKGhhc2gpID0+IGNhY2hlLmdldEFjY291bnQoaGFzaCksXG4gICAgZ292ZXJuaW5nVG9rZW5IYXNoOiBibG9ja2NoYWluLnNldHRpbmdzLmdvdmVybmluZ1Rva2VuLmhhc2hIZXgsXG4gIH0pO1xuXG4gIGF3YWl0IHByb2Nlc3NTdGF0ZVRyYW5zYWN0aW9uKHtcbiAgICB2YWxpZGF0b3JDaGFuZ2VzLFxuICAgIHZhbGlkYXRvcnNDb3VudENoYW5nZXMsXG4gICAgdHJ5R2V0VmFsaWRhdG9yc0NvdW50OiBhc3luYyAoKSA9PiBjYWNoZS5nZXRWYWxpZGF0b3JzQ291bnQoKSxcbiAgICBhZGRWYWxpZGF0b3JzQ291bnQ6IGFzeW5jICh2YWx1ZSkgPT4gY2FjaGUuYWRkVmFsaWRhdG9yc0NvdW50KHZhbHVlKSxcbiAgICB1cGRhdGVWYWxpZGF0b3JzQ291bnQ6IGFzeW5jICh1cGRhdGUpID0+IHtcbiAgICAgIGF3YWl0IGNhY2hlLnVwZGF0ZVZhbGlkYXRvcnNDb3VudCh1cGRhdGUpO1xuICAgIH0sXG4gICAgdHJ5R2V0VmFsaWRhdG9yOiBhc3luYyAoa2V5KSA9PiBjYWNoZS5nZXRWYWxpZGF0b3Ioa2V5LnB1YmxpY0tleSksXG4gICAgYWRkVmFsaWRhdG9yOiBhc3luYyAodmFsaWRhdG9yKSA9PiBjYWNoZS5hZGRWYWxpZGF0b3IodmFsaWRhdG9yKSxcbiAgICBkZWxldGVWYWxpZGF0b3I6IGFzeW5jIChrZXkpID0+IGNhY2hlLmRlbGV0ZVZhbGlkYXRvcihrZXkucHVibGljS2V5KSxcbiAgICB1cGRhdGVWYWxpZGF0b3I6IGFzeW5jICh2YWx1ZSwgdXBkYXRlKSA9PiBjYWNoZS51cGRhdGVWYWxpZGF0b3IodmFsdWUucHVibGljS2V5LCB1cGRhdGUpLFxuICB9KTtcblxuICBjb25zdCBbdmFsaWRhdG9yc0NvdW50LCB2YWxpZGF0b3JzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtjYWNoZS5nZXRWYWxpZGF0b3JzQ291bnQoKSwgY2FjaGUuZ2V0QWxsVmFsaWRhdG9ycygpXSk7XG5cbiAgY29uc3QgbnVtVmFsaWRhdG9ycyA9IE1hdGgubWF4KFxuICAgIHV0aWxzLndlaWdodGVkQXZlcmFnZShcbiAgICAgIHV0aWxzXG4gICAgICAgIC53ZWlnaHRlZEZpbHRlcihcbiAgICAgICAgICB2YWxpZGF0b3JzQ291bnQudm90ZXNcbiAgICAgICAgICAgIC5tYXAoKHZvdGVzLCBjb3VudCkgPT4gKHsgY291bnQsIHZvdGVzOiB2b3RlcyA9PT0gdW5kZWZpbmVkID8gdXRpbHMuWkVSTyA6IHZvdGVzIH0pKVxuICAgICAgICAgICAgLmZpbHRlcigoeyB2b3RlcyB9KSA9PiB2b3Rlcy5ndCh1dGlscy5aRVJPKSksXG4gICAgICAgICAgMC4yNSxcbiAgICAgICAgICAwLjc1LFxuICAgICAgICAgICh7IGNvdW50IH0pID0+IG5ldyBCTihjb3VudCksXG4gICAgICAgIClcbiAgICAgICAgLm1hcCgoW3sgY291bnQgfSwgd2VpZ2h0XSkgPT4gKHsgdmFsdWU6IGNvdW50LCB3ZWlnaHQgfSkpLFxuICAgICksXG5cbiAgICBibG9ja2NoYWluLnNldHRpbmdzLnN0YW5kYnlWYWxpZGF0b3JzLmxlbmd0aCxcbiAgKTtcblxuICBjb25zdCBzdGFuZGJ5VmFsaWRhdG9yc1NldCA9IG5ldyBTZXQoXG4gICAgYmxvY2tjaGFpbi5zZXR0aW5ncy5zdGFuZGJ5VmFsaWRhdG9ycy5tYXAoKHB1YmxpY0tleSkgPT4gY29tbW9uLmVjUG9pbnRUb0hleChwdWJsaWNLZXkpKSxcbiAgKTtcblxuICBjb25zdCB2YWxpZGF0b3JzUHVibGljS2V5U2V0ID0gbmV3IFNldChcbiAgICBfLnRha2UoXG4gICAgICB2YWxpZGF0b3JzXG4gICAgICAgIC5maWx0ZXIoXG4gICAgICAgICAgKHZhbGlkYXRvcikgPT5cbiAgICAgICAgICAgICh2YWxpZGF0b3IucmVnaXN0ZXJlZCAmJiB2YWxpZGF0b3Iudm90ZXMuZ3QodXRpbHMuWkVSTykpIHx8XG4gICAgICAgICAgICBzdGFuZGJ5VmFsaWRhdG9yc1NldC5oYXMoY29tbW9uLmVjUG9pbnRUb0hleCh2YWxpZGF0b3IucHVibGljS2V5KSksXG4gICAgICAgIClcbiAgICAgICAgLnNvcnQoXG4gICAgICAgICAgKGFWYWxpZGF0b3IsIGJWYWxpZGF0b3IpID0+XG4gICAgICAgICAgICBhVmFsaWRhdG9yLnZvdGVzLmVxKGJWYWxpZGF0b3Iudm90ZXMpXG4gICAgICAgICAgICAgID8gY29tbW9uLmVjUG9pbnRDb21wYXJlKGFWYWxpZGF0b3IucHVibGljS2V5LCBiVmFsaWRhdG9yLnB1YmxpY0tleSlcbiAgICAgICAgICAgICAgOiAtYVZhbGlkYXRvci52b3Rlcy5jbXAoYlZhbGlkYXRvci52b3RlcyksXG4gICAgICAgIClcbiAgICAgICAgLm1hcCgodmFsaWRhdG9yKSA9PiBjb21tb24uZWNQb2ludFRvSGV4KHZhbGlkYXRvci5wdWJsaWNLZXkpKSxcbiAgICAgIG51bVZhbGlkYXRvcnMsXG4gICAgKSxcbiAgKTtcblxuICBjb25zdCBzdGFuZGJ5VmFsaWRhdG9yc0FycmF5ID0gWy4uLnN0YW5kYnlWYWxpZGF0b3JzU2V0XTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdGFuZGJ5VmFsaWRhdG9yc0FycmF5Lmxlbmd0aCAmJiB2YWxpZGF0b3JzUHVibGljS2V5U2V0LnNpemUgPCBudW1WYWxpZGF0b3JzOyBpICs9IDEpIHtcbiAgICB2YWxpZGF0b3JzUHVibGljS2V5U2V0LmFkZChzdGFuZGJ5VmFsaWRhdG9yc0FycmF5W2ldKTtcbiAgfVxuXG4gIGNvbnN0IHZhbGlkYXRvcnNQdWJsaWNLZXlzID0gWy4uLnZhbGlkYXRvcnNQdWJsaWNLZXlTZXRdLm1hcCgoaGV4KSA9PiBjb21tb24uaGV4VG9FQ1BvaW50KGhleCkpO1xuXG4gIHJldHVybiB2YWxpZGF0b3JzUHVibGljS2V5cy5zb3J0KChhS2V5LCBiS2V5KSA9PiBjb21tb24uZWNQb2ludENvbXBhcmUoYUtleSwgYktleSkpO1xufTtcbiJdfQ==