@coolwallet/sol
Version:
Coolwallet Solana sdk
329 lines (323 loc) • 73 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(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
var Message = exports.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;
}
return (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);
}
}]);
}();
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJCdWZmZXJMYXlvdXQiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfc3RyaW5nVXRpbCIsIl9jb21tb25MYXlvdXQiLCJfcGFyYW1zIiwic2hvcnR2ZWMiLCJfYnVmZmVyVXRpbHMiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX19lc01vZHVsZSIsIl90eXBlb2YiLCJoYXMiLCJnZXQiLCJuIiwiX19wcm90b19fIiwiYSIsIk9iamVjdCIsImRlZmluZVByb3BlcnR5IiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidSIsImhhc093blByb3BlcnR5IiwiY2FsbCIsImkiLCJzZXQiLCJNZXNzYWdlIiwiZXhwb3J0cyIsIm1lc3NhZ2UiLCJfY2xhc3NDYWxsQ2hlY2syIiwiaGVhZGVyIiwiYWNjb3VudEtleXMiLCJyZWNlbnRCbG9ja2hhc2giLCJpbnN0cnVjdGlvbnMiLCJfY3JlYXRlQ2xhc3MyIiwia2V5IiwidmFsdWUiLCJzZXJpYWxpemVIZWFkZXIiLCJudW1iZXJUb1N0cmluZ0hleCIsIm51bVJlcXVpcmVkU2lnbmF0dXJlcyIsIm51bVJlYWRvbmx5U2lnbmVkQWNjb3VudHMiLCJudW1SZWFkb25seVVuc2lnbmVkQWNjb3VudHMiLCJlbmNvZGVkTGVuZ3RoIiwibnVtS2V5cyIsImxlbmd0aCIsImtleUNvdW50IiwiZW5jb2RlTGVuZ3RoIiwibWFwIiwiaW5zdHJ1Y3Rpb24iLCJhY2NvdW50cyIsInByb2dyYW1JZEluZGV4IiwiZGF0YSIsIkFycmF5IiwiZnJvbSIsIkJ1ZmZlciIsImtleUluZGljZXNDb3VudCIsImRhdGFDb3VudCIsImtleUluZGljZXMiLCJkYXRhTGVuZ3RoIiwiaW5zdHJ1Y3Rpb25Db3VudCIsInNlcmlhbGl6ZSIsIl90aGlzJGVuY29kZWRMZW5ndGgiLCJpbnN0cnVjdGlvbkJ1ZmZlciIsImFsbG9jIiwiUEFDS0VUX0RBVEFfU0laRSIsImNvcHkiLCJpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCIsImZvckVhY2giLCJpbnN0cnVjdGlvbkxheW91dCIsInN0cnVjdCIsInU4IiwiYmxvYiIsInNlcSIsImVuY29kZSIsInNsaWNlIiwic2lnbkRhdGFMYXlvdXQiLCJwdWJsaWNLZXkiLCJ0cmFuc2FjdGlvbiIsImtleXMiLCJzaWduRGF0YSIsInNlcmlhbGl6ZVRyYW5zZmVyTWVzc2FnZSIsIl90aGlzJGVuY29kZWRMZW5ndGgyIiwiZ2FzUHJpY2UiLCJnYXNMaW1pdCIsInRyYW5zZmVyIiwiX2luc3RydWN0aW9ucyIsIl9zbGljZWRUb0FycmF5MiIsImdhc1ByaWNlTGF5b3V0IiwiZ2FzTGltaXRMYXlvdXQiLCJfaW5zdHJ1Y3Rpb25zMiIsInRyYW5zZmVyTGF5b3V0IiwiX3RvQ29uc3VtYWJsZUFycmF5MiIsImNvbmNhdCIsIlBBRERJTkdfUFVCTElDS0VZIiwidG9TdHJpbmciLCJzZXJpYWxpemVDcmVhdGVBbmRUcmFuc2ZlclNQTFRva2VuIiwiX3RoaXMkZW5jb2RlZExlbmd0aDMiLCJhc3NvY2lhdGVBY2NvdW50IiwidG9rZW5UcmFuc2ZlciIsIl9pbnN0cnVjdGlvbnMzIiwiYXNzb2NpYXRlQWNjb3VudExheW91dCIsIl9pbnN0cnVjdGlvbnM0IiwidG9rZW5UcmFuc2ZlckxheW91dCIsInJlc2VydmVQYWRkaW5nQWNjb3VudEtleXMiLCJtYXhBY2NvdW50S2V5TGVuZ3RoIiwibmVlZFBhZGRpbmdLZXlMZW5ndGgiLCJwdXNoIiwic2VyaWFsaXplRGVsZWdhdGVBbmRDcmVhdGVBY2NvdW50V2l0aFNlZWQiLCJfdGhpcyRlbmNvZGVkTGVuZ3RoNCIsImluaXRBbmRQYWRkaW5nSW5zdHJ1Y3Rpb24iLCJpbml0QW5kUGFkZGluZ0NvbXB1dGVCdWRnZXRJbnN0cnVjdGlvbkJ1ZmZlciIsImVuY29kZUFuZFBhZGRpbmdTZWVkSW5zdHJ1Y3Rpb25CdWZmZXIiLCJuZXdBY2NvdW50S2V5cyIsImVuY29kZVNpZ25EYXRhIiwic2VyaWFsaXplVW5kZWxlZ2F0ZSIsIl90aGlzJGVuY29kZWRMZW5ndGg1IiwiZW5jb2RlSW5zdHJ1Y3Rpb25CdWZmZXIiLCJzZXJpYWxpemVXaXRoZHJhdyIsIl90aGlzJGVuY29kZWRMZW5ndGg2IiwiYnVmZmVyIiwiYnl0ZUFycmF5Iiwic2hpZnQiLCJWRVJTSU9OX1BSRUZJWF9NQVNLIiwiRXJyb3IiLCJhY2NvdW50Q291bnQiLCJkZWNvZGVMZW5ndGgiLCJhY2NvdW50IiwiUFVCTElDX0tFWV9MRU5HVEgiLCJpbnN0cnVjdGlvbkFjY291bnRDb3VudCIsImRhdGFTbGljZSIsIm1lc3NhZ2VBcmdzIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lc3NhZ2UvbGVnYWN5LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIEJ1ZmZlckxheW91dCBmcm9tICdAc29sYW5hL2J1ZmZlci1sYXlvdXQnO1xuaW1wb3J0IHsgZW5jb2RlTGVuZ3RoLCBudW1iZXJUb1N0cmluZ0hleCB9IGZyb20gJy4uL3V0aWxzL3N0cmluZ1V0aWwnO1xuaW1wb3J0IHsgcHVibGljS2V5IH0gZnJvbSAnLi4vdXRpbHMvY29tbW9uTGF5b3V0JztcbmltcG9ydCB7IFBBQ0tFVF9EQVRBX1NJWkUsIFBBRERJTkdfUFVCTElDS0VZLCBQVUJMSUNfS0VZX0xFTkdUSCwgVkVSU0lPTl9QUkVGSVhfTUFTSyB9IGZyb20gJy4uL2NvbmZpZy9wYXJhbXMnO1xuaW1wb3J0IHsgQ29tcGlsZWRJbnN0cnVjdGlvbiwgQ29tcGxpZWRJbnN0cnVjdGlvbiwgU2VyaWFsaXplZEluc3RydWN0aW9uIH0gZnJvbSAnLi4vY29uZmlnL3R5cGVzJztcbmltcG9ydCAqIGFzIHNob3J0dmVjIGZyb20gJy4uL3V0aWxzL3Nob3J0dmVjLWVuY29kaW5nJztcbmltcG9ydCB7XG4gIGVuY29kZUFuZFBhZGRpbmdTZWVkSW5zdHJ1Y3Rpb25CdWZmZXIsXG4gIGVuY29kZUluc3RydWN0aW9uQnVmZmVyLFxuICBlbmNvZGVTaWduRGF0YSxcbiAgaW5pdEFuZFBhZGRpbmdDb21wdXRlQnVkZ2V0SW5zdHJ1Y3Rpb25CdWZmZXIsXG59IGZyb20gJy4uL3V0aWxzL2J1ZmZlclV0aWxzJztcblxudHlwZSBNZXNzYWdlSGVhZGVyID0ge1xuICBudW1SZXF1aXJlZFNpZ25hdHVyZXM6IG51bWJlcjtcbiAgbnVtUmVhZG9ubHlTaWduZWRBY2NvdW50czogbnVtYmVyO1xuICBudW1SZWFkb25seVVuc2lnbmVkQWNjb3VudHM6IG51bWJlcjtcbn07XG5cbnR5cGUgTWVzc2FnZUFyZ3MgPSB7XG4gIGhlYWRlcjogTWVzc2FnZUhlYWRlcjtcbiAgYWNjb3VudEtleXM6IHN0cmluZ1tdO1xuICByZWNlbnRCbG9ja2hhc2g6IHN0cmluZztcbiAgaW5zdHJ1Y3Rpb25zOiBDb21wbGllZEluc3RydWN0aW9uW107XG59O1xuXG5leHBvcnQgY2xhc3MgTWVzc2FnZSB7XG4gIGhlYWRlcjogTWVzc2FnZUhlYWRlcjtcbiAgYWNjb3VudEtleXM6IHN0cmluZ1tdO1xuICByZWNlbnRCbG9ja2hhc2g6IHN0cmluZztcbiAgaW5zdHJ1Y3Rpb25zOiBDb21wbGllZEluc3RydWN0aW9uW107XG5cbiAgY29uc3RydWN0b3IobWVzc2FnZTogTWVzc2FnZUFyZ3MpIHtcbiAgICB0aGlzLmhlYWRlciA9IG1lc3NhZ2UuaGVhZGVyO1xuICAgIHRoaXMuYWNjb3VudEtleXMgPSBtZXNzYWdlLmFjY291bnRLZXlzO1xuICAgIHRoaXMucmVjZW50QmxvY2toYXNoID0gbWVzc2FnZS5yZWNlbnRCbG9ja2hhc2g7XG4gICAgdGhpcy5pbnN0cnVjdGlvbnMgPSBtZXNzYWdlLmluc3RydWN0aW9ucztcbiAgfVxuXG4gIHNlcmlhbGl6ZUhlYWRlcigpOiBzdHJpbmcge1xuICAgIHJldHVybiAoXG4gICAgICBudW1iZXJUb1N0cmluZ0hleCh0aGlzLmhlYWRlci5udW1SZXF1aXJlZFNpZ25hdHVyZXMsIDIpICtcbiAgICAgIG51bWJlclRvU3RyaW5nSGV4KHRoaXMuaGVhZGVyLm51bVJlYWRvbmx5U2lnbmVkQWNjb3VudHMsIDIpICtcbiAgICAgIG51bWJlclRvU3RyaW5nSGV4KHRoaXMuaGVhZGVyLm51bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50cywgMilcbiAgICApO1xuICB9XG5cbiAgZW5jb2RlZExlbmd0aCgpOiB7IGtleUNvdW50OiBudW1iZXJbXTsgaW5zdHJ1Y3Rpb25Db3VudDogbnVtYmVyW107IGluc3RydWN0aW9uczogU2VyaWFsaXplZEluc3RydWN0aW9uW10gfSB7XG4gICAgLy8gZW5jb2RlIGtleSBjb3VudFxuICAgIGNvbnN0IG51bUtleXMgPSB0aGlzLmFjY291bnRLZXlzLmxlbmd0aDtcbiAgICBjb25zdCBrZXlDb3VudDogbnVtYmVyW10gPSBbXTtcbiAgICBlbmNvZGVMZW5ndGgoa2V5Q291bnQsIG51bUtleXMpO1xuXG4gICAgLy8gZXh0cmFjdCBpbnB1dCBpbnN0cnVjdGlvbnMgdG8gc2VyaWFsaXplIGluc3RydWN0aW9uc1xuICAgIGNvbnN0IGluc3RydWN0aW9ucyA9IHRoaXMuaW5zdHJ1Y3Rpb25zLm1hcCgoaW5zdHJ1Y3Rpb24pID0+IHtcbiAgICAgIGNvbnN0IHsgYWNjb3VudHMsIHByb2dyYW1JZEluZGV4IH0gPSBpbnN0cnVjdGlvbjtcbiAgICAgIGNvbnN0IGRhdGEgPSBBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKGluc3RydWN0aW9uLmRhdGEsICdoZXgnKSk7XG5cbiAgICAgIGNvbnN0IGtleUluZGljZXNDb3VudDogbnVtYmVyW10gPSBbXTtcbiAgICAgIGVuY29kZUxlbmd0aChrZXlJbmRpY2VzQ291bnQsIGFjY291bnRzLmxlbmd0aCk7XG5cbiAgICAgIGNvbnN0IGRhdGFDb3VudDogbnVtYmVyW10gPSBbXTtcbiAgICAgIGVuY29kZUxlbmd0aChkYXRhQ291bnQsIGRhdGEubGVuZ3RoKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcHJvZ3JhbUlkSW5kZXgsXG4gICAgICAgIGtleUluZGljZXNDb3VudDogQnVmZmVyLmZyb20oa2V5SW5kaWNlc0NvdW50KSxcbiAgICAgICAga2V5SW5kaWNlczogYWNjb3VudHMsXG4gICAgICAgIGRhdGFMZW5ndGg6IEJ1ZmZlci5mcm9tKGRhdGFDb3VudCksXG4gICAgICAgIGRhdGEsXG4gICAgICB9O1xuICAgIH0pO1xuXG4gICAgLy8gZW5jb2RlIGluc3RydWN0aW9uIGNvdW50XG4gICAgY29uc3QgaW5zdHJ1Y3Rpb25Db3VudDogbnVtYmVyW10gPSBbXTtcbiAgICBlbmNvZGVMZW5ndGgoaW5zdHJ1Y3Rpb25Db3VudCwgaW5zdHJ1Y3Rpb25zLmxlbmd0aCk7XG4gICAgcmV0dXJuIHsga2V5Q291bnQsIGluc3RydWN0aW9uQ291bnQsIGluc3RydWN0aW9ucyB9O1xuICB9XG5cbiAgc2VyaWFsaXplKCk6IEJ1ZmZlciB7XG4gICAgY29uc3QgeyBrZXlDb3VudCwgaW5zdHJ1Y3Rpb25Db3VudCwgaW5zdHJ1Y3Rpb25zIH0gPSB0aGlzLmVuY29kZWRMZW5ndGgoKTtcbiAgICAvLyBlbmNvZGUgaW5zdHJ1Y3Rpb25cbiAgICBsZXQgaW5zdHJ1Y3Rpb25CdWZmZXIgPSBCdWZmZXIuYWxsb2MoUEFDS0VUX0RBVEFfU0laRSk7XG4gICAgQnVmZmVyLmZyb20oaW5zdHJ1Y3Rpb25Db3VudCkuY29weShpbnN0cnVjdGlvbkJ1ZmZlcik7XG4gICAgbGV0IGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoID0gaW5zdHJ1Y3Rpb25Db3VudC5sZW5ndGg7XG5cbiAgICBpbnN0cnVjdGlvbnMuZm9yRWFjaCgoaW5zdHJ1Y3Rpb24pID0+IHtcbiAgICAgIGNvbnN0IGluc3RydWN0aW9uTGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgICAgUmVhZG9ubHk8e1xuICAgICAgICAgIGRhdGE6IG51bWJlcltdO1xuICAgICAgICAgIGRhdGFMZW5ndGg6IFVpbnQ4QXJyYXk7XG4gICAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgICAga2V5SW5kaWNlc0NvdW50OiBVaW50OEFycmF5O1xuICAgICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgIH0+XG4gICAgICA+KFtcbiAgICAgICAgQnVmZmVyTGF5b3V0LnU4KCdwcm9ncmFtSWRJbmRleCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihpbnN0cnVjdGlvbi5rZXlJbmRpY2VzQ291bnQubGVuZ3RoLCAna2V5SW5kaWNlc0NvdW50JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCdrZXlJbmRleCcpLCBpbnN0cnVjdGlvbi5rZXlJbmRpY2VzLmxlbmd0aCwgJ2tleUluZGljZXMnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoaW5zdHJ1Y3Rpb24uZGF0YUxlbmd0aC5sZW5ndGgsICdkYXRhTGVuZ3RoJyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5zZXEoQnVmZmVyTGF5b3V0LnU4KCd1c2VyZGF0dW0nKSwgaW5zdHJ1Y3Rpb24uZGF0YS5sZW5ndGgsICdkYXRhJyksXG4gICAgICBdKTtcbiAgICAgIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoICs9IGluc3RydWN0aW9uTGF5b3V0LmVuY29kZShpbnN0cnVjdGlvbiwgaW5zdHJ1Y3Rpb25CdWZmZXIsIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoKTtcbiAgICB9KTtcbiAgICBpbnN0cnVjdGlvbkJ1ZmZlciA9IGluc3RydWN0aW9uQnVmZmVyLnNsaWNlKDAsIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoKTtcblxuICAgIC8vIGVuY29kZSBzaWduIGRhdGFcbiAgICBjb25zdCBzaWduRGF0YUxheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICBSZWFkb25seTx7XG4gICAgICAgIGtleUNvdW50OiBVaW50OEFycmF5O1xuICAgICAgICBrZXlzOiBVaW50OEFycmF5W107XG4gICAgICAgIG51bVJlYWRvbmx5U2lnbmVkQWNjb3VudHM6IFVpbnQ4QXJyYXk7XG4gICAgICAgIG51bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50czogVWludDhBcnJheTtcbiAgICAgICAgbnVtUmVxdWlyZWRTaWduYXR1cmVzOiBVaW50OEFycmF5O1xuICAgICAgICByZWNlbnRCbG9ja2hhc2g6IFVpbnQ4QXJyYXk7XG4gICAgICB9PlxuICAgID4oW1xuICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoMSwgJ251bVJlcXVpcmVkU2lnbmF0dXJlcycpLFxuICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoMSwgJ251bVJlYWRvbmx5U2lnbmVkQWNjb3VudHMnKSxcbiAgICAgIEJ1ZmZlckxheW91dC5ibG9iKDEsICdudW1SZWFkb25seVVuc2lnbmVkQWNjb3VudHMnKSxcbiAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGtleUNvdW50Lmxlbmd0aCwgJ2tleUNvdW50JyksXG4gICAgICBCdWZmZXJMYXlvdXQuc2VxKHB1YmxpY0tleSgna2V5JyksIHRoaXMuYWNjb3VudEtleXMubGVuZ3RoLCAna2V5cycpLFxuICAgICAgcHVibGljS2V5KCdyZWNlbnRCbG9ja2hhc2gnKSxcbiAgICBdKTtcbiAgICBjb25zdCB0cmFuc2FjdGlvbiA9IHtcbiAgICAgIG51bVJlcXVpcmVkU2lnbmF0dXJlczogQnVmZmVyLmZyb20oW3RoaXMuaGVhZGVyLm51bVJlcXVpcmVkU2lnbmF0dXJlc10pLFxuICAgICAgbnVtUmVhZG9ubHlTaWduZWRBY2NvdW50czogQnVmZmVyLmZyb20oW3RoaXMuaGVhZGVyLm51bVJlYWRvbmx5U2lnbmVkQWNjb3VudHNdKSxcbiAgICAgIG51bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50czogQnVmZmVyLmZyb20oW3RoaXMuaGVhZGVyLm51bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50c10pLFxuICAgICAga2V5Q291bnQ6IEJ1ZmZlci5mcm9tKGtleUNvdW50KSxcbiAgICAgIGtleXM6IHRoaXMuYWNjb3VudEtleXMubWFwKChrZXkpID0+IEJ1ZmZlci5mcm9tKGtleSwgJ2hleCcpKSxcbiAgICAgIHJlY2VudEJsb2NraGFzaDogQnVmZmVyLmZyb20odGhpcy5yZWNlbnRCbG9ja2hhc2gsICdoZXgnKSxcbiAgICB9O1xuICAgIGNvbnN0IHNpZ25EYXRhID0gQnVmZmVyLmFsbG9jKDIwNDgpOyAvLyBzaWduIGRhdGEgbWF4IGxlbmd0aFxuICAgIGNvbnN0IGxlbmd0aCA9IHNpZ25EYXRhTGF5b3V0LmVuY29kZSh0cmFuc2FjdGlvbiwgc2lnbkRhdGEpO1xuICAgIGluc3RydWN0aW9uQnVmZmVyLmNvcHkoc2lnbkRhdGEsIGxlbmd0aCk7XG5cbiAgICAvLyByZXR1cm4gc2lnbkRhdGEuc2xpY2UoMCwgbGVuZ3RoICsgaW5zdHJ1Y3Rpb25CdWZmZXIubGVuZ3RoKS50b1N0cmluZygnaGV4Jyk7XG4gICAgcmV0dXJuIHNpZ25EYXRhLnNsaWNlKDAsIGxlbmd0aCArIGluc3RydWN0aW9uQnVmZmVyLmxlbmd0aCk7XG4gIH1cblxuICBzZXJpYWxpemVUcmFuc2Zlck1lc3NhZ2UoKTogc3RyaW5nIHtcbiAgICBjb25zdCB7IGtleUNvdW50LCBpbnN0cnVjdGlvbnMgfSA9IHRoaXMuZW5jb2RlZExlbmd0aCgpO1xuICAgIGxldCBpbnN0cnVjdGlvbkJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhQQUNLRVRfREFUQV9TSVpFKTtcbiAgICBsZXQgZ2FzUHJpY2U7XG4gICAgbGV0IGdhc0xpbWl0O1xuICAgIGxldCB0cmFuc2ZlcjtcbiAgICBsZXQgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggPSAwO1xuICAgIGlmIChpbnN0cnVjdGlvbnMubGVuZ3RoID09PSAzKSB7XG4gICAgICBbZ2FzUHJpY2UsIGdhc0xpbWl0LCB0cmFuc2Zlcl0gPSBpbnN0cnVjdGlvbnM7XG4gICAgICBjb25zdCBnYXNQcmljZUxheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgICBkYXRhOiBudW1iZXJbXTtcbiAgICAgICAgICBkYXRhTGVuZ3RoOiBVaW50OEFycmF5O1xuICAgICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgICAga2V5SW5kaWNlc0NvdW50OiBVaW50OEFycmF5O1xuICAgICAgICB9PlxuICAgICAgPihbXG4gICAgICAgIEJ1ZmZlckxheW91dC51OCgncHJvZ3JhbUlkSW5kZXgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoZ2FzUHJpY2Uua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgZ2FzUHJpY2Uua2V5SW5kaWNlcy5sZW5ndGgsICdrZXlJbmRpY2VzJyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGdhc1ByaWNlLmRhdGFMZW5ndGgubGVuZ3RoLCAnZGF0YUxlbmd0aCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIGdhc1ByaWNlLmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgICAgXSk7XG4gICAgICBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCA9IGdhc1ByaWNlTGF5b3V0LmVuY29kZShnYXNQcmljZSwgaW5zdHJ1Y3Rpb25CdWZmZXIsIDApO1xuICAgICAgY29uc3QgZ2FzTGltaXRMYXlvdXQgPSBCdWZmZXJMYXlvdXQuc3RydWN0PFxuICAgICAgICBSZWFkb25seTx7XG4gICAgICAgICAgZGF0YTogbnVtYmVyW107XG4gICAgICAgICAgZGF0YUxlbmd0aDogVWludDhBcnJheTtcbiAgICAgICAgICBwcm9ncmFtSWRJbmRleDogbnVtYmVyO1xuICAgICAgICAgIGtleUluZGljZXM6IG51bWJlcltdO1xuICAgICAgICAgIGtleUluZGljZXNDb3VudDogVWludDhBcnJheTtcbiAgICAgICAgfT5cbiAgICAgID4oW1xuICAgICAgICBCdWZmZXJMYXlvdXQudTgoJ3Byb2dyYW1JZEluZGV4JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGdhc0xpbWl0LmtleUluZGljZXNDb3VudC5sZW5ndGgsICdrZXlJbmRpY2VzQ291bnQnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ2tleUluZGV4JyksIGdhc0xpbWl0LmtleUluZGljZXMubGVuZ3RoLCAna2V5SW5kaWNlcycpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihnYXNMaW1pdC5kYXRhTGVuZ3RoLmxlbmd0aCwgJ2RhdGFMZW5ndGgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ3VzZXJkYXR1bScpLCBnYXNMaW1pdC5kYXRhLmxlbmd0aCwgJ2RhdGEnKSxcbiAgICAgIF0pO1xuICAgICAgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggKz0gZ2FzTGltaXRMYXlvdXQuZW5jb2RlKGdhc0xpbWl0LCBpbnN0cnVjdGlvbkJ1ZmZlciwgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBbdHJhbnNmZXJdID0gaW5zdHJ1Y3Rpb25zO1xuICAgIH1cblxuICAgIGNvbnN0IHRyYW5zZmVyTGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgZGF0YTogbnVtYmVyW107XG4gICAgICAgIGRhdGFMZW5ndGg6IFVpbnQ4QXJyYXk7XG4gICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgIGtleUluZGljZXM6IG51bWJlcltdO1xuICAgICAgICBrZXlJbmRpY2VzQ291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICB9PlxuICAgID4oW1xuICAgICAgQnVmZmVyTGF5b3V0LnU4KCdwcm9ncmFtSWRJbmRleCcpLFxuICAgICAgQnVmZmVyTGF5b3V0LmJsb2IodHJhbnNmZXIua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ2tleUluZGV4JyksIHRyYW5zZmVyLmtleUluZGljZXMubGVuZ3RoLCAna2V5SW5kaWNlcycpLFxuICAgICAgQnVmZmVyTGF5b3V0LmJsb2IodHJhbnNmZXIuZGF0YUxlbmd0aC5sZW5ndGgsICdkYXRhTGVuZ3RoJyksXG4gICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIHRyYW5zZmVyLmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgIF0pO1xuXG4gICAgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggKz0gdHJhbnNmZXJMYXlvdXQuZW5jb2RlKHRyYW5zZmVyLCBpbnN0cnVjdGlvbkJ1ZmZlciwgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGgpO1xuICAgIGluc3RydWN0aW9uQnVmZmVyID0gaW5zdHJ1Y3Rpb25CdWZmZXIuc2xpY2UoMCwgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGgpO1xuICAgIGxldCBhY2NvdW50S2V5cyA9IFsuLi50aGlzLmFjY291bnRLZXlzXTtcbiAgICBmb3IgKGxldCBpID0gdGhpcy5hY2NvdW50S2V5cy5sZW5ndGg7IGkgPCA2OyBpKyspIHtcbiAgICAgIGFjY291bnRLZXlzID0gYWNjb3VudEtleXMuY29uY2F0KFBBRERJTkdfUFVCTElDS0VZKTtcbiAgICB9XG5cbiAgICBjb25zdCBzaWduRGF0YUxheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICBSZWFkb25seTx7XG4gICAgICAgIGtleUNvdW50OiBVaW50OEFycmF5O1xuICAgICAgICBrZXlzOiBVaW50OEFycmF5W107XG4gICAgICAgIHJlY2VudEJsb2NraGFzaDogVWludDhBcnJheTtcbiAgICAgIH0+XG4gICAgPihbXG4gICAgICBCdWZmZXJMYXlvdXQuYmxvYihrZXlDb3VudC5sZW5ndGgsICdrZXlDb3VudCcpLFxuICAgICAgQnVmZmVyTGF5b3V0LnNlcShwdWJsaWNLZXkoJ2tleScpLCBhY2NvdW50S2V5cy5sZW5ndGgsICdrZXlzJyksXG4gICAgICBwdWJsaWNLZXkoJ3JlY2VudEJsb2NraGFzaCcpLFxuICAgIF0pO1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uID0ge1xuICAgICAga2V5Q291bnQ6IEJ1ZmZlci5mcm9tKGtleUNvdW50KSxcbiAgICAgIGtleXM6IGFjY291bnRLZXlzLm1hcCgoa2V5KSA9PiBCdWZmZXIuZnJvbShrZXksICdoZXgnKSksXG4gICAgICByZWNlbnRCbG9ja2hhc2g6IEJ1ZmZlci5mcm9tKHRoaXMucmVjZW50QmxvY2toYXNoLCAnaGV4JyksXG4gICAgfTtcbiAgICBjb25zdCBzaWduRGF0YSA9IEJ1ZmZlci5hbGxvYygyMDQ4KTsgLy8gc2lnbiBkYXRhIG1heCBsZW5ndGhcbiAgICBjb25zdCBsZW5ndGggPSBzaWduRGF0YUxheW91dC5lbmNvZGUodHJhbnNhY3Rpb24sIHNpZ25EYXRhKTtcbiAgICBpbnN0cnVjdGlvbkJ1ZmZlci5jb3B5KHNpZ25EYXRhLCBsZW5ndGgpO1xuXG4gICAgcmV0dXJuIHNpZ25EYXRhLnNsaWNlKDAsIGxlbmd0aCArIGluc3RydWN0aW9uQnVmZmVyLmxlbmd0aCkudG9TdHJpbmcoJ2hleCcpO1xuICB9XG5cbiAgc2VyaWFsaXplQ3JlYXRlQW5kVHJhbnNmZXJTUExUb2tlbigpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsga2V5Q291bnQsIGluc3RydWN0aW9ucyB9ID0gdGhpcy5lbmNvZGVkTGVuZ3RoKCk7XG4gICAgbGV0IGluc3RydWN0aW9uQnVmZmVyID0gQnVmZmVyLmFsbG9jKFBBQ0tFVF9EQVRBX1NJWkUpO1xuICAgIGxldCBhc3NvY2lhdGVBY2NvdW50O1xuICAgIGxldCBnYXNQcmljZTtcbiAgICBsZXQgZ2FzTGltaXQ7XG4gICAgbGV0IHRva2VuVHJhbnNmZXI7XG4gICAgbGV0IGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoID0gMDtcbiAgICBpZiAoaW5zdHJ1Y3Rpb25zLmxlbmd0aCA9PT0gNCkge1xuICAgICAgW2Fzc29jaWF0ZUFjY291bnQsIGdhc1ByaWNlLCBnYXNMaW1pdCwgdG9rZW5UcmFuc2Zlcl0gPSBpbnN0cnVjdGlvbnM7XG5cbiAgICAgIGNvbnN0IGFzc29jaWF0ZUFjY291bnRMYXlvdXQgPSBCdWZmZXJMYXlvdXQuc3RydWN0PFxuICAgICAgICBSZWFkb25seTx7XG4gICAgICAgICAgZGF0YTogbnVtYmVyW107XG4gICAgICAgICAgZGF0YUxlbmd0aDogVWludDhBcnJheTtcbiAgICAgICAgICBwcm9ncmFtSWRJbmRleDogbnVtYmVyO1xuICAgICAgICAgIGtleUluZGljZXM6IG51bWJlcltdO1xuICAgICAgICAgIGtleUluZGljZXNDb3VudDogVWludDhBcnJheTtcbiAgICAgICAgfT5cbiAgICAgID4oW1xuICAgICAgICBCdWZmZXJMYXlvdXQudTgoJ3Byb2dyYW1JZEluZGV4JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGFzc29jaWF0ZUFjY291bnQua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgYXNzb2NpYXRlQWNjb3VudC5rZXlJbmRpY2VzLmxlbmd0aCwgJ2tleUluZGljZXMnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoYXNzb2NpYXRlQWNjb3VudC5kYXRhTGVuZ3RoLmxlbmd0aCwgJ2RhdGFMZW5ndGgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ3VzZXJkYXR1bScpLCBhc3NvY2lhdGVBY2NvdW50LmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgICAgXSk7XG4gICAgICBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCA9IGFzc29jaWF0ZUFjY291bnRMYXlvdXQuZW5jb2RlKGFzc29jaWF0ZUFjY291bnQsIGluc3RydWN0aW9uQnVmZmVyLCAwKTtcblxuICAgICAgY29uc3QgZ2FzUHJpY2VMYXlvdXQgPSBCdWZmZXJMYXlvdXQuc3RydWN0PFxuICAgICAgICBSZWFkb25seTx7XG4gICAgICAgICAgZGF0YTogbnVtYmVyW107XG4gICAgICAgICAgZGF0YUxlbmd0aDogVWludDhBcnJheTtcbiAgICAgICAgICBwcm9ncmFtSWRJbmRleDogbnVtYmVyO1xuICAgICAgICAgIGtleUluZGljZXM6IG51bWJlcltdO1xuICAgICAgICAgIGtleUluZGljZXNDb3VudDogVWludDhBcnJheTtcbiAgICAgICAgfT5cbiAgICAgID4oW1xuICAgICAgICBCdWZmZXJMYXlvdXQudTgoJ3Byb2dyYW1JZEluZGV4JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGdhc1ByaWNlLmtleUluZGljZXNDb3VudC5sZW5ndGgsICdrZXlJbmRpY2VzQ291bnQnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ2tleUluZGV4JyksIGdhc1ByaWNlLmtleUluZGljZXMubGVuZ3RoLCAna2V5SW5kaWNlcycpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuYmxvYihnYXNQcmljZS5kYXRhTGVuZ3RoLmxlbmd0aCwgJ2RhdGFMZW5ndGgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ3VzZXJkYXR1bScpLCBnYXNQcmljZS5kYXRhLmxlbmd0aCwgJ2RhdGEnKSxcbiAgICAgIF0pO1xuICAgICAgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGggKz0gZ2FzUHJpY2VMYXlvdXQuZW5jb2RlKGdhc1ByaWNlLCBpbnN0cnVjdGlvbkJ1ZmZlciwgaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGgpO1xuXG4gICAgICBjb25zdCBnYXNMaW1pdExheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAgICBkYXRhOiBudW1iZXJbXTtcbiAgICAgICAgICBkYXRhTGVuZ3RoOiBVaW50OEFycmF5O1xuICAgICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgICAga2V5SW5kaWNlczogbnVtYmVyW107XG4gICAgICAgICAga2V5SW5kaWNlc0NvdW50OiBVaW50OEFycmF5O1xuICAgICAgICB9PlxuICAgICAgPihbXG4gICAgICAgIEJ1ZmZlckxheW91dC51OCgncHJvZ3JhbUlkSW5kZXgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoZ2FzTGltaXQua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgZ2FzTGltaXQua2V5SW5kaWNlcy5sZW5ndGgsICdrZXlJbmRpY2VzJyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGdhc0xpbWl0LmRhdGFMZW5ndGgubGVuZ3RoLCAnZGF0YUxlbmd0aCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgndXNlcmRhdHVtJyksIGdhc0xpbWl0LmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgICAgXSk7XG4gICAgICBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCArPSBnYXNMaW1pdExheW91dC5lbmNvZGUoZ2FzTGltaXQsIGluc3RydWN0aW9uQnVmZmVyLCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIFthc3NvY2lhdGVBY2NvdW50LCB0b2tlblRyYW5zZmVyXSA9IGluc3RydWN0aW9ucztcbiAgICAgIGNvbnN0IGFzc29jaWF0ZUFjY291bnRMYXlvdXQgPSBCdWZmZXJMYXlvdXQuc3RydWN0PFxuICAgICAgICBSZWFkb25seTx7XG4gICAgICAgICAgZGF0YTogbnVtYmVyW107XG4gICAgICAgICAgZGF0YUxlbmd0aDogVWludDhBcnJheTtcbiAgICAgICAgICBwcm9ncmFtSWRJbmRleDogbnVtYmVyO1xuICAgICAgICAgIGtleUluZGljZXM6IG51bWJlcltdO1xuICAgICAgICAgIGtleUluZGljZXNDb3VudDogVWludDhBcnJheTtcbiAgICAgICAgfT5cbiAgICAgID4oW1xuICAgICAgICBCdWZmZXJMYXlvdXQudTgoJ3Byb2dyYW1JZEluZGV4JyksXG4gICAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGFzc29jaWF0ZUFjY291bnQua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgICBCdWZmZXJMYXlvdXQuc2VxKEJ1ZmZlckxheW91dC51OCgna2V5SW5kZXgnKSwgYXNzb2NpYXRlQWNjb3VudC5rZXlJbmRpY2VzLmxlbmd0aCwgJ2tleUluZGljZXMnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LmJsb2IoYXNzb2NpYXRlQWNjb3VudC5kYXRhTGVuZ3RoLmxlbmd0aCwgJ2RhdGFMZW5ndGgnKSxcbiAgICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ3VzZXJkYXR1bScpLCBhc3NvY2lhdGVBY2NvdW50LmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgICAgXSk7XG4gICAgICBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCA9IGFzc29jaWF0ZUFjY291bnRMYXlvdXQuZW5jb2RlKGFzc29jaWF0ZUFjY291bnQsIGluc3RydWN0aW9uQnVmZmVyLCAwKTtcbiAgICB9XG4gICAgY29uc3QgdG9rZW5UcmFuc2ZlckxheW91dCA9IEJ1ZmZlckxheW91dC5zdHJ1Y3Q8XG4gICAgICBSZWFkb25seTx7XG4gICAgICAgIHByb2dyYW1JZEluZGV4OiBudW1iZXI7XG4gICAgICAgIGtleUluZGljZXM6IG51bWJlcltdO1xuICAgICAgICBrZXlJbmRpY2VzQ291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICAgIGRhdGE6IG51bWJlcltdO1xuICAgICAgICBkYXRhTGVuZ3RoOiBVaW50OEFycmF5O1xuICAgICAgfT5cbiAgICA+KFtcbiAgICAgIEJ1ZmZlckxheW91dC51OCgncHJvZ3JhbUlkSW5kZXgnKSxcbiAgICAgIEJ1ZmZlckxheW91dC5ibG9iKHRva2VuVHJhbnNmZXIua2V5SW5kaWNlc0NvdW50Lmxlbmd0aCwgJ2tleUluZGljZXNDb3VudCcpLFxuICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ2tleUluZGV4JyksIHRva2VuVHJhbnNmZXIua2V5SW5kaWNlcy5sZW5ndGgsICdrZXlJbmRpY2VzJyksXG4gICAgICBCdWZmZXJMYXlvdXQuYmxvYih0b2tlblRyYW5zZmVyLmRhdGFMZW5ndGgubGVuZ3RoLCAnZGF0YUxlbmd0aCcpLFxuICAgICAgQnVmZmVyTGF5b3V0LnNlcShCdWZmZXJMYXlvdXQudTgoJ3VzZXJkYXR1bScpLCB0b2tlblRyYW5zZmVyLmRhdGEubGVuZ3RoLCAnZGF0YScpLFxuICAgIF0pO1xuICAgIGluc3RydWN0aW9uQnVmZmVyTGVuZ3RoICs9IHRva2VuVHJhbnNmZXJMYXlvdXQuZW5jb2RlKHRva2VuVHJhbnNmZXIsIGluc3RydWN0aW9uQnVmZmVyLCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCk7XG4gICAgaW5zdHJ1Y3Rpb25CdWZmZXIgPSBpbnN0cnVjdGlvbkJ1ZmZlci5zbGljZSgwLCBpbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aCk7XG4gICAgbGV0IGFjY291bnRLZXlzID0gWy4uLnRoaXMuYWNjb3VudEtleXNdO1xuICAgIGZvciAobGV0IGkgPSB0aGlzLmFjY291bnRLZXlzLmxlbmd0aDsgaSA8IDk7IGkrKykge1xuICAgICAgYWNjb3VudEtleXMgPSBhY2NvdW50S2V5cy5jb25jYXQoQnVmZmVyLmFsbG9jKDMyKS50b1N0cmluZygnaGV4JykpO1xuICAgIH1cblxuICAgIGNvbnN0IHNpZ25EYXRhTGF5b3V0ID0gQnVmZmVyTGF5b3V0LnN0cnVjdDxcbiAgICAgIFJlYWRvbmx5PHtcbiAgICAgICAga2V5Q291bnQ6IFVpbnQ4QXJyYXk7XG4gICAgICAgIGtleXM6IFVpbnQ4QXJyYXlbXTtcbiAgICAgICAgcmVjZW50QmxvY2toYXNoOiBVaW50OEFycmF5O1xuICAgICAgfT5cbiAgICA+KFtcbiAgICAgIEJ1ZmZlckxheW91dC5ibG9iKGtleUNvdW50Lmxlbmd0aCwgJ2tleUNvdW50JyksXG4gICAgICBCdWZmZXJMYXlvdXQuc2VxKHB1YmxpY0tleSgna2V5JyksIGFjY291bnRLZXlzLmxlbmd0aCwgJ2tleXMnKSxcbiAgICAgIHB1YmxpY0tleSgncmVjZW50QmxvY2toYXNoJyksXG4gICAgXSk7XG4gICAgY29uc3QgdHJhbnNhY3Rpb24gPSB7XG4gICAgICBrZXlDb3VudDogQnVmZmVyLmZyb20oa2V5Q291bnQpLFxuICAgICAga2V5czogYWNjb3VudEtleXMubWFwKChrZXkpID0+IEJ1ZmZlci5mcm9tKGtleSwgJ2hleCcpKSxcbiAgICAgIHJlY2VudEJsb2NraGFzaDogQnVmZmVyLmZyb20odGhpcy5yZWNlbnRCbG9ja2hhc2gsICdoZXgnKSxcbiAgICB9O1xuICAgIGNvbnN0IHNpZ25EYXRhID0gQnVmZmVyLmFsbG9jKDIwNDgpOyAvLyBzaWduIGRhdGEgbWF4IGxlbmd0aFxuICAgIGNvbnN0IGxlbmd0aCA9IHNpZ25EYXRhTGF5b3V0LmVuY29kZSh0cmFuc2FjdGlvbiwgc2lnbkRhdGEpO1xuICAgIGluc3RydWN0aW9uQnVmZmVyLmNvcHkoc2lnbkRhdGEsIGxlbmd0aCk7XG5cbiAgICByZXR1cm4gc2lnbkRhdGEuc2xpY2UoMCwgbGVuZ3RoICsgaW5zdHJ1Y3Rpb25CdWZmZXIubGVuZ3RoKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICByZXNlcnZlUGFkZGluZ0FjY291bnRLZXlzKG1heEFjY291bnRLZXlMZW5ndGg6IG51bWJlcik6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBhY2NvdW50S2V5cyA9IHRoaXMuYWNjb3VudEtleXM7XG4gICAgY29uc3QgbmVlZFBhZGRpbmdLZXlMZW5ndGggPSBtYXhBY2NvdW50S2V5TGVuZ3RoIC0gdGhpcy5hY2NvdW50S2V5cy5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZWVkUGFkZGluZ0tleUxlbmd0aDsgaSsrKSB7XG4gICAgICBhY2NvdW50S2V5cy5wdXNoKFBBRERJTkdfUFVCTElDS0VZKTtcbiAgICB9XG4gICAgcmV0dXJuIGFjY291bnRLZXlzO1xuICB9XG5cbiAgc2VyaWFsaXplRGVsZWdhdGVBbmRDcmVhdGVBY2NvdW50V2l0aFNlZWQoKTogc3RyaW5nIHtcbiAgICBjb25zdCB7IGtleUNvdW50LCBpbnN0cnVjdGlvbkNvdW50LCBpbnN0cnVjdGlvbnMgfSA9IHRoaXMuZW5jb2RlZExlbmd0aCgpO1xuICAgIGNvbnN0IGluaXRBbmRQYWRkaW5nSW5zdHJ1Y3Rpb24gPSBpbml0QW5kUGFkZGluZ0NvbXB1dGVCdWRnZXRJbnN0cnVjdGlvbkJ1ZmZlcihcbiAgICAgIHRoaXMuYWNjb3VudEtleXMsXG4gICAgICBpbnN0cnVjdGlvbnMsXG4gICAgICBpbnN0cnVjdGlvbkNvdW50XG4gICAgKTtcbiAgICBjb25zdCBpbnN0cnVjdGlvbkJ1ZmZlciA9IGVuY29kZUFuZFBhZGRpbmdTZWVkSW5zdHJ1Y3Rpb25CdWZmZXIoXG4gICAgICB0aGlzLmFjY291bnRLZXlzLFxuICAgICAgaW5zdHJ1Y3Rpb25zLFxuICAgICAgaW5pdEFuZFBhZGRpbmdJbnN0cnVjdGlvbi5pbnN0cnVjdGlvbkJ1ZmZlcixcbiAgICAgIGluaXRBbmRQYWRkaW5nSW5zdHJ1Y3Rpb24uaW5zdHJ1Y3Rpb25CdWZmZXJMZW5ndGhcbiAgICApO1xuICAgIC8qKlxuICAgICAqIHNpZ25lclB1YmtleVxuICAgICAqIHN0YWtlQWNjb3VudFB1YmtleVxuICAgICAqIDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExXG4gICAgICogdmFsaWRhdG9yUHVia2V5XG4gICAgICogU3Rha2UxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIFN0YWtlQ29uZmlnMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTFcbiAgICAgKiBTeXN2YXJDMW9jazExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExXG4gICAgICogU3lzdmFyUmVudDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIFN5c3ZhclN0YWtlSGlzdG9yeTExMTExMTExMTExMTExMTExMTExMTExMTFcbiAgICAgKiBDb21wdXRlQnVkZ2V0MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExICAob3B0aW9uYWwpXG4gICAgICovXG4gICAgY29uc3QgbmV3QWNjb3VudEtleXMgPSB0aGlzLnJlc2VydmVQYWRkaW5nQWNjb3VudEtleXMoMTApO1xuICAgIHJldHVybiBlbmNvZGVTaWduRGF0YShrZXlDb3VudCwgbmV3QWNjb3VudEtleXMsIHRoaXMucmVjZW50QmxvY2toYXNoLCBpbnN0cnVjdGlvbkJ1ZmZlcikudG9TdHJpbmcoJ2hleCcpO1xuICB9XG5cbiAgc2VyaWFsaXplVW5kZWxlZ2F0ZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsga2V5Q291bnQsIGluc3RydWN0aW9uQ291bnQsIGluc3RydWN0aW9ucyB9ID0gdGhpcy5lbmNvZGVkTGVuZ3RoKCk7XG4gICAgY29uc3QgaW5pdEFuZFBhZGRpbmdJbnN0cnVjdGlvbiA9IGluaXRBbmRQYWRkaW5nQ29tcHV0ZUJ1ZGdldEluc3RydWN0aW9uQnVmZmVyKFxuICAgICAgdGhpcy5hY2NvdW50S2V5cyxcbiAgICAgIGluc3RydWN0aW9ucyxcbiAgICAgIGluc3RydWN0aW9uQ291bnRcbiAgICApO1xuICAgIGNvbnN0IGluc3RydWN0aW9uQnVmZmVyID0gZW5jb2RlSW5zdHJ1Y3Rpb25CdWZmZXIoXG4gICAgICBpbnN0cnVjdGlvbnMsXG4gICAgICBpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uLmluc3RydWN0aW9uQnVmZmVyLFxuICAgICAgaW5pdEFuZFBhZGRpbmdJbnN0cnVjdGlvbi5pbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aFxuICAgICk7XG4gICAgLyoqXG4gICAgICogc2lnbmVyUHVia2V5XG4gICAgICogc3Rha2VBY2NvdW50UHVia2V5XG4gICAgICogU3Rha2UxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIFN5c3ZhckMxb2NrMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTFcbiAgICAgKiBDb21wdXRlQnVkZ2V0MTExMTExMTExMTExMTExMTExMTExMTExMTExMTExICAob3B0aW9uYWwpXG4gICAgICovXG4gICAgY29uc3QgbmV3QWNjb3VudEtleXMgPSB0aGlzLnJlc2VydmVQYWRkaW5nQWNjb3VudEtleXMoNSk7XG4gICAgcmV0dXJuIGVuY29kZVNpZ25EYXRhKGtleUNvdW50LCBuZXdBY2NvdW50S2V5cywgdGhpcy5yZWNlbnRCbG9ja2hhc2gsIGluc3RydWN0aW9uQnVmZmVyKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICBzZXJpYWxpemVXaXRoZHJhdygpOiBzdHJpbmcge1xuICAgIGNvbnN0IHsga2V5Q291bnQsIGluc3RydWN0aW9uQ291bnQsIGluc3RydWN0aW9ucyB9ID0gdGhpcy5lbmNvZGVkTGVuZ3RoKCk7XG4gICAgY29uc3QgaW5pdEFuZFBhZGRpbmdJbnN0cnVjdGlvbiA9IGluaXRBbmRQYWRkaW5nQ29tcHV0ZUJ1ZGdldEluc3RydWN0aW9uQnVmZmVyKFxuICAgICAgdGhpcy5hY2NvdW50S2V5cyxcbiAgICAgIGluc3RydWN0aW9ucyxcbiAgICAgIGluc3RydWN0aW9uQ291bnRcbiAgICApO1xuICAgIGNvbnN0IGluc3RydWN0aW9uQnVmZmVyID0gZW5jb2RlSW5zdHJ1Y3Rpb25CdWZmZXIoXG4gICAgICBpbnN0cnVjdGlvbnMsXG4gICAgICBpbml0QW5kUGFkZGluZ0luc3RydWN0aW9uLmluc3RydWN0aW9uQnVmZmVyLFxuICAgICAgaW5pdEFuZFBhZGRpbmdJbnN0cnVjdGlvbi5pbnN0cnVjdGlvbkJ1ZmZlckxlbmd0aFxuICAgICk7XG4gICAgLyoqXG4gICAgICogc2lnbmVyUHVia2V5XG4gICAgICogc3Rha2VBY2NvdW50UHVia2V5XG4gICAgICogd2l0aGRyYXdUb1B1YmtleSAgICAgICAgICAgICAgICAgICAgICAgICAgICAob3B0aW9uYWwpXG4gICAgICogU3Rha2UxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMVxuICAgICAqIFN5c3ZhckMxb2NrMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTFcbiAgICAgKiBTeXN2YXJTdGFrZUhpc3RvcnkxMTExMTExMTExMTExMTExMTExMTExMTExXG4gICAgICogQ29tcHV0ZUJ1ZGdldDExMTExMTExMTExMTExMTExMTExMTExMTExMTExMSAob3B0aW9uYWwpXG4gICAgICovXG4gICAgY29uc3QgbmV3QWNjb3VudEtleXMgPSB0aGlzLnJlc2VydmVQYWRkaW5nQWNjb3VudEtleXMoNyk7XG4gICAgcmV0dXJuIGVuY29kZVNpZ25EYXRhKGtleUNvdW50LCBuZXdBY2NvdW50S2V5cywgdGhpcy5yZWNlbnRCbG9ja2hhc2gsIGluc3RydWN0aW9uQnVmZmVyKS50b1N0cmluZygnaGV4Jyk7XG4gIH1cblxuICAvKipcbiAgICogRGVjb2RlIGEgY29tcGlsZWQgbWVzc2FnZSBpbnRvIGEgTWVzc2FnZSBvYmplY3QuXG4gICAqL1xuICBzdGF0aWMgZnJvbShidWZmZXI6IEJ1ZmZlciB8IFVpbnQ4QXJyYXkgfCBBcnJheTxudW1iZXI+KTogTWVzc2FnZSB7XG4gICAgLy8gU2xpY2UgdXAgd2lyZSBkYXRhXG4gICAgbGV0IGJ5dGVBcnJheSA9IFsuLi5idWZmZXJdO1xuXG4gICAgY29uc3QgbnVtUmVxdWlyZWRTaWduYXR1cmVzID0gYnl0ZUFycmF5LnNoaWZ0KCkhO1xuICAgIGlmIChudW1SZXF1aXJlZFNpZ25hdHVyZXMgIT09IChudW1SZXF1aXJlZFNpZ25hdHVyZXMgJiBWRVJTSU9OX1BSRUZJWF9NQVNLKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdWZXJzaW9uZWQgbWVzc2FnZXMgbXVzdCBiZSBkZXNlcmlhbGl6ZWQgd2l0aCBWZXJzaW9uZWRNZXNzYWdlLmRlc2VyaWFsaXplKCknKTtcbiAgICB9XG5cbiAgICBjb25zdCBudW1SZWFkb25seVNpZ25lZEFjY291bnRzID0gYnl0ZUFycmF5LnNoaWZ0KCkhO1xuICAgIGNvbnN0IG51bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50cyA9IGJ5dGVBcnJheS5zaGlmdCgpITtcblxuICAgIGNvbnN0IGFjY291bnRDb3VudCA9IHNob3J0dmVjLmRlY29kZUxlbmd0aChieXRlQXJyYXkpO1xuICAgIGNvbnN0IGFjY291bnRLZXlzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhY2NvdW50Q291bnQ7IGkrKykge1xuICAgICAgY29uc3QgYWNjb3VudCA9IGJ5dGVBcnJheS5zbGljZSgwLCBQVUJMSUNfS0VZX0xFTkdUSCk7XG4gICAgICBieXRlQXJyYXkgPSBieXRlQXJyYXkuc2xpY2UoUFVCTElDX0tFWV9MRU5HVEgpO1xuICAgICAgYWNjb3VudEtleXMucHVzaChCdWZmZXIuZnJvbShhY2NvdW50KS50b1N0cmluZygnaGV4JykpO1xuICAgIH1cblxuICAgIGNvbnN0IHJlY2VudEJsb2NraGFzaCA9IGJ5dGVBcnJheS5zbGljZSgwLCBQVUJMSUNfS0VZX0xFTkdUSCk7XG4gICAgYnl0ZUFycmF5ID0gYnl0ZUFycmF5LnNsaWNlKFBVQkxJQ19LRVlfTEVOR1RIKTtcblxuICAgIGNvbnN0IGluc3RydWN0aW9uQ291bnQgPSBzaG9ydHZlYy5kZWNvZGVMZW5ndGgoYnl0ZUFycmF5KTtcbiAgICBjb25zdCBpbnN0cnVjdGlvbnM6IENvbXBpbGVkSW5zdHJ1Y3Rpb25bXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5zdHJ1Y3Rpb25Db3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBwcm9ncmFtSWRJbmRleCA9IGJ5dGVBcnJheS5zaGlmdCgpITtcbiAgICAgIGNvbnN0IGluc3RydWN0aW9uQWNjb3VudENvdW50ID0gc2hvcnR2ZWMuZGVjb2RlTGVuZ3RoKGJ5dGVBcnJheSk7XG4gICAgICBjb25zdCBhY2NvdW50cyA9IGJ5dGVBcnJheS5zbGljZSgwLCBpbnN0cnVjdGlvbkFjY291bnRDb3VudCk7XG4gICAgICBieXRlQXJyYXkgPSBieXRlQXJyYXkuc2xpY2UoaW5zdHJ1Y3Rpb25BY2NvdW50Q291bnQpO1xuICAgICAgY29uc3QgZGF0YUxlbmd0aCA9IHNob3J0dmVjLmRlY29kZUxlbmd0aChieXRlQXJyYXkpO1xuICAgICAgY29uc3QgZGF0YVNsaWNlID0gYnl0ZUFycmF5LnNsaWNlKDAsIGRhdGFMZW5ndGgpO1xuICAgICAgY29uc3QgZGF0YSA9IEJ1ZmZlci5mcm9tKGRhdGFTbGljZSkudG9TdHJpbmcoJ2hleCcpO1xuICAgICAgYnl0ZUFycmF5ID0gYnl0ZUFycmF5LnNsaWNlKGRhdGFMZW5ndGgpO1xuICAgICAgaW5zdHJ1Y3Rpb25zLnB1c2goe1xuICAgICAgICBwcm9ncmFtSWRJbmRleCxcbiAgICAgICAgYWNjb3VudHMsXG4gICAgICAgIGRhdGEsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBtZXNzYWdlQXJncyA9IHtcbiAgICAgIGhlYWRlcjoge1xuICAgICAgICBudW1SZXF1aXJlZFNpZ25hdHVyZXMsXG4gICAgICAgIG51bVJlYWRvbmx5U2lnbmVkQWNjb3VudHMsXG4gICAgICAgIG51bVJlYWRvbmx5VW5zaWduZWRBY2NvdW50cyxcbiAgICAgIH0sXG4gICAgICByZWNlbnRCbG9ja2hhc2g6IEJ1ZmZlci5mcm9tKHJlY2VudEJsb2NraGFzaCkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgYWNjb3VudEtleX