PHP WebShell

Текущая директория: /opt/BitGoJS/modules/sdk-core/dist/src/account-lib/mpc/tss/eddsa

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

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
 * Module provides functions for MPC using threshold signature scheme (TSS). It contains
 * functions for key generation and message signing with EdDSA.
 *
 *
 * ======================
 * EdDSA Key Generation
 * ======================
 * 1. Each signer generates their own key share, which involves a private u-share and a public y-share.
 * 2. Signers distribute their y-share to other signers.
 * 3. After exchanging y-shares the next phase is to combine key shares. Each signer combines their u-share
 *    with the y-shares received from other signers in order to generate a p-share for themselves. We
 *    also save j-shares for other signers.
 * 4. At this point the players do not distribute any shares and the first phase of the
 *    signing protocol is complete.
 *
 * ======================
 * EdDSA Signing
 * ======================
 * 1. The parties from key generation decide they want to sign something. They begin the signing protocol
 *    by generating shares of an ephemeral key.
 *
 *    a) Each signer uses his p-share and the j-shares stored for other players to generate his signing share.
 *    b) This results in each signer having a private x-share and public r-shares.
 *
 * 2. Signers distribute their r-shares to other signers.
 * 3. After exchanging r-shares, each signer signs their share of the ephemeral key using their private
 *    x-share with the r-shares from other signers.
 * 4. This results in each signer having a public g-share which they send to the other signers.
 * 5. After the signers broadcast their g-shares, the final signature can be re-constructed independently.
 */
