PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-xtz/dist/src/lib
Просмотр файла: utils.js
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TRANSACTION_GAS_LIMIT = exports.TRANSACTION_STORAGE_LIMIT = exports.TRANSACTION_FEE = exports.DEFAULT_STORAGE_LIMIT = exports.DEFAULT_FEE = exports.DEFAULT_GAS_LIMIT = exports.hashTypes = exports.DEFAULT_WATERMARK = void 0;
exports.base58encode = base58encode;
exports.calculateTransactionId = calculateTransactionId;
exports.calculateOriginatedAddress = calculateOriginatedAddress;
exports.sign = sign;
exports.verifySignature = verifySignature;
exports.generateDataToSign = generateDataToSign;
exports.isValidHash = isValidHash;
exports.isValidAddress = isValidAddress;
exports.isValidImplicitAddress = isValidImplicitAddress;
exports.isValidOriginatedAddress = isValidOriginatedAddress;
exports.isValidSignature = isValidSignature;
exports.isValidPublicKey = isValidPublicKey;
exports.isValidPrivateKey = isValidPrivateKey;
exports.isValidBlockHash = isValidBlockHash;
exports.isValidTransactionHash = isValidTransactionHash;
exports.isValidKey = isValidKey;
exports.decodeKey = decodeKey;
exports.decodeSignature = decodeSignature;
const sdk_core_1 = require("@bitgo/sdk-core");
const signer_1 = require("@taquito/signer");
const base58check = __importStar(require("bs58check"));
const secp256k1_1 = require("@noble/curves/secp256k1");
const libsodium_wrappers_1 = __importDefault(require("libsodium-wrappers"));
const multisigUtils_1 = require("./multisigUtils");
// By default, use the transactions prefix
exports.DEFAULT_WATERMARK = new Uint8Array([3]);
/**
* Encode the payload to base58 with a specific Tezos prefix.
*
* @param {Buffer} prefix to add to the encoded payload
* @param {Buffer} payload to encode
* @returns {any} base58 payload with a Tezos prefix
*/
function base58encode(prefix, payload) {
const n = Buffer.alloc(prefix.length + payload.length);
n.set(prefix);
n.set(payload, prefix.length);
return base58check.encode(n);
}
/**
* Calculate the transaction id for a for a signed transaction.
*
* @param {string} encodedTransaction Signed transaction in hexadecimal
* @returns {Promise<string>} The transaction id
*/
async function calculateTransactionId(encodedTransaction) {
await libsodium_wrappers_1.default.ready;
const encodedTransactionBuffer = Uint8Array.from(Buffer.from(encodedTransaction, 'hex'));
const operationHashPayload = libsodium_wrappers_1.default.crypto_generichash(32, encodedTransactionBuffer);
return base58encode(exports.hashTypes.o.prefix, Buffer.from(operationHashPayload));
}
/**
* Calculate the address of a new originated account.
*
* @param {string} transactionId The transaction id
* @param {number} index The index of the origination operation inside the transaction (starts at 0)
* @returns {Promise<string>} An originated address with the KT prefix
*/
async function calculateOriginatedAddress(transactionId, index) {
// From https://github.com/TezTech/eztz/blob/cfdc4fcfc891f4f4f077c3056f414476dde3610b/src/main.js#L768
const ob = base58check.decode(transactionId).slice(exports.hashTypes.o.prefix.length);
let tt = [];
for (let i = 0; i < ob.length; i++) {
tt.push(ob[i]);
}
tt = tt.concat([
(index & 0xff000000) >> 24,
(index & 0x00ff0000) >> 16,
(index & 0x0000ff00) >> 8,
index & 0x000000ff,
]);
await libsodium_wrappers_1.default.ready;
const payload = libsodium_wrappers_1.default.crypto_generichash(20, new Uint8Array(tt));
return base58encode(exports.hashTypes.KT.prefix, Buffer.from(payload));
}
/**
* Generic data signing using Tezos library.
*
* @param {KeyPair} keyPair A Key Pair with a private key set
* @param {string} data The data in hexadecimal to sign
* @param {Uint8Array} watermark Magic byte: 1 for block, 2 for endorsement, 3 for generic
* @returns {Promise<SignResponse>}
*/
async function sign(keyPair, data, watermark = exports.DEFAULT_WATERMARK) {
if (!keyPair.getKeys().prv) {
throw new sdk_core_1.SigningError('Missing private key');
}
const signer = new signer_1.InMemorySigner(keyPair.getKeys().prv);
return signer.sign(data, watermark);
}
/**
* Verifies the signature produced for a given message belongs to a secp256k1 public key.
*
* @param {string} message Message in hex format to verify
* @param {string} publicKey secp256k1 public key with "sppk" prefix to verify the signature with
* @param {string} signature Tezos signature with "sig" prefix
* @param {Uint8Array} watermark Optional watermark used to generate the signature
* @returns {Promise<boolean>}
*/
async function verifySignature(message, publicKey, signature, watermark = exports.DEFAULT_WATERMARK) {
const rawPublicKey = decodeKey(publicKey, exports.hashTypes.sppk).toString('hex');
const key = secp256k1_1.secp256k1.ProjectivePoint.fromHex(rawPublicKey);
const messageBuffer = Uint8Array.from(Buffer.from(message, 'hex'));
// Tezos signatures always have a watermark
const messageWithWatermark = new Uint8Array(watermark.length + messageBuffer.length);
messageWithWatermark.set(watermark);
messageWithWatermark.set(messageBuffer, watermark.length);
await libsodium_wrappers_1.default.ready;
const bytesHash = Buffer.from(libsodium_wrappers_1.default.crypto_generichash(32, messageWithWatermark));
const rawSignature = decodeSignature(signature, exports.hashTypes.sig);
return secp256k1_1.secp256k1.verify(rawSignature, bytesHash, key.toHex());
}
/**
* Useful wrapper to create the generic multisig contract data to sign when moving funds.
*
* @param {string} contractAddress The wallet contract address with the funds to withdraw
* @param {string} destinationAddress The address to transfer the funds to
* @param {number} amount Number mutez to transfer
* @param {string} contractCounter Wallet counter to use in the transaction
* @returns {any} A JSON representation of the Michelson script to sign and approve a transfer
*/
function generateDataToSign(contractAddress, destinationAddress, amount, contractCounter) {
if (!isValidOriginatedAddress(contractAddress)) {
throw new Error('Invalid contract address ' + contractAddress + '. An originated account address was expected');
}
if (!isValidAddress(destinationAddress)) {
throw new Error('Invalid destination address ' + destinationAddress);
}
return (0, multisigUtils_1.genericMultisigDataToSign)(contractAddress, destinationAddress, amount, contractCounter);
}
/**
* Returns whether or not the string is a valid Tezos hash of the given type
*
* @param {string} hash - the string to validate
* @param {HashType} hashType - the type of the provided hash
* @returns {boolean}
*/
function isValidHash(hash, hashType) {
// Validate encoding
let decodedHash;
try {
decodedHash = base58check.decode(hash);
}
catch (e) {
return false;
}
const hashPrefix = decodedHash.slice(0, hashType.prefix.length);
// Check prefix
if (!hashPrefix.equals(Buffer.from(hashType.prefix))) {
return false;
}
// Check length
const hashLength = decodedHash.length - hashPrefix.length;
return hashLength === hashType.byteLength;
}
/**
* Returns whether or not the string is a valid Tezos address
*
* @param {string} hash - the address to validate
* @returns {boolean}
*/
function isValidAddress(hash) {
return isValidImplicitAddress(hash) || isValidHash(hash, exports.hashTypes.KT);
}
/**
* Returns whether or not the string is a valid Tezos implicit account address
*
* @param {string} hash - the address to validate
* @returns {boolean}
*/
function isValidImplicitAddress(hash) {
return isValidHash(hash, exports.hashTypes.tz1) || isValidHash(hash, exports.hashTypes.tz2) || isValidHash(hash, exports.hashTypes.tz3);
}
/**
* Returns whether or not the string is a valid Tezos originated account address
*
* @param {string} hash - the address to validate
* @returns {boolean}
*/
function isValidOriginatedAddress(hash) {
return isValidHash(hash, exports.hashTypes.KT);
}
/**
* Returns whether or not the string is a valid Tezos signature
*
* @param {string} hash - the signature to validate
* @returns {boolean}
*/
function isValidSignature(hash) {
return (isValidHash(hash, exports.hashTypes.edsig) ||
isValidHash(hash, exports.hashTypes.spsig1) ||
isValidHash(hash, exports.hashTypes.p2sig) ||
isValidHash(hash, exports.hashTypes.sig));
}
/**
* Returns whether or not the string is a valid Tezos public key
*
* @param {string} publicKey The public key to validate
* @returns {boolean}
*/
function isValidPublicKey(publicKey) {
return (isValidHash(publicKey, exports.hashTypes.sppk) ||
isValidHash(publicKey, exports.hashTypes.p2pk) ||
isValidHash(publicKey, exports.hashTypes.edpk) ||
(0, sdk_core_1.isValidXpub)(publicKey) // xpubs are valid too.
);
}
/**
* Returns whether or not the string is a valid Tezos private key
*
* @param {string} privateKey The private key to validate
* @returns {boolean}
*/
function isValidPrivateKey(privateKey) {
return (isValidHash(privateKey, exports.hashTypes.edesk) ||
isValidHash(privateKey, exports.hashTypes.edsk) ||
isValidHash(privateKey, exports.hashTypes.spsk) ||
isValidHash(privateKey, exports.hashTypes.p2sk));
}
/**
* Returns whether or not the string is a valid Tezos block hash
*
* @param {string} hash - the address to validate
* @returns {boolean}
*/
function isValidBlockHash(hash) {
return isValidHash(hash, exports.hashTypes.b);
}
/**
* Returns whether or not the string is a valid Tezos transaction hash
*
* @param {string} hash - the address to validate
* @returns {boolean}
*/
function isValidTransactionHash(hash) {
return isValidHash(hash, exports.hashTypes.o);
}
/**
* Returns whether or not the string is a valid Tezos key given a prefix
*
* @param {string} hash - the key to validate
* @param {HashType} hashType - the type of the provided hash
* @returns {boolean}
*/
function isValidKey(hash, hashType) {
return isValidHash(hash, hashType);
}
/**
* Get the original key form the text without the given prefix.
*
* @param {string} hash - base58 encoded key with a Tezos prefix
* @param {HashType} hashType - the type of the provided hash
* @returns {Buffer} the original decoded key
*/
function decodeKey(hash, hashType) {
if (!isValidKey(hash, hashType)) {
throw new Error('Unsupported private key');
}
const decodedPrv = base58check.decode(hash);
return Buffer.from(decodedPrv.slice(hashType.prefix.length, decodedPrv.length));
}
/**
* Get the raw signature from a Tezos encoded one.
*
* @param {string} signature Tezos signatures prefixed with sig, edsig, p2sig or spsig
* @param {HashType} hashType The prefix of remove
* @returns {Buffer} The decoded signature without prefix
*/
function decodeSignature(signature, hashType) {
if (!isValidSignature(signature)) {
throw new Error('Unsupported signature');
}
const decodedPrv = base58check.decode(signature);
return Buffer.from(decodedPrv.slice(hashType.prefix.length, decodedPrv.length));
}
// Base58Check is used for encoding
// hashedTypes is used to validate hashes by type, by checking their prefix and
// the length of the Buffer obtained by decoding the hash (excluding the prefix)
exports.hashTypes = {
/* 20 bytes long */
// ed25519 public key hash
tz1: {
prefix: Buffer.from([6, 161, 159]),
byteLength: 20,
},
// secp256k1 public key hash
tz2: {
prefix: Buffer.from([6, 161, 161]),
byteLength: 20,
},
// p256 public key hash
tz3: {
prefix: Buffer.from([6, 161, 164]),
byteLength: 20,
},
KT: {
prefix: Buffer.from([2, 90, 121]),
byteLength: 20,
},
/* 32 bytes long */
// ed25519 public key
edpk: {
prefix: Buffer.from([13, 15, 37, 217]),
byteLength: 32,
},
// ed25519 secret key
edsk2: {
prefix: Buffer.from([13, 15, 58, 7]),
byteLength: 32,
},
// secp256k1 secret key
spsk: {
prefix: Buffer.from([17, 162, 224, 201]),
byteLength: 32,
},
// p256 secret key
p2sk: {
prefix: Buffer.from([16, 81, 238, 189]),
byteLength: 32,
},
// block hash
b: {
prefix: Buffer.from([1, 52]),
byteLength: 32,
},
// operation hash
o: {
prefix: Buffer.from([5, 116]),
byteLength: 32,
},
// operation list hash
Lo: {
prefix: Buffer.from([133, 233]),
byteLength: 32,
},
// operation list list hash
LLo: {
prefix: Buffer.from([29, 159, 109]),
byteLength: 32,
},
// protocol hash
P: {
prefix: Buffer.from([2, 170]),
byteLength: 32,
},
// context hash
Co: {
prefix: Buffer.from([79, 179]),
byteLength: 32,
},
/* 33 bytes long */
// secp256k1 public key
sppk: {
prefix: Buffer.from([3, 254, 226, 86]),
byteLength: 33,
},
// p256 public key
p2pk: {
prefix: Buffer.from([3, 178, 139, 127]),
byteLength: 33,
},
/* 56 bytes long */
// ed25519 encrypted seed
edesk: {
prefix: Buffer.from([7, 90, 60, 179, 41]),
byteLength: 56,
},
/* 63 bytes long */
// ed25519 secret key
edsk: {
prefix: Buffer.from([43, 246, 78, 7]),
byteLength: 64,
},
// ed25519 signature
edsig: {
prefix: Buffer.from([9, 245, 205, 134, 18]),
byteLength: 64,
},
// secp256k1 signature
spsig1: {
prefix: Buffer.from([13, 115, 101, 19, 63]),
byteLength: 64,
},
// p256_signature
p2sig: {
prefix: Buffer.from([54, 240, 44, 52]),
byteLength: 64,
},
// generic signature
sig: {
prefix: Buffer.from([4, 130, 43]),
byteLength: 64,
},
/* 15 bytes long */
// network hash
Net: {
prefix: Buffer.from([87, 82, 0]),
byteLength: 15,
},
// nonce hash
nce: {
prefix: Buffer.from([69, 220, 169]),
byteLength: 15,
},
/* 4 bytes long */
// chain id
id: {
prefix: Buffer.from([153, 103]),
byteLength: 4,
},
};
// From https://github.com/ecadlabs/taquito/blob/master/packages/taquito/src/constants.ts
var DEFAULT_GAS_LIMIT;
(function (DEFAULT_GAS_LIMIT) {
DEFAULT_GAS_LIMIT[DEFAULT_GAS_LIMIT["DELEGATION"] = 10600] = "DELEGATION";
DEFAULT_GAS_LIMIT[DEFAULT_GAS_LIMIT["ORIGINATION"] = 10600] = "ORIGINATION";
DEFAULT_GAS_LIMIT[DEFAULT_GAS_LIMIT["TRANSFER"] = 10600] = "TRANSFER";
DEFAULT_GAS_LIMIT[DEFAULT_GAS_LIMIT["REVEAL"] = 10600] = "REVEAL";
})(DEFAULT_GAS_LIMIT || (exports.DEFAULT_GAS_LIMIT = DEFAULT_GAS_LIMIT = {}));
var DEFAULT_FEE;
(function (DEFAULT_FEE) {
DEFAULT_FEE[DEFAULT_FEE["DELEGATION"] = 1257] = "DELEGATION";
DEFAULT_FEE[DEFAULT_FEE["ORIGINATION"] = 10000] = "ORIGINATION";
DEFAULT_FEE[DEFAULT_FEE["TRANSFER"] = 10000] = "TRANSFER";
DEFAULT_FEE[DEFAULT_FEE["REVEAL"] = 1420] = "REVEAL";
})(DEFAULT_FEE || (exports.DEFAULT_FEE = DEFAULT_FEE = {}));
var DEFAULT_STORAGE_LIMIT;
(function (DEFAULT_STORAGE_LIMIT) {
DEFAULT_STORAGE_LIMIT[DEFAULT_STORAGE_LIMIT["DELEGATION"] = 0] = "DELEGATION";
DEFAULT_STORAGE_LIMIT[DEFAULT_STORAGE_LIMIT["ORIGINATION"] = 257] = "ORIGINATION";
DEFAULT_STORAGE_LIMIT[DEFAULT_STORAGE_LIMIT["TRANSFER"] = 257] = "TRANSFER";
DEFAULT_STORAGE_LIMIT[DEFAULT_STORAGE_LIMIT["REVEAL"] = 0] = "REVEAL";
})(DEFAULT_STORAGE_LIMIT || (exports.DEFAULT_STORAGE_LIMIT = DEFAULT_STORAGE_LIMIT = {}));
var TRANSACTION_FEE;
(function (TRANSACTION_FEE) {
TRANSACTION_FEE[TRANSACTION_FEE["ORIGINATION"] = 47640] = "ORIGINATION";
TRANSACTION_FEE[TRANSACTION_FEE["TRANSFER"] = 47640] = "TRANSFER";
TRANSACTION_FEE[TRANSACTION_FEE["REVEAL"] = 1420] = "REVEAL";
})(TRANSACTION_FEE || (exports.TRANSACTION_FEE = TRANSACTION_FEE = {}));
var TRANSACTION_STORAGE_LIMIT;
(function (TRANSACTION_STORAGE_LIMIT) {
TRANSACTION_STORAGE_LIMIT[TRANSACTION_STORAGE_LIMIT["ORIGINATION"] = 3000] = "ORIGINATION";
TRANSACTION_STORAGE_LIMIT[TRANSACTION_STORAGE_LIMIT["TRANSFER"] = 300] = "TRANSFER";
TRANSACTION_STORAGE_LIMIT[TRANSACTION_STORAGE_LIMIT["REVEAL"] = 5] = "REVEAL";
})(TRANSACTION_STORAGE_LIMIT || (exports.TRANSACTION_STORAGE_LIMIT = TRANSACTION_STORAGE_LIMIT = {}));
var TRANSACTION_GAS_LIMIT;
(function (TRANSACTION_GAS_LIMIT) {
TRANSACTION_GAS_LIMIT[TRANSACTION_GAS_LIMIT["ORIGINATION"] = 4600] = "ORIGINATION";
TRANSACTION_GAS_LIMIT[TRANSACTION_GAS_LIMIT["TRANSFER"] = 6000] = "TRANSFER";
TRANSACTION_GAS_LIMIT[TRANSACTION_GAS_LIMIT["CONTRACT_TRANSFER"] = 20000] = "CONTRACT_TRANSFER";
TRANSACTION_GAS_LIMIT[TRANSACTION_GAS_LIMIT["REVEAL"] = 1500] = "REVEAL";
})(TRANSACTION_GAS_LIMIT || (exports.TRANSACTION_GAS_LIMIT = TRANSACTION_GAS_LIMIT = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW1CQSxvQ0FNQztBQVFELHdEQUtDO0FBU0QsZ0VBbUJDO0FBVUQsb0JBVUM7QUFXRCwwQ0FvQkM7QUFXRCxnREFhQztBQVNELGtDQWtCQztBQVFELHdDQUVDO0FBUUQsd0RBRUM7QUFRRCw0REFFQztBQVFELDRDQU9DO0FBUUQsNENBT0M7QUFRRCw4Q0FPQztBQVFELDRDQUVDO0FBUUQsd0RBRUM7QUFTRCxnQ0FFQztBQVNELDhCQU1DO0FBU0QsMENBTUM7QUFoVEQsOENBQTREO0FBQzVELDRDQUFpRDtBQUNqRCx1REFBeUM7QUFDekMsdURBQW9EO0FBQ3BELDRFQUF3QztBQUd4QyxtREFBNEQ7QUFFNUQsMENBQTBDO0FBQzdCLFFBQUEsaUJBQWlCLEdBQUcsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRXJEOzs7Ozs7R0FNRztBQUNILFNBQWdCLFlBQVksQ0FBQyxNQUFjLEVBQUUsT0FBZTtJQUMxRCxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3ZELENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDZCxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFOUIsT0FBTyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQy9CLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNJLEtBQUssVUFBVSxzQkFBc0IsQ0FBQyxrQkFBMEI7SUFDckUsTUFBTSw0QkFBTSxDQUFDLEtBQUssQ0FBQztJQUNuQixNQUFNLHdCQUF3QixHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3pGLE1BQU0sb0JBQW9CLEdBQUcsNEJBQU0sQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLEVBQUUsd0JBQXdCLENBQUMsQ0FBQztJQUNyRixPQUFPLFlBQVksQ0FBQyxpQkFBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLENBQUM7QUFDN0UsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNJLEtBQUssVUFBVSwwQkFBMEIsQ0FBQyxhQUFxQixFQUFFLEtBQWE7SUFDbkYsc0dBQXNHO0lBQ3RHLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsS0FBSyxDQUFDLGlCQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUU5RSxJQUFJLEVBQUUsR0FBYSxFQUFFLENBQUM7SUFDdEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNuQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2pCLENBQUM7SUFFRCxFQUFFLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQztRQUNiLENBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxJQUFJLEVBQUU7UUFDMUIsQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDLElBQUksRUFBRTtRQUMxQixDQUFDLEtBQUssR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQ3pCLEtBQUssR0FBRyxVQUFVO0tBQ25CLENBQUMsQ0FBQztJQUVILE1BQU0sNEJBQU0sQ0FBQyxLQUFLLENBQUM7SUFDbkIsTUFBTSxPQUFPLEdBQUcsNEJBQU0sQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLEVBQUUsSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNsRSxPQUFPLFlBQVksQ0FBQyxpQkFBUyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ2pFLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0ksS0FBSyxVQUFVLElBQUksQ0FDeEIsT0FBZ0IsRUFDaEIsSUFBWSxFQUNaLFlBQXdCLHlCQUFpQjtJQUV6QyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQzNCLE1BQU0sSUFBSSx1QkFBWSxDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLElBQUksdUJBQWMsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBSSxDQUFDLENBQUM7SUFDMUQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztBQUN0QyxDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSSxLQUFLLFVBQVUsZUFBZSxDQUNuQyxPQUFlLEVBQ2YsU0FBaUIsRUFDakIsU0FBaUIsRUFDakIsWUFBd0IseUJBQWlCO0lBRXpDLE1BQU0sWUFBWSxHQUFHLFNBQVMsQ0FBQyxTQUFTLEVBQUUsaUJBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUUsTUFBTSxHQUFHLEdBQUcscUJBQVMsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRTVELE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNuRSwyQ0FBMkM7SUFDM0MsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNyRixvQkFBb0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDcEMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7SUFFMUQsTUFBTSw0QkFBTSxDQUFDLEtBQUssQ0FBQztJQUNuQixNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUFNLENBQUMsa0JBQWtCLENBQUMsRUFBRSxFQUFFLG9CQUFvQixDQUFDLENBQUMsQ0FBQztJQUVuRixNQUFNLFlBQVksR0FBRyxlQUFlLENBQUMsU0FBUyxFQUFFLGlCQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0QsT0FBTyxxQkFBUyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsU0FBUyxFQUFFLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQWdCLGtCQUFrQixDQUNoQyxlQUF1QixFQUN2QixrQkFBMEIsRUFDMUIsTUFBYyxFQUNkLGVBQXVCO0lBRXZCLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO1FBQy9DLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLEdBQUcsZUFBZSxHQUFHLDhDQUE4QyxDQUFDLENBQUM7SUFDbEgsQ0FBQztJQUNELElBQUksQ0FBQyxjQUFjLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLEdBQUcsa0JBQWtCLENBQUMsQ0FBQztJQUN2RSxDQUFDO0lBQ0QsT0FBTyxJQUFBLHlDQUF5QixFQUFDLGVBQWUsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLEVBQUUsZUFBZSxDQUFDLENBQUM7QUFDakcsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLFdBQVcsQ0FBQyxJQUFZLEVBQUUsUUFBa0I7SUFDMUQsb0JBQW9CO0lBQ3BCLElBQUksV0FBVyxDQUFDO0lBQ2hCLElBQUksQ0FBQztRQUNILFdBQVcsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUVoRSxlQUFlO0lBQ2YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3JELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELGVBQWU7SUFDZixNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7SUFDMUQsT0FBTyxVQUFVLEtBQUssUUFBUSxDQUFDLFVBQVUsQ0FBQztBQUM1QyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixjQUFjLENBQUMsSUFBWTtJQUN6QyxPQUFPLHNCQUFzQixDQUFDLElBQUksQ0FBQyxJQUFJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsaUJBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN6RSxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixzQkFBc0IsQ0FBQyxJQUFZO0lBQ2pELE9BQU8sV0FBVyxDQUFDLElBQUksRUFBRSxpQkFBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsaUJBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxXQUFXLENBQUMsSUFBSSxFQUFFLGlCQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDbEgsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0Isd0JBQXdCLENBQUMsSUFBWTtJQUNuRCxPQUFPLFdBQVcsQ0FBQyxJQUFJLEVBQUUsaUJBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxJQUFZO0lBQzNDLE9BQU8sQ0FDTCxXQUFXLENBQUMsSUFBSSxFQUFFLGlCQUFTLENBQUMsS0FBSyxDQUFDO1FBQ2xDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsaUJBQVMsQ0FBQyxNQUFNLENBQUM7UUFDbkMsV0FBVyxDQUFDLElBQUksRUFBRSxpQkFBUyxDQUFDLEtBQUssQ0FBQztRQUNsQyxXQUFXLENBQUMsSUFBSSxFQUFFLGlCQUFTLENBQUMsR0FBRyxDQUFDLENBQ2pDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxTQUFpQjtJQUNoRCxPQUFPLENBQ0wsV0FBVyxDQUFDLFNBQVMsRUFBRSxpQkFBUyxDQUFDLElBQUksQ0FBQztRQUN0QyxXQUFXLENBQUMsU0FBUyxFQUFFLGlCQUFTLENBQUMsSUFBSSxDQUFDO1FBQ3RDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsaUJBQVMsQ0FBQyxJQUFJLENBQUM7UUFDdEMsSUFBQSxzQkFBVyxFQUFDLFNBQVMsQ0FBQyxDQUFDLHVCQUF1QjtLQUMvQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsVUFBa0I7SUFDbEQsT0FBTyxDQUNMLFdBQVcsQ0FBQyxVQUFVLEVBQUUsaUJBQVMsQ0FBQyxLQUFLLENBQUM7UUFDeEMsV0FBVyxDQUFDLFVBQVUsRUFBRSxpQkFBUyxDQUFDLElBQUksQ0FBQztRQUN2QyxXQUFXLENBQUMsVUFBVSxFQUFFLGlCQUFTLENBQUMsSUFBSSxDQUFDO1FBQ3ZDLFdBQVcsQ0FBQyxVQUFVLEVBQUUsaUJBQVMsQ0FBQyxJQUFJLENBQUMsQ0FDeEMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQWdCLGdCQUFnQixDQUFDLElBQVk7SUFDM0MsT0FBTyxXQUFXLENBQUMsSUFBSSxFQUFFLGlCQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEMsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBZ0Isc0JBQXNCLENBQUMsSUFBWTtJQUNqRCxPQUFPLFdBQVcsQ0FBQyxJQUFJLEVBQUUsaUJBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN4QyxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLElBQVksRUFBRSxRQUFrQjtJQUN6RCxPQUFPLFdBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7QUFDckMsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLFNBQVMsQ0FBQyxJQUFZLEVBQUUsUUFBa0I7SUFDeEQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUNoQyxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7SUFDN0MsQ0FBQztJQUNELE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUMsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDbEYsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQWdCLGVBQWUsQ0FBQyxTQUFpQixFQUFFLFFBQWtCO0lBQ25FLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBQ0QsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNqRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNsRixDQUFDO0FBRUQsbUNBQW1DO0FBQ25DLCtFQUErRTtBQUMvRSxnRkFBZ0Y7QUFDbkUsUUFBQSxTQUFTLEdBQUc7SUFDdkIsbUJBQW1CO0lBQ25CLDBCQUEwQjtJQUMxQixHQUFHLEVBQUU7UUFDSCxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDbEMsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELDRCQUE0QjtJQUM1QixHQUFHLEVBQUU7UUFDSCxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDbEMsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELHVCQUF1QjtJQUN2QixHQUFHLEVBQUU7UUFDSCxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDbEMsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELEVBQUUsRUFBRTtRQUNGLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNqQyxVQUFVLEVBQUUsRUFBRTtLQUNmO0lBQ0QsbUJBQW1CO0lBQ25CLHFCQUFxQjtJQUNyQixJQUFJLEVBQUU7UUFDSixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3RDLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCxxQkFBcUI7SUFDckIsS0FBSyxFQUFFO1FBQ0wsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNwQyxVQUFVLEVBQUUsRUFBRTtLQUNmO0lBQ0QsdUJBQXVCO0lBQ3ZCLElBQUksRUFBRTtRQUNKLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDeEMsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELGtCQUFrQjtJQUNsQixJQUFJLEVBQUU7UUFDSixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZDLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCxhQUFhO0lBQ2IsQ0FBQyxFQUFFO1FBQ0QsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDNUIsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELGlCQUFpQjtJQUNqQixDQUFDLEVBQUU7UUFDRCxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM3QixVQUFVLEVBQUUsRUFBRTtLQUNmO0lBQ0Qsc0JBQXNCO0lBQ3RCLEVBQUUsRUFBRTtRQUNGLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCwyQkFBMkI7SUFDM0IsR0FBRyxFQUFFO1FBQ0gsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ25DLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCxnQkFBZ0I7SUFDaEIsQ0FBQyxFQUFFO1FBQ0QsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDN0IsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELGVBQWU7SUFDZixFQUFFLEVBQUU7UUFDRixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM5QixVQUFVLEVBQUUsRUFBRTtLQUNmO0lBQ0QsbUJBQW1CO0lBQ25CLHVCQUF1QjtJQUN2QixJQUFJLEVBQUU7UUFDSixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3RDLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCxrQkFBa0I7SUFDbEIsSUFBSSxFQUFFO1FBQ0osTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN2QyxVQUFVLEVBQUUsRUFBRTtLQUNmO0lBQ0QsbUJBQW1CO0lBQ25CLHlCQUF5QjtJQUN6QixLQUFLLEVBQUU7UUFDTCxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN6QyxVQUFVLEVBQUUsRUFBRTtLQUNmO0lBQ0QsbUJBQW1CO0lBQ25CLHFCQUFxQjtJQUNyQixJQUFJLEVBQUU7UUFDSixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCxvQkFBb0I7SUFDcEIsS0FBSyxFQUFFO1FBQ0wsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDM0MsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELHNCQUFzQjtJQUN0QixNQUFNLEVBQUU7UUFDTixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMzQyxVQUFVLEVBQUUsRUFBRTtLQUNmO0lBQ0QsaUJBQWlCO0lBQ2pCLEtBQUssRUFBRTtRQUNMLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDdEMsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELG9CQUFvQjtJQUNwQixHQUFHLEVBQUU7UUFDSCxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakMsVUFBVSxFQUFFLEVBQUU7S0FDZjtJQUNELG1CQUFtQjtJQUNuQixlQUFlO0lBQ2YsR0FBRyxFQUFFO1FBQ0gsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2hDLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCxhQUFhO0lBQ2IsR0FBRyxFQUFFO1FBQ0gsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ25DLFVBQVUsRUFBRSxFQUFFO0tBQ2Y7SUFDRCxrQkFBa0I7SUFDbEIsV0FBVztJQUNYLEVBQUUsRUFBRTtRQUNGLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQy9CLFVBQVUsRUFBRSxDQUFDO0tBQ2Q7Q0FDRixDQUFDO0FBRUYseUZBQXlGO0FBRXpGLElBQVksaUJBS1g7QUFMRCxXQUFZLGlCQUFpQjtJQUMzQix5RUFBa0IsQ0FBQTtJQUNsQiwyRUFBbUIsQ0FBQTtJQUNuQixxRUFBZ0IsQ0FBQTtJQUNoQixpRUFBYyxDQUFBO0FBQ2hCLENBQUMsRUFMVyxpQkFBaUIsaUNBQWpCLGlCQUFpQixRQUs1QjtBQUVELElBQVksV0FLWDtBQUxELFdBQVksV0FBVztJQUNyQiw0REFBaUIsQ0FBQTtJQUNqQiwrREFBbUIsQ0FBQTtJQUNuQix5REFBZ0IsQ0FBQTtJQUNoQixvREFBYSxDQUFBO0FBQ2YsQ0FBQyxFQUxXLFdBQVcsMkJBQVgsV0FBVyxRQUt0QjtBQUVELElBQVkscUJBS1g7QUFMRCxXQUFZLHFCQUFxQjtJQUMvQiw2RUFBYyxDQUFBO0lBQ2QsaUZBQWlCLENBQUE7SUFDakIsMkVBQWMsQ0FBQTtJQUNkLHFFQUFVLENBQUE7QUFDWixDQUFDLEVBTFcscUJBQXFCLHFDQUFyQixxQkFBcUIsUUFLaEM7QUFFRCxJQUFZLGVBSVg7QUFKRCxXQUFZLGVBQWU7SUFDekIsdUVBQW1CLENBQUE7SUFDbkIsaUVBQWdCLENBQUE7SUFDaEIsNERBQWEsQ0FBQTtBQUNmLENBQUMsRUFKVyxlQUFlLCtCQUFmLGVBQWUsUUFJMUI7QUFFRCxJQUFZLHlCQUlYO0FBSkQsV0FBWSx5QkFBeUI7SUFDbkMsMEZBQWtCLENBQUE7SUFDbEIsbUZBQWMsQ0FBQTtJQUNkLDZFQUFVLENBQUE7QUFDWixDQUFDLEVBSlcseUJBQXlCLHlDQUF6Qix5QkFBeUIsUUFJcEM7QUFFRCxJQUFZLHFCQUtYO0FBTEQsV0FBWSxxQkFBcUI7SUFDL0Isa0ZBQWtCLENBQUE7SUFDbEIsNEVBQWUsQ0FBQTtJQUNmLCtGQUF5QixDQUFBO0lBQ3pCLHdFQUFhLENBQUE7QUFDZixDQUFDLEVBTFcscUJBQXFCLHFDQUFyQixxQkFBcUIsUUFLaEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc1ZhbGlkWHB1YiwgU2lnbmluZ0Vycm9yIH0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IEluTWVtb3J5U2lnbmVyIH0gZnJvbSAnQHRhcXVpdG8vc2lnbmVyJztcbmltcG9ydCAqIGFzIGJhc2U1OGNoZWNrIGZyb20gJ2JzNThjaGVjayc7XG5pbXBvcnQgeyBzZWNwMjU2azEgfSBmcm9tICdAbm9ibGUvY3VydmVzL3NlY3AyNTZrMSc7XG5pbXBvcnQgc29kaXVtIGZyb20gJ2xpYnNvZGl1bS13cmFwcGVycyc7XG5pbXBvcnQgeyBIYXNoVHlwZSwgU2lnblJlc3BvbnNlIH0gZnJvbSAnLi9pZmFjZSc7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmltcG9ydCB7IGdlbmVyaWNNdWx0aXNpZ0RhdGFUb1NpZ24gfSBmcm9tICcuL211bHRpc2lnVXRpbHMnO1xuXG4vLyBCeSBkZWZhdWx0LCB1c2UgdGhlIHRyYW5zYWN0aW9ucyBwcmVmaXhcbmV4cG9ydCBjb25zdCBERUZBVUxUX1dBVEVSTUFSSyA9IG5ldyBVaW50OEFycmF5KFszXSk7XG5cbi8qKlxuICogRW5jb2RlIHRoZSBwYXlsb2FkIHRvIGJhc2U1OCB3aXRoIGEgc3BlY2lmaWMgVGV6b3MgcHJlZml4LlxuICpcbiAqIEBwYXJhbSB7QnVmZmVyfSBwcmVmaXggdG8gYWRkIHRvIHRoZSBlbmNvZGVkIHBheWxvYWRcbiAqIEBwYXJhbSB7QnVmZmVyfSBwYXlsb2FkIHRvIGVuY29kZVxuICogQHJldHVybnMge2FueX0gYmFzZTU4IHBheWxvYWQgd2l0aCBhIFRlem9zIHByZWZpeFxuICovXG5leHBvcnQgZnVuY3Rpb24gYmFzZTU4ZW5jb2RlKHByZWZpeDogQnVmZmVyLCBwYXlsb2FkOiBCdWZmZXIpOiBzdHJpbmcge1xuICBjb25zdCBuID0gQnVmZmVyLmFsbG9jKHByZWZpeC5sZW5ndGggKyBwYXlsb2FkLmxlbmd0aCk7XG4gIG4uc2V0KHByZWZpeCk7XG4gIG4uc2V0KHBheWxvYWQsIHByZWZpeC5sZW5ndGgpO1xuXG4gIHJldHVybiBiYXNlNThjaGVjay5lbmNvZGUobik7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlIHRoZSB0cmFuc2FjdGlvbiBpZCBmb3IgYSBmb3IgYSBzaWduZWQgdHJhbnNhY3Rpb24uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGVuY29kZWRUcmFuc2FjdGlvbiBTaWduZWQgdHJhbnNhY3Rpb24gaW4gaGV4YWRlY2ltYWxcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFRoZSB0cmFuc2FjdGlvbiBpZFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2FsY3VsYXRlVHJhbnNhY3Rpb25JZChlbmNvZGVkVHJhbnNhY3Rpb246IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGF3YWl0IHNvZGl1bS5yZWFkeTtcbiAgY29uc3QgZW5jb2RlZFRyYW5zYWN0aW9uQnVmZmVyID0gVWludDhBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKGVuY29kZWRUcmFuc2FjdGlvbiwgJ2hleCcpKTtcbiAgY29uc3Qgb3BlcmF0aW9uSGFzaFBheWxvYWQgPSBzb2RpdW0uY3J5cHRvX2dlbmVyaWNoYXNoKDMyLCBlbmNvZGVkVHJhbnNhY3Rpb25CdWZmZXIpO1xuICByZXR1cm4gYmFzZTU4ZW5jb2RlKGhhc2hUeXBlcy5vLnByZWZpeCwgQnVmZmVyLmZyb20ob3BlcmF0aW9uSGFzaFBheWxvYWQpKTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGUgdGhlIGFkZHJlc3Mgb2YgYSBuZXcgb3JpZ2luYXRlZCBhY2NvdW50LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0cmFuc2FjdGlvbklkIFRoZSB0cmFuc2FjdGlvbiBpZFxuICogQHBhcmFtIHtudW1iZXJ9IGluZGV4IFRoZSBpbmRleCBvZiB0aGUgb3JpZ2luYXRpb24gb3BlcmF0aW9uIGluc2lkZSB0aGUgdHJhbnNhY3Rpb24gKHN0YXJ0cyBhdCAwKVxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gQW4gb3JpZ2luYXRlZCBhZGRyZXNzIHdpdGggdGhlIEtUIHByZWZpeFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2FsY3VsYXRlT3JpZ2luYXRlZEFkZHJlc3ModHJhbnNhY3Rpb25JZDogc3RyaW5nLCBpbmRleDogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgLy8gRnJvbSBodHRwczovL2dpdGh1Yi5jb20vVGV6VGVjaC9lenR6L2Jsb2IvY2ZkYzRmY2ZjODkxZjRmNGYwNzdjMzA1NmY0MTQ0NzZkZGUzNjEwYi9zcmMvbWFpbi5qcyNMNzY4XG4gIGNvbnN0IG9iID0gYmFzZTU4Y2hlY2suZGVjb2RlKHRyYW5zYWN0aW9uSWQpLnNsaWNlKGhhc2hUeXBlcy5vLnByZWZpeC5sZW5ndGgpO1xuXG4gIGxldCB0dDogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBvYi5sZW5ndGg7IGkrKykge1xuICAgIHR0LnB1c2gob2JbaV0pO1xuICB9XG5cbiAgdHQgPSB0dC5jb25jYXQoW1xuICAgIChpbmRleCAmIDB4ZmYwMDAwMDApID4+IDI0LFxuICAgIChpbmRleCAmIDB4MDBmZjAwMDApID4+IDE2LFxuICAgIChpbmRleCAmIDB4MDAwMGZmMDApID4+IDgsXG4gICAgaW5kZXggJiAweDAwMDAwMGZmLFxuICBdKTtcblxuICBhd2FpdCBzb2RpdW0ucmVhZHk7XG4gIGNvbnN0IHBheWxvYWQgPSBzb2RpdW0uY3J5cHRvX2dlbmVyaWNoYXNoKDIwLCBuZXcgVWludDhBcnJheSh0dCkpO1xuICByZXR1cm4gYmFzZTU4ZW5jb2RlKGhhc2hUeXBlcy5LVC5wcmVmaXgsIEJ1ZmZlci5mcm9tKHBheWxvYWQpKTtcbn1cblxuLyoqXG4gKiBHZW5lcmljIGRhdGEgc2lnbmluZyB1c2luZyBUZXpvcyBsaWJyYXJ5LlxuICpcbiAqIEBwYXJhbSB7S2V5UGFpcn0ga2V5UGFpciBBIEtleSBQYWlyIHdpdGggYSBwcml2YXRlIGtleSBzZXRcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIFRoZSBkYXRhIGluIGhleGFkZWNpbWFsIHRvIHNpZ25cbiAqIEBwYXJhbSB7VWludDhBcnJheX0gd2F0ZXJtYXJrIE1hZ2ljIGJ5dGU6IDEgZm9yIGJsb2NrLCAyIGZvciBlbmRvcnNlbWVudCwgMyBmb3IgZ2VuZXJpY1xuICogQHJldHVybnMge1Byb21pc2U8U2lnblJlc3BvbnNlPn1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNpZ24oXG4gIGtleVBhaXI6IEtleVBhaXIsXG4gIGRhdGE6IHN0cmluZyxcbiAgd2F0ZXJtYXJrOiBVaW50OEFycmF5ID0gREVGQVVMVF9XQVRFUk1BUktcbik6IFByb21pc2U8U2lnblJlc3BvbnNlPiB7XG4gIGlmICgha2V5UGFpci5nZXRLZXlzKCkucHJ2KSB7XG4gICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignTWlzc2luZyBwcml2YXRlIGtleScpO1xuICB9XG4gIGNvbnN0IHNpZ25lciA9IG5ldyBJbk1lbW9yeVNpZ25lcihrZXlQYWlyLmdldEtleXMoKS5wcnYhKTtcbiAgcmV0dXJuIHNpZ25lci5zaWduKGRhdGEsIHdhdGVybWFyayk7XG59XG5cbi8qKlxuICogVmVyaWZpZXMgdGhlIHNpZ25hdHVyZSBwcm9kdWNlZCBmb3IgYSBnaXZlbiBtZXNzYWdlIGJlbG9uZ3MgdG8gYSBzZWNwMjU2azEgcHVibGljIGtleS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSBNZXNzYWdlIGluIGhleCBmb3JtYXQgdG8gdmVyaWZ5XG4gKiBAcGFyYW0ge3N0cmluZ30gcHVibGljS2V5IHNlY3AyNTZrMSBwdWJsaWMga2V5IHdpdGggXCJzcHBrXCIgcHJlZml4IHRvIHZlcmlmeSB0aGUgc2lnbmF0dXJlIHdpdGhcbiAqIEBwYXJhbSB7c3RyaW5nfSBzaWduYXR1cmUgVGV6b3Mgc2lnbmF0dXJlIHdpdGggXCJzaWdcIiBwcmVmaXhcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gd2F0ZXJtYXJrIE9wdGlvbmFsIHdhdGVybWFyayB1c2VkIHRvIGdlbmVyYXRlIHRoZSBzaWduYXR1cmVcbiAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5U2lnbmF0dXJlKFxuICBtZXNzYWdlOiBzdHJpbmcsXG4gIHB1YmxpY0tleTogc3RyaW5nLFxuICBzaWduYXR1cmU6IHN0cmluZyxcbiAgd2F0ZXJtYXJrOiBVaW50OEFycmF5ID0gREVGQVVMVF9XQVRFUk1BUktcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCByYXdQdWJsaWNLZXkgPSBkZWNvZGVLZXkocHVibGljS2V5LCBoYXNoVHlwZXMuc3BwaykudG9TdHJpbmcoJ2hleCcpO1xuICBjb25zdCBrZXkgPSBzZWNwMjU2azEuUHJvamVjdGl2ZVBvaW50LmZyb21IZXgocmF3UHVibGljS2V5KTtcblxuICBjb25zdCBtZXNzYWdlQnVmZmVyID0gVWludDhBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKG1lc3NhZ2UsICdoZXgnKSk7XG4gIC8vIFRlem9zIHNpZ25hdHVyZXMgYWx3YXlzIGhhdmUgYSB3YXRlcm1hcmtcbiAgY29uc3QgbWVzc2FnZVdpdGhXYXRlcm1hcmsgPSBuZXcgVWludDhBcnJheSh3YXRlcm1hcmsubGVuZ3RoICsgbWVzc2FnZUJ1ZmZlci5sZW5ndGgpO1xuICBtZXNzYWdlV2l0aFdhdGVybWFyay5zZXQod2F0ZXJtYXJrKTtcbiAgbWVzc2FnZVdpdGhXYXRlcm1hcmsuc2V0KG1lc3NhZ2VCdWZmZXIsIHdhdGVybWFyay5sZW5ndGgpO1xuXG4gIGF3YWl0IHNvZGl1bS5yZWFkeTtcbiAgY29uc3QgYnl0ZXNIYXNoID0gQnVmZmVyLmZyb20oc29kaXVtLmNyeXB0b19nZW5lcmljaGFzaCgzMiwgbWVzc2FnZVdpdGhXYXRlcm1hcmspKTtcblxuICBjb25zdCByYXdTaWduYXR1cmUgPSBkZWNvZGVTaWduYXR1cmUoc2lnbmF0dXJlLCBoYXNoVHlwZXMuc2lnKTtcbiAgcmV0dXJuIHNlY3AyNTZrMS52ZXJpZnkocmF3U2lnbmF0dXJlLCBieXRlc0hhc2gsIGtleS50b0hleCgpKTtcbn1cblxuLyoqXG4gKiBVc2VmdWwgd3JhcHBlciB0byBjcmVhdGUgdGhlIGdlbmVyaWMgbXVsdGlzaWcgY29udHJhY3QgZGF0YSB0byBzaWduIHdoZW4gbW92aW5nIGZ1bmRzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250cmFjdEFkZHJlc3MgVGhlIHdhbGxldCBjb250cmFjdCBhZGRyZXNzIHdpdGggdGhlIGZ1bmRzIHRvIHdpdGhkcmF3XG4gKiBAcGFyYW0ge3N0cmluZ30gZGVzdGluYXRpb25BZGRyZXNzIFRoZSBhZGRyZXNzIHRvIHRyYW5zZmVyIHRoZSBmdW5kcyB0b1xuICogQHBhcmFtIHtudW1iZXJ9IGFtb3VudCBOdW1iZXIgbXV0ZXogdG8gdHJhbnNmZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBjb250cmFjdENvdW50ZXIgV2FsbGV0IGNvdW50ZXIgdG8gdXNlIGluIHRoZSB0cmFuc2FjdGlvblxuICogQHJldHVybnMge2FueX0gQSBKU09OIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBNaWNoZWxzb24gc2NyaXB0IHRvIHNpZ24gYW5kIGFwcHJvdmUgYSB0cmFuc2ZlclxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVEYXRhVG9TaWduKFxuICBjb250cmFjdEFkZHJlc3M6IHN0cmluZyxcbiAgZGVzdGluYXRpb25BZGRyZXNzOiBzdHJpbmcsXG4gIGFtb3VudDogc3RyaW5nLFxuICBjb250cmFjdENvdW50ZXI6IHN0cmluZ1xuKTogYW55IHtcbiAgaWYgKCFpc1ZhbGlkT3JpZ2luYXRlZEFkZHJlc3MoY29udHJhY3RBZGRyZXNzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb250cmFjdCBhZGRyZXNzICcgKyBjb250cmFjdEFkZHJlc3MgKyAnLiBBbiBvcmlnaW5hdGVkIGFjY291bnQgYWRkcmVzcyB3YXMgZXhwZWN0ZWQnKTtcbiAgfVxuICBpZiAoIWlzVmFsaWRBZGRyZXNzKGRlc3RpbmF0aW9uQWRkcmVzcykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZGVzdGluYXRpb24gYWRkcmVzcyAnICsgZGVzdGluYXRpb25BZGRyZXNzKTtcbiAgfVxuICByZXR1cm4gZ2VuZXJpY011bHRpc2lnRGF0YVRvU2lnbihjb250cmFjdEFkZHJlc3MsIGRlc3RpbmF0aW9uQWRkcmVzcywgYW1vdW50LCBjb250cmFjdENvdW50ZXIpO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIFRlem9zIGhhc2ggb2YgdGhlIGdpdmVuIHR5cGVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaGFzaCAtIHRoZSBzdHJpbmcgdG8gdmFsaWRhdGVcbiAqIEBwYXJhbSB7SGFzaFR5cGV9IGhhc2hUeXBlIC0gdGhlIHR5cGUgb2YgdGhlIHByb3ZpZGVkIGhhc2hcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEhhc2goaGFzaDogc3RyaW5nLCBoYXNoVHlwZTogSGFzaFR5cGUpOiBib29sZWFuIHtcbiAgLy8gVmFsaWRhdGUgZW5jb2RpbmdcbiAgbGV0IGRlY29kZWRIYXNoO1xuICB0cnkge1xuICAgIGRlY29kZWRIYXNoID0gYmFzZTU4Y2hlY2suZGVjb2RlKGhhc2gpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGhhc2hQcmVmaXggPSBkZWNvZGVkSGFzaC5zbGljZSgwLCBoYXNoVHlwZS5wcmVmaXgubGVuZ3RoKTtcblxuICAvLyBDaGVjayBwcmVmaXhcbiAgaWYgKCFoYXNoUHJlZml4LmVxdWFscyhCdWZmZXIuZnJvbShoYXNoVHlwZS5wcmVmaXgpKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8vIENoZWNrIGxlbmd0aFxuICBjb25zdCBoYXNoTGVuZ3RoID0gZGVjb2RlZEhhc2gubGVuZ3RoIC0gaGFzaFByZWZpeC5sZW5ndGg7XG4gIHJldHVybiBoYXNoTGVuZ3RoID09PSBoYXNoVHlwZS5ieXRlTGVuZ3RoO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIFRlem9zIGFkZHJlc3NcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaGFzaCAtIHRoZSBhZGRyZXNzIHRvIHZhbGlkYXRlXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRBZGRyZXNzKGhhc2g6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNWYWxpZEltcGxpY2l0QWRkcmVzcyhoYXNoKSB8fCBpc1ZhbGlkSGFzaChoYXNoLCBoYXNoVHlwZXMuS1QpO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIFRlem9zIGltcGxpY2l0IGFjY291bnQgYWRkcmVzc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoIC0gdGhlIGFkZHJlc3MgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEltcGxpY2l0QWRkcmVzcyhoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIGlzVmFsaWRIYXNoKGhhc2gsIGhhc2hUeXBlcy50ejEpIHx8IGlzVmFsaWRIYXNoKGhhc2gsIGhhc2hUeXBlcy50ejIpIHx8IGlzVmFsaWRIYXNoKGhhc2gsIGhhc2hUeXBlcy50ejMpO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIFRlem9zIG9yaWdpbmF0ZWQgYWNjb3VudCBhZGRyZXNzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggLSB0aGUgYWRkcmVzcyB0byB2YWxpZGF0ZVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkT3JpZ2luYXRlZEFkZHJlc3MoaGFzaDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBpc1ZhbGlkSGFzaChoYXNoLCBoYXNoVHlwZXMuS1QpO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIFRlem9zIHNpZ25hdHVyZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoIC0gdGhlIHNpZ25hdHVyZSB0byB2YWxpZGF0ZVxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkU2lnbmF0dXJlKGhhc2g6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gKFxuICAgIGlzVmFsaWRIYXNoKGhhc2gsIGhhc2hUeXBlcy5lZHNpZykgfHxcbiAgICBpc1ZhbGlkSGFzaChoYXNoLCBoYXNoVHlwZXMuc3BzaWcxKSB8fFxuICAgIGlzVmFsaWRIYXNoKGhhc2gsIGhhc2hUeXBlcy5wMnNpZykgfHxcbiAgICBpc1ZhbGlkSGFzaChoYXNoLCBoYXNoVHlwZXMuc2lnKVxuICApO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIFRlem9zIHB1YmxpYyBrZXlcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHVibGljS2V5IFRoZSBwdWJsaWMga2V5IHRvIHZhbGlkYXRlXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRQdWJsaWNLZXkocHVibGljS2V5OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBpc1ZhbGlkSGFzaChwdWJsaWNLZXksIGhhc2hUeXBlcy5zcHBrKSB8fFxuICAgIGlzVmFsaWRIYXNoKHB1YmxpY0tleSwgaGFzaFR5cGVzLnAycGspIHx8XG4gICAgaXNWYWxpZEhhc2gocHVibGljS2V5LCBoYXNoVHlwZXMuZWRwaykgfHxcbiAgICBpc1ZhbGlkWHB1YihwdWJsaWNLZXkpIC8vIHhwdWJzIGFyZSB2YWxpZCB0b28uXG4gICk7XG59XG5cbi8qKlxuICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgc3RyaW5nIGlzIGEgdmFsaWQgVGV6b3MgcHJpdmF0ZSBrZXlcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJpdmF0ZUtleSBUaGUgcHJpdmF0ZSBrZXkgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFByaXZhdGVLZXkocHJpdmF0ZUtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgaXNWYWxpZEhhc2gocHJpdmF0ZUtleSwgaGFzaFR5cGVzLmVkZXNrKSB8fFxuICAgIGlzVmFsaWRIYXNoKHByaXZhdGVLZXksIGhhc2hUeXBlcy5lZHNrKSB8fFxuICAgIGlzVmFsaWRIYXNoKHByaXZhdGVLZXksIGhhc2hUeXBlcy5zcHNrKSB8fFxuICAgIGlzVmFsaWRIYXNoKHByaXZhdGVLZXksIGhhc2hUeXBlcy5wMnNrKVxuICApO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIHN0cmluZyBpcyBhIHZhbGlkIFRlem9zIGJsb2NrIGhhc2hcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaGFzaCAtIHRoZSBhZGRyZXNzIHRvIHZhbGlkYXRlXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRCbG9ja0hhc2goaGFzaDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBpc1ZhbGlkSGFzaChoYXNoLCBoYXNoVHlwZXMuYik7XG59XG5cbi8qKlxuICogUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgc3RyaW5nIGlzIGEgdmFsaWQgVGV6b3MgdHJhbnNhY3Rpb24gaGFzaFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoIC0gdGhlIGFkZHJlc3MgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZFRyYW5zYWN0aW9uSGFzaChoYXNoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIGlzVmFsaWRIYXNoKGhhc2gsIGhhc2hUeXBlcy5vKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHdoZXRoZXIgb3Igbm90IHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBUZXpvcyBrZXkgZ2l2ZW4gYSBwcmVmaXhcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaGFzaCAtIHRoZSBrZXkgdG8gdmFsaWRhdGVcbiAqIEBwYXJhbSB7SGFzaFR5cGV9IGhhc2hUeXBlIC0gdGhlIHR5cGUgb2YgdGhlIHByb3ZpZGVkIGhhc2hcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEtleShoYXNoOiBzdHJpbmcsIGhhc2hUeXBlOiBIYXNoVHlwZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gaXNWYWxpZEhhc2goaGFzaCwgaGFzaFR5cGUpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgb3JpZ2luYWwga2V5IGZvcm0gdGhlIHRleHQgd2l0aG91dCB0aGUgZ2l2ZW4gcHJlZml4LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBoYXNoIC0gYmFzZTU4IGVuY29kZWQga2V5IHdpdGggYSBUZXpvcyBwcmVmaXhcbiAqIEBwYXJhbSB7SGFzaFR5cGV9IGhhc2hUeXBlIC0gdGhlIHR5cGUgb2YgdGhlIHByb3ZpZGVkIGhhc2hcbiAqIEByZXR1cm5zIHtCdWZmZXJ9IHRoZSBvcmlnaW5hbCBkZWNvZGVkIGtleVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlS2V5KGhhc2g6IHN0cmluZywgaGFzaFR5cGU6IEhhc2hUeXBlKTogQnVmZmVyIHtcbiAgaWYgKCFpc1ZhbGlkS2V5KGhhc2gsIGhhc2hUeXBlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignVW5zdXBwb3J0ZWQgcHJpdmF0ZSBrZXknKTtcbiAgfVxuICBjb25zdCBkZWNvZGVkUHJ2ID0gYmFzZTU4Y2hlY2suZGVjb2RlKGhhc2gpO1xuICByZXR1cm4gQnVmZmVyLmZyb20oZGVjb2RlZFBydi5zbGljZShoYXNoVHlwZS5wcmVmaXgubGVuZ3RoLCBkZWNvZGVkUHJ2Lmxlbmd0aCkpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgcmF3IHNpZ25hdHVyZSBmcm9tIGEgVGV6b3MgZW5jb2RlZCBvbmUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHNpZ25hdHVyZSBUZXpvcyBzaWduYXR1cmVzIHByZWZpeGVkIHdpdGggc2lnLCBlZHNpZywgcDJzaWcgb3Igc3BzaWdcbiAqIEBwYXJhbSB7SGFzaFR5cGV9IGhhc2hUeXBlIFRoZSBwcmVmaXggb2YgcmVtb3ZlXG4gKiBAcmV0dXJucyB7QnVmZmVyfSBUaGUgZGVjb2RlZCBzaWduYXR1cmUgd2l0aG91dCBwcmVmaXhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVNpZ25hdHVyZShzaWduYXR1cmU6IHN0cmluZywgaGFzaFR5cGU6IEhhc2hUeXBlKTogQnVmZmVyIHtcbiAgaWYgKCFpc1ZhbGlkU2lnbmF0dXJlKHNpZ25hdHVyZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIHNpZ25hdHVyZScpO1xuICB9XG4gIGNvbnN0IGRlY29kZWRQcnYgPSBiYXNlNThjaGVjay5kZWNvZGUoc2lnbmF0dXJlKTtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRlY29kZWRQcnYuc2xpY2UoaGFzaFR5cGUucHJlZml4Lmxlbmd0aCwgZGVjb2RlZFBydi5sZW5ndGgpKTtcbn1cblxuLy8gQmFzZTU4Q2hlY2sgaXMgdXNlZCBmb3IgZW5jb2Rpbmdcbi8vIGhhc2hlZFR5cGVzIGlzIHVzZWQgdG8gdmFsaWRhdGUgaGFzaGVzIGJ5IHR5cGUsIGJ5IGNoZWNraW5nIHRoZWlyIHByZWZpeCBhbmRcbi8vIHRoZSBsZW5ndGggb2YgdGhlIEJ1ZmZlciBvYnRhaW5lZCBieSBkZWNvZGluZyB0aGUgaGFzaCAoZXhjbHVkaW5nIHRoZSBwcmVmaXgpXG5leHBvcnQgY29uc3QgaGFzaFR5cGVzID0ge1xuICAvKiAyMCBieXRlcyBsb25nICovXG4gIC8vIGVkMjU1MTkgcHVibGljIGtleSBoYXNoXG4gIHR6MToge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzYsIDE2MSwgMTU5XSksXG4gICAgYnl0ZUxlbmd0aDogMjAsXG4gIH0sXG4gIC8vIHNlY3AyNTZrMSBwdWJsaWMga2V5IGhhc2hcbiAgdHoyOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbNiwgMTYxLCAxNjFdKSxcbiAgICBieXRlTGVuZ3RoOiAyMCxcbiAgfSxcbiAgLy8gcDI1NiBwdWJsaWMga2V5IGhhc2hcbiAgdHozOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbNiwgMTYxLCAxNjRdKSxcbiAgICBieXRlTGVuZ3RoOiAyMCxcbiAgfSxcbiAgS1Q6IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFsyLCA5MCwgMTIxXSksXG4gICAgYnl0ZUxlbmd0aDogMjAsXG4gIH0sXG4gIC8qIDMyIGJ5dGVzIGxvbmcgKi9cbiAgLy8gZWQyNTUxOSBwdWJsaWMga2V5XG4gIGVkcGs6IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFsxMywgMTUsIDM3LCAyMTddKSxcbiAgICBieXRlTGVuZ3RoOiAzMixcbiAgfSxcbiAgLy8gZWQyNTUxOSBzZWNyZXQga2V5XG4gIGVkc2syOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbMTMsIDE1LCA1OCwgN10pLFxuICAgIGJ5dGVMZW5ndGg6IDMyLFxuICB9LFxuICAvLyBzZWNwMjU2azEgc2VjcmV0IGtleVxuICBzcHNrOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbMTcsIDE2MiwgMjI0LCAyMDFdKSxcbiAgICBieXRlTGVuZ3RoOiAzMixcbiAgfSxcbiAgLy8gcDI1NiBzZWNyZXQga2V5XG4gIHAyc2s6IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFsxNiwgODEsIDIzOCwgMTg5XSksXG4gICAgYnl0ZUxlbmd0aDogMzIsXG4gIH0sXG4gIC8vIGJsb2NrIGhhc2hcbiAgYjoge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzEsIDUyXSksXG4gICAgYnl0ZUxlbmd0aDogMzIsXG4gIH0sXG4gIC8vIG9wZXJhdGlvbiBoYXNoXG4gIG86IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFs1LCAxMTZdKSxcbiAgICBieXRlTGVuZ3RoOiAzMixcbiAgfSxcbiAgLy8gb3BlcmF0aW9uIGxpc3QgaGFzaFxuICBMbzoge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzEzMywgMjMzXSksXG4gICAgYnl0ZUxlbmd0aDogMzIsXG4gIH0sXG4gIC8vIG9wZXJhdGlvbiBsaXN0IGxpc3QgaGFzaFxuICBMTG86IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFsyOSwgMTU5LCAxMDldKSxcbiAgICBieXRlTGVuZ3RoOiAzMixcbiAgfSxcbiAgLy8gcHJvdG9jb2wgaGFzaFxuICBQOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbMiwgMTcwXSksXG4gICAgYnl0ZUxlbmd0aDogMzIsXG4gIH0sXG4gIC8vIGNvbnRleHQgaGFzaFxuICBDbzoge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzc5LCAxNzldKSxcbiAgICBieXRlTGVuZ3RoOiAzMixcbiAgfSxcbiAgLyogMzMgYnl0ZXMgbG9uZyAqL1xuICAvLyBzZWNwMjU2azEgcHVibGljIGtleVxuICBzcHBrOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbMywgMjU0LCAyMjYsIDg2XSksXG4gICAgYnl0ZUxlbmd0aDogMzMsXG4gIH0sXG4gIC8vIHAyNTYgcHVibGljIGtleVxuICBwMnBrOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbMywgMTc4LCAxMzksIDEyN10pLFxuICAgIGJ5dGVMZW5ndGg6IDMzLFxuICB9LFxuICAvKiA1NiBieXRlcyBsb25nICovXG4gIC8vIGVkMjU1MTkgZW5jcnlwdGVkIHNlZWRcbiAgZWRlc2s6IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFs3LCA5MCwgNjAsIDE3OSwgNDFdKSxcbiAgICBieXRlTGVuZ3RoOiA1NixcbiAgfSxcbiAgLyogNjMgYnl0ZXMgbG9uZyAqL1xuICAvLyBlZDI1NTE5IHNlY3JldCBrZXlcbiAgZWRzazoge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzQzLCAyNDYsIDc4LCA3XSksXG4gICAgYnl0ZUxlbmd0aDogNjQsXG4gIH0sXG4gIC8vIGVkMjU1MTkgc2lnbmF0dXJlXG4gIGVkc2lnOiB7XG4gICAgcHJlZml4OiBCdWZmZXIuZnJvbShbOSwgMjQ1LCAyMDUsIDEzNCwgMThdKSxcbiAgICBieXRlTGVuZ3RoOiA2NCxcbiAgfSxcbiAgLy8gc2VjcDI1NmsxIHNpZ25hdHVyZVxuICBzcHNpZzE6IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFsxMywgMTE1LCAxMDEsIDE5LCA2M10pLFxuICAgIGJ5dGVMZW5ndGg6IDY0LFxuICB9LFxuICAvLyBwMjU2X3NpZ25hdHVyZVxuICBwMnNpZzoge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzU0LCAyNDAsIDQ0LCA1Ml0pLFxuICAgIGJ5dGVMZW5ndGg6IDY0LFxuICB9LFxuICAvLyBnZW5lcmljIHNpZ25hdHVyZVxuICBzaWc6IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFs0LCAxMzAsIDQzXSksXG4gICAgYnl0ZUxlbmd0aDogNjQsXG4gIH0sXG4gIC8qIDE1IGJ5dGVzIGxvbmcgKi9cbiAgLy8gbmV0d29yayBoYXNoXG4gIE5ldDoge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzg3LCA4MiwgMF0pLFxuICAgIGJ5dGVMZW5ndGg6IDE1LFxuICB9LFxuICAvLyBub25jZSBoYXNoXG4gIG5jZToge1xuICAgIHByZWZpeDogQnVmZmVyLmZyb20oWzY5LCAyMjAsIDE2OV0pLFxuICAgIGJ5dGVMZW5ndGg6IDE1LFxuICB9LFxuICAvKiA0IGJ5dGVzIGxvbmcgKi9cbiAgLy8gY2hhaW4gaWRcbiAgaWQ6IHtcbiAgICBwcmVmaXg6IEJ1ZmZlci5mcm9tKFsxNTMsIDEwM10pLFxuICAgIGJ5dGVMZW5ndGg6IDQsXG4gIH0sXG59O1xuXG4vLyBGcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9lY2FkbGFicy90YXF1aXRvL2Jsb2IvbWFzdGVyL3BhY2thZ2VzL3RhcXVpdG8vc3JjL2NvbnN0YW50cy50c1xuXG5leHBvcnQgZW51bSBERUZBVUxUX0dBU19MSU1JVCB7XG4gIERFTEVHQVRJT04gPSAxMDYwMCxcbiAgT1JJR0lOQVRJT04gPSAxMDYwMCxcbiAgVFJBTlNGRVIgPSAxMDYwMCxcbiAgUkVWRUFMID0gMTA2MDAsXG59XG5cbmV4cG9ydCBlbnVtIERFRkFVTFRfRkVFIHtcbiAgREVMRUdBVElPTiA9IDEyNTcsXG4gIE9SSUdJTkFUSU9OID0gMTAwMDAsXG4gIFRSQU5TRkVSID0gMTAwMDAsXG4gIFJFVkVBTCA9IDE0MjAsXG59XG5cbmV4cG9ydCBlbnVtIERFRkFVTFRfU1RPUkFHRV9MSU1JVCB7XG4gIERFTEVHQVRJT04gPSAwLFxuICBPUklHSU5BVElPTiA9IDI1NyxcbiAgVFJBTlNGRVIgPSAyNTcsXG4gIFJFVkVBTCA9IDAsXG59XG5cbmV4cG9ydCBlbnVtIFRSQU5TQUNUSU9OX0ZFRSB7XG4gIE9SSUdJTkFUSU9OID0gNDc2NDAsXG4gIFRSQU5TRkVSID0gNDc2NDAsXG4gIFJFVkVBTCA9IDE0MjAsXG59XG5cbmV4cG9ydCBlbnVtIFRSQU5TQUNUSU9OX1NUT1JBR0VfTElNSVQge1xuICBPUklHSU5BVElPTiA9IDMwMDAsXG4gIFRSQU5TRkVSID0gMzAwLFxuICBSRVZFQUwgPSA1LFxufVxuXG5leHBvcnQgZW51bSBUUkFOU0FDVElPTl9HQVNfTElNSVQge1xuICBPUklHSU5BVElPTiA9IDQ2MDAsXG4gIFRSQU5TRkVSID0gNjAwMCxcbiAgQ09OVFJBQ1RfVFJBTlNGRVIgPSAyMDAwMCxcbiAgUkVWRUFMID0gMTUwMCxcbn1cbiJdfQ==Выполнить команду
Для локальной разработки. Не используйте в интернете!