PHP WebShell

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

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

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const ecpair_1 = require("ecpair");
const src_1 = require("../src");
const taproot_1 = require("../src/taproot");
const ECPair = (0, ecpair_1.ECPairFactory)(src_1.ecc);
describe('taproot utils', () => {
    describe('musig key aggregation', () => {
        // Expected values for the test cases assertions below are derived from the
        // MuSig2 implementation example code in secp256k1-zkp.
        // https://github.com/jonasnick/secp256k1-zkp/blob/musig2/src/modules/musig/example.c
        it('aggregates 2 pubkeys', () => {
            const aggregatePubkey = src_1.taproot.aggregateMuSigPubkeys(src_1.ecc, [
                Buffer.from('b2eea3c2431bdda9003b30e385f6a59a74fddb39f4aa927f95ad7a6c147c9f6c', 'hex'),
                Buffer.from('d37c98a14d3a749e45a15bcc6836552a7458632f5bc46dca197011e031d6014f', 'hex'),
            ]);
            assert.strictEqual(Buffer.from(aggregatePubkey).toString('hex'), '0ae195f849375eb836fa9f11dd8a44643f424e2671df6e63a2ad9becb853a9fe');
        });
        it('aggregates 3 unsorted pubkeys', () => {
            const aggregatePubkey = src_1.taproot.aggregateMuSigPubkeys(src_1.ecc, [
                Buffer.from('c03b14ebd188344d78ed45a0e4857fc65c7e25f50e0c0d84938220ef37da63d6', 'hex'),
                Buffer.from('8f3bb821cf276d78199fc26f5b7d912e30326a2d21f856ee1c653a896f4e5334', 'hex'),
                Buffer.from('95f6fd0d52f4be09a076a99b77e34dc005eec62bb7cec50ade968dd2f597fc52', 'hex'),
            ]);
            assert.strictEqual(Buffer.from(aggregatePubkey).toString('hex'), '349740502d79dd7a1253235da3b203de6e7717f487a8d1807e683bdfe7bd17ec');
        });
        it('throws an error if no keys are provided', () => {
            assert.throws(() => src_1.taproot.aggregateMuSigPubkeys(src_1.ecc, []));
        });
        it('throws an error if a single key is provided', () => {
            assert.throws(() => src_1.taproot.aggregateMuSigPubkeys(src_1.ecc, [ECPair.makeRandom().publicKey]));
        });
    });
    describe('taptree construction', () => {
        // Expected values for test case assertions below are derived from code and
        // examples provided by the Bitcoin Optech taproot workshop exercises:
        // https://github.com/bitcoinops/taproot-workshop
        const internalPubKey = Buffer.from('af455f4989d122e9185f8c351dbaecd13adca3eef8a9d38ef8ffed6867e342e3', 'hex');
        it('serializes script size', () => {
            const u8 = Buffer.allocUnsafe(0x01);
            const u16 = Buffer.allocUnsafe(0x0101);
            const u32 = Buffer.allocUnsafe(0x010101);
            const u8SerSize = src_1.taproot.serializeScriptSize(u8);
            const u16SerSize = src_1.taproot.serializeScriptSize(u16);
            const u32SerSize = src_1.taproot.serializeScriptSize(u32);
            assert.strictEqual(u8SerSize.toString('hex'), '01');
            assert.strictEqual(u16SerSize.toString('hex'), 'fd0101');
            assert.strictEqual(u32SerSize.toString('hex'), 'fe01010100');
        });
        it('hashes a tap leaf', () => {
            const pubkey = Buffer.from('3627a049c3dd937b1ef01432a54f2e31642be754764f5a677c174576fb02571e', 'hex');
            const script = Buffer.concat([
                new Uint8Array([32]), // push 32 byte pub key
                pubkey,
                new Uint8Array([0xac]), // OP_CHECKSIG
            ]);
            const tapLeafHash = src_1.taproot.hashTapLeaf(script);
            assert.strictEqual(tapLeafHash.toString('hex'), '17e20b19dc7e8093c4278d3bf42447a2334546f874ba1693c9d7bc4d81db15c4');
        });
        it('hashes a tap branch', () => {
            const child1 = Buffer.from('f248f2fee0977d141e19e0fddae1cfcdcede1a34a77ebc53c8fe96f346c7f7fc', 'hex');
            const child2 = Buffer.from('72e4cc6e974cae355cf72476edeff8e9a2877ad67cfa4f12bad6f178c6918b9c', 'hex');
            const tapBranchHash = src_1.taproot.hashTapBranch(child1, child2);
            assert.strictEqual(tapBranchHash.toString('hex'), '3009565ab85ceb87d3dfdedc469ec205b2ea139a148af1dcbcc1addf8f1b68a4');
        });
        it('taptweaks a pubkey', () => {
            const taptreeRoot = Buffer.from('dde870346c0f5f1f1c2341041520baa4e252723474c6969f432c2af98251ac01', 'hex');
            const taprootPubkey = src_1.taproot.tapTweakPubkey(src_1.ecc, internalPubKey, taptreeRoot);
            assert.strictEqual(Buffer.from(taprootPubkey.xOnlyPubkey).toString('hex'), 'b23960be1cb56ed0f9044ded73d758f466493cf9e2a6ce139a04fac8d630a601');
            const outputScript = (0, taproot_1.createTaprootOutputScript)({ internalPubKey, taptreeRoot });
            const outputKey = (0, taproot_1.getTaprootOutputKey)(outputScript);
            assert.ok(outputKey.equals(taprootPubkey.xOnlyPubkey));
        });
        it('builds a weighted taptree from scripts and tweaks a pubkey with it', () => {
            const scriptA = Buffer.from('2052b319d011c12225b8f9c63349e7b0e78118a1cb7e406fc70e3e08862b49d10aac', 'hex');
            const scriptB = Buffer.from('20622e61f750f10e597b18a3bb4e5dea88548508b8cb37bfc0fb7af20f7a417d6aac', 'hex');
            const scriptC = Buffer.from('2092a7d17376802e183fc49fb93d4c9b0a4d1cf845c005debbcc9cd57550a6f617ac', 'hex');
            const tapTree = src_1.taproot.getHuffmanTaptree([scriptA, scriptB, scriptC], [1, 1, 2]);
            const tapTreeRoot = tapTree.root;
            const taprootPubkey = src_1.taproot.tapTweakPubkey(src_1.ecc, internalPubKey, tapTreeRoot);
            assert.strictEqual(Buffer.from(taprootPubkey.xOnlyPubkey).toString('hex'), '4c537b89b6763b2c415dee24f75a4c80b48bea926361fbf7636cbf9025c46128');
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFwcm9vdC5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdGVzdC90YXByb290LnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxpQ0FBaUM7QUFDakMsbUNBQWtEO0FBQ2xELGdDQUFzQztBQUN0Qyw0Q0FBZ0Y7QUFFaEYsTUFBTSxNQUFNLEdBQWMsSUFBQSxzQkFBYSxFQUFDLFNBQUcsQ0FBQyxDQUFDO0FBRTdDLFFBQVEsQ0FBQyxlQUFlLEVBQUUsR0FBRyxFQUFFO0lBQzdCLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxHQUFHLEVBQUU7UUFDckMsMkVBQTJFO1FBQzNFLHVEQUF1RDtRQUN2RCxxRkFBcUY7UUFFckYsRUFBRSxDQUFDLHNCQUFzQixFQUFFLEdBQUcsRUFBRTtZQUM5QixNQUFNLGVBQWUsR0FBRyxhQUFPLENBQUMscUJBQXFCLENBQUMsU0FBRyxFQUFFO2dCQUN6RCxNQUFNLENBQUMsSUFBSSxDQUFDLGtFQUFrRSxFQUFFLEtBQUssQ0FBQztnQkFDdEYsTUFBTSxDQUFDLElBQUksQ0FBQyxrRUFBa0UsRUFBRSxLQUFLLENBQUM7YUFDdkYsQ0FBQyxDQUFDO1lBRUgsTUFBTSxDQUFDLFdBQVcsQ0FDaEIsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQzVDLGtFQUFrRSxDQUNuRSxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsK0JBQStCLEVBQUUsR0FBRyxFQUFFO1lBQ3ZDLE1BQU0sZUFBZSxHQUFHLGFBQU8sQ0FBQyxxQkFBcUIsQ0FBQyxTQUFHLEVBQUU7Z0JBQ3pELE1BQU0sQ0FBQyxJQUFJLENBQUMsa0VBQWtFLEVBQUUsS0FBSyxDQUFDO2dCQUN0RixNQUFNLENBQUMsSUFBSSxDQUFDLGtFQUFrRSxFQUFFLEtBQUssQ0FBQztnQkFDdEYsTUFBTSxDQUFDLElBQUksQ0FBQyxrRUFBa0UsRUFBRSxLQUFLLENB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QUFDLElBQUksQ0FBQyxzRUFBc0UsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUMzRyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLHNFQUFzRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBRTNHLE1BQU0sT0FBTyxHQUFHLGFBQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbEYsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztZQUVqQyxNQUFNLGFBQWEsR0FBRyxhQUFPLENBQUMsY0FBYyxDQUFDLFNBQUcsRUFBRSxjQUFjLEVBQUUsV0FBVyxDQUFDLENBQUM7WUFFL0UsTUFBTSxDQUFDLFdBQVcsQ0FDaEIsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUN0RCxrRUFBa0UsQ0FDbkUsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgRUNQYWlyQVBJLCBFQ1BhaXJGYWN0b3J5IH0gZnJvbSAnZWNwYWlyJztcbmltcG9ydCB7IGVjYywgdGFwcm9vdCB9IGZyb20gJy4uL3NyYyc7XG5pbXBvcnQgeyBjcmVhdGVUYXByb290T3V0cHV0U2NyaXB0LCBnZXRUYXByb290T3V0cHV0S2V5IH0gZnJvbSAnLi4vc3JjL3RhcHJvb3QnO1xuXG5jb25zdCBFQ1BhaXI6IEVDUGFpckFQSSA9IEVDUGFpckZhY3RvcnkoZWNjKTtcblxuZGVzY3JpYmUoJ3RhcHJvb3QgdXRpbHMnLCAoKSA9PiB7XG4gIGRlc2NyaWJlKCdtdXNpZyBrZXkgYWdncmVnYXRpb24nLCAoKSA9PiB7XG4gICAgLy8gRXhwZWN0ZWQgdmFsdWVzIGZvciB0aGUgdGVzdCBjYXNlcyBhc3NlcnRpb25zIGJlbG93IGFyZSBkZXJpdmVkIGZyb20gdGhlXG4gICAgLy8gTXVTaWcyIGltcGxlbWVudGF0aW9uIGV4YW1wbGUgY29kZSBpbiBzZWNwMjU2azEtemtwLlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qb25hc25pY2svc2VjcDI1NmsxLXprcC9ibG9iL211c2lnMi9zcmMvbW9kdWxlcy9tdXNpZy9leGFtcGxlLmNcblxuICAgIGl0KCdhZ2dyZWdhdGVzIDIgcHVia2V5cycsICgpID0+IHtcbiAgICAgIGNvbnN0IGFnZ3JlZ2F0ZVB1YmtleSA9IHRhcHJvb3QuYWdncmVnYXRlTXVTaWdQdWJrZXlzKGVjYywgW1xuICAgICAgICBCdWZmZXIuZnJvbSgnYjJlZWEzYzI0MzFiZGRhOTAwM2IzMGUzODVmNmE1OWE3NGZkZGIzOWY0YWE5MjdmOTVhZDdhNmMxNDdjOWY2YycsICdoZXgnKSxcbiAgICAgICAgQnVmZmVyLmZyb20oJ2QzN2M5OGExNGQzYTc0OWU0NWExNWJjYzY4MzY1NTJhNzQ1ODYzMmY1YmM0NmRjYTE5NzAxMWUwMzFkNjAxNGYnLCAnaGV4JyksXG4gICAgICBdKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICBCdWZmZXIuZnJvbShhZ2dyZWdhdGVQdWJrZXkpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgJzBhZTE5NWY4NDkzNzVlYjgzNmZhOWYxMWRkOGE0NDY0M2Y0MjRlMjY3MWRmNmU2M2EyYWQ5YmVjYjg1M2E5ZmUnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ2FnZ3JlZ2F0ZXMgMyB1bnNvcnRlZCBwdWJrZXlzJywgKCkgPT4ge1xuICAgICAgY29uc3QgYWdncmVnYXRlUHVia2V5ID0gdGFwcm9vdC5hZ2dyZWdhdGVNdVNpZ1B1YmtleXMoZWNjLCBbXG4gICAgICAgIEJ1ZmZlci5mcm9tKCdjMDNiMTRlYmQxODgzNDRkNzhlZDQ1YTBlNDg1N2ZjNjVjN2UyNWY1MGUwYzBkODQ5MzgyMjBlZjM3ZGE2M2Q2JywgJ2hleCcpLFxuICAgICAgICBCdWZmZXIuZnJvbSgnOGYzYmI4MjFjZjI3NmQ3ODE5OWZjMjZmNWI3ZDkxMmUzMDMyNmEyZDIxZjg1NmVlMWM2NTNhODk2ZjRlNTMzNCcsICdoZXgnKSxcbiAgICAgICAgQnVmZmVyLmZyb20oJzk1ZjZmZDBkNTJmNGJlMDlhMDc2YTk5Yjc3ZTM0ZGMwMDVlZWM2MmJiN2NlYzUwYWRlOTY4ZGQyZjU5N2ZjNTInLCAnaGV4JyksXG4gICAgICBdKTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICBCdWZmZXIuZnJvbShhZ2dyZWdhdGVQdWJrZXkpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgJzM0OTc0MDUwMmQ3OWRkN2ExMjUzMjM1ZGEzYjIwM2RlNmU3NzE3ZjQ4N2E4ZDE4MDdlNjgzYmRmZTdiZDE3ZWMnXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyBhbiBlcnJvciBpZiBubyBrZXlzIGFyZSBwcm92aWRlZCcsICgpID0+IHtcbiAgICAgIGFzc2VydC50aHJvd3MoKCkgPT4gdGFwcm9vdC5hZ2dyZWdhdGVNdVNpZ1B1YmtleXMoZWNjLCBbXSkpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Rocm93cyBhbiBlcnJvciBpZiBhIHNpbmdsZSBrZXkgaXMgcHJvdmlkZWQnLCAoKSA9PiB7XG4gICAgICBhc3NlcnQudGhyb3dzKCgpID0+IHRhcHJvb3QuYWdncmVnYXRlTXVTaWdQdWJrZXlzKGVjYywgW0VDUGFpci5tYWtlUmFuZG9tKCkucHVibGljS2V5XSkpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgndGFwdHJlZSBjb25zdHJ1Y3Rpb24nLCAoKSA9PiB7XG4gICAgLy8gRXhwZWN0ZWQgdmFsdWVzIGZvciB0ZXN0IGNhc2UgYXNzZXJ0aW9ucyBiZWxvdyBhcmUgZGVyaXZlZCBmcm9tIGNvZGUgYW5kXG4gICAgLy8gZXhhbXBsZXMgcHJvdmlkZWQgYnkgdGhlIEJpdGNvaW4gT3B0ZWNoIHRhcHJvb3Qgd29ya3Nob3AgZXhlcmNpc2VzOlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9iaXRjb2lub3BzL3RhcHJvb3Qtd29ya3Nob3BcblxuICAgIGNvbnN0IGludGVybmFsUHViS2V5ID0gQnVmZmVyLmZyb20oJ2FmNDU1ZjQ5ODlkMTIyZTkxODVmOGMzNTFkYmFlY2QxM2FkY2EzZWVmOGE5ZDM4ZWY4ZmZlZDY4NjdlMzQyZTMnLCAnaGV4Jyk7XG5cbiAgICBpdCgnc2VyaWFsaXplcyBzY3JpcHQgc2l6ZScsICgpID0+IHtcbiAgICAgIGNvbnN0IHU4ID0gQnVmZmVyLmFsbG9jVW5zYWZlKDB4MDEpO1xuICAgICAgY29uc3QgdTE2ID0gQnVmZmVyLmFsbG9jVW5zYWZlKDB4MDEwMSk7XG4gICAgICBjb25zdCB1MzIgPSBCdWZmZXIuYWxsb2NVbnNhZmUoMHgwMTAxMDEpO1xuXG4gICAgICBjb25zdCB1OFNlclNpemUgPSB0YXByb290LnNlcmlhbGl6ZVNjcmlwdFNpemUodTgpO1xuICAgICAgY29uc3QgdTE2U2VyU2l6ZSA9IHRhcHJvb3Quc2VyaWFsaXplU2NyaXB0U2l6ZSh1MTYpO1xuICAgICAgY29uc3QgdTMyU2VyU2l6ZSA9IHRhcHJvb3Quc2VyaWFsaXplU2NyaXB0U2l6ZSh1MzIpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodThTZXJTaXplLnRvU3RyaW5nKCdoZXgnKSwgJzAxJyk7XG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodTE2U2VyU2l6ZS50b1N0cmluZygnaGV4JyksICdmZDAxMDEnKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1MzJTZXJTaXplLnRvU3RyaW5nKCdoZXgnKSwgJ2ZlMDEwMTAxMDAnKTtcbiAgICB9KTtcblxuICAgIGl0KCdoYXNoZXMgYSB0YXAgbGVhZicsICgpID0+IHtcbiAgICAgIGNvbnN0IHB1YmtleSA9IEJ1ZmZlci5mcm9tKCczNjI3YTA0OWMzZGQ5MzdiMWVmMDE0MzJhNTRmMmUzMTY0MmJlNzU0NzY0ZjVhNjc3YzE3NDU3NmZiMDI1NzFlJywgJ2hleCcpO1xuXG4gICAgICBjb25zdCBzY3JpcHQgPSBCdWZmZXIuY29uY2F0KFtcbiAgICAgICAgbmV3IFVpbnQ4QXJyYXkoWzMyXSksIC8vIHB1c2ggMzIgYnl0ZSBwdWIga2V5XG4gICAgICAgIHB1YmtleSxcbiAgICAgICAgbmV3IFVpbnQ4QXJyYXkoWzB4YWNdKSwgLy8gT1BfQ0hFQ0tTSUdcbiAgICAgIF0pO1xuXG4gICAgICBjb25zdCB0YXBMZWFmSGFzaCA9IHRhcHJvb3QuaGFzaFRhcExlYWYoc2NyaXB0KTtcblxuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKFxuICAgICAgICB0YXBMZWFmSGFzaC50b1N0cmluZygnaGV4JyksXG4gICAgICAgICcxN2UyMGIxOWRjN2U4MDkzYzQyNzhkM2JmNDI0NDdhMjMzNDU0NmY4NzRiYTE2OTNjOWQ3YmM0ZDgxZGIxNWM0J1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdoYXNoZXMgYSB0YXAgYnJhbmNoJywgKCkgPT4ge1xuICAgICAgY29uc3QgY2hpbGQxID0gQnVmZmVyLmZyb20oJ2YyNDhmMmZlZTA5NzdkMTQxZTE5ZTBmZGRhZTFjZmNkY2VkZTFhMzRhNzdlYmM1M2M4ZmU5NmYzNDZjN2Y3ZmMnLCAnaGV4Jyk7XG4gICAgICBjb25zdCBjaGlsZDIgPSBCdWZmZXIuZnJvbSgnNzJlNGNjNmU5NzRjYWUzNTVjZjcyNDc2ZWRlZmY4ZTlhMjg3N2FkNjdjZmE0ZjEyYmFkNmYxNzhjNjkxOGI5YycsICdoZXgnKTtcblxuICAgICAgY29uc3QgdGFwQnJhbmNoSGFzaCA9IHRhcHJvb3QuaGFzaFRhcEJyYW5jaChjaGlsZDEsIGNoaWxkMik7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgdGFwQnJhbmNoSGFzaC50b1N0cmluZygnaGV4JyksXG4gICAgICAgICczMDA5NTY1YWI4NWNlYjg3ZDNkZmRlZGM0NjllYzIwNWIyZWExMzlhMTQ4YWYxZGNiY2MxYWRkZjhmMWI2OGE0J1xuICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCd0YXB0d2Vha3MgYSBwdWJrZXknLCAoKSA9PiB7XG4gICAgICBjb25zdCB0YXB0cmVlUm9vdCA9IEJ1ZmZlci5mcm9tKCdkZGU4NzAzNDZjMGY1ZjFmMWMyMzQxMDQxNTIwYmFhNGUyNTI3MjM0NzRjNjk2OWY0MzJjMmFmOTgyNTFhYzAxJywgJ2hleCcpO1xuXG4gICAgICBjb25zdCB0YXByb290UHVia2V5ID0gdGFwcm9vdC50YXBUd2Vha1B1YmtleShlY2MsIGludGVybmFsUHViS2V5LCB0YXB0cmVlUm9vdCk7XG5cbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChcbiAgICAgICAgQnVmZmVyLmZyb20odGFwcm9vdFB1YmtleS54T25seVB1YmtleSkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICAnYjIzOTYwYmUxY2I1NmVkMGY5MDQ0ZGVkNzNkNzU4ZjQ2NjQ5M2NmOWUyYTZjZTEzOWEwNGZhYzhkNjMwYTYwMSdcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IG91dHB1dFNjcmlwdCA9IGNyZWF0ZVRhcHJvb3RPdXRwdXRTY3JpcHQoeyBpbnRlcm5hbFB1YktleSwgdGFwdHJlZVJvb3QgfSk7XG4gICAgICBjb25zdCBvdXRwdXRLZXkgPSBnZXRUYXByb290T3V0cHV0S2V5KG91dHB1dFNjcmlwdCk7XG4gICAgICBhc3NlcnQub2sob3V0cHV0S2V5LmVxdWFscyh0YXByb290UHVia2V5LnhPbmx5UHVia2V5KSk7XG4gICAgfSk7XG5cbiAgICBpdCgnYnVpbGRzIGEgd2VpZ2h0ZWQgdGFwdHJlZSBmcm9tIHNjcmlwdHMgYW5kIHR3ZWFrcyBhIHB1YmtleSB3aXRoIGl0JywgKCkgPT4ge1xuICAgICAgY29uc3Qgc2NyaXB0QSA9IEJ1ZmZlci5mcm9tKCcyMDUyYjMxOWQwMTFjMTIyMjViOGY5YzYzMzQ5ZTdiMGU3ODExOGExY2I3ZTQwNmZjNzBlM2UwODg2MmI0OWQxMGFhYycsICdoZXgnKTtcbiAgICAgIGNvbnN0IHNjcmlwdEIgPSBCdWZmZXIuZnJvbSgnMjA2MjJlNjFmNzUwZjEwZTU5N2IxOGEzYmI0ZTVkZWE4ODU0ODUwOGI4Y2IzN2JmYzBmYjdhZjIwZjdhNDE3ZDZhYWMnLCAnaGV4Jyk7XG4gICAgICBjb25zdCBzY3JpcHRDID0gQnVmZmVyLmZyb20oJzIwOTJhN2QxNzM3NjgwMmUxODNmYzQ5ZmI5M2Q0YzliMGE0ZDFjZjg0NWMwMDVkZWJiY2M5Y2Q1NzU1MGE2ZjYxN2FjJywgJ2hleCcpO1xuXG4gICAgICBjb25zdCB0YXBUcmVlID0gdGFwcm9vdC5nZXRIdWZmbWFuVGFwdHJlZShbc2NyaXB0QSwgc2NyaXB0Qiwgc2NyaXB0Q10sIFsxLCAxLCAyXSk7XG4gICAgICBjb25zdCB0YXBUcmVlUm9vdCA9IHRhcFRyZWUucm9vdDtcblxuICAgICAgY29uc3QgdGFwcm9vdFB1YmtleSA9IHRhcHJvb3QudGFwVHdlYWtQdWJrZXkoZWNjLCBpbnRlcm5hbFB1YktleSwgdGFwVHJlZVJvb3QpO1xuXG4gICAgICBhc3NlcnQuc3RyaWN0RXF1YWwoXG4gICAgICAgIEJ1ZmZlci5mcm9tKHRhcHJvb3RQdWJrZXkueE9ubHlQdWJrZXkpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgJzRjNTM3Yjg5YjY3NjNiMmM0MTVkZWUyNGY3NWE0YzgwYjQ4YmVhOTI2MzYxZmJmNzYzNmNiZjkwMjVjNDYxMjgnXG4gICAgICApO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuIl19

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


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