PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-coin-cspr/dist/src/lib
Просмотр файла: transactionBuilder.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransactionBuilder = exports.DEFAULT_N = exports.DEFAULT_M = void 0;
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const casper_js_sdk_1 = require("casper-js-sdk");
const lodash_1 = __importDefault(require("lodash"));
const sdk_core_1 = require("@bitgo/sdk-core");
const transaction_1 = require("./transaction");
const keyPair_1 = require("./keyPair");
const utils_1 = require("./utils");
const constants_1 = require("./constants");
exports.DEFAULT_M = 3;
exports.DEFAULT_N = 2;
class TransactionBuilder extends sdk_core_1.BaseTransactionBuilder {
constructor(_coinConfig) {
super(_coinConfig);
this.transaction = new transaction_1.Transaction(_coinConfig);
this._multiSignerKeyPairs = [];
this._signatures = [];
this._chainName = this.coinName() === 'cspr' ? constants_1.DEFAULT_CHAIN_NAMES.mainnet : constants_1.DEFAULT_CHAIN_NAMES.testnet;
}
// region Base Builder
/** @inheritdoc */
async buildImplementation() {
const deployParams = this.getDeployParams();
const session = this.getSession();
const payment = casper_js_sdk_1.DeployUtil.standardPayment(lodash_1.default.parseInt(this._fee.gasLimit));
let cTransaction = this.transaction.casperTx || casper_js_sdk_1.DeployUtil.makeDeploy(deployParams, session, payment);
// Cannot add arguments to an already signed deploy.
if (cTransaction.approvals.length === 0) {
this._session.extraArguments.forEach((extraArgument, extraArgumentName) => {
if (!cTransaction.session.getArgByName(extraArgumentName)) {
cTransaction = casper_js_sdk_1.DeployUtil.addArgToDeploy(cTransaction, extraArgumentName, extraArgument);
}
});
}
this.transaction.casperTx = cTransaction;
this.processSigning();
return this.transaction;
}
/** @inheritdoc */
fromImplementation(rawTransaction) {
const tx = new transaction_1.Transaction(this._coinConfig);
const jsonTransaction = JSON.parse(rawTransaction);
tx.casperTx = casper_js_sdk_1.DeployUtil.deployFromJson(jsonTransaction).unwrap();
this.initBuilder(tx);
return this.transaction;
}
/** @inheritdoc */
signImplementation(key) {
this.checkDuplicatedKeys(key);
const signer = new keyPair_1.KeyPair({ prv: key.key });
// Signing the transaction is an operation that relies on all the data being set,
// so we set the source here and leave the actual signing for the build step
this._multiSignerKeyPairs.push(signer);
return this.transaction;
}
/**
* Initialize the transaction builder fields using the decoded transaction data
*
* @param {Transaction} tx the transaction data
*/
initBuilder(tx) {
this.transaction = tx;
this.transaction.loadPreviousSignatures();
const txData = tx.toJson();
this.fee(txData.fee);
this.source({ address: txData.from });
this.expiration(txData.expiration || constants_1.TRANSACTION_EXPIRATION);
}
// endregion
// region Common builder methods
/**
* Set the transaction fees
*
* @param {BaseFee} fee The maximum gas to pay
* @returns {TransactionBuilder} This transaction builder
*/
fee(fee) {
this.validateValue(new bignumber_js_1.default(fee.gasLimit));
this._fee = fee;
return this;
}
/**
* Set the transaction source
*
* @param {BaseAddress} address The source account
* @returns {TransactionBuilder} This transaction builder
*/
source(address) {
this.validateAddress(address);
this._source = address;
return this;
}
/**
* Set the transaction expirationTime
*
* @param {string} expirationTime The transaction expirationTime
* @returns {TransactionBuilder} This transaction builder
*/
expiration(expirationTime) {
const transactionExpiration = new bignumber_js_1.default(expirationTime);
if (transactionExpiration.isNaN() || transactionExpiration.isGreaterThan(constants_1.TRANSACTION_EXPIRATION)) {
throw new sdk_core_1.BuildTransactionError('Invalid transaction expiration');
}
this.validateValue(transactionExpiration);
this._expiration = transactionExpiration.toNumber();
return this;
}
/**
* Set an external transaction signature
*
* @param {string} signature Hex encoded signature string
* @param {KeyPair} keyPair The public key keypair that was used to create the signature
* @returns {TransactionBuilder} This transaction builder
*/
signature(signature, keyPair) {
// if we already have a signature for this key pair, just update it
for (const oldSignature of this._signatures) {
if (oldSignature.keyPair.getKeys().pub === keyPair.getKeys().pub) {
oldSignature.signature = signature;
return this;
}
}
// otherwise add the new signature
this._signatures.push({ signature, keyPair });
return this;
}
nodeChainName(chainName) {
this._chainName = chainName;
return this;
}
// endregion
// region Validators
/** @inheritdoc */
validateAddress(address) {
if (!(0, utils_1.isValidAddress)(address.address)) {
throw new sdk_core_1.BuildTransactionError('Invalid address ' + address.address);
}
}
/** @inheritdoc */
validateKey(key) {
if (!new keyPair_1.KeyPair({ prv: key.key })) {
throw new sdk_core_1.BuildTransactionError('Invalid key');
}
}
/** @inheritdoc */
validateRawTransaction(rawTransaction) {
if (!rawTransaction) {
throw new sdk_core_1.InvalidTransactionError('Raw transaction is empty');
}
try {
casper_js_sdk_1.DeployUtil.deployFromJson(JSON.parse(rawTransaction));
}
catch (e) {
throw new sdk_core_1.ParseTransactionError('There was an error parsing the JSON string');
}
}
/** @inheritdoc */
validateTransaction(transaction) {
this.validateMandatoryFields();
}
/** @inheritdoc */
validateValue(value) {
if (value.isLessThan(0)) {
throw new sdk_core_1.BuildTransactionError('Value cannot be less than zero');
}
}
/**
* Validates that the mandatory fields are defined
*/
validateMandatoryFields() {
this.validateFee();
this.validateSource();
}
/**
* Validates that the fee field is defined
*/
validateFee() {
if (this._fee === undefined) {
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing fee');
}
if (!this._fee.gasLimit) {
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing gas limit');
}
try {
this.validateValue(new bignumber_js_1.default(this._fee.gasLimit));
}
catch (e) {
throw new sdk_core_1.BuildTransactionError('Invalid gas limit');
}
}
/**
* Validates that the source field is defined
*/
validateSource() {
if (this._source === undefined) {
throw new sdk_core_1.BuildTransactionError('Invalid transaction: missing source');
}
this.validateAddress(this._source);
}
/**
* Validates that the given key is not already in this._multiSignerKeyPairs
*
* @param {BaseKey} key - The key to check
*/
checkDuplicatedKeys(key) {
this._multiSignerKeyPairs.forEach((_sourceKeyPair) => {
if (_sourceKeyPair.getKeys().prv === key.key) {
throw new sdk_core_1.SigningError('Repeated sign: ' + key.key);
}
// Try to get extended keys in order to validate them
let xprv;
try {
xprv = _sourceKeyPair.getExtendedKeys().xprv;
}
catch (err) {
return;
}
if (xprv && xprv === key.key) {
throw new sdk_core_1.SigningError('Repeated sign: ' + key.key);
}
});
}
// endregion
// region Getters and Setters
/** @inheritdoc */
get transaction() {
return this._transaction;
}
/** @inheritdoc */
set transaction(transaction) {
this._transaction = transaction;
}
/**
* Get the chain name for the coin environment
*/
get chainName() {
return this._chainName;
}
// endregion
// region auxiliaryMethods
/**
* Generate a DeployParams instance with the transaction data
*
* @returns {DeployUtil.DeployParams}
*/
getDeployParams() {
const gasPrice = this._fee.gasPrice ? lodash_1.default.parseInt(this._fee.gasPrice) : undefined;
return new casper_js_sdk_1.DeployUtil.DeployParams(casper_js_sdk_1.CLPublicKey.fromHex(this._source.address), this._chainName, gasPrice, this._expiration || constants_1.TRANSACTION_EXPIRATION);
}
/**
* Generate the session for the Deploy according to the transactionType.
*
* @returns {DeployUtil.ExecutableDeployItem}
*/
getSession() {
let session;
switch (this.transaction.type) {
case sdk_core_1.TransactionType.Send:
const transferSession = this._session;
session = casper_js_sdk_1.DeployUtil.ExecutableDeployItem.newTransferWithOptionalTransferId(transferSession.amount, transferSession.target, undefined, transferSession.id);
break;
case sdk_core_1.TransactionType.WalletInitialization:
case sdk_core_1.TransactionType.StakingLock:
case sdk_core_1.TransactionType.StakingUnlock:
const moduleBytesSession = this._session;
session = casper_js_sdk_1.DeployUtil.ExecutableDeployItem.newModuleBytes(moduleBytesSession.moduleBytes, moduleBytesSession.args);
break;
default:
throw new sdk_core_1.BuildTransactionError('Transaction Type error');
}
return session;
}
/**
* Checks whether the transaction has the owner signature
*
* @param {string} pub - public key of the signer
* @returns {boolean} true if the pub key already signed th transaction
* @private
*/
isTransactionSignedByPub(pub) {
return (lodash_1.default.findIndex(this.transaction.casperTx.approvals, (approval) => {
const approvalSigner = (0, utils_1.removeAlgoPrefixFromHexValue)(approval.signer);
return approvalSigner === pub;
}) !== -1);
}
/**
* Add signatures to the transaction
*
* @private
*/
processSigning() {
for (const keyPair of this._multiSignerKeyPairs) {
// Add signature if it's not already in the deploy
if (!this.isTransactionSignedByPub(keyPair.getKeys().pub)) {
this.transaction.sign(keyPair);
}
}
for (const { signature, keyPair } of this._signatures) {
// Add signature if it's not already in the deploy
if (!this.isTransactionSignedByPub(keyPair.getKeys().pub)) {
this.transaction.addSignature(signature, keyPair);
}
}
}
}
exports.TransactionBuilder = TransactionBuilder;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25CdWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi90cmFuc2FjdGlvbkJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsZ0VBQXFDO0FBRXJDLGlEQUFxRTtBQUNyRSxvREFBdUI7QUFDdkIsOENBU3lCO0FBQ3pCLCtDQUE0QztBQUM1Qyx1Q0FBb0M7QUFRcEMsbUNBQXVFO0FBQ3ZFLDJDQUEwRTtBQUU3RCxRQUFBLFNBQVMsR0FBRyxDQUFDLENBQUM7QUFDZCxRQUFBLFNBQVMsR0FBRyxDQUFDLENBQUM7QUFDM0IsTUFBc0Isa0JBQW1CLFNBQVEsaUNBQXNCO0lBVXJFLFlBQVksV0FBaUM7UUFDM0MsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSx5QkFBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2hELElBQUksQ0FBQyxvQkFBb0IsR0FBRyxFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDLFdBQVcsR0FBRyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQywrQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLCtCQUFtQixDQUFDLE9BQU8sQ0FBQztJQUMzRyxDQUFDO0lBRUQsc0JBQXNCO0lBQ3RCLGtCQUFrQjtJQUNSLEtBQUssQ0FBQyxtQkFBbUI7UUFDakMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQzVDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUVsQyxNQUFNLE9BQU8sR0FBRywwQkFBVSxDQUFDLGVBQWUsQ0FBQyxnQkFBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFFM0Us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QUFDO1lBQ3JFLE9BQU8sY0FBYyxLQUFLLEdBQUcsQ0FBQztRQUNoQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDVixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxjQUFjO1FBQ3BCLEtBQUssTUFBTSxPQUFPLElBQUksSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDaEQsa0RBQWtEO1lBQ2xELElBQUksQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzFELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ2pDLENBQUM7UUFDSCxDQUFDO1FBQ0QsS0FBSyxNQUFNLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN0RCxrREFBa0Q7WUFDbEQsSUFBSSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDMUQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ3BELENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUVGO0FBaFdELGdEQWdXQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBCaWdOdW1iZXIgZnJvbSAnYmlnbnVtYmVyLmpzJztcbmltcG9ydCB7IEJhc2VDb2luIGFzIENvaW5Db25maWcgfSBmcm9tICdAYml0Z28vc3RhdGljcyc7XG5pbXBvcnQgeyBEZXBsb3lVdGlsLCBDTFB1YmxpY0tleSBhcyBQdWJsaWNLZXkgfSBmcm9tICdjYXNwZXItanMtc2RrJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge1xuICBCYXNlQWRkcmVzcyxcbiAgQmFzZUtleSxcbiAgQmFzZVRyYW5zYWN0aW9uQnVpbGRlcixcbiAgQnVpbGRUcmFuc2FjdGlvbkVycm9yLFxuICBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcixcbiAgUGFyc2VUcmFuc2FjdGlvbkVycm9yLFxuICBTaWduaW5nRXJyb3IsXG4gIFRyYW5zYWN0aW9uVHlwZSxcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IFRyYW5zYWN0aW9uIH0gZnJvbSAnLi90cmFuc2FjdGlvbic7XG5pbXBvcnQgeyBLZXlQYWlyIH0gZnJvbSAnLi9rZXlQYWlyJztcbmltcG9ydCB7XG4gIEZlZSxcbiAgQ2FzcGVyTW9kdWxlQnl0ZXNUcmFuc2FjdGlvbixcbiAgQ2FzcGVyVHJhbnNmZXJUcmFuc2FjdGlvbixcbiAgQ2FzcGVyRGVsZWdhdGVUcmFuc2FjdGlvbixcbiAgU2lnbmF0dXJlRGF0YSxcbn0gZnJvbSAnLi9pZmFjZXMnO1xuaW1wb3J0IHsgaXNWYWxpZEFkZHJlc3MsIHJlbW92ZUFsZ29QcmVmaXhGcm9tSGV4VmFsdWUgfSBmcm9tICcuL3V0aWxzJztcbmltcG9ydCB7IERFRkFVTFRfQ0hBSU5fTkFNRVMsIFRSQU5TQUNUSU9OX0VYUElSQVRJT04gfSBmcm9tICcuL2NvbnN0YW50cyc7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX00gPSAzO1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfTiA9IDI7XG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVHJhbnNhY3Rpb25CdWlsZGVyIGV4dGVuZHMgQmFzZVRyYW5zYWN0aW9uQnVpbGRlciB7XG4gIHByb3RlY3RlZCBfc291cmNlOiBCYXNlQWRkcmVzcztcbiAgcHJvdGVjdGVkIF9mZWU6IEZlZTtcbiAgcHJpdmF0ZSBfdHJhbnNhY3Rpb246IFRyYW5zYWN0aW9uO1xuICBwcm90ZWN0ZWQgX3Nlc3Npb246IENhc3BlclRyYW5zZmVyVHJhbnNhY3Rpb24gfCBDYXNwZXJNb2R1bGVCeXRlc1RyYW5zYWN0aW9uIHwgQ2FzcGVyRGVsZWdhdGVUcmFuc2FjdGlvbjtcbiAgcHJvdGVjdGVkIF9leHBpcmF0aW9uOiBudW1iZXI7XG4gIHByb3RlY3RlZCBfbXVsdGlTaWduZXJLZXlQYWlyczogS2V5UGFpcltdO1xuICBwcm90ZWN0ZWQgX3NpZ25hdHVyZXM6IFNpZ25hdHVyZURhdGFbXTtcbiAgcHJvdGVjdGVkIF9jaGFpbk5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihfY29pbkNvbmZpZzogUmVhZG9ubHk8Q29pbkNvbmZpZz4pIHtcbiAgICBzdXBlcihfY29pbkNvbmZpZyk7XG4gICAgdGhpcy50cmFuc2FjdGlvbiA9IG5ldyBUcmFuc2FjdGlvbihfY29pbkNvbmZpZyk7XG4gICAgdGhpcy5fbXVsdGlTaWduZXJLZXlQYWlycyA9IFtdO1xuICAgIHRoaXMuX3NpZ25hdHVyZXMgPSBbXTtcbiAgICB0aGlzLl9jaGFpbk5hbWUgPSB0aGlzLmNvaW5OYW1lKCkgPT09ICdjc3ByJyA/IERFRkFVTFRfQ0hBSU5fTkFNRVMubWFpbm5ldCA6IERFRkFVTFRfQ0hBSU5fTkFNRVMudGVzdG5ldDtcbiAgfVxuXG4gIC8vIHJlZ2lvbiBCYXNlIEJ1aWxkZXJcbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHByb3RlY3RlZCBhc3luYyBidWlsZEltcGxlbWVudGF0aW9uKCk6IFByb21pc2U8VHJhbnNhY3Rpb24+IHtcbiAgICBjb25zdCBkZXBsb3lQYXJhbXMgPSB0aGlzLmdldERlcGxveVBhcmFtcygpO1xuICAgIGNvbnN0IHNlc3Npb24gPSB0aGlzLmdldFNlc3Npb24oKTtcblxuICAgIGNvbnN0IHBheW1lbnQgPSBEZXBsb3lVdGlsLnN0YW5kYXJkUGF5bWVudChfLnBhcnNlSW50KHRoaXMuX2ZlZS5nYXNMaW1pdCkpO1xuXG4gICAgbGV0IGNUcmFuc2FjdGlvbiA9IHRoaXMudHJhbnNhY3Rpb24uY2FzcGVyVHggfHwgRGVwbG95VXRpbC5tYWtlRGVwbG95KGRlcGxveVBhcmFtcywgc2Vzc2lvbiwgcGF5bWVudCk7XG5cbiAgICAvLyBDYW5ub3QgYWRkIGFyZ3VtZW50cyB0byBhbiBhbHJlYWR5IHNpZ25lZCBkZXBsb3kuXG4gICAgaWYgKGNUcmFuc2FjdGlvbi5hcHByb3ZhbHMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLl9zZXNzaW9uLmV4dHJhQXJndW1lbnRzLmZvckVhY2goKGV4dHJhQXJndW1lbnQsIGV4dHJhQXJndW1lbnROYW1lKSA9PiB7XG4gICAgICAgIGlmICghY1RyYW5zYWN0aW9uLnNlc3Npb24uZ2V0QXJnQnlOYW1lKGV4dHJhQXJndW1lbnROYW1lKSkge1xuICAgICAgICAgIGNUcmFuc2FjdGlvbiA9IERlcGxveVV0aWwuYWRkQXJnVG9EZXBsb3koY1RyYW5zYWN0aW9uLCBleHRyYUFyZ3VtZW50TmFtZSwgZXh0cmFBcmd1bWVudCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMudHJhbnNhY3Rpb24uY2FzcGVyVHggPSBjVHJhbnNhY3Rpb247XG5cbiAgICB0aGlzLnByb2Nlc3NTaWduaW5nKCk7XG5cbiAgICByZXR1cm4gdGhpcy50cmFuc2FjdGlvbjtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZnJvbUltcGxlbWVudGF0aW9uKHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcpOiBUcmFuc2FjdGlvbiB7XG4gICAgY29uc3QgdHggPSBuZXcgVHJhbnNhY3Rpb24odGhpcy5fY29pbkNvbmZpZyk7XG4gICAgY29uc3QganNvblRyYW5zYWN0aW9uID0gSlNPTi5wYXJzZShyYXdUcmFuc2FjdGlvbik7XG4gICAgdHguY2FzcGVyVHggPSBEZXBsb3lVdGlsLmRlcGxveUZyb21Kc29uKGpzb25UcmFuc2FjdGlvbikudW53cmFwKCk7XG4gICAgdGhpcy5pbml0QnVpbGRlcih0eCk7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIHNpZ25JbXBsZW1lbnRhdGlvbihrZXk6IEJhc2VLZXkpOiBUcmFuc2FjdGlvbiB7XG4gICAgdGhpcy5jaGVja0R1cGxpY2F0ZWRLZXlzKGtleSk7XG4gICAgY29uc3Qgc2lnbmVyID0gbmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSk7XG5cbiAgICAvLyBTaWduaW5nIHRoZSB0cmFuc2FjdGlvbiBpcyBhbiBvcGVyYXRpb24gdGhhdCByZWxpZXMgb24gYWxsIHRoZSBkYXRhIGJlaW5nIHNldCxcbiAgICAvLyBzbyB3ZSBzZXQgdGhlIHNvdXJjZSBoZXJlIGFuZCBsZWF2ZSB0aGUgYWN0dWFsIHNpZ25pbmcgZm9yIHRoZSBidWlsZCBzdGVwXG4gICAgdGhpcy5fbXVsdGlTaWduZXJLZXlQYWlycy5wdXNoKHNpZ25lcik7XG4gICAgcmV0dXJuIHRoaXMudHJhbnNhY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSB0aGUgdHJhbnNhY3Rpb24gYnVpbGRlciBmaWVsZHMgdXNpbmcgdGhlIGRlY29kZWQgdHJhbnNhY3Rpb24gZGF0YVxuICAgKlxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9ufSB0eCB0aGUgdHJhbnNhY3Rpb24gZGF0YVxuICAgKi9cbiAgaW5pdEJ1aWxkZXIodHg6IFRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy50cmFuc2FjdGlvbiA9IHR4O1xuICAgIHRoaXMudHJhbnNhY3Rpb24ubG9hZFByZXZpb3VzU2lnbmF0dXJlcygpO1xuICAgIGNvbnN0IHR4RGF0YSA9IHR4LnRvSnNvbigpO1xuICAgIHRoaXMuZmVlKHR4RGF0YS5mZWUpO1xuICAgIHRoaXMuc291cmNlKHsgYWRkcmVzczogdHhEYXRhLmZyb20gfSk7XG4gICAgdGhpcy5leHBpcmF0aW9uKHR4RGF0YS5leHBpcmF0aW9uIHx8IFRSQU5TQUNUSU9OX0VYUElSQVRJT04pO1xuICB9XG5cbiAgLy8gZW5kcmVnaW9uXG5cbiAgLy8gcmVnaW9uIENvbW1vbiBidWlsZGVyIG1ldGhvZHNcblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBmZWVzXG4gICAqXG4gICAqIEBwYXJhbSB7QmFzZUZlZX0gZmVlIFRoZSBtYXhpbXVtIGdhcyB0byBwYXlcbiAgICogQHJldHVybnMge1RyYW5zYWN0aW9uQnVpbGRlcn0gVGhpcyB0cmFuc2FjdGlvbiBidWlsZGVyXG4gICAqL1xuICBmZWUoZmVlOiBGZWUpOiB0aGlzIHtcbiAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcihmZWUuZ2FzTGltaXQpKTtcbiAgICB0aGlzLl9mZWUgPSBmZWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSB0cmFuc2FjdGlvbiBzb3VyY2VcbiAgICpcbiAgICogQHBhcmFtIHtCYXNlQWRkcmVzc30gYWRkcmVzcyBUaGUgc291cmNlIGFjY291bnRcbiAgICogQHJldHVybnMge1RyYW5zYWN0aW9uQnVpbGRlcn0gVGhpcyB0cmFuc2FjdGlvbiBidWlsZGVyXG4gICAqL1xuICBzb3VyY2UoYWRkcmVzczogQmFzZUFkZHJlc3MpOiB0aGlzIHtcbiAgICB0aGlzLnZhbGlkYXRlQWRkcmVzcyhhZGRyZXNzKTtcbiAgICB0aGlzLl9zb3VyY2UgPSBhZGRyZXNzO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgdHJhbnNhY3Rpb24gZXhwaXJhdGlvblRpbWVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV4cGlyYXRpb25UaW1lIFRoZSB0cmFuc2FjdGlvbiBleHBpcmF0aW9uVGltZVxuICAgKiBAcmV0dXJucyB7VHJhbnNhY3Rpb25CdWlsZGVyfSBUaGlzIHRyYW5zYWN0aW9uIGJ1aWxkZXJcbiAgICovXG4gIGV4cGlyYXRpb24oZXhwaXJhdGlvblRpbWU6IG51bWJlcik6IHRoaXMge1xuICAgIGNvbnN0IHRyYW5zYWN0aW9uRXhwaXJhdGlvbiA9IG5ldyBCaWdOdW1iZXIoZXhwaXJhdGlvblRpbWUpO1xuICAgIGlmICh0cmFuc2FjdGlvbkV4cGlyYXRpb24uaXNOYU4oKSB8fCB0cmFuc2FjdGlvbkV4cGlyYXRpb24uaXNHcmVhdGVyVGhhbihUUkFOU0FDVElPTl9FWFBJUkFUSU9OKSkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbiBleHBpcmF0aW9uJyk7XG4gICAgfVxuICAgIHRoaXMudmFsaWRhdGVWYWx1ZSh0cmFuc2FjdGlvbkV4cGlyYXRpb24pO1xuICAgIHRoaXMuX2V4cGlyYXRpb24gPSB0cmFuc2FjdGlvbkV4cGlyYXRpb24udG9OdW1iZXIoKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgYW4gZXh0ZXJuYWwgdHJhbnNhY3Rpb24gc2lnbmF0dXJlXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzaWduYXR1cmUgSGV4IGVuY29kZWQgc2lnbmF0dXJlIHN0cmluZ1xuICAgKiBAcGFyYW0ge0tleVBhaXJ9IGtleVBhaXIgVGhlIHB1YmxpYyBrZXkga2V5cGFpciB0aGF0IHdhcyB1c2VkIHRvIGNyZWF0ZSB0aGUgc2lnbmF0dXJlXG4gICAqIEByZXR1cm5zIHtUcmFuc2FjdGlvbkJ1aWxkZXJ9IFRoaXMgdHJhbnNhY3Rpb24gYnVpbGRlclxuICAgKi9cbiAgc2lnbmF0dXJlKHNpZ25hdHVyZTogc3RyaW5nLCBrZXlQYWlyOiBLZXlQYWlyKTogdGhpcyB7XG4gICAgLy8gaWYgd2UgYWxyZWFkeSBoYXZlIGEgc2lnbmF0dXJlIGZvciB0aGlzIGtleSBwYWlyLCBqdXN0IHVwZGF0ZSBpdFxuICAgIGZvciAoY29uc3Qgb2xkU2lnbmF0dXJlIG9mIHRoaXMuX3NpZ25hdHVyZXMpIHtcbiAgICAgIGlmIChvbGRTaWduYXR1cmUua2V5UGFpci5nZXRLZXlzKCkucHViID09PSBrZXlQYWlyLmdldEtleXMoKS5wdWIpIHtcbiAgICAgICAgb2xkU2lnbmF0dXJlLnNpZ25hdHVyZSA9IHNpZ25hdHVyZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gb3RoZXJ3aXNlIGFkZCB0aGUgbmV3IHNpZ25hdHVyZVxuICAgIHRoaXMuX3NpZ25hdHVyZXMucHVzaCh7IHNpZ25hdHVyZSwga2V5UGFpciB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIG5vZGVDaGFpbk5hbWUoY2hhaW5OYW1lOiBzdHJpbmcpOiB0aGlzIHtcbiAgICB0aGlzLl9jaGFpbk5hbWUgPSBjaGFpbk5hbWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvLyBlbmRyZWdpb25cblxuICAvLyByZWdpb24gVmFsaWRhdG9yc1xuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVBZGRyZXNzKGFkZHJlc3M6IEJhc2VBZGRyZXNzKTogdm9pZCB7XG4gICAgaWYgKCFpc1ZhbGlkQWRkcmVzcyhhZGRyZXNzLmFkZHJlc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGFkZHJlc3MgJyArIGFkZHJlc3MuYWRkcmVzcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlS2V5KGtleTogQmFzZUtleSk6IHZvaWQge1xuICAgIGlmICghbmV3IEtleVBhaXIoeyBwcnY6IGtleS5rZXkgfSkpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQga2V5Jyk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlUmF3VHJhbnNhY3Rpb24ocmF3VHJhbnNhY3Rpb246IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghcmF3VHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignUmF3IHRyYW5zYWN0aW9uIGlzIGVtcHR5Jyk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBEZXBsb3lVdGlsLmRlcGxveUZyb21Kc29uKEpTT04ucGFyc2UocmF3VHJhbnNhY3Rpb24pKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2VUcmFuc2FjdGlvbkVycm9yKCdUaGVyZSB3YXMgYW4gZXJyb3IgcGFyc2luZyB0aGUgSlNPTiBzdHJpbmcnKTtcbiAgICB9XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgdmFsaWRhdGVUcmFuc2FjdGlvbih0cmFuc2FjdGlvbj86IFRyYW5zYWN0aW9uKTogdm9pZCB7XG4gICAgdGhpcy52YWxpZGF0ZU1hbmRhdG9yeUZpZWxkcygpO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHZhbGlkYXRlVmFsdWUodmFsdWU6IEJpZ051bWJlcik6IHZvaWQge1xuICAgIGlmICh2YWx1ZS5pc0xlc3NUaGFuKDApKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdWYWx1ZSBjYW5ub3QgYmUgbGVzcyB0aGFuIHplcm8nKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoYXQgdGhlIG1hbmRhdG9yeSBmaWVsZHMgYXJlIGRlZmluZWRcbiAgICovXG4gIHZhbGlkYXRlTWFuZGF0b3J5RmllbGRzKCk6IHZvaWQge1xuICAgIHRoaXMudmFsaWRhdGVGZWUoKTtcbiAgICB0aGlzLnZhbGlkYXRlU291cmNlKCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHRoYXQgdGhlIGZlZSBmaWVsZCBpcyBkZWZpbmVkXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlRmVlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9mZWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignSW52YWxpZCB0cmFuc2FjdGlvbjogbWlzc2luZyBmZWUnKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLl9mZWUuZ2FzTGltaXQpIHtcbiAgICAgIHRocm93IG5ldyBCdWlsZFRyYW5zYWN0aW9uRXJyb3IoJ0ludmFsaWQgdHJhbnNhY3Rpb246IG1pc3NpbmcgZ2FzIGxpbWl0Jyk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICB0aGlzLnZhbGlkYXRlVmFsdWUobmV3IEJpZ051bWJlcih0aGlzLl9mZWUuZ2FzTGltaXQpKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIGdhcyBsaW1pdCcpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhhdCB0aGUgc291cmNlIGZpZWxkIGlzIGRlZmluZWRcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVTb3VyY2UoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX3NvdXJjZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQnVpbGRUcmFuc2FjdGlvbkVycm9yKCdJbnZhbGlkIHRyYW5zYWN0aW9uOiBtaXNzaW5nIHNvdXJjZScpO1xuICAgIH1cbiAgICB0aGlzLnZhbGlkYXRlQWRkcmVzcyh0aGlzLl9zb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGF0IHRoZSBnaXZlbiBrZXkgaXMgbm90IGFscmVhZHkgaW4gdGhpcy5fbXVsdGlTaWduZXJLZXlQYWlyc1xuICAgKlxuICAgKiBAcGFyYW0ge0Jhc2VLZXl9IGtleSAtIFRoZSBrZXkgdG8gY2hlY2tcbiAgICovXG4gIHByaXZhdGUgY2hlY2tEdXBsaWNhdGVkS2V5cyhrZXk6IEJhc2VLZXkpIHtcbiAgICB0aGlzLl9tdWx0aVNpZ25lcktleVBhaXJzLmZvckVhY2goKF9zb3VyY2VLZXlQYWlyKSA9PiB7XG4gICAgICBpZiAoX3NvdXJjZUtleVBhaXIuZ2V0S2V5cygpLnBydiA9PT0ga2V5LmtleSkge1xuICAgICAgICB0aHJvdyBuZXcgU2lnbmluZ0Vycm9yKCdSZXBlYXRlZCBzaWduOiAnICsga2V5LmtleSk7XG4gICAgICB9XG4gICAgICAvLyBUcnkgdG8gZ2V0IGV4dGVuZGVkIGtleXMgaW4gb3JkZXIgdG8gdmFsaWRhdGUgdGhlbVxuICAgICAgbGV0IHhwcnY7XG4gICAgICB0cnkge1xuICAgICAgICB4cHJ2ID0gX3NvdXJjZUtleVBhaXIuZ2V0RXh0ZW5kZWRLZXlzKCkueHBydjtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoeHBydiAmJiB4cHJ2ID09PSBrZXkua2V5KSB7XG4gICAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ1JlcGVhdGVkIHNpZ246ICcgKyBrZXkua2V5KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vIGVuZHJlZ2lvblxuXG4gIC8vIHJlZ2lvbiBHZXR0ZXJzIGFuZCBTZXR0ZXJzXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBwcm90ZWN0ZWQgZ2V0IHRyYW5zYWN0aW9uKCk6IFRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fdHJhbnNhY3Rpb247XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgcHJvdGVjdGVkIHNldCB0cmFuc2FjdGlvbih0cmFuc2FjdGlvbjogVHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLl90cmFuc2FjdGlvbiA9IHRyYW5zYWN0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY2hhaW4gbmFtZSBmb3IgdGhlIGNvaW4gZW52aXJvbm1lbnRcbiAgICovXG4gIHB1YmxpYyBnZXQgY2hhaW5OYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2NoYWluTmFtZTtcbiAgfVxuICAvLyBlbmRyZWdpb25cblxuICAvLyByZWdpb24gYXV4aWxpYXJ5TWV0aG9kc1xuICAvKipcbiAgICogR2VuZXJhdGUgYSBEZXBsb3lQYXJhbXMgaW5zdGFuY2Ugd2l0aCB0aGUgdHJhbnNhY3Rpb24gZGF0YVxuICAgKlxuICAgKiBAcmV0dXJucyB7RGVwbG95VXRpbC5EZXBsb3lQYXJhbXN9XG4gICAqL1xuICBwcml2YXRlIGdldERlcGxveVBhcmFtcygpOiBEZXBsb3lVdGlsLkRlcGxveVBhcmFtcyB7XG4gICAgY29uc3QgZ2FzUHJpY2UgPSB0aGlzLl9mZWUuZ2FzUHJpY2UgPyBfLnBhcnNlSW50KHRoaXMuX2ZlZS5nYXNQcmljZSkgOiB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIG5ldyBEZXBsb3lVdGlsLkRlcGxveVBhcmFtcyhcbiAgICAgIFB1YmxpY0tleS5mcm9tSGV4KHRoaXMuX3NvdXJjZS5hZGRyZXNzKSxcbiAgICAgIHRoaXMuX2NoYWluTmFtZSxcbiAgICAgIGdhc1ByaWNlLFxuICAgICAgdGhpcy5fZXhwaXJhdGlvbiB8fCBUUkFOU0FDVElPTl9FWFBJUkFUSU9OXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSB0aGUgc2Vzc2lvbiBmb3IgdGhlIERlcGxveSBhY2NvcmRpbmcgdG8gdGhlIHRyYW5zYWN0aW9uVHlwZS5cbiAgICpcbiAgICogQHJldHVybnMge0RlcGxveVV0aWwuRXhlY3V0YWJsZURlcGxveUl0ZW19XG4gICAqL1xuICBwcml2YXRlIGdldFNlc3Npb24oKTogRGVwbG95VXRpbC5FeGVjdXRhYmxlRGVwbG95SXRlbSB7XG4gICAgbGV0IHNlc3Npb247XG4gICAgc3dpdGNoICh0aGlzLnRyYW5zYWN0aW9uLnR5cGUpIHtcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICAgIGNvbnN0IHRyYW5zZmVyU2Vzc2lvbiA9IHRoaXMuX3Nlc3Npb24gYXMgQ2FzcGVyVHJhbnNmZXJUcmFuc2FjdGlvbjtcbiAgICAgICAgc2Vzc2lvbiA9IERlcGxveVV0aWwuRXhlY3V0YWJsZURlcGxveUl0ZW0ubmV3VHJhbnNmZXJXaXRoT3B0aW9uYWxUcmFuc2ZlcklkKFxuICAgICAgICAgIHRyYW5zZmVyU2Vzc2lvbi5hbW91bnQsXG4gICAgICAgICAgdHJhbnNmZXJTZXNzaW9uLnRhcmdldCxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgdHJhbnNmZXJTZXNzaW9uLmlkXG4gICAgICAgICk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuV2FsbGV0SW5pdGlhbGl6YXRpb246XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nTG9jazpcbiAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdVbmxvY2s6XG4gICAgICAgIGNvbnN0IG1vZHVsZUJ5dGVzU2Vzc2lvbiA9IHRoaXMuX3Nlc3Npb24gYXMgQ2FzcGVyTW9kdWxlQnl0ZXNUcmFuc2FjdGlvbjtcbiAgICAgICAgc2Vzc2lvbiA9IERlcGxveVV0aWwuRXhlY3V0YWJsZURlcGxveUl0ZW0ubmV3TW9kdWxlQnl0ZXMoXG4gICAgICAgICAgbW9kdWxlQnl0ZXNTZXNzaW9uLm1vZHVsZUJ5dGVzLFxuICAgICAgICAgIG1vZHVsZUJ5dGVzU2Vzc2lvbi5hcmdzXG4gICAgICAgICk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEJ1aWxkVHJhbnNhY3Rpb25FcnJvcignVHJhbnNhY3Rpb24gVHlwZSBlcnJvcicpO1xuICAgIH1cbiAgICByZXR1cm4gc2Vzc2lvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVja3Mgd2hldGhlciB0aGUgdHJhbnNhY3Rpb24gaGFzIHRoZSBvd25lciBzaWduYXR1cmVcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHB1YiAtIHB1YmxpYyBrZXkgb2YgdGhlIHNpZ25lclxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgcHViIGtleSBhbHJlYWR5IHNpZ25lZCB0aCB0cmFuc2FjdGlvblxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBpc1RyYW5zYWN0aW9uU2lnbmVkQnlQdWIocHViOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgXy5maW5kSW5kZXgodGhpcy50cmFuc2FjdGlvbi5jYXNwZXJUeC5hcHByb3ZhbHMsIChhcHByb3ZhbCkgPT4ge1xuICAgICAgICBjb25zdCBhcHByb3ZhbFNpZ25lciA9IHJlbW92ZUFsZ29QcmVmaXhGcm9tSGV4VmFsdWUoYXBwcm92YWwuc2lnbmVyKTtcbiAgICAgICAgcmV0dXJuIGFwcHJvdmFsU2lnbmVyID09PSBwdWI7XG4gICAgICB9KSAhPT0gLTFcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBzaWduYXR1cmVzIHRvIHRoZSB0cmFuc2FjdGlvblxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBwcm9jZXNzU2lnbmluZygpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGtleVBhaXIgb2YgdGhpcy5fbXVsdGlTaWduZXJLZXlQYWlycykge1xuICAgICAgLy8gQWRkIHNpZ25hdHVyZSBpZiBpdCdzIG5vdCBhbHJlYWR5IGluIHRoZSBkZXBsb3lcbiAgICAgIGlmICghdGhpcy5pc1RyYW5zYWN0aW9uU2lnbmVkQnlQdWIoa2V5UGFpci5nZXRLZXlzKCkucHViKSkge1xuICAgICAgICB0aGlzLnRyYW5zYWN0aW9uLnNpZ24oa2V5UGFpcik7XG4gICAgICB9XG4gICAgfVxuICAgIGZvciAoY29uc3QgeyBzaWduYXR1cmUsIGtleVBhaXIgfSBvZiB0aGlzLl9zaWduYXR1cmVzKSB7XG4gICAgICAvLyBBZGQgc2lnbmF0dXJlIGlmIGl0J3Mgbm90IGFscmVhZHkgaW4gdGhlIGRlcGxveVxuICAgICAgaWYgKCF0aGlzLmlzVHJhbnNhY3Rpb25TaWduZWRCeVB1YihrZXlQYWlyLmdldEtleXMoKS5wdWIpKSB7XG4gICAgICAgIHRoaXMudHJhbnNhY3Rpb24uYWRkU2lnbmF0dXJlKHNpZ25hdHVyZSwga2V5UGFpcik7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIC8vIGVuZHJlZ2lvblxufVxuIl19Выполнить команду
Для локальной разработки. Не используйте в интернете!