PHP WebShell

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

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

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const paillierBigint = __importStar(require("paillier-bigint"));
require("should");
const sinon_1 = __importDefault(require("sinon"));
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
const tss_1 = require("../../../../../../src/account-lib/mpc/tss");
const fixtures_1 = require("./fixtures");
const sdk_opensslbytes_1 = require("@bitgo/sdk-opensslbytes");
const openSSLBytes = (0, sdk_opensslbytes_1.loadWebAssembly)().buffer;
describe('ecdsa tss', function () {
    const ecdsa = new tss_1.Ecdsa();
    let signCombine1, signCombine2;
    before('generate key and sign phase 1 to 4', async function () {
        const paillierKeyStub = sinon_1.default.stub(paillierBigint, 'generateRandomKeys');
        paillierKeyStub.onCall(0).returns(Promise.resolve(fixtures_1.paillierKeyPairs[0]));
        paillierKeyStub.onCall(1).returns(Promise.resolve(fixtures_1.paillierKeyPairs[1]));
        paillierKeyStub.onCall(2).returns(Promise.resolve(fixtures_1.paillierKeyPairs[2]));
        const [keyShare1, keyShare2, keyShare3] = await Promise.all([
            ecdsa.keyShare(1, 2, 3),
            ecdsa.keyShare(2, 2, 3),
            ecdsa.keyShare(3, 2, 3),
        ]);
        const [keyCombined1, keyCombined2, keyCombined3] = [
            ecdsa.keyCombine(keyShare1.pShare, [keyShare2.nShares[1], keyShare3.nShares[1]]),
            ecdsa.keyCombine(keyShare2.pShare, [keyShare1.nShares[2], keyShare3.nShares[2]]),
            ecdsa.keyCombine(keyShare3.pShare, [keyShare1.nShares[3], keyShare2.nShares[3]]),
        ];
        keyCombined1.xShare.y.should.equal(keyCombined2.xShare.y);
        keyCombined1.xShare.y.should.equal(keyCombined3.xShare.y);
        // Collect all VSS from nShares and verify Schnorr proofs against X_i.
        // Note that this is something WP needs to do after keyCombine/keyDerive.
        const Y = (0, sdk_lib_mpc_1.hexToBigInt)(keyCombined1.xShare.y);
        const VSSs = [
            [(0, sdk_lib_mpc_1.hexToBigInt)(keyShare1.nShares[2].v)],
            [(0, sdk_lib_mpc_1.hexToBigInt)(keyShare2.nShares[3].v)],
            [(0, sdk_lib_mpc_1.hexToBigInt)(keyShare3.nShares[1].v)],
        ];
        ecdsa.verifySchnorrProofX(Y, VSSs, 1, keyCombined1.xShare.schnorrProofX).should.be.true();
        ecdsa.verifySchnorrProofX(Y, VSSs, 2, keyCombined2.xShare.schnorrProofX).should.be.true();
        ecdsa.verifySchnorrProofX(Y, VSSs, 3, keyCombined3.xShare.schnorrProofX).should.be.true();
        // Verify Schnorr proofs against X_i for keyDerive and subsequent keyCombine.
        const path = 'm/0/1/2';
        const keyDerive1 = ecdsa.keyDerive(keyShare1.pShare, [keyShare2.nShares[1], keyShare3.nShares[1]], path);
        // Note the VSSs used here are different from the ones used above.
        const derivedY = (0, sdk_lib_mpc_1.hexToBigInt)(keyDerive1.xShare.y);
        const derivedVSSs = [
            [(0, sdk_lib_mpc_1.hexToBigInt)(keyDerive1.nShares[2].v)],
            [(0, sdk_lib_mpc_1.hexToBigInt)(keyShare2.nShares[3].v)],
            [(0, sdk_lib_mpc_1.hexToBigInt)(keyShare3.nShares[1].v)],
        ];
        ecdsa.verifySchnorrProofX(derivedY, derivedVSSs, 1, keyDerive1.xShare.schnorrProofX).should.be.true();
        const keyCombined2FromKeyDerive1 = ecdsa.keyCombine(keyShare2.pShare, [
            keyDerive1.nShares[2],
            keyShare3.nShares[2],
        ]);
        ecdsa
            .verifySchnorrProofX(derivedY, derivedVSSs, 2, keyCombined2FromKeyDerive1.xShare.schnorrProofX)
            .should.be.true();
        const [ntilde1, ntilde2] = await Promise.all([
            sdk_lib_mpc_1.EcdsaRangeProof.generateNtilde(openSSLBytes, 512),
            sdk_lib_mpc_1.EcdsaRangeProof.generateNtilde(openSSLBytes, 512),
        ]);
        const [serializeNtilde1, serializeNtilde2] = [
            sdk_lib_mpc_1.EcdsaTypes.serializeNtildeWithProofs(ntilde1),
            sdk_lib_mpc_1.EcdsaTypes.serializeNtildeWithProofs(ntilde2),
        ];
        const [index1, index2] = [keyCombined1.xShare.i, keyCombined2.xShare.i];
        const [paillierN1to2, paillierN2to1] = [keyCombined1.yShares[index2].n, keyCombined2.yShares[index1].n];
        const [paillierChallenger1to2, paillierChallenger2to1] = await Promise.all([
            sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_lib_mpc_1.hexToBigInt)(paillierN1to2)),
            sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_lib_mpc_1.hexToBigInt)(paillierN2to1)),
        ]);
        const [xShare1, xShare2] = [
            ecdsa.appendChallenge(keyCombined1.xShare, serializeNtilde1, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: paillierChallenger1to2 })),
            ecdsa.appendChallenge(keyCombined2.xShare, serializeNtilde2, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: paillierChallenger2to1 })),
        ];
        const yShare2 = ecdsa.appendChallenge(keyCombined1.yShares[index2], serializeNtilde2, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: paillierChallenger2to1 }));
        const signShares = await ecdsa.signShare(xShare1, yShare2);
        const signConvertS21 = await ecdsa.signConvertStep1({
            xShare: xShare2,
            yShare: keyCombined2.yShares[index1],
            kShare: signShares.kShare,
        });
        const signConvertS12 = await ecdsa.signConvertStep2({
            aShare: signConvertS21.aShare,
            wShare: signShares.wShare,
        });
        const signConvertS21_2 = await ecdsa.signConvertStep3({
            muShare: signConvertS12.muShare,
            bShare: signConvertS21.bShare,
        });
        [signCombine1, signCombine2] = [
            ecdsa.signCombine({
                gShare: signConvertS12.gShare,
                signIndex: {
                    i: signConvertS12.muShare.i,
                    j: signConvertS12.muShare.j,
                },
            }),
            ecdsa.signCombine({
                gShare: signConvertS21_2.gShare,
                signIndex: {
                    i: signConvertS21_2.signIndex.i,
                    j: signConvertS21_2.signIndex.j,
                },
            }),
        ];
    });
    it('sign phase 5 should succeed', async function () {
        // TODO(HSM-129): There is a bug signing unhashed message (although this deviates from DSA spec) if the message is a little long.
        //       Some discrepancy between Ecdsa.sign and secp256k1.recoverPublicKey on handling the message input.
        const message = Buffer.from('GG18 PHASE 5');
        // Starting phase 5
        // In addition to returning s_i, Ecdsa.sign() now also calculates data needed for steps 5A and 5B:
        //   - sample random l_i and rho_i (5A)
        //   - computes V_i and A_i (5B)]
        //   - computes commitment and decommitment of (V_i, A_i) (5A, 5B)
        //   - generates proofs of knowledge of s_i, l_i, rho_i w.r.t. V_i, A_i (5B)
        const [sign1, sign2] = [
            ecdsa.generateVAProofs(message, ecdsa.sign(message, signCombine1.oShare, signCombine2.dShare)),
            ecdsa.generateVAProofs(message, ecdsa.sign(message, signCombine2.oShare, signCombine1.dShare)),
        ];
        sign1.R.should.equal(sign2.R);
        sign1.y.should.equal(sign2.y);
        sign1.m.toString('hex').should.equal(sign2.m.toString('hex'));
        // Step 5A: Calculations done by Ecdsa.sign() above, and broadcast commitment of (V_i, A_i) to other parties.
        //          The following values will be sent via communication channel at the end of 5A.
        // const commitmentVA1 = sign1.comDecomVA.commitment;
        // const commitmentVA2 = sign2.comDecomVA.commitment;
        // Step 5B: After having received all commitments of (V_i, A_i) from other parties,
        //          each party will broadcast decommitment of (V_i, A_i) and ZK proofs returned by Ecdsa.sign() above
        //          to other parties.  Then Ecdsa.verifyVAShares() below will:
        //   - verify commitments of (V_i, A_i) received from other parties (5B)
        //   - verify ZK proofs of (V_i, A_i) received from other parties (5B)
        //   - calculate V out of G, y, r, m, and all V_i, calculate A as sum of all A_i (5B)
        //   - calculate U_i and T_i and commitment and decommitment of (U_i, T_i) (5C)
        const [publicVAShares_1, publicVAShares_2] = [sign1, sign2];
        const [UT1, UT2] = [
            ecdsa.verifyVAShares(sign1, [publicVAShares_2]),
            ecdsa.verifyVAShares(sign2, [publicVAShares_1]),
        ];
        // Step 5C: Calculations of U_i, T_i done by Ecdsa.verifyVAShares above,
        //          and broadcast commitment of (U_i, T_i) to other parties.
        //          The following values will be sent via communication channel at the end of 5C.
        // const commitmentUT1 = UT1.comDecomUT.commitment;
        // const commitmentUT2 = UT2.comDecomUT.commitment;
        // Step 5D: After having received all commitments of (U_i, T_i) from other parties,
        //          each party will broadcast decommitment of (U_i, T_i) returned by Ecdsa.verifyVAShares() above
        //          to other parties.  Then Ecdsa.verifyUTShares() below will:
        //  - verify commitments of (U_i, T_i) received from other parties (5D)
        //  - calculate U as sum of all U_i, calculate T as sum of all T_i (5D)
        //  - if U equals T, then return own SShare which is being returned by Ecdsa.sign() right now (5E)
        const [publicUTShares_1, publicUTShares_2] = [UT1, UT2];
        const [signature1, signature2] = [
            ecdsa.verifyUTShares(UT1, [publicUTShares_2]),
            ecdsa.verifyUTShares(UT2, [publicUTShares_1]),
        ];
        // Step 5E: Broadcast s_i returned by Ecdsa.verifyUTShares() above to other parties.
        //          Verify the sum of s_i should be a valid signature.
        const signature = ecdsa.constructSignature([signature1, signature2]);
        ecdsa.verify(message, signature).should.be.true();
    });
    it('sign phase 5 fail - malicious player cheats with bad s share', async function () {
        const message = Buffer.from('GG18 PHASE 5');
        const [sign1, sign2] = [
            ecdsa.generateVAProofs(message, ecdsa.sign(message, signCombine1.oShare, signCombine2.dShare)),
            ecdsa.generateVAProofs(message, ecdsa.sign(message, signCombine2.oShare, signCombine1.dShare)),
        ];
        sign1.R.should.equal(sign2.R);
        sign1.y.should.equal(sign2.y);
        sign1.m.toString('hex').should.equal(sign2.m.toString('hex'));
        // Change the s share of sign1, and recalcualte its V along with the commitment/proof by following protocol.
        const bad_s = (0, sdk_lib_mpc_1.hexToBigInt)(sign1.s) + BigInt(1);
        const bad_V = tss_1.Ecdsa.curve.pointAdd(tss_1.Ecdsa.curve.pointMultiply((0, sdk_lib_mpc_1.hexToBigInt)(sign1.R), bad_s), tss_1.Ecdsa.curve.basePointMult(sign1.l));
        const comDecom_V_A = sdk_lib_mpc_1.HashCommitment.createCommitment(Buffer.concat([
            (0, sdk_lib_mpc_1.bigIntToBufferBE)(bad_V, tss_1.Ecdsa.curve.pointBytes),
            (0, sdk_lib_mpc_1.bigIntToBufferBE)(sign1.A, tss_1.Ecdsa.curve.pointBytes),
        ]));
        const zkVProof = sdk_lib_mpc_1.EcdsaZkVProof.createZkVProof(bad_V, bad_s, sign1.l, (0, sdk_lib_mpc_1.hexToBigInt)(sign1.R), tss_1.Ecdsa.curve, sign1.proofContext);
        sign1.s = (0, sdk_lib_mpc_1.bigIntToBufferBE)(bad_s, 32).toString('hex');
        sign1.V = bad_V;
        sign1.comDecomVA = comDecom_V_A;
        sign1.zkVProofV = zkVProof;
        // 5B will pass.
        const [publicVAShares_1, publicVAShares_2] = [sign1, sign2];
        const [UT1, UT2] = [
            ecdsa.verifyVAShares(sign1, [publicVAShares_2]),
            ecdsa.verifyVAShares(sign2, [publicVAShares_1]),
        ];
        // But verification at beginning of 5E will fail.
        const [publicUTShares_1, publicUTShares_2] = [UT1, UT2];
        (() => ecdsa.verifyUTShares(UT1, [publicUTShares_2])).should.throw('Sum of all U_i does not match sum of all T_i');
        (() => ecdsa.verifyUTShares(UT2, [publicUTShares_1])).should.throw('Sum of all U_i does not match sum of all T_i');
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNkc2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi90ZXN0L3VuaXQvYWNjb3VudC1saWIvbXBjL3Rzcy9lY2RzYS9lY2RzYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdFQUFrRDtBQUNsRCxrQkFBZ0I7QUFDaEIsa0RBQTBCO0FBQzFCLG9EQVE0QjtBQUM1QixtRUFBa0U7QUFNbEUseUNBQThDO0FBQzlDLDhEQUEwRDtBQUUxRCxNQUFNLFlBQVksR0FBRyxJQUFBLGtDQUFlLEdBQUUsQ0FBQyxNQUFNLENBQUM7QUFFOUMsUUFBUSxDQUFDLFdBQVcsRUFBRTtJQUNwQixNQUFNLEtBQUssR0FBRyxJQUFJLFdBQUssRUFBRSxDQUFDO0lBRTFCLElBQUksWUFBMkIsRUFBRSxZQUEyQixDQUFDO0lBRTdELE1BQU0sQ0FBQyxvQ0FBb0MsRUFBRSxLQUFLO1FBQ2hELE1BQU0sZUFBZSxHQUFHLGVBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLG9CQUFvQixDQUFDLENBQUM7UUFFekUsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEUsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQywyQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEUsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFD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S0FBSyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztTQUNoRCxDQUFDO1FBRUYsaURBQWlEO1FBQ2pELE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsR0FBb0IsRUFBRSxHQUFvQixDQUFDLENBQUM7UUFDMUYsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLEdBQUcsRUFBRSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztRQUNuSCxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsR0FBRyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO0lBQ3JILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYWlsbGllckJpZ2ludCBmcm9tICdwYWlsbGllci1iaWdpbnQnO1xuaW1wb3J0ICdzaG91bGQnO1xuaW1wb3J0IHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7XG4gIEVjZHNhUGFpbGxpZXJQcm9vZixcbiAgRWNkc2FSYW5nZVByb29mLFxuICBFY2RzYVR5cGVzLFxuICBFY2RzYVprVlByb29mLFxuICBIYXNoQ29tbWl0bWVudCxcbiAgaGV4VG9CaWdJbnQsXG4gIGJpZ0ludFRvQnVmZmVyQkUsXG59IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5pbXBvcnQgeyBFY2RzYSB9IGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hY2NvdW50LWxpYi9tcGMvdHNzJztcbmltcG9ydCB7XG4gIFB1YmxpY1VUU2hhcmUsXG4gIFB1YmxpY1ZBU2hhcmVXaXRoUHJvb2ZzLFxuICBTaWduQ29tYmluZVJULFxufSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYWNjb3VudC1saWIvbXBjL3Rzcy9lY2RzYS90eXBlcyc7XG5pbXBvcnQgeyBwYWlsbGllcktleVBhaXJzIH0gZnJvbSAnLi9maXh0dXJlcyc7XG5pbXBvcnQgeyBsb2FkV2ViQXNzZW1ibHkgfSBmcm9tICdAYml0Z28vc2RrLW9wZW5zc2xieXRlcyc7XG5cbmNvbnN0IG9wZW5TU0xCeXRlcyA9IGxvYWRXZWJBc3NlbWJseSgpLmJ1ZmZlcjtcblxuZGVzY3JpYmUoJ2VjZHNhIHRzcycsIGZ1bmN0aW9uICgpIHtcbiAgY29uc3QgZWNkc2EgPSBuZXcgRWNkc2EoKTtcblxuICBsZXQgc2lnbkNvbWJpbmUxOiBTaWduQ29tYmluZVJULCBzaWduQ29tYmluZTI6IFNpZ25Db21iaW5lUlQ7XG5cbiAgYmVmb3JlKCdnZW5lcmF0ZSBrZXkgYW5kIHNpZ24gcGhhc2UgMSB0byA0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHBhaWxsaWVyS2V5U3R1YiA9IHNpbm9uLnN0dWIocGFpbGxpZXJCaWdpbnQsICdnZW5lcmF0ZVJhbmRvbUtleXMnKTtcblxuICAgIHBhaWxsaWVyS2V5U3R1Yi5vbkNhbGwoMCkucmV0dXJucyhQcm9taXNlLnJlc29sdmUocGFpbGxpZXJLZXlQYWlyc1swXSkpO1xuICAgIHBhaWxsaWVyS2V5U3R1Yi5vbkNhbGwoMSkucmV0dXJucyhQcm9taXNlLnJlc29sdmUocGFpbGxpZXJLZXlQYWlyc1sxXSkpO1xuICAgIHBhaWxsaWVyS2V5U3R1Yi5vbkNhbGwoMikucmV0dXJucyhQcm9taXNlLnJlc29sdmUocGFpbGxpZXJLZXlQYWlyc1syXSkpO1xuXG4gICAgY29uc3QgW2tleVNoYXJlMSwga2V5U2hhcmUyLCBrZXlTaGFyZTNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgZWNkc2Eua2V5U2hhcmUoMSwgMiwgMyksXG4gICAgICBlY2RzYS5rZXlTaGFyZSgyLCAyLCAzKSxcbiAgICAgIGVjZHNhLmtleVNoYXJlKDMsIDIsIDMpLFxuICAgIF0pO1xuXG4gICAgY29uc3QgW2tleUNvbWJpbmVkMSwga2V5Q29tYmluZWQyLCBrZXlDb21iaW5lZDNdID0gW1xuICAgICAgZWNkc2Eua2V5Q29tYmluZShrZXlTaGFyZTEucFNoYXJlLCBba2V5U2hhcmUyLm5TaGFyZXNbMV0sIGtleVNoYXJlMy5uU2hhcmVzWzFdXSksXG4gICAgICBlY2RzYS5rZXlDb21iaW5lKGtleVNoYXJlMi5wU2hhcmUsIFtrZXlTaGFyZTEublNoYXJlc1syXSwga2V5U2hhcmUzLm5TaGFyZXNbMl1dKSxcbiAgICAgIGVjZHNhLmtleUNvbWJpbmUoa2V5U2hhcmUzLnBTaGFyZSwgW2tleVNoYXJlMS5uU2hhcmVzWzNdLCBrZXlTaGFyZTIublNoYXJlc1szXV0pLFxuICAgIF07XG5cbiAgICBrZXlDb21iaW5lZDEueFNoYXJlLnkuc2hvdWxkLmVxdWFsKGtleUNvbWJpbmVkMi54U2hhcmUueSk7XG4gICAga2V5Q29tYmluZWQxLnhTaGFyZS55LnNob3VsZC5lcXVhbChrZXlDb21iaW5lZDMueFNoYXJlLnkpO1xuXG4gICAgLy8gQ29sbGVjdCBhbGwgVlNTIGZyb20gblNoYXJlcyBhbmQgdmVyaWZ5IFNjaG5vcnIgcHJvb2ZzIGFnYWluc3QgWF9pLlxuICAgIC8vIE5vdGUgdGhhdCB0aGlzIGlzIHNvbWV0aGluZyBXUCBuZWVkcyB0byBkbyBhZnRlciBrZXlDb21iaW5lL2tleURlcml2ZS5cbiAgICBjb25zdCBZID0gaGV4VG9CaWdJbnQoa2V5Q29tYmluZWQxLnhTaGFyZS55KTtcblxuICAgIGNvbnN0IFZTU3MgPSBbXG4gICAgICBbaGV4VG9CaWdJbnQoa2V5U2hhcmUxLm5TaGFyZXNbMl0udiEpXSxcbiAgICAgIFtoZXhUb0JpZ0ludChrZXlTaGFyZTIublNoYXJlc1szXS52ISldLFxuICAgICAgW2hleFRvQmlnSW50KGtleVNoYXJlMy5uU2hhcmVzWzFdLnYhKV0sXG4gICAgXTtcblxuICAgIGVjZHNhLnZlcmlmeVNjaG5vcnJQcm9vZlgoWSwgVlNTcywgMSwga2V5Q29tYmluZWQxLnhTaGFyZS5zY2hub3JyUHJvb2ZYKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIGVjZHNhLnZlcmlmeVNjaG5vcnJQcm9vZlgoWSwgVlNTcywgMiwga2V5Q29tYmluZWQyLnhTaGFyZS5zY2hub3JyUHJvb2ZYKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIGVjZHNhLnZlcmlmeVNjaG5vcnJQcm9vZlgoWSwgVlNTcywgMywga2V5Q29tYmluZWQzLnhTaGFyZS5zY2hub3JyUHJvb2ZYKS5zaG91bGQuYmUudHJ1ZSgpO1xuXG4gICAgLy8gVmVyaWZ5IFNjaG5vcnIgcHJvb2ZzIGFnYWluc3QgWF9pIGZvciBrZXlEZXJpdmUgYW5kIHN1YnNlcXVlbnQga2V5Q29tYmluZS5cbiAgICBjb25zdCBwYXRoID0gJ20vMC8xLzInO1xuICAgIGNvbnN0IGtleURlcml2ZTEgPSBlY2RzYS5rZXlEZXJpdmUoa2V5U2hhcmUxLnBTaGFyZSwgW2tleVNoYXJlMi5uU2hhcmVzWzFdLCBrZXlTaGFyZTMublNoYXJlc1sxXV0sIHBhdGgpO1xuXG4gICAgLy8gTm90ZSB0aGUgVlNTcyB1c2VkIGhlcmUgYXJlIGRpZmZlcmVudCBmcm9tIHRoZSBvbmVzIHVzZWQgYWJvdmUuXG4gICAgY29uc3QgZGVyaXZlZFkgPSBoZXhUb0JpZ0ludChrZXlEZXJpdmUxLnhTaGFyZS55KTtcbiAgICBjb25zdCBkZXJpdmVkVlNTcyA9IFtcbiAgICAgIFtoZXhUb0JpZ0ludChrZXlEZXJpdmUxLm5TaGFyZXNbMl0udiEpXSxcbiAgICAgIFtoZXhUb0JpZ0ludChrZXlTaGFyZTIublNoYXJlc1szXS52ISldLFxuICAgICAgW2hleFRvQmlnSW50KGtleVNoYXJlMy5uU2hhcmVzWzFdLnYhKV0sXG4gICAgXTtcbiAgICBlY2RzYS52ZXJpZnlTY2hub3JyUHJvb2ZYKGRlcml2ZWRZLCBkZXJpdmVkVlNTcywgMSwga2V5RGVyaXZlMS54U2hhcmUuc2Nobm9yclByb29mWCkuc2hvdWxkLmJlLnRydWUoKTtcblxuICAgIGNvbnN0IGtleUNvbWJpbmVkMkZyb21LZXlEZXJpdmUxID0gZWNkc2Eua2V5Q29tYmluZShrZXlTaGFyZTIucFNoYXJlLCBbXG4gICAgICBrZXlEZXJpdmUxLm5TaGFyZXNbMl0sXG4gICAgICBrZXlTaGFyZTMublNoYXJlc1syXSxcbiAgICBdKTtcbiAgICBlY2RzYVxuICAgICAgLnZlcmlmeVNjaG5vcnJQcm9vZlgoZGVyaXZlZFksIGRlcml2ZWRWU1NzLCAyLCBrZXlDb21iaW5lZDJGcm9tS2V5RGVyaXZlMS54U2hhcmUuc2Nobm9yclByb29mWClcbiAgICAgIC5zaG91bGQuYmUudHJ1ZSgpO1xuXG4gICAgY29uc3QgW250aWxkZTEsIG50aWxkZTJdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgRWNkc2FSYW5nZVByb29mLmdlbmVyYXRlTnRpbGRlKG9wZW5TU0xCeXRlcywgNTEyKSxcbiAgICAgIEVjZHNhUmFuZ2VQcm9vZi5nZW5lcmF0ZU50aWxkZShvcGVuU1NMQnl0ZXMsIDUxMiksXG4gICAgXSk7XG5cbiAgICBjb25zdCBbc2VyaWFsaXplTnRpbGRlMSwgc2VyaWFsaXplTnRpbGRlMl0gPSBbXG4gICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZU50aWxkZVdpdGhQcm9vZnMobnRpbGRlMSksXG4gICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZU50aWxkZVdpdGhQcm9vZnMobnRpbGRlMiksXG4gICAgXTtcblxuICAgIGNvbnN0IFtpbmRleDEsIGluZGV4Ml0gPSBba2V5Q29tYmluZWQxLnhTaGFyZS5pLCBrZXlDb21iaW5lZDIueFNoYXJlLmldO1xuXG4gICAgY29uc3QgW3BhaWxsaWVyTjF0bzIsIHBhaWxsaWVyTjJ0bzFdID0gW2tleUNvbWJpbmVkMS55U2hhcmVzW2luZGV4Ml0ubiwga2V5Q29tYmluZWQyLnlTaGFyZXNbaW5kZXgxXS5uXTtcblxuICAgIGNvbnN0IFtwYWlsbGllckNoYWxsZW5nZXIxdG8yLCBwYWlsbGllckNoYWxsZW5nZXIydG8xXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIEVjZHNhUGFpbGxpZXJQcm9vZi5nZW5lcmF0ZVAoaGV4VG9CaWdJbnQocGFpbGxpZXJOMXRvMikpLFxuICAgICAgRWNkc2FQYWlsbGllclByb29mLmdlbmVyYXRlUChoZXhUb0JpZ0ludChwYWlsbGllck4ydG8xKSksXG4gICAgXSk7XG5cbiAgICBjb25zdCBbeFNoYXJlMSwgeFNoYXJlMl0gPSBbXG4gICAgICBlY2RzYS5hcHBlbmRDaGFsbGVuZ2UoXG4gICAgICAgIGtleUNvbWJpbmVkMS54U2hhcmUsXG4gICAgICAgIHNlcmlhbGl6ZU50aWxkZTEsXG4gICAgICAgIEVjZHNhVHlwZXMuc2VyaWFsaXplUGFpbGxpZXJDaGFsbGVuZ2UoeyBwOiBwYWlsbGllckNoYWxsZW5nZXIxdG8yIH0pXG4gICAgICApLFxuICAgICAgZWNkc2EuYXBwZW5kQ2hhbGxlbmdlKFxuICAgICAgICBrZXlDb21iaW5lZDIueFNoYXJlLFxuICAgICAgICBzZXJpYWxpemVOdGlsZGUyLFxuICAgICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZVBhaWxsaWVyQ2hhbGxlbmdlKHsgcDogcGFpbGxpZXJDaGFsbGVuZ2VyMnRvMSB9KVxuICAgICAgKSxcbiAgICBdO1xuXG4gICAgY29uc3QgeVNoYXJlMiA9IGVjZHNhLmFwcGVuZENoYWxsZW5nZShcbiAgICAgIGtleUNvbWJpbmVkMS55U2hhcmVzW2luZGV4Ml0sXG4gICAgICBzZXJpYWxpemVOdGlsZGUyLFxuICAgICAgRWNkc2FUeXBlcy5zZXJpYWxpemVQYWlsbGllckNoYWxsZW5nZSh7IHA6IHBhaWxsaWVyQ2hhbGxlbmdlcjJ0bzEgfSlcbiAgICApO1xuXG4gICAgY29uc3Qgc2lnblNoYXJlcyA9IGF3YWl0IGVjZHNhLnNpZ25TaGFyZSh4U2hhcmUxLCB5U2hhcmUyKTtcblxuICAgIGNvbnN0IHNpZ25Db252ZXJ0UzIxID0gYXdhaXQgZWNkc2Euc2lnbkNvbnZlcnRTdGVwMSh7XG4gICAgICB4U2hhcmU6IHhTaGFyZTIsXG4gICAgICB5U2hhcmU6IGtleUNvbWJpbmVkMi55U2hhcmVzW2luZGV4MV0sXG4gICAgICBrU2hhcmU6IHNpZ25TaGFyZXMua1NoYXJlLFxuICAgIH0pO1xuICAgIGNvbnN0IHNpZ25Db252ZXJ0UzEyID0gYXdhaXQgZWNkc2Euc2lnbkNvbnZlcnRTdGVwMih7XG4gICAgICBhU2hhcmU6IHNpZ25Db252ZXJ0UzIxLmFTaGFyZSxcbiAgICAgIHdTaGFyZTogc2lnblNoYXJlcy53U2hhcmUsXG4gICAgfSk7XG4gICAgY29uc3Qgc2lnbkNvbnZlcnRTMjFfMiA9IGF3YWl0IGVjZHNhLnNpZ25Db252ZXJ0U3RlcDMoe1xuICAgICAgbXVTaGFyZTogc2lnbkNvbnZlcnRTMTIubXVTaGFyZSxcbiAgICAgIGJTaGFyZTogc2lnbkNvbnZlcnRTMjEuYlNoYXJlLFxuICAgIH0pO1xuXG4gICAgW3NpZ25Db21iaW5lMSwgc2lnbkNvbWJpbmUyXSA9IFtcbiAgICAgIGVjZHNhLnNpZ25Db21iaW5lKHtcbiAgICAgICAgZ1NoYXJlOiBzaWduQ29udmVydFMxMi5nU2hhcmUsXG4gICAgICAgIHNpZ25JbmRleDoge1xuICAgICAgICAgIGk6IHNpZ25Db252ZXJ0UzEyLm11U2hhcmUuaSxcbiAgICAgICAgICBqOiBzaWduQ29udmVydFMxMi5tdVNoYXJlLmosXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICAgIGVjZHNhLnNpZ25Db21iaW5lKHtcbiAgICAgICAgZ1NoYXJlOiBzaWduQ29udmVydFMyMV8yLmdTaGFyZSxcbiAgICAgICAgc2lnbkluZGV4OiB7XG4gICAgICAgICAgaTogc2lnbkNvbnZlcnRTMjFfMi5zaWduSW5kZXguaSxcbiAgICAgICAgICBqOiBzaWduQ29udmVydFMyMV8yLnNpZ25JbmRleC5qLFxuICAgICAgICB9LFxuICAgICAgfSksXG4gICAgXTtcbiAgfSk7XG5cbiAgaXQoJ3NpZ24gcGhhc2UgNSBzaG91bGQgc3VjY2VlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBUT0RPKEhTTS0xMjkpOiBUaGVyZSBpcyBhIGJ1ZyBzaWduaW5nIHVuaGFzaGVkIG1lc3NhZ2UgKGFsdGhvdWdoIHRoaXMgZGV2aWF0ZXMgZnJvbSBEU0Egc3BlYykgaWYgdGhlIG1lc3NhZ2UgaXMgYSBsaXR0bGUgbG9uZy5cbiAgICAvLyAgICAgICBTb21lIGRpc2NyZXBhbmN5IGJldHdlZW4gRWNkc2Euc2lnbiBhbmQgc2VjcDI1NmsxLnJlY292ZXJQdWJsaWNLZXkgb24gaGFuZGxpbmcgdGhlIG1lc3NhZ2UgaW5wdXQuXG4gICAgY29uc3QgbWVzc2FnZSA9IEJ1ZmZlci5mcm9tKCdHRzE4IFBIQVNFIDUnKTtcblxuICAgIC8vIFN0YXJ0aW5nIHBoYXNlIDVcbiAgICAvLyBJbiBhZGRpdGlvbiB0byByZXR1cm5pbmcgc19pLCBFY2RzYS5zaWduKCkgbm93IGFsc28gY2FsY3VsYXRlcyBkYXRhIG5lZWRlZCBmb3Igc3RlcHMgNUEgYW5kIDVCOlxuICAgIC8vICAgLSBzYW1wbGUgcmFuZG9tIGxfaSBhbmQgcmhvX2kgKDVBKVxuICAgIC8vICAgLSBjb21wdXRlcyBWX2kgYW5kIEFfaSAoNUIpXVxuICAgIC8vICAgLSBjb21wdXRlcyBjb21taXRtZW50IGFuZCBkZWNvbW1pdG1lbnQgb2YgKFZfaSwgQV9pKSAoNUEsIDVCKVxuICAgIC8vICAgLSBnZW5lcmF0ZXMgcHJvb2ZzIG9mIGtub3dsZWRnZSBvZiBzX2ksIGxfaSwgcmhvX2kgdy5yLnQuIFZfaSwgQV9pICg1QilcbiAgICBjb25zdCBbc2lnbjEsIHNpZ24yXSA9IFtcbiAgICAgIGVjZHNhLmdlbmVyYXRlVkFQcm9vZnMobWVzc2FnZSwgZWNkc2Euc2lnbihtZXNzYWdlLCBzaWduQ29tYmluZTEub1NoYXJlLCBzaWduQ29tYmluZTIuZFNoYXJlKSksXG4gICAgICBlY2RzYS5nZW5lcmF0ZVZBUHJvb2ZzKG1lc3NhZ2UsIGVjZHNhLnNpZ24obWVzc2FnZSwgc2lnbkNvbWJpbmUyLm9TaGFyZSwgc2lnbkNvbWJpbmUxLmRTaGFyZSkpLFxuICAgIF07XG5cbiAgICBzaWduMS5SLnNob3VsZC5lcXVhbChzaWduMi5SKTtcbiAgICBzaWduMS55LnNob3VsZC5lcXVhbChzaWduMi55KTtcbiAgICBzaWduMS5tLnRvU3RyaW5nKCdoZXgnKS5zaG91bGQuZXF1YWwoc2lnbjIubS50b1N0cmluZygnaGV4JykpO1xuXG4gICAgLy8gU3RlcCA1QTogQ2FsY3VsYXRpb25zIGRvbmUgYnkgRWNkc2Euc2lnbigpIGFib3ZlLCBhbmQgYnJvYWRjYXN0IGNvbW1pdG1lbnQgb2YgKFZfaSwgQV9pKSB0byBvdGhlciBwYXJ0aWVzLlxuICAgIC8vICAgICAgICAgIFRoZSBmb2xsb3dpbmcgdmFsdWVzIHdpbGwgYmUgc2VudCB2aWEgY29tbXVuaWNhdGlvbiBjaGFubmVsIGF0IHRoZSBlbmQgb2YgNUEuXG4gICAgLy8gY29uc3QgY29tbWl0bWVudFZBMSA9IHNpZ24xLmNvbURlY29tVkEuY29tbWl0bWVudDtcbiAgICAvLyBjb25zdCBjb21taXRtZW50VkEyID0gc2lnbjIuY29tRGVjb21WQS5jb21taXRtZW50O1xuXG4gICAgLy8gU3RlcCA1QjogQWZ0ZXIgaGF2aW5nIHJlY2VpdmVkIGFsbCBjb21taXRtZW50cyBvZiAoVl9pLCBBX2kpIGZyb20gb3RoZXIgcGFydGllcyxcbiAgICAvLyAgICAgICAgICBlYWNoIHBhcnR5IHdpbGwgYnJvYWRjYXN0IGRlY29tbWl0bWVudCBvZiAoVl9pLCBBX2kpIGFuZCBaSyBwcm9vZnMgcmV0dXJuZWQgYnkgRWNkc2Euc2lnbigpIGFib3ZlXG4gICAgLy8gICAgICAgICAgdG8gb3RoZXIgcGFydGllcy4gIFRoZW4gRWNkc2EudmVyaWZ5VkFTaGFyZXMoKSBiZWxvdyB3aWxsOlxuICAgIC8vICAgLSB2ZXJpZnkgY29tbWl0bWVudHMgb2YgKFZfaSwgQV9pKSByZWNlaXZlZCBmcm9tIG90aGVyIHBhcnRpZXMgKDVCKVxuICAgIC8vICAgLSB2ZXJpZnkgWksgcHJvb2ZzIG9mIChWX2ksIEFfaSkgcmVjZWl2ZWQgZnJvbSBvdGhlciBwYXJ0aWVzICg1QilcbiAgICAvLyAgIC0gY2FsY3VsYXRlIFYgb3V0IG9mIEcsIHksIHIsIG0sIGFuZCBhbGwgVl9pLCBjYWxjdWxhdGUgQSBhcyBzdW0gb2YgYWxsIEFfaSAoNUIpXG4gICAgLy8gICAtIGNhbGN1bGF0ZSBVX2kgYW5kIFRfaSBhbmQgY29tbWl0bWVudCBhbmQgZGVjb21taXRtZW50IG9mIChVX2ksIFRfaSkgKDVDKVxuICAgIGNvbnN0IFtwdWJsaWNWQVNoYXJlc18xLCBwdWJsaWNWQVNoYXJlc18yXSA9IFtzaWduMSBhcyBQdWJsaWNWQVNoYXJlV2l0aFByb29mcywgc2lnbjIgYXMgUHVibGljVkFTaGFyZVdpdGhQcm9vZnNdO1xuICAgIGNvbnN0IFtVVDEsIFVUMl0gPSBbXG4gICAgICBlY2RzYS52ZXJpZnlWQVNoYXJlcyhzaWduMSwgW3B1YmxpY1ZBU2hhcmVzXzJdKSxcbiAgICAgIGVjZHNhLnZlcmlmeVZBU2hhcmVzKHNpZ24yLCBbcHVibGljVkFTaGFyZXNfMV0pLFxuICAgIF07XG5cbiAgICAvLyBTdGVwIDVDOiBDYWxjdWxhdGlvbnMgb2YgVV9pLCBUX2kgZG9uZSBieSBFY2RzYS52ZXJpZnlWQVNoYXJlcyBhYm92ZSxcbiAgICAvLyAgICAgICAgICBhbmQgYnJvYWRjYXN0IGNvbW1pdG1lbnQgb2YgKFVfaSwgVF9pKSB0byBvdGhlciBwYXJ0aWVzLlxuICAgIC8vICAgICAgICAgIFRoZSBmb2xsb3dpbmcgdmFsdWVzIHdpbGwgYmUgc2VudCB2aWEgY29tbXVuaWNhdGlvbiBjaGFubmVsIGF0IHRoZSBlbmQgb2YgNUMuXG4gICAgLy8gY29uc3QgY29tbWl0bWVudFVUMSA9IFVUMS5jb21EZWNvbVVULmNvbW1pdG1lbnQ7XG4gICAgLy8gY29uc3QgY29tbWl0bWVudFVUMiA9IFVUMi5jb21EZWNvbVVULmNvbW1pdG1lbnQ7XG5cbiAgICAvLyBTdGVwIDVEOiBBZnRlciBoYXZpbmcgcmVjZWl2ZWQgYWxsIGNvbW1pdG1lbnRzIG9mIChVX2ksIFRfaSkgZnJvbSBvdGhlciBwYXJ0aWVzLFxuICAgIC8vICAgICAgICAgIGVhY2ggcGFydHkgd2lsbCBicm9hZGNhc3QgZGVjb21taXRtZW50IG9mIChVX2ksIFRfaSkgcmV0dXJuZWQgYnkgRWNkc2EudmVyaWZ5VkFTaGFyZXMoKSBhYm92ZVxuICAgIC8vICAgICAgICAgIHRvIG90aGVyIHBhcnRpZXMuICBUaGVuIEVjZHNhLnZlcmlmeVVUU2hhcmVzKCkgYmVsb3cgd2lsbDpcbiAgICAvLyAgLSB2ZXJpZnkgY29tbWl0bWVudHMgb2YgKFVfaSwgVF9pKSByZWNlaXZlZCBmcm9tIG90aGVyIHBhcnRpZXMgKDVEKVxuICAgIC8vICAtIGNhbGN1bGF0ZSBVIGFzIHN1bSBvZiBhbGwgVV9pLCBjYWxjdWxhdGUgVCBhcyBzdW0gb2YgYWxsIFRfaSAoNUQpXG4gICAgLy8gIC0gaWYgVSBlcXVhbHMgVCwgdGhlbiByZXR1cm4gb3duIFNTaGFyZSB3aGljaCBpcyBiZWluZyByZXR1cm5lZCBieSBFY2RzYS5zaWduKCkgcmlnaHQgbm93ICg1RSlcbiAgICBjb25zdCBbcHVibGljVVRTaGFyZXNfMSwgcHVibGljVVRTaGFyZXNfMl0gPSBbVVQxIGFzIFB1YmxpY1VUU2hhcmUsIFVUMiBhcyBQdWJsaWNVVFNoYXJlXTtcbiAgICBjb25zdCBbc2lnbmF0dXJlMSwgc2lnbmF0dXJlMl0gPSBbXG4gICAgICBlY2RzYS52ZXJpZnlVVFNoYXJlcyhVVDEsIFtwdWJsaWNVVFNoYXJlc18yXSksXG4gICAgICBlY2RzYS52ZXJpZnlVVFNoYXJlcyhVVDIsIFtwdWJsaWNVVFNoYXJlc18xXSksXG4gICAgXTtcblxuICAgIC8vIFN0ZXAgNUU6IEJyb2FkY2FzdCBzX2kgcmV0dXJuZWQgYnkgRWNkc2EudmVyaWZ5VVRTaGFyZXMoKSBhYm92ZSB0byBvdGhlciBwYXJ0aWVzLlxuICAgIC8vICAgICAgICAgIFZlcmlmeSB0aGUgc3VtIG9mIHNfaSBzaG91bGQgYmUgYSB2YWxpZCBzaWduYXR1cmUuXG4gICAgY29uc3Qgc2lnbmF0dXJlID0gZWNkc2EuY29uc3RydWN0U2lnbmF0dXJlKFtzaWduYXR1cmUxLCBzaWduYXR1cmUyXSk7XG4gICAgZWNkc2EudmVyaWZ5KG1lc3NhZ2UsIHNpZ25hdHVyZSkuc2hvdWxkLmJlLnRydWUoKTtcbiAgfSk7XG5cbiAgaXQoJ3NpZ24gcGhhc2UgNSBmYWlsIC0gbWFsaWNpb3VzIHBsYXllciBjaGVhdHMgd2l0aCBiYWQgcyBzaGFyZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBtZXNzYWdlID0gQnVmZmVyLmZyb20oJ0dHMTggUEhBU0UgNScpO1xuXG4gICAgY29uc3QgW3NpZ24xLCBzaWduMl0gPSBbXG4gICAgICBlY2RzYS5nZW5lcmF0ZVZBUHJvb2ZzKG1lc3NhZ2UsIGVjZHNhLnNpZ24obWVzc2FnZSwgc2lnbkNvbWJpbmUxLm9TaGFyZSwgc2lnbkNvbWJpbmUyLmRTaGFyZSkpLFxuICAgICAgZWNkc2EuZ2VuZXJhdGVWQVByb29mcyhtZXNzYWdlLCBlY2RzYS5zaWduKG1lc3NhZ2UsIHNpZ25Db21iaW5lMi5vU2hhcmUsIHNpZ25Db21iaW5lMS5kU2hhcmUpKSxcbiAgICBdO1xuXG4gICAgc2lnbjEuUi5zaG91bGQuZXF1YWwoc2lnbjIuUik7XG4gICAgc2lnbjEueS5zaG91bGQuZXF1YWwoc2lnbjIueSk7XG4gICAgc2lnbjEubS50b1N0cmluZygnaGV4Jykuc2hvdWxkLmVxdWFsKHNpZ24yLm0udG9TdHJpbmcoJ2hleCcpKTtcblxuICAgIC8vIENoYW5nZSB0aGUgcyBzaGFyZSBvZiBzaWduMSwgYW5kIHJlY2FsY3VhbHRlIGl0cyBWIGFsb25nIHdpdGggdGhlIGNvbW1pdG1lbnQvcHJvb2YgYnkgZm9sbG93aW5nIHByb3RvY29sLlxuICAgIGNvbnN0IGJhZF9zID0gaGV4VG9CaWdJbnQoc2lnbjEucykgKyBCaWdJbnQoMSk7XG5cbiAgICBjb25zdCBiYWRfViA9IEVjZHNhLmN1cnZlLnBvaW50QWRkKFxuICAgICAgRWNkc2EuY3VydmUucG9pbnRNdWx0aXBseShoZXhUb0JpZ0ludChzaWduMS5SKSwgYmFkX3MpLFxuICAgICAgRWNkc2EuY3VydmUuYmFzZVBvaW50TXVsdChzaWduMS5sKVxuICAgICk7XG5cbiAgICBjb25zdCBjb21EZWNvbV9WX0EgPSBIYXNoQ29tbWl0bWVudC5jcmVhdGVDb21taXRtZW50KFxuICAgICAgQnVmZmVyLmNvbmNhdChbXG4gICAgICAgIGJpZ0ludFRvQnVmZmVyQkUoYmFkX1YsIEVjZHNhLmN1cnZlLnBvaW50Qnl0ZXMpLFxuICAgICAgICBiaWdJbnRUb0J1ZmZlckJFKHNpZ24xLkEsIEVjZHNhLmN1cnZlLnBvaW50Qnl0ZXMpLFxuICAgICAgXSlcbiAgICApO1xuICAgIGNvbnN0IHprVlByb29mID0gRWNkc2Faa1ZQcm9vZi5jcmVhdGVaa1ZQcm9vZihcbiAgICAgIGJhZF9WLFxuICAgICAgYmFkX3MsXG4gICAgICBzaWduMS5sLFxuICAgICAgaGV4VG9CaWdJbnQoc2lnbjEuUiksXG4gICAgICBFY2RzYS5jdXJ2ZSxcbiAgICAgIHNpZ24xLnByb29mQ29udGV4dFxuICAgICk7XG5cbiAgICBzaWduMS5zID0gYmlnSW50VG9CdWZmZXJCRShiYWRfcywgMzIpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICBzaWduMS5WID0gYmFkX1Y7XG4gICAgc2lnbjEuY29tRGVjb21WQSA9IGNvbURlY29tX1ZfQTtcbiAgICBzaWduMS56a1ZQcm9vZlYgPSB6a1ZQcm9vZjtcblxuICAgIC8vIDVCIHdpbGwgcGFzcy5cbiAgICBjb25zdCBbcHVibGljVkFTaGFyZXNfMSwgcHVibGljVkFTaGFyZXNfMl0gPSBbc2lnbjEgYXMgUHVibGljVkFTaGFyZVdpdGhQcm9vZnMsIHNpZ24yIGFzIFB1YmxpY1ZBU2hhcmVXaXRoUHJvb2ZzXTtcbiAgICBjb25zdCBbVVQxLCBVVDJdID0gW1xuICAgICAgZWNkc2EudmVyaWZ5VkFTaGFyZXMoc2lnbjEsIFtwdWJsaWNWQVNoYXJlc18yXSksXG4gICAgICBlY2RzYS52ZXJpZnlWQVNoYXJlcyhzaWduMiwgW3B1YmxpY1ZBU2hhcmVzXzFdKSxcbiAgICBdO1xuXG4gICAgLy8gQnV0IHZlcmlmaWNhdGlvbiBhdCBiZWdpbm5pbmcgb2YgNUUgd2lsbCBmYWlsLlxuICAgIGNvbnN0IFtwdWJsaWNVVFNoYXJlc18xLCBwdWJsaWNVVFNoYXJlc18yXSA9IFtVVDEgYXMgUHVibGljVVRTaGFyZSwgVVQyIGFzIFB1YmxpY1VUU2hhcmVdO1xuICAgICgoKSA9PiBlY2RzYS52ZXJpZnlVVFNoYXJlcyhVVDEsIFtwdWJsaWNVVFNoYXJlc18yXSkpLnNob3VsZC50aHJvdygnU3VtIG9mIGFsbCBVX2kgZG9lcyBub3QgbWF0Y2ggc3VtIG9mIGFsbCBUX2knKTtcbiAgICAoKCkgPT4gZWNkc2EudmVyaWZ5VVRTaGFyZXMoVVQyLCBbcHVibGljVVRTaGFyZXNfMV0pKS5zaG91bGQudGhyb3coJ1N1bSBvZiBhbGwgVV9pIGRvZXMgbm90IG1hdGNoIHN1bSBvZiBhbGwgVF9pJyk7XG4gIH0pO1xufSk7XG4iXX0=

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


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