PHP WebShell

Текущая директория: /opt/BitGoJS/modules/utxo-lib/dist/test/bitgo/psbt

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

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const src_1 = require("../../../src");
const bitgo_1 = require("../../../src/bitgo");
const outputScripts_1 = require("../../../src/bitgo/outputScripts");
const testutil_1 = require("../../../src/testutil");
const transaction_util_1 = require("../../transaction_util");
const psbtUtil_1 = require("./psbtUtil");
const testutil_2 = require("../../../src/testutil");
const Musig2Util_1 = require("./Musig2Util");
const CHANGE_INDEX = 100;
const FEE = BigInt(100);
const network = src_1.networks.bitcoin;
const rootWalletKeys = (0, testutil_1.getDefaultWalletKeys)();
function getScriptTypes2Of3() {
    // FIXME(BG-66941): p2trMusig2 signing does not work in this test suite yet
    //  because the test suite is written with TransactionBuilder
    return bitgo_1.outputScripts.scriptTypes2Of3.filter((scriptType) => scriptType !== 'p2trMusig2');
}
const halfSignedInputs = ['p2sh', 'p2wsh', 'p2shP2wsh'].map((scriptType) => ({
    scriptType,
    value: BigInt(1000),
}));
const halfSignedOutputs = testutil_1.outputScriptTypes.map((scriptType) => ({ scriptType, value: BigInt(500) }));
const psbtInputs = testutil_1.inputScriptTypes.map((scriptType) => ({ scriptType, value: BigInt(1000) }));
const psbtOutputs = testutil_1.outputScriptTypes.map((scriptType) => ({ scriptType, value: BigInt(900) }));
describe('Psbt Misc', function () {
    function getTestPsbt() {
        return src_1.testutil.constructPsbt([{ scriptType: 'p2tr', value: BigInt(1000) }], [{ scriptType: 'p2sh', value: BigInt(900) }], network, rootWalletKeys, 'fullsigned');
    }
    it('fail to finalise p2tr sighash mismatch', function () {
        const psbt = getTestPsbt();
        assert(psbt.validateSignaturesOfAllInputs());
        const tapScriptSig = psbt.data.inputs[0].tapScriptSig;
        assert(tapScriptSig);
        tapScriptSig[0].signature = Buffer.concat([tapScriptSig[0].signature, Buffer.of(src_1.Transaction.SIGHASH_ALL)]);
        assert.throws(() => psbt.finalizeAllInputs(), (e) => e.message === 'signature sighash does not match input sighash type');
    });
    describe('isPsbtLite', function () {
        it('no inputs', function () {
            const psbt = src_1.testutil.constructPsbt([], [], network, rootWalletKeys, 'unsigned');
            assert.strictEqual((0, bitgo_1.isPsbtLite)(psbt), false);
        });
        it('all inputs are segwit', function () {
            const psbt = src_1.testutil.constructPsbt(psbtInputs.filter((s) => s.scriptType !== 'p2sh' && s.scriptType !== 'p2shP2pk'), psbtOutputs, network, rootWalletKeys, 'unsigned');
            assert.strictEqual((0, bitgo_1.isPsbtLite)(psbt), false);
        });
        it('some inputs are non-segwit', function () {
            const psbt = src_1.testutil.constructPsbt(psbtInputs, psbtOutputs, network, rootWalletKeys, 'unsigned');
            assert.strictEqual((0, bitgo_1.isPsbtLite)(psbt), false);
        });
        it('should be true if after clonePsbtWithoutNonWitnessUtxo', function () {
            const psbt = src_1.testutil.constructPsbt(psbtInputs, psbtOutputs, network, rootWalletKeys, 'unsigned');
            const clonedPsbt = (0, bitgo_1.clonePsbtWithoutNonWitnessUtxo)(psbt);
            assert.strictEqual((0, bitgo_1.isPsbtLite)(clonedPsbt), true);
        });
    });
});
describe('extractP2msOnlyHalfSignedTx failure', function () {
    it('invalid signature count', function () {
        const psbt = src_1.testutil.constructPsbt(halfSignedInputs, halfSignedOutputs, network, rootWalletKeys, 'unsigned');
        assert.throws(() => (0, bitgo_1.extractP2msOnlyHalfSignedTx)(psbt), (e) => e.message === 'unexpected signature count undefined');
    });
    it('empty inputs', function () {
        const psbt = src_1.testutil.constructPsbt([], [], network, rootWalletKeys, 'unsigned');
        assert.throws(() => (0, bitgo_1.extractP2msOnlyHalfSignedTx)(psbt), (e) => e.message === 'empty inputs or outputs');
    });
    it('unsupported script type', function () {
        const psbt = src_1.testutil.constructPsbt([{ scriptType: 'p2tr', value: BigInt(1000) }], [{ scriptType: 'p2sh', value: BigInt(900) }], network, rootWalletKeys, 'halfsigned');
        assert.throws(() => (0, bitgo_1.extractP2msOnlyHalfSignedTx)(psbt), (e) => e.message === 'unsupported script type taprootScriptPathSpend');
    });
});
function runExtractP2msOnlyHalfSignedTxTest(network, inputs, outputs) {
    const coin = (0, src_1.getNetworkName)(network);
    describe(`extractP2msOnlyHalfSignedTx success for ${coin}`, function () {
        it(`success for ${coin}`, function () {
            const signers = { signerName: 'user', cosignerName: 'backup' };
            const txnOutputs = outputs;
            const txnInputs = inputs
                .map((v) => v.scriptType === 'p2sh' || v.scriptType === 'p2shP2wsh' || v.scriptType === 'p2wsh'
                ? {
                    scriptType: v.scriptType,
                    value: v.value,
                }
                : undefined)
                .filter((v) => !!v);
            const psbt = src_1.testutil.constructPsbt(inputs, outputs, network, rootWalletKeys, 'halfsigned', { signers });
            const halfSignedPsbtTx = (0, bitgo_1.extractP2msOnlyHalfSignedTx)(psbt);
            let txb = src_1.testutil.constructTxnBuilder(txnInputs, txnOutputs, network, rootWalletKeys, 'halfsigned', signers);
            const halfSignedTxbTx = txb.buildIncomplete();
            const unspents = (0, psbtUtil_1.toBigInt)(inputs.map((input, i) => src_1.testutil.toUnspent(input, i, network, rootWalletKeys)));
            (0, psbtUtil_1.assertEqualTransactions)(halfSignedPsbtTx, halfSignedTxbTx);
            (0, psbtUtil_1.validatePsbtParsing)(halfSignedPsbtTx, psbt, unspents, 'halfsigned');
            (0, psbtUtil_1.validatePsbtParsing)(halfSignedTxbTx, psbt, unspents, 'halfsigned');
            src_1.testutil.signAllPsbtInputs(psbt, inputs, rootWalletKeys, 'fullsigned', { signers });
            const fullySignedPsbt = psbt.clone();
            const psbtTx = psbt.finalizeAllInputs().extractTransaction();
            const txnUnspents = txnInputs.map((v, i) => src_1.testutil.toTxnUnspent(v, i, network, rootWalletKeys));
            const prevOutputs = txnUnspents.map((u) => (0, bitgo_1.toOutput)(u, network));
            txb = (0, bitgo_1.createTransactionBuilderFromTransaction)(halfSignedTxbTx, prevOutputs);
            (0, testutil_1.signAllTxnInputs)(txb, txnInputs, rootWalletKeys, 'fullsigned', signers);
            const txbTx = txb.build();
            (0, psbtUtil_1.assertEqualTransactions)(psbtTx, txbTx);
            (0, psbtUtil_1.validatePsbtParsing)(psbtTx, fullySignedPsbt, unspents, 'fullsigned');
            (0, psbtUtil_1.validatePsbtParsing)(txbTx, fullySignedPsbt, unspents, 'fullsigned');
        });
    });
}
function runBuildSignSendFlowTest(network, inputs, outputs, { skipNonWitnessUtxo = false } = {}) {
    const coin = (0, src_1.getNetworkName)(network);
    function assertValidate(psbt) {
        psbt.data.inputs.forEach((input, i) => {
            assert.ok(psbt.validateSignaturesOfInputHD(i, rootWalletKeys['user']));
            if ((0, bitgo_1.getPsbtInputScriptType)(input) !== 'p2shP2pk') {
                assert.ok(psbt.validateSignaturesOfInputHD(i, rootWalletKeys['bitgo']));
            }
        });
        assert.ok(psbt.validateSignaturesOfAllInputs());
    }
    describe(`Build, sign & send flow for ${coin}`, function () {
        /**
         * Skip adding nonWitnessUtxos to psbts
         * ------------------------------------
         * In the instance that we want to doing a bulk sweep, for network and client performance reasons we are substituting
         * the nonWitnessUtxo for p2sh and p2shP2pk inputs with a witnessUtxo. We need the witnessUtxo so that we can half
         * sign the transaction locally with the user key. When we send the half signed to BitGo, the PSBT will be properly
         * populated such that the non-segwit inputs have the nonWitnessUtxo. This means when we send it to BitGo we should
         * remove the witnessUtxo so that it just has the partialSig and redeemScript.
         */
        it(`success for ${coin}${skipNonWitnessUtxo ? ' without nonWitnessUtxo for p2sh' : ''}`, function () {
            const parentPsbt = src_1.testutil.constructPsbt(inputs, outputs, network, rootWalletKeys, 'unsigned', {
                signers: {
                    signerName: 'user',
                    cosignerName: 'bitgo',
                },
            });
            let psbt = skipNonWitnessUtxo ? (0, bitgo_1.clonePsbtWithoutNonWitnessUtxo)(parentPsbt) : parentPsbt;
            (0, bitgo_1.addXpubsToPsbt)(psbt, rootWalletKeys);
            psbt.setAllInputsMusig2NonceHD(rootWalletKeys['user']);
            let psbtWithoutPrevTx = (0, bitgo_1.clonePsbtWithoutNonWitnessUtxo)(psbt);
            let hex = psbtWithoutPrevTx.toHex();
            let psbtAtHsm = (0, bitgo_1.createPsbtFromHex)(hex, network);
            psbtAtHsm.setAllInputsMusig2NonceHD(rootWalletKeys['bitgo'], { deterministic: true });
            let hexAtHsm = psbtAtHsm.toHex();
            let psbtFromHsm = (0, bitgo_1.createPsbtFromHex)(hexAtHsm, network);
            (0, bitgo_1.deleteWitnessUtxoForNonSegwitInputs)(psbtFromHsm);
            psbt.combine(psbtFromHsm);
            src_1.testutil.signAllPsbtInputs(psbt, inputs, rootWalletKeys, 'halfsigned', {
                signers: {
                    signerName: 'user',
                    cosignerName: 'bitgo',
                },
                skipNonWitnessUtxo,
            });
            psbtWithoutPrevTx = (0, bitgo_1.clonePsbtWithoutNonWitnessUtxo)(psbt);
            hex = psbtWithoutPrevTx.toHex();
            psbtAtHsm = (0, bitgo_1.createPsbtFromHex)(hex, network);
            (0, bitgo_1.withUnsafeNonSegwit)(psbtAtHsm, () => {
                src_1.testutil.signAllPsbtInputs(psbtAtHsm, inputs, rootWalletKeys, 'fullsigned', {
                    signers: {
                        signerName: 'user',
                        cosignerName: 'bitgo',
                    },
                    deterministic: true,
                });
            });
            (0, bitgo_1.withUnsafeNonSegwit)(psbtAtHsm, () => {
                assertValidate(psbtAtHsm);
            });
            hexAtHsm = psbtAtHsm.toHex();
            psbtFromHsm = (0, bitgo_1.createPsbtFromHex)(hexAtHsm, network);
            (0, bitgo_1.deleteWitnessUtxoForNonSegwitInputs)(psbtFromHsm);
            if (skipNonWitnessUtxo) {
                psbt = parentPsbt;
            }
            psbt.combine(psbtFromHsm);
            assertValidate(psbt);
            assert.doesNotThrow(() => psbt.finalizeAllInputs().extractTransaction());
        });
    });
}
function runBuildPsbtWithSDK(network, inputs, outputs) {
    const coin = (0, src_1.getNetworkName)(network);
    it(`check that building a PSBT while skipping nonWitnessUtxo works - ${coin}`, async function () {
        const psbtWithNonWitness = src_1.testutil.constructPsbt(inputs, outputs, network, rootWalletKeys, 'unsigned', {
            signers: {
                signerName: 'user',
                cosignerName: 'bitgo',
            },
        });
        const psbtWithoutNonWitness = src_1.testutil.constructPsbt(inputs, outputs, network, rootWalletKeys, 'unsigned', {
            signers: {
                signerName: 'user',
                cosignerName: 'bitgo',
            },
            skipNonWitnessUtxo: true,
        });
        const clonedPsbt = (0, bitgo_1.clonePsbtWithoutNonWitnessUtxo)(psbtWithNonWitness);
        assert.deepStrictEqual(psbtWithoutNonWitness.toHex(), clonedPsbt.toHex());
    });
}
(0, src_1.getNetworkList)()
    .filter((v) => (0, src_1.isMainnet)(v) && v !== src_1.networks.bitcoinsv)
    .forEach((network) => {
    runExtractP2msOnlyHalfSignedTxTest(network, halfSignedInputs.filter((input) => (0, outputScripts_1.isSupportedScriptType)(network, input.scriptType)), halfSignedOutputs.filter((output) => (0, outputScripts_1.isSupportedScriptType)(network, output.scriptType)));
    const supportedPsbtInputs = psbtInputs.filter((input) => (0, outputScripts_1.isSupportedScriptType)(network, input.scriptType === 'taprootKeyPathSpend' ? 'p2trMusig2' : input.scriptType));
    const supportedPsbtOutputs = psbtOutputs.filter((output) => (0, outputScripts_1.isSupportedScriptType)(network, output.scriptType));
    [false, true].forEach((skipNonWitnessUtxo) => runBuildSignSendFlowTest(network, supportedPsbtInputs, supportedPsbtOutputs, { skipNonWitnessUtxo }));
    runBuildPsbtWithSDK(network, supportedPsbtInputs, supportedPsbtOutputs);
});
describe('isTransactionWithKeyPathSpendInput', function () {
    describe('transaction input', function () {
        it('empty inputs', function () {
            const tx = src_1.testutil.constructTxnBuilder([], [], network, rootWalletKeys, 'unsigned').buildIncomplete();
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx), false);
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx.ins), false);
        });
        it('taprootKeyPath inputs successfully triggers', function () {
            const psbt = src_1.testutil.constructPsbt([
                { scriptType: 'taprootKeyPathSpend', value: BigInt(1e8) },
                { scriptType: 'p2sh', value: BigInt(1e8) },
            ], [{ scriptType: 'p2sh', value: BigInt(2e8 - 10000) }], network, rootWalletKeys, 'fullsigned');
            assert(psbt.validateSignaturesOfAllInputs());
            psbt.finalizeAllInputs();
            const tx = psbt.extractTransaction();
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx), true);
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx.ins), true);
        });
        it('no taprootKeyPath inputs successfully does not trigger', function () {
            const psbt = src_1.testutil.constructPsbt([
                { scriptType: 'p2trMusig2', value: BigInt(1e8) },
                { scriptType: 'p2sh', value: BigInt(1e8) },
            ], [{ scriptType: 'p2sh', value: BigInt(2e8 - 10000) }], network, rootWalletKeys, 'fullsigned');
            assert(psbt.validateSignaturesOfAllInputs());
            psbt.finalizeAllInputs();
            const tx = psbt.extractTransaction();
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx), false);
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx.ins), false);
        });
        it('unsigned inputs successfully fail', function () {
            const psbt = src_1.testutil.constructPsbt([
                { scriptType: 'p2wsh', value: BigInt(1e8) },
                { scriptType: 'p2sh', value: BigInt(1e8) },
            ], [{ scriptType: 'p2sh', value: BigInt(2e8 - 10000) }], network, rootWalletKeys, 'unsigned');
            const tx = psbt.getUnsignedTx();
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx), false);
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(tx.ins), false);
        });
    });
    describe('psbt input', function () {
        it('empty inputs', function () {
            const psbt = src_1.testutil.constructPsbt([], [], network, rootWalletKeys, 'unsigned');
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(psbt), false);
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(psbt.data.inputs), false);
        });
        it('psbt with taprootKeyPathInputs successfully triggers', function () {
            const psbt = src_1.testutil.constructPsbt([
                { scriptType: 'taprootKeyPathSpend', value: BigInt(1e8) },
                { scriptType: 'p2sh', value: BigInt(1e8) },
            ], [{ scriptType: 'p2sh', value: BigInt(2e8 - 10000) }], network, rootWalletKeys, 'unsigned');
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(psbt), true);
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(psbt.data.inputs), true);
        });
        it('psbt without taprootKeyPathInputs successfully does not trigger', function () {
            const psbt = src_1.testutil.constructPsbt([
                { scriptType: 'p2wsh', value: BigInt(1e8) },
                { scriptType: 'p2sh', value: BigInt(1e8) },
            ], [{ scriptType: 'p2sh', value: BigInt(2e8 - 10000) }], network, rootWalletKeys, 'halfsigned');
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(psbt), false);
            assert.strictEqual((0, bitgo_1.isTransactionWithKeyPathSpendInput)(psbt.data.inputs), false);
        });
    });
});
describe('Parse PSBT', function () {
    it('p2shP2pk parsing', function () {
        const signer = rootWalletKeys['user'];
        const psbt = (0, bitgo_1.createPsbtForNetwork)({ network: src_1.networks.bitcoincash });
        const unspent = (0, testutil_1.mockReplayProtectionUnspent)(src_1.networks.bitcoincash, BigInt(1e8), { key: signer });
        const { redeemScript } = (0, outputScripts_1.createOutputScriptP2shP2pk)(signer.publicKey);
        assert(redeemScript);
        (0, bitgo_1.addReplayProtectionUnspentToPsbt)(psbt, unspent, redeemScript);
        (0, bitgo_1.addWalletOutputToPsbt)(psbt, rootWalletKeys, (0, bitgo_1.getInternalChainCode)('p2sh'), 0, BigInt(1e8 - 10000));
        const input = psbt.data.inputs[0];
        let parsed = (0, bitgo_1.parsePsbtInput)(input);
        assert.strictEqual(parsed.scriptType, 'p2shP2pk');
        assert.strictEqual(parsed.signatures, undefined);
        assert.strictEqual(parsed.publicKeys.length, 1);
        assert.ok(parsed.publicKeys[0].length === 33);
        assert.ok(parsed.pubScript.equals(redeemScript));
        psbt.signAllInputs(signer);
        assert.ok(psbt.validateSignaturesOfAllInputs());
        parsed = (0, bitgo_1.parsePsbtInput)(input);
        assert.strictEqual(parsed.scriptType, 'p2shP2pk');
        assert.strictEqual(parsed.signatures?.length, 1);
        assert.strictEqual(parsed.publicKeys.length, 1);
        assert.ok(parsed.publicKeys[0].length === 33);
        assert.ok(parsed.pubScript.equals(redeemScript));
        const sighash = parsed.signatures[0][parsed.signatures[0].length - 1];
        assert.strictEqual(sighash, (0, bitgo_1.getDefaultSigHash)(psbt.network));
    });
    it('fail to parse finalized psbt', function () {
        const unspents = (0, testutil_2.mockUnspents)(rootWalletKeys, getScriptTypes2Of3().map((inputType) => inputType), BigInt('10000000000000000'), network);
        const txBuilderParams = {
            signer: 'user',
            cosigner: 'bitgo',
            amountType: 'bigint',
            outputType: 'p2sh',
            signatureTarget: 'fullsigned',
            network,
            changeIndex: CHANGE_INDEX,
            fee: FEE,
        };
        const tx = (0, psbtUtil_1.constructTransactionUsingTxBuilder)(unspents, rootWalletKeys, txBuilderParams);
        const psbt = (0, bitgo_1.toWalletPsbt)(tx, (0, psbtUtil_1.toBigInt)(unspents), rootWalletKeys);
        psbt.validateSignaturesOfAllInputs();
        psbt.finalizeAllInputs();
        psbt.data.inputs.forEach((input, i) => {
            assert.throws(() => (0, bitgo_1.parsePsbtInput)(input), (e) => e.message === 'Finalized PSBT parsing is not supported');
        });
    });
    it('fail to parse input with more than one script type metadata', function () {
        const unspents = (0, testutil_2.mockUnspents)(rootWalletKeys, ['p2tr'], BigInt('10000000000000000'), network);
        const txBuilderParams = {
            signer: 'user',
            cosigner: 'bitgo',
            amountType: 'bigint',
            outputType: 'p2sh',
            signatureTarget: 'halfsigned',
            network,
            changeIndex: CHANGE_INDEX,
            fee: FEE,
        };
        const txP2tr = (0, psbtUtil_1.constructTransactionUsingTxBuilder)([unspents[0]], rootWalletKeys, txBuilderParams);
        const psbtP2tr = (0, bitgo_1.toWalletPsbt)(txP2tr, (0, psbtUtil_1.toBigInt)([unspents[0]]), rootWalletKeys);
        const walletKeys = rootWalletKeys.deriveForChainAndIndex((0, bitgo_1.getExternalChainCode)('p2sh'), 0);
        const { redeemScript } = (0, outputScripts_1.createOutputScript2of3)(walletKeys.publicKeys, 'p2sh');
        psbtP2tr.updateInput(0, { redeemScript });
        assert.throws(() => (0, bitgo_1.parsePsbtInput)(psbtP2tr.data.inputs[0]), (e) => e.message === 'Found both p2sh and taprootScriptPath PSBT metadata.');
    });
    it('fail to parse more than one tap leaf script per input', function () {
        const unspents = (0, testutil_2.mockUnspents)(rootWalletKeys, ['p2tr'], BigInt('10000000000000000'), network);
        const txBuilderParams = {
            signer: 'user',
            cosigner: 'bitgo',
            amountType: 'bigint',
            outputType: 'p2sh',
            signatureTarget: 'halfsigned',
            network,
            changeIndex: CHANGE_INDEX,
            fee: FEE,
        };
        const txP2tr1 = (0, psbtUtil_1.constructTransactionUsingTxBuilder)([unspents[0]], rootWalletKeys, txBuilderParams);
        const psbtP2tr1 = (0, bitgo_1.toWalletPsbt)(txP2tr1, (0, psbtUtil_1.toBigInt)([unspents[0]]), rootWalletKeys);
        const txBuilderParams2 = {
            signer: 'user',
            cosigner: 'backup',
            amountType: 'bigint',
            outputType: 'p2sh',
            signatureTarget: 'halfsigned',
            network,
            changeIndex: CHANGE_INDEX,
            fee: FEE,
        };
        const txP2tr2 = (0, psbtUtil_1.constructTransactionUsingTxBuilder)([unspents[0]], rootWalletKeys, txBuilderParams2);
        const psbtP2tr2 = (0, bitgo_1.toWalletPsbt)(txP2tr2, (0, psbtUtil_1.toBigInt)([unspents[0]]), rootWalletKeys);
        const txBuilderParams3 = {
            signer: 'user',
            cosigner: 'bitgo',
            amountType: 'bigint',
            outputType: 'p2sh',
            signatureTarget: 'unsigned',
            network,
            changeIndex: CHANGE_INDEX,
            fee: FEE,
        };
        const txP2tr3 = (0, psbtUtil_1.constructTransactionUsingTxBuilder)([unspents[0]], rootWalletKeys, txBuilderParams3);
        const psbtP2tr3 = (0, bitgo_1.toWalletPsbt)(txP2tr3, (0, psbtUtil_1.toBigInt)([unspents[0]]), rootWalletKeys);
        if (psbtP2tr1.data.inputs[0].tapLeafScript && psbtP2tr2.data.inputs[0].tapLeafScript) {
            const tapLeafScripts = [psbtP2tr1.data.inputs[0].tapLeafScript[0], psbtP2tr2.data.inputs[0].tapLeafScript[0]];
            psbtP2tr3.updateInput(0, { tapLeafScript: tapLeafScripts });
            assert.throws(() => (0, bitgo_1.parsePsbtInput)(psbtP2tr3.data.inputs[0]), (e) => e.message === 'Bitgo only supports a single tap leaf script per input.');
        }
    });
});
describe('isPsbt', function () {
    function isPsbtForNetwork(n) {
        describe(`network: ${(0, src_1.getNetworkName)(n)}`, function () {
            const psbt = (0, bitgo_1.createPsbtForNetwork)({ network: n });
            it('should return true for a valid PSBT', function () {
                const psbtBuff = psbt.toBuffer();
                assert.strictEqual((0, bitgo_1.isPsbt)(psbtBuff), true);
                assert.strictEqual((0, bitgo_1.isPsbt)(psbtBuff.toString('hex')), true);
            });
            it('should return false for a transaction', function () {
                assert.strictEqual((0, bitgo_1.isPsbt)(psbt.getUnsignedTx().toBuffer()), false);
            });
            it('should return false for a truncated magic word', function () {
                const hex = psbt.toBuffer().slice(0, 3);
                assert.strictEqual((0, bitgo_1.isPsbt)(hex), false);
                assert.strictEqual((0, bitgo_1.isPsbt)(Buffer.from(hex)), false);
            });
            it('should return false for a valid PSBT with an invalid magic', function () {
                const buffer = psbt.toBuffer();
                buffer.writeUInt8(0x00, 1);
                assert.strictEqual((0, bitgo_1.isPsbt)(psbt.getUnsignedTx().toBuffer()), false);
            });
            it('should return false for a valid PSBT with an invalid separator', function () {
                const buffer = psbt.toBuffer();
                buffer.writeUInt8(0xfe, 4);
                assert.strictEqual((0, bitgo_1.isPsbt)(psbt.getUnsignedTx().toBuffer()), false);
            });
            it('should return false for a random buffer', function () {
                const random = 'deadbeaf';
                const buffer = Buffer.from(random, 'hex');
                assert.strictEqual((0, bitgo_1.isPsbt)(random), false);
                assert.strictEqual((0, bitgo_1.isPsbt)(buffer), false);
            });
            it('should return true if buffer is changed after the separator', function () {
                const buffer = psbt.toBuffer();
                buffer.writeUInt8(0x00, 5);
                assert.strictEqual((0, bitgo_1.isPsbt)(buffer), true);
            });
        });
    }
    (0, src_1.getNetworkList)().forEach((n) => isPsbtForNetwork(n));
});
describe('Update incomplete psbt', function () {
    function removeFromPsbt(psbtHex, network, remove) {
        const utxoPsbt = (0, bitgo_1.createPsbtFromHex)(psbtHex, network);
        const psbt = (0, bitgo_1.createPsbtForNetwork)({ network: utxoPsbt.network });
        const txInputs = utxoPsbt.txInputs;
        utxoPsbt.data.inputs.map((input, ii) => {
            const { hash, index } = txInputs[ii];
            if (remove.input && ii === remove.input.index) {
                delete input[remove.input.fieldToRemove];
            }
            psbt.addInput({ ...input, hash, index });
        });
        const txOutputs = utxoPsbt.txOutputs;
        utxoPsbt.data.outputs.map((output, ii) => {
            if (remove.output && remove.output.index === ii) {
                delete output[remove.output.fieldToRemove];
            }
            psbt.addOutput({ ...output, script: txOutputs[ii].script, value: txOutputs[ii].value });
        });
        return psbt;
    }
    function signAllInputs(psbt, { assertValidSignaturesAndExtractable = true } = {}) {
        psbt.data.inputs.forEach((input, inputIndex) => {
            const parsedInput = (0, bitgo_1.parsePsbtInput)(input);
            if (parsedInput.scriptType === 'taprootKeyPathSpend') {
                psbt.setInputMusig2NonceHD(inputIndex, rootWalletKeys[signer]);
                psbt.setInputMusig2NonceHD(inputIndex, rootWalletKeys[cosigner]);
            }
            if (parsedInput.scriptType === 'p2shP2pk') {
                psbt.signInput(inputIndex, testutil_1.replayProtectionKeyPair);
            }
            else {
                psbt.signInputHD(inputIndex, rootWalletKeys[signer]);
                psbt.signInputHD(inputIndex, rootWalletKeys[cosigner]);
            }
        });
        if (assertValidSignaturesAndExtractable) {
            assert.ok(psbt.validateSignaturesOfAllInputs());
            psbt.finalizeAllInputs();
            const txExtracted = psbt.extractTransaction();
            assert.ok(txExtracted);
        }
    }
    let psbtHex;
    let unspents;
    const signer = 'user';
    const cosigner = 'bitgo';
    const scriptTypes = [...outputScripts_1.scriptTypes2Of3, 'p2shP2pk'];
    const outputValue = BigInt((2e8 * scriptTypes.length - 100) / 5);
    const outputs = [
        { chain: (0, bitgo_1.getExternalChainCode)('p2sh'), index: 88, value: outputValue },
        { chain: (0, bitgo_1.getExternalChainCode)('p2shP2wsh'), index: 89, value: outputValue },
        { chain: (0, bitgo_1.getExternalChainCode)('p2wsh'), index: 90, value: outputValue },
        { chain: (0, bitgo_1.getExternalChainCode)('p2tr'), index: 91, value: outputValue },
        { chain: (0, bitgo_1.getExternalChainCode)('p2trMusig2'), index: 92, value: outputValue },
    ];
    before(function () {
        unspents = (0, testutil_2.mockUnspents)(rootWalletKeys, scriptTypes, BigInt(2e8), network);
        const psbt = (0, Musig2Util_1.constructPsbt)(unspents, rootWalletKeys, signer, cosigner, outputs);
        psbtHex = psbt.toHex();
    });
    it('can create a sign-able psbt from an unsigned transaction extracted from the psbt', function () {
        if (true) {
            return;
        }
        const psbtOrig = (0, bitgo_1.createPsbtFromHex)(psbtHex, network);
        const tx = psbtOrig.getUnsignedTx();
        const psbt = (0, bitgo_1.createPsbtFromTransaction)(tx, unspents.map((u) => (0, bitgo_1.toPrevOutput)(u, network)));
        unspents.forEach((u, inputIndex) => {
            if ((0, bitgo_1.isWalletUnspent)(u)) {
                (0, bitgo_1.updateWalletUnspentForPsbt)(psbt, inputIndex, u, rootWalletKeys, signer, cosigner);
            }
            else {
                const { redeemScript } = (0, outputScripts_1.createOutputScriptP2shP2pk)(testutil_1.replayProtectionKeyPair.publicKey);
                (0, bitgo_1.updateReplayProtectionUnspentToPsbt)(psbt, inputIndex, u, redeemScript);
            }
        });
        signAllInputs(psbt);
    });
    const componentsOnEachInputScriptType = {
        p2sh: ['nonWitnessUtxo', 'redeemScript', 'bip32Derivation'],
        p2shP2wsh: ['witnessUtxo', 'bip32Derivation', 'redeemScript', 'witnessScript'],
        p2wsh: ['witnessUtxo', 'witnessScript', 'bip32Derivation'],
        p2tr: ['witnessUtxo', 'tapLeafScript', 'tapBip32Derivation'],
        p2trMusig2: ['witnessUtxo', 'tapBip32Derivation', 'tapInternalKey', 'tapMerkleRoot', 'unknownKeyVals'],
        p2shP2pk: ['redeemScript', 'nonWitnessUtxo'],
    };
    const p2trComponents = ['tapTree', 'tapInternalKey', 'tapBip32Derivation'];
    const componentsOnEachOutputScriptType = {
        p2sh: ['bip32Derivation', 'redeemScript'],
        p2shP2wsh: ['bip32Derivation', 'witnessScript', 'redeemScript'],
        p2wsh: ['bip32Derivation', 'witnessScript'],
        p2tr: p2trComponents,
        p2trMusig2: p2trComponents,
        p2shP2pk: [],
    };
    scriptTypes.forEach((scriptType, i) => {
        componentsOnEachInputScriptType[scriptType].forEach((inputComponent) => {
            it(`[${scriptType}] missing ${inputComponent} on input should succeed in fully signing unsigned psbt after update`, function () {
                const psbt = removeFromPsbt(psbtHex, network, { input: { index: i, fieldToRemove: inputComponent } });
                const unspent = unspents[i];
                if ((0, bitgo_1.isWalletUnspent)(unspent)) {
                    (0, bitgo_1.updateWalletUnspentForPsbt)(psbt, i, unspent, rootWalletKeys, signer, cosigner);
                }
                else {
                    const { redeemScript } = (0, outputScripts_1.createOutputScriptP2shP2pk)(testutil_1.replayProtectionKeyPair.publicKey);
                    assert.ok(redeemScript);
                    (0, bitgo_1.updateReplayProtectionUnspentToPsbt)(psbt, i, unspent, redeemScript);
                }
                signAllInputs(psbt);
            });
        });
        componentsOnEachOutputScriptType[scriptType].forEach((outputComponent) => {
            it(`[${scriptType}] missing ${outputComponent} on output should produce same hex as fully hydrated after update`, function () {
                const psbt = removeFromPsbt(psbtHex, network, { output: { index: i, fieldToRemove: outputComponent } });
                (0, bitgo_1.updateWalletOutputForPsbt)(psbt, rootWalletKeys, i, outputs[i].chain, outputs[i].index);
                assert.strictEqual(psbt.toHex(), psbtHex);
            });
        });
    });
});
describe('Psbt from transaction using wallet unspents', function () {
    function runTestSignUnspents({ inputScriptTypes, outputScriptType, signer, cosigner, amountType, testOutputAmount, signatureTarget, }) {
        it(`can be signed [inputs=${inputScriptTypes} signer=${signer} cosigner=${cosigner} amountType=${amountType} signatureTarget=${signatureTarget}]`, function () {
            const unspents = (0, testutil_2.mockUnspents)(rootWalletKeys, inputScriptTypes, testOutputAmount, network);
            // const txBuilderParams = { network, changeIndex: CHANGE_INDEX, fee: FEE };
            const txBuilderParams = {
                signer,
                cosigner,
                amountType,
                outputType: outputScriptType,
                signatureTarget: signatureTarget,
                network,
                changeIndex: CHANGE_INDEX,
                fee: FEE,
            };
            const tx = (0, psbtUtil_1.constructTransactionUsingTxBuilder)(unspents, rootWalletKeys, txBuilderParams);
            const unspentBigInt = (0, psbtUtil_1.toBigInt)(unspents);
            const psbt = (0, bitgo_1.toWalletPsbt)(tx, unspentBigInt, rootWalletKeys);
            (0, psbtUtil_1.validatePsbtParsing)(tx, psbt, unspentBigInt, signatureTarget);
            // Check that the correct unspent corresponds to the input
            unspentBigInt.forEach((unspent, inputIndex) => {
                const otherUnspent = inputIndex === 0 ? unspentBigInt[1] : unspentBigInt[0];
                assert.strictEqual((0, bitgo_1.psbtIncludesUnspentAtIndex)(psbt, inputIndex, unspent.id), true);
                assert.strictEqual((0, bitgo_1.psbtIncludesUnspentAtIndex)(psbt, inputIndex, otherUnspent.id), false);
                (0, bitgo_1.updateWalletUnspentForPsbt)(psbt, inputIndex, unspent, rootWalletKeys, signer, cosigner);
            });
            if (signatureTarget !== 'fullsigned') {
                // Now signing to make it fully signed psbt.
                // So it will be easy to verify its validity with another similar tx to be built with tx builder.
                (0, psbtUtil_1.signPsbt)(psbt, unspentBigInt, rootWalletKeys, signer, cosigner, signatureTarget);
            }
            assert.deepStrictEqual(psbt.validateSignaturesOfAllInputs(), true);
            psbt.finalizeAllInputs();
            const txFromPsbt = psbt.extractTransaction();
            const txBuilderParams2 = {
                signer,
                cosigner,
                amountType,
                outputType: outputScriptType,
                signatureTarget: 'fullsigned',
                network,
                changeIndex: CHANGE_INDEX,
                fee: FEE,
            };
            // New legacy tx resembles the signed psbt.
            const txFromTxBuilder = (0, psbtUtil_1.constructTransactionUsingTxBuilder)(unspents, rootWalletKeys, txBuilderParams2);
            assert.deepStrictEqual(txFromPsbt.getHash(), txFromTxBuilder.getHash());
        });
    }
    function getInputScripts() {
        return getScriptTypes2Of3().flatMap((t) => {
            return getScriptTypes2Of3().flatMap((lastType) => {
                return [[t, t, lastType]];
            });
        });
    }
    function getSignerPairs(containsTaprootInput) {
        const signaturePairs = [['user', 'bitgo']];
        if (containsTaprootInput) {
            signaturePairs.push(['user', 'backup']);
        }
        return signaturePairs;
    }
    ['unsigned', 'halfsigned', 'fullsigned'].forEach((signatureTarget) => {
        getInputScripts().forEach((inputScriptTypes) => {
            getSignerPairs(inputScriptTypes.includes('p2tr')).forEach(([signer, cosigner]) => {
                runTestSignUnspents({
                    inputScriptTypes,
                    outputScriptType: 'p2sh',
                    signer,
                    cosigner,
                    amountType: 'number',
                    testOutputAmount: transaction_util_1.defaultTestOutputAmount,
                    signatureTarget,
                });
                runTestSignUnspents({
                    inputScriptTypes,
                    outputScriptType: 'p2sh',
                    signer,
                    cosigner,
                    amountType: 'bigint',
                    testOutputAmount: BigInt('10000000000000000'),
                    signatureTarget,
                });
            });
        });
    });
});
function testUtxoPsbt(coinNetwork) {
    describe(`Testing UtxoPsbt (de)serialization for ${(0, src_1.getNetworkName)(coinNetwork)} network`, function () {
        let psbt;
        let psbtHex;
        let unspents;
        before(async function () {
            unspents = (0, testutil_2.mockUnspents)(rootWalletKeys, ['p2sh'], BigInt('10000000000000'), coinNetwork);
            const txBuilderParams = {
                signer: 'user',
                cosigner: 'bitgo',
                amountType: 'bigint',
                outputType: 'p2sh',
                signatureTarget: 'fullsigned',
                network: coinNetwork,
                changeIndex: CHANGE_INDEX,
                fee: FEE,
            };
            const tx = (0, psbtUtil_1.constructTransactionUsingTxBuilder)(unspents, rootWalletKeys, txBuilderParams);
            psbt = (0, bitgo_1.toWalletPsbt)(tx, (0, psbtUtil_1.toBigInt)(unspents), rootWalletKeys);
            if (coinNetwork === src_1.networks.zcash) {
                psbt.setDefaultsForVersion(network, 450);
            }
            psbtHex = psbt.toHex();
        });
        it('should be able to clone psbt', async function () {
            const clone = psbt.clone();
            assert(clone instanceof psbt.constructor, `Expected clone to be instance of ${psbt.constructor.name}`);
            assert.deepStrictEqual(clone.toBuffer(), psbt.toBuffer());
            assert.deepStrictEqual(clone.clone().toBuffer(), psbt.toBuffer());
            assert.strictEqual(clone.network, psbt.network);
            assert.strictEqual(clone.clone().network, psbt.network);
        });
        it('should be able to round-trip', async function () {
            assert.deepStrictEqual((0, bitgo_1.createPsbtFromHex)(psbtHex, coinNetwork, false).toBuffer(), psbt.toBuffer());
        });
        it('should be able to get transaction info from psbt', function () {
            const txInfo = (0, bitgo_1.getTransactionAmountsFromPsbt)(psbt);
            assert.strictEqual(txInfo.fee, FEE);
            assert.strictEqual(txInfo.inputCount, unspents.length);
            assert.strictEqual(txInfo.inputAmount, BigInt('10000000000000') * BigInt(unspents.length));
            assert.strictEqual(txInfo.outputAmount, BigInt('10000000000000') * BigInt(unspents.length) - FEE);
            assert.strictEqual(txInfo.outputCount, psbt.data.outputs.length);
        });
        function deserializeBip32PathsCorrectly(bip32PathsAbsolute) {
            function checkDerivationPrefix(bip32Derivation) {
                const path = bip32Derivation.path.split('/');
                const prefix = bip32PathsAbsolute ? 'm' : '0';
                assert(path[0] === prefix);
            }
            it(`should deserialize PSBT bip32Derivations with paths ${bip32PathsAbsolute ? '' : 'not '} absolute`, async function () {
                const deserializedPsbt = (0, bitgo_1.createPsbtFromHex)(psbtHex, coinNetwork, bip32PathsAbsolute);
                assert(deserializedPsbt);
                deserializedPsbt.data.inputs.forEach((input) => {
                    input?.bip32Derivation?.forEach((derivation) => checkDerivationPrefix(derivation));
                    input?.tapBip32Derivation?.forEach((derivation) => checkDerivationPrefix(derivation));
                });
            });
        }
        [true, false].forEach((bip32PathsAbsolute) => deserializeBip32PathsCorrectly(bip32PathsAbsolute));
    });
}
[src_1.networks.bitcoin, src_1.networks.zcash, src_1.networks.dash, src_1.networks.dogecoin, src_1.networks.litecoin].forEach((coinNetwork) => testUtxoPsbt(coinNetwork));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHNidC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Rlc3QvYml0Z28vcHNidC9Qc2J0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaUNBQWlDO0FBRWpDLHNDQUFtSDtBQUNuSCw4Q0FvQzRCO0FBQzVCLG9FQU8wQztBQUUxQyxvREFTK0I7QUFFL0IsNkRBQWlFO0FBQ2pFLHlDQU1vQjtBQUVwQixvREFBcUQ7QUFDckQsNkNBQTZDO0FBRTdDLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQztBQUN6QixNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7QUFNeEIsTUFBTSxPQUFPLEdBQUcsY0FBUSxDQUFDLE9BQU8sQ0FBQztBQUNqQyxNQUFNLGNBQWMsR0FBRyxJQUFBLCtCQUFvQixHQUFFLENBQUM7QUFFOUMsU0FBUyxrQkFBa0I7SUFDekIsMkVBQTJFO0lBQzNFLDZEQUE2RDtJQUM3RCxPQUFPLHFCQUFhLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxLQUFLLFlBQVksQ0FBQyxDQUFDO0FBQzNGLENBQUM7QUFFRCxNQUFNLGdCQUFnQixHQUFJLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxXQUFXLENBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdEYsVUFBVTtJQUNWLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDO0NBQ3BCLENBQUMsQ0FBQyxDQUFDO0FBQ0osTUFBTSxpQkFBaUIsR0FBRyw0QkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUV0RyxNQUFNLFVBQVUsR0FBRywyQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FB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Q0FBQztRQUVELENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQyw4QkFBOEIsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDcEcsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsQ0FBQyxjQUFRLENBQUMsT0FBTyxFQUFFLGNBQVEsQ0FBQyxLQUFLLEVBQUUsY0FBUSxDQUFDLElBQUksRUFBRSxjQUFRLENBQUMsUUFBUSxFQUFFLGNBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUM5RyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQzFCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcblxuaW1wb3J0IHsgTmV0d29yaywgZ2V0TmV0d29ya05hbWUsIG5ldHdvcmtzLCBnZXROZXR3b3JrTGlzdCwgdGVzdHV0aWwsIGlzTWFpbm5ldCwgVHJhbnNhY3Rpb24gfSBmcm9tICcuLi8uLi8uLi9zcmMnO1xuaW1wb3J0IHtcbiAgZ2V0RXh0ZXJuYWxDaGFpbkNvZGUsXG4gIG91dHB1dFNjcmlwdHMsXG4gIEtleU5hbWUsXG4gIFV0eG9Qc2J0LFxuICBaY2FzaFBzYnQsXG4gIGNyZWF0ZVBzYnRGcm9tSGV4LFxuICBwYXJzZVBzYnRJbnB1dCxcbiAgdG9XYWxsZXRQc2J0LFxuICBjcmVhdGVQc2J0Rm9yTmV0d29yayxcbiAgYWRkUmVwbGF5UHJvdGVjdGlvblVuc3BlbnRUb1BzYnQsXG4gIGFkZFdhbGxldE91dHB1dFRvUHNidCxcbiAgZ2V0SW50ZXJuYWxDaGFpbkNvZGUsXG4gIFV0eG9UcmFuc2FjdGlvbixcbiAgaXNUcmFuc2FjdGlvbldpdGhLZXlQYXRoU3BlbmRJbnB1dCxcbiAgaXNQc2J0LFxuICBwc2J0SW5jbHVkZXNVbnNwZW50QXRJbmRleCxcbiAgdXBkYXRlV2FsbGV0VW5zcGVudEZvclBzYnQsXG4gIGNyZWF0ZVBzYnRGcm9tVHJhbnNhY3Rpb24sXG4gIHRvUHJldk91dHB1dCxcbiAgdXBkYXRlUmVwbGF5UHJvdGVjdGlvblVuc3BlbnRUb1BzYnQsXG4gIFVuc3BlbnQsXG4gIGlzV2FsbGV0VW5zcGVudCxcbiAgdXBkYXRlV2FsbGV0T3V0cHV0Rm9yUHNidCxcbiAgZXh0cmFjdFAybXNPbmx5SGFsZlNpZ25lZFR4LFxuICB0b091dHB1dCxcbiAgY3JlYXRlVHJhbnNhY3Rpb25CdWlsZGVyRnJvbVRyYW5zYWN0aW9uLFxuICBhZGRYcHVic1RvUHNidCxcbiAgY2xvbmVQc2J0V2l0aG91dE5vbldpdG5lc3NVdHhvLFxuICBkZWxldGVXaXRuZXNzVXR4b0Zvck5vblNlZ3dpdElucHV0cyxcbiAgZ2V0UHNidElucHV0U2NyaXB0VHlwZSxcbiAgd2l0aFVuc2FmZU5vblNlZ3dpdCxcbiAgZ2V0VHJhbnNhY3Rpb25BbW91bnRzRnJvbVBzYnQsXG4gIFdhbGxldFVuc3BlbnQsXG4gIGdldERlZmF1bHRTaWdIYXNoLFxuICBpc1BzYnRMaXRlLFxufSBmcm9tICcuLi8uLi8uLi9zcmMvYml0Z28nO1xuaW1wb3J0IHtcbiAgY3JlYXRlT3V0cHV0U2NyaXB0Mm9mMyxcbiAgY3JlYXRlT3V0cHV0U2NyaXB0UDJzaFAycGssXG4gIGlzU3VwcG9ydGVkU2NyaXB0VHlwZSxcbiAgU2NyaXB0VHlwZTJPZjMsXG4gIFNjcmlwdFR5cGVQMnNoUDJwayxcbiAgc2NyaXB0VHlwZXMyT2YzLFxufSBmcm9tICcuLi8uLi8uLi9zcmMvYml0Z28vb3V0cHV0U2NyaXB0cyc7XG5cbmltcG9ydCB7XG4gIGdldERlZmF1bHRXYWxsZXRLZXlzLFxuICBJbnB1dCxcbiAgaW5wdXRTY3JpcHRUeXBlcyxcbiAgbW9ja1JlcGxheVByb3RlY3Rpb25VbnNwZW50LFxuICBPdXRwdXQsXG4gIG91dHB1dFNjcmlwdFR5cGVzLFxuICByZXBsYXlQcm90ZWN0aW9uS2V5UGFpcixcbiAgc2lnbkFsbFR4bklucHV0cyxcbn0gZnJvbSAnLi4vLi4vLi4vc3JjL3Rlc3R1dGlsJztcblxuaW1wb3J0IHsgZGVmYXVsdFRlc3RPdXRwdXRBbW91bnQgfSBmcm9tICcuLi8uLi90cmFuc2FjdGlvbl91dGlsJztcbmltcG9ydCB7XG4gIGFzc2VydEVxdWFsVHJhbnNhY3Rpb25zLFxuICBjb25zdHJ1Y3RUcmFuc2FjdGlvblVzaW5nVHhCdWlsZGVyLFxuICBzaWduUHNidCxcbiAgdG9CaWdJbnQsXG4gIHZhbGlkYXRlUHNidFBhcnNpbmcsXG59IGZyb20gJy4vcHNidFV0aWwnO1xuXG5pbXBvcnQgeyBtb2NrVW5zcGVudHMgfSBmcm9tICcuLi8uLi8uLi9zcmMvdGVzdHV0aWwnO1xuaW1wb3J0IHsgY29uc3RydWN0UHNidCB9IGZyb20gJy4vTXVzaWcyVXRpbCc7XG5cbmNvbnN0IENIQU5HRV9JTkRFWCA9IDEwMDtcbmNvbnN0IEZFRSA9IEJpZ0ludCgxMDApO1xuXG5leHBvcnQgdHlwZSBBbW91bnRUeXBlID0gJ251bWJlcicgfCAnYmlnaW50JztcbmV4cG9ydCB0eXBlIElucHV0VHlwZSA9IG91dHB1dFNjcmlwdHMuU2NyaXB0VHlwZTJPZjM7XG5leHBvcnQgdHlwZSBTaWduYXR1cmVUYXJnZXRUeXBlID0gJ3Vuc2lnbmVkJyB8ICdoYWxmc2lnbmVkJyB8ICdmdWxsc2lnbmVkJztcblxuY29uc3QgbmV0d29yayA9IG5ldHdvcmtzLmJpdGNvaW47XG5jb25zdCByb290V2FsbGV0S2V5cyA9IGdldERlZmF1bHRXYWxsZXRLZXlzKCk7XG5cbmZ1bmN0aW9uIGdldFNjcmlwdFR5cGVzMk9mMygpIHtcbiAgLy8gRklYTUUoQkctNjY5NDEpOiBwMnRyTXVzaWcyIHNpZ25pbmcgZG9lcyBub3Qgd29yayBpbiB0aGlzIHRlc3Qgc3VpdGUgeWV0XG4gIC8vICBiZWNhdXNlIHRoZSB0ZXN0IHN1aXRlIGlzIHdyaXR0ZW4gd2l0aCBUcmFuc2FjdGlvbkJ1aWxkZXJcbiAgcmV0dXJuIG91dHB1dFNjcmlwdHMuc2NyaXB0VHlwZXMyT2YzLmZpbHRlcigoc2NyaXB0VHlwZSkgPT4gc2NyaXB0VHlwZSAhPT0gJ3AydHJNdXNpZzInKTtcbn1cblxuY29uc3QgaGFsZlNpZ25lZElucHV0cyA9IChbJ3Ayc2gnLCAncDJ3c2gnLCAncDJzaFAyd3NoJ10gYXMgY29uc3QpLm1hcCgoc2NyaXB0VHlwZSkgPT4gKHtcbiAgc2NyaXB0VHlwZSxcbiAgdmFsdWU6IEJpZ0ludCgxMDAwKSxcbn0pKTtcbmNvbnN0IGhhbGZTaWduZWRPdXRwdXRzID0gb3V0cHV0U2NyaXB0VHlwZXMubWFwKChzY3JpcHRUeXBlKSA9PiAoeyBzY3JpcHRUeXBlLCB2YWx1ZTogQmlnSW50KDUwMCkgfSkpO1xuXG5jb25zdCBwc2J0SW5wdXRzID0gaW5wdXRTY3JpcHRUeXBlcy5tYXAoKHNjcmlwdFR5cGUpID0+ICh7IHNjcmlwdFR5cGUsIHZhbHVlOiBCaWdJbnQoMTAwMCkgfSkpO1xuY29uc3QgcHNidE91dHB1dHMgPSBvdXRwdXRTY3JpcHRUeXBlcy5tYXAoKHNjcmlwdFR5cGUpID0+ICh7IHNjcmlwdFR5cGUsIHZhbHVlOiBCaWdJbnQoOTAwKSB9KSk7XG5cbmRlc2NyaWJlKCdQc2J0IE1pc2MnLCBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIGdldFRlc3RQc2J0KCkge1xuICAgIHJldHVybiB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KFxuICAgICAgW3sgc2NyaXB0VHlwZTogJ3AydHInLCB2YWx1ZTogQmlnSW50KDEwMDApIH1dLFxuICAgICAgW3sgc2NyaXB0VHlwZTogJ3Ayc2gnLCB2YWx1ZTogQmlnSW50KDkwMCkgfV0sXG4gICAgICBuZXR3b3JrLFxuICAgICAgcm9vdFdhbGxldEtleXMsXG4gICAgICAnZnVsbHNpZ25lZCdcbiAgICApO1xuICB9XG4gIGl0KCdmYWlsIHRvIGZpbmFsaXNlIHAydHIgc2lnaGFzaCBtaXNtYXRjaCcsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBwc2J0ID0gZ2V0VGVzdFBzYnQoKTtcbiAgICBhc3NlcnQocHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZkFsbElucHV0cygpKTtcbiAgICBjb25zdCB0YXBTY3JpcHRTaWcgPSBwc2J0LmRhdGEuaW5wdXRzWzBdLnRhcFNjcmlwdFNpZztcbiAgICBhc3NlcnQodGFwU2NyaXB0U2lnKTtcbiAgICB0YXBTY3JpcHRTaWdbMF0uc2lnbmF0dXJlID0gQnVmZmVyLmNvbmNhdChbdGFwU2NyaXB0U2lnWzBdLnNpZ25hdHVyZSwgQnVmZmVyLm9mKFRyYW5zYWN0aW9uLlNJR0hBU0hfQUxMKV0pO1xuICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAoKSA9PiBwc2J0LmZpbmFsaXplQWxsSW5wdXRzKCksXG4gICAgICAoZTogYW55KSA9PiBlLm1lc3NhZ2UgPT09ICdzaWduYXR1cmUgc2lnaGFzaCBkb2VzIG5vdCBtYXRjaCBpbnB1dCBzaWdoYXNoIHR5cGUnXG4gICAgKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2lzUHNidExpdGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ25vIGlucHV0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBzYnQgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KFtdLCBbXSwgbmV0d29yaywgcm9vdFdhbGxldEtleXMsICd1bnNpZ25lZCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzUHNidExpdGUocHNidCksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdhbGwgaW5wdXRzIGFyZSBzZWd3aXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwc2J0ID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChcbiAgICAgICAgcHNidElucHV0cy5maWx0ZXIoKHMpID0+IHMuc2NyaXB0VHlwZSAhPT0gJ3Ayc2gnICYmIHMuc2NyaXB0VHlwZSAhPT0gJ3Ayc2hQMnBrJyksXG4gICAgICAgIHBzYnRPdXRwdXRzLFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgICByb290V2FsbGV0S2V5cyxcbiAgICAgICAgJ3Vuc2lnbmVkJ1xuICAgICAgKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1BzYnRMaXRlKHBzYnQpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc29tZSBpbnB1dHMgYXJlIG5vbi1zZWd3aXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwc2J0ID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChwc2J0SW5wdXRzLCBwc2J0T3V0cHV0cywgbmV0d29yaywgcm9vdFdhbGxldEtleXMsICd1bnNpZ25lZCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzUHNidExpdGUocHNidCksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYmUgdHJ1ZSBpZiBhZnRlciBjbG9uZVBzYnRXaXRob3V0Tm9uV2l0bmVzc1V0eG8nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwc2J0ID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChwc2J0SW5wdXRzLCBwc2J0T3V0cHV0cywgbmV0d29yaywgcm9vdFdhbGxldEtleXMsICd1bnNpZ25lZCcpO1xuICAgICAgY29uc3QgY2xvbmVkUHNidCA9IGNsb25lUHNidFdpdGhvdXROb25XaXRuZXNzVXR4byhwc2J0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1BzYnRMaXRlKGNsb25lZFBzYnQpLCB0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ2V4dHJhY3RQMm1zT25seUhhbGZTaWduZWRUeCBmYWlsdXJlJywgZnVuY3Rpb24gKCkge1xuICBpdCgnaW52YWxpZCBzaWduYXR1cmUgY291bnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcHNidCA9IHRlc3R1dGlsLmNvbnN0cnVjdFBzYnQoaGFsZlNpZ25lZElucHV0cywgaGFsZlNpZ25lZE91dHB1dHMsIG5ldHdvcmssIHJvb3RXYWxsZXRLZXlzLCAndW5zaWduZWQnKTtcbiAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgKCkgPT4gZXh0cmFjdFAybXNPbmx5SGFsZlNpZ25lZFR4KHBzYnQpLFxuICAgICAgKGU6IGFueSkgPT4gZS5tZXNzYWdlID09PSAndW5leHBlY3RlZCBzaWduYXR1cmUgY291bnQgdW5kZWZpbmVkJ1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCdlbXB0eSBpbnB1dHMnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcHNidCA9IHRlc3R1dGlsLmNvbnN0cnVjdFBzYnQoW10sIFtdLCBuZXR3b3JrLCByb290V2FsbGV0S2V5cywgJ3Vuc2lnbmVkJyk7XG4gICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICgpID0+IGV4dHJhY3RQMm1zT25seUhhbGZTaWduZWRUeChwc2J0KSxcbiAgICAgIChlOiBhbnkpID0+IGUubWVzc2FnZSA9PT0gJ2VtcHR5IGlucHV0cyBvciBvdXRwdXRzJ1xuICAgICk7XG4gIH0pO1xuXG4gIGl0KCd1bnN1cHBvcnRlZCBzY3JpcHQgdHlwZScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBwc2J0ID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChcbiAgICAgIFt7IHNjcmlwdFR5cGU6ICdwMnRyJywgdmFsdWU6IEJpZ0ludCgxMDAwKSB9XSxcbiAgICAgIFt7IHNjcmlwdFR5cGU6ICdwMnNoJywgdmFsdWU6IEJpZ0ludCg5MDApIH1dLFxuICAgICAgbmV0d29yayxcbiAgICAgIHJvb3RXYWxsZXRLZXlzLFxuICAgICAgJ2hhbGZzaWduZWQnXG4gICAgKTtcbiAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgKCkgPT4gZXh0cmFjdFAybXNPbmx5SGFsZlNpZ25lZFR4KHBzYnQpLFxuICAgICAgKGU6IGFueSkgPT4gZS5tZXNzYWdlID09PSAndW5zdXBwb3J0ZWQgc2NyaXB0IHR5cGUgdGFwcm9vdFNjcmlwdFBhdGhTcGVuZCdcbiAgICApO1xuICB9KTtcbn0pO1xuXG5mdW5jdGlvbiBydW5FeHRyYWN0UDJtc09ubHlIYWxmU2lnbmVkVHhUZXN0KG5ldHdvcms6IE5ldHdvcmssIGlucHV0czogSW5wdXRbXSwgb3V0cHV0czogT3V0cHV0W10pIHtcbiAgY29uc3QgY29pbiA9IGdldE5ldHdvcmtOYW1lKG5ldHdvcmspO1xuXG4gIGRlc2NyaWJlKGBleHRyYWN0UDJtc09ubHlIYWxmU2lnbmVkVHggc3VjY2VzcyBmb3IgJHtjb2lufWAsIGZ1bmN0aW9uICgpIHtcbiAgICBpdChgc3VjY2VzcyBmb3IgJHtjb2lufWAsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lcnM6IHsgc2lnbmVyTmFtZTogS2V5TmFtZTsgY29zaWduZXJOYW1lOiBLZXlOYW1lIH0gPSB7IHNpZ25lck5hbWU6ICd1c2VyJywgY29zaWduZXJOYW1lOiAnYmFja3VwJyB9O1xuICAgICAgY29uc3QgdHhuT3V0cHV0cyA9IG91dHB1dHM7XG4gICAgICBjb25zdCB0eG5JbnB1dHMgPSBpbnB1dHNcbiAgICAgICAgLm1hcCgodikgPT5cbiAgICAgICAgICB2LnNjcmlwdFR5cGUgPT09ICdwMnNoJyB8fCB2LnNjcmlwdFR5cGUgPT09ICdwMnNoUDJ3c2gnIHx8IHYuc2NyaXB0VHlwZSA9PT0gJ3Ayd3NoJ1xuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgc2NyaXB0VHlwZTogdi5zY3JpcHRUeXBlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiB2LnZhbHVlLFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHVuZGVmaW5lZFxuICAgICAgICApXG4gICAgICAgIC5maWx0ZXIoKHYpID0+ICEhdikgYXMgdGVzdHV0aWwuVHhuSW5wdXQ8YmlnaW50PltdO1xuXG4gICAgICBjb25zdCBwc2J0ID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChpbnB1dHMsIG91dHB1dHMsIG5ldHdvcmssIHJvb3RXYWxsZXRLZXlzLCAnaGFsZnNpZ25lZCcsIHsgc2lnbmVycyB9KTtcbiAgICAgIGNvbnN0IGhhbGZTaWduZWRQc2J0VHggPSBleHRyYWN0UDJtc09ubHlIYWxmU2lnbmVkVHgocHNidCk7XG5cbiAgICAgIGxldCB0eGIgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RUeG5CdWlsZGVyKHR4bklucHV0cywgdHhuT3V0cHV0cywgbmV0d29yaywgcm9vdFdhbGxldEtleXMsICdoYWxmc2lnbmVkJywgc2lnbmVycyk7XG4gICAgICBjb25zdCBoYWxmU2lnbmVkVHhiVHggPSB0eGIuYnVpbGRJbmNvbXBsZXRlKCk7XG5cbiAgICAgIGNvbnN0IHVuc3BlbnRzID0gdG9CaWdJbnQoaW5wdXRzLm1hcCgoaW5wdXQsIGkpID0+IHRlc3R1dGlsLnRvVW5zcGVudChpbnB1dCwgaSwgbmV0d29yaywgcm9vdFdhbGxldEtleXMpKSk7XG5cbiAgICAgIGFzc2VydEVxdWFsVHJhbnNhY3Rpb25zKGhhbGZTaWduZWRQc2J0VHgsIGhhbGZTaWduZWRUeGJUeCk7XG4gICAgICB2YWxpZGF0ZVBzYnRQYXJzaW5nKGhhbGZTaWduZWRQc2J0VHgsIHBzYnQsIHVuc3BlbnRzLCAnaGFsZnNpZ25lZCcpO1xuICAgICAgdmFsaWRhdGVQc2J0UGFyc2luZyhoYWxmU2lnbmVkVHhiVHgsIHBzYnQsIHVuc3BlbnRzLCAnaGFsZnNpZ25lZCcpO1xuXG4gICAgICB0ZXN0dXRpbC5zaWduQWxsUHNidElucHV0cyhwc2J0LCBpbnB1dHMsIHJvb3RXYWxsZXRLZXlzLCAnZnVsbHNpZ25lZCcsIHsgc2lnbmVycyB9KTtcbiAgICAgIGNvbnN0IGZ1bGx5U2lnbmVkUHNidCA9IHBzYnQuY2xvbmUoKTtcbiAgICAgIGNvbnN0IHBzYnRUeCA9IHBzYnQuZmluYWxpemVBbGxJbnB1dHMoKS5leHRyYWN0VHJhbnNhY3Rpb24oKTtcblxuICAgICAgY29uc3QgdHhuVW5zcGVudHMgPSB0eG5JbnB1dHMubWFwKCh2LCBpKSA9PiB0ZXN0dXRpbC50b1R4blVuc3BlbnQodiwgaSwgbmV0d29yaywgcm9vdFdhbGxldEtleXMpKTtcbiAgICAgIGNvbnN0IHByZXZPdXRwdXRzID0gdHhuVW5zcGVudHMubWFwKCh1KSA9PiB0b091dHB1dCh1LCBuZXR3b3JrKSk7XG4gICAgICB0eGIgPSBjcmVhdGVUcmFuc2FjdGlvbkJ1aWxkZXJGcm9tVHJhbnNhY3Rpb248YmlnaW50PihoYWxmU2lnbmVkVHhiVHgsIHByZXZPdXRwdXRzKTtcbiAgICAgIHNpZ25BbGxUeG5JbnB1dHModHhiLCB0eG5JbnB1dHMsIHJvb3RXYWxsZXRLZXlzLCAnZnVsbHNpZ25lZCcsIHNpZ25lcnMpO1xuICAgICAgY29uc3QgdHhiVHggPSB0eGIuYnVpbGQoKTtcblxuICAgICAgYXNzZXJ0RXF1YWxUcmFuc2FjdGlvbnMocHNidFR4LCB0eGJUeCk7XG4gICAgICB2YWxpZGF0ZVBzYnRQYXJzaW5nKHBzYnRUeCwgZnVsbHlTaWduZWRQc2J0LCB1bnNwZW50cywgJ2Z1bGxzaWduZWQnKTtcbiAgICAgIHZhbGlkYXRlUHNidFBhcnNpbmcodHhiVHgsIGZ1bGx5U2lnbmVkUHNidCwgdW5zcGVudHMsICdmdWxsc2lnbmVkJyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBydW5CdWlsZFNpZ25TZW5kRmxvd1Rlc3QoXG4gIG5ldHdvcms6IE5ldHdvcmssXG4gIGlucHV0czogSW5wdXRbXSxcbiAgb3V0cHV0czogT3V0cHV0W10sXG4gIHsgc2tpcE5vbldpdG5lc3NVdHhvID0gZmFsc2UgfSA9IHt9XG4pIHtcbiAgY29uc3QgY29pbiA9IGdldE5ldHdvcmtOYW1lKG5ldHdvcmspO1xuXG4gIGZ1bmN0aW9uIGFzc2VydFZhbGlkYXRlKHBzYnQ6IFV0eG9Qc2J0KSB7XG4gICAgcHNidC5kYXRhLmlucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgICAgYXNzZXJ0Lm9rKHBzYnQudmFsaWRhdGVTaWduYXR1cmVzT2ZJbnB1dEhEKGksIHJvb3RXYWxsZXRLZXlzWyd1c2VyJ10pKTtcbiAgICAgIGlmIChnZXRQc2J0SW5wdXRTY3JpcHRUeXBlKGlucHV0KSAhPT0gJ3Ayc2hQMnBrJykge1xuICAgICAgICBhc3NlcnQub2socHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZklucHV0SEQoaSwgcm9vdFdhbGxldEtleXNbJ2JpdGdvJ10pKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBhc3NlcnQub2socHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZkFsbElucHV0cygpKTtcbiAgfVxuXG4gIGRlc2NyaWJlKGBCdWlsZCwgc2lnbiAmIHNlbmQgZmxvdyBmb3IgJHtjb2lufWAsIGZ1bmN0aW9uICgpIHtcbiAgICAvKipcbiAgICAgKiBTa2lwIGFkZGluZyBub25XaXRuZXNzVXR4b3MgdG8gcHNidHNcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBJbiB0aGUgaW5zdGFuY2UgdGhhdCB3ZSB3YW50IHRvIGRvaW5nIGEgYnVsayBzd2VlcCwgZm9yIG5ldHdvcmsgYW5kIGNsaWVudCBwZXJmb3JtYW5jZSByZWFzb25zIHdlIGFyZSBzdWJzdGl0dXRpbmdcbiAgICAgKiB0aGUgbm9uV2l0bmVzc1V0eG8gZm9yIHAyc2ggYW5kIHAyc2hQMnBrIGlucHV0cyB3aXRoIGEgd2l0bmVzc1V0eG8uIFdlIG5lZWQgdGhlIHdpdG5lc3NVdHhvIHNvIHRoYXQgd2UgY2FuIGhhbGZcbiAgICAgKiBzaWduIHRoZSB0cmFuc2FjdGlvbiBsb2NhbGx5IHdpdGggdGhlIHVzZXIga2V5LiBXaGVuIHdlIHNlbmQgdGhlIGhhbGYgc2lnbmVkIHRvIEJpdEdvLCB0aGUgUFNCVCB3aWxsIGJlIHByb3Blcmx5XG4gICAgICogcG9wdWxhdGVkIHN1Y2ggdGhhdCB0aGUgbm9uLXNlZ3dpdCBpbnB1dHMgaGF2ZSB0aGUgbm9uV2l0bmVzc1V0eG8uIFRoaXMgbWVhbnMgd2hlbiB3ZSBzZW5kIGl0IHRvIEJpdEdvIHdlIHNob3VsZFxuICAgICAqIHJlbW92ZSB0aGUgd2l0bmVzc1V0eG8gc28gdGhhdCBpdCBqdXN0IGhhcyB0aGUgcGFydGlhbFNpZyBhbmQgcmVkZWVtU2NyaXB0LlxuICAgICAqL1xuICAgIGl0KGBzdWNjZXNzIGZvciAke2NvaW59JHtza2lwTm9uV2l0bmVzc1V0eG8gPyAnIHdpdGhvdXQgbm9uV2l0bmVzc1V0eG8gZm9yIHAyc2gnIDogJyd9YCwgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFyZW50UHNidCA9IHRlc3R1dGlsLmNvbnN0cnVjdFBzYnQoaW5wdXRzLCBvdXRwdXRzLCBuZXR3b3JrLCByb290V2FsbGV0S2V5cywgJ3Vuc2lnbmVkJywge1xuICAgICAgICBzaWduZXJzOiB7XG4gICAgICAgICAgc2lnbmVyTmFtZTogJ3VzZXInLFxuICAgICAgICAgIGNvc2lnbmVyTmFtZTogJ2JpdGdvJyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBsZXQgcHNidCA9IHNraXBOb25XaXRuZXNzVXR4byA/IGNsb25lUHNidFdpdGhvdXROb25XaXRuZXNzVXR4byhwYXJlbnRQc2J0KSA6IHBhcmVudFBzYnQ7XG4gICAgICBhZGRYcHVic1RvUHNidChwc2J0LCByb290V2FsbGV0S2V5cyk7XG4gICAgICBwc2J0LnNldEFsbElucHV0c011c2lnMk5vbmNlSEQocm9vdFdhbGxldEtleXNbJ3VzZXInXSk7XG5cbiAgICAgIGxldCBwc2J0V2l0aG91dFByZXZUeCA9IGNsb25lUHNidFdpdGhvdXROb25XaXRuZXNzVXR4byhwc2J0KTtcbiAgICAgIGxldCBoZXggPSBwc2J0V2l0aG91dFByZXZUeC50b0hleCgpO1xuXG4gICAgICBsZXQgcHNidEF0SHNtID0gY3JlYXRlUHNidEZyb21IZXgoaGV4LCBuZXR3b3JrKTtcbiAgICAgIHBzYnRBdEhzbS5zZXRBbGxJbnB1dHNNdXNpZzJOb25jZUhEKHJvb3RXYWxsZXRLZXlzWydiaXRnbyddLCB7IGRldGVybWluaXN0aWM6IHRydWUgfSk7XG4gICAgICBsZXQgaGV4QXRIc20gPSBwc2J0QXRIc20udG9IZXgoKTtcblxuICAgICAgbGV0IHBzYnRGcm9tSHNtID0gY3JlYXRlUHNidEZyb21IZXgoaGV4QXRIc20sIG5ldHdvcmspO1xuICAgICAgZGVsZXRlV2l0bmVzc1V0eG9Gb3JOb25TZWd3aXRJbnB1dHMocHNidEZyb21Ic20pO1xuICAgICAgcHNidC5jb21iaW5lKHBzYnRGcm9tSHNtKTtcblxuICAgICAgdGVzdHV0aWwuc2lnbkFsbFBzYnRJbnB1dHMocHNidCwgaW5wdXRzLCByb290V2FsbGV0S2V5cywgJ2hhbGZzaWduZWQnLCB7XG4gICAgICAgIHNpZ25lcnM6IHtcbiAgICAgICAgICBzaWduZXJOYW1lOiAndXNlcicsXG4gICAgICAgICAgY29zaWduZXJOYW1lOiAnYml0Z28nLFxuICAgICAgICB9LFxuICAgICAgICBza2lwTm9uV2l0bmVzc1V0eG8sXG4gICAgICB9KTtcblxuICAgICAgcHNidFdpdGhvdXRQcmV2VHggPSBjbG9uZVBzYnRXaXRob3V0Tm9uV2l0bmVzc1V0eG8ocHNidCk7XG4gICAgICBoZXggPSBwc2J0V2l0aG91dFByZXZUeC50b0hleCgpO1xuXG4gICAgICBwc2J0QXRIc20gPSBjcmVhdGVQc2J0RnJvbUhleChoZXgsIG5ldHdvcmspO1xuICAgICAgd2l0aFVuc2FmZU5vblNlZ3dpdChwc2J0QXRIc20sICgpID0+IHtcbiAgICAgICAgdGVzdHV0aWwuc2lnbkFsbFBzYnRJbnB1dHMocHNidEF0SHNtLCBpbnB1dHMsIHJvb3RXYWxsZXRLZXlzLCAnZnVsbHNpZ25lZCcsIHtcbiAgICAgICAgICBzaWduZXJzOiB7XG4gICAgICAgICAgICBzaWduZXJOYW1lOiAndXNlcicsXG4gICAgICAgICAgICBjb3NpZ25lck5hbWU6ICdiaXRnbycsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBkZXRlcm1pbmlzdGljOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgd2l0aFVuc2FmZU5vblNlZ3dpdChwc2J0QXRIc20sICgpID0+IHtcbiAgICAgICAgYXNzZXJ0VmFsaWRhdGUocHNidEF0SHNtKTtcbiAgICAgIH0pO1xuICAgICAgaGV4QXRIc20gPSBwc2J0QXRIc20udG9IZXgoKTtcblxuICAgICAgcHNidEZyb21Ic20gPSBjcmVhdGVQc2J0RnJvbUhleChoZXhBdEhzbSwgbmV0d29yayk7XG4gICAgICBkZWxldGVXaXRuZXNzVXR4b0Zvck5vblNlZ3dpdElucHV0cyhwc2J0RnJvbUhzbSk7XG5cbiAgICAgIGlmIChza2lwTm9uV2l0bmVzc1V0eG8pIHtcbiAgICAgICAgcHNidCA9IHBhcmVudFBzYnQ7XG4gICAgICB9XG4gICAgICBwc2J0LmNvbWJpbmUocHNidEZyb21Ic20pO1xuXG4gICAgICBhc3NlcnRWYWxpZGF0ZShwc2J0KTtcbiAgICAgIGFzc2VydC5kb2VzTm90VGhyb3coKCkgPT4gcHNidC5maW5hbGl6ZUFsbElucHV0cygpLmV4dHJhY3RUcmFuc2FjdGlvbigpKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJ1bkJ1aWxkUHNidFdpdGhTREsobmV0d29yazogTmV0d29yaywgaW5wdXRzOiBJbnB1dFtdLCBvdXRwdXRzOiBPdXRwdXRbXSkge1xuICBjb25zdCBjb2luID0gZ2V0TmV0d29ya05hbWUobmV0d29yayk7XG4gIGl0KGBjaGVjayB0aGF0IGJ1aWxkaW5nIGEgUFNCVCB3aGlsZSBza2lwcGluZyBub25XaXRuZXNzVXR4byB3b3JrcyAtICR7Y29pbn1gLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgcHNidFdpdGhOb25XaXRuZXNzID0gdGVzdHV0aWwuY29uc3RydWN0UHNidChpbnB1dHMsIG91dHB1dHMsIG5ldHdvcmssIHJvb3RXYWxsZXRLZXlzLCAndW5zaWduZWQnLCB7XG4gICAgICBzaWduZXJzOiB7XG4gICAgICAgIHNpZ25lck5hbWU6ICd1c2VyJyxcbiAgICAgICAgY29zaWduZXJOYW1lOiAnYml0Z28nLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBjb25zdCBwc2J0V2l0aG91dE5vbldpdG5lc3MgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KGlucHV0cywgb3V0cHV0cywgbmV0d29yaywgcm9vdFdhbGxldEtleXMsICd1bnNpZ25lZCcsIHtcbiAgICAgIHNpZ25lcnM6IHtcbiAgICAgICAgc2lnbmVyTmFtZTogJ3VzZXInLFxuICAgICAgICBjb3NpZ25lck5hbWU6ICdiaXRnbycsXG4gICAgICB9LFxuICAgICAgc2tpcE5vbldpdG5lc3NVdHhvOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgY2xvbmVkUHNidCA9IGNsb25lUHNidFdpdGhvdXROb25XaXRuZXNzVXR4byhwc2J0V2l0aE5vbldpdG5lc3MpO1xuICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocHNidFdpdGhvdXROb25XaXRuZXNzLnRvSGV4KCksIGNsb25lZFBzYnQudG9IZXgoKSk7XG4gIH0pO1xufVxuXG5nZXROZXR3b3JrTGlzdCgpXG4gIC5maWx0ZXIoKHYpID0+IGlzTWFpbm5ldCh2KSAmJiB2ICE9PSBuZXR3b3Jrcy5iaXRjb2luc3YpXG4gIC5mb3JFYWNoKChuZXR3b3JrKSA9PiB7XG4gICAgcnVuRXh0cmFjdFAybXNPbmx5SGFsZlNpZ25lZFR4VGVzdChcbiAgICAgIG5ldHdvcmssXG4gICAgICBoYWxmU2lnbmVkSW5wdXRzLmZpbHRlcigoaW5wdXQpID0+IGlzU3VwcG9ydGVkU2NyaXB0VHlwZShuZXR3b3JrLCBpbnB1dC5zY3JpcHRUeXBlKSksXG4gICAgICBoYWxmU2lnbmVkT3V0cHV0cy5maWx0ZXIoKG91dHB1dCkgPT4gaXNTdXBwb3J0ZWRTY3JpcHRUeXBlKG5ldHdvcmssIG91dHB1dC5zY3JpcHRUeXBlKSlcbiAgICApO1xuXG4gICAgY29uc3Qgc3VwcG9ydGVkUHNidElucHV0cyA9IHBzYnRJbnB1dHMuZmlsdGVyKChpbnB1dCkgPT5cbiAgICAgIGlzU3VwcG9ydGVkU2NyaXB0VHlwZShuZXR3b3JrLCBpbnB1dC5zY3JpcHRUeXBlID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCcgPyAncDJ0ck11c2lnMicgOiBpbnB1dC5zY3JpcHRUeXBlKVxuICAgICk7XG4gICAgY29uc3Qgc3VwcG9ydGVkUHNidE91dHB1dHMgPSBwc2J0T3V0cHV0cy5maWx0ZXIoKG91dHB1dCkgPT4gaXNTdXBwb3J0ZWRTY3JpcHRUeXBlKG5ldHdvcmssIG91dHB1dC5zY3JpcHRUeXBlKSk7XG4gICAgW2ZhbHNlLCB0cnVlXS5mb3JFYWNoKChza2lwTm9uV2l0bmVzc1V0eG8pID0+XG4gICAgICBydW5CdWlsZFNpZ25TZW5kRmxvd1Rlc3QobmV0d29yaywgc3VwcG9ydGVkUHNidElucHV0cywgc3VwcG9ydGVkUHNidE91dHB1dHMsIHsgc2tpcE5vbldpdG5lc3NVdHhvIH0pXG4gICAgKTtcblxuICAgIHJ1bkJ1aWxkUHNidFdpdGhTREsobmV0d29yaywgc3VwcG9ydGVkUHNidElucHV0cywgc3VwcG9ydGVkUHNidE91dHB1dHMpO1xuICB9KTtcblxuZGVzY3JpYmUoJ2lzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQnLCBmdW5jdGlvbiAoKSB7XG4gIGRlc2NyaWJlKCd0cmFuc2FjdGlvbiBpbnB1dCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnZW1wdHkgaW5wdXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHggPSB0ZXN0dXRpbC5jb25zdHJ1Y3RUeG5CdWlsZGVyKFtdLCBbXSwgbmV0d29yaywgcm9vdFdhbGxldEtleXMsICd1bnNpZ25lZCcpLmJ1aWxkSW5jb21wbGV0ZSgpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQodHgpLCBmYWxzZSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNUcmFuc2FjdGlvbldpdGhLZXlQYXRoU3BlbmRJbnB1dCh0eC5pbnMpLCBmYWxzZSk7XG4gICAgfSk7XG5cbiAgICBpdCgndGFwcm9vdEtleVBhdGggaW5wdXRzIHN1Y2Nlc3NmdWxseSB0cmlnZ2VycycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBzYnQgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KFxuICAgICAgICBbXG4gICAgICAgICAgeyBzY3JpcHRUeXBlOiAndGFwcm9vdEtleVBhdGhTcGVuZCcsIHZhbHVlOiBCaWdJbnQoMWU4KSB9LFxuICAgICAgICAgIHsgc2NyaXB0VHlwZTogJ3Ayc2gnLCB2YWx1ZTogQmlnSW50KDFlOCkgfSxcbiAgICAgICAgXSxcbiAgICAgICAgW3sgc2NyaXB0VHlwZTogJ3Ayc2gnLCB2YWx1ZTogQmlnSW50KDJlOCAtIDEwMDAwKSB9XSxcbiAgICAgICAgbmV0d29yayxcbiAgICAgICAgcm9vdFdhbGxldEtleXMsXG4gICAgICAgICdmdWxsc2lnbmVkJ1xuICAgICAgKTtcbiAgICAgIGFzc2VydChwc2J0LnZhbGlkYXRlU2lnbmF0dXJlc09mQWxsSW5wdXRzKCkpO1xuICAgICAgcHNidC5maW5hbGl6ZUFsbElucHV0cygpO1xuICAgICAgY29uc3QgdHggPSBwc2J0LmV4dHJhY3RUcmFuc2FjdGlvbigpIGFzIFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+O1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNUcmFuc2FjdGlvbldpdGhLZXlQYXRoU3BlbmRJbnB1dCh0eCksIHRydWUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQodHguaW5zKSwgdHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnbm8gdGFwcm9vdEtleVBhdGggaW5wdXRzIHN1Y2Nlc3NmdWxseSBkb2VzIG5vdCB0cmlnZ2VyJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcHNidCA9IHRlc3R1dGlsLmNvbnN0cnVjdFBzYnQoXG4gICAgICAgIFtcbiAgICAgICAgICB7IHNjcmlwdFR5cGU6ICdwMnRyTXVzaWcyJywgdmFsdWU6IEJpZ0ludCgxZTgpIH0sXG4gICAgICAgICAgeyBzY3JpcHRUeXBlOiAncDJzaCcsIHZhbHVlOiBCaWdJbnQoMWU4KSB9LFxuICAgICAgICBdLFxuICAgICAgICBbeyBzY3JpcHRUeXBlOiAncDJzaCcsIHZhbHVlOiBCaWdJbnQoMmU4IC0gMTAwMDApIH1dLFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgICByb290V2FsbGV0S2V5cyxcbiAgICAgICAgJ2Z1bGxzaWduZWQnXG4gICAgICApO1xuICAgICAgYXNzZXJ0KHBzYnQudmFsaWRhdGVTaWduYXR1cmVzT2ZBbGxJbnB1dHMoKSk7XG4gICAgICBwc2J0LmZpbmFsaXplQWxsSW5wdXRzKCk7XG4gICAgICBjb25zdCB0eCA9IHBzYnQuZXh0cmFjdFRyYW5zYWN0aW9uKCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1RyYW5zYWN0aW9uV2l0aEtleVBhdGhTcGVuZElucHV0KHR4KSwgZmFsc2UpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQodHguaW5zKSwgZmFsc2UpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Vuc2lnbmVkIGlucHV0cyBzdWNjZXNzZnVsbHkgZmFpbCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBzYnQgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KFxuICAgICAgICBbXG4gICAgICAgICAgeyBzY3JpcHRUeXBlOiAncDJ3c2gnLCB2YWx1ZTogQmlnSW50KDFlOCkgfSxcbiAgICAgICAgICB7IHNjcmlwdFR5cGU6ICdwMnNoJywgdmFsdWU6IEJpZ0ludCgxZTgpIH0sXG4gICAgICAgIF0sXG4gICAgICAgIFt7IHNjcmlwdFR5cGU6ICdwMnNoJywgdmFsdWU6IEJpZ0ludCgyZTggLSAxMDAwMCkgfV0sXG4gICAgICAgIG5ldHdvcmssXG4gICAgICAgIHJvb3RXYWxsZXRLZXlzLFxuICAgICAgICAndW5zaWduZWQnXG4gICAgICApO1xuICAgICAgY29uc3QgdHggPSBwc2J0LmdldFVuc2lnbmVkVHgoKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1RyYW5zYWN0aW9uV2l0aEtleVBhdGhTcGVuZElucHV0KHR4KSwgZmFsc2UpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQodHguaW5zKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgncHNidCBpbnB1dCcsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnZW1wdHkgaW5wdXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcHNidCA9IHRlc3R1dGlsLmNvbnN0cnVjdFBzYnQoW10sIFtdLCBuZXR3b3JrLCByb290V2FsbGV0S2V5cywgJ3Vuc2lnbmVkJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNUcmFuc2FjdGlvbldpdGhLZXlQYXRoU3BlbmRJbnB1dChwc2J0KSwgZmFsc2UpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQocHNidC5kYXRhLmlucHV0cyksIGZhbHNlKTtcbiAgICB9KTtcblxuICAgIGl0KCdwc2J0IHdpdGggdGFwcm9vdEtleVBhdGhJbnB1dHMgc3VjY2Vzc2Z1bGx5IHRyaWdnZXJzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcHNidCA9IHRlc3R1dGlsLmNvbnN0cnVjdFBzYnQoXG4gICAgICAgIFtcbiAgICAgICAgICB7IHNjcmlwdFR5cGU6ICd0YXByb290S2V5UGF0aFNwZW5kJywgdmFsdWU6IEJpZ0ludCgxZTgpIH0sXG4gICAgICAgICAgeyBzY3JpcHRUeXBlOiAncDJzaCcsIHZhbHVlOiBCaWdJbnQoMWU4KSB9LFxuICAgICAgICBdLFxuICAgICAgICBbeyBzY3JpcHRUeXBlOiAncDJzaCcsIHZhbHVlOiBCaWdJbnQoMmU4IC0gMTAwMDApIH1dLFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgICByb290V2FsbGV0S2V5cyxcbiAgICAgICAgJ3Vuc2lnbmVkJ1xuICAgICAgKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQocHNidCksIHRydWUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzVHJhbnNhY3Rpb25XaXRoS2V5UGF0aFNwZW5kSW5wdXQocHNidC5kYXRhLmlucHV0cyksIHRydWUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3BzYnQgd2l0aG91dCB0YXByb290S2V5UGF0aElucHV0cyBzdWNjZXNzZnVsbHkgZG9lcyBub3QgdHJpZ2dlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBzYnQgPSB0ZXN0dXRpbC5jb25zdHJ1Y3RQc2J0KFxuICAgICAgICBbXG4gICAgICAgICAgeyBzY3JpcHRUeXBlOiAncDJ3c2gnLCB2YWx1ZTogQmlnSW50KDFlOCkgfSxcbiAgICAgICAgICB7IHNjcmlwdFR5cGU6ICdwMnNoJywgdmFsdWU6IEJpZ0ludCgxZTgpIH0sXG4gICAgICAgIF0sXG4gICAgICAgIFt7IHNjcmlwdFR5cGU6ICdwMnNoJywgdmFsdWU6IEJpZ0ludCgyZTggLSAxMDAwMCkgfV0sXG4gICAgICAgIG5ldHdvcmssXG4gICAgICAgIHJvb3RXYWxsZXRLZXlzLFxuICAgICAgICAnaGFsZnNpZ25lZCdcbiAgICAgICk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1RyYW5zYWN0aW9uV2l0aEtleVBhdGhTcGVuZElucHV0KHBzYnQpLCBmYWxzZSk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNUcmFuc2FjdGlvbldpdGhLZXlQYXRoU3BlbmRJbnB1dChwc2J0LmRhdGEuaW5wdXRzKSwgZmFsc2UpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnUGFyc2UgUFNCVCcsIGZ1bmN0aW9uICgpIHtcbiAgaXQoJ3Ayc2hQMnBrIHBhcnNpbmcnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgc2lnbmVyID0gcm9vdFdhbGxldEtleXNbJ3VzZXInXTtcbiAgICBjb25zdCBwc2J0ID0gY3JlYXRlUHNidEZvck5ldHdvcmsoeyBuZXR3b3JrOiBuZXR3b3Jrcy5iaXRjb2luY2FzaCB9KTtcbiAgICBjb25zdCB1bnNwZW50ID0gbW9ja1JlcGxheVByb3RlY3Rpb25VbnNwZW50KG5ldHdvcmtzLmJpdGNvaW5jYXNoLCBCaWdJbnQoMWU4KSwgeyBrZXk6IHNpZ25lciB9KTtcbiAgICBjb25zdCB7IHJlZGVlbVNjcmlwdCB9ID0gY3JlYXRlT3V0cHV0U2NyaXB0UDJzaFAycGsoc2lnbmVyLnB1YmxpY0tleSk7XG4gICAgYXNzZXJ0KHJlZGVlbVNjcmlwdCk7XG4gICAgYWRkUmVwbGF5UHJvdGVjdGlvblVuc3BlbnRUb1BzYnQocHNidCwgdW5zcGVudCwgcmVkZWVtU2NyaXB0KTtcbiAgICBhZGRXYWxsZXRPdXRwdXRUb1BzYnQocHNidCwgcm9vdFdhbGxldEtleXMsIGdldEludGVybmFsQ2hhaW5Db2RlKCdwMnNoJyksIDAsIEJpZ0ludCgxZTggLSAxMDAwMCkpO1xuICAgIGNvbnN0IGlucHV0ID0gcHNidC5kYXRhLmlucHV0c1swXTtcbiAgICBsZXQgcGFyc2VkID0gcGFyc2VQc2J0SW5wdXQoaW5wdXQpO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5zY3JpcHRUeXBlLCAncDJzaFAycGsnKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnNpZ25hdHVyZXMsIHVuZGVmaW5lZCk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5wdWJsaWNLZXlzLmxlbmd0aCwgMSk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5wdWJsaWNLZXlzWzBdLmxlbmd0aCA9PT0gMzMpO1xuICAgIGFzc2VydC5vayhwYXJzZWQucHViU2NyaXB0LmVxdWFscyhyZWRlZW1TY3JpcHQpKTtcblxuICAgIHBzYnQuc2lnbkFsbElucHV0cyhzaWduZXIpO1xuICAgIGFzc2VydC5vayhwc2J0LnZhbGlkYXRlU2lnbmF0dXJlc09mQWxsSW5wdXRzKCkpO1xuXG4gICAgcGFyc2VkID0gcGFyc2VQc2J0SW5wdXQoaW5wdXQpO1xuXG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5zY3JpcHRUeXBlLCAncDJzaFAycGsnKTtcbiAgICBhc3NlcnQuc3RyaWN0RXF1YWwocGFyc2VkLnNpZ25hdHVyZXM/Lmxlbmd0aCwgMSk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBhcnNlZC5wdWJsaWNLZXlzLmxlbmd0aCwgMSk7XG4gICAgYXNzZXJ0Lm9rKHBhcnNlZC5wdWJsaWNLZXlzWzBdLmxlbmd0aCA9PT0gMzMpO1xuICAgIGFzc2VydC5vayhwYXJzZWQucHViU2NyaXB0LmVxdWFscyhyZWRlZW1TY3JpcHQpKTtcblxuICAgIGNvbnN0IHNpZ2hhc2g6IG51bWJlciA9IHBhcnNlZC5zaWduYXR1cmVzWzBdW3BhcnNlZC5zaWduYXR1cmVzWzBdLmxlbmd0aCAtIDFdO1xuICAgIGFzc2VydC5zdHJpY3RFcXVhbChzaWdoYXNoLCBnZXREZWZhdWx0U2lnSGFzaChwc2J0Lm5ldHdvcmspKTtcbiAgfSk7XG5cbiAgaXQoJ2ZhaWwgdG8gcGFyc2UgZmluYWxpemVkIHBzYnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdW5zcGVudHMgPSBtb2NrVW5zcGVudHMoXG4gICAgICByb290V2FsbGV0S2V5cyxcbiAgICAgIGdldFNjcmlwdFR5cGVzMk9mMygpLm1hcCgoaW5wdXRUeXBlKSA9PiBpbnB1dFR5cGUpLFxuICAgICAgQmlnSW50KCcxMDAwMDAwMDAwMDAwMDAwMCcpLFxuICAgICAgbmV0d29ya1xuICAgICk7XG4gICAgY29uc3QgdHhCdWlsZGVyUGFyYW1zID0ge1xuICAgICAgc2lnbmVyOiAndXNlcicsXG4gICAgICBjb3NpZ25lcjogJ2JpdGdvJyxcbiAgICAgIGFtb3VudFR5cGU6ICdiaWdpbnQnLFxuICAgICAgb3V0cHV0VHlwZTogJ3Ayc2gnLFxuICAgICAgc2lnbmF0dXJlVGFyZ2V0OiAnZnVsbHNpZ25lZCcsXG4gICAgICBuZXR3b3JrLFxuICAgICAgY2hhbmdlSW5kZXg6IENIQU5HRV9JTkRFWCxcbiAgICAgIGZlZTogRkVFLFxuICAgIH0gYXMgY29uc3Q7XG4gICAgY29uc3QgdHggPSBjb25zdHJ1Y3RUcmFuc2FjdGlvblVzaW5nVHhCdWlsZGVyKHVuc3BlbnRzLCByb290V2FsbGV0S2V5cywgdHhCdWlsZGVyUGFyYW1zKTtcbiAgICBjb25zdCBwc2J0ID0gdG9XYWxsZXRQc2J0KHR4LCB0b0JpZ0ludCh1bnNwZW50cyksIHJvb3RXYWxsZXRLZXlzKTtcbiAgICBwc2J0LnZhbGlkYXRlU2lnbmF0dXJlc09mQWxsSW5wdXRzKCk7XG4gICAgcHNidC5maW5hbGl6ZUFsbElucHV0cygpO1xuICAgIHBzYnQuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGkpID0+IHtcbiAgICAgIGFzc2VydC50aHJvd3MoXG4gICAgICAgICgpID0+IHBhcnNlUHNidElucHV0KGlucHV0KSxcbiAgICAgICAgKGU6IGFueSkgPT4gZS5tZXNzYWdlID09PSAnRmluYWxpemVkIFBTQlQgcGFyc2luZyBpcyBub3Qgc3VwcG9ydGVkJ1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgaXQoJ2ZhaWwgdG8gcGFyc2UgaW5wdXQgd2l0aCBtb3JlIHRoYW4gb25lIHNjcmlwdCB0eXBlIG1ldGFkYXRhJywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHVuc3BlbnRzID0gbW9ja1Vuc3BlbnRzKHJvb3RXYWxsZXRLZXlzLCBbJ3AydHInXSwgQmlnSW50KCcxMDAwMDAwMDAwMDAwMDAwMCcpLCBuZXR3b3JrKTtcblxuICAgIGNvbnN0IHR4QnVpbGRlclBhcmFtcyA9IHtcbiAgICAgIHNpZ25lcjogJ3VzZXInLFxuICAgICAgY29zaWduZXI6ICdiaXRnbycsXG4gICAgICBhbW91bnRUeXBlOiAnYmlnaW50JyxcbiAgICAgIG91dHB1dFR5cGU6ICdwMnNoJyxcbiAgICAgIHNpZ25hdHVyZVRhcmdldDogJ2hhbGZzaWduZWQnLFxuICAgICAgbmV0d29yayxcbiAgICAgIGNoYW5nZUluZGV4OiBDSEFOR0VfSU5ERVgsXG4gICAgICBmZWU6IEZFRSxcbiAgICB9IGFzIGNvbnN0O1xuXG4gICAgY29uc3QgdHhQMnRyID0gY29uc3RydWN0VHJhbnNhY3Rpb25Vc2luZ1R4QnVpbGRlcihbdW5zcGVudHNbMF1dLCByb290V2FsbGV0S2V5cywgdHhCdWlsZGVyUGFyYW1zKTtcbiAgICBjb25zdCBwc2J0UDJ0ciA9IHRvV2FsbGV0UHNidCh0eFAydHIsIHRvQmlnSW50KFt1bnNwZW50c1swXV0pLCByb290V2FsbGV0S2V5cyk7XG5cbiAgICBjb25zdCB3YWxsZXRLZXlzID0gcm9vdFdhbGxldEtleXMuZGVyaXZlRm9yQ2hhaW5BbmRJbmRleChnZXRFeHRlcm5hbENoYWluQ29kZSgncDJzaCcpLCAwKTtcbiAgICBjb25zdCB7IHJlZGVlbVNjcmlwdCB9ID0gY3JlYXRlT3V0cHV0U2NyaXB0Mm9mMyh3YWxsZXRLZXlzLnB1YmxpY0tleXMsICdwMnNoJyk7XG4gICAgcHNidFAydHIudXBkYXRlSW5wdXQoMCwgeyByZWRlZW1TY3JpcHQgfSk7XG5cbiAgICBhc3NlcnQudGhyb3dzKFxuICAgICAgKCkgPT4gcGFyc2VQc2J0SW5wdXQocHNidFAydHIuZGF0YS5pbnB1dHNbMF0pLFxuICAgICAgKGU6IGFueSkgPT4gZS5tZXNzYWdlID09PSAnRm91bmQgYm90aCBwMnNoIGFuZCB0YXByb290U2NyaXB0UGF0aCBQU0JUIG1ldGFkYXRhLidcbiAgICApO1xuICB9KTtcblxuICBpdCgnZmFpbCB0byBwYXJzZSBtb3JlIHRoYW4gb25lIHRhcCBsZWFmIHNjcmlwdCBwZXIgaW5wdXQnLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdW5zcGVudHMgPSBtb2NrVW5zcGVudHMocm9vdFdhbGxldEtleXMsIFsncDJ0ciddLCBCaWdJbnQoJzEwMDAwMDAwMDAwMDAwMDAwJyksIG5ldHdvcmspO1xuXG4gICAgY29uc3QgdHhCdWlsZGVyUGFyYW1zID0ge1xuICAgICAgc2lnbmVyOiAndXNlcicsXG4gICAgICBjb3NpZ25lcjogJ2JpdGdvJyxcbiAgICAgIGFtb3VudFR5cGU6ICdiaWdpbnQnLFxuICAgICAgb3V0cHV0VHlwZTogJ3Ayc2gnLFxuICAgICAgc2lnbmF0dXJlVGFyZ2V0OiAnaGFsZnNpZ25lZCcsXG4gICAgICBuZXR3b3JrLFxuICAgICAgY2hhbmdlSW5kZXg6IENIQU5HRV9JTkRFWCxcbiAgICAgIGZlZTogRkVFLFxuICAgIH0gYXMgY29uc3Q7XG5cbiAgICBjb25zdCB0eFAydHIxID0gY29uc3RydWN0VHJhbnNhY3Rpb25Vc2luZ1R4QnVpbGRlcihbdW5zcGVudHNbMF1dLCByb290V2FsbGV0S2V5cywgdHhCdWlsZGVyUGFyYW1zKTtcbiAgICBjb25zdCBwc2J0UDJ0cjEgPSB0b1dhbGxldFBzYnQodHhQMnRyMSwgdG9CaWdJbnQoW3Vuc3BlbnRzWzBdXSksIHJvb3RXYWxsZXRLZXlzKTtcblxuICAgIGNvbnN0IHR4QnVpbGRlclBhcmFtczIgPSB7XG4gICAgICBzaWduZXI6ICd1c2VyJyBhcyBLZXlOYW1lLFxuICAgICAgY29zaWduZXI6ICdiYWNrdXAnIGFzIEtleU5hbWUsXG4gICAgICBhbW91bnRUeXBlOiAnYmlnaW50JyBhcyBBbW91bnRUeXBlLFxuICAgICAgb3V0cHV0VHlwZTogJ3Ayc2gnIGFzIElucHV0VHlwZSxcbiAgICAgIHNpZ25hdHVyZVRhcmdldDogJ2hhbGZzaWduZWQnIGFzIFNpZ25hdHVyZVRhcmdldFR5cGUsXG4gICAgICBuZXR3b3JrLFxuICAgICAgY2hhbmdlSW5kZXg6IENIQU5HRV9JTkRFWCxcbiAgICAgIGZlZTogRkVFLFxuICAgIH07XG5cbiAgICBjb25zdCB0eFAydHIyID0gY29uc3RydWN0VHJhbnNhY3Rpb25Vc2luZ1R4QnVpbGRlcihbdW5zcGVudHNbMF1dLCByb290V2FsbGV0S2V5cywgdHhCdWlsZGVyUGFyYW1zMik7XG4gICAgY29uc3QgcHNidFAydHIyID0gdG9XYWxsZXRQc2J0KHR4UDJ0cjIsIHRvQmlnSW50KFt1bnNwZW50c1swXV0pLCByb290V2FsbGV0S2V5cyk7XG5cbiAgICBjb25zdCB0eEJ1aWxkZXJQYXJhbXMzID0ge1xuICAgICAgc2lnbmVyOiAndXNlcicsXG4gICAgICBjb3NpZ25lcjogJ2JpdGdvJyxcbiAgICAgIGFtb3VudFR5cGU6ICdiaWdpbnQnLFxuICAgICAgb3V0cHV0VHlwZTogJ3Ayc2gnLFxuICAgICAgc2lnbmF0dXJlVGFyZ2V0OiAndW5zaWduZWQnLFxuICAgICAgbmV0d29yayxcbiAgICAgIGNoYW5nZUluZGV4OiBDSEFOR0VfSU5ERVgsXG4gICAgICBmZWU6IEZFRSxcbiAgICB9IGFzIGNvbnN0O1xuICAgIGNvbnN0IHR4UDJ0cjMgPSBjb25zdHJ1Y3RUcmFuc2FjdGlvblVzaW5nVHhCdWlsZGVyKFt1bnNwZW50c1swXV0sIHJvb3RXYWxsZXRLZXlzLCB0eEJ1aWxkZXJQYXJhbXMzKTtcbiAgICBjb25zdCBwc2J0UDJ0cjMgPSB0b1dhbGxldFBzYnQodHhQMnRyMywgdG9CaWdJbnQoW3Vuc3BlbnRzWzBdXSksIHJvb3RXYWxsZXRLZXlzKTtcbiAgICBpZiAocHNidFAydHIxLmRhdGEuaW5wdXRzWzBdLnRhcExlYWZTY3JpcHQgJiYgcHNidFAydHIyLmRhdGEuaW5wdXRzWzBdLnRhcExlYWZTY3JpcHQpIHtcbiAgICAgIGNvbnN0IHRhcExlYWZTY3JpcHRzID0gW3BzYnRQMnRyMS5kYXRhLmlucHV0c1swXS50YXBMZWFmU2NyaXB0WzBdLCBwc2J0UDJ0cjIuZGF0YS5pbnB1dHNbMF0udGFwTGVhZlNjcmlwdFswXV07XG4gICAgICBwc2J0UDJ0cjMudXBkYXRlSW5wdXQoMCwgeyB0YXBMZWFmU2NyaXB0OiB0YXBMZWFmU2NyaXB0cyB9KTtcblxuICAgICAgYXNzZXJ0LnRocm93cyhcbiAgICAgICAgKCkgPT4gcGFyc2VQc2J0SW5wdXQocHNidFAydHIzLmRhdGEuaW5wdXRzWzBdKSxcbiAgICAgICAgKGU6IGFueSkgPT4gZS5tZXNzYWdlID09PSAnQml0Z28gb25seSBzdXBwb3J0cyBhIHNpbmdsZSB0YXAgbGVhZiBzY3JpcHQgcGVyIGlucHV0LidcbiAgICAgICk7XG4gICAgfVxuICB9KTtcbn0pO1xuXG5kZXNjcmliZSgnaXNQc2J0JywgZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBpc1BzYnRGb3JOZXR3b3JrKG46IE5ldHdvcmspIHtcbiAgICBkZXNjcmliZShgbmV0d29yazogJHtnZXROZXR3b3JrTmFtZShuKX1gLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwc2J0ID0gY3JlYXRlUHNidEZvck5ldHdvcmsoeyBuZXR3b3JrOiBuIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGZvciBhIHZhbGlkIFBTQlQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IHBzYnRCdWZmID0gcHNidC50b0J1ZmZlcigpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNQc2J0KHBzYnRCdWZmKSwgdHJ1ZSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1BzYnQocHNidEJ1ZmYudG9TdHJpbmcoJ2hleCcpKSwgdHJ1ZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGEgdHJhbnNhY3Rpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1BzYnQocHNidC5nZXRVbnNpZ25lZFR4KCkudG9CdWZmZXIoKSksIGZhbHNlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3IgYSB0cnVuY2F0ZWQgbWFnaWMgd29yZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgaGV4ID0gcHNidC50b0J1ZmZlcigpLnNsaWNlKDAsIDMpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNQc2J0KGhleCksIGZhbHNlKTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGlzUHNidChCdWZmZXIuZnJvbShoZXgpKSwgZmFsc2UpO1xuICAgICAgfSk7XG5cbiAgICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBhIHZhbGlkIFBTQlQgd2l0aCBhbiBpbnZhbGlkIG1hZ2ljJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBidWZmZXIgPSBwc2J0LnRvQnVmZmVyKCk7XG4gICAgICAgIGJ1ZmZlci53cml0ZVVJbnQ4KDB4MDAsIDEpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNQc2J0KHBzYnQuZ2V0VW5zaWduZWRUeCgpLnRvQnVmZmVyKCkpLCBmYWxzZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGEgdmFsaWQgUFNCVCB3aXRoIGFuIGludmFsaWQgc2VwYXJhdG9yJywgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBidWZmZXIgPSBwc2J0LnRvQnVmZmVyKCk7XG4gICAgICAgIGJ1ZmZlci53cml0ZVVJbnQ4KDB4ZmUsIDQpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNQc2J0KHBzYnQuZ2V0VW5zaWduZWRUeCgpLnRvQnVmZmVyKCkpLCBmYWxzZSk7XG4gICAgICB9KTtcblxuICAgICAgaXQoJ3Nob3VsZCByZXR1cm4gZmFsc2UgZm9yIGEgcmFuZG9tIGJ1ZmZlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcmFuZG9tID0gJ2RlYWRiZWFmJztcbiAgICAgICAgY29uc3QgYnVmZmVyID0gQnVmZmVyLmZyb20ocmFuZG9tLCAnaGV4Jyk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1BzYnQocmFuZG9tKSwgZmFsc2UpO1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoaXNQc2J0KGJ1ZmZlciksIGZhbHNlKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdCgnc2hvdWxkIHJldHVybiB0cnVlIGlmIGJ1ZmZlciBpcyBjaGFuZ2VkIGFmdGVyIHRoZSBzZXBhcmF0b3InLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IHBzYnQudG9CdWZmZXIoKTtcbiAgICAgICAgYnVmZmVyLndyaXRlVUludDgoMHgwMCwgNSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChpc1BzYnQoYnVmZmVyKSwgdHJ1ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldE5ldHdvcmtMaXN0KCkuZm9yRWFjaCgobikgPT4gaXNQc2J0Rm9yTmV0d29yayhuKSk7XG59KTtcblxuZGVzY3JpYmUoJ1VwZGF0ZSBpbmNvbXBsZXRlIHBzYnQnLCBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIHJlbW92ZUZyb21Qc2J0KFxuICAgIHBzYnRIZXg6IHN0cmluZyxcbiAgICBuZXR3b3JrOiBOZXR3b3JrLFxuICAgIHJlbW92ZTogeyBpbnB1dD86IHsgaW5kZXg6IG51bWJlcjsgZmllbGRUb1JlbW92ZTogc3RyaW5nIH07IG91dHB1dD86IHsgaW5kZXg6IG51bWJlcjsgZmllbGRUb1JlbW92ZTogc3RyaW5nIH0gfVxuICApOiBVdHhvUHNidCB7XG4gICAgY29uc3QgdXR4b1BzYnQgPSBjcmVhdGVQc2J0RnJvbUhleChwc2J0SGV4LCBuZXR3b3JrKTtcbiAgICBjb25zdCBwc2J0ID0gY3JlYXRlUHNidEZvck5ldHdvcmsoeyBuZXR3b3JrOiB1dHhvUHNidC5uZXR3b3JrIH0pO1xuICAgIGNvbnN0IHR4SW5wdXRzID0gdXR4b1BzYnQudHhJbnB1dHM7XG4gICAgdXR4b1BzYnQuZGF0YS5pbnB1dHMubWFwKChpbnB1dCwgaWkpID0+IHtcbiAgICAgIGNvbnN0IHsgaGFzaCwgaW5kZXggfSA9IHR4SW5wdXRzW2lpXTtcbiAgICAgIGlmIChyZW1vdmUuaW5wdXQgJiYgaWkgPT09IHJlbW92ZS5pbnB1dC5pbmRleCkge1xuICAgICAgICBkZWxldGUgaW5wdXRbcmVtb3ZlLmlucHV0LmZpZWxkVG9SZW1vdmVdO1xuICAgICAgfVxuICAgICAgcHNidC5hZGRJbnB1dCh7IC4uLmlucHV0LCBoYXNoLCBpbmRleCB9KTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHR4T3V0cHV0cyA9IHV0eG9Qc2J0LnR4T3V0cHV0cztcbiAgICB1dHhvUHNidC5kYXRhLm91dHB1dHMubWFwKChvdXRwdXQsIGlpKSA9PiB7XG4gICAgICBpZiAocmVtb3ZlLm91dHB1dCAmJiByZW1vdmUub3V0cHV0LmluZGV4ID09PSBpaSkge1xuICAgICAgICBkZWxldGUgb3V0cHV0W3JlbW92ZS5vdXRwdXQuZmllbGRUb1JlbW92ZV07XG4gICAgICB9XG4gICAgICBwc2J0LmFkZE91dHB1dCh7IC4uLm91dHB1dCwgc2NyaXB0OiB0eE91dHB1dHNbaWldLnNjcmlwdCwgdmFsdWU6IHR4T3V0cHV0c1tpaV0udmFsdWUgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHBzYnQ7XG4gIH1cblxuICBmdW5jdGlvbiBzaWduQWxsSW5wdXRzKHBzYnQ6IFV0eG9Qc2J0LCB7IGFzc2VydFZhbGlkU2lnbmF0dXJlc0FuZEV4dHJhY3RhYmxlID0gdHJ1ZSB9ID0ge30pIHtcbiAgICBwc2J0LmRhdGEuaW5wdXRzLmZvckVhY2goKGlucHV0LCBpbnB1dEluZGV4KSA9PiB7XG4gICAgICBjb25zdCBwYXJzZWRJbnB1dCA9IHBhcnNlUHNidElucHV0KGlucHV0KTtcbiAgICAgIGlmIChwYXJzZWRJbnB1dC5zY3JpcHRUeXBlID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCcpIHtcbiAgICAgICAgcHNidC5zZXRJbnB1dE11c2lnMk5vbmNlSEQoaW5wdXRJbmRleCwgcm9vdFdhbGxldEtleXNbc2lnbmVyXSk7XG4gICAgICAgIHBzYnQuc2V0SW5wdXRNdXNpZzJOb25jZUhEKGlucHV0SW5kZXgsIHJvb3RXYWxsZXRLZXlzW2Nvc2lnbmVyXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJzZWRJbnB1dC5zY3JpcHRUeXBlID09PSAncDJzaFAycGsnKSB7XG4gICAgICAgIHBzYnQuc2lnbklucHV0KGlucHV0SW5kZXgsIHJlcGxheVByb3RlY3Rpb25LZXlQYWlyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBzYnQuc2lnbklucHV0SEQoaW5wdXRJbmRleCwgcm9vdFdhbGxldEtleXNbc2lnbmVyXSk7XG4gICAgICAgIHBzYnQuc2lnbklucHV0SEQoaW5wdXRJbmRleCwgcm9vdFdhbGxldEtleXNbY29zaWduZXJdKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmIChhc3NlcnRWYWxpZFNpZ25hdHVyZXNBbmRFeHRyYWN0YWJsZSkge1xuICAgICAgYXNzZXJ0Lm9rKHBzYnQudmFsaWRhdGVTaWduYXR1cmVzT2ZBbGxJbnB1dHMoKSk7XG4gICAgICBwc2J0LmZpbmFsaXplQWxsSW5wdXRzKCk7XG4gICAgICBjb25zdCB0eEV4dHJhY3RlZCA9IHBzYnQuZXh0cmFjdFRyYW5zYWN0aW9uKCk7XG4gICAgICBhc3NlcnQub2sodHhFeHRyYWN0ZWQpO1xuICAgIH1cbiAgfVxuXG4gIGxldCBwc2J0SGV4OiBzdHJpbmc7XG4gIGxldCB1bnNwZW50czogVW5zcGVudDxiaWdpbnQ+W107XG4gIGNvbnN0IHNpZ25lciA9ICd1c2VyJztcbiAgY29uc3QgY29zaWduZXIgPSAnYml0Z28nO1xuICBjb25zdCBzY3JpcHRUeXBlcyA9IFsuLi5zY3JpcHRUeXBlczJPZjMsICdwMnNoUDJwayddIGFzIChTY3JpcHRUeXBlMk9mMyB8IFNjcmlwdFR5cGVQMnNoUDJwaylbXTtcbiAgY29uc3Qgb3V0cHV0VmFsdWUgPSBCaWdJbnQoKDJlOCAqIHNjcmlwdFR5cGVzLmxlbmd0aCAtIDEwMCkgLyA1KTtcbiAgY29uc3Qgb3V0cHV0cyA9IFtcbiAgICB7IGNoYWluOiBnZXRFeHRlcm5hbENoYWluQ29kZSgncDJzaCcpLCBpbmRleDogODgsIHZhbHVlOiBvdXRwdXRWYWx1ZSB9LFxuICAgIHsgY2hhaW46IGdldEV4dGVybmFsQ2hhaW5Db2RlKCdwMnNoUDJ3c2gnKSwgaW5kZXg6IDg5LCB2YWx1ZTogb3V0cHV0VmFsdWUgfSxcbiAgICB7IGNoYWluOiBnZXRFeHRlcm5hbENoYWluQ29kZSgncDJ3c2gnKSwgaW5kZXg6IDkwLCB2YWx1ZTogb3V0cHV0VmFsdWUgfSxcbiAgICB7IGNoYWluOiBnZXRFeHRlcm5hbENoYWluQ29kZSgncDJ0cicpLCBpbmRleDogOTEsIHZhbHVlOiBvdXRwdXRWYWx1ZSB9LFxuICAgIHsgY2hhaW46IGdldEV4dGVybmFsQ2hhaW5Db2RlKCdwMnRyTXVzaWcyJyksIGluZGV4OiA5MiwgdmFsdWU6IG91dHB1dFZhbHVlIH0sXG4gIF07XG4gIGJlZm9yZShmdW5jdGlvbiAoKSB7XG4gICAgdW5zcGVudHMgPSBtb2NrVW5zcGVudHMocm9vdFdhbGxldEtleXMsIHNjcmlwdFR5cGVzLCBCaWdJbnQoMmU4KSwgbmV0d29yayk7XG4gICAgY29uc3QgcHNidCA9IGNvbnN0cnVjdFBzYnQodW5zcGVudHMsIHJvb3RXYWxsZXRLZXlzLCBzaWduZXIsIGNvc2lnbmVyLCBvdXRwdXRzKTtcbiAgICBwc2J0SGV4ID0gcHNidC50b0hleCgpO1xuICB9KTtcblxuICBpdCgnY2FuIGNyZWF0ZSBhIHNpZ24tYWJsZSBwc2J0IGZyb20gYW4gdW5zaWduZWQgdHJhbnNhY3Rpb24gZXh0cmFjdGVkIGZyb20gdGhlIHBzYnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRydWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcHNidE9yaWcgPSBjcmVhdGVQc2J0RnJvbUhleChwc2J0SGV4LCBuZXR3b3JrKTtcbiAgICBjb25zdCB0eCA9IHBzYnRPcmlnLmdldFVuc2lnbmVkVHgoKTtcbiAgICBjb25zdCBwc2J0ID0gY3JlYXRlUHNidEZyb21UcmFuc2FjdGlvbihcbiAgICAgIHR4LFxuICAgICAgdW5zcGVudHMubWFwKCh1KSA9PiB0b1ByZXZPdXRwdXQodSwgbmV0d29yaykpXG4gICAgKTtcbiAgICB1bnNwZW50cy5mb3JFYWNoKCh1LCBpbnB1dEluZGV4KSA9PiB7XG4gICAgICBpZiAoaXNXYWxsZXRVbnNwZW50KHUpKSB7XG4gICAgICAgIHVwZGF0ZVdhbGxldFVuc3BlbnRGb3JQc2J0KHBzYnQsIGlucHV0SW5kZXgsIHUsIHJvb3RXYWxsZXRLZXlzLCBzaWduZXIsIGNvc2lnbmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHsgcmVkZWVtU2NyaXB0IH0gPSBjcmVhdGVPdXRwdXRTY3JpcHRQMnNoUDJwayhyZXBsYXlQcm90ZWN0aW9uS2V5UGFpci5wdWJsaWNLZXkpO1xuICAgICAgICB1cGRhdGVSZXBsYXlQcm90ZWN0aW9uVW5zcGVudFRvUHNidChwc2J0LCBpbnB1dEluZGV4LCB1LCByZWRlZW1TY3JpcHQpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgc2lnbkFsbElucHV0cyhwc2J0KTtcbiAgfSk7XG5cbiAgY29uc3QgY29tcG9uZW50c09uRWFjaElucHV0U2NyaXB0VHlwZSA9IHtcbiAgICBwMnNoOiBbJ25vbldpdG5lc3NVdHhvJywgJ3JlZGVlbVNjcmlwdCcsICdiaXAzMkRlcml2YXRpb24nXSxcbiAgICBwMnNoUDJ3c2g6IFsnd2l0bmVzc1V0eG8nLCAnYmlwMzJEZXJpdmF0aW9uJywgJ3JlZGVlbVNjcmlwdCcsICd3aXRuZXNzU2NyaXB0J10sXG4gICAgcDJ3c2g6IFsnd2l0bmVzc1V0eG8nLCAnd2l0bmVzc1NjcmlwdCcsICdiaXAzMkRlcml2YXRpb24nXSxcbiAgICBwMnRyOiBbJ3dpdG5lc3NVdHhvJywgJ3RhcExlYWZTY3JpcHQnLCAndGFwQmlwMzJEZXJpdmF0aW9uJ10sXG4gICAgcDJ0ck11c2lnMjogWyd3aXRuZXNzVXR4bycsICd0YXBCaXAzMkRlcml2YXRpb24nLCAndGFwSW50ZXJuYWxLZXknLCAndGFwTWVya2xlUm9vdCcsICd1bmtub3duS2V5VmFscyddLFxuICAgIHAyc2hQMnBrOiBbJ3JlZGVlbVNjcmlwdCcsICdub25XaXRuZXNzVXR4byddLFxuICB9O1xuXG4gIGNvbnN0IHAydHJDb21wb25lbnRzID0gWyd0YXBUcmVlJywgJ3RhcEludGVybmFsS2V5JywgJ3RhcEJpcDMyRGVyaXZhdGlvbiddO1xuICBjb25zdCBjb21wb25lbnRzT25FYWNoT3V0cHV0U2NyaXB0VHlwZSA9IHtcbiAgICBwMnNoOiBbJ2JpcDMyRGVyaXZhdGlvbicsICdyZWRlZW1TY3JpcHQnXSxcbiAgICBwMnNoUDJ3c2g6IFsnYmlwMzJEZXJpdmF0aW9uJywgJ3dpdG5lc3NTY3JpcHQnLCAncmVkZWVtU2NyaXB0J10sXG4gICAgcDJ3c2g6IFsnYmlwMzJEZXJpdmF0aW9uJywgJ3dpdG5lc3NTY3JpcHQnXSxcbiAgICBwMnRyOiBwMnRyQ29tcG9uZW50cyxcbiAgICBwMnRyTXVzaWcyOiBwMnRyQ29tcG9uZW50cyxcbiAgICBwMnNoUDJwazogW10sXG4gIH07XG4gIHNjcmlwdFR5cGVzLmZvckVhY2goKHNjcmlwdFR5cGUsIGkpID0+IHtcbiAgICBjb21wb25lbnRzT25FYWNoSW5wdXRTY3JpcHRUeXBlW3NjcmlwdFR5cGVdLmZvckVhY2goKGlucHV0Q29tcG9uZW50KSA9PiB7XG4gICAgICBpdChgWyR7c2NyaXB0VHlwZX1dIG1pc3NpbmcgJHtpbnB1dENvbXBvbmVudH0gb24gaW5wdXQgc2hvdWxkIHN1Y2NlZWQgaW4gZnVsbHkgc2lnbmluZyB1bnNpZ25lZCBwc2J0IGFmdGVyIHVwZGF0ZWAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgcHNidCA9IHJlbW92ZUZyb21Qc2J0KHBzYnRIZXgsIG5ldHdvcmssIHsgaW5wdXQ6IHsgaW5kZXg6IGksIGZpZWxkVG9SZW1vdmU6IGlucHV0Q29tcG9uZW50IH0gfSk7XG4gICAgICAgIGNvbnN0IHVuc3BlbnQgPSB1bnNwZW50c1tpXTtcbiAgICAgICAgaWYgKGlzV2FsbGV0VW5zcGVudCh1bnNwZW50KSkge1xuICAgICAgICAgIHVwZGF0ZVdhbGxldFVuc3BlbnRGb3JQc2J0KHBzYnQsIGksIHVuc3BlbnQsIHJvb3RXYWxsZXRLZXlzLCBzaWduZXIsIGNvc2lnbmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCB7IHJlZGVlbVNjcmlwdCB9ID0gY3JlYXRlT3V0cHV0U2NyaXB0UDJzaFAycGsocmVwbGF5UHJvdGVjdGlvbktleVBhaXIucHVibGljS2V5KTtcbiAgICAgICAgICBhc3NlcnQub2socmVkZWVtU2NyaXB0KTtcbiAgICAgICAgICB1cGRhdGVSZXBsYXlQcm90ZWN0aW9uVW5zcGVudFRvUHNidChwc2J0LCBpLCB1bnNwZW50LCByZWRlZW1TY3JpcHQpO1xuICAgICAgICB9XG4gICAgICAgIHNpZ25BbGxJbnB1dHMocHNidCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGNvbXBvbmVudHNPbkVhY2hPdXRwdXRTY3JpcHRUeXBlW3NjcmlwdFR5cGVdLmZvckVhY2goKG91dHB1dENvbXBvbmVudCkgPT4ge1xuICAgICAgaXQoYFske3NjcmlwdFR5cGV9XSBtaXNzaW5nICR7b3V0cHV0Q29tcG9uZW50fSBvbiBvdXRwdXQgc2hvdWxkIHByb2R1Y2Ugc2FtZSBoZXggYXMgZnVsbHkgaHlkcmF0ZWQgYWZ0ZXIgdXBkYXRlYCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBwc2J0ID0gcmVtb3ZlRnJvbVBzYnQocHNidEhleCwgbmV0d29yaywgeyBvdXRwdXQ6IHsgaW5kZXg6IGksIGZpZWxkVG9SZW1vdmU6IG91dHB1dENvbXBvbmVudCB9IH0pO1xuICAgICAgICB1cGRhdGVXYWxsZXRPdXRwdXRGb3JQc2J0KHBzYnQsIHJvb3RXYWxsZXRLZXlzLCBpLCBvdXRwdXRzW2ldLmNoYWluLCBvdXRwdXRzW2ldLmluZGV4KTtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHBzYnQudG9IZXgoKSwgcHNidEhleCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ1BzYnQgZnJvbSB0cmFuc2FjdGlvbiB1c2luZyB3YWxsZXQgdW5zcGVudHMnLCBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIHJ1blRlc3RTaWduVW5zcGVudHM8VE51bWJlciBleHRlbmRzIG51bWJlciB8IGJpZ2ludD4oe1xuICAgIGlucHV0U2NyaXB0VHlwZXMsXG4gICAgb3V0cHV0U2NyaXB0VHlwZSxcbiAgICBzaWduZXIsXG4gICAgY29zaWduZXIsXG4gICAgYW1vdW50VHlwZSxcbiAgICB0ZXN0T3V0cHV0QW1vdW50LFxuICAgIHNpZ25hdHVyZVRhcmdldCxcbiAgfToge1xuICAgIGlucHV0U2NyaXB0VHlwZXM6IElucHV0VHlwZVtdO1xuICAgIG91dHB1dFNjcmlwdFR5cGU6IG91dHB1dFNjcmlwdHMuU2NyaXB0VHlwZTJPZjM7XG4gICAgc2lnbmVyOiBLZXlOYW1lO1xuICAgIGNvc2lnbmVyOiBLZXlOYW1lO1xuICAgIGFtb3VudFR5cGU6ICdudW1iZXInIHwgJ2JpZ2ludCc7XG4gICAgdGVzdE91dHB1dEFtb3VudDogVE51bWJlcjtcbiAgICBzaWduYXR1cmVUYXJnZXQ6IFNpZ25hdHVyZVRhcmdldFR5cGU7XG4gIH0pIHtcbiAgICBpdChgY2FuIGJlIHNpZ25lZCBbaW5wdXRzPSR7aW5wdXRTY3JpcHRUeXBlc30gc2lnbmVyPSR7c2lnbmVyfSBjb3NpZ25lcj0ke2Nvc2lnbmVyfSBhbW91bnRUeXBlPSR7YW1vdW50VHlwZX0gc2lnbmF0dXJlVGFyZ2V0PSR7c2lnbmF0dXJlVGFyZ2V0fV1gLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1bnNwZW50cyA9IG1vY2tVbnNwZW50cyhyb290V2FsbGV0S2V5cywgaW5wdXRTY3JpcHRUeXBlcywgdGVzdE91dHB1dEFtb3VudCwgbmV0d29yayk7XG4gICAgICAvLyBjb25zdCB0eEJ1aWxkZXJQYXJhbXMgPSB7IG5ldHdvcmssIGNoYW5nZUluZGV4OiBDSEFOR0VfSU5ERVgsIGZlZTogRkVFIH07XG4gICAgICBjb25zdCB0eEJ1aWxkZXJQYXJhbXMgPSB7XG4gICAgICAgIHNpZ25lcixcbiAgICAgICAgY29zaWduZXIsXG4gICAgICAgIGFtb3VudFR5cGUsXG4gICAgICAgIG91dHB1dFR5cGU6IG91dHB1dFNjcmlwdFR5cGUsXG4gICAgICAgIHNpZ25hdHVyZVRhcmdldDogc2lnbmF0dXJlVGFyZ2V0LFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgICBjaGFuZ2VJbmRleDogQ0hBTkdFX0lOREVYLFxuICAgICAgICBmZWU6IEZFRSxcbiAgICAgIH07XG4gICAgICBjb25zdCB0eCA9IGNvbnN0cnVjdFRyYW5zYWN0aW9uVXNpbmdUeEJ1aWxkZXIodW5zcGVudHMsIHJvb3RXYWxsZXRLZXlzLCB0eEJ1aWxkZXJQYXJhbXMpO1xuXG4gICAgICBjb25zdCB1bnNwZW50QmlnSW50ID0gdG9CaWdJbnQodW5zcGVudHMpO1xuXG4gICAgICBjb25zdCBwc2J0ID0gdG9XYWxsZXRQc2J0KHR4LCB1bnNwZW50QmlnSW50LCByb290V2FsbGV0S2V5cyk7XG5cbiAgICAgIHZhbGlkYXRlUHNidFBhcnNpbmcodHgsIHBzYnQsIHVuc3BlbnRCaWdJbnQsIHNpZ25hdHVyZVRhcmdldCk7XG5cbiAgICAgIC8vIENoZWNrIHRoYXQgdGhlIGNvcnJlY3QgdW5zcGVudCBjb3JyZXNwb25kcyB0byB0aGUgaW5wdXRcbiAgICAgIHVuc3BlbnRCaWdJbnQuZm9yRWFjaCgodW5zcGVudCwgaW5wdXRJbmRleCkgPT4ge1xuICAgICAgICBjb25zdCBvdGhlclVuc3BlbnQgPSBpbnB1dEluZGV4ID09PSAwID8gdW5zcGVudEJpZ0ludFsxXSA6IHVuc3BlbnRCaWdJbnRbMF07XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwc2J0SW5jbHVkZXNVbnNwZW50QXRJbmRleChwc2J0LCBpbnB1dEluZGV4LCB1bnNwZW50LmlkKSwgdHJ1ZSk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChwc2J0SW5jbHVkZXNVbnNwZW50QXRJbmRleChwc2J0LCBpbnB1dEluZGV4LCBvdGhlclVuc3BlbnQuaWQpLCBmYWxzZSk7XG4gICAgICAgIHVwZGF0ZVdhbGxldFVuc3BlbnRGb3JQc2J0KHBzYnQsIGlucHV0SW5kZXgsIHVuc3BlbnQsIHJvb3RXYWxsZXRLZXlzLCBzaWduZXIsIGNvc2lnbmVyKTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoc2lnbmF0dXJlVGFyZ2V0ICE9PSAnZnVsbHNpZ25lZCcpIHtcbiAgICAgICAgLy8gTm93IHNpZ25pbmcgdG8gbWFrZSBpdCBmdWxseSBzaWduZWQgcHNidC5cbiAgICAgICAgLy8gU28gaXQgd2lsbCBiZSBlYXN5IHRvIHZlcmlmeSBpdHMgdmFsaWRpdHkgd2l0aCBhbm90aGVyIHNpbWlsYXIgdHggdG8gYmUgYnVpbHQgd2l0aCB0eCBidWlsZGVyLlxuICAgICAgICBzaWduUHNidChwc2J0LCB1bnNwZW50QmlnSW50LCByb290V2FsbGV0S2V5cywgc2lnbmVyLCBjb3NpZ25lciwgc2lnbmF0dXJlVGFyZ2V0KTtcbiAgICAgIH1cbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwocHNidC52YWxpZGF0ZVNpZ25hdHVyZXNPZkFsbElucHV0cygpLCB0cnVlKTtcbiAgICAgIHBzYnQuZmluYWxpemVBbGxJbnB1dHMoKTtcbiAgICAgIGNvbnN0IHR4RnJvbVBzYnQgPSBwc2J0LmV4dHJhY3RUcmFuc2FjdGlvbigpO1xuXG4gICAgICBjb25zdCB0eEJ1aWxkZXJQYXJhbXMyID0ge1xuICAgICAgICBzaWduZXIsXG4gICAgICAgIGNvc2lnbmVyLFxuICAgICAgICBhbW91bnRUeXBlLFxuICAgICAgICBvdXRwdXRUeXBlOiBvdXRwdXRTY3JpcHRUeXBlLFxuICAgICAgICBzaWduYXR1cmVUYXJnZXQ6ICdmdWxsc2lnbmVkJyBhcyBTaWduYXR1cmVUYXJnZXRUeXBlLFxuICAgICAgICBuZXR3b3JrLFxuICAgICAgICBjaGFuZ2VJbmRleDogQ0hBTkdFX0lOREVYLFxuICAgICAgICBmZWU6IEZFRSxcbiAgICAgIH07XG5cbiAgICAgIC8vIE5ldyBsZWdhY3kgdHggcmVzZW1ibGVzIHRoZSBzaWduZWQgcHNidC5cbiAgICAgIGNvbnN0IHR4RnJvbVR4QnVpbGRlciA9IGNvbnN0cnVjdFRyYW5zYWN0aW9uVXNpbmdUeEJ1aWxkZXIodW5zcGVudHMsIHJvb3RXYWxsZXRLZXlzLCB0eEJ1aWxkZXJQYXJhbXMyKTtcblxuICAgICAgYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCh0eEZyb21Qc2J0LmdldEhhc2goKSwgdHhGcm9tVHhCdWlsZGVyLmdldEhhc2goKSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRJbnB1dFNjcmlwdHMoKTogSW5wdXRUeXBlW11bXSB7XG4gICAgcmV0dXJuIGdldFNjcmlwdFR5cGVzMk9mMygpLmZsYXRNYXAoKHQpID0+IHtcbiAgICAgIHJldHVybiBnZXRTY3JpcHRUeXBlczJPZjMoKS5mbGF0TWFwKChsYXN0VHlwZSkgPT4ge1xuICAgICAgICByZXR1cm4gW1t0LCB0LCBsYXN0VHlwZV1dO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTaWduZXJQYWlycyhjb250YWluc1RhcHJvb3RJbnB1dDogYm9vbGVhbik6IFtzaWduZXI6IEtleU5hbWUsIGNvc2lnbmVyOiBLZXlOYW1lXVtdIHtcbiAgICBjb25zdCBzaWduYXR1cmVQYWlycyA9IFtbJ3VzZXInLCAnYml0Z28nXSBhcyBbc2lnbmVyOiBLZXlOYW1lLCBjb3NpZ25lcjogS2V5TmFtZV1dO1xuICAgIGlmIChjb250YWluc1RhcHJvb3RJbnB1dCkge1xuICAgICAgc2lnbmF0dXJlUGFpcnMucHVzaChbJ3VzZXInLCAnYmFja3VwJ10gYXMgW3NpZ25lcjogS2V5TmFtZSwgY29zaWduZXI6IEtleU5hbWVdKTtcbiAgICB9XG4gICAgcmV0dXJuIHNpZ25hdHVyZVBhaXJzO1xuICB9XG5cbiAgKFsndW5zaWduZWQnLCAnaGFsZnNpZ25lZCcsICdmdWxsc2lnbmVkJ10gYXMgU2lnbmF0dXJlVGFyZ2V0VHlwZVtdKS5mb3JFYWNoKChzaWduYXR1cmVUYXJnZXQpID0+IHtcbiAgICBnZXRJbnB1dFNjcmlwdHMoKS5mb3JFYWNoKChpbnB1dFNjcmlwdFR5cGVzKSA9PiB7XG4gICAgICBnZXRTaWduZXJQYWlycyhpbnB1dFNjcmlwdFR5cGVzLmluY2x1ZGVzKCdwMnRyJykpLmZvckVhY2goKFtzaWduZXIsIGNvc2lnbmVyXSkgPT4ge1xuICAgICAgICBydW5UZXN0U2lnblVuc3BlbnRzKHtcbiAgICAgICAgICBpbnB1dFNjcmlwdFR5cGVzLFxuICAgICAgICAgIG91dHB1dFNjcmlwdFR5cGU6ICdwMnNoJyxcbiAgICAgICAgICBzaWduZXIsXG4gICAgICAgICAgY29zaWduZXIsXG4gICAgICAgICAgYW1vdW50VHlwZTogJ251bWJlcicsXG4gICAgICAgICAgdGVzdE91dHB1dEFtb3VudDogZGVmYXVsdFRlc3RPdXRwdXRBbW91bnQsXG4gICAgICAgICAgc2lnbmF0dXJlVGFyZ2V0LFxuICAgICAgICB9KTtcbiAgICAgICAgcnVuVGVzdFNpZ25VbnNwZW50czxiaWdpbnQ+KHtcbiAgICAgICAgICBpbnB1dFNjcmlwdFR5cGVzLFxuICAgICAgICAgIG91dHB1dFNjcmlwdFR5cGU6ICdwMnNoJyxcbiAgICAgICAgICBzaWduZXIsXG4gICAgICAgICAgY29zaWduZXIsXG4gICAgICAgICAgYW1vdW50VHlwZTogJ2JpZ2ludCcsXG4gICAgICAgICAgdGVzdE91dHB1dEFtb3VudDogQmlnSW50KCcxMDAwMDAwMDAwMDAwMDAwMCcpLFxuICAgICAgICAgIHNpZ25hdHVyZVRhcmdldCxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcblxuZnVuY3Rpb24gdGVzdFV0eG9Qc2J0KGNvaW5OZXR3b3JrOiBOZXR3b3JrKSB7XG4gIGRlc2NyaWJlKGBUZXN0aW5nIFV0eG9Qc2J0IChkZSlzZXJpYWxpemF0aW9uIGZvciAke2dldE5ldHdvcmtOYW1lKGNvaW5OZXR3b3JrKX0gbmV0d29ya2AsIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgcHNidDogVXR4b1BzYnQ7XG4gICAgbGV0IHBzYnRIZXg6IHN0cmluZztcbiAgICBsZXQgdW5zcGVudHM6IChXYWxsZXRVbnNwZW50PGJpZ2ludD4gfCBVbnNwZW50PGJpZ2ludD4pW107XG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIHVuc3BlbnRzID0gbW9ja1Vuc3BlbnRzKHJvb3RXYWxsZXRLZXlzLCBbJ3Ayc2gnXSwgQmlnSW50KCcxMDAwMDAwMDAwMDAwMCcpLCBjb2luTmV0d29yayk7XG4gICAgICBjb25zdCB0eEJ1aWxkZXJQYXJhbXMgPSB7XG4gICAgICAgIHNpZ25lcjogJ3VzZXInLFxuICAgICAgICBjb3NpZ25lcjogJ2JpdGdvJyxcbiAgICAgICAgYW1vdW50VHlwZTogJ2JpZ2ludCcsXG4gICAgICAgIG91dHB1dFR5cGU6ICdwMnNoJyxcbiAgICAgICAgc2lnbmF0dXJlVGFyZ2V0OiAnZnVsbHNpZ25lZCcsXG4gICAgICAgIG5ldHdvcms6IGNvaW5OZXR3b3JrLFxuICAgICAgICBjaGFuZ2VJbmRleDogQ0hBTkdFX0lOREVYLFxuICAgICAgICBmZWU6IEZFRSxcbiAgICAgIH0gYXMgY29uc3Q7XG4gICAgICBjb25zdCB0eCA9IGNvbnN0cnVjdFRyYW5zYWN0aW9uVXNpbmdUeEJ1aWxkZXIodW5zcGVudHMsIHJvb3RXYWxsZXRLZXlzLCB0eEJ1aWxkZXJQYXJhbXMpO1xuICAgICAgcHNidCA9IHRvV2FsbGV0UHNidCh0eCwgdG9CaWdJbnQodW5zcGVudHMpLCByb290V2FsbGV0S2V5cyk7XG4gICAgICBpZiAoY29pbk5ldHdvcmsgPT09IG5ldHdvcmtzLnpjYXNoKSB7XG4gICAgICAgIChwc2J0IGFzIFpjYXNoUHNidCkuc2V0RGVmYXVsdHNGb3JWZXJzaW9uKG5ldHdvcmssIDQ1MCk7XG4gICAgICB9XG4gICAgICBwc2J0SGV4ID0gcHNidC50b0hleCgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBiZSBhYmxlIHRvIGNsb25lIHBzYnQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjbG9uZSA9IHBzYnQuY2xvbmUoKTtcbiAgICAgIGFzc2VydChjbG9uZSBpbnN0YW5jZW9mIHBzYnQuY29uc3RydWN0b3IsIGBFeHBlY3RlZCBjbG9uZSB0byBiZSBpbnN0YW5jZSBvZiAke3BzYnQuY29uc3RydWN0b3IubmFtZX1gKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoY2xvbmUudG9CdWZmZXIoKSwgcHNidC50b0J1ZmZlcigpKTtcbiAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwoY2xvbmUuY2xvbmUoKS50b0J1ZmZlcigpLCBwc2J0LnRvQnVmZmVyKCkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGNsb25lLm5ldHdvcmssIHBzYnQubmV0d29yayk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoY2xvbmUuY2xvbmUoKS5uZXR3b3JrLCBwc2J0Lm5ldHdvcmspO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBiZSBhYmxlIHRvIHJvdW5kLXRyaXAnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKGNyZWF0ZVBzYnRGcm9tSGV4KHBzYnRIZXgsIGNvaW5OZXR3b3JrLCBmYWxzZSkudG9CdWZmZXIoKSwgcHNidC50b0J1ZmZlcigpKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYmUgYWJsZSB0byBnZXQgdHJhbnNhY3Rpb24gaW5mbyBmcm9tIHBzYnQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB0eEluZm8gPSBnZXRUcmFuc2FjdGlvbkFtb3VudHNGcm9tUHNidChwc2J0KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eEluZm8uZmVlLCBGRUUpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4SW5mby5pbnB1dENvdW50LCB1bnNwZW50cy5sZW5ndGgpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4SW5mby5pbnB1dEFtb3VudCwgQmlnSW50KCcxMDAwMDAwMDAwMDAwMCcpICogQmlnSW50KHVuc3BlbnRzLmxlbmd0aCkpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4SW5mby5vdXRwdXRBbW91bnQsIEJpZ0ludCgnMTAwMDAwMDAwMDAwMDAnKSAqIEJpZ0ludCh1bnNwZW50cy5sZW5ndGgpIC0gRkVFKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eEluZm8ub3V0cHV0Q291bnQsIHBzYnQuZGF0YS5vdXRwdXRzLmxlbmd0aCk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBkZXNlcmlhbGl6ZUJpcDMyUGF0aHNDb3JyZWN0bHkoYmlwMzJQYXRoc0Fic29sdXRlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICBmdW5jdGlvbiBjaGVja0Rlcml2YXRpb25QcmVmaXgoYmlwMzJEZXJpdmF0aW9uOiB7IHBhdGg6IHN0cmluZyB9KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHBhdGggPSBiaXAzMkRlcml2YXRpb24ucGF0aC5zcGxpdCgnLycpO1xuICAgICAgICBjb25zdCBwcmVmaXggPSBiaXAzMlBhdGhzQWJzb2x1dGUgPyAnbScgOiAnMCc7XG4gICAgICAgIGFzc2VydChwYXRoWzBdID09PSBwcmVmaXgpO1xuICAgICAgfVxuICAgICAgaXQoYHNob3VsZCBkZXNlcmlhbGl6ZSBQU0JUIGJpcDMyRGVyaXZhdGlvbnMgd2l0aCBwYXRocyAke1xuICAgICAgICBiaXAzMlBhdGhzQWJzb2x1dGUgPyAnJyA6ICdub3QgJ1xuICAgICAgfSBhYnNvbHV0ZWAsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgZGVzZXJpYWxpemVkUHNidCA9IGNyZWF0ZVBzYnRGcm9tSGV4KHBzYnRIZXgsIGNvaW5OZXR3b3JrLCBiaXAzMlBhdGhzQWJzb2x1dGUpO1xuICAgICAgICBhc3NlcnQoZGVzZXJpYWxpemVkUHNidCk7XG4gICAgICAgIGRlc2VyaWFsaXplZFBzYnQuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQpID0+IHtcbiAgICAgICAgICBpbnB1dD8uYmlwMzJEZXJpdmF0aW9uPy5mb3JFYWNoKChkZXJpdmF0aW9uKSA9PiBjaGVja0Rlcml2YXRpb25QcmVmaXgoZGVyaXZhdGlvbikpO1xuICAgICAgICAgIGlucHV0Py50YXBCaXAzMkRlcml2YXRpb24/LmZvckVhY2goKGRlcml2YXRpb24pID0+IGNoZWNrRGVyaXZhdGlvblByZWZpeChkZXJpdmF0aW9uKSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgW3RydWUsIGZhbHNlXS5mb3JFYWNoKChiaXAzMlBhdGhzQWJzb2x1dGUpID0+IGRlc2VyaWFsaXplQmlwMzJQYXRoc0NvcnJlY3RseShiaXAzMlBhdGhzQWJzb2x1dGUpKTtcbiAgfSk7XG59XG5cbltuZXR3b3Jrcy5iaXRjb2luLCBuZXR3b3Jrcy56Y2FzaCwgbmV0d29ya3MuZGFzaCwgbmV0d29ya3MuZG9nZWNvaW4sIG5ldHdvcmtzLmxpdGVjb2luXS5mb3JFYWNoKChjb2luTmV0d29yaykgPT5cbiAgdGVzdFV0eG9Qc2J0KGNvaW5OZXR3b3JrKVxuKTtcbiJdfQ==

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


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