PHP WebShell

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

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

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const mocha_1 = require("mocha");
const src_1 = require("../../src");
const testutil_1 = require("../../src/testutil");
const bitgo_1 = require("../../src/bitgo");
const outputScripts_1 = require("../../src/bitgo/outputScripts");
const outputScripts_util_1 = require("./generate/outputScripts.util");
const fixtures_1 = require("./generate/fixtures");
const transaction_util_1 = require("../transaction_util");
const compare_1 = require("./compare");
const testutil_2 = require("../testutil");
const fixtureTxTypes = ['deposit', 'spend'];
function getScriptTypes() {
    // FIXME(BG-66941): p2trMusig2 signing does not work in this test suite yet
    //  because the test suite is written with TransactionBuilder
    return outputScripts_util_1.scriptTypes.filter((scriptType) => scriptType !== 'p2trMusig2');
}
function runTestParse(protocol, txType, scriptType, amountType) {
    if (txType === 'deposit' && !(0, outputScripts_util_1.isSupportedDepositType)(protocol.network, scriptType)) {
        return;
    }
    if (txType === 'spend' && !(0, outputScripts_util_1.isSupportedSpendType)(protocol.network, scriptType)) {
        return;
    }
    const fixtureName = `${txType}_${scriptType}.json`;
    (0, mocha_1.describe)(`${fixtureName} amountType=${amountType}`, function () {
        let fixture;
        let txBuffer;
        let parsedTx;
        before(async function () {
            fixture = await (0, fixtures_1.readFixture)({
                network: protocol.network,
                version: protocol.version ?? (0, bitgo_1.getDefaultTransactionVersion)(protocol.network),
            }, fixtureName);
            txBuffer = Buffer.from(fixture.transaction.hex, 'hex');
            parsedTx = (0, bitgo_1.createTransactionFromBuffer)(txBuffer, protocol.network, {
                version: protocol.version,
                amountType,
            });
        });
        function getPrevOutput(input) {
            if (input.hash) {
                input = {
                    ...input,
                    ...(0, bitgo_1.getOutputIdForInput)(input),
                };
            }
            const inputTx = fixture.inputs.find((tx) => tx.txid === input.txid);
            if (!inputTx) {
                throw new Error(`could not find inputTx`);
            }
            const prevOutput = inputTx.vout[input.index];
            if (!prevOutput) {
                throw new Error(`could not prevOutput`);
            }
            return prevOutput;
        }
        function getPrevOutputValue(input) {
            return (0, testutil_2.decimalCoinsToSats)(getPrevOutput(input).value, amountType);
        }
        function getPrevOutputScript(input) {
            return Buffer.from(getPrevOutput(input).scriptPubKey.hex, 'hex');
        }
        function getPrevOutputs() {
            return parsedTx.ins.map((i) => ({
                ...(0, bitgo_1.getOutputIdForInput)(i),
                script: getPrevOutputScript(i),
                value: getPrevOutputValue(i),
                prevTx: txBuffer,
            }));
        }
        (0, mocha_1.it)(`round-trip`, function () {
            (0, transaction_util_1.parseTransactionRoundTrip)(Buffer.from(fixture.transaction.hex, 'hex'), protocol.network, {
                inputs: getPrevOutputs(),
                amountType,
                version: protocol.version,
                // FIXME: prevTx parsing for Zcash not working yet
                roundTripPsbt: txType === 'spend' && protocol.network !== src_1.networks.zcashTest,
            });
        });
        (0, mocha_1.it)(`round-trip (high-precision values)`, function () {
            if (amountType !== 'bigint') {
                return;
            }
            const tx = (0, bitgo_1.createTransactionFromBuffer)(Buffer.from(fixture.transaction.hex, 'hex'), protocol.network, {
                amountType,
            });
            tx.outs.forEach((o) => {
                o.value = (BigInt(1e16) + BigInt(1));
                assert.notStrictEqual(BigInt(Number(o.value)), o.value);
            });
            const txRoundTrip = (0, transaction_util_1.parseTransactionRoundTrip)(tx.toBuffer(), protocol.network, { amountType });
            assert.strictEqual(txRoundTrip.outs.length, tx.outs.length);
            txRoundTrip.outs.forEach((o, i) => {
                assert.deepStrictEqual(o, tx.outs[i]);
            });
        });
        (0, mocha_1.it)(`recreate from unsigned hex`, function () {
            if (txType === 'deposit') {
                return;
            }
            const txbUnsigned = (0, bitgo_1.createTransactionBuilderForNetwork)(protocol.network, { version: protocol.version });
            getPrevOutputs().forEach((o) => {
                txbUnsigned.addInput(o.txid, o.vout);
            });
            fixture.transaction.vout.forEach((o) => {
                txbUnsigned.addOutput(Buffer.from(o.scriptPubKey.hex, 'hex'), (0, testutil_2.decimalCoinsToSats)(o.value, amountType));
            });
            const tx = (0, bitgo_1.createTransactionFromBuffer)(txbUnsigned.buildIncomplete().toBuffer(), protocol.network, {
                version: protocol.version,
                amountType,
            });
            const txb = (0, bitgo_1.createTransactionBuilderFromTransaction)(tx, getPrevOutputs());
            const signKeys = [fixtures_1.fixtureKeys[0], fixtures_1.fixtureKeys[2]];
            const publicKeys = fixtures_1.fixtureKeys.map((k) => k.publicKey);
            getPrevOutputs().forEach(({ value }, vin) => {
                signKeys.forEach((key) => {
                    (0, bitgo_1.signInput2Of3)(txb, vin, scriptType, publicKeys, key, (0, testutil_1.getDefaultCosigner)(publicKeys, key.publicKey), value);
                });
            });
            assert.strictEqual(txb.build().version, tx.version);
            assert.strictEqual(txb.build().toBuffer().toString('hex'), fixture.transaction.hex);
        });
        (0, mocha_1.it)('compare against RPC data', function () {
            assert.deepStrictEqual((0, compare_1.normalizeRpcTransaction)(fixture.transaction, protocol.network), (0, compare_1.normalizeParsedTransaction)(parsedTx, protocol.network));
        });
        (0, mocha_1.it)(`parseSignatureScript`, function () {
            if (txType === 'deposit') {
                return;
            }
            parsedTx.ins.forEach((input, i) => {
                const result = (0, bitgo_1.parseSignatureScript)(input);
                assert.strict(result.publicKeys !== undefined);
                assert.strictEqual(result.publicKeys.length, scriptType === 'p2tr' ? 2 : 3);
            });
        });
        if (txType === 'deposit') {
            return;
        }
        (0, mocha_1.it)(`verifySignatures for original transaction`, function () {
            parsedTx.ins.forEach((input, i) => {
                const prevOutValue = getPrevOutputValue(input);
                const result = (0, bitgo_1.parseSignatureScript2Of3)(input);
                assert.ok(result.scriptType !== 'taprootKeyPathSpend');
                if (!result.publicKeys) {
                    throw new Error(`expected publicKeys`);
                }
                assert.strictEqual(result.publicKeys.length, scriptType === 'p2tr' ? 2 : 3);
                if (scriptType === 'p2tr') {
                    // TODO implement verifySignature for p2tr
                    this.skip();
                }
                result.publicKeys.forEach((publicKey, publicKeyIndex) => {
                    assert.strictEqual((0, bitgo_1.verifySignature)(parsedTx, i, prevOutValue, {
                        publicKey,
                    }), publicKeyIndex === 0 || publicKeyIndex === 2);
                });
                assert.strictEqual((0, bitgo_1.verifySignature)(parsedTx, i, prevOutValue), true);
            });
        });
        function getRebuiltTransaction(signKeys) {
            assert.strict(parsedTx.outs.length === 1);
            assert.strict((0, outputScripts_1.isScriptType2Of3)(scriptType));
            const recipientScript = parsedTx.outs[0].script;
            return (0, outputScripts_util_1.createSpendTransactionFromPrevOutputs)(fixtures_1.fixtureKeys, scriptType, getPrevOutputs(), recipientScript, protocol.network, { signKeys, version: protocol.version });
        }
        (0, mocha_1.it)(`verifySignatures with one or two signatures`, function () {
            fixtures_1.fixtureKeys.forEach((key1) => {
                const rebuiltTx = getRebuiltTransaction([key1]);
                const prevOutputs = rebuiltTx.ins.map((v) => ({
                    script: getPrevOutputScript(v),
                    value: getPrevOutputValue(v),
                }));
                rebuiltTx.ins.forEach((input, i) => {
                    assert.strict((0, bitgo_1.verifySignature)(rebuiltTx, i, getPrevOutputValue(input), {}, prevOutputs));
                });
                fixtures_1.fixtureKeys.forEach((key2) => {
                    if (key1 === key2) {
                        return;
                    }
                    if (scriptType === 'p2tr') {
                        const keypair = [fixtures_1.fixtureKeys[0], fixtures_1.fixtureKeys[2]];
                        if (!keypair.includes(key1) || !keypair.includes(key2)) {
                            return;
                        }
                    }
                    const rebuiltTx = getRebuiltTransaction([key1, key2]);
                    rebuiltTx.ins.forEach((input, i) => {
                        assert.strict((0, bitgo_1.verifySignature)(rebuiltTx, i, getPrevOutputValue(input), {}, prevOutputs));
                    });
                });
            });
        });
        (0, mocha_1.it)('createSpendTransaction match', function () {
            const rebuiltTx = getRebuiltTransaction();
            assert.strictEqual(rebuiltTx.toBuffer().toString('hex'), fixture.transaction.hex);
        });
    });
}
(0, mocha_1.describe)(`regtest fixtures`, function () {
    (0, src_1.getNetworkList)().forEach((network) => {
        if (!(0, src_1.isTestnet)(network)) {
            return;
        }
        const allVersions = (0, fixtures_1.getProtocolVersions)(network);
        (0, mocha_1.it)('tests default version', function () {
            // FIXME(BTC-1633): fix generating fixtures for version 455 NU6
            if (src_1.networks.zcashTest === network) {
                assert.strictEqual((0, bitgo_1.getDefaultTransactionVersion)(network), 455);
            }
            else {
                assert.strictEqual(allVersions.filter((v) => v === (0, bitgo_1.getDefaultTransactionVersion)(network)).length, 1);
            }
        });
        (0, fixtures_1.getProtocolVersions)(network).forEach((version) => {
            const isDefault = version === (0, bitgo_1.getDefaultTransactionVersion)(network);
            (0, mocha_1.describe)(`${(0, src_1.getNetworkName)(network)} fixtures (version=${version}, isDefault=${isDefault})`, function () {
                getScriptTypes().forEach((scriptType) => {
                    fixtureTxTypes.forEach((txType) => {
                        runTestParse({ network, version }, txType, scriptType, network === src_1.networks.dogecoinTest ? 'bigint' : 'number');
                    });
                });
            });
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90ZXN0L2ludGVncmF0aW9uX2xvY2FsX3JwYy9wYXJzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFpQztBQUNqQyxpQ0FBcUM7QUFHckMsbUNBQTBGO0FBQzFGLGlEQUF3RDtBQUV4RCwyQ0FjeUI7QUFDekIsaUVBQWlGO0FBRWpGLHNFQU11QztBQUN2QyxrREFNNkI7QUFDN0IsMERBQWdFO0FBQ2hFLHVDQUFnRjtBQUNoRiwwQ0FBaUQ7QUFFakQsTUFBTSxjQUFjLEdBQUcsQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFVLENBQUM7QUFHckQsU0FBUyxjQUFjO0lBQ3JCLDJFQUEyRTtJQUMzRSw2REFBNkQ7SUFDN0QsT0FBTyxnQ0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxLQUFLLFlBQVksQ0FBQyxDQUFDO0FBQ3pFLENBQUM7QUFFRCxTQUFTLFlBQVksQ0FDbkIsUUFBa0IsRUFDbEIsTUFBcUIsRUFDckIsVUFBc0IsRUFDdEIsVUFBK0I7SUFFL0IsSUFBSSxNQUFNLEtBQUssU0FBUyxJQUFJLENBQUMsSUFBQSwyQ0FBc0IsRUFBQyxRQUFRLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUM7UUFDbEYsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLE1BQU0sS0FBSyxPQUFPLElBQUksQ0FBQyxJQUFBLHlDQUFvQixFQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUM5RSxPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sV0FBVyxHQUFHLEdBQUcsTUFBTSxJQUFJLFVBQVUsT0FBTyxDQUFDO0lBQ25ELElBQUEsZ0JBQVEsRUFBQyxHQUFHLFdBQVcsZUFBZSxVQUFVLEVBQUUsRUFBRTtRQUNsRCxJQUFJLE9BQXFDLENBQUM7UUFDMUMsSUFBSSxRQUFnQixDQUFDO1FBQ3JC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QUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxJQUFBLG9DQUE0QixFQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3ZHLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUEsOEJBQW1CLEVBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDL0MsTUFBTSxTQUFTLEdBQUcsT0FBTyxLQUFLLElBQUEsb0NBQTRCLEVBQUMsT0FBTyxDQUFDLENBQUM7WUFDcEUsSUFBQSxnQkFBUSxFQUFDLEdBQUcsSUFBQSxvQkFBYyxFQUFDLE9BQU8sQ0FBQyxzQkFBc0IsT0FBTyxlQUFlLFNBQVMsR0FBRyxFQUFFO2dCQUMzRixjQUFjLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRTtvQkFDdEMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO3dCQUNoQyxZQUFZLENBQ1YsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQ3BCLE1BQU0sRUFDTixVQUFVLEVBQ1YsT0FBTyxLQUFLLGNBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUN4RCxDQUFDO29CQUNKLENBQUMsQ0FBQyxDQUFDO2dCQUNMLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IGRlc2NyaWJlLCBpdCB9IGZyb20gJ21vY2hhJztcbmltcG9ydCB7IEJJUDMySW50ZXJmYWNlIH0gZnJvbSAnYmlwMzInO1xuXG5pbXBvcnQgeyBpc1Rlc3RuZXQsIFR4T3V0cHV0LCBnZXROZXR3b3JrTGlzdCwgZ2V0TmV0d29ya05hbWUsIG5ldHdvcmtzIH0gZnJvbSAnLi4vLi4vc3JjJztcbmltcG9ydCB7IGdldERlZmF1bHRDb3NpZ25lciB9IGZyb20gJy4uLy4uL3NyYy90ZXN0dXRpbCc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVRyYW5zYWN0aW9uQnVpbGRlckZvck5ldHdvcmssXG4gIGNyZWF0ZVRyYW5zYWN0aW9uQnVpbGRlckZyb21UcmFuc2FjdGlvbixcbiAgY3JlYXRlVHJhbnNhY3Rpb25Gcm9tQnVmZmVyLFxuICBnZXREZWZhdWx0VHJhbnNhY3Rpb25WZXJzaW9uLFxuICBnZXRPdXRwdXRJZEZvcklucHV0LFxuICBQYXJzZWRTaWduYXR1cmVTY3JpcHRQMm1zLFxuICBwYXJzZVNpZ25hdHVyZVNjcmlwdCxcbiAgcGFyc2VTaWduYXR1cmVTY3JpcHQyT2YzLFxuICBzaWduSW5wdXQyT2YzLFxuICBUcmlwbGUsXG4gIFR4T3V0UG9pbnQsXG4gIFV0eG9UcmFuc2FjdGlvbixcbiAgdmVyaWZ5U2lnbmF0dXJlLFxufSBmcm9tICcuLi8uLi9zcmMvYml0Z28nO1xuaW1wb3J0IHsgaXNTY3JpcHRUeXBlMk9mMywgU2NyaXB0VHlwZTJPZjMgfSBmcm9tICcuLi8uLi9zcmMvYml0Z28vb3V0cHV0U2NyaXB0cyc7XG5cbmltcG9ydCB7XG4gIGNyZWF0ZVNwZW5kVHJhbnNhY3Rpb25Gcm9tUHJldk91dHB1dHMsXG4gIGlzU3VwcG9ydGVkRGVwb3NpdFR5cGUsXG4gIGlzU3VwcG9ydGVkU3BlbmRUeXBlLFxuICBTY3JpcHRUeXBlLFxuICBzY3JpcHRUeXBlcyxcbn0gZnJvbSAnLi9nZW5lcmF0ZS9vdXRwdXRTY3JpcHRzLnV0aWwnO1xuaW1wb3J0IHtcbiAgZml4dHVyZUtleXMsXG4gIGdldFByb3RvY29sVmVyc2lvbnMsXG4gIFByb3RvY29sLFxuICByZWFkRml4dHVyZSxcbiAgVHJhbnNhY3Rpb25GaXh0dXJlV2l0aElucHV0cyxcbn0gZnJvbSAnLi9nZW5lcmF0ZS9maXh0dXJlcyc7XG5pbXBvcnQgeyBwYXJzZVRyYW5zYWN0aW9uUm91bmRUcmlwIH0gZnJvbSAnLi4vdHJhbnNhY3Rpb25fdXRpbCc7XG5pbXBvcnQgeyBub3JtYWxpemVQYXJzZWRUcmFuc2FjdGlvbiwgbm9ybWFsaXplUnBjVHJhbnNhY3Rpb24gfSBmcm9tICcuL2NvbXBhcmUnO1xuaW1wb3J0IHsgZGVjaW1hbENvaW5zVG9TYXRzIH0gZnJvbSAnLi4vdGVzdHV0aWwnO1xuXG5jb25zdCBmaXh0dXJlVHhUeXBlcyA9IFsnZGVwb3NpdCcsICdzcGVuZCddIGFzIGNvbnN0O1xudHlwZSBGaXh0dXJlVHhUeXBlID0gKHR5cGVvZiBmaXh0dXJlVHhUeXBlcylbbnVtYmVyXTtcblxuZnVuY3Rpb24gZ2V0U2NyaXB0VHlwZXMoKSB7XG4gIC8vIEZJWE1FKEJHLTY2OTQxKTogcDJ0ck11c2lnMiBzaWduaW5nIGRvZXMgbm90IHdvcmsgaW4gdGhpcyB0ZXN0IHN1aXRlIHlldFxuICAvLyAgYmVjYXVzZSB0aGUgdGVzdCBzdWl0ZSBpcyB3cml0dGVuIHdpdGggVHJhbnNhY3Rpb25CdWlsZGVyXG4gIHJldHVybiBzY3JpcHRUeXBlcy5maWx0ZXIoKHNjcmlwdFR5cGUpID0+IHNjcmlwdFR5cGUgIT09ICdwMnRyTXVzaWcyJyk7XG59XG5cbmZ1bmN0aW9uIHJ1blRlc3RQYXJzZTxUTnVtYmVyIGV4dGVuZHMgbnVtYmVyIHwgYmlnaW50PihcbiAgcHJvdG9jb2w6IFByb3RvY29sLFxuICB0eFR5cGU6IEZpeHR1cmVUeFR5cGUsXG4gIHNjcmlwdFR5cGU6IFNjcmlwdFR5cGUsXG4gIGFtb3VudFR5cGU6ICdudW1iZXInIHwgJ2JpZ2ludCdcbikge1xuICBpZiAodHhUeXBlID09PSAnZGVwb3NpdCcgJiYgIWlzU3VwcG9ydGVkRGVwb3NpdFR5cGUocHJvdG9jb2wubmV0d29yaywgc2NyaXB0VHlwZSkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAodHhUeXBlID09PSAnc3BlbmQnICYmICFpc1N1cHBvcnRlZFNwZW5kVHlwZShwcm90b2NvbC5uZXR3b3JrLCBzY3JpcHRUeXBlKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGZpeHR1cmVOYW1lID0gYCR7dHhUeXBlfV8ke3NjcmlwdFR5cGV9Lmpzb25gO1xuICBkZXNjcmliZShgJHtmaXh0dXJlTmFtZX0gYW1vdW50VHlwZT0ke2Ftb3VudFR5cGV9YCwgZnVuY3Rpb24gKCkge1xuICAgIGxldCBmaXh0dXJlOiBUcmFuc2FjdGlvbkZpeHR1cmVXaXRoSW5wdXRzO1xuICAgIGxldCB0eEJ1ZmZlcjogQnVmZmVyO1xuICAgIGxldCBwYXJzZWRUeDogVXR4b1RyYW5zYWN0aW9uPFROdW1iZXI+O1xuXG4gICAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZpeHR1cmUgPSBhd2FpdCByZWFkRml4dHVyZShcbiAgICAgICAge1xuICAgICAgICAgIG5ldHdvcms6IHByb3RvY29sLm5ldHdvcmssXG4gICAgICAgICAgdmVyc2lvbjogcHJvdG9jb2wudmVyc2lvbiA/PyBnZXREZWZhdWx0VHJhbnNhY3Rpb25WZXJzaW9uKHByb3RvY29sLm5ldHdvcmspLFxuICAgICAgICB9LFxuICAgICAgICBmaXh0dXJlTmFtZVxuICAgICAgKTtcbiAgICAgIHR4QnVmZmVyID0gQnVmZmVyLmZyb20oZml4dHVyZS50cmFuc2FjdGlvbi5oZXgsICdoZXgnKTtcbiAgICAgIHBhcnNlZFR4ID0gY3JlYXRlVHJhbnNhY3Rpb25Gcm9tQnVmZmVyPFROdW1iZXI+KHR4QnVmZmVyLCBwcm90b2NvbC5uZXR3b3JrLCB7XG4gICAgICAgIHZlcnNpb246IHByb3RvY29sLnZlcnNpb24sXG4gICAgICAgIGFtb3VudFR5cGUsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHR5cGUgSW5wdXRMb29rdXAgPSB7IHR4aWQ/OiBzdHJpbmc7IGhhc2g/OiBCdWZmZXI7IGluZGV4OiBudW1iZXIgfTtcblxuICAgIGZ1bmN0aW9uIGdldFByZXZPdXRwdXQoaW5wdXQ6IElucHV0TG9va3VwKSB7XG4gICAgICBpZiAoaW5wdXQuaGFzaCkge1xuICAgICAgICBpbnB1dCA9IHtcbiAgICAgICAgICAuLi5pbnB1dCxcbiAgICAgICAgICAuLi5nZXRPdXRwdXRJZEZvcklucHV0KGlucHV0IGFzIHsgaGFzaDogQnVmZmVyOyBpbmRleDogbnVtYmVyIH0pLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBpbnB1dFR4ID0gZml4dHVyZS5pbnB1dHMuZmluZCgodHgpID0+IHR4LnR4aWQgPT09IGlucHV0LnR4aWQpO1xuICAgICAgaWYgKCFpbnB1dFR4KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgY291bGQgbm90IGZpbmQgaW5wdXRUeGApO1xuICAgICAgfVxuICAgICAgY29uc3QgcHJldk91dHB1dCA9IGlucHV0VHgudm91dFtpbnB1dC5pbmRleF07XG4gICAgICBpZiAoIXByZXZPdXRwdXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjb3VsZCBub3QgcHJldk91dHB1dGApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByZXZPdXRwdXQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0UHJldk91dHB1dFZhbHVlKGlucHV0OiBJbnB1dExvb2t1cCk6IFROdW1iZXIge1xuICAgICAgcmV0dXJuIGRlY2ltYWxDb2luc1RvU2F0czxUTnVtYmVyPihnZXRQcmV2T3V0cHV0KGlucHV0KS52YWx1ZSwgYW1vdW50VHlwZSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0UHJldk91dHB1dFNjcmlwdChpbnB1dDogSW5wdXRMb29rdXApOiBCdWZmZXIge1xuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGdldFByZXZPdXRwdXQoaW5wdXQpLnNjcmlwdFB1YktleS5oZXgsICdoZXgnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRQcmV2T3V0cHV0cygpOiAoVHhPdXRQb2ludCAmIFR4T3V0cHV0PFROdW1iZXI+KVtdIHtcbiAgICAgIHJldHVybiBwYXJzZWRUeC5pbnMubWFwKChpKSA9PiAoe1xuICAgICAgICAuLi5nZXRPdXRwdXRJZEZvcklucHV0KGkpLFxuICAgICAgICBzY3JpcHQ6IGdldFByZXZPdXRwdXRTY3JpcHQoaSksXG4gICAgICAgIHZhbHVlOiBnZXRQcmV2T3V0cHV0VmFsdWUoaSksXG4gICAgICAgIHByZXZUeDogdHhCdWZmZXIsXG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgaXQoYHJvdW5kLXRyaXBgLCBmdW5jdGlvbiAoKSB7XG4gICAgICBwYXJzZVRyYW5zYWN0aW9uUm91bmRUcmlwKEJ1ZmZlci5mcm9tKGZpeHR1cmUudHJhbnNhY3Rpb24uaGV4LCAnaGV4JyksIHByb3RvY29sLm5ldHdvcmssIHtcbiAgICAgICAgaW5wdXRzOiBnZXRQcmV2T3V0cHV0cygpLFxuICAgICAgICBhbW91bnRUeXBlLFxuICAgICAgICB2ZXJzaW9uOiBwcm90b2NvbC52ZXJzaW9uLFxuICAgICAgICAvLyBGSVhNRTogcHJldlR4IHBhcnNpbmcgZm9yIFpjYXNoIG5vdCB3b3JraW5nIHlldFxuICAgICAgICByb3VuZFRyaXBQc2J0OiB0eFR5cGUgPT09ICdzcGVuZCcgJiYgcHJvdG9jb2wubmV0d29yayAhPT0gbmV0d29ya3MuemNhc2hUZXN0LFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdChgcm91bmQtdHJpcCAoaGlnaC1wcmVjaXNpb24gdmFsdWVzKWAsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChhbW91bnRUeXBlICE9PSAnYmlnaW50Jykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCB0eCA9IGNyZWF0ZVRyYW5zYWN0aW9uRnJvbUJ1ZmZlcjxUTnVtYmVyPihCdWZmZXIuZnJvbShmaXh0dXJlLnRyYW5zYWN0aW9uLmhleCwgJ2hleCcpLCBwcm90b2NvbC5uZXR3b3JrLCB7XG4gICAgICAgIGFtb3VudFR5cGUsXG4gICAgICB9KTtcbiAgICAgIHR4Lm91dHMuZm9yRWFjaCgobykgPT4ge1xuICAgICAgICBvLnZhbHVlID0gKEJpZ0ludCgxZTE2KSArIEJpZ0ludCgxKSkgYXMgVE51bWJlcjtcbiAgICAgICAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKEJpZ0ludChOdW1iZXIoby52YWx1ZSkpLCBvLnZhbHVlKTtcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdHhSb3VuZFRyaXAgPSBwYXJzZVRyYW5zYWN0aW9uUm91bmRUcmlwKHR4LnRvQnVmZmVyKCksIHByb3RvY29sLm5ldHdvcmssIHsgYW1vdW50VHlwZSB9KTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0eFJvdW5kVHJpcC5vdXRzLmxlbmd0aCwgdHgub3V0cy5sZW5ndGgpO1xuICAgICAgdHhSb3VuZFRyaXAub3V0cy5mb3JFYWNoKChvLCBpKSA9PiB7XG4gICAgICAgIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwobywgdHgub3V0c1tpXSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KGByZWNyZWF0ZSBmcm9tIHVuc2lnbmVkIGhleGAsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmICh0eFR5cGUgPT09ICdkZXBvc2l0Jykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBjb25zdCB0eGJVbnNpZ25lZCA9IGNyZWF0ZVRyYW5zYWN0aW9uQnVpbGRlckZvck5ldHdvcms8VE51bWJlcj4ocHJvdG9jb2wubmV0d29yaywgeyB2ZXJzaW9uOiBwcm90b2NvbC52ZXJzaW9uIH0pO1xuICAgICAgZ2V0UHJldk91dHB1dHMoKS5mb3JFYWNoKChvKSA9PiB7XG4gICAgICAgIHR4YlVuc2lnbmVkLmFkZElucHV0KG8udHhpZCwgby52b3V0KTtcbiAgICAgIH0pO1xuICAgICAgZml4dHVyZS50cmFuc2FjdGlvbi52b3V0LmZvckVhY2goKG8pID0+IHtcbiAgICAgICAgdHhiVW5zaWduZWQuYWRkT3V0cHV0KEJ1ZmZlci5mcm9tKG8uc2NyaXB0UHViS2V5LmhleCwgJ2hleCcpLCBkZWNpbWFsQ29pbnNUb1NhdHM8VE51bWJlcj4oby52YWx1ZSwgYW1vdW50VHlwZSkpO1xuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHR4ID0gY3JlYXRlVHJhbnNhY3Rpb25Gcm9tQnVmZmVyPFROdW1iZXI+KHR4YlVuc2lnbmVkLmJ1aWxkSW5jb21wbGV0ZSgpLnRvQnVmZmVyKCksIHByb3RvY29sLm5ldHdvcmssIHtcbiAgICAgICAgdmVyc2lvbjogcHJvdG9jb2wudmVyc2lvbixcbiAgICAgICAgYW1vdW50VHlwZSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdHhiID0gY3JlYXRlVHJhbnNhY3Rpb25CdWlsZGVyRnJvbVRyYW5zYWN0aW9uKHR4LCBnZXRQcmV2T3V0cHV0cygpKTtcbiAgICAgIGNvbnN0IHNpZ25LZXlzID0gW2ZpeHR1cmVLZXlzWzBdLCBmaXh0dXJlS2V5c1syXV07XG4gICAgICBjb25zdCBwdWJsaWNLZXlzID0gZml4dHVyZUtleXMubWFwKChrKSA9PiBrLnB1YmxpY0tleSkgYXMgVHJpcGxlPEJ1ZmZlcj47XG4gICAgICBnZXRQcmV2T3V0cHV0cygpLmZvckVhY2goKHsgdmFsdWUgfSwgdmluKSA9PiB7XG4gICAgICAgIHNpZ25LZXlzLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgIHNpZ25JbnB1dDJPZjMoXG4gICAgICAgICAgICB0eGIsXG4gICAgICAgICAgICB2aW4sXG4gICAgICAgICAgICBzY3JpcHRUeXBlIGFzIFNjcmlwdFR5cGUyT2YzLFxuICAgICAgICAgICAgcHVibGljS2V5cyxcbiAgICAgICAgICAgIGtleSxcbiAgICAgICAgICAgIGdldERlZmF1bHRDb3NpZ25lcihwdWJsaWNLZXlzLCBrZXkucHVibGljS2V5KSxcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHR4Yi5idWlsZCgpLnZlcnNpb24sIHR4LnZlcnNpb24pO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHhiLmJ1aWxkKCkudG9CdWZmZXIoKS50b1N0cmluZygnaGV4JyksIGZpeHR1cmUudHJhbnNhY3Rpb24uaGV4KTtcbiAgICB9KTtcblxuICAgIGl0KCdjb21wYXJlIGFnYWluc3QgUlBDIGRhdGEnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBhc3NlcnQuZGVlcFN0cmljdEVxdWFsKFxuICAgICAgICBub3JtYWxpemVScGNUcmFuc2FjdGlvbihmaXh0dXJlLnRyYW5zYWN0aW9uLCBwcm90b2NvbC5uZXR3b3JrKSxcbiAgICAgICAgbm9ybWFsaXplUGFyc2VkVHJhbnNhY3Rpb24ocGFyc2VkVHgsIHByb3RvY29sLm5ldHdvcmspXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoYHBhcnNlU2lnbmF0dXJlU2NyaXB0YCwgZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKHR4VHlwZSA9PT0gJ2RlcG9zaXQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgcGFyc2VkVHguaW5zLmZvckVhY2goKGlucHV0LCBpKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlU2lnbmF0dXJlU2NyaXB0KGlucHV0KSBhcyBQYXJzZWRTaWduYXR1cmVTY3JpcHRQMm1zO1xuXG4gICAgICAgIGFzc2VydC5zdHJpY3QocmVzdWx0LnB1YmxpY0tleXMgIT09IHVuZGVmaW5lZCk7XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQucHVibGljS2V5cy5sZW5ndGgsIHNjcmlwdFR5cGUgPT09ICdwMnRyJyA/IDIgOiAzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaWYgKHR4VHlwZSA9PT0gJ2RlcG9zaXQnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaXQoYHZlcmlmeVNpZ25hdHVyZXMgZm9yIG9yaWdpbmFsIHRyYW5zYWN0aW9uYCwgZnVuY3Rpb24gKCkge1xuICAgICAgcGFyc2VkVHguaW5zLmZvckVhY2goKGlucHV0LCBpKSA9PiB7XG4gICAgICAgIGNvbnN0IHByZXZPdXRWYWx1ZSA9IGdldFByZXZPdXRwdXRWYWx1ZShpbnB1dCk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHBhcnNlU2lnbmF0dXJlU2NyaXB0Mk9mMyhpbnB1dCk7XG4gICAgICAgIGFzc2VydC5vayhyZXN1bHQuc2NyaXB0VHlwZSAhPT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnKTtcbiAgICAgICAgaWYgKCFyZXN1bHQucHVibGljS2V5cykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZXhwZWN0ZWQgcHVibGljS2V5c2ApO1xuICAgICAgICB9XG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChyZXN1bHQucHVibGljS2V5cy5sZW5ndGgsIHNjcmlwdFR5cGUgPT09ICdwMnRyJyA/IDIgOiAzKTtcblxuICAgICAgICBpZiAoc2NyaXB0VHlwZSA9PT0gJ3AydHInKSB7XG4gICAgICAgICAgLy8gVE9ETyBpbXBsZW1lbnQgdmVyaWZ5U2lnbmF0dXJlIGZvciBwMnRyXG4gICAgICAgICAgdGhpcy5za2lwKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXN1bHQucHVibGljS2V5cy5mb3JFYWNoKChwdWJsaWNLZXksIHB1YmxpY0tleUluZGV4KSA9PiB7XG4gICAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICAgICAgdmVyaWZ5U2lnbmF0dXJlKHBhcnNlZFR4LCBpLCBwcmV2T3V0VmFsdWUsIHtcbiAgICAgICAgICAgICAgcHVibGljS2V5LFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBwdWJsaWNLZXlJbmRleCA9PT0gMCB8fCBwdWJsaWNLZXlJbmRleCA9PT0gMlxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh2ZXJpZnlTaWduYXR1cmUocGFyc2VkVHgsIGksIHByZXZPdXRWYWx1ZSksIHRydWUpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBnZXRSZWJ1aWx0VHJhbnNhY3Rpb24oc2lnbktleXM/OiBCSVAzMkludGVyZmFjZVtdKSB7XG4gICAgICBhc3NlcnQuc3RyaWN0KHBhcnNlZFR4Lm91dHMubGVuZ3RoID09PSAxKTtcbiAgICAgIGFzc2VydC5zdHJpY3QoaXNTY3JpcHRUeXBlMk9mMyhzY3JpcHRUeXBlKSk7XG4gICAgICBjb25zdCByZWNpcGllbnRTY3JpcHQgPSBwYXJzZWRUeC5vdXRzWzBdLnNjcmlwdDtcbiAgICAgIHJldHVybiBjcmVhdGVTcGVuZFRyYW5zYWN0aW9uRnJvbVByZXZPdXRwdXRzKFxuICAgICAgICBmaXh0dXJlS2V5cyxcbiAgICAgICAgc2NyaXB0VHlwZSxcbiAgICAgICAgZ2V0UHJldk91dHB1dHMoKSxcbiAgICAgICAgcmVjaXBpZW50U2NyaXB0LFxuICAgICAgICBwcm90b2NvbC5uZXR3b3JrLFxuICAgICAgICB7IHNpZ25LZXlzLCB2ZXJzaW9uOiBwcm90b2NvbC52ZXJzaW9uIH1cbiAgICAgICk7XG4gICAgfVxuXG4gICAgaXQoYHZlcmlmeVNpZ25hdHVyZXMgd2l0aCBvbmUgb3IgdHdvIHNpZ25hdHVyZXNgLCBmdW5jdGlvbiAoKSB7XG4gICAgICBmaXh0dXJlS2V5cy5mb3JFYWNoKChrZXkxKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGdldFJlYnVpbHRUcmFuc2FjdGlvbihba2V5MV0pO1xuICAgICAgICBjb25zdCBwcmV2T3V0cHV0cyA9IHJlYnVpbHRUeC5pbnMubWFwKCh2KSA9PiAoe1xuICAgICAgICAgIHNjcmlwdDogZ2V0UHJldk91dHB1dFNjcmlwdCh2KSxcbiAgICAgICAgICB2YWx1ZTogZ2V0UHJldk91dHB1dFZhbHVlKHYpLFxuICAgICAgICB9KSk7XG4gICAgICAgIHJlYnVpbHRUeC5pbnMuZm9yRWFjaCgoaW5wdXQsIGkpID0+IHtcbiAgICAgICAgICBhc3NlcnQuc3RyaWN0KHZlcmlmeVNpZ25hdHVyZShyZWJ1aWx0VHgsIGksIGdldFByZXZPdXRwdXRWYWx1ZShpbnB1dCksIHt9LCBwcmV2T3V0cHV0cykpO1xuICAgICAgICB9KTtcblxuICAgICAgICBmaXh0dXJlS2V5cy5mb3JFYWNoKChrZXkyKSA9PiB7XG4gICAgICAgICAgaWYgKGtleTEgPT09IGtleTIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoc2NyaXB0VHlwZSA9PT0gJ3AydHInKSB7XG4gICAgICAgICAgICBjb25zdCBrZXlwYWlyID0gW2ZpeHR1cmVLZXlzWzBdLCBmaXh0dXJlS2V5c1syXV07XG4gICAgICAgICAgICBpZiAoIWtleXBhaXIuaW5jbHVkZXMoa2V5MSkgfHwgIWtleXBhaXIuaW5jbHVkZXMoa2V5MikpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGdldFJlYnVpbHRUcmFuc2FjdGlvbihba2V5MSwga2V5Ml0pO1xuICAgICAgICAgIHJlYnVpbHRUeC5pbnMuZm9yRWFjaCgoaW5wdXQsIGkpID0+IHtcbiAgICAgICAgICAgIGFzc2VydC5zdHJpY3QodmVyaWZ5U2lnbmF0dXJlKHJlYnVpbHRUeCwgaSwgZ2V0UHJldk91dHB1dFZhbHVlKGlucHV0KSwge30sIHByZXZPdXRwdXRzKSk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnY3JlYXRlU3BlbmRUcmFuc2FjdGlvbiBtYXRjaCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHJlYnVpbHRUeCA9IGdldFJlYnVpbHRUcmFuc2FjdGlvbigpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJlYnVpbHRUeC50b0J1ZmZlcigpLnRvU3RyaW5nKCdoZXgnKSwgZml4dHVyZS50cmFuc2FjdGlvbi5oZXgpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuZGVzY3JpYmUoYHJlZ3Rlc3QgZml4dHVyZXNgLCBmdW5jdGlvbiAoKSB7XG4gIGdldE5ldHdvcmtMaXN0KCkuZm9yRWFjaCgobmV0d29yaykgPT4ge1xuICAgIGlmICghaXNUZXN0bmV0KG5ldHdvcmspKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgYWxsVmVyc2lvbnMgPSBnZXRQcm90b2NvbFZlcnNpb25zKG5ldHdvcmspO1xuICAgIGl0KCd0ZXN0cyBkZWZhdWx0IHZlcnNpb24nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBGSVhNRShCVEMtMTYzMyk6IGZpeCBnZW5lcmF0aW5nIGZpeHR1cmVzIGZvciB2ZXJzaW9uIDQ1NSBOVTZcbiAgICAgIGlmIChuZXR3b3Jrcy56Y2FzaFRlc3QgPT09IG5ldHdvcmspIHtcbiAgICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGdldERlZmF1bHRUcmFuc2FjdGlvblZlcnNpb24obmV0d29yayksIDQ1NSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoYWxsVmVyc2lvbnMuZmlsdGVyKCh2KSA9PiB2ID09PSBnZXREZWZhdWx0VHJhbnNhY3Rpb25WZXJzaW9uKG5ldHdvcmspKS5sZW5ndGgsIDEpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgZ2V0UHJvdG9jb2xWZXJzaW9ucyhuZXR3b3JrKS5mb3JFYWNoKCh2ZXJzaW9uKSA9PiB7XG4gICAgICBjb25zdCBpc0RlZmF1bHQgPSB2ZXJzaW9uID09PSBnZXREZWZhdWx0VHJhbnNhY3Rpb25WZXJzaW9uKG5ldHdvcmspO1xuICAgICAgZGVzY3JpYmUoYCR7Z2V0TmV0d29ya05hbWUobmV0d29yayl9IGZpeHR1cmVzICh2ZXJzaW9uPSR7dmVyc2lvbn0sIGlzRGVmYXVsdD0ke2lzRGVmYXVsdH0pYCwgZnVuY3Rpb24gKCkge1xuICAgICAgICBnZXRTY3JpcHRUeXBlcygpLmZvckVhY2goKHNjcmlwdFR5cGUpID0+IHtcbiAgICAgICAgICBmaXh0dXJlVHhUeXBlcy5mb3JFYWNoKCh0eFR5cGUpID0+IHtcbiAgICAgICAgICAgIHJ1blRlc3RQYXJzZShcbiAgICAgICAgICAgICAgeyBuZXR3b3JrLCB2ZXJzaW9uIH0sXG4gICAgICAgICAgICAgIHR4VHlwZSxcbiAgICAgICAgICAgICAgc2NyaXB0VHlwZSxcbiAgICAgICAgICAgICAgbmV0d29yayA9PT0gbmV0d29ya3MuZG9nZWNvaW5UZXN0ID8gJ2JpZ2ludCcgOiAnbnVtYmVyJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==

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


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