PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-icp/dist/src
Просмотр файла: icp.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.Icp = void 0;
const assert_1 = __importDefault(require("assert"));
const sdk_core_1 = require("@bitgo/sdk-core");
const statics_1 = require("@bitgo/statics");
const principal_1 = require("@dfinity/principal");
const axios_1 = __importDefault(require("axios"));
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const crypto_1 = require("crypto");
const mpc = __importStar(require("@bitgo/sdk-lib-mpc"));
const iface_1 = require("./lib/iface");
const transactionBuilderFactory_1 = require("./lib/transactionBuilderFactory");
const utils_1 = __importDefault(require("./lib/utils"));
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
const icpAgent_1 = require("./lib/icpAgent");
/**
* Class representing the Internet Computer (ICP) coin.
* Extends the BaseCoin class and provides specific implementations for ICP.
*
* @see {@link https://internetcomputer.org/}
* @see {@link https://internetcomputer.org/docs/current/developer-docs/defi/rosetta/icp_rosetta/data_api/}
*/
class Icp extends sdk_core_1.BaseCoin {
constructor(bitgo, staticsCoin) {
super(bitgo);
if (!staticsCoin) {
throw new Error('missing required constructor parameter staticsCoin');
}
this._staticsCoin = staticsCoin;
}
static createInstance(bitgo, staticsCoin) {
return new Icp(bitgo, staticsCoin);
}
getChain() {
return 'icp';
}
getBaseChain() {
return 'icp';
}
getFamily() {
return this._staticsCoin.family;
}
getFullName() {
return 'Internet Computer';
}
getBaseFactor() {
return Math.pow(10, this._staticsCoin.decimalPlaces);
}
async explainTransaction(params) {
const factory = this.getBuilderFactory();
const txBuilder = await factory.from(params.transactionHex);
const transaction = await txBuilder.build();
if (params.signableHex !== undefined) {
const generatedSignableHex = txBuilder.transaction.payloadsData.payloads[0].hex_bytes;
if (generatedSignableHex !== params.signableHex) {
throw new Error('generated signableHex is not equal to params.signableHex');
}
}
return transaction.explainTransaction();
}
async verifyTransaction(params) {
const { txParams, txPrebuild } = params;
const txHex = txPrebuild?.txHex;
if (!txHex) {
throw new Error('txHex is required');
}
const txHexParams = {
transactionHex: txHex,
};
if (txPrebuild.txInfo && txPrebuild.txInfo !== undefined && typeof txPrebuild.txInfo === 'string') {
txHexParams.signableHex = txPrebuild.txInfo;
}
const explainedTx = await this.explainTransaction(txHexParams);
if (Array.isArray(txParams.recipients) && txParams.recipients.length > 0) {
if (txParams.recipients.length > 1) {
throw new Error(`${this.getChain()} doesn't support sending to more than 1 destination address within a single transaction. Try again, using only a single recipient.`);
}
(0, assert_1.default)(explainedTx.outputs.length === 1, 'Tx outputs does not match with expected txParams recipients');
const output = explainedTx.outputs[0];
const recipient = txParams.recipients[0];
(0, assert_1.default)(typeof recipient.address === 'string' &&
typeof output.address === 'string' &&
output.address === recipient.address &&
(0, bignumber_js_1.default)(output.amount).eq((0, bignumber_js_1.default)(recipient.amount)), 'Tx outputs does not match with expected txParams recipients');
}
return true;
}
async isWalletAddress(params) {
return this.isValidAddress(params.address);
}
async parseTransaction(params) {
return {};
}
/**
* Generate a new keypair for this coin.
* @param seed Seed from which the new keypair should be generated, otherwise a random seed is used
*/
generateKeyPair(seed) {
return utils_1.default.generateKeyPair(seed);
}
isValidAddress(address) {
return utils_1.default.isValidAddress(address);
}
async signTransaction(params) {
const txHex = params?.txPrebuild?.txHex;
const privateKey = params?.prv;
if (!txHex) {
throw new sdk_core_1.SigningError('missing required txPrebuild parameter: params.txPrebuild.txHex');
}
if (!privateKey) {
throw new sdk_core_1.SigningError('missing required prv parameter: params.prv');
}
const factory = this.getBuilderFactory();
const txBuilder = await factory.from(params.txPrebuild.txHex);
txBuilder.sign({ key: params.prv });
txBuilder.combine();
const serializedTx = txBuilder.transaction.toBroadcastFormat();
return {
txHex: serializedTx,
};
}
isValidPub(key) {
return utils_1.default.isValidPublicKey(key);
}
isValidPrv(key) {
return utils_1.default.isValidPrivateKey(key);
}
/** @inheritDoc */
supportsTss() {
return true;
}
/** inherited doc */
getDefaultMultisigType() {
return sdk_core_1.multisigTypes.tss;
}
/** @inheritDoc */
getMPCAlgorithm() {
return 'ecdsa';
}
/** @inheritDoc **/
getHashFunction() {
return (0, crypto_1.createHash)('sha256');
}
async getAddressFromPublicKey(hexEncodedPublicKey) {
return utils_1.default.getAddressFromPublicKey(hexEncodedPublicKey);
}
/** @inheritDoc **/
getPublicNodeUrl() {
return sdk_core_1.Environments[this.bitgo.getEnv()].icpNodeUrl;
}
/** @inheritDoc **/
// this method calls the public node to broadcast the transaction and not the rosetta node
async broadcastTransaction(payload) {
const endpoint = this.getPublicNodeBroadcastEndpoint();
try {
const bodyBytes = utils_1.default.blobFromHex(payload.serializedSignedTransaction);
const response = await axios_1.default.post(endpoint, bodyBytes, {
headers: { 'Content-Type': 'application/cbor' },
responseType: 'arraybuffer', // This ensures you get a Buffer, not a string
});
if (response.status !== 200) {
throw new Error(`Transaction broadcast failed with status: ${response.status} - ${response.statusText}`);
}
const decodedResponse = utils_1.default.cborDecode(response.data);
if (decodedResponse.status === 'replied') {
// it is considered a success because ICP returns response in a CBOR map with a status of 'replied'
return {}; // returned empty object as ICP does not return a txid
}
else {
throw new Error(`Unexpected response status from node: ${decodedResponse.status}`);
}
}
catch (error) {
throw new Error(`Transaction broadcast error: ${error?.message || JSON.stringify(error)}`);
}
}
getPublicNodeBroadcastEndpoint() {
const nodeUrl = this.getPublicNodeUrl();
const principal = principal_1.Principal.fromUint8Array(iface_1.LEDGER_CANISTER_ID);
const canisterIdHex = principal.toText();
const endpoint = `${nodeUrl}${iface_1.PUBLIC_NODE_REQUEST_ENDPOINT}${canisterIdHex}/call`;
return endpoint;
}
/**
* Fetches the account balance for a given public key.
* @param publicKeyHex - Hex-encoded public key of the account.
* @returns Promise resolving to the account balance as a string.
* @throws Error if the balance could not be fetched.
*/
async getAccountBalance(publicKeyHex) {
const principalId = utils_1.default.getPrincipalIdFromPublicKey(publicKeyHex).toText();
const agent = new icpAgent_1.IcpAgent(this.getPublicNodeUrl());
return agent.getBalance(principalId);
}
/**
* Retrieves the current transaction fee data from the ICP public node.
*
* This method creates an instance of `IcpAgent` using the public node URL,
* then queries the node for the current fee information.
*
* @returns A promise that resolves to a `BigNumber` representing the current transaction fee.
* @throws Will propagate any errors encountered while communicating with the ICP node.
*/
async getFeeData() {
const agent = new icpAgent_1.IcpAgent(this.getPublicNodeUrl());
return await agent.getFee();
}
getBuilderFactory() {
return new transactionBuilderFactory_1.TransactionBuilderFactory(statics_1.coins.get(this.getBaseChain()));
}
/**
* Generates an array of signatures for the provided payloads using MPC
*
* @param payloadsData - The data containing the payloads to be signed.
* @param senderPublicKey - The public key of the sender in hexadecimal format.
* @param userKeyShare - The user's key share as a Buffer.
* @param backupKeyShare - The backup key share as a Buffer.
* @param commonKeyChain - The common key chain identifier used for MPC signing.
* @returns A promise that resolves to an array of `Signatures` objects, each containing the signing payload,
* signature type, public key, and the generated signature in hexadecimal format.
*/
async signatures(payloadsData, senderPublicKey, userKeyShare, backupKeyShare, commonKeyChain) {
try {
const payload = payloadsData.payloads[0];
const message = Buffer.from(payload.hex_bytes, 'hex');
const messageHash = (0, crypto_1.createHash)('sha256').update(message).digest();
const signature = await sdk_core_1.ECDSAUtils.signRecoveryMpcV2(messageHash, userKeyShare, backupKeyShare, commonKeyChain);
const signaturePayload = {
signing_payload: payload,
signature_type: payload.signature_type,
public_key: {
hex_bytes: senderPublicKey,
curve_type: iface_1.CurveType.SECP256K1,
},
hex_bytes: signature.r + signature.s,
};
return [signaturePayload];
}
catch (error) {
throw new Error(`Error generating signatures: ${error.message || error}`);
}
}
/**
* Builds a funds recovery transaction without BitGo
* @param params
*/
async recover(params) {
try {
if (!params.recoveryDestination || !this.isValidAddress(params.recoveryDestination)) {
throw new Error('invalid recoveryDestination');
}
const isUnsignedSweep = !params.userKey && !params.backupKey && !params.walletPassphrase;
let publicKey;
let userKeyShare, backupKeyShare, commonKeyChain;
const MPC = new sdk_core_1.Ecdsa();
if (!isUnsignedSweep) {
if (!params.userKey) {
throw new Error('missing userKey');
}
if (!params.backupKey) {
throw new Error('missing backupKey');
}
if (!params.walletPassphrase) {
throw new Error('missing wallet passphrase');
}
const userKey = params.userKey.replace(/\s/g, '');
const backupKey = params.backupKey.replace(/\s/g, '');
({ userKeyShare, backupKeyShare, commonKeyChain } = await sdk_core_1.ECDSAUtils.getMpcV2RecoveryKeyShares(userKey, backupKey, params.walletPassphrase));
publicKey = MPC.deriveUnhardened(commonKeyChain, iface_1.ROOT_PATH).slice(0, 66);
}
else {
const bitgoKey = params.bitgoKey;
if (!bitgoKey) {
throw new Error('missing bitgoKey');
}
const hdTree = new mpc.Secp256k1Bip32HdTree();
const derivationPath = 'm/0';
const derivedPub = hdTree.publicDerive({
pk: mpc.bigIntFromBufferBE(Buffer.from(bitgoKey.slice(0, 66), 'hex')),
chaincode: mpc.bigIntFromBufferBE(Buffer.from(bitgoKey.slice(66), 'hex')),
}, derivationPath);
publicKey = mpc.bigIntToBufferBE(derivedPub.pk).toString('hex');
}
if (!publicKey) {
throw new Error('failed to derive public key');
}
const senderAddress = await this.getAddressFromPublicKey(publicKey);
const balance = await this.getAccountBalance(publicKey);
const feeData = await this.getFeeData();
const actualBalance = balance.minus(feeData);
if (actualBalance.isLessThanOrEqualTo(0)) {
throw new Error('Did not have enough funds to recover');
}
const factory = this.getBuilderFactory();
const txBuilder = factory.getTransferBuilder();
txBuilder.sender(senderAddress, publicKey);
txBuilder.receiverId(params.recoveryDestination);
txBuilder.amount(actualBalance.toString());
if (params.memo !== undefined && utils_1.default.validateMemo(params.memo)) {
txBuilder.memo(Number(params.memo));
}
await txBuilder.build();
if (txBuilder.transaction.payloadsData.payloads.length === 0) {
throw new Error('Missing payloads to generate signatures');
}
if (isUnsignedSweep) {
return {
txHex: txBuilder.transaction.unsignedTransaction,
coin: this.getChain(),
};
}
const signatures = await this.signatures(txBuilder.transaction.payloadsData, publicKey, userKeyShare, backupKeyShare, commonKeyChain);
if (!signatures || signatures.length === 0) {
throw new Error('Failed to generate signatures');
}
txBuilder.transaction.addSignature(signatures);
txBuilder.combine();
const broadcastableTxn = txBuilder.transaction.toBroadcastFormat();
await this.broadcastTransaction({ serializedSignedTransaction: broadcastableTxn });
const txId = txBuilder.transaction.id;
const recoveredTransaction = {
id: txId,
tx: broadcastableTxn,
};
return recoveredTransaction;
}
catch (error) {
throw new Error(`Error during ICP recovery: ${error.message || error}`);
}
}
/** @inheritDoc */
auditDecryptedKey({ multiSigType, prv, publicKey }) {
if (multiSigType !== 'tss') {
throw new Error('Unsupported multisigtype ');
}
(0, sdk_lib_mpc_1.auditEcdsaPrivateKey)(prv, publicKey);
}
}
exports.Icp = Icp;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWNwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ljcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsOENBb0J5QjtBQUN6Qiw0Q0FBb0U7QUFDcEUsa0RBQStDO0FBQy9DLGtEQUEwQjtBQUMxQixnRUFBcUM7QUFDckMsbUNBQTBDO0FBQzFDLHdEQUEwQztBQUUxQyx1Q0FjcUI7QUFDckIsK0VBQTRFO0FBQzVFLHdEQUFnQztBQUNoQyxvREFBMEQ7QUFDMUQsNkNBQTBDO0FBRTFDOzs7Ozs7R0FNRztBQUNILE1BQWEsR0FBSSxTQUFRLG1CQUFRO0lBRS9CLFlBQXNCLEtBQWdCLEVBQUUsV0FBdUM7UUFDN0UsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsb0RBQW9ELENBQUMsQ0FBQztRQUN4RSxDQUFDO1FBRUQsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLENBQUM7SUFDbEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBZ0IsRUFBRSxXQUF1QztRQUM3RSxPQUFPLElBQUksR0FBRyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQsUUFBUTtRQUNOLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELFlBQVk7UUFDVixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxTQUFTO1FBQ1AsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQztJQUNsQyxDQUFDO0lBRUQsV0FBVztRQUNULE9BQU8sbUJBQW1CLENBQUM7SUFDN0IsQ0FBQztJQUVELGFBQWE7UUFDWCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsYUFB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Q3BCLE1BQU0sZ0JBQWdCLEdBQUcsU0FBUyxDQUFDLFdBQVcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQ25FLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixDQUFDLEVBQUUsMkJBQTJCLEVBQUUsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDO1lBQ25GLE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sb0JBQW9CLEdBQXdCO2dCQUNoRCxFQUFFLEVBQUUsSUFBSTtnQkFDUixFQUFFLEVBQUUsZ0JBQWdCO2FBQ3JCLENBQUM7WUFDRixPQUFPLG9CQUFvQixDQUFDO1FBQzlCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsS0FBSyxDQUFDLE9BQU8sSUFBSSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQzFFLENBQUM7SUFDSCxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGlCQUFpQixDQUFDLEVBQUUsWUFBWSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQTJCO1FBQ3pFLElBQUksWUFBWSxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQztRQUMvQyxDQUFDO1FBQ0QsSUFBQSxrQ0FBb0IsRUFBQyxHQUFhLEVBQUUsU0FBbUIsQ0FBQyxDQUFDO0lBQzNELENBQUM7Q0FDRjtBQXZZRCxrQkF1WUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQge1xuICBBdWRpdERlY3J5cHRlZEtleVBhcmFtcyxcbiAgQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uT3B0aW9ucyxcbiAgQmFzZUJyb2FkY2FzdFRyYW5zYWN0aW9uUmVzdWx0LFxuICBCYXNlQ29pbixcbiAgQml0R29CYXNlLFxuICBFY2RzYSxcbiAgRUNEU0FVdGlscyxcbiAgRW52aXJvbm1lbnRzLFxuICBLZXlQYWlyLFxuICBNUENBbGdvcml0aG0sXG4gIE11bHRpc2lnVHlwZSxcbiAgbXVsdGlzaWdUeXBlcyxcbiAgUGFyc2VkVHJhbnNhY3Rpb24sXG4gIFBhcnNlVHJhbnNhY3Rpb25PcHRpb25zLFxuICBTaWduZWRUcmFuc2FjdGlvbixcbiAgU2lnbmluZ0Vycm9yLFxuICBTaWduVHJhbnNhY3Rpb25PcHRpb25zLFxuICBUc3NWZXJpZnlBZGRyZXNzT3B0aW9ucyxcbiAgVmVyaWZ5VHJhbnNhY3Rpb25PcHRpb25zLFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgY29pbnMsIEJhc2VDb2luIGFzIFN0YXRpY3NCYXNlQ29pbiB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCB7IFByaW5jaXBhbCB9IGZyb20gJ0BkZmluaXR5L3ByaW5jaXBhbCc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IEJpZ051bWJlciBmcm9tICdiaWdudW1iZXIuanMnO1xuaW1wb3J0IHsgY3JlYXRlSGFzaCwgSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQgKiBhcyBtcGMgZnJvbSAnQGJpdGdvL3Nkay1saWItbXBjJztcblxuaW1wb3J0IHtcbiAgQ3VydmVUeXBlLFxuICBMRURHRVJfQ0FOSVNURVJfSUQsXG4gIFBheWxvYWRzRGF0YSxcbiAgUFVCTElDX05PREVfUkVRVUVTVF9FTkRQT0lOVCxcbiAgUHVibGljTm9kZVN1Ym1pdFJlc3BvbnNlLFxuICBSZWNvdmVyeU9wdGlvbnMsXG4gIFJlY292ZXJ5VHJhbnNhY3Rpb24sXG4gIFJPT1RfUEFUSCxcbiAgU2lnbmF0dXJlcyxcbiAgU2lnbmluZ1BheWxvYWQsXG4gIEljcFRyYW5zYWN0aW9uRXhwbGFuYXRpb24sXG4gIFRyYW5zYWN0aW9uSGV4UGFyYW1zLFxuICBVbnNpZ25lZFN3ZWVwUmVjb3ZlcnlUcmFuc2FjdGlvbixcbn0gZnJvbSAnLi9saWIvaWZhY2UnO1xuaW1wb3J0IHsgVHJhbnNhY3Rpb25CdWlsZGVyRmFjdG9yeSB9IGZyb20gJy4vbGliL3RyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnknO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4vbGliL3V0aWxzJztcbmltcG9ydCB7IGF1ZGl0RWNkc2FQcml2YXRlS2V5IH0gZnJvbSAnQGJpdGdvL3Nkay1saWItbXBjJztcbmltcG9ydCB7IEljcEFnZW50IH0gZnJvbSAnLi9saWIvaWNwQWdlbnQnO1xuXG4vKipcbiAqIENsYXNzIHJlcHJlc2VudGluZyB0aGUgSW50ZXJuZXQgQ29tcHV0ZXIgKElDUCkgY29pbi5cbiAqIEV4dGVuZHMgdGhlIEJhc2VDb2luIGNsYXNzIGFuZCBwcm92aWRlcyBzcGVjaWZpYyBpbXBsZW1lbnRhdGlvbnMgZm9yIElDUC5cbiAqXG4gKiBAc2VlIHtAbGluayBodHRwczovL2ludGVybmV0Y29tcHV0ZXIub3JnL31cbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vaW50ZXJuZXRjb21wdXRlci5vcmcvZG9jcy9jdXJyZW50L2RldmVsb3Blci1kb2NzL2RlZmkvcm9zZXR0YS9pY3Bfcm9zZXR0YS9kYXRhX2FwaS99XG4gKi9cbmV4cG9ydCBjbGFzcyBJY3AgZXh0ZW5kcyBCYXNlQ29pbiB7XG4gIHByb3RlY3RlZCByZWFkb25seSBfc3RhdGljc0NvaW46IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj47XG4gIHByb3RlY3RlZCBjb25zdHJ1Y3RvcihiaXRnbzogQml0R29CYXNlLCBzdGF0aWNzQ29pbj86IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj4pIHtcbiAgICBzdXBlcihiaXRnbyk7XG5cbiAgICBpZiAoIXN0YXRpY3NDb2luKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgcmVxdWlyZWQgY29uc3RydWN0b3IgcGFyYW1ldGVyIHN0YXRpY3NDb2luJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fc3RhdGljc0NvaW4gPSBzdGF0aWNzQ29pbjtcbiAgfVxuXG4gIHN0YXRpYyBjcmVhdGVJbnN0YW5jZShiaXRnbzogQml0R29CYXNlLCBzdGF0aWNzQ29pbj86IFJlYWRvbmx5PFN0YXRpY3NCYXNlQ29pbj4pOiBCYXNlQ29pbiB7XG4gICAgcmV0dXJuIG5ldyBJY3AoYml0Z28sIHN0YXRpY3NDb2luKTtcbiAgfVxuXG4gIGdldENoYWluKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdpY3AnO1xuICB9XG5cbiAgZ2V0QmFzZUNoYWluKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdpY3AnO1xuICB9XG5cbiAgZ2V0RmFtaWx5KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXRpY3NDb2luLmZhbWlseTtcbiAgfVxuXG4gIGdldEZ1bGxOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdJbnRlcm5ldCBDb21wdXRlcic7XG4gIH1cblxuICBnZXRCYXNlRmFjdG9yKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGgucG93KDEwLCB0aGlzLl9zdGF0aWNzQ29pbi5kZWNpbWFsUGxhY2VzKTtcbiAgfVxuXG4gIGFzeW5jIGV4cGxhaW5UcmFuc2FjdGlvbihwYXJhbXM6IFRyYW5zYWN0aW9uSGV4UGFyYW1zKTogUHJvbWlzZTxJY3BUcmFuc2FjdGlvbkV4cGxhbmF0aW9uPiB7XG4gICAgY29uc3QgZmFjdG9yeSA9IHRoaXMuZ2V0QnVpbGRlckZhY3RvcnkoKTtcbiAgICBjb25zdCB0eEJ1aWxkZXIgPSBhd2FpdCBmYWN0b3J5LmZyb20ocGFyYW1zLnRyYW5zYWN0aW9uSGV4KTtcbiAgICBjb25zdCB0cmFuc2FjdGlvbiA9IGF3YWl0IHR4QnVpbGRlci5idWlsZCgpO1xuICAgIGlmIChwYXJhbXMuc2lnbmFibGVIZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgZ2VuZXJhdGVkU2lnbmFibGVIZXggPSB0eEJ1aWxkZXIudHJhbnNhY3Rpb24ucGF5bG9hZHNEYXRhLnBheWxvYWRzWzBdLmhleF9ieXRlcztcbiAgICAgIGlmIChnZW5lcmF0ZWRTaWduYWJsZUhleCAhPT0gcGFyYW1zLnNpZ25hYmxlSGV4KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZ2VuZXJhdGVkIHNpZ25hYmxlSGV4IGlzIG5vdCBlcXVhbCB0byBwYXJhbXMuc2lnbmFibGVIZXgnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRyYW5zYWN0aW9uLmV4cGxhaW5UcmFuc2FjdGlvbigpO1xuICB9XG5cbiAgYXN5bmMgdmVyaWZ5VHJhbnNhY3Rpb24ocGFyYW1zOiBWZXJpZnlUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB7IHR4UGFyYW1zLCB0eFByZWJ1aWxkIH0gPSBwYXJhbXM7XG4gICAgY29uc3QgdHhIZXggPSB0eFByZWJ1aWxkPy50eEhleDtcbiAgICBpZiAoIXR4SGV4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3R4SGV4IGlzIHJlcXVpcmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IHR4SGV4UGFyYW1zOiBUcmFuc2FjdGlvbkhleFBhcmFtcyA9IHtcbiAgICAgIHRyYW5zYWN0aW9uSGV4OiB0eEhleCxcbiAgICB9O1xuXG4gICAgaWYgKHR4UHJlYnVpbGQudHhJbmZvICYmIHR4UHJlYnVpbGQudHhJbmZvICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIHR4UHJlYnVpbGQudHhJbmZvID09PSAnc3RyaW5nJykge1xuICAgICAgdHhIZXhQYXJhbXMuc2lnbmFibGVIZXggPSB0eFByZWJ1aWxkLnR4SW5mbztcbiAgICB9XG5cbiAgICBjb25zdCBleHBsYWluZWRUeCA9IGF3YWl0IHRoaXMuZXhwbGFpblRyYW5zYWN0aW9uKHR4SGV4UGFyYW1zKTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KHR4UGFyYW1zLnJlY2lwaWVudHMpICYmIHR4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKHR4UGFyYW1zLnJlY2lwaWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYCR7dGhpcy5nZXRDaGFpbigpfSBkb2Vzbid0IHN1cHBvcnQgc2VuZGluZyB0byBtb3JlIHRoYW4gMSBkZXN0aW5hdGlvbiBhZGRyZXNzIHdpdGhpbiBhIHNpbmdsZSB0cmFuc2FjdGlvbi4gVHJ5IGFnYWluLCB1c2luZyBvbmx5IGEgc2luZ2xlIHJlY2lwaWVudC5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBhc3NlcnQoZXhwbGFpbmVkVHgub3V0cHV0cy5sZW5ndGggPT09IDEsICdUeCBvdXRwdXRzIGRvZXMgbm90IG1hdGNoIHdpdGggZXhwZWN0ZWQgdHhQYXJhbXMgcmVjaXBpZW50cycpO1xuXG4gICAgICBjb25zdCBvdXRwdXQgPSBleHBsYWluZWRUeC5vdXRwdXRzWzBdO1xuICAgICAgY29uc3QgcmVjaXBpZW50ID0gdHhQYXJhbXMucmVjaXBpZW50c1swXTtcbiAgICAgIGFzc2VydChcbiAgICAgICAgdHlwZW9mIHJlY2lwaWVudC5hZGRyZXNzID09PSAnc3RyaW5nJyAmJlxuICAgICAgICAgIHR5cGVvZiBvdXRwdXQuYWRkcmVzcyA9PT0gJ3N0cmluZycgJiZcbiAgICAgICAgICBvdXRwdXQuYWRkcmVzcyA9PT0gcmVjaXBpZW50LmFkZHJlc3MgJiZcbiAgICAgICAgICBCaWdOdW1iZXIob3V0cHV0LmFtb3VudCkuZXEoQmlnTnVtYmVyKHJlY2lwaWVudC5hbW91bnQpKSxcbiAgICAgICAgJ1R4IG91dHB1dHMgZG9lcyBub3QgbWF0Y2ggd2l0aCBleHBlY3RlZCB0eFBhcmFtcyByZWNpcGllbnRzJ1xuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBhc3luYyBpc1dhbGxldEFkZHJlc3MocGFyYW1zOiBUc3NWZXJpZnlBZGRyZXNzT3B0aW9ucyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWRBZGRyZXNzKHBhcmFtcy5hZGRyZXNzKTtcbiAgfVxuXG4gIGFzeW5jIHBhcnNlVHJhbnNhY3Rpb24ocGFyYW1zOiBQYXJzZVRyYW5zYWN0aW9uT3B0aW9ucyk6IFByb21pc2U8UGFyc2VkVHJhbnNhY3Rpb24+IHtcbiAgICByZXR1cm4ge307XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgYSBuZXcga2V5cGFpciBmb3IgdGhpcyBjb2luLlxuICAgKiBAcGFyYW0gc2VlZCBTZWVkIGZyb20gd2hpY2ggdGhlIG5ldyBrZXlwYWlyIHNob3VsZCBiZSBnZW5lcmF0ZWQsIG90aGVyd2lzZSBhIHJhbmRvbSBzZWVkIGlzIHVzZWRcbiAgICovXG4gIHB1YmxpYyBnZW5lcmF0ZUtleVBhaXIoc2VlZD86IEJ1ZmZlcik6IEtleVBhaXIge1xuICAgIHJldHVybiB1dGlscy5nZW5lcmF0ZUtleVBhaXIoc2VlZCk7XG4gIH1cblxuICBpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdXRpbHMuaXNWYWxpZEFkZHJlc3MoYWRkcmVzcyk7XG4gIH1cblxuICBhc3luYyBzaWduVHJhbnNhY3Rpb24oXG4gICAgcGFyYW1zOiBTaWduVHJhbnNhY3Rpb25PcHRpb25zICYgeyB0eFByZWJ1aWxkOiB7IHR4SGV4OiBzdHJpbmcgfTsgcHJ2OiBzdHJpbmcgfVxuICApOiBQcm9taXNlPFNpZ25lZFRyYW5zYWN0aW9uPiB7XG4gICAgY29uc3QgdHhIZXggPSBwYXJhbXM/LnR4UHJlYnVpbGQ/LnR4SGV4O1xuICAgIGNvbnN0IHByaXZhdGVLZXkgPSBwYXJhbXM/LnBydjtcbiAgICBpZiAoIXR4SGV4KSB7XG4gICAgICB0aHJvdyBuZXcgU2lnbmluZ0Vycm9yKCdtaXNzaW5nIHJlcXVpcmVkIHR4UHJlYnVpbGQgcGFyYW1ldGVyOiBwYXJhbXMudHhQcmVidWlsZC50eEhleCcpO1xuICAgIH1cbiAgICBpZiAoIXByaXZhdGVLZXkpIHtcbiAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ21pc3NpbmcgcmVxdWlyZWQgcHJ2IHBhcmFtZXRlcjogcGFyYW1zLnBydicpO1xuICAgIH1cbiAgICBjb25zdCBmYWN0b3J5ID0gdGhpcy5nZXRCdWlsZGVyRmFjdG9yeSgpO1xuICAgIGNvbnN0IHR4QnVpbGRlciA9IGF3YWl0IGZhY3RvcnkuZnJvbShwYXJhbXMudHhQcmVidWlsZC50eEhleCk7XG4gICAgdHhCdWlsZGVyLnNpZ24oeyBrZXk6IHBhcmFtcy5wcnYgfSk7XG4gICAgdHhCdWlsZGVyLmNvbWJpbmUoKTtcbiAgICBjb25zdCBzZXJpYWxpemVkVHggPSB0eEJ1aWxkZXIudHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICByZXR1cm4ge1xuICAgICAgdHhIZXg6IHNlcmlhbGl6ZWRUeCxcbiAgICB9O1xuICB9XG5cbiAgaXNWYWxpZFB1YihrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB1dGlscy5pc1ZhbGlkUHVibGljS2V5KGtleSk7XG4gIH1cblxuICBpc1ZhbGlkUHJ2KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHV0aWxzLmlzVmFsaWRQcml2YXRlS2V5KGtleSk7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgc3VwcG9ydHNUc3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogaW5oZXJpdGVkIGRvYyAqL1xuICBnZXREZWZhdWx0TXVsdGlzaWdUeXBlKCk6IE11bHRpc2lnVHlwZSB7XG4gICAgcmV0dXJuIG11bHRpc2lnVHlwZXMudHNzO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICovXG4gIGdldE1QQ0FsZ29yaXRobSgpOiBNUENBbGdvcml0aG0ge1xuICAgIHJldHVybiAnZWNkc2EnO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICoqL1xuICBnZXRIYXNoRnVuY3Rpb24oKTogSGFzaCB7XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRBZGRyZXNzRnJvbVB1YmxpY0tleShoZXhFbmNvZGVkUHVibGljS2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdXRpbHMuZ2V0QWRkcmVzc0Zyb21QdWJsaWNLZXkoaGV4RW5jb2RlZFB1YmxpY0tleSk7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKiovXG4gIHByb3RlY3RlZCBnZXRQdWJsaWNOb2RlVXJsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIEVudmlyb25tZW50c1t0aGlzLmJpdGdvLmdldEVudigpXS5pY3BOb2RlVXJsO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0RG9jICoqL1xuICAvLyB0aGlzIG1ldGhvZCBjYWxscyB0aGUgcHVibGljIG5vZGUgdG8gYnJvYWRjYXN0IHRoZSB0cmFuc2FjdGlvbiBhbmQgbm90IHRoZSByb3NldHRhIG5vZGVcbiAgcHVibGljIGFzeW5jIGJyb2FkY2FzdFRyYW5zYWN0aW9uKHBheWxvYWQ6IEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvbk9wdGlvbnMpOiBQcm9taXNlPEJhc2VCcm9hZGNhc3RUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIGNvbnN0IGVuZHBvaW50ID0gdGhpcy5nZXRQdWJsaWNOb2RlQnJvYWRjYXN0RW5kcG9pbnQoKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBib2R5Qnl0ZXMgPSB1dGlscy5ibG9iRnJvbUhleChwYXlsb2FkLnNlcmlhbGl6ZWRTaWduZWRUcmFuc2FjdGlvbik7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zLnBvc3QoZW5kcG9pbnQsIGJvZHlCeXRlcywge1xuICAgICAgICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vY2JvcicgfSxcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAnYXJyYXlidWZmZXInLCAvLyBUaGlzIGVuc3VyZXMgeW91IGdldCBhIEJ1ZmZlciwgbm90IGEgc3RyaW5nXG4gICAgICB9KTtcblxuICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyAhPT0gMjAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVHJhbnNhY3Rpb24gYnJvYWRjYXN0IGZhaWxlZCB3aXRoIHN0YXR1czogJHtyZXNwb25zZS5zdGF0dXN9IC0gJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkZWNvZGVkUmVzcG9uc2UgPSB1dGlscy5jYm9yRGVjb2RlKHJlc3BvbnNlLmRhdGEpIGFzIFB1YmxpY05vZGVTdWJtaXRSZXNwb25zZTtcblxuICAgICAgaWYgKGRlY29kZWRSZXNwb25zZS5zdGF0dXMgPT09ICdyZXBsaWVkJykge1xuICAgICAgICAvLyBpdCBpcyBjb25zaWRlcmVkIGEgc3VjY2VzcyBiZWNhdXNlIElDUCByZXR1cm5zIHJlc3BvbnNlIGluIGEgQ0JPUiBtYXAgd2l0aCBhIHN0YXR1cyBvZiAncmVwbGllZCdcbiAgICAgICAgcmV0dXJuIHt9OyAvLyByZXR1cm5lZCBlbXB0eSBvYmplY3QgYXMgSUNQIGRvZXMgbm90IHJldHVybiBhIHR4aWRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5leHBlY3RlZCByZXNwb25zZSBzdGF0dXMgZnJvbSBub2RlOiAke2RlY29kZWRSZXNwb25zZS5zdGF0dXN9YCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVHJhbnNhY3Rpb24gYnJvYWRjYXN0IGVycm9yOiAke2Vycm9yPy5tZXNzYWdlIHx8IEpTT04uc3RyaW5naWZ5KGVycm9yKX1gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldFB1YmxpY05vZGVCcm9hZGNhc3RFbmRwb2ludCgpOiBzdHJpbmcge1xuICAgIGNvbnN0IG5vZGVVcmwgPSB0aGlzLmdldFB1YmxpY05vZGVVcmwoKTtcbiAgICBjb25zdCBwcmluY2lwYWwgPSBQcmluY2lwYWwuZnJvbVVpbnQ4QXJyYXkoTEVER0VSX0NBTklTVEVSX0lEKTtcbiAgICBjb25zdCBjYW5pc3RlcklkSGV4ID0gcHJpbmNpcGFsLnRvVGV4dCgpO1xuICAgIGNvbnN0IGVuZHBvaW50ID0gYCR7bm9kZVVybH0ke1BVQkxJQ19OT0RFX1JFUVVFU1RfRU5EUE9JTlR9JHtjYW5pc3RlcklkSGV4fS9jYWxsYDtcbiAgICByZXR1cm4gZW5kcG9pbnQ7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2hlcyB0aGUgYWNjb3VudCBiYWxhbmNlIGZvciBhIGdpdmVuIHB1YmxpYyBrZXkuXG4gICAqIEBwYXJhbSBwdWJsaWNLZXlIZXggLSBIZXgtZW5jb2RlZCBwdWJsaWMga2V5IG9mIHRoZSBhY2NvdW50LlxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgYWNjb3VudCBiYWxhbmNlIGFzIGEgc3RyaW5nLlxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHRoZSBiYWxhbmNlIGNvdWxkIG5vdCBiZSBmZXRjaGVkLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEFjY291bnRCYWxhbmNlKHB1YmxpY0tleUhleDogc3RyaW5nKTogUHJvbWlzZTxCaWdOdW1iZXI+IHtcbiAgICBjb25zdCBwcmluY2lwYWxJZCA9IHV0aWxzLmdldFByaW5jaXBhbElkRnJvbVB1YmxpY0tleShwdWJsaWNLZXlIZXgpLnRvVGV4dCgpO1xuICAgIGNvbnN0IGFnZW50ID0gbmV3IEljcEFnZW50KHRoaXMuZ2V0UHVibGljTm9kZVVybCgpKTtcbiAgICByZXR1cm4gYWdlbnQuZ2V0QmFsYW5jZShwcmluY2lwYWxJZCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBjdXJyZW50IHRyYW5zYWN0aW9uIGZlZSBkYXRhIGZyb20gdGhlIElDUCBwdWJsaWMgbm9kZS5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgY3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBgSWNwQWdlbnRgIHVzaW5nIHRoZSBwdWJsaWMgbm9kZSBVUkwsXG4gICAqIHRoZW4gcXVlcmllcyB0aGUgbm9kZSBmb3IgdGhlIGN1cnJlbnQgZmVlIGluZm9ybWF0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGBCaWdOdW1iZXJgIHJlcHJlc2VudGluZyB0aGUgY3VycmVudCB0cmFuc2FjdGlvbiBmZWUuXG4gICAqIEB0aHJvd3MgV2lsbCBwcm9wYWdhdGUgYW55IGVycm9ycyBlbmNvdW50ZXJlZCB3aGlsZSBjb21tdW5pY2F0aW5nIHdpdGggdGhlIElDUCBub2RlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGdldEZlZURhdGEoKTogUHJvbWlzZTxCaWdOdW1iZXI+IHtcbiAgICBjb25zdCBhZ2VudCA9IG5ldyBJY3BBZ2VudCh0aGlzLmdldFB1YmxpY05vZGVVcmwoKSk7XG4gICAgcmV0dXJuIGF3YWl0IGFnZW50LmdldEZlZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRCdWlsZGVyRmFjdG9yeSgpOiBUcmFuc2FjdGlvbkJ1aWxkZXJGYWN0b3J5IHtcbiAgICByZXR1cm4gbmV3IFRyYW5zYWN0aW9uQnVpbGRlckZhY3RvcnkoY29pbnMuZ2V0KHRoaXMuZ2V0QmFzZUNoYWluKCkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYW4gYXJyYXkgb2Ygc2lnbmF0dXJlcyBmb3IgdGhlIHByb3ZpZGVkIHBheWxvYWRzIHVzaW5nIE1QQ1xuICAgKlxuICAgKiBAcGFyYW0gcGF5bG9hZHNEYXRhIC0gVGhlIGRhdGEgY29udGFpbmluZyB0aGUgcGF5bG9hZHMgdG8gYmUgc2lnbmVkLlxuICAgKiBAcGFyYW0gc2VuZGVyUHVibGljS2V5IC0gVGhlIHB1YmxpYyBrZXkgb2YgdGhlIHNlbmRlciBpbiBoZXhhZGVjaW1hbCBmb3JtYXQuXG4gICAqIEBwYXJhbSB1c2VyS2V5U2hhcmUgLSBUaGUgdXNlcidzIGtleSBzaGFyZSBhcyBhIEJ1ZmZlci5cbiAgICogQHBhcmFtIGJhY2t1cEtleVNoYXJlIC0gVGhlIGJhY2t1cCBrZXkgc2hhcmUgYXMgYSBCdWZmZXIuXG4gICAqIEBwYXJhbSBjb21tb25LZXlDaGFpbiAtIFRoZSBjb21tb24ga2V5IGNoYWluIGlkZW50aWZpZXIgdXNlZCBmb3IgTVBDIHNpZ25pbmcuXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIGBTaWduYXR1cmVzYCBvYmplY3RzLCBlYWNoIGNvbnRhaW5pbmcgdGhlIHNpZ25pbmcgcGF5bG9hZCxcbiAgICogICAgICAgICAgc2lnbmF0dXJlIHR5cGUsIHB1YmxpYyBrZXksIGFuZCB0aGUgZ2VuZXJhdGVkIHNpZ25hdHVyZSBpbiBoZXhhZGVjaW1hbCBmb3JtYXQuXG4gICAqL1xuICBhc3luYyBzaWduYXR1cmVzKFxuICAgIHBheWxvYWRzRGF0YTogUGF5bG9hZHNEYXRhLFxuICAgIHNlbmRlclB1YmxpY0tleTogc3RyaW5nLFxuICAgIHVzZXJLZXlTaGFyZTogQnVmZmVyPEFycmF5QnVmZmVyTGlrZT4sXG4gICAgYmFja3VwS2V5U2hhcmU6IEJ1ZmZlcjxBcnJheUJ1ZmZlckxpa2U+LFxuICAgIGNvbW1vbktleUNoYWluOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxTaWduYXR1cmVzW10+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcGF5bG9hZCA9IHBheWxvYWRzRGF0YS5wYXlsb2Fkc1swXSBhcyBTaWduaW5nUGF5bG9hZDtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBCdWZmZXIuZnJvbShwYXlsb2FkLmhleF9ieXRlcywgJ2hleCcpO1xuICAgICAgY29uc3QgbWVzc2FnZUhhc2ggPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUobWVzc2FnZSkuZGlnZXN0KCk7XG4gICAgICBjb25zdCBzaWduYXR1cmUgPSBhd2FpdCBFQ0RTQVV0aWxzLnNpZ25SZWNvdmVyeU1wY1YyKG1lc3NhZ2VIYXNoLCB1c2VyS2V5U2hhcmUsIGJhY2t1cEtleVNoYXJlLCBjb21tb25LZXlDaGFpbik7XG4gICAgICBjb25zdCBzaWduYXR1cmVQYXlsb2FkOiBTaWduYXR1cmVzID0ge1xuICAgICAgICBzaWduaW5nX3BheWxvYWQ6IHBheWxvYWQsXG4gICAgICAgIHNpZ25hdHVyZV90eXBlOiBwYXlsb2FkLnNpZ25hdHVyZV90eXBlLFxuICAgICAgICBwdWJsaWNfa2V5OiB7XG4gICAgICAgICAgaGV4X2J5dGVzOiBzZW5kZXJQdWJsaWNLZXksXG4gICAgICAgICAgY3VydmVfdHlwZTogQ3VydmVUeXBlLlNFQ1AyNTZLMSxcbiAgICAgICAgfSxcbiAgICAgICAgaGV4X2J5dGVzOiBzaWduYXR1cmUuciArIHNpZ25hdHVyZS5zLFxuICAgICAgfTtcblxuICAgICAgcmV0dXJuIFtzaWduYXR1cmVQYXlsb2FkXTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBnZW5lcmF0aW5nIHNpZ25hdHVyZXM6ICR7ZXJyb3IubWVzc2FnZSB8fCBlcnJvcn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQnVpbGRzIGEgZnVuZHMgcmVjb3ZlcnkgdHJhbnNhY3Rpb24gd2l0aG91dCBCaXRHb1xuICAgKiBAcGFyYW0gcGFyYW1zXG4gICAqL1xuICBhc3luYyByZWNvdmVyKHBhcmFtczogUmVjb3ZlcnlPcHRpb25zKTogUHJvbWlzZTxSZWNvdmVyeVRyYW5zYWN0aW9uIHwgVW5zaWduZWRTd2VlcFJlY292ZXJ5VHJhbnNhY3Rpb24+IHtcbiAgICB0cnkge1xuICAgICAgaWYgKCFwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbiB8fCAhdGhpcy5pc1ZhbGlkQWRkcmVzcyhwYXJhbXMucmVjb3ZlcnlEZXN0aW5hdGlvbikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHJlY292ZXJ5RGVzdGluYXRpb24nKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgaXNVbnNpZ25lZFN3ZWVwID0gIXBhcmFtcy51c2VyS2V5ICYmICFwYXJhbXMuYmFja3VwS2V5ICYmICFwYXJhbXMud2FsbGV0UGFzc3BocmFzZTtcblxuICAgICAgbGV0IHB1YmxpY0tleTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgbGV0IHVzZXJLZXlTaGFyZSwgYmFja3VwS2V5U2hhcmUsIGNvbW1vbktleUNoYWluO1xuICAgICAgY29uc3QgTVBDID0gbmV3IEVjZHNhKCk7XG5cbiAgICAgIGlmICghaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICAgIGlmICghcGFyYW1zLnVzZXJLZXkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21pc3NpbmcgdXNlcktleScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFwYXJhbXMuYmFja3VwS2V5KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaXNzaW5nIGJhY2t1cEtleScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFwYXJhbXMud2FsbGV0UGFzc3BocmFzZSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyB3YWxsZXQgcGFzc3BocmFzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdXNlcktleSA9IHBhcmFtcy51c2VyS2V5LnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgICAgIGNvbnN0IGJhY2t1cEtleSA9IHBhcmFtcy5iYWNrdXBLZXkucmVwbGFjZSgvXFxzL2csICcnKTtcblxuICAgICAgICAoeyB1c2VyS2V5U2hhcmUsIGJhY2t1cEtleVNoYXJlLCBjb21tb25LZXlDaGFpbiB9ID0gYXdhaXQgRUNEU0FVdGlscy5nZXRNcGNWMlJlY292ZXJ5S2V5U2hhcmVzKFxuICAgICAgICAgIHVzZXJLZXksXG4gICAgICAgICAgYmFja3VwS2V5LFxuICAgICAgICAgIHBhcmFtcy53YWxsZXRQYXNzcGhyYXNlXG4gICAgICAgICkpO1xuICAgICAgICBwdWJsaWNLZXkgPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChjb21tb25LZXlDaGFpbiwgUk9PVF9QQVRIKS5zbGljZSgwLCA2Nik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBiaXRnb0tleSA9IHBhcmFtcy5iaXRnb0tleTtcbiAgICAgICAgaWYgKCFiaXRnb0tleSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignbWlzc2luZyBiaXRnb0tleScpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaGRUcmVlID0gbmV3IG1wYy5TZWNwMjU2azFCaXAzMkhkVHJlZSgpO1xuICAgICAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzAnO1xuICAgICAgICBjb25zdCBkZXJpdmVkUHViID0gaGRUcmVlLnB1YmxpY0Rlcml2ZShcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwazogbXBjLmJpZ0ludEZyb21CdWZmZXJCRShCdWZmZXIuZnJvbShiaXRnb0tleS5zbGljZSgwLCA2NiksICdoZXgnKSksXG4gICAgICAgICAgICBjaGFpbmNvZGU6IG1wYy5iaWdJbnRGcm9tQnVmZmVyQkUoQnVmZmVyLmZyb20oYml0Z29LZXkuc2xpY2UoNjYpLCAnaGV4JykpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgZGVyaXZhdGlvblBhdGhcbiAgICAgICAgKTtcblxuICAgICAgICBwdWJsaWNLZXkgPSBtcGMuYmlnSW50VG9CdWZmZXJCRShkZXJpdmVkUHViLnBrKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmICghcHVibGljS2V5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZmFpbGVkIHRvIGRlcml2ZSBwdWJsaWMga2V5Jyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNlbmRlckFkZHJlc3MgPSBhd2FpdCB0aGlzLmdldEFkZHJlc3NGcm9tUHVibGljS2V5KHB1YmxpY0tleSk7XG4gICAgICBjb25zdCBiYWxhbmNlID0gYXdhaXQgdGhpcy5nZXRBY2NvdW50QmFsYW5jZShwdWJsaWNLZXkpO1xuICAgICAgY29uc3QgZmVlRGF0YSA9IGF3YWl0IHRoaXMuZ2V0RmVlRGF0YSgpO1xuICAgICAgY29uc3QgYWN0dWFsQmFsYW5jZSA9IGJhbGFuY2UubWludXMoZmVlRGF0YSk7XG4gICAgICBpZiAoYWN0dWFsQmFsYW5jZS5pc0xlc3NUaGFuT3JFcXVhbFRvKDApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRGlkIG5vdCBoYXZlIGVub3VnaCBmdW5kcyB0byByZWNvdmVyJyk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZhY3RvcnkgPSB0aGlzLmdldEJ1aWxkZXJGYWN0b3J5KCk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXIgPSBmYWN0b3J5LmdldFRyYW5zZmVyQnVpbGRlcigpO1xuICAgICAgdHhCdWlsZGVyLnNlbmRlcihzZW5kZXJBZGRyZXNzLCBwdWJsaWNLZXkgYXMgc3RyaW5nKTtcbiAgICAgIHR4QnVpbGRlci5yZWNlaXZlcklkKHBhcmFtcy5yZWNvdmVyeURlc3RpbmF0aW9uKTtcbiAgICAgIHR4QnVpbGRlci5hbW91bnQoYWN0dWFsQmFsYW5jZS50b1N0cmluZygpKTtcbiAgICAgIGlmIChwYXJhbXMubWVtbyAhPT0gdW5kZWZpbmVkICYmIHV0aWxzLnZhbGlkYXRlTWVtbyhwYXJhbXMubWVtbykpIHtcbiAgICAgICAgdHhCdWlsZGVyLm1lbW8oTnVtYmVyKHBhcmFtcy5tZW1vKSk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0eEJ1aWxkZXIuYnVpbGQoKTtcbiAgICAgIGlmICh0eEJ1aWxkZXIudHJhbnNhY3Rpb24ucGF5bG9hZHNEYXRhLnBheWxvYWRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcGF5bG9hZHMgdG8gZ2VuZXJhdGUgc2lnbmF0dXJlcycpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNVbnNpZ25lZFN3ZWVwKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHhIZXg6IHR4QnVpbGRlci50cmFuc2FjdGlvbi51bnNpZ25lZFRyYW5zYWN0aW9uLFxuICAgICAgICAgIGNvaW46IHRoaXMuZ2V0Q2hhaW4oKSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2lnbmF0dXJlcyA9IGF3YWl0IHRoaXMuc2lnbmF0dXJlcyhcbiAgICAgICAgdHhCdWlsZGVyLnRyYW5zYWN0aW9uLnBheWxvYWRzRGF0YSxcbiAgICAgICAgcHVibGljS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBjb21tb25LZXlDaGFpblxuICAgICAgKTtcbiAgICAgIGlmICghc2lnbmF0dXJlcyB8fCBzaWduYXR1cmVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZhaWxlZCB0byBnZW5lcmF0ZSBzaWduYXR1cmVzJyk7XG4gICAgICB9XG4gICAgICB0eEJ1aWxkZXIudHJhbnNhY3Rpb24uYWRkU2lnbmF0dXJlKHNpZ25hdHVyZXMpO1xuICAgICAgdHhCdWlsZGVyLmNvbWJpbmUoKTtcbiAgICAgIGNvbnN0IGJyb2FkY2FzdGFibGVUeG4gPSB0eEJ1aWxkZXIudHJhbnNhY3Rpb24udG9Ccm9hZGNhc3RGb3JtYXQoKTtcbiAgICAgIGF3YWl0IHRoaXMuYnJvYWRjYXN0VHJhbnNhY3Rpb24oeyBzZXJpYWxpemVkU2lnbmVkVHJhbnNhY3Rpb246IGJyb2FkY2FzdGFibGVUeG4gfSk7XG4gICAgICBjb25zdCB0eElkID0gdHhCdWlsZGVyLnRyYW5zYWN0aW9uLmlkO1xuICAgICAgY29uc3QgcmVjb3ZlcmVkVHJhbnNhY3Rpb246IFJlY292ZXJ5VHJhbnNhY3Rpb24gPSB7XG4gICAgICAgIGlkOiB0eElkLFxuICAgICAgICB0eDogYnJvYWRjYXN0YWJsZVR4bixcbiAgICAgIH07XG4gICAgICByZXR1cm4gcmVjb3ZlcmVkVHJhbnNhY3Rpb247XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZHVyaW5nIElDUCByZWNvdmVyeTogJHtlcnJvci5tZXNzYWdlIHx8IGVycm9yfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBhdWRpdERlY3J5cHRlZEtleSh7IG11bHRpU2lnVHlwZSwgcHJ2LCBwdWJsaWNLZXkgfTogQXVkaXREZWNyeXB0ZWRLZXlQYXJhbXMpIHtcbiAgICBpZiAobXVsdGlTaWdUeXBlICE9PSAndHNzJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBtdWx0aXNpZ3R5cGUgJyk7XG4gICAgfVxuICAgIGF1ZGl0RWNkc2FQcml2YXRlS2V5KHBydiBhcyBzdHJpbmcsIHB1YmxpY0tleSBhcyBzdHJpbmcpO1xuICB9XG59XG4iXX0=Выполнить команду
Для локальной разработки. Не используйте в интернете!