PHP WebShell

Текущая директория: /opt/BitGoJS/modules/account-lib/dist/test/unit/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 });
/**
 * @prettier
 */
const assert_1 = __importDefault(require("assert"));
const crypto_1 = require("crypto");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
const sinon = __importStar(require("sinon"));
const keccak_1 = __importDefault(require("keccak"));
const paillierBigint = __importStar(require("paillier-bigint"));
const ecdsa_1 = require("../fixtures/ecdsa");
describe('TSS ECDSA TESTS', function () {
    const MPC = new sdk_core_1.Ecdsa();
    const base = BigInt('0x010000000000000000000000000000000000000000000000000000000000000000'); // 2^256
    let keyShares;
    let commonPublicKey;
    const seed = Buffer.from('c4d1583a0b7b88626b56f0c83ee6df4d95d99cca73893ffb57c5e4411fa1b2b9c87456080e8d3f03462f065688abc28be2d4af3164d593c50b55269b435ea48d', 'hex');
    let A, B, C;
    before(async () => {
        const paillierMock = sinon
            .stub(paillierBigint, 'generateRandomKeys')
            .onCall(0)
            .resolves(ecdsa_1.paillerKeys[0])
            .onCall(1)
            .resolves(ecdsa_1.paillerKeys[1])
            .onCall(2)
            .resolves(ecdsa_1.paillerKeys[2])
            .onCall(3)
            .resolves(ecdsa_1.paillerKeys[0])
            .onCall(4)
            .resolves(ecdsa_1.paillerKeys[1])
            .onCall(5)
            .resolves(ecdsa_1.paillerKeys[2]);
        const schnorrProofMock = sinon
            .stub(sdk_lib_mpc_1.Schnorr, 'createSchnorrProof')
            .onCall(0)
            .returns(ecdsa_1.schnorrProofs[0])
            .onCall(1)
            .returns(ecdsa_1.schnorrProofs[1])
            .onCall(2)
            .returns(ecdsa_1.schnorrProofs[2])
            .onCall(3)
            .returns(ecdsa_1.schnorrProofs[3])
            .onCall(4)
            .returns(ecdsa_1.schnorrProofs[4])
            .onCall(5)
            .returns(ecdsa_1.schnorrProofs[5]);
        [A, B, C] = await Promise.all([MPC.keyShare(1, 2, 3), MPC.keyShare(2, 2, 3), MPC.keyShare(3, 2, 3)]);
        // Needs to run this serially for testing deterministic key generation
        // to get specific paillier keys to be assigned
        const D = await MPC.keyShare(1, 2, 3, seed);
        const E = await MPC.keyShare(2, 2, 3, seed);
        const F = await MPC.keyShare(3, 2, 3, seed);
        const aKeyCombine = MPC.keyCombine(A.pShare, [B.nShares[1], C.nShares[1]]);
        const bKeyCombine = MPC.keyCombine(B.pShare, [A.nShares[2], C.nShares[2]]);
        const cKeyCombine = MPC.keyCombine(C.pShare, [A.nShares[3], B.nShares[3]]);
        // Shares with specific seeds
        const dKeyCombine = MPC.keyCombine(D.pShare, [E.nShares[1], F.nShares[1]]);
        const eKeyCombine = MPC.keyCombine(E.pShare, [D.nShares[2], F.nShares[2]]);
        const fKeyCombine = MPC.keyCombine(F.pShare, [D.nShares[3], E.nShares[3]]);
        // Shares for derived keys.
        const path = 'm/0/1';
        const aKeyDerive = MPC.keyDerive(A.pShare, [B.nShares[1], C.nShares[1]], path);
        const gKeyCombine = {
            xShare: aKeyDerive.xShare,
            yShares: aKeyCombine.yShares,
        };
        const hKeyCombine = MPC.keyCombine(B.pShare, [aKeyDerive.nShares[2], C.nShares[2]]);
        keyShares = [
            aKeyCombine,
            bKeyCombine,
            cKeyCombine,
            dKeyCombine,
            eKeyCombine,
            fKeyCombine,
            gKeyCombine,
            hKeyCombine,
        ];
        commonPublicKey = aKeyCombine.xShare.y;
        paillierMock.reset();
        paillierMock.restore();
        schnorrProofMock.reset();
        schnorrProofMock.restore();
    });
    describe('Ecdsa Key Generation Test', function () {
        it('should generate keys with correct threshold and share number', async function () {
            for (let index = 0; index < 3; index++) {
                const participantOne = (index % 3) + 1;
                const participantTwo = ((index + 1) % 3) + 1;
                const participantThree = ((index + 2) % 3) + 1;
                keyShares[index].xShare.i.should.equal(participantOne);
                keyShares[index].xShare.y.should.equal(commonPublicKey);
                keyShares[index].xShare.m.should.not.be.Null;
                keyShares[index].xShare.l.should.not.be.Null;
                keyShares[index].xShare.n.should.not.be.Null;
                const chaincode = BigInt('0x' + keyShares[index].xShare.chaincode);
                const isChainCodeValid = chaincode > BigInt(0) && chaincode <= base;
                isChainCodeValid.should.equal(true);
                keyShares[index].yShares[participantTwo].i.should.equal(participantOne);
                keyShares[index].yShares[participantThree].i.should.equal(participantOne);
                keyShares[index].yShares[participantTwo].j.should.equal(participantTwo);
                keyShares[index].yShares[participantThree].j.should.equal(participantThree);
                keyShares[index].yShares[participantTwo].n.should.not.be.Null;
                keyShares[index].yShares[participantThree].n.should.not.be.Null;
                const publicKeyPrefix = keyShares[index].xShare.y.slice(0, 2);
                const isRightPrefix = publicKeyPrefix === '03' || publicKeyPrefix === '02';
                isRightPrefix.should.equal(true);
            }
        });
        it('should generate keyshares with specific seed', async function () {
            // Keys should be deterministic when using seed
            const [, , , D, E, F] = keyShares;
            assert_1.default.deepEqual(D, ecdsa_1.mockDKeyShare);
            assert_1.default.deepEqual(E, ecdsa_1.mockEKeyShare);
            assert_1.default.deepEqual(F, ecdsa_1.mockFKeyShare);
        });
        it('should fail if seed is length less than 64 bytes', async function () {
            await MPC.keyShare(1, 2, 3, (0, crypto_1.randomBytes)(16)).should.be.rejectedWith('Seed must have a length of at least 64 bytes');
            await MPC.keyShare(1, 2, 3, (0, crypto_1.randomBytes)(32)).should.be.rejectedWith('Seed must have a length of at least 64 bytes');
        });
        it('should pass if seed length is greater than 64', async function () {
            const paillierMock = sinon
                .stub(paillierBigint, 'generateRandomKeys')
                .onCall(0)
                .resolves(ecdsa_1.paillerKeys[0]);
            const seed72Bytes = Buffer.from('4f7e914dc9ec696398675d1544aab61cb7a67662ffcbdb4079ec5d682be565d87c1b2de75c943dec14c96586984860268779498e6732473aed9ed9c2538f50bea0af926bdccc0134', 'hex');
            (await MPC.keyShare(1, 2, 3, seed72Bytes)).pShare.u.length.should.equal(64);
            paillierMock.restore();
        });
        it('should calculate correct chaincode while combining', async function () {
            const keyCombine = MPC.keyCombine(ecdsa_1.mockPShare, ecdsa_1.mockNShares);
            keyCombine.xShare.chaincode.should.equal('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc32');
        });
        it('should fail to generate keys with invalid threshold and share number', async function () {
            const invalidConfigs = [
                { index: 1, threshold: 5, numShares: 3 },
                { index: -1, threshold: 2, numShares: 3 },
                { index: 1, threshold: 2, numShares: 1 },
            ];
            for (let index = 0; index < invalidConfigs.length; index++) {
                try {
                    await MPC.keyShare(invalidConfigs[index].index, invalidConfigs[index].threshold, invalidConfigs[index].numShares);
                }
                catch (e) {
                    e.should.equal('Invalid KeyShare Config');
                }
            }
        });
        it('should derive unhardened child keys', async function () {
            // parent key
            const aKeyCombine = keyShares[0];
            const commonKeychain = aKeyCombine.xShare.y + aKeyCombine.xShare.chaincode;
            for (let index = 0; index < 10; index++) {
                const path = `m/0/0/${index}`;
                const subkey = MPC.keyDerive(A.pShare, [B.nShares[1], C.nShares[1]], path);
                const derive1 = MPC.deriveUnhardened(commonKeychain, path);
                const derive2 = MPC.deriveUnhardened(commonKeychain, path);
                derive1.should.equal(derive2, 'derivation should be deterministic');
                (subkey.xShare.y + subkey.xShare.chaincode).should.equal(derive1, 'subkey common keychain should match derived keychain');
            }
        });
    });
    describe('ECDSA Signing', async function () {
        let config;
        before(() => {
            const [A, B, C, D, E, F, G, H] = keyShares;
            config = [
                { signerOne: A, signerTwo: B },
                { signerOne: A, signerTwo: C },
                { signerOne: B, signerTwo: A },
                { signerOne: B, signerTwo: C },
                { signerOne: C, signerTwo: A },
                { signerOne: C, signerTwo: B },
                // Checks signing with specific seed
                { signerOne: D, signerTwo: E },
                { signerOne: E, signerTwo: F },
                { signerOne: F, signerTwo: D },
                // Checks with specific hashing algorithm
                { signerOne: A, signerTwo: B, hash: 'keccak256' },
                // checks with no hashing
                { signerOne: A, signerTwo: B, shouldHash: false },
                // Checks with derived subkey
                { signerOne: G, signerTwo: H },
            ];
        });
        for (let index = 0; index < 9; index++) {
            it(`should properly sign the message case ${index}`, async function () {
                // Step One
                // signerOne, signerTwo have decided to sign the message
                const signerOne = config[index].signerOne;
                const signerOneIndex = signerOne.xShare.i;
                const signerTwo = config[index].signerTwo;
                const signerTwoIndex = signerTwo.xShare.i;
                const [signerOneToTwoPaillierChallenge, signerTwoToOnePaillierChallenge] = await Promise.all([
                    sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_core_1.hexToBigInt)(signerOne.yShares[signerTwoIndex].n)),
                    sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_core_1.hexToBigInt)(signerTwo.yShares[signerOneIndex].n)),
                ]);
                // Step Two
                // First signer generates their range proof challenge.
                const signerOneXShare = MPC.appendChallenge(signerOne.xShare, sdk_lib_mpc_1.EcdsaTypes.serializeNtilde(ecdsa_1.ntildes[index]), sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: signerOneToTwoPaillierChallenge }));
                // Step Three
                //  Second signer generates their range proof challenge.
                const signerTwoXShare = MPC.appendChallenge(signerTwo.xShare, sdk_lib_mpc_1.EcdsaTypes.serializeNtilde(ecdsa_1.ntildes[index + 1]), sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: signerTwoToOnePaillierChallenge }));
                const signerTwoChallenge = { ntilde: signerTwoXShare.ntilde, h1: signerTwoXShare.h1, h2: signerTwoXShare.h2 };
                // Step Four
                // First signer receives the challenge from the second signer and appends it to their YShare
                const signerTwoYShare = MPC.appendChallenge(signerOne.yShares[signerTwoIndex], signerTwoChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: signerTwoToOnePaillierChallenge }));
                // Step Five
                // Sign Shares are created by one of the participants (signerOne)
                // with its private XShare and YShare corresponding to the other participant (signerTwo)
                // This step produces a private WShare which signerOne saves and KShare which signerOne sends to signerTwo
                const signShares = await MPC.signShare(signerOneXShare, signerTwoYShare);
                // Step Six
                // signerTwo receives the KShare from signerOne and uses it produce private
                // BShare (Beta Share) which signerTwo saves and AShare (Alpha Share)
                // which is sent to signerOne
                const signConvertS21 = await MPC.signConvertStep1({
                    xShare: signerTwoXShare,
                    yShare: signerTwo.yShares[signerOneIndex], // YShare corresponding to the other participant signerOne
                    kShare: signShares.kShare,
                });
                // Step Seven
                // signerOne receives the AShare from signerTwo and signerOne using the private WShare from step two
                // uses it produce private GShare (Gamma Share) and MUShare (Mu Share) which
                // is sent to signerTwo to produce its Gamma Share
                const signConvertS12 = await MPC.signConvertStep2({
                    aShare: signConvertS21.aShare,
                    wShare: signShares.wShare,
                });
                // Step Eight
                // signerTwo receives the MUShare from signerOne and signerOne using the private BShare from step three
                // uses it produce private GShare (Gamma Share)
                const signConvertS21_2 = await MPC.signConvertStep3({
                    muShare: signConvertS12.muShare,
                    bShare: signConvertS21.bShare,
                });
                // Step Nine
                // signerOne and signerTwo both have successfully generated GShares and they use
                // the sign combine function to generate their private omicron shares and
                // delta shares which they share to each other
                const [signCombineOne, signCombineTwo] = [
                    MPC.signCombine({
                        gShare: signConvertS12.gShare,
                        signIndex: {
                            i: signConvertS12.muShare.i,
                            j: signConvertS12.muShare.j,
                        },
                    }),
                    MPC.signCombine({
                        gShare: signConvertS21_2.gShare,
                        signIndex: {
                            i: signConvertS21_2.signIndex.i,
                            j: signConvertS21_2.signIndex.j,
                        },
                    }),
                ];
                const MESSAGE = Buffer.from('TOO MANY SECRETS');
                // Step Ten
                // signerOne and signerTwo shares the delta share from each other
                // and finally signs the message using their private OShare
                // and delta share received from the other signer
                const hashGenerator = (hashType) => {
                    return hashType === 'keccak256' ? (0, keccak_1.default)('keccak256') : undefined;
                };
                const [signA, signB] = [
                    MPC.sign(MESSAGE, signCombineOne.oShare, signCombineTwo.dShare, hashGenerator(config[index].hash), config[index].shouldHash),
                    MPC.sign(MESSAGE, signCombineTwo.oShare, signCombineOne.dShare, hashGenerator(config[index].hash), config[index].shouldHash),
                ];
                // Step Eleven
                // Construct the final signature
                const signature = MPC.constructSignature([signA, signB]);
                // Step Twelve
                // Verify signature
                const isValid = MPC.verify(MESSAGE, signature, hashGenerator(config[index].hash), config[index].shouldHash);
                isValid.should.equal(true);
            });
        }
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNkc2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZXN0L3VuaXQvbXBjL3Rzcy9lY2RzYS9lY2RzYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztHQUVHO0FBQ0gsb0RBQTRCO0FBQzVCLG1DQUEyQztBQUMzQyw4Q0FBNEQ7QUFDNUQsb0RBQTJGO0FBQzNGLDZDQUErQjtBQUMvQixvREFBc0M7QUFDdEMsZ0VBQWtEO0FBQ2xELDZDQVMyQjtBQUUzQixRQUFRLENBQUMsaUJBQWlCLEVBQUU7SUFDMUIsTUFBTSxHQUFHLEdBQUcsSUFBSSxnQkFBSyxFQUFFLENBQUM7SUFDeEIsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLHNFQUFzRSxDQUFDLENBQUMsQ0FBQyxRQUFRO0lBQ3JHLElBQUksU0FBOEIsQ0FBQztJQUNuQyxJQUFJLGVBQXVCLENBQUM7SUFDNUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FDdEIsa0lBQWtJLEVBQ2xJLEtBQUssQ0FDTixDQUFDO0lBQ0YsSUFBSSxDQUFpQixFQUFFLENBQWlCLEVBQUUsQ0FBaUIsQ0FBQztJQUM1RCxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUU7UUFDaEIsTUFBTSxZQUFZLEdBQUcsS0FBSzthQUN2QixJQUFJLENBQUMsY0FBYyxFQUFFLG9CQUFvQixDQUFDO2FBQzFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7YUFDVCxRQUFRLENBQUMsbUJBQVcsQ0FBQyxDQUFDLENBQXNDLENBQUM7YUFDN0QsTUFBTSxDQUFDLENBQUMsQ0FBQzthQUNULFFBQVEsQ0FBQyxtQkFBVyxDQUFDLENBQUMsQ0FBc0MsQ0FBQzthQUM3RCxNQUFNLENBQUMsQ0FBQyxDQUFDO2FBQ1QsUUFBUSxDQUFDLG1CQUFXLENBQUMsQ0FBQyxDQUFzQyxDQUFDO2FBQzdELE1BQU0sQ0FBQyxDQUFDLENBQUM7YUFDVCxRQUFRLENBQUMsbUJBQVcsQ0FBQyxDQUFDLENBQXNDLENBQUM7YUFDN0QsTUFBTSxDQUFDLENBQUMsQ0FBQzthQUNULFFBQVEsQ0FBQyxtQkFBVyxDQUFDLENBQUMsQ0FBc0MsQ0FBQzthQUM3RCxNQUFNLENBQUMsQ0FBQyxDQUFDO2FBQ1QsUUFBUSxDQUFDLG1CQUFXLENBQUMsQ0FBQyxDQUFzQyxDQUFDLENBQUM7UUFFakUsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLO2FBQzNCLElBQUksQ0FBQyxxQkFBTyxFQUFFLG9CQUFvQixDQUFDO2FBQ25DLE1BQU0sQ0FBQyxDQUFDLENBQUM7YUFDVCxPQUFPLENBQUMscUJBQWEsQ0FBQyxDQUFDLENBQTRCLENBQUM7YUFDcEQsTUFBTSxDQUFDLENBQUMsQ0FBQzthQUNULE9BQU8sQ0FBQyxxQkFBYSxDQUFDLENBQUMsQ0FBNEIsQ0FBQzthQUNwRCxNQUFNLENBQUMsQ0FBQyxDQUFDO2FBQ1QsT0FBTyxDQUFDLHFCQUFhLENBQUMsQ0FBQyxDQUE0QixDQUFDO2FBQ3BELE1BQU0sQ0FBQyxDQUFDLENBQUM7YUFDVCxPQUFPLENBQUMscUJBQWEsQ0FBQyxDQUFDLENBQTRCLENBQUM7YUFDcEQsTUFBTSxDQUFDLENBQUMsQ0FBQzthQUNULE9BQU8sQ0FBQyxxQkFBYSxDQUFDLENBQUMsQ0FBNEIsQ0FBQzthQUNwRCxNQUFNLENBQUMsQ0FBQyxDQUFDO2FBQ1QsT0FBTyxDQUFDLHFCQUFhLENBQUMsQ0FBQyxDQUE0QixDQUFDLENBQUM7UUFFeEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVyRyxzRUFBc0U7UUFDdEUsK0NBQStDO1FBQy9DLE1BQU0sQ0FBQyxHQUFHLE1BQU0sR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUM1QyxNQUFNLENBQUMsR0FBRyxNQUFNLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDNUMsTUFBTSxDQUFDLEdBQUcsTUFBTSxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRTVDLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRSxNQUFNLFdBQVcsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRTNFLDZCQUE2QjtRQUM3QixNQUFNLFdBQVcsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNFLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUzRSwyQkFBMkI7UUFDM0IsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDO1FBQ3JCLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9FLE1BQU0sV0FBVyxHQUFzQjtZQUNyQyxNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU07WUFDekIsT0FBTyxFQUFFLFdBQVcsQ0FBQyxPQUFPO1NBQzdCLENBQUM7UUFDRixNQUFNLFdBQVcsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BGLFNBQVMsR0FBRztZQUNWLFdBQVc7WUFDWCxXQUFXO1lBQ1gsV0FBVztZQUNYLFdBQVc7WUFDWCxXQUFXO1lBQ1gsV0FBVztZQUNYLFdBQVc7WUFDWCxXQUFXO1NBQ1osQ0FBQztRQUNGLGVBQWUsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUN2QyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDckIsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3ZCLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3pCLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzdCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLDJCQUEyQixFQUFFO1FBQ3BDLEVBQUUsQ0FBQyw4REFBOEQsRUFBRSxLQUFLO1lBQ3RFLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDdkMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN2QyxNQUFNLGNBQWMsR0FBRyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDN0MsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDL0MsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDdkQsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDeEQsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDO2dCQUM3QyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUM7Z0JBQzdDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQztnQkFFN0MsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUNuRSxNQUFNLGdCQUFnQixHQUFHLFNBQVMsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksU0FBUyxJQUFJLElBQUksQ0FBQztnQkFDcEUsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFcEMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDeEUsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUMxRSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUN4RSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztnQkFDNUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDO2dCQUM5RCxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQztnQkFFaEUsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDOUQsTUFBTSxhQUFhLEdBQUcsZUFBZSxLQUFLLElBQUksSUFBSSxlQUFlLEtBQUssSUFBSSxDQUFDO2dCQUMzRSxhQUFhLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNuQyxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsOENBQThDLEVBQUUsS0FBSztZQUN0RCwrQ0FBK0M7WUFDL0MsTUFBTSxDQUFDLEVBQUUsQUFBRCxFQUFHLEFBQUQsRUFBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQztZQUNsQyxnQkFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUscUJBQWEsQ0FBQyxDQUFDO1lBQ25DLGdCQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxxQkFBYSxDQUFDLENBQUM7WUFDbkMsZ0JBQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLHFCQUFhLENBQUMsQ0FBQztRQUNyQyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxrREFBa0QsRUFBRSxLQUFLO1lBQzFELE1BQU0sR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFBLG9CQUFXLEVBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FDakUsOENBQThDLENBQy9DLENBQUM7WUFDRixNQUFNLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBQSxvQkFBVyxFQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQ2pFLDhDQUE4QyxDQUMvQyxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsK0NBQStDLEVBQUUsS0FBSztZQUN2RCxNQUFNLFlBQVksR0FBRyxLQUFLO2lCQUN2QixJQUFJLENBQUMsY0FBYyxFQUFFLG9CQUFvQixDQUFDO2lCQUMxQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2lCQUNULFFBQVEsQ0FBQyxtQkFBVyxDQUFDLENBQUMsQ0FBc0MsQ0FBQyxDQUFDO1lBQ2pFLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQzdCLGtKQUFrSixFQUNsSixLQUFLLENBQ04sQ0FBQztZQUNGLENBQUMsTUFBTSxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUM1RSxZQUFZLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsb0RBQW9ELEVBQUUsS0FBSztZQUM1RCxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLGtCQUFVLEVBQUUsbUJBQVcsQ0FBQyxDQUFDO1lBQzNELFVBQVUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsa0VBQWtFLENBQUMsQ0FBQztRQUMvRyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyxzRUFBc0UsRUFBRSxLQUFLO1lBQzlFLE1BQU0sY0FBYyxHQUFHO2dCQUNyQixFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFO2dCQUN4QyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUU7Z0JBQ3pDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUU7YUFDekMsQ0FBQztZQUNGLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxjQUFjLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7Z0JBQzNELElBQUksQ0FBQztvQkFDSCxNQUFNLEdBQUcsQ0FBQyxRQUFRLENBQ2hCLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQzNCLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLEVBQy9CLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLENBQ2hDLENBQUM7Z0JBQ0osQ0FBQztnQkFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO29CQUNYLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7Z0JBQzVDLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMscUNBQXFDLEVBQUUsS0FBSztZQUM3QyxhQUFhO1lBQ2IsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2pDLE1BQU0sY0FBYyxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDO1lBRTNFLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztnQkFDeEMsTUFBTSxJQUFJLEdBQUcsU0FBUyxLQUFLLEVBQUUsQ0FBQztnQkFFOUIsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBRTNFLE1BQU0sT0FBTyxHQUFXLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ25FLE1BQU0sT0FBTyxHQUFXLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBRW5FLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxvQ0FBb0MsQ0FBQyxDQUFDO2dCQUVwRSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FDdEQsT0FBTyxFQUNQLHNEQUFzRCxDQUN2RCxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxRQUFRLENBQUMsZUFBZSxFQUFFLEtBQUs7UUFDN0IsSUFBSSxNQUE2RyxDQUFDO1FBRWxILE1BQU0sQ0FBQyxHQUFHLEVBQUU7WUFDVixNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQztZQUUzQyxNQUFNLEdBQUc7Z0JBQ1AsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUU7Z0JBQzlCLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFO2dCQUM5QixFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRTtnQkFDOUIsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUU7Z0JBQzlCLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFO2dCQUM5QixFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRTtnQkFFOUIsb0NBQW9DO2dCQUNwQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRTtnQkFDOUIsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUU7Z0JBQzlCLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFO2dCQUU5Qix5Q0FBeUM7Z0JBQ3pDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUU7Z0JBRWpELHlCQUF5QjtnQkFDekIsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRTtnQkFFakQsNkJBQTZCO2dCQUM3QixFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRTthQUMvQixDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxLQUFLLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDdkMsRUFBRSxDQUFDLHlDQUF5QyxLQUFLLEVBQUUsRUFBRSxLQUFLO2dCQUN4RCxXQUFXO2dCQUNYLHdEQUF3RDtnQkFDeEQsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQztnQkFDMUMsTUFBTSxjQUFjLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzFDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBQzFDLE1BQU0sY0FBYyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUUxQyxNQUFNLENBQUMsK0JBQStCLEVBQUUsK0JBQStCLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7b0JBQzNGLGdDQUFrQixDQUFDLFNBQVMsQ0FBQyxJQUFBLHNCQUFXLEVBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDOUUsZ0NBQWtCLENBQUMsU0FBUyxDQUFDLElBQUEsc0JBQVcsRUFBQyxTQUFTLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUMvRSxDQUFDLENBQUM7Z0JBQ0gsV0FBVztnQkFDWCxzREFBc0Q7Z0JBQ3RELE1BQU0sZUFBZSxHQUErQixHQUFHLENBQUMsZUFBZSxDQUNyRSxTQUFTLENBQUMsTUFBTSxFQUNoQix3QkFBVSxDQUFDLGVBQWUsQ0FBQyxlQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFDMUMsd0JBQVUsQ0FBQywwQkFBMEIsQ0FBQyxFQUFFLENBQUMsRUFBRSwrQkFBK0IsRUFBRSxDQUFDLENBQzlFLENBQUM7Z0JBRUYsYUFBYTtnQkFDYix3REFBd0Q7Z0JBQ3hELE1BQU0sZUFBZSxHQUErQixHQUFHLENBQUMsZUFBZSxDQUNyRSxTQUFTLENBQUMsTUFBTSxFQUNoQix3QkFBVSxDQUFDLGVBQWUsQ0FBQyxlQUFPLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQzlDLHdCQUFVLENBQUMsMEJBQTBCLENBQUMsRUFBRSxDQUFDLEVBQUUsK0JBQStCLEVBQUUsQ0FBQyxDQUM5RSxDQUFDO2dCQUNGLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxNQUFNLEVBQUUsZUFBZSxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsZUFBZSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsZUFBZSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUU5RyxZQUFZO2dCQUNaLDRGQUE0RjtnQkFDNUYsTUFBTSxlQUFlLEdBQStCLEdBQUcsQ0FBQyxlQUFlLENBQ3JFLFNBQVMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLEVBQ2pDLGtCQUFrQixFQUNsQix3QkFBVSxDQUFDLDBCQUEwQixDQUFDLEVBQUUsQ0FBQyxFQUFFLCtCQUErQixFQUFFLENBQUMsQ0FDOUUsQ0FBQztnQkFFRixZQUFZO2dCQUNaLGlFQUFpRTtnQkFDakUsd0ZBQXdGO2dCQUN4RiwwR0FBMEc7Z0JBQzFHLE1BQU0sVUFBVSxHQUFHLE1BQU0sR0FBRyxDQUFDLFNBQVMsQ0FBQyxlQUFlLEVBQUUsZUFBZSxDQUFDLENBQUM7Z0JBRXpFLFdBQVc7Z0JBQ1gsMkVBQTJFO2dCQUMzRSxxRUFBcUU7Z0JBQ3JFLDZCQUE2QjtnQkFFN0IsTUFBTSxjQUFjLEdBQUcsTUFBTSxHQUFHLENBQUMsZ0JBQWdCLENBQUM7b0JBQ2hELE1BQU0sRUFBRSxlQUFlO29CQUN2QixNQUFNLEVBQUUsU0FBUyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsRUFBRSwwREFBMEQ7b0JBQ3JHLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTTtpQkFDMUIsQ0FBQyxDQUFDO2dCQUVILGFBQWE7Z0JBQ2Isb0dBQW9HO2dCQUNwRyw0RUFBNEU7Z0JBQzVFLGtEQUFrRDtnQkFDbEQsTUFBTSxjQUFjLEdBQUcsTUFBTSxHQUFHLENBQUMsZ0JBQWdCLENBQUM7b0JBQ2hELE1BQU0sRUFBRSxjQUFjLENBQUMsTUFBTTtvQkFDN0IsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNO2lCQUMxQixDQUFDLENBQUM7Z0JBRUgsYUFBYTtnQkFDYix1R0FBdUc7Z0JBQ3ZHLCtDQUErQztnQkFDL0MsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQztvQkFDbEQsT0FBTyxFQUFFLGNBQWMsQ0FBQyxPQUFPO29CQUMvQixNQUFNLEVBQUUsY0FBYyxDQUFDLE1BQU07aUJBQzlCLENBQUMsQ0FBQztnQkFFSCxZQUFZO2dCQUNaLGdGQUFnRjtnQkFDaEYseUVBQXlFO2dCQUN6RSw4Q0FBOEM7Z0JBRTlDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDLEdBQUc7b0JBQ3ZDLEdBQUcsQ0FBQyxXQUFXLENBQUM7d0JBQ2QsTUFBTSxFQUFFLGNBQWMsQ0FBQyxNQUFNO3dCQUM3QixTQUFTLEVBQUU7NEJBQ1QsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQzs0QkFDM0IsQ0FBQyxFQUFFLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQzt5QkFDNUI7cUJBQ0YsQ0FBQztvQkFDRixHQUFHLENBQUMsV0FBVyxDQUFDO3dCQUNkLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxNQUFNO3dCQUMvQixTQUFTLEVBQUU7NEJBQ1QsQ0FBQyxFQUFFLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDOzRCQUMvQixDQUFDLEVBQUUsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7eUJBQ2hDO3FCQUNGLENBQUM7aUJBQ0gsQ0FBQztnQkFFRixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7Z0JBRWhELFdBQVc7Z0JBQ1gsaUVBQWlFO2dCQUNqRSwyREFBMkQ7Z0JBQzNELGlEQUFpRDtnQkFFakQsTUFBTSxhQUFhLEdBQUcsQ0FBQyxRQUFpQixFQUFvQixFQUFFO29CQUM1RCxPQUFPLFFBQVEsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFFLElBQUEsZ0JBQWdCLEVBQUMsV0FBVyxDQUFVLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztnQkFDeEYsQ0FBQyxDQUFDO2dCQUNGLE1BQU0sQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEdBQUc7b0JBQ3JCLEdBQUcsQ0FBQyxJQUFJLENBQ04sT0FBTyxFQUNQLGNBQWMsQ0FBQyxNQUFNLEVBQ3JCLGNBQWMsQ0FBQyxNQUFNLEVBQ3JCLGFBQWEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQ2pDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLENBQ3pCO29CQUNELEdBQUcsQ0FBQyxJQUFJLENBQ04sT0FBTyxFQUNQLGNBQWMsQ0FBQyxNQUFNLEVBQ3JCLGNBQWMsQ0FBQyxNQUFNLEVBQ3JCLGFBQWEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQ2pDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLENBQ3pCO2lCQUNGLENBQUM7Z0JBRUYsY0FBYztnQkFDZCxnQ0FBZ0M7Z0JBRWhDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUV6RCxjQUFjO2dCQUNkLG1CQUFtQjtnQkFFbkIsTUFBTSxPQUFPLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLGFBQWEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUM1RyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM3QixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuaW1wb3J0IGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IHsgSGFzaCwgcmFuZG9tQnl0ZXMgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgRWNkc2EsIEVDRFNBLCBoZXhUb0JpZ0ludCB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBFY2RzYVBhaWxsaWVyUHJvb2YsIEVjZHNhVHlwZXMsIFNjaG5vcnIsIFNjaG5vcnJQcm9vZiB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQgY3JlYXRlS2VjY2FrSGFzaCBmcm9tICdrZWNjYWsnO1xuaW1wb3J0ICogYXMgcGFpbGxpZXJCaWdpbnQgZnJvbSAncGFpbGxpZXItYmlnaW50JztcbmltcG9ydCB7XG4gIHNjaG5vcnJQcm9vZnMsXG4gIG50aWxkZXMsXG4gIHBhaWxsZXJLZXlzLFxuICBtb2NrTlNoYXJlcyxcbiAgbW9ja1BTaGFyZSxcbiAgbW9ja0RLZXlTaGFyZSxcbiAgbW9ja0VLZXlTaGFyZSxcbiAgbW9ja0ZLZXlTaGFyZSxcbn0gZnJvbSAnLi4vZml4dHVyZXMvZWNkc2EnO1xuXG5kZXNjcmliZSgnVFNTIEVDRFNBIFRFU1RTJywgZnVuY3Rpb24gKCkge1xuICBjb25zdCBNUEMgPSBuZXcgRWNkc2EoKTtcbiAgY29uc3QgYmFzZSA9IEJpZ0ludCgnMHgwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAnKTsgLy8gMl4yNTZcbiAgbGV0IGtleVNoYXJlczogRUNEU0EuS2V5Q29tYmluZWRbXTtcbiAgbGV0IGNvbW1vblB1YmxpY0tleTogc3RyaW5nO1xuICBjb25zdCBzZWVkID0gQnVmZmVyLmZyb20oXG4gICAgJ2M0ZDE1ODNhMGI3Yjg4NjI2YjU2ZjBjODNlZTZkZjRkOTVkOTljY2E3Mzg5M2ZmYjU3YzVlNDQxMWZhMWIyYjljODc0NTYwODBlOGQzZjAzNDYyZjA2NTY4OGFiYzI4YmUyZDRhZjMxNjRkNTkzYzUwYjU1MjY5YjQzNWVhNDhkJyxcbiAgICAnaGV4JyxcbiAgKTtcbiAgbGV0IEE6IEVDRFNBLktleVNoYXJlLCBCOiBFQ0RTQS5LZXlTaGFyZSwgQzogRUNEU0EuS2V5U2hhcmU7XG4gIGJlZm9yZShhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcGFpbGxpZXJNb2NrID0gc2lub25cbiAgICAgIC5zdHViKHBhaWxsaWVyQmlnaW50LCAnZ2VuZXJhdGVSYW5kb21LZXlzJylcbiAgICAgIC5vbkNhbGwoMClcbiAgICAgIC5yZXNvbHZlcyhwYWlsbGVyS2V5c1swXSBhcyB1bmtub3duIGFzIHBhaWxsaWVyQmlnaW50LktleVBhaXIpXG4gICAgICAub25DYWxsKDEpXG4gICAgICAucmVzb2x2ZXMocGFpbGxlcktleXNbMV0gYXMgdW5rbm93biBhcyBwYWlsbGllckJpZ2ludC5LZXlQYWlyKVxuICAgICAgLm9uQ2FsbCgyKVxuICAgICAgLnJlc29sdmVzKHBhaWxsZXJLZXlzWzJdIGFzIHVua25vd24gYXMgcGFpbGxpZXJCaWdpbnQuS2V5UGFpcilcbiAgICAgIC5vbkNhbGwoMylcbiAgICAgIC5yZXNvbHZlcyhwYWlsbGVyS2V5c1swXSBhcyB1bmtub3duIGFzIHBhaWxsaWVyQmlnaW50LktleVBhaXIpXG4gICAgICAub25DYWxsKDQpXG4gICAgICAucmVzb2x2ZXMocGFpbGxlcktleXNbMV0gYXMgdW5rbm93biBhcyBwYWlsbGllckJpZ2ludC5LZXlQYWlyKVxuICAgICAgLm9uQ2FsbCg1KVxuICAgICAgLnJlc29sdmVzKHBhaWxsZXJLZXlzWzJdIGFzIHVua25vd24gYXMgcGFpbGxpZXJCaWdpbnQuS2V5UGFpcik7XG5cbiAgICBjb25zdCBzY2hub3JyUHJvb2ZNb2NrID0gc2lub25cbiAgICAgIC5zdHViKFNjaG5vcnIsICdjcmVhdGVTY2hub3JyUHJvb2YnKVxuICAgICAgLm9uQ2FsbCgwKVxuICAgICAgLnJldHVybnMoc2Nobm9yclByb29mc1swXSBhcyB1bmtub3duIGFzIFNjaG5vcnJQcm9vZilcbiAgICAgIC5vbkNhbGwoMSlcbiAgICAgIC5yZXR1cm5zKHNjaG5vcnJQcm9vZnNbMV0gYXMgdW5rbm93biBhcyBTY2hub3JyUHJvb2YpXG4gICAgICAub25DYWxsKDIpXG4gICAgICAucmV0dXJucyhzY2hub3JyUHJvb2ZzWzJdIGFzIHVua25vd24gYXMgU2Nobm9yclByb29mKVxuICAgICAgLm9uQ2FsbCgzKVxuICAgICAgLnJldHVybnMoc2Nobm9yclByb29mc1szXSBhcyB1bmtub3duIGFzIFNjaG5vcnJQcm9vZilcbiAgICAgIC5vbkNhbGwoNClcbiAgICAgIC5yZXR1cm5zKHNjaG5vcnJQcm9vZnNbNF0gYXMgdW5rbm93biBhcyBTY2hub3JyUHJvb2YpXG4gICAgICAub25DYWxsKDUpXG4gICAgICAucmV0dXJucyhzY2hub3JyUHJvb2ZzWzVdIGFzIHVua25vd24gYXMgU2Nobm9yclByb29mKTtcblxuICAgIFtBLCBCLCBDXSA9IGF3YWl0IFByb21pc2UuYWxsKFtNUEMua2V5U2hhcmUoMSwgMiwgMyksIE1QQy5rZXlTaGFyZSgyLCAyLCAzKSwgTVBDLmtleVNoYXJlKDMsIDIsIDMpXSk7XG5cbiAgICAvLyBOZWVkcyB0byBydW4gdGhpcyBzZXJpYWxseSBmb3IgdGVzdGluZyBkZXRlcm1pbmlzdGljIGtleSBnZW5lcmF0aW9uXG4gICAgLy8gdG8gZ2V0IHNwZWNpZmljIHBhaWxsaWVyIGtleXMgdG8gYmUgYXNzaWduZWRcbiAgICBjb25zdCBEID0gYXdhaXQgTVBDLmtleVNoYXJlKDEsIDIsIDMsIHNlZWQpO1xuICAgIGNvbnN0IEUgPSBhd2FpdCBNUEMua2V5U2hhcmUoMiwgMiwgMywgc2VlZCk7XG4gICAgY29uc3QgRiA9IGF3YWl0IE1QQy5rZXlTaGFyZSgzLCAyLCAzLCBzZWVkKTtcblxuICAgIGNvbnN0IGFLZXlDb21iaW5lID0gTVBDLmtleUNvbWJpbmUoQS5wU2hhcmUsIFtCLm5TaGFyZXNbMV0sIEMublNoYXJlc1sxXV0pO1xuICAgIGNvbnN0IGJLZXlDb21iaW5lID0gTVBDLmtleUNvbWJpbmUoQi5wU2hhcmUsIFtBLm5TaGFyZXNbMl0sIEMublNoYXJlc1syXV0pO1xuICAgIGNvbnN0IGNLZXlDb21iaW5lID0gTVBDLmtleUNvbWJpbmUoQy5wU2hhcmUsIFtBLm5TaGFyZXNbM10sIEIublNoYXJlc1szXV0pO1xuXG4gICAgLy8gU2hhcmVzIHdpdGggc3BlY2lmaWMgc2VlZHNcbiAgICBjb25zdCBkS2V5Q29tYmluZSA9IE1QQy5rZXlDb21iaW5lKEQucFNoYXJlLCBbRS5uU2hhcmVzWzFdLCBGLm5TaGFyZXNbMV1dKTtcbiAgICBjb25zdCBlS2V5Q29tYmluZSA9IE1QQy5rZXlDb21iaW5lKEUucFNoYXJlLCBbRC5uU2hhcmVzWzJdLCBGLm5TaGFyZXNbMl1dKTtcbiAgICBjb25zdCBmS2V5Q29tYmluZSA9IE1QQy5rZXlDb21iaW5lKEYucFNoYXJlLCBbRC5uU2hhcmVzWzNdLCBFLm5TaGFyZXNbM11dKTtcblxuICAgIC8vIFNoYXJlcyBmb3IgZGVyaXZlZCBrZXlzLlxuICAgIGNvbnN0IHBhdGggPSAnbS8wLzEnO1xuICAgIGNvbnN0IGFLZXlEZXJpdmUgPSBNUEMua2V5RGVyaXZlKEEucFNoYXJlLCBbQi5uU2hhcmVzWzFdLCBDLm5TaGFyZXNbMV1dLCBwYXRoKTtcbiAgICBjb25zdCBnS2V5Q29tYmluZTogRUNEU0EuS2V5Q29tYmluZWQgPSB7XG4gICAgICB4U2hhcmU6IGFLZXlEZXJpdmUueFNoYXJlLFxuICAgICAgeVNoYXJlczogYUtleUNvbWJpbmUueVNoYXJlcyxcbiAgICB9O1xuICAgIGNvbnN0IGhLZXlDb21iaW5lID0gTVBDLmtleUNvbWJpbmUoQi5wU2hhcmUsIFthS2V5RGVyaXZlLm5TaGFyZXNbMl0sIEMublNoYXJlc1syXV0pO1xuICAgIGtleVNoYXJlcyA9IFtcbiAgICAgIGFLZXlDb21iaW5lLFxuICAgICAgYktleUNvbWJpbmUsXG4gICAgICBjS2V5Q29tYmluZSxcbiAgICAgIGRLZXlDb21iaW5lLFxuICAgICAgZUtleUNvbWJpbmUsXG4gICAgICBmS2V5Q29tYmluZSxcbiAgICAgIGdLZXlDb21iaW5lLFxuICAgICAgaEtleUNvbWJpbmUsXG4gICAgXTtcbiAgICBjb21tb25QdWJsaWNLZXkgPSBhS2V5Q29tYmluZS54U2hhcmUueTtcbiAgICBwYWlsbGllck1vY2sucmVzZXQoKTtcbiAgICBwYWlsbGllck1vY2sucmVzdG9yZSgpO1xuICAgIHNjaG5vcnJQcm9vZk1vY2sucmVzZXQoKTtcbiAgICBzY2hub3JyUHJvb2ZNb2NrLnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0VjZHNhIEtleSBHZW5lcmF0aW9uIFRlc3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBrZXlzIHdpdGggY29ycmVjdCB0aHJlc2hvbGQgYW5kIHNoYXJlIG51bWJlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCAzOyBpbmRleCsrKSB7XG4gICAgICAgIGNvbnN0IHBhcnRpY2lwYW50T25lID0gKGluZGV4ICUgMykgKyAxO1xuICAgICAgICBjb25zdCBwYXJ0aWNpcGFudFR3byA9ICgoaW5kZXggKyAxKSAlIDMpICsgMTtcbiAgICAgICAgY29uc3QgcGFydGljaXBhbnRUaHJlZSA9ICgoaW5kZXggKyAyKSAlIDMpICsgMTtcbiAgICAgICAga2V5U2hhcmVzW2luZGV4XS54U2hhcmUuaS5zaG91bGQuZXF1YWwocGFydGljaXBhbnRPbmUpO1xuICAgICAgICBrZXlTaGFyZXNbaW5kZXhdLnhTaGFyZS55LnNob3VsZC5lcXVhbChjb21tb25QdWJsaWNLZXkpO1xuICAgICAgICBrZXlTaGFyZXNbaW5kZXhdLnhTaGFyZS5tLnNob3VsZC5ub3QuYmUuTnVsbDtcbiAgICAgICAga2V5U2hhcmVzW2luZGV4XS54U2hhcmUubC5zaG91bGQubm90LmJlLk51bGw7XG4gICAgICAgIGtleVNoYXJlc1tpbmRleF0ueFNoYXJlLm4uc2hvdWxkLm5vdC5iZS5OdWxsO1xuXG4gICAgICAgIGNvbnN0IGNoYWluY29kZSA9IEJpZ0ludCgnMHgnICsga2V5U2hhcmVzW2luZGV4XS54U2hhcmUuY2hhaW5jb2RlKTtcbiAgICAgICAgY29uc3QgaXNDaGFpbkNvZGVWYWxpZCA9IGNoYWluY29kZSA+IEJpZ0ludCgwKSAmJiBjaGFpbmNvZGUgPD0gYmFzZTtcbiAgICAgICAgaXNDaGFpbkNvZGVWYWxpZC5zaG91bGQuZXF1YWwodHJ1ZSk7XG5cbiAgICAgICAga2V5U2hhcmVzW2luZGV4XS55U2hhcmVzW3BhcnRpY2lwYW50VHdvXS5pLnNob3VsZC5lcXVhbChwYXJ0aWNpcGFudE9uZSk7XG4gICAgICAgIGtleVNoYXJlc1tpbmRleF0ueVNoYXJlc1twYXJ0aWNpcGFudFRocmVlXS5pLnNob3VsZC5lcXVhbChwYXJ0aWNpcGFudE9uZSk7XG4gICAgICAgIGtleVNoYXJlc1tpbmRleF0ueVNoYXJlc1twYXJ0aWNpcGFudFR3b10uai5zaG91bGQuZXF1YWwocGFydGljaXBhbnRUd28pO1xuICAgICAgICBrZXlTaGFyZXNbaW5kZXhdLnlTaGFyZXNbcGFydGljaXBhbnRUaHJlZV0uai5zaG91bGQuZXF1YWwocGFydGljaXBhbnRUaHJlZSk7XG4gICAgICAgIGtleVNoYXJlc1tpbmRleF0ueVNoYXJlc1twYXJ0aWNpcGFudFR3b10ubi5zaG91bGQubm90LmJlLk51bGw7XG4gICAgICAgIGtleVNoYXJlc1tpbmRleF0ueVNoYXJlc1twYXJ0aWNpcGFudFRocmVlXS5uLnNob3VsZC5ub3QuYmUuTnVsbDtcblxuICAgICAgICBjb25zdCBwdWJsaWNLZXlQcmVmaXggPSBrZXlTaGFyZXNbaW5kZXhdLnhTaGFyZS55LnNsaWNlKDAsIDIpO1xuICAgICAgICBjb25zdCBpc1JpZ2h0UHJlZml4ID0gcHVibGljS2V5UHJlZml4ID09PSAnMDMnIHx8IHB1YmxpY0tleVByZWZpeCA9PT0gJzAyJztcbiAgICAgICAgaXNSaWdodFByZWZpeC5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIGtleXNoYXJlcyB3aXRoIHNwZWNpZmljIHNlZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBLZXlzIHNob3VsZCBiZSBkZXRlcm1pbmlzdGljIHdoZW4gdXNpbmcgc2VlZFxuICAgICAgY29uc3QgWywgLCAsIEQsIEUsIEZdID0ga2V5U2hhcmVzO1xuICAgICAgYXNzZXJ0LmRlZXBFcXVhbChELCBtb2NrREtleVNoYXJlKTtcbiAgICAgIGFzc2VydC5kZWVwRXF1YWwoRSwgbW9ja0VLZXlTaGFyZSk7XG4gICAgICBhc3NlcnQuZGVlcEVxdWFsKEYsIG1vY2tGS2V5U2hhcmUpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIGlmIHNlZWQgaXMgbGVuZ3RoIGxlc3MgdGhhbiA2NCBieXRlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGF3YWl0IE1QQy5rZXlTaGFyZSgxLCAyLCAzLCByYW5kb21CeXRlcygxNikpLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICdTZWVkIG11c3QgaGF2ZSBhIGxlbmd0aCBvZiBhdCBsZWFzdCA2NCBieXRlcycsXG4gICAgICApO1xuICAgICAgYXdhaXQgTVBDLmtleVNoYXJlKDEsIDIsIDMsIHJhbmRvbUJ5dGVzKDMyKSkuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgJ1NlZWQgbXVzdCBoYXZlIGEgbGVuZ3RoIG9mIGF0IGxlYXN0IDY0IGJ5dGVzJyxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHBhc3MgaWYgc2VlZCBsZW5ndGggaXMgZ3JlYXRlciB0aGFuIDY0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFpbGxpZXJNb2NrID0gc2lub25cbiAgICAgICAgLnN0dWIocGFpbGxpZXJCaWdpbnQsICdnZW5lcmF0ZVJhbmRvbUtleXMnKVxuICAgICAgICAub25DYWxsKDApXG4gICAgICAgIC5yZXNvbHZlcyhwYWlsbGVyS2V5c1swXSBhcyB1bmtub3duIGFzIHBhaWxsaWVyQmlnaW50LktleVBhaXIpO1xuICAgICAgY29uc3Qgc2VlZDcyQnl0ZXMgPSBCdWZmZXIuZnJvbShcbiAgICAgICAgJzRmN2U5MTRkYzllYzY5NjM5ODY3NWQxNTQ0YWFiNjFjYjdhNjc2NjJmZmNiZGI0MDc5ZWM1ZDY4MmJlNTY1ZDg3YzFiMmRlNzVjOTQzZGVjMTRjOTY1ODY5ODQ4NjAyNjg3Nzk0OThlNjczMjQ3M2FlZDllZDljMjUzOGY1MGJlYTBhZjkyNmJkY2NjMDEzNCcsXG4gICAgICAgICdoZXgnLFxuICAgICAgKTtcbiAgICAgIChhd2FpdCBNUEMua2V5U2hhcmUoMSwgMiwgMywgc2VlZDcyQnl0ZXMpKS5wU2hhcmUudS5sZW5ndGguc2hvdWxkLmVxdWFsKDY0KTtcbiAgICAgIHBhaWxsaWVyTW9jay5yZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGN1bGF0ZSBjb3JyZWN0IGNoYWluY29kZSB3aGlsZSBjb21iaW5pbmcnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXlDb21iaW5lID0gTVBDLmtleUNvbWJpbmUobW9ja1BTaGFyZSwgbW9ja05TaGFyZXMpO1xuICAgICAga2V5Q29tYmluZS54U2hhcmUuY2hhaW5jb2RlLnNob3VsZC5lcXVhbCgnZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmVmZmZmZmMzMicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGdlbmVyYXRlIGtleXMgd2l0aCBpbnZhbGlkIHRocmVzaG9sZCBhbmQgc2hhcmUgbnVtYmVyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaW52YWxpZENvbmZpZ3MgPSBbXG4gICAgICAgIHsgaW5kZXg6IDEsIHRocmVzaG9sZDogNSwgbnVtU2hhcmVzOiAzIH0sXG4gICAgICAgIHsgaW5kZXg6IC0xLCB0aHJlc2hvbGQ6IDIsIG51bVNoYXJlczogMyB9LFxuICAgICAgICB7IGluZGV4OiAxLCB0aHJlc2hvbGQ6IDIsIG51bVNoYXJlczogMSB9LFxuICAgICAgXTtcbiAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBpbnZhbGlkQ29uZmlncy5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBNUEMua2V5U2hhcmUoXG4gICAgICAgICAgICBpbnZhbGlkQ29uZmlnc1tpbmRleF0uaW5kZXgsXG4gICAgICAgICAgICBpbnZhbGlkQ29uZmlnc1tpbmRleF0udGhyZXNob2xkLFxuICAgICAgICAgICAgaW52YWxpZENvbmZpZ3NbaW5kZXhdLm51bVNoYXJlcyxcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgZS5zaG91bGQuZXF1YWwoJ0ludmFsaWQgS2V5U2hhcmUgQ29uZmlnJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZGVyaXZlIHVuaGFyZGVuZWQgY2hpbGQga2V5cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIHBhcmVudCBrZXlcbiAgICAgIGNvbnN0IGFLZXlDb21iaW5lID0ga2V5U2hhcmVzWzBdO1xuICAgICAgY29uc3QgY29tbW9uS2V5Y2hhaW4gPSBhS2V5Q29tYmluZS54U2hhcmUueSArIGFLZXlDb21iaW5lLnhTaGFyZS5jaGFpbmNvZGU7XG5cbiAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCAxMDsgaW5kZXgrKykge1xuICAgICAgICBjb25zdCBwYXRoID0gYG0vMC8wLyR7aW5kZXh9YDtcblxuICAgICAgICBjb25zdCBzdWJrZXkgPSBNUEMua2V5RGVyaXZlKEEucFNoYXJlLCBbQi5uU2hhcmVzWzFdLCBDLm5TaGFyZXNbMV1dLCBwYXRoKTtcblxuICAgICAgICBjb25zdCBkZXJpdmUxOiBzdHJpbmcgPSBNUEMuZGVyaXZlVW5oYXJkZW5lZChjb21tb25LZXljaGFpbiwgcGF0aCk7XG4gICAgICAgIGNvbnN0IGRlcml2ZTI6IHN0cmluZyA9IE1QQy5kZXJpdmVVbmhhcmRlbmVkKGNvbW1vbktleWNoYWluLCBwYXRoKTtcblxuICAgICAgICBkZXJpdmUxLnNob3VsZC5lcXVhbChkZXJpdmUyLCAnZGVyaXZhdGlvbiBzaG91bGQgYmUgZGV0ZXJtaW5pc3RpYycpO1xuXG4gICAgICAgIChzdWJrZXkueFNoYXJlLnkgKyBzdWJrZXkueFNoYXJlLmNoYWluY29kZSkuc2hvdWxkLmVxdWFsKFxuICAgICAgICAgIGRlcml2ZTEsXG4gICAgICAgICAgJ3N1YmtleSBjb21tb24ga2V5Y2hhaW4gc2hvdWxkIG1hdGNoIGRlcml2ZWQga2V5Y2hhaW4nLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnRUNEU0EgU2lnbmluZycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBsZXQgY29uZmlnOiB7IHNpZ25lck9uZTogRUNEU0EuS2V5Q29tYmluZWQ7IHNpZ25lclR3bzogRUNEU0EuS2V5Q29tYmluZWQ7IGhhc2g/OiBzdHJpbmc7IHNob3VsZEhhc2g/OiBib29sZWFuIH1bXTtcblxuICAgIGJlZm9yZSgoKSA9PiB7XG4gICAgICBjb25zdCBbQSwgQiwgQywgRCwgRSwgRiwgRywgSF0gPSBrZXlTaGFyZXM7XG5cbiAgICAgIGNvbmZpZyA9IFtcbiAgICAgICAgeyBzaWduZXJPbmU6IEEsIHNpZ25lclR3bzogQiB9LFxuICAgICAgICB7IHNpZ25lck9uZTogQSwgc2lnbmVyVHdvOiBDIH0sXG4gICAgICAgIHsgc2lnbmVyT25lOiBCLCBzaWduZXJUd286IEEgfSxcbiAgICAgICAgeyBzaWduZXJPbmU6IEIsIHNpZ25lclR3bzogQyB9LFxuICAgICAgICB7IHNpZ25lck9uZTogQywgc2lnbmVyVHdvOiBBIH0sXG4gICAgICAgIHsgc2lnbmVyT25lOiBDLCBzaWduZXJUd286IEIgfSxcblxuICAgICAgICAvLyBDaGVja3Mgc2lnbmluZyB3aXRoIHNwZWNpZmljIHNlZWRcbiAgICAgICAgeyBzaWduZXJPbmU6IEQsIHNpZ25lclR3bzogRSB9LFxuICAgICAgICB7IHNpZ25lck9uZTogRSwgc2lnbmVyVHdvOiBGIH0sXG4gICAgICAgIHsgc2lnbmVyT25lOiBGLCBzaWduZXJUd286IEQgfSxcblxuICAgICAgICAvLyBDaGVja3Mgd2l0aCBzcGVjaWZpYyBoYXNoaW5nIGFsZ29yaXRobVxuICAgICAgICB7IHNpZ25lck9uZTogQSwgc2lnbmVyVHdvOiBCLCBoYXNoOiAna2VjY2FrMjU2JyB9LFxuXG4gICAgICAgIC8vIGNoZWNrcyB3aXRoIG5vIGhhc2hpbmdcbiAgICAgICAgeyBzaWduZXJPbmU6IEEsIHNpZ25lclR3bzogQiwgc2hvdWxkSGFzaDogZmFsc2UgfSxcblxuICAgICAgICAvLyBDaGVja3Mgd2l0aCBkZXJpdmVkIHN1YmtleVxuICAgICAgICB7IHNpZ25lck9uZTogRywgc2lnbmVyVHdvOiBIIH0sXG4gICAgICBdO1xuICAgIH0pO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IDk7IGluZGV4KyspIHtcbiAgICAgIGl0KGBzaG91bGQgcHJvcGVybHkgc2lnbiB0aGUgbWVzc2FnZSBjYXNlICR7aW5kZXh9YCwgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBTdGVwIE9uZVxuICAgICAgICAvLyBzaWduZXJPbmUsIHNpZ25lclR3byBoYXZlIGRlY2lkZWQgdG8gc2lnbiB0aGUgbWVzc2FnZVxuICAgICAgICBjb25zdCBzaWduZXJPbmUgPSBjb25maWdbaW5kZXhdLnNpZ25lck9uZTtcbiAgICAgICAgY29uc3Qgc2lnbmVyT25lSW5kZXggPSBzaWduZXJPbmUueFNoYXJlLmk7XG4gICAgICAgIGNvbnN0IHNpZ25lclR3byA9IGNvbmZpZ1tpbmRleF0uc2lnbmVyVHdvO1xuICAgICAgICBjb25zdCBzaWduZXJUd29JbmRleCA9IHNpZ25lclR3by54U2hhcmUuaTtcblxuICAgICAgICBjb25zdCBbc2lnbmVyT25lVG9Ud29QYWlsbGllckNoYWxsZW5nZSwgc2lnbmVyVHdvVG9PbmVQYWlsbGllckNoYWxsZW5nZV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgRWNkc2FQYWlsbGllclByb29mLmdlbmVyYXRlUChoZXhUb0JpZ0ludChzaWduZXJPbmUueVNoYXJlc1tzaWduZXJUd29JbmRleF0ubikpLFxuICAgICAgICAgIEVjZHNhUGFpbGxpZXJQcm9vZi5nZW5lcmF0ZVAoaGV4VG9CaWdJbnQoc2lnbmVyVHdvLnlTaGFyZXNbc2lnbmVyT25lSW5kZXhdLm4pKSxcbiAgICAgICAgXSk7XG4gICAgICAgIC8vIFN0ZXAgVHdvXG4gICAgICAgIC8vIEZpcnN0IHNpZ25lciBnZW5lcmF0ZXMgdGhlaXIgcmFuZ2UgcHJvb2YgY2hhbGxlbmdlLlxuICAgICAgICBjb25zdCBzaWduZXJPbmVYU2hhcmU6IEVDRFNBLlhTaGFyZVdpdGhDaGFsbGVuZ2VzID0gTVBDLmFwcGVuZENoYWxsZW5nZShcbiAgICAgICAgICBzaWduZXJPbmUueFNoYXJlLFxuICAgICAgICAgIEVjZHNhVHlwZXMuc2VyaWFsaXplTnRpbGRlKG50aWxkZXNbaW5kZXhdKSxcbiAgICAgICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZVBhaWxsaWVyQ2hhbGxlbmdlKHsgcDogc2lnbmVyT25lVG9Ud29QYWlsbGllckNoYWxsZW5nZSB9KSxcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBTdGVwIFRocmVlXG4gICAgICAgIC8vICBTZWNvbmQgc2lnbmVyIGdlbmVyYXRlcyB0aGVpciByYW5nZSBwcm9vZiBjaGFsbGVuZ2UuXG4gICAgICAgIGNvbnN0IHNpZ25lclR3b1hTaGFyZTogRUNEU0EuWFNoYXJlV2l0aENoYWxsZW5nZXMgPSBNUEMuYXBwZW5kQ2hhbGxlbmdlKFxuICAgICAgICAgIHNpZ25lclR3by54U2hhcmUsXG4gICAgICAgICAgRWNkc2FUeXBlcy5zZXJpYWxpemVOdGlsZGUobnRpbGRlc1tpbmRleCArIDFdKSxcbiAgICAgICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZVBhaWxsaWVyQ2hhbGxlbmdlKHsgcDogc2lnbmVyVHdvVG9PbmVQYWlsbGllckNoYWxsZW5nZSB9KSxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3Qgc2lnbmVyVHdvQ2hhbGxlbmdlID0geyBudGlsZGU6IHNpZ25lclR3b1hTaGFyZS5udGlsZGUsIGgxOiBzaWduZXJUd29YU2hhcmUuaDEsIGgyOiBzaWduZXJUd29YU2hhcmUuaDIgfTtcblxuICAgICAgICAvLyBTdGVwIEZvdXJcbiAgICAgICAgLy8gRmlyc3Qgc2lnbmVyIHJlY2VpdmVzIHRoZSBjaGFsbGVuZ2UgZnJvbSB0aGUgc2Vjb25kIHNpZ25lciBhbmQgYXBwZW5kcyBpdCB0byB0aGVpciBZU2hhcmVcbiAgICAgICAgY29uc3Qgc2lnbmVyVHdvWVNoYXJlOiBFQ0RTQS5ZU2hhcmVXaXRoQ2hhbGxlbmdlcyA9IE1QQy5hcHBlbmRDaGFsbGVuZ2UoXG4gICAgICAgICAgc2lnbmVyT25lLnlTaGFyZXNbc2lnbmVyVHdvSW5kZXhdLFxuICAgICAgICAgIHNpZ25lclR3b0NoYWxsZW5nZSxcbiAgICAgICAgICBFY2RzYVR5cGVzLnNlcmlhbGl6ZVBhaWxsaWVyQ2hhbGxlbmdlKHsgcDogc2lnbmVyVHdvVG9PbmVQYWlsbGllckNoYWxsZW5nZSB9KSxcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBTdGVwIEZpdmVcbiAgICAgICAgLy8gU2lnbiBTaGFyZXMgYXJlIGNyZWF0ZWQgYnkgb25lIG9mIHRoZSBwYXJ0aWNpcGFudHMgKHNpZ25lck9uZSlcbiAgICAgICAgLy8gd2l0aCBpdHMgcHJpdmF0ZSBYU2hhcmUgYW5kIFlTaGFyZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBvdGhlciBwYXJ0aWNpcGFudCAoc2lnbmVyVHdvKVxuICAgICAgICAvLyBUaGlzIHN0ZXAgcHJvZHVjZXMgYSBwcml2YXRlIFdTaGFyZSB3aGljaCBzaWduZXJPbmUgc2F2ZXMgYW5kIEtTaGFyZSB3aGljaCBzaWduZXJPbmUgc2VuZHMgdG8gc2lnbmVyVHdvXG4gICAgICAgIGNvbnN0IHNpZ25TaGFyZXMgPSBhd2FpdCBNUEMuc2lnblNoYXJlKHNpZ25lck9uZVhTaGFyZSwgc2lnbmVyVHdvWVNoYXJlKTtcblxuICAgICAgICAvLyBTdGVwIFNpeFxuICAgICAgICAvLyBzaWduZXJUd28gcmVjZWl2ZXMgdGhlIEtTaGFyZSBmcm9tIHNpZ25lck9uZSBhbmQgdXNlcyBpdCBwcm9kdWNlIHByaXZhdGVcbiAgICAgICAgLy8gQlNoYXJlIChCZXRhIFNoYXJlKSB3aGljaCBzaWduZXJUd28gc2F2ZXMgYW5kIEFTaGFyZSAoQWxwaGEgU2hhcmUpXG4gICAgICAgIC8vIHdoaWNoIGlzIHNlbnQgdG8gc2lnbmVyT25lXG5cbiAgICAgICAgY29uc3Qgc2lnbkNvbnZlcnRTMjEgPSBhd2FpdCBNUEMuc2lnbkNvbnZlcnRTdGVwMSh7XG4gICAgICAgICAgeFNoYXJlOiBzaWduZXJUd29YU2hhcmUsXG4gICAgICAgICAgeVNoYXJlOiBzaWduZXJUd28ueVNoYXJlc1tzaWduZXJPbmVJbmRleF0sIC8vIFlTaGFyZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBvdGhlciBwYXJ0aWNpcGFudCBzaWduZXJPbmVcbiAgICAgICAgICBrU2hhcmU6IHNpZ25TaGFyZXMua1NoYXJlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTdGVwIFNldmVuXG4gICAgICAgIC8vIHNpZ25lck9uZSByZWNlaXZlcyB0aGUgQVNoYXJlIGZyb20gc2lnbmVyVHdvIGFuZCBzaWduZXJPbmUgdXNpbmcgdGhlIHByaXZhdGUgV1NoYXJlIGZyb20gc3RlcCB0d29cbiAgICAgICAgLy8gdXNlcyBpdCBwcm9kdWNlIHByaXZhdGUgR1NoYXJlIChHYW1tYSBTaGFyZSkgYW5kIE1VU2hhcmUgKE11IFNoYXJlKSB3aGljaFxuICAgICAgICAvLyBpcyBzZW50IHRvIHNpZ25lclR3byB0byBwcm9kdWNlIGl0cyBHYW1tYSBTaGFyZVxuICAgICAgICBjb25zdCBzaWduQ29udmVydFMxMiA9IGF3YWl0IE1QQy5zaWduQ29udmVydFN0ZXAyKHtcbiAgICAgICAgICBhU2hhcmU6IHNpZ25Db252ZXJ0UzIxLmFTaGFyZSxcbiAgICAgICAgICB3U2hhcmU6IHNpZ25TaGFyZXMud1NoYXJlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTdGVwIEVpZ2h0XG4gICAgICAgIC8vIHNpZ25lclR3byByZWNlaXZlcyB0aGUgTVVTaGFyZSBmcm9tIHNpZ25lck9uZSBhbmQgc2lnbmVyT25lIHVzaW5nIHRoZSBwcml2YXRlIEJTaGFyZSBmcm9tIHN0ZXAgdGhyZWVcbiAgICAgICAgLy8gdXNlcyBpdCBwcm9kdWNlIHByaXZhdGUgR1NoYXJlIChHYW1tYSBTaGFyZSlcbiAgICAgICAgY29uc3Qgc2lnbkNvbnZlcnRTMjFfMiA9IGF3YWl0IE1QQy5zaWduQ29udmVydFN0ZXAzKHtcbiAgICAgICAgICBtdVNoYXJlOiBzaWduQ29udmVydFMxMi5tdVNoYXJlLFxuICAgICAgICAgIGJTaGFyZTogc2lnbkNvbnZlcnRTMjEuYlNoYXJlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBTdGVwIE5pbmVcbiAgICAgICAgLy8gc2lnbmVyT25lIGFuZCBzaWduZXJUd28gYm90aCBoYXZlIHN1Y2Nlc3NmdWxseSBnZW5lcmF0ZWQgR1NoYXJlcyBhbmQgdGhleSB1c2VcbiAgICAgICAgLy8gdGhlIHNpZ24gY29tYmluZSBmdW5jdGlvbiB0byBnZW5lcmF0ZSB0aGVpciBwcml2YXRlIG9taWNyb24gc2hhcmVzIGFuZFxuICAgICAgICAvLyBkZWx0YSBzaGFyZXMgd2hpY2ggdGhleSBzaGFyZSB0byBlYWNoIG90aGVyXG5cbiAgICAgICAgY29uc3QgW3NpZ25Db21iaW5lT25lLCBzaWduQ29tYmluZVR3b10gPSBbXG4gICAgICAgICAgTVBDLnNpZ25Db21iaW5lKHtcbiAgICAgICAgICAgIGdTaGFyZTogc2lnbkNvbnZlcnRTMTIuZ1NoYXJlLFxuICAgICAgICAgICAgc2lnbkluZGV4OiB7XG4gICAgICAgICAgICAgIGk6IHNpZ25Db252ZXJ0UzEyLm11U2hhcmUuaSxcbiAgICAgICAgICAgICAgajogc2lnbkNvbnZlcnRTMTIubXVTaGFyZS5qLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBNUEMuc2lnbkNvbWJpbmUoe1xuICAgICAgICAgICAgZ1NoYXJlOiBzaWduQ29udmVydFMyMV8yLmdTaGFyZSxcbiAgICAgICAgICAgIHNpZ25JbmRleDoge1xuICAgICAgICAgICAgICBpOiBzaWduQ29udmVydFMyMV8yLnNpZ25JbmRleC5pLFxuICAgICAgICAgICAgICBqOiBzaWduQ29udmVydFMyMV8yLnNpZ25JbmRleC5qLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgXTtcblxuICAgICAgICBjb25zdCBNRVNTQUdFID0gQnVmZmVyLmZyb20oJ1RPTyBNQU5ZIFNFQ1JFVFMnKTtcblxuICAgICAgICAvLyBTdGVwIFRlblxuICAgICAgICAvLyBzaWduZXJPbmUgYW5kIHNpZ25lclR3byBzaGFyZXMgdGhlIGRlbHRhIHNoYXJlIGZyb20gZWFjaCBvdGhlclxuICAgICAgICAvLyBhbmQgZmluYWxseSBzaWducyB0aGUgbWVzc2FnZSB1c2luZyB0aGVpciBwcml2YXRlIE9TaGFyZVxuICAgICAgICAvLyBhbmQgZGVsdGEgc2hhcmUgcmVjZWl2ZWQgZnJvbSB0aGUgb3RoZXIgc2lnbmVyXG5cbiAgICAgICAgY29uc3QgaGFzaEdlbmVyYXRvciA9IChoYXNoVHlwZT86IHN0cmluZyk6IEhhc2ggfCB1bmRlZmluZWQgPT4ge1xuICAgICAgICAgIHJldHVybiBoYXNoVHlwZSA9PT0gJ2tlY2NhazI1NicgPyAoY3JlYXRlS2VjY2FrSGFzaCgna2VjY2FrMjU2JykgYXMgSGFzaCkgOiB1bmRlZmluZWQ7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IFtzaWduQSwgc2lnbkJdID0gW1xuICAgICAgICAgIE1QQy5zaWduKFxuICAgICAgICAgICAgTUVTU0FHRSxcbiAgICAgICAgICAgIHNpZ25Db21iaW5lT25lLm9TaGFyZSxcbiAgICAgICAgICAgIHNpZ25Db21iaW5lVHdvLmRTaGFyZSxcbiAgICAgICAgICAgIGhhc2hHZW5lcmF0b3IoY29uZmlnW2luZGV4XS5oYXNoKSxcbiAgICAgICAgICAgIGNvbmZpZ1tpbmRleF0uc2hvdWxkSGFzaCxcbiAgICAgICAgICApLFxuICAgICAgICAgIE1QQy5zaWduKFxuICAgICAgICAgICAgTUVTU0FHRSxcbiAgICAgICAgICAgIHNpZ25Db21iaW5lVHdvLm9TaGFyZSxcbiAgICAgICAgICAgIHNpZ25Db21iaW5lT25lLmRTaGFyZSxcbiAgICAgICAgICAgIGhhc2hHZW5lcmF0b3IoY29uZmlnW2luZGV4XS5oYXNoKSxcbiAgICAgICAgICAgIGNvbmZpZ1tpbmRleF0uc2hvdWxkSGFzaCxcbiAgICAgICAgICApLFxuICAgICAgICBdO1xuXG4gICAgICAgIC8vIFN0ZXAgRWxldmVuXG4gICAgICAgIC8vIENvbnN0cnVjdCB0aGUgZmluYWwgc2lnbmF0dXJlXG5cbiAgICAgICAgY29uc3Qgc2lnbmF0dXJlID0gTVBDLmNvbnN0cnVjdFNpZ25hdHVyZShbc2lnbkEsIHNpZ25CXSk7XG5cbiAgICAgICAgLy8gU3RlcCBUd2VsdmVcbiAgICAgICAgLy8gVmVyaWZ5IHNpZ25hdHVyZVxuXG4gICAgICAgIGNvbnN0IGlzVmFsaWQgPSBNUEMudmVyaWZ5KE1FU1NBR0UsIHNpZ25hdHVyZSwgaGFzaEdlbmVyYXRvcihjb25maWdbaW5kZXhdLmhhc2gpLCBjb25maWdbaW5kZXhdLnNob3VsZEhhc2gpO1xuICAgICAgICBpc1ZhbGlkLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSk7XG59KTtcbiJdfQ==

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


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