PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/utxo-lib/dist/src/bitgo/wallet

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

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toWalletPsbt = toWalletPsbt;
exports.signWalletPsbt = signWalletPsbt;
exports.getPsbtInputScriptType = getPsbtInputScriptType;
exports.parsePsbtInput = parsePsbtInput;
exports.toScriptType2Of3s = toScriptType2Of3s;
exports.getStrictSignatureCount = getStrictSignatureCount;
exports.getStrictSignatureCounts = getStrictSignatureCounts;
exports.isPsbtInputArray = isPsbtInputArray;
exports.isTxInputArray = isTxInputArray;
exports.isTransactionWithKeyPathSpendInput = isTransactionWithKeyPathSpendInput;
exports.addXpubsToPsbt = addXpubsToPsbt;
exports.getSignatureValidationArrayPsbt = getSignatureValidationArrayPsbt;
exports.extractP2msOnlyHalfSignedTx = extractP2msOnlyHalfSignedTx;
exports.clonePsbtWithoutNonWitnessUtxo = clonePsbtWithoutNonWitnessUtxo;
exports.isPsbtLite = isPsbtLite;
exports.deleteWitnessUtxoForNonSegwitInputs = deleteWitnessUtxoForNonSegwitInputs;
const assert = require("assert");
const utils_1 = require("bip174/src/lib/utils");
const bs58check = require("bs58check");
const UtxoPsbt_1 = require("../UtxoPsbt");
const UtxoTransaction_1 = require("../UtxoTransaction");
const outputScripts_1 = require("../outputScripts");
const WalletKeys_1 = require("./WalletKeys");
const Unspent_1 = require("../Unspent");
const transaction_1 = require("../transaction");
const Unspent_2 = require("./Unspent");
const parseInput_1 = require("../parseInput");
const Musig2_1 = require("../Musig2");
const types_1 = require("../types");
const taproot_1 = require("../../taproot");
const bitcoinjs_lib_1 = require("bitcoinjs-lib");
const index_1 = require("../../index");
const PsbtUtil_1 = require("../PsbtUtil");
function getTaprootSigners(script, walletKeys) {
    const parsedPublicKeys = (0, parseInput_1.parsePubScript2Of3)(script, 'taprootScriptPathSpend').publicKeys;
    const walletSigners = parsedPublicKeys.map((publicKey) => {
        const index = walletKeys.publicKeys.findIndex((walletPublicKey) => (0, outputScripts_1.toXOnlyPublicKey)(walletPublicKey).equals(publicKey));
        if (index >= 0) {
            return { walletKey: walletKeys.triple[index], rootKey: walletKeys.parent.triple[index] };
        }
        throw new Error('Taproot public key is not a wallet public key');
    });
    return [walletSigners[0], walletSigners[1]];
}
function updatePsbtInput(psbt, inputIndex, unspent, rootWalletKeys) {
    const input = (0, utils_1.checkForInput)(psbt.data.inputs, inputIndex);
    const signatureCount = (0, PsbtUtil_1.getPsbtInputSignatureCount)(input);
    const scriptType = (0, outputScripts_1.scriptTypeForChain)(unspent.chain);
    if (signatureCount === 0 && scriptType === 'p2tr') {
        return;
    }
    const walletKeys = rootWalletKeys.deriveForChainAndIndex(unspent.chain, unspent.index);
    if (scriptType === 'p2tr') {
        if (!Array.isArray(input.tapLeafScript) || input.tapLeafScript.length === 0) {
            throw new Error('Invalid PSBT state. Missing required fields.');
        }
        if (input.tapLeafScript.length > 1) {
            throw new Error('Bitgo only supports a single tap leaf script per input');
        }
        const [signer, cosigner] = getTaprootSigners(input.tapLeafScript[0].script, walletKeys);
        const leafHash = (0, outputScripts_1.getLeafHash)({
            publicKeys: walletKeys.publicKeys,
            signer: signer.walletKey.publicKey,
            cosigner: cosigner.walletKey.publicKey,
        });
        psbt.updateInput(inputIndex, {
            tapBip32Derivation: [signer, cosigner].map((walletSigner) => ({
                leafHashes: [leafHash],
                pubkey: (0, outputScripts_1.toXOnlyPublicKey)(walletSigner.walletKey.publicKey),
                path: rootWalletKeys.getDerivationPath(walletSigner.rootKey, unspent.chain, unspent.index),
                masterFingerprint: walletSigner.rootKey.fingerprint,
            })),
        });
    }
    else {
        if (signatureCount === 0) {
            const { witnessScript, redeemScript } = (0, outputScripts_1.createOutputScript2of3)(walletKeys.publicKeys, scriptType);
            if (witnessScript && psbt.data.inputs[inputIndex].witnessScript === undefined) {
                psbt.updateInput(inputIndex, { witnessScript });
            }
            if (redeemScript && psbt.data.inputs[inputIndex].redeemScript === undefined) {
                psbt.updateInput(inputIndex, { redeemScript });
            }
        }
        psbt.updateInput(inputIndex, {
            bip32Derivation: [0, 1, 2].map((idx) => ({
                pubkey: walletKeys.triple[idx].publicKey,
                path: walletKeys.paths[idx],
                masterFingerprint: rootWalletKeys.triple[idx].fingerprint,
            })),
        });
    }
}
/**
 * @return PSBT filled with metatdata as per input params tx, unspents and rootWalletKeys.
 * Unsigned PSBT for taproot input with witnessUtxo
 * Unsigned PSBT for other input with witnessUtxo/nonWitnessUtxo, redeemScript/witnessScript, bip32Derivation
 * Signed PSBT for taproot input with witnessUtxo, tapLeafScript, tapBip32Derivation, tapScriptSig
 * Signed PSBT for other input with witnessUtxo/nonWitnessUtxo, redeemScript/witnessScript, bip32Derivation, partialSig
 */
function toWalletPsbt(tx, unspents, rootWalletKeys) {
    const prevOutputs = unspents.map((u) => {
        assert.notStrictEqual((0, outputScripts_1.scriptTypeForChain)(u.chain), 'p2trMusig2');
        return (0, Unspent_1.toPrevOutputWithPrevTx)(u, tx.network);
    });
    const psbt = (0, transaction_1.createPsbtFromTransaction)(tx, prevOutputs);
    unspents.forEach((u, i) => {
        if ((0, Unspent_2.isWalletUnspent)(u) && u.index !== undefined) {
            updatePsbtInput(psbt, i, u, rootWalletKeys);
        }
    });
    return psbt;
}
/**
 * @param psbt
 * @param inputIndex
 * @param signer
 * @param unspent
 * @return signed PSBT with signer's key for unspent
 */
function signWalletPsbt(psbt, inputIndex, signer, unspent) {
    const scriptType = (0, outputScripts_1.scriptTypeForChain)(unspent.chain);
    if (scriptType === 'p2tr' || scriptType === 'p2trMusig2') {
        psbt.signTaprootInputHD(inputIndex, signer);
    }
    else {
        psbt.signInputHD(inputIndex, signer);
    }
}
/**
 * @returns script type of the input
 */
function getPsbtInputScriptType(input) {
    const isP2pk = (script) => {
        try {
            const chunks = bitcoinjs_lib_1.script.decompile(script);
            return (chunks?.length === 2 &&
                Buffer.isBuffer(chunks[0]) &&
                bitcoinjs_lib_1.script.isCanonicalPubKey(chunks[0]) &&
                chunks[1] === index_1.opcodes.OP_CHECKSIG);
        }
        catch (e) {
            return false;
        }
    };
    let scriptType;
    if (Buffer.isBuffer(input.redeemScript) && Buffer.isBuffer(input.witnessScript)) {
        scriptType = 'p2shP2wsh';
    }
    else if (Buffer.isBuffer(input.redeemScript)) {
        scriptType = isP2pk(input.redeemScript) ? 'p2shP2pk' : 'p2sh';
    }
    else if (Buffer.isBuffer(input.witnessScript)) {
        scriptType = 'p2wsh';
    }
    if (Array.isArray(input.tapLeafScript) && input.tapLeafScript.length > 0) {
        if (scriptType) {
            throw new Error(`Found both ${scriptType} and taprootScriptPath PSBT metadata.`);
        }
        if (input.tapLeafScript.length > 1) {
            throw new Error('Bitgo only supports a single tap leaf script per input.');
        }
        scriptType = 'taprootScriptPathSpend';
    }
    if (input.tapInternalKey) {
        if (scriptType) {
            throw new Error(`Found both ${scriptType} and taprootKeyPath PSBT metadata.`);
        }
        scriptType = 'taprootKeyPathSpend';
    }
    if (scriptType) {
        return scriptType;
    }
    throw new Error('could not parse input');
}
function parseTaprootKeyPathSignatures(input) {
    const partialSigs = (0, Musig2_1.parsePsbtMusig2PartialSigs)(input);
    if (!partialSigs) {
        return { signatures: undefined, participantPublicKeys: undefined };
    }
    const signatures = partialSigs.map((pSig) => pSig.partialSig);
    const participantPublicKeys = partialSigs.map((pSig) => pSig.participantPubKey);
    return (0, types_1.isTuple)(signatures) && (0, types_1.isTuple)(participantPublicKeys)
        ? { signatures, participantPublicKeys }
        : { signatures: [signatures[0]], participantPublicKeys: [participantPublicKeys[0]] };
}
function parsePartialOrTapScriptSignatures(sig) {
    if (!sig?.length) {
        return { signatures: undefined };
    }
    if (sig.length > 2) {
        throw new Error('unexpected signature count');
    }
    const signatures = sig.map((tSig) => tSig.signature);
    return (0, types_1.isTuple)(signatures) ? { signatures } : { signatures: [signatures[0]] };
}
function parseSignatures(input, scriptType) {
    return scriptType === 'taprootKeyPathSpend'
        ? parseTaprootKeyPathSignatures(input)
        : scriptType === 'taprootScriptPathSpend'
            ? parsePartialOrTapScriptSignatures(input.tapScriptSig)
            : parsePartialOrTapScriptSignatures(input.partialSig);
}
function parseScript(input, scriptType) {
    let pubScript;
    if (scriptType === 'p2sh' || scriptType === 'p2shP2pk') {
        pubScript = input.redeemScript;
    }
    else if (scriptType === 'p2wsh' || scriptType === 'p2shP2wsh') {
        pubScript = input.witnessScript;
    }
    else if (scriptType === 'taprootScriptPathSpend') {
        pubScript = input.tapLeafScript ? input.tapLeafScript[0].script : undefined;
    }
    else if (scriptType === 'taprootKeyPathSpend') {
        if (input.witnessUtxo?.script) {
            pubScript = input.witnessUtxo.script;
        }
        else if (input.tapInternalKey && input.tapMerkleRoot) {
            pubScript = (0, taproot_1.createTaprootOutputScript)({ internalPubKey: input.tapInternalKey, taptreeRoot: input.tapMerkleRoot });
        }
    }
    if (!pubScript) {
        throw new Error(`Invalid PSBT state for ${scriptType}. Missing required fields.`);
    }
    return (0, parseInput_1.parsePubScript)(pubScript, scriptType);
}
/**
 * @return psbt metadata are parsed as per below conditions.
 * redeemScript/witnessScript/tapLeafScript matches BitGo.
 * signature and public key count matches BitGo.
 * P2SH-P2PK => scriptType, redeemScript, public key, signature.
 * P2SH => scriptType, redeemScript, public keys, signatures.
 * PW2SH => scriptType, witnessScript, public keys, signatures.
 * P2SH-PW2SH => scriptType, redeemScript, witnessScript, public keys, signatures.
 * P2TR and P2TR MUSIG2 script path => scriptType (taprootScriptPathSpend), pubScript (leaf script), controlBlock,
 * scriptPathLevel, leafVersion, public keys, signatures.
 * P2TR MUSIG2 kep path => scriptType (taprootKeyPathSpend), pubScript (scriptPubKey), participant pub keys (signer),
 * public key (tapOutputkey), signatures (partial signer sigs).
 */