const crypto_1 = require("crypto");
const curves_1 = require("../../curves");
const shamir_1 = __importDefault(require("../../shamir"));
const util_1 = require("../../util");
const assert_1 = __importDefault(require("assert"));
// 2^256
const base = BigInt('0x010000000000000000000000000000000000000000000000000000000000000000');
class Eddsa {
    static async initialize(hdTree) {
        if (!Eddsa.initialized) {
            await curves_1.Ed25519Curve.initialize();
            Eddsa.initialized = true;
        }
        return new Eddsa(hdTree);
    }
    constructor(hdTree) {
        this.hdTree = hdTree;
    }
    keyShare(index, threshold, numShares, seed) {
        if (!(index > 0 && index <= numShares)) {
            throw new Error('Invalid KeyShare config');
        }
        if (seed && seed.length !== 64) {
            throw new Error('Seed must have length 64');
        }
        const seedchain = seed ?? (0, crypto_1.randomBytes)(64);
        const actualSeed = seedchain.slice(0, 32);
        const chaincode = seedchain.slice(32);
        const h = (0, crypto_1.createHash)('sha512').update(actualSeed).digest();
        const u = (0, util_1.clamp)((0, util_1.bigIntFromBufferLE)(h.slice(0, 32)));
        const y = Eddsa.curve.basePointMult(u);
        const { shares: split_u, v } = Eddsa.shamir.split(u, threshold, numShares);
        const P_i = {
            i: index,
            t: threshold,
            n: numShares,
            y: (0, util_1.bigIntToBufferLE)(y, 32).toString('hex'),
            seed: actualSeed.toString('hex'),
            chaincode: chaincode.toString('hex'),
        };
        const shares = {
            uShare: P_i,
            yShares: {},
        };
        for (const ind in split_u) {
            const i = parseInt(ind, 10);
            if (i === index) {
                continue;
            }
            shares.yShares[i] = {
                i,
                j: P_i.i,
                y: (0, util_1.bigIntToBufferLE)(y, 32).toString('hex'),
                v: (0, util_1.bigIntToBufferLE)(v[0], 32).toString('hex'),
                u: (0, util_1.bigIntToBufferLE)(split_u[ind], 32).toString('hex'),
                chaincode: chaincode.toString('hex'),
            };
        }
        return shares;
    }
    keyCombine(uShare, yShares) {
        const h = (0, crypto_1.createHash)('sha512').update(Buffer.from(uShare.seed, 'hex')).digest();
        const u = (0, util_1.clamp)((0, util_1.bigIntFromBufferLE)(h.slice(0, 32)));
        const yValues = [uShare, ...yShares].map((share) => (0, util_1.bigIntFromBufferLE)(Buffer.from(share.y, 'hex')));
        const y = yValues.reduce((partial, share) => Eddsa.curve.pointAdd(partial, share));
        const chaincodes = [uShare, ...yShares].map(({ chaincode }) => (0, util_1.bigIntFromBufferBE)(Buffer.from(chaincode, 'hex')));
        const chaincode = chaincodes.reduce((acc, chaincode) => (acc + chaincode) % base);
        // Verify shares.
        for (const share of yShares) {
            if ('v' in share) {
                try {
                    Eddsa.shamir.verify((0, util_1.bigIntFromBufferLE)(Buffer.from(share.u, 'hex')), [(0, util_1.bigIntFromBufferLE)(Buffer.from(share.y, 'hex')), (0, util_1.bigIntFromBufferLE)(Buffer.from(share.v, 'hex'))], uShare.i);
                }
                catch (err) {
                    throw new Error(`Could not verify share from participant ${share.j}. Verification error: ${err}`);
                }
            }
        }
        const P_i = {
            i: uShare.i,
            t: uShare.t,
            n: uShare.n,
            y: (0, util_1.bigIntToBufferLE)(y, 32).toString('hex'),
            u: (0, util_1.bigIntToBufferLE)(u, 32).toString('hex'),
            prefix: h.slice(32).toString('hex'),
            chaincode: (0, util_1.bigIntToBufferBE)(chaincode, 32).toString('hex'),
        };
        const players = {
            pShare: P_i,
            jShares: {},
        };
        for (let ind = 0; ind < yShares.length; ind++) {
            const P_j = yShares[ind];
            players.jShares[P_j.j] = {
                i: P_j.j,
                j: P_i.i,
            };
        }
        return players;
    }
    /**
     * Derives a child common keychain from common keychain
     *
     * @param commonKeychain - common keychain as a hex string
     * @param path - bip32 path
     * @return {string} derived common keychain as a hex string
     */
    deriveUnhardened(commonKeychain, path) {
        if (this.hdTree === undefined) {
            throw new Error("Can't derive key without HDTree implementation");
        }
        const keychain = Buffer.from(commonKeychain, 'hex');
        const derivedPublicKeychain = this.hdTree.publicDerive({
            pk: (0, util_1.bigIntFromBufferLE)(keychain.slice(0, 32)),
            chaincode: (0, util_1.bigIntFromBufferBE)(keychain.slice(32)),
        }, path);
        const derivedPk = (0, util_1.bigIntToBufferLE)(derivedPublicKeychain.pk, 32).toString('hex');
        const derivedChaincode = (0, util_1.bigIntToBufferBE)(derivedPublicKeychain.chaincode, 32).toString('hex');
        return derivedPk + derivedChaincode;
    }
    keyDerive(uShare, yShares, path) {
        if (this.hdTree === undefined) {
            throw new Error("Can't derive key without HDTree implementation");
        }
        const h = (0, crypto_1.createHash)('sha512').update(Buffer.from(uShare.seed, 'hex')).digest();
        const yValues = [uShare, ...yShares].map((share) => (0, util_1.bigIntFromBufferLE)(Buffer.from(share.y, 'hex')));
        const y = yValues.reduce((partial, share) => Eddsa.curve.pointAdd(partial, share));
        const u = (0, util_1.clamp)((0, util_1.bigIntFromBufferLE)(h.slice(0, 32)));
        const prefix = (0, util_1.bigIntFromBufferBE)(h.slice(32));
        let contribChaincode = (0, util_1.bigIntFromBufferBE)(Buffer.from(uShare.chaincode, 'hex'));
        const chaincodes = [
            contribChaincode,
            ...yShares.map(({ chaincode }) => (0, util_1.bigIntFromBufferBE)(Buffer.from(chaincode, 'hex'))),
        ];
        const chaincode = chaincodes.reduce((acc, chaincode) => (acc + chaincode) % base);
        // Derive subkey.
        const subkey = this.hdTree.privateDerive({ pk: y, sk: u, prefix, chaincode }, path);
        // Calculate new public key contribution.
        const contribY = Eddsa.curve.basePointMult(subkey.sk);
        // Calculate new chaincode contribution.
        const chaincodeDelta = (base + subkey.chaincode - chaincode) % base;
        contribChaincode = (contribChaincode + chaincodeDelta) % base;
        // Calculate new u values.
        const { shares: split_u, v } = Eddsa.shamir.split(subkey.sk, uShare.t, uShare.n);
        const P_i = {
            i: uShare.i,
            t: uShare.t,
            n: uShare.n,
            y: (0, util_1.bigIntToBufferLE)(subkey.pk, 32).toString('hex'),
            u: (0, util_1.bigIntToBufferLE)(subkey.sk, 32).toString('hex'),
            prefix: (0, util_1.bigIntToBufferBE)(subkey.prefix, 32).toString('hex'),
            chaincode: (0, util_1.bigIntToBufferBE)(subkey.chaincode, 32).toString('hex'),
        };
        const shares = {
            pShare: P_i,
            yShares: {},
        };
        for (let ind = 0; ind < yShares.length; ind++) {
            const P_j = yShares[ind];
            shares.yShares[P_j.j] = {
                i: P_j.j,
                j: P_i.i,
                y: (0, util_1.bigIntToBufferLE)(contribY, 32).toString('hex'),
                v: (0, util_1.bigIntToBufferLE)(v[0], 32).toString('hex'),
                u: (0, util_1.bigIntToBufferLE)(split_u[P_j.j], 32).toString('hex'),
                chaincode: (0, util_1.bigIntToBufferBE)(contribChaincode, 32).toString('hex'),
            };
        }
        return shares;
    }
    signShare(message, pShare, jShares, seed) {
        if (seed && seed.length !== 64) {
            throw new Error('Seed must have length 64');
        }
        const indices = [pShare, ...jShares].map(({ i }) => i);
        const { shares: split_u, v } = Eddsa.shamir.split((0, util_1.bigIntFromBufferLE)(Buffer.from(pShare.u, 'hex')), pShare.t, pShare.n);
        // Generate nonce contribution.
        const prefix = Buffer.from(pShare.prefix, 'hex');
        const randomBuffer = seed ?? (0, crypto_1.randomBytes)(64);
        const digest = (0, crypto_1.createHash)('sha512')
            .update(Buffer.concat([prefix, message, randomBuffer]))
            .digest();
        const r = Eddsa.curve.scalarReduce((0, util_1.bigIntFromBufferLE)(digest));
        const R = Eddsa.curve.basePointMult(r);
        const { shares: split_r } = Eddsa.shamir.split(r, indices.length, indices.length, indices);
        const P_i = {
            i: pShare.i,
            y: pShare.y,
            u: (0, util_1.bigIntToBufferLE)(split_u[pShare.i], 32).toString('hex'),
            r: (0, util_1.bigIntToBufferLE)(split_r[pShare.i], 32).toString('hex'),
            R: (0, util_1.bigIntToBufferLE)(R, 32).toString('hex'),
        };
        const resultShares = {
            xShare: P_i,
            rShares: {},
        };
        for (let ind = 0; ind < jShares.length; ind++) {
            const S_j = jShares[ind];
            resultShares.rShares[S_j.i] = {
                i: S_j.i,
                j: pShare.i,
                u: (0, util_1.bigIntToBufferLE)(split_u[S_j.i], 32).toString('hex'),
                v: (0, util_1.bigIntToBufferLE)(v[0], 32).toString('hex'),
                r: (0, util_1.bigIntToBufferLE)(split_r[S_j.i], 32).toString('hex'),
                R: (0, util_1.bigIntToBufferLE)(R, 32).toString('hex'),
                commitment: (0, util_1.bigIntToBufferLE)(Eddsa.curve.basePointMult(split_r[S_j.i]), 32).toString('hex'),
            };
        }
        return resultShares;
    }
    sign(message, playerShare, rShares, yShares = []) {
        for (const rShare of rShares) {
            this.validateCommitment(rShare);
        }
        const S_i = playerShare;
        const uValues = [playerShare, ...rShares, ...yShares].map(({ u }) => (0, util_1.bigIntFromBufferLE)(Buffer.from(u, 'hex')));
        const x = uValues.reduce((acc, u) => Eddsa.curve.scalarAdd(acc, u));
        const RValues = [playerShare, ...rShares].map(({ R }) => (0, util_1.bigIntFromBufferLE)(Buffer.from(R, 'hex')));
        const R = RValues.reduce((partial, share) => Eddsa.curve.pointAdd(partial, share));
        const rValues = [playerShare, ...rShares].map(({ r }) => (0, util_1.bigIntFromBufferLE)(Buffer.from(r, 'hex')));
        const r = rValues.reduce((partial, share) => Eddsa.curve.scalarAdd(partial, share));
        const combinedBuffer = Buffer.concat([(0, util_1.bigIntToBufferLE)(R, 32), Buffer.from(S_i.y, 'hex'), message]);
        const digest = (0, crypto_1.createHash)('sha512').update(combinedBuffer).digest();
        const k = Eddsa.curve.scalarReduce((0, util_1.bigIntFromBufferLE)(digest));
        const gamma = Eddsa.curve.scalarAdd(r, Eddsa.curve.scalarMult(k, x));
        const result = {
            i: playerShare.i,
            y: playerShare.y,
            gamma: (0, util_1.bigIntToBufferLE)(gamma, 32).toString('hex'),
            R: (0, util_1.bigIntToBufferLE)(R, 32).toString('hex'),
        };
        return result;
    }
    signCombine(shares) {
        const y = shares[0].y;
        const R = shares[0].R;
        const resultShares = {};
        for (const ind in shares) {
            const S_i = shares[ind];
            resultShares[S_i.i] = (0, util_1.bigIntFromBufferLE)(Buffer.from(S_i.gamma, 'hex'));
        }
        const sigma = Eddsa.shamir.combine(resultShares);
        const result = {
            y,
            R,
            sigma: (0, util_1.bigIntToBufferLE)(sigma, 32).toString('hex'),
        };
        return result;
    }
    verify(message, signature) {
        const publicKey = (0, util_1.bigIntFromBufferLE)(Buffer.from(signature.y, 'hex'));
        const signedMessage = Buffer.concat([Buffer.from(signature.R, 'hex'), Buffer.from(signature.sigma, 'hex')]);
        return Eddsa.curve.verify(message, signedMessage, publicKey);
    }
    validateCommitment(RShare) {
        (0, assert_1.default)(RShare.commitment, 'Commitment is missing');
        const c = Eddsa.curve.basePointMult((0, util_1.bigIntFromBufferLE)(Buffer.from(RShare.r, 'hex')));
        const otherPlayerCommitment = (0, util_1.bigIntFromBufferLE)(Buffer.from(RShare.commitment, 'hex'));
        if (c !== otherPlayerCommitment) {
            throw new Error('Could not verify other player share');
        }
    }
}
Eddsa.curve = new curves_1.Ed25519Curve();
Eddsa.shamir = new shamir_1.default(Eddsa.curve);
Eddsa.initialized = false;
exports.default = Eddsa;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRkc2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYWNjb3VudC1saWIvbXBjL3Rzcy9lZGRzYS9lZGRzYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Qkc7QUFDSCxtQ0FBaUQ7QUFDakQseUNBQTRDO0FBQzVDLDBEQUFrQztBQUNsQyxxQ0FBK0c7QUFlL0csb0RBQTRCO0FBRzVCLFFBQVE7QUFDUixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsc0VBQXNFLENBQUMsQ0FBQztBQUU1RixNQUFxQixLQUFLO0lBS3hCLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQWU7UUFDckMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN2QixNQUFNLHFCQUFZLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDaEMsS0FBSyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7UUFDM0IsQ0FBQztRQUVELE9BQU8sSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUlELFlBQVksTUFBZTtRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRUQsUUFBUSxDQUFDLEtBQWEsRUFBRSxTQUFpQixFQUFFLFNBQWlCLEVBQUUsSUFBYTtRQUN6RSxJQUFJLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLEtBQUssSUFBSSxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sSUFBSSxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUM3QyxDQUFDO1FBQ0QsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLDBCQUEwQixDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUNELE1BQU0s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QUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFBLHlCQUFrQixFQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoSCxNQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFcEUsTUFBTSxPQUFPLEdBQUcsQ0FBQyxXQUFXLEVBQUUsR0FBRyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFBLHlCQUFrQixFQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRyxNQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFbkYsTUFBTSxPQUFPLEdBQUcsQ0FBQyxXQUFXLEVBQUUsR0FBRyxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFBLHlCQUFrQixFQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRyxNQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFcEYsTUFBTSxjQUFjLEdBQUcs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TSxDQUFDLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBQSx5QkFBa0IsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLE1BQU0scUJBQXFCLEdBQUcsSUFBQSx5QkFBa0IsRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUN4RixJQUFJLENBQUMsS0FBSyxxQkFBcUIsRUFBRSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQztRQUN6RCxDQUFDO0lBQ0gsQ0FBQzs7QUF0VE0sV0FBSyxHQUFpQixJQUFJLHFCQUFZLEVBQUUsQ0FBQztBQUN6QyxZQUFNLEdBQVcsSUFBSSxnQkFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN6QyxpQkFBVyxHQUFHLEtBQUssQ0FBQztrQkFIUixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNb2R1bGUgcHJvdmlkZXMgZnVuY3Rpb25zIGZvciBNUEMgdXNpbmcgdGhyZXNob2xkIHNpZ25hdHVyZSBzY2hlbWUgKFRTUykuIEl0IGNvbnRhaW5zXG4gKiBmdW5jdGlvbnMgZm9yIGtleSBnZW5lcmF0aW9uIGFuZCBtZXNzYWdlIHNpZ25pbmcgd2l0aCBFZERTQS5cbiAqXG4gKlxuICogPT09PT09PT09PT09PT09PT09PT09PVxuICogRWREU0EgS2V5IEdlbmVyYXRpb25cbiAqID09PT09PT09PT09PT09PT09PT09PT1cbiAqIDEuIEVhY2ggc2lnbmVyIGdlbmVyYXRlcyB0aGVpciBvd24ga2V5IHNoYXJlLCB3aGljaCBpbnZvbHZlcyBhIHByaXZhdGUgdS1zaGFyZSBhbmQgYSBwdWJsaWMgeS1zaGFyZS5cbiAqIDIuIFNpZ25lcnMgZGlzdHJpYnV0ZSB0aGVpciB5LXNoYXJlIHRvIG90aGVyIHNpZ25lcnMuXG4gKiAzLiBBZnRlciBleGNoYW5naW5nIHktc2hhcmVzIHRoZSBuZXh0IHBoYXNlIGlzIHRvIGNvbWJpbmUga2V5IHNoYXJlcy4gRWFjaCBzaWduZXIgY29tYmluZXMgdGhlaXIgdS1zaGFyZVxuICogICAgd2l0aCB0aGUgeS1zaGFyZXMgcmVjZWl2ZWQgZnJvbSBvdGhlciBzaWduZXJzIGluIG9yZGVyIHRvIGdlbmVyYXRlIGEgcC1zaGFyZSBmb3IgdGhlbXNlbHZlcy4gV2VcbiAqICAgIGFsc28gc2F2ZSBqLXNoYXJlcyBmb3Igb3RoZXIgc2lnbmVycy5cbiAqIDQuIEF0IHRoaXMgcG9pbnQgdGhlIHBsYXllcnMgZG8gbm90IGRpc3RyaWJ1dGUgYW55IHNoYXJlcyBhbmQgdGhlIGZpcnN0IHBoYXNlIG9mIHRoZVxuICogICAgc2lnbmluZyBwcm90b2NvbCBpcyBjb21wbGV0ZS5cbiAqXG4gKiA9PT09PT09PT09PT09PT09PT09PT09XG4gKiBFZERTQSBTaWduaW5nXG4gKiA9PT09PT09PT09PT09PT09PT09PT09XG4gKiAxLiBUaGUgcGFydGllcyBmcm9tIGtleSBnZW5lcmF0aW9uIGRlY2lkZSB0aGV5IHdhbnQgdG8gc2lnbiBzb21ldGhpbmcuIFRoZXkgYmVnaW4gdGhlIHNpZ25pbmcgcHJvdG9jb2xcbiAqICAgIGJ5IGdlbmVyYXRpbmcgc2hhcmVzIG9mIGFuIGVwaGVtZXJhbCBrZXkuXG4gKlxuICogICAgYSkgRWFjaCBzaWduZXIgdXNlcyBoaXMgcC1zaGFyZSBhbmQgdGhlIGotc2hhcmVzIHN0b3JlZCBmb3Igb3RoZXIgcGxheWVycyB0byBnZW5lcmF0ZSBoaXMgc2lnbmluZyBzaGFyZS5cbiAqICAgIGIpIFRoaXMgcmVzdWx0cyBpbiBlYWNoIHNpZ25lciBoYXZpbmcgYSBwcml2YXRlIHgtc2hhcmUgYW5kIHB1YmxpYyByLXNoYXJlcy5cbiAqXG4gKiAyLiBTaWduZXJzIGRpc3RyaWJ1dGUgdGhlaXIgci1zaGFyZXMgdG8gb3RoZXIgc2lnbmVycy5cbiAqIDMuIEFmdGVyIGV4Y2hhbmdpbmcgci1zaGFyZXMsIGVhY2ggc2lnbmVyIHNpZ25zIHRoZWlyIHNoYXJlIG9mIHRoZSBlcGhlbWVyYWwga2V5IHVzaW5nIHRoZWlyIHByaXZhdGVcbiAqICAgIHgtc2hhcmUgd2l0aCB0aGUgci1zaGFyZXMgZnJvbSBvdGhlciBzaWduZXJzLlxuICogNC4gVGhpcyByZXN1bHRzIGluIGVhY2ggc2lnbmVyIGhhdmluZyBhIHB1YmxpYyBnLXNoYXJlIHdoaWNoIHRoZXkgc2VuZCB0byB0aGUgb3RoZXIgc2lnbmVycy5cbiAqIDUuIEFmdGVyIHRoZSBzaWduZXJzIGJyb2FkY2FzdCB0aGVpciBnLXNoYXJlcywgdGhlIGZpbmFsIHNpZ25hdHVyZSBjYW4gYmUgcmUtY29uc3RydWN0ZWQgaW5kZXBlbmRlbnRseS5cbiAqL1xuaW1wb3J0IHsgcmFuZG9tQnl0ZXMsIGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgRWQyNTUxOUN1cnZlIH0gZnJvbSAnLi4vLi4vY3VydmVzJztcbmltcG9ydCBTaGFtaXIgZnJvbSAnLi4vLi4vc2hhbWlyJztcbmltcG9ydCB7IGJpZ0ludEZyb21CdWZmZXJMRSwgYmlnSW50VG9CdWZmZXJMRSwgYmlnSW50RnJvbUJ1ZmZlckJFLCBiaWdJbnRUb0J1ZmZlckJFLCBjbGFtcCB9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtcbiAgS2V5U2hhcmUsXG4gIFVTaGFyZSxcbiAgWVNoYXJlLFxuICBLZXlDb21iaW5lLFxuICBQU2hhcmUsXG4gIFN1YmtleVNoYXJlLFxuICBKU2hhcmUsXG4gIFNpZ25TaGFyZSxcbiAgU2lnbmF0dXJlLFxuICBYU2hhcmUsXG4gIFJTaGFyZSxcbiAgR1NoYXJlLFxufSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCB7IEhEVHJlZSB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5cbi8vIDJeMjU2XG5jb25zdCBiYXNlID0gQmlnSW50KCcweDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcpO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBFZGRzYSB7XG4gIHN0YXRpYyBjdXJ2ZTogRWQyNTUxOUN1cnZlID0gbmV3IEVkMjU1MTlDdXJ2ZSgpO1xuICBzdGF0aWMgc2hhbWlyOiBTaGFtaXIgPSBuZXcgU2hhbWlyKEVkZHNhLmN1cnZlKTtcbiAgc3RhdGljIGluaXRpYWxpemVkID0gZmFsc2U7XG5cbiAgc3RhdGljIGFzeW5jIGluaXRpYWxpemUoaGRUcmVlPzogSERUcmVlKTogUHJvbWlzZTxFZGRzYT4ge1xuICAgIGlmICghRWRkc2EuaW5pdGlhbGl6ZWQpIHtcbiAgICAgIGF3YWl0IEVkMjU1MTlDdXJ2ZS5pbml0aWFsaXplKCk7XG4gICAgICBFZGRzYS5pbml0aWFsaXplZCA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBFZGRzYShoZFRyZWUpO1xuICB9XG5cbiAgaGRUcmVlPzogSERUcmVlO1xuXG4gIGNvbnN0cnVjdG9yKGhkVHJlZT86IEhEVHJlZSkge1xuICAgIHRoaXMuaGRUcmVlID0gaGRUcmVlO1xuICB9XG5cbiAga2V5U2hhcmUoaW5kZXg6IG51bWJlciwgdGhyZXNob2xkOiBudW1iZXIsIG51bVNoYXJlczogbnVtYmVyLCBzZWVkPzogQnVmZmVyKTogS2V5U2hhcmUge1xuICAgIGlmICghKGluZGV4ID4gMCAmJiBpbmRleCA8PSBudW1TaGFyZXMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgS2V5U2hhcmUgY29uZmlnJyk7XG4gICAgfVxuICAgIGlmIChzZWVkICYmIHNlZWQubGVuZ3RoICE9PSA2NCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTZWVkIG11c3QgaGF2ZSBsZW5ndGggNjQnKTtcbiAgICB9XG4gICAgY29uc3Qgc2VlZGNoYWluID0gc2VlZCA/PyByYW5kb21CeXRlcyg2NCk7XG4gICAgY29uc3QgYWN0dWFsU2VlZCA9IHNlZWRjaGFpbi5zbGljZSgwLCAzMik7XG4gICAgY29uc3QgY2hhaW5jb2RlID0gc2VlZGNoYWluLnNsaWNlKDMyKTtcbiAgICBjb25zdCBoID0gY3JlYXRlSGFzaCgnc2hhNTEyJykudXBkYXRlKGFjdHVhbFNlZWQpLmRpZ2VzdCgpO1xuICAgIGNvbnN0IHUgPSBjbGFtcChiaWdJbnRGcm9tQnVmZmVyTEUoaC5zbGljZSgwLCAzMikpKTtcbiAgICBjb25zdCB5ID0gRWRkc2EuY3VydmUuYmFzZVBvaW50TXVsdCh1KTtcbiAgICBjb25zdCB7IHNoYXJlczogc3BsaXRfdSwgdiB9ID0gRWRkc2Euc2hhbWlyLnNwbGl0KHUsIHRocmVzaG9sZCwgbnVtU2hhcmVzKTtcblxuICAgIGNvbnN0IFBfaTogVVNoYXJlID0ge1xuICAgICAgaTogaW5kZXgsXG4gICAgICB0OiB0aHJlc2hvbGQsXG4gICAgICBuOiBudW1TaGFyZXMsXG4gICAgICB5OiBiaWdJbnRUb0J1ZmZlckxFKHksIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICBzZWVkOiBhY3R1YWxTZWVkLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIGNoYWluY29kZTogY2hhaW5jb2RlLnRvU3RyaW5nKCdoZXgnKSxcbiAgICB9O1xuICAgIGNvbnN0IHNoYXJlczogS2V5U2hhcmUgPSB7XG4gICAgICB1U2hhcmU6IFBfaSxcbiAgICAgIHlTaGFyZXM6IHt9LFxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IGluZCBpbiBzcGxpdF91KSB7XG4gICAgICBjb25zdCBpID0gcGFyc2VJbnQoaW5kLCAxMCk7XG4gICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBzaGFyZXMueVNoYXJlc1tpXSA9IHtcbiAgICAgICAgaSxcbiAgICAgICAgajogUF9pLmksXG4gICAgICAgIHk6IGJpZ0ludFRvQnVmZmVyTEUoeSwgMzIpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgdjogYmlnSW50VG9CdWZmZXJMRSh2WzBdLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICB1OiBiaWdJbnRUb0J1ZmZlckxFKHNwbGl0X3VbaW5kXSwgMzIpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgY2hhaW5jb2RlOiBjaGFpbmNvZGUudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHNoYXJlcztcbiAgfVxuXG4gIGtleUNvbWJpbmUodVNoYXJlOiBVU2hhcmUsIHlTaGFyZXM6IFlTaGFyZVtdKTogS2V5Q29tYmluZSB7XG4gICAgY29uc3QgaCA9IGNyZWF0ZUhhc2goJ3NoYTUxMicpLnVwZGF0ZShCdWZmZXIuZnJvbSh1U2hhcmUuc2VlZCwgJ2hleCcpKS5kaWdlc3QoKTtcbiAgICBjb25zdCB1ID0gY2xhbXAoYmlnSW50RnJvbUJ1ZmZlckxFKGguc2xpY2UoMCwgMzIpKSk7XG4gICAgY29uc3QgeVZhbHVlcyA9IFt1U2hhcmUsIC4uLnlTaGFyZXNdLm1hcCgoc2hhcmUpID0+IGJpZ0ludEZyb21CdWZmZXJMRShCdWZmZXIuZnJvbShzaGFyZS55LCAnaGV4JykpKTtcbiAgICBjb25zdCB5ID0geVZhbHVlcy5yZWR1Y2UoKHBhcnRpYWwsIHNoYXJlKSA9PiBFZGRzYS5jdXJ2ZS5wb2ludEFkZChwYXJ0aWFsLCBzaGFyZSkpO1xuICAgIGNvbnN0IGNoYWluY29kZXMgPSBbdVNoYXJlLCAuLi55U2hhcmVzXS5tYXAoKHsgY2hhaW5jb2RlIH0pID0+IGJpZ0ludEZyb21CdWZmZXJCRShCdWZmZXIuZnJvbShjaGFpbmNvZGUsICdoZXgnKSkpO1xuICAgIGNvbnN0IGNoYWluY29kZSA9IGNoYWluY29kZXMucmVkdWNlKChhY2MsIGNoYWluY29kZSkgPT4gKGFjYyArIGNoYWluY29kZSkgJSBiYXNlKTtcblxuICAgIC8vIFZlcmlmeSBzaGFyZXMuXG4gICAgZm9yIChjb25zdCBzaGFyZSBvZiB5U2hhcmVzKSB7XG4gICAgICBpZiAoJ3YnIGluIHNoYXJlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgRWRkc2Euc2hhbWlyLnZlcmlmeShcbiAgICAgICAgICAgIGJpZ0ludEZyb21CdWZmZXJMRShCdWZmZXIuZnJvbShzaGFyZS51LCAnaGV4JykpLFxuICAgICAgICAgICAgW2JpZ0ludEZyb21CdWZmZXJMRShCdWZmZXIuZnJvbShzaGFyZS55LCAnaGV4JykpLCBiaWdJbnRGcm9tQnVmZmVyTEUoQnVmZmVyLmZyb20oc2hhcmUudiEsICdoZXgnKSldLFxuICAgICAgICAgICAgdVNoYXJlLmlcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCB2ZXJpZnkgc2hhcmUgZnJvbSBwYXJ0aWNpcGFudCAke3NoYXJlLmp9LiBWZXJpZmljYXRpb24gZXJyb3I6ICR7ZXJyfWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgUF9pOiBQU2hhcmUgPSB7XG4gICAgICBpOiB1U2hhcmUuaSxcbiAgICAgIHQ6IHVTaGFyZS50LFxuICAgICAgbjogdVNoYXJlLm4sXG4gICAgICB5OiBiaWdJbnRUb0J1ZmZlckxFKHksIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICB1OiBiaWdJbnRUb0J1ZmZlckxFKHUsIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICBwcmVmaXg6IGguc2xpY2UoMzIpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIGNoYWluY29kZTogYmlnSW50VG9CdWZmZXJCRShjaGFpbmNvZGUsIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgfTtcbiAgICBjb25zdCBwbGF5ZXJzOiBLZXlDb21iaW5lID0ge1xuICAgICAgcFNoYXJlOiBQX2ksXG4gICAgICBqU2hhcmVzOiB7fSxcbiAgICB9O1xuXG4gICAgZm9yIChsZXQgaW5kID0gMDsgaW5kIDwgeVNoYXJlcy5sZW5ndGg7IGluZCsrKSB7XG4gICAgICBjb25zdCBQX2ogPSB5U2hhcmVzW2luZF07XG4gICAgICBwbGF5ZXJzLmpTaGFyZXNbUF9qLmpdID0ge1xuICAgICAgICBpOiBQX2ouaixcbiAgICAgICAgajogUF9pLmksXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gcGxheWVycztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXJpdmVzIGEgY2hpbGQgY29tbW9uIGtleWNoYWluIGZyb20gY29tbW9uIGtleWNoYWluXG4gICAqXG4gICAqIEBwYXJhbSBjb21tb25LZXljaGFpbiAtIGNvbW1vbiBrZXljaGFpbiBhcyBhIGhleCBzdHJpbmdcbiAgICogQHBhcmFtIHBhdGggLSBiaXAzMiBwYXRoXG4gICAqIEByZXR1cm4ge3N0cmluZ30gZGVyaXZlZCBjb21tb24ga2V5Y2hhaW4gYXMgYSBoZXggc3RyaW5nXG4gICAqL1xuICBkZXJpdmVVbmhhcmRlbmVkKGNvbW1vbktleWNoYWluOiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuaGRUcmVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IGRlcml2ZSBrZXkgd2l0aG91dCBIRFRyZWUgaW1wbGVtZW50YXRpb25cIik7XG4gICAgfVxuXG4gICAgY29uc3Qga2V5Y2hhaW4gPSBCdWZmZXIuZnJvbShjb21tb25LZXljaGFpbiwgJ2hleCcpO1xuXG4gICAgY29uc3QgZGVyaXZlZFB1YmxpY0tleWNoYWluID0gdGhpcy5oZFRyZWUucHVibGljRGVyaXZlKFxuICAgICAge1xuICAgICAgICBwazogYmlnSW50RnJvbUJ1ZmZlckxFKGtleWNoYWluLnNsaWNlKDAsIDMyKSksXG4gICAgICAgIGNoYWluY29kZTogYmlnSW50RnJvbUJ1ZmZlckJFKGtleWNoYWluLnNsaWNlKDMyKSksXG4gICAgICB9LFxuICAgICAgcGF0aFxuICAgICk7XG5cbiAgICBjb25zdCBkZXJpdmVkUGsgPSBiaWdJbnRUb0J1ZmZlckxFKGRlcml2ZWRQdWJsaWNLZXljaGFpbi5waywgMzIpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBjb25zdCBkZXJpdmVkQ2hhaW5jb2RlID0gYmlnSW50VG9CdWZmZXJCRShkZXJpdmVkUHVibGljS2V5Y2hhaW4uY2hhaW5jb2RlLCAzMikudG9TdHJpbmcoJ2hleCcpO1xuXG4gICAgcmV0dXJuIGRlcml2ZWRQayArIGRlcml2ZWRDaGFpbmNvZGU7XG4gIH1cblxuICBrZXlEZXJpdmUodVNoYXJlOiBVU2hhcmUsIHlTaGFyZXM6IFlTaGFyZVtdLCBwYXRoOiBzdHJpbmcpOiBTdWJrZXlTaGFyZSB7XG4gICAgaWYgKHRoaXMuaGRUcmVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IGRlcml2ZSBrZXkgd2l0aG91dCBIRFRyZWUgaW1wbGVtZW50YXRpb25cIik7XG4gICAgfVxuICAgIGNvbnN0IGggPSBjcmVhdGVIYXNoKCdzaGE1MTInKS51cGRhdGUoQnVmZmVyLmZyb20odVNoYXJlLnNlZWQsICdoZXgnKSkuZGlnZXN0KCk7XG4gICAgY29uc3QgeVZhbHVlcyA9IFt1U2hhcmUsIC4uLnlTaGFyZXNdLm1hcCgoc2hhcmUpID0+IGJpZ0ludEZyb21CdWZmZXJMRShCdWZmZXIuZnJvbShzaGFyZS55LCAnaGV4JykpKTtcbiAgICBjb25zdCB5ID0geVZhbHVlcy5yZWR1Y2UoKHBhcnRpYWwsIHNoYXJlKSA9PiBFZGRzYS5jdXJ2ZS5wb2ludEFkZChwYXJ0aWFsLCBzaGFyZSkpO1xuICAgIGNvbnN0IHUgPSBjbGFtcChiaWdJbnRGcm9tQnVmZmVyTEUoaC5zbGljZSgwLCAzMikpKTtcbiAgICBjb25zdCBwcmVmaXggPSBiaWdJbnRGcm9tQnVmZmVyQkUoaC5zbGljZSgzMikpO1xuICAgIGxldCBjb250cmliQ2hhaW5jb2RlID0gYmlnSW50RnJvbUJ1ZmZlckJFKEJ1ZmZlci5mcm9tKHVTaGFyZS5jaGFpbmNvZGUsICdoZXgnKSk7XG4gICAgY29uc3QgY2hhaW5jb2RlcyA9IFtcbiAgICAgIGNvbnRyaWJDaGFpbmNvZGUsXG4gICAgICAuLi55U2hhcmVzLm1hcCgoeyBjaGFpbmNvZGUgfSkgPT4gYmlnSW50RnJvbUJ1ZmZlckJFKEJ1ZmZlci5mcm9tKGNoYWluY29kZSwgJ2hleCcpKSksXG4gICAgXTtcbiAgICBjb25zdCBjaGFpbmNvZGUgPSBjaGFpbmNvZGVzLnJlZHVjZSgoYWNjLCBjaGFpbmNvZGUpID0+IChhY2MgKyBjaGFpbmNvZGUpICUgYmFzZSk7XG5cbiAgICAvLyBEZXJpdmUgc3Via2V5LlxuICAgIGNvbnN0IHN1YmtleSA9IHRoaXMuaGRUcmVlLnByaXZhdGVEZXJpdmUoeyBwazogeSwgc2s6IHUsIHByZWZpeCwgY2hhaW5jb2RlIH0sIHBhdGgpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIG5ldyBwdWJsaWMga2V5IGNvbnRyaWJ1dGlvbi5cbiAgICBjb25zdCBjb250cmliWSA9IEVkZHNhLmN1cnZlLmJhc2VQb2ludE11bHQoc3Via2V5LnNrKTtcblxuICAgIC8vIENhbGN1bGF0ZSBuZXcgY2hhaW5jb2RlIGNvbnRyaWJ1dGlvbi5cbiAgICBjb25zdCBjaGFpbmNvZGVEZWx0YSA9IChiYXNlICsgc3Via2V5LmNoYWluY29kZSAtIGNoYWluY29kZSkgJSBiYXNlO1xuICAgIGNvbnRyaWJDaGFpbmNvZGUgPSAoY29udHJpYkNoYWluY29kZSArIGNoYWluY29kZURlbHRhKSAlIGJhc2U7XG5cbiAgICAvLyBDYWxjdWxhdGUgbmV3IHUgdmFsdWVzLlxuICAgIGNvbnN0IHsgc2hhcmVzOiBzcGxpdF91LCB2IH0gPSBFZGRzYS5zaGFtaXIuc3BsaXQoc3Via2V5LnNrLCB1U2hhcmUudCwgdVNoYXJlLm4pO1xuXG4gICAgY29uc3QgUF9pOiBQU2hhcmUgPSB7XG4gICAgICBpOiB1U2hhcmUuaSxcbiAgICAgIHQ6IHVTaGFyZS50LFxuICAgICAgbjogdVNoYXJlLm4sXG4gICAgICB5OiBiaWdJbnRUb0J1ZmZlckxFKHN1YmtleS5waywgMzIpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIHU6IGJpZ0ludFRvQnVmZmVyTEUoc3Via2V5LnNrLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgcHJlZml4OiBiaWdJbnRUb0J1ZmZlckJFKHN1YmtleS5wcmVmaXghLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgY2hhaW5jb2RlOiBiaWdJbnRUb0J1ZmZlckJFKHN1YmtleS5jaGFpbmNvZGUsIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgfTtcblxuICAgIGNvbnN0IHNoYXJlczogU3Via2V5U2hhcmUgPSB7XG4gICAgICBwU2hhcmU6IFBfaSxcbiAgICAgIHlTaGFyZXM6IHt9LFxuICAgIH07XG5cbiAgICBmb3IgKGxldCBpbmQgPSAwOyBpbmQgPCB5U2hhcmVzLmxlbmd0aDsgaW5kKyspIHtcbiAgICAgIGNvbnN0IFBfaiA9IHlTaGFyZXNbaW5kXTtcbiAgICAgIHNoYXJlcy55U2hhcmVzW1Bfai5qXSA9IHtcbiAgICAgICAgaTogUF9qLmosXG4gICAgICAgIGo6IFBfaS5pLFxuICAgICAgICB5OiBiaWdJbnRUb0J1ZmZlckxFKGNvbnRyaWJZLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICB2OiBiaWdJbnRUb0J1ZmZlckxFKHZbMF0sIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIHU6IGJpZ0ludFRvQnVmZmVyTEUoc3BsaXRfdVtQX2oual0sIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIGNoYWluY29kZTogYmlnSW50VG9CdWZmZXJCRShjb250cmliQ2hhaW5jb2RlLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2hhcmVzO1xuICB9XG5cbiAgc2lnblNoYXJlKG1lc3NhZ2U6IEJ1ZmZlciwgcFNoYXJlOiBQU2hhcmUsIGpTaGFyZXM6IEpTaGFyZVtdLCBzZWVkPzogQnVmZmVyKTogU2lnblNoYXJlIHtcbiAgICBpZiAoc2VlZCAmJiBzZWVkLmxlbmd0aCAhPT0gNjQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU2VlZCBtdXN0IGhhdmUgbGVuZ3RoIDY0Jyk7XG4gICAgfVxuICAgIGNvbnN0IGluZGljZXMgPSBbcFNoYXJlLCAuLi5qU2hhcmVzXS5tYXAoKHsgaSB9KSA9PiBpKTtcbiAgICBjb25zdCB7IHNoYXJlczogc3BsaXRfdSwgdiB9ID0gRWRkc2Euc2hhbWlyLnNwbGl0KFxuICAgICAgYmlnSW50RnJvbUJ1ZmZlckxFKEJ1ZmZlci5mcm9tKHBTaGFyZS51LCAnaGV4JykpLFxuICAgICAgcFNoYXJlLnQsXG4gICAgICBwU2hhcmUublxuICAgICk7XG5cbiAgICAvLyBHZW5lcmF0ZSBub25jZSBjb250cmlidXRpb24uXG4gICAgY29uc3QgcHJlZml4ID0gQnVmZmVyLmZyb20ocFNoYXJlLnByZWZpeCwgJ2hleCcpO1xuICAgIGNvbnN0IHJhbmRvbUJ1ZmZlciA9IHNlZWQgPz8gcmFuZG9tQnl0ZXMoNjQpO1xuXG4gICAgY29uc3QgZGlnZXN0ID0gY3JlYXRlSGFzaCgnc2hhNTEyJylcbiAgICAgIC51cGRhdGUoQnVmZmVyLmNvbmNhdChbcHJlZml4LCBtZXNzYWdlLCByYW5kb21CdWZmZXJdKSlcbiAgICAgIC5kaWdlc3QoKTtcblxuICAgIGNvbnN0IHIgPSBFZGRzYS5jdXJ2ZS5zY2FsYXJSZWR1Y2UoYmlnSW50RnJvbUJ1ZmZlckxFKGRpZ2VzdCkpO1xuICAgIGNvbnN0IFIgPSBFZGRzYS5jdXJ2ZS5iYXNlUG9pbnRNdWx0KHIpO1xuICAgIGNvbnN0IHsgc2hhcmVzOiBzcGxpdF9yIH0gPSBFZGRzYS5zaGFtaXIuc3BsaXQociwgaW5kaWNlcy5sZW5ndGgsIGluZGljZXMubGVuZ3RoLCBpbmRpY2VzKTtcblxuICAgIGNvbnN0IFBfaTogWFNoYXJlID0ge1xuICAgICAgaTogcFNoYXJlLmksXG4gICAgICB5OiBwU2hhcmUueSxcbiAgICAgIHU6IGJpZ0ludFRvQnVmZmVyTEUoc3BsaXRfdVtwU2hhcmUuaV0sIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICByOiBiaWdJbnRUb0J1ZmZlckxFKHNwbGl0X3JbcFNoYXJlLmldLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgUjogYmlnSW50VG9CdWZmZXJMRShSLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgIH07XG5cbiAgICBjb25zdCByZXN1bHRTaGFyZXM6IFNpZ25TaGFyZSA9IHtcbiAgICAgIHhTaGFyZTogUF9pLFxuICAgICAgclNoYXJlczoge30sXG4gICAgfTtcblxuICAgIGZvciAobGV0IGluZCA9IDA7IGluZCA8IGpTaGFyZXMubGVuZ3RoOyBpbmQrKykge1xuICAgICAgY29uc3QgU19qID0galNoYXJlc1tpbmRdO1xuICAgICAgcmVzdWx0U2hhcmVzLnJTaGFyZXNbU19qLmldID0ge1xuICAgICAgICBpOiBTX2ouaSxcbiAgICAgICAgajogcFNoYXJlLmksXG4gICAgICAgIHU6IGJpZ0ludFRvQnVmZmVyTEUoc3BsaXRfdVtTX2ouaV0sIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICAgIHY6IGJpZ0ludFRvQnVmZmVyTEUodlswXSwgMzIpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgcjogYmlnSW50VG9CdWZmZXJMRShzcGxpdF9yW1Nfai5pXSwgMzIpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgICAgUjogYmlnSW50VG9CdWZmZXJMRShSLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgICBjb21taXRtZW50OiBiaWdJbnRUb0J1ZmZlckxFKEVkZHNhLmN1cnZlLmJhc2VQb2ludE11bHQoc3BsaXRfcltTX2ouaV0pLCAzMikudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFNoYXJlcztcbiAgfVxuXG4gIHNpZ24obWVzc2FnZTogQnVmZmVyLCBwbGF5ZXJTaGFyZTogWFNoYXJlLCByU2hhcmVzOiBSU2hhcmVbXSwgeVNoYXJlczogWVNoYXJlW10gPSBbXSk6IEdTaGFyZSB7XG4gICAgZm9yIChjb25zdCByU2hhcmUgb2YgclNoYXJlcykge1xuICAgICAgdGhpcy52YWxpZGF0ZUNvbW1pdG1lbnQoclNoYXJlKTtcbiAgICB9XG5cbiAgICBjb25zdCBTX2kgPSBwbGF5ZXJTaGFyZTtcblxuICAgIGNvbnN0IHVWYWx1ZXMgPSBbcGxheWVyU2hhcmUsIC4uLnJTaGFyZXMsIC4uLnlTaGFyZXNdLm1hcCgoeyB1IH0pID0+IGJpZ0ludEZyb21CdWZmZXJMRShCdWZmZXIuZnJvbSh1LCAnaGV4JykpKTtcbiAgICBjb25zdCB4ID0gdVZhbHVlcy5yZWR1Y2UoKGFjYywgdSkgPT4gRWRkc2EuY3VydmUuc2NhbGFyQWRkKGFjYywgdSkpO1xuXG4gICAgY29uc3QgUlZhbHVlcyA9IFtwbGF5ZXJTaGFyZSwgLi4uclNoYXJlc10ubWFwKCh7IFIgfSkgPT4gYmlnSW50RnJvbUJ1ZmZlckxFKEJ1ZmZlci5mcm9tKFIsICdoZXgnKSkpO1xuICAgIGNvbnN0IFIgPSBSVmFsdWVzLnJlZHVjZSgocGFydGlhbCwgc2hhcmUpID0+IEVkZHNhLmN1cnZlLnBvaW50QWRkKHBhcnRpYWwsIHNoYXJlKSk7XG5cbiAgICBjb25zdCByVmFsdWVzID0gW3BsYXllclNoYXJlLCAuLi5yU2hhcmVzXS5tYXAoKHsgciB9KSA9PiBiaWdJbnRGcm9tQnVmZmVyTEUoQnVmZmVyLmZyb20ociwgJ2hleCcpKSk7XG4gICAgY29uc3QgciA9IHJWYWx1ZXMucmVkdWNlKChwYXJ0aWFsLCBzaGFyZSkgPT4gRWRkc2EuY3VydmUuc2NhbGFyQWRkKHBhcnRpYWwsIHNoYXJlKSk7XG5cbiAgICBjb25zdCBjb21iaW5lZEJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW2JpZ0ludFRvQnVmZmVyTEUoUiwgMzIpLCBCdWZmZXIuZnJvbShTX2kueSwgJ2hleCcpLCBtZXNzYWdlXSk7XG4gICAgY29uc3QgZGlnZXN0ID0gY3JlYXRlSGFzaCgnc2hhNTEyJykudXBkYXRlKGNvbWJpbmVkQnVmZmVyKS5kaWdlc3QoKTtcbiAgICBjb25zdCBrID0gRWRkc2EuY3VydmUuc2NhbGFyUmVkdWNlKGJpZ0ludEZyb21CdWZmZXJMRShkaWdlc3QpKTtcblxuICAgIGNvbnN0IGdhbW1hID0gRWRkc2EuY3VydmUuc2NhbGFyQWRkKHIsIEVkZHNhLmN1cnZlLnNjYWxhck11bHQoaywgeCkpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgIGk6IHBsYXllclNoYXJlLmksXG4gICAgICB5OiBwbGF5ZXJTaGFyZS55LFxuICAgICAgZ2FtbWE6IGJpZ0ludFRvQnVmZmVyTEUoZ2FtbWEsIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgICBSOiBiaWdJbnRUb0J1ZmZlckxFKFIsIDMyKS50b1N0cmluZygnaGV4JyksXG4gICAgfTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgc2lnbkNvbWJpbmUoc2hhcmVzOiBHU2hhcmVbXSk6IFNpZ25hdHVyZSB7XG4gICAgY29uc3QgeSA9IHNoYXJlc1swXS55O1xuICAgIGNvbnN0IFIgPSBzaGFyZXNbMF0uUjtcblxuICAgIGNvbnN0IHJlc3VsdFNoYXJlcyA9IHt9O1xuICAgIGZvciAoY29uc3QgaW5kIGluIHNoYXJlcykge1xuICAgICAgY29uc3QgU19pID0gc2hhcmVzW2luZF07XG4gICAgICByZXN1bHRTaGFyZXNbU19pLmldID0gYmlnSW50RnJvbUJ1ZmZlckxFKEJ1ZmZlci5mcm9tKFNfaS5nYW1tYSwgJ2hleCcpKTtcbiAgICB9XG4gICAgY29uc3Qgc2lnbWE6IGJpZ2ludCA9IEVkZHNhLnNoYW1pci5jb21iaW5lKHJlc3VsdFNoYXJlcyk7XG4gICAgY29uc3QgcmVzdWx0ID0ge1xuICAgICAgeSxcbiAgICAgIFIsXG4gICAgICBzaWdtYTogYmlnSW50VG9CdWZmZXJMRShzaWdtYSwgMzIpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICB9O1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICB2ZXJpZnkobWVzc2FnZTogQnVmZmVyLCBzaWduYXR1cmU6IFNpZ25hdHVyZSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHB1YmxpY0tleSA9IGJpZ0ludEZyb21CdWZmZXJMRShCdWZmZXIuZnJvbShzaWduYXR1cmUueSwgJ2hleCcpKTtcbiAgICBjb25zdCBzaWduZWRNZXNzYWdlID0gQnVmZmVyLmNvbmNhdChbQnVmZmVyLmZyb20oc2lnbmF0dXJlLlIsICdoZXgnKSwgQnVmZmVyLmZyb20oc2lnbmF0dXJlLnNpZ21hLCAnaGV4JyldKTtcbiAgICByZXR1cm4gRWRkc2EuY3VydmUudmVyaWZ5KG1lc3NhZ2UsIHNpZ25lZE1lc3NhZ2UsIHB1YmxpY0tleSk7XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlQ29tbWl0bWVudChSU2hhcmU6IFJTaGFyZSk6IHZvaWQge1xuICAgIGFzc2VydChSU2hhcmUuY29tbWl0bWVudCwgJ0NvbW1pdG1lbnQgaXMgbWlzc2luZycpO1xuICAgIGNvbnN0IGMgPSBFZGRzYS5jdXJ2ZS5iYXNlUG9pbnRNdWx0KGJpZ0ludEZyb21CdWZmZXJMRShCdWZmZXIuZnJvbShSU2hhcmUuciwgJ2hleCcpKSk7XG4gICAgY29uc3Qgb3RoZXJQbGF5ZXJDb21taXRtZW50ID0gYmlnSW50RnJvbUJ1ZmZlckxFKEJ1ZmZlci5mcm9tKFJTaGFyZS5jb21taXRtZW50LCAnaGV4JykpO1xuICAgIGlmIChjICE9PSBvdGhlclBsYXllckNvbW1pdG1lbnQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IHZlcmlmeSBvdGhlciBwbGF5ZXIgc2hhcmUnKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==

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


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