UNPKG

bitgo

Version:
378 lines • 71.4 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const nock = require("nock");
const openpgp = require("openpgp");
const cbor_x_1 = require("cbor-x");
const sdk_test_1 = require("@bitgo/sdk-test");
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
const src_1 = require("../../../../../../src");
function serializeVrfMessages(messages) {
    const transfers = [
        ...messages.broadcastMessages.map((m) => ({ from: m.from, payload: Buffer.from(m.payload).toString('base64') })),
        ...messages.p2pMessages.map((m) => ({
            from: m.from,
            to: m.to,
            payload: Buffer.from(m.payload).toString('base64'),
        })),
    ];
    return Buffer.from(JSON.stringify(transfers)).toString('base64');
}
function deserializeVrfMessages(blob, forParty) {
    const transfers = JSON.parse(Buffer.from(blob, 'base64').toString());
    return {
        broadcastMessages: transfers
            .filter((t) => t.to === undefined)
            .map((t) => ({ from: t.from, payload: new Uint8Array(Buffer.from(t.payload, 'base64')) })),
        p2pMessages: transfers
            .filter((t) => t.to === forParty)
            .map((t) => ({ from: t.from, to: t.to, payload: new Uint8Array(Buffer.from(t.payload, 'base64')) })),
    };
}
describe('TSS Ecdsa VRF MPCv2 Utils:', async function () {
    const coinName = 'hteth';
    const enterpriseId = '6449153a6f6bc20006d66771cdbe15d3';
    const safeId = '6fa8537e3ef5a878fd3ae899f3ab7e5a';
    let storedUserCommitment2;
    let storedBackupCommitment2;
    let storedBitgoCommitment2;
    let storedBitgoVrfOpenings;
    let bgUrl;
    let tssUtils;
    let wallet;
    let bitgo;
    let baseCoin;
    let bitgoVrfShare;
    let bitGoGgpKey;
    let constants;
    let bitgoGpgPrvKey;
    let userGpgPubKey;
    let backupGpgPubKey;
    beforeEach(async function () {
        nock.cleanAll();
        await nockGetBitgoPublicKeyBasedOnFeatureFlags(coinName, enterpriseId, bitGoGgpKey);
        nock(bgUrl).get('/api/v1/client/constants').times(16).reply(200, { ttl: 3600, constants });
    });
    before(async function () {
        // Allow secp256k1 GPG keys used by these fixtures (the full suite enables this
        // globally via sibling test files; set it here so this file also runs in isolation).
        openpgp.config.rejectCurves = new Set();
        bitGoGgpKey = await openpgp.generateKey({
            userIDs: [
                {
                    name: 'bitgo',
                    email: 'bitgo@test.com',
                },
            ],
            curve: 'secp256k1',
        });
        constants = {
            mpc: {
                bitgoPublicKey: bitGoGgpKey.publicKey,
                bitgoMPCv2PublicKey: bitGoGgpKey.publicKey,
            },
        };
        bitgoGpgPrvKey = {
            partyId: 2,
            gpgKey: bitGoGgpKey.privateKey,
        };
        bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
        bitgo.initializeTestVars();
        baseCoin = bitgo.coin(coinName);
        bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
        const walletData = {
            id: '5b34252f1bf349930e34020a00000000',
            enterprise: enterpriseId,
            coin: coinName,
            coinSpecific: {},
            multisigType: 'tss',
        };
        wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData);
        tssUtils = new sdk_core_1.ECDSAUtils.EcdsaVrfMPCv2Utils(bitgo, baseCoin, wallet);
    });
    after(function () {
        nock.cleanAll();
    });
    it('should generate TSS MPCv2 keys with VRF keyshares for safe roots', async function () {
        const bitgoSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, 2);
        const bitgoVrfSession = new sdk_lib_mpc_1.DklsVrf.VrfDkg(3, 2, 2);
        const round1Nock = await nockKeyGenRound1(bitgoSession, bitgoVrfSession);
        const round2Nock = await nockKeyGenRound2(bitgoSession, bitgoVrfSession);
        const round3Nock = await nockKeyGenRound3(bitgoSession, bitgoVrfSession);
        const addKeyNock = await nockAddKeyChain(coinName, 3);
        const params = {
            passphrase: 'test',
            enterprise: enterpriseId,
            originalPasscodeEncryptionCode: '123456',
            safeId,
        };
        const { userKeychain, backupKeychain, bitgoKeychain } = await tssUtils.createKeychains(params);
        assert.ok(round1Nock.isDone());
        assert.ok(round2Nock.isDone());
        assert.ok(round3Nock.isDone());
        assert.ok(addKeyNock.isDone());
        assert.ok(userKeychain);
        assert.equal(userKeychain.source, 'user');
        assert.ok(userKeychain.commonKeychain);
        assert.ok(sdk_core_1.ECDSAUtils.EcdsaMPCv2Utils.validateCommonKeychainPublicKey(userKeychain.commonKeychain));
        assert.ok(userKeychain.encryptedPrv);
        assert.ok(backupKeychain);
        assert.ok(backupKeychain.encryptedPrv);
        assert.ok(bitgoKeychain);
        // The VRF DKG must have completed on the (simulated) HSM side as well.
        assert.ok(bitgoVrfShare, 'BitGo VRF keyshare was not produced');
        assert.ok(userKeychain.encryptedPrv);
        const decryptedUserPrv = await bitgo.decrypt({ input: userKeychain.encryptedPrv, password: params.passphrase });
        const userEnvelope = (0, cbor_x_1.decode)(Buffer.from(decryptedUserPrv, 'base64'));
        assert.equal(userEnvelope.version, 1);
        assert.ok(userEnvelope.prvKeyShare);
        assert.ok(userEnvelope.vrf);
        const userKeyShare = Buffer.from(userEnvelope.prvKeyShare);
        assert.equal(sdk_lib_mpc_1.DklsTypes.getCommonKeychain(userKeyShare), userKeychain.commonKeychain);
        const userVrfShare = (0, cbor_x_1.decode)(userEnvelope.vrf);
        assert.equal(userVrfShare.party_id, 0);
        // All three parties' VRF DKGs agree on the VRF public key.
        assert.equal(Buffer.from(userVrfShare.public_key).toString('hex'), Buffer.from(bitgoVrfShare.public_key).toString('hex'));
        assert.ok(backupKeychain.encryptedPrv);
        const decryptedBackupPrv = await bitgo.decrypt({
            input: backupKeychain.encryptedPrv,
            password: params.passphrase,
        });
        const backupEnvelope = (0, cbor_x_1.decode)(Buffer.from(decryptedBackupPrv, 'base64'));
        assert.equal(backupEnvelope.version, 1);
        const backupVrfShare = (0, cbor_x_1.decode)(backupEnvelope.vrf);
        assert.equal(backupVrfShare.party_id, 1);
        assert.equal(Buffer.from(backupVrfShare.public_key).toString('hex'), Buffer.from(bitgoVrfShare.public_key).toString('hex'));
        assert.notDeepStrictEqual(userVrfShare.d_i, backupVrfShare.d_i);
        // reducedEncryptedPrv takes the same envelope and carries VRF material.
        const reducedEncryptedPrv = userKeychain.reducedEncryptedPrv;
        assert.ok(reducedEncryptedPrv);
        const reducedDecrypted = await bitgo.decrypt({ input: reducedEncryptedPrv, password: params.passphrase });
        const reducedEnvelope = (0, cbor_x_1.decode)(Buffer.from(reducedDecrypted, 'base64'));
        assert.equal(reducedEnvelope.version, 1);
        const reducedKeyShare = sdk_lib_mpc_1.DklsTypes.getDecodedReducedKeyShare(Buffer.from(reducedEnvelope.prvKeyShare));
        assert.ok(reducedKeyShare.prv.length > 0);
        assert.ok(Buffer.from(reducedEnvelope.vrf).length > 0);
        // common keychains agree across parties
        assert.equal(userKeychain.commonKeychain, backupKeychain.commonKeychain);
        assert.equal(userKeychain.commonKeychain, bitgoKeychain.commonKeychain);
    });
    async function nockGetBitgoPublicKeyBasedOnFeatureFlags(coin, enterpriseId, bitgoGpgKeyPair) {
        const bitgoGPGPublicKeyResponse = {
            name: 'irrelevant',
            publicKey: bitgoGpgKeyPair.publicKey,
            mpcv2PublicKey: bitgoGpgKeyPair.publicKey,
            enterpriseId,
        };
        nock(bgUrl).get(`/api/v2/${coin}/tss/pubkey`).query({ enterpriseId }).reply(200, bitgoGPGPublicKeyResponse);
        return bitgoGPGPublicKeyResponse;
    }
    async function nockKeyGenRound1(bitgoSession, bitgoVrfSession, times = 1) {
        return nock(bgUrl)
            .post(`/api/v2/mpc/generatekey`, (body) => body.round === 'MPCv2-R1')
            .times(times)
            .reply(200, async (uri, { payload }) => {
            const { userGpgPublicKey, backupGpgPublicKey, userMsg1, backupMsg1, userVrfMsg1, backupVrfMsg1 } = payload;
            assert.ok(userVrfMsg1, 'userVrfMsg1 must be present on a safe keygen round 1 payload');
            assert.ok(backupVrfMsg1, 'backupVrfMsg1 must be present on a safe keygen round 1 payload');
            userGpgPubKey = {
                partyId: 0,
                gpgKey: userGpgPublicKey,
            };
            backupGpgPubKey = {
                partyId: 1,
                gpgKey: backupGpgPublicKey,
            };
            const bitgoBroadcastMsg1Unsigned = await bitgoSession.initDkg();
            const bitgoMsgs1Signed = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages({ broadcastMessages: [sdk_lib_mpc_1.DklsTypes.serializeBroadcastMessage(bitgoBroadcastMsg1Unsigned)], p2pMessages: [] }, [], [bitgoGpgPrvKey]);
            const bitgoMsg1 = bitgoMsgs1Signed.broadcastMessages.find((m) => m.from === 2);
            assert.ok(bitgoMsg1, 'bitgoMsg1 not found');
            const round1IncomingMsgs = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                p2pMessages: [],
                broadcastMessages: [
                    { from: 0, payload: userMsg1 },
                    { from: 1, payload: backupMsg1 },
                ],
            }, [userGpgPubKey, backupGpgPubKey], [bitgoGpgPrvKey]);
            const round2Messages = sdk_lib_mpc_1.DklsTypes.serializeMessages(bitgoSession.handleIncomingMessages(sdk_lib_mpc_1.DklsTypes.deserializeMessages(round1IncomingMsgs)));
            const round2SignedMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(round2Messages, [userGpgPubKey, backupGpgPubKey], [bitgoGpgPrvKey]);
            const bitgoToUserMsg2 = round2SignedMessages.p2pMessages.find((m) => m.to === 0);
            const bitgoToBackupMsg2 = round2SignedMessages.p2pMessages.find((m) => m.to === 1);
            assert.ok(bitgoToUserMsg2, 'bitgoToUserMsg2 not found');
            assert.ok(bitgoToBackupMsg2, 'bitgoToBackupMsg2 not found');
            assert.ok(bitgoToUserMsg2.commitment, 'bitgoToUserMsg2.commitment not found');
            storedBitgoCommitment2 = bitgoToUserMsg2?.commitment;
            // VRF DKG: BitGo commits, then consumes user and backup commitments.
            const bitgoVrfMsg1Unsigned = await bitgoVrfSession.initDkg();
            const userVrfCommitments = deserializeVrfMessages(userVrfMsg1, 2);
            const backupVrfCommitments = deserializeVrfMessages(backupVrfMsg1, 2);
            assert.equal(userVrfCommitments.broadcastMessages.length, 1);
            assert.equal(userVrfCommitments.broadcastMessages[0].from, 0);
            assert.equal(backupVrfCommitments.broadcastMessages.length, 1);
            assert.equal(backupVrfCommitments.broadcastMessages[0].from, 1);
            storedBitgoVrfOpenings = await bitgoVrfSession.handleIncomingMessages({
                broadcastMessages: [...userVrfCommitments.broadcastMessages, ...backupVrfCommitments.broadcastMessages],
                p2pMessages: [],
            });
            // BitGo's openings are addressed to each party, itself included.
            assert.equal(storedBitgoVrfOpenings.p2pMessages.length, 3);
            return {
                sessionId: 'testid',
                bitgoMsg1: { from: 2, ...bitgoMsg1.payload },
                bitgoToBackupMsg2: {
                    from: 2,
                    to: 1,
                    encryptedMessage: bitgoToBackupMsg2.payload.encryptedMessage,
                    signature: bitgoToBackupMsg2.payload.signature,
                },
                bitgoToUserMsg2: {
                    from: 2,
                    to: 0,
                    encryptedMessage: bitgoToUserMsg2.payload.encryptedMessage,
                    signature: bitgoToUserMsg2.payload.signature,
                },
                walletGpgPubKeySigs: 'something',
                bitgoVrfMsg1: serializeVrfMessages(bitgoVrfMsg1Unsigned),
            };
        });
    }
    async function nockKeyGenRound2(bitgoSession, bitgoVrfSession, times = 1) {
        return nock(bgUrl)
            .post(`/api/v2/mpc/generatekey`, (body) => body.round === 'MPCv2-R2')
            .times(times)
            .reply(200, async (uri, { payload }) => {
            const { sessionId, userMsg2, backupMsg2, userCommitment2, backupCommitment2, userVrfMsg2, backupVrfMsg2 } = payload;
            assert.ok(userVrfMsg2, 'userVrfMsg2 must be present on a safe keygen round 2 payload');
            assert.ok(backupVrfMsg2, 'backupVrfMsg2 must be present on a safe keygen round 2 payload');
            storedUserCommitment2 = userCommitment2;
            storedBackupCommitment2 = backupCommitment2;
            const round2IncomingMsgs = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                p2pMessages: [
                    {
                        from: userMsg2.from,
                        to: userMsg2.to,
                        payload: { signature: userMsg2.signature, encryptedMessage: userMsg2.encryptedMessage },
                    },
                    {
                        from: backupMsg2.from,
                        to: backupMsg2.to,
                        payload: { signature: backupMsg2.signature, encryptedMessage: backupMsg2.encryptedMessage },
                    },
                ],
                broadcastMessages: [],
            }, [userGpgPubKey, backupGpgPubKey], [bitgoGpgPrvKey]);
            const round3Messages = sdk_lib_mpc_1.DklsTypes.serializeMessages(bitgoSession.handleIncomingMessages(sdk_lib_mpc_1.DklsTypes.deserializeMessages(round2IncomingMsgs)));
            const round3SignedMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(round3Messages, [userGpgPubKey, backupGpgPubKey], [bitgoGpgPrvKey]);
            const bitgoToUserMsg3 = round3SignedMessages.p2pMessages.find((m) => m.to === 0);
            const bitgoToBackupMsg3 = round3SignedMessages.p2pMessages.find((m) => m.to === 1);
            assert.ok(bitgoToUserMsg3, 'bitgoToUserMsg3 not found');
            assert.ok(bitgoToBackupMsg3, 'bitgoToBackupMsg3 not found');
            // VRF DKG: BitGo consumes the openings addressed to it (its own included) and finalizes.
            const userOpenings = deserializeVrfMessages(userVrfMsg2, 2).p2pMessages;
            const backupOpenings = deserializeVrfMessages(backupVrfMsg2, 2).p2pMessages;
            assert.ok(userOpenings.some((m) => m.from === 0 && m.to === 2));
            assert.ok(backupOpenings.some((m) => m.from === 1 && m.to === 2));
            assert.ok(storedBitgoVrfOpenings, 'BitGo VRF openings from round 1 not found');
            await bitgoVrfSession.handleIncomingMessages({
                broadcastMessages: [],
                p2pMessages: [
                    ...userOpenings,
                    ...backupOpenings,
                    ...storedBitgoVrfOpenings.p2pMessages.filter((m) => m.to === 2),
                ],
            });
            const share = (0, cbor_x_1.decode)(bitgoVrfSession.getKeyShare());
            assert.equal(share.party_id, 2);
            bitgoVrfShare = share;
            return {
                sessionId,
                bitgoCommitment2: storedBitgoCommitment2,
                bitgoToUserMsg3: {
                    from: 2,
                    to: 0,
                    encryptedMessage: bitgoToUserMsg3.payload.encryptedMessage,
                    signature: bitgoToUserMsg3.payload.signature,
                },
                bitgoToBackupMsg3: {
                    from: 2,
                    to: 1,
                    encryptedMessage: bitgoToBackupMsg3.payload.encryptedMessage,
                    signature: bitgoToBackupMsg3.payload.signature,
                },
                // BitGo's full opening batch, so user (0) and backup (1) can each pick theirs.
                bitgoVrfMsg2: serializeVrfMessages(storedBitgoVrfOpenings),
            };
        });
    }
    async function nockKeyGenRound3(bitgoSession, bitgoVrfSession, times = 1) {
        return nock(bgUrl)
            .post(`/api/v2/mpc/generatekey`, (body) => body.round === 'MPCv2-R3')
            .times(times)
            .reply(200, async (uri, { payload }) => {
            const { sessionId, userMsg3, userMsg4, backupMsg3, backupMsg4 } = payload;
            // The VRF DKG has no messages on round 3; it already finalized after round 2.
            assert.ok(bitgoVrfShare, 'BitGo VRF keyshare should be complete before round 3');
            const round3IncomingMsgs = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                p2pMessages: [
                    {
                        from: userMsg3.from,
                        to: userMsg3.to,
                        payload: { signature: userMsg3.signature, encryptedMessage: userMsg3.encryptedMessage },
                        commitment: storedUserCommitment2,
                    },
                    {
                        from: backupMsg3.from,
                        to: backupMsg3.to,
                        payload: { signature: backupMsg3.signature, encryptedMessage: backupMsg3.encryptedMessage },
                        commitment: storedBackupCommitment2,
                    },
                ],
                broadcastMessages: [],
            }, [userGpgPubKey, backupGpgPubKey], [bitgoGpgPrvKey]);
            const round4Messages = sdk_lib_mpc_1.DklsTypes.serializeMessages(bitgoSession.handleIncomingMessages(sdk_lib_mpc_1.DklsTypes.deserializeMessages(round3IncomingMsgs)));
            const round4SignedMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(round4Messages, [], [bitgoGpgPrvKey]);
            const bitgoMsg4 = round4SignedMessages.broadcastMessages.find((m) => m.from === 2);
            assert.ok(bitgoMsg4, 'bitgoMsg4 not found');
            const round4IncomingMsgs = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                p2pMessages: [],
                broadcastMessages: [
                    {
                        from: userMsg4.from,
                        payload: { signature: userMsg4.signature, message: userMsg4.message },
                    },
                    {
                        from: backupMsg4.from,
                        payload: { signature: backupMsg4.signature, message: backupMsg4.message },
                    },
                ],
            }, [userGpgPubKey, backupGpgPubKey], []);
            bitgoSession.handleIncomingMessages(sdk_lib_mpc_1.DklsTypes.deserializeMessages(round4IncomingMsgs));
            const keyShare = bitgoSession.getKeyShare();
            const commonKeychain = sdk_lib_mpc_1.DklsTypes.getCommonKeychain(keyShare);
            return {
                sessionId,
                commonKeychain: commonKeychain,
                bitgoMsg4: { from: 2, ...bitgoMsg4.payload },
            };
        });
    }
    async function nockAddKeyChain(coin, times = 1) {
        return nock('https://bitgo.fakeurl')
            .post(`/api/v2/${coin}/key`, (body) => body.keyType === 'tss' && body.isMPCv2 && body.safeId === safeId)
            .times(times)
            .reply(200, async (uri, requestBody) => {
            const key = {
                id: requestBody.source,
                source: requestBody.source,
                type: requestBody.keyType,
                commonKeychain: requestBody.commonKeychain,
                encryptedPrv: requestBody.encryptedPrv,
            };
            // nock gets
            nock('https://bitgo.fakeurl').get(`/api/v2/${coin}/key/${requestBody.source}`).reply(200, key);
            return key;
        });
    }
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlS2V5Y2hhaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vdGVzdC92Mi91bml0L2ludGVybmFsL3Rzc1V0aWxzL2VjZHNhVnJmTVBDdjIvY3JlYXRlS2V5Y2hhaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaUNBQWlDO0FBQ2pDLDZCQUE4QjtBQUM5QixtQ0FBbUM7QUFDbkMsbUNBQWdDO0FBRWhDLDhDQUF3RDtBQUN4RCw4Q0FBcUc7QUFDckcsb0RBQTRFO0FBVTVFLCtDQUFpRTtBQVlqRSxTQUFTLG9CQUFvQixDQUFDLFFBQXdDO0lBQ3BFLE1BQU0sU0FBUyxHQUF5QjtRQUN0QyxHQUFHLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNoSCxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2xDLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSTtZQUNaLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRTtZQUNSLE9BQU8sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO1NBQ25ELENBQUMsQ0FBQztLQUNKLENBQUM7SUFDRixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNuRSxDQUFDO0FBRUQsU0FBUyxzQkFBc0IsQ0FBQyxJQUFZLEVBQUUsUUFBZ0I7SUFDNUQsTUFBTSxTQUFTLEdBQXlCLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUMzRixPQUFPO1FBQ0wsaUJBQWlCLEVBQUUsU0FBUzthQUN6QixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssU0FBUyxDQUFDO2FBQ2pDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUYsV0FBVyxFQUFFLFNBQVM7YUFDbkIsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUE0QyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxRQUFRLENBQUM7YUFDMUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztLQUN2RyxDQUFDO0FBQ0osQ0FBQztBQXlCRCxRQUFRLENBQUMsNEJBQTRCLEVBQUUsS0FBSztJQUMxQyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUM7SUFDekIsTUFBTSxZQUFZLEdBQUcsa0NBQWtDLENBQUM7SUFDeEQsTUFBTSxNQUFNLEdBQUcsa0NBQWtDLENBQUM7SUFDbEQsSUFBSSxxQkFBNkIsQ0FBQztJQUNsQyxJQUFJLHVCQUErQixDQUFDO0lBQ3BDLElBQUksc0JBQThCLENBQUM7SUFDbkMsSUFBSSxzQkFBa0UsQ0FBQztJQUV2RSxJQUFJLEtBQWEsQ0FBQztJQUNsQixJQUFJLFFBQXVDLENBQUM7SUFDNUMsSUFBSSxNQUFjLENBQUM7SUFDbkIsSUFBSSxLQUF5QixDQUFDO0lBQzlCLElBQUksUUFBa0IsQ0FBQztJQUN2QixJQUFJLGFBQTZDLENBQUM7SUFDbEQsSUFBSSxXQUVILENBQUM7SUFDRixJQUFJLFNBQTJFLENBQUM7SUFDaEYsSUFBSSxjQUFtRCxDQUFDO0lBQ3hELElBQUksYUFBa0QsQ0FBQztJQUN2RCxJQUFJLGVBQW9ELENBQUM7SUFFekQsVUFBVSxDQUFDLEtBQUs7UUFDZCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDaEIsTUFBTSx3Q0FBd0MsQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3BGLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsMEJBQTBCLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUM3RixDQUFDLENBQUMsQ0FBQztJQUVILE1BQU0sQ0FBQyxLQUFLO1FBQ1YsK0VBQStFO1FBQy9FLHFGQUFxRjtRQUNyRixPQUFPLENBQUMsTUFBTSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ3hDLFdBQVcsR0FBRyxNQUFNLE9BQU8sQ0FBQyxXQUFXLENBQUM7WUFDdEMsT0FBTyxFQUFFO2dCQUNQO29CQUNFLElBQUksRUFBRSxPQUFPO29CQUNiLEtBQUssRUFBRSxnQkFBZ0I7aUJBQ3hCO2FBQ0Y7WUFDRCxLQUFLLEVBQUUsV0FBVztTQUNuQixDQUFDLENBQUM7UUFDSCxTQUFTLEdBQUc7WUFDVixHQUFHLEVBQUU7Z0JBQ0gsY0FBYyxFQUFFLFdBQVcsQ0FBQyxTQUFTO2dCQUNyQyxtQkFBbUIsRUFBRSxXQUFXLENBQUMsU0FBUzthQUMzQztTQUNGLENBQUM7UUFFRixjQUFjLEdBQUc7WUFDZixPQUFPLEVBQUUsQ0FBQztZQUNWLE1BQU0sRUFBRSxXQUFXLENBQUMsVUFBVTtTQUMvQixDQUFDO1FBRUYsS0FBSyxHQUFHLG9CQUFTLENBQUMsUUFBUSxDQUFDLFdBQUssRUFBRSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ25ELEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBRTNCLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRWhDLEtBQUssR0FBRyxpQkFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFFaEQsTUFBTSxVQUFVLEdBQUc7WUFDakIsRUFBRSxFQUFFLGtDQUFrQztZQUN0QyxVQUFVLEVBQUUsWUFBWTtZQUN4QixJQUFJLEVBQUUsUUFBUTtZQUNkLFlBQVksRUFBRSxFQUFFO1lBQ2hCLFlBQVksRUFBRSxLQUFLO1NBQ3BCLENBQUM7UUFDRixNQUFNLEdBQUcsSUFBSSxpQkFBTSxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDakQsUUFBUSxHQUFHLElBQUkscUJBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3hFLENBQUMsQ0FBQyxDQUFDO0lBRUgsS0FBSyxDQUFDO1FBQ0osSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLGtFQUFrRSxFQUFFLEtBQUs7UUFDMUUsTUFBTSxZQUFZLEdBQUcsSUFBSSxxQkFBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sZUFBZSxHQUFHLElBQUkscUJBQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUVwRCxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxlQUFlLENBQUMsQ0FBQztRQUN6RSxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxlQUFlLENBQUMsQ0FBQztRQUN6RSxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxlQUFlLENBQUMsQ0FBQztRQUN6RSxNQUFNLFVBQVUsR0FBRyxNQUFNLGVBQWUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdEQsTUFBTSxNQUFNLEdBQUc7WUFDYixVQUFVLEVBQUUsTUFBTTtZQUNsQixVQUFVLEVBQUUsWUFBWTtZQUN4Qiw4QkFBOEIsRUFBRSxRQUFRO1lBQ3hDLE1BQU07U0FDUCxDQUFDO1FBQ0YsTUFBTSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLEdBQUcsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9GLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMvQixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQy9CLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFFL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN4QixNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDMUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdkMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxxQkFBVSxDQUFDLGVBQWUsQ0FBQywrQkFBK0IsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztRQUNuRyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNyQyxNQUFNLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFekIsdUVBQXVFO1FBQ3ZFLE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLHFDQUFxQyxDQUFDLENBQUM7UUFFaEUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDckMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUM7UUFDaEgsTUFBTSxZQUFZLEdBQUcsSUFBQSxlQUFNLEVBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN0QyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNwQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM1QixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMzRCxNQUFNLENBQUMsS0FBSyxDQUFDLHVCQUFTLENBQUMsaUJBQWlCLENBQUMsWUFBWSxDQUFDLEVBQUUsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JGLE1BQU0sWUFBWSxHQUFHLElBQUEsZUFBTSxFQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM5QyxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdkMsMkRBQTJEO1FBQzNELE1BQU0sQ0FBQyxLQUFLLENBQ1YsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUNwRCxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQ3RELENBQUM7UUFFRixNQUFNLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN2QyxNQUFNLGtCQUFrQixHQUFHLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQztZQUM3QyxLQUFLLEVBQUUsY0FBYyxDQUFDLFlBQVk7WUFDbEMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxVQUFVO1NBQzVCLENBQUMsQ0FBQztRQUNILE1BQU0sY0FBYyxHQUFHLElBQUEsZUFBTSxFQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUN6RSxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDeEMsTUFBTSxjQUFjLEdBQUcsSUFBQSxlQUFNLEVBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN6QyxNQUFNLENBQUMsS0FBSyxDQUNWLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFDdEQsTUFBTSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUN0RCxDQUFDO1FBQ0YsTUFBTSxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRWhFLHdFQUF3RTtRQUN4RSxNQUFNLG1CQUFtQixHQUFJLFlBQTRELENBQUMsbUJBQW1CLENBQUM7UUFDOUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQy9CLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztRQUMxRyxNQUFNLGVBQWUsR0FBRyxJQUFBLGVBQU0sRUFBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDeEUsTUFBTSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLE1BQU0sZUFBZSxHQUFHLHVCQUFTLENBQUMseUJBQXlCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUN0RyxNQUFNLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRXZELHdDQUF3QztRQUN4QyxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3pFLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLGNBQWMsRUFBRSxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDMUUsQ0FBQyxDQUFDLENBQUM7SUFFSCxLQUFLLFVBQVUsd0NBQXdDLENBQ3JELElBQVksRUFDWixZQUFvQixFQUNwQixlQUFrRDtRQUVsRCxNQUFNLHlCQUF5QixHQUFzQjtZQUNuRCxJQUFJLEVBQUUsWUFBWTtZQUNsQixTQUFTLEVBQUUsZUFBZSxDQUFDLFNBQVM7WUFDcEMsY0FBYyxFQUFFLGVBQWUsQ0FBQyxTQUFTO1lBQ3pDLFlBQVk7U0FDYixDQUFDO1FBQ0YsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLElBQUksYUFBYSxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLHlCQUF5QixDQUFDLENBQUM7UUFFNUcsT0FBTyx5QkFBeUIsQ0FBQztJQUNuQyxDQUFDO0lBRUQsS0FBSyxVQUFVLGdCQUFnQixDQUFDLFlBQXlCLEVBQUUsZUFBK0IsRUFBRSxLQUFLLEdBQUcsQ0FBQztRQUNuRyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7YUFDZixJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDO2FBQ3BFLEtBQUssQ0FBQyxLQUFLLENBQUM7YUFDWixLQUFLLENBQ0osR0FBRyxFQUNILEtBQUssRUFDSCxHQUFHLEVBQ0gsRUFBRSxPQUFPLEVBQWtFLEVBQ2IsRUFBRTtZQUNoRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLEdBQUcsT0FBTyxDQUFDO1lBQzNHLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLDhEQUE4RCxDQUFDLENBQUM7WUFDdkYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsZ0VBQWdFLENBQUMsQ0FBQztZQUMzRixhQUFhLEdBQUc7Z0JBQ2QsT0FBTyxFQUFFLENBQUM7Z0JBQ1YsTUFBTSxFQUFFLGdCQUFnQjthQUN6QixDQUFDO1lBQ0YsZUFBZSxHQUFHO2dCQUNoQixPQUFPLEVBQUUsQ0FBQztnQkFDVixNQUFNLEVBQUUsa0JBQWtCO2FBQzNCLENBQUM7WUFFRixNQUFNLDBCQUEwQixHQUFHLE1BQU0sWUFBWSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2hFLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLDhCQUE4QixDQUNyRSxFQUFFLGlCQUFpQixFQUFFLENBQUMsdUJBQVMsQ0FBQyx5QkFBeUIsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxFQUN6RyxFQUFFLEVBQ0YsQ0FBQyxjQUFjLENBQUMsQ0FDakIsQ0FBQztZQUNGLE1BQU0sU0FBUyxHQUFHLGdCQUFnQixDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQztZQUMvRSxNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1lBRTVDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUN6RTtnQkFDRSxXQUFXLEVBQUUsRUFBRTtnQkFDZixpQkFBaUIsRUFBRTtvQkFDakIsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUU7b0JBQzlCLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFO2lCQUNqQzthQUNGLEVBQ0QsQ0FBQyxhQUFhLEVBQUUsZUFBZSxDQUFDLEVBQ2hDLENBQUMsY0FBYyxDQUFDLENBQ2pCLENBQUM7WUFFRixNQUFNLGNBQWMsR0FBRyx1QkFBUyxDQUFDLGlCQUFpQixDQUNoRCxZQUFZLENBQUMsc0JBQXNCLENBQUMsdUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQ3ZGLENBQUM7WUFFRixNQUFNLG9CQUFvQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyw4QkFBOEIsQ0FDekUsY0FBYyxFQUNkLENBQUMsYUFBYSxFQUFFLGVBQWUsQ0FBQyxFQUNoQyxDQUFDLGNBQWMsQ0FBQyxDQUNqQixDQUFDO1lBRUYsTUFBTSxlQUFlLEdBQUcsb0JBQW9CLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUNqRixNQUFNLGlCQUFpQixHQUFHLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDbkYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxlQUFlLEVBQUUsMkJBQTJCLENBQUMsQ0FBQztZQUN4RCxNQUFNLENBQUMsRUFBRSxDQUFDLGlCQUFpQixFQUFFLDZCQUE2QixDQUFDLENBQUM7WUFDNUQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxlQUFlLENBQUMsVUFBVSxFQUFFLHNDQUFzQyxDQUFDLENBQUM7WUFFOUUsc0JBQXNCLEdBQUcsZUFBZSxFQUFFLFVBQVUsQ0FBQztZQUVyRCxxRUFBcUU7WUFDckUsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLGVBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUM3RCxNQUFNLGtCQUFrQixHQUFHLHNCQUFzQixDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNsRSxNQUFNLG9CQUFvQixHQUFHLHNCQUFzQixDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN0RSxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM3RCxNQUFNLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5RCxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMvRCxNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNoRSxzQkFBc0IsR0FBRyxNQUFNLGVBQWUsQ0FBQyxzQkFBc0IsQ0FBQztnQkFDcEUsaUJBQWlCLEVBQUUsQ0FBQyxHQUFHLGtCQUFrQixDQUFDLGlCQUFpQixFQUFFLEdBQUcsb0JBQW9CLENBQUMsaUJBQWlCLENBQUM7Z0JBQ3ZHLFdBQVcsRUFBRSxFQUFFO2FBQ2hCLENBQUMsQ0FBQztZQUNILGlFQUFpRTtZQUNqRSxNQUFNLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFM0QsT0FBTztnQkFDTCxTQUFTLEVBQUUsUUFBMEI7Z0JBQ3JDLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBRyxTQUFTLENBQUMsT0FBTyxFQUFFO2dCQUM1QyxpQkFBaUIsRUFBRTtvQkFDakIsSUFBSSxFQUFFLENBQUM7b0JBQ1AsRUFBRSxFQUFFLENBQUM7b0JBQ0wsZ0JBQWdCLEVBQUUsaUJBQWlCLENBQUMsT0FBTyxDQUFDLGdCQUFnQjtvQkFDNUQsU0FBUyxFQUFFLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxTQUFTO2lCQUMvQztnQkFDRCxlQUFlLEVBQUU7b0JBQ2YsSUFBSSxFQUFFLENBQUM7b0JBQ1AsRUFBRSxFQUFFLENBQUM7b0JBQ0wsZ0JBQWdCLEVBQUUsZUFBZSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0I7b0JBQzFELFNBQVMsRUFBRSxlQUFlLENBQUMsT0FBTyxDQUFDLFNBQVM7aUJBQzdDO2dCQUNELG1CQUFtQixFQUFFLFdBQTZCO2dCQUNsRCxZQUFZLEVBQUUsb0JBQW9CLENBQUMsb0JBQW9CLENBQUM7YUFDekQsQ0FBQztRQUNKLENBQUMsQ0FDRixDQUFDO0lBQ04sQ0FBQztJQUVELEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxZQUF5QixFQUFFLGVBQStCLEVBQUUsS0FBSyxHQUFHLENBQUM7UUFDbkcsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO2FBQ2YsSUFBSSxDQUFDLHlCQUF5QixFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLFVBQVUsQ0FBQzthQUNwRSxLQUFLLENBQUMsS0FBSyxDQUFDO2FBQ1osS0FBSyxDQUNKLEdBQUcsRUFDSCxLQUFLLEVBQ0gsR0FBRyxFQUNILEVBQUUsT0FBTyxFQUFrRSxFQUNiLEVBQUU7WUFDaEUsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLEdBQ3ZHLE9BQU8sQ0FBQztZQUNWLE1BQU0sQ0FBQyxFQUFFLENBQUMsV0FBVyxFQUFFLDhEQUE4RCxDQUFDLENBQUM7WUFDdkYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsZ0VBQWdFLENBQUMsQ0FBQztZQUMzRixxQkFBcUIsR0FBRyxlQUFlLENBQUM7WUFDeEMsdUJBQXVCLEdBQUcsaUJBQWlCLENBQUM7WUFDNUMsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLHVCQUFTLENBQUMsZ0NBQWdDLENBQ3pFO2dCQUNFLFdBQVcsRUFBRTtvQkFDWDt3QkFDRSxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUk7d0JBQ25CLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRTt3QkFDZixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7cUJBQ3hGO29CQUNEO3dCQUNFLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTt3QkFDckIsRUFBRSxFQUFFLFVBQVUsQ0FBQyxFQUFFO3dCQUNqQixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLENBQUMsZ0JBQWdCLEVBQUU7cUJBQzVGO2lCQUNGO2dCQUNELGlCQUFpQixFQUFFLEVBQUU7YUFDdEIsRUFDRCxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsRUFDaEMsQ0FBQyxjQUFjLENBQUMsQ0FDakIsQ0FBQztZQUVGLE1BQU0sY0FBYyxHQUFHLHVCQUFTLENBQUMsaUJBQWlCLENBQ2hELFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyx1QkFBUyxDQUFDLG1CQUFtQixDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FDdkYsQ0FBQztZQUVGLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSx1QkFBUyxDQUFDLDhCQUE4QixDQUN6RSxjQUFjLEVBQ2QsQ0FBQyxhQUFhLEVBQUUsZUFBZSxDQUFDLEVBQ2hDLENBQUMsY0FBYyxDQUFDLENBQ2pCLENBQUM7WUFFRixNQUFNLGVBQWUsR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ2pGLE1BQU0saUJBQWlCLEdBQUcsb0JBQW9CLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUNuRixNQUFNLENBQUMsRUFBRSxDQUFDLGVBQWUsRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxFQUFFLENBQUMsaUJBQWlCLEVBQUUsNkJBQTZCLENBQUMsQ0FBQztZQUU1RCx5RkFBeUY7WUFDekYsTUFBTSxZQUFZLEdBQUcsc0JBQXNCLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztZQUN4RSxNQUFNLGNBQWMsR0FBRyxzQkFBc0IsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1lBQzVFLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2hFLE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sQ0FBQyxFQUFFLENBQUMsc0JBQXNCLEVBQUUsMkNBQTJDLENBQUMsQ0FBQztZQUMvRSxNQUFNLGVBQWUsQ0FBQyxzQkFBc0IsQ0FBQztnQkFDM0MsaUJBQWlCLEVBQUUsRUFBRTtnQkFDckIsV0FBVyxFQUFFO29CQUNYLEdBQUcsWUFBWTtvQkFDZixHQUFHLGNBQWM7b0JBQ2pCLEdBQUcsc0JBQXNCLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7aUJBQ2hFO2FBQ0YsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxLQUFLLEdBQUcsSUFBQSxlQUFNLEVBQUMsZUFBZSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDcEQsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLGFBQWEsR0FBRyxLQUFLLENBQUM7WUFFdEIsT0FBTztnQkFDTCxTQUFTO2dCQUNULGdCQUFnQixFQUFFLHNCQUF3QztnQkFDMUQsZUFBZSxFQUFFO29CQUNmLElBQUksRUFBRSxDQUFDO29CQUNQLEVBQUUsRUFBRSxDQUFDO29CQUNMLGdCQUFnQixFQUFFLGVBQWUsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCO29CQUMxRCxTQUFTLEVBQUUsZUFBZSxDQUFDLE9BQU8sQ0FBQyxTQUFTO2lCQUM3QztnQkFDRCxpQkFBaUIsRUFBRTtvQkFDakIsSUFBSSxFQUFFLENBQUM7b0JBQ1AsRUFBRSxFQUFFLENBQUM7b0JBQ0wsZ0JBQWdCLEVBQUUsaUJBQWlCLENBQUMsT0FBTyxDQUFDLGdCQUFnQjtvQkFDNUQsU0FBUyxFQUFFLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxTQUFTO2lCQUMvQztnQkFDRCwrRUFBK0U7Z0JBQy9FLFlBQVksRUFBRSxvQkFBb0IsQ0FBQyxzQkFBc0IsQ0FBQzthQUMzRCxDQUFDO1FBQ0osQ0FBQyxDQUNGLENBQUM7SUFDTixDQUFDO0lBRUQsS0FBSyxVQUFVLGdCQUFnQixDQUFDLFlBQXlCLEVBQUUsZUFBK0IsRUFBRSxLQUFLLEdBQUcsQ0FBQztRQUNuRyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7YUFDZixJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDO2FBQ3BFLEtBQUssQ0FBQyxLQUFLLENBQUM7YUFDWixLQUFLLENBQ0osR0FBRyxFQUNILEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQXlDLEVBQXNDLEVBQUU7WUFDcEcsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUM7WUFDMUUsOEVBQThFO1lBQzlFLE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLHNEQUFzRCxDQUFDLENBQUM7WUFFakYsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLHVCQUFTLENBQUMsZ0NBQWdDLENBQ3pFO2dCQUNFLFdBQVcsRUFBRTtvQkFDWDt3QkFDRSxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUk7d0JBQ25CLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRTt3QkFDZixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7d0JBQ3ZGLFVBQVUsRUFBRSxxQkFBcUI7cUJBQ2xDO29CQUNEO3dCQUNFLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTt3QkFDckIsRUFBRSxFQUFFLFVBQVUsQ0FBQyxFQUFFO3dCQUNqQixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLENBQUMsZ0JBQWdCLEVBQUU7d0JBQzNGLFVBQVUsRUFBRSx1QkFBdUI7cUJBQ3BDO2lCQUNGO2dCQUNELGlCQUFpQixFQUFFLEVBQUU7YUFDdEIsRUFDRCxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsRUFDaEMsQ0FBQyxjQUFjLENBQUMsQ0FDakIsQ0FBQztZQUVGLE1BQU0sY0FBYyxHQUFHLHVCQUFTLENBQUMsaUJBQWlCLENBQ2hELFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyx1QkFBUyxDQUFDLG1CQUFtQixDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FDdkYsQ0FBQztZQUNGLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSx1QkFBUyxDQUFDLDhCQUE4QixDQUN6RSxjQUFjLEVBQ2QsRUFBRSxFQUNGLENBQUMsY0FBYyxDQUFDLENBQ2pCLENBQUM7WUFDRixNQUFNLFNBQVMsR0FBRyxvQkFBb0IsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDbkYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUscUJBQXFCLENBQUMsQ0FBQztZQUU1QyxNQUFNLGtCQUFrQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyxnQ0FBZ0MsQ0FDekU7Z0JBQ0UsV0FBVyxFQUFFLEVBQUU7Z0JBQ2YsaUJBQWlCLEVBQUU7b0JBQ2pCO3dCQUNFLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTt3QkFDbkIsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEVBQUU7cUJBQ3RFO29CQUNEO3dCQUNFLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTt3QkFFckIsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLFVBQVUsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxPQUFPLEVBQUU7cUJBQzFFO2lCQUNGO2FBQ0YsRUFDRCxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsRUFDaEMsRUFBRSxDQUNILENBQUM7WUFDRixZQUFZLENBQUMsc0JBQXNCLENBQUMsdUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7WUFDdkYsTUFBTSxRQUFRLEdBQUcsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzVDLE1BQU0sY0FBYyxHQUFHLHVCQUFTLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFN0QsT0FBTztnQkFDTCxTQUFTO2dCQUNULGNBQWMsRUFBRSxjQUFnQztnQkFDaEQsU0FBUyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHLFNBQVMsQ0FBQyxPQUFPLEVBQUU7YUFDN0MsQ0FBQztRQUNKLENBQUMsQ0FDRixDQUFDO0lBQ04sQ0FBQztJQUVELEtBQUssVUFBVSxlQUFlLENBQUMsSUFBWSxFQUFFLEtBQUssR0FBRyxDQUFDO1FBQ3BELE9BQU8sSUFBSSxDQUFDLHVCQUF1QixDQUFDO2FBQ2pDLElBQUksQ0FBQyxXQUFXLElBQUksTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxLQUFLLEtBQUssSUFBSSxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssTUFBTSxDQUFDO2FBQ3ZHLEtBQUssQ0FBQyxLQUFLLENBQUM7YUFDWixLQUFLLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsV0FBK0IsRUFBRSxFQUFFO1lBQ3pELE1BQU0sR0FBRyxHQUFHO2dCQUNWLEVBQUUsRUFBRSxXQUFXLENBQUMsTUFBTTtnQkFDdEIsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNO2dCQUMxQixJQUFJLEVBQUUsV0FBVyxDQUFDLE9BQU87Z0JBQ3pCLGNBQWMsRUFBRSxXQUFXLENBQUMsY0FBYztnQkFDMUMsWUFBWSxFQUFFLFdBQVcsQ0FBQyxZQUFZO2FBQ3ZDLENBQUM7WUFDRixZQUFZO1lBQ1osSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUMsR0FBRyxDQUFDLFdBQVcsSUFBSSxRQUFRLFdBQVcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDL0YsT0FBTyxHQUFHLENBQUM7UUFDYixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0IG5vY2sgPSByZXF1aXJlKCdub2NrJyk7XG5pbXBvcnQgKiBhcyBvcGVucGdwIGZyb20gJ29wZW5wZ3AnO1xuaW1wb3J0IHsgZGVjb2RlIH0gZnJvbSAnY2Jvci14JztcblxuaW1wb3J0IHsgVGVzdGFibGVCRywgVGVzdEJpdEdvIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCB7IEFkZEtleWNoYWluT3B0aW9ucywgQmFzZUNvaW4sIGNvbW1vbiwgRUNEU0FVdGlscywgS2V5Y2hhaW4sIFdhbGxldCB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBEa2xzQ29tbXMsIERrbHNEa2csIERrbHNUeXBlcywgRGtsc1ZyZiB9IGZyb20gJ0BiaXRnby9zZGstbGliLW1wYyc7XG5pbXBvcnQge1xuICBNUEN2MktleUdlblJvdW5kMVJlcXVlc3QsXG4gIE1QQ3YyS2V5R2VuUm91bmQxUmVzcG9uc2UsXG4gIE1QQ3YyS2V5R2VuUm91bmQyUmVxdWVzdCxcbiAgTVBDdjJLZXlHZW5Sb3VuZDJSZXNwb25zZSxcbiAgTVBDdjJLZXlHZW5Sb3VuZDNSZXF1ZXN0LFxuICBNUEN2MktleUdlblJvdW5kM1Jlc3BvbnNlLFxufSBmcm9tICdAYml0Z28vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IE5vbkVtcHR5U3RyaW5nIH0gZnJvbSAnaW8tdHMtdHlwZXMnO1xuaW1wb3J0IHsgQml0R28sIEJpdGdvR1BHUHVibGljS2V5IH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vLi4vc3JjJztcblxuLyoqXG4gKiBWUkYgREtHIG1lc3NhZ2UgYmxvYnMgcmlkaW5nIHRoZSBNUEN2Mi1SMS9SMiBrZXlnZW4gcGF5bG9hZHMuIE1pcnJvcnMgdGhlIHdpcmVcbiAqIGZvcm1hdCBwcm9kdWNlZCBieSBzZGstY29yZSdzIGVjZHNhVnJmTVBDdjIudHMuXG4gKi9cbmludGVyZmFjZSBWcmZNZXNzYWdlVHJhbnNmZXIge1xuICBmcm9tOiBudW1iZXI7XG4gIHRvPzogbnVtYmVyO1xuICBwYXlsb2FkOiBzdHJpbmc7IC8vIGJhc2U2NFxufVxuXG5mdW5jdGlvbiBzZXJpYWxpemVWcmZNZXNzYWdlcyhtZXNzYWdlczogRGtsc1R5cGVzLkRlc2VyaWFsaXplZE1lc3NhZ2VzKTogc3RyaW5nIHtcbiAgY29uc3QgdHJhbnNmZXJzOiBWcmZNZXNzYWdlVHJhbnNmZXJbXSA9IFtcbiAgICAuLi5tZXNzYWdlcy5icm9hZGNhc3RNZXNzYWdlcy5tYXAoKG0pID0+ICh7IGZyb206IG0uZnJvbSwgcGF5bG9hZDogQnVmZmVyLmZyb20obS5wYXlsb2FkKS50b1N0cmluZygnYmFzZTY0JykgfSkpLFxuICAgIC4uLm1lc3NhZ2VzLnAycE1lc3NhZ2VzLm1hcCgobSkgPT4gKHtcbiAgICAgIGZyb206IG0uZnJvbSxcbiAgICAgIHRvOiBtLnRvLFxuICAgICAgcGF5bG9hZDogQnVmZmVyLmZyb20obS5wYXlsb2FkKS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgfSkpLFxuICBdO1xuICByZXR1cm4gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkodHJhbnNmZXJzKSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xufVxuXG5mdW5jdGlvbiBkZXNlcmlhbGl6ZVZyZk1lc3NhZ2VzKGJsb2I6IHN0cmluZywgZm9yUGFydHk6IG51bWJlcik6IERrbHNUeXBlcy5EZXNlcmlhbGl6ZWRNZXNzYWdlcyB7XG4gIGNvbnN0IHRyYW5zZmVyczogVnJmTWVzc2FnZVRyYW5zZmVyW10gPSBKU09OLnBhcnNlKEJ1ZmZlci5mcm9tKGJsb2IsICdiYXNlNjQnKS50b1N0cmluZygpKTtcbiAgcmV0dXJuIHtcbiAgICBicm9hZGNhc3RNZXNzYWdlczogdHJhbnNmZXJzXG4gICAgICAuZmlsdGVyKCh0KSA9PiB0LnRvID09PSB1bmRlZmluZWQpXG4gICAgICAubWFwKCh0KSA9PiAoeyBmcm9tOiB0LmZyb20sIHBheWxvYWQ6IG5ldyBVaW50OEFycmF5KEJ1ZmZlci5mcm9tKHQucGF5bG9hZCwgJ2Jhc2U2NCcpKSB9KSksXG4gICAgcDJwTWVzc2FnZXM6IHRyYW5zZmVyc1xuICAgICAgLmZpbHRlcigodCk6IHQgaXMgVnJmTWVzc2FnZVRyYW5zZmVyICYgeyB0bzogbnVtYmVyIH0gPT4gdC50byA9PT0gZm9yUGFydHkpXG4gICAgICAubWFwKCh0KSA9PiAoeyBmcm9tOiB0LmZyb20sIHRvOiB0LnRvLCBwYXlsb2FkOiBuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbSh0LnBheWxvYWQsICdiYXNlNjQnKSkgfSkpLFxuICB9O1xufVxuXG50eXBlIFZyZktleUdlblJlcXVlc3RGaWVsZHMgPSB7XG4gIHVzZXJWcmZNc2cxPzogc3RyaW5nO1xuICBiYWNrdXBWcmZNc2cxPzogc3RyaW5nO1xuICB1c2VyVnJmTXNnMj86IHN0cmluZztcbiAgYmFja3VwVnJmTXNnMj86IHN0cmluZztcbn07XG5cbnR5cGUgVnJmS2V5c2hhcmVEZWNvZGVkID0ge1xuICB0aHJlc2hvbGQ6IG51bWJlcjtcbiAgdG90YWxfcGFydGllczogbnVtYmVyO1xuICBwYXJ0eV9pZDogbnVtYmVyO1xuICBkX2k6IFVpbnQ4QXJyYXk7XG4gIHB1YmxpY19rZXk6IFVpbnQ4QXJyYXk7XG4gIHBhcnR5X3B1YmxpY19zaGFyZXM6IFVpbnQ4QXJyYXlbXTtcbiAga2V5X2lkOiBVaW50OEFycmF5O1xuICByb290X2NoYWluX2NvZGU6IFVpbnQ4QXJyYXk7XG4gIGZpbmFsX3Nlc3Npb25faWQ6IFVpbnQ4QXJyYXk7XG59O1xudHlwZSBWcmZLZXlHZW5SZXNwb25zZUZpZWxkcyA9IHtcbiAgYml0Z29WcmZNc2cxPzogc3RyaW5nO1xuICBiaXRnb1ZyZk1zZzI/OiBzdHJpbmc7XG59O1xuXG5kZXNjcmliZSgnVFNTIEVjZHNhIFZSRiBNUEN2MiBVdGlsczonLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gIGNvbnN0IGNvaW5OYW1lID0gJ2h0ZXRoJztcbiAgY29uc3QgZW50ZXJwcmlzZUlkID0gJzY0NDkxNTNhNmY2YmMyMDAwNmQ2Njc3MWNkYmUxNWQzJztcbiAgY29uc3Qgc2FmZUlkID0gJzZmYTg1MzdlM2VmNWE4NzhmZDNhZTg5OWYzYWI3ZTVhJztcbiAgbGV0IHN0b3JlZFVzZXJDb21taXRtZW50Mjogc3RyaW5nO1xuICBsZXQgc3RvcmVkQmFja3VwQ29tbWl0bWVudDI6IHN0cmluZztcbiAgbGV0IHN0b3JlZEJpdGdvQ29tbWl0bWVudDI6IHN0cmluZztcbiAgbGV0IHN0b3JlZEJpdGdvVnJmT3BlbmluZ3M6IERrbHNUeXBlcy5EZXNlcmlhbGl6ZWRNZXNzYWdlcyB8IHVuZGVmaW5lZDtcblxuICBsZXQgYmdVcmw6IHN0cmluZztcbiAgbGV0IHRzc1V0aWxzOiBFQ0RTQVV0aWxzLkVjZHNhVnJmTVBDdjJVdGlscztcbiAgbGV0IHdhbGxldDogV2FsbGV0O1xuICBsZXQgYml0Z286IFRlc3RhYmxlQkcgJiBCaXRHbztcbiAgbGV0IGJhc2VDb2luOiBCYXNlQ29pbjtcbiAgbGV0IGJpdGdvVnJmU2hhcmU6IFZyZktleXNoYXJlRGVjb2RlZCB8IHVuZGVmaW5lZDtcbiAgbGV0IGJpdEdvR2dwS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz4gJiB7XG4gICAgcmV2b2NhdGlvbkNlcnRpZmljYXRlOiBzdHJpbmc7XG4gIH07XG4gIGxldCBjb25zdGFudHM6IHsgbXBjOiB7IGJpdGdvUHVibGljS2V5OiBzdHJpbmc7IGJpdGdvTVBDdjJQdWJsaWNLZXk6IHN0cmluZyB9IH07XG4gIGxldCBiaXRnb0dwZ1BydktleTogeyBwYXJ0eUlkOiBudW1iZXI7IGdwZ0tleTogc3RyaW5nIH07XG4gIGxldCB1c2VyR3BnUHViS2V5OiB7IHBhcnR5SWQ6IG51bWJlcjsgZ3BnS2V5OiBzdHJpbmcgfTtcbiAgbGV0IGJhY2t1cEdwZ1B1YktleTogeyBwYXJ0eUlkOiBudW1iZXI7IGdwZ0tleTogc3RyaW5nIH07XG5cbiAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIGF3YWl0IG5vY2tHZXRCaXRnb1B1YmxpY0tleUJhc2VkT25GZWF0dXJlRmxhZ3MoY29pbk5hbWUsIGVudGVycHJpc2VJZCwgYml0R29HZ3BLZXkpO1xuICAgIG5vY2soYmdVcmwpLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJykudGltZXMoMTYpLnJlcGx5KDIwMCwgeyB0dGw6IDM2MDAsIGNvbnN0YW50cyB9KTtcbiAgfSk7XG5cbiAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBBbGxvdyBzZWNwMjU2azEgR1BHIGtleXMgdXNlZCBieSB0aGVzZSBmaXh0dXJlcyAodGhlIGZ1bGwgc3VpdGUgZW5hYmxlcyB0aGlzXG4gICAgLy8gZ2xvYmFsbHkgdmlhIHNpYmxpbmcgdGVzdCBmaWxlczsgc2V0IGl0IGhlcmUgc28gdGhpcyBmaWxlIGFsc28gcnVucyBpbiBpc29sYXRpb24pLlxuICAgIG9wZW5wZ3AuY29uZmlnLnJlamVjdEN1cnZlcyA9IG5ldyBTZXQoKTtcbiAgICBiaXRHb0dncEtleSA9IGF3YWl0IG9wZW5wZ3AuZ2VuZXJhdGVLZXkoe1xuICAgICAgdXNlcklEczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ2JpdGdvJyxcbiAgICAgICAgICBlbWFpbDogJ2JpdGdvQHRlc3QuY29tJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBjdXJ2ZTogJ3NlY3AyNTZrMScsXG4gICAgfSk7XG4gICAgY29uc3RhbnRzID0ge1xuICAgICAgbXBjOiB7XG4gICAgICAgIGJpdGdvUHVibGljS2V5OiBiaXRHb0dncEtleS5wdWJsaWNLZXksXG4gICAgICAgIGJpdGdvTVBDdjJQdWJsaWNLZXk6IGJpdEdvR2dwS2V5LnB1YmxpY0tleSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGJpdGdvR3BnUHJ2S2V5ID0ge1xuICAgICAgcGFydHlJZDogMixcbiAgICAgIGdwZ0tleTogYml0R29HZ3BLZXkucHJpdmF0ZUtleSxcbiAgICB9O1xuXG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG5cbiAgICBiYXNlQ29pbiA9IGJpdGdvLmNvaW4oY29pbk5hbWUpO1xuXG4gICAgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG5cbiAgICBjb25zdCB3YWxsZXREYXRhID0ge1xuICAgICAgaWQ6ICc1YjM0MjUyZjFiZjM0OTkzMGUzNDAyMGEwMDAwMDAwMCcsXG4gICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlSWQsXG4gICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgIGNvaW5TcGVjaWZpYzoge30sXG4gICAgICBtdWx0aXNpZ1R5cGU6ICd0c3MnLFxuICAgIH07XG4gICAgd2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZUNvaW4sIHdhbGxldERhdGEpO1xuICAgIHRzc1V0aWxzID0gbmV3IEVDRFNBVXRpbHMuRWNkc2FWcmZNUEN2MlV0aWxzKGJpdGdvLCBiYXNlQ29pbiwgd2FsbGV0KTtcbiAgfSk7XG5cbiAgYWZ0ZXIoZnVuY3Rpb24gKCkge1xuICAgIG5vY2suY2xlYW5BbGwoKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBUU1MgTVBDdjIga2V5cyB3aXRoIFZSRiBrZXlzaGFyZXMgZm9yIHNhZmUgcm9vdHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgYml0Z29TZXNzaW9uID0gbmV3IERrbHNEa2cuRGtnKDMsIDIsIDIpO1xuICAgIGNvbnN0IGJpdGdvVnJmU2Vzc2lvbiA9IG5ldyBEa2xzVnJmLlZyZkRrZygzLCAyLCAyKTtcblxuICAgIGNvbnN0IHJvdW5kMU5vY2sgPSBhd2FpdCBub2NrS2V5R2VuUm91bmQxKGJpdGdvU2Vzc2lvbiwgYml0Z29WcmZTZXNzaW9uKTtcbiAgICBjb25zdCByb3VuZDJOb2NrID0gYXdhaXQgbm9ja0tleUdlblJvdW5kMihiaXRnb1Nlc3Npb24sIGJpdGdvVnJmU2Vzc2lvbik7XG4gICAgY29uc3Qgcm91bmQzTm9jayA9IGF3YWl0IG5vY2tLZXlHZW5Sb3VuZDMoYml0Z29TZXNzaW9uLCBiaXRnb1ZyZlNlc3Npb24pO1xuICAgIGNvbnN0IGFkZEtleU5vY2sgPSBhd2FpdCBub2NrQWRkS2V5Q2hhaW4oY29pbk5hbWUsIDMpO1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIHBhc3NwaHJhc2U6ICd0ZXN0JyxcbiAgICAgIGVudGVycHJpc2U6IGVudGVycHJpc2VJZCxcbiAgICAgIG9yaWdpbmFsUGFzc2NvZGVFbmNyeXB0aW9uQ29kZTogJzEyMzQ1NicsXG4gICAgICBzYWZlSWQsXG4gICAgfTtcbiAgICBjb25zdCB7IHVzZXJLZXljaGFpbiwgYmFja3VwS2V5Y2hhaW4sIGJpdGdvS2V5Y2hhaW4gfSA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUtleWNoYWlucyhwYXJhbXMpO1xuICAgIGFzc2VydC5vayhyb3VuZDFOb2NrLmlzRG9uZSgpKTtcbiAgICBhc3NlcnQub2socm91bmQyTm9jay5pc0RvbmUoKSk7XG4gICAgYXNzZXJ0Lm9rKHJvdW5kM05vY2suaXNEb25lKCkpO1xuICAgIGFzc2VydC5vayhhZGRLZXlOb2NrLmlzRG9uZSgpKTtcblxuICAgIGFzc2VydC5vayh1c2VyS2V5Y2hhaW4pO1xuICAgIGFzc2VydC5lcXVhbCh1c2VyS2V5Y2hhaW4uc291cmNlLCAndXNlcicpO1xuICAgIGFzc2VydC5vayh1c2VyS2V5Y2hhaW4uY29tbW9uS2V5Y2hhaW4pO1xuICAgIGFzc2VydC5vayhFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscy52YWxpZGF0ZUNvbW1vbktleWNoYWluUHVibGljS2V5KHVzZXJLZXljaGFpbi5jb21tb25LZXljaGFpbikpO1xuICAgIGFzc2VydC5vayh1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICBhc3NlcnQub2soYmFja3VwS2V5Y2hhaW4pO1xuICAgIGFzc2VydC5vayhiYWNrdXBLZXljaGFpbi5lbmNyeXB0ZWRQcnYpO1xuICAgIGFzc2VydC5vayhiaXRnb0tleWNoYWluKTtcblxuICAgIC8vIFRoZSBWUkYgREtHIG11c3QgaGF2ZSBjb21wbGV0ZWQgb24gdGhlIChzaW11bGF0ZWQpIEhTTSBzaWRlIGFzIHdlbGwuXG4gICAgYXNzZXJ0Lm9rKGJpdGdvVnJmU2hhcmUsICdCaXRHbyBWUkYga2V5c2hhcmUgd2FzIG5vdCBwcm9kdWNlZCcpO1xuXG4gICAgYXNzZXJ0Lm9rKHVzZXJLZXljaGFpbi5lbmNyeXB0ZWRQcnYpO1xuICAgIGNvbnN0IGRlY3J5cHRlZFVzZXJQcnYgPSBhd2FpdCBiaXRnby5kZWNyeXB0KHsgaW5wdXQ6IHVzZXJLZXljaGFpbi5lbmNyeXB0ZWRQcnYsIHBhc3N3b3JkOiBwYXJhbXMucGFzc3BocmFzZSB9KTtcbiAgICBjb25zdCB1c2VyRW52ZWxvcGUgPSBkZWNvZGUoQnVmZmVyLmZyb20oZGVjcnlwdGVkVXNlclBydiwgJ2Jhc2U2NCcpKTtcbiAgICBhc3NlcnQuZXF1YWwodXNlckVudmVsb3BlLnZlcnNpb24sIDEpO1xuICAgIGFzc2VydC5vayh1c2VyRW52ZWxvcGUucHJ2S2V5U2hhcmUpO1xuICAgIGFzc2VydC5vayh1c2VyRW52ZWxvcGUudnJmKTtcbiAgICBjb25zdCB1c2VyS2V5U2hhcmUgPSBCdWZmZXIuZnJvbSh1c2VyRW52ZWxvcGUucHJ2S2V5U2hhcmUpO1xuICAgIGFzc2VydC5lcXVhbChEa2xzVHlwZXMuZ2V0Q29tbW9uS2V5Y2hhaW4odXNlcktleVNoYXJlKSwgdXNlcktleWNoYWluLmNvbW1vbktleWNoYWluKTtcbiAgICBjb25zdCB1c2VyVnJmU2hhcmUgPSBkZWNvZGUodXNlckVudmVsb3BlLnZyZik7XG4gICAgYXNzZXJ0LmVxdWFsKHVzZXJWcmZTaGFyZS5wYXJ0eV9pZCwgMCk7XG4gICAgLy8gQWxsIHRocmVlIHBhcnRpZXMnIFZSRiBES0dzIGFncmVlIG9uIHRoZSBWUkYgcHVibGljIGtleS5cbiAgICBhc3NlcnQuZXF1YWwoXG4gICAgICBCdWZmZXIuZnJvbSh1c2VyVnJmU2hhcmUucHVibGljX2tleSkudG9TdHJpbmcoJ2hleCcpLFxuICAgICAgQnVmZmVyLmZyb20oYml0Z29WcmZTaGFyZS5wdWJsaWNfa2V5KS50b1N0cmluZygnaGV4JylcbiAgICApO1xuXG4gICAgYXNzZXJ0Lm9rKGJhY2t1cEtleWNoYWluLmVuY3J5cHRlZFBydik7XG4gICAgY29uc3QgZGVjcnlwdGVkQmFja3VwUHJ2ID0gYXdhaXQgYml0Z28uZGVjcnlwdCh7XG4gICAgICBpbnB1dDogYmFja3VwS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2LFxuICAgICAgcGFzc3dvcmQ6IHBhcmFtcy5wYXNzcGhyYXNlLFxuICAgIH0pO1xuICAgIGNvbnN0IGJhY2t1cEVudmVsb3BlID0gZGVjb2RlKEJ1ZmZlci5mcm9tKGRlY3J5cHRlZEJhY2t1cFBydiwgJ2Jhc2U2NCcpKTtcbiAgICBhc3NlcnQuZXF1YWwoYmFja3VwRW52ZWxvcGUudmVyc2lvbiwgMSk7XG4gICAgY29uc3QgYmFja3VwVnJmU2hhcmUgPSBkZWNvZGUoYmFja3VwRW52ZWxvcGUudnJmKTtcbiAgICBhc3NlcnQuZXF1YWwoYmFja3VwVnJmU2hhcmUucGFydHlfaWQsIDEpO1xuICAgIGFzc2VydC5lcXVhbChcbiAgICAgIEJ1ZmZlci5mcm9tKGJhY2t1cFZyZlNoYXJlLnB1YmxpY19rZXkpLnRvU3RyaW5nKCdoZXgnKSxcbiAgICAgIEJ1ZmZlci5mcm9tKGJpdGdvVnJmU2hhcmUucHVibGljX2tleSkudG9TdHJpbmcoJ2hleCcpXG4gICAgKTtcbiAgICBhc3NlcnQubm90RGVlcFN0cmljdEVxdWFsKHVzZXJWcmZTaGFyZS5kX2ksIGJhY2t1cFZyZlNoYXJlLmRfaSk7XG5cbiAgICAvLyByZWR1Y2VkRW5jcnlwdGVkUHJ2IHRha2VzIHRoZSBzYW1lIGVudmVsb3BlIGFuZCBjYXJyaWVzIFZSRiBtYXRlcmlhbC5cbiAgICBjb25zdCByZWR1Y2VkRW5jcnlwdGVkUHJ2ID0gKHVzZXJLZXljaGFpbiBhcyBLZXljaGFpbiAmIHsgcmVkdWNlZEVuY3J5cHRlZFBydj86IHN0cmluZyB9KS5yZWR1Y2VkRW5jcnlwdGVkUHJ2O1xuICAgIGFzc2VydC5vayhyZWR1Y2VkRW5jcnlwdGVkUHJ2KTtcbiAgICBjb25zdCByZWR1Y2VkRGVjcnlwdGVkID0gYXdhaXQgYml0Z28uZGVjcnlwdCh7IGlucHV0OiByZWR1Y2VkRW5jcnlwdGVkUHJ2LCBwYXNzd29yZDogcGFyYW1zLnBhc3NwaHJhc2UgfSk7XG4gICAgY29uc3QgcmVkdWNlZEVudmVsb3BlID0gZGVjb2RlKEJ1ZmZlci5mcm9tKHJlZHVjZWREZWNyeXB0ZWQsICdiYXNlNjQnKSk7XG4gICAgYXNzZXJ0LmVxdWFsKHJlZHVjZWRFbnZlbG9wZS52ZXJzaW9uLCAxKTtcbiAgICBjb25zdCByZWR1Y2VkS2V5U2hhcmUgPSBEa2xzVHlwZXMuZ2V0RGVjb2RlZFJlZHVjZWRLZXlTaGFyZShCdWZmZXIuZnJvbShyZWR1Y2VkRW52ZWxvcGUucHJ2S2V5U2hhcmUpKTtcbiAgICBhc3NlcnQub2socmVkdWNlZEtleVNoYXJlLnBydi5sZW5ndGggPiAwKTtcbiAgICBhc3NlcnQub2soQnVmZmVyLmZyb20ocmVkdWNlZEVudmVsb3BlLnZyZikubGVuZ3RoID4gMCk7XG5cbiAgICAvLyBjb21tb24ga2V5Y2hhaW5zIGFncmVlIGFjcm9zcyBwYXJ0aWVzXG4gICAgYXNzZXJ0LmVxdWFsKHVzZXJLZXljaGFpbi5jb21tb25LZXljaGFpbiwgYmFja3VwS2V5Y2hhaW4uY29tbW9uS2V5Y2hhaW4pO1xuICAgIGFzc2VydC5lcXVhbCh1c2VyS2V5Y2hhaW4uY29tbW9uS2V5Y2hhaW4sIGJpdGdvS2V5Y2hhaW4uY29tbW9uS2V5Y2hhaW4pO1xuICB9KTtcblxuICBhc3luYyBmdW5jdGlvbiBub2NrR2V0Qml0Z29QdWJsaWNLZXlCYXNlZE9uRmVhdHVyZUZsYWdzKFxuICAgIGNvaW46IHN0cmluZyxcbiAgICBlbnRlcnByaXNlSWQ6IHN0cmluZyxcbiAgICBiaXRnb0dwZ0tleVBhaXI6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPlxuICApOiBQcm9taXNlPEJpdGdvR1BHUHVibGljS2V5PiB7XG4gICAgY29uc3QgYml0Z29HUEdQdWJsaWNLZXlSZXNwb25zZTogQml0Z29HUEdQdWJsaWNLZXkgPSB7XG4gICAgICBuYW1lOiAnaXJyZWxldmFudCcsXG4gICAgICBwdWJsaWNLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBtcGN2MlB1YmxpY0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgIGVudGVycHJpc2VJZCxcbiAgICB9O1xuICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi8ke2NvaW59L3Rzcy9wdWJrZXlgKS5xdWVyeSh7IGVudGVycHJpc2VJZCB9KS5yZXBseSgyMDAsIGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2UpO1xuXG4gICAgcmV0dXJuIGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2U7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrS2V5R2VuUm91bmQxKGJpdGdvU2Vzc2lvbjogRGtsc0RrZy5Ea2csIGJpdGdvVnJmU2Vzc2lvbjogRGtsc1ZyZi5WcmZEa2csIHRpbWVzID0gMSkge1xuICAgIHJldHVybiBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvbXBjL2dlbmVyYXRla2V5YCwgKGJvZHkpID0+IGJvZHkucm91bmQgPT09ICdNUEN2Mi1SMScpXG4gICAgICAudGltZXModGltZXMpXG4gICAgICAucmVwbHkoXG4gICAgICAgIDIwMCxcbiAgICAgICAgYXN5bmMgKFxuICAgICAgICAgIHVyaSxcbiAgICAgICAgICB7IHBheWxvYWQgfTogeyBwYXlsb2FkOiBNUEN2MktleUdlblJvdW5kMVJlcXVlc3QgJiBWcmZLZXlHZW5SZXF1ZXN0RmllbGRzIH1cbiAgICAgICAgKTogUHJvbWlzZTxNUEN2MktleUdlblJvdW5kMVJlc3BvbnNlICYgVnJmS2V5R2VuUmVzcG9uc2VGaWVsZHM+ID0+IHtcbiAgICAgICAgICBjb25zdCB7IHVzZXJHcGdQdWJsaWNLZXksIGJhY2t1cEdwZ1B1YmxpY0tleSwgdXNlck1zZzEsIGJhY2t1cE1zZzEsIHVzZXJWcmZNc2cxLCBiYWNrdXBWcmZNc2cxIH0gPSBwYXlsb2FkO1xuICAgICAgICAgIGFzc2VydC5vayh1c2VyVnJmTXNnMSwgJ3VzZXJWcmZNc2cxIG11c3QgYmUgcHJlc2VudCBvbiBhIHNhZmUga2V5Z2VuIHJvdW5kIDEgcGF5bG9hZCcpO1xuICAgICAgICAgIGFzc2VydC5vayhiYWNrdXBWcmZNc2cxLCAnYmFja3VwVnJmTXNnMSBtdXN0IGJlIHByZXNlbnQgb24gYSBzYWZlIGtleWdlbiByb3VuZCAxIHBheWxvYWQnKTtcbiAgICAgICAgICB1c2VyR3BnUHViS2V5ID0ge1xuICAgICAgICAgICAgcGFydHlJZDogMCxcbiAgICAgICAgICAgIGdwZ0tleTogdXNlckdwZ1B1YmxpY0tleSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGJhY2t1cEdwZ1B1YktleSA9IHtcbiAgICAgICAgICAgIHBhcnR5SWQ6IDEsXG4gICAgICAgICAgICBncGdLZXk6IGJhY2t1cEdwZ1B1YmxpY0tleSxcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgY29uc3QgYml0Z29Ccm9hZGNhc3RNc2cxVW5zaWduZWQgPSBhd2FpdCBiaXRnb1Nlc3Npb24uaW5pdERrZygpO1xuICAgICAgICAgIGNvbnN0IGJpdGdvTXNnczFTaWduZWQgPSBhd2FpdCBEa2xzQ29tbXMuZW5jcnlwdEFuZEF1dGhPdXRnb2luZ01lc3NhZ2VzKFxuICAgICAgICAgICAgeyBicm9hZGNhc3RNZXNzYWdlczogW0RrbHNUeXBlcy5zZXJpYWxpemVCcm9hZGNhc3RNZXNzYWdlKGJpdGdvQnJvYWRjYXN0TXNnMVVuc2lnbmVkKV0sIHAycE1lc3NhZ2VzOiBbXSB9LFxuICAgICAgICAgICAgW10sXG4gICAgICAgICAgICBbYml0Z29HcGdQcnZLZXldXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBiaXRnb01zZzEgPSBiaXRnb01zZ3MxU2lnbmVkLmJyb2FkY2FzdE1lc3NhZ2VzLmZpbmQoKG0pID0+IG0uZnJvbSA9PT0gMik7XG4gICAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvTXNnMSwgJ2JpdGdvTXNnMSBub3QgZm91bmQnKTtcblxuICAgICAgICAgIGNvbnN0IHJvdW5kMUluY29taW5nTXNncyA9IGF3YWl0IERrbHNDb21tcy5kZWNyeXB0QW5kVmVyaWZ5SW5jb21pbmdNZXNzYWdlcyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgICAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW1xuICAgICAgICAgICAgICAgIHsgZnJvbTogMCwgcGF5bG9hZDogdXNlck1zZzEgfSxcbiAgICAgICAgICAgICAgICB7IGZyb206IDEsIHBheWxvYWQ6IGJhY2t1cE1zZzEgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBbdXNlckdwZ1B1YktleSwgYmFja3VwR3BnUHViS2V5XSxcbiAgICAgICAgICAgIFtiaXRnb0dwZ1BydktleV1cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3Qgcm91bmQyTWVzc2FnZXMgPSBEa2xzVHlwZXMuc2VyaWFsaXplTWVzc2FnZXMoXG4gICAgICAgICAgICBiaXRnb1Nlc3Npb24uaGFuZGxlSW5jb21pbmdNZXNzYWdlcyhEa2xzVHlwZXMuZGVzZXJpYWxpemVNZXNzYWdlcyhyb3VuZDFJbmNvbWluZ01zZ3MpKVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCByb3VuZDJTaWduZWRNZXNzYWdlcyA9IGF3YWl0IERrbHNDb21tcy5lbmNyeXB0QW5kQXV0aE91dGdvaW5nTWVzc2FnZXMoXG4gICAgICAgICAgICByb3VuZDJNZXNzYWdlcyxcbiAgICAgICAgICAgIFt1c2VyR3BnUHViS2V5LCBiYWNrdXBHcGdQdWJLZXldLFxuICAgICAgICAgICAgW2JpdGdvR3BnUHJ2S2V5XVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCBiaXRnb1RvVXNlck1zZzIgPSByb3VuZDJTaWduZWRNZXNzYWdlcy5wMnBNZXNzYWdlcy5maW5kKChtKSA9PiBtLnRvID09PSAwKTtcbiAgICAgICAgICBjb25zdCBiaXRnb1RvQmFja3VwTXNnMiA9IHJvdW5kMlNpZ25lZE1lc3NhZ2VzLnAycE1lc3NhZ2VzLmZpbmQoKG0pID0+IG0udG8gPT09IDEpO1xuICAgICAgICAgIGFzc2VydC5vayhiaXRnb1RvVXNlck1zZzIsICdiaXRnb1RvVXNlck1zZzIgbm90IGZvdW5kJyk7XG4gICAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvVG9CYWNrdXBNc2cyLCAnYml0Z29Ub0JhY2t1cE1zZzIgbm90IGZvdW5kJyk7XG4gICAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvVG9Vc2VyTXNnMi5jb21taXRtZW50LCAnYml0Z29Ub1VzZXJNc2cyLmNvbW1pdG1lbnQgbm90IGZvdW5kJyk7XG5cbiAgICAgICAgICBzdG9yZWRCaXRnb0NvbW1pdG1lbnQyID0gYml0Z29Ub1VzZXJNc2cyPy5jb21taXRtZW50O1xuXG4gICAgICAgICAgLy8gVlJGIERLRzogQml0R28gY29tbWl0cywgdGhlbiBjb25zdW1lcyB1c2VyIGFuZCBiYWNrdXAgY29tbWl0bWVudHMuXG4gICAgICAgICAgY29uc3QgYml0Z29WcmZNc2cxVW5zaWduZWQgPSBhd2FpdCBiaXRnb1ZyZlNlc3Npb24uaW5pdERrZygpO1xuICAgICAgICAgIGNvbnN0IHVzZXJWcmZDb21taXRtZW50cyA9IGRlc2VyaWFsaXplVnJmTWVzc2FnZXModXNlclZyZk1zZzEsIDIpO1xuICAgICAgICAgIGNvbnN0IGJhY2t1cFZyZkNvbW1pdG1lbnRzID0gZGVzZXJpYWxpemVWcmZNZXNzYWdlcyhiYWNrdXBWcmZNc2cxLCAyKTtcbiAgICAgICAgICBhc3NlcnQuZXF1YWwodXNlclZyZkNvbW1pdG1lbnRzLmJyb2FkY2FzdE1lc3NhZ2VzLmxlbmd0aCwgMSk7XG4gICAgICAgICAgYXNzZXJ0LmVxdWFsKHVzZXJWcmZDb21taXRtZW50cy5icm9hZGNhc3RNZXNzYWdlc1swXS5mcm9tLCAwKTtcbiAgICAgICAgICBhc3NlcnQuZXF1YWwoYmFja3VwVnJmQ29tbWl0bWVudHMuYnJvYWRjYXN0TWVzc2FnZXMubGVuZ3RoLCAxKTtcbiAgICAgICAgICBhc3NlcnQuZXF1YWwoYmFja3VwVnJmQ29tbWl0bWVudHMuYnJvYWRjYXN0TWVzc2FnZXNbMF0uZnJvbSwgMSk7XG4gICAgICAgICAgc3RvcmVkQml0Z29WcmZPcGVuaW5ncyA9IGF3YWl0IGJpdGdvVnJmU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKHtcbiAgICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbLi4udXNlclZyZkNvbW1pdG1lbnRzLmJyb2FkY2FzdE1lc3NhZ2VzLCAuLi5iYWNrdXBWcmZDb21taXRtZW50cy5icm9hZGNhc3RNZXNzYWdlc10sXG4gICAgICAgICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgLy8gQml0R28ncyBvcGVuaW5ncyBhcmUgYWRkcmVzc2VkIHRvIGVhY2ggcGFydHksIGl0c2VsZiBpbmNsdWRlZC5cbiAgICAgICAgICBhc3NlcnQuZXF1YWwoc3RvcmVkQml0Z29WcmZPcGVuaW5ncy5wMnBNZXNzYWdlcy5sZW5ndGgsIDMpO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNlc3Npb25JZDogJ3Rlc3RpZCcgYXMgTm9uRW1wdHlTdHJpbmcsXG4gICAgICAgICAgICBiaXRnb01zZzE6IHsgZnJvbTogMiwgLi4uYml0Z29Nc2cxLnBheWxvYWQgfSxcbiAgICAgICAgICAgIGJpdGdvVG9CYWNrdXBNc2cyOiB7XG4gICAgICAgICAgICAgIGZyb206IDIsXG4gICAgICAgICAgICAgIHRvOiAxLFxuICAgICAgICAgICAgICBlbmNyeXB0ZWRNZXNzYWdlOiBiaXRnb1RvQmFja3VwTXNnMi5wYXlsb2FkLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgICAgICAgIHNpZ25hdHVyZTogYml0Z29Ub0JhY2t1cE1zZzIucGF5bG9hZC5zaWduYXR1cmUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYml0Z29Ub1VzZXJNc2cyOiB7XG4gICAgICAgICAgICAgIGZyb206IDIsXG4gICAgICAgICAgICAgIHRvOiAwLFxuICAgICAgICAgICAgICBlbmNyeXB0ZWRNZXNzYWdlOiBiaXRnb1RvVXNlck1zZzIucGF5bG9hZC5lbmNyeXB0ZWRNZXNzYWdlLFxuICAgICAgICAgICAgICBzaWduYXR1cmU6IGJpdGdvVG9Vc2VyTXNnMi5wYXlsb2FkLnNpZ25hdHVyZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB3YWxsZXRHcGdQdWJLZXlTaWdzOiAnc29tZXRoaW5nJyBhcyBOb25FbXB0eVN0cmluZyxcbiAgICAgICAgICAgIGJpdGdvVnJmTXNnMTogc2VyaWFsaXplVnJmTWVzc2FnZXMoYml0Z29WcmZNc2cxVW5zaWduZWQpLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrS2V5R2VuUm91bmQyKGJpdGdvU2Vzc2lvbjogRGtsc0RrZy5Ea2csIGJpdGdvVnJmU2Vzc2lvbjogRGtsc1ZyZi5WcmZEa2csIHRpbWVzID0gMSkge1xuICAgIHJldHVybiBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvbXBjL2dlbmVyYXRla2V5YCwgKGJvZHkpID0+IGJvZHkucm91bmQgPT09ICdNUEN2Mi1SMicpXG4gICAgICAudGltZXModGltZXMpXG4gICAgICAucmVwbHkoXG4gICAgICAgIDIwMCxcbiAgICAgICAgYXN5bmMgKFxuICAgICAgICAgIHVyaSxcbiAgICAgICAgICB7IHBheWxvYWQgfTogeyBwYXlsb2FkOiBNUEN2MktleUdlblJvdW5kMlJlcXVlc3QgJiBWcmZLZXlHZW5SZXF1ZXN0RmllbGRzIH1cbiAgICAgICAgKTogUHJvbWlzZTxNUEN2MktleUdlblJvdW5kMlJlc3BvbnNlICYgVnJmS2V5R2VuUmVzcG9uc2VGaWVsZHM+ID0+IHtcbiAgICAgICAgICBjb25zdCB7IHNlc3Npb25JZCwgdXNlck1zZzIsIGJhY2t1cE1zZzIsIHVzZXJDb21taXRtZW50MiwgYmFja3VwQ29tbWl0bWVudDIsIHVzZXJWcmZNc2cyLCBiYWNrdXBWcmZNc2cyIH0gPVxuICAgICAgICAgICAgcGF5bG9hZDtcbiAgICAgICAgICBhc3NlcnQub2sodXNlclZyZk1zZzIsICd1c2VyVnJmTXNnMiBtdXN0IGJlIHByZXNlbnQgb24gYSBzYWZlIGtleWdlbiByb3VuZCAyIHBheWxvYWQnKTtcbiAgICAgICAgICBhc3NlcnQub2soYmFja3VwVnJmTXNnMiwgJ2JhY2t1cFZyZk1zZzIgbXVzdCBiZSBwcmVzZW50IG9uIGEgc2FmZSBrZXlnZW4gcm91bmQgMiBwYXlsb2FkJyk7XG4gICAgICAgICAgc3RvcmVkVXNlckNvbW1pdG1lbnQyID0gdXNlckNvbW1pdG1lbnQyO1xuICAgICAgICAgIHN0b3JlZEJhY2t1cENvbW1pdG1lbnQyID0gYmFja3VwQ29tbWl0bWVudDI7XG4gICAgICAgICAgY29uc3Qgcm91bmQySW5jb21pbmdNc2dzID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBwMnBNZXNzYWdlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGZyb206IHVzZXJNc2cyLmZyb20sXG4gICAgICAgICAgICAgICAgICB0bzogdXNlck1zZzIudG8sXG4gICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IHNpZ25hdHVyZTogdXNlck1zZzIuc2lnbmF0dXJlLCBlbmNyeXB0ZWRNZXNzYWdlOiB1c2VyTXNnMi5lbmNyeXB0ZWRNZXNzYWdlIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBmcm9tOiBiYWNrdXBNc2cyLmZyb20sXG4gICAgICAgICAgICAgICAgICB0bzogYmFja3VwTXNnMi50byxcbiAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgc2lnbmF0dXJlOiBiYWNrdXBNc2cyLnNpZ25hdHVyZSwgZW5jcnlwdGVkTWVzc2FnZTogYmFja3VwTXNnMi5lbmNyeXB0ZWRNZXNzYWdlIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFt1c2VyR3BnUHViS2V5LCBiYWNrdXBHcGdQdWJLZXldLFxuICAgICAgICAgICAgW2JpdGdvR3BnUHJ2S2V5XVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCByb3VuZDNNZXNzYWdlcyA9IERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyhcbiAgICAgICAgICAgIGJpdGdvU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKERrbHNUeXBlcy5kZXNlcmlhbGl6ZU1lc3NhZ2VzKHJvdW5kMkluY29taW5nTXNncykpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHJvdW5kM1NpZ25lZE1lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICAgIHJvdW5kM01lc3NhZ2VzLFxuICAgICAgICAgICAgW3VzZXJHcGdQdWJLZXksIGJhY2t1cEdwZ1B1YktleV0sXG4gICAgICAgICAgICBbYml0Z29HcGdQcnZLZXldXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IGJpdGdvVG9Vc2VyTXNnMyA9IHJvdW5kM1NpZ25lZE1lc3NhZ2VzLnAycE1lc3NhZ2VzLmZpbmQoKG0pID0+IG0udG8gPT09IDApO1xuICAgICAgICAgIGNvbnN0IGJpdGdvVG9CYWNrdXBNc2czID0gcm91bmQzU2lnbmVkTWVzc2FnZXMucDJwTWVzc2FnZXMuZmluZCgobSkgPT4gbS50byA9PT0gMSk7XG4gICAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvVG9Vc2VyTXNnMywgJ2JpdGdvVG9Vc2VyTXNnMyBub3QgZm91bmQnKTtcbiAgICAgICAgICBhc3NlcnQub2soYml0Z29Ub0JhY2t1cE1zZzMsICdiaXRnb1RvQmFja3VwTXNnMyBub3QgZm91bmQnKTtcblxuICAgICAgICAgIC8vIFZSRiBES0c6IEJpdEdvIGNvbnN1bWVzIHRoZSBvcGVuaW5ncyBhZGRyZXNzZWQgdG8gaXQgKGl0cyBvd24gaW5jbHVkZWQpIGFuZCBmaW5hbGl6ZXMuXG4gICAgICAgICAgY29uc3QgdXNlck9wZW5pbmdzID0gZGVzZXJpYWxpemVWcmZNZXNzYWdlcyh1c2VyVnJmTXNnMiwgMikucDJwTWVzc2FnZXM7XG4gICAgICAgICAgY29uc3QgYmFja3VwT3BlbmluZ3MgPSBkZXNlcmlhbGl6ZVZyZk1lc3NhZ2VzKGJhY2t1cFZyZk1zZzIsIDIpLnAycE1lc3NhZ2VzO1xuICAgICAgICAgIGFzc2VydC5vayh1c2VyT3BlbmluZ3Muc29tZSgobSkgPT4gbS5mcm9tID09PSAwICYmIG0udG8gPT09IDIpKTtcbiAgICAgICAgICBhc3NlcnQub2soYmFja3VwT3BlbmluZ3Muc29tZSgobSkgPT4gbS5mcm9tID09PSAxICYmIG0udG8gPT09IDIpKTtcbiAgICAgICAgICBhc3NlcnQub2soc3RvcmVkQml0Z29WcmZPcGVuaW5ncywgJ0JpdEdvIFZSRiBvcGVuaW5ncyBmcm9tIHJvdW5kIDEgbm90IGZvdW5kJyk7XG4gICAgICAgICAgYXdhaXQgYml0Z29WcmZTZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoe1xuICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgICAgICAgcDJwTWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAgLi4udXNlck9wZW5pbmdzLFxuICAgICAgICAgICAgICAuLi5iYWNrdXBPcGVuaW5ncyxcbiAgICAgICAgICAgICAgLi4uc3RvcmVkQml0Z29WcmZPcGVuaW5ncy5wMnBNZXNzYWdlcy5maWx0ZXIoKG0pID0+IG0udG8gPT09IDIpLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBjb25zdCBzaGFyZSA9IGRlY29kZShiaXRnb1ZyZlNlc3Npb24uZ2V0S2V5U2hhcmUoKSk7XG4gICAgICAgICAgYXNzZXJ0LmVxdWFsKHNoYXJlLnBhcnR5X2lkLCAyKTtcbiAgICAgICAgICBiaXRnb1ZyZlNoYXJlID0gc2hhcmU7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc2Vzc2lvbklkLFxuICAgICAgICAgICAgYml0Z29Db21taXRtZW50Mjogc3RvcmVkQml0Z29Db21taXRtZW50MiBhcyBOb25FbXB0eVN0cmluZyxcbiAgICAgICAgICAgIGJpdGdvVG9Vc2VyTXNnMzoge1xuICAgICAgICAgICAgICBmcm9tOiAyLFxuICAgICAgICAgICAgICB0bzogMCxcbiAgICAgICAgICAgICAgZW5jcnlwdGVkTWVzc2FnZTogYml0Z29Ub1VzZXJNc2czLnBheWxvYWQuZW5jcnlwdGVkTWVzc2FnZSxcbiAgICAgICAgICAgICAgc2lnbmF0dXJlOiBiaXRnb1RvVXNlck1zZzMucGF5bG9hZC5zaWduYXR1cmUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYml0Z29Ub0JhY2t1cE1zZzM6IHtcbiAgICAgICAgICAgICAgZnJvbTogMixcbiAgICAgICAgICAgICAgdG86IDEsXG4gICAgICAgICAgICAgIGVuY3J5cHRlZE1lc3NhZ2U6IGJpdGdvVG9CYWNrdXBNc2czLnBheWxvYWQuZW5jcnlwdGVkTWVzc2FnZSxcbiAgICAgICAgICAgICAgc2lnbmF0dXJlOiBiaXRnb1RvQmFja3VwTXNnMy5wYXlsb2FkLnNpZ25hdHVyZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAvLyBCaXRHbydzIGZ1bGwgb3BlbmluZyBiYXRjaCwgc28gdXNlciAoMCkgYW5kIGJhY2t1cCAoMSkgY2FuIGVhY2ggcGljayB0aGVpcnMuXG4gICAgICAgICAgICBiaXRnb1ZyZk1zZzI6IHNlcmlhbGl6ZVZyZk1lc3NhZ2VzKHN0b3JlZEJpdGdvVnJmT3BlbmluZ3MpLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrS2V5R2VuUm91bmQzKGJpdGdvU2Vzc2lvbjogRGtsc0RrZy5Ea2csIGJpdGdvVnJmU2Vzc2lvbjogRGtsc1ZyZi5WcmZEa2csIHRpbWVzID0gMSkge1xuICAgIHJldHVybiBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvbXBjL2dlbmVyYXRla2V5YCwgKGJvZHkpID0+IGJvZHkucm91bmQgPT09ICdNUEN2Mi1SMycpXG4gICAgICAudGltZXModGltZXMpXG4gICAgICAucmVwbHkoXG4gICAgICAgIDIwMCxcbiAgICAgICAgYXN5bmMgKHVyaSwgeyBwYXlsb2FkIH06IHsgcGF5bG9hZDogTVBDdjJLZXlHZW5Sb3VuZDNSZXF1ZXN0IH0pOiBQcm9taXNlPE1QQ3YyS2V5R2VuUm91bmQzUmVzcG9uc2U+ID0+IHtcbiAgICAgICAgICBjb25zdCB7IHNlc3Npb25JZCwgdXNlck1zZzMsIHVzZXJNc2c0LCBiYWNrdXBNc2czLCBiYWNrdXBNc2c0IH0gPSBwYXlsb2FkO1xuICAgICAgICAgIC8vIFRoZSBWUkYgREtHIGhhcyBubyBtZXNzYWdlcyBvbiByb3VuZCAzOyBpdCBhbHJlYWR5IGZpbmFsaXplZCBhZnRlciByb3VuZCAyLlxuICAgICAgICAgIGFzc2VydC5vayhiaXRnb1ZyZlNoYXJlLCAnQml0R28gVlJGIGtleXNoYXJlIHNob3VsZCBiZSBjb21wbGV0ZSBiZWZvcmUgcm91bmQgMycpO1xuXG4gICAgICAgICAgY29uc3Qgcm91bmQzSW5jb21pbmdNc2dzID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBwMnBNZXNzYWdlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGZyb206IHVzZXJNc2czLmZyb20sXG4gICAgICAgICAgICAgICAgICB0bzogdXNlck1zZzMudG8sXG4gICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IHNpZ25hdHVyZTogdXNlck1zZzMuc2lnbmF0dXJlLCBlbmNyeXB0ZWRNZXNzYWdlOiB1c2VyTXNnMy5lbmNyeXB0ZWRNZXNzYWdlIH0sXG4gICAgICAgICAgICAgICAgICBjb21taXRtZW50OiBzdG9yZWRVc2VyQ29tbWl0bWVudDIsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBmcm9tOiBiYWNrdXBNc2czLmZyb20sXG4gICAgICAgICAgICAgICAgICB0bzogYmFja3VwTXNnMy50byxcbiAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgc2lnbmF0dXJlOiBiYWNrdXBNc2czLnNpZ25hdHVyZSwgZW5jcnlwdGVkTWVzc2FnZTogYmFja3VwTXNnMy5lbmNyeXB0ZWRNZXNzYWdlIH0sXG4gICAgICAgICAgICAgICAgICBjb21taXRtZW50OiBzdG9yZWRCYWNrdXBDb21taXRtZW50MixcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW3VzZXJHcGdQdWJLZXksIGJhY2t1cEdwZ1B1YktleV0sXG4gICAgICAgICAgICBbYml0Z29HcGdQcnZLZXldXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHJvdW5kNE1lc3NhZ2VzID0gRGtsc1R5cGVzLnNlcmlhbGl6ZU1lc3NhZ2VzKFxuICAgICAgICAgICAgYml0Z29TZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoRGtsc1R5cGVzLmRlc2VyaWFsaXplTWVzc2FnZXMocm91bmQzSW5jb21pbmdNc2dzKSlcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvbnN0IHJvdW5kNFNpZ25lZE1lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICAgIHJvdW5kNE1lc3NhZ2VzLFxuICAgICAgICAgICAgW10sXG4gICAgICAgICAgICBbYml0Z29HcGdQcnZLZXldXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCBiaXRnb01zZzQgPSByb3VuZDRTaWduZWRNZXNzYWdlcy5icm9hZGNhc3RNZXNzYWdlcy5maW5kKChtKSA9PiBtLmZyb20gPT09IDIpO1xuICAgICAgICAgIGFzc2VydC5vayhiaXRnb01zZzQsICdiaXRnb01zZzQgbm90IGZvdW5kJyk7XG5cbiAgICAgICAgICBjb25zdCByb3VuZDRJbmNvbWluZ01zZ3MgPSBhd2FpdCBEa2xzQ29tbXMuZGVjcnlwdEFuZFZlcmlmeUluY29taW5nTWVzc2FnZXMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHAycE1lc3NhZ2VzOiBbXSxcbiAgICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBmcm9tOiB1c2VyTXNnNC5mcm9tLFxuICAgICAgICAgICAgICAgICAgcGF5bG9hZDogeyBzaWduYXR1cmU6IHVzZXJNc2c0LnNpZ25hdHVyZSwgbWVzc2FnZTogdXNlck1zZzQubWVzc2FnZSB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZnJvbTogYmFja3VwTXNnNC5mcm9tLFxuXG4gICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IHNpZ25hdHVyZTogYmFja3VwTXNnNC5zaWduYXR1cmUsIG1lc3NhZ2U6IGJhY2t1cE1zZzQubWVzc2FnZSB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW3VzZXJHcGdQdWJLZXksIGJhY2t1cEdwZ1B1YktleV0sXG4gICAgICAgICAgICBbXVxuICAgICAgICAgICk7XG4gICAgICAgICAgYml0Z29TZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoRGtsc1R5cGVzLmRlc2VyaWFsaXplTWVzc2FnZXMocm91bmQ0SW5jb21pbmdNc2dzKSk7XG4gICAgICAgICAgY29uc3Qga2V5U2hhcmUgPSBiaXRnb1Nlc3Npb24uZ2V0S2V5U2hhcmUoKTtcbiAgICAgICAgICBjb25zdCBjb21tb25LZXljaGFpbiA9IERrbHNUeXBlcy5nZXRDb21tb25LZXljaGFpbihrZXlTaGFyZSk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc2Vzc2lvbklkLFxuICAgICAgICAgICAgY29tbW9uS2V5Y2hhaW46IGNvbW1vbktleWNoYWluIGFzIE5vbkVtcHR5U3RyaW5nLFxuICAgICAgICAgICAgYml0Z29Nc2c0OiB7IGZyb206IDIsIC4uLmJpdGdvTXNnNC5wYXlsb2FkIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIG5vY2tBZGRLZXlDaGFpbihjb2luOiBzdHJpbmcsIHRpbWVzID0gMSkge1xuICAgIHJldHVybiBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvJHtjb2lufS9rZXlgLCAoYm9keSkgPT4gYm9keS5rZXlUeXBlID09PSAndHNzJyAmJiBib2R5LmlzTVBDdjIgJiYgYm9keS5zYWZlSWQgPT09IHNhZmVJZClcbiAgICAgIC50aW1lcyh0aW1lcylcbiAgICAgIC5yZXBseSgyMDAsIGFzeW5jICh1cmksIHJlcXVlc3RCb2R5OiBBZGRLZXljaGFpbk9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3Qga2V5ID0ge1xuICAgICAgICAgIGlkOiByZXF1ZXN0Qm9keS5zb3VyY2UsXG4gICAgICAgICAgc291cmNlOiByZXF1ZXN0Qm9keS5zb3VyY2UsXG4gICAgICAgICAgdHlwZTogcmVxdWVzdEJvZHkua2V5VHlwZSxcbiAgICAgICAgICBjb21tb25LZXljaGFpbjogcmVxdWVzdEJvZHkuY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgZW5jcnlwdGVkUHJ2OiByZXF1ZXN0Qm9keS5lbmNyeXB0ZWRQcnYsXG4gICAgICAgIH07XG4gICAgICAgIC8vIG5vY2sgZ2V0c1xuICAgICAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKS5nZXQoYC9hcGkvdjIvJHtjb2lufS9rZXkvJHtyZXF1ZXN0Qm9keS5zb3VyY2V9YCkucmVwbHkoMjAwLCBrZXkpO1xuICAgICAgICByZXR1cm4ga2V5O1xuICAgICAgfSk7XG4gIH1cbn0pO1xuIl19