PHP WebShell

Текущая директория: /opt/BitGoJS/modules/bitgo/dist/test/v2/unit/internal/tssUtils

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

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sodium = require("libsodium-wrappers-sumo");
const _ = require("lodash");
const nock = require("nock");
const openpgp = require("openpgp");
const should = require("should");
const sinon = require("sinon");
const sdk_test_1 = require("@bitgo/sdk-test");
const bitgo_1 = require("../../../../../src/bitgo");
const sdk_core_1 = require("@bitgo/sdk-core");
const helpers_1 = require("../../tss/helpers");
const common_1 = require("./common");
openpgp.config.rejectCurves = new Set();
describe('TSS Utils:', async function () {
    let sandbox;
    let MPC;
    let bgUrl;
    let tssUtils;
    let userGpgKey;
    let backupGpgKey;
    let bitgoGpgKey;
    let bitgo;
    let baseCoin;
    let wallet;
    let bitgoKeyShare;
    const reqId = new sdk_core_1.RequestTracer();
    const coinName = 'tsol';
    const validUserSigningMaterial = {
        uShare: {
            i: 1,
            t: 2,
            n: 3,
            y: '093c8603ad86c41d5ee25a814b88185b435dd3a9ceccf9c9fd691a465ac4a8b0',
            seed: 'ca40c789813250c334ddd2ba19050f6ed20b5a08853ceca492358f2711ad4b15',
            chaincode: '596d5404a7eb918ee78247b952d06539619884091fdd9e0ff5a665f349e32fca',
        },
        commonChaincode: '596d5404a7eb918ee78247b952d06539619884091fdd9e0ff5a665f349e32fca',
        bitgoYShare: {
            i: 1,
            j: 3,
            y: '59d8000ba5e85fa402f39382960e7d5ede82b1b6e22b146a18b7df238c3a3225',
            v: '01ea3f425b1adf8aec6cfe4fc8f9b94755c34657965f32397655dcd784f1b517',
            u: '9ce3204a8c9757738967f3f81b463d87267bf6f2c0e5eaf2843167537b872b0b',
            chaincode: 'd21dbd8eae5d4789292ecea2efa53e0165b2439d57f5158eb4dd57dc26b59236',
        },
        backupYShare: {
            i: 1,
            j: 2,
            y: 'e0ae75077715686a121acb41b29a55bde426971154f40a41fc317f7f774a9424',
            v: 'f76ef629dfc15ab5e4531e532b5d67f2176637ca752b195876b7e3172459c969',
            u: 'fe6b89fb6acfcd7392c35c084f58bde0846b888c4df57e466caf0a3271b06a05',
            chaincode: '1c34e5dfbbd4a870f4479caaa5e6a46e3438f976ad5aefd4905b8fe8bca1101e',
        },
    };
    const validUserSignShare = {
        xShare: {
            i: 1,
            y: '4d9343988e68191aac945a6963031dddde3490f9020d0571a6e6c6e15cca0296',
            u: '1e159d6a0ae3a8dccc74615113e7c3e25d3080e5e0ffeb0ae04dd6a967268102',
            r: 'c8f64cc48926216c3f60e1d8ff1e24eba060d7c1ff020d0fc1d735d4564efd03',
            R: '9be2208ee28cd4b2577a9a66f6aab1ed8b08a300969eeb9b203a52aa54d2c23c',
        },
        rShares: {
            3: {
                i: 3,
                j: 1,
                u: 'd675f9099fbef03aa9fcdca4009286f435e56369c374d0042f03cc60b49e690a',
                v: '3c090e88ed42da0dd0bade35c8d6b88bc050284536b98e5b27d33ff45da9755b',
                r: '7f16224dbf5b02adb6c21380fcb2a8ee00323daae62cac3575a4d328fd23a905',
                R: '9be2208ee28cd4b2577a9a66f6aab1ed8b08a300969eeb9b203a52aa54d2c23c',
                commitment: '445c8cb1dee0166b6bdd5ad1d0a53fbfe86c4d3a470f184745530a863eedff28',
            },
        },
    };
    const validBitgoToUserSignShare = {
        xShare: {
            i: 3,
            y: '4d9343988e68191aac945a6963031dddde3490f9020d0571a6e6c6e15cca0296',
            u: '1315dbe18069825b4a27188b813eae7ff2917a614499ed553e70d65d4fa4820b',
            r: 'd0539375e6566f2fe540cba48c5e56bd1cdf68cfe1f0d527d2b730fe4e879809',
            R: 'c883fe2ae9b8da1764cc36a526cfa1a21f81d604320b209867f8de9223f1de32',
        },
        rShares: {
            1: {
                i: 1,
                j: 3,
                u: '9ce3204a8c9757738967f3f81b463d87267bf6f2c0e5eaf2843167537b872b0b',
                v: '01ea3f425b1adf8aec6cfe4fc8f9b94755c34657965f32397655dcd784f1b517',
                r: '0375e8c5a5691a73c21df00d49d423e3f83fe08d7b5d5af33c5c6aa9cae59d0a',
                R: 'c883fe2ae9b8da1764cc36a526cfa1a21f81d604320b209867f8de9223f1de32',
                commitment: '62b21f98bf885841ad469145192d4df0697b3f42c581e3e926394eae0b101ecb',
            },
        },
    };
    const txRequest = {
        txRequestId: 'randomId',
        unsignedTxs: [{ signableHex: 'MPC on a Friday night', serializedTxHex: 'MPC on a Friday night' }],
        signatureShares: [
            {
                from: 'bitgo',
                to: 'user',
                share: validBitgoToUserSignShare.rShares[1].r + validBitgoToUserSignShare.rShares[1].R,
            },
        ],
    };
    beforeEach(function () {
        sandbox = sinon.createSandbox();
    });
    afterEach(function () {
        sandbox.restore();
    });
    before('initializes mpc', async function () {
        const hdTree = await sdk_core_1.Ed25519BIP32.initialize();
        MPC = await sdk_core_1.Eddsa.initialize(hdTree);
    });
    before(async function () {
        bitgoKeyShare = await MPC.keyShare(3, 2, 3);
        userGpgKey = await openpgp.generateKey({
            userIDs: [
                {
                    name: 'test',
                    email: 'test@test.com',
                },
            ],
            curve: 'secp256k1',
        });
        backupGpgKey = await openpgp.generateKey({
            userIDs: [
                {
                    name: 'testBackup',
                    email: 'testBackup@test.com',
                },
            ],
            curve: 'secp256k1',
        });
        bitgoGpgKey = await openpgp.generateKey({
            userIDs: [
                {
                    name: 'bitgo',
                    email: 'bitgo@test.com',
                },
            ],
            curve: 'secp256k1',
        });
        const constants = {
            mpc: {
                bitgoPublicKey: bitgoGpgKey.publicKey,
            },
        };
        bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'mock' });
        bitgo.initializeTestVars();
        baseCoin = bitgo.coin(coinName);
        bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
        // TODO(WP-346): sdk-test mocks conflict so we can't use persist
        nock(bgUrl).get('/api/v1/client/constants').times(23).reply(200, { ttl: 3600, constants });
        const walletData = {
            id: '5b34252f1bf349930e34020a00000000',
            coin: 'tsol',
            keys: [
                '5b3424f91bf349930e34017500000000',
                '5b3424f91bf349930e34017600000000',
                '5b3424f91bf349930e34017700000000',
            ],
            coinSpecific: {},
            multisigType: 'tss',
        };
        wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData);
        tssUtils = new sdk_core_1.TssUtils(bitgo, baseCoin, wallet);
    });
    after(function () {
        nock.cleanAll();
    });
    describe('TSS key chains:', async function () {
        it('should generate TSS key chains', async function () {
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            const nockedBitGoKeychain = await nockBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            const nockedUserKeychain = await nockUserKeychain({ coin: coinName });
            await nockBackupKeychain({ coin: coinName });
            const bitgoKeychain = await tssUtils.createBitgoKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
            });
            const userKeychain = await tssUtils.createUserKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain,
                passphrase: 'passphrase',
            });
            const backupKeychain = await tssUtils.createBackupKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain,
                passphrase: 'passphrase',
            });
            bitgoKeychain.should.deepEqual(nockedBitGoKeychain);
            userKeychain.should.deepEqual(nockedUserKeychain);
            // unencrypted `prv` property should exist on backup keychain
            JSON.stringify({
                uShare: backupKeyShare.uShare,
                bitgoYShare: bitgoKeyShare.yShares[2],
                userYShare: userKeyShare.yShares[2],
            }).should.equal(backupKeychain.prv);
            should.exist(backupKeychain.encryptedPrv);
        });
        it('should generate TSS key chains without passphrase', async function () {
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            const nockedBitGoKeychain = await nockBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                // reusing the user gpg key as the backup gpg key, i.e. the user is their own the backup provider
                backupGpgKey,
                bitgoGpgKey,
            });
            const nockedUserKeychain = await nockUserKeychain({ coin: coinName });
            await nockBackupKeychain({ coin: coinName });
            const bitgoKeychain = await tssUtils.createBitgoKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
            });
            const userKeychain = await tssUtils.createUserKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain,
            });
            const backupKeychain = await tssUtils.createBackupKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain,
            });
            bitgoKeychain.should.deepEqual(nockedBitGoKeychain);
            userKeychain.should.deepEqual(nockedUserKeychain);
            // unencrypted `prv` property should exist on backup keychain
            JSON.stringify({
                uShare: backupKeyShare.uShare,
                bitgoYShare: bitgoKeyShare.yShares[2],
                userYShare: userKeyShare.yShares[2],
            }).should.equal(backupKeychain.prv);
        });
        it('should generate TSS key chains with optional params', async function () {
            const enterprise = 'enterprise';
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            const nockedBitGoKeychain = await nockBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            const nockedUserKeychain = await nockUserKeychain({ coin: coinName });
            await nockBackupKeychain({ coin: coinName });
            const bitgoKeychain = await tssUtils.createBitgoKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                enterprise,
            });
            const userKeychain = await tssUtils.createUserKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain,
                passphrase: 'passphrase',
                originalPasscodeEncryptionCode: 'originalPasscodeEncryptionCode',
            });
            const backupKeychain = await tssUtils.createBackupKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain,
                passphrase: 'passphrase',
            });
            bitgoKeychain.should.deepEqual(nockedBitGoKeychain);
            userKeychain.should.deepEqual(nockedUserKeychain);
            // unencrypted `prv` property should exist on backup keychain
            JSON.stringify({
                uShare: backupKeyShare.uShare,
                bitgoYShare: bitgoKeyShare.yShares[2],
                userYShare: userKeyShare.yShares[2],
            }).should.equal(backupKeychain.prv);
            should.exist(backupKeychain.encryptedPrv);
        });
        it('should fail to generate TSS keychains when received invalid number of wallet signatures', async function () {
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            const bitgoKeychain = await generateBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            const certsString = await (0, sdk_core_1.createSharedDataProof)(bitgoGpgKey.privateKey, userGpgKey.publicKey, []);
            const certsKey = await openpgp.readKey({ armoredKey: certsString });
            const finalKey = new openpgp.PacketList();
            certsKey.toPacketList().forEach((packet) => finalKey.push(packet));
            // the underlying function only requires two arguments but the according .d.ts file for openpgp has the further
            // arguments marked as mandatory as well.
            // Once the following PR has been merged and released we no longer need the ts-ignore:
            // https://github.com/openpgpjs/openpgpjs/pull/1576
            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
            // @ts-ignore
            bitgoKeychain.walletHSMGPGPublicKeySigs = openpgp.armor(openpgp.enums.armor.publicKey, finalKey.write());
            await tssUtils
                .verifyWalletSignatures(userGpgKey.publicKey, backupGpgKey.publicKey, bitgoKeychain, '', 1)
                .should.be.rejectedWith('Invalid wallet signatures');
        });
        it('should fail to generate TSS keychains when wallet signature fingerprints do not match passed user/backup fingerprints', async function () {
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            const bitgoKeychain = await generateBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            // using the backup gpg here instead of the user gpg key to simulate that the first signature has a different
            // fingerprint from the passed in first gpg key
            await tssUtils
                .verifyWalletSignatures(backupGpgKey.publicKey, backupGpgKey.publicKey, bitgoKeychain, '', 1)
                .should.be.rejectedWith(`first wallet signature's fingerprint does not match passed user gpg key's fingerprint`);
            // using the user gpg here instead of the backup gpg key to simulate that the second signature has a different
            // fingerprint from the passed in second gpg key
            await tssUtils
                .verifyWalletSignatures(userGpgKey.publicKey, userGpgKey.publicKey, bitgoKeychain, '', 1)
                .should.be.rejectedWith(`second wallet signature's fingerprint does not match passed backup gpg key's fingerprint`);
        });
        it('should fail to generate TSS keychains when wallet signature is for different key share', async function () {
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            const customBitgoKeyShare = MPC.keyShare(3, 2, 3);
            const bitgoKeychain1 = await generateBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            const bitgoKeychain2 = await generateBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare: customBitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            // using the other bitgo keychains common keychain and walletHSMGPGPublicKeySigs so that the verification of the
            // commmon keychain passes but fails for the bitgo to user/ backup shares
            bitgoKeychain1.commonKeychain = bitgoKeychain2.commonKeychain;
            bitgoKeychain1.walletHSMGPGPublicKeySigs = bitgoKeychain2.walletHSMGPGPublicKeySigs;
            await tssUtils
                .createUserKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain: bitgoKeychain1,
            })
                .should.be.rejectedWith('bitgo share mismatch');
            await tssUtils
                .createBackupKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain: bitgoKeychain1,
            })
                .should.be.rejectedWith('bitgo share mismatch');
        });
        it('should fail to generate TSS key chains when common keychains do not match', async function () {
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            const nockedBitGoKeychain = await nockBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            const bitgoKeychain = await tssUtils.createBitgoKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
            });
            bitgoKeychain.should.deepEqual(nockedBitGoKeychain);
            await tssUtils
                .createUserKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare: MPC.keyShare(2, 2, 3),
                bitgoKeychain,
                passphrase: 'passphrase',
            })
                .should.be.rejectedWith('Failed to create user keychain - commonKeychains do not match.');
            await tssUtils
                .createUserKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare: MPC.keyShare(1, 2, 3),
                backupKeyShare,
                bitgoKeychain,
                passphrase: 'passphrase',
            })
                .should.be.rejectedWith('Failed to create user keychain - commonKeychains do not match.');
            await tssUtils
                .createBackupKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare: MPC.keyShare(1, 2, 3),
                backupKeyShare,
                bitgoKeychain,
                passphrase: 'passphrase',
            })
                .should.be.rejectedWith('Failed to create backup keychain - commonKeychains do not match.');
            await tssUtils
                .createBackupKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare: MPC.keyShare(2, 2, 3),
                bitgoKeychain,
                passphrase: 'passphrase',
            })
                .should.be.rejectedWith('Failed to create backup keychain - commonKeychains do not match.');
        });
    });
    describe('signTxRequest:', function () {
        const txRequestId = 'randomid';
        const txRequest = {
            txRequestId,
            transactions: [],
            unsignedTxs: [
                {
                    serializedTxHex: 'MPC on a Friday night',
                    signableHex: 'MPC on a Friday night',
                    derivationPath: 'm/0',
                },
            ],
            date: new Date().toISOString(),
            intent: {
                intentType: 'payment',
            },
            latest: true,
            state: 'pendingUserSignature',
            walletType: 'hot',
            walletId: 'walletId',
            policiesChecked: true,
            version: 1,
            userId: 'userId',
        };
        beforeEach(async function () {
            const userSignShare = validUserSignShare;
            const rShare = userSignShare.rShares[3];
            const signatureShare = {
                from: sdk_core_1.SignatureShareType.USER,
                to: sdk_core_1.SignatureShareType.BITGO,
                share: rShare.r + rShare.R,
            };
            await (0, common_1.nockSendSignatureShare)({
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
                signatureShare,
            });
            const signatureShare2 = {
                from: sdk_core_1.SignatureShareType.BITGO,
                to: sdk_core_1.SignatureShareType.USER,
                share: validBitgoToUserSignShare.rShares[1].r + validBitgoToUserSignShare.rShares[1].R,
            };
            const response = { txRequests: [{ ...txRequest, signatureShares: [signatureShare2] }] };
            await (0, common_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
            const bitgoToUserCommitmentShare = {
                from: sdk_core_1.SignatureShareType.BITGO,
                to: sdk_core_1.SignatureShareType.USER,
                type: sdk_core_1.CommitmentType.COMMITMENT,
                share: validBitgoToUserSignShare.rShares[1].commitment,
            };
            const exchangeCommitResponse = { commitmentShare: bitgoToUserCommitmentShare };
            await (0, common_1.nockExchangeCommitments)({
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
                response: exchangeCommitResponse,
            });
        });
        it('signTxRequest should succeed with txRequest object as input', async function () {
            const signedTxRequest = await tssUtils.signTxRequest({
                txRequest,
                prv: JSON.stringify(validUserSigningMaterial),
                reqId,
            });
            signedTxRequest.unsignedTxs.should.deepEqual(txRequest.unsignedTxs);
            sandbox.verifyAndRestore();
        });
        it('signTxRequest should succeed with txRequest id as input', async function () {
            const getTxRequest = sandbox.stub(tssUtils, 'getTxRequest');
            getTxRequest.resolves(txRequest);
            getTxRequest.calledWith(txRequestId);
            const signedTxRequest = await tssUtils.signTxRequest({
                txRequest: txRequestId,
                prv: JSON.stringify(validUserSigningMaterial),
                reqId,
            });
            signedTxRequest.unsignedTxs.should.deepEqual(txRequest.unsignedTxs);
            sandbox.verifyAndRestore();
        });
    });
    describe('signTxRequest With Commitment:', function () {
        const txRequestId = 'randomid';
        const txRequest = {
            txRequestId,
            transactions: [],
            unsignedTxs: [
                {
                    serializedTxHex: 'MPC on a Friday night',
                    signableHex: 'MPC on a Friday night',
                    derivationPath: 'm/0',
                },
            ],
            date: new Date().toISOString(),
            intent: {
                intentType: 'payment',
            },
            latest: true,
            state: 'pendingUserSignature',
            walletType: 'hot',
            walletId: 'walletId',
            policiesChecked: true,
            version: 1,
            userId: 'userId',
        };
        beforeEach(async function () {
            const userSignShare = validUserSignShare;
            const rShare = userSignShare.rShares[3];
            const signatureShare = {
                from: sdk_core_1.SignatureShareType.USER,
                to: sdk_core_1.SignatureShareType.BITGO,
                share: rShare.r + rShare.R,
            };
            await (0, common_1.nockSendSignatureShare)({
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
                signatureShare,
            });
            const signatureShare2 = {
                from: sdk_core_1.SignatureShareType.BITGO,
                to: sdk_core_1.SignatureShareType.USER,
                share: validBitgoToUserSignShare.rShares[1].r + validBitgoToUserSignShare.rShares[1].R,
            };
            const response = { txRequests: [{ ...txRequest, signatureShares: [signatureShare2] }] };
            await (0, common_1.nockGetTxRequest)({ walletId: wallet.id(), txRequestId: txRequest.txRequestId, response });
            const bitgoToUserCommitmentShare = {
                from: sdk_core_1.SignatureShareType.BITGO,
                to: sdk_core_1.SignatureShareType.USER,
                type: sdk_core_1.CommitmentType.COMMITMENT,
                share: validBitgoToUserSignShare.rShares[1].commitment,
            };
            const exchangeCommitResponse = { commitmentShare: bitgoToUserCommitmentShare };
            await (0, common_1.nockExchangeCommitments)({
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
                response: exchangeCommitResponse,
            });
        });
        it('signTxRequest should succeed with txRequest object as input', async function () {
            const signedTxRequest = await tssUtils.signTxRequest({
                txRequest,
                prv: JSON.stringify(validUserSigningMaterial),
                reqId,
            });
            signedTxRequest.unsignedTxs.should.deepEqual(txRequest.unsignedTxs);
            sandbox.verifyAndRestore();
        });
        it('signTxRequest should succeed with txRequest id as input', async function () {
            const getTxRequest = sandbox.stub(tssUtils, 'getTxRequest');
            getTxRequest.resolves(txRequest);
            getTxRequest.calledWith(txRequestId);
            const signedTxRequest = await tssUtils.signTxRequest({
                txRequest: txRequestId,
                prv: JSON.stringify(validUserSigningMaterial),
                reqId,
            });
            signedTxRequest.unsignedTxs.should.deepEqual(txRequest.unsignedTxs);
            sandbox.verifyAndRestore();
        });
    });
    describe('prebuildTxWithIntent:', async function () {
        it('should build single recipient tx', async function () {
            const nockedCreateTx = await (0, common_1.nockCreateTxRequest)({
                walletId: wallet.id(),
                requestBody: {
                    apiVersion: 'lite',
                    intent: {
                        intentType: 'payment',
                        recipients: [
                            {
                                address: {
                                    address: 'recipient',
                                },
                                amount: {
                                    value: '10000',
                                    symbol: 'tsol',
                                },
                            },
                        ],
                    },
                },
                // don't care about the actual response - just need to make sure request body matches
                response: {},
            });
            await tssUtils.prebuildTxWithIntent({
                reqId,
                recipients: [
                    {
                        address: 'recipient',
                        amount: '10000',
                    },
                ],
                intentType: 'payment',
            });
            nockedCreateTx.isDone().should.be.true();
        });
        it('should build multiple recipients with memo tx', async function () {
            const nockedCreateTx = await (0, common_1.nockCreateTxRequest)({
                walletId: wallet.id(),
                requestBody: {
                    apiVersion: 'lite',
                    intent: {
                        intentType: 'payment',
                        recipients: [
                            {
                                address: {
                                    address: 'recipient1',
                                },
                                amount: {
                                    value: '10000',
                                    symbol: 'tsol',
                                },
                            },
                            {
                                address: {
                                    address: 'recipient2',
                                },
                                amount: {
                                    value: '20000',
                                    symbol: 'tsol',
                                },
                            },
                        ],
                        memo: 'memo',
                    },
                },
                // don't care about the actual response - just need to make sure request body matches
                response: {},
            });
            await tssUtils.prebuildTxWithIntent({
                reqId,
                recipients: [
                    {
                        address: 'recipient1',
                        amount: '10000',
                    },
                    {
                        address: 'recipient2',
                        amount: '20000',
                    },
                ],
                memo: {
                    value: 'memo',
                    type: 'text',
                },
                intentType: 'payment',
            });
            nockedCreateTx.isDone().should.be.true();
        });
    });
    describe('delete SignatureShare:', async function () {
        it('should succeed to delete Signature Share', async function () {
            const signatureShare = { from: 'user', to: 'bitgo', share: '128bytestring' };
            const nock = await (0, common_1.nockDeleteSignatureShare)({
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
                signatureShare,
            });
            const response = await tssUtils.deleteSignatureShares(txRequest.txRequestId);
            response.should.deepEqual([signatureShare]);
            response.should.length(1);
            nock.isDone().should.equal(true);
        });
        it('should call setRequestTracer', async function () {
            const signatureShare = { from: 'user', to: 'bitgo', share: '128bytestring' };
            const nock = await (0, common_1.nockDeleteSignatureShare)({
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
                signatureShare,
            });
            const reqId = new sdk_core_1.RequestTracer();
            const setRequestTracerSpy = sinon.spy(bitgo, 'setRequestTracer');
            setRequestTracerSpy.withArgs(reqId);
            const response = await tssUtils.deleteSignatureShares(txRequest.txRequestId, reqId);
            response.should.deepEqual([signatureShare]);
            response.should.length(1);
            nock.isDone().should.equal(true);
            sinon.assert.calledOnce(setRequestTracerSpy);
            setRequestTracerSpy.restore();
        });
    });
    describe('sendTxRequest:', async function () {
        it('should succeed to send tx request', async function () {
            const nock = await (0, common_1.nockSendTxRequest)({
                coin: coinName,
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
            });
            await tssUtils.sendTxRequest(txRequest.txRequestId).should.be.fulfilled();
            nock.isDone().should.equal(true);
        });
        it('should call setRequestTracer', async function () {
            const nock = await (0, common_1.nockSendTxRequest)({
                coin: coinName,
                walletId: wallet.id(),
                txRequestId: txRequest.txRequestId,
            });
            const reqId = new sdk_core_1.RequestTracer();
            const setRequestTracerSpy = sinon.spy(bitgo, 'setRequestTracer');
            setRequestTracerSpy.withArgs(reqId);
            await tssUtils.sendTxRequest(txRequest.txRequestId, reqId).should.be.fulfilled();
            nock.isDone().should.equal(true);
            sinon.assert.calledOnce(setRequestTracerSpy);
            setRequestTracerSpy.restore();
        });
    });
    describe('createUserToBitgoCommitmentShare', function () {
        it('should create a valid commitmentShare', async function () {
            const value = 'randomstring';
            const validUserToBitgoCommitmentShare = {
                from: sdk_core_1.SignatureShareType.USER,
                to: sdk_core_1.SignatureShareType.BITGO,
                type: sdk_core_1.CommitmentType.COMMITMENT,
                share: value,
            };
            const commitmentShare = tssUtils.createUserToBitgoCommitmentShare(value);
            commitmentShare.should.deepEqual(validUserToBitgoCommitmentShare);
        });
    });
    describe('createUserToBitgoEncryptedSignerShare', function () {
        it('should create a valid encryptedSignerShare', async function () {
            const value = 'randomstring';
            const validUserToBitgoEncryptedSignerShare = {
                from: sdk_core_1.SignatureShareType.USER,
                to: sdk_core_1.SignatureShareType.BITGO,
                type: sdk_core_1.EncryptedSignerShareType.ENCRYPTED_SIGNER_SHARE,
                share: value,
            };
            const encryptedSignerShare = tssUtils.createUserToBitgoEncryptedSignerShare(value);
            encryptedSignerShare.should.deepEqual(validUserToBitgoEncryptedSignerShare);
        });
    });
    describe('supportedTxRequestVersions', function () {
        it('should return full for custodial wallets', async function () {
            const custodialWallet = new sdk_core_1.Wallet(bitgo, baseCoin, { multisigType: 'tss', type: 'custodial' });
            const custodialTssUtils = new sdk_core_1.TssUtils(bitgo, baseCoin, custodialWallet);
            custodialTssUtils.supportedTxRequestVersions().should.deepEqual(['full']);
        });
        it('should return full for cold wallets', async function () {
            const coldWallet = new sdk_core_1.Wallet(bitgo, baseCoin, { multisigType: 'tss', type: 'cold' });
            const coldWalletTssUtils = new sdk_core_1.TssUtils(bitgo, baseCoin, coldWallet);
            coldWalletTssUtils.supportedTxRequestVersions().should.deepEqual(['full']);
        });
        it('should return full and lite for hot wallets', async function () {
            const hotWallet = new sdk_core_1.Wallet(bitgo, baseCoin, { multisigType: 'tss', type: 'hot' });
            const hotTssUtils = new sdk_core_1.TssUtils(bitgo, baseCoin, hotWallet);
            const supportedTxRequestVersions = hotTssUtils.supportedTxRequestVersions();
            supportedTxRequestVersions.should.deepEqual(['lite', 'full']);
        });
        it('should return empty for trading wallets', function () {
            const tradingWallets = new sdk_core_1.Wallet(bitgo, baseCoin, { multisigType: 'tss', type: 'trading' });
            const tradingWalletTssUtils = new sdk_core_1.TssUtils(bitgo, baseCoin, tradingWallets);
            const supportedTxRequestVersions = tradingWalletTssUtils.supportedTxRequestVersions();
            supportedTxRequestVersions.should.deepEqual([]);
        });
        it('should return empty for non-tss wallets', function () {
            const nonTssWalletData = { coin: 'btc', multisigType: 'onchain' };
            const btcCoin = bitgo.coin('tbtc');
            const nonTssWallet = new sdk_core_1.Wallet(bitgo, btcCoin, nonTssWalletData);
            const nonTssWalletTssUtils = new sdk_core_1.TssUtils(bitgo, btcCoin, nonTssWallet);
            nonTssWalletTssUtils.supportedTxRequestVersions().should.deepEqual([]);
        });
    });
    describe('isPendingApprovalTxRequestFull', () => {
        it('should return true for full apiVersion and pendingApproval state', async () => {
            const txRequest = {
                apiVersion: 'full',
                state: 'pendingApproval',
            };
            const result = await tssUtils.isPendingApprovalTxRequestFull(txRequest);
            result.should.be.true();
        });
        it('should return false for non-full apiVersion', async () => {
            const txRequest = {
                apiVersion: 'lite',
                state: 'pendingApproval',
            };
            const result = await tssUtils.isPendingApprovalTxRequestFull(txRequest);
            result.should.be.false();
        });
        it('should return false for non-pendingApproval state', async () => {
            const txRequest = {
                apiVersion: 'full',
                state: 'pendingDelivery',
            };
            const result = await tssUtils.isPendingApprovalTxRequestFull(txRequest);
            result.should.be.false();
        });
    });
    // #region Nock helpers
    async function generateBitgoKeychain(params) {
        const bitgoCombined = MPC.keyCombine(params.bitgoKeyShare.uShare, [
            params.userKeyShare.yShares[3],
            params.backupKeyShare.yShares[3],
        ]);
        const userGpgKeyActual = await openpgp.readKey({ armoredKey: params.userGpgKey.publicKey });
        const backupGpgKeyActual = await openpgp.readKey({ armoredKey: params.backupGpgKey.publicKey });
        const bitgoToUserMessage = await openpgp.createMessage({
            text: Buffer.concat([
                Buffer.from(params.bitgoKeyShare.yShares[1].u, 'hex'),
                Buffer.from(params.bitgoKeyShare.yShares[1].chaincode, 'hex'),
            ]).toString('hex'),
        });
        const encryptedBitgoToUserMessage = await openpgp.encrypt({
            message: bitgoToUserMessage,
            encryptionKeys: [userGpgKeyActual.toPublic()],
            format: 'armored',
        });
        const bitgoToBackupMessage = await openpgp.createMessage({
            text: Buffer.concat([
                Buffer.from(params.bitgoKeyShare.yShares[2].u, 'hex'),
                Buffer.from(params.bitgoKeyShare.yShares[2].chaincode, 'hex'),
            ]).toString('hex'),
        });
        const encryptedBitgoToBackupMessage = await openpgp.encrypt({
            message: bitgoToBackupMessage,
            encryptionKeys: [backupGpgKeyActual.toPublic()],
            format: 'armored',
        });
        const bitgoKeychain = {
            id: '3',
            pub: '',
            commonKeychain: bitgoCombined.pShare.y + bitgoCombined.pShare.chaincode,
            keyShares: [
                {
                    from: 'bitgo',
                    to: 'user',
                    publicShare: params.bitgoKeyShare.yShares[1].y + params.bitgoKeyShare.yShares[1].chaincode,
                    privateShare: encryptedBitgoToUserMessage.toString(),
                    vssProof: params.bitgoKeyShare.yShares[1].v,
                },
                {
                    from: 'bitgo',
                    to: 'backup',
                    publicShare: params.bitgoKeyShare.yShares[2].y + params.bitgoKeyShare.yShares[2].chaincode,
                    privateShare: encryptedBitgoToBackupMessage.toString(),
                    vssProof: params.bitgoKeyShare.yShares[2].v,
                },
            ],
            type: 'tss',
        };
        const userKeyId = userGpgKeyActual.keyPacket.getFingerprint();
        const backupKeyId = backupGpgKeyActual.keyPacket.getFingerprint();
        const bitgoToUserPublicShare = Buffer.from(await sodium.crypto_scalarmult_ed25519_base_noclamp(Buffer.from(params.bitgoKeyShare.yShares[1].u, 'hex'))).toString('hex') + params.bitgoKeyShare.yShares[1].chaincode;
        const bitgoToBackupPublicShare = Buffer.from(await sodium.crypto_scalarmult_ed25519_base_noclamp(Buffer.from(params.bitgoKeyShare.yShares[2].u, 'hex'))).toString('hex') + params.bitgoKeyShare.yShares[2].chaincode;
        bitgoKeychain.walletHSMGPGPublicKeySigs = await (0, helpers_1.createWalletSignatures)(params.bitgoGpgKey.privateKey, params.userGpgKey.publicKey, params.backupGpgKey.publicKey, [
            { name: 'commonKeychain', value: bitgoCombined.pShare.y + bitgoCombined.pShare.chaincode },
            { name: 'userKeyId', value: userKeyId },
            { name: 'backupKeyId', value: backupKeyId },
            { name: 'bitgoToUserPublicShare', value: bitgoToUserPublicShare },
            { name: 'bitgoToBackupPublicShare', value: bitgoToBackupPublicShare },
        ]);
        return bitgoKeychain;
    }
    async function nockBitgoKeychain(params) {
        const bitgoKeychain = await generateBitgoKeychain(params);
        nock(bgUrl)
            .post(`/api/v2/${params.coin}/key`, _.matches({ keyType: 'tss', source: 'bitgo' }))
            .reply(200, bitgoKeychain);
        return bitgoKeychain;
    }
    async function nockUserKeychain(params) {
        const userKeychain = {
            id: '1',
            pub: '',
            type: 'tss',
        };
        nock('https://bitgo.fakeurl')
            .post(`/api/v2/${params.coin}/key`, _.matches({ keyType: 'tss', source: 'user' }))
            .reply(200, userKeychain);
        return userKeychain;
    }
    async function nockBackupKeychain(params) {
        const backupKeychain = {
            id: '2',
            pub: '',
            type: 'tss',
        };
        nock('https://bitgo.fakeurl')
            .post(`/api/v2/${params.coin}/key`, _.matches({ keyType: 'tss', source: 'backup' }))
            .reply(200, backupKeychain);
        return backupKeychain;
    }
    // #endregion Nock helpers
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRkc2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZXN0L3YyL3VuaXQvaW50ZXJuYWwvdHNzVXRpbHMvZWRkc2EudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxrREFBa0Q7QUFDbEQsNEJBQTRCO0FBQzVCLDZCQUE2QjtBQUM3QixtQ0FBbUM7QUFDbkMsaUNBQWlDO0FBQ2pDLCtCQUErQjtBQUUvQiw4Q0FBd0Q7QUFDeEQsb0RBQWlEO0FBQ2pELDhDQWtCeUI7QUFDekIsK0NBQTJEO0FBQzNELHFDQU9rQjtBQUVsQixPQUFPLENBQUMsTUFBTSxDQUFDLFlBQVksR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0FBRXhDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsS0FBSztJQUMxQixJQUFJLE9BQTJCLENBQUM7SUFDaEMsSUFBSSxHQUFVLENBQUM7SUFDZixJQUFJLEtBQWEsQ0FBQztJQUNsQixJQUFJLFFBQWtCLENBQUM7SUFDdkIsSUFBSSxVQUFVLENBQUM7SUFDZixJQUFJLFlBQVksQ0FBQztJQUNqQixJQUFJLFdBQVcsQ0FBQztJQUNoQixJQUFJLEtBQXlCLENBQUM7SUFDOUIsSUFBSSxRQUFrQixDQUFDO0lBQ3ZCLElBQUksTUFBYyxDQUFDO0lBQ25CLElBQUksYUFBYSxDQUFDO0lBQ2xCLE1BQU0sS0FBSyxHQUFHLElBQUksd0JBQWEsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQztJQUN4QixNQUFNLHdCQUF3QixHQUFHO1FBQy9CLE1BQU0sRUFBRTtZQUNOLENBQUMsRUFBRSxDQUFDO1lBQ0osQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQztZQUNKLENBQUMsRUFBRSxrRUFBa0U7WUFDckUsSUFBSSxFQUFFLGtFQUFrRTtZQUN4RSxTQUFTLEVBQUUsa0VBQWtFO1NBQzlFO1FBQ0QsZUFBZSxFQUFFLGtFQUFrRTtRQUNuRixXQUFXLEVBQUU7WUFDWCxDQUFD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SUFBSSxDQUFDLHVCQUF1QixDQUFDO2FBQzFCLElBQUksQ0FBQyxXQUFXLE1BQU0sQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQzthQUNqRixLQUFLLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBRTVCLE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxLQUFLLFVBQVUsa0JBQWtCLENBQUMsTUFBd0I7UUFDeEQsTUFBTSxjQUFjLEdBQWE7WUFDL0IsRUFBRSxFQUFFLEdBQUc7WUFDUCxHQUFHLEVBQUUsRUFBRTtZQUNQLElBQUksRUFBRSxLQUFLO1NBQ1osQ0FBQztRQUVGLElBQUksQ0FBQyx1QkFBdUIsQ0FBQzthQUMxQixJQUFJLENBQUMsV0FBVyxNQUFNLENBQUMsSUFBSSxNQUFNLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7YUFDbkYsS0FBSyxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUU5QixPQUFPLGNBQWMsQ0FBQztJQUN4QixDQUFDO0lBRUQsMEJBQTBCO0FBQzVCLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgc29kaXVtIGZyb20gJ2xpYnNvZGl1bS13cmFwcGVycy1zdW1vJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCAqIGFzIG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgKiBhcyBvcGVucGdwIGZyb20gJ29wZW5wZ3AnO1xuaW1wb3J0ICogYXMgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5cbmltcG9ydCB7IFRlc3RhYmxlQkcsIFRlc3RCaXRHbyB9IGZyb20gJ0BiaXRnby9zZGstdGVzdCc7XG5pbXBvcnQgeyBCaXRHbyB9IGZyb20gJy4uLy4uLy4uLy4uLy4uL3NyYy9iaXRnbyc7XG5pbXBvcnQge1xuICBjb21tb24sXG4gIEtleWNoYWluLFxuICBSZXF1ZXN0VHJhY2VyLFxuICBTaWduYXR1cmVTaGFyZVJlY29yZCxcbiAgU2lnbmF0dXJlU2hhcmVUeXBlLFxuICBUc3NVdGlscyxcbiAgVHhSZXF1ZXN0LFxuICBXYWxsZXQsXG4gIEVkZHNhLFxuICBLZXlTaGFyZSxcbiAgRWQyNTUxOUJJUDMyLFxuICBjcmVhdGVTaGFyZWREYXRhUHJvb2YsXG4gIENvbW1pdG1lbnRTaGFyZVJlY29yZCxcbiAgQ29tbWl0bWVudFR5cGUsXG4gIEV4Y2hhbmdlQ29tbWl0bWVudFJlc3BvbnNlLFxuICBFbmNyeXB0ZWRTaWduZXJTaGFyZVR5cGUsXG4gIEJhc2VDb2luLFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgY3JlYXRlV2FsbGV0U2lnbmF0dXJlcyB9IGZyb20gJy4uLy4uL3Rzcy9oZWxwZXJzJztcbmltcG9ydCB7XG4gIG5vY2tTZW5kU2lnbmF0dXJlU2hhcmUsXG4gIG5vY2tHZXRUeFJlcXVlc3QsXG4gIG5vY2tDcmVhdGVUeFJlcXVlc3QsXG4gIG5vY2tEZWxldGVTaWduYXR1cmVTaGFyZSxcbiAgbm9ja1NlbmRUeFJlcXVlc3QsXG4gIG5vY2tFeGNoYW5nZUNvbW1pdG1lbnRzLFxufSBmcm9tICcuL2NvbW1vbic7XG5cbm9wZW5wZ3AuY29uZmlnLnJlamVjdEN1cnZlcyA9IG5ldyBTZXQoKTtcblxuZGVzY3JpYmUoJ1RTUyBVdGlsczonLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gIGxldCBzYW5kYm94OiBzaW5vbi5TaW5vblNhbmRib3g7XG4gIGxldCBNUEM6IEVkZHNhO1xuICBsZXQgYmdVcmw6IHN0cmluZztcbiAgbGV0IHRzc1V0aWxzOiBUc3NVdGlscztcbiAgbGV0IHVzZXJHcGdLZXk7XG4gIGxldCBiYWNrdXBHcGdLZXk7XG4gIGxldCBiaXRnb0dwZ0tleTtcbiAgbGV0IGJpdGdvOiBUZXN0YWJsZUJHICYgQml0R287XG4gIGxldCBiYXNlQ29pbjogQmFzZUNvaW47XG4gIGxldCB3YWxsZXQ6IFdhbGxldDtcbiAgbGV0IGJpdGdvS2V5U2hhcmU7XG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgY29uc3QgY29pbk5hbWUgPSAndHNvbCc7XG4gIGNvbnN0IHZhbGlkVXNlclNpZ25pbmdNYXRlcmlhbCA9IHtcbiAgICB1U2hhcmU6IHtcbiAgICAgIGk6IDEsXG4gICAgICB0OiAyLFxuICAgICAgbjogMyxcbiAgICAgIHk6ICcwOTNjODYwM2FkODZjNDFkNWVlMjVhODE0Yjg4MTg1YjQzNWRkM2E5Y2VjY2Y5YzlmZDY5MWE0NjVhYzRhOGIwJyxcbiAgICAgIHNlZWQ6ICdjYTQwYzc4OTgxMzI1MGMzMzRkZGQyYmExOTA1MGY2ZWQyMGI1YTA4ODUzY2VjYTQ5MjM1OGYyNzExYWQ0YjE1JyxcbiAgICAgIGNoYWluY29kZTogJzU5NmQ1NDA0YTdlYjkxOGVlNzgyNDdiOTUyZDA2NTM5NjE5ODg0MDkxZmRkOWUwZmY1YTY2NWYzNDllMzJmY2EnLFxuICAgIH0sXG4gICAgY29tbW9uQ2hhaW5jb2RlOiAnNTk2ZDU0MDRhN2ViOTE4ZWU3ODI0N2I5NTJkMDY1Mzk2MTk4ODQwOTFmZGQ5ZTBmZjVhNjY1ZjM0OWUzMmZjYScsXG4gICAgYml0Z29ZU2hhcmU6IHtcbiAgICAgIGk6IDEsXG4gICAgICBqOiAzLFxuICAgICAgeTogJzU5ZDgwMDBiYTVlODVmYTQwMmYzOTM4Mjk2MGU3ZDVlZGU4MmIxYjZlMjJiMTQ2YTE4YjdkZjIzOGMzYTMyMjUnLFxuICAgICAgdjogJzAxZWEzZjQyNWIxYWRmOGFlYzZjZmU0ZmM4ZjliOTQ3NTVjMzQ2NTc5NjVmMzIzOTc2NTVkY2Q3ODRmMWI1MTcnLFxuICAgICAgdTogJzljZTMyMDRhOGM5NzU3NzM4OTY3ZjNmODFiNDYzZDg3MjY3YmY2ZjJjMGU1ZWFmMjg0MzE2NzUzN2I4NzJiMGInLFxuICAgICAgY2hhaW5jb2RlOiAnZDIxZGJkOGVhZTVkNDc4OTI5MmVjZWEyZWZhNTNlMDE2NWIyNDM5ZDU3ZjUxNThlYjRkZDU3ZGMyNmI1OTIzNicsXG4gICAgfSxcbiAgICBiYWNrdXBZU2hhcmU6IHtcbiAgICAgIGk6IDEsXG4gICAgICBqOiAyLFxuICAgICAgeTogJ2UwYWU3NTA3NzcxNTY4NmExMjFhY2I0MWIyOWE1NWJkZTQyNjk3MTE1NGY0MGE0MWZjMzE3ZjdmNzc0YTk0MjQnLFxuICAgICAgdjogJ2Y3NmVmNjI5ZGZjMTVhYjVlNDUzMWU1MzJiNWQ2N2YyMTc2NjM3Y2E3NTJiMTk1ODc2YjdlMzE3MjQ1OWM5NjknLFxuICAgICAgdTogJ2ZlNmI4OWZiNmFjZmNkNzM5MmMzNWMwODRmNThiZGUwODQ2Yjg4OGM0ZGY1N2U0NjZjYWYwYTMyNzFiMDZhMDUnLFxuICAgICAgY2hhaW5jb2RlOiAnMWMzNGU1ZGZiYmQ0YTg3MGY0NDc5Y2FhYTVlNmE0NmUzNDM4Zjk3NmFkNWFlZmQ0OTA1YjhmZThiY2ExMTAxZScsXG4gICAgfSxcbiAgfTtcblxuICBjb25zdCB2YWxpZFVzZXJTaWduU2hhcmUgPSB7XG4gICAgeFNoYXJlOiB7XG4gICAgICBpOiAxLFxuICAgICAgeTogJzRkOTM0Mzk4OGU2ODE5MWFhYzk0NWE2OTYzMDMxZGRkZGUzNDkwZjkwMjBkMDU3MWE2ZTZjNmUxNWNjYTAyOTYnLFxuICAgICAgdTogJzFlMTU5ZDZhMGFlM2E4ZGNjYzc0NjE1MTEzZTdjM2UyNWQzMDgwZTVlMGZmZWIwYWUwNGRkNmE5NjcyNjgxMDInLFxuICAgICAgcjogJ2M4ZjY0Y2M0ODkyNjIxNmMzZjYwZTFkOGZmMWUyNGViYTA2MGQ3YzFmZjAyMGQwZmMxZDczNWQ0NTY0ZWZkMDMnLFxuICAgICAgUjogJzliZTIyMDhlZTI4Y2Q0YjI1NzdhOWE2NmY2YWFiMWVkOGIwOGEzMDA5NjllZWI5YjIwM2E1MmFhNTRkMmMyM2MnLFxuICAgIH0sXG4gICAgclNoYXJlczoge1xuICAgICAgMzoge1xuICAgICAgICBpOiAzLFxuICAgICAgICBqOiAxLFxuICAgICAgICB1OiAnZDY3NWY5MDk5ZmJlZjAzYWE5ZmNkY2E0MDA5Mjg2ZjQzNWU1NjM2OWMzNzRkMDA0MmYwM2NjNjBiNDllNjkwYScsXG4gICAgICAgIHY6ICczYzA5MGU4OGVkNDJkYTBkZDBiYWRlMzVjOGQ2Yjg4YmMwNTAyODQ1MzZiOThlNWIyN2QzM2ZmNDVkYTk3NTViJyxcbiAgICAgICAgcjogJzdmMTYyMjRkYmY1YjAyYWRiNmMyMTM4MGZjYjJhOGVlMDAzMjNkYWFlNjJjYWMzNTc1YTRkMzI4ZmQyM2E5MDUnLFxuICAgICAgICBSOiAnOWJlMjIwOGVlMjhjZDRiMjU3N2E5YTY2ZjZhYWIxZWQ4YjA4YTMwMDk2OWVlYjliMjAzYTUyYWE1NGQyYzIzYycsXG4gICAgICAgIGNvbW1pdG1lbnQ6ICc0NDVjOGNiMWRlZTAxNjZiNmJkZDVhZDFkMGE1M2ZiZmU4NmM0ZDNhNDcwZjE4NDc0NTUzMGE4NjNlZWRmZjI4JyxcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcblxuICBjb25zdCB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlID0ge1xuICAgIHhTaGFyZToge1xuICAgICAgaTogMyxcbiAgICAgIHk6ICc0ZDkzNDM5ODhlNjgxOTFhYWM5NDVhNjk2MzAzMWRkZGRlMzQ5MGY5MDIwZDA1NzFhNmU2YzZlMTVjY2EwMjk2JyxcbiAgICAgIHU6ICcxMzE1ZGJlMTgwNjk4MjViNGEyNzE4OGI4MTNlYWU3ZmYyOTE3YTYxNDQ5OWVkNTUzZTcwZDY1ZDRmYTQ4MjBiJyxcbiAgICAgIHI6ICdkMDUzOTM3NWU2NTY2ZjJmZTU0MGNiYTQ4YzVlNTZiZDFjZGY2OGNmZTFmMGQ1MjdkMmI3MzBmZTRlODc5ODA5JyxcbiAgICAgIFI6ICdjODgzZmUyYWU5YjhkYTE3NjRjYzM2YTUyNmNmYTFhMjFmODFkNjA0MzIwYjIwOTg2N2Y4ZGU5MjIzZjFkZTMyJyxcbiAgICB9LFxuICAgIHJTaGFyZXM6IHtcbiAgICAgIDE6IHtcbiAgICAgICAgaTogMSxcbiAgICAgICAgajogMyxcbiAgICAgICAgdTogJzljZTMyMDRhOGM5NzU3NzM4OTY3ZjNmODFiNDYzZDg3MjY3YmY2ZjJjMGU1ZWFmMjg0MzE2NzUzN2I4NzJiMGInLFxuICAgICAgICB2OiAnMDFlYTNmNDI1YjFhZGY4YWVjNmNmZTRmYzhmOWI5NDc1NWMzNDY1Nzk2NWYzMjM5NzY1NWRjZDc4NGYxYjUxNycsXG4gICAgICAgIHI6ICcwMzc1ZThjNWE1NjkxYTczYzIxZGYwMGQ0OWQ0MjNlM2Y4M2ZlMDhkN2I1ZDVhZjMzYzVjNmFhOWNhZTU5ZDBhJyxcbiAgICAgICAgUjogJ2M4ODNmZTJhZTliOGRhMTc2NGNjMzZhNTI2Y2ZhMWEyMWY4MWQ2MDQzMjBiMjA5ODY3ZjhkZTkyMjNmMWRlMzInLFxuICAgICAgICBjb21taXRtZW50OiAnNjJiMjFmOThiZjg4NTg0MWFkNDY5MTQ1MTkyZDRkZjA2OTdiM2Y0MmM1ODFlM2U5MjYzOTRlYWUwYjEwMWVjYicsXG4gICAgICB9LFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgdHhSZXF1ZXN0ID0ge1xuICAgIHR4UmVxdWVzdElkOiAncmFuZG9tSWQnLFxuICAgIHVuc2lnbmVkVHhzOiBbeyBzaWduYWJsZUhleDogJ01QQyBvbiBhIEZyaWRheSBuaWdodCcsIHNlcmlhbGl6ZWRUeEhleDogJ01QQyBvbiBhIEZyaWRheSBuaWdodCcgfV0sXG4gICAgc2lnbmF0dXJlU2hhcmVzOiBbXG4gICAgICB7XG4gICAgICAgIGZyb206ICdiaXRnbycsXG4gICAgICAgIHRvOiAndXNlcicsXG4gICAgICAgIHNoYXJlOiB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlLnJTaGFyZXNbMV0uciArIHZhbGlkQml0Z29Ub1VzZXJTaWduU2hhcmUuclNoYXJlc1sxXS5SLFxuICAgICAgfSxcbiAgICBdLFxuICB9O1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGJlZm9yZSgnaW5pdGlhbGl6ZXMgbXBjJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGhkVHJlZSA9IGF3YWl0IEVkMjU1MTlCSVAzMi5pbml0aWFsaXplKCk7XG4gICAgTVBDID0gYXdhaXQgRWRkc2EuaW5pdGlhbGl6ZShoZFRyZWUpO1xuICB9KTtcblxuICBiZWZvcmUoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvS2V5U2hhcmUgPSBhd2FpdCBNUEMua2V5U2hhcmUoMywgMiwgMyk7XG5cbiAgICB1c2VyR3BnS2V5ID0gYXdhaXQgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICB1c2VySURzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAndGVzdCcsXG4gICAgICAgICAgZW1haWw6ICd0ZXN0QHRlc3QuY29tJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBjdXJ2ZTogJ3NlY3AyNTZrMScsXG4gICAgfSk7XG5cbiAgICBiYWNrdXBHcGdLZXkgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgIHVzZXJJRHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICd0ZXN0QmFja3VwJyxcbiAgICAgICAgICBlbWFpbDogJ3Rlc3RCYWNrdXBAdGVzdC5jb20nLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGN1cnZlOiAnc2VjcDI1NmsxJyxcbiAgICB9KTtcblxuICAgIGJpdGdvR3BnS2V5ID0gYXdhaXQgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICB1c2VySURzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnYml0Z28nLFxuICAgICAgICAgIGVtYWlsOiAnYml0Z29AdGVzdC5jb20nLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGN1cnZlOiAnc2VjcDI1NmsxJyxcbiAgICB9KTtcbiAgICBjb25zdCBjb25zdGFudHMgPSB7XG4gICAgICBtcGM6IHtcbiAgICAgICAgYml0Z29QdWJsaWNLZXk6IGJpdGdvR3BnS2V5LnB1YmxpY0tleSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuXG4gICAgYmFzZUNvaW4gPSBiaXRnby5jb2luKGNvaW5OYW1lKTtcblxuICAgIGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuXG4gICAgLy8gVE9ETyhXUC0zNDYpOiBzZGstdGVzdCBtb2NrcyBjb25mbGljdCBzbyB3ZSBjYW4ndCB1c2UgcGVyc2lzdFxuICAgIG5vY2soYmdVcmwpLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJykudGltZXMoMjMpLnJlcGx5KDIwMCwgeyB0dGw6IDM2MDAsIGNvbnN0YW50cyB9KTtcblxuICAgIGNvbnN0IHdhbGxldERhdGEgPSB7XG4gICAgICBpZDogJzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwJyxcbiAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgIGtleXM6IFtcbiAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NTAwMDAwMDAwJyxcbiAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NjAwMDAwMDAwJyxcbiAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NzAwMDAwMDAwJyxcbiAgICAgIF0sXG4gICAgICBjb2luU3BlY2lmaWM6IHt9LFxuICAgICAgbXVsdGlzaWdUeXBlOiAndHNzJyxcbiAgICB9O1xuICAgIHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2VDb2luLCB3YWxsZXREYXRhKTtcbiAgICB0c3NVdGlscyA9IG5ldyBUc3NVdGlscyhiaXRnbywgYmFzZUNvaW4sIHdhbGxldCk7XG4gIH0pO1xuXG4gIGFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUU1Mga2V5IGNoYWluczonLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBUU1Mga2V5IGNoYWlucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICBjb25zdCBub2NrZWRCaXRHb0tleWNoYWluID0gYXdhaXQgbm9ja0JpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgbm9ja2VkVXNlcktleWNoYWluID0gYXdhaXQgbm9ja1VzZXJLZXljaGFpbih7IGNvaW46IGNvaW5OYW1lIH0pO1xuICAgICAgYXdhaXQgbm9ja0JhY2t1cEtleWNoYWluKHsgY29pbjogY29pbk5hbWUgfSk7XG5cbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB1c2VyS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVVc2VyS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYmFja3VwS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCYWNrdXBLZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnLFxuICAgICAgfSk7XG5cbiAgICAgIGJpdGdvS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRCaXRHb0tleWNoYWluKTtcbiAgICAgIHVzZXJLZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZFVzZXJLZXljaGFpbik7XG5cbiAgICAgIC8vIHVuZW5jcnlwdGVkIGBwcnZgIHByb3BlcnR5IHNob3VsZCBleGlzdCBvbiBiYWNrdXAga2V5Y2hhaW5cbiAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgdVNoYXJlOiBiYWNrdXBLZXlTaGFyZS51U2hhcmUsXG4gICAgICAgIGJpdGdvWVNoYXJlOiBiaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0sXG4gICAgICAgIHVzZXJZU2hhcmU6IHVzZXJLZXlTaGFyZS55U2hhcmVzWzJdLFxuICAgICAgfSkuc2hvdWxkLmVxdWFsKGJhY2t1cEtleWNoYWluLnBydik7XG4gICAgICBzaG91bGQuZXhpc3QoYmFja3VwS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgVFNTIGtleSBjaGFpbnMgd2l0aG91dCBwYXNzcGhyYXNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdXNlcktleVNoYXJlID0gTVBDLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgICAgY29uc3QgYmFja3VwS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMiwgMiwgMyk7XG5cbiAgICAgIGNvbnN0IG5vY2tlZEJpdEdvS2V5Y2hhaW4gPSBhd2FpdCBub2NrQml0Z29LZXljaGFpbih7XG4gICAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleVNoYXJlLFxuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAvLyByZXVzaW5nIHRoZSB1c2VyIGdwZyBrZXkgYXMgdGhlIGJhY2t1cCBncGcga2V5LCBpLmUuIHRoZSB1c2VyIGlzIHRoZWlyIG93biB0aGUgYmFja3VwIHByb3ZpZGVyXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgYml0Z29HcGdLZXksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IG5vY2tlZFVzZXJLZXljaGFpbiA9IGF3YWl0IG5vY2tVc2VyS2V5Y2hhaW4oeyBjb2luOiBjb2luTmFtZSB9KTtcbiAgICAgIGF3YWl0IG5vY2tCYWNrdXBLZXljaGFpbih7IGNvaW46IGNvaW5OYW1lIH0pO1xuXG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlQml0Z29LZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdXNlcktleWNoYWluID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlVXNlcktleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBiYWNrdXBLZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUJhY2t1cEtleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgfSk7XG5cbiAgICAgIGJpdGdvS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRCaXRHb0tleWNoYWluKTtcbiAgICAgIHVzZXJLZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZFVzZXJLZXljaGFpbik7XG5cbiAgICAgIC8vIHVuZW5jcnlwdGVkIGBwcnZgIHByb3BlcnR5IHNob3VsZCBleGlzdCBvbiBiYWNrdXAga2V5Y2hhaW5cbiAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgdVNoYXJlOiBiYWNrdXBLZXlTaGFyZS51U2hhcmUsXG4gICAgICAgIGJpdGdvWVNoYXJlOiBiaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0sXG4gICAgICAgIHVzZXJZU2hhcmU6IHVzZXJLZXlTaGFyZS55U2hhcmVzWzJdLFxuICAgICAgfSkuc2hvdWxkLmVxdWFsKGJhY2t1cEtleWNoYWluLnBydik7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIFRTUyBrZXkgY2hhaW5zIHdpdGggb3B0aW9uYWwgcGFyYW1zJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZW50ZXJwcmlzZSA9ICdlbnRlcnByaXNlJztcblxuICAgICAgY29uc3QgdXNlcktleVNoYXJlID0gTVBDLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgICAgY29uc3QgYmFja3VwS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMiwgMiwgMyk7XG5cbiAgICAgIGNvbnN0IG5vY2tlZEJpdEdvS2V5Y2hhaW4gPSBhd2FpdCBub2NrQml0Z29LZXljaGFpbih7XG4gICAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleVNoYXJlLFxuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIGJpdGdvR3BnS2V5LFxuICAgICAgfSk7XG4gICAgICBjb25zdCBub2NrZWRVc2VyS2V5Y2hhaW4gPSBhd2FpdCBub2NrVXNlcktleWNoYWluKHsgY29pbjogY29pbk5hbWUgfSk7XG4gICAgICBhd2FpdCBub2NrQmFja3VwS2V5Y2hhaW4oeyBjb2luOiBjb2luTmFtZSB9KTtcblxuICAgICAgY29uc3QgYml0Z29LZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUJpdGdvS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGVudGVycHJpc2UsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHVzZXJLZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZVVzZXJLZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnLFxuICAgICAgICBvcmlnaW5hbFBhc3Njb2RlRW5jcnlwdGlvbkNvZGU6ICdvcmlnaW5hbFBhc3Njb2RlRW5jcnlwdGlvbkNvZGUnLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBiYWNrdXBLZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUJhY2t1cEtleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICBwYXNzcGhyYXNlOiAncGFzc3BocmFzZScsXG4gICAgICB9KTtcblxuICAgICAgYml0Z29LZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZEJpdEdvS2V5Y2hhaW4pO1xuICAgICAgdXNlcktleWNoYWluLnNob3VsZC5kZWVwRXF1YWwobm9ja2VkVXNlcktleWNoYWluKTtcblxuICAgICAgLy8gdW5lbmNyeXB0ZWQgYHBydmAgcHJvcGVydHkgc2hvdWxkIGV4aXN0IG9uIGJhY2t1cCBrZXljaGFpblxuICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICB1U2hhcmU6IGJhY2t1cEtleVNoYXJlLnVTaGFyZSxcbiAgICAgICAgYml0Z29ZU2hhcmU6IGJpdGdvS2V5U2hhcmUueVNoYXJlc1syXSxcbiAgICAgICAgdXNlcllTaGFyZTogdXNlcktleVNoYXJlLnlTaGFyZXNbMl0sXG4gICAgICB9KS5zaG91bGQuZXF1YWwoYmFja3VwS2V5Y2hhaW4ucHJ2KTtcbiAgICAgIHNob3VsZC5leGlzdChiYWNrdXBLZXljaGFpbi5lbmNyeXB0ZWRQcnYpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGdlbmVyYXRlIFRTUyBrZXljaGFpbnMgd2hlbiByZWNlaXZlZCBpbnZhbGlkIG51bWJlciBvZiB3YWxsZXQgc2lnbmF0dXJlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgZ2VuZXJhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5U2hhcmUsXG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgYml0Z29HcGdLZXksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgY2VydHNTdHJpbmcgPSBhd2FpdCBjcmVhdGVTaGFyZWREYXRhUHJvb2YoYml0Z29HcGdLZXkucHJpdmF0ZUtleSwgdXNlckdwZ0tleS5wdWJsaWNLZXksIFtdKTtcbiAgICAgIGNvbnN0IGNlcnRzS2V5ID0gYXdhaXQgb3BlbnBncC5yZWFkS2V5KHsgYXJtb3JlZEtleTogY2VydHNTdHJpbmcgfSk7XG4gICAgICBjb25zdCBmaW5hbEtleSA9IG5ldyBvcGVucGdwLlBhY2tldExpc3QoKTtcbiAgICAgIGNlcnRzS2V5LnRvUGFja2V0TGlzdCgpLmZvckVhY2goKHBhY2tldCkgPT4gZmluYWxLZXkucHVzaChwYWNrZXQpKTtcbiAgICAgIC8vIHRoZSB1bmRlcmx5aW5nIGZ1bmN0aW9uIG9ubHkgcmVxdWlyZXMgdHdvIGFyZ3VtZW50cyBidXQgdGhlIGFjY29yZGluZyAuZC50cyBmaWxlIGZvciBvcGVucGdwIGhhcyB0aGUgZnVydGhlclxuICAgICAgLy8gYXJndW1lbnRzIG1hcmtlZCBhcyBtYW5kYXRvcnkgYXMgd2VsbC5cbiAgICAgIC8vIE9uY2UgdGhlIGZvbGxvd2luZyBQUiBoYXMgYmVlbiBtZXJnZWQgYW5kIHJlbGVhc2VkIHdlIG5vIGxvbmdlciBuZWVkIHRoZSB0cy1pZ25vcmU6XG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vb3BlbnBncGpzL29wZW5wZ3Bqcy9wdWxsLzE1NzZcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgIGJpdGdvS2V5Y2hhaW4ud2FsbGV0SFNNR1BHUHVibGljS2V5U2lncyA9IG9wZW5wZ3AuYXJtb3Iob3BlbnBncC5lbnVtcy5hcm1vci5wdWJsaWNLZXksIGZpbmFsS2V5LndyaXRlKCkpO1xuXG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAudmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyh1c2VyR3BnS2V5LnB1YmxpY0tleSwgYmFja3VwR3BnS2V5LnB1YmxpY0tleSwgYml0Z29LZXljaGFpbiwgJycsIDEpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdJbnZhbGlkIHdhbGxldCBzaWduYXR1cmVzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gZ2VuZXJhdGUgVFNTIGtleWNoYWlucyB3aGVuIHdhbGxldCBzaWduYXR1cmUgZmluZ2VycHJpbnRzIGRvIG5vdCBtYXRjaCBwYXNzZWQgdXNlci9iYWNrdXAgZmluZ2VycHJpbnRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdXNlcktleVNoYXJlID0gTVBDLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgICAgY29uc3QgYmFja3VwS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMiwgMiwgMyk7XG5cbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4gPSBhd2FpdCBnZW5lcmF0ZUJpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyB1c2luZyB0aGUgYmFja3VwIGdwZyBoZXJlIGluc3RlYWQgb2YgdGhlIHVzZXIgZ3BnIGtleSB0byBzaW11bGF0ZSB0aGF0IHRoZSBmaXJzdCBzaWduYXR1cmUgaGFzIGEgZGlmZmVyZW50XG4gICAgICAvLyBmaW5nZXJwcmludCBmcm9tIHRoZSBwYXNzZWQgaW4gZmlyc3QgZ3BnIGtleVxuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLnZlcmlmeVdhbGxldFNpZ25hdHVyZXMoYmFja3VwR3BnS2V5LnB1YmxpY0tleSwgYmFja3VwR3BnS2V5LnB1YmxpY0tleSwgYml0Z29LZXljaGFpbiwgJycsIDEpXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKFxuICAgICAgICAgIGBmaXJzdCB3YWxsZXQgc2lnbmF0dXJlJ3MgZmluZ2VycHJpbnQgZG9lcyBub3QgbWF0Y2ggcGFzc2VkIHVzZXIgZ3BnIGtleSdzIGZpbmdlcnByaW50YFxuICAgICAgICApO1xuXG4gICAgICAvLyB1c2luZyB0aGUgdXNlciBncGcgaGVyZSBpbnN0ZWFkIG9mIHRoZSBiYWNrdXAgZ3BnIGtleSB0byBzaW11bGF0ZSB0aGF0IHRoZSBzZWNvbmQgc2lnbmF0dXJlIGhhcyBhIGRpZmZlcmVudFxuICAgICAgLy8gZmluZ2VycHJpbnQgZnJvbSB0aGUgcGFzc2VkIGluIHNlY29uZCBncGcga2V5XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAudmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyh1c2VyR3BnS2V5LnB1YmxpY0tleSwgdXNlckdwZ0tleS5wdWJsaWNLZXksIGJpdGdvS2V5Y2hhaW4sICcnLCAxKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICBgc2Vjb25kIHdhbGxldCBzaWduYXR1cmUncyBmaW5nZXJwcmludCBkb2VzIG5vdCBtYXRjaCBwYXNzZWQgYmFja3VwIGdwZyBrZXkncyBmaW5nZXJwcmludGBcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBnZW5lcmF0ZSBUU1Mga2V5Y2hhaW5zIHdoZW4gd2FsbGV0IHNpZ25hdHVyZSBpcyBmb3IgZGlmZmVyZW50IGtleSBzaGFyZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuICAgICAgY29uc3QgY3VzdG9tQml0Z29LZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgzLCAyLCAzKTtcblxuICAgICAgY29uc3QgYml0Z29LZXljaGFpbjEgPSBhd2FpdCBnZW5lcmF0ZUJpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYml0Z29LZXljaGFpbjIgPSBhd2FpdCBnZW5lcmF0ZUJpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZTogY3VzdG9tQml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyB1c2luZyB0aGUgb3RoZXIgYml0Z28ga2V5Y2hhaW5zIGNvbW1vbiBrZXljaGFpbiBhbmQgd2FsbGV0SFNNR1BHUHVibGljS2V5U2lncyBzbyB0aGF0IHRoZSB2ZXJpZmljYXRpb24gb2YgdGhlXG4gICAgICAvLyBjb21tbW9uIGtleWNoYWluIHBhc3NlcyBidXQgZmFpbHMgZm9yIHRoZSBiaXRnbyB0byB1c2VyLyBiYWNrdXAgc2hhcmVzXG4gICAgICBiaXRnb0tleWNoYWluMS5jb21tb25LZXljaGFpbiA9IGJpdGdvS2V5Y2hhaW4yLmNvbW1vbktleWNoYWluO1xuICAgICAgYml0Z29LZXljaGFpbjEud2FsbGV0SFNNR1BHUHVibGljS2V5U2lncyA9IGJpdGdvS2V5Y2hhaW4yLndhbGxldEhTTUdQR1B1YmxpY0tleVNpZ3M7XG5cbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC5jcmVhdGVVc2VyS2V5Y2hhaW4oe1xuICAgICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgICBiaXRnb0tleWNoYWluOiBiaXRnb0tleWNoYWluMSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2JpdGdvIHNoYXJlIG1pc21hdGNoJyk7XG5cbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC5jcmVhdGVCYWNrdXBLZXljaGFpbih7XG4gICAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICAgIGJpdGdvS2V5Y2hhaW46IGJpdGdvS2V5Y2hhaW4xLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnYml0Z28gc2hhcmUgbWlzbWF0Y2gnKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBnZW5lcmF0ZSBUU1Mga2V5IGNoYWlucyB3aGVuIGNvbW1vbiBrZXljaGFpbnMgZG8gbm90IG1hdGNoJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdXNlcktleVNoYXJlID0gTVBDLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgICAgY29uc3QgYmFja3VwS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMiwgMiwgMyk7XG5cbiAgICAgIGNvbnN0IG5vY2tlZEJpdEdvS2V5Y2hhaW4gPSBhd2FpdCBub2NrQml0Z29LZXljaGFpbih7XG4gICAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleVNoYXJlLFxuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIGJpdGdvR3BnS2V5LFxuICAgICAgfSk7XG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgdHNzVXRpbHMuY3JlYXRlQml0Z29LZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgIH0pO1xuICAgICAgYml0Z29LZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZEJpdEdvS2V5Y2hhaW4pO1xuXG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuY3JlYXRlVXNlcktleWNoYWluKHtcbiAgICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgICAgYmFja3VwS2V5U2hhcmU6IE1QQy5rZXlTaGFyZSgyLCAyLCAzKSxcbiAgICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ZhaWxlZCB0byBjcmVhdGUgdXNlciBrZXljaGFpbiAtIGNvbW1vbktleWNoYWlucyBkbyBub3QgbWF0Y2guJyk7XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuY3JlYXRlVXNlcktleWNoYWluKHtcbiAgICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgICB1c2VyS2V5U2hhcmU6IE1QQy5rZXlTaGFyZSgxLCAyLCAzKSxcbiAgICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ZhaWxlZCB0byBjcmVhdGUgdXNlciBrZXljaGFpbiAtIGNvbW1vbktleWNoYWlucyBkbyBub3QgbWF0Y2guJyk7XG5cbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC5jcmVhdGVCYWNrdXBLZXljaGFpbih7XG4gICAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgICAgdXNlcktleVNoYXJlOiBNUEMua2V5U2hhcmUoMSwgMiwgMyksXG4gICAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgICBwYXNzcGhyYXNlOiAncGFzc3BocmFzZScsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdGYWlsZWQgdG8gY3JlYXRlIGJhY2t1cCBrZXljaGFpbiAtIGNvbW1vbktleWNoYWlucyBkbyBub3QgbWF0Y2guJyk7XG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuY3JlYXRlQmFja3VwS2V5Y2hhaW4oe1xuICAgICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgICBiYWNrdXBLZXlTaGFyZTogTVBDLmtleVNoYXJlKDIsIDIsIDMpLFxuICAgICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnRmFpbGVkIHRvIGNyZWF0ZSBiYWNrdXAga2V5Y2hhaW4gLSBjb21tb25LZXljaGFpbnMgZG8gbm90IG1hdGNoLicpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2lnblR4UmVxdWVzdDonLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhSZXF1ZXN0SWQgPSAncmFuZG9taWQnO1xuICAgIGNvbnN0IHR4UmVxdWVzdDogVHhSZXF1ZXN0ID0ge1xuICAgICAgdHhSZXF1ZXN0SWQsXG4gICAgICB0cmFuc2FjdGlvbnM6IFtdLFxuICAgICAgdW5zaWduZWRUeHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogJ01QQyBvbiBhIEZyaWRheSBuaWdodCcsXG4gICAgICAgICAgc2lnbmFibGVIZXg6ICdNUEMgb24gYSBGcmlkYXkgbmlnaHQnLFxuICAgICAgICAgIGRlcml2YXRpb25QYXRoOiAnbS8wJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkYXRlOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICBpbnRlbnQ6IHtcbiAgICAgICAgaW50ZW50VHlwZTogJ3BheW1lbnQnLFxuICAgICAgfSxcbiAgICAgIGxhdGVzdDogdHJ1ZSxcbiAgICAgIHN0YXRlOiAncGVuZGluZ1VzZXJTaWduYXR1cmUnLFxuICAgICAgd2FsbGV0VHlwZTogJ2hvdCcsXG4gICAgICB3YWxsZXRJZDogJ3dhbGxldElkJyxcbiAgICAgIHBvbGljaWVzQ2hlY2tlZDogdHJ1ZSxcbiAgICAgIHZlcnNpb246IDEsXG4gICAgICB1c2VySWQ6ICd1c2VySWQnLFxuICAgIH07XG5cbiAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJTaWduU2hhcmUgPSB2YWxpZFVzZXJTaWduU2hhcmU7XG4gICAgICBjb25zdCByU2hhcmUgPSB1c2VyU2lnblNoYXJlLnJTaGFyZXNbM107XG4gICAgICBjb25zdCBzaWduYXR1cmVTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7XG4gICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICBzaGFyZTogclNoYXJlLnIgKyByU2hhcmUuUixcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IG5vY2tTZW5kU2lnbmF0dXJlU2hhcmUoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlMjogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7XG4gICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICBzaGFyZTogdmFsaWRCaXRnb1RvVXNlclNpZ25TaGFyZS5yU2hhcmVzWzFdLnIgKyB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlLnJTaGFyZXNbMV0uUixcbiAgICAgIH07XG4gICAgICBjb25zdCByZXNwb25zZSA9IHsgdHhSZXF1ZXN0czogW3sgLi4udHhSZXF1ZXN0LCBzaWduYXR1cmVTaGFyZXM6IFtzaWduYXR1cmVTaGFyZTJdIH1dIH07XG4gICAgICBhd2FpdCBub2NrR2V0VHhSZXF1ZXN0KHsgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLCB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLCByZXNwb25zZSB9KTtcblxuICAgICAgY29uc3QgYml0Z29Ub1VzZXJDb21taXRtZW50U2hhcmU6IENvbW1pdG1lbnRTaGFyZVJlY29yZCA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHR5cGU6IENvbW1pdG1lbnRUeXBlLkNPTU1JVE1FTlQsXG4gICAgICAgIHNoYXJlOiB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlLnJTaGFyZXNbMV0uY29tbWl0bWVudCxcbiAgICAgIH07XG4gICAgICBjb25zdCBleGNoYW5nZUNvbW1pdFJlc3BvbnNlOiBFeGNoYW5nZUNvbW1pdG1lbnRSZXNwb25zZSA9IHsgY29tbWl0bWVudFNoYXJlOiBiaXRnb1RvVXNlckNvbW1pdG1lbnRTaGFyZSB9O1xuICAgICAgYXdhaXQgbm9ja0V4Y2hhbmdlQ29tbWl0bWVudHMoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgIHJlc3BvbnNlOiBleGNoYW5nZUNvbW1pdFJlc3BvbnNlLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2lnblR4UmVxdWVzdCBzaG91bGQgc3VjY2VlZCB3aXRoIHR4UmVxdWVzdCBvYmplY3QgYXMgaW5wdXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBzaWduZWRUeFJlcXVlc3QgPSBhd2FpdCB0c3NVdGlscy5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0LFxuICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHZhbGlkVXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICAgIHJlcUlkLFxuICAgICAgfSk7XG4gICAgICBzaWduZWRUeFJlcXVlc3QudW5zaWduZWRUeHMuc2hvdWxkLmRlZXBFcXVhbCh0eFJlcXVlc3QudW5zaWduZWRUeHMpO1xuXG4gICAgICBzYW5kYm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBzdWNjZWVkIHdpdGggdHhSZXF1ZXN0IGlkIGFzIGlucHV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZ2V0VHhSZXF1ZXN0ID0gc2FuZGJveC5zdHViKHRzc1V0aWxzLCAnZ2V0VHhSZXF1ZXN0Jyk7XG4gICAgICBnZXRUeFJlcXVlc3QucmVzb2x2ZXModHhSZXF1ZXN0KTtcbiAgICAgIGdldFR4UmVxdWVzdC5jYWxsZWRXaXRoKHR4UmVxdWVzdElkKTtcblxuICAgICAgY29uc3Qgc2lnbmVkVHhSZXF1ZXN0ID0gYXdhaXQgdHNzVXRpbHMuc2lnblR4UmVxdWVzdCh7XG4gICAgICAgIHR4UmVxdWVzdDogdHhSZXF1ZXN0SWQsXG4gICAgICAgIHBydjogSlNPTi5zdHJpbmdpZnkodmFsaWRVc2VyU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgICAgcmVxSWQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4UmVxdWVzdC51bnNpZ25lZFR4cy5zaG91bGQuZGVlcEVxdWFsKHR4UmVxdWVzdC51bnNpZ25lZFR4cyk7XG5cbiAgICAgIHNhbmRib3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2lnblR4UmVxdWVzdCBXaXRoIENvbW1pdG1lbnQ6JywgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHR4UmVxdWVzdElkID0gJ3JhbmRvbWlkJztcbiAgICBjb25zdCB0eFJlcXVlc3Q6IFR4UmVxdWVzdCA9IHtcbiAgICAgIHR4UmVxdWVzdElkLFxuICAgICAgdHJhbnNhY3Rpb25zOiBbXSxcbiAgICAgIHVuc2lnbmVkVHhzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBzZXJpYWxpemVkVHhIZXg6ICdNUEMgb24gYSBGcmlkYXkgbmlnaHQnLFxuICAgICAgICAgIHNpZ25hYmxlSGV4OiAnTVBDIG9uIGEgRnJpZGF5IG5pZ2h0JyxcbiAgICAgICAgICBkZXJpdmF0aW9uUGF0aDogJ20vMCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZGF0ZTogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgaW50ZW50OiB7XG4gICAgICAgIGludGVudFR5cGU6ICdwYXltZW50JyxcbiAgICAgIH0sXG4gICAgICBsYXRlc3Q6IHRydWUsXG4gICAgICBzdGF0ZTogJ3BlbmRpbmdVc2VyU2lnbmF0dXJlJyxcbiAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgd2FsbGV0SWQ6ICd3YWxsZXRJZCcsXG4gICAgICBwb2xpY2llc0NoZWNrZWQ6IHRydWUsXG4gICAgICB2ZXJzaW9uOiAxLFxuICAgICAgdXNlcklkOiAndXNlcklkJyxcbiAgICB9O1xuXG4gICAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1c2VyU2lnblNoYXJlID0gdmFsaWRVc2VyU2lnblNoYXJlO1xuICAgICAgY29uc3QgclNoYXJlID0gdXNlclNpZ25TaGFyZS5yU2hhcmVzWzNdO1xuICAgICAgY29uc3Qgc2lnbmF0dXJlU2hhcmU6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgc2hhcmU6IHJTaGFyZS5yICsgclNoYXJlLlIsXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCBub2NrU2VuZFNpZ25hdHVyZVNoYXJlKHtcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLFxuICAgICAgICBzaWduYXR1cmVTaGFyZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBzaWduYXR1cmVTaGFyZTI6IFNpZ25hdHVyZVNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgc2hhcmU6IHZhbGlkQml0Z29Ub1VzZXJTaWduU2hhcmUuclNoYXJlc1sxXS5yICsgdmFsaWRCaXRnb1RvVXNlclNpZ25TaGFyZS5yU2hhcmVzWzFdLlIsXG4gICAgICB9O1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSB7IHR4UmVxdWVzdHM6IFt7IC4uLnR4UmVxdWVzdCwgc2lnbmF0dXJlU2hhcmVzOiBbc2lnbmF0dXJlU2hhcmUyXSB9XSB9O1xuICAgICAgYXdhaXQgbm9ja0dldFR4UmVxdWVzdCh7IHdhbGxldElkOiB3YWxsZXQuaWQoKSwgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCwgcmVzcG9uc2UgfSk7XG4gICAgICBjb25zdCBiaXRnb1RvVXNlckNvbW1pdG1lbnRTaGFyZTogQ29tbWl0bWVudFNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgdHlwZTogQ29tbWl0bWVudFR5cGUuQ09NTUlUTUVOVCxcbiAgICAgICAgc2hhcmU6IHZhbGlkQml0Z29Ub1VzZXJTaWduU2hhcmUuclNoYXJlc1sxXS5jb21taXRtZW50LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV4Y2hhbmdlQ29tbWl0UmVzcG9uc2U6IEV4Y2hhbmdlQ29tbWl0bWVudFJlc3BvbnNlID0geyBjb21taXRtZW50U2hhcmU6IGJpdGdvVG9Vc2VyQ29tbWl0bWVudFNoYXJlIH07XG4gICAgICBhd2FpdCBub2NrRXhjaGFuZ2VDb21taXRtZW50cyh7XG4gICAgICAgIHdhbGxldElkOiB3YWxsZXQuaWQoKSxcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgICAgcmVzcG9uc2U6IGV4Y2hhbmdlQ29tbWl0UmVzcG9uc2UsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBzdWNjZWVkIHdpdGggdHhSZXF1ZXN0IG9iamVjdCBhcyBpbnB1dCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lZFR4UmVxdWVzdCA9IGF3YWl0IHRzc1V0aWxzLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgICB0eFJlcXVlc3QsXG4gICAgICAgIHBydjogSlNPTi5zdHJpbmdpZnkodmFsaWRVc2VyU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgICAgcmVxSWQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4UmVxdWVzdC51bnNpZ25lZFR4cy5zaG91bGQuZGVlcEVxdWFsKHR4UmVxdWVzdC51bnNpZ25lZFR4cyk7XG5cbiAgICAgIHNhbmRib3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NpZ25UeFJlcXVlc3Qgc2hvdWxkIHN1Y2NlZWQgd2l0aCB0eFJlcXVlc3QgaWQgYXMgaW5wdXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBnZXRUeFJlcXVlc3QgPSBzYW5kYm94LnN0dWIodHNzVXRpbHMsICdnZXRUeFJlcXVlc3QnKTtcbiAgICAgIGdldFR4UmVxdWVzdC5yZXNvbHZlcyh0eFJlcXVlc3QpO1xuICAgICAgZ2V0VHhSZXF1ZXN0LmNhbGxlZFdpdGgodHhSZXF1ZXN0SWQpO1xuXG4gICAgICBjb25zdCBzaWduZWRUeFJlcXVlc3QgPSBhd2FpdCB0c3NVdGlscy5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RJZCxcbiAgICAgICAgcHJ2OiBKU09OLnN0cmluZ2lmeSh2YWxpZFVzZXJTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgICByZXFJZCxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkVHhSZXF1ZXN0LnVuc2lnbmVkVHhzLnNob3VsZC5kZWVwRXF1YWwodHhSZXF1ZXN0LnVuc2lnbmVkVHhzKTtcblxuICAgICAgc2FuZGJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdwcmVidWlsZFR4V2l0aEludGVudDonLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBidWlsZCBzaW5nbGUgcmVjaXBpZW50IHR4JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgbm9ja2VkQ3JlYXRlVHggPSBhd2FpdCBub2NrQ3JlYXRlVHhSZXF1ZXN0KHtcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICByZXF1ZXN0Qm9keToge1xuICAgICAgICAgIGFwaVZlcnNpb246ICdsaXRlJyxcbiAgICAgICAgICBpbnRlbnQ6IHtcbiAgICAgICAgICAgIGludGVudFR5cGU6ICdwYXltZW50JyxcbiAgICAgICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFkZHJlc3M6IHtcbiAgICAgICAgICAgICAgICAgIGFkZHJlc3M6ICdyZWNpcGllbnQnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYW1vdW50OiB7XG4gICAgICAgICAgICAgICAgICB2YWx1ZTogJzEwMDAwJyxcbiAgICAgICAgICAgICAgICAgIHN5bWJvbDogJ3Rzb2wnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIC8vIGRvbid0IGNhcmUgYWJvdXQgdGhlIGFjdHVhbCByZXNwb25zZSAtIGp1c3QgbmVlZCB0byBtYWtlIHN1cmUgcmVxdWVzdCBib2R5IG1hdGNoZXNcbiAgICAgICAgcmVzcG9uc2U6IHt9LFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IHRzc1V0aWxzLnByZWJ1aWxkVHhXaXRoSW50ZW50KHtcbiAgICAgICAgcmVxSWQsXG4gICAgICAgIHJlY2lwaWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBhZGRyZXNzOiAncmVjaXBpZW50JyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBpbnRlbnRUeXBlOiAncGF5bWVudCcsXG4gICAgICB9KTtcblxuICAgICAgbm9ja2VkQ3JlYXRlVHguaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgYnVpbGQgbXVsdGlwbGUgcmVjaXBpZW50cyB3aXRoIG1lbW8gdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub2NrZWRDcmVhdGVUeCA9IGF3YWl0IG5vY2tDcmVhdGVUeFJlcXVlc3Qoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHJlcXVlc3RCb2R5OiB7XG4gICAgICAgICAgYXBpVmVyc2lvbjogJ2xpdGUnLFxuICAgICAgICAgIGludGVudDoge1xuICAgICAgICAgICAgaW50ZW50VHlwZTogJ3BheW1lbnQnLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWRkcmVzczoge1xuICAgICAgICAgICAgICAgICAgYWRkcmVzczogJ3JlY2lwaWVudDEnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYW1vdW50OiB7XG4gICAgICAgICAgICAgICAgICB2YWx1ZTogJzEwMDAwJyxcbiAgICAgICAgICAgICAgICAgIHN5bWJvbDogJ3Rzb2wnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiB7XG4gICAgICAgICAgICAgICAgICBhZGRyZXNzOiAncmVjaXBpZW50MicsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IHtcbiAgICAgICAgICAgICAgICAgIHZhbHVlOiAnMjAwMDAnLFxuICAgICAgICAgICAgICAgICAgc3ltYm9sOiAndHNvbCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBtZW1vOiAnbWVtbycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gZG9uJ3QgY2FyZSBhYm91dCB0aGUgYWN0dWFsIHJlc3BvbnNlIC0ganVzdCBuZWVkIHRvIG1ha2Ugc3VyZSByZXF1ZXN0IGJvZHkgbWF0Y2hlc1xuICAgICAgICByZXNwb25zZToge30sXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdHNzVXRpbHMucHJlYnVpbGRUeFdpdGhJbnRlbnQoe1xuICAgICAgICByZXFJZCxcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICdyZWNpcGllbnQxJyxcbiAgICAgICAgICAgIGFtb3VudDogJzEwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICdyZWNpcGllbnQyJyxcbiAgICAgICAgICAgIGFtb3VudDogJzIwMDAwJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBtZW1vOiB7XG4gICAgICAgICAgdmFsdWU6ICdtZW1vJyxcbiAgICAgICAgICB0eXBlOiAndGV4dCcsXG4gICAgICAgIH0sXG4gICAgICAgIGludGVudFR5cGU6ICdwYXltZW50JyxcbiAgICAgIH0pO1xuXG4gICAgICBub2NrZWRDcmVhdGVUeC5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZGVsZXRlIFNpZ25hdHVyZVNoYXJlOicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHN1Y2NlZWQgdG8gZGVsZXRlIFNpZ25hdHVyZSBTaGFyZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlID0geyBmcm9tOiAndXNlcicsIHRvOiAnYml0Z28nLCBzaGFyZTogJzEyOGJ5dGVzdHJpbmcnIH0gYXMgU2lnbmF0dXJlU2hhcmVSZWNvcmQ7XG4gICAgICBjb25zdCBub2NrID0gYXdhaXQgbm9ja0RlbGV0ZVNpZ25hdHVyZVNoYXJlKHtcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLFxuICAgICAgICBzaWduYXR1cmVTaGFyZSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0c3NVdGlscy5kZWxldGVTaWduYXR1cmVTaGFyZXModHhSZXF1ZXN0LnR4UmVxdWVzdElkKTtcbiAgICAgIHJlc3BvbnNlLnNob3VsZC5kZWVwRXF1YWwoW3NpZ25hdHVyZVNoYXJlXSk7XG4gICAgICByZXNwb25zZS5zaG91bGQubGVuZ3RoKDEpO1xuICAgICAgbm9jay5pc0RvbmUoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgc2V0UmVxdWVzdFRyYWNlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlID0geyBmcm9tOiAndXNlcicsIHRvOiAnYml0Z28nLCBzaGFyZTogJzEyOGJ5dGVzdHJpbmcnIH0gYXMgU2lnbmF0dXJlU2hhcmVSZWNvcmQ7XG4gICAgICBjb25zdCBub2NrID0gYXdhaXQgbm9ja0RlbGV0ZVNpZ25hdHVyZVNoYXJlKHtcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLFxuICAgICAgICBzaWduYXR1cmVTaGFyZSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmVxSWQgPSBuZXcgUmVxdWVzdFRyYWNlcigpO1xuICAgICAgY29uc3Qgc2V0UmVxdWVzdFRyYWNlclNweSA9IHNpbm9uLnNweShiaXRnbywgJ3NldFJlcXVlc3RUcmFjZXInKTtcbiAgICAgIHNldFJlcXVlc3RUcmFjZXJTcHkud2l0aEFyZ3MocmVxSWQpO1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0c3NVdGlscy5kZWxldGVTaWduYXR1cmVTaGFyZXModHhSZXF1ZXN0LnR4UmVxdWVzdElkLCByZXFJZCk7XG4gICAgICByZXNwb25zZS5zaG91bGQuZGVlcEVxdWFsKFtzaWduYXR1cmVTaGFyZV0pO1xuICAgICAgcmVzcG9uc2Uuc2hvdWxkLmxlbmd0aCgxKTtcbiAgICAgIG5vY2suaXNEb25lKCkuc2hvdWxkLmVxdWFsKHRydWUpO1xuICAgICAgc2lub24uYXNzZXJ0LmNhbGxlZE9uY2Uoc2V0UmVxdWVzdFRyYWNlclNweSk7XG4gICAgICBzZXRSZXF1ZXN0VHJhY2VyU3B5LnJlc3RvcmUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3NlbmRUeFJlcXVlc3Q6JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgc3VjY2VlZCB0byBzZW5kIHR4IHJlcXVlc3QnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub2NrID0gYXdhaXQgbm9ja1NlbmRUeFJlcXVlc3Qoe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLFxuICAgICAgfSk7XG4gICAgICBhd2FpdCB0c3NVdGlscy5zZW5kVHhSZXF1ZXN0KHR4UmVxdWVzdC50eFJlcXVlc3RJZCkuc2hvdWxkLmJlLmZ1bGZpbGxlZCgpO1xuICAgICAgbm9jay5pc0RvbmUoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGNhbGwgc2V0UmVxdWVzdFRyYWNlcicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vY2sgPSBhd2FpdCBub2NrU2VuZFR4UmVxdWVzdCh7XG4gICAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgICAgIGNvbnN0IHNldFJlcXVlc3RUcmFjZXJTcHkgPSBzaW5vbi5zcHkoYml0Z28sICdzZXRSZXF1ZXN0VHJhY2VyJyk7XG4gICAgICBzZXRSZXF1ZXN0VHJhY2VyU3B5LndpdGhBcmdzKHJlcUlkKTtcbiAgICAgIGF3YWl0IHRzc1V0aWxzLnNlbmRUeFJlcXVlc3QodHhSZXF1ZXN0LnR4UmVxdWVzdElkLCByZXFJZCkuc2hvdWxkLmJlLmZ1bGZpbGxlZCgpO1xuICAgICAgbm9jay5pc0RvbmUoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBzaW5vbi5hc3NlcnQuY2FsbGVkT25jZShzZXRSZXF1ZXN0VHJhY2VyU3B5KTtcbiAgICAgIHNldFJlcXVlc3RUcmFjZXJTcHkucmVzdG9yZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlVXNlclRvQml0Z29Db21taXRtZW50U2hhcmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgYSB2YWxpZCBjb21taXRtZW50U2hhcmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9ICdyYW5kb21zdHJpbmcnO1xuICAgICAgY29uc3QgdmFsaWRVc2VyVG9CaXRnb0NvbW1pdG1lbnRTaGFyZSA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHR5cGU6IENvbW1pdG1lbnRUeXBlLkNPTU1JVE1FTlQsXG4gICAgICAgIHNoYXJlOiB2YWx1ZSxcbiAgICAgIH07XG4gICAgICBjb25zdCBjb21taXRtZW50U2hhcmUgPSB0c3NVdGlscy5jcmVhdGVVc2VyVG9CaXRnb0NvbW1pdG1lbnRTaGFyZSh2YWx1ZSk7XG4gICAgICBjb21taXRtZW50U2hhcmUuc2hvdWxkLmRlZXBFcXVhbCh2YWxpZFVzZXJUb0JpdGdvQ29tbWl0bWVudFNoYXJlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2NyZWF0ZVVzZXJUb0JpdGdvRW5jcnlwdGVkU2lnbmVyU2hhcmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBjcmVhdGUgYSB2YWxpZCBlbmNyeXB0ZWRTaWduZXJTaGFyZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gJ3JhbmRvbXN0cmluZyc7XG4gICAgICBjb25zdCB2YWxpZFVzZXJUb0JpdGdvRW5jcnlwdGVkU2lnbmVyU2hhcmUgPSB7XG4gICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICB0eXBlOiBFbmNyeXB0ZWRTaWduZXJTaGFyZVR5cGUuRU5DUllQVEVEX1NJR05FUl9TSEFSRSxcbiAgICAgICAgc2hhcmU6IHZhbHVlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGVuY3J5cHRlZFNpZ25lclNoYXJlID0gdHNzVXRpbHMuY3JlYXRlVXNlclRvQml0Z29FbmNyeXB0ZWRTaWduZXJTaGFyZSh2YWx1ZSk7XG4gICAgICBlbmNyeXB0ZWRTaWduZXJTaGFyZS5zaG91bGQuZGVlcEVxdWFsKHZhbGlkVXNlclRvQml0Z29FbmNyeXB0ZWRTaWduZXJTaGFyZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdzdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBmdWxsIGZvciBjdXN0b2RpYWwgd2FsbGV0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGN1c3RvZGlhbFdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2VDb2luLCB7IG11bHRpc2lnVHlwZTogJ3RzcycsIHR5cGU6ICdjdXN0b2RpYWwnIH0pO1xuICAgICAgY29uc3QgY3VzdG9kaWFsVHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJhc2VDb2luLCBjdXN0b2RpYWxXYWxsZXQpO1xuICAgICAgY3VzdG9kaWFsVHNzVXRpbHMuc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMoKS5zaG91bGQuZGVlcEVxdWFsKFsnZnVsbCddKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBmdWxsIGZvciBjb2xkIHdhbGxldHMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBjb2xkV2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZUNvaW4sIHsgbXVsdGlzaWdUeXBlOiAndHNzJywgdHlwZTogJ2NvbGQnIH0pO1xuICAgICAgY29uc3QgY29sZFdhbGxldFRzc1V0aWxzID0gbmV3IFRzc1V0aWxzKGJpdGdvLCBiYXNlQ29pbiwgY29sZFdhbGxldCk7XG4gICAgICBjb2xkV2FsbGV0VHNzVXRpbHMuc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMoKS5zaG91bGQuZGVlcEVxdWFsKFsnZnVsbCddKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBmdWxsIGFuZCBsaXRlIGZvciBob3Qgd2FsbGV0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGhvdFdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2VDb2luLCB7IG11bHRpc2lnVHlwZTogJ3RzcycsIHR5cGU6ICdob3QnIH0pO1xuICAgICAgY29uc3QgaG90VHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJhc2VDb2luLCBob3RXYWxsZXQpO1xuICAgICAgY29uc3Qgc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMgPSBob3RUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpO1xuICAgICAgc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMuc2hvdWxkLmRlZXBFcXVhbChbJ2xpdGUnLCAnZnVsbCddKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBmb3IgdHJhZGluZyB3YWxsZXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHJhZGluZ1dhbGxldHMgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwgeyBtdWx0aXNpZ1R5cGU6ICd0c3MnLCB0eXBlOiAndHJhZGluZycgfSk7XG4gICAgICBjb25zdCB0cmFkaW5nV2FsbGV0VHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJhc2VDb2luLCB0cmFkaW5nV2FsbGV0cyk7XG4gICAgICBjb25zdCBzdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucyA9IHRyYWRpbmdXYWxsZXRUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpO1xuICAgICAgc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMuc2hvdWxkLmRlZXBFcXVhbChbXSk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZW1wdHkgZm9yIG5vbi10c3Mgd2FsbGV0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vblRzc1dhbGxldERhdGEgPSB7IGNvaW46ICdidGMnLCBtdWx0aXNpZ1R5cGU6ICdvbmNoYWluJyB9O1xuICAgICAgY29uc3QgYnRjQ29pbiA9IGJpdGdvLmNvaW4oJ3RidGMnKTtcbiAgICAgIGNvbnN0IG5vblRzc1dhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJ0Y0NvaW4sIG5vblRzc1dhbGxldERhdGEpO1xuICAgICAgY29uc3Qgbm9uVHNzV2FsbGV0VHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJ0Y0NvaW4sIG5vblRzc1dhbGxldCk7XG4gICAgICBub25Uc3NXYWxsZXRUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpLnNob3VsZC5kZWVwRXF1YWwoW10pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNQZW5kaW5nQXBwcm92YWxUeFJlcXVlc3RGdWxsJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIGZ1bGwgYXBpVmVyc2lvbiBhbmQgcGVuZGluZ0FwcHJvdmFsIHN0YXRlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhSZXF1ZXN0ID0ge1xuICAgICAgICBhcGlWZXJzaW9uOiAnZnVsbCcsXG4gICAgICAgIHN0YXRlOiAncGVuZGluZ0FwcHJvdmFsJyxcbiAgICAgIH0gYXMgVHhSZXF1ZXN0O1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdHNzVXRpbHMuaXNQZW5kaW5nQXBwcm92YWxUeFJlcXVlc3RGdWxsKHR4UmVxdWVzdCk7XG4gICAgICByZXN1bHQuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBub24tZnVsbCBhcGlWZXJzaW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhSZXF1ZXN0ID0ge1xuICAgICAgICBhcGlWZXJzaW9uOiAnbGl0ZScsXG4gICAgICAgIHN0YXRlOiAncGVuZGluZ0FwcHJvdmFsJyxcbiAgICAgIH0gYXMgVHhSZXF1ZXN0O1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdHNzVXRpbHMuaXNQZW5kaW5nQXBwcm92YWxUeFJlcXVlc3RGdWxsKHR4UmVxdWVzdCk7XG4gICAgICByZXN1bHQuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3Igbm9uLXBlbmRpbmdBcHByb3ZhbCBzdGF0ZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdCA9IHtcbiAgICAgICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgICAgICBzdGF0ZTogJ3BlbmRpbmdEZWxpdmVyeScsXG4gICAgICB9IGFzIFR4UmVxdWVzdDtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRzc1V0aWxzLmlzUGVuZGluZ0FwcHJvdmFsVHhSZXF1ZXN0RnVsbCh0eFJlcXVlc3QpO1xuICAgICAgcmVzdWx0LnNob3VsZC5iZS5mYWxzZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyAjcmVnaW9uIE5vY2sgaGVscGVyc1xuICBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUJpdGdvS2V5Y2hhaW4ocGFyYW1zOiB7XG4gICAgY29pbjogc3RyaW5nO1xuICAgIHVzZXJLZXlTaGFyZTogS2V5U2hhcmU7XG4gICAgYmFja3VwS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIGJpdGdvS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIHVzZXJHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgICBiYWNrdXBHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgICBiaXRnb0dwZ0tleTogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuICB9KTogUHJvbWlzZTxLZXljaGFpbj4ge1xuICAgIGNvbnN0IGJpdGdvQ29tYmluZWQgPSBNUEMua2V5Q29tYmluZShwYXJhbXMuYml0Z29LZXlTaGFyZS51U2hhcmUsIFtcbiAgICAgIHBhcmFtcy51c2VyS2V5U2hhcmUueVNoYXJlc1szXSxcbiAgICAgIHBhcmFtcy5iYWNrdXBLZXlTaGFyZS55U2hhcmVzWzNdLFxuICAgIF0pO1xuICAgIGNvbnN0IHVzZXJHcGdLZXlBY3R1YWwgPSBhd2FpdCBvcGVucGdwLnJlYWRLZXkoeyBhcm1vcmVkS2V5OiBwYXJhbXMudXNlckdwZ0tleS5wdWJsaWNLZXkgfSk7XG4gICAgY29uc3QgYmFja3VwR3BnS2V5QWN0dWFsID0gYXdhaXQgb3BlbnBncC5yZWFkS2V5KHsgYXJtb3JlZEtleTogcGFyYW1zLmJhY2t1cEdwZ0tleS5wdWJsaWNLZXkgfSk7XG5cbiAgICBjb25zdCBiaXRnb1RvVXNlck1lc3NhZ2UgPSBhd2FpdCBvcGVucGdwLmNyZWF0ZU1lc3NhZ2Uoe1xuICAgICAgdGV4dDogQnVmZmVyLmNvbmNhdChbXG4gICAgICAgIEJ1ZmZlci5mcm9tKHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMV0udSwgJ2hleCcpLFxuICAgICAgICBCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS55U2hhcmVzWzFdLmNoYWluY29kZSwgJ2hleCcpLFxuICAgICAgXSkudG9TdHJpbmcoJ2hleCcpLFxuICAgIH0pO1xuICAgIGNvbnN0IGVuY3J5cHRlZEJpdGdvVG9Vc2VyTWVzc2FnZSA9IGF3YWl0IG9wZW5wZ3AuZW5jcnlwdCh7XG4gICAgICBtZXNzYWdlOiBiaXRnb1RvVXNlck1lc3NhZ2UsXG4gICAgICBlbmNyeXB0aW9uS2V5czogW3VzZXJHcGdLZXlBY3R1YWwudG9QdWJsaWMoKV0sXG4gICAgICBmb3JtYXQ6ICdhcm1vcmVkJyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGJpdGdvVG9CYWNrdXBNZXNzYWdlID0gYXdhaXQgb3BlbnBncC5jcmVhdGVNZXNzYWdlKHtcbiAgICAgIHRleHQ6IEJ1ZmZlci5jb25jYXQoW1xuICAgICAgICBCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS55U2hhcmVzWzJdLnUsICdoZXgnKSxcbiAgICAgICAgQnVmZmVyLmZyb20ocGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1syXS5jaGFpbmNvZGUsICdoZXgnKSxcbiAgICAgIF0pLnRvU3RyaW5nKCdoZXgnKSxcbiAgICB9KTtcbiAgICBjb25zdCBlbmNyeXB0ZWRCaXRnb1RvQmFja3VwTWVzc2FnZSA9IGF3YWl0IG9wZW5wZ3AuZW5jcnlwdCh7XG4gICAgICBtZXNzYWdlOiBiaXRnb1RvQmFja3VwTWVzc2FnZSxcbiAgICAgIGVuY3J5cHRpb25LZXlzOiBbYmFja3VwR3BnS2V5QWN0dWFsLnRvUHVibGljKCldLFxuICAgICAgZm9ybWF0OiAnYXJtb3JlZCcsXG4gICAgfSk7XG5cbiAgICBjb25zdCBiaXRnb0tleWNoYWluOiBLZXljaGFpbiA9IHtcbiAgICAgIGlkOiAnMycsXG4gICAgICBwdWI6ICcnLFxuICAgICAgY29tbW9uS2V5Y2hhaW46IGJpdGdvQ29tYmluZWQucFNoYXJlLnkgKyBiaXRnb0NvbWJpbmVkLnBTaGFyZS5jaGFpbmNvZGUsXG4gICAgICBrZXlTaGFyZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGZyb206ICdiaXRnbycsXG4gICAgICAgICAgdG86ICd1c2VyJyxcbiAgICAgICAgICBwdWJsaWNTaGFyZTogcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS55ICsgcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS5jaGFpbmNvZGUsXG4gICAgICAgICAgcHJpdmF0ZVNoYXJlOiBlbmNyeXB0ZWRCaXRnb1RvVXNlck1lc3NhZ2UudG9TdHJpbmcoKSxcbiAgICAgICAgICB2c3NQcm9vZjogcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS52LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgZnJvbTogJ2JpdGdvJyxcbiAgICAgICAgICB0bzogJ2JhY2t1cCcsXG4gICAgICAgICAgcHVibGljU2hhcmU6IHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0ueSArIHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0uY2hhaW5jb2RlLFxuICAgICAgICAgIHByaXZhdGVTaGFyZTogZW5jcnlwdGVkQml0Z29Ub0JhY2t1cE1lc3NhZ2UudG9TdHJpbmcoKSxcbiAgICAgICAgICB2c3NQcm9vZjogcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1syXS52LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHR5cGU6ICd0c3MnLFxuICAgIH07XG5cbiAgICBjb25zdCB1c2VyS2V5SWQgPSB1c2VyR3BnS2V5QWN0dWFsLmtleVBhY2tldC5nZXRGaW5nZXJwcmludCgpO1xuICAgIGNvbnN0IGJhY2t1cEtleUlkID0gYmFja3VwR3BnS2V5QWN0dWFsLmtleVBhY2tldC5nZXRGaW5nZXJwcmludCgpO1xuICAgIGNvbnN0IGJpdGdvVG9Vc2VyUHVibGljU2hhcmUgPVxuICAgICAgQnVmZmVyLmZyb20oXG4gICAgICAgIGF3YWl0IHNvZGl1bS5jcnlwdG9fc2NhbGFybXVsdF9lZDI1NTE5X2Jhc2Vfbm9jbGFtcChCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS55U2hhcmVzWzFdLnUsICdoZXgnKSlcbiAgICAgICkudG9TdHJpbmcoJ2hleCcpICsgcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS5jaGFpbmNvZGU7XG4gICAgY29uc3QgYml0Z29Ub0JhY2t1cFB1YmxpY1NoYXJlID1cbiAgICAgIEJ1ZmZlci5mcm9tKFxuICAgICAgICBhd2FpdCBzb2RpdW0uY3J5cHRvX3NjYWxhcm11bHRfZWQyNTUxOV9iYXNlX25vY2xhbXAoQnVmZmVyLmZyb20ocGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1syXS51LCAnaGV4JykpXG4gICAgICApLnRvU3RyaW5nKCdoZXgnKSArIHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0uY2hhaW5jb2RlO1xuXG4gICAgYml0Z29LZXljaGFpbi53YWxsZXRIU01HUEdQdWJsaWNLZXlTaWdzID0gYXdhaXQgY3JlYXRlV2FsbGV0U2lnbmF0dXJlcyhcbiAgICAgIHBhcmFtcy5iaXRnb0dwZ0tleS5wcml2YXRlS2V5LFxuICAgICAgcGFyYW1zLnVzZXJHcGdLZXkucHVibGljS2V5LFxuICAgICAgcGFyYW1zLmJhY2t1cEdwZ0tleS5wdWJsaWNLZXksXG4gICAgICBbXG4gICAgICAgIHsgbmFtZTogJ2NvbW1vbktleWNoYWluJywgdmFsdWU6IGJpdGdvQ29tYmluZWQucFNoYXJlLnkgKyBiaXRnb0NvbWJpbmVkLnBTaGFyZS5jaGFpbmNvZGUgfSxcbiAgICAgICAgeyBuYW1lOiAndXNlcktleUlkJywgdmFsdWU6IHVzZXJLZXlJZCB9LFxuICAgICAgICB7IG5hbWU6ICdiYWNrdXBLZXlJZCcsIHZhbHVlOiBiYWNrdXBLZXlJZCB9LFxuICAgICAgICB7IG5hbWU6ICdiaXRnb1RvVXNlclB1YmxpY1NoYXJlJywgdmFsdWU6IGJpdGdvVG9Vc2VyUHVibGljU2hhcmUgfSxcbiAgICAgICAgeyBuYW1lOiAnYml0Z29Ub0JhY2t1cFB1YmxpY1NoYXJlJywgdmFsdWU6IGJpdGdvVG9CYWNrdXBQdWJsaWNTaGFyZSB9LFxuICAgICAgXVxuICAgICk7XG5cbiAgICByZXR1cm4gYml0Z29LZXljaGFpbjtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIG5vY2tCaXRnb0tleWNoYWluKHBhcmFtczoge1xuICAgIGNvaW46IHN0cmluZztcbiAgICB1c2VyS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIGJhY2t1cEtleVNoYXJlOiBLZXlTaGFyZTtcbiAgICBiaXRnb0tleVNoYXJlOiBLZXlTaGFyZTtcbiAgICB1c2VyR3BnS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gICAgYmFja3VwR3BnS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gICAgYml0Z29HcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgfSk6IFByb21pc2U8S2V5Y2hhaW4+IHtcbiAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgZ2VuZXJhdGVCaXRnb0tleWNoYWluKHBhcmFtcyk7XG5cbiAgICBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvJHtwYXJhbXMuY29pbn0va2V5YCwgXy5tYXRjaGVzKHsga2V5VHlwZTogJ3RzcycsIHNvdXJjZTogJ2JpdGdvJyB9KSlcbiAgICAgIC5yZXBseSgyMDAsIGJpdGdvS2V5Y2hhaW4pO1xuXG4gICAgcmV0dXJuIGJpdGdvS2V5Y2hhaW47XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrVXNlcktleWNoYWluKHBhcmFtczogeyBjb2luOiBzdHJpbmcgfSk6IFByb21pc2U8S2V5Y2hhaW4+IHtcbiAgICBjb25zdCB1c2VyS2V5Y2hhaW46IEtleWNoYWluID0ge1xuICAgICAgaWQ6ICcxJyxcbiAgICAgIHB1YjogJycsXG4gICAgICB0eXBlOiAndHNzJyxcbiAgICB9O1xuXG4gICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgIC5wb3N0KGAvYXBpL3YyLyR7cGFyYW1zLmNvaW59L2tleWAsIF8ubWF0Y2hlcyh7IGtleVR5cGU6ICd0c3MnLCBzb3VyY2U6ICd1c2VyJyB9KSlcbiAgICAgIC5yZXBseSgyMDAsIHVzZXJLZXljaGFpbik7XG5cbiAgICByZXR1cm4gdXNlcktleWNoYWluO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gbm9ja0JhY2t1cEtleWNoYWluKHBhcmFtczogeyBjb2luOiBzdHJpbmcgfSk6IFByb21pc2U8S2V5Y2hhaW4+IHtcbiAgICBjb25zdCBiYWNrdXBLZXljaGFpbjogS2V5Y2hhaW4gPSB7XG4gICAgICBpZDogJzInLFxuICAgICAgcHViOiAnJyxcbiAgICAgIHR5cGU6ICd0c3MnLFxuICAgIH07XG5cbiAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvJHtwYXJhbXMuY29pbn0va2V5YCwgXy5tYXRjaGVzKHsga2V5VHlwZTogJ3RzcycsIHNvdXJjZTogJ2JhY2t1cCcgfSkpXG4gICAgICAucmVwbHkoMjAwLCBiYWNrdXBLZXljaGFpbik7XG5cbiAgICByZXR1cm4gYmFja3VwS2V5Y2hhaW47XG4gIH1cblxuICAvLyAjZW5kcmVnaW9uIE5vY2sgaGVscGVyc1xufSk7XG4iXX0=

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


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