UNPKG

bitgo

Version:
856 lines • 166 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const nock = require("nock");
const openpgp = require("openpgp");
const crypto = require("crypto");
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 public_types_1 = require("@bitgo/public-types");
const src_1 = require("../../../../../../src");
const v1Fixtures = require("./fixtures/mpcv1KeyShares");
describe('TSS Ecdsa MPCv2 Utils:', async function () {
    const coinName = 'hteth';
    const walletId = '5b34252f1bf349930e34020a00000000';
    const enterpriseId = '6449153a6f6bc20006d66771cdbe15d3';
    let storedUserCommitment2;
    let storedBackupCommitment2;
    let storedBitgoCommitment2;
    let bgUrl;
    let tssUtils;
    let wallet;
    let bitgo;
    let baseCoin;
    let bitGoGgpKey;
    let constants;
    let bitgoGpgPrvKey;
    let userGpgPubKey;
    let backupGpgPubKey;
    let bitgoGpgPubKey;
    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,
            },
        };
        bitgoGpgPubKey = {
            partyId: 2,
            gpgKey: 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: walletId,
            enterprise: enterpriseId,
            coin: coinName,
            coinSpecific: {},
            multisigType: 'tss',
        };
        wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData);
        tssUtils = new sdk_core_1.ECDSAUtils.EcdsaMPCv2Utils(bitgo, baseCoin, wallet);
    });
    after(function () {
        nock.cleanAll();
    });
    describe('Retrofit MPCv1 to MPCv2 keys', async function () {
        it('should generate TSS MPCv2 keys from MPCv1 keys and sign a message', async function () {
            const retrofitData = tssUtils.getMpcV2RetrofitDataFromMpcV1Keys({
                mpcv1UserKeyShare: JSON.stringify(v1Fixtures.mockUserSigningMaterial),
                mpcv1BackupKeyShare: JSON.stringify(v1Fixtures.mockBackupSigningMaterial),
            });
            const bitgoRetrofitData = {
                xiList: retrofitData.mpcv2UserKeyShare.xiList,
                xShare: v1Fixtures.mockBitGoShareSigningMaterial.xShare,
            };
            const [user, backup, bitgo] = await sdk_lib_mpc_1.DklsUtils.generateDKGKeyShares(retrofitData.mpcv2UserKeyShare, retrofitData.mpcv2BackupKeyShare, bitgoRetrofitData);
            assert.ok(bitgo.getKeyShare());
            const messageToSign = crypto.createHash('sha256').update(Buffer.from('ffff', 'hex')).digest();
            const derivationPath = 'm/999/988/0/0';
            const signature = await sdk_lib_mpc_1.DklsUtils.executeTillRound(5, new sdk_lib_mpc_1.DklsDsg.Dsg(user.getKeyShare(), 0, derivationPath, messageToSign), new sdk_lib_mpc_1.DklsDsg.Dsg(backup.getKeyShare(), 1, derivationPath, messageToSign));
            const convertedSignature = sdk_lib_mpc_1.DklsUtils.verifyAndConvertDklsSignature(Buffer.from('ffff', 'hex'), signature, v1Fixtures.mockBitGoShareSigningMaterial.xShare.y + v1Fixtures.mockBitGoShareSigningMaterial.xShare.chaincode, derivationPath);
            assert.ok(convertedSignature);
            convertedSignature.split(':').length.should.equal(4);
        });
    });
    describe('TSS key chains', async function () {
        it('should generate TSS MPCv2 keys', async function () {
            const bitgoSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, 2);
            const round1Nock = await nockKeyGenRound1(bitgoSession, 1);
            const round2Nock = await nockKeyGenRound2(bitgoSession, 1);
            const round3Nock = await nockKeyGenRound3(bitgoSession, 1);
            const addKeyNock = await nockAddKeyChain(coinName, 3);
            const params = {
                passphrase: 'test',
                enterprise: enterpriseId,
                originalPasscodeEncryptionCode: '123456',
            };
            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(bitgo.decrypt({ input: userKeychain.encryptedPrv, password: params.passphrase }));
            assert.ok(backupKeychain);
            assert.equal(backupKeychain.source, 'backup');
            assert.ok(backupKeychain.commonKeychain);
            assert.ok(sdk_core_1.ECDSAUtils.EcdsaMPCv2Utils.validateCommonKeychainPublicKey(backupKeychain.commonKeychain));
            assert.ok(backupKeychain.encryptedPrv);
            assert.ok(bitgo.decrypt({ input: backupKeychain.encryptedPrv, password: params.passphrase }));
            assert.ok(bitgoKeychain);
            assert.equal(bitgoKeychain.source, 'bitgo');
        });
        it('should send webauthnInfo (with enterpriseId) on the user keychain when webauthnInfo is provided', async function () {
            const bitgoSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, 2);
            const round1Nock = await nockKeyGenRound1(bitgoSession, 1);
            const round2Nock = await nockKeyGenRound2(bitgoSession, 1);
            const round3Nock = await nockKeyGenRound3(bitgoSession, 1);
            // Capture each keychain POST body by source so we can assert what the user key sends.
            const capturedBodies = {};
            const addKeyNock = nock('https://bitgo.fakeurl')
                .post(`/api/v2/${coinName}/key`, (body) => body.keyType === 'tss' && body.isMPCv2)
                .times(3)
                .reply(200, async (uri, requestBody) => {
                capturedBodies[requestBody.source] = requestBody;
                const key = {
                    id: requestBody.source,
                    source: requestBody.source,
                    type: requestBody.keyType,
                    commonKeychain: requestBody.commonKeychain,
                    encryptedPrv: requestBody.encryptedPrv,
                };
                nock('https://bitgo.fakeurl').get(`/api/v2/${coinName}/key/${requestBody.source}`).reply(200, key);
                return key;
            });
            const webauthnInfo = {
                otpDeviceId: 'device-123',
                prfSalt: 'salt-abc',
                passphrase: 'prf-derived-passphrase',
            };
            const params = {
                passphrase: 'test',
                enterprise: enterpriseId,
                originalPasscodeEncryptionCode: '123456',
                webauthnInfo,
            };
            await tssUtils.createKeychains(params);
            assert.ok(round1Nock.isDone());
            assert.ok(round2Nock.isDone());
            assert.ok(round3Nock.isDone());
            assert.ok(addKeyNock.isDone());
            // User keychain must carry webauthnInfo (the field the backend POST /key consumes),
            // including enterpriseId, and must NOT use the deprecated webauthnDevices array.
            const userBody = capturedBodies['user'];
            assert.ok(userBody, 'user keychain should have been created');
            assert.ok(userBody.webauthnInfo, 'user keychain body should include webauthnInfo');
            assert.equal(userBody.webauthnInfo.otpDeviceId, webauthnInfo.otpDeviceId);
            assert.equal(userBody.webauthnInfo.prfSalt, webauthnInfo.prfSalt);
            assert.equal(userBody.webauthnInfo.enterpriseId, enterpriseId);
            assert.ok(userBody.webauthnInfo.encryptedPrv, 'encryptedPrv should be set');
            // encryptedPrv is the user key share encrypted with the PRF-derived passphrase.
            assert.ok(bitgo.decrypt({ input: userBody.webauthnInfo.encryptedPrv, password: webauthnInfo.passphrase }));
            assert.strictEqual(userBody.webauthnDevices, undefined, 'deprecated webauthnDevices should not be sent');
            // Backup keychain must never carry passkey material.
            const backupBody = capturedBodies['backup'];
            assert.ok(backupBody, 'backup keychain should have been created');
            assert.strictEqual(backupBody.webauthnInfo, undefined);
            assert.strictEqual(backupBody.webauthnDevices, undefined);
        });
        it('should generate TSS MPCv2 keys with v2 encryption envelopes', async function () {
            const bitgoSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, 2);
            const round1Nock = await nockKeyGenRound1(bitgoSession, 1);
            const round2Nock = await nockKeyGenRound2(bitgoSession, 1);
            const round3Nock = await nockKeyGenRound3(bitgoSession, 1);
            const addKeyNock = await nockAddKeyChain(coinName, 3);
            const params = {
                passphrase: 'test',
                enterprise: enterpriseId,
                originalPasscodeEncryptionCode: '123456',
                encryptionVersion: 2,
            };
            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));
            // Verify v2 envelopes for encryptedPrv
            assert.ok(userKeychain.encryptedPrv);
            const encryptedPrvParsed = JSON.parse(userKeychain.encryptedPrv);
            assert.equal(encryptedPrvParsed.v, 2, 'encryptedPrv should be a v2 envelope');
            // Verify v2 envelopes for reducedEncryptedPrv
            assert.ok(userKeychain.reducedEncryptedPrv);
            const reducedEncryptedPrvParsed = JSON.parse(userKeychain.reducedEncryptedPrv);
            assert.equal(reducedEncryptedPrvParsed.v, 2, 'reducedEncryptedPrv should be a v2 envelope');
            // Verify v2 envelope is decryptable via decrypt
            const decrypted = await bitgo.decrypt({ input: userKeychain.encryptedPrv, password: params.passphrase });
            assert.ok(decrypted, 'decrypt should successfully decrypt v2 envelope');
            // Verify backup keychain also uses v2 envelopes
            assert.ok(backupKeychain);
            assert.equal(backupKeychain.source, 'backup');
            assert.ok(backupKeychain.encryptedPrv);
            const backupEncryptedPrvParsed = JSON.parse(backupKeychain.encryptedPrv);
            assert.equal(backupEncryptedPrvParsed.v, 2, 'backup encryptedPrv should be a v2 envelope');
            assert.ok(bitgoKeychain);
            assert.equal(bitgoKeychain.source, 'bitgo');
        });
        it('should generate TSS MPCv2 keys for retrofit', async function () {
            const xiList = [
                Array.from((0, sdk_lib_mpc_1.bigIntToBufferBE)(BigInt(1), 32)),
                Array.from((0, sdk_lib_mpc_1.bigIntToBufferBE)(BigInt(2), 32)),
                Array.from((0, sdk_lib_mpc_1.bigIntToBufferBE)(BigInt(3), 32)),
            ];
            const bitgoRetrofitData = {
                xiList,
                xShare: v1Fixtures.mockBitGoShareSigningMaterial.xShare,
            };
            const bitgoSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BITGO, undefined, bitgoRetrofitData);
            const round1Nock = await nockKeyGenRound1(bitgoSession, 1);
            const round2Nock = await nockKeyGenRound2(bitgoSession, 1);
            const round3Nock = await nockKeyGenRound3(bitgoSession, 1);
            const addKeyNock = await nockAddKeyChain(coinName, 3);
            const params = {
                passphrase: 'test',
                enterprise: enterpriseId,
                originalPasscodeEncryptionCode: '123456',
                retrofit: {
                    decryptedUserKey: JSON.stringify(v1Fixtures.mockUserSigningMaterial),
                    decryptedBackupKey: JSON.stringify(v1Fixtures.mockBackupSigningMaterial),
                    walletId: '123',
                },
            };
            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(bitgo.decrypt({ input: userKeychain.encryptedPrv, password: params.passphrase }));
            assert.ok(backupKeychain);
            assert.equal(backupKeychain.source, 'backup');
            assert.ok(backupKeychain.commonKeychain);
            assert.ok(sdk_core_1.ECDSAUtils.EcdsaMPCv2Utils.validateCommonKeychainPublicKey(backupKeychain.commonKeychain));
            assert.ok(backupKeychain.encryptedPrv);
            assert.ok(bitgo.decrypt({ input: backupKeychain.encryptedPrv, password: params.passphrase }));
            assert.ok(bitgoKeychain);
            assert.equal(bitgoKeychain.source, 'bitgo');
        });
        it('should create TSS key chains', async function () {
            const nockPromises = [
                nockKeychain({
                    coin: coinName,
                    keyChain: { id: '1', pub: '1', type: 'tss', reducedEncryptedPrv: '' },
                    source: 'user',
                }),
                nockKeychain({
                    coin: coinName,
                    keyChain: { id: '2', pub: '2', type: 'tss', reducedEncryptedPrv: '' },
                    source: 'backup',
                }),
                nockKeychain({
                    coin: coinName,
                    keyChain: { id: '3', pub: '3', type: 'tss', reducedEncryptedPrv: '' },
                    source: 'bitgo',
                }),
            ];
            const [nockedUserKeychain, nockedBackupKeychain, nockedBitGoKeychain] = await Promise.all(nockPromises);
            const bitgoKeychainPromise = tssUtils.createParticipantKeychain(sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BITGO, 'test');
            const usersKeychainPromise = tssUtils.createParticipantKeychain(sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER, 'test', Buffer.from('test'), Buffer.from('test'), 'passphrase', 'test');
            const backupKeychainPromise = tssUtils.createParticipantKeychain(sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP, 'test', Buffer.from('test'), Buffer.from('test'), 'passphrase', 'test');
            const [userKeychain, backupKeychain, bitgoKeychain] = await Promise.all([
                usersKeychainPromise,
                backupKeychainPromise,
                bitgoKeychainPromise,
            ]);
            ({ ...userKeychain, reducedEncryptedPrv: '' }).should.deepEqual(nockedUserKeychain);
            ({ ...backupKeychain, reducedEncryptedPrv: '' }).should.deepEqual(nockedBackupKeychain);
            ({ ...bitgoKeychain, reducedEncryptedPrv: '' }).should.deepEqual(nockedBitGoKeychain);
        });
        it('should create TSS MPCv2 key chains with OVCs', async function () {
            const MPCv2SMCUtils = new sdk_core_1.ECDSAUtils.MPCv2SMCUtils(bitgo, baseCoin);
            const bitgoSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, 2);
            const round1Nock = await nockKeyGenRound1(bitgoSession, 1);
            const round2Nock = await nockKeyGenRound2(bitgoSession, 1);
            const round3Nock = await nockKeyGenRound3(bitgoSession, 1);
            const addKeyNock = await nockAddKeyChain(coinName, 3);
            // OVC 1 - User GPG key
            const userGgpKey = await openpgp.generateKey({
                userIDs: [
                    {
                        name: 'user',
                        email: 'user@test.com',
                    },
                ],
                curve: 'secp256k1',
            });
            const userGpgPrvKey = {
                partyId: 0,
                gpgKey: userGgpKey.privateKey,
            };
            // Round 1 User
            const userSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, 0);
            let OVC1ToOVC2Round1Payload;
            {
                const userBroadcastMsg1Unsigned = await userSession.initDkg();
                const userMsgs1Signed = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages({ broadcastMessages: [sdk_lib_mpc_1.DklsTypes.serializeBroadcastMessage(userBroadcastMsg1Unsigned)], p2pMessages: [] }, [], [userGpgPrvKey]);
                const userMsg1 = userMsgs1Signed.broadcastMessages.find((m) => m.from === 0);
                assert.ok(userMsg1, 'userMsg1 not found');
                OVC1ToOVC2Round1Payload = {
                    tssVersion: '0.0.1',
                    walletType: public_types_1.WalletTypeEnum.tss,
                    coin: 'eth',
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC2Round1Data,
                    ovc: {
                        [public_types_1.OVCIndexEnum.ONE]: {
                            gpgPubKey: userGgpKey.publicKey,
                            ovcMsg1: userMsg1,
                        },
                    },
                };
            }
            // OVC 2 - Backup GPG key
            const backupGgpKey = await openpgp.generateKey({
                userIDs: [
                    {
                        name: 'backup',
                        email: 'backup@test.com',
                    },
                ],
                curve: 'secp256k1',
            });
            const backupGpgPrvKey = {
                partyId: 1,
                gpgKey: backupGgpKey.privateKey,
            };
            // Round 1 Backup
            const backupSession = new sdk_lib_mpc_1.DklsDkg.Dkg(3, 2, 1);
            let OVC2ToBitgoRound1Payload;
            {
                assert.ok(OVC1ToOVC2Round1Payload.state === 0, 'OVC1ToOVC2Round1Payload.state should be 0');
                const backupBroadcastMsg1Unsigned = await backupSession.initDkg();
                const backupMsgs1Signed = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages({ broadcastMessages: [sdk_lib_mpc_1.DklsTypes.serializeBroadcastMessage(backupBroadcastMsg1Unsigned)], p2pMessages: [] }, [], [backupGpgPrvKey]);
                const backupMsg1 = backupMsgs1Signed.broadcastMessages.find((m) => m.from === 1);
                assert.ok(backupMsg1, 'backupMsg1 not found');
                OVC2ToBitgoRound1Payload = {
                    ...OVC1ToOVC2Round1Payload,
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForBitgoRound1Data,
                    ovc: {
                        ...OVC1ToOVC2Round1Payload.ovc,
                        [public_types_1.OVCIndexEnum.TWO]: {
                            gpgPubKey: backupGgpKey.publicKey,
                            ovcMsg1: backupMsg1,
                        },
                    },
                };
            }
            // Round 1 BitGo
            const bitgoToOVC1Round1Payload = await MPCv2SMCUtils.keyGenRound1('testId', OVC2ToBitgoRound1Payload);
            // Round 2 User
            let OVC1ToOVC2Round2Payload;
            {
                assert.ok(bitgoToOVC1Round1Payload.state === 2, 'bitgoToOVC1Round1Payload.state should be 2');
                const toUserRound1BroadcastMessages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: [
                        bitgoToOVC1Round1Payload.ovc[public_types_1.OVCIndexEnum.TWO].ovcMsg1,
                        bitgoToOVC1Round1Payload.platform.bitgoMsg1,
                    ],
                }, [bitgoGpgPubKey, { partyId: 1, gpgKey: bitgoToOVC1Round1Payload.ovc[public_types_1.OVCIndexEnum.TWO].gpgPubKey }], [userGpgPrvKey]);
                const userRound2P2PMessages = userSession.handleIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: toUserRound1BroadcastMessages.broadcastMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeBroadcastMessage),
                });
                const userRound2Messages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(sdk_lib_mpc_1.DklsTypes.serializeMessages(userRound2P2PMessages), [{ partyId: 1, gpgKey: bitgoToOVC1Round1Payload.ovc[public_types_1.OVCIndexEnum.TWO].gpgPubKey }, bitgoGpgPubKey], [userGpgPrvKey]);
                const userToBackupMsg2 = userRound2Messages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP);
                assert.ok(userToBackupMsg2, 'userToBackupMsg2 not found');
                const userToBitgoMsg2 = userRound2Messages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BITGO);
                assert.ok(userToBitgoMsg2, 'userToBitgoMsg2 not found');
                OVC1ToOVC2Round2Payload = {
                    ...bitgoToOVC1Round1Payload,
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC2Round2Data,
                    ovc: {
                        ...bitgoToOVC1Round1Payload.ovc,
                        [public_types_1.OVCIndexEnum.ONE]: Object.assign(bitgoToOVC1Round1Payload.ovc[public_types_1.OVCIndexEnum.ONE], {
                            ovcToBitgoMsg2: userToBitgoMsg2,
                            ovcToOvcMsg2: userToBackupMsg2,
                        }),
                    },
                };
            }
            // Round 2 Backup
            let OVC2ToBitgoRound2Payload;
            {
                assert.ok(OVC1ToOVC2Round2Payload.state === 3, 'bitgoToOVC1Round1Payload.state should be 3');
                const toBackupRound1BroadcastMessages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: [
                        bitgoToOVC1Round1Payload.ovc[public_types_1.OVCIndexEnum.ONE].ovcMsg1,
                        bitgoToOVC1Round1Payload.platform.bitgoMsg1,
                    ],
                }, [bitgoGpgPubKey, { partyId: 0, gpgKey: OVC1ToOVC2Round2Payload.ovc[public_types_1.OVCIndexEnum.ONE].gpgPubKey }], [backupGpgPrvKey]);
                const backupRound2P2PMessages = backupSession.handleIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: toBackupRound1BroadcastMessages.broadcastMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeBroadcastMessage),
                });
                const backupRound2Messages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(sdk_lib_mpc_1.DklsTypes.serializeMessages(backupRound2P2PMessages), [{ partyId: 0, gpgKey: bitgoToOVC1Round1Payload.ovc[public_types_1.OVCIndexEnum.ONE].gpgPubKey }, bitgoGpgPubKey], [backupGpgPrvKey]);
                const backupToUserMsg2 = backupRound2Messages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER);
                assert.ok(backupToUserMsg2, 'backupToUserMsg2 not found');
                const backupToBitgoMsg2 = backupRound2Messages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BITGO);
                assert.ok(backupToBitgoMsg2, 'backupToBitgoMsg2 not found');
                OVC2ToBitgoRound2Payload = {
                    ...OVC1ToOVC2Round2Payload,
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForBitgoRound2Data,
                    ovc: {
                        ...OVC1ToOVC2Round2Payload.ovc,
                        [public_types_1.OVCIndexEnum.TWO]: Object.assign(OVC1ToOVC2Round2Payload.ovc[public_types_1.OVCIndexEnum.TWO], {
                            ovcToBitgoMsg2: backupToBitgoMsg2,
                            ovcToOvcMsg2: backupToUserMsg2,
                        }),
                    },
                };
            }
            // Round 2 BitGo
            // call bitgo round 2
            const bitgoToOVC1Round2Payload = await MPCv2SMCUtils.keyGenRound2('testId', OVC2ToBitgoRound2Payload);
            // Round 3A User
            let OVC1ToOVC2Round3Payload;
            {
                assert.ok(bitgoToOVC1Round2Payload.state === 5, 'bitgoToOVC1Round2Payload.state should be 5');
                const toUserRound2P2PMessages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [
                        bitgoToOVC1Round2Payload.ovc[public_types_1.OVCIndexEnum.TWO].ovcToOvcMsg2,
                        bitgoToOVC1Round2Payload.platform.ovc[public_types_1.OVCIndexEnum.ONE].bitgoToOvcMsg2,
                    ],
                    broadcastMessages: [],
                }, [bitgoGpgPubKey, { partyId: 1, gpgKey: bitgoToOVC1Round2Payload.ovc[public_types_1.OVCIndexEnum.TWO].gpgPubKey }], [userGpgPrvKey]);
                const userRound3AP2PMessages = userSession.handleIncomingMessages({
                    p2pMessages: toUserRound2P2PMessages.p2pMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeP2PMessage),
                    broadcastMessages: [],
                }).p2pMessages;
                const userRound3AMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(sdk_lib_mpc_1.DklsTypes.serializeMessages({
                    p2pMessages: userRound3AP2PMessages,
                    broadcastMessages: [],
                }), [{ partyId: 1, gpgKey: bitgoToOVC1Round2Payload.ovc[public_types_1.OVCIndexEnum.TWO].gpgPubKey }, bitgoGpgPubKey], [userGpgPrvKey]);
                const userToBitgoMsg3 = userRound3AMessages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BITGO);
                assert.ok(userToBitgoMsg3, 'userToBitgoMsg3 not found');
                const userToBackupMsg3 = userRound3AMessages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP);
                assert.ok(userToBackupMsg3, 'userToBackupMsg3 not found');
                OVC1ToOVC2Round3Payload = {
                    ...bitgoToOVC1Round2Payload,
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC2Round3Data,
                    ovc: {
                        ...bitgoToOVC1Round2Payload.ovc,
                        [public_types_1.OVCIndexEnum.ONE]: Object.assign(bitgoToOVC1Round2Payload.ovc[public_types_1.OVCIndexEnum.ONE], {
                            ovcToBitgoMsg3: userToBitgoMsg3,
                            ovcToOvcMsg3: userToBackupMsg3,
                        }),
                    },
                };
            }
            // Round 3 Backup
            let OVC2ToOVC1Round3Payload;
            {
                assert.ok(OVC1ToOVC2Round3Payload.state === 6, 'OVC1ToOVC2Round3Payload.state should be 6');
                const toBackupRound3P2PMessages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [
                        OVC1ToOVC2Round3Payload.ovc[public_types_1.OVCIndexEnum.ONE].ovcToOvcMsg2,
                        OVC1ToOVC2Round3Payload.platform.ovc[public_types_1.OVCIndexEnum.TWO].bitgoToOvcMsg2,
                    ],
                    broadcastMessages: [],
                }, [bitgoGpgPubKey, { partyId: 0, gpgKey: OVC1ToOVC2Round3Payload.ovc[public_types_1.OVCIndexEnum.ONE].gpgPubKey }], [backupGpgPrvKey]);
                const backupRound3P2PMessages = backupSession.handleIncomingMessages({
                    p2pMessages: toBackupRound3P2PMessages.p2pMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeP2PMessage),
                    broadcastMessages: [],
                });
                const backupRound3Messages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(sdk_lib_mpc_1.DklsTypes.serializeMessages(backupRound3P2PMessages), [{ partyId: 0, gpgKey: OVC1ToOVC2Round3Payload.ovc[public_types_1.OVCIndexEnum.ONE].gpgPubKey }, bitgoGpgPubKey], [backupGpgPrvKey]);
                const backupToBitgoMsg3 = backupRound3Messages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BITGO);
                assert.ok(backupToBitgoMsg3, 'backupToBitgoMsg3 not found');
                const backupToUserMsg3 = backupRound3Messages.p2pMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP && m.to === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER);
                assert.ok(backupToUserMsg3, 'backupToUserMsg3 not found');
                const toBackupRound3Messages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [
                        {
                            ...OVC1ToOVC2Round3Payload.ovc[public_types_1.OVCIndexEnum.ONE].ovcToOvcMsg3,
                            commitment: OVC1ToOVC2Round3Payload.ovc[public_types_1.OVCIndexEnum.ONE].ovcToOvcMsg2.commitment,
                        },
                        {
                            ...OVC1ToOVC2Round3Payload.platform.ovc[public_types_1.OVCIndexEnum.TWO].bitgoToOvcMsg3,
                            commitment: OVC1ToOVC2Round3Payload.platform.bitgoCommitment2,
                        },
                    ],
                    broadcastMessages: [],
                }, [bitgoGpgPubKey, { partyId: 0, gpgKey: OVC1ToOVC2Round3Payload.ovc[public_types_1.OVCIndexEnum.ONE].gpgPubKey }], [backupGpgPrvKey]);
                const backupRound4Messages = backupSession.handleIncomingMessages({
                    p2pMessages: toBackupRound3Messages.p2pMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeP2PMessage),
                    broadcastMessages: [],
                }).broadcastMessages;
                const backupRound4BroadcastMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(sdk_lib_mpc_1.DklsTypes.serializeMessages({
                    p2pMessages: [],
                    broadcastMessages: backupRound4Messages,
                }), [], [backupGpgPrvKey]);
                const backupMsg4 = backupRound4BroadcastMessages.broadcastMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.BACKUP);
                assert.ok(backupMsg4, 'backupMsg4 not found');
                OVC2ToOVC1Round3Payload = {
                    ...OVC1ToOVC2Round3Payload,
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC1Round3bData,
                    ovc: {
                        ...OVC1ToOVC2Round3Payload.ovc,
                        [public_types_1.OVCIndexEnum.TWO]: Object.assign(OVC1ToOVC2Round3Payload.ovc[public_types_1.OVCIndexEnum.TWO], {
                            ovcToOvcMsg3: backupToUserMsg3,
                            ovcToBitgoMsg3: backupToBitgoMsg3,
                            ovcMsg4: backupMsg4,
                        }),
                    },
                };
            }
            // Round 3B User
            let OVC1ToBitgoRound3BPayload;
            {
                assert.ok(OVC2ToOVC1Round3Payload.state === 7, 'OVC2ToOVC1Round3Payload.state should be 7');
                const toUserRound4Messages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [
                        {
                            ...OVC2ToOVC1Round3Payload.ovc[public_types_1.OVCIndexEnum.TWO].ovcToOvcMsg3,
                            commitment: OVC2ToOVC1Round3Payload.ovc[public_types_1.OVCIndexEnum.TWO].ovcToOvcMsg2.commitment,
                        },
                        {
                            ...OVC2ToOVC1Round3Payload.platform.ovc[public_types_1.OVCIndexEnum.ONE].bitgoToOvcMsg3,
                            commitment: OVC2ToOVC1Round3Payload.platform.bitgoCommitment2,
                        },
                    ],
                    broadcastMessages: [],
                }, [bitgoGpgPubKey, { partyId: 1, gpgKey: OVC2ToOVC1Round3Payload.ovc[public_types_1.OVCIndexEnum.TWO].gpgPubKey }], [userGpgPrvKey]);
                const userRound4BroadcastMessages = userSession.handleIncomingMessages({
                    p2pMessages: toUserRound4Messages.p2pMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeP2PMessage),
                    broadcastMessages: [],
                }).broadcastMessages;
                assert.ok(userRound4BroadcastMessages.length === 1, 'userRound4BroadcastMessages length should be 1');
                const userRound4Messages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(sdk_lib_mpc_1.DklsTypes.serializeMessages({
                    p2pMessages: [],
                    broadcastMessages: userRound4BroadcastMessages,
                }), [], [userGpgPrvKey]);
                const userMsg4 = userRound4Messages.broadcastMessages.find((m) => m.from === sdk_core_1.ECDSAUtils.MPCv2PartiesEnum.USER);
                assert.ok(userMsg4, 'userMsg4 not found');
                OVC1ToBitgoRound3BPayload = {
                    ...OVC2ToOVC1Round3Payload,
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForBitgoRound3Data,
                    ovc: {
                        ...OVC2ToOVC1Round3Payload.ovc,
                        [public_types_1.OVCIndexEnum.ONE]: Object.assign(OVC2ToOVC1Round3Payload.ovc[public_types_1.OVCIndexEnum.ONE], {
                            ovcMsg4: userMsg4,
                        }),
                    },
                };
            }
            // Round 3 BitGo
            // creates bitgo keychain
            const bitgoToOVC1Round3Payload = await MPCv2SMCUtils.keyGenRound3('testId', OVC1ToBitgoRound3BPayload);
            // Round 4 User
            let userCommonKeychain;
            let OVC1ToOVC2Round4Payload;
            {
                assert.ok(bitgoToOVC1Round3Payload.state === 9, 'bitgoToOVC1Round3Payload.state should be 9');
                assert.ok(bitgoToOVC1Round3Payload.bitGoKeyId, 'bitgoToOVC1Round3Payload.bitGoKeyId not found');
                const toUserBitgoRound3Msg = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: [
                        bitgoToOVC1Round3Payload.ovc[public_types_1.OVCIndexEnum.TWO].ovcMsg4,
                        bitgoToOVC1Round3Payload.platform.bitgoMsg4,
                    ],
                }, [bitgoGpgPubKey, { partyId: 1, gpgKey: bitgoToOVC1Round3Payload.ovc[public_types_1.OVCIndexEnum.TWO].gpgPubKey }], [userGpgPrvKey]);
                userSession.handleIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: toUserBitgoRound3Msg.broadcastMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeBroadcastMessage),
                });
                const userPrivateMaterial = userSession.getKeyShare();
                userCommonKeychain = sdk_lib_mpc_1.DklsTypes.getCommonKeychain(userPrivateMaterial);
                assert.equal(bitgoToOVC1Round3Payload.platform.commonKeychain, userCommonKeychain, 'User and Bitgo Common keychains do not match');
                const userPrv = userPrivateMaterial.toString('base64');
                assert.ok(userPrv, 'userPrv not found');
                OVC1ToOVC2Round4Payload = {
                    bitgoKeyId: bitgoToOVC1Round3Payload.bitGoKeyId,
                    ...bitgoToOVC1Round3Payload,
                    state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC2GenerateKey,
                };
            }
            // Round 4 Backup
            let backupCommonKeychain;
            {
                assert.ok(OVC1ToOVC2Round4Payload.state === 10, 'OVC1ToOVC2Round4Payload.state should be 10');
                assert.ok(OVC1ToOVC2Round4Payload.bitgoKeyId, 'OVC1ToOVC2Round4Payload.bitGoKeyId not found');
                const toBackupBitgoRound3Msg = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: [
                        OVC1ToOVC2Round4Payload.ovc[public_types_1.OVCIndexEnum.ONE].ovcMsg4,
                        OVC1ToOVC2Round4Payload.platform.bitgoMsg4,
                    ],
                }, [bitgoGpgPubKey, { partyId: 0, gpgKey: OVC1ToOVC2Round4Payload.ovc[public_types_1.OVCIndexEnum.ONE].gpgPubKey }], [backupGpgPrvKey]);
                backupSession.handleIncomingMessages({
                    p2pMessages: [],
                    broadcastMessages: toBackupBitgoRound3Msg.broadcastMessages.map(sdk_lib_mpc_1.DklsTypes.deserializeBroadcastMessage),
                });
                const backupPrivateMaterial = backupSession.getKeyShare();
                backupCommonKeychain = sdk_lib_mpc_1.DklsTypes.getCommonKeychain(backupPrivateMaterial);
                assert.equal(OVC1ToOVC2Round4Payload.platform.commonKeychain, backupCommonKeychain, 'Backup and Bitgo Common keychains do not match');
                const backupPrv = backupPrivateMaterial.toString('base64');
                assert.ok(backupPrv, 'backupPrv not found');
            }
            // Round 4 BitGo
            // creates user and backup keychain
            const keychains = await MPCv2SMCUtils.uploadClientKeys(bitgoToOVC1Round3Payload.bitGoKeyId, userCommonKeychain, backupCommonKeychain);
            assert.deepEqual(keychains.userKeychain, {
                commonKeychain: userCommonKeychain,
                type: 'tss',
                source: 'user',
                id: 'user',
            });
            assert.deepEqual(keychains.backupKeychain, {
                commonKeychain: backupCommonKeychain,
                type: 'tss',
                source: 'backup',
                id: 'backup',
            });
            assert.ok(round1Nock.isDone());
            assert.ok(round2Nock.isDone());
            assert.ok(round3Nock.isDone());
            assert.ok(addKeyNock.isDone());
        });
        it('should throw for MPCv2 SMC utils if the state is invalid', async function () {
            const MPCv2SMCUtils = new sdk_core_1.ECDSAUtils.MPCv2SMCUtils(bitgo, baseCoin);
            const invalidPayload = {
                state: public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC1Round2Data,
            };
            await assert.rejects(async () => await MPCv2SMCUtils.keyGenRound1('testId', invalidPayload), {
                message: `Invalid state for round 1, expected: ${public_types_1.KeyCreationMPCv2StateEnum.WaitingForBitgoRound1Data}, got: ${public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC1Round2Data}`,
            });
            await assert.rejects(async () => await MPCv2SMCUtils.keyGenRound2('testId', invalidPayload), {
                message: `Invalid state for round 2, expected: ${public_types_1.KeyCreationMPCv2StateEnum.WaitingForBitgoRound2Data}, got: ${public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC1Round2Data}`,
            });
            await assert.rejects(async () => await MPCv2SMCUtils.keyGenRound3('testId', invalidPayload), {
                message: `Invalid state for round 3, expected: ${public_types_1.KeyCreationMPCv2StateEnum.WaitingForBitgoRound3Data}, got: ${public_types_1.KeyCreationMPCv2StateEnum.WaitingForOVC1Round2Data}`,
            });
        });
    });
    async function nockKeychain(params, times = 1) {
        nock(bgUrl)
            .post(`/api/v2/${params.coin}/key`, (body) => {
            return body.keyType === 'tss' && body.source === params.source;
        })
            .times(times)
            .reply(200, params.keyChain);
        return params.keyChain;
    }
    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, 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 } = 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;
            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',
            };
        });
    }
    async function nockKeyGenRound2(bitgoSession, 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 } = 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');
            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,
                },
            };
        });
    }
    async function nockKeyGenRound3(bitgoSession, 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;
            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)
            .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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlS2V5Y2hhaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vdGVzdC92Mi91bml0L2ludGVybmFsL3Rzc1V0aWxzL2VjZHNhTVBDdjIvY3JlYXRlS2V5Y2hhaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaUNBQWlDO0FBQ2pDLDZCQUE4QjtBQUM5QixtQ0FBbUM7QUFDbkMsaUNBQWlDO0FBRWpDLDhDQUF3RDtBQUN4RCw4Q0FBcUc7QUFDckcsb0RBQXlHO0FBQ3pHLHNEQWlCNkI7QUFFN0IsK0NBQWlFO0FBQ2pFLHdEQUF3RDtBQUV4RCxRQUFRLENBQUMsd0JBQXdCLEVBQUUsS0FBSztJQUN0QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUM7SUFDekIsTUFBTSxRQUFRLEdBQUcsa0NBQWtDLENBQUM7SUFDcEQsTUFBTSxZQUFZLEdBQUcsa0NBQWtDLENBQUM7SUFDeEQsSUFBSSxxQkFBNkIsQ0FBQztJQUNsQyxJQUFJLHVCQUErQixDQUFDO0lBQ3BDLElBQUksc0JBQThCLENBQUM7SUFFbkMsSUFBSSxLQUFhLENBQUM7SUFDbEIsSUFBSSxRQUFvQyxDQUFDO0lBQ3pDLElBQUksTUFBYyxDQUFDO0lBQ25CLElBQUksS0FBeUIsQ0FBQztJQUM5QixJQUFJLFFBQWtCLENBQUM7SUFDdkIsSUFBSSxXQUVILENBQUM7SUFDRixJQUFJLFNBQTJFLENBQUM7SUFDaEYsSUFBSSxjQUFtRCxDQUFDO0lBQ3hELElBQUksYUFBa0QsQ0FBQztJQUN2RCxJQUFJLGVBQW9ELENBQUM7SUFDekQsSUFBSSxjQUFtRCxDQUFDO0lBRXhELFVBQVUsQ0FBQyxLQUFLO1FBQ2QsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sd0NBQXdDLENBQUMsUUFBUSxFQUFFLFlBQVksRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNwRixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLDBCQUEwQixDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7SUFDN0YsQ0FBQyxDQUFDLENBQUM7SUFFSCxNQUFNLENBQUMsS0FBSztRQUNWLCtFQUErRTtRQUMvRSxxRkFBcUY7UUFDckYsT0FBTyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN4QyxXQUFXLEdBQUcsTUFBTSxPQUFPLENBQUMsV0FBVyxDQUFDO1lBQ3RDLE9BQU8sRUFBRTtnQkFDUDtvQkFDRSxJQUFJLEVBQUUsT0FBTztvQkFDYixLQUFLLEVBQUUsZ0JBQWdCO2lCQUN4QjthQUNGO1lBQ0QsS0FBSyxFQUFFLFdBQVc7U0FDbkIsQ0FBQyxDQUFDO1FBQ0gsU0FBUyxHQUFHO1lBQ1YsR0FBRyxFQUFFO2dCQUNILGNBQWMsRUFBRSxXQUFXLENBQUMsU0FBUztnQkFDckMsbUJBQW1CLEVBQUUsV0FBVyxDQUFDLFNBQVM7YUFDM0M7U0FDRixDQUFDO1FBRUYsY0FBYyxHQUFHO1lBQ2YsT0FBTyxFQUFFLENBQUM7WUFDVixNQUFNLEVBQUUsV0FBVyxDQUFDLFNBQVM7U0FDOUIsQ0FBQztRQUVGLGNBQWMsR0FBRztZQUNmLE9BQU8sRUFBRSxDQUFDO1lBQ1YsTUFBTSxFQUFFLFdBQVcsQ0FBQyxVQUFVO1NBQy9CLENBQUM7UUFFRixLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsV0FBSyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDbkQsS0FBSyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFFM0IsUUFBUSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFaEMsS0FBSyxHQUFHLGlCQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUVoRCxNQUFNLFVBQVUsR0FBRztZQUNqQixFQUFFLEVBQUUsUUFBUTtZQUNaLFVBQVUsRUFBRSxZQUFZO1lBQ3hCLElBQUksRUFBRSxRQUFRO1lBQ2QsWUFBWSxFQUFFLEVBQUU7WUFDaEIsWUFBWSxFQUFFLEtBQUs7U0FDcEIsQ0FBQztRQUNGLE1BQU0sR0FBRyxJQUFJLGlCQUFNLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUNqRCxRQUFRLEdBQUcsSUFBSSxxQkFBVSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3JFLENBQUMsQ0FBQyxDQUFDO0lBRUgsS0FBSyxDQUFDO1FBQ0osSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2xCLENBQUMsQ0FBQyxDQUFDO0lBRUgsUUFBUSxDQUFDLDhCQUE4QixFQUFFLEtBQUs7UUFDNUMsRUFBRSxDQUFDLG1FQUFtRSxFQUFFLEtBQUs7WUFDM0UsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLGlDQUFpQyxDQUFDO2dCQUM5RCxpQkFBaUIsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyx1QkFBdUIsQ0FBQztnQkFDckUsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMseUJBQXlCLENBQUM7YUFDMUUsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxpQkFBaUIsR0FBMkI7Z0JBQ2hELE1BQU0sRUFBRSxZQUFZLENBQUMsaUJBQWlCLENBQUMsTUFBTTtnQkFDN0MsTUFBTSxFQUFFLFVBQVUsQ0FBQyw2QkFBNkIsQ0FBQyxNQUFNO2FBQ3hELENBQUM7WUFDRixNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsR0FBRyxNQUFNLHVCQUFTLENBQUMsb0JBQW9CLENBQ2hFLFlBQVksQ0FBQyxpQkFBaUIsRUFDOUIsWUFBWSxDQUFDLG1CQUFtQixFQUNoQyxpQkFBaUIsQ0FDbEIsQ0FBQztZQUNGLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDL0IsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUM5RixNQUFNLGNBQWMsR0FBRyxlQUFlLENBQUM7WUFDdkMsTUFBTSxTQUFTLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdCQUFnQixDQUNoRCxDQUFDLEVBQ0QsSUFBSSxxQkFBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxFQUFFLGNBQWMsRUFBRSxhQUFhLENBQUMsRUFDckUsSUFBSSxxQkFBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxFQUFFLGNBQWMsRUFBRSxhQUFhLENBQUMsQ0FDeEUsQ0FBQztZQUNGLE1BQU0sa0JBQWtCLEdBQUcsdUJBQVMsQ0FBQyw2QkFBNkIsQ0FDaEUsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQzFCLFNBQWdELEVBQ2hELFVBQVUsQ0FBQyw2QkFBNkIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyw2QkFBNkIsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUM3RyxjQUFjLENBQ2YsQ0FBQztZQUNGLE1BQU0sQ0FBQyxFQUFFLENBQUMsa0JBQWtCLENBQUMsQ0FBQztZQUM5QixrQkFBa0IsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkQsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLO1FBQzlCLEVBQUUsQ0FBQyxnQ0FBZ0MsRUFBRSxLQUFLO1lBQ3hDLE1BQU0sWUFBWSxHQUFHLElBQUkscUJBQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUU5QyxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxNQUFNLFVBQVUsR0FBRyxNQUFNLGVBQWUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdEQsTUFBTSxNQUFNLEdBQUc7Z0JBQ2IsVUFBVSxFQUFFLE1BQU07Z0JBQ2xCLFVBQVUsRUFBRSxZQUFZO2dCQUN4Qiw4QkFBOEIsRUFBRSxRQUFRO2FBQ3pDLENBQUM7WUFDRixNQUFNLEVBQUUsWUFBWSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsR0FBRyxNQUFNLFFBQVEsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDL0YsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUUvQixNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3hCLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMxQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUN2QyxNQUFNLENBQUMsRUFBRSxDQUFDLHFCQUFVLENBQUMsZUFBZSxDQUFDLCtCQUErQixDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1lBQ25HLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3JDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRTVGLE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDMUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzlDLE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sQ0FBQyxFQUFFLENBQUMscUJBQVUsQ0FBQyxlQUFlLENBQUMsK0JBQStCLENBQUMsY0FBYyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7WUFDckcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdkMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLGNBQWMsQ0FBQyxZQUFZLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFOUYsTUFBTSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN6QixNQUFNLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsaUdBQWlHLEVBQUUsS0FBSztZQUN6RyxNQUFNLFlBQVksR0FBRyxJQUFJLHFCQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFOUMsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFM0Qsc0ZBQXNGO1lBQ3RGLE1BQU0sY0FBYyxHQUF1QyxFQUFFLENBQUM7WUFDOUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDO2lCQUM3QyxJQUFJLENBQUMsV0FBVyxRQUFRLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxLQUFLLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQztpQkFDakYsS0FBSyxDQUFDLENBQUMsQ0FBQztpQkFDUixLQUFLLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsV0FBK0IsRUFBRSxFQUFFO2dCQUN6RCxjQUFjLENBQUMsV0FBVyxDQUFDLE1BQWdCLENBQUMsR0FBRyxXQUFXLENBQUM7Z0JBQzNELE1BQU0sR0FBRyxHQUFHO29CQUNWLEVBQUUsRUFBRSxXQUFXLENBQUMsTUFBTTtvQkFDdEIsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNO29CQUMxQixJQUFJLEVBQUUsV0FBVyxDQUFDLE9BQU87b0JBQ3pCLGNBQWMsRUFBRSxXQUFXLENBQUMsY0FBYztvQkFDMUMsWUFBWSxFQUFFLFdBQVcsQ0FBQyxZQUFZO2lCQUN2QyxDQUFDO2dCQUNGLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLFFBQVEsUUFBUSxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUNuRyxPQUFPLEdBQUcsQ0FBQztZQUNiLENBQUMsQ0FBQyxDQUFDO1lBRUwsTUFBTSxZQUFZLEdBQUc7Z0JBQ25CLFdBQVcsRUFBRSxZQUFZO2dCQUN6QixPQUFPLEVBQUUsVUFBVTtnQkFDbkIsVUFBVSxFQUFFLHdCQUF3QjthQUNyQyxDQUFDO1lBQ0YsTUFBTSxNQUFNLEdBQUc7Z0JBQ2IsVUFBVSxFQUFFLE1BQU07Z0JBQ2xCLFVBQVUsRUFBRSxZQUFZO2dCQUN4Qiw4QkFBOEIsRUFBRSxRQUFRO2dCQUN4QyxZQUFZO2FBQ2IsQ0FBQztZQUNGLE1BQU0sUUFBUSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN2QyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBRS9CLG9GQUFvRjtZQUNwRixpRkFBaUY7WUFDakYsTUFBTSxRQUFRLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3hDLE1BQU0sQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLHdDQUF3QyxDQUFDLENBQUM7WUFDOUQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLGdEQUFnRCxDQUFDLENBQUM7WUFDbkYsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDMUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDbEUsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQztZQUMvRCxNQUFNLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLDRCQUE0QixDQUFDLENBQUM7WUFDNUUsZ0ZBQWdGO1lBQ2hGLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxRQUFRLEVBQUUsWUFBWSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRyxNQUFNLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxlQUFlLEVBQUUsU0FBUyxFQUFFLCtDQUErQyxDQUFDLENBQUM7WUFFekcscURBQXFEO1lBQ3JELE1BQU0sVUFBVSxHQUFHLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM1QyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSwwQ0FBMEMsQ0FBQyxDQUFDO1lBQ2xFLE1BQU0sQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQztZQUN2RCxNQUFNLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxlQUFlLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDNUQsQ0FBQyxDQUFDLENBQUM7UUFFSCxFQUFFLENBQUMsNkRBQTZELEVBQUUsS0FBSztZQUNyRSxNQUFNLFlBQVksR0FBRyxJQUFJLHFCQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFOUMsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxlQUFlLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RELE1BQU0sTUFBTSxHQUFHO2dCQUNiLFVBQVUsRUFBRSxNQUFNO2dCQUNsQixVQUFVLEVBQUUsWUFBWTtnQkFDeEIsOEJBQThCLEVBQUUsUUFBUTtnQkFDeEMsaUJBQWlCLEVBQUUsQ0FBVTthQUM5QixDQUFDO1lBQ0YsTUFBTSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLEdBQUcsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQy9GLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFFL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN4QixNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDMUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDdkMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxxQkFBVSxDQUFDLGVBQWUsQ0FBQywrQkFBK0IsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztZQUVuRyx1Q0FBdUM7WUFDdkMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDckMsTUFBTSxrQkFBa0IsR0FBa0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDaEYsTUFBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLHNDQUFzQyxDQUFDLENBQUM7WUFFOUUsOENBQThDO1lBQzlDLE1BQU0sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDNUMsTUFBTSx5QkFBeUIsR0FBa0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUM5RixNQUFNLENBQUMsS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsNkNBQTZDLENBQUMsQ0FBQztZQUU1RixnREFBZ0Q7WUFDaEQsTUFBTSxTQUFTLEdBQUcsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxZQUFZLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1lBQ3pHLE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLGlEQUFpRCxDQUFDLENBQUM7WUFFeEUsZ0RBQWdEO1lBQ2hELE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDMUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQzlDLE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3ZDLE1BQU0sd0JBQXdCLEdBQWtCLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3hGLE1BQU0sQ0FBQyxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSw2Q0FBNkMsQ0FBQyxDQUFDO1lBRTNGLE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDekIsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDZDQUE2QyxFQUFFLEtBQUs7WUFDckQsTUFBTSxNQUFNLEdBQUc7Z0JBQ2IsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFBLDhCQUFnQixFQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDM0MsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFBLDhCQUFnQixFQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDM0MsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFBLDhCQUFnQixFQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQzthQUM1QyxDQUFDO1lBQ0YsTUFBTSxpQkFBaUIsR0FBMkI7Z0JBQ2hELE1BQU07Z0JBQ04sTUFBTSxFQUFFLFVBQVUsQ0FBQyw2QkFBNkIsQ0FBQyxNQUFNO2FBQ3hELENBQUM7WUFDRixNQUFNLFlBQVksR0FBRyxJQUFJLHFCQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUscUJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFFNUcsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxlQUFlLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RELE1BQU0sTUFBTSxHQUFtRDtnQkFDN0QsVUFBVSxFQUFFLE1BQU07Z0JBQ2xCLFVBQVUsRUFBRSxZQUFZO2dCQUN4Qiw4QkFBOEIsRUFBRSxRQUFRO2dCQUN4QyxRQUFRLEVBQUU7b0JBQ1IsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsdUJBQXVCLENBQUM7b0JBQ3BFLGtCQUFrQixFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDO29CQUN4RSxRQUFRLEVBQUUsS0FBSztpQkFDaEI7YUFDRixDQUFDO1lBQ0YsTUFBTSxFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLEdBQUcsTUFBTSxRQUFRLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQy9GLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFFL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN4QixNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDMUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7WUFDdkMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxxQkFBVSxDQUFDLGVBQWUsQ0FBQywrQkFBK0IsQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztZQUNuRyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNyQyxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsWUFBWSxDQUFDLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUU1RixNQUFNLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzFCLE1BQU0sQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztZQUM5QyxNQUFNLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUN6QyxNQUFNLENBQUMsRUFBRSxDQUFDLHFCQUFVLENBQUMsZUFBZSxDQUFDLCtCQUErQixDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1lBQ3JHLE1BQU0sQ0FBQyxFQUFFLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3ZDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxjQUFjLENBQUMsWUFBWSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRTlGLE1BQU0sQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDekIsTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLENBQUMsQ0FBQyxDQUFDO1FBRUgsRUFBRSxDQUFDLDhCQUE4QixFQUFFLEtBQUs7WUFDdEMsTUFBTSxZQUFZLEdBQUc7Z0JBQ25CLFlBQVksQ0FBQztvQkFDWCxJQUFJLEVBQUUsUUFBUTtvQkFDZCxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUU7b0JBQ3JFLE1BQU0sRUFBRSxNQUFNO2lCQUNmLENBQUM7Z0JBQ0YsWUFBWSxDQUFDO29CQUNYLElBQUksRUFBRSxRQUFRO29CQUNkLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixFQUFFLEVBQUUsRUFBRTtvQkFDckUsTUFBTSxFQUFFLFFBQVE7aUJBQ2pCLENBQUM7Z0JBQ0YsWUFBWSxDQUFDO29CQUNYLElBQUksRUFBRSxRQUFRO29CQUNkLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixFQUFFLEVBQUUsRUFBRTtvQkFDckUsTUFBTSxFQUFFLE9BQU87aUJBQ2hCLENBQUM7YUFDSCxDQUFDO1lBQ0YsTUFBTSxDQUFDLGtCQUFrQixFQUFFLG9CQUFvQixFQUFFLG1CQUFtQixDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBRXhHLE1BQU0sb0JBQW9CLEdBQUcsUUFBUSxDQUFDLHlCQUF5QixDQUFDLHFCQUFVLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQzNHLE1BQU0sb0JBQW9CLEdBQUcsUUFBUSxDQUFDLHlCQUF5QixDQUM3RCxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFDaEMsTUFBTSxFQUNOLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQ25CLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQ25CLFlBQVksRUFDWixNQUFNLENBQ1AsQ0FBQztZQUNGLE1BQU0scUJBQXFCLEdBQUcsUUFBUSxDQUFDLHlCQUF5QixDQUM5RCxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFDbEMsTUFBTSxFQUNOLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQ25CLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQ25CLFlBQVksRUFDWixNQUFNLENBQ1AsQ0FBQztZQUVGLE1BQU0sQ0FBQyxZQUFZLEVBQUUsY0FBYyxFQUFFLGFBQWEsQ0FBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQztnQkFDdEUsb0JBQW9CO2dCQUNwQixxQkFBcUI7Z0JBQ3JCLG9CQUFvQjthQUNyQixDQUFDLENBQUM7WUFFSCxDQUFDLEVBQUUsR0FBRyxZQUFZLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDcEYsQ0FBQyxFQUFFLEdBQUcsY0FBYyxFQUFFLG1CQUFtQixFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1lBQ3hGLENBQUMsRUFBRSxHQUFHLGFBQWEsRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUN4RixDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQyw4Q0FBOEMsRUFBRSxLQUFLO1lBQ3RELE1BQU0sYUFBYSxHQUFHLElBQUkscUJBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3BFLE1BQU0sWUFBWSxHQUFHLElBQUkscUJBQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUU5QyxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxNQUFNLFVBQVUsR0FBRyxNQUFNLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMzRCxNQUFNLFVBQVUsR0FBRyxNQUFNLGVBQWUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFFdEQsdUJBQXVCO1lBQ3ZCLE1BQU0sVUFBVSxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsQ0FBQztnQkFDM0MsT0FBTyxFQUFFO29CQUNQO3dCQUNFLElBQUksRUFBRSxNQUFNO3dCQUNaLEtBQUssRUFBRSxlQUFlO3FCQUN2QjtpQkFDRjtnQkFDRCxLQUFLLEVBQUUsV0FBVzthQUNuQixDQUFDLENBQUM7WUFDSCxNQUFNLGFBQWEsR0FBRztnQkFDcEIsT0FBTyxFQUFFLENBQUM7Z0JBQ1YsTUFBTSxFQUFFLFVBQVUsQ0FBQyxVQUFVO2FBQzlCLENBQUM7WUFFRixlQUFlO1lBQ2YsTUFBTSxXQUFXLEdBQUcsSUFBSSxxQkFBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzdDLElBQUksdUJBQWdELENBQUM7WUFDckQsQ0FBQztnQkFDQyxNQUFNLHlCQUF5QixHQUFHLE1BQU0sV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUM5RCxNQUFNLGVBQWUsR0FBRyxNQUFNLHVCQUFTLENBQUMsOEJBQThCLENBQ3BFLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyx1QkFBUyxDQUFDLHlCQUF5QixDQUFDLHlCQUF5QixDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLEVBQ3hHLEVBQUUsRUFDRixDQUFDLGFBQWEsQ0FBQyxDQUNoQixDQUFDO2dCQUNGLE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7Z0JBQzdFLE1BQU0sQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLG9CQUFvQixDQUFDLENBQUM7Z0JBRTFDLHVCQUF1QixHQUFHO29CQUN4QixVQUFVLEVBQUUsT0FBeUI7b0JBQ3JDLFVBQVUsRUFBRSw2QkFBYyxDQUFDLEdBQUc7b0JBQzlCLElBQUksRUFBRSxLQUF1QjtvQkFDN0IsS0FBSyxFQUFFLHdDQUF5QixDQUFDLHdCQUF3QjtvQkFDekQsR0FBRyxFQUFFO3dCQUNILENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsRUFBRTs0QkFDbEIsU0FBUyxFQUFFLFVBQVUsQ0FBQyxTQUEyQjs0QkFDakQsT0FBTyxFQUFFLFFBQWU7eUJBQ3pCO3FCQUNGO2lCQUNGLENBQUM7WUFDSixDQUFDO1lBRUQseUJBQXlCO1lBQ3pCLE1BQU0sWUFBWSxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsQ0FBQztnQkFDN0MsT0FBTyxFQUFFO29CQUNQO3dCQUNFLElBQUksRUFBRSxRQUFRO3dCQUNkLEtBQUssRUFBRSxpQkFBaUI7cUJBQ3pCO2lCQUNGO2dCQUNELEtBQUssRUFBRSxXQUFXO2FBQ25CLENBQUMsQ0FBQztZQUVILE1BQU0sZUFBZSxHQUFHO2dCQUN0QixPQUFPLEVBQUUsQ0FBQztnQkFDVixNQUFNLEVBQUUsWUFBWSxDQUFDLFVBQVU7YUFDaEMsQ0FBQztZQUNGLGlCQUFpQjtZQUNqQixNQUFNLGFBQWEsR0FBRyxJQUFJLHFCQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDL0MsSUFBSSx3QkFBa0QsQ0FBQztZQUN2RCxDQUFDO2dCQUNDLE1BQU0sQ0FBQyxFQUFFLENBQUMsdUJBQXVCLENBQUMsS0FBSyxLQUFLLENBQUMsRUFBRSwyQ0FBMkMsQ0FBQyxDQUFDO2dCQUM1RixNQUFNLDJCQUEyQixHQUFHLE1BQU0sYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUNsRSxNQUFNLGlCQUFpQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyw4QkFBOEIsQ0FDdEUsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLHVCQUFTLENBQUMseUJBQXlCLENBQUMsMkJBQTJCLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsRUFDMUcsRUFBRSxFQUNGLENBQUMsZUFBZSxDQUFDLENBQ2xCLENBQUM7Z0JBQ0YsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDO2dCQUNqRixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO2dCQUU5Qyx3QkFBd0IsR0FBRztvQkFDekIsR0FBRyx1QkFBdUI7b0JBQzFCLEtBQUssRUFBRSx3Q0FBeUIsQ0FBQyx5QkFBeUI7b0JBQzFELEdBQUcsRUFBRTt3QkFDSCxHQUFHLHVCQUF1QixDQUFDLEdBQUc7d0JBQzlCLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsRUFBRTs0QkFDbEIsU0FBUyxFQUFFLFlBQVksQ0FBQyxTQUEyQjs0QkFDbkQsT0FBTyxFQUFFLFVBQWlCO3lCQUMzQjtxQkFDRjtpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUVELGdCQUFnQjtZQUNoQixNQUFNLHdCQUF3QixHQUFHLE1BQU0sYUFBYSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsd0JBQXdCLENBQUMsQ0FBQztZQUV0RyxlQUFlO1lBQ2YsSUFBSSx1QkFBZ0QsQ0FBQztZQUNyRCxDQUFDO2dCQUNDLE1BQU0sQ0FBQyxFQUFFLENBQUMsd0JBQXdCLENBQUMsS0FBSyxLQUFLLENBQUMsRUFBRSw0Q0FBNEMsQ0FBQyxDQUFDO2dCQUM5RixNQUFNLDZCQUE2QixHQUFHLE1BQU0sdUJBQVMsQ0FBQyxnQ0FBZ0MsQ0FDcEY7b0JBQ0UsV0FBVyxFQUFFLEVBQUU7b0JBQ2YsaUJBQWlCLEVBQUU7d0JBQ2pCLHdCQUF3QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU87d0JBQ3RELHdCQUF3QixDQUFDLFFBQVEsQ0FBQyxTQUFTO3FCQUM1QztpQkFDRixFQUNELENBQUMsY0FBYyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsd0JBQXdCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsRUFDbEcsQ0FBQyxhQUFhLENBQUMsQ0FDaEIsQ0FBQztnQkFFRixNQUFNLHFCQUFxQixHQUFHLFdBQVcsQ0FBQyxzQkFBc0IsQ0FBQztvQkFDL0QsV0FBVyxFQUFFLEVBQUU7b0JBQ2YsaUJBQWlCLEVBQUUsNkJBQTZCLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLHVCQUFTLENBQUMsMkJBQTJCLENBQUM7aUJBQzlHLENBQUMsQ0FBQztnQkFDSCxNQUFNLGtCQUFrQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyw4QkFBOEIsQ0FDdkUsdUJBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxxQkFBcUIsQ0FBQyxFQUNsRCxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsd0JBQXdCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsY0FBYyxDQUFDLEVBQ2xHLENBQUMsYUFBYSxDQUFDLENBQ2hCLENBQUM7Z0JBQ0YsTUFBTSxnQkFBZ0IsR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUMxRCxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsRUFBRSxLQUFLLHFCQUFVLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUNsRyxDQUFDO2dCQUNGLE1BQU0sQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsNEJBQTRCLENBQUMsQ0FBQztnQkFDMUQsTUFBTSxlQUFlLEdBQUcsa0JBQWtCLENBQUMsV0FBVyxDQUFDLElBQUksQ0FDekQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUsscUJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FDakcsQ0FBQztnQkFDRixNQUFNLENBQUMsRUFBRSxDQUFDLGVBQWUsRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO2dCQUV4RCx1QkFBdUIsR0FBRztvQkFDeEIsR0FBRyx3QkFBd0I7b0JBQzNCLEtBQUssRUFBRSx3Q0FBeUIsQ0FBQyx3QkFBd0I7b0JBQ3pELEdBQUcsRUFBRTt3QkFDSCxHQUFHLHdCQUF3QixDQUFDLEdBQUc7d0JBQy9CLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFOzRCQUNoRixjQUFjLEVBQUUsZUFBZTs0QkFDL0IsWUFBWSxFQUFFLGdCQUFnQjt5QkFDL0IsQ0FBUTtxQkFDVjtpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUVELGlCQUFpQjtZQUNqQixJQUFJLHdCQUFrRCxDQUFDO1lBRXZELENBQUM7Z0JBQ0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLEtBQUssQ0FBQyxFQUFFLDRDQUE0QyxDQUFDLENBQUM7Z0JBQzdGLE1BQU0sK0JBQStCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUN0RjtvQkFDRSxXQUFXLEVBQUUsRUFBRTtvQkFDZixpQkFBaUIsRUFBRTt3QkFDakIsd0JBQXdCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTzt3QkFDdEQsd0JBQXdCLENBQUMsUUFBUSxDQUFDLFNBQVM7cUJBQzVDO2lCQUNGLEVBQ0QsQ0FBQyxjQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUNqRyxDQUFDLGVBQWUsQ0FBQyxDQUNsQixDQUFDO2dCQUVGLE1BQU0sdUJBQXVCLEdBQUcsYUFBYSxDQUFDLHNCQUFzQixDQUFDO29CQUNuRSxXQUFXLEVBQUUsRUFBRTtvQkFDZixpQkFBaUIsRUFBRSwrQkFBK0IsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQ3RFLHVCQUFTLENBQUMsMkJBQTJCLENBQ3RDO2lCQUNGLENBQUMsQ0FBQztnQkFDSCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyw4QkFBOEIsQ0FDekUsdUJBQVMsQ0FBQyxpQkFBaUIsQ0FBQyx1QkFBdUIsQ0FBQyxFQUNwRCxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsd0JBQXdCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsY0FBYyxDQUFDLEVBQ2xHLENBQUMsZUFBZSxDQUFDLENBQ2xCLENBQUM7Z0JBQ0YsTUFBTSxnQkFBZ0IsR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUM1RCxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsRUFBRSxLQUFLLHFCQUFVLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUNsRyxDQUFDO2dCQUNGLE1BQU0sQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsNEJBQTRCLENBQUMsQ0FBQztnQkFDMUQsTUFBTSxpQkFBaUIsR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUM3RCxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsRUFBRSxLQUFLLHFCQUFVLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUNuRyxDQUFDO2dCQUNGLE1BQU0sQ0FBQyxFQUFFLENBQUMsaUJBQWlCLEVBQUUsNkJBQTZCLENBQUMsQ0FBQztnQkFFNUQsd0JBQXdCLEdBQUc7b0JBQ3pCLEdBQUcsdUJBQXVCO29CQUMxQixLQUFLLEVBQUUsd0NBQXlCLENBQUMseUJBQXlCO29CQUMxRCxHQUFHLEVBQUU7d0JBQ0gsR0FBRyx1QkFBdUIsQ0FBQyxHQUFHO3dCQUM5QixDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsRUFBRTs0QkFDL0UsY0FBYyxFQUFFLGlCQUFpQjs0QkFDakMsWUFBWSxFQUFFLGdCQUFnQjt5QkFDL0IsQ0FBUTtxQkFDVjtpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUVELGdCQUFnQjtZQUNoQixxQkFBcUI7WUFDckIsTUFBTSx3QkFBd0IsR0FBRyxNQUFNLGFBQWEsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLHdCQUF3QixDQUFDLENBQUM7WUFFdEcsZ0JBQWdCO1lBQ2hCLElBQUksdUJBQWdELENBQUM7WUFDckQsQ0FBQztnQkFDQyxNQUFNLENBQUMsRUFBRSxDQUFDLHdCQUF3QixDQUFDLEtBQUssS0FBSyxDQUFDLEVBQUUsNENBQTRDLENBQUMsQ0FBQztnQkFDOUYsTUFBTSx1QkFBdUIsR0FBRyxNQUFNLHVCQUFTLENBQUMsZ0NBQWdDLENBQzlFO29CQUNFLFdBQVcsRUFBRTt3QkFDWCx3QkFBd0IsQ0FBQyxHQUFHLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxZQUFZO3dCQUMzRCx3QkFBd0IsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYztxQkFDdkU7b0JBQ0QsaUJBQWlCLEVBQUUsRUFBRTtpQkFDdEIsRUFDRCxDQUFDLGNBQWMsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLHdCQUF3QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQ2xHLENBQUMsYUFBYSxDQUFDLENBQ2hCLENBQUM7Z0JBQ0YsTUFBTSxzQkFBc0IsR0FBRyxXQUFXLENBQUMsc0JBQXNCLENBQUM7b0JBQ2hFLFdBQVcsRUFBRSx1QkFBdUIsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLHVCQUFTLENBQUMscUJBQXFCLENBQUM7b0JBQ3JGLGlCQUFpQixFQUFFLEVBQUU7aUJBQ3RCLENBQUMsQ0FBQyxXQUFXLENBQUM7Z0JBRWYsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLHVCQUFTLENBQUMsOEJBQThCLENBQ3hFLHVCQUFTLENBQUMsaUJBQWlCLENBQUM7b0JBQzFCLFdBQVcsRUFBRSxzQkFBc0I7b0JBQ25DLGlCQUFpQixFQUFFLEVBQUU7aUJBQ3RCLENBQUMsRUFDRixDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsd0JBQXdCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsY0FBYyxDQUFDLEVBQ2xHLENBQUMsYUFBYSxDQUFDLENBQ2hCLENBQUM7Z0JBRUYsTUFBTSxlQUFlLEdBQUcsbUJBQW1CLENBQUMsV0FBVyxDQUFDLElBQUksQ0FDMUQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUsscUJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FDakcsQ0FBQztnQkFDRixNQUFNLENBQUMsRUFBRSxDQUFDLGVBQWUsRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO2dCQUN4RCxNQUFNLGdCQUFnQixHQUFHLG1CQUFtQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQzNELENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLHFCQUFVLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFLEtBQUsscUJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQ2xHLENBQUM7Z0JBQ0YsTUFBTSxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSw0QkFBNEIsQ0FBQyxDQUFDO2dCQUUxRCx1QkFBdUIsR0FBRztvQkFDeEIsR0FBRyx3QkFBd0I7b0JBQzNCLEtBQUssRUFBRSx3Q0FBeUIsQ0FBQyx3QkFBd0I7b0JBQ3pELEdBQUcsRUFBRTt3QkFDSCxHQUFHLHdCQUF3QixDQUFDLEdBQUc7d0JBQy9CLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFOzRCQUNoRixjQUFjLEVBQUUsZUFBZTs0QkFDL0IsWUFBWSxFQUFFLGdCQUFnQjt5QkFDL0IsQ0FBUTtxQkFDVjtpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUVELGlCQUFpQjtZQUNqQixJQUFJLHVCQUFnRCxDQUFDO1lBQ3JELENBQUM7Z0JBQ0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLEtBQUssQ0FBQyxFQUFFLDJDQUEyQyxDQUFDLENBQUM7Z0JBQzVGLE1BQU0seUJBQXlCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUNoRjtvQkFDRSxXQUFXLEVBQUU7d0JBQ1gsdUJBQXVCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWTt3QkFDMUQsdUJBQXVCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWM7cUJBQ3RFO29CQUNELGlCQUFpQixFQUFFLEVBQUU7aUJBQ3RCLEVBQ0QsQ0FBQyxjQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUNqRyxDQUFDLGVBQWUsQ0FBQyxDQUNsQixDQUFDO2dCQUVGLE1BQU0sdUJBQXVCLEdBQUcsYUFBYSxDQUFDLHNCQUFzQixDQUFDO29CQUNuRSxXQUFXLEVBQUUseUJBQXlCLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyx1QkFBUyxDQUFDLHFCQUFxQixDQUFDO29CQUN2RixpQkFBaUIsRUFBRSxFQUFFO2lCQUN0QixDQUFDLENBQUM7Z0JBRUgsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLHVCQUFTLENBQUMsOEJBQThCLENBQ3pFLHVCQUFTLENBQUMsaUJBQWlCLENBQUMsdUJBQXVCLENBQUMsRUFDcEQsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLHVCQUF1QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLGNBQWMsQ0FBQyxFQUNqRyxDQUFDLGVBQWUsQ0FBQyxDQUNsQixDQUFDO2dCQUVGLE1BQU0saUJBQWlCLEdBQUcsb0JBQW9CLENBQUMsV0FBVyxDQUFDLElBQUksQ0FDN0QsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUsscUJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FDbkcsQ0FBQztnQkFDRixNQUFNLENBQUMsRUFBRSxDQUFDLGlCQUFpQixFQUFFLDZCQUE2QixDQUFDLENBQUM7Z0JBQzVELE1BQU0sZ0JBQWdCLEdBQUcsb0JBQW9CLENBQUMsV0FBVyxDQUFDLElBQUksQ0FDNUQsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUsscUJBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLEVBQUUsS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FDbEcsQ0FBQztnQkFDRixNQUFNLENBQUMsRUFBRSxDQUFDLGdCQUFnQixFQUFFLDRCQUE0QixDQUFDLENBQUM7Z0JBRTFELE1BQU0sc0JBQXNCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUM3RTtvQkFDRSxXQUFXLEVBQUU7d0JBQ1g7NEJBQ0UsR0FBRyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxZQUFZOzRCQUM3RCxVQUFVLEVBQUUsdUJBQXVCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxDQUFDLFVBQVU7eUJBQ2xGO3dCQUNEOzRCQUNFLEdBQUcsdUJBQXVCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWM7NEJBQ3hFLFVBQVUsRUFBRSx1QkFBdUIsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCO3lCQUM5RDtxQkFDRjtvQkFDRCxpQkFBaUIsRUFBRSxFQUFFO2lCQUN0QixFQUNELENBQUMsY0FBYyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsdUJBQXVCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsRUFDakcsQ0FBQyxlQUFlLENBQUMsQ0FDbEIsQ0FBQztnQkFFRixNQUFNLG9CQUFvQixHQUFHLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQztvQkFDaEUsV0FBVyxFQUFFLHNCQUFzQixDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsdUJBQVMsQ0FBQyxxQkFBcUIsQ0FBQztvQkFDcEYsaUJBQWlCLEVBQUUsRUFBRTtpQkFDdEIsQ0FBQyxDQUFDLGlCQUFpQixDQUFDO2dCQUVyQixNQUFNLDZCQUE2QixHQUFHLE1BQU0sdUJBQVMsQ0FBQyw4QkFBOEIsQ0FDbEYsdUJBQVMsQ0FBQyxpQkFBaUIsQ0FBQztvQkFDMUIsV0FBVyxFQUFFLEVBQUU7b0JBQ2YsaUJBQWlCLEVBQUUsb0JBQW9CO2lCQUN4QyxDQUFDLEVBQ0YsRUFBRSxFQUNGLENBQUMsZUFBZSxDQUFDLENBQ2xCLENBQUM7Z0JBRUYsTUFBTSxVQUFVLEdBQUcsNkJBQTZCLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUNyRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FDckQsQ0FBQztnQkFDRixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO2dCQUU5Qyx1QkFBdUIsR0FBRztvQkFDeEIsR0FBRyx1QkFBdUI7b0JBQzFCLEtBQUssRUFBRSx3Q0FBeUIsQ0FBQyx5QkFBeUI7b0JBQzFELEdBQUcsRUFBRTt3QkFDSCxHQUFHLHVCQUF1QixDQUFDLEdBQUc7d0JBQzlCLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLHVCQUF1QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFOzRCQUMvRSxZQUFZLEVBQUUsZ0JBQWdCOzRCQUM5QixjQUFjLEVBQUUsaUJBQWlCOzRCQUNqQyxPQUFPLEVBQUUsVUFBVTt5QkFDcEIsQ0FBUTtxQkFDVjtpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUVELGdCQUFnQjtZQUNoQixJQUFJLHlCQUFtRCxDQUFDO1lBQ3hELENBQUM7Z0JBQ0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLEtBQUssQ0FBQyxFQUFFLDJDQUEyQyxDQUFDLENBQUM7Z0JBQzVGLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUMzRTtvQkFDRSxXQUFXLEVBQUU7d0JBQ1g7NEJBQ0UsR0FBRyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxZQUFZOzRCQUM3RCxVQUFVLEVBQUUsdUJBQXVCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsWUFBWSxDQUFDLFVBQVU7eUJBQ2xGO3dCQUNEOzRCQUNFLEdBQUcsdUJBQXVCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLGNBQWM7NEJBQ3hFLFVBQVUsRUFBRSx1QkFBdUIsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCO3lCQUM5RDtxQkFDRjtvQkFDRCxpQkFBaUIsRUFBRSxFQUFFO2lCQUN0QixFQUNELENBQUMsY0FBYyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsdUJBQXVCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsRUFDakcsQ0FBQyxhQUFhLENBQUMsQ0FDaEIsQ0FBQztnQkFFRixNQUFNLDJCQUEyQixHQUFHLFdBQVcsQ0FBQyxzQkFBc0IsQ0FBQztvQkFDckUsV0FBVyxFQUFFLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsdUJBQVMsQ0FBQyxxQkFBcUIsQ0FBQztvQkFDbEYsaUJBQWlCLEVBQUUsRUFBRTtpQkFDdEIsQ0FBQyxDQUFDLGlCQUFpQixDQUFDO2dCQUNyQixNQUFNLENBQUMsRUFBRSxDQUFDLDJCQUEyQixDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsZ0RBQWdELENBQUMsQ0FBQztnQkFFdEcsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLHVCQUFTLENBQUMsOEJBQThCLENBQ3ZFLHVCQUFTLENBQUMsaUJBQWlCLENBQUM7b0JBQzFCLFdBQVcsRUFBRSxFQUFFO29CQUNmLGlCQUFpQixFQUFFLDJCQUEyQjtpQkFDL0MsQ0FBQyxFQUNGLEVBQUUsRUFDRixDQUFDLGFBQWEsQ0FBQyxDQUNoQixDQUFDO2dCQUVGLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxxQkFBVSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUMvRyxNQUFNLENBQUMsRUFBRSxDQUFDLFFBQVEsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO2dCQUUxQyx5QkFBeUIsR0FBRztvQkFDMUIsR0FBRyx1QkFBdUI7b0JBQzFCLEtBQUssRUFBRSx3Q0FBeUIsQ0FBQyx5QkFBeUI7b0JBQzFELEdBQUcsRUFBRTt3QkFDSCxHQUFHLHVCQUF1QixDQUFDLEdBQUc7d0JBQzlCLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLHVCQUF1QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxFQUFFOzRCQUMvRSxPQUFPLEVBQUUsUUFBUTt5QkFDbEIsQ0FBUTtxQkFDVjtpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUVELGdCQUFnQjtZQUNoQix5QkFBeUI7WUFDekIsTUFBTSx3QkFBd0IsR0FBRyxNQUFNLGFBQWEsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLHlCQUF5QixDQUFDLENBQUM7WUFFdkcsZUFBZTtZQUNmLElBQUksa0JBQTBCLENBQUM7WUFDL0IsSUFBSSx1QkFBdUIsQ0FBQztZQUM1QixDQUFDO2dCQUNDLE1BQU0sQ0FBQyxFQUFFLENBQUMsd0JBQXdCLENBQUMsS0FBSyxLQUFLLENBQUMsRUFBRSw0Q0FBNEMsQ0FBQyxDQUFDO2dCQUM5RixNQUFNLENBQUMsRUFBRSxDQUFDLHdCQUF3QixDQUFDLFVBQVUsRUFBRSwrQ0FBK0MsQ0FBQyxDQUFDO2dCQUNoRyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyxnQ0FBZ0MsQ0FDM0U7b0JBQ0UsV0FBVyxFQUFFLEVBQUU7b0JBQ2YsaUJBQWlCLEVBQUU7d0JBQ2pCLHdCQUF3QixDQUFDLEdBQUcsQ0FBQywyQkFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU87d0JBQ3RELHdCQUF3QixDQUFDLFFBQVEsQ0FBQyxTQUFTO3FCQUM1QztpQkFDRixFQUNELENBQUMsY0FBYyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsd0JBQXdCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUMsRUFDbEcsQ0FBQyxhQUFhLENBQUMsQ0FDaEIsQ0FBQztnQkFFRixXQUFXLENBQUMsc0JBQXNCLENBQUM7b0JBQ2pDLFdBQVcsRUFBRSxFQUFFO29CQUNmLGlCQUFpQixFQUFFLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyx1QkFBUyxDQUFDLDJCQUEyQixDQUFDO2lCQUNyRyxDQUFDLENBQUM7Z0JBRUgsTUFBTSxtQkFBbUIsR0FBRyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ3RELGtCQUFrQixHQUFHLHVCQUFTLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztnQkFDdEUsTUFBTSxDQUFDLEtBQUssQ0FDVix3QkFBd0IsQ0FBQyxRQUFRLENBQUMsY0FBYyxFQUNoRCxrQkFBa0IsRUFDbEIsOENBQThDLENBQy9DLENBQUM7Z0JBQ0YsTUFBTSxPQUFPLEdBQUcsbUJBQW1CLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUN2RCxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO2dCQUV4Qyx1QkFBdUIsR0FBRztvQkFDeEIsVUFBVSxFQUFFLHdCQUF3QixDQUFDLFVBQVU7b0JBQy9DLEdBQUcsd0JBQXdCO29CQUMzQixLQUFLLEVBQUUsd0NBQXlCLENBQUMseUJBQXlCO2lCQUMzRCxDQUFDO1lBQ0osQ0FBQztZQUVELGlCQUFpQjtZQUNqQixJQUFJLG9CQUE0QixDQUFDO1lBQ2pDLENBQUM7Z0JBQ0MsTUFBTSxDQUFDLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLEtBQUssRUFBRSxFQUFFLDRDQUE0QyxDQUFDLENBQUM7Z0JBQzlGLE1BQU0sQ0FBQyxFQUFFLENBQUMsdUJBQXVCLENBQUMsVUFBVSxFQUFFLDhDQUE4QyxDQUFDLENBQUM7Z0JBRTlGLE1BQU0sc0JBQXNCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUM3RTtvQkFDRSxXQUFXLEVBQUUsRUFBRTtvQkFDZixpQkFBaUIsRUFBRTt3QkFDakIsdUJBQXVCLENBQUMsR0FBRyxDQUFDLDJCQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTzt3QkFDckQsdUJBQXVCLENBQUMsUUFBUSxDQUFDLFNBQVM7cUJBQzNDO2lCQUNGLEVBQ0QsQ0FBQyxjQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsMkJBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxFQUNqRyxDQUFDLGVBQWUsQ0FBQyxDQUNsQixDQUFDO2dCQUVGLGFBQWEsQ0FBQyxzQkFBc0IsQ0FBQztvQkFDbkMsV0FBVyxFQUFFLEVBQUU7b0JBQ2YsaUJBQWlCLEVBQUUsc0JBQXNCLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLHVCQUFTLENBQUMsMkJBQTJCLENBQUM7aUJBQ3ZHLENBQUMsQ0FBQztnQkFFSCxNQUFNLHFCQUFxQixHQUFHLGFBQWEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDMUQsb0JBQW9CLEdBQUcsdUJBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO2dCQUMxRSxNQUFNLENBQUMsS0FBSyxDQUNWLHVCQUF1QixDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQy9DLG9CQUFvQixFQUNwQixnREFBZ0QsQ0FDakQsQ0FBQztnQkFDRixNQUFNLFNBQVMsR0FBRyxxQkFBcUIsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBQzNELE1BQU0sQ0FBQyxFQUFFLENBQUMsU0FBUyxFQUFFLHFCQUFxQixDQUFDLENBQUM7WUFDOUMsQ0FBQztZQUVELGdCQUFnQjtZQUNoQixtQ0FBbUM7WUFDbkMsTUFBTSxTQUFTLEdBQUcsTUFBTSxhQUFhLENBQUMsZ0JBQWdCLENBQ3BELHdCQUF3QixDQUFDLFVBQVUsRUFDbkMsa0JBQWtCLEVBQ2xCLG9CQUFvQixDQUNyQixDQUFDO1lBQ0YsTUFBTSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFO2dCQUN2QyxjQUFjLEVBQUUsa0JBQWtCO2dCQUNsQyxJQUFJLEVBQUUsS0FBSztnQkFDWCxNQUFNLEVBQUUsTUFBTTtnQkFDZCxFQUFFLEVBQUUsTUFBTTthQUNYLENBQUMsQ0FBQztZQUNILE1BQU0sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRTtnQkFDekMsY0FBYyxFQUFFLG9CQUFvQjtnQkFDcEMsSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsTUFBTSxFQUFFLFFBQVE7Z0JBQ2hCLEVBQUUsRUFBRSxRQUFRO2FBQ2IsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvQixNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7WUFDL0IsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNqQyxDQUFDLENBQUMsQ0FBQztRQUVILEVBQUUsQ0FBQywwREFBMEQsRUFBRSxLQUFLO1lBQ2xFLE1BQU0sYUFBYSxHQUFHLElBQUkscUJBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3BFLE1BQU0sY0FBYyxHQUFHO2dCQUNyQixLQUFLLEVBQUUsd0NBQXlCLENBQUMsd0JBQXdCO2FBQ25ELENBQUM7WUFFVCxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxNQUFNLGFBQWEsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLGNBQWMsQ0FBQyxFQUFFO2dCQUMzRixPQUFPLEVBQUUsd0NBQXdDLHdDQUF5QixDQUFDLHlCQUF5QixVQUFVLHdDQUF5QixDQUFDLHdCQUF3QixFQUFFO2FBQ25LLENBQUMsQ0FBQztZQUNILE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLE1BQU0sYUFBYSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsY0FBYyxDQUFDLEVBQUU7Z0JBQzNGLE9BQU8sRUFBRSx3Q0FBd0Msd0NBQXlCLENBQUMseUJBQXlCLFVBQVUsd0NBQXlCLENBQUMsd0JBQXdCLEVBQUU7YUFDbkssQ0FBQyxDQUFDO1lBQ0gsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsTUFBTSxhQUFhLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxjQUFjLENBQUMsRUFBRTtnQkFDM0YsT0FBTyxFQUFFLHdDQUF3Qyx3Q0FBeUIsQ0FBQyx5QkFBeUIsVUFBVSx3Q0FBeUIsQ0FBQyx3QkFBd0IsRUFBRTthQUNuSyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0lBRUgsS0FBSyxVQUFVLFlBQVksQ0FDekIsTUFJQyxFQUNELEtBQUssR0FBRyxDQUFDO1FBRVQsSUFBSSxDQUFDLEtBQUssQ0FBQzthQUNSLElBQUksQ0FBQyxXQUFXLE1BQU0sQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFO1lBQzNDLE9BQU8sSUFBSSxDQUFDLE9BQU8sS0FBSyxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQ2pFLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxLQUFLLENBQUM7YUFDWixLQUFLLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUUvQixPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUM7SUFDekIsQ0FBQztJQUVELEtBQUssVUFBVSx3Q0FBd0MsQ0FDckQsSUFBWSxFQUNaLFlBQW9CLEVBQ3BCLGVBQWtEO1FBRWxELE1BQU0seUJBQXlCLEdBQXNCO1lBQ25ELElBQUksRUFBRSxZQUFZO1lBQ2xCLFNBQVMsRUFBRSxlQUFlLENBQUMsU0FBUztZQUNwQyxjQUFjLEVBQUUsZUFBZSxDQUFDLFNBQVM7WUFDekMsWUFBWTtTQUNiLENBQUM7UUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLFdBQVcsSUFBSSxhQUFhLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUseUJBQXlCLENBQUMsQ0FBQztRQUU1RyxPQUFPLHlCQUF5QixDQUFDO0lBQ25DLENBQUM7SUFFRCxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsWUFBeUIsRUFBRSxLQUFLLEdBQUcsQ0FBQztRQUNsRSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7YUFDZixJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDO2FBQ3BFLEtBQUssQ0FBQyxLQUFLLENBQUM7YUFDWixLQUFLLENBQ0osR0FBRyxFQUNILEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQXlDLEVBQXNDLEVBQUU7WUFDcEcsTUFBTSxFQUFFLGdCQUFnQixFQUFFLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUM7WUFDL0UsYUFBYSxHQUFHO2dCQUNkLE9BQU8sRUFBRSxDQUFDO2dCQUNWLE1BQU0sRUFBRSxnQkFBZ0I7YUFDekIsQ0FBQztZQUNGLGVBQWUsR0FBRztnQkFDaEIsT0FBTyxFQUFFLENBQUM7Z0JBQ1YsTUFBTSxFQUFFLGtCQUFrQjthQUMzQixDQUFDO1lBRUYsTUFBTSwwQkFBMEIsR0FBRyxNQUFNLFlBQVksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoRSxNQUFNLGdCQUFnQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyw4QkFBOEIsQ0FDckUsRUFBRSxpQkFBaUIsRUFBRSxDQUFDLHVCQUFTLENBQUMseUJBQXlCLENBQUMsMEJBQTBCLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsRUFDekcsRUFBRSxFQUNGLENBQUMsY0FBYyxDQUFDLENBQ2pCLENBQUM7WUFDRixNQUFNLFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDL0UsTUFBTSxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUscUJBQXFCLENBQUMsQ0FBQztZQUU1QyxNQUFNLGtCQUFrQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyxnQ0FBZ0MsQ0FDekU7Z0JBQ0UsV0FBVyxFQUFFLEVBQUU7Z0JBQ2YsaUJBQWlCLEVBQUU7b0JBQ2pCLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFO29CQUM5QixFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRTtpQkFDakM7YUFDRixFQUNELENBQUMsYUFBYSxFQUFFLGVBQWUsQ0FBQyxFQUNoQyxDQUFDLGNBQWMsQ0FBQyxDQUNqQixDQUFDO1lBRUYsTUFBTSxjQUFjLEdBQUcsdUJBQVMsQ0FBQyxpQkFBaUIsQ0FDaEQsWUFBWSxDQUFDLHNCQUFzQixDQUFDLHVCQUFTLENBQUMsbUJBQW1CLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUN2RixDQUFDO1lBRUYsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLHVCQUFTLENBQUMsOEJBQThCLENBQ3pFLGNBQWMsRUFDZCxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsRUFDaEMsQ0FBQyxjQUFjLENBQUMsQ0FDakIsQ0FBQztZQUVGLE1BQU0sZUFBZSxHQUFHLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDakYsTUFBTSxpQkFBaUIsR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ25GLE1BQU0sQ0FBQyxFQUFFLENBQUMsZUFBZSxFQUFFLDJCQUEyQixDQUFDLENBQUM7WUFDeEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSw2QkFBNkIsQ0FBQyxDQUFDO1lBQzVELE1BQU0sQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLFVBQVUsRUFBRSxzQ0FBc0MsQ0FBQyxDQUFDO1lBRTlFLHNCQUFzQixHQUFHLGVBQWUsRUFBRSxVQUFVLENBQUM7WUFDckQsT0FBTztnQkFDTCxTQUFTLEVBQUUsUUFBMEI7Z0JBQ3JDLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBRyxTQUFTLENBQUMsT0FBTyxFQUFFO2dCQUM1QyxpQkFBaUIsRUFBRTtvQkFDakIsSUFBSSxFQUFFLENBQUM7b0JBQ1AsRUFBRSxFQUFFLENBQUM7b0JBQ0wsZ0JBQWdCLEVBQUUsaUJBQWlCLENBQUMsT0FBTyxDQUFDLGdCQUFnQjtvQkFDNUQsU0FBUyxFQUFFLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxTQUFTO2lCQUMvQztnQkFDRCxlQUFlLEVBQUU7b0JBQ2YsSUFBSSxFQUFFLENBQUM7b0JBQ1AsRUFBRSxFQUFFLENBQUM7b0JBQ0wsZ0JBQWdCLEVBQUUsZUFBZSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0I7b0JBQzFELFNBQVMsRUFBRSxlQUFlLENBQUMsT0FBTyxDQUFDLFNBQVM7aUJBQzdDO2dCQUNELG1CQUFtQixFQUFFLFdBQTZCO2FBQ25ELENBQUM7UUFDSixDQUFDLENBQ0YsQ0FBQztJQUNOLENBQUM7SUFFRCxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsWUFBeUIsRUFBRSxLQUFLLEdBQUcsQ0FBQztRQUNsRSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7YUFDZixJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDO2FBQ3BFLEtBQUssQ0FBQyxLQUFLLENBQUM7YUFDWixLQUFLLENBQ0osR0FBRyxFQUNILEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQXlDLEVBQXNDLEVBQUU7WUFDcEcsTUFBTSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxHQUFHLE9BQU8sQ0FBQztZQUN4RixxQkFBcUIsR0FBRyxlQUFlLENBQUM7WUFDeEMsdUJBQXVCLEdBQUcsaUJBQWlCLENBQUM7WUFDNUMsTUFBTSxrQkFBa0IsR0FBRyxNQUFNLHVCQUFTLENBQUMsZ0NBQWdDLENBQ3pFO2dCQUNFLFdBQVcsRUFBRTtvQkFDWDt3QkFDRSxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUk7d0JBQ25CLEVBQUUsRUFBRSxRQUFRLENBQUMsRUFBRTt3QkFDZixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7cUJBQ3hGO29CQUNEO3dCQUNFLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTt3QkFDckIsRUFBRSxFQUFFLFVBQVUsQ0FBQyxFQUFFO3dCQUNqQixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLENBQUMsZ0JBQWdCLEVBQUU7cUJBQzVGO2lCQUNGO2dCQUNELGlCQUFpQixFQUFFLEVBQUU7YUFDdEIsRUFDRCxDQUFDLGFBQWEsRUFBRSxlQUFlLENBQUMsRUFDaEMsQ0FBQyxjQUFjLENBQUMsQ0FDakIsQ0FBQztZQUVGLE1BQU0sY0FBYyxHQUFHLHVCQUFTLENBQUMsaUJBQWlCLENBQ2hELFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyx1QkFBUyxDQUFDLG1CQUFtQixDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FDdkYsQ0FBQztZQUVGLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSx1QkFBUyxDQUFDLDhCQUE4QixDQUN6RSxjQUFjLEVBQ2QsQ0FBQyxhQUFhLEVBQUUsZUFBZSxDQUFDLEVBQ2hDLENBQUMsY0FBYyxDQUFDLENBQ2pCLENBQUM7WUFFRixNQUFNLGVBQWUsR0FBRyxvQkFBb0IsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ2pGLE1BQU0saUJBQWlCLEdBQUcsb0JBQW9CLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUNuRixNQUFNLENBQUMsRUFBRSxDQUFDLGVBQWUsRUFBRSwyQkFBMkIsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxFQUFFLENBQUMsaUJBQWlCLEVBQUUsNkJBQTZCLENBQUMsQ0FBQztZQUU1RCxPQUFPO2dCQUNMLFNBQVM7Z0JBQ1QsZ0JBQWdCLEVBQUUsc0JBQXdDO2dCQUMxRCxlQUFlLEVBQUU7b0JBQ2YsSUFBSSxFQUFFLENBQUM7b0JBQ1AsRUFBRSxFQUFFLENBQUM7b0JBQ0wsZ0JBQWdCLEVBQUUsZUFBZSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0I7b0JBQzFELFNBQVMsRUFBRSxlQUFlLENBQUMsT0FBTyxDQUFDLFNBQVM7aUJBQzdDO2dCQUNELGlCQUFpQixFQUFFO29CQUNqQixJQUFJLEVBQUUsQ0FBQztvQkFDUCxFQUFFLEVBQUUsQ0FBQztvQkFDTCxnQkFBZ0IsRUFBRSxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCO29CQUM1RCxTQUFTLEVBQUUsaUJBQWlCLENBQUMsT0FBTyxDQUFDLFNBQVM7aUJBQy9DO2FBQ0YsQ0FBQztRQUNKLENBQUMsQ0FDRixDQUFDO0lBQ04sQ0FBQztJQUVELEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxZQUF5QixFQUFFLEtBQUssR0FBRyxDQUFDO1FBQ2xFLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQzthQUNmLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssS0FBSyxVQUFVLENBQUM7YUFDcEUsS0FBSyxDQUFDLEtBQUssQ0FBQzthQUNaLEtBQUssQ0FDSixHQUFHLEVBQ0gsS0FBSyxFQUFFLEdBQUcsRUFBRSxFQUFFLE9BQU8sRUFBeUMsRUFBc0MsRUFBRTtZQUNwRyxNQUFNLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQztZQUUxRSxNQUFNLGtCQUFrQixHQUFHLE1BQU0sdUJBQVMsQ0FBQyxnQ0FBZ0MsQ0FDekU7Z0JBQ0UsV0FBVyxFQUFFO29CQUNYO3dCQUNFLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTt3QkFDbkIsRUFBRSxFQUFFLFFBQVEsQ0FBQyxFQUFFO3dCQUNmLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUyxFQUFFLGdCQUFnQixFQUFFLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRTt3QkFDdkYsVUFBVSxFQUFFLHFCQUFxQjtxQkFDbEM7b0JBQ0Q7d0JBQ0UsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO3dCQUNyQixFQUFFLEVBQUUsVUFBVSxDQUFDLEVBQUU7d0JBQ2pCLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxVQUFVLENBQUMsU0FBUyxFQUFFLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxnQkFBZ0IsRUFBRTt3QkFDM0YsVUFBVSxFQUFFLHVCQUF1QjtxQkFDcEM7aUJBQ0Y7Z0JBQ0QsaUJBQWlCLEVBQUUsRUFBRTthQUN0QixFQUNELENBQUMsYUFBYSxFQUFFLGVBQWUsQ0FBQyxFQUNoQyxDQUFDLGNBQWMsQ0FBQyxDQUNqQixDQUFDO1lBRUYsTUFBTSxjQUFjLEdBQUcsdUJBQVMsQ0FBQyxpQkFBaUIsQ0FDaEQsWUFBWSxDQUFDLHNCQUFzQixDQUFDLHVCQUFTLENBQUMsbUJBQW1CLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUN2RixDQUFDO1lBQ0YsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLHVCQUFTLENBQUMsOEJBQThCLENBQ3pFLGNBQWMsRUFDZCxFQUFFLEVBQ0YsQ0FBQyxjQUFjLENBQUMsQ0FDakIsQ0FBQztZQUNGLE1BQU0sU0FBUyxHQUFHLG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQztZQUNuRixNQUFNLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1lBRTVDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUN6RTtnQkFDRSxXQUFXLEVBQUUsRUFBRTtnQkFDZixpQkFBaUIsRUFBRTtvQkFDakI7d0JBQ0UsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJO3dCQUNuQixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU8sRUFBRTtxQkFDdEU7b0JBQ0Q7d0JBQ0UsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO3dCQUVyQixPQUFPLEVBQUUsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLE9BQU8sRUFBRTtxQkFDMUU7aUJBQ0Y7YUFDRixFQUNELENBQUMsYUFBYSxFQUFFLGVBQWUsQ0FBQyxFQUNoQyxFQUFFLENBQ0gsQ0FBQztZQUNGLFlBQVksQ0FBQyxzQkFBc0IsQ0FBQyx1QkFBUyxDQUFDLG1CQUFtQixDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztZQUN2RixNQUFNLFFBQVEsR0FBRyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDNUMsTUFBTSxjQUFjLEdBQUcsdUJBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUU3RCxPQUFPO2dCQUNMLFNBQVM7Z0JBQ1QsY0FBYyxFQUFFLGNBQWdDO2dCQUNoRCxTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLEdBQUcsU0FBUyxDQUFDLE9BQU8sRUFBRTthQUM3QyxDQUFDO1FBQ0osQ0FBQyxDQUNGLENBQUM7SUFDTixDQUFDO0lBRUQsS0FBSyxVQUFVLGVBQWUsQ0FBQyxJQUFZLEVBQUUsS0FBSyxHQUFHLENBQUM7UUFDcEQsT0FBTyxJQUFJLENBQUMsdUJBQXVCLENBQUM7YUFDakMsSUFBSSxDQUFDLFdBQVcsSUFBSSxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUM7YUFDN0UsS0FBSyxDQUFDLEtBQUssQ0FBQzthQUNaLEtBQUssQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxXQUErQixFQUFFLEVBQUU7WUFDekQsTUFBTSxHQUFHLEdBQUc7Z0JBQ1YsRUFBRSxFQUFFLFdBQVcsQ0FBQyxNQUFNO2dCQUN0QixNQUFNLEVBQUUsV0FBVyxDQUFDLE1BQU07Z0JBQzFCLElBQUksRUFBRSxXQUFXLENBQUMsT0FBTztnQkFDekIsY0FBYyxFQUFFLFdBQVcsQ0FBQyxjQUFjO2dCQUMxQyxZQUFZLEVBQUUsV0FBVyxDQUFDLFlBQVk7YUFDdkMsQ0FBQztZQUNGLFlBQVk7WUFDWixJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxHQUFHLENBQUMsV0FBVyxJQUFJLFFBQVEsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUMvRixPQUFPLEdBQUcsQ0FBQztRQUNiLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztBQUNILENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXNzZXJ0IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgbm9jayA9IHJlcXVpcmUoJ25vY2snKTtcbmltcG9ydCAqIGFzIG9wZW5wZ3AgZnJvbSAnb3BlbnBncCc7XG5pbXBvcnQgKiBhcyBjcnlwdG8gZnJvbSAnY3J5cHRvJztcblxuaW1wb3J0IHsgVGVzdGFibGVCRywgVGVzdEJpdEdvIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCB7IEFkZEtleWNoYWluT3B0aW9ucywgQmFzZUNvaW4sIGNvbW1vbiwgRUNEU0FVdGlscywgS2V5Y2hhaW4sIFdhbGxldCB9IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBiaWdJbnRUb0J1ZmZlckJFLCBEa2xzQ29tbXMsIERrbHNEa2csIERrbHNEc2csIERrbHNUeXBlcywgRGtsc1V0aWxzIH0gZnJvbSAnQGJpdGdvL3Nkay1saWItbXBjJztcbmltcG9ydCB7XG4gIEtleUNyZWF0aW9uTVBDdjJTdGF0ZUVudW0sXG4gIE1QQ3YyS2V5R2VuUm91bmQxUmVxdWVzdCxcbiAgTVBDdjJLZXlHZW5Sb3VuZDFSZXNwb25zZSxcbiAgTVBDdjJLZXlHZW5Sb3VuZDJSZXF1ZXN0LFxuICBNUEN2MktleUdlblJvdW5kMlJlc3BvbnNlLFxuICBNUEN2MktleUdlblJvdW5kM1JlcXVlc3QsXG4gIE1QQ3YyS2V5R2VuUm91bmQzUmVzcG9uc2UsXG4gIE9WQzFUb0JpdGdvUm91bmQzUGF5bG9hZCxcbiAgT1ZDMVRvT1ZDMlJvdW5kMVBheWxvYWQsXG4gIE9WQzFUb09WQzJSb3VuZDJQYXlsb2FkLFxuICBPVkMxVG9PVkMyUm91bmQzUGF5bG9hZCxcbiAgT1ZDMlRvQml0Z29Sb3VuZDFQYXlsb2FkLFxuICBPVkMyVG9CaXRnb1JvdW5kMlBheWxvYWQsXG4gIE9WQzJUb09WQzFSb3VuZDNQYXlsb2FkLFxuICBPVkNJbmRleEVudW0sXG4gIFdhbGxldFR5cGVFbnVtLFxufSBmcm9tICdAYml0Z28vcHVibGljLXR5cGVzJztcbmltcG9ydCB7IE5vbkVtcHR5U3RyaW5nIH0gZnJvbSAnaW8tdHMtdHlwZXMnO1xuaW1wb3J0IHsgQml0R28sIEJpdGdvR1BHUHVibGljS2V5IH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vLi4vc3JjJztcbmltcG9ydCAqIGFzIHYxRml4dHVyZXMgZnJvbSAnLi9maXh0dXJlcy9tcGN2MUtleVNoYXJlcyc7XG5cbmRlc2NyaWJlKCdUU1MgRWNkc2EgTVBDdjIgVXRpbHM6JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICBjb25zdCBjb2luTmFtZSA9ICdodGV0aCc7XG4gIGNvbnN0IHdhbGxldElkID0gJzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwJztcbiAgY29uc3QgZW50ZXJwcmlzZUlkID0gJzY0NDkxNTNhNmY2YmMyMDAwNmQ2Njc3MWNkYmUxNWQzJztcbiAgbGV0IHN0b3JlZFVzZXJDb21taXRtZW50Mjogc3RyaW5nO1xuICBsZXQgc3RvcmVkQmFja3VwQ29tbWl0bWVudDI6IHN0cmluZztcbiAgbGV0IHN0b3JlZEJpdGdvQ29tbWl0bWVudDI6IHN0cmluZztcblxuICBsZXQgYmdVcmw6IHN0cmluZztcbiAgbGV0IHRzc1V0aWxzOiBFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscztcbiAgbGV0IHdhbGxldDogV2FsbGV0O1xuICBsZXQgYml0Z286IFRlc3RhYmxlQkcgJiBCaXRHbztcbiAgbGV0IGJhc2VDb2luOiBCYXNlQ29pbjtcbiAgbGV0IGJpdEdvR2dwS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz4gJiB7XG4gICAgcmV2b2NhdGlvbkNlcnRpZmljYXRlOiBzdHJpbmc7XG4gIH07XG4gIGxldCBjb25zdGFudHM6IHsgbXBjOiB7IGJpdGdvUHVibGljS2V5OiBzdHJpbmc7IGJpdGdvTVBDdjJQdWJsaWNLZXk6IHN0cmluZyB9IH07XG4gIGxldCBiaXRnb0dwZ1BydktleTogeyBwYXJ0eUlkOiBudW1iZXI7IGdwZ0tleTogc3RyaW5nIH07XG4gIGxldCB1c2VyR3BnUHViS2V5OiB7IHBhcnR5SWQ6IG51bWJlcjsgZ3BnS2V5OiBzdHJpbmcgfTtcbiAgbGV0IGJhY2t1cEdwZ1B1YktleTogeyBwYXJ0eUlkOiBudW1iZXI7IGdwZ0tleTogc3RyaW5nIH07XG4gIGxldCBiaXRnb0dwZ1B1YktleTogeyBwYXJ0eUlkOiBudW1iZXI7IGdwZ0tleTogc3RyaW5nIH07XG5cbiAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICAgIGF3YWl0IG5vY2tHZXRCaXRnb1B1YmxpY0tleUJhc2VkT25GZWF0dXJlRmxhZ3MoY29pbk5hbWUsIGVudGVycHJpc2VJZCwgYml0R29HZ3BLZXkpO1xuICAgIG5vY2soYmdVcmwpLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJykudGltZXMoMTYpLnJlcGx5KDIwMCwgeyB0dGw6IDM2MDAsIGNvbnN0YW50cyB9KTtcbiAgfSk7XG5cbiAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBBbGxvdyBzZWNwMjU2azEgR1BHIGtleXMgdXNlZCBieSB0aGVzZSBmaXh0dXJlcyAodGhlIGZ1bGwgc3VpdGUgZW5hYmxlcyB0aGlzXG4gICAgLy8gZ2xvYmFsbHkgdmlhIHNpYmxpbmcgdGVzdCBmaWxlczsgc2V0IGl0IGhlcmUgc28gdGhpcyBmaWxlIGFsc28gcnVucyBpbiBpc29sYXRpb24pLlxuICAgIG9wZW5wZ3AuY29uZmlnLnJlamVjdEN1cnZlcyA9IG5ldyBTZXQoKTtcbiAgICBiaXRHb0dncEtleSA9IGF3YWl0IG9wZW5wZ3AuZ2VuZXJhdGVLZXkoe1xuICAgICAgdXNlcklEczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogJ2JpdGdvJyxcbiAgICAgICAgICBlbWFpbDogJ2JpdGdvQHRlc3QuY29tJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBjdXJ2ZTogJ3NlY3AyNTZrMScsXG4gICAgfSk7XG4gICAgY29uc3RhbnRzID0ge1xuICAgICAgbXBjOiB7XG4gICAgICAgIGJpdGdvUHVibGljS2V5OiBiaXRHb0dncEtleS5wdWJsaWNLZXksXG4gICAgICAgIGJpdGdvTVBDdjJQdWJsaWNLZXk6IGJpdEdvR2dwS2V5LnB1YmxpY0tleSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGJpdGdvR3BnUHViS2V5ID0ge1xuICAgICAgcGFydHlJZDogMixcbiAgICAgIGdwZ0tleTogYml0R29HZ3BLZXkucHVibGljS2V5LFxuICAgIH07XG5cbiAgICBiaXRnb0dwZ1BydktleSA9IHtcbiAgICAgIHBhcnR5SWQ6IDIsXG4gICAgICBncGdLZXk6IGJpdEdvR2dwS2V5LnByaXZhdGVLZXksXG4gICAgfTtcblxuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuXG4gICAgYmFzZUNvaW4gPSBiaXRnby5jb2luKGNvaW5OYW1lKTtcblxuICAgIGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuXG4gICAgY29uc3Qgd2FsbGV0RGF0YSA9IHtcbiAgICAgIGlkOiB3YWxsZXRJZCxcbiAgICAgIGVudGVycHJpc2U6IGVudGVycHJpc2VJZCxcbiAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgY29pblNwZWNpZmljOiB7fSxcbiAgICAgIG11bHRpc2lnVHlwZTogJ3RzcycsXG4gICAgfTtcbiAgICB3YWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwgd2FsbGV0RGF0YSk7XG4gICAgdHNzVXRpbHMgPSBuZXcgRUNEU0FVdGlscy5FY2RzYU1QQ3YyVXRpbHMoYml0Z28sIGJhc2VDb2luLCB3YWxsZXQpO1xuICB9KTtcblxuICBhZnRlcihmdW5jdGlvbiAoKSB7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICB9KTtcblxuICBkZXNjcmliZSgnUmV0cm9maXQgTVBDdjEgdG8gTVBDdjIga2V5cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIFRTUyBNUEN2MiBrZXlzIGZyb20gTVBDdjEga2V5cyBhbmQgc2lnbiBhIG1lc3NhZ2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByZXRyb2ZpdERhdGEgPSB0c3NVdGlscy5nZXRNcGNWMlJldHJvZml0RGF0YUZyb21NcGNWMUtleXMoe1xuICAgICAgICBtcGN2MVVzZXJLZXlTaGFyZTogSlNPTi5zdHJpbmdpZnkodjFGaXh0dXJlcy5tb2NrVXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICAgIG1wY3YxQmFja3VwS2V5U2hhcmU6IEpTT04uc3RyaW5naWZ5KHYxRml4dHVyZXMubW9ja0JhY2t1cFNpZ25pbmdNYXRlcmlhbCksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGJpdGdvUmV0cm9maXREYXRhOiBEa2xzVHlwZXMuUmV0cm9maXREYXRhID0ge1xuICAgICAgICB4aUxpc3Q6IHJldHJvZml0RGF0YS5tcGN2MlVzZXJLZXlTaGFyZS54aUxpc3QsXG4gICAgICAgIHhTaGFyZTogdjFGaXh0dXJlcy5tb2NrQml0R29TaGFyZVNpZ25pbmdNYXRlcmlhbC54U2hhcmUsXG4gICAgICB9O1xuICAgICAgY29uc3QgW3VzZXIsIGJhY2t1cCwgYml0Z29dID0gYXdhaXQgRGtsc1V0aWxzLmdlbmVyYXRlREtHS2V5U2hhcmVzKFxuICAgICAgICByZXRyb2ZpdERhdGEubXBjdjJVc2VyS2V5U2hhcmUsXG4gICAgICAgIHJldHJvZml0RGF0YS5tcGN2MkJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb1JldHJvZml0RGF0YVxuICAgICAgKTtcbiAgICAgIGFzc2VydC5vayhiaXRnby5nZXRLZXlTaGFyZSgpKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2VUb1NpZ24gPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKEJ1ZmZlci5mcm9tKCdmZmZmJywgJ2hleCcpKS5kaWdlc3QoKTtcbiAgICAgIGNvbnN0IGRlcml2YXRpb25QYXRoID0gJ20vOTk5Lzk4OC8wLzAnO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlID0gYXdhaXQgRGtsc1V0aWxzLmV4ZWN1dGVUaWxsUm91bmQoXG4gICAgICAgIDUsXG4gICAgICAgIG5ldyBEa2xzRHNnLkRzZyh1c2VyLmdldEtleVNoYXJlKCksIDAsIGRlcml2YXRpb25QYXRoLCBtZXNzYWdlVG9TaWduKSxcbiAgICAgICAgbmV3IERrbHNEc2cuRHNnKGJhY2t1cC5nZXRLZXlTaGFyZSgpLCAxLCBkZXJpdmF0aW9uUGF0aCwgbWVzc2FnZVRvU2lnbilcbiAgICAgICk7XG4gICAgICBjb25zdCBjb252ZXJ0ZWRTaWduYXR1cmUgPSBEa2xzVXRpbHMudmVyaWZ5QW5kQ29udmVydERrbHNTaWduYXR1cmUoXG4gICAgICAgIEJ1ZmZlci5mcm9tKCdmZmZmJywgJ2hleCcpLFxuICAgICAgICBzaWduYXR1cmUgYXMgRGtsc1R5cGVzLkRlc2VyaWFsaXplZERrbHNTaWduYXR1cmUsXG4gICAgICAgIHYxRml4dHVyZXMubW9ja0JpdEdvU2hhcmVTaWduaW5nTWF0ZXJpYWwueFNoYXJlLnkgKyB2MUZpeHR1cmVzLm1vY2tCaXRHb1NoYXJlU2lnbmluZ01hdGVyaWFsLnhTaGFyZS5jaGFpbmNvZGUsXG4gICAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgICApO1xuICAgICAgYXNzZXJ0Lm9rKGNvbnZlcnRlZFNpZ25hdHVyZSk7XG4gICAgICBjb252ZXJ0ZWRTaWduYXR1cmUuc3BsaXQoJzonKS5sZW5ndGguc2hvdWxkLmVxdWFsKDQpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVFNTIGtleSBjaGFpbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBUU1MgTVBDdjIga2V5cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGJpdGdvU2Vzc2lvbiA9IG5ldyBEa2xzRGtnLkRrZygzLCAyLCAyKTtcblxuICAgICAgY29uc3Qgcm91bmQxTm9jayA9IGF3YWl0IG5vY2tLZXlHZW5Sb3VuZDEoYml0Z29TZXNzaW9uLCAxKTtcbiAgICAgIGNvbnN0IHJvdW5kMk5vY2sgPSBhd2FpdCBub2NrS2V5R2VuUm91bmQyKGJpdGdvU2Vzc2lvbiwgMSk7XG4gICAgICBjb25zdCByb3VuZDNOb2NrID0gYXdhaXQgbm9ja0tleUdlblJvdW5kMyhiaXRnb1Nlc3Npb24sIDEpO1xuICAgICAgY29uc3QgYWRkS2V5Tm9jayA9IGF3YWl0IG5vY2tBZGRLZXlDaGFpbihjb2luTmFtZSwgMyk7XG4gICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgIHBhc3NwaHJhc2U6ICd0ZXN0JyxcbiAgICAgICAgZW50ZXJwcmlzZTogZW50ZXJwcmlzZUlkLFxuICAgICAgICBvcmlnaW5hbFBhc3Njb2RlRW5jcnlwdGlvbkNvZGU6ICcxMjM0NTYnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHsgdXNlcktleWNoYWluLCBiYWNrdXBLZXljaGFpbiwgYml0Z29LZXljaGFpbiB9ID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlS2V5Y2hhaW5zKHBhcmFtcyk7XG4gICAgICBhc3NlcnQub2socm91bmQxTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2socm91bmQyTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2socm91bmQzTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2soYWRkS2V5Tm9jay5pc0RvbmUoKSk7XG5cbiAgICAgIGFzc2VydC5vayh1c2VyS2V5Y2hhaW4pO1xuICAgICAgYXNzZXJ0LmVxdWFsKHVzZXJLZXljaGFpbi5zb3VyY2UsICd1c2VyJyk7XG4gICAgICBhc3NlcnQub2sodXNlcktleWNoYWluLmNvbW1vbktleWNoYWluKTtcbiAgICAgIGFzc2VydC5vayhFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscy52YWxpZGF0ZUNvbW1vbktleWNoYWluUHVibGljS2V5KHVzZXJLZXljaGFpbi5jb21tb25LZXljaGFpbikpO1xuICAgICAgYXNzZXJ0Lm9rKHVzZXJLZXljaGFpbi5lbmNyeXB0ZWRQcnYpO1xuICAgICAgYXNzZXJ0Lm9rKGJpdGdvLmRlY3J5cHQoeyBpbnB1dDogdXNlcktleWNoYWluLmVuY3J5cHRlZFBydiwgcGFzc3dvcmQ6IHBhcmFtcy5wYXNzcGhyYXNlIH0pKTtcblxuICAgICAgYXNzZXJ0Lm9rKGJhY2t1cEtleWNoYWluKTtcbiAgICAgIGFzc2VydC5lcXVhbChiYWNrdXBLZXljaGFpbi5zb3VyY2UsICdiYWNrdXAnKTtcbiAgICAgIGFzc2VydC5vayhiYWNrdXBLZXljaGFpbi5jb21tb25LZXljaGFpbik7XG4gICAgICBhc3NlcnQub2soRUNEU0FVdGlscy5FY2RzYU1QQ3YyVXRpbHMudmFsaWRhdGVDb21tb25LZXljaGFpblB1YmxpY0tleShiYWNrdXBLZXljaGFpbi5jb21tb25LZXljaGFpbikpO1xuICAgICAgYXNzZXJ0Lm9rKGJhY2t1cEtleWNoYWluLmVuY3J5cHRlZFBydik7XG4gICAgICBhc3NlcnQub2soYml0Z28uZGVjcnlwdCh7IGlucHV0OiBiYWNrdXBLZXljaGFpbi5lbmNyeXB0ZWRQcnYsIHBhc3N3b3JkOiBwYXJhbXMucGFzc3BocmFzZSB9KSk7XG5cbiAgICAgIGFzc2VydC5vayhiaXRnb0tleWNoYWluKTtcbiAgICAgIGFzc2VydC5lcXVhbChiaXRnb0tleWNoYWluLnNvdXJjZSwgJ2JpdGdvJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHNlbmQgd2ViYXV0aG5JbmZvICh3aXRoIGVudGVycHJpc2VJZCkgb24gdGhlIHVzZXIga2V5Y2hhaW4gd2hlbiB3ZWJhdXRobkluZm8gaXMgcHJvdmlkZWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBiaXRnb1Nlc3Npb24gPSBuZXcgRGtsc0RrZy5Ea2coMywgMiwgMik7XG5cbiAgICAgIGNvbnN0IHJvdW5kMU5vY2sgPSBhd2FpdCBub2NrS2V5R2VuUm91bmQxKGJpdGdvU2Vzc2lvbiwgMSk7XG4gICAgICBjb25zdCByb3VuZDJOb2NrID0gYXdhaXQgbm9ja0tleUdlblJvdW5kMihiaXRnb1Nlc3Npb24sIDEpO1xuICAgICAgY29uc3Qgcm91bmQzTm9jayA9IGF3YWl0IG5vY2tLZXlHZW5Sb3VuZDMoYml0Z29TZXNzaW9uLCAxKTtcblxuICAgICAgLy8gQ2FwdHVyZSBlYWNoIGtleWNoYWluIFBPU1QgYm9keSBieSBzb3VyY2Ugc28gd2UgY2FuIGFzc2VydCB3aGF0IHRoZSB1c2VyIGtleSBzZW5kcy5cbiAgICAgIGNvbnN0IGNhcHR1cmVkQm9kaWVzOiBSZWNvcmQ8c3RyaW5nLCBBZGRLZXljaGFpbk9wdGlvbnM+ID0ge307XG4gICAgICBjb25zdCBhZGRLZXlOb2NrID0gbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgICAgLnBvc3QoYC9hcGkvdjIvJHtjb2luTmFtZX0va2V5YCwgKGJvZHkpID0+IGJvZHkua2V5VHlwZSA9PT0gJ3RzcycgJiYgYm9keS5pc01QQ3YyKVxuICAgICAgICAudGltZXMoMylcbiAgICAgICAgLnJlcGx5KDIwMCwgYXN5bmMgKHVyaSwgcmVxdWVzdEJvZHk6IEFkZEtleWNoYWluT3B0aW9ucykgPT4ge1xuICAgICAgICAgIGNhcHR1cmVkQm9kaWVzW3JlcXVlc3RCb2R5LnNvdXJjZSBhcyBzdHJpbmddID0gcmVxdWVzdEJvZHk7XG4gICAgICAgICAgY29uc3Qga2V5ID0ge1xuICAgICAgICAgICAgaWQ6IHJlcXVlc3RCb2R5LnNvdXJjZSxcbiAgICAgICAgICAgIHNvdXJjZTogcmVxdWVzdEJvZHkuc291cmNlLFxuICAgICAgICAgICAgdHlwZTogcmVxdWVzdEJvZHkua2V5VHlwZSxcbiAgICAgICAgICAgIGNvbW1vbktleWNoYWluOiByZXF1ZXN0Qm9keS5jb21tb25LZXljaGFpbixcbiAgICAgICAgICAgIGVuY3J5cHRlZFBydjogcmVxdWVzdEJvZHkuZW5jcnlwdGVkUHJ2LFxuICAgICAgICAgIH07XG4gICAgICAgICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJykuZ2V0KGAvYXBpL3YyLyR7Y29pbk5hbWV9L2tleS8ke3JlcXVlc3RCb2R5LnNvdXJjZX1gKS5yZXBseSgyMDAsIGtleSk7XG4gICAgICAgICAgcmV0dXJuIGtleTtcbiAgICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHdlYmF1dGhuSW5mbyA9IHtcbiAgICAgICAgb3RwRGV2aWNlSWQ6ICdkZXZpY2UtMTIzJyxcbiAgICAgICAgcHJmU2FsdDogJ3NhbHQtYWJjJyxcbiAgICAgICAgcGFzc3BocmFzZTogJ3ByZi1kZXJpdmVkLXBhc3NwaHJhc2UnLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgcGFzc3BocmFzZTogJ3Rlc3QnLFxuICAgICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlSWQsXG4gICAgICAgIG9yaWdpbmFsUGFzc2NvZGVFbmNyeXB0aW9uQ29kZTogJzEyMzQ1NicsXG4gICAgICAgIHdlYmF1dGhuSW5mbyxcbiAgICAgIH07XG4gICAgICBhd2FpdCB0c3NVdGlscy5jcmVhdGVLZXljaGFpbnMocGFyYW1zKTtcbiAgICAgIGFzc2VydC5vayhyb3VuZDFOb2NrLmlzRG9uZSgpKTtcbiAgICAgIGFzc2VydC5vayhyb3VuZDJOb2NrLmlzRG9uZSgpKTtcbiAgICAgIGFzc2VydC5vayhyb3VuZDNOb2NrLmlzRG9uZSgpKTtcbiAgICAgIGFzc2VydC5vayhhZGRLZXlOb2NrLmlzRG9uZSgpKTtcblxuICAgICAgLy8gVXNlciBrZXljaGFpbiBtdXN0IGNhcnJ5IHdlYmF1dGhuSW5mbyAodGhlIGZpZWxkIHRoZSBiYWNrZW5kIFBPU1QgL2tleSBjb25zdW1lcyksXG4gICAgICAvLyBpbmNsdWRpbmcgZW50ZXJwcmlzZUlkLCBhbmQgbXVzdCBOT1QgdXNlIHRoZSBkZXByZWNhdGVkIHdlYmF1dGhuRGV2aWNlcyBhcnJheS5cbiAgICAgIGNvbnN0IHVzZXJCb2R5ID0gY2FwdHVyZWRCb2RpZXNbJ3VzZXInXTtcbiAgICAgIGFzc2VydC5vayh1c2VyQm9keSwgJ3VzZXIga2V5Y2hhaW4gc2hvdWxkIGhhdmUgYmVlbiBjcmVhdGVkJyk7XG4gICAgICBhc3NlcnQub2sodXNlckJvZHkud2ViYXV0aG5JbmZvLCAndXNlciBrZXljaGFpbiBib2R5IHNob3VsZCBpbmNsdWRlIHdlYmF1dGhuSW5mbycpO1xuICAgICAgYXNzZXJ0LmVxdWFsKHVzZXJCb2R5LndlYmF1dGhuSW5mby5vdHBEZXZpY2VJZCwgd2ViYXV0aG5JbmZvLm90cERldmljZUlkKTtcbiAgICAgIGFzc2VydC5lcXVhbCh1c2VyQm9keS53ZWJhdXRobkluZm8ucHJmU2FsdCwgd2ViYXV0aG5JbmZvLnByZlNhbHQpO1xuICAgICAgYXNzZXJ0LmVxdWFsKHVzZXJCb2R5LndlYmF1dGhuSW5mby5lbnRlcnByaXNlSWQsIGVudGVycHJpc2VJZCk7XG4gICAgICBhc3NlcnQub2sodXNlckJvZHkud2ViYXV0aG5JbmZvLmVuY3J5cHRlZFBydiwgJ2VuY3J5cHRlZFBydiBzaG91bGQgYmUgc2V0Jyk7XG4gICAgICAvLyBlbmNyeXB0ZWRQcnYgaXMgdGhlIHVzZXIga2V5IHNoYXJlIGVuY3J5cHRlZCB3aXRoIHRoZSBQUkYtZGVyaXZlZCBwYXNzcGhyYXNlLlxuICAgICAgYXNzZXJ0Lm9rKGJpdGdvLmRlY3J5cHQoeyBpbnB1dDogdXNlckJvZHkud2ViYXV0aG5JbmZvLmVuY3J5cHRlZFBydiwgcGFzc3dvcmQ6IHdlYmF1dGhuSW5mby5wYXNzcGhyYXNlIH0pKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbCh1c2VyQm9keS53ZWJhdXRobkRldmljZXMsIHVuZGVmaW5lZCwgJ2RlcHJlY2F0ZWQgd2ViYXV0aG5EZXZpY2VzIHNob3VsZCBub3QgYmUgc2VudCcpO1xuXG4gICAgICAvLyBCYWNrdXAga2V5Y2hhaW4gbXVzdCBuZXZlciBjYXJyeSBwYXNza2V5IG1hdGVyaWFsLlxuICAgICAgY29uc3QgYmFja3VwQm9keSA9IGNhcHR1cmVkQm9kaWVzWydiYWNrdXAnXTtcbiAgICAgIGFzc2VydC5vayhiYWNrdXBCb2R5LCAnYmFja3VwIGtleWNoYWluIHNob3VsZCBoYXZlIGJlZW4gY3JlYXRlZCcpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJhY2t1cEJvZHkud2ViYXV0aG5JbmZvLCB1bmRlZmluZWQpO1xuICAgICAgYXNzZXJ0LnN0cmljdEVxdWFsKGJhY2t1cEJvZHkud2ViYXV0aG5EZXZpY2VzLCB1bmRlZmluZWQpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBUU1MgTVBDdjIga2V5cyB3aXRoIHYyIGVuY3J5cHRpb24gZW52ZWxvcGVzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYml0Z29TZXNzaW9uID0gbmV3IERrbHNEa2cuRGtnKDMsIDIsIDIpO1xuXG4gICAgICBjb25zdCByb3VuZDFOb2NrID0gYXdhaXQgbm9ja0tleUdlblJvdW5kMShiaXRnb1Nlc3Npb24sIDEpO1xuICAgICAgY29uc3Qgcm91bmQyTm9jayA9IGF3YWl0IG5vY2tLZXlHZW5Sb3VuZDIoYml0Z29TZXNzaW9uLCAxKTtcbiAgICAgIGNvbnN0IHJvdW5kM05vY2sgPSBhd2FpdCBub2NrS2V5R2VuUm91bmQzKGJpdGdvU2Vzc2lvbiwgMSk7XG4gICAgICBjb25zdCBhZGRLZXlOb2NrID0gYXdhaXQgbm9ja0FkZEtleUNoYWluKGNvaW5OYW1lLCAzKTtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgcGFzc3BocmFzZTogJ3Rlc3QnLFxuICAgICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlSWQsXG4gICAgICAgIG9yaWdpbmFsUGFzc2NvZGVFbmNyeXB0aW9uQ29kZTogJzEyMzQ1NicsXG4gICAgICAgIGVuY3J5cHRpb25WZXJzaW9uOiAyIGFzIGNvbnN0LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHsgdXNlcktleWNoYWluLCBiYWNrdXBLZXljaGFpbiwgYml0Z29LZXljaGFpbiB9ID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlS2V5Y2hhaW5zKHBhcmFtcyk7XG4gICAgICBhc3NlcnQub2socm91bmQxTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2socm91bmQyTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2socm91bmQzTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2soYWRkS2V5Tm9jay5pc0RvbmUoKSk7XG5cbiAgICAgIGFzc2VydC5vayh1c2VyS2V5Y2hhaW4pO1xuICAgICAgYXNzZXJ0LmVxdWFsKHVzZXJLZXljaGFpbi5zb3VyY2UsICd1c2VyJyk7XG4gICAgICBhc3NlcnQub2sodXNlcktleWNoYWluLmNvbW1vbktleWNoYWluKTtcbiAgICAgIGFzc2VydC5vayhFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscy52YWxpZGF0ZUNvbW1vbktleWNoYWluUHVibGljS2V5KHVzZXJLZXljaGFpbi5jb21tb25LZXljaGFpbikpO1xuXG4gICAgICAvLyBWZXJpZnkgdjIgZW52ZWxvcGVzIGZvciBlbmNyeXB0ZWRQcnZcbiAgICAgIGFzc2VydC5vayh1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICAgIGNvbnN0IGVuY3J5cHRlZFBydlBhcnNlZDogeyB2OiBudW1iZXIgfSA9IEpTT04ucGFyc2UodXNlcktleWNoYWluLmVuY3J5cHRlZFBydik7XG4gICAgICBhc3NlcnQuZXF1YWwoZW5jcnlwdGVkUHJ2UGFyc2VkLnYsIDIsICdlbmNyeXB0ZWRQcnYgc2hvdWxkIGJlIGEgdjIgZW52ZWxvcGUnKTtcblxuICAgICAgLy8gVmVyaWZ5IHYyIGVudmVsb3BlcyBmb3IgcmVkdWNlZEVuY3J5cHRlZFBydlxuICAgICAgYXNzZXJ0Lm9rKHVzZXJLZXljaGFpbi5yZWR1Y2VkRW5jcnlwdGVkUHJ2KTtcbiAgICAgIGNvbnN0IHJlZHVjZWRFbmNyeXB0ZWRQcnZQYXJzZWQ6IHsgdjogbnVtYmVyIH0gPSBKU09OLnBhcnNlKHVzZXJLZXljaGFpbi5yZWR1Y2VkRW5jcnlwdGVkUHJ2KTtcbiAgICAgIGFzc2VydC5lcXVhbChyZWR1Y2VkRW5jcnlwdGVkUHJ2UGFyc2VkLnYsIDIsICdyZWR1Y2VkRW5jcnlwdGVkUHJ2IHNob3VsZCBiZSBhIHYyIGVudmVsb3BlJyk7XG5cbiAgICAgIC8vIFZlcmlmeSB2MiBlbnZlbG9wZSBpcyBkZWNyeXB0YWJsZSB2aWEgZGVjcnlwdFxuICAgICAgY29uc3QgZGVjcnlwdGVkID0gYXdhaXQgYml0Z28uZGVjcnlwdCh7IGlucHV0OiB1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2LCBwYXNzd29yZDogcGFyYW1zLnBhc3NwaHJhc2UgfSk7XG4gICAgICBhc3NlcnQub2soZGVjcnlwdGVkLCAnZGVjcnlwdCBzaG91bGQgc3VjY2Vzc2Z1bGx5IGRlY3J5cHQgdjIgZW52ZWxvcGUnKTtcblxuICAgICAgLy8gVmVyaWZ5IGJhY2t1cCBrZXljaGFpbiBhbHNvIHVzZXMgdjIgZW52ZWxvcGVzXG4gICAgICBhc3NlcnQub2soYmFja3VwS2V5Y2hhaW4pO1xuICAgICAgYXNzZXJ0LmVxdWFsKGJhY2t1cEtleWNoYWluLnNvdXJjZSwgJ2JhY2t1cCcpO1xuICAgICAgYXNzZXJ0Lm9rKGJhY2t1cEtleWNoYWluLmVuY3J5cHRlZFBydik7XG4gICAgICBjb25zdCBiYWNrdXBFbmNyeXB0ZWRQcnZQYXJzZWQ6IHsgdjogbnVtYmVyIH0gPSBKU09OLnBhcnNlKGJhY2t1cEtleWNoYWluLmVuY3J5cHRlZFBydik7XG4gICAgICBhc3NlcnQuZXF1YWwoYmFja3VwRW5jcnlwdGVkUHJ2UGFyc2VkLnYsIDIsICdiYWNrdXAgZW5jcnlwdGVkUHJ2IHNob3VsZCBiZSBhIHYyIGVudmVsb3BlJyk7XG5cbiAgICAgIGFzc2VydC5vayhiaXRnb0tleWNoYWluKTtcbiAgICAgIGFzc2VydC5lcXVhbChiaXRnb0tleWNoYWluLnNvdXJjZSwgJ2JpdGdvJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIFRTUyBNUEN2MiBrZXlzIGZvciByZXRyb2ZpdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHhpTGlzdCA9IFtcbiAgICAgICAgQXJyYXkuZnJvbShiaWdJbnRUb0J1ZmZlckJFKEJpZ0ludCgxKSwgMzIpKSxcbiAgICAgICAgQXJyYXkuZnJvbShiaWdJbnRUb0J1ZmZlckJFKEJpZ0ludCgyKSwgMzIpKSxcbiAgICAgICAgQXJyYXkuZnJvbShiaWdJbnRUb0J1ZmZlckJFKEJpZ0ludCgzKSwgMzIpKSxcbiAgICAgIF07XG4gICAgICBjb25zdCBiaXRnb1JldHJvZml0RGF0YTogRGtsc1R5cGVzLlJldHJvZml0RGF0YSA9IHtcbiAgICAgICAgeGlMaXN0LFxuICAgICAgICB4U2hhcmU6IHYxRml4dHVyZXMubW9ja0JpdEdvU2hhcmVTaWduaW5nTWF0ZXJpYWwueFNoYXJlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGJpdGdvU2Vzc2lvbiA9IG5ldyBEa2xzRGtnLkRrZygzLCAyLCBFQ0RTQVV0aWxzLk1QQ3YyUGFydGllc0VudW0uQklUR08sIHVuZGVmaW5lZCwgYml0Z29SZXRyb2ZpdERhdGEpO1xuXG4gICAgICBjb25zdCByb3VuZDFOb2NrID0gYXdhaXQgbm9ja0tleUdlblJvdW5kMShiaXRnb1Nlc3Npb24sIDEpO1xuICAgICAgY29uc3Qgcm91bmQyTm9jayA9IGF3YWl0IG5vY2tLZXlHZW5Sb3VuZDIoYml0Z29TZXNzaW9uLCAxKTtcbiAgICAgIGNvbnN0IHJvdW5kM05vY2sgPSBhd2FpdCBub2NrS2V5R2VuUm91bmQzKGJpdGdvU2Vzc2lvbiwgMSk7XG4gICAgICBjb25zdCBhZGRLZXlOb2NrID0gYXdhaXQgbm9ja0FkZEtleUNoYWluKGNvaW5OYW1lLCAzKTtcbiAgICAgIGNvbnN0IHBhcmFtczogUGFyYW1ldGVyczx0eXBlb2YgdHNzVXRpbHMuY3JlYXRlS2V5Y2hhaW5zPlswXSA9IHtcbiAgICAgICAgcGFzc3BocmFzZTogJ3Rlc3QnLFxuICAgICAgICBlbnRlcnByaXNlOiBlbnRlcnByaXNlSWQsXG4gICAgICAgIG9yaWdpbmFsUGFzc2NvZGVFbmNyeXB0aW9uQ29kZTogJzEyMzQ1NicsXG4gICAgICAgIHJldHJvZml0OiB7XG4gICAgICAgICAgZGVjcnlwdGVkVXNlcktleTogSlNPTi5zdHJpbmdpZnkodjFGaXh0dXJlcy5tb2NrVXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICAgICAgZGVjcnlwdGVkQmFja3VwS2V5OiBKU09OLnN0cmluZ2lmeSh2MUZpeHR1cmVzLm1vY2tCYWNrdXBTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgICAgIHdhbGxldElkOiAnMTIzJyxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICBjb25zdCB7IHVzZXJLZXljaGFpbiwgYmFja3VwS2V5Y2hhaW4sIGJpdGdvS2V5Y2hhaW4gfSA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUtleWNoYWlucyhwYXJhbXMpO1xuICAgICAgYXNzZXJ0Lm9rKHJvdW5kMU5vY2suaXNEb25lKCkpO1xuICAgICAgYXNzZXJ0Lm9rKHJvdW5kMk5vY2suaXNEb25lKCkpO1xuICAgICAgYXNzZXJ0Lm9rKHJvdW5kM05vY2suaXNEb25lKCkpO1xuICAgICAgYXNzZXJ0Lm9rKGFkZEtleU5vY2suaXNEb25lKCkpO1xuXG4gICAgICBhc3NlcnQub2sodXNlcktleWNoYWluKTtcbiAgICAgIGFzc2VydC5lcXVhbCh1c2VyS2V5Y2hhaW4uc291cmNlLCAndXNlcicpO1xuICAgICAgYXNzZXJ0Lm9rKHVzZXJLZXljaGFpbi5jb21tb25LZXljaGFpbik7XG4gICAgICBhc3NlcnQub2soRUNEU0FVdGlscy5FY2RzYU1QQ3YyVXRpbHMudmFsaWRhdGVDb21tb25LZXljaGFpblB1YmxpY0tleSh1c2VyS2V5Y2hhaW4uY29tbW9uS2V5Y2hhaW4pKTtcbiAgICAgIGFzc2VydC5vayh1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICAgIGFzc2VydC5vayhiaXRnby5kZWNyeXB0KHsgaW5wdXQ6IHVzZXJLZXljaGFpbi5lbmNyeXB0ZWRQcnYsIHBhc3N3b3JkOiBwYXJhbXMucGFzc3BocmFzZSB9KSk7XG5cbiAgICAgIGFzc2VydC5vayhiYWNrdXBLZXljaGFpbik7XG4gICAgICBhc3NlcnQuZXF1YWwoYmFja3VwS2V5Y2hhaW4uc291cmNlLCAnYmFja3VwJyk7XG4gICAgICBhc3NlcnQub2soYmFja3VwS2V5Y2hhaW4uY29tbW9uS2V5Y2hhaW4pO1xuICAgICAgYXNzZXJ0Lm9rKEVDRFNBVXRpbHMuRWNkc2FNUEN2MlV0aWxzLnZhbGlkYXRlQ29tbW9uS2V5Y2hhaW5QdWJsaWNLZXkoYmFja3VwS2V5Y2hhaW4uY29tbW9uS2V5Y2hhaW4pKTtcbiAgICAgIGFzc2VydC5vayhiYWNrdXBLZXljaGFpbi5lbmNyeXB0ZWRQcnYpO1xuICAgICAgYXNzZXJ0Lm9rKGJpdGdvLmRlY3J5cHQoeyBpbnB1dDogYmFja3VwS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2LCBwYXNzd29yZDogcGFyYW1zLnBhc3NwaHJhc2UgfSkpO1xuXG4gICAgICBhc3NlcnQub2soYml0Z29LZXljaGFpbik7XG4gICAgICBhc3NlcnQuZXF1YWwoYml0Z29LZXljaGFpbi5zb3VyY2UsICdiaXRnbycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgVFNTIGtleSBjaGFpbnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub2NrUHJvbWlzZXMgPSBbXG4gICAgICAgIG5vY2tLZXljaGFpbih7XG4gICAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgICAga2V5Q2hhaW46IHsgaWQ6ICcxJywgcHViOiAnMScsIHR5cGU6ICd0c3MnLCByZWR1Y2VkRW5jcnlwdGVkUHJ2OiAnJyB9LFxuICAgICAgICAgIHNvdXJjZTogJ3VzZXInLFxuICAgICAgICB9KSxcbiAgICAgICAgbm9ja0tleWNoYWluKHtcbiAgICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgICBrZXlDaGFpbjogeyBpZDogJzInLCBwdWI6ICcyJywgdHlwZTogJ3RzcycsIHJlZHVjZWRFbmNyeXB0ZWRQcnY6ICcnIH0sXG4gICAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgfSksXG4gICAgICAgIG5vY2tLZXljaGFpbih7XG4gICAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgICAga2V5Q2hhaW46IHsgaWQ6ICczJywgcHViOiAnMycsIHR5cGU6ICd0c3MnLCByZWR1Y2VkRW5jcnlwdGVkUHJ2OiAnJyB9LFxuICAgICAgICAgIHNvdXJjZTogJ2JpdGdvJyxcbiAgICAgICAgfSksXG4gICAgICBdO1xuICAgICAgY29uc3QgW25vY2tlZFVzZXJLZXljaGFpbiwgbm9ja2VkQmFja3VwS2V5Y2hhaW4sIG5vY2tlZEJpdEdvS2V5Y2hhaW5dID0gYXdhaXQgUHJvbWlzZS5hbGwobm9ja1Byb21pc2VzKTtcblxuICAgICAgY29uc3QgYml0Z29LZXljaGFpblByb21pc2UgPSB0c3NVdGlscy5jcmVhdGVQYXJ0aWNpcGFudEtleWNoYWluKEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5CSVRHTywgJ3Rlc3QnKTtcbiAgICAgIGNvbnN0IHVzZXJzS2V5Y2hhaW5Qcm9taXNlID0gdHNzVXRpbHMuY3JlYXRlUGFydGljaXBhbnRLZXljaGFpbihcbiAgICAgICAgRUNEU0FVdGlscy5NUEN2MlBhcnRpZXNFbnVtLlVTRVIsXG4gICAgICAgICd0ZXN0JyxcbiAgICAgICAgQnVmZmVyLmZyb20oJ3Rlc3QnKSxcbiAgICAgICAgQnVmZmVyLmZyb20oJ3Rlc3QnKSxcbiAgICAgICAgJ3Bhc3NwaHJhc2UnLFxuICAgICAgICAndGVzdCdcbiAgICAgICk7XG4gICAgICBjb25zdCBiYWNrdXBLZXljaGFpblByb21pc2UgPSB0c3NVdGlscy5jcmVhdGVQYXJ0aWNpcGFudEtleWNoYWluKFxuICAgICAgICBFQ0RTQVV0aWxzLk1QQ3YyUGFydGllc0VudW0uQkFDS1VQLFxuICAgICAgICAndGVzdCcsXG4gICAgICAgIEJ1ZmZlci5mcm9tKCd0ZXN0JyksXG4gICAgICAgIEJ1ZmZlci5mcm9tKCd0ZXN0JyksXG4gICAgICAgICdwYXNzcGhyYXNlJyxcbiAgICAgICAgJ3Rlc3QnXG4gICAgICApO1xuXG4gICAgICBjb25zdCBbdXNlcktleWNoYWluLCBiYWNrdXBLZXljaGFpbiwgYml0Z29LZXljaGFpbl0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgIHVzZXJzS2V5Y2hhaW5Qcm9taXNlLFxuICAgICAgICBiYWNrdXBLZXljaGFpblByb21pc2UsXG4gICAgICAgIGJpdGdvS2V5Y2hhaW5Qcm9taXNlLFxuICAgICAgXSk7XG5cbiAgICAgICh7IC4uLnVzZXJLZXljaGFpbiwgcmVkdWNlZEVuY3J5cHRlZFBydjogJycgfSkuc2hvdWxkLmRlZXBFcXVhbChub2NrZWRVc2VyS2V5Y2hhaW4pO1xuICAgICAgKHsgLi4uYmFja3VwS2V5Y2hhaW4sIHJlZHVjZWRFbmNyeXB0ZWRQcnY6ICcnIH0pLnNob3VsZC5kZWVwRXF1YWwobm9ja2VkQmFja3VwS2V5Y2hhaW4pO1xuICAgICAgKHsgLi4uYml0Z29LZXljaGFpbiwgcmVkdWNlZEVuY3J5cHRlZFBydjogJycgfSkuc2hvdWxkLmRlZXBFcXVhbChub2NrZWRCaXRHb0tleWNoYWluKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY3JlYXRlIFRTUyBNUEN2MiBrZXkgY2hhaW5zIHdpdGggT1ZDcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IE1QQ3YyU01DVXRpbHMgPSBuZXcgRUNEU0FVdGlscy5NUEN2MlNNQ1V0aWxzKGJpdGdvLCBiYXNlQ29pbik7XG4gICAgICBjb25zdCBiaXRnb1Nlc3Npb24gPSBuZXcgRGtsc0RrZy5Ea2coMywgMiwgMik7XG5cbiAgICAgIGNvbnN0IHJvdW5kMU5vY2sgPSBhd2FpdCBub2NrS2V5R2VuUm91bmQxKGJpdGdvU2Vzc2lvbiwgMSk7XG4gICAgICBjb25zdCByb3VuZDJOb2NrID0gYXdhaXQgbm9ja0tleUdlblJvdW5kMihiaXRnb1Nlc3Npb24sIDEpO1xuICAgICAgY29uc3Qgcm91bmQzTm9jayA9IGF3YWl0IG5vY2tLZXlHZW5Sb3VuZDMoYml0Z29TZXNzaW9uLCAxKTtcbiAgICAgIGNvbnN0IGFkZEtleU5vY2sgPSBhd2FpdCBub2NrQWRkS2V5Q2hhaW4oY29pbk5hbWUsIDMpO1xuXG4gICAgICAvLyBPVkMgMSAtIFVzZXIgR1BHIGtleVxuICAgICAgY29uc3QgdXNlckdncEtleSA9IGF3YWl0IG9wZW5wZ3AuZ2VuZXJhdGVLZXkoe1xuICAgICAgICB1c2VySURzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ3VzZXInLFxuICAgICAgICAgICAgZW1haWw6ICd1c2VyQHRlc3QuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBjdXJ2ZTogJ3NlY3AyNTZrMScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHVzZXJHcGdQcnZLZXkgPSB7XG4gICAgICAgIHBhcnR5SWQ6IDAsXG4gICAgICAgIGdwZ0tleTogdXNlckdncEtleS5wcml2YXRlS2V5LFxuICAgICAgfTtcblxuICAgICAgLy8gUm91bmQgMSBVc2VyXG4gICAgICBjb25zdCB1c2VyU2Vzc2lvbiA9IG5ldyBEa2xzRGtnLkRrZygzLCAyLCAwKTtcbiAgICAgIGxldCBPVkMxVG9PVkMyUm91bmQxUGF5bG9hZDogT1ZDMVRvT1ZDMlJvdW5kMVBheWxvYWQ7XG4gICAgICB7XG4gICAgICAgIGNvbnN0IHVzZXJCcm9hZGNhc3RNc2cxVW5zaWduZWQgPSBhd2FpdCB1c2VyU2Vzc2lvbi5pbml0RGtnKCk7XG4gICAgICAgIGNvbnN0IHVzZXJNc2dzMVNpZ25lZCA9IGF3YWl0IERrbHNDb21tcy5lbmNyeXB0QW5kQXV0aE91dGdvaW5nTWVzc2FnZXMoXG4gICAgICAgICAgeyBicm9hZGNhc3RNZXNzYWdlczogW0RrbHNUeXBlcy5zZXJpYWxpemVCcm9hZGNhc3RNZXNzYWdlKHVzZXJCcm9hZGNhc3RNc2cxVW5zaWduZWQpXSwgcDJwTWVzc2FnZXM6IFtdIH0sXG4gICAgICAgICAgW10sXG4gICAgICAgICAgW3VzZXJHcGdQcnZLZXldXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHVzZXJNc2cxID0gdXNlck1zZ3MxU2lnbmVkLmJyb2FkY2FzdE1lc3NhZ2VzLmZpbmQoKG0pID0+IG0uZnJvbSA9PT0gMCk7XG4gICAgICAgIGFzc2VydC5vayh1c2VyTXNnMSwgJ3VzZXJNc2cxIG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIE9WQzFUb09WQzJSb3VuZDFQYXlsb2FkID0ge1xuICAgICAgICAgIHRzc1ZlcnNpb246ICcwLjAuMScgYXMgTm9uRW1wdHlTdHJpbmcsXG4gICAgICAgICAgd2FsbGV0VHlwZTogV2FsbGV0VHlwZUVudW0udHNzLFxuICAgICAgICAgIGNvaW46ICdldGgnIGFzIE5vbkVtcHR5U3RyaW5nLFxuICAgICAgICAgIHN0YXRlOiBLZXlDcmVhdGlvbk1QQ3YyU3RhdGVFbnVtLldhaXRpbmdGb3JPVkMyUm91bmQxRGF0YSxcbiAgICAgICAgICBvdmM6IHtcbiAgICAgICAgICAgIFtPVkNJbmRleEVudW0uT05FXToge1xuICAgICAgICAgICAgICBncGdQdWJLZXk6IHVzZXJHZ3BLZXkucHVibGljS2V5IGFzIE5vbkVtcHR5U3RyaW5nLFxuICAgICAgICAgICAgICBvdmNNc2cxOiB1c2VyTXNnMSBhcyBhbnksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIE9WQyAyIC0gQmFja3VwIEdQRyBrZXlcbiAgICAgIGNvbnN0IGJhY2t1cEdncEtleSA9IGF3YWl0IG9wZW5wZ3AuZ2VuZXJhdGVLZXkoe1xuICAgICAgICB1c2VySURzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ2JhY2t1cCcsXG4gICAgICAgICAgICBlbWFpbDogJ2JhY2t1cEB0ZXN0LmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgY3VydmU6ICdzZWNwMjU2azEnLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGJhY2t1cEdwZ1BydktleSA9IHtcbiAgICAgICAgcGFydHlJZDogMSxcbiAgICAgICAgZ3BnS2V5OiBiYWNrdXBHZ3BLZXkucHJpdmF0ZUtleSxcbiAgICAgIH07XG4gICAgICAvLyBSb3VuZCAxIEJhY2t1cFxuICAgICAgY29uc3QgYmFja3VwU2Vzc2lvbiA9IG5ldyBEa2xzRGtnLkRrZygzLCAyLCAxKTtcbiAgICAgIGxldCBPVkMyVG9CaXRnb1JvdW5kMVBheWxvYWQ6IE9WQzJUb0JpdGdvUm91bmQxUGF5bG9hZDtcbiAgICAgIHtcbiAgICAgICAgYXNzZXJ0Lm9rKE9WQzFUb09WQzJSb3VuZDFQYXlsb2FkLnN0YXRlID09PSAwLCAnT1ZDMVRvT1ZDMlJvdW5kMVBheWxvYWQuc3RhdGUgc2hvdWxkIGJlIDAnKTtcbiAgICAgICAgY29uc3QgYmFja3VwQnJvYWRjYXN0TXNnMVVuc2lnbmVkID0gYXdhaXQgYmFja3VwU2Vzc2lvbi5pbml0RGtnKCk7XG4gICAgICAgIGNvbnN0IGJhY2t1cE1zZ3MxU2lnbmVkID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICB7IGJyb2FkY2FzdE1lc3NhZ2VzOiBbRGtsc1R5cGVzLnNlcmlhbGl6ZUJyb2FkY2FzdE1lc3NhZ2UoYmFja3VwQnJvYWRjYXN0TXNnMVVuc2lnbmVkKV0sIHAycE1lc3NhZ2VzOiBbXSB9LFxuICAgICAgICAgIFtdLFxuICAgICAgICAgIFtiYWNrdXBHcGdQcnZLZXldXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGJhY2t1cE1zZzEgPSBiYWNrdXBNc2dzMVNpZ25lZC5icm9hZGNhc3RNZXNzYWdlcy5maW5kKChtKSA9PiBtLmZyb20gPT09IDEpO1xuICAgICAgICBhc3NlcnQub2soYmFja3VwTXNnMSwgJ2JhY2t1cE1zZzEgbm90IGZvdW5kJyk7XG5cbiAgICAgICAgT1ZDMlRvQml0Z29Sb3VuZDFQYXlsb2FkID0ge1xuICAgICAgICAgIC4uLk9WQzFUb09WQzJSb3VuZDFQYXlsb2FkLFxuICAgICAgICAgIHN0YXRlOiBLZXlDcmVhdGlvbk1QQ3YyU3RhdGVFbnVtLldhaXRpbmdGb3JCaXRnb1JvdW5kMURhdGEsXG4gICAgICAgICAgb3ZjOiB7XG4gICAgICAgICAgICAuLi5PVkMxVG9PVkMyUm91bmQxUGF5bG9hZC5vdmMsXG4gICAgICAgICAgICBbT1ZDSW5kZXhFbnVtLlRXT106IHtcbiAgICAgICAgICAgICAgZ3BnUHViS2V5OiBiYWNrdXBHZ3BLZXkucHVibGljS2V5IGFzIE5vbkVtcHR5U3RyaW5nLFxuICAgICAgICAgICAgICBvdmNNc2cxOiBiYWNrdXBNc2cxIGFzIGFueSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgLy8gUm91bmQgMSBCaXRHb1xuICAgICAgY29uc3QgYml0Z29Ub09WQzFSb3VuZDFQYXlsb2FkID0gYXdhaXQgTVBDdjJTTUNVdGlscy5rZXlHZW5Sb3VuZDEoJ3Rlc3RJZCcsIE9WQzJUb0JpdGdvUm91bmQxUGF5bG9hZCk7XG5cbiAgICAgIC8vIFJvdW5kIDIgVXNlclxuICAgICAgbGV0IE9WQzFUb09WQzJSb3VuZDJQYXlsb2FkOiBPVkMxVG9PVkMyUm91bmQyUGF5bG9hZDtcbiAgICAgIHtcbiAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvVG9PVkMxUm91bmQxUGF5bG9hZC5zdGF0ZSA9PT0gMiwgJ2JpdGdvVG9PVkMxUm91bmQxUGF5bG9hZC5zdGF0ZSBzaG91bGQgYmUgMicpO1xuICAgICAgICBjb25zdCB0b1VzZXJSb3VuZDFCcm9hZGNhc3RNZXNzYWdlcyA9IGF3YWl0IERrbHNDb21tcy5kZWNyeXB0QW5kVmVyaWZ5SW5jb21pbmdNZXNzYWdlcyhcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW1xuICAgICAgICAgICAgICBiaXRnb1RvT1ZDMVJvdW5kMVBheWxvYWQub3ZjW09WQ0luZGV4RW51bS5UV09dLm92Y01zZzEsXG4gICAgICAgICAgICAgIGJpdGdvVG9PVkMxUm91bmQxUGF5bG9hZC5wbGF0Zm9ybS5iaXRnb01zZzEsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgW2JpdGdvR3BnUHViS2V5LCB7IHBhcnR5SWQ6IDEsIGdwZ0tleTogYml0Z29Ub09WQzFSb3VuZDFQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uVFdPXS5ncGdQdWJLZXkgfV0sXG4gICAgICAgICAgW3VzZXJHcGdQcnZLZXldXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgdXNlclJvdW5kMlAyUE1lc3NhZ2VzID0gdXNlclNlc3Npb24uaGFuZGxlSW5jb21pbmdNZXNzYWdlcyh7XG4gICAgICAgICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiB0b1VzZXJSb3VuZDFCcm9hZGNhc3RNZXNzYWdlcy5icm9hZGNhc3RNZXNzYWdlcy5tYXAoRGtsc1R5cGVzLmRlc2VyaWFsaXplQnJvYWRjYXN0TWVzc2FnZSksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB1c2VyUm91bmQyTWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZW5jcnlwdEFuZEF1dGhPdXRnb2luZ01lc3NhZ2VzKFxuICAgICAgICAgIERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyh1c2VyUm91bmQyUDJQTWVzc2FnZXMpLFxuICAgICAgICAgIFt7IHBhcnR5SWQ6IDEsIGdwZ0tleTogYml0Z29Ub09WQzFSb3VuZDFQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uVFdPXS5ncGdQdWJLZXkgfSwgYml0Z29HcGdQdWJLZXldLFxuICAgICAgICAgIFt1c2VyR3BnUHJ2S2V5XVxuICAgICAgICApO1xuICAgICAgICBjb25zdCB1c2VyVG9CYWNrdXBNc2cyID0gdXNlclJvdW5kMk1lc3NhZ2VzLnAycE1lc3NhZ2VzLmZpbmQoXG4gICAgICAgICAgKG0pID0+IG0uZnJvbSA9PT0gRUNEU0FVdGlscy5NUEN2MlBhcnRpZXNFbnVtLlVTRVIgJiYgbS50byA9PT0gRUNEU0FVdGlscy5NUEN2MlBhcnRpZXNFbnVtLkJBQ0tVUFxuICAgICAgICApO1xuICAgICAgICBhc3NlcnQub2sodXNlclRvQmFja3VwTXNnMiwgJ3VzZXJUb0JhY2t1cE1zZzIgbm90IGZvdW5kJyk7XG4gICAgICAgIGNvbnN0IHVzZXJUb0JpdGdvTXNnMiA9IHVzZXJSb3VuZDJNZXNzYWdlcy5wMnBNZXNzYWdlcy5maW5kKFxuICAgICAgICAgIChtKSA9PiBtLmZyb20gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5VU0VSICYmIG0udG8gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5CSVRHT1xuICAgICAgICApO1xuICAgICAgICBhc3NlcnQub2sodXNlclRvQml0Z29Nc2cyLCAndXNlclRvQml0Z29Nc2cyIG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIE9WQzFUb09WQzJSb3VuZDJQYXlsb2FkID0ge1xuICAgICAgICAgIC4uLmJpdGdvVG9PVkMxUm91bmQxUGF5bG9hZCxcbiAgICAgICAgICBzdGF0ZTogS2V5Q3JlYXRpb25NUEN2MlN0YXRlRW51bS5XYWl0aW5nRm9yT1ZDMlJvdW5kMkRhdGEsXG4gICAgICAgICAgb3ZjOiB7XG4gICAgICAgICAgICAuLi5iaXRnb1RvT1ZDMVJvdW5kMVBheWxvYWQub3ZjLFxuICAgICAgICAgICAgW09WQ0luZGV4RW51bS5PTkVdOiBPYmplY3QuYXNzaWduKGJpdGdvVG9PVkMxUm91bmQxUGF5bG9hZC5vdmNbT1ZDSW5kZXhFbnVtLk9ORV0sIHtcbiAgICAgICAgICAgICAgb3ZjVG9CaXRnb01zZzI6IHVzZXJUb0JpdGdvTXNnMixcbiAgICAgICAgICAgICAgb3ZjVG9PdmNNc2cyOiB1c2VyVG9CYWNrdXBNc2cyLFxuICAgICAgICAgICAgfSkgYXMgYW55LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFJvdW5kIDIgQmFja3VwXG4gICAgICBsZXQgT1ZDMlRvQml0Z29Sb3VuZDJQYXlsb2FkOiBPVkMyVG9CaXRnb1JvdW5kMlBheWxvYWQ7XG5cbiAgICAgIHtcbiAgICAgICAgYXNzZXJ0Lm9rKE9WQzFUb09WQzJSb3VuZDJQYXlsb2FkLnN0YXRlID09PSAzLCAnYml0Z29Ub09WQzFSb3VuZDFQYXlsb2FkLnN0YXRlIHNob3VsZCBiZSAzJyk7XG4gICAgICAgIGNvbnN0IHRvQmFja3VwUm91bmQxQnJvYWRjYXN0TWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZGVjcnlwdEFuZFZlcmlmeUluY29taW5nTWVzc2FnZXMoXG4gICAgICAgICAge1xuICAgICAgICAgICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAgYml0Z29Ub09WQzFSb3VuZDFQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uT05FXS5vdmNNc2cxLFxuICAgICAgICAgICAgICBiaXRnb1RvT1ZDMVJvdW5kMVBheWxvYWQucGxhdGZvcm0uYml0Z29Nc2cxLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIFtiaXRnb0dwZ1B1YktleSwgeyBwYXJ0eUlkOiAwLCBncGdLZXk6IE9WQzFUb09WQzJSb3VuZDJQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uT05FXS5ncGdQdWJLZXkgfV0sXG4gICAgICAgICAgW2JhY2t1cEdwZ1BydktleV1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBiYWNrdXBSb3VuZDJQMlBNZXNzYWdlcyA9IGJhY2t1cFNlc3Npb24uaGFuZGxlSW5jb21pbmdNZXNzYWdlcyh7XG4gICAgICAgICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiB0b0JhY2t1cFJvdW5kMUJyb2FkY2FzdE1lc3NhZ2VzLmJyb2FkY2FzdE1lc3NhZ2VzLm1hcChcbiAgICAgICAgICAgIERrbHNUeXBlcy5kZXNlcmlhbGl6ZUJyb2FkY2FzdE1lc3NhZ2VcbiAgICAgICAgICApLFxuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgYmFja3VwUm91bmQyTWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZW5jcnlwdEFuZEF1dGhPdXRnb2luZ01lc3NhZ2VzKFxuICAgICAgICAgIERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyhiYWNrdXBSb3VuZDJQMlBNZXNzYWdlcyksXG4gICAgICAgICAgW3sgcGFydHlJZDogMCwgZ3BnS2V5OiBiaXRnb1RvT1ZDMVJvdW5kMVBheWxvYWQub3ZjW09WQ0luZGV4RW51bS5PTkVdLmdwZ1B1YktleSB9LCBiaXRnb0dwZ1B1YktleV0sXG4gICAgICAgICAgW2JhY2t1cEdwZ1BydktleV1cbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgYmFja3VwVG9Vc2VyTXNnMiA9IGJhY2t1cFJvdW5kMk1lc3NhZ2VzLnAycE1lc3NhZ2VzLmZpbmQoXG4gICAgICAgICAgKG0pID0+IG0uZnJvbSA9PT0gRUNEU0FVdGlscy5NUEN2MlBhcnRpZXNFbnVtLkJBQ0tVUCAmJiBtLnRvID09PSBFQ0RTQVV0aWxzLk1QQ3YyUGFydGllc0VudW0uVVNFUlxuICAgICAgICApO1xuICAgICAgICBhc3NlcnQub2soYmFja3VwVG9Vc2VyTXNnMiwgJ2JhY2t1cFRvVXNlck1zZzIgbm90IGZvdW5kJyk7XG4gICAgICAgIGNvbnN0IGJhY2t1cFRvQml0Z29Nc2cyID0gYmFja3VwUm91bmQyTWVzc2FnZXMucDJwTWVzc2FnZXMuZmluZChcbiAgICAgICAgICAobSkgPT4gbS5mcm9tID09PSBFQ0RTQVV0aWxzLk1QQ3YyUGFydGllc0VudW0uQkFDS1VQICYmIG0udG8gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5CSVRHT1xuICAgICAgICApO1xuICAgICAgICBhc3NlcnQub2soYmFja3VwVG9CaXRnb01zZzIsICdiYWNrdXBUb0JpdGdvTXNnMiBub3QgZm91bmQnKTtcblxuICAgICAgICBPVkMyVG9CaXRnb1JvdW5kMlBheWxvYWQgPSB7XG4gICAgICAgICAgLi4uT1ZDMVRvT1ZDMlJvdW5kMlBheWxvYWQsXG4gICAgICAgICAgc3RhdGU6IEtleUNyZWF0aW9uTVBDdjJTdGF0ZUVudW0uV2FpdGluZ0ZvckJpdGdvUm91bmQyRGF0YSxcbiAgICAgICAgICBvdmM6IHtcbiAgICAgICAgICAgIC4uLk9WQzFUb09WQzJSb3VuZDJQYXlsb2FkLm92YyxcbiAgICAgICAgICAgIFtPVkNJbmRleEVudW0uVFdPXTogT2JqZWN0LmFzc2lnbihPVkMxVG9PVkMyUm91bmQyUGF5bG9hZC5vdmNbT1ZDSW5kZXhFbnVtLlRXT10sIHtcbiAgICAgICAgICAgICAgb3ZjVG9CaXRnb01zZzI6IGJhY2t1cFRvQml0Z29Nc2cyLFxuICAgICAgICAgICAgICBvdmNUb092Y01zZzI6IGJhY2t1cFRvVXNlck1zZzIsXG4gICAgICAgICAgICB9KSBhcyBhbnksXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgLy8gUm91bmQgMiBCaXRHb1xuICAgICAgLy8gY2FsbCBiaXRnbyByb3VuZCAyXG4gICAgICBjb25zdCBiaXRnb1RvT1ZDMVJvdW5kMlBheWxvYWQgPSBhd2FpdCBNUEN2MlNNQ1V0aWxzLmtleUdlblJvdW5kMigndGVzdElkJywgT1ZDMlRvQml0Z29Sb3VuZDJQYXlsb2FkKTtcblxuICAgICAgLy8gUm91bmQgM0EgVXNlclxuICAgICAgbGV0IE9WQzFUb09WQzJSb3VuZDNQYXlsb2FkOiBPVkMxVG9PVkMyUm91bmQzUGF5bG9hZDtcbiAgICAgIHtcbiAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvVG9PVkMxUm91bmQyUGF5bG9hZC5zdGF0ZSA9PT0gNSwgJ2JpdGdvVG9PVkMxUm91bmQyUGF5bG9hZC5zdGF0ZSBzaG91bGQgYmUgNScpO1xuICAgICAgICBjb25zdCB0b1VzZXJSb3VuZDJQMlBNZXNzYWdlcyA9IGF3YWl0IERrbHNDb21tcy5kZWNyeXB0QW5kVmVyaWZ5SW5jb21pbmdNZXNzYWdlcyhcbiAgICAgICAgICB7XG4gICAgICAgICAgICBwMnBNZXNzYWdlczogW1xuICAgICAgICAgICAgICBiaXRnb1RvT1ZDMVJvdW5kMlBheWxvYWQub3ZjW09WQ0luZGV4RW51bS5UV09dLm92Y1RvT3ZjTXNnMixcbiAgICAgICAgICAgICAgYml0Z29Ub09WQzFSb3VuZDJQYXlsb2FkLnBsYXRmb3JtLm92Y1tPVkNJbmRleEVudW0uT05FXS5iaXRnb1RvT3ZjTXNnMixcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBbYml0Z29HcGdQdWJLZXksIHsgcGFydHlJZDogMSwgZ3BnS2V5OiBiaXRnb1RvT1ZDMVJvdW5kMlBheWxvYWQub3ZjW09WQ0luZGV4RW51bS5UV09dLmdwZ1B1YktleSB9XSxcbiAgICAgICAgICBbdXNlckdwZ1BydktleV1cbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdXNlclJvdW5kM0FQMlBNZXNzYWdlcyA9IHVzZXJTZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoe1xuICAgICAgICAgIHAycE1lc3NhZ2VzOiB0b1VzZXJSb3VuZDJQMlBNZXNzYWdlcy5wMnBNZXNzYWdlcy5tYXAoRGtsc1R5cGVzLmRlc2VyaWFsaXplUDJQTWVzc2FnZSksXG4gICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgICB9KS5wMnBNZXNzYWdlcztcblxuICAgICAgICBjb25zdCB1c2VyUm91bmQzQU1lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICBEa2xzVHlwZXMuc2VyaWFsaXplTWVzc2FnZXMoe1xuICAgICAgICAgICAgcDJwTWVzc2FnZXM6IHVzZXJSb3VuZDNBUDJQTWVzc2FnZXMsXG4gICAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gICAgICAgICAgfSksXG4gICAgICAgICAgW3sgcGFydHlJZDogMSwgZ3BnS2V5OiBiaXRnb1RvT1ZDMVJvdW5kMlBheWxvYWQub3ZjW09WQ0luZGV4RW51bS5UV09dLmdwZ1B1YktleSB9LCBiaXRnb0dwZ1B1YktleV0sXG4gICAgICAgICAgW3VzZXJHcGdQcnZLZXldXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgdXNlclRvQml0Z29Nc2czID0gdXNlclJvdW5kM0FNZXNzYWdlcy5wMnBNZXNzYWdlcy5maW5kKFxuICAgICAgICAgIChtKSA9PiBtLmZyb20gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5VU0VSICYmIG0udG8gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5CSVRHT1xuICAgICAgICApO1xuICAgICAgICBhc3NlcnQub2sodXNlclRvQml0Z29Nc2czLCAndXNlclRvQml0Z29Nc2czIG5vdCBmb3VuZCcpO1xuICAgICAgICBjb25zdCB1c2VyVG9CYWNrdXBNc2czID0gdXNlclJvdW5kM0FNZXNzYWdlcy5wMnBNZXNzYWdlcy5maW5kKFxuICAgICAgICAgIChtKSA9PiBtLmZyb20gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5VU0VSICYmIG0udG8gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVBcbiAgICAgICAgKTtcbiAgICAgICAgYXNzZXJ0Lm9rKHVzZXJUb0JhY2t1cE1zZzMsICd1c2VyVG9CYWNrdXBNc2czIG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIE9WQzFUb09WQzJSb3VuZDNQYXlsb2FkID0ge1xuICAgICAgICAgIC4uLmJpdGdvVG9PVkMxUm91bmQyUGF5bG9hZCxcbiAgICAgICAgICBzdGF0ZTogS2V5Q3JlYXRpb25NUEN2MlN0YXRlRW51bS5XYWl0aW5nRm9yT1ZDMlJvdW5kM0RhdGEsXG4gICAgICAgICAgb3ZjOiB7XG4gICAgICAgICAgICAuLi5iaXRnb1RvT1ZDMVJvdW5kMlBheWxvYWQub3ZjLFxuICAgICAgICAgICAgW09WQ0luZGV4RW51bS5PTkVdOiBPYmplY3QuYXNzaWduKGJpdGdvVG9PVkMxUm91bmQyUGF5bG9hZC5vdmNbT1ZDSW5kZXhFbnVtLk9ORV0sIHtcbiAgICAgICAgICAgICAgb3ZjVG9CaXRnb01zZzM6IHVzZXJUb0JpdGdvTXNnMyxcbiAgICAgICAgICAgICAgb3ZjVG9PdmNNc2czOiB1c2VyVG9CYWNrdXBNc2czLFxuICAgICAgICAgICAgfSkgYXMgYW55LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFJvdW5kIDMgQmFja3VwXG4gICAgICBsZXQgT1ZDMlRvT1ZDMVJvdW5kM1BheWxvYWQ6IE9WQzJUb09WQzFSb3VuZDNQYXlsb2FkO1xuICAgICAge1xuICAgICAgICBhc3NlcnQub2soT1ZDMVRvT1ZDMlJvdW5kM1BheWxvYWQuc3RhdGUgPT09IDYsICdPVkMxVG9PVkMyUm91bmQzUGF5bG9hZC5zdGF0ZSBzaG91bGQgYmUgNicpO1xuICAgICAgICBjb25zdCB0b0JhY2t1cFJvdW5kM1AyUE1lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHAycE1lc3NhZ2VzOiBbXG4gICAgICAgICAgICAgIE9WQzFUb09WQzJSb3VuZDNQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uT05FXS5vdmNUb092Y01zZzIsXG4gICAgICAgICAgICAgIE9WQzFUb09WQzJSb3VuZDNQYXlsb2FkLnBsYXRmb3JtLm92Y1tPVkNJbmRleEVudW0uVFdPXS5iaXRnb1RvT3ZjTXNnMixcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBbYml0Z29HcGdQdWJLZXksIHsgcGFydHlJZDogMCwgZ3BnS2V5OiBPVkMxVG9PVkMyUm91bmQzUGF5bG9hZC5vdmNbT1ZDSW5kZXhFbnVtLk9ORV0uZ3BnUHViS2V5IH1dLFxuICAgICAgICAgIFtiYWNrdXBHcGdQcnZLZXldXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgYmFja3VwUm91bmQzUDJQTWVzc2FnZXMgPSBiYWNrdXBTZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoe1xuICAgICAgICAgIHAycE1lc3NhZ2VzOiB0b0JhY2t1cFJvdW5kM1AyUE1lc3NhZ2VzLnAycE1lc3NhZ2VzLm1hcChEa2xzVHlwZXMuZGVzZXJpYWxpemVQMlBNZXNzYWdlKSxcbiAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGJhY2t1cFJvdW5kM01lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICBEa2xzVHlwZXMuc2VyaWFsaXplTWVzc2FnZXMoYmFja3VwUm91bmQzUDJQTWVzc2FnZXMpLFxuICAgICAgICAgIFt7IHBhcnR5SWQ6IDAsIGdwZ0tleTogT1ZDMVRvT1ZDMlJvdW5kM1BheWxvYWQub3ZjW09WQ0luZGV4RW51bS5PTkVdLmdwZ1B1YktleSB9LCBiaXRnb0dwZ1B1YktleV0sXG4gICAgICAgICAgW2JhY2t1cEdwZ1BydktleV1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBiYWNrdXBUb0JpdGdvTXNnMyA9IGJhY2t1cFJvdW5kM01lc3NhZ2VzLnAycE1lc3NhZ2VzLmZpbmQoXG4gICAgICAgICAgKG0pID0+IG0uZnJvbSA9PT0gRUNEU0FVdGlscy5NUEN2MlBhcnRpZXNFbnVtLkJBQ0tVUCAmJiBtLnRvID09PSBFQ0RTQVV0aWxzLk1QQ3YyUGFydGllc0VudW0uQklUR09cbiAgICAgICAgKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGJhY2t1cFRvQml0Z29Nc2czLCAnYmFja3VwVG9CaXRnb01zZzMgbm90IGZvdW5kJyk7XG4gICAgICAgIGNvbnN0IGJhY2t1cFRvVXNlck1zZzMgPSBiYWNrdXBSb3VuZDNNZXNzYWdlcy5wMnBNZXNzYWdlcy5maW5kKFxuICAgICAgICAgIChtKSA9PiBtLmZyb20gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVAgJiYgbS50byA9PT0gRUNEU0FVdGlscy5NUEN2MlBhcnRpZXNFbnVtLlVTRVJcbiAgICAgICAgKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGJhY2t1cFRvVXNlck1zZzMsICdiYWNrdXBUb1VzZXJNc2czIG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIGNvbnN0IHRvQmFja3VwUm91bmQzTWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZGVjcnlwdEFuZFZlcmlmeUluY29taW5nTWVzc2FnZXMoXG4gICAgICAgICAge1xuICAgICAgICAgICAgcDJwTWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC4uLk9WQzFUb09WQzJSb3VuZDNQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uT05FXS5vdmNUb092Y01zZzMsXG4gICAgICAgICAgICAgICAgY29tbWl0bWVudDogT1ZDMVRvT1ZDMlJvdW5kM1BheWxvYWQub3ZjW09WQ0luZGV4RW51bS5PTkVdLm92Y1RvT3ZjTXNnMi5jb21taXRtZW50LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgLi4uT1ZDMVRvT1ZDMlJvdW5kM1BheWxvYWQucGxhdGZvcm0ub3ZjW09WQ0luZGV4RW51bS5UV09dLmJpdGdvVG9PdmNNc2czLFxuICAgICAgICAgICAgICAgIGNvbW1pdG1lbnQ6IE9WQzFUb09WQzJSb3VuZDNQYXlsb2FkLnBsYXRmb3JtLmJpdGdvQ29tbWl0bWVudDIsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgW2JpdGdvR3BnUHViS2V5LCB7IHBhcnR5SWQ6IDAsIGdwZ0tleTogT1ZDMVRvT1ZDMlJvdW5kM1BheWxvYWQub3ZjW09WQ0luZGV4RW51bS5PTkVdLmdwZ1B1YktleSB9XSxcbiAgICAgICAgICBbYmFja3VwR3BnUHJ2S2V5XVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGJhY2t1cFJvdW5kNE1lc3NhZ2VzID0gYmFja3VwU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKHtcbiAgICAgICAgICBwMnBNZXNzYWdlczogdG9CYWNrdXBSb3VuZDNNZXNzYWdlcy5wMnBNZXNzYWdlcy5tYXAoRGtsc1R5cGVzLmRlc2VyaWFsaXplUDJQTWVzc2FnZSksXG4gICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgICB9KS5icm9hZGNhc3RNZXNzYWdlcztcblxuICAgICAgICBjb25zdCBiYWNrdXBSb3VuZDRCcm9hZGNhc3RNZXNzYWdlcyA9IGF3YWl0IERrbHNDb21tcy5lbmNyeXB0QW5kQXV0aE91dGdvaW5nTWVzc2FnZXMoXG4gICAgICAgICAgRGtsc1R5cGVzLnNlcmlhbGl6ZU1lc3NhZ2VzKHtcbiAgICAgICAgICAgIHAycE1lc3NhZ2VzOiBbXSxcbiAgICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBiYWNrdXBSb3VuZDRNZXNzYWdlcyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBbXSxcbiAgICAgICAgICBbYmFja3VwR3BnUHJ2S2V5XVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGJhY2t1cE1zZzQgPSBiYWNrdXBSb3VuZDRCcm9hZGNhc3RNZXNzYWdlcy5icm9hZGNhc3RNZXNzYWdlcy5maW5kKFxuICAgICAgICAgIChtKSA9PiBtLmZyb20gPT09IEVDRFNBVXRpbHMuTVBDdjJQYXJ0aWVzRW51bS5CQUNLVVBcbiAgICAgICAgKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGJhY2t1cE1zZzQsICdiYWNrdXBNc2c0IG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIE9WQzJUb09WQzFSb3VuZDNQYXlsb2FkID0ge1xuICAgICAgICAgIC4uLk9WQzFUb09WQzJSb3VuZDNQYXlsb2FkLFxuICAgICAgICAgIHN0YXRlOiBLZXlDcmVhdGlvbk1QQ3YyU3RhdGVFbnVtLldhaXRpbmdGb3JPVkMxUm91bmQzYkRhdGEsXG4gICAgICAgICAgb3ZjOiB7XG4gICAgICAgICAgICAuLi5PVkMxVG9PVkMyUm91bmQzUGF5bG9hZC5vdmMsXG4gICAgICAgICAgICBbT1ZDSW5kZXhFbnVtLlRXT106IE9iamVjdC5hc3NpZ24oT1ZDMVRvT1ZDMlJvdW5kM1BheWxvYWQub3ZjW09WQ0luZGV4RW51bS5UV09dLCB7XG4gICAgICAgICAgICAgIG92Y1RvT3ZjTXNnMzogYmFja3VwVG9Vc2VyTXNnMyxcbiAgICAgICAgICAgICAgb3ZjVG9CaXRnb01zZzM6IGJhY2t1cFRvQml0Z29Nc2czLFxuICAgICAgICAgICAgICBvdmNNc2c0OiBiYWNrdXBNc2c0LFxuICAgICAgICAgICAgfSkgYXMgYW55LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFJvdW5kIDNCIFVzZXJcbiAgICAgIGxldCBPVkMxVG9CaXRnb1JvdW5kM0JQYXlsb2FkOiBPVkMxVG9CaXRnb1JvdW5kM1BheWxvYWQ7XG4gICAgICB7XG4gICAgICAgIGFzc2VydC5vayhPVkMyVG9PVkMxUm91bmQzUGF5bG9hZC5zdGF0ZSA9PT0gNywgJ09WQzJUb09WQzFSb3VuZDNQYXlsb2FkLnN0YXRlIHNob3VsZCBiZSA3Jyk7XG4gICAgICAgIGNvbnN0IHRvVXNlclJvdW5kNE1lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHAycE1lc3NhZ2VzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAuLi5PVkMyVG9PVkMxUm91bmQzUGF5bG9hZC5vdmNbT1ZDSW5kZXhFbnVtLlRXT10ub3ZjVG9PdmNNc2czLFxuICAgICAgICAgICAgICAgIGNvbW1pdG1lbnQ6IE9WQzJUb09WQzFSb3VuZDNQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uVFdPXS5vdmNUb092Y01zZzIuY29tbWl0bWVudCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC4uLk9WQzJUb09WQzFSb3VuZDNQYXlsb2FkLnBsYXRmb3JtLm92Y1tPVkNJbmRleEVudW0uT05FXS5iaXRnb1RvT3ZjTXNnMyxcbiAgICAgICAgICAgICAgICBjb21taXRtZW50OiBPVkMyVG9PVkMxUm91bmQzUGF5bG9hZC5wbGF0Zm9ybS5iaXRnb0NvbW1pdG1lbnQyLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbXSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIFtiaXRnb0dwZ1B1YktleSwgeyBwYXJ0eUlkOiAxLCBncGdLZXk6IE9WQzJUb09WQzFSb3VuZDNQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uVFdPXS5ncGdQdWJLZXkgfV0sXG4gICAgICAgICAgW3VzZXJHcGdQcnZLZXldXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgdXNlclJvdW5kNEJyb2FkY2FzdE1lc3NhZ2VzID0gdXNlclNlc3Npb24uaGFuZGxlSW5jb21pbmdNZXNzYWdlcyh7XG4gICAgICAgICAgcDJwTWVzc2FnZXM6IHRvVXNlclJvdW5kNE1lc3NhZ2VzLnAycE1lc3NhZ2VzLm1hcChEa2xzVHlwZXMuZGVzZXJpYWxpemVQMlBNZXNzYWdlKSxcbiAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gICAgICAgIH0pLmJyb2FkY2FzdE1lc3NhZ2VzO1xuICAgICAgICBhc3NlcnQub2sodXNlclJvdW5kNEJyb2FkY2FzdE1lc3NhZ2VzLmxlbmd0aCA9PT0gMSwgJ3VzZXJSb3VuZDRCcm9hZGNhc3RNZXNzYWdlcyBsZW5ndGggc2hvdWxkIGJlIDEnKTtcblxuICAgICAgICBjb25zdCB1c2VyUm91bmQ0TWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZW5jcnlwdEFuZEF1dGhPdXRnb2luZ01lc3NhZ2VzKFxuICAgICAgICAgIERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyh7XG4gICAgICAgICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICAgICAgICBicm9hZGNhc3RNZXNzYWdlczogdXNlclJvdW5kNEJyb2FkY2FzdE1lc3NhZ2VzLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIFtdLFxuICAgICAgICAgIFt1c2VyR3BnUHJ2S2V5XVxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IHVzZXJNc2c0ID0gdXNlclJvdW5kNE1lc3NhZ2VzLmJyb2FkY2FzdE1lc3NhZ2VzLmZpbmQoKG0pID0+IG0uZnJvbSA9PT0gRUNEU0FVdGlscy5NUEN2MlBhcnRpZXNFbnVtLlVTRVIpO1xuICAgICAgICBhc3NlcnQub2sodXNlck1zZzQsICd1c2VyTXNnNCBub3QgZm91bmQnKTtcblxuICAgICAgICBPVkMxVG9CaXRnb1JvdW5kM0JQYXlsb2FkID0ge1xuICAgICAgICAgIC4uLk9WQzJUb09WQzFSb3VuZDNQYXlsb2FkLFxuICAgICAgICAgIHN0YXRlOiBLZXlDcmVhdGlvbk1QQ3YyU3RhdGVFbnVtLldhaXRpbmdGb3JCaXRnb1JvdW5kM0RhdGEsXG4gICAgICAgICAgb3ZjOiB7XG4gICAgICAgICAgICAuLi5PVkMyVG9PVkMxUm91bmQzUGF5bG9hZC5vdmMsXG4gICAgICAgICAgICBbT1ZDSW5kZXhFbnVtLk9ORV06IE9iamVjdC5hc3NpZ24oT1ZDMlRvT1ZDMVJvdW5kM1BheWxvYWQub3ZjW09WQ0luZGV4RW51bS5PTkVdLCB7XG4gICAgICAgICAgICAgIG92Y01zZzQ6IHVzZXJNc2c0LFxuICAgICAgICAgICAgfSkgYXMgYW55LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIC8vIFJvdW5kIDMgQml0R29cbiAgICAgIC8vIGNyZWF0ZXMgYml0Z28ga2V5Y2hhaW5cbiAgICAgIGNvbnN0IGJpdGdvVG9PVkMxUm91bmQzUGF5bG9hZCA9IGF3YWl0IE1QQ3YyU01DVXRpbHMua2V5R2VuUm91bmQzKCd0ZXN0SWQnLCBPVkMxVG9CaXRnb1JvdW5kM0JQYXlsb2FkKTtcblxuICAgICAgLy8gUm91bmQgNCBVc2VyXG4gICAgICBsZXQgdXNlckNvbW1vbktleWNoYWluOiBzdHJpbmc7XG4gICAgICBsZXQgT1ZDMVRvT1ZDMlJvdW5kNFBheWxvYWQ7XG4gICAgICB7XG4gICAgICAgIGFzc2VydC5vayhiaXRnb1RvT1ZDMVJvdW5kM1BheWxvYWQuc3RhdGUgPT09IDksICdiaXRnb1RvT1ZDMVJvdW5kM1BheWxvYWQuc3RhdGUgc2hvdWxkIGJlIDknKTtcbiAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvVG9PVkMxUm91bmQzUGF5bG9hZC5iaXRHb0tleUlkLCAnYml0Z29Ub09WQzFSb3VuZDNQYXlsb2FkLmJpdEdvS2V5SWQgbm90IGZvdW5kJyk7XG4gICAgICAgIGNvbnN0IHRvVXNlckJpdGdvUm91bmQzTXNnID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHAycE1lc3NhZ2VzOiBbXSxcbiAgICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbXG4gICAgICAgICAgICAgIGJpdGdvVG9PVkMxUm91bmQzUGF5bG9hZC5vdmNbT1ZDSW5kZXhFbnVtLlRXT10ub3ZjTXNnNCxcbiAgICAgICAgICAgICAgYml0Z29Ub09WQzFSb3VuZDNQYXlsb2FkLnBsYXRmb3JtLmJpdGdvTXNnNCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBbYml0Z29HcGdQdWJLZXksIHsgcGFydHlJZDogMSwgZ3BnS2V5OiBiaXRnb1RvT1ZDMVJvdW5kM1BheWxvYWQub3ZjW09WQ0luZGV4RW51bS5UV09dLmdwZ1B1YktleSB9XSxcbiAgICAgICAgICBbdXNlckdwZ1BydktleV1cbiAgICAgICAgKTtcblxuICAgICAgICB1c2VyU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKHtcbiAgICAgICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IHRvVXNlckJpdGdvUm91bmQzTXNnLmJyb2FkY2FzdE1lc3NhZ2VzLm1hcChEa2xzVHlwZXMuZGVzZXJpYWxpemVCcm9hZGNhc3RNZXNzYWdlKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgdXNlclByaXZhdGVNYXRlcmlhbCA9IHVzZXJTZXNzaW9uLmdldEtleVNoYXJlKCk7XG4gICAgICAgIHVzZXJDb21tb25LZXljaGFpbiA9IERrbHNUeXBlcy5nZXRDb21tb25LZXljaGFpbih1c2VyUHJpdmF0ZU1hdGVyaWFsKTtcbiAgICAgICAgYXNzZXJ0LmVxdWFsKFxuICAgICAgICAgIGJpdGdvVG9PVkMxUm91bmQzUGF5bG9hZC5wbGF0Zm9ybS5jb21tb25LZXljaGFpbixcbiAgICAgICAgICB1c2VyQ29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgJ1VzZXIgYW5kIEJpdGdvIENvbW1vbiBrZXljaGFpbnMgZG8gbm90IG1hdGNoJ1xuICAgICAgICApO1xuICAgICAgICBjb25zdCB1c2VyUHJ2ID0gdXNlclByaXZhdGVNYXRlcmlhbC50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgICAgIGFzc2VydC5vayh1c2VyUHJ2LCAndXNlclBydiBub3QgZm91bmQnKTtcblxuICAgICAgICBPVkMxVG9PVkMyUm91bmQ0UGF5bG9hZCA9IHtcbiAgICAgICAgICBiaXRnb0tleUlkOiBiaXRnb1RvT1ZDMVJvdW5kM1BheWxvYWQuYml0R29LZXlJZCxcbiAgICAgICAgICAuLi5iaXRnb1RvT1ZDMVJvdW5kM1BheWxvYWQsXG4gICAgICAgICAgc3RhdGU6IEtleUNyZWF0aW9uTVBDdjJTdGF0ZUVudW0uV2FpdGluZ0Zvck9WQzJHZW5lcmF0ZUtleSxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgLy8gUm91bmQgNCBCYWNrdXBcbiAgICAgIGxldCBiYWNrdXBDb21tb25LZXljaGFpbjogc3RyaW5nO1xuICAgICAge1xuICAgICAgICBhc3NlcnQub2soT1ZDMVRvT1ZDMlJvdW5kNFBheWxvYWQuc3RhdGUgPT09IDEwLCAnT1ZDMVRvT1ZDMlJvdW5kNFBheWxvYWQuc3RhdGUgc2hvdWxkIGJlIDEwJyk7XG4gICAgICAgIGFzc2VydC5vayhPVkMxVG9PVkMyUm91bmQ0UGF5bG9hZC5iaXRnb0tleUlkLCAnT1ZDMVRvT1ZDMlJvdW5kNFBheWxvYWQuYml0R29LZXlJZCBub3QgZm91bmQnKTtcblxuICAgICAgICBjb25zdCB0b0JhY2t1cEJpdGdvUm91bmQzTXNnID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHAycE1lc3NhZ2VzOiBbXSxcbiAgICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbXG4gICAgICAgICAgICAgIE9WQzFUb09WQzJSb3VuZDRQYXlsb2FkLm92Y1tPVkNJbmRleEVudW0uT05FXS5vdmNNc2c0LFxuICAgICAgICAgICAgICBPVkMxVG9PVkMyUm91bmQ0UGF5bG9hZC5wbGF0Zm9ybS5iaXRnb01zZzQsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgW2JpdGdvR3BnUHViS2V5LCB7IHBhcnR5SWQ6IDAsIGdwZ0tleTogT1ZDMVRvT1ZDMlJvdW5kNFBheWxvYWQub3ZjW09WQ0luZGV4RW51bS5PTkVdLmdwZ1B1YktleSB9XSxcbiAgICAgICAgICBbYmFja3VwR3BnUHJ2S2V5XVxuICAgICAgICApO1xuXG4gICAgICAgIGJhY2t1cFNlc3Npb24uaGFuZGxlSW5jb21pbmdNZXNzYWdlcyh7XG4gICAgICAgICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiB0b0JhY2t1cEJpdGdvUm91bmQzTXNnLmJyb2FkY2FzdE1lc3NhZ2VzLm1hcChEa2xzVHlwZXMuZGVzZXJpYWxpemVCcm9hZGNhc3RNZXNzYWdlKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgYmFja3VwUHJpdmF0ZU1hdGVyaWFsID0gYmFja3VwU2Vzc2lvbi5nZXRLZXlTaGFyZSgpO1xuICAgICAgICBiYWNrdXBDb21tb25LZXljaGFpbiA9IERrbHNUeXBlcy5nZXRDb21tb25LZXljaGFpbihiYWNrdXBQcml2YXRlTWF0ZXJpYWwpO1xuICAgICAgICBhc3NlcnQuZXF1YWwoXG4gICAgICAgICAgT1ZDMVRvT1ZDMlJvdW5kNFBheWxvYWQucGxhdGZvcm0uY29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgYmFja3VwQ29tbW9uS2V5Y2hhaW4sXG4gICAgICAgICAgJ0JhY2t1cCBhbmQgQml0Z28gQ29tbW9uIGtleWNoYWlucyBkbyBub3QgbWF0Y2gnXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGJhY2t1cFBydiA9IGJhY2t1cFByaXZhdGVNYXRlcmlhbC50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgICAgIGFzc2VydC5vayhiYWNrdXBQcnYsICdiYWNrdXBQcnYgbm90IGZvdW5kJyk7XG4gICAgICB9XG5cbiAgICAgIC8vIFJvdW5kIDQgQml0R29cbiAgICAgIC8vIGNyZWF0ZXMgdXNlciBhbmQgYmFja3VwIGtleWNoYWluXG4gICAgICBjb25zdCBrZXljaGFpbnMgPSBhd2FpdCBNUEN2MlNNQ1V0aWxzLnVwbG9hZENsaWVudEtleXMoXG4gICAgICAgIGJpdGdvVG9PVkMxUm91bmQzUGF5bG9hZC5iaXRHb0tleUlkLFxuICAgICAgICB1c2VyQ29tbW9uS2V5Y2hhaW4sXG4gICAgICAgIGJhY2t1cENvbW1vbktleWNoYWluXG4gICAgICApO1xuICAgICAgYXNzZXJ0LmRlZXBFcXVhbChrZXljaGFpbnMudXNlcktleWNoYWluLCB7XG4gICAgICAgIGNvbW1vbktleWNoYWluOiB1c2VyQ29tbW9uS2V5Y2hhaW4sXG4gICAgICAgIHR5cGU6ICd0c3MnLFxuICAgICAgICBzb3VyY2U6ICd1c2VyJyxcbiAgICAgICAgaWQ6ICd1c2VyJyxcbiAgICAgIH0pO1xuICAgICAgYXNzZXJ0LmRlZXBFcXVhbChrZXljaGFpbnMuYmFja3VwS2V5Y2hhaW4sIHtcbiAgICAgICAgY29tbW9uS2V5Y2hhaW46IGJhY2t1cENvbW1vbktleWNoYWluLFxuICAgICAgICB0eXBlOiAndHNzJyxcbiAgICAgICAgc291cmNlOiAnYmFja3VwJyxcbiAgICAgICAgaWQ6ICdiYWNrdXAnLFxuICAgICAgfSk7XG4gICAgICBhc3NlcnQub2socm91bmQxTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2socm91bmQyTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2socm91bmQzTm9jay5pc0RvbmUoKSk7XG4gICAgICBhc3NlcnQub2soYWRkS2V5Tm9jay5pc0RvbmUoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHRocm93IGZvciBNUEN2MiBTTUMgdXRpbHMgaWYgdGhlIHN0YXRlIGlzIGludmFsaWQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBNUEN2MlNNQ1V0aWxzID0gbmV3IEVDRFNBVXRpbHMuTVBDdjJTTUNVdGlscyhiaXRnbywgYmFzZUNvaW4pO1xuICAgICAgY29uc3QgaW52YWxpZFBheWxvYWQgPSB7XG4gICAgICAgIHN0YXRlOiBLZXlDcmVhdGlvbk1QQ3YyU3RhdGVFbnVtLldhaXRpbmdGb3JPVkMxUm91bmQyRGF0YSxcbiAgICAgIH0gYXMgYW55O1xuXG4gICAgICBhd2FpdCBhc3NlcnQucmVqZWN0cyhhc3luYyAoKSA9PiBhd2FpdCBNUEN2MlNNQ1V0aWxzLmtleUdlblJvdW5kMSgndGVzdElkJywgaW52YWxpZFBheWxvYWQpLCB7XG4gICAgICAgIG1lc3NhZ2U6IGBJbnZhbGlkIHN0YXRlIGZvciByb3VuZCAxLCBleHBlY3RlZDogJHtLZXlDcmVhdGlvbk1QQ3YyU3RhdGVFbnVtLldhaXRpbmdGb3JCaXRnb1JvdW5kMURhdGF9LCBnb3Q6ICR7S2V5Q3JlYXRpb25NUEN2MlN0YXRlRW51bS5XYWl0aW5nRm9yT1ZDMVJvdW5kMkRhdGF9YCxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgYXNzZXJ0LnJlamVjdHMoYXN5bmMgKCkgPT4gYXdhaXQgTVBDdjJTTUNVdGlscy5rZXlHZW5Sb3VuZDIoJ3Rlc3RJZCcsIGludmFsaWRQYXlsb2FkKSwge1xuICAgICAgICBtZXNzYWdlOiBgSW52YWxpZCBzdGF0ZSBmb3Igcm91bmQgMiwgZXhwZWN0ZWQ6ICR7S2V5Q3JlYXRpb25NUEN2MlN0YXRlRW51bS5XYWl0aW5nRm9yQml0Z29Sb3VuZDJEYXRhfSwgZ290OiAke0tleUNyZWF0aW9uTVBDdjJTdGF0ZUVudW0uV2FpdGluZ0Zvck9WQzFSb3VuZDJEYXRhfWAsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IGFzc2VydC5yZWplY3RzKGFzeW5jICgpID0+IGF3YWl0IE1QQ3YyU01DVXRpbHMua2V5R2VuUm91bmQzKCd0ZXN0SWQnLCBpbnZhbGlkUGF5bG9hZCksIHtcbiAgICAgICAgbWVzc2FnZTogYEludmFsaWQgc3RhdGUgZm9yIHJvdW5kIDMsIGV4cGVjdGVkOiAke0tleUNyZWF0aW9uTVBDdjJTdGF0ZUVudW0uV2FpdGluZ0ZvckJpdGdvUm91bmQzRGF0YX0sIGdvdDogJHtLZXlDcmVhdGlvbk1QQ3YyU3RhdGVFbnVtLldhaXRpbmdGb3JPVkMxUm91bmQyRGF0YX1gLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGFzeW5jIGZ1bmN0aW9uIG5vY2tLZXljaGFpbihcbiAgICBwYXJhbXM6IHtcbiAgICAgIGNvaW46IHN0cmluZztcbiAgICAgIGtleUNoYWluOiBLZXljaGFpbjtcbiAgICAgIHNvdXJjZTogJ3VzZXInIHwgJ2JhY2t1cCcgfCAnYml0Z28nO1xuICAgIH0sXG4gICAgdGltZXMgPSAxXG4gICk6IFByb21pc2U8S2V5Y2hhaW4+IHtcbiAgICBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvJHtwYXJhbXMuY29pbn0va2V5YCwgKGJvZHkpID0+IHtcbiAgICAgICAgcmV0dXJuIGJvZHkua2V5VHlwZSA9PT0gJ3RzcycgJiYgYm9keS5zb3VyY2UgPT09IHBhcmFtcy5zb3VyY2U7XG4gICAgICB9KVxuICAgICAgLnRpbWVzKHRpbWVzKVxuICAgICAgLnJlcGx5KDIwMCwgcGFyYW1zLmtleUNoYWluKTtcblxuICAgIHJldHVybiBwYXJhbXMua2V5Q2hhaW47XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrR2V0Qml0Z29QdWJsaWNLZXlCYXNlZE9uRmVhdHVyZUZsYWdzKFxuICAgIGNvaW46IHN0cmluZyxcbiAgICBlbnRlcnByaXNlSWQ6IHN0cmluZyxcbiAgICBiaXRnb0dwZ0tleVBhaXI6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPlxuICApOiBQcm9taXNlPEJpdGdvR1BHUHVibGljS2V5PiB7XG4gICAgY29uc3QgYml0Z29HUEdQdWJsaWNLZXlSZXNwb25zZTogQml0Z29HUEdQdWJsaWNLZXkgPSB7XG4gICAgICBuYW1lOiAnaXJyZWxldmFudCcsXG4gICAgICBwdWJsaWNLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgICBtcGN2MlB1YmxpY0tleTogYml0Z29HcGdLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgIGVudGVycHJpc2VJZCxcbiAgICB9O1xuICAgIG5vY2soYmdVcmwpLmdldChgL2FwaS92Mi8ke2NvaW59L3Rzcy9wdWJrZXlgKS5xdWVyeSh7IGVudGVycHJpc2VJZCB9KS5yZXBseSgyMDAsIGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2UpO1xuXG4gICAgcmV0dXJuIGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2U7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrS2V5R2VuUm91bmQxKGJpdGdvU2Vzc2lvbjogRGtsc0RrZy5Ea2csIHRpbWVzID0gMSkge1xuICAgIHJldHVybiBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvbXBjL2dlbmVyYXRla2V5YCwgKGJvZHkpID0+IGJvZHkucm91bmQgPT09ICdNUEN2Mi1SMScpXG4gICAgICAudGltZXModGltZXMpXG4gICAgICAucmVwbHkoXG4gICAgICAgIDIwMCxcbiAgICAgICAgYXN5bmMgKHVyaSwgeyBwYXlsb2FkIH06IHsgcGF5bG9hZDogTVBDdjJLZXlHZW5Sb3VuZDFSZXF1ZXN0IH0pOiBQcm9taXNlPE1QQ3YyS2V5R2VuUm91bmQxUmVzcG9uc2U+ID0+IHtcbiAgICAgICAgICBjb25zdCB7IHVzZXJHcGdQdWJsaWNLZXksIGJhY2t1cEdwZ1B1YmxpY0tleSwgdXNlck1zZzEsIGJhY2t1cE1zZzEgfSA9IHBheWxvYWQ7XG4gICAgICAgICAgdXNlckdwZ1B1YktleSA9IHtcbiAgICAgICAgICAgIHBhcnR5SWQ6IDAsXG4gICAgICAgICAgICBncGdLZXk6IHVzZXJHcGdQdWJsaWNLZXksXG4gICAgICAgICAgfTtcbiAgICAgICAgICBiYWNrdXBHcGdQdWJLZXkgPSB7XG4gICAgICAgICAgICBwYXJ0eUlkOiAxLFxuICAgICAgICAgICAgZ3BnS2V5OiBiYWNrdXBHcGdQdWJsaWNLZXksXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGNvbnN0IGJpdGdvQnJvYWRjYXN0TXNnMVVuc2lnbmVkID0gYXdhaXQgYml0Z29TZXNzaW9uLmluaXREa2coKTtcbiAgICAgICAgICBjb25zdCBiaXRnb01zZ3MxU2lnbmVkID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICAgIHsgYnJvYWRjYXN0TWVzc2FnZXM6IFtEa2xzVHlwZXMuc2VyaWFsaXplQnJvYWRjYXN0TWVzc2FnZShiaXRnb0Jyb2FkY2FzdE1zZzFVbnNpZ25lZCldLCBwMnBNZXNzYWdlczogW10gfSxcbiAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgW2JpdGdvR3BnUHJ2S2V5XVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgYml0Z29Nc2cxID0gYml0Z29Nc2dzMVNpZ25lZC5icm9hZGNhc3RNZXNzYWdlcy5maW5kKChtKSA9PiBtLmZyb20gPT09IDIpO1xuICAgICAgICAgIGFzc2VydC5vayhiaXRnb01zZzEsICdiaXRnb01zZzEgbm90IGZvdW5kJyk7XG5cbiAgICAgICAgICBjb25zdCByb3VuZDFJbmNvbWluZ01zZ3MgPSBhd2FpdCBEa2xzQ29tbXMuZGVjcnlwdEFuZFZlcmlmeUluY29taW5nTWVzc2FnZXMoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHAycE1lc3NhZ2VzOiBbXSxcbiAgICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAgICB7IGZyb206IDAsIHBheWxvYWQ6IHVzZXJNc2cxIH0sXG4gICAgICAgICAgICAgICAgeyBmcm9tOiAxLCBwYXlsb2FkOiBiYWNrdXBNc2cxIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW3VzZXJHcGdQdWJLZXksIGJhY2t1cEdwZ1B1YktleV0sXG4gICAgICAgICAgICBbYml0Z29HcGdQcnZLZXldXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHJvdW5kMk1lc3NhZ2VzID0gRGtsc1R5cGVzLnNlcmlhbGl6ZU1lc3NhZ2VzKFxuICAgICAgICAgICAgYml0Z29TZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoRGtsc1R5cGVzLmRlc2VyaWFsaXplTWVzc2FnZXMocm91bmQxSW5jb21pbmdNc2dzKSlcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3Qgcm91bmQyU2lnbmVkTWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZW5jcnlwdEFuZEF1dGhPdXRnb2luZ01lc3NhZ2VzKFxuICAgICAgICAgICAgcm91bmQyTWVzc2FnZXMsXG4gICAgICAgICAgICBbdXNlckdwZ1B1YktleSwgYmFja3VwR3BnUHViS2V5XSxcbiAgICAgICAgICAgIFtiaXRnb0dwZ1BydktleV1cbiAgICAgICAgICApO1xuXG4gICAgICAgICAgY29uc3QgYml0Z29Ub1VzZXJNc2cyID0gcm91bmQyU2lnbmVkTWVzc2FnZXMucDJwTWVzc2FnZXMuZmluZCgobSkgPT4gbS50byA9PT0gMCk7XG4gICAgICAgICAgY29uc3QgYml0Z29Ub0JhY2t1cE1zZzIgPSByb3VuZDJTaWduZWRNZXNzYWdlcy5wMnBNZXNzYWdlcy5maW5kKChtKSA9PiBtLnRvID09PSAxKTtcbiAgICAgICAgICBhc3NlcnQub2soYml0Z29Ub1VzZXJNc2cyLCAnYml0Z29Ub1VzZXJNc2cyIG5vdCBmb3VuZCcpO1xuICAgICAgICAgIGFzc2VydC5vayhiaXRnb1RvQmFja3VwTXNnMiwgJ2JpdGdvVG9CYWNrdXBNc2cyIG5vdCBmb3VuZCcpO1xuICAgICAgICAgIGFzc2VydC5vayhiaXRnb1RvVXNlck1zZzIuY29tbWl0bWVudCwgJ2JpdGdvVG9Vc2VyTXNnMi5jb21taXRtZW50IG5vdCBmb3VuZCcpO1xuXG4gICAgICAgICAgc3RvcmVkQml0Z29Db21taXRtZW50MiA9IGJpdGdvVG9Vc2VyTXNnMj8uY29tbWl0bWVudDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgc2Vzc2lvbklkOiAndGVzdGlkJyBhcyBOb25FbXB0eVN0cmluZyxcbiAgICAgICAgICAgIGJpdGdvTXNnMTogeyBmcm9tOiAyLCAuLi5iaXRnb01zZzEucGF5bG9hZCB9LFxuICAgICAgICAgICAgYml0Z29Ub0JhY2t1cE1zZzI6IHtcbiAgICAgICAgICAgICAgZnJvbTogMixcbiAgICAgICAgICAgICAgdG86IDEsXG4gICAgICAgICAgICAgIGVuY3J5cHRlZE1lc3NhZ2U6IGJpdGdvVG9CYWNrdXBNc2cyLnBheWxvYWQuZW5jcnlwdGVkTWVzc2FnZSxcbiAgICAgICAgICAgICAgc2lnbmF0dXJlOiBiaXRnb1RvQmFja3VwTXNnMi5wYXlsb2FkLnNpZ25hdHVyZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBiaXRnb1RvVXNlck1zZzI6IHtcbiAgICAgICAgICAgICAgZnJvbTogMixcbiAgICAgICAgICAgICAgdG86IDAsXG4gICAgICAgICAgICAgIGVuY3J5cHRlZE1lc3NhZ2U6IGJpdGdvVG9Vc2VyTXNnMi5wYXlsb2FkLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgICAgICAgIHNpZ25hdHVyZTogYml0Z29Ub1VzZXJNc2cyLnBheWxvYWQuc2lnbmF0dXJlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdhbGxldEdwZ1B1YktleVNpZ3M6ICdzb21ldGhpbmcnIGFzIE5vbkVtcHR5U3RyaW5nLFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrS2V5R2VuUm91bmQyKGJpdGdvU2Vzc2lvbjogRGtsc0RrZy5Ea2csIHRpbWVzID0gMSkge1xuICAgIHJldHVybiBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvbXBjL2dlbmVyYXRla2V5YCwgKGJvZHkpID0+IGJvZHkucm91bmQgPT09ICdNUEN2Mi1SMicpXG4gICAgICAudGltZXModGltZXMpXG4gICAgICAucmVwbHkoXG4gICAgICAgIDIwMCxcbiAgICAgICAgYXN5bmMgKHVyaSwgeyBwYXlsb2FkIH06IHsgcGF5bG9hZDogTVBDdjJLZXlHZW5Sb3VuZDJSZXF1ZXN0IH0pOiBQcm9taXNlPE1QQ3YyS2V5R2VuUm91bmQyUmVzcG9uc2U+ID0+IHtcbiAgICAgICAgICBjb25zdCB7IHNlc3Npb25JZCwgdXNlck1zZzIsIGJhY2t1cE1zZzIsIHVzZXJDb21taXRtZW50MiwgYmFja3VwQ29tbWl0bWVudDIgfSA9IHBheWxvYWQ7XG4gICAgICAgICAgc3RvcmVkVXNlckNvbW1pdG1lbnQyID0gdXNlckNvbW1pdG1lbnQyO1xuICAgICAgICAgIHN0b3JlZEJhY2t1cENvbW1pdG1lbnQyID0gYmFja3VwQ29tbWl0bWVudDI7XG4gICAgICAgICAgY29uc3Qgcm91bmQySW5jb21pbmdNc2dzID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBwMnBNZXNzYWdlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGZyb206IHVzZXJNc2cyLmZyb20sXG4gICAgICAgICAgICAgICAgICB0bzogdXNlck1zZzIudG8sXG4gICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IHNpZ25hdHVyZTogdXNlck1zZzIuc2lnbmF0dXJlLCBlbmNyeXB0ZWRNZXNzYWdlOiB1c2VyTXNnMi5lbmNyeXB0ZWRNZXNzYWdlIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBmcm9tOiBiYWNrdXBNc2cyLmZyb20sXG4gICAgICAgICAgICAgICAgICB0bzogYmFja3VwTXNnMi50byxcbiAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgc2lnbmF0dXJlOiBiYWNrdXBNc2cyLnNpZ25hdHVyZSwgZW5jcnlwdGVkTWVzc2FnZTogYmFja3VwTXNnMi5lbmNyeXB0ZWRNZXNzYWdlIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFt1c2VyR3BnUHViS2V5LCBiYWNrdXBHcGdQdWJLZXldLFxuICAgICAgICAgICAgW2JpdGdvR3BnUHJ2S2V5XVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCByb3VuZDNNZXNzYWdlcyA9IERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyhcbiAgICAgICAgICAgIGJpdGdvU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKERrbHNUeXBlcy5kZXNlcmlhbGl6ZU1lc3NhZ2VzKHJvdW5kMkluY29taW5nTXNncykpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IHJvdW5kM1NpZ25lZE1lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICAgIHJvdW5kM01lc3NhZ2VzLFxuICAgICAgICAgICAgW3VzZXJHcGdQdWJLZXksIGJhY2t1cEdwZ1B1YktleV0sXG4gICAgICAgICAgICBbYml0Z29HcGdQcnZLZXldXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGNvbnN0IGJpdGdvVG9Vc2VyTXNnMyA9IHJvdW5kM1NpZ25lZE1lc3NhZ2VzLnAycE1lc3NhZ2VzLmZpbmQoKG0pID0+IG0udG8gPT09IDApO1xuICAgICAgICAgIGNvbnN0IGJpdGdvVG9CYWNrdXBNc2czID0gcm91bmQzU2lnbmVkTWVzc2FnZXMucDJwTWVzc2FnZXMuZmluZCgobSkgPT4gbS50byA9PT0gMSk7XG4gICAgICAgICAgYXNzZXJ0Lm9rKGJpdGdvVG9Vc2VyTXNnMywgJ2JpdGdvVG9Vc2VyTXNnMyBub3QgZm91bmQnKTtcbiAgICAgICAgICBhc3NlcnQub2soYml0Z29Ub0JhY2t1cE1zZzMsICdiaXRnb1RvQmFja3VwTXNnMyBub3QgZm91bmQnKTtcblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBzZXNzaW9uSWQsXG4gICAgICAgICAgICBiaXRnb0NvbW1pdG1lbnQyOiBzdG9yZWRCaXRnb0NvbW1pdG1lbnQyIGFzIE5vbkVtcHR5U3RyaW5nLFxuICAgICAgICAgICAgYml0Z29Ub1VzZXJNc2czOiB7XG4gICAgICAgICAgICAgIGZyb206IDIsXG4gICAgICAgICAgICAgIHRvOiAwLFxuICAgICAgICAgICAgICBlbmNyeXB0ZWRNZXNzYWdlOiBiaXRnb1RvVXNlck1zZzMucGF5bG9hZC5lbmNyeXB0ZWRNZXNzYWdlLFxuICAgICAgICAgICAgICBzaWduYXR1cmU6IGJpdGdvVG9Vc2VyTXNnMy5wYXlsb2FkLnNpZ25hdHVyZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBiaXRnb1RvQmFja3VwTXNnMzoge1xuICAgICAgICAgICAgICBmcm9tOiAyLFxuICAgICAgICAgICAgICB0bzogMSxcbiAgICAgICAgICAgICAgZW5jcnlwdGVkTWVzc2FnZTogYml0Z29Ub0JhY2t1cE1zZzMucGF5bG9hZC5lbmNyeXB0ZWRNZXNzYWdlLFxuICAgICAgICAgICAgICBzaWduYXR1cmU6IGJpdGdvVG9CYWNrdXBNc2czLnBheWxvYWQuc2lnbmF0dXJlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICApO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gbm9ja0tleUdlblJvdW5kMyhiaXRnb1Nlc3Npb246IERrbHNEa2cuRGtnLCB0aW1lcyA9IDEpIHtcbiAgICByZXR1cm4gbm9jayhiZ1VybClcbiAgICAgIC5wb3N0KGAvYXBpL3YyL21wYy9nZW5lcmF0ZWtleWAsIChib2R5KSA9PiBib2R5LnJvdW5kID09PSAnTVBDdjItUjMnKVxuICAgICAgLnRpbWVzKHRpbWVzKVxuICAgICAgLnJlcGx5KFxuICAgICAgICAyMDAsXG4gICAgICAgIGFzeW5jICh1cmksIHsgcGF5bG9hZCB9OiB7IHBheWxvYWQ6IE1QQ3YyS2V5R2VuUm91bmQzUmVxdWVzdCB9KTogUHJvbWlzZTxNUEN2MktleUdlblJvdW5kM1Jlc3BvbnNlPiA9PiB7XG4gICAgICAgICAgY29uc3QgeyBzZXNzaW9uSWQsIHVzZXJNc2czLCB1c2VyTXNnNCwgYmFja3VwTXNnMywgYmFja3VwTXNnNCB9ID0gcGF5bG9hZDtcblxuICAgICAgICAgIGNvbnN0IHJvdW5kM0luY29taW5nTXNncyA9IGF3YWl0IERrbHNDb21tcy5kZWNyeXB0QW5kVmVyaWZ5SW5jb21pbmdNZXNzYWdlcyhcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgcDJwTWVzc2FnZXM6IFtcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBmcm9tOiB1c2VyTXNnMy5mcm9tLFxuICAgICAgICAgICAgICAgICAgdG86IHVzZXJNc2czLnRvLFxuICAgICAgICAgICAgICAgICAgcGF5bG9hZDogeyBzaWduYXR1cmU6IHVzZXJNc2czLnNpZ25hdHVyZSwgZW5jcnlwdGVkTWVzc2FnZTogdXNlck1zZzMuZW5jcnlwdGVkTWVzc2FnZSB9LFxuICAgICAgICAgICAgICAgICAgY29tbWl0bWVudDogc3RvcmVkVXNlckNvbW1pdG1lbnQyLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZnJvbTogYmFja3VwTXNnMy5mcm9tLFxuICAgICAgICAgICAgICAgICAgdG86IGJhY2t1cE1zZzMudG8sXG4gICAgICAgICAgICAgICAgICBwYXlsb2FkOiB7IHNpZ25hdHVyZTogYmFja3VwTXNnMy5zaWduYXR1cmUsIGVuY3J5cHRlZE1lc3NhZ2U6IGJhY2t1cE1zZzMuZW5jcnlwdGVkTWVzc2FnZSB9LFxuICAgICAgICAgICAgICAgICAgY29tbWl0bWVudDogc3RvcmVkQmFja3VwQ29tbWl0bWVudDIsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFt1c2VyR3BnUHViS2V5LCBiYWNrdXBHcGdQdWJLZXldLFxuICAgICAgICAgICAgW2JpdGdvR3BnUHJ2S2V5XVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBjb25zdCByb3VuZDRNZXNzYWdlcyA9IERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyhcbiAgICAgICAgICAgIGJpdGdvU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKERrbHNUeXBlcy5kZXNlcmlhbGl6ZU1lc3NhZ2VzKHJvdW5kM0luY29taW5nTXNncykpXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb25zdCByb3VuZDRTaWduZWRNZXNzYWdlcyA9IGF3YWl0IERrbHNDb21tcy5lbmNyeXB0QW5kQXV0aE91dGdvaW5nTWVzc2FnZXMoXG4gICAgICAgICAgICByb3VuZDRNZXNzYWdlcyxcbiAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgW2JpdGdvR3BnUHJ2S2V5XVxuICAgICAgICAgICk7XG4gICAgICAgICAgY29uc3QgYml0Z29Nc2c0ID0gcm91bmQ0U2lnbmVkTWVzc2FnZXMuYnJvYWRjYXN0TWVzc2FnZXMuZmluZCgobSkgPT4gbS5mcm9tID09PSAyKTtcbiAgICAgICAgICBhc3NlcnQub2soYml0Z29Nc2c0LCAnYml0Z29Nc2c0IG5vdCBmb3VuZCcpO1xuXG4gICAgICAgICAgY29uc3Qgcm91bmQ0SW5jb21pbmdNc2dzID0gYXdhaXQgRGtsc0NvbW1zLmRlY3J5cHRBbmRWZXJpZnlJbmNvbWluZ01lc3NhZ2VzKFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZnJvbTogdXNlck1zZzQuZnJvbSxcbiAgICAgICAgICAgICAgICAgIHBheWxvYWQ6IHsgc2lnbmF0dXJlOiB1c2VyTXNnNC5zaWduYXR1cmUsIG1lc3NhZ2U6IHVzZXJNc2c0Lm1lc3NhZ2UgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGZyb206IGJhY2t1cE1zZzQuZnJvbSxcblxuICAgICAgICAgICAgICAgICAgcGF5bG9hZDogeyBzaWduYXR1cmU6IGJhY2t1cE1zZzQuc2lnbmF0dXJlLCBtZXNzYWdlOiBiYWNrdXBNc2c0Lm1lc3NhZ2UgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFt1c2VyR3BnUHViS2V5LCBiYWNrdXBHcGdQdWJLZXldLFxuICAgICAgICAgICAgW11cbiAgICAgICAgICApO1xuICAgICAgICAgIGJpdGdvU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKERrbHNUeXBlcy5kZXNlcmlhbGl6ZU1lc3NhZ2VzKHJvdW5kNEluY29taW5nTXNncykpO1xuICAgICAgICAgIGNvbnN0IGtleVNoYXJlID0gYml0Z29TZXNzaW9uLmdldEtleVNoYXJlKCk7XG4gICAgICAgICAgY29uc3QgY29tbW9uS2V5Y2hhaW4gPSBEa2xzVHlwZXMuZ2V0Q29tbW9uS2V5Y2hhaW4oa2V5U2hhcmUpO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgICAgIGNvbW1vbktleWNoYWluOiBjb21tb25LZXljaGFpbiBhcyBOb25FbXB0eVN0cmluZyxcbiAgICAgICAgICAgIGJpdGdvTXNnNDogeyBmcm9tOiAyLCAuLi5iaXRnb01zZzQucGF5bG9hZCB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICk7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrQWRkS2V5Q2hhaW4oY29pbjogc3RyaW5nLCB0aW1lcyA9IDEpIHtcbiAgICByZXR1cm4gbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgIC5wb3N0KGAvYXBpL3YyLyR7Y29pbn0va2V5YCwgKGJvZHkpID0+IGJvZHkua2V5VHlwZSA9PT0gJ3RzcycgJiYgYm9keS5pc01QQ3YyKVxuICAgICAgLnRpbWVzKHRpbWVzKVxuICAgICAgLnJlcGx5KDIwMCwgYXN5bmMgKHVyaSwgcmVxdWVzdEJvZHk6IEFkZEtleWNoYWluT3B0aW9ucykgPT4ge1xuICAgICAgICBjb25zdCBrZXkgPSB7XG4gICAgICAgICAgaWQ6IHJlcXVlc3RCb2R5LnNvdXJjZSxcbiAgICAgICAgICBzb3VyY2U6IHJlcXVlc3RCb2R5LnNvdXJjZSxcbiAgICAgICAgICB0eXBlOiByZXF1ZXN0Qm9keS5rZXlUeXBlLFxuICAgICAgICAgIGNvbW1vbktleWNoYWluOiByZXF1ZXN0Qm9keS5jb21tb25LZXljaGFpbixcbiAgICAgICAgICBlbmNyeXB0ZWRQcnY6IHJlcXVlc3RCb2R5LmVuY3J5cHRlZFBydixcbiAgICAgICAgfTtcbiAgICAgICAgLy8gbm9jayBnZXRzXG4gICAgICAgIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpLmdldChgL2FwaS92Mi8ke2NvaW59L2tleS8ke3JlcXVlc3RCb2R5LnNvdXJjZX1gKS5yZXBseSgyMDAsIGtleSk7XG4gICAgICAgIHJldHVybiBrZXk7XG4gICAgICB9KTtcbiAgfVxufSk7XG4iXX0=