PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-coin-sol/dist/src/lib

Просмотр файла: transaction.js

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transaction = void 0;
const sdk_core_1 = require("@bitgo/sdk-core");
const web3_js_1 = require("@solana/web3.js");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const bs58_1 = __importDefault(require("bs58"));
const constants_1 = require("./constants");
const instructionParamsFactory_1 = require("./instructionParamsFactory");
const utils_1 = require("./utils");
class Transaction extends sdk_core_1.BaseTransaction {
    constructor(_coinConfig) {
        super(_coinConfig);
    }
    get solTransaction() {
        return this._solTransaction;
    }
    set solTransaction(tx) {
        this._solTransaction = tx;
    }
    get numberOfRequiredSignatures() {
        return this._solTransaction.compileMessage().header.numRequiredSignatures;
    }
    get numberOfATACreationInstructions() {
        return this._solTransaction.instructions.filter((instruction) => (0, utils_1.getInstructionType)(instruction) === constants_1.ValidInstructionTypesEnum.InitializeAssociatedTokenAccount).length;
    }
    /** @inheritDoc */
    get signablePayload() {
        return this._solTransaction.serializeMessage();
    }
    /** @inheritDoc **/
    get id() {
        // Solana transaction ID === first signature: https://docs.solana.com/terminology#transaction-id
        if (this._solTransaction.signature) {
            return bs58_1.default.encode(this._solTransaction.signature);
        }
        else {
            return constants_1.UNAVAILABLE_TEXT;
        }
    }
    get lamportsPerSignature() {
        return this._lamportsPerSignature;
    }
    set lamportsPerSignature(lamportsPerSignature) {
        this._lamportsPerSignature = lamportsPerSignature;
    }
    get tokenAccountRentExemptAmount() {
        return this._tokenAccountRentExemptAmount;
    }
    set tokenAccountRentExemptAmount(tokenAccountRentExemptAmount) {
        this._tokenAccountRentExemptAmount = tokenAccountRentExemptAmount;
    }
    /** @inheritDoc */
    get signature() {
        const signatures = [];
        for (const solSignature of this._solTransaction.signatures) {
            if (solSignature.signature) {
                signatures.push(bs58_1.default.encode(solSignature.signature));
            }
        }
        return signatures;
    }
    /**
     * Set the transaction type.
     *
     * @param {TransactionType} transactionType The transaction type to be set.
     */
    setTransactionType(transactionType) {
        this._type = transactionType;
    }
    /** @inheritdoc */
    canSign() {
        return true;
    }
    /**
     * Signs transaction.
     *
     * @param {KeyPair} keyPair Signer keys.
     */
    async sign(keyPair) {
        if (!this._solTransaction || !this._solTransaction.recentBlockhash) {
            throw new sdk_core_1.SigningError('Nonce is required before signing');
        }
        if (!this._solTransaction || !this._solTransaction.feePayer) {
            throw new sdk_core_1.SigningError('feePayer is required before signing');
        }
        const keyPairs = keyPair instanceof Array ? keyPair : [keyPair];
        const signers = [];
        for (const kp of keyPairs) {
            const keys = kp.getKeys(true);
            if (!keys.prv) {
                throw new sdk_core_1.SigningError('Missing private key');
            }
            signers.push({ publicKey: new web3_js_1.PublicKey(keys.pub), secretKey: keys.prv });
        }
        try {
            this._solTransaction.partialSign(...signers);
        }
        catch (e) {
            throw e;
        }
    }
    /** @inheritdoc */
    toBroadcastFormat() {
        if (!this._solTransaction) {
            throw new sdk_core_1.ParseTransactionError('Empty transaction');
        }
        // The signatures can have null signatures (which means they are required but yet unsigned)
        // In order to be able to serializer the txs, we have to change the requireAllSignatures based
        // on if the TX is fully signed or not
        const requireAllSignatures = (0, utils_1.requiresAllSignatures)(this._solTransaction.signatures);
        try {
            // Based on the recomendation encoding found here https://docs.solana.com/developing/clients/jsonrpc-api#sendtransaction
            // We use base64 encoding
            return this._solTransaction.serialize({ requireAllSignatures }).toString('base64');
        }
        catch (e) {
            throw e;
        }
    }
    /**
     * Sets this transaction payload
     *
     * @param rawTransaction
     */
    fromRawTransaction(rawTransaction) {
        try {
            (0, utils_1.isValidRawTransaction)(rawTransaction);
            this._solTransaction = web3_js_1.Transaction.from(Buffer.from(rawTransaction, 'base64'));
            if (this._solTransaction.signature && this._solTransaction.signature !== null) {
                this._id = bs58_1.default.encode(this._solTransaction.signature);
            }
            const transactionType = (0, utils_1.getTransactionType)(this._solTransaction);
            switch (transactionType) {
                case sdk_core_1.TransactionType.WalletInitialization:
                    this.setTransactionType(sdk_core_1.TransactionType.WalletInitialization);
                    break;
                case sdk_core_1.TransactionType.Send:
                    this.setTransactionType(sdk_core_1.TransactionType.Send);
                    break;
                case sdk_core_1.TransactionType.StakingActivate:
                    this.setTransactionType(sdk_core_1.TransactionType.StakingActivate);
                    break;
                case sdk_core_1.TransactionType.StakingDeactivate:
                    this.setTransactionType(sdk_core_1.TransactionType.StakingDeactivate);
                    break;
                case sdk_core_1.TransactionType.StakingWithdraw:
                    this.setTransactionType(sdk_core_1.TransactionType.StakingWithdraw);
                    break;
                case sdk_core_1.TransactionType.AssociatedTokenAccountInitialization:
                    this.setTransactionType(sdk_core_1.TransactionType.AssociatedTokenAccountInitialization);
                    break;
                case sdk_core_1.TransactionType.CloseAssociatedTokenAccount:
                    this.setTransactionType(sdk_core_1.TransactionType.CloseAssociatedTokenAccount);
                    break;
                case sdk_core_1.TransactionType.StakingAuthorize:
                    this.setTransactionType(sdk_core_1.TransactionType.StakingAuthorize);
                    break;
                case sdk_core_1.TransactionType.StakingAuthorizeRaw:
                    this.setTransactionType(sdk_core_1.TransactionType.StakingAuthorizeRaw);
                    break;
                case sdk_core_1.TransactionType.StakingDelegate:
                    this.setTransactionType(sdk_core_1.TransactionType.StakingDelegate);
                    break;
            }
            if (transactionType !== sdk_core_1.TransactionType.StakingAuthorizeRaw) {
                this.loadInputsAndOutputs();
            }
        }
        catch (e) {
            throw e;
        }
    }
    /** @inheritdoc */
    toJson() {
        if (!this._solTransaction) {
            throw new sdk_core_1.ParseTransactionError('Empty transaction');
        }
        let durableNonce;
        if (this._solTransaction.nonceInfo) {
            const nonceInstruction = web3_js_1.SystemInstruction.decodeNonceAdvance(this._solTransaction.nonceInfo.nonceInstruction);
            durableNonce = {
                walletNonceAddress: nonceInstruction.noncePubkey.toString(),
                authWalletAddress: nonceInstruction.authorizedPubkey.toString(),
            };
        }
        const instructionData = (0, instructionParamsFactory_1.instructionParamsFactory)(this._type, this._solTransaction.instructions, this._coinConfig.name);
        if (this._type) {
            if (!durableNonce &&
                instructionData.length > 1 &&
                instructionData[0].type === constants_1.InstructionBuilderTypes.NonceAdvance) {
                durableNonce = instructionData[0].params;
            }
        }
        const result = {
            id: this._solTransaction.signature ? this.id : undefined,
            feePayer: this._solTransaction.feePayer?.toString(),
            lamportsPerSignature: this.lamportsPerSignature,
            nonce: this.getNonce(),
            durableNonce: durableNonce,
            numSignatures: this.signature.length,
            instructionsData: instructionData,
        };
        return result;
    }
    /**
     * Get the nonce from the Solana Transaction
     * Throws if not set
     */
    getNonce() {
        if (this._solTransaction.recentBlockhash) {
            return this._solTransaction.recentBlockhash;
        }
        else if (this._solTransaction.nonceInfo) {
            return this._solTransaction.nonceInfo.nonce;
        }
        else {
            throw new sdk_core_1.InvalidTransactionError('Nonce is not set');
        }
    }
    /**
     * Load the input and output data on this transaction.
     */
    loadInputsAndOutputs() {
        if (!this._solTransaction || this._solTransaction.instructions?.length === 0) {
            return;
        }
        const outputs = [];
        const inputs = [];
        const instructionParams = (0, instructionParamsFactory_1.instructionParamsFactory)(this.type, this._solTransaction.instructions, this._coinConfig.name);
        for (const instruction of instructionParams) {
            switch (instruction.type) {
                case constants_1.InstructionBuilderTypes.CreateNonceAccount:
                    inputs.push({
                        address: instruction.params.fromAddress,
                        value: instruction.params.amount,
                        coin: this._coinConfig.name,
                    });
                    break;
                case constants_1.InstructionBuilderTypes.Transfer:
                    inputs.push({
                        address: instruction.params.fromAddress,
                        value: instruction.params.amount,
                        coin: this._coinConfig.name,
                    });
                    outputs.push({
                        address: instruction.params.toAddress,
                        value: instruction.params.amount,
                        coin: this._coinConfig.name,
                    });
                    break;
                case constants_1.InstructionBuilderTypes.TokenTransfer:
                    inputs.push({
                        address: instruction.params.fromAddress,
                        value: instruction.params.amount,
                        coin: instruction.params.tokenName,
                    });
                    outputs.push({
                        address: instruction.params.toAddress,
                        value: instruction.params.amount,
                        coin: instruction.params.tokenName,
                    });
                    break;
                case constants_1.InstructionBuilderTypes.StakingActivate:
                    inputs.push({
                        address: instruction.params.fromAddress,
                        value: instruction.params.amount,
                        coin: this._coinConfig.name,
                    });
                    outputs.push({
                        address: instruction.params.stakingAddress,
                        value: instruction.params.amount,
                        coin: this._coinConfig.name,
                    });
                    break;
                case constants_1.InstructionBuilderTypes.StakingDeactivate:
                    if (instruction.params.amount && instruction.params.unstakingAddress) {
                        inputs.push({
                            address: instruction.params.stakingAddress,
                            value: instruction.params.amount,
                            coin: this._coinConfig.name,
                        });
                        outputs.push({
                            address: instruction.params.unstakingAddress,
                            value: instruction.params.amount,
                            coin: this._coinConfig.name,
                        });
                    }
                    break;
                case constants_1.InstructionBuilderTypes.StakingWithdraw:
                    inputs.push({
                        address: instruction.params.stakingAddress,
                        value: instruction.params.amount,
                        coin: this._coinConfig.name,
                    });
                    outputs.push({
                        address: instruction.params.fromAddress,
                        value: instruction.params.amount,
                        coin: this._coinConfig.name,
                    });
                    break;
                case constants_1.InstructionBuilderTypes.CreateAssociatedTokenAccount:
                    break;
                case constants_1.InstructionBuilderTypes.CloseAssociatedTokenAccount:
                    break;
                case constants_1.InstructionBuilderTypes.StakingAuthorize:
                    break;
                case constants_1.InstructionBuilderTypes.StakingDelegate:
                    break;
                case constants_1.InstructionBuilderTypes.SetPriorityFee:
                    break;
            }
        }
        this._outputs = outputs;
        this._inputs = inputs;
    }
    /** @inheritDoc */
    explainTransaction() {
        if ((0, utils_1.validateRawMsgInstruction)(this._solTransaction.instructions)) {
            return this.explainRawMsgAuthorizeTransaction();
        }
        const decodedInstructions = (0, instructionParamsFactory_1.instructionParamsFactory)(this._type, this._solTransaction.instructions, this._coinConfig.name);
        let memo = undefined;
        let durableNonce = undefined;
        let outputAmount = new bignumber_js_1.default(0);
        const outputs = [];
        for (const instruction of decodedInstructions) {
            switch (instruction.type) {
                case constants_1.InstructionBuilderTypes.NonceAdvance:
                    durableNonce = instruction.params;
                    break;
                case constants_1.InstructionBuilderTypes.Memo:
                    memo = instruction.params.memo;
                    break;
                case constants_1.InstructionBuilderTypes.Transfer:
                    const transferInstruction = instruction;
                    outputs.push({
                        address: transferInstruction.params.toAddress,
                        amount: transferInstruction.params.amount,
                    });
                    outputAmount = outputAmount.plus(transferInstruction.params.amount);
                    break;
                case constants_1.InstructionBuilderTypes.TokenTransfer:
                    const tokenTransferInstruction = instruction;
                    outputs.push({
                        address: tokenTransferInstruction.params.toAddress,
                        amount: tokenTransferInstruction.params.amount,
                        tokenName: tokenTransferInstruction.params.tokenName,
                    });
                    break;
                case constants_1.InstructionBuilderTypes.CreateNonceAccount:
                    const createInstruction = instruction;
                    outputs.push({
                        address: createInstruction.params.nonceAddress,
                        amount: createInstruction.params.amount,
                    });
                    outputAmount = outputAmount.plus(createInstruction.params.amount);
                    break;
                case constants_1.InstructionBuilderTypes.StakingActivate:
                    const stakingActivateInstruction = instruction;
                    outputs.push({
                        address: stakingActivateInstruction.params.stakingAddress,
                        amount: stakingActivateInstruction.params.amount,
                    });
                    outputAmount = outputAmount.plus(stakingActivateInstruction.params.amount);
                    break;
                case constants_1.InstructionBuilderTypes.StakingWithdraw:
                    const stakingWithdrawInstruction = instruction;
                    outputs.push({
                        address: stakingWithdrawInstruction.params.fromAddress,
                        amount: stakingWithdrawInstruction.params.amount,
                    });
                    outputAmount = outputAmount.plus(stakingWithdrawInstruction.params.amount);
                    break;
                case constants_1.InstructionBuilderTypes.CreateAssociatedTokenAccount:
                    break;
                default:
                    continue;
            }
            // After deserializing a transaction, durable nonce details are populated in the nonceInfo field
            if (!durableNonce && this._solTransaction.nonceInfo) {
                const nonceAdvanceInstruction = web3_js_1.SystemInstruction.decodeNonceAdvance(this._solTransaction.nonceInfo.nonceInstruction);
                durableNonce = {
                    authWalletAddress: nonceAdvanceInstruction.authorizedPubkey.toString(),
                    walletNonceAddress: nonceAdvanceInstruction.noncePubkey.toString(),
                };
            }
        }
        return this.getExplainedTransaction(outputAmount, outputs, memo, durableNonce);
    }
    calculateFee() {
        if (this.lamportsPerSignature || this.tokenAccountRentExemptAmount) {
            const signatureFees = this.lamportsPerSignature
                ? new bignumber_js_1.default(this.lamportsPerSignature).multipliedBy(this.numberOfRequiredSignatures).toFixed(0)
                : 0;
            const rentFees = this.tokenAccountRentExemptAmount
                ? new bignumber_js_1.default(this.tokenAccountRentExemptAmount).multipliedBy(this.numberOfATACreationInstructions).toFixed(0)
                : 0;
            return new bignumber_js_1.default(signatureFees).plus(rentFees).toFixed(0);
        }
        return constants_1.UNAVAILABLE_TEXT;
    }
    getExplainedTransaction(outputAmount, outputs, memo = undefined, durableNonce = undefined) {
        const feeString = this.calculateFee();
        return {
            displayOrder: [
                'id',
                'type',
                'blockhash',
                'durableNonce',
                'outputAmount',
                'changeAmount',
                'outputs',
                'changeOutputs',
                'fee',
                'memo',
            ],
            id: this.id,
            type: sdk_core_1.TransactionType[this.type].toString(),
            changeOutputs: [],
            changeAmount: '0',
            outputAmount: outputAmount.toFixed(0),
            outputs: outputs,
            fee: {
                fee: feeString,
                feeRate: this.lamportsPerSignature,
            },
            memo: memo,
            blockhash: this.getNonce(),
            durableNonce: durableNonce,
        };
    }
    explainRawMsgAuthorizeTransaction() {
        const { instructions } = this._solTransaction;
        const nonceInstruction = web3_js_1.SystemInstruction.decodeNonceAdvance(instructions[0]);
        const durableNonce = {
            walletNonceAddress: nonceInstruction.noncePubkey.toString(),
            authWalletAddress: nonceInstruction.authorizedPubkey.toString(),
        };
        const data = instructions[1].data.toString('hex');
        const stakingAuthorizeParams = data === constants_1.validInstructionData
            ? {
                stakingAddress: instructions[1].keys[0].pubkey.toString(),
                oldWithdrawAddress: instructions[1].keys[2].pubkey.toString(),
                newWithdrawAddress: instructions[1].keys[3].pubkey.toString(),
                custodianAddress: instructions[1].keys[4].pubkey.toString(),
            }
            : {
                stakingAddress: instructions[1].keys[0].pubkey.toString(),
                oldWithdrawAddress: '',
                newWithdrawAddress: '',
                oldStakingAuthorityAddress: instructions[1].keys[2].pubkey.toString(),
                newStakingAuthorityAddress: instructions[1].keys[3].pubkey.toString(),
            };
        const feeString = this.calculateFee();
        return {
            displayOrder: [
                'id',
                'type',
                'blockhash',
                'durableNonce',
                'outputAmount',
                'changeAmount',
                'outputs',
                'changeOutputs',
                'fee',
                'memo',
            ],
            id: this.id,
            type: sdk_core_1.TransactionType[this.type].toString(),
            changeOutputs: [],
            changeAmount: '0',
            outputAmount: 0,
            outputs: [],
            fee: {
                fee: feeString,
                feeRate: this.lamportsPerSignature,
            },
            blockhash: this.getNonce(),
            durableNonce: durableNonce,
            stakingAuthorize: stakingAuthorizeParams,
        };
    }
}
exports.Transaction = Transaction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDhDQVF5QjtBQUV6Qiw2Q0FBaUg7QUFDakgsZ0VBQXFDO0FBQ3JDLGdEQUEwQjtBQUUxQiwyQ0FLcUI7QUFjckIseUVBQXNFO0FBQ3RFLG1DQU1pQjtBQUVqQixNQUFhLFdBQVksU0FBUSwwQkFBZTtJQU05QyxZQUFZLFdBQWlDO1FBQzNDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNyQixDQUFDO0lBRUQsSUFBSSxjQUFjO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQztJQUM5QixDQUFDO0lBRUQsSUFBSSxjQUFjLENBQUMsRUFBa0I7UUFDbkMsSUFBSSxDQUFDLGVBQWUsR0FBRyxFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVELElBQVksMEJBQTBCO1FBQ3BDLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxNQUFNLENBQUMscUJBQXFCLENBQUM7SUFDNUUsQ0FBQztJQUVELElBQVksK0JBQStCO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUM3QyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsSUFBQSwwQkFBa0IsRUFBQyxXQUFXLENBQUMsS0FBSyxxQ0FBeUIsQ0FBQyxnQ0FBZ0MsQ0FDaEgsQ0FBQyxNQUFNLENBQUM7SUFDWCxDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLElBQUksZUFBZTtRQUNqQixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUNqRCxDQUFDO0lBRUQsbUJBQW1CO0lBQ25CLElBQUksRUFBRTtRQUNKLGdHQUFnRztRQUNoRyxJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbkMsT0FBTyxjQUFNLENBQUMs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LFxuICBFbnRyeSxcbiAgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IsXG4gIFBhcnNlVHJhbnNhY3Rpb25FcnJvcixcbiAgU2lnbmluZ0Vycm9yLFxuICBUcmFuc2FjdGlvblJlY2lwaWVudCxcbiAgVHJhbnNhY3Rpb25UeXBlLFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgQmFzZUNvaW4gYXMgQ29pbkNvbmZpZyB9IGZyb20gJ0BiaXRnby9zdGF0aWNzJztcbmltcG9ydCB7IEJsb2NraGFzaCwgUHVibGljS2V5LCBTaWduZXIsIFRyYW5zYWN0aW9uIGFzIFNvbFRyYW5zYWN0aW9uLCBTeXN0ZW1JbnN0cnVjdGlvbiB9IGZyb20gJ0Bzb2xhbmEvd2ViMy5qcyc7XG5pbXBvcnQgQmlnTnVtYmVyIGZyb20gJ2JpZ251bWJlci5qcyc7XG5pbXBvcnQgYmFzZTU4IGZyb20gJ2JzNTgnO1xuaW1wb3J0IHsgS2V5UGFpciB9IGZyb20gJy4nO1xuaW1wb3J0IHtcbiAgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMsXG4gIFVOQVZBSUxBQkxFX1RFWFQsXG4gIHZhbGlkSW5zdHJ1Y3Rpb25EYXRhLFxuICBWYWxpZEluc3RydWN0aW9uVHlwZXNFbnVtLFxufSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQge1xuICBEdXJhYmxlTm9uY2VQYXJhbXMsXG4gIE1lbW8sXG4gIE5vbmNlLFxuICBTdGFraW5nQWN0aXZhdGUsXG4gIFN0YWtpbmdBdXRob3JpemVQYXJhbXMsXG4gIFN0YWtpbmdXaXRoZHJhdyxcbiAgVG9rZW5UcmFuc2ZlcixcbiAgVHJhbnNhY3Rpb25FeHBsYW5hdGlvbixcbiAgVHJhbnNmZXIsXG4gIFR4RGF0YSxcbiAgV2FsbGV0SW5pdCxcbn0gZnJvbSAnLi9pZmFjZSc7XG5pbXBvcnQgeyBpbnN0cnVjdGlvblBhcmFtc0ZhY3RvcnkgfSBmcm9tICcuL2luc3RydWN0aW9uUGFyYW1zRmFjdG9yeSc7XG5pbXBvcnQge1xuICBnZXRJbnN0cnVjdGlvblR5cGUsXG4gIGdldFRyYW5zYWN0aW9uVHlwZSxcbiAgaXNWYWxpZFJhd1RyYW5zYWN0aW9uLFxuICByZXF1aXJlc0FsbFNpZ25hdHVyZXMsXG4gIHZhbGlkYXRlUmF3TXNnSW5zdHJ1Y3Rpb24sXG59IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgVHJhbnNhY3Rpb24gZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb24ge1xuICBwcm90ZWN0ZWQgX3NvbFRyYW5zYWN0aW9uOiBTb2xUcmFuc2FjdGlvbjtcbiAgcHJpdmF0ZSBfbGFtcG9ydHNQZXJTaWduYXR1cmU6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfdG9rZW5BY2NvdW50UmVudEV4ZW1wdEFtb3VudDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwcm90ZWN0ZWQgX3R5cGU6IFRyYW5zYWN0aW9uVHlwZTtcblxuICBjb25zdHJ1Y3RvcihfY29pbkNvbmZpZzogUmVhZG9ubHk8Q29pbkNvbmZpZz4pIHtcbiAgICBzdXBlcihfY29pbkNvbmZpZyk7XG4gIH1cblxuICBnZXQgc29sVHJhbnNhY3Rpb24oKTogU29sVHJhbnNhY3Rpb24ge1xuICAgIHJldHVybiB0aGlzLl9zb2xUcmFuc2FjdGlvbjtcbiAgfVxuXG4gIHNldCBzb2xUcmFuc2FjdGlvbih0eDogU29sVHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLl9zb2xUcmFuc2FjdGlvbiA9IHR4O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgbnVtYmVyT2ZSZXF1aXJlZFNpZ25hdHVyZXMoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fc29sVHJhbnNhY3Rpb24uY29tcGlsZU1lc3NhZ2UoKS5oZWFkZXIubnVtUmVxdWlyZWRTaWduYXR1cmVzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgbnVtYmVyT2ZBVEFDcmVhdGlvbkluc3RydWN0aW9ucygpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9zb2xUcmFuc2FjdGlvbi5pbnN0cnVjdGlvbnMuZmlsdGVyKFxuICAgICAgKGluc3RydWN0aW9uKSA9PiBnZXRJbnN0cnVjdGlvblR5cGUoaW5zdHJ1Y3Rpb24pID09PSBWYWxpZEluc3RydWN0aW9uVHlwZXNFbnVtLkluaXRpYWxpemVBc3NvY2lhdGVkVG9rZW5BY2NvdW50XG4gICAgKS5sZW5ndGg7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgZ2V0IHNpZ25hYmxlUGF5bG9hZCgpOiBCdWZmZXIge1xuICAgIHJldHVybiB0aGlzLl9zb2xUcmFuc2FjdGlvbi5zZXJpYWxpemVNZXNzYWdlKCk7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKiovXG4gIGdldCBpZCgpOiBzdHJpbmcge1xuICAgIC8vIFNvbGFuYSB0cmFuc2FjdGlvbiBJRCA9PT0gZmlyc3Qgc2lnbmF0dXJlOiBodHRwczovL2RvY3Muc29sYW5hLmNvbS90ZXJtaW5vbG9neSN0cmFuc2FjdGlvbi1pZFxuICAgIGlmICh0aGlzLl9zb2xUcmFuc2FjdGlvbi5zaWduYXR1cmUpIHtcbiAgICAgIHJldHVybiBiYXNlNTguZW5jb2RlKHRoaXMuX3NvbFRyYW5zYWN0aW9uLnNpZ25hdHVyZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBVTkFWQUlMQUJMRV9URVhUO1xuICAgIH1cbiAgfVxuXG4gIGdldCBsYW1wb3J0c1BlclNpZ25hdHVyZSgpOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9sYW1wb3J0c1BlclNpZ25hdHVyZTtcbiAgfVxuXG4gIHNldCBsYW1wb3J0c1BlclNpZ25hdHVyZShsYW1wb3J0c1BlclNpZ25hdHVyZTogbnVtYmVyIHwgdW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fbGFtcG9ydHNQZXJTaWduYXR1cmUgPSBsYW1wb3J0c1BlclNpZ25hdHVyZTtcbiAgfVxuXG4gIGdldCB0b2tlbkFjY291bnRSZW50RXhlbXB0QW1vdW50KCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3Rva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnQ7XG4gIH1cblxuICBzZXQgdG9rZW5BY2NvdW50UmVudEV4ZW1wdEFtb3VudCh0b2tlbkFjY291bnRSZW50RXhlbXB0QW1vdW50OiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl90b2tlbkFjY291bnRSZW50RXhlbXB0QW1vdW50ID0gdG9rZW5BY2NvdW50UmVudEV4ZW1wdEFtb3VudDtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdERvYyAqL1xuICBnZXQgc2lnbmF0dXJlKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBzaWduYXR1cmVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBzb2xTaWduYXR1cmUgb2YgdGhpcy5fc29sVHJhbnNhY3Rpb24uc2lnbmF0dXJlcykge1xuICAgICAgaWYgKHNvbFNpZ25hdHVyZS5zaWduYXR1cmUpIHtcbiAgICAgICAgc2lnbmF0dXJlcy5wdXNoKGJhc2U1OC5lbmNvZGUoc29sU2lnbmF0dXJlLnNpZ25hdHVyZSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzaWduYXR1cmVzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgdHJhbnNhY3Rpb24gdHlwZS5cbiAgICpcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvblR5cGV9IHRyYW5zYWN0aW9uVHlwZSBUaGUgdHJhbnNhY3Rpb24gdHlwZSB0byBiZSBzZXQuXG4gICAqL1xuICBzZXRUcmFuc2FjdGlvblR5cGUodHJhbnNhY3Rpb25UeXBlOiBUcmFuc2FjdGlvblR5cGUpOiB2b2lkIHtcbiAgICB0aGlzLl90eXBlID0gdHJhbnNhY3Rpb25UeXBlO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIGNhblNpZ24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU2lnbnMgdHJhbnNhY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB7S2V5UGFpcn0ga2V5UGFpciBTaWduZXIga2V5cy5cbiAgICovXG4gIGFzeW5jIHNpZ24oa2V5UGFpcjogS2V5UGFpcltdIHwgS2V5UGFpcik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5fc29sVHJhbnNhY3Rpb24gfHwgIXRoaXMuX3NvbFRyYW5zYWN0aW9uLnJlY2VudEJsb2NraGFzaCkge1xuICAgICAgdGhyb3cgbmV3IFNpZ25pbmdFcnJvcignTm9uY2UgaXMgcmVxdWlyZWQgYmVmb3JlIHNpZ25pbmcnKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLl9zb2xUcmFuc2FjdGlvbiB8fCAhdGhpcy5fc29sVHJhbnNhY3Rpb24uZmVlUGF5ZXIpIHtcbiAgICAgIHRocm93IG5ldyBTaWduaW5nRXJyb3IoJ2ZlZVBheWVyIGlzIHJlcXVpcmVkIGJlZm9yZSBzaWduaW5nJyk7XG4gICAgfVxuICAgIGNvbnN0IGtleVBhaXJzID0ga2V5UGFpciBpbnN0YW5jZW9mIEFycmF5ID8ga2V5UGFpciA6IFtrZXlQYWlyXTtcbiAgICBjb25zdCBzaWduZXJzOiBTaWduZXJbXSA9IFtdO1xuICAgIGZvciAoY29uc3Qga3Agb2Yga2V5UGFpcnMpIHtcbiAgICAgIGNvbnN0IGtleXMgPSBrcC5nZXRLZXlzKHRydWUpO1xuICAgICAgaWYgKCFrZXlzLnBydikge1xuICAgICAgICB0aHJvdyBuZXcgU2lnbmluZ0Vycm9yKCdNaXNzaW5nIHByaXZhdGUga2V5Jyk7XG4gICAgICB9XG4gICAgICBzaWduZXJzLnB1c2goeyBwdWJsaWNLZXk6IG5ldyBQdWJsaWNLZXkoa2V5cy5wdWIpLCBzZWNyZXRLZXk6IGtleXMucHJ2IGFzIFVpbnQ4QXJyYXkgfSk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICB0aGlzLl9zb2xUcmFuc2FjdGlvbi5wYXJ0aWFsU2lnbiguLi5zaWduZXJzKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB0b0Jyb2FkY2FzdEZvcm1hdCgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fc29sVHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ0VtcHR5IHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICAgIC8vIFRoZSBzaWduYXR1cmVzIGNhbiBoYXZlIG51bGwgc2lnbmF0dXJlcyAod2hpY2ggbWVhbnMgdGhleSBhcmUgcmVxdWlyZWQgYnV0IHlldCB1bnNpZ25lZClcbiAgICAvLyBJbiBvcmRlciB0byBiZSBhYmxlIHRvIHNlcmlhbGl6ZXIgdGhlIHR4cywgd2UgaGF2ZSB0byBjaGFuZ2UgdGhlIHJlcXVpcmVBbGxTaWduYXR1cmVzIGJhc2VkXG4gICAgLy8gb24gaWYgdGhlIFRYIGlzIGZ1bGx5IHNpZ25lZCBvciBub3RcbiAgICBjb25zdCByZXF1aXJlQWxsU2lnbmF0dXJlcyA9IHJlcXVpcmVzQWxsU2lnbmF0dXJlcyh0aGlzLl9zb2xUcmFuc2FjdGlvbi5zaWduYXR1cmVzKTtcbiAgICB0cnkge1xuICAgICAgLy8gQmFzZWQgb24gdGhlIHJlY29tZW5kYXRpb24gZW5jb2RpbmcgZm91bmQgaGVyZSBodHRwczovL2RvY3Muc29sYW5hLmNvbS9kZXZlbG9waW5nL2NsaWVudHMvanNvbnJwYy1hcGkjc2VuZHRyYW5zYWN0aW9uXG4gICAgICAvLyBXZSB1c2UgYmFzZTY0IGVuY29kaW5nXG4gICAgICByZXR1cm4gdGhpcy5fc29sVHJhbnNhY3Rpb24uc2VyaWFsaXplKHsgcmVxdWlyZUFsbFNpZ25hdHVyZXMgfSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhpcyB0cmFuc2FjdGlvbiBwYXlsb2FkXG4gICAqXG4gICAqIEBwYXJhbSByYXdUcmFuc2FjdGlvblxuICAgKi9cbiAgZnJvbVJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgaXNWYWxpZFJhd1RyYW5zYWN0aW9uKHJhd1RyYW5zYWN0aW9uKTtcbiAgICAgIHRoaXMuX3NvbFRyYW5zYWN0aW9uID0gU29sVHJhbnNhY3Rpb24uZnJvbShCdWZmZXIuZnJvbShyYXdUcmFuc2FjdGlvbiwgJ2Jhc2U2NCcpKTtcbiAgICAgIGlmICh0aGlzLl9zb2xUcmFuc2FjdGlvbi5zaWduYXR1cmUgJiYgdGhpcy5fc29sVHJhbnNhY3Rpb24uc2lnbmF0dXJlICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuX2lkID0gYmFzZTU4LmVuY29kZSh0aGlzLl9zb2xUcmFuc2FjdGlvbi5zaWduYXR1cmUpO1xuICAgICAgfVxuICAgICAgY29uc3QgdHJhbnNhY3Rpb25UeXBlID0gZ2V0VHJhbnNhY3Rpb25UeXBlKHRoaXMuX3NvbFRyYW5zYWN0aW9uKTtcbiAgICAgIHN3aXRjaCAodHJhbnNhY3Rpb25UeXBlKSB7XG4gICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLldhbGxldEluaXRpYWxpemF0aW9uOlxuICAgICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5XYWxsZXRJbml0aWFsaXphdGlvbik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlNlbmQ6XG4gICAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQWN0aXZhdGU6XG4gICAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdEZWFjdGl2YXRlOlxuICAgICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nRGVhY3RpdmF0ZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdXaXRoZHJhdzpcbiAgICAgICAgICB0aGlzLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1dpdGhkcmF3KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuQXNzb2NpYXRlZFRva2VuQWNjb3VudEluaXRpYWxpemF0aW9uOlxuICAgICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5Bc3NvY2lhdGVkVG9rZW5BY2NvdW50SW5pdGlhbGl6YXRpb24pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5DbG9zZUFzc29jaWF0ZWRUb2tlbkFjY291bnQ6XG4gICAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLkNsb3NlQXNzb2NpYXRlZFRva2VuQWNjb3VudCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBdXRob3JpemU6XG4gICAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBdXRob3JpemUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQXV0aG9yaXplUmF3OlxuICAgICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nQXV0aG9yaXplUmF3KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0RlbGVnYXRlOlxuICAgICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nRGVsZWdhdGUpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKHRyYW5zYWN0aW9uVHlwZSAhPT0gVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBdXRob3JpemVSYXcpIHtcbiAgICAgICAgdGhpcy5sb2FkSW5wdXRzQW5kT3V0cHV0cygpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHRvSnNvbigpOiBUeERhdGEge1xuICAgIGlmICghdGhpcy5fc29sVHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZVRyYW5zYWN0aW9uRXJyb3IoJ0VtcHR5IHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuXG4gICAgbGV0IGR1cmFibGVOb25jZTogRHVyYWJsZU5vbmNlUGFyYW1zIHwgdW5kZWZpbmVkO1xuICAgIGlmICh0aGlzLl9zb2xUcmFuc2FjdGlvbi5ub25jZUluZm8pIHtcbiAgICAgIGNvbnN0IG5vbmNlSW5zdHJ1Y3Rpb24gPSBTeXN0ZW1JbnN0cnVjdGlvbi5kZWNvZGVOb25jZUFkdmFuY2UodGhpcy5fc29sVHJhbnNhY3Rpb24ubm9uY2VJbmZvLm5vbmNlSW5zdHJ1Y3Rpb24pO1xuICAgICAgZHVyYWJsZU5vbmNlID0ge1xuICAgICAgICB3YWxsZXROb25jZUFkZHJlc3M6IG5vbmNlSW5zdHJ1Y3Rpb24ubm9uY2VQdWJrZXkudG9TdHJpbmcoKSxcbiAgICAgICAgYXV0aFdhbGxldEFkZHJlc3M6IG5vbmNlSW5zdHJ1Y3Rpb24uYXV0aG9yaXplZFB1YmtleS50b1N0cmluZygpLFxuICAgICAgfTtcbiAgICB9XG4gICAgY29uc3QgaW5zdHJ1Y3Rpb25EYXRhID0gaW5zdHJ1Y3Rpb25QYXJhbXNGYWN0b3J5KFxuICAgICAgdGhpcy5fdHlwZSxcbiAgICAgIHRoaXMuX3NvbFRyYW5zYWN0aW9uLmluc3RydWN0aW9ucyxcbiAgICAgIHRoaXMuX2NvaW5Db25maWcubmFtZVxuICAgICk7XG4gICAgaWYgKHRoaXMuX3R5cGUpIHtcbiAgICAgIGlmIChcbiAgICAgICAgIWR1cmFibGVOb25jZSAmJlxuICAgICAgICBpbnN0cnVjdGlvbkRhdGEubGVuZ3RoID4gMSAmJlxuICAgICAgICBpbnN0cnVjdGlvbkRhdGFbMF0udHlwZSA9PT0gSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuTm9uY2VBZHZhbmNlXG4gICAgICApIHtcbiAgICAgICAgZHVyYWJsZU5vbmNlID0gaW5zdHJ1Y3Rpb25EYXRhWzBdLnBhcmFtcztcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgcmVzdWx0OiBUeERhdGEgPSB7XG4gICAgICBpZDogdGhpcy5fc29sVHJhbnNhY3Rpb24uc2lnbmF0dXJlID8gdGhpcy5pZCA6IHVuZGVmaW5lZCxcbiAgICAgIGZlZVBheWVyOiB0aGlzLl9zb2xUcmFuc2FjdGlvbi5mZWVQYXllcj8udG9TdHJpbmcoKSxcbiAgICAgIGxhbXBvcnRzUGVyU2lnbmF0dXJlOiB0aGlzLmxhbXBvcnRzUGVyU2lnbmF0dXJlLFxuICAgICAgbm9uY2U6IHRoaXMuZ2V0Tm9uY2UoKSxcbiAgICAgIGR1cmFibGVOb25jZTogZHVyYWJsZU5vbmNlLFxuICAgICAgbnVtU2lnbmF0dXJlczogdGhpcy5zaWduYXR1cmUubGVuZ3RoLFxuICAgICAgaW5zdHJ1Y3Rpb25zRGF0YTogaW5zdHJ1Y3Rpb25EYXRhLFxuICAgIH07XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG5vbmNlIGZyb20gdGhlIFNvbGFuYSBUcmFuc2FjdGlvblxuICAgKiBUaHJvd3MgaWYgbm90IHNldFxuICAgKi9cbiAgcHJpdmF0ZSBnZXROb25jZSgpOiBCbG9ja2hhc2gge1xuICAgIGlmICh0aGlzLl9zb2xUcmFuc2FjdGlvbi5yZWNlbnRCbG9ja2hhc2gpIHtcbiAgICAgIHJldHVybiB0aGlzLl9zb2xUcmFuc2FjdGlvbi5yZWNlbnRCbG9ja2hhc2g7XG4gICAgfSBlbHNlIGlmICh0aGlzLl9zb2xUcmFuc2FjdGlvbi5ub25jZUluZm8pIHtcbiAgICAgIHJldHVybiB0aGlzLl9zb2xUcmFuc2FjdGlvbi5ub25jZUluZm8ubm9uY2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignTm9uY2UgaXMgbm90IHNldCcpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkIHRoZSBpbnB1dCBhbmQgb3V0cHV0IGRhdGEgb24gdGhpcyB0cmFuc2FjdGlvbi5cbiAgICovXG4gIGxvYWRJbnB1dHNBbmRPdXRwdXRzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5fc29sVHJhbnNhY3Rpb24gfHwgdGhpcy5fc29sVHJhbnNhY3Rpb24uaW5zdHJ1Y3Rpb25zPy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3Qgb3V0cHV0czogRW50cnlbXSA9IFtdO1xuICAgIGNvbnN0IGlucHV0czogRW50cnlbXSA9IFtdO1xuICAgIGNvbnN0IGluc3RydWN0aW9uUGFyYW1zID0gaW5zdHJ1Y3Rpb25QYXJhbXNGYWN0b3J5KFxuICAgICAgdGhpcy50eXBlLFxuICAgICAgdGhpcy5fc29sVHJhbnNhY3Rpb24uaW5zdHJ1Y3Rpb25zLFxuICAgICAgdGhpcy5fY29pbkNvbmZpZy5uYW1lXG4gICAgKTtcblxuICAgIGZvciAoY29uc3QgaW5zdHJ1Y3Rpb24gb2YgaW5zdHJ1Y3Rpb25QYXJhbXMpIHtcbiAgICAgIHN3aXRjaCAoaW5zdHJ1Y3Rpb24udHlwZSkge1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLkNyZWF0ZU5vbmNlQWNjb3VudDpcbiAgICAgICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiBpbnN0cnVjdGlvbi5wYXJhbXMuZnJvbUFkZHJlc3MsXG4gICAgICAgICAgICB2YWx1ZTogaW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCxcbiAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBJbnN0cnVjdGlvbkJ1aWxkZXJUeXBlcy5UcmFuc2ZlcjpcbiAgICAgICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiBpbnN0cnVjdGlvbi5wYXJhbXMuZnJvbUFkZHJlc3MsXG4gICAgICAgICAgICB2YWx1ZTogaW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCxcbiAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICAgICAgYWRkcmVzczogaW5zdHJ1Y3Rpb24ucGFyYW1zLnRvQWRkcmVzcyxcbiAgICAgICAgICAgIHZhbHVlOiBpbnN0cnVjdGlvbi5wYXJhbXMuYW1vdW50LFxuICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLlRva2VuVHJhbnNmZXI6XG4gICAgICAgICAgaW5wdXRzLnB1c2goe1xuICAgICAgICAgICAgYWRkcmVzczogaW5zdHJ1Y3Rpb24ucGFyYW1zLmZyb21BZGRyZXNzLFxuICAgICAgICAgICAgdmFsdWU6IGluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgICBjb2luOiBpbnN0cnVjdGlvbi5wYXJhbXMudG9rZW5OYW1lLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiBpbnN0cnVjdGlvbi5wYXJhbXMudG9BZGRyZXNzLFxuICAgICAgICAgICAgdmFsdWU6IGluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgICBjb2luOiBpbnN0cnVjdGlvbi5wYXJhbXMudG9rZW5OYW1lLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLlN0YWtpbmdBY3RpdmF0ZTpcbiAgICAgICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiBpbnN0cnVjdGlvbi5wYXJhbXMuZnJvbUFkZHJlc3MsXG4gICAgICAgICAgICB2YWx1ZTogaW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCxcbiAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICAgICAgYWRkcmVzczogaW5zdHJ1Y3Rpb24ucGFyYW1zLnN0YWtpbmdBZGRyZXNzLFxuICAgICAgICAgICAgdmFsdWU6IGluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgICBjb2luOiB0aGlzLl9jb2luQ29uZmlnLm5hbWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuU3Rha2luZ0RlYWN0aXZhdGU6XG4gICAgICAgICAgaWYgKGluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQgJiYgaW5zdHJ1Y3Rpb24ucGFyYW1zLnVuc3Rha2luZ0FkZHJlc3MpIHtcbiAgICAgICAgICAgIGlucHV0cy5wdXNoKHtcbiAgICAgICAgICAgICAgYWRkcmVzczogaW5zdHJ1Y3Rpb24ucGFyYW1zLnN0YWtpbmdBZGRyZXNzLFxuICAgICAgICAgICAgICB2YWx1ZTogaW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCxcbiAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICAgICAgICBhZGRyZXNzOiBpbnN0cnVjdGlvbi5wYXJhbXMudW5zdGFraW5nQWRkcmVzcyxcbiAgICAgICAgICAgICAgdmFsdWU6IGluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBJbnN0cnVjdGlvbkJ1aWxkZXJUeXBlcy5TdGFraW5nV2l0aGRyYXc6XG4gICAgICAgICAgaW5wdXRzLnB1c2goe1xuICAgICAgICAgICAgYWRkcmVzczogaW5zdHJ1Y3Rpb24ucGFyYW1zLnN0YWtpbmdBZGRyZXNzLFxuICAgICAgICAgICAgdmFsdWU6IGluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgICBjb2luOiB0aGlzLl9jb2luQ29uZmlnLm5hbWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICAgIGFkZHJlc3M6IGluc3RydWN0aW9uLnBhcmFtcy5mcm9tQWRkcmVzcyxcbiAgICAgICAgICAgIHZhbHVlOiBpbnN0cnVjdGlvbi5wYXJhbXMuYW1vdW50LFxuICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLkNyZWF0ZUFzc29jaWF0ZWRUb2tlbkFjY291bnQ6XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuQ2xvc2VBc3NvY2lhdGVkVG9rZW5BY2NvdW50OlxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLlN0YWtpbmdBdXRob3JpemU6XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuU3Rha2luZ0RlbGVnYXRlOlxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLlNldFByaW9yaXR5RmVlOlxuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLl9vdXRwdXRzID0gb3V0cHV0cztcbiAgICB0aGlzLl9pbnB1dHMgPSBpbnB1dHM7XG4gIH1cblxuICAvKiogQGluaGVyaXREb2MgKi9cbiAgZXhwbGFpblRyYW5zYWN0aW9uKCk6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24ge1xuICAgIGlmICh2YWxpZGF0ZVJhd01zZ0luc3RydWN0aW9uKHRoaXMuX3NvbFRyYW5zYWN0aW9uLmluc3RydWN0aW9ucykpIHtcbiAgICAgIHJldHVybiB0aGlzLmV4cGxhaW5SYXdNc2dBdXRob3JpemVUcmFuc2FjdGlvbigpO1xuICAgIH1cbiAgICBjb25zdCBkZWNvZGVkSW5zdHJ1Y3Rpb25zID0gaW5zdHJ1Y3Rpb25QYXJhbXNGYWN0b3J5KFxuICAgICAgdGhpcy5fdHlwZSxcbiAgICAgIHRoaXMuX3NvbFRyYW5zYWN0aW9uLmluc3RydWN0aW9ucyxcbiAgICAgIHRoaXMuX2NvaW5Db25maWcubmFtZVxuICAgICk7XG5cbiAgICBsZXQgbWVtbzogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgIGxldCBkdXJhYmxlTm9uY2U6IER1cmFibGVOb25jZVBhcmFtcyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICAgIGxldCBvdXRwdXRBbW91bnQgPSBuZXcgQmlnTnVtYmVyKDApO1xuICAgIGNvbnN0IG91dHB1dHM6IFRyYW5zYWN0aW9uUmVjaXBpZW50W10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgaW5zdHJ1Y3Rpb24gb2YgZGVjb2RlZEluc3RydWN0aW9ucykge1xuICAgICAgc3dpdGNoIChpbnN0cnVjdGlvbi50eXBlKSB7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuTm9uY2VBZHZhbmNlOlxuICAgICAgICAgIGR1cmFibGVOb25jZSA9IChpbnN0cnVjdGlvbiBhcyBOb25jZSkucGFyYW1zO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLk1lbW86XG4gICAgICAgICAgbWVtbyA9IChpbnN0cnVjdGlvbiBhcyBNZW1vKS5wYXJhbXMubWVtbztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBJbnN0cnVjdGlvbkJ1aWxkZXJUeXBlcy5UcmFuc2ZlcjpcbiAgICAgICAgICBjb25zdCB0cmFuc2Zlckluc3RydWN0aW9uID0gaW5zdHJ1Y3Rpb24gYXMgVHJhbnNmZXI7XG4gICAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICAgIGFkZHJlc3M6IHRyYW5zZmVySW5zdHJ1Y3Rpb24ucGFyYW1zLnRvQWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogdHJhbnNmZXJJbnN0cnVjdGlvbi5wYXJhbXMuYW1vdW50LFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIG91dHB1dEFtb3VudCA9IG91dHB1dEFtb3VudC5wbHVzKHRyYW5zZmVySW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuVG9rZW5UcmFuc2ZlcjpcbiAgICAgICAgICBjb25zdCB0b2tlblRyYW5zZmVySW5zdHJ1Y3Rpb24gPSBpbnN0cnVjdGlvbiBhcyBUb2tlblRyYW5zZmVyO1xuICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiB0b2tlblRyYW5zZmVySW5zdHJ1Y3Rpb24ucGFyYW1zLnRvQWRkcmVzcyxcbiAgICAgICAgICAgIGFtb3VudDogdG9rZW5UcmFuc2Zlckluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgICB0b2tlbk5hbWU6IHRva2VuVHJhbnNmZXJJbnN0cnVjdGlvbi5wYXJhbXMudG9rZW5OYW1lLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEluc3RydWN0aW9uQnVpbGRlclR5cGVzLkNyZWF0ZU5vbmNlQWNjb3VudDpcbiAgICAgICAgICBjb25zdCBjcmVhdGVJbnN0cnVjdGlvbiA9IGluc3RydWN0aW9uIGFzIFdhbGxldEluaXQ7XG4gICAgICAgICAgb3V0cHV0cy5wdXNoKHtcbiAgICAgICAgICAgIGFkZHJlc3M6IGNyZWF0ZUluc3RydWN0aW9uLnBhcmFtcy5ub25jZUFkZHJlc3MsXG4gICAgICAgICAgICBhbW91bnQ6IGNyZWF0ZUluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgb3V0cHV0QW1vdW50ID0gb3V0cHV0QW1vdW50LnBsdXMoY3JlYXRlSW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuU3Rha2luZ0FjdGl2YXRlOlxuICAgICAgICAgIGNvbnN0IHN0YWtpbmdBY3RpdmF0ZUluc3RydWN0aW9uID0gaW5zdHJ1Y3Rpb24gYXMgU3Rha2luZ0FjdGl2YXRlO1xuICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiBzdGFraW5nQWN0aXZhdGVJbnN0cnVjdGlvbi5wYXJhbXMuc3Rha2luZ0FkZHJlc3MsXG4gICAgICAgICAgICBhbW91bnQ6IHN0YWtpbmdBY3RpdmF0ZUluc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgb3V0cHV0QW1vdW50ID0gb3V0cHV0QW1vdW50LnBsdXMoc3Rha2luZ0FjdGl2YXRlSW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuU3Rha2luZ1dpdGhkcmF3OlxuICAgICAgICAgIGNvbnN0IHN0YWtpbmdXaXRoZHJhd0luc3RydWN0aW9uID0gaW5zdHJ1Y3Rpb24gYXMgU3Rha2luZ1dpdGhkcmF3O1xuICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICBhZGRyZXNzOiBzdGFraW5nV2l0aGRyYXdJbnN0cnVjdGlvbi5wYXJhbXMuZnJvbUFkZHJlc3MsXG4gICAgICAgICAgICBhbW91bnQ6IHN0YWtpbmdXaXRoZHJhd0luc3RydWN0aW9uLnBhcmFtcy5hbW91bnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgb3V0cHV0QW1vdW50ID0gb3V0cHV0QW1vdW50LnBsdXMoc3Rha2luZ1dpdGhkcmF3SW5zdHJ1Y3Rpb24ucGFyYW1zLmFtb3VudCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgSW5zdHJ1Y3Rpb25CdWlsZGVyVHlwZXMuQ3JlYXRlQXNzb2NpYXRlZFRva2VuQWNjb3VudDpcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gQWZ0ZXIgZGVzZXJpYWxpemluZyBhIHRyYW5zYWN0aW9uLCBkdXJhYmxlIG5vbmNlIGRldGFpbHMgYXJlIHBvcHVsYXRlZCBpbiB0aGUgbm9uY2VJbmZvIGZpZWxkXG4gICAgICBpZiAoIWR1cmFibGVOb25jZSAmJiB0aGlzLl9zb2xUcmFuc2FjdGlvbi5ub25jZUluZm8pIHtcbiAgICAgICAgY29uc3Qgbm9uY2VBZHZhbmNlSW5zdHJ1Y3Rpb24gPSBTeXN0ZW1JbnN0cnVjdGlvbi5kZWNvZGVOb25jZUFkdmFuY2UoXG4gICAgICAgICAgdGhpcy5fc29sVHJhbnNhY3Rpb24ubm9uY2VJbmZvLm5vbmNlSW5zdHJ1Y3Rpb25cbiAgICAgICAgKTtcbiAgICAgICAgZHVyYWJsZU5vbmNlID0ge1xuICAgICAgICAgIGF1dGhXYWxsZXRBZGRyZXNzOiBub25jZUFkdmFuY2VJbnN0cnVjdGlvbi5hdXRob3JpemVkUHVia2V5LnRvU3RyaW5nKCksXG4gICAgICAgICAgd2FsbGV0Tm9uY2VBZGRyZXNzOiBub25jZUFkdmFuY2VJbnN0cnVjdGlvbi5ub25jZVB1YmtleS50b1N0cmluZygpLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmdldEV4cGxhaW5lZFRyYW5zYWN0aW9uKG91dHB1dEFtb3VudCwgb3V0cHV0cywgbWVtbywgZHVyYWJsZU5vbmNlKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FsY3VsYXRlRmVlKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMubGFtcG9ydHNQZXJTaWduYXR1cmUgfHwgdGhpcy50b2tlbkFjY291bnRSZW50RXhlbXB0QW1vdW50KSB7XG4gICAgICBjb25zdCBzaWduYXR1cmVGZWVzID0gdGhpcy5sYW1wb3J0c1BlclNpZ25hdHVyZVxuICAgICAgICA/IG5ldyBCaWdOdW1iZXIodGhpcy5sYW1wb3J0c1BlclNpZ25hdHVyZSkubXVsdGlwbGllZEJ5KHRoaXMubnVtYmVyT2ZSZXF1aXJlZFNpZ25hdHVyZXMpLnRvRml4ZWQoMClcbiAgICAgICAgOiAwO1xuICAgICAgY29uc3QgcmVudEZlZXMgPSB0aGlzLnRva2VuQWNjb3VudFJlbnRFeGVtcHRBbW91bnRcbiAgICAgICAgPyBuZXcgQmlnTnVtYmVyKHRoaXMudG9rZW5BY2NvdW50UmVudEV4ZW1wdEFtb3VudCkubXVsdGlwbGllZEJ5KHRoaXMubnVtYmVyT2ZBVEFDcmVhdGlvbkluc3RydWN0aW9ucykudG9GaXhlZCgwKVxuICAgICAgICA6IDA7XG4gICAgICByZXR1cm4gbmV3IEJpZ051bWJlcihzaWduYXR1cmVGZWVzKS5wbHVzKHJlbnRGZWVzKS50b0ZpeGVkKDApO1xuICAgIH1cbiAgICByZXR1cm4gVU5BVkFJTEFCTEVfVEVYVDtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRFeHBsYWluZWRUcmFuc2FjdGlvbihcbiAgICBvdXRwdXRBbW91bnQ6IEJpZ051bWJlcixcbiAgICBvdXRwdXRzOiBUcmFuc2FjdGlvblJlY2lwaWVudFtdLFxuICAgIG1lbW86IHVuZGVmaW5lZCB8IHN0cmluZyA9IHVuZGVmaW5lZCxcbiAgICBkdXJhYmxlTm9uY2U6IHVuZGVmaW5lZCB8IER1cmFibGVOb25jZVBhcmFtcyA9IHVuZGVmaW5lZFxuICApOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCBmZWVTdHJpbmcgPSB0aGlzLmNhbGN1bGF0ZUZlZSgpO1xuICAgIHJldHVybiB7XG4gICAgICBkaXNwbGF5T3JkZXI6IFtcbiAgICAgICAgJ2lkJyxcbiAgICAgICAgJ3R5cGUnLFxuICAgICAgICAnYmxvY2toYXNoJyxcbiAgICAgICAgJ2R1cmFibGVOb25jZScsXG4gICAgICAgICdvdXRwdXRBbW91bnQnLFxuICAgICAgICAnY2hhbmdlQW1vdW50JyxcbiAgICAgICAgJ291dHB1dHMnLFxuICAgICAgICAnY2hhbmdlT3V0cHV0cycsXG4gICAgICAgICdmZWUnLFxuICAgICAgICAnbWVtbycsXG4gICAgICBdLFxuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICB0eXBlOiBUcmFuc2FjdGlvblR5cGVbdGhpcy50eXBlXS50b1N0cmluZygpLFxuICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICBjaGFuZ2VBbW91bnQ6ICcwJyxcbiAgICAgIG91dHB1dEFtb3VudDogb3V0cHV0QW1vdW50LnRvRml4ZWQoMCksXG4gICAgICBvdXRwdXRzOiBvdXRwdXRzLFxuICAgICAgZmVlOiB7XG4gICAgICAgIGZlZTogZmVlU3RyaW5nLFxuICAgICAgICBmZWVSYXRlOiB0aGlzLmxhbXBvcnRzUGVyU2lnbmF0dXJlLFxuICAgICAgfSxcbiAgICAgIG1lbW86IG1lbW8sXG4gICAgICBibG9ja2hhc2g6IHRoaXMuZ2V0Tm9uY2UoKSxcbiAgICAgIGR1cmFibGVOb25jZTogZHVyYWJsZU5vbmNlLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGV4cGxhaW5SYXdNc2dBdXRob3JpemVUcmFuc2FjdGlvbigpOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCB7IGluc3RydWN0aW9ucyB9ID0gdGhpcy5fc29sVHJhbnNhY3Rpb247XG4gICAgY29uc3Qgbm9uY2VJbnN0cnVjdGlvbiA9IFN5c3RlbUluc3RydWN0aW9uLmRlY29kZU5vbmNlQWR2YW5jZShpbnN0cnVjdGlvbnNbMF0pO1xuICAgIGNvbnN0IGR1cmFibGVOb25jZSA9IHtcbiAgICAgIHdhbGxldE5vbmNlQWRkcmVzczogbm9uY2VJbnN0cnVjdGlvbi5ub25jZVB1YmtleS50b1N0cmluZygpLFxuICAgICAgYXV0aFdhbGxldEFkZHJlc3M6IG5vbmNlSW5zdHJ1Y3Rpb24uYXV0aG9yaXplZFB1YmtleS50b1N0cmluZygpLFxuICAgIH07XG4gICAgY29uc3QgZGF0YSA9IGluc3RydWN0aW9uc1sxXS5kYXRhLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBzdGFraW5nQXV0aG9yaXplUGFyYW1zOiBTdGFraW5nQXV0aG9yaXplUGFyYW1zID1cbiAgICAgIGRhdGEgPT09IHZhbGlkSW5zdHJ1Y3Rpb25EYXRhXG4gICAgICAgID8ge1xuICAgICAgICAgICAgc3Rha2luZ0FkZHJlc3M6IGluc3RydWN0aW9uc1sxXS5rZXlzWzBdLnB1YmtleS50b1N0cmluZygpLFxuICAgICAgICAgICAgb2xkV2l0aGRyYXdBZGRyZXNzOiBpbnN0cnVjdGlvbnNbMV0ua2V5c1syXS5wdWJrZXkudG9TdHJpbmcoKSxcbiAgICAgICAgICAgIG5ld1dpdGhkcmF3QWRkcmVzczogaW5zdHJ1Y3Rpb25zWzFdLmtleXNbM10ucHVia2V5LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBjdXN0b2RpYW5BZGRyZXNzOiBpbnN0cnVjdGlvbnNbMV0ua2V5c1s0XS5wdWJrZXkudG9TdHJpbmcoKSxcbiAgICAgICAgICB9XG4gICAgICAgIDoge1xuICAgICAgICAgICAgc3Rha2luZ0FkZHJlc3M6IGluc3RydWN0aW9uc1sxXS5rZXlzWzBdLnB1YmtleS50b1N0cmluZygpLFxuICAgICAgICAgICAgb2xkV2l0aGRyYXdBZGRyZXNzOiAnJyxcbiAgICAgICAgICAgIG5ld1dpdGhkcmF3QWRkcmVzczogJycsXG4gICAgICAgICAgICBvbGRTdGFraW5nQXV0aG9yaXR5QWRkcmVzczogaW5zdHJ1Y3Rpb25zWzFdLmtleXNbMl0ucHVia2V5LnRvU3RyaW5nKCksXG4gICAgICAgICAgICBuZXdTdGFraW5nQXV0aG9yaXR5QWRkcmVzczogaW5zdHJ1Y3Rpb25zWzFdLmtleXNbM10ucHVia2V5LnRvU3RyaW5nKCksXG4gICAgICAgICAgfTtcbiAgICBjb25zdCBmZWVTdHJpbmcgPSB0aGlzLmNhbGN1bGF0ZUZlZSgpO1xuICAgIHJldHVybiB7XG4gICAgICBkaXNwbGF5T3JkZXI6IFtcbiAgICAgICAgJ2lkJyxcbiAgICAgICAgJ3R5cGUnLFxuICAgICAgICAnYmxvY2toYXNoJyxcbiAgICAgICAgJ2R1cmFibGVOb25jZScsXG4gICAgICAgICdvdXRwdXRBbW91bnQnLFxuICAgICAgICAnY2hhbmdlQW1vdW50JyxcbiAgICAgICAgJ291dHB1dHMnLFxuICAgICAgICAnY2hhbmdlT3V0cHV0cycsXG4gICAgICAgICdmZWUnLFxuICAgICAgICAnbWVtbycsXG4gICAgICBdLFxuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICB0eXBlOiBUcmFuc2FjdGlvblR5cGVbdGhpcy50eXBlXS50b1N0cmluZygpLFxuICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICBjaGFuZ2VBbW91bnQ6ICcwJyxcbiAgICAgIG91dHB1dEFtb3VudDogMCxcbiAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgZmVlOiB7XG4gICAgICAgIGZlZTogZmVlU3RyaW5nLFxuICAgICAgICBmZWVSYXRlOiB0aGlzLmxhbXBvcnRzUGVyU2lnbmF0dXJlLFxuICAgICAgfSxcbiAgICAgIGJsb2NraGFzaDogdGhpcy5nZXROb25jZSgpLFxuICAgICAgZHVyYWJsZU5vbmNlOiBkdXJhYmxlTm9uY2UsXG4gICAgICBzdGFraW5nQXV0aG9yaXplOiBzdGFraW5nQXV0aG9yaXplUGFyYW1zLFxuICAgIH07XG4gIH1cbn1cbiJdfQ==

Выполнить команду


Для локальной разработки. Не используйте в интернете!