@coolwallet/sol
Version:
Coolwallet Solana sdk
331 lines (325 loc) • 73.5 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Message = void 0;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var BufferLayout = _interopRequireWildcard(require("@solana/buffer-layout"));
var _stringUtil = require("../utils/stringUtil");
var _commonLayout = require("../utils/commonLayout");
var _params = require("../config/params");
var shortvec = _interopRequireWildcard(require("../utils/shortvec-encoding"));
var _bufferUtils = require("../utils/bufferUtils");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
var Message = /*#__PURE__*/function () {
function Message(message) {
(0, _classCallCheck2["default"])(this, Message);
this.header = message.header;
this.accountKeys = message.accountKeys;
this.recentBlockhash = message.recentBlockhash;
this.instructions = message.instructions;
}
(0, _createClass2["default"])(Message, [{
key: "serializeHeader",
value: function serializeHeader() {
return (0, _stringUtil.numberToStringHex)(this.header.numRequiredSignatures, 2) + (0, _stringUtil.numberToStringHex)(this.header.numReadonlySignedAccounts, 2) + (0, _stringUtil.numberToStringHex)(this.header.numReadonlyUnsignedAccounts, 2);
}
}, {
key: "encodedLength",
value: function encodedLength() {
// encode key count
var numKeys = this.accountKeys.length;
var keyCount = [];
(0, _stringUtil.encodeLength)(keyCount, numKeys);
// extract input instructions to serialize instructions
var instructions = this.instructions.map(function (instruction) {
var accounts = instruction.accounts,
programIdIndex = instruction.programIdIndex;
var data = Array.from(Buffer.from(instruction.data, 'hex'));
var keyIndicesCount = [];
(0, _stringUtil.encodeLength)(keyIndicesCount, accounts.length);
var dataCount = [];
(0, _stringUtil.encodeLength)(dataCount, data.length);
return {
programIdIndex: programIdIndex,
keyIndicesCount: Buffer.from(keyIndicesCount),
keyIndices: accounts,
dataLength: Buffer.from(dataCount),
data: data
};
});
// encode instruction count
var instructionCount = [];
(0, _stringUtil.encodeLength)(instructionCount, instructions.length);
return {
keyCount: keyCount,
instructionCount: instructionCount,
instructions: instructions
};
}
}, {
key: "serialize",
value: function serialize() {
var _this$encodedLength = this.encodedLength(),
keyCount = _this$encodedLength.keyCount,
instructionCount = _this$encodedLength.instructionCount,
instructions = _this$encodedLength.instructions;
// encode instruction
var instructionBuffer = Buffer.alloc(_params.PACKET_DATA_SIZE);
Buffer.from(instructionCount).copy(instructionBuffer);
var instructionBufferLength = instructionCount.length;
instructions.forEach(function (instruction) {
var instructionLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(instruction.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), instruction.keyIndices.length, 'keyIndices'), BufferLayout.blob(instruction.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), instruction.data.length, 'data')]);
instructionBufferLength += instructionLayout.encode(instruction, instructionBuffer, instructionBufferLength);
});
instructionBuffer = instructionBuffer.slice(0, instructionBufferLength);
// encode sign data
var signDataLayout = BufferLayout.struct([BufferLayout.blob(1, 'numRequiredSignatures'), BufferLayout.blob(1, 'numReadonlySignedAccounts'), BufferLayout.blob(1, 'numReadonlyUnsignedAccounts'), BufferLayout.blob(keyCount.length, 'keyCount'), BufferLayout.seq((0, _commonLayout.publicKey)('key'), this.accountKeys.length, 'keys'), (0, _commonLayout.publicKey)('recentBlockhash')]);
var transaction = {
numRequiredSignatures: Buffer.from([this.header.numRequiredSignatures]),
numReadonlySignedAccounts: Buffer.from([this.header.numReadonlySignedAccounts]),
numReadonlyUnsignedAccounts: Buffer.from([this.header.numReadonlyUnsignedAccounts]),
keyCount: Buffer.from(keyCount),
keys: this.accountKeys.map(function (key) {
return Buffer.from(key, 'hex');
}),
recentBlockhash: Buffer.from(this.recentBlockhash, 'hex')
};
var signData = Buffer.alloc(2048); // sign data max length
var length = signDataLayout.encode(transaction, signData);
instructionBuffer.copy(signData, length);
// return signData.slice(0, length + instructionBuffer.length).toString('hex');
return signData.slice(0, length + instructionBuffer.length);
}
}, {
key: "serializeTransferMessage",
value: function serializeTransferMessage() {
var _this$encodedLength2 = this.encodedLength(),
keyCount = _this$encodedLength2.keyCount,
instructions = _this$encodedLength2.instructions;
var instructionBuffer = Buffer.alloc(_params.PACKET_DATA_SIZE);
var gasPrice;
var gasLimit;
var transfer;
var instructionBufferLength = 0;
if (instructions.length === 3) {
var _instructions = (0, _slicedToArray2["default"])(instructions, 3);
gasPrice = _instructions[0];
gasLimit = _instructions[1];
transfer = _instructions[2];
var gasPriceLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(gasPrice.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), gasPrice.keyIndices.length, 'keyIndices'), BufferLayout.blob(gasPrice.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), gasPrice.data.length, 'data')]);
instructionBufferLength = gasPriceLayout.encode(gasPrice, instructionBuffer, 0);
var gasLimitLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(gasLimit.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), gasLimit.keyIndices.length, 'keyIndices'), BufferLayout.blob(gasLimit.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), gasLimit.data.length, 'data')]);
instructionBufferLength += gasLimitLayout.encode(gasLimit, instructionBuffer, instructionBufferLength);
} else {
var _instructions2 = (0, _slicedToArray2["default"])(instructions, 1);
transfer = _instructions2[0];
}
var transferLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(transfer.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), transfer.keyIndices.length, 'keyIndices'), BufferLayout.blob(transfer.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), transfer.data.length, 'data')]);
instructionBufferLength += transferLayout.encode(transfer, instructionBuffer, instructionBufferLength);
instructionBuffer = instructionBuffer.slice(0, instructionBufferLength);
var accountKeys = (0, _toConsumableArray2["default"])(this.accountKeys);
for (var i = this.accountKeys.length; i < 6; i++) {
accountKeys = accountKeys.concat(_params.PADDING_PUBLICKEY);
}
var signDataLayout = BufferLayout.struct([BufferLayout.blob(keyCount.length, 'keyCount'), BufferLayout.seq((0, _commonLayout.publicKey)('key'), accountKeys.length, 'keys'), (0, _commonLayout.publicKey)('recentBlockhash')]);
var transaction = {
keyCount: Buffer.from(keyCount),
keys: accountKeys.map(function (key) {
return Buffer.from(key, 'hex');
}),
recentBlockhash: Buffer.from(this.recentBlockhash, 'hex')
};
var signData = Buffer.alloc(2048); // sign data max length
var length = signDataLayout.encode(transaction, signData);
instructionBuffer.copy(signData, length);
return signData.slice(0, length + instructionBuffer.length).toString('hex');
}
}, {
key: "serializeCreateAndTransferSPLToken",
value: function serializeCreateAndTransferSPLToken() {
var _this$encodedLength3 = this.encodedLength(),
keyCount = _this$encodedLength3.keyCount,
instructions = _this$encodedLength3.instructions;
var instructionBuffer = Buffer.alloc(_params.PACKET_DATA_SIZE);
var associateAccount;
var gasPrice;
var gasLimit;
var tokenTransfer;
var instructionBufferLength = 0;
if (instructions.length === 4) {
var _instructions3 = (0, _slicedToArray2["default"])(instructions, 4);
associateAccount = _instructions3[0];
gasPrice = _instructions3[1];
gasLimit = _instructions3[2];
tokenTransfer = _instructions3[3];
var associateAccountLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(associateAccount.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), associateAccount.keyIndices.length, 'keyIndices'), BufferLayout.blob(associateAccount.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), associateAccount.data.length, 'data')]);
instructionBufferLength = associateAccountLayout.encode(associateAccount, instructionBuffer, 0);
var gasPriceLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(gasPrice.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), gasPrice.keyIndices.length, 'keyIndices'), BufferLayout.blob(gasPrice.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), gasPrice.data.length, 'data')]);
instructionBufferLength += gasPriceLayout.encode(gasPrice, instructionBuffer, instructionBufferLength);
var gasLimitLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(gasLimit.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), gasLimit.keyIndices.length, 'keyIndices'), BufferLayout.blob(gasLimit.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), gasLimit.data.length, 'data')]);
instructionBufferLength += gasLimitLayout.encode(gasLimit, instructionBuffer, instructionBufferLength);
} else {
var _instructions4 = (0, _slicedToArray2["default"])(instructions, 2);
associateAccount = _instructions4[0];
tokenTransfer = _instructions4[1];
var _associateAccountLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(associateAccount.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), associateAccount.keyIndices.length, 'keyIndices'), BufferLayout.blob(associateAccount.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), associateAccount.data.length, 'data')]);
instructionBufferLength = _associateAccountLayout.encode(associateAccount, instructionBuffer, 0);
}
var tokenTransferLayout = BufferLayout.struct([BufferLayout.u8('programIdIndex'), BufferLayout.blob(tokenTransfer.keyIndicesCount.length, 'keyIndicesCount'), BufferLayout.seq(BufferLayout.u8('keyIndex'), tokenTransfer.keyIndices.length, 'keyIndices'), BufferLayout.blob(tokenTransfer.dataLength.length, 'dataLength'), BufferLayout.seq(BufferLayout.u8('userdatum'), tokenTransfer.data.length, 'data')]);
instructionBufferLength += tokenTransferLayout.encode(tokenTransfer, instructionBuffer, instructionBufferLength);
instructionBuffer = instructionBuffer.slice(0, instructionBufferLength);
var accountKeys = (0, _toConsumableArray2["default"])(this.accountKeys);
for (var i = this.accountKeys.length; i < 9; i++) {
accountKeys = accountKeys.concat(Buffer.alloc(32).toString('hex'));
}
var signDataLayout = BufferLayout.struct([BufferLayout.blob(keyCount.length, 'keyCount'), BufferLayout.seq((0, _commonLayout.publicKey)('key'), accountKeys.length, 'keys'), (0, _commonLayout.publicKey)('recentBlockhash')]);
var transaction = {
keyCount: Buffer.from(keyCount),
keys: accountKeys.map(function (key) {
return Buffer.from(key, 'hex');
}),
recentBlockhash: Buffer.from(this.recentBlockhash, 'hex')
};
var signData = Buffer.alloc(2048); // sign data max length
var length = signDataLayout.encode(transaction, signData);
instructionBuffer.copy(signData, length);
return signData.slice(0, length + instructionBuffer.length).toString('hex');
}
}, {
key: "reservePaddingAccountKeys",
value: function reservePaddingAccountKeys(maxAccountKeyLength) {
var accountKeys = this.accountKeys;
var needPaddingKeyLength = maxAccountKeyLength - this.accountKeys.length;
for (var i = 0; i < needPaddingKeyLength; i++) {
accountKeys.push(_params.PADDING_PUBLICKEY);
}
return accountKeys;
}
}, {
key: "serializeDelegateAndCreateAccountWithSeed",
value: function serializeDelegateAndCreateAccountWithSeed() {
var _this$encodedLength4 = this.encodedLength(),
keyCount = _this$encodedLength4.keyCount,
instructionCount = _this$encodedLength4.instructionCount,
instructions = _this$encodedLength4.instructions;
var initAndPaddingInstruction = (0, _bufferUtils.initAndPaddingComputeBudgetInstructionBuffer)(this.accountKeys, instructions, instructionCount);
var instructionBuffer = (0, _bufferUtils.encodeAndPaddingSeedInstructionBuffer)(this.accountKeys, instructions, initAndPaddingInstruction.instructionBuffer, initAndPaddingInstruction.instructionBufferLength);
/**
* signerPubkey
* stakeAccountPubkey
* 11111111111111111111111111111111
* validatorPubkey
* Stake11111111111111111111111111111111111111
* StakeConfig11111111111111111111111111111111
* SysvarC1ock11111111111111111111111111111111
* SysvarRent111111111111111111111111111111111
* SysvarStakeHistory1111111111111111111111111
* ComputeBudget111111111111111111111111111111 (optional)
*/
var newAccountKeys = this.reservePaddingAccountKeys(10);
return (0, _bufferUtils.encodeSignData)(keyCount, newAccountKeys, this.recentBlockhash, instructionBuffer).toString('hex');
}
}, {
key: "serializeUndelegate",
value: function serializeUndelegate() {
var _this$encodedLength5 = this.encodedLength(),
keyCount = _this$encodedLength5.keyCount,
instructionCount = _this$encodedLength5.instructionCount,
instructions = _this$encodedLength5.instructions;
var initAndPaddingInstruction = (0, _bufferUtils.initAndPaddingComputeBudgetInstructionBuffer)(this.accountKeys, instructions, instructionCount);
var instructionBuffer = (0, _bufferUtils.encodeInstructionBuffer)(instructions, initAndPaddingInstruction.instructionBuffer, initAndPaddingInstruction.instructionBufferLength);
/**
* signerPubkey
* stakeAccountPubkey
* Stake11111111111111111111111111111111111111
* SysvarC1ock11111111111111111111111111111111
* ComputeBudget111111111111111111111111111111 (optional)
*/
var newAccountKeys = this.reservePaddingAccountKeys(5);
return (0, _bufferUtils.encodeSignData)(keyCount, newAccountKeys, this.recentBlockhash, instructionBuffer).toString('hex');
}
}, {
key: "serializeWithdraw",
value: function serializeWithdraw() {
var _this$encodedLength6 = this.encodedLength(),
keyCount = _this$encodedLength6.keyCount,
instructionCount = _this$encodedLength6.instructionCount,
instructions = _this$encodedLength6.instructions;
var initAndPaddingInstruction = (0, _bufferUtils.initAndPaddingComputeBudgetInstructionBuffer)(this.accountKeys, instructions, instructionCount);
var instructionBuffer = (0, _bufferUtils.encodeInstructionBuffer)(instructions, initAndPaddingInstruction.instructionBuffer, initAndPaddingInstruction.instructionBufferLength);
/**
* signerPubkey
* stakeAccountPubkey
* withdrawToPubkey (optional)
* Stake11111111111111111111111111111111111111
* SysvarC1ock11111111111111111111111111111111
* SysvarStakeHistory1111111111111111111111111
* ComputeBudget111111111111111111111111111111 (optional)
*/
var newAccountKeys = this.reservePaddingAccountKeys(7);
return (0, _bufferUtils.encodeSignData)(keyCount, newAccountKeys, this.recentBlockhash, instructionBuffer).toString('hex');
}
/**
* Decode a compiled message into a Message object.
*/
}], [{
key: "from",
value: function from(buffer) {
// Slice up wire data
var byteArray = (0, _toConsumableArray2["default"])(buffer);
var numRequiredSignatures = byteArray.shift();
if (numRequiredSignatures !== (numRequiredSignatures & _params.VERSION_PREFIX_MASK)) {
throw new Error('Versioned messages must be deserialized with VersionedMessage.deserialize()');
}
var numReadonlySignedAccounts = byteArray.shift();
var numReadonlyUnsignedAccounts = byteArray.shift();
var accountCount = shortvec.decodeLength(byteArray);
var accountKeys = [];
for (var i = 0; i < accountCount; i++) {
var account = byteArray.slice(0, _params.PUBLIC_KEY_LENGTH);
byteArray = byteArray.slice(_params.PUBLIC_KEY_LENGTH);
accountKeys.push(Buffer.from(account).toString('hex'));
}
var recentBlockhash = byteArray.slice(0, _params.PUBLIC_KEY_LENGTH);
byteArray = byteArray.slice(_params.PUBLIC_KEY_LENGTH);
var instructionCount = shortvec.decodeLength(byteArray);
var instructions = [];
for (var _i = 0; _i < instructionCount; _i++) {
var programIdIndex = byteArray.shift();
var instructionAccountCount = shortvec.decodeLength(byteArray);
var accounts = byteArray.slice(0, instructionAccountCount);
byteArray = byteArray.slice(instructionAccountCount);
var dataLength = shortvec.decodeLength(byteArray);
var dataSlice = byteArray.slice(0, dataLength);
var data = Buffer.from(dataSlice).toString('hex');
byteArray = byteArray.slice(dataLength);
instructions.push({
programIdIndex: programIdIndex,
accounts: accounts,
data: data
});
}
var messageArgs = {
header: {
numRequiredSignatures: numRequiredSignatures,
numReadonlySignedAccounts: numReadonlySignedAccounts,
numReadonlyUnsignedAccounts: numReadonlyUnsignedAccounts
},
recentBlockhash: Buffer.from(recentBlockhash).toString('hex'),
accountKeys: accountKeys,
instructions: instructions
};
return new Message(messageArgs);
}
}]);
return Message;
}();
exports.Message = Message;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJCdWZmZXJMYXlvdXQiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfc3RyaW5nVXRpbCIsIl9jb21tb25MYXlvdXQiLCJfcGFyYW1zIiwic2hvcnR2ZWMiLCJfYnVmZmVyVXRpbHMiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJub2RlSW50ZXJvcCIsIldlYWtNYXAiLCJjYWNoZUJhYmVsSW50ZXJvcCIsImNhY2hlTm9kZUludGVyb3AiLCJvYmoiLCJfX2VzTW9kdWxlIiwiX3R5cGVvZiIsImNhY2hlIiwiaGFzIiwiZ2V0IiwibmV3T2JqIiwiaGFzUHJvcGVydHlEZXNjcmlwdG9yIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJrZXkiLCJwcm90b3R5cGUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJkZXNjIiwic2V0IiwiTWVzc2FnZSIsIm1lc3NhZ2UiLCJfY2xhc3NDYWxsQ2hlY2syIiwiaGVhZGVyIiwiYWNjb3VudEtleXMiLCJyZWNlbnRCbG9ja2hhc2giLCJpbnN0cnVjdGlvbnMiLCJfY3JlYXRlQ2xhc3MyIiwidmFsdWUiLCJzZXJpYWxpemVIZWFkZXIiLCJudW1iZXJUb1N0cmluZ0hleCIsIm51bVJlcXVpcmVkU2lnbmF0dXJlcyIsIm51bVJlYWRvbmx5U2lnbmVkQWNjb3VudHMiLCJudW1SZWFkb25seVVuc2lnbmVkQWNjb3VudHMiLCJlbmNvZGVkTGVuZ3RoIiwibnVtS2V5cyIsImxlbmd0aCIsImtleUNvdW50IiwiZW5jb2RlTGVuZ3RoIiwibWFwIiwiaW5zdHJ1Y3Rpb24iLCJhY2NvdW50cyIsInByb2dyYW1JZEluZGV4IiwiZGF0YSIsIkFycmF5IiwiZnJvbSIsIkJ1ZmZlciIsImtleUluZGljZXNDb3VudCIsImRhdGFDb3VudCIsImtleUluZGljZXMiLCJkYXRhTGVuZ3RoIiwiaW5zdHJ1Y3Rpb25Db3VudCIsInNlcmlhbGl6ZSIsIl90aGlzJGVuY29kZWRMZW5ndGgiLCJpbnN0cnVjdGlvbkJ1ZmZlciIsImFsbG9jIiwiUEFDS0VUX0RBVEFfU0laRSIsImNvcHkiLCJpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCIsImZvckVhY2giLCJpbnN0cnVjdGlvbkxheW91dCIsInN0cnVjdCIsInU4IiwiYmxvYiIsInNlcSIsImVuY29kZSIsInNsaWNlIiwic2lnbkRhdGFMYXlvdXQiLCJwdWJsaWNLZXkiLCJ0cmFuc2FjdGlvbiIsImtleXMiLCJzaWduRGF0YSIsInNlcmlhbGl6ZVRyYW5zZmVyTWVzc2FnZSIsIl90aGlzJGVuY29kZWRMZW5ndGgyIiwiZ2FzUHJpY2UiLCJnYXNMaW1pdCIsInRyYW5zZmVyIiwiX2luc3RydWN0aW9ucyIsIl9zbGljZWRUb0FycmF5MiIsImdhc1ByaWNlTGF5b3V0IiwiZ2FzTGltaXRMYXlvdXQiLCJfaW5zdHJ1Y3Rpb25zMiIsInRyYW5zZmVyTGF5b3V0IiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsImkiLCJjb25jYXQiLCJQQURESU5HX1BVQkxJQ0tFWSIsInRvU3RyaW5nIiwic2VyaWFsaXplQ3JlYXRlQW5kVHJhbnNmZXJTUExUb2tlbiIsIl90aGlzJGVuY29kZWRMZW5ndGgzIiwiYXNzb2NpYXRlQWNjb3VudCIsInRva2VuVHJhbnNmZXIiLCJfaW5zdHJ1Y3Rpb25zMyIsImFzc29jaWF0ZUFjY291bnRMYXlvdXQiLCJfaW5zdHJ1Y3Rpb25zNCIsInRva2VuVHJhbnNmZXJMYXlvdXQiLCJyZXNlcnZlUGFkZGluZ0FjY291bnRLZXlzIiwibWF4QWNjb3VudEtleUxlbmd0aCIsIm5lZWRQYWRkaW5nS2V5TGVuZ3RoIiwicHVzaCIsInNlcmlhbGl6ZURlbGVnYXRlQW5kQ3JlYXRlQWNjb3VudFdpdGhTZWVkIiwiX3RoaXMkZW5jb2RlZExlbmd0aDQiLCJpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uIiwiaW5pdEFuZFBhZGRpbmdDb21wdXRlQnVkZ2V0SW5zdHJ1Y3Rpb25CdWZmZXIiLCJlbmNvZGVBbmRQYWRkaW5nU2VlZEluc3RydWN0aW9uQnVmZmVyIiwibmV3QWNjb3VudEtleXMiLCJlbmNvZGVTaWduRGF0YSIsInNlcmlhbGl6ZVVuZGVsZWdhdGUiLCJfdGhpcyRlbmNvZGVkTGVuZ3RoNSIsImVuY29kZUluc3RydWN0aW9uQnVmZmVyIiwic2VyaWFsaXplV2l0aGRyYXciLCJfdGhpcyRlbmNvZGVkTGVuZ3RoNiIsImJ1ZmZlciIsImJ5dGVBcnJheSIsInNoaWZ0IiwiVkVSU0lPTl9QUkVGSVhfTUFTSyIsIkVycm9yIiwiYWNjb3VudENvdW50IiwiZGVjb2RlTGVuZ3RoIiwiYWNjb3VudCIsIlBVQkxJQ19LRVlfTEVOR1RIIiwiaW5zdHJ1Y3Rpb25BY2NvdW50Q291bnQiLCJkYXRhU2xpY2UiLCJtZXNzYWdlQXJncyIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVzc2FnZS9sZWdhY3kudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgQnVmZmVyTGF5b3V0IGZyb20gJ0Bzb2xhbmEvYnVmZmVyLWxheW91dCc7XG5pbXBvcnQgeyBlbmNvZGVMZW5ndGgsIG51bWJlclRvU3RyaW5nSGV4IH0gZnJvbSAnLi4vdXRpbHMvc3RyaW5nVXRpbCc7XG5pbXBvcnQgeyBwdWJsaWNLZXkgfSBmcm9tICcuLi91dGlscy9jb21tb25MYXlvdXQnO1xuaW1wb3J0IHsgUEFDS0VUX0RBVEFfU0laRSwgUEFERElOR19QVUJMSUNLRVksIFBVQkxJQ19LRVlfTEVOR1RILCBWRVJTSU9OX1BSRUZJWF9NQVNLIH0gZnJvbSAnLi4vY29uZmlnL3BhcmFtcyc7XG5pbXBvcnQgeyBDb21waWxlZEluc3RydWN0aW9uLCBDb21wbGllZEluc3RydWN0aW9uLCBTZXJpYWxpemVkSW5zdHJ1Y3Rpb24gfSBmcm9tICcuLi9jb25maWcvdHlwZXMnO1xuaW1wb3J0ICogYXMgc2hvcnR2ZWMgZnJvbSAnLi4vdXRpbHMvc2hvcnR2ZWMtZW5jb2RpbmcnO1xuaW1wb3J0IHtcbiAgZW5jb2RlQW5kUGFkZGluZ1NlZWRJbnN0cnVjdGlvbkJ1ZmZlcixcbiAgZW5jb2RlSW5zdHJ1Y3Rpb25CdWZmZXIsXG4gIGVuY29kZVNpZ25EYXRhLFxuICBpbml0QW5kUGFkZGluZ0NvbXB1dGVCdWRnZXRJbnN0cnVjdGlvbkJ1ZmZlcixcbn0gZnJvbSAnLi4vdXRpbHMvYnVmZmVyVXRpbHMnO1xuXG50eXBlIE1lc3NhZ2VIZWFkZXIgPSB7XG4gIG51bVJlcXVpcmVkU2lnbmF0dXJlczogbnVtYmVyO1xuICBudW1SZWFkb25seVNpZ25lZEFjY291bnRzOiBudW1iZXI7XG4gIG51bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50czogbnVtYmVyO1xufTtcblxudHlwZSBNZXNzYWdlQXJncyA9IHtcbiAgaGVhZGVyOiBNZXNzYWdlSGVhZGVyO1xuICBhY2NvdW50S2V5czogc3RyaW5nW107XG4gIHJlY2VudEJsb2NraGFzaDogc3RyaW5nO1xuICBpbnN0cnVjdGlvbnM6IENvbXBsaWVkSW5zdHJ1Y3Rpb25bXTtcbn07XG5cbmV4cG9ydCBjbGFzcyBNZXNzYWdlIHtcbiAgaGVhZGVyOiBNZXNzYWdlSGVhZGVyO1xuICBhY2NvdW50S2V5czogc3RyaW5nW107XG4gIHJlY2VudEJsb2NraGFzaDogc3RyaW5nO1xuICBpbnN0cnVjdGlvbnM6IENvbXBsaWVkSW5zdHJ1Y3Rpb25bXTtcblxuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBNZXNzYWdlQXJncykge1xuICAgIHRoaXMuaGVhZGVyID0gbWVzc2FnZS5oZWFkZXI7XG4gICAgdGhpcy5hY2NvdW50S2V5cyA9IG1lc3NhZ2UuYWNjb3VudEtleXM7XG4gICAgdGhpcy5yZWNlbnRCbG9ja2hhc2ggPSBtZXNzYWdlLnJlY2VudEJsb2NraGFzaDtcbiAgICB0aGlzLmluc3RydWN0aW9ucyA9IG1lc3NhZ2UuaW5zdHJ1Y3Rpb25zO1xuICB9XG5cbiAgc2VyaWFsaXplSGVhZGVyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIChcbiAgICAgIG51bWJlclRvU3RyaW5nSGV4KHRoaXMuaGVhZGVyLm51bVJlcXVpcmVkU2lnbmF0dXJlcywgMikgK1xuICAgICAgbnVtYmVyVG9TdHJpbmdIZXgodGhpcy5oZWFkZXIubnVtUmVhZG9ubHlTaWduZWRBY2NvdW50cywgMikgK1xuICAgICAgbnVtYmVyVG9TdHJpbmdIZXgodGhpcy5oZWFkZXIubnVtUmVhZG9ubHlVbnNpZ25lZEFjY291bnRzLCAyKVxuICAgICk7XG4gIH1cblxuICBlbmNvZGVkTGVuZ3RoKCk6IHsga2V5Q291bnQ6IG51bWJlcltdOyBpbnN0cnVjdGlvbkNvdW50OiBudW1iZXJbXTsgaW5zdHJ1Y3Rpb25zOiBTZXJpYWxpemVkSW5zdHJ1Y3Rpb25bXSB9IHtcbiAgICAvLyBlbmNvZGUga2V5IGNvdW50XG4gICAgY29uc3QgbnVtS2V5cyA9IHRoaXMuYWNjb3VudEtleXMubGVuZ3RoO1xuICAgIGNvbnN0IGtleUNvdW50OiBudW1iZXJbXSA9IFtdO1xuICAgIGVuY29kZUxlbmd0aChrZXlDb3VudCwgbnVtS2V5cyk7XG5cbiAgICAvLyBleHRyYWN0IGlucHV0IGluc3RydWN0aW9ucyB0byBzZXJpYWxpemUgaW5zdHJ1Y3Rpb25zXG4gICAgY29uc3QgaW5zdHJ1Y3Rpb25zID0gdGhpcy5pbnN0cnVjdGlvbnMubWFwKChpbnN0cnVjdGlvbikgPT4ge1xuICAgICAgY29uc3QgeyBhY2NvdW50cywgcHJvZ3JhbUlkSW5kZXggfSA9IGluc3RydWN0aW9uO1xuICAgICAgY29uc3QgZGF0YSA9IEFycmF5LmZyb20oQnVmZmVyLmZyb20oaW5zdHJ1Y3Rpb24uZGF0YSwgJ2hleCcpKTtcblxuICAgICAgY29uc3Qga2V5SW5kaWNlc0NvdW50OiBudW1iZXJbXSA9IFtdO1xuICAgICAgZW5jb2RlTGVuZ3RoKGtleUluZGljZXNDb3VudCwgYWNjb3VudHMubGVuZ3RoKTtcblxuICAgICAgY29uc3QgZGF0YUNvdW50OiBudW1iZXJbXSA9IFtdO1xuICAgICAgZW5jb2RlTGVuZ3RoKGRhdGFDb3VudCwgZGF0YS5sZW5ndGgpO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBwcm9ncmFtSWRJbmRleCxcbiAgICAgICAga2V5SW5kaWNlc0NvdW50OiBCdWZmZXIuZnJvbShrZXlJbmRpY2VzQ291bnQpLFxuICAgICAgICBrZXlJbmRpY2VzOiBhY2NvdW50cyxcbiAgICAgICAgZGF0YUxlbmd0aDogQnVmZmVyLmZyb20oZGF0YUNvdW50KSxcbiAgICAgICAgZGF0YSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBlbmNvZGUgaW5zdHJ1Y3Rpb24gY291bnRcbiAgICBjb25zdCBpbnN0cnVjdGlvbkNvdW50OiBudW1iZXJbXSA9IFtdO1xuICAgIGVuY29kZUxlbmd0aChpbnN0cnVjdGlvbkNvdW50LCBpbnN0cnVjdGlvbnMubGVuZ3RoKTtcbiAgICByZXR1cm4geyBrZXlDb3VudCwgaW5zdHJ1Y3Rpb25Db3VudCwgaW5zdHJ1Y3Rpb25zIH07XG4gIH1cblxuICBzZXJpYWxpemUoKTogQnVmZmVyIHtcbiAgICBjb25zdCB7IGtleUNvdW50LCBpbnN0cnVjdGlvbkNvdW50LCBpbnN0cnVjdGlvbnMgfSA9IHRoaXMuZW5jb2RlZExlbmd0aCgpO1xuICAgIC8vIGVuY29kZSBpbnN0cnVjdGlvblxuICAgIGxldCBpbnN0cnVjdGlvbkJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhQQUNLRVRfREFUQV9TSVpFKTtcbiAgICBCdWZmZXIuZnJvbShpbnN0cnVjdGlvbkNvdW50KS5jb3B5KGluc3RydWN0aW9uQnVmZmVyKTtcbiAgICBsZXQgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggPSBpbnN0cnVjdGlvbkNvdW50Lmxlbmd0aDtcblxuICAgIGluc3RydWN0aW9ucy5mb3JFYWNoKChpbnN0cnVjdGlvbikgPT4ge1xuICAgICAgY29uc3QgaW5zdHJ1Y3Rpb25MYXlvdXQgPSBCdWZmZXJMYXlvdXQuc3RydWN0PFxuICAgICAgICBSZWFkb25seTx7XG4gICAgICAgICAgZGF0YTogbnVtYmVyW107XG4gICAgICAgICAgZGF0YUxlbmd0aDogVWludDhBcnJheTtcbiAgICAgICAgICBrZXlJbmRpY2VzOiBudW1iZXJbXTtcbiAgICAgICAgICBrZXlJbmRpY2VzQ291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICAgICAgcHJvZ3JhbUlkSW5kZXg6IG51bWJlcjtcbiAgICAgICAgfT5cbiAgICAgID4oW1xuICAgICAgICBCdWZmZXJMYXlvdXQudTgoJ3Byb2dyYW1JZEluZGV4JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGluc3RydWN0aW9uLmtleUluZGljZXNDb3VudC5sZW5ndGgsICdrZXlJbmRpY2VzQ291bnQnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ2tleUluZGV4JyksIGluc3RydWN0aW9uLmtleUluZGljZXMubGVuZ3RoLCAna2V5SW5kaWNlcycpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihpbnN0cnVjdGlvbi5kYXRhTGVuZ3RoLmxlbmd0aCwgJ2RhdGFMZW5ndGgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ3VzZXJkYXR1bScpLCBpbnN0cnVjdGlvbi5kYXRhLmxlbmd0aCwgJ2RhdGEnKSxcbiAgICAgIF0pO1xuICAgICAgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggKz0gaW5zdHJ1Y3Rpb25MYXlvdXQuZW5jb2RlKGluc3RydWN0aW9uLCBpbnN0cnVjdGlvbkJ1ZmZlciwgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGgpO1xuICAgIH0pO1xuICAgIGluc3RydWN0aW9uQnVmZmVyID0gaW5zdHJ1Y3Rpb25CdWZmZXIuc2xpY2UoMCwgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGgpO1xuXG4gICAgLy8gZW5jb2RlIHNpZ24gZGF0YVxuICAgIGNvbnN0IHNpZ25EYXRhTGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAga2V5Q291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICAgIGtleXM6IFVpbnQ4QXJyYXlbXTtcbiAgICAgICAgbnVtUmVhZG9ubHlTaWduZWRBY2NvdW50czogVWludDhBcnJheTtcbiAgICAgICAgbnVtUmVhZG9ubHlVbnNpZ25lZEFjY291bnRzOiBVaW50OEFycmF5O1xuICAgICAgICBudW1SZXF1aXJlZFNpZ25hdHVyZXM6IFVpbnQ4QXJyYXk7XG4gICAgICAgIHJlY2VudEJsb2NraGFzaDogVWludDhBcnJheTtcbiAgICAgIH0+XG4gICAgPihbXG4gICAgICBCdWZmZXJMYXlvdXQuYmxvYigxLCAnbnVtUmVxdWlyZWRTaWduYXR1cmVzJyksXG4gICAgICBCdWZmZXJMYXlvdXQuYmxvYigxLCAnbnVtUmVhZG9ubHlTaWduZWRBY2NvdW50cycpLFxuICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoMSwgJ251bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50cycpLFxuICAgICAgQnVmZmVyTGF5b3V0LmJsb2Ioa2V5Q291bnQubGVuZ3RoLCAna2V5Q291bnQnKSxcbiAgICAgIEJ1ZmZlckxheW91dC5zZXEocHVibGljS2V5KCdrZXknKSwgdGhpcy5hY2NvdW50S2V5cy5sZW5ndGgsICdrZXlzJyksXG4gICAgICBwdWJsaWNLZXkoJ3JlY2VudEJsb2NraGFzaCcpLFxuICAgIF0pO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0ge1xuICAgICAgbnVtUmVxdWlyZWRTaWduYXR1cmVzOiBCdWZmZXIuZnJvbShbdGhpcy5oZWFkZXIubnVtUmVxdWlyZWRTaWduYXR1cmVzXSksXG4gICAgICBudW1SZWFkb25seVNpZ25lZEFjY291bnRzOiBCdWZmZXIuZnJvbShbdGhpcy5oZWFkZXIubnVtUmVhZG9ubHlTaWduZWRBY2NvdW50c10pLFxuICAgICAgbnVtUmVhZG9ubHlVbnNpZ25lZEFjY291bnRzOiBCdWZmZXIuZnJvbShbdGhpcy5oZWFkZXIubnVtUmVhZG9ubHlVbnNpZ25lZEFjY291bnRzXSksXG4gICAgICBrZXlDb3VudDogQnVmZmVyLmZyb20oa2V5Q291bnQpLFxuICAgICAga2V5czogdGhpcy5hY2NvdW50S2V5cy5tYXAoKGtleSkgPT4gQnVmZmVyLmZyb20oa2V5LCAnaGV4JykpLFxuICAgICAgcmVjZW50QmxvY2toYXNoOiBCdWZmZXIuZnJvbSh0aGlzLnJlY2VudEJsb2NraGFzaCwgJ2hleCcpLFxuICAgIH07XG4gICAgY29uc3Qgc2lnbkRhdGEgPSBCdWZmZXIuYWxsb2MoMjA0OCk7IC8vIHNpZ24gZGF0YSBtYXggbGVuZ3RoXG4gICAgY29uc3QgbGVuZ3RoID0gc2lnbkRhdGFMYXlvdXQuZW5jb2RlKHRyYW5zYWN0aW9uLCBzaWduRGF0YSk7XG4gICAgaW5zdHJ1Y3Rpb25CdWZmZXIuY29weShzaWduRGF0YSwgbGVuZ3RoKTtcblxuICAgIC8vIHJldHVybiBzaWduRGF0YS5zbGljZSgwLCBsZW5ndGggKyBpbnN0cnVjdGlvbkJ1ZmZlci5sZW5ndGgpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICByZXR1cm4gc2lnbkRhdGEuc2xpY2UoMCwgbGVuZ3RoICsgaW5zdHJ1Y3Rpb25CdWZmZXIubGVuZ3RoKTtcbiAgfVxuXG4gIHNlcmlhbGl6ZVRyYW5zZmVyTWVzc2FnZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsga2V5Q291bnQsIGluc3RydWN0aW9ucyB9ID0gdGhpcy5lbmNvZGVkTGVuZ3RoKCk7XG4gICAgbGV0IGluc3RydWN0aW9uQnVmZmVyID0gQnVmZmVyLmFsbG9jKFBBQ0tFVF9EQVRBX1NJWkUpO1xuICAgIGxldCBnYXNQcmljZTtcbiAgICBsZXQgZ2FzTGltaXQ7XG4gICAgbGV0IHRyYW5zZmVyO1xuICAgIGxldCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCA9IDA7XG4gICAgaWYgKGluc3RydWN0aW9ucy5sZW5ndGggPT09IDMpIHtcbiAgICAgIFtnYXNQcmljZSwgZ2FzTGltaXQsIHRyYW5zZmVyXSA9IGluc3RydWN0aW9ucztcbiAgICAgIGNvbnN0IGdhc1ByaWNlTGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgICAgUmVhZG9ubHk8e1xuICAgICAgICAgIGRhdGE6IG51bWJlcltdO1xuICAgICAgICAgIGRhdGFMZW5ndGg6IFVpbnQ4QXJyYXk7XG4gICAgICAgICAgcHJvZ3JhbUlkSW5kZXg6IG51bWJlcjtcbiAgICAgICAgICBrZXlJbmRpY2VzOiBudW1iZXJbXTtcbiAgICAgICAgICBrZXlJbmRpY2VzQ291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICAgIH0+XG4gICAgICA+KFtcbiAgICAgICAgQnVmZmVyTGF5b3V0LnU4KCdwcm9ncmFtSWRJbmRleCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihnYXNQcmljZS5rZXlJbmRpY2VzQ291bnQubGVuZ3RoLCAna2V5SW5kaWNlc0NvdW50JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCdrZXlJbmRleCcpLCBnYXNQcmljZS5rZXlJbmRpY2VzLmxlbmd0aCwgJ2tleUluZGljZXMnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoZ2FzUHJpY2UuZGF0YUxlbmd0aC5sZW5ndGgsICdkYXRhTGVuZ3RoJyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCd1c2VyZGF0dW0nKSwgZ2FzUHJpY2UuZGF0YS5sZW5ndGgsICdkYXRhJyksXG4gICAgICBdKTtcbiAgICAgIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoID0gZ2FzUHJpY2VMYXlvdXQuZW5jb2RlKGdhc1ByaWNlLCBpbnN0cnVjdGlvbkJ1ZmZlciwgMCk7XG4gICAgICBjb25zdCBnYXNMaW1pdExheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgICBkYXRhOiBudW1iZXJbXTtcbiAgICAgICAgICBkYXRhTGVuZ3RoOiBVaW50OEFycmF5O1xuICAgICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgICAga2V5SW5kaWNlc0NvdW50OiBVaW50OEFycmF5O1xuICAgICAgICB9PlxuICAgICAgPihbXG4gICAgICAgIEJ1ZmZlckxheW91dC51OCgncHJvZ3JhbUlkSW5kZXgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoZ2FzTGltaXQua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgZ2FzTGltaXQua2V5SW5kaWNlcy5sZW5ndGgsICdrZXlJbmRpY2VzJyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGdhc0xpbWl0LmRhdGFMZW5ndGgubGVuZ3RoLCAnZGF0YUxlbmd0aCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIGdhc0xpbWl0LmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgICAgXSk7XG4gICAgICBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCArPSBnYXNMaW1pdExheW91dC5lbmNvZGUoZ2FzTGltaXQsIGluc3RydWN0aW9uQnVmZmVyLCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIFt0cmFuc2Zlcl0gPSBpbnN0cnVjdGlvbnM7XG4gICAgfVxuXG4gICAgY29uc3QgdHJhbnNmZXJMYXlvdXQgPSBCdWZmZXJMYXlvdXQuc3RydWN0PFxuICAgICAgUmVhZG9ubHk8e1xuICAgICAgICBkYXRhOiBudW1iZXJbXTtcbiAgICAgICAgZGF0YUxlbmd0aDogVWludDhBcnJheTtcbiAgICAgICAgcHJvZ3JhbUlkSW5kZXg6IG51bWJlcjtcbiAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgIGtleUluZGljZXNDb3VudDogVWludDhBcnJheTtcbiAgICAgIH0+XG4gICAgPihbXG4gICAgICBCdWZmZXJMYXlvdXQudTgoJ3Byb2dyYW1JZEluZGV4JyksXG4gICAgICBCdWZmZXJMYXlvdXQuYmxvYih0cmFuc2Zlci5rZXlJbmRpY2VzQ291bnQubGVuZ3RoLCAna2V5SW5kaWNlc0NvdW50JyksXG4gICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgdHJhbnNmZXIua2V5SW5kaWNlcy5sZW5ndGgsICdrZXlJbmRpY2VzJyksXG4gICAgICBCdWZmZXJMYXlvdXQuYmxvYih0cmFuc2Zlci5kYXRhTGVuZ3RoLmxlbmd0aCwgJ2RhdGFMZW5ndGgnKSxcbiAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCd1c2VyZGF0dW0nKSwgdHJhbnNmZXIuZGF0YS5sZW5ndGgsICdkYXRhJyksXG4gICAgXSk7XG5cbiAgICBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCArPSB0cmFuc2ZlckxheW91dC5lbmNvZGUodHJhbnNmZXIsIGluc3RydWN0aW9uQnVmZmVyLCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCk7XG4gICAgaW5zdHJ1Y3Rpb25CdWZmZXIgPSBpbnN0cnVjdGlvbkJ1ZmZlci5zbGljZSgwLCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCk7XG4gICAgbGV0IGFjY291bnRLZXlzID0gWy4uLnRoaXMuYWNjb3VudEtleXNdO1xuICAgIGZvciAobGV0IGkgPSB0aGlzLmFjY291bnRLZXlzLmxlbmd0aDsgaSA8IDY7IGkrKykge1xuICAgICAgYWNjb3VudEtleXMgPSBhY2NvdW50S2V5cy5jb25jYXQoUEFERElOR19QVUJMSUNLRVkpO1xuICAgIH1cblxuICAgIGNvbnN0IHNpZ25EYXRhTGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAga2V5Q291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICAgIGtleXM6IFVpbnQ4QXJyYXlbXTtcbiAgICAgICAgcmVjZW50QmxvY2toYXNoOiBVaW50OEFycmF5O1xuICAgICAgfT5cbiAgICA+KFtcbiAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGtleUNvdW50Lmxlbmd0aCwgJ2tleUNvdW50JyksXG4gICAgICBCdWZmZXJMYXlvdXQuc2VxKHB1YmxpY0tleSgna2V5JyksIGFjY291bnRLZXlzLmxlbmd0aCwgJ2tleXMnKSxcbiAgICAgIHB1YmxpY0tleSgncmVjZW50QmxvY2toYXNoJyksXG4gICAgXSk7XG4gICAgY29uc3QgdHJhbnNhY3Rpb24gPSB7XG4gICAgICBrZXlDb3VudDogQnVmZmVyLmZyb20oa2V5Q291bnQpLFxuICAgICAga2V5czogYWNjb3VudEtleXMubWFwKChrZXkpID0+IEJ1ZmZlci5mcm9tKGtleSwgJ2hleCcpKSxcbiAgICAgIHJlY2VudEJsb2NraGFzaDogQnVmZmVyLmZyb20odGhpcy5yZWNlbnRCbG9ja2hhc2gsICdoZXgnKSxcbiAgICB9O1xuICAgIGNvbnN0IHNpZ25EYXRhID0gQnVmZmVyLmFsbG9jKDIwNDgpOyAvLyBzaWduIGRhdGEgbWF4IGxlbmd0aFxuICAgIGNvbnN0IGxlbmd0aCA9IHNpZ25EYXRhTGF5b3V0LmVuY29kZSh0cmFuc2FjdGlvbiwgc2lnbkRhdGEpO1xuICAgIGluc3RydWN0aW9uQnVmZmVyLmNvcHkoc2lnbkRhdGEsIGxlbmd0aCk7XG5cbiAgICByZXR1cm4gc2lnbkRhdGEuc2xpY2UoMCwgbGVuZ3RoICsgaW5zdHJ1Y3Rpb25CdWZmZXIubGVuZ3RoKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICBzZXJpYWxpemVDcmVhdGVBbmRUcmFuc2ZlclNQTFRva2VuKCk6IHN0cmluZyB7XG4gICAgY29uc3QgeyBrZXlDb3VudCwgaW5zdHJ1Y3Rpb25zIH0gPSB0aGlzLmVuY29kZWRMZW5ndGgoKTtcbiAgICBsZXQgaW5zdHJ1Y3Rpb25CdWZmZXIgPSBCdWZmZXIuYWxsb2MoUEFDS0VUX0RBVEFfU0laRSk7XG4gICAgbGV0IGFzc29jaWF0ZUFjY291bnQ7XG4gICAgbGV0IGdhc1ByaWNlO1xuICAgIGxldCBnYXNMaW1pdDtcbiAgICBsZXQgdG9rZW5UcmFuc2ZlcjtcbiAgICBsZXQgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggPSAwO1xuICAgIGlmIChpbnN0cnVjdGlvbnMubGVuZ3RoID09PSA0KSB7XG4gICAgICBbYXNzb2NpYXRlQWNjb3VudCwgZ2FzUHJpY2UsIGdhc0xpbWl0LCB0b2tlblRyYW5zZmVyXSA9IGluc3RydWN0aW9ucztcblxuICAgICAgY29uc3QgYXNzb2NpYXRlQWNjb3VudExheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgICBkYXRhOiBudW1iZXJbXTtcbiAgICAgICAgICBkYXRhTGVuZ3RoOiBVaW50OEFycmF5O1xuICAgICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgICAga2V5SW5kaWNlc0NvdW50OiBVaW50OEFycmF5O1xuICAgICAgICB9PlxuICAgICAgPihbXG4gICAgICAgIEJ1ZmZlckxheW91dC51OCgncHJvZ3JhbUlkSW5kZXgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoYXNzb2NpYXRlQWNjb3VudC5rZXlJbmRpY2VzQ291bnQubGVuZ3RoLCAna2V5SW5kaWNlc0NvdW50JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCdrZXlJbmRleCcpLCBhc3NvY2lhdGVBY2NvdW50LmtleUluZGljZXMubGVuZ3RoLCAna2V5SW5kaWNlcycpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihhc3NvY2lhdGVBY2NvdW50LmRhdGFMZW5ndGgubGVuZ3RoLCAnZGF0YUxlbmd0aCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIGFzc29jaWF0ZUFjY291bnQuZGF0YS5sZW5ndGgsICdkYXRhJyksXG4gICAgICBdKTtcbiAgICAgIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoID0gYXNzb2NpYXRlQWNjb3VudExheW91dC5lbmNvZGUoYXNzb2NpYXRlQWNjb3VudCwgaW5zdHJ1Y3Rpb25CdWZmZXIsIDApO1xuXG4gICAgICBjb25zdCBnYXNQcmljZUxheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgICBkYXRhOiBudW1iZXJbXTtcbiAgICAgICAgICBkYXRhTGVuZ3RoOiBVaW50OEFycmF5O1xuICAgICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgICAga2V5SW5kaWNlc0NvdW50OiBVaW50OEFycmF5O1xuICAgICAgICB9PlxuICAgICAgPihbXG4gICAgICAgIEJ1ZmZlckxheW91dC51OCgncHJvZ3JhbUlkSW5kZXgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoZ2FzUHJpY2Uua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgZ2FzUHJpY2Uua2V5SW5kaWNlcy5sZW5ndGgsICdrZXlJbmRpY2VzJyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGdhc1ByaWNlLmRhdGFMZW5ndGgubGVuZ3RoLCAnZGF0YUxlbmd0aCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIGdhc1ByaWNlLmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgICAgXSk7XG4gICAgICBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCArPSBnYXNQcmljZUxheW91dC5lbmNvZGUoZ2FzUHJpY2UsIGluc3RydWN0aW9uQnVmZmVyLCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCk7XG5cbiAgICAgIGNvbnN0IGdhc0xpbWl0TGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgICAgUmVhZG9ubHk8e1xuICAgICAgICAgIGRhdGE6IG51bWJlcltdO1xuICAgICAgICAgIGRhdGFMZW5ndGg6IFVpbnQ4QXJyYXk7XG4gICAgICAgICAgcHJvZ3JhbUlkSW5kZXg6IG51bWJlcjtcbiAgICAgICAgICBrZXlJbmRpY2VzOiBudW1iZXJbXTtcbiAgICAgICAgICBrZXlJbmRpY2VzQ291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICAgIH0+XG4gICAgICA+KFtcbiAgICAgICAgQnVmZmVyTGF5b3V0LnU4KCdwcm9ncmFtSWRJbmRleCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihnYXNMaW1pdC5rZXlJbmRpY2VzQ291bnQubGVuZ3RoLCAna2V5SW5kaWNlc0NvdW50JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCdrZXlJbmRleCcpLCBnYXNMaW1pdC5rZXlJbmRpY2VzLmxlbmd0aCwgJ2tleUluZGljZXMnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoZ2FzTGltaXQuZGF0YUxlbmd0aC5sZW5ndGgsICdkYXRhTGVuZ3RoJyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCd1c2VyZGF0dW0nKSwgZ2FzTGltaXQuZGF0YS5sZW5ndGgsICdkYXRhJyksXG4gICAgICBdKTtcbiAgICAgIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoICs9IGdhc0xpbWl0TGF5b3V0LmVuY29kZShnYXNMaW1pdCwgaW5zdHJ1Y3Rpb25CdWZmZXIsIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgW2Fzc29jaWF0ZUFjY291bnQsIHRva2VuVHJhbnNmZXJdID0gaW5zdHJ1Y3Rpb25zO1xuICAgICAgY29uc3QgYXNzb2NpYXRlQWNjb3VudExheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgICBkYXRhOiBudW1iZXJbXTtcbiAgICAgICAgICBkYXRhTGVuZ3RoOiBVaW50OEFycmF5O1xuICAgICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgICAga2V5SW5kaWNlc0NvdW50OiBVaW50OEFycmF5O1xuICAgICAgICB9PlxuICAgICAgPihbXG4gICAgICAgIEJ1ZmZlckxheW91dC51OCgncHJvZ3JhbUlkSW5kZXgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoYXNzb2NpYXRlQWNjb3VudC5rZXlJbmRpY2VzQ291bnQubGVuZ3RoLCAna2V5SW5kaWNlc0NvdW50JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCdrZXlJbmRleCcpLCBhc3NvY2lhdGVBY2NvdW50LmtleUluZGljZXMubGVuZ3RoLCAna2V5SW5kaWNlcycpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihhc3NvY2lhdGVBY2NvdW50LmRhdGFMZW5ndGgubGVuZ3RoLCAnZGF0YUxlbmd0aCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIGFzc29jaWF0ZUFjY291bnQuZGF0YS5sZW5ndGgsICdkYXRhJyksXG4gICAgICBdKTtcbiAgICAgIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoID0gYXNzb2NpYXRlQWNjb3VudExheW91dC5lbmNvZGUoYXNzb2NpYXRlQWNjb3VudCwgaW5zdHJ1Y3Rpb25CdWZmZXIsIDApO1xuICAgIH1cbiAgICBjb25zdCB0b2tlblRyYW5zZmVyTGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgcHJvZ3JhbUlkSW5kZXg6IG51bWJlcjtcbiAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgIGtleUluZGljZXNDb3VudDogVWludDhBcnJheTtcbiAgICAgICAgZGF0YTogbnVtYmVyW107XG4gICAgICAgIGRhdGFMZW5ndGg6IFVpbnQ4QXJyYXk7XG4gICAgICB9PlxuICAgID4oW1xuICAgICAgQnVmZmVyTGF5b3V0LnU4KCdwcm9ncmFtSWRJbmRleCcpLFxuICAgICAgQnVmZmVyTGF5b3V0LmJsb2IodG9rZW5UcmFuc2Zlci5rZXlJbmRpY2VzQ291bnQubGVuZ3RoLCAna2V5SW5kaWNlc0NvdW50JyksXG4gICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgdG9rZW5UcmFuc2Zlci5rZXlJbmRpY2VzLmxlbmd0aCwgJ2tleUluZGljZXMnKSxcbiAgICAgIEJ1ZmZlckxheW91dC5ibG9iKHRva2VuVHJhbnNmZXIuZGF0YUxlbmd0aC5sZW5ndGgsICdkYXRhTGVuZ3RoJyksXG4gICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIHRva2VuVHJhbnNmZXIuZGF0YS5sZW5ndGgsICdkYXRhJyksXG4gICAgXSk7XG4gICAgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggKz0gdG9rZW5UcmFuc2ZlckxheW91dC5lbmNvZGUodG9rZW5UcmFuc2ZlciwgaW5zdHJ1Y3Rpb25CdWZmZXIsIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoKTtcbiAgICBpbnN0cnVjdGlvbkJ1ZmZlciA9IGluc3RydWN0aW9uQnVmZmVyLnNsaWNlKDAsIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoKTtcbiAgICBsZXQgYWNjb3VudEtleXMgPSBbLi4udGhpcy5hY2NvdW50S2V5c107XG4gICAgZm9yIChsZXQgaSA9IHRoaXMuYWNjb3VudEtleXMubGVuZ3RoOyBpIDwgOTsgaSsrKSB7XG4gICAgICBhY2NvdW50S2V5cyA9IGFjY291bnRLZXlzLmNvbmNhdChCdWZmZXIuYWxsb2MoMzIpLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2lnbkRhdGFMYXlvdXQgPSBCdWZmZXJMYXlvdXQuc3RydWN0PFxuICAgICAgUmVhZG9ubHk8e1xuICAgICAgICBrZXlDb3VudDogVWludDhBcnJheTtcbiAgICAgICAga2V5czogVWludDhBcnJheVtdO1xuICAgICAgICByZWNlbnRCbG9ja2hhc2g6IFVpbnQ4QXJyYXk7XG4gICAgICB9PlxuICAgID4oW1xuICAgICAgQnVmZmVyTGF5b3V0LmJsb2Ioa2V5Q291bnQubGVuZ3RoLCAna2V5Q291bnQnKSxcbiAgICAgIEJ1ZmZlckxheW91dC5zZXEocHVibGljS2V5KCdrZXknKSwgYWNjb3VudEtleXMubGVuZ3RoLCAna2V5cycpLFxuICAgICAgcHVibGljS2V5KCdyZWNlbnRCbG9ja2hhc2gnKSxcbiAgICBdKTtcbiAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHtcbiAgICAgIGtleUNvdW50OiBCdWZmZXIuZnJvbShrZXlDb3VudCksXG4gICAgICBrZXlzOiBhY2NvdW50S2V5cy5tYXAoKGtleSkgPT4gQnVmZmVyLmZyb20oa2V5LCAnaGV4JykpLFxuICAgICAgcmVjZW50QmxvY2toYXNoOiBCdWZmZXIuZnJvbSh0aGlzLnJlY2VudEJsb2NraGFzaCwgJ2hleCcpLFxuICAgIH07XG4gICAgY29uc3Qgc2lnbkRhdGEgPSBCdWZmZXIuYWxsb2MoMjA0OCk7IC8vIHNpZ24gZGF0YSBtYXggbGVuZ3RoXG4gICAgY29uc3QgbGVuZ3RoID0gc2lnbkRhdGFMYXlvdXQuZW5jb2RlKHRyYW5zYWN0aW9uLCBzaWduRGF0YSk7XG4gICAgaW5zdHJ1Y3Rpb25CdWZmZXIuY29weShzaWduRGF0YSwgbGVuZ3RoKTtcblxuICAgIHJldHVybiBzaWduRGF0YS5zbGljZSgwLCBsZW5ndGggKyBpbnN0cnVjdGlvbkJ1ZmZlci5sZW5ndGgpLnRvU3RyaW5nKCdoZXgnKTtcbiAgfVxuXG4gIHJlc2VydmVQYWRkaW5nQWNjb3VudEtleXMobWF4QWNjb3VudEtleUxlbmd0aDogbnVtYmVyKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGFjY291bnRLZXlzID0gdGhpcy5hY2NvdW50S2V5cztcbiAgICBjb25zdCBuZWVkUGFkZGluZ0tleUxlbmd0aCA9IG1heEFjY291bnRLZXlMZW5ndGggLSB0aGlzLmFjY291bnRLZXlzLmxlbmd0aDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5lZWRQYWRkaW5nS2V5TGVuZ3RoOyBpKyspIHtcbiAgICAgIGFjY291bnRLZXlzLnB1c2goUEFERElOR19QVUJMSUNLRVkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjb3VudEtleXM7XG4gIH1cblxuICBzZXJpYWxpemVEZWxlZ2F0ZUFuZENyZWF0ZUFjY291bnRXaXRoU2VlZCgpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsga2V5Q291bnQsIGluc3RydWN0aW9uQ291bnQsIGluc3RydWN0aW9ucyB9ID0gdGhpcy5lbmNvZGVkTGVuZ3RoKCk7XG4gICAgY29uc3QgaW5pdEFuZFBhZGRpbmdJbnN0cnVjdGlvbiA9IGluaXRBbmRQYWRkaW5nQ29tcHV0ZUJ1ZGdldEluc3RydWN0aW9uQnVmZmVyKFxuICAgICAgdGhpcy5hY2NvdW50S2V5cyxcbiAgICAgIGluc3RydWN0aW9ucyxcbiAgICAgIGluc3RydWN0aW9uQ291bnRcbiAgICApO1xuICAgIGNvbnN0IGluc3RydWN0aW9uQnVmZmVyID0gZW5jb2RlQW5kUGFkZGluZ1NlZWRJbnN0cnVjdGlvbkJ1ZmZlcihcbiAgICAgIHRoaXMuYWNjb3VudEtleXMsXG4gICAgICBpbnN0cnVjdGlvbnMsXG4gICAgICBpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uLmluc3RydWN0aW9uQnVmZmVyLFxuICAgICAgaW5pdEFuZFBhZGRpbmdJbnN0cnVjdGlvbi5pbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aFxuICAgICk7XG4gICAgLyoqXG4gICAgICogc2lnbmVyUHVia2V5XG4gICAgICogc3Rha2VBY2NvdW50UHVia2V5XG4gICAgICogMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTFcbiAgICAgKiB2YWxpZGF0b3JQdWJrZXlcbiAgICAgKiBTdGFrZTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExXG4gICAgICogU3Rha2VDb25maWcxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIFN5c3ZhckMxb2NrMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTFcbiAgICAgKiBTeXN2YXJSZW50MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExXG4gICAgICogU3lzdmFyU3Rha2VIaXN0b3J5MTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIENvbXB1dGVCdWRnZXQxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEgIChvcHRpb25hbClcbiAgICAgKi9cbiAgICBjb25zdCBuZXdBY2NvdW50S2V5cyA9IHRoaXMucmVzZXJ2ZVBhZGRpbmdBY2NvdW50S2V5cygxMCk7XG4gICAgcmV0dXJuIGVuY29kZVNpZ25EYXRhKGtleUNvdW50LCBuZXdBY2NvdW50S2V5cywgdGhpcy5yZWNlbnRCbG9ja2hhc2gsIGluc3RydWN0aW9uQnVmZmVyKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICBzZXJpYWxpemVVbmRlbGVnYXRlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgeyBrZXlDb3VudCwgaW5zdHJ1Y3Rpb25Db3VudCwgaW5zdHJ1Y3Rpb25zIH0gPSB0aGlzLmVuY29kZWRMZW5ndGgoKTtcbiAgICBjb25zdCBpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uID0gaW5pdEFuZFBhZGRpbmdDb21wdXRlQnVkZ2V0SW5zdHJ1Y3Rpb25CdWZmZXIoXG4gICAgICB0aGlzLmFjY291bnRLZXlzLFxuICAgICAgaW5zdHJ1Y3Rpb25zLFxuICAgICAgaW5zdHJ1Y3Rpb25Db3VudFxuICAgICk7XG4gICAgY29uc3QgaW5zdHJ1Y3Rpb25CdWZmZXIgPSBlbmNvZGVJbnN0cnVjdGlvbkJ1ZmZlcihcbiAgICAgIGluc3RydWN0aW9ucyxcbiAgICAgIGluaXRBbmRQYWRkaW5nSW5zdHJ1Y3Rpb24uaW5zdHJ1Y3Rpb25CdWZmZXIsXG4gICAgICBpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uLmluc3RydWN0aW9uQnVmZmVyTGVuZ3RoXG4gICAgKTtcbiAgICAvKipcbiAgICAgKiBzaWduZXJQdWJrZXlcbiAgICAgKiBzdGFrZUFjY291bnRQdWJrZXlcbiAgICAgKiBTdGFrZTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExXG4gICAgICogU3lzdmFyQzFvY2sxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIENvbXB1dGVCdWRnZXQxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTEgIChvcHRpb25hbClcbiAgICAgKi9cbiAgICBjb25zdCBuZXdBY2NvdW50S2V5cyA9IHRoaXMucmVzZXJ2ZVBhZGRpbmdBY2NvdW50S2V5cyg1KTtcbiAgICByZXR1cm4gZW5jb2RlU2lnbkRhdGEoa2V5Q291bnQsIG5ld0FjY291bnRLZXlzLCB0aGlzLnJlY2VudEJsb2NraGFzaCwgaW5zdHJ1Y3Rpb25CdWZmZXIpLnRvU3RyaW5nKCdoZXgnKTtcbiAgfVxuXG4gIHNlcmlhbGl6ZVdpdGhkcmF3KCk6IHN0cmluZyB7XG4gICAgY29uc3QgeyBrZXlDb3VudCwgaW5zdHJ1Y3Rpb25Db3VudCwgaW5zdHJ1Y3Rpb25zIH0gPSB0aGlzLmVuY29kZWRMZW5ndGgoKTtcbiAgICBjb25zdCBpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uID0gaW5pdEFuZFBhZGRpbmdDb21wdXRlQnVkZ2V0SW5zdHJ1Y3Rpb25CdWZmZXIoXG4gICAgICB0aGlzLmFjY291bnRLZXlzLFxuICAgICAgaW5zdHJ1Y3Rpb25zLFxuICAgICAgaW5zdHJ1Y3Rpb25Db3VudFxuICAgICk7XG4gICAgY29uc3QgaW5zdHJ1Y3Rpb25CdWZmZXIgPSBlbmNvZGVJbnN0cnVjdGlvbkJ1ZmZlcihcbiAgICAgIGluc3RydWN0aW9ucyxcbiAgICAgIGluaXRBbmRQYWRkaW5nSW5zdHJ1Y3Rpb24uaW5zdHJ1Y3Rpb25CdWZmZXIsXG4gICAgICBpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uLmluc3RydWN0aW9uQnVmZmVyTGVuZ3RoXG4gICAgKTtcbiAgICAvKipcbiAgICAgKiBzaWduZXJQdWJrZXlcbiAgICAgKiBzdGFrZUFjY291bnRQdWJrZXlcbiAgICAgKiB3aXRoZHJhd1RvUHVia2V5ICAgICAgICAgICAgICAgICAgICAgICAgICAgIChvcHRpb25hbClcbiAgICAgKiBTdGFrZTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExXG4gICAgICogU3lzdmFyQzFvY2sxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIFN5c3ZhclN0YWtlSGlzdG9yeTExMTExMTExMTExMTExMTExMTExMTExMTFcbiAgICAgKiBDb21wdXRlQnVkZ2V0MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExIChvcHRpb25hbClcbiAgICAgKi9cbiAgICBjb25zdCBuZXdBY2NvdW50S2V5cyA9IHRoaXMucmVzZXJ2ZVBhZGRpbmdBY2NvdW50S2V5cyg3KTtcbiAgICByZXR1cm4gZW5jb2RlU2lnbkRhdGEoa2V5Q291bnQsIG5ld0FjY291bnRLZXlzLCB0aGlzLnJlY2VudEJsb2NraGFzaCwgaW5zdHJ1Y3Rpb25CdWZmZXIpLnRvU3RyaW5nKCdoZXgnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNvZGUgYSBjb21waWxlZCBtZXNzYWdlIGludG8gYSBNZXNzYWdlIG9iamVjdC5cbiAgICovXG4gIHN0YXRpYyBmcm9tKGJ1ZmZlcjogQnVmZmVyIHwgVWludDhBcnJheSB8IEFycmF5PG51bWJlcj4pOiBNZXNzYWdlIHtcbiAgICAvLyBTbGljZSB1cCB3aXJlIGRhdGFcbiAgICBsZXQgYnl0ZUFycmF5ID0gWy4uLmJ1ZmZlcl07XG5cbiAgICBjb25zdCBudW1SZXF1aXJlZFNpZ25hdHVyZXMgPSBieXRlQXJyYXkuc2hpZnQoKSE7XG4gICAgaWYgKG51bVJlcXVpcmVkU2lnbmF0dXJlcyAhPT0gKG51bVJlcXVpcmVkU2lnbmF0dXJlcyAmIFZFUlNJT05fUFJFRklYX01BU0spKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ZlcnNpb25lZCBtZXNzYWdlcyBtdXN0IGJlIGRlc2VyaWFsaXplZCB3aXRoIFZlcnNpb25lZE1lc3NhZ2UuZGVzZXJpYWxpemUoKScpO1xuICAgIH1cblxuICAgIGNvbnN0IG51bVJlYWRvbmx5U2lnbmVkQWNjb3VudHMgPSBieXRlQXJyYXkuc2hpZnQoKSE7XG4gICAgY29uc3QgbnVtUmVhZG9ubHlVbnNpZ25lZEFjY291bnRzID0gYnl0ZUFycmF5LnNoaWZ0KCkhO1xuXG4gICAgY29uc3QgYWNjb3VudENvdW50ID0gc2hvcnR2ZWMuZGVjb2RlTGVuZ3RoKGJ5dGVBcnJheSk7XG4gICAgY29uc3QgYWNjb3VudEtleXMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFjY291bnRDb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBhY2NvdW50ID0gYnl0ZUFycmF5LnNsaWNlKDAsIFBVQkxJQ19LRVlfTEVOR1RIKTtcbiAgICAgIGJ5dGVBcnJheSA9IGJ5dGVBcnJheS5zbGljZShQVUJMSUNfS0VZX0xFTkdUSCk7XG4gICAgICBhY2NvdW50S2V5cy5wdXNoKEJ1ZmZlci5mcm9tKGFjY291bnQpLnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVjZW50QmxvY2toYXNoID0gYnl0ZUFycmF5LnNsaWNlKDAsIFBVQkxJQ19LRVlfTEVOR1RIKTtcbiAgICBieXRlQXJyYXkgPSBieXRlQXJyYXkuc2xpY2UoUFVCTElDX0tFWV9MRU5HVEgpO1xuXG4gICAgY29uc3QgaW5zdHJ1Y3Rpb25Db3VudCA9IHNob3J0dmVjLmRlY29kZUxlbmd0aChieXRlQXJyYXkpO1xuICAgIGNvbnN0IGluc3RydWN0aW9uczogQ29tcGlsZWRJbnN0cnVjdGlvbltdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnN0cnVjdGlvbkNvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IHByb2dyYW1JZEluZGV4ID0gYnl0ZUFycmF5LnNoaWZ0KCkhO1xuICAgICAgY29uc3QgaW5zdHJ1Y3Rpb25BY2NvdW50Q291bnQgPSBzaG9ydHZlYy5kZWNvZGVMZW5ndGgoYnl0ZUFycmF5KTtcbiAgICAgIGNvbnN0IGFjY291bnRzID0gYnl0ZUFycmF5LnNsaWNlKDAsIGluc3RydWN0aW9uQWNjb3VudENvdW50KTtcbiAgICAgIGJ5dGVBcnJheSA9IGJ5dGVBcnJheS5zbGljZShpbnN0cnVjdGlvbkFjY291bnRDb3VudCk7XG4gICAgICBjb25zdCBkYXRhTGVuZ3RoID0gc2hvcnR2ZWMuZGVjb2RlTGVuZ3RoKGJ5dGVBcnJheSk7XG4gICAgICBjb25zdCBkYXRhU2xpY2UgPSBieXRlQXJyYXkuc2xpY2UoMCwgZGF0YUxlbmd0aCk7XG4gICAgICBjb25zdCBkYXRhID0gQnVmZmVyLmZyb20oZGF0YVNsaWNlKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICBieXRlQXJyYXkgPSBieXRlQXJyYXkuc2xpY2UoZGF0YUxlbmd0aCk7XG4gICAgIC