UNPKG

@coolwallet/sol

Version:
331 lines (325 loc) 73.5 kB
"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