function parsePsbtInput(input) {
    if ((0, PsbtUtil_1.isPsbtInputFinalized)(input)) {
        throw new Error('Finalized PSBT parsing is not supported');
    }
    const scriptType = getPsbtInputScriptType(input);
    const parsedPubScript = parseScript(input, scriptType);
    const signatures = parseSignatures(input, scriptType);
    if (parsedPubScript.scriptType === 'taprootKeyPathSpend' && 'participantPublicKeys' in signatures) {
        return {
            ...parsedPubScript,
            ...signatures,
            scriptType: parsedPubScript.scriptType,
        };
    }
    if (parsedPubScript.scriptType === 'taprootScriptPathSpend') {
        if (!input.tapLeafScript) {
            throw new Error('Invalid PSBT state for taprootScriptPathSpend. Missing required fields.');
        }
        const controlBlock = input.tapLeafScript[0].controlBlock;
        if (!(0, parseInput_1.isValidControlBock)(controlBlock)) {
            throw new Error('Invalid PSBT taprootScriptPathSpend controlBlock.');
        }
        const scriptPathLevel = (0, parseInput_1.calculateScriptPathLevel)(controlBlock);
        const leafVersion = (0, parseInput_1.getLeafVersion)(controlBlock);
        return {
            ...parsedPubScript,
            ...signatures,
            scriptType: parsedPubScript.scriptType,
            controlBlock,
            scriptPathLevel,
            leafVersion,
        };
    }
    if (parsedPubScript.scriptType === 'p2sh' ||
        parsedPubScript.scriptType === 'p2wsh' ||
        parsedPubScript.scriptType === 'p2shP2wsh') {
        if (parsedPubScript.scriptType === 'p2shP2wsh') {
            parsedPubScript.redeemScript = input.redeemScript;
        }
        return {
            ...parsedPubScript,
            ...signatures,
        };
    }
    if (parsedPubScript.scriptType === 'p2shP2pk' && (!signatures.signatures || !(0, types_1.isTuple)(signatures.signatures))) {
        return {
            ...parsedPubScript,
            signatures: signatures.signatures,
        };
    }
    throw new Error('invalid pub script');
}
/**
 * Converts a parsed script type into an array of script types.
 * @param parsedScriptType - The parsed script type.
 * @returns An array of ScriptType2Of3 values corresponding to the parsed script type.
 */
function toScriptType2Of3s(parsedScriptType) {
    return parsedScriptType === 'taprootScriptPathSpend'
        ? ['p2trMusig2', 'p2tr']
        : parsedScriptType === 'taprootKeyPathSpend'
            ? ['p2trMusig2']
            : [parsedScriptType];
}
/**
 * @returns strictly parse the input and get signature count.
 * unsigned(0), half-signed(1) or fully-signed(2)
 */
function getStrictSignatureCount(input) {
    const calculateSignatureCount = (signatures) => {
        const count = signatures ? signatures.filter((s) => !(0, parseInput_1.isPlaceholderSignature)(s)).length : 0;
        if (count === 0 || count === 1 || count === 2) {
            return count;
        }
        throw new Error('invalid signature count');
    };
    if ('hash' in input) {
        if (input.script?.length || input.witness?.length) {
            const parsedInput = (0, parseInput_1.parseSignatureScript)(input);
            return parsedInput.scriptType === 'taprootKeyPathSpend' ? 2 : calculateSignatureCount(parsedInput.signatures);
        }
        return 0;
    }
    else {
        return calculateSignatureCount(parsePsbtInput(input).signatures);
    }
}
/**
 * @returns strictly parse input and get signature count for all inputs.
 * 0=unsigned, 1=half-signed or 2=fully-signed
 */
function getStrictSignatureCounts(tx) {
    const inputs = tx instanceof UtxoPsbt_1.UtxoPsbt ? tx.data.inputs : tx instanceof UtxoTransaction_1.UtxoTransaction ? tx.ins : tx;
    return inputs.map((input, _) => getStrictSignatureCount(input));
}
/**
 * @return true iff inputs array is of PsbtInputType type
 * */
function isPsbtInputArray(inputs) {
    return !isTxInputArray(inputs);
}
/**
 * @return true iff inputs array is of TxInput type
 * */
function isTxInputArray(inputs) {
    assert.ok(!!inputs.length, 'empty inputs array');
    return 'hash' in inputs[0];
}
/**
 * @returns true iff given psbt/transaction/tx-input-array/psbt-input-array contains at least one taproot key path spend input
 */
function isTransactionWithKeyPathSpendInput(data) {
    const inputs = data instanceof UtxoPsbt_1.UtxoPsbt ? data.data.inputs : data instanceof UtxoTransaction_1.UtxoTransaction ? data.ins : data;
    if (!inputs.length) {
        return false;
    }
    if (isPsbtInputArray(inputs)) {
        return inputs.some((input, _) => getPsbtInputScriptType(input) === 'taprootKeyPathSpend');
    }
    return inputs.some((input, _) => {
        // If the input is not signed, it cannot be a taprootKeyPathSpend input because you can only
        // extract a fully signed psbt into a transaction with taprootKeyPathSpend inputs.
        if (getStrictSignatureCount(input) === 0) {
            return false;
        }
        return (0, parseInput_1.parseSignatureScript)(input).scriptType === 'taprootKeyPathSpend';
    });
}
/**
 * Set the RootWalletKeys as the globalXpubs on the psbt
 *
 * We do all the matching of the (tap)bip32Derivations masterFingerprint to the fingerprint of the
 * extendedPubkey.
 */
function addXpubsToPsbt(psbt, rootWalletKeys) {
    const safeRootWalletKeys = new WalletKeys_1.RootWalletKeys(rootWalletKeys.triple.map((bip32) => bip32.neutered()), rootWalletKeys.derivationPrefixes);
    const xPubs = safeRootWalletKeys.triple.map((bip32) => ({
        extendedPubkey: bs58check.decode(bip32.toBase58()),
        masterFingerprint: bip32.fingerprint,
        // TODO: BG-73797 - bip174 currently requires m prefix for this to be a valid globalXpub
        path: 'm',
    }));
    psbt.updateGlobal({ globalXpub: xPubs });
}
/**
 * validates signatures for each 2 of 3 input against user, backup, bitgo keys derived from rootWalletKeys.
 * @returns array of input index and its [is valid user sig exist, is valid backup sig exist, is valid user bitgo exist]
 * For p2shP2pk input, [false, false, false] is returned since it is not a 2 of 3 sig input.
 */
function getSignatureValidationArrayPsbt(psbt, rootWalletKeys) {
    return psbt.data.inputs.map((input, i) => {
        const sigValArrayForInput = getPsbtInputScriptType(input) === 'p2shP2pk'
            ? [false, false, false]
            : psbt.getSignatureValidationArray(i, { rootNodes: rootWalletKeys.triple });
        return [i, sigValArrayForInput];
    });
}
/**
 * Extracts the half signed transaction from the psbt for p2ms based script types - p2sh, p2wsh, and p2shP2wsh.
 * The purpose is to provide backward compatibility to keyternal (KRS) that only supports network transaction and p2ms script types.
 */
function extractP2msOnlyHalfSignedTx(psbt) {
    assert.ok(!!(psbt.data.inputs.length && psbt.data.outputs.length), 'empty inputs or outputs');
    const tx = psbt.getUnsignedTx();
    function isP2msParsedPsbtInput(parsed) {
        return ['p2sh', 'p2shP2wsh', 'p2wsh'].includes(parsed.scriptType);
    }
    psbt.data.inputs.forEach((input, i) => {
        const parsed = parsePsbtInput(input);
        assert.ok(isP2msParsedPsbtInput(parsed), `unsupported script type ${parsed.scriptType}`);
        assert.ok(input.partialSig?.length === 1, `unexpected signature count ${input.partialSig?.length}`);
        const [partialSig] = input.partialSig;
        assert.ok(input.sighashType !== undefined && input.sighashType === bitcoinjs_lib_1.script.signature.decode(partialSig.signature).hashType, 'signature sighash does not match input sighash type');
        // type casting is to address the invalid type checking in payments.p2ms
        const signatures = parsed.publicKeys.map((pk) => partialSig.pubkey.equals(pk) ? partialSig.signature : bitcoinjs_lib_1.opcodes.OP_0);
        const isP2SH = !!parsed.redeemScript;
        const isP2WSH = !!parsed.witnessScript;
        const payment = index_1.payments.p2ms({ output: parsed.pubScript, signatures }, { validate: false, allowIncomplete: true });
        const p2wsh = isP2WSH ? index_1.payments.p2wsh({ redeem: payment }) : undefined;
        const p2sh = isP2SH ? index_1.payments.p2sh({ redeem: p2wsh || payment }) : undefined;
        if (p2sh?.input) {
            tx.setInputScript(i, p2sh.input);
        }
        if (p2wsh?.witness) {
            tx.setWitness(i, p2wsh.witness);
        }
    });
    return tx;
}
/**
 * Clones the psbt without nonWitnessUtxo for non-segwit inputs and witnessUtxo is added instead.
 * It is not BIP-174 compliant, so use it carefully.
 */
function clonePsbtWithoutNonWitnessUtxo(psbt) {
    const newPsbt = (0, transaction_1.createPsbtFromHex)(psbt.toHex(), psbt.network);
    const txInputs = psbt.txInputs;
    psbt.data.inputs.forEach((input, i) => {
        if (input.nonWitnessUtxo && !input.witnessUtxo) {
            const tx = (0, transaction_1.createTransactionFromBuffer)(input.nonWitnessUtxo, psbt.network, { amountType: 'bigint' });
            if (!txInputs[i].hash.equals(tx.getHash())) {
                throw new Error(`Non-witness UTXO hash for input #${i} doesn't match the hash specified in the prevout`);
            }
            newPsbt.data.inputs[i].witnessUtxo = tx.outs[txInputs[i].index];
        }
        delete newPsbt.data.inputs[i].nonWitnessUtxo;
    });
    return newPsbt;
}
/**
 * Returns true if there are non-segwit inputs in the PSBT that do not contain the
 * nonWitnessUtxo.
 *
 * isPsbtLite(clonePsbtWithoutNonWitnessUtxo(psbt)) === true
 *
 * @param psbt
 */
function isPsbtLite(psbt) {
    let isFull = true;
    const nonSegwitInputTypes = ['p2shP2pk', 'p2sh'];
    psbt.data.inputs.forEach((input) => {
        if (isFull && nonSegwitInputTypes.includes(getPsbtInputScriptType(input))) {
            isFull = !!input.nonWitnessUtxo;
        }
    });
    return !isFull;
}
/**
 * Deletes witnessUtxo for non-segwit inputs to make the PSBT BIP-174 compliant.
 */
function deleteWitnessUtxoForNonSegwitInputs(psbt) {
    psbt.data.inputs.forEach((input, i) => {
        const scriptType = getPsbtInputScriptType(input);
        if (scriptType === 'p2sh' || scriptType === 'p2shP2pk') {
            delete input.witnessUtxo;
        }
    });
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHNidC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9iaXRnby93YWxsZXQvUHNidC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQWdNQSxvQ0FnQkM7QUFTRCx3Q0FZQztBQUtELHdEQXlDQztBQXlFRCx3Q0FzREM7QUFPRCw4Q0FNQztBQU1ELDBEQW9CQztBQU1ELDREQUtDO0FBS0QsNENBRUM7QUFLRCx3Q0FHQztBQUtELGdGQWtCQztBQVFELHdDQWNDO0FBT0QsMEVBUUM7QUFNRCxrRUF5Q0M7QUFNRCx3RUFnQkM7QUFVRCxnQ0FTQztBQUtELGtGQU9DO0FBbm5CRCxpQ0FBaUM7QUFHakMsZ0RBQXFEO0FBRXJELHVDQUF1QztBQUN2QywwQ0FBdUM7QUFFdkMsd0RBQXFEO0FBQ3JELG9EQU0wQjtBQUMxQiw2Q0FBaUU7QUFDakUsd0NBQW9EO0FBQ3BELGdEQUEyRztBQUMzRyx1Q0FBMkQ7QUFFM0QsOENBZXVCO0FBQ3ZCLHNDQUF1RDtBQUN2RCxvQ0FBMkM7QUFDM0MsMkNBQTBEO0FBQzFELGlEQUEyRTtBQUMzRSx1Q0FBZ0Q7QUFDaEQsMENBQStFO0FBcUUvRSxTQUFTLGlCQUFpQixDQUFDLE1BQWMsRUFBRSxVQUE2QjtJQUN0RSxNQUFNLGdCQUFnQixHQUFHLElBQUEsK0JBQWtCLEVBQUMsTUFBTSxFQUFFLHdCQUF3QixDQUFDLENBQUMsVUFBVSxDQUFDO0lBQ3pGLE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO1FBQ3ZELE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FDaEUsSUFBQSxnQ0FBZ0IsRUFBQyxlQUFlLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQ3BELENBQUM7UUFDRixJQUFJLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxT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IGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuXG5pbXBvcnQgeyBHbG9iYWxYcHViLCBQYXJ0aWFsU2lnLCBQc2J0SW5wdXQsIFRhcFNjcmlwdFNpZyB9IGZyb20gJ2JpcDE3NC9zcmMvbGliL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgY2hlY2tGb3JJbnB1dCB9IGZyb20gJ2JpcDE3NC9zcmMvbGliL3V0aWxzJztcbmltcG9ydCB7IEJJUDMySW50ZXJmYWNlIH0gZnJvbSAnYmlwMzInO1xuaW1wb3J0ICogYXMgYnM1OGNoZWNrIGZyb20gJ2JzNThjaGVjayc7XG5pbXBvcnQgeyBVdHhvUHNidCB9IGZyb20gJy4uL1V0eG9Qc2J0JztcbmltcG9ydCB7IFBzYnQgfSBmcm9tICcuLi8uLi8nO1xuaW1wb3J0IHsgVXR4b1RyYW5zYWN0aW9uIH0gZnJvbSAnLi4vVXR4b1RyYW5zYWN0aW9uJztcbmltcG9ydCB7XG4gIGNyZWF0ZU91dHB1dFNjcmlwdDJvZjMsXG4gIGdldExlYWZIYXNoLFxuICBTY3JpcHRUeXBlMk9mMyxcbiAgc2NyaXB0VHlwZUZvckNoYWluLFxuICB0b1hPbmx5UHVibGljS2V5LFxufSBmcm9tICcuLi9vdXRwdXRTY3JpcHRzJztcbmltcG9ydCB7IERlcml2ZWRXYWxsZXRLZXlzLCBSb290V2FsbGV0S2V5cyB9IGZyb20gJy4vV2FsbGV0S2V5cyc7XG5pbXBvcnQgeyB0b1ByZXZPdXRwdXRXaXRoUHJldlR4IH0gZnJvbSAnLi4vVW5zcGVudCc7XG5pbXBvcnQgeyBjcmVhdGVQc2J0RnJvbUhleCwgY3JlYXRlUHNidEZyb21UcmFuc2FjdGlvbiwgY3JlYXRlVHJhbnNhY3Rpb25Gcm9tQnVmZmVyIH0gZnJvbSAnLi4vdHJhbnNhY3Rpb24nO1xuaW1wb3J0IHsgaXNXYWxsZXRVbnNwZW50LCBXYWxsZXRVbnNwZW50IH0gZnJvbSAnLi9VbnNwZW50JztcblxuaW1wb3J0IHtcbiAgZ2V0TGVhZlZlcnNpb24sXG4gIGNhbGN1bGF0ZVNjcmlwdFBhdGhMZXZlbCxcbiAgaXNWYWxpZENvbnRyb2xCb2NrLFxuICBQYXJzZWRQdWJTY3JpcHRQMm1zLFxuICBQYXJzZWRQdWJTY3JpcHRUYXByb290U2NyaXB0UGF0aCxcbiAgcGFyc2VQdWJTY3JpcHQyT2YzLFxuICBQYXJzZWRQdWJTY3JpcHRUYXByb290LFxuICBQYXJzZWRQdWJTY3JpcHRUYXByb290S2V5UGF0aCxcbiAgcGFyc2VQdWJTY3JpcHQsXG4gIFBhcnNlZFB1YlNjcmlwdFAyc2hQMnBrLFxuICBQYXJzZWRTY3JpcHRUeXBlLFxuICBpc1BsYWNlaG9sZGVyU2lnbmF0dXJlLFxuICBwYXJzZVNpZ25hdHVyZVNjcmlwdCxcbiAgUGFyc2VkU2NyaXB0VHlwZTJPZjMsXG59IGZyb20gJy4uL3BhcnNlSW5wdXQnO1xuaW1wb3J0IHsgcGFyc2VQc2J0TXVzaWcyUGFydGlhbFNpZ3MgfSBmcm9tICcuLi9NdXNpZzInO1xuaW1wb3J0IHsgaXNUdXBsZSwgVHJpcGxlIH0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHsgY3JlYXRlVGFwcm9vdE91dHB1dFNjcmlwdCB9IGZyb20gJy4uLy4uL3RhcHJvb3QnO1xuaW1wb3J0IHsgb3Bjb2RlcyBhcyBvcHMsIHNjcmlwdCBhcyBic2NyaXB0LCBUeElucHV0IH0gZnJvbSAnYml0Y29pbmpzLWxpYic7XG5pbXBvcnQgeyBvcGNvZGVzLCBwYXltZW50cyB9IGZyb20gJy4uLy4uL2luZGV4JztcbmltcG9ydCB7IGdldFBzYnRJbnB1dFNpZ25hdHVyZUNvdW50LCBpc1BzYnRJbnB1dEZpbmFsaXplZCB9IGZyb20gJy4uL1BzYnRVdGlsJztcblxuLy8gb25seSB1c2VkIGZvciBidWlsZGluZyBgU2lnbmF0dXJlQ29udGFpbmVyYFxudHlwZSBCYXNlU2lnbmF0dXJlQ29udGFpbmVyPFQ+ID0ge1xuICBzaWduYXR1cmVzOiBUO1xufTtcblxudHlwZSBVbnNpZ25lZFNpZ25hdHVyZUNvbnRhaW5lciA9IEJhc2VTaWduYXR1cmVDb250YWluZXI8dW5kZWZpbmVkPjtcbnR5cGUgSGFsZlNpZ25lZFNpZ25hdHVyZUNvbnRhaW5lciA9IEJhc2VTaWduYXR1cmVDb250YWluZXI8W0J1ZmZlcl0+O1xudHlwZSBGdWxsU2lnbmVkU2lnbmF0dXJlQ29udGFpbmVyID0gQmFzZVNpZ25hdHVyZUNvbnRhaW5lcjxbQnVmZmVyLCBCdWZmZXJdPjtcblxudHlwZSBTaWduYXR1cmVDb250YWluZXIgPSBVbnNpZ25lZFNpZ25hdHVyZUNvbnRhaW5lciB8IEhhbGZTaWduZWRTaWduYXR1cmVDb250YWluZXIgfCBGdWxsU2lnbmVkU2lnbmF0dXJlQ29udGFpbmVyO1xuXG4vKipcbiAqIENvbnRlbnRzIG9mIGEgcHJlLWZpbmFsaXplZCBQU0JUIElucHV0IGZvciBwMnRyTXVzaWcyIGtleSBwYXRoIGluIHRoZSBub24tZmluYWxpemVkIHN0YXRlLlxuICogVCBpcyBbQnVmZmVyXSBmb3IgZmlyc3Qgc2lnbmF0dXJlLCBbQnVmZmVyLCBCdWZmZXJdIGZvciBib3RoIHNpZ25hdHVyZXMgYW5kIGB1bmRlZmluZWRgIGZvciBubyBzaWduYXR1cmVzLlxuICovXG50eXBlIEJhc2VUYXByb290S2V5UGF0aFNpZ25hdHVyZUNvbnRhaW5lcjxUPiA9IHtcbiAgc2lnbmF0dXJlczogVDtcbiAgLyoqIE9ubHkgY29udGFpbnMgcGFydGljaXBhbnRzIHRoYXQgaGF2ZSBhZGRlZCBhIHNpZ25hdHVyZSAqL1xuICBwYXJ0aWNpcGFudFB1YmxpY0tleXM6IFQ7XG59O1xuXG50eXBlIFVuc2lnbmVkVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXIgPSBCYXNlVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXI8dW5kZWZpbmVkPjtcbnR5cGUgSGFsZlNpZ25lZFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyID0gQmFzZVRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyPFtCdWZmZXJdPjtcbnR5cGUgRnVsbFNpZ25lZFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyID0gQmFzZVRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyPFtCdWZmZXIsIEJ1ZmZlcl0+O1xuXG50eXBlIFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyID1cbiAgfCBVbnNpZ25lZFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyXG4gIHwgSGFsZlNpZ25lZFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyXG4gIHwgRnVsbFNpZ25lZFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyO1xuXG4vKipcbiAqIFRvIGhvbGQgcGFyc2VkIHBzYnQgZGF0YSBmb3IgcDJtcyBiYXNlZCBzY3JpcHQgdHlwZXMgLSBwMnNoLCBwMndzaCwgYW5kIHAyc2hQMndzaFxuICovXG5leHBvcnQgdHlwZSBQYXJzZWRQc2J0UDJtcyA9IFBhcnNlZFB1YlNjcmlwdFAybXMgJiBTaWduYXR1cmVDb250YWluZXI7XG5cbi8qKlxuICogVG8gaG9sZCBwYXJzZWQgcHNidCBkYXRhIGZvciBUYXByb290S2V5UGF0aFNwZW5kIHNjcmlwdCB0eXBlLlxuICovXG5leHBvcnQgdHlwZSBQYXJzZWRQc2J0VGFwcm9vdEtleVBhdGggPSBQYXJzZWRQdWJTY3JpcHRUYXByb290S2V5UGF0aCAmIFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyO1xuXG4vKipcbiAqIFRvIGhvbGQgcGFyc2VkIHBzYnQgZGF0YSBmb3IgVGFwcm9vdFNjcmlwdFBhdGhTcGVuZCBzY3JpcHQgcGF0aCBzY3JpcHQgdHlwZS5cbiAqL1xuZXhwb3J0IHR5cGUgUGFyc2VkUHNidFRhcHJvb3RTY3JpcHRQYXRoID0gUGFyc2VkUHViU2NyaXB0VGFwcm9vdFNjcmlwdFBhdGggJlxuICBTaWduYXR1cmVDb250YWluZXIgJiB7XG4gICAgY29udHJvbEJsb2NrOiBCdWZmZXI7XG4gICAgbGVhZlZlcnNpb246IG51bWJlcjtcbiAgICAvKiogSW5kaWNhdGVzIHRoZSBsZXZlbCBpbnNpZGUgdGhlIHRhcHRyZWUuICovXG4gICAgc2NyaXB0UGF0aExldmVsOiBudW1iZXI7XG4gIH07XG5cbmV4cG9ydCB0eXBlIFBhcnNlZFBzYnRUYXByb290ID0gUGFyc2VkUHNidFRhcHJvb3RLZXlQYXRoIHwgUGFyc2VkUHNidFRhcHJvb3RTY3JpcHRQYXRoO1xuXG50eXBlIFAyc2hQMnBrU2lnbmF0dXJlQ29udGFpbmVyID0gVW5zaWduZWRTaWduYXR1cmVDb250YWluZXIgfCBIYWxmU2lnbmVkU2lnbmF0dXJlQ29udGFpbmVyO1xuXG5leHBvcnQgdHlwZSBQYXJzZWRQc2J0UDJzaFAycGsgPSBQYXJzZWRQdWJTY3JpcHRQMnNoUDJwayAmIFAyc2hQMnBrU2lnbmF0dXJlQ29udGFpbmVyO1xuXG5pbnRlcmZhY2UgV2FsbGV0U2lnbmVyIHtcbiAgd2FsbGV0S2V5OiBCSVAzMkludGVyZmFjZTtcbiAgcm9vdEtleTogQklQMzJJbnRlcmZhY2U7XG59XG5cbi8qKlxuICogcHNidCBpbnB1dCBpbmRleCBhbmQgaXRzIHVzZXIsIGJhY2t1cCwgYml0Z28gc2lnbmF0dXJlcyBzdGF0dXNcbiAqL1xuZXhwb3J0IHR5cGUgU2lnbmF0dXJlVmFsaWRhdGlvbiA9IFtpbmRleDogbnVtYmVyLCBzaWdUcmlwbGU6IFRyaXBsZTxib29sZWFuPl07XG5cbmZ1bmN0aW9uIGdldFRhcHJvb3RTaWduZXJzKHNjcmlwdDogQnVmZmVyLCB3YWxsZXRLZXlzOiBEZXJpdmVkV2FsbGV0S2V5cyk6IFtXYWxsZXRTaWduZXIsIFdhbGxldFNpZ25lcl0ge1xuICBjb25zdCBwYXJzZWRQdWJsaWNLZXlzID0gcGFyc2VQdWJTY3JpcHQyT2YzKHNjcmlwdCwgJ3RhcHJvb3RTY3JpcHRQYXRoU3BlbmQnKS5wdWJsaWNLZXlzO1xuICBjb25zdCB3YWxsZXRTaWduZXJzID0gcGFyc2VkUHVibGljS2V5cy5tYXAoKHB1YmxpY0tleSkgPT4ge1xuICAgIGNvbnN0IGluZGV4ID0gd2FsbGV0S2V5cy5wdWJsaWNLZXlzLmZpbmRJbmRleCgod2FsbGV0UHVibGljS2V5KSA9PlxuICAgICAgdG9YT25seVB1YmxpY0tleSh3YWxsZXRQdWJsaWNLZXkpLmVxdWFscyhwdWJsaWNLZXkpXG4gICAgKTtcbiAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgcmV0dXJuIHsgd2FsbGV0S2V5OiB3YWxsZXRLZXlzLnRyaXBsZVtpbmRleF0sIHJvb3RLZXk6IHdhbGxldEtleXMucGFyZW50LnRyaXBsZVtpbmRleF0gfTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUYXByb290IHB1YmxpYyBrZXkgaXMgbm90IGEgd2FsbGV0IHB1YmxpYyBrZXknKTtcbiAgfSk7XG4gIHJldHVybiBbd2FsbGV0U2lnbmVyc1swXSwgd2FsbGV0U2lnbmVyc1sxXV07XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVBzYnRJbnB1dChcbiAgcHNidDogVXR4b1BzYnQsXG4gIGlucHV0SW5kZXg6IG51bWJlcixcbiAgdW5zcGVudDogV2FsbGV0VW5zcGVudDxiaWdpbnQ+LFxuICByb290V2FsbGV0S2V5czogUm9vdFdhbGxldEtleXNcbik6IHZvaWQge1xuICBjb25zdCBpbnB1dCA9IGNoZWNrRm9ySW5wdXQocHNidC5kYXRhLmlucHV0cywgaW5wdXRJbmRleCk7XG4gIGNvbnN0IHNpZ25hdHVyZUNvdW50ID0gZ2V0UHNidElucHV0U2lnbmF0dXJlQ291bnQoaW5wdXQpO1xuICBjb25zdCBzY3JpcHRUeXBlID0gc2NyaXB0VHlwZUZvckNoYWluKHVuc3BlbnQuY2hhaW4pO1xuICBpZiAoc2lnbmF0dXJlQ291bnQgPT09IDAgJiYgc2NyaXB0VHlwZSA9PT0gJ3AydHInKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IHdhbGxldEtleXMgPSByb290V2FsbGV0S2V5cy5kZXJpdmVGb3JDaGFpbkFuZEluZGV4KHVuc3BlbnQuY2hhaW4sIHVuc3BlbnQuaW5kZXgpO1xuXG4gIGlmIChzY3JpcHRUeXBlID09PSAncDJ0cicpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoaW5wdXQudGFwTGVhZlNjcmlwdCkgfHwgaW5wdXQudGFwTGVhZlNjcmlwdC5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBQU0JUIHN0YXRlLiBNaXNzaW5nIHJlcXVpcmVkIGZpZWxkcy4nKTtcbiAgICB9XG5cbiAgICBpZiAoaW5wdXQudGFwTGVhZlNjcmlwdC5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JpdGdvIG9ubHkgc3VwcG9ydHMgYSBzaW5nbGUgdGFwIGxlYWYgc2NyaXB0IHBlciBpbnB1dCcpO1xuICAgIH1cblxuICAgIGNvbnN0IFtzaWduZXIsIGNvc2lnbmVyXSA9IGdldFRhcHJvb3RTaWduZXJzKGlucHV0LnRhcExlYWZTY3JpcHRbMF0uc2NyaXB0LCB3YWxsZXRLZXlzKTtcblxuICAgIGNvbnN0IGxlYWZIYXNoID0gZ2V0TGVhZkhhc2goe1xuICAgICAgcHVibGljS2V5czogd2FsbGV0S2V5cy5wdWJsaWNLZXlzLFxuICAgICAgc2lnbmVyOiBzaWduZXIud2FsbGV0S2V5LnB1YmxpY0tleSxcbiAgICAgIGNvc2lnbmVyOiBjb3NpZ25lci53YWxsZXRLZXkucHVibGljS2V5LFxuICAgIH0pO1xuXG4gICAgcHNidC51cGRhdGVJbnB1dChpbnB1dEluZGV4LCB7XG4gICAgICB0YXBCaXAzMkRlcml2YXRpb246IFtzaWduZXIsIGNvc2lnbmVyXS5tYXAoKHdhbGxldFNpZ25lcikgPT4gKHtcbiAgICAgICAgbGVhZkhhc2hlczogW2xlYWZIYXNoXSxcbiAgICAgICAgcHVia2V5OiB0b1hPbmx5UHVibGljS2V5KHdhbGxldFNpZ25lci53YWxsZXRLZXkucHVibGljS2V5KSxcbiAgICAgICAgcGF0aDogcm9vdFdhbGxldEtleXMuZ2V0RGVyaXZhdGlvblBhdGgod2FsbGV0U2lnbmVyLnJvb3RLZXksIHVuc3BlbnQuY2hhaW4sIHVuc3BlbnQuaW5kZXgpLFxuICAgICAgICBtYXN0ZXJGaW5nZXJwcmludDogd2FsbGV0U2lnbmVyLnJvb3RLZXkuZmluZ2VycHJpbnQsXG4gICAgICB9KSksXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHNpZ25hdHVyZUNvdW50ID09PSAwKSB7XG4gICAgICBjb25zdCB7IHdpdG5lc3NTY3JpcHQsIHJlZGVlbVNjcmlwdCB9ID0gY3JlYXRlT3V0cHV0U2NyaXB0Mm9mMyh3YWxsZXRLZXlzLnB1YmxpY0tleXMsIHNjcmlwdFR5cGUpO1xuICAgICAgaWYgKHdpdG5lc3NTY3JpcHQgJiYgcHNidC5kYXRhLmlucHV0c1tpbnB1dEluZGV4XS53aXRuZXNzU2NyaXB0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcHNidC51cGRhdGVJbnB1dChpbnB1dEluZGV4LCB7IHdpdG5lc3NTY3JpcHQgfSk7XG4gICAgICB9XG4gICAgICBpZiAocmVkZWVtU2NyaXB0ICYmIHBzYnQuZGF0YS5pbnB1dHNbaW5wdXRJbmRleF0ucmVkZWVtU2NyaXB0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcHNidC51cGRhdGVJbnB1dChpbnB1dEluZGV4LCB7IHJlZGVlbVNjcmlwdCB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwc2J0LnVwZGF0ZUlucHV0KGlucHV0SW5kZXgsIHtcbiAgICAgIGJpcDMyRGVyaXZhdGlvbjogWzAsIDEsIDJdLm1hcCgoaWR4KSA9PiAoe1xuICAgICAgICBwdWJrZXk6IHdhbGxldEtleXMudHJpcGxlW2lkeF0ucHVibGljS2V5LFxuICAgICAgICBwYXRoOiB3YWxsZXRLZXlzLnBhdGhzW2lkeF0sXG4gICAgICAgIG1hc3RlckZpbmdlcnByaW50OiByb290V2FsbGV0S2V5cy50cmlwbGVbaWR4XS5maW5nZXJwcmludCxcbiAgICAgIH0pKSxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIEByZXR1cm4gUFNCVCBmaWxsZWQgd2l0aCBtZXRhdGRhdGEgYXMgcGVyIGlucHV0IHBhcmFtcyB0eCwgdW5zcGVudHMgYW5kIHJvb3RXYWxsZXRLZXlzLlxuICogVW5zaWduZWQgUFNCVCBmb3IgdGFwcm9vdCBpbnB1dCB3aXRoIHdpdG5lc3NVdHhvXG4gKiBVbnNpZ25lZCBQU0JUIGZvciBvdGhlciBpbnB1dCB3aXRoIHdpdG5lc3NVdHhvL25vbldpdG5lc3NVdHhvLCByZWRlZW1TY3JpcHQvd2l0bmVzc1NjcmlwdCwgYmlwMzJEZXJpdmF0aW9uXG4gKiBTaWduZWQgUFNCVCBmb3IgdGFwcm9vdCBpbnB1dCB3aXRoIHdpdG5lc3NVdHhvLCB0YXBMZWFmU2NyaXB0LCB0YXBCaXAzMkRlcml2YXRpb24sIHRhcFNjcmlwdFNpZ1xuICogU2lnbmVkIFBTQlQgZm9yIG90aGVyIGlucHV0IHdpdGggd2l0bmVzc1V0eG8vbm9uV2l0bmVzc1V0eG8sIHJlZGVlbVNjcmlwdC93aXRuZXNzU2NyaXB0LCBiaXAzMkRlcml2YXRpb24sIHBhcnRpYWxTaWdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvV2FsbGV0UHNidChcbiAgdHg6IFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+LFxuICB1bnNwZW50czogV2FsbGV0VW5zcGVudDxiaWdpbnQ+W10sXG4gIHJvb3RXYWxsZXRLZXlzOiBSb290V2FsbGV0S2V5c1xuKTogVXR4b1BzYnQge1xuICBjb25zdCBwcmV2T3V0cHV0cyA9IHVuc3BlbnRzLm1hcCgodSkgPT4ge1xuICAgIGFzc2VydC5ub3RTdHJpY3RFcXVhbChzY3JpcHRUeXBlRm9yQ2hhaW4odS5jaGFpbiksICdwMnRyTXVzaWcyJyk7XG4gICAgcmV0dXJuIHRvUHJldk91dHB1dFdpdGhQcmV2VHgodSwgdHgubmV0d29yayk7XG4gIH0pO1xuICBjb25zdCBwc2J0ID0gY3JlYXRlUHNidEZyb21UcmFuc2FjdGlvbih0eCwgcHJldk91dHB1dHMpO1xuICB1bnNwZW50cy5mb3JFYWNoKCh1LCBpKSA9PiB7XG4gICAgaWYgKGlzV2FsbGV0VW5zcGVudCh1KSAmJiB1LmluZGV4ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHVwZGF0ZVBzYnRJbnB1dChwc2J0LCBpLCB1LCByb290V2FsbGV0S2V5cyk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHBzYnQ7XG59XG5cbi8qKlxuICogQHBhcmFtIHBzYnRcbiAqIEBwYXJhbSBpbnB1dEluZGV4XG4gKiBAcGFyYW0gc2lnbmVyXG4gKiBAcGFyYW0gdW5zcGVudFxuICogQHJldHVybiBzaWduZWQgUFNCVCB3aXRoIHNpZ25lcidzIGtleSBmb3IgdW5zcGVudFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2lnbldhbGxldFBzYnQoXG4gIHBzYnQ6IFV0eG9Qc2J0LFxuICBpbnB1dEluZGV4OiBudW1iZXIsXG4gIHNpZ25lcjogQklQMzJJbnRlcmZhY2UsXG4gIHVuc3BlbnQ6IFdhbGxldFVuc3BlbnQ8YmlnaW50PlxuKTogdm9pZCB7XG4gIGNvbnN0IHNjcmlwdFR5cGUgPSBzY3JpcHRUeXBlRm9yQ2hhaW4odW5zcGVudC5jaGFpbik7XG4gIGlmIChzY3JpcHRUeXBlID09PSAncDJ0cicgfHwgc2NyaXB0VHlwZSA9PT0gJ3AydHJNdXNpZzInKSB7XG4gICAgcHNidC5zaWduVGFwcm9vdElucHV0SEQoaW5wdXRJbmRleCwgc2lnbmVyKTtcbiAgfSBlbHNlIHtcbiAgICBwc2J0LnNpZ25JbnB1dEhEKGlucHV0SW5kZXgsIHNpZ25lcik7XG4gIH1cbn1cblxuLyoqXG4gKiBAcmV0dXJucyBzY3JpcHQgdHlwZSBvZiB0aGUgaW5wdXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFBzYnRJbnB1dFNjcmlwdFR5cGUoaW5wdXQ6IFBzYnRJbnB1dCk6IFBhcnNlZFNjcmlwdFR5cGUge1xuICBjb25zdCBpc1AycGsgPSAoc2NyaXB0OiBCdWZmZXIpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY2h1bmtzID0gYnNjcmlwdC5kZWNvbXBpbGUoc2NyaXB0KTtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGNodW5rcz8ubGVuZ3RoID09PSAyICYmXG4gICAgICAgIEJ1ZmZlci5pc0J1ZmZlcihjaHVua3NbMF0pICYmXG4gICAgICAgIGJzY3JpcHQuaXNDYW5vbmljYWxQdWJLZXkoY2h1bmtzWzBdKSAmJlxuICAgICAgICBjaHVua3NbMV0gPT09IG9wY29kZXMuT1BfQ0hFQ0tTSUdcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfTtcbiAgbGV0IHNjcmlwdFR5cGU6IFBhcnNlZFNjcmlwdFR5cGUgfCB1bmRlZmluZWQ7XG4gIGlmIChCdWZmZXIuaXNCdWZmZXIoaW5wdXQucmVkZWVtU2NyaXB0KSAmJiBCdWZmZXIuaXNCdWZmZXIoaW5wdXQud2l0bmVzc1NjcmlwdCkpIHtcbiAgICBzY3JpcHRUeXBlID0gJ3Ayc2hQMndzaCc7XG4gIH0gZWxzZSBpZiAoQnVmZmVyLmlzQnVmZmVyKGlucHV0LnJlZGVlbVNjcmlwdCkpIHtcbiAgICBzY3JpcHRUeXBlID0gaXNQMnBrKGlucHV0LnJlZGVlbVNjcmlwdCkgPyAncDJzaFAycGsnIDogJ3Ayc2gnO1xuICB9IGVsc2UgaWYgKEJ1ZmZlci5pc0J1ZmZlcihpbnB1dC53aXRuZXNzU2NyaXB0KSkge1xuICAgIHNjcmlwdFR5cGUgPSAncDJ3c2gnO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGlucHV0LnRhcExlYWZTY3JpcHQpICYmIGlucHV0LnRhcExlYWZTY3JpcHQubGVuZ3RoID4gMCkge1xuICAgIGlmIChzY3JpcHRUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZvdW5kIGJvdGggJHtzY3JpcHRUeXBlfSBhbmQgdGFwcm9vdFNjcmlwdFBhdGggUFNCVCBtZXRhZGF0YS5gKTtcbiAgICB9XG4gICAgaWYgKGlucHV0LnRhcExlYWZTY3JpcHQubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCaXRnbyBvbmx5IHN1cHBvcnRzIGEgc2luZ2xlIHRhcCBsZWFmIHNjcmlwdCBwZXIgaW5wdXQuJyk7XG4gICAgfVxuICAgIHNjcmlwdFR5cGUgPSAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCc7XG4gIH1cbiAgaWYgKGlucHV0LnRhcEludGVybmFsS2V5KSB7XG4gICAgaWYgKHNjcmlwdFR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRm91bmQgYm90aCAke3NjcmlwdFR5cGV9IGFuZCB0YXByb290S2V5UGF0aCBQU0JUIG1ldGFkYXRhLmApO1xuICAgIH1cbiAgICBzY3JpcHRUeXBlID0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnO1xuICB9XG4gIGlmIChzY3JpcHRUeXBlKSB7XG4gICAgcmV0dXJuIHNjcmlwdFR5cGU7XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgcGFyc2UgaW5wdXQnKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VUYXByb290S2V5UGF0aFNpZ25hdHVyZXMoaW5wdXQ6IFBzYnRJbnB1dCk6IFRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyIHtcbiAgY29uc3QgcGFydGlhbFNpZ3MgPSBwYXJzZVBzYnRNdXNpZzJQYXJ0aWFsU2lncyhpbnB1dCk7XG4gIGlmICghcGFydGlhbFNpZ3MpIHtcbiAgICByZXR1cm4geyBzaWduYXR1cmVzOiB1bmRlZmluZWQsIHBhcnRpY2lwYW50UHVibGljS2V5czogdW5kZWZpbmVkIH07XG4gIH1cbiAgY29uc3Qgc2lnbmF0dXJlcyA9IHBhcnRpYWxTaWdzLm1hcCgocFNpZykgPT4gcFNpZy5wYXJ0aWFsU2lnKTtcbiAgY29uc3QgcGFydGljaXBhbnRQdWJsaWNLZXlzID0gcGFydGlhbFNpZ3MubWFwKChwU2lnKSA9PiBwU2lnLnBhcnRpY2lwYW50UHViS2V5KTtcbiAgcmV0dXJuIGlzVHVwbGU8QnVmZmVyPihzaWduYXR1cmVzKSAmJiBpc1R1cGxlPEJ1ZmZlcj4ocGFydGljaXBhbnRQdWJsaWNLZXlzKVxuICAgID8geyBzaWduYXR1cmVzLCBwYXJ0aWNpcGFudFB1YmxpY0tleXMgfVxuICAgIDogeyBzaWduYXR1cmVzOiBbc2lnbmF0dXJlc1swXV0sIHBhcnRpY2lwYW50UHVibGljS2V5czogW3BhcnRpY2lwYW50UHVibGljS2V5c1swXV0gfTtcbn1cblxuZnVuY3Rpb24gcGFyc2VQYXJ0aWFsT3JUYXBTY3JpcHRTaWduYXR1cmVzKHNpZzogUGFydGlhbFNpZ1tdIHwgVGFwU2NyaXB0U2lnW10gfCB1bmRlZmluZWQpOiBTaWduYXR1cmVDb250YWluZXIge1xuICBpZiAoIXNpZz8ubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHsgc2lnbmF0dXJlczogdW5kZWZpbmVkIH07XG4gIH1cbiAgaWYgKHNpZy5sZW5ndGggPiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd1bmV4cGVjdGVkIHNpZ25hdHVyZSBjb3VudCcpO1xuICB9XG4gIGNvbnN0IHNpZ25hdHVyZXMgPSBzaWcubWFwKCh0U2lnKSA9PiB0U2lnLnNpZ25hdHVyZSk7XG4gIHJldHVybiBpc1R1cGxlPEJ1ZmZlcj4oc2lnbmF0dXJlcykgPyB7IHNpZ25hdHVyZXMgfSA6IHsgc2lnbmF0dXJlczogW3NpZ25hdHVyZXNbMF1dIH07XG59XG5cbmZ1bmN0aW9uIHBhcnNlU2lnbmF0dXJlcyhcbiAgaW5wdXQ6IFBzYnRJbnB1dCxcbiAgc2NyaXB0VHlwZTogUGFyc2VkU2NyaXB0VHlwZVxuKTogU2lnbmF0dXJlQ29udGFpbmVyIHwgVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXIge1xuICByZXR1cm4gc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnXG4gICAgPyBwYXJzZVRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlcyhpbnB1dClcbiAgICA6IHNjcmlwdFR5cGUgPT09ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJ1xuICAgID8gcGFyc2VQYXJ0aWFsT3JUYXBTY3JpcHRTaWduYXR1cmVzKGlucHV0LnRhcFNjcmlwdFNpZylcbiAgICA6IHBhcnNlUGFydGlhbE9yVGFwU2NyaXB0U2lnbmF0dXJlcyhpbnB1dC5wYXJ0aWFsU2lnKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VTY3JpcHQoXG4gIGlucHV0OiBQc2J0SW5wdXQsXG4gIHNjcmlwdFR5cGU6IFBhcnNlZFNjcmlwdFR5cGVcbik6IFBhcnNlZFB1YlNjcmlwdFAybXMgfCBQYXJzZWRQdWJTY3JpcHRUYXByb290IHwgUGFyc2VkUHViU2NyaXB0UDJzaFAycGsge1xuICBsZXQgcHViU2NyaXB0OiBCdWZmZXIgfCB1bmRlZmluZWQ7XG4gIGlmIChzY3JpcHRUeXBlID09PSAncDJzaCcgfHwgc2NyaXB0VHlwZSA9PT0gJ3Ayc2hQMnBrJykge1xuICAgIHB1YlNjcmlwdCA9IGlucHV0LnJlZGVlbVNjcmlwdDtcbiAgfSBlbHNlIGlmIChzY3JpcHRUeXBlID09PSAncDJ3c2gnIHx8IHNjcmlwdFR5cGUgPT09ICdwMnNoUDJ3c2gnKSB7XG4gICAgcHViU2NyaXB0ID0gaW5wdXQud2l0bmVzc1NjcmlwdDtcbiAgfSBlbHNlIGlmIChzY3JpcHRUeXBlID09PSAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCcpIHtcbiAgICBwdWJTY3JpcHQgPSBpbnB1dC50YXBMZWFmU2NyaXB0ID8gaW5wdXQudGFwTGVhZlNjcmlwdFswXS5zY3JpcHQgOiB1bmRlZmluZWQ7XG4gIH0gZWxzZSBpZiAoc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnKSB7XG4gICAgaWYgKGlucHV0LndpdG5lc3NVdHhvPy5zY3JpcHQpIHtcbiAgICAgIHB1YlNjcmlwdCA9IGlucHV0LndpdG5lc3NVdHhvLnNjcmlwdDtcbiAgICB9IGVsc2UgaWYgKGlucHV0LnRhcEludGVybmFsS2V5ICYmIGlucHV0LnRhcE1lcmtsZVJvb3QpIHtcbiAgICAgIHB1YlNjcmlwdCA9IGNyZWF0ZVRhcHJvb3RPdXRwdXRTY3JpcHQoeyBpbnRlcm5hbFB1YktleTogaW5wdXQudGFwSW50ZXJuYWxLZXksIHRhcHRyZWVSb290OiBpbnB1dC50YXBNZXJrbGVSb290IH0pO1xuICAgIH1cbiAgfVxuICBpZiAoIXB1YlNjcmlwdCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBQU0JUIHN0YXRlIGZvciAke3NjcmlwdFR5cGV9LiBNaXNzaW5nIHJlcXVpcmVkIGZpZWxkcy5gKTtcbiAgfVxuICByZXR1cm4gcGFyc2VQdWJTY3JpcHQocHViU2NyaXB0LCBzY3JpcHRUeXBlKTtcbn1cblxuLyoqXG4gKiBAcmV0dXJuIHBzYnQgbWV0YWRhdGEgYXJlIHBhcnNlZCBhcyBwZXIgYmVsb3cgY29uZGl0aW9ucy5cbiAqIHJlZGVlbVNjcmlwdC93aXRuZXNzU2NyaXB0L3RhcExlYWZTY3JpcHQgbWF0Y2hlcyBCaXRHby5cbiAqIHNpZ25hdHVyZSBhbmQgcHVibGljIGtleSBjb3VudCBtYXRjaGVzIEJpdEdvLlxuICogUDJTSC1QMlBLID0+IHNjcmlwdFR5cGUsIHJlZGVlbVNjcmlwdCwgcHVibGljIGtleSwgc2lnbmF0dXJlLlxuICogUDJTSCA9PiBzY3JpcHRUeXBlLCByZWRlZW1TY3JpcHQsIHB1YmxpYyBrZXlzLCBzaWduYXR1cmVzLlxuICogUFcyU0ggPT4gc2NyaXB0VHlwZSwgd2l0bmVzc1NjcmlwdCwgcHVibGljIGtleXMsIHNpZ25hdHVyZXMuXG4gKiBQMlNILVBXMlNIID0+IHNjcmlwdFR5cGUsIHJlZGVlbVNjcmlwdCwgd2l0bmVzc1NjcmlwdCwgcHVibGljIGtleXMsIHNpZ25hdHVyZXMuXG4gKiBQMlRSIGFuZCBQMlRSIE1VU0lHMiBzY3JpcHQgcGF0aCA9PiBzY3JpcHRUeXBlICh0YXByb290U2NyaXB0UGF0aFNwZW5kKSwgcHViU2NyaXB0IChsZWFmIHNjcmlwdCksIGNvbnRyb2xCbG9jayxcbiAqIHNjcmlwdFBhdGhMZXZlbCwgbGVhZlZlcnNpb24sIHB1YmxpYyBrZXlzLCBzaWduYXR1cmVzLlxuICogUDJUUiBNVVNJRzIga2VwIHBhdGggPT4gc2NyaXB0VHlwZSAodGFwcm9vdEtleVBhdGhTcGVuZCksIHB1YlNjcmlwdCAoc2NyaXB0UHViS2V5KSwgcGFydGljaXBhbnQgcHViIGtleXMgKHNpZ25lciksXG4gKiBwdWJsaWMga2V5ICh0YXBPdXRwdXRrZXkpLCBzaWduYXR1cmVzIChwYXJ0aWFsIHNpZ25lciBzaWdzKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUHNidElucHV0KGlucHV0OiBQc2J0SW5wdXQpOiBQYXJzZWRQc2J0UDJtcyB8IFBhcnNlZFBzYnRUYXByb290IHwgUGFyc2VkUHNidFAyc2hQMnBrIHtcbiAgaWYgKGlzUHNidElucHV0RmluYWxpemVkKGlucHV0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmluYWxpemVkIFBTQlQgcGFyc2luZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgY29uc3Qgc2NyaXB0VHlwZSA9IGdldFBzYnRJbnB1dFNjcmlwdFR5cGUoaW5wdXQpO1xuICBjb25zdCBwYXJzZWRQdWJTY3JpcHQgPSBwYXJzZVNjcmlwdChpbnB1dCwgc2NyaXB0VHlwZSk7XG4gIGNvbnN0IHNpZ25hdHVyZXMgPSBwYXJzZVNpZ25hdHVyZXMoaW5wdXQsIHNjcmlwdFR5cGUpO1xuXG4gIGlmIChwYXJzZWRQdWJTY3JpcHQuc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnICYmICdwYXJ0aWNpcGFudFB1YmxpY0tleXMnIGluIHNpZ25hdHVyZXMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4ucGFyc2VkUHViU2NyaXB0LFxuICAgICAgLi4uc2lnbmF0dXJlcyxcbiAgICAgIHNjcmlwdFR5cGU6IHBhcnNlZFB1YlNjcmlwdC5zY3JpcHRUeXBlLFxuICAgIH07XG4gIH1cbiAgaWYgKHBhcnNlZFB1YlNjcmlwdC5zY3JpcHRUeXBlID09PSAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCcpIHtcbiAgICBpZiAoIWlucHV0LnRhcExlYWZTY3JpcHQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBQU0JUIHN0YXRlIGZvciB0YXByb290U2NyaXB0UGF0aFNwZW5kLiBNaXNzaW5nIHJlcXVpcmVkIGZpZWxkcy4nKTtcbiAgICB9XG4gICAgY29uc3QgY29udHJvbEJsb2NrID0gaW5wdXQudGFwTGVhZlNjcmlwdFswXS5jb250cm9sQmxvY2s7XG4gICAgaWYgKCFpc1ZhbGlkQ29udHJvbEJvY2soY29udHJvbEJsb2NrKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFBTQlQgdGFwcm9vdFNjcmlwdFBhdGhTcGVuZCBjb250cm9sQmxvY2suJyk7XG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdFBhdGhMZXZlbCA9IGNhbGN1bGF0ZVNjcmlwdFBhdGhMZXZlbChjb250cm9sQmxvY2spO1xuICAgIGNvbnN0IGxlYWZWZXJzaW9uID0gZ2V0TGVhZlZlcnNpb24oY29udHJvbEJsb2NrKTtcbiAgICByZXR1cm4ge1xuICAgICAgLi4ucGFyc2VkUHViU2NyaXB0LFxuICAgICAgLi4uc2lnbmF0dXJlcyxcbiAgICAgIHNjcmlwdFR5cGU6IHBhcnNlZFB1YlNjcmlwdC5zY3JpcHRUeXBlLFxuICAgICAgY29udHJvbEJsb2NrLFxuICAgICAgc2NyaXB0UGF0aExldmVsLFxuICAgICAgbGVhZlZlcnNpb24sXG4gICAgfTtcbiAgfVxuICBpZiAoXG4gICAgcGFyc2VkUHViU2NyaXB0LnNjcmlwdFR5cGUgPT09ICdwMnNoJyB8fFxuICAgIHBhcnNlZFB1YlNjcmlwdC5zY3JpcHRUeXBlID09PSAncDJ3c2gnIHx8XG4gICAgcGFyc2VkUHViU2NyaXB0LnNjcmlwdFR5cGUgPT09ICdwMnNoUDJ3c2gnXG4gICkge1xuICAgIGlmIChwYXJzZWRQdWJTY3JpcHQuc2NyaXB0VHlwZSA9PT0gJ3Ayc2hQMndzaCcpIHtcbiAgICAgIHBhcnNlZFB1YlNjcmlwdC5yZWRlZW1TY3JpcHQgPSBpbnB1dC5yZWRlZW1TY3JpcHQ7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAuLi5wYXJzZWRQdWJTY3JpcHQsXG4gICAgICAuLi5zaWduYXR1cmVzLFxuICAgIH07XG4gIH1cbiAgaWYgKHBhcnNlZFB1YlNjcmlwdC5zY3JpcHRUeXBlID09PSAncDJzaFAycGsnICYmICghc2lnbmF0dXJlcy5zaWduYXR1cmVzIHx8ICFpc1R1cGxlKHNpZ25hdHVyZXMuc2lnbmF0dXJlcykpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnBhcnNlZFB1YlNjcmlwdCxcbiAgICAgIHNpZ25hdHVyZXM6IHNpZ25hdHVyZXMuc2lnbmF0dXJlcyxcbiAgICB9O1xuICB9XG4gIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBwdWIgc2NyaXB0Jyk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBwYXJzZWQgc2NyaXB0IHR5cGUgaW50byBhbiBhcnJheSBvZiBzY3JpcHQgdHlwZXMuXG4gKiBAcGFyYW0gcGFyc2VkU2NyaXB0VHlwZSAtIFRoZSBwYXJzZWQgc2NyaXB0IHR5cGUuXG4gKiBAcmV0dXJucyBBbiBhcnJheSBvZiBTY3JpcHRUeXBlMk9mMyB2YWx1ZXMgY29ycmVzcG9uZGluZyB0byB0aGUgcGFyc2VkIHNjcmlwdCB0eXBlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9TY3JpcHRUeXBlMk9mM3MocGFyc2VkU2NyaXB0VHlwZTogUGFyc2VkU2NyaXB0VHlwZTJPZjMpOiBTY3JpcHRUeXBlMk9mM1tdIHtcbiAgcmV0dXJuIHBhcnNlZFNjcmlwdFR5cGUgPT09ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJ1xuICAgID8gWydwMnRyTXVzaWcyJywgJ3AydHInXVxuICAgIDogcGFyc2VkU2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnXG4gICAgPyBbJ3AydHJNdXNpZzInXVxuICAgIDogW3BhcnNlZFNjcmlwdFR5cGVdO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHN0cmljdGx5IHBhcnNlIHRoZSBpbnB1dCBhbmQgZ2V0IHNpZ25hdHVyZSBjb3VudC5cbiAqIHVuc2lnbmVkKDApLCBoYWxmLXNpZ25lZCgxKSBvciBmdWxseS1zaWduZWQoMilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFN0cmljdFNpZ25hdHVyZUNvdW50KGlucHV0OiBUeElucHV0IHwgUHNidElucHV0KTogMCB8IDEgfCAyIHtcbiAgY29uc3QgY2FsY3VsYXRlU2lnbmF0dXJlQ291bnQgPSAoXG4gICAgc2lnbmF0dXJlczogW0J1ZmZlciB8IDAsIEJ1ZmZlciB8IDAsIEJ1ZmZlciB8IDBdIHwgW0J1ZmZlciwgQnVmZmVyXSB8IFtCdWZmZXJdIHwgdW5kZWZpbmVkXG4gICk6IDAgfCAxIHwgMiA9PiB7XG4gICAgY29uc3QgY291bnQgPSBzaWduYXR1cmVzID8gc2lnbmF0dXJlcy5maWx0ZXIoKHMpID0+ICFpc1BsYWNlaG9sZGVyU2lnbmF0dXJlKHMpKS5sZW5ndGggOiAwO1xuICAgIGlmIChjb3VudCA9PT0gMCB8fCBjb3VudCA9PT0gMSB8fCBjb3VudCA9PT0gMikge1xuICAgICAgcmV0dXJuIGNvdW50O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2lnbmF0dXJlIGNvdW50Jyk7XG4gIH07XG5cbiAgaWYgKCdoYXNoJyBpbiBpbnB1dCkge1xuICAgIGlmIChpbnB1dC5zY3JpcHQ/Lmxlbmd0aCB8fCBpbnB1dC53aXRuZXNzPy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHBhcnNlZElucHV0ID0gcGFyc2VTaWduYXR1cmVTY3JpcHQoaW5wdXQpO1xuICAgICAgcmV0dXJuIHBhcnNlZElucHV0LnNjcmlwdFR5cGUgPT09ICd0YXByb290S2V5UGF0aFNwZW5kJyA/IDIgOiBjYWxjdWxhdGVTaWduYXR1cmVDb3VudChwYXJzZWRJbnB1dC5zaWduYXR1cmVzKTtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNhbGN1bGF0ZVNpZ25hdHVyZUNvdW50KHBhcnNlUHNidElucHV0KGlucHV0KS5zaWduYXR1cmVzKTtcbiAgfVxufVxuXG4vKipcbiAqIEByZXR1cm5zIHN0cmljdGx5IHBhcnNlIGlucHV0IGFuZCBnZXQgc2lnbmF0dXJlIGNvdW50IGZvciBhbGwgaW5wdXRzLlxuICogMD11bnNpZ25lZCwgMT1oYWxmLXNpZ25lZCBvciAyPWZ1bGx5LXNpZ25lZFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RyaWN0U2lnbmF0dXJlQ291bnRzKFxuICB0eDogVXR4b1BzYnQgfCBVdHhvVHJhbnNhY3Rpb248bnVtYmVyIHwgYmlnaW50PiB8IFBzYnRJbnB1dFtdIHwgVHhJbnB1dFtdXG4pOiAoMCB8IDEgfCAyKVtdIHtcbiAgY29uc3QgaW5wdXRzID0gdHggaW5zdGFuY2VvZiBVdHhvUHNidCA/IHR4LmRhdGEuaW5wdXRzIDogdHggaW5zdGFuY2VvZiBVdHhvVHJhbnNhY3Rpb24gPyB0eC5pbnMgOiB0eDtcbiAgcmV0dXJuIGlucHV0cy5tYXAoKGlucHV0LCBfKSA9PiBnZXRTdHJpY3RTaWduYXR1cmVDb3VudChpbnB1dCkpO1xufVxuXG4vKipcbiAqIEByZXR1cm4gdHJ1ZSBpZmYgaW5wdXRzIGFycmF5IGlzIG9mIFBzYnRJbnB1dFR5cGUgdHlwZVxuICogKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1BzYnRJbnB1dEFycmF5KGlucHV0czogUHNidElucHV0W10gfCBUeElucHV0W10pOiBpbnB1dHMgaXMgUHNidElucHV0W10ge1xuICByZXR1cm4gIWlzVHhJbnB1dEFycmF5KGlucHV0cyk7XG59XG5cbi8qKlxuICogQHJldHVybiB0cnVlIGlmZiBpbnB1dHMgYXJyYXkgaXMgb2YgVHhJbnB1dCB0eXBlXG4gKiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHhJbnB1dEFycmF5KGlucHV0czogUHNidElucHV0W10gfCBUeElucHV0W10pOiBpbnB1dHMgaXMgVHhJbnB1dFtdIHtcbiAgYXNzZXJ0Lm9rKCEhaW5wdXRzLmxlbmd0aCwgJ2VtcHR5IGlucHV0cyBhcnJheScpO1xuICByZXR1cm4gJ2hhc2gnIGluIGlucHV0c1swXTtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB0cnVlIGlmZiBnaXZlbiBwc2J0L3RyYW5zYWN0aW9uL3R4LWlucHV0LWFycmF5L3BzYnQtaW5wdXQtYXJyYXkgY29udGFpbnMgYXQgbGVhc3Qgb25lIHRhcHJvb3Qga2V5IHBhdGggc3BlbmQgaW5wdXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQoXG4gIGRhdGE6IFV0eG9Qc2J0IHwgVXR4b1RyYW5zYWN0aW9uPGJpZ2ludCB8IG51bWJlcj4gfCBQc2J0SW5wdXRbXSB8IFR4SW5wdXRbXVxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGlucHV0cyA9IGRhdGEgaW5zdGFuY2VvZiBVdHhvUHNidCA/IGRhdGEuZGF0YS5pbnB1dHMgOiBkYXRhIGluc3RhbmNlb2YgVXR4b1RyYW5zYWN0aW9uID8gZGF0YS5pbnMgOiBkYXRhO1xuICBpZiAoIWlucHV0cy5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKGlzUHNidElucHV0QXJyYXkoaW5wdXRzKSkge1xuICAgIHJldHVybiBpbnB1dHMuc29tZSgoaW5wdXQsIF8pID0+IGdldFBzYnRJbnB1dFNjcmlwdFR5cGUoaW5wdXQpID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCcpO1xuICB9XG4gIHJldHVybiBpbnB1dHMuc29tZSgoaW5wdXQsIF8pID0+IHtcbiAgICAvLyBJZiB0aGUgaW5wdXQgaXMgbm90IHNpZ25lZCwgaXQgY2Fubm90IGJlIGEgdGFwcm9vdEtleVBhdGhTcGVuZCBpbnB1dCBiZWNhdXNlIHlvdSBjYW4gb25seVxuICAgIC8vIGV4dHJhY3QgYSBmdWxseSBzaWduZWQgcHNidCBpbnRvIGEgdHJhbnNhY3Rpb24gd2l0aCB0YXByb290S2V5UGF0aFNwZW5kIGlucHV0cy5cbiAgICBpZiAoZ2V0U3RyaWN0U2lnbmF0dXJlQ291bnQoaW5wdXQpID09PSAwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBwYXJzZVNpZ25hdHVyZVNjcmlwdChpbnB1dCkuc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnO1xuICB9KTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIFJvb3RXYWxsZXRLZXlzIGFzIHRoZSBnbG9iYWxYcHVicyBvbiB0aGUgcHNidFxuICpcbiAqIFdlIGRvIGFsbCB0aGUgbWF0Y2hpbmcgb2YgdGhlICh0YXApYmlwMzJEZXJpdmF0aW9ucyBtYXN0ZXJGaW5nZXJwcmludCB0byB0aGUgZmluZ2VycHJpbnQgb2YgdGhlXG4gKiBleHRlbmRlZFB1YmtleS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZFhwdWJzVG9Qc2J0KHBzYnQ6IFBzYnQsIHJvb3RXYWxsZXRLZXlzOiBSb290V2FsbGV0S2V5cyk6IHZvaWQge1xuICBjb25zdCBzYWZlUm9vdFdhbGxldEtleXMgPSBuZXcgUm9vdFdhbGxldEtleXMoXG4gICAgcm9vdFdhbGxldEtleXMudHJpcGxlLm1hcCgoYmlwMzIpID0+IGJpcDMyLm5ldXRlcmVkKCkpIGFzIFRyaXBsZTxCSVAzMkludGVyZmFjZT4sXG4gICAgcm9vdFdhbGxldEtleXMuZGVyaXZhdGlvblByZWZpeGVzXG4gICk7XG4gIGNvbnN0IHhQdWJzID0gc2FmZVJvb3RXYWxsZXRLZXlzLnRyaXBsZS5tYXAoXG4gICAgKGJpcDMyKTogR2xvYmFsWHB1YiA9PiAoe1xuICAgICAgZXh0ZW5kZWRQdWJrZXk6IGJzNThjaGVjay5kZWNvZGUoYmlwMzIudG9CYXNlNTgoKSksXG4gICAgICBtYXN0ZXJGaW5nZXJwcmludDogYmlwMzIuZmluZ2VycHJpbnQsXG4gICAgICAvLyBUT0RPOiBCRy03Mzc5NyAtIGJpcDE3NCBjdXJyZW50bHkgcmVxdWlyZXMgbSBwcmVmaXggZm9yIHRoaXMgdG8gYmUgYSB2YWxpZCBnbG9iYWxYcHViXG4gICAgICBwYXRoOiAnbScsXG4gICAgfSlcbiAgKTtcbiAgcHNidC51cGRhdGVHbG9iYWwoeyBnbG9iYWxYcHViOiB4UHVicyB9KTtcbn1cblxuLyoqXG4gKiB2YWxpZGF0ZXMgc2lnbmF0dXJlcyBmb3IgZWFjaCAyIG9mIDMgaW5wdXQgYWdhaW5zdCB1c2VyLCBiYWNrdXAsIGJpdGdvIGtleXMgZGVyaXZlZCBmcm9tIHJvb3RXYWxsZXRLZXlzLlxuICogQHJldHVybnMgYXJyYXkgb2YgaW5wdXQgaW5kZXggYW5kIGl0cyBbaXMgdmFsaWQgdXNlciBzaWcgZXhpc3QsIGlzIHZhbGlkIGJhY2t1cCBzaWcgZXhpc3QsIGlzIHZhbGlkIHVzZXIgYml0Z28gZXhpc3RdXG4gKiBGb3IgcDJzaFAycGsgaW5wdXQsIFtmYWxzZSwgZmFsc2UsIGZhbHNlXSBpcyByZXR1cm5lZCBzaW5jZSBpdCBpcyBub3QgYSAyIG9mIDMgc2lnIGlucHV0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2lnbmF0dXJlVmFsaWRhdGlvbkFycmF5UHNidChwc2J0OiBVdHhvUHNidCwgcm9vdFdhbGxldEtleXM6IFJvb3RXYWxsZXRLZXlzKTogU2lnbmF0dXJlVmFsaWRhdGlvbltdIHtcbiAgcmV0dXJuIHBzYnQuZGF0YS5pbnB1dHMubWFwKChpbnB1dCwgaSkgPT4ge1xuICAgIGNvbnN0IHNpZ1ZhbEFycmF5Rm9ySW5wdXQ6IFRyaXBsZTxib29sZWFuPiA9XG4gICAgICBnZXRQc2J0SW5wdXRTY3JpcHRUeXBlKGlucHV0KSA9PT0gJ3Ayc2hQMnBrJ1xuICAgICAgICA/IFtmYWxzZSwgZmFsc2UsIGZhbHNlXVxuICAgICAgICA6IHBzYnQuZ2V0U2lnbmF0dXJlVmFsaWRhdGlvbkFycmF5KGksIHsgcm9vdE5vZGVzOiByb290V2FsbGV0S2V5cy50cmlwbGUgfSk7XG4gICAgcmV0dXJuIFtpLCBzaWdWYWxBcnJheUZvcklucHV0XTtcbiAgfSk7XG59XG5cbi8qKlxuICogRXh0cmFjdHMgdGhlIGhhbGYgc2lnbmVkIHRyYW5zYWN0aW9uIGZyb20gdGhlIHBzYnQgZm9yIHAybXMgYmFzZWQgc2NyaXB0IHR5cGVzIC0gcDJzaCwgcDJ3c2gsIGFuZCBwMnNoUDJ3c2guXG4gKiBUaGUgcHVycG9zZSBpcyB0byBwcm92aWRlIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgdG8ga2V5dGVybmFsIChLUlMpIHRoYXQgb25seSBzdXBwb3J0cyBuZXR3b3JrIHRyYW5zYWN0aW9uIGFuZCBwMm1zIHNjcmlwdCB0eXBlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RQMm1zT25seUhhbGZTaWduZWRUeChwc2J0OiBVdHhvUHNidCk6IFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+IHtcbiAgYXNzZXJ0Lm9rKCEhKHBzYnQuZGF0YS5pbnB1dHMubGVuZ3RoICYmIHBzYnQuZGF0YS5vdXRwdXRzLmxlbmd0aCksICdlbXB0eSBpbnB1dHMgb3Igb3V0cHV0cycpO1xuICBjb25zdCB0eCA9IHBzYnQuZ2V0VW5zaWduZWRUeCgpO1xuXG4gIGZ1bmN0aW9uIGlzUDJtc1BhcnNlZFBzYnRJbnB1dChcbiAgICBwYXJzZWQ6IFBhcnNlZFBzYnRQMm1zIHwgUGFyc2VkUHNidFRhcHJvb3QgfCBQYXJzZWRQc2J0UDJzaFAycGtcbiAgKTogcGFyc2VkIGlzIFBhcnNlZFBzYnRQMm1zIHtcbiAgICByZXR1cm4gWydwMnNoJywgJ3Ayc2hQMndzaCcsICdwMndzaCddLmluY2x1ZGVzKHBhcnNlZC5zY3JpcHRUeXBlKTtcbiAgfVxuXG4gIHBzYnQuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGkpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVBzYnRJbnB1dChpbnB1dCk7XG4gICAgYXNzZXJ0Lm9rKGlzUDJtc1BhcnNlZFBzYnRJbnB1dChwYXJzZWQpLCBgdW5zdXBwb3J0ZWQgc2NyaXB0IHR5cGUgJHtwYXJzZWQuc2NyaXB0VHlwZX1gKTtcbiAgICBhc3NlcnQub2soaW5wdXQucGFydGlhbFNpZz8ubGVuZ3RoID09PSAxLCBgdW5leHBlY3RlZCBzaWduYXR1cmUgY291bnQgJHtpbnB1dC5wYXJ0aWFsU2lnPy5sZW5ndGh9YCk7XG4gICAgY29uc3QgW3BhcnRpYWxTaWddID0gaW5wdXQucGFydGlhbFNpZztcbiAgICBhc3NlcnQub2soXG4gICAgICBpbnB1dC5zaWdoYXNoVHlwZSAhPT0gdW5kZWZpbmVkICYmIGlucHV0LnNpZ2hhc2hUeXBlID09PSBic2NyaXB0LnNpZ25hdHVyZS5kZWNvZGUocGFydGlhbFNpZy5zaWduYXR1cmUpLmhhc2hUeXBlLFxuICAgICAgJ3NpZ25hdHVyZSBzaWdoYXNoIGRvZXMgbm90IG1hdGNoIGlucHV0IHNpZ2hhc2ggdHlwZSdcbiAgICApO1xuXG4gICAgLy8gdHlwZSBjYXN0aW5nIGlzIHRvIGFkZHJlc3MgdGhlIGludmFsaWQgdHlwZSBjaGVja2luZyBpbiBwYXltZW50cy5wMm1zXG4gICAgY29uc3Qgc2lnbmF0dXJlcyA9IHBhcnNlZC5wdWJsaWNLZXlzLm1hcCgocGspID0+XG4gICAgICBwYXJ0aWFsU2lnLnB1YmtleS5lcXVhbHMocGspID8gcGFydGlhbFNpZy5zaWduYXR1cmUgOiAob3BzLk9QXzAgYXMgdW5rbm93biBhcyBCdWZmZXIpXG4gICAgKTtcblxuICAgIGNvbnN0IGlzUDJTSCA9ICEhcGFyc2VkLnJlZGVlbVNjcmlwdDtcbiAgICBjb25zdCBpc1AyV1NIID0gISFwYXJzZWQud2l0bmVzc1NjcmlwdDtcblxuICAgIGNvbnN0IHBheW1lbnQgPSBwYXltZW50cy5wMm1zKHsgb3V0cHV0OiBwYXJzZWQucHViU2NyaXB0LCBzaWduYXR1cmVzIH0sIHsgdmFsaWRhdGU6IGZhbHNlLCBhbGxvd0luY29tcGxldGU6IHRydWUgfSk7XG4gICAgY29uc3QgcDJ3c2ggPSBpc1AyV1NIID8gcGF5bWVudHMucDJ3c2goeyByZWRlZW06IHBheW1lbnQgfSkgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgcDJzaCA9IGlzUDJTSCA/IHBheW1lbnRzLnAyc2goeyByZWRlZW06IHAyd3NoIHx8IHBheW1lbnQgfSkgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAocDJzaD8uaW5wdXQpIHtcbiAgICAgIHR4LnNldElucHV0U2NyaXB0KGksIHAyc2guaW5wdXQpO1xuICAgIH1cbiAgICBpZiAocDJ3c2g/LndpdG5lc3MpIHtcbiAgICAgIHR4LnNldFdpdG5lc3MoaSwgcDJ3c2gud2l0bmVzcyk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gdHg7XG59XG5cbi8qKlxuICogQ2xvbmVzIHRoZSBwc2J0IHdpdGhvdXQgbm9uV2l0bmVzc1V0eG8gZm9yIG5vbi1zZWd3aXQgaW5wdXRzIGFuZCB3aXRuZXNzVXR4byBpcyBhZGRlZCBpbnN0ZWFkLlxuICogSXQgaXMgbm90IEJJUC0xNzQgY29tcGxpYW50LCBzbyB1c2UgaXQgY2FyZWZ1bGx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvbmVQc2J0V2l0aG91dE5vbldpdG5lc3NVdHhvKHBzYnQ6IFV0eG9Qc2J0KTogVXR4b1BzYnQge1xuICBjb25zdCBuZXdQc2J0ID0gY3JlYXRlUHNidEZyb21IZXgocHNidC50b0hleCgpLCBwc2J0Lm5ldHdvcmspO1xuICBjb25zdCB0eElucHV0cyA9IHBzYnQudHhJbnB1dHM7XG5cbiAgcHNidC5kYXRhLmlucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgIGlmIChpbnB1dC5ub25XaXRuZXNzVXR4byAmJiAhaW5wdXQud2l0bmVzc1V0eG8pIHtcbiAgICAgIGNvbnN0IHR4ID0gY3JlYXRlVHJhbnNhY3Rpb25Gcm9tQnVmZmVyKGlucHV0Lm5vbldpdG5lc3NVdHhvLCBwc2J0Lm5ldHdvcmssIHsgYW1vdW50VHlwZTogJ2JpZ2ludCcgfSk7XG4gICAgICBpZiAoIXR4SW5wdXRzW2ldLmhhc2guZXF1YWxzKHR4LmdldEhhc2goKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb24td2l0bmVzcyBVVFhPIGhhc2ggZm9yIGlucHV0ICMke2l9IGRvZXNuJ3QgbWF0Y2ggdGhlIGhhc2ggc3BlY2lmaWVkIGluIHRoZSBwcmV2b3V0YCk7XG4gICAgICB9XG4gICAgICBuZXdQc2J0LmRhdGEuaW5wdXRzW2ldLndpdG5lc3NVdHhvID0gdHgub3V0c1t0eElucHV0c1tpXS5pbmRleF07XG4gICAgfVxuICAgIGRlbGV0ZSBuZXdQc2J0LmRhdGEuaW5wdXRzW2ldLm5vbldpdG5lc3NVdHhvO1xuICB9KTtcblxuICByZXR1cm4gbmV3UHNidDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlcmUgYXJlIG5vbi1zZWd3aXQgaW5wdXRzIGluIHRoZSBQU0JUIHRoYXQgZG8gbm90IGNvbnRhaW4gdGhlXG4gKiBub25XaXRuZXNzVXR4by5cbiAqXG4gKiBpc1BzYnRMaXRlKGNsb25lUHNidFdpdGhvdXROb25XaXRuZXNzVXR4byhwc2J0KSkgPT09IHRydWVcbiAqXG4gKiBAcGFyYW0gcHNidFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQc2J0TGl0ZShwc2J0OiBVdHhvUHNidCk6IGJvb2xlYW4ge1xuICBsZXQgaXNGdWxsID0gdHJ1ZTtcbiAgY29uc3Qgbm9uU2Vnd2l0SW5wdXRUeXBlcyA9IFsncDJzaFAycGsnLCAncDJzaCddO1xuICBwc2J0LmRhdGEuaW5wdXRzLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgaWYgKGlzRnVsbCAmJiBub25TZWd3aXRJbnB1dFR5cGVzLmluY2x1ZGVzKGdldFBzYnRJbnB1dFNjcmlwdFR5cGUoaW5wdXQpKSkge1xuICAgICAgaXNGdWxsID0gISFpbnB1dC5ub25XaXRuZXNzVXR4bztcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gIWlzRnVsbDtcbn1cblxuLyoqXG4gKiBEZWxldGVzIHdpdG5lc3NVdHhvIGZvciBub24tc2Vnd2l0IGlucHV0cyB0byBtYWtlIHRoZSBQU0JUIEJJUC0xNzQgY29tcGxpYW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVsZXRlV2l0bmVzc1V0eG9Gb3JOb25TZWd3aXRJbnB1dHMocHNidDogVXR4b1BzYnQpOiB2b2lkIHtcbiAgcHNidC5kYXRhLmlucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgIGNvbnN0IHNjcmlwdFR5cGUgPSBnZXRQc2J0SW5wdXRTY3JpcHRUeXBlKGlucHV0KTtcbiAgICBpZiAoc2NyaXB0VHlwZSA9PT0gJ3Ayc2gnIHx8IHNjcmlwdFR5cGUgPT09ICdwMnNoUDJwaycpIHtcbiAgICAgIGRlbGV0ZSBpbnB1dC53aXRuZXNzVXR4bztcbiAgICB9XG4gIH0pO1xufVxuIl19

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


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