UNPKG

bitgo

Version:
1,250 lines • 176 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
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 src_1 = require("../../../../../src");
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(src_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 send webauthnInfo (with enterpriseId) on the user keychain when webauthnInfo is provided', async function () {
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            // Real crypto deps (constants w/ bitgo gpg key for verifyWalletSignatures + bitgo keychain),
            // then capture the user keychain add() params by stubbing baseCoin.keychains().
            nock.cleanAll();
            nock(bgUrl)
                .get('/api/v1/client/constants')
                .times(23)
                .reply(200, { ttl: 3600, constants: { mpc: { bitgoPublicKey: bitgoGpgKey.publicKey } } });
            await nockBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            const bitgoKeychain = await tssUtils.createBitgoKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
            });
            const addStub = sandbox.stub().resolves({ id: '1', pub: '', type: 'tss' });
            sandbox.stub(baseCoin, 'keychains').returns({ add: addStub });
            const enterpriseId = 'enterprise_id';
            const webauthnInfo = { otpDeviceId: 'device-123', prfSalt: 'salt-abc', passphrase: 'prf-derived-passphrase' };
            await tssUtils.createUserKeychain({
                userGpgKey,
                backupGpgKey,
                userKeyShare,
                backupKeyShare,
                bitgoKeychain,
                passphrase: 'passphrase',
                webauthnInfo,
                enterprise: enterpriseId,
            });
            // User keychain must carry webauthnInfo (the field the backend POST /key consumes), including
            // enterpriseId, and must NOT use the deprecated webauthnDevices array.
            assert.ok(addStub.calledOnce, 'keychains().add should have been called for the user keychain');
            const body = addStub.firstCall.args[0];
            assert.ok(body.webauthnInfo, 'user keychain body should include webauthnInfo');
            assert.equal(body.webauthnInfo.otpDeviceId, webauthnInfo.otpDeviceId);
            assert.equal(body.webauthnInfo.prfSalt, webauthnInfo.prfSalt);
            assert.equal(body.webauthnInfo.enterpriseId, enterpriseId);
            assert.ok(body.webauthnInfo.encryptedPrv, 'encryptedPrv should be set');
            assert.ok(await bitgo.decrypt({ input: body.webauthnInfo.encryptedPrv, password: webauthnInfo.passphrase }));
            assert.strictEqual(body.webauthnDevices, undefined, 'deprecated webauthnDevices should not be sent');
        });
        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.');
        });
        it('should generate TSS key chains with v2 encryption envelopes', async function () {
            const passphrase = 'passphrase';
            const userKeyShare = MPC.keyShare(1, 2, 3);
            const backupKeyShare = MPC.keyShare(2, 2, 3);
            await nockBitgoKeychain({
                coin: coinName,
                userKeyShare,
                backupKeyShare,
                bitgoKeyShare,
                userGpgKey,
                backupGpgKey,
                bitgoGpgKey,
            });
            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,
                encryptionVersion: 2,
            });
            should.exist(userKeychain.encryptedPrv);
            const envelope = JSON.parse(userKeychain.encryptedPrv);
            envelope.v.should.equal(2);
            const decrypted = await bitgo.decrypt({ input: userKeychain.encryptedPrv, password: passphrase });
            should.exist(decrypted);
            const parsed = JSON.parse(decrypted);
            should.exist(parsed.uShare);
        });
    });
    describe('v2 encryption (EdDSA signing dispatch)', function () {
        const signingTxRequest = {
            txRequestId: 'v2-signing-test',
            unsignedTxs: [
                {
                    serializedTxHex: 'test-payload',
                    signableHex: 'deadbeef',
                    derivationPath: 'm/0',
                },
            ],
            date: new Date().toISOString(),
            intent: { intentType: 'payment' },
            latest: true,
            state: 'pendingUserSignature',
            walletType: 'hot',
            walletId: 'walletId',
            policiesChecked: true,
            version: 1,
            userId: 'userId',
        };
        it('v2 R-share round-trip: encrypt via commitment, verify envelope, decrypt via createRShare', async function () {
            const passphrase = 'test-passphrase';
            const prv = JSON.stringify(validUserSigningMaterial);
            // 1. Encrypt prv with v2
            const encryptedPrv = await bitgo.encrypt({
                input: prv,
                password: passphrase,
                encryptionVersion: 2,
            });
            JSON.parse(encryptedPrv).v.should.equal(2);
            // 2. Create commitment -- R-share should be a v2 envelope
            const commitResult = await tssUtils.createCommitmentShareFromTxRequest({
                txRequest: signingTxRequest,
                prv,
                walletPassphrase: passphrase,
                bitgoGpgPubKey: bitgoGpgKey.publicKey,
                encryptedPrv,
            });
            const rShareEnvelope = JSON.parse(commitResult.encryptedUserToBitgoRShare.share);
            rShareEnvelope.v.should.equal(2);
            rShareEnvelope.should.have.property('hkdfSalt');
            // 3. Round-trip: decrypt the v2 R-share
            const { rShare } = await tssUtils.createRShareFromTxRequest({
                txRequest: signingTxRequest,
                walletPassphrase: passphrase,
                encryptedUserToBitgoRShare: commitResult.encryptedUserToBitgoRShare,
            });
            should.exist(rShare.xShare);
            should.exist(rShare.rShares);
        });
    });
    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('signTxRequestForMessage:', function () {
        const txRequestId = 'randomid-abc';
        const messageRaw = 'hello world';
        const messageEncoded = Buffer.from(`${messageRaw}`).toString('hex');
        const bufferToSign = Buffer.from(messageEncoded, 'hex');
        const txRequest = {
            txRequestId,
            transactions: [],
            messages: [
                {
                    state: 'pendingSignature',
                    signatureShares: [],
                    messageRaw,
                    messageEncoded,
                    derivationPath: 'm/0',
                },
            ],
            unsignedTxs: [],
            date: new Date().toISOString(),
            intent: {
                intentType: 'payment',
            },
            latest: true,
            state: 'pendingUserSignature',
            walletType: 'hot',
            walletId: 'walletId',
            policiesChecked: true,
            version: 1,
            userId: 'userId',
            apiVersion: 'full',
        };
        beforeEach(async function () {
            const rShare = validUserSignShare.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,
                requestType: sdk_core_1.RequestType.message,
                apiMode: 'full',
            });
            const signatureShare2 = {
                from: sdk_core_1.SignatureShareType.BITGO,
                to: sdk_core_1.SignatureShareType.USER,
                share: validBitgoToUserSignShare.rShares[1].r + validBitgoToUserSignShare.rShares[1].R,
            };
            txRequest.messages[0].signatureShares.push(signatureShare2);
            const response = { txRequests: [{ ...txRequest, apiVersion: 'full' }] };
            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,
                apiMode: 'full',
            });
        });
        afterEach(async function () {
            txRequest.messages[0].signatureShares = [];
        });
        it('signTxRequest should succeed with txRequest object as input', async function () {
            const signedTxRequest = await tssUtils.signTxRequestForMessage({
                messageRaw,
                bufferToSign,
                txRequest,
                prv: JSON.stringify(validUserSigningMaterial),
                reqId,
            });
            signedTxRequest.messages.should.deepEqual(txRequest.messages);
            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.signTxRequestForMessage({
                txRequest: txRequestId,
                prv: JSON.stringify(validUserSigningMaterial),
                reqId,
                messageRaw,
                bufferToSign,
            });
            signedTxRequest.messages.should.deepEqual(txRequest.messages);
            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',
                multisigTypeVersion: undefined,
                type: 'hot',
            });
            const hotTssUtils = new sdk_core_1.TssUtils(bitgo, baseCoin, hotWallet);
            const supportedTxRequestVersions = hotTssUtils.supportedTxRequestVersions();
            supportedTxRequestVersions.should.deepEqual(['lite', 'full']);
        });
        it('should return only full for hot MPCv2 wallets', function () {
            const hotMPCv2Wallet = new sdk_core_1.Wallet(bitgo, baseCoin, {
                multisigType: 'tss',
                multisigTypeVersion: 'MPCv2',
                type: 'hot',
            });
            const mpcv2TssUtils = new sdk_core_1.EDDSAUtils.EddsaMPCv2Utils(bitgo, baseCoin, hotMPCv2Wallet);
            mpcv2TssUtils.supportedTxRequestVersions().should.deepEqual(['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;
    }
    describe('getPublicKeyFromCommonKeychain', function () {
        // 32-byte ed25519 public key as hex (64 chars) + 32-byte chaincode (64 chars) = 128 chars
        const pubHex = 'a304733c16cc821fe171d5c7dbd7276fd90deae808b7553d17a1e55e4a76b270';
        const chaincode = '9d91c2e6353202cf61f8f275158b3468e9a00f7872fc2fd310b72cd026e2e2f9';
        const commonKeychain = pubHex + chaincode;
        it('should decode the 32-byte public key from a 128-char commonKeychain', function () {
            commonKeychain.length.should.equal(128);
            const result = sdk_core_1.TssUtils.getPublicKeyFromCommonKeychain(commonKeychain);
            result.should.equal('ByMPeVxs7e8zGecu8n1M43Mq9qkxBSypNNwHeEu2N6vb');
        });
        it('should throw for an invalid commonKeychain length', function () {
            should.throws(() => sdk_core_1.TssUtils.getPublicKeyFromCommonKeychain('abcd'), /Invalid commonKeychain length, expected 128, got 4/);
        });
    });
    describe('getBitgoGpgPubkeyBasedOnFeatureFlags', function () {
        it('should return eddsaMpcv2PublicKey when present in feature flags response', async function () {
            const ed25519KeyPair = await openpgp.generateKey({
                userIDs: [{ name: 'bitgo eddsa', email: 'bitgo@test.com' }],
                curve: 'ed25519',
            });
            const response = {
                name: 'irrelevant',
                publicKey: ed25519KeyPair.publicKey,
                mpcv2PublicKey: ed25519KeyPair.publicKey,
                eddsaMpcv2PublicKey: ed25519KeyPair.publicKey,
                enterpriseId: 'enterprise_id',
            };
            nock(bgUrl).get(`/api/v2/${coinName}/tss/pubkey`).query({ enterpriseId: 'enterprise_id' }).reply(200, response);
            const { eddsaMpcv2PublicKey } = await tssUtils.getBitgoGpgPubkeyBasedOnFeatureFlags('enterprise_id');
            should.exist(eddsaMpcv2PublicKey);
            should.equal(ed25519KeyPair.publicKey, eddsaMpcv2PublicKey.armor());
        });
        it('should return undefined eddsaMpcv2PublicKey when absent from feature flags response', async function () {
            const keyPair = await openpgp.generateKey({
                userIDs: [{ name: 'bitgo', email: 'bitgo@test.com' }],
            });
            const response = {
                name: 'irrelevant',
                publicKey: keyPair.publicKey,
                mpcv2PublicKey: keyPair.publicKey,
                enterpriseId: 'enterprise_id',
            };
            nock(bgUrl).get(`/api/v2/${coinName}/tss/pubkey`).query({ enterpriseId: 'enterprise_id' }).reply(200, response);
            const { eddsaMpcv2PublicKey } = await tssUtils.getBitgoGpgPubkeyBasedOnFeatureFlags('enterprise_id');
            should.not.exist(eddsaMpcv2PublicKey);
        });
    });
    // #endregion Nock helpers
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRkc2EuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi90ZXN0L3YyL3VuaXQvaW50ZXJuYWwvdHNzVXRpbHMvZWRkc2EudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxpQ0FBaUM7QUFDakMsa0RBQWtEO0FBQ2xELDRCQUE0QjtBQUM1Qiw2QkFBOEI7QUFDOUIsbUNBQW1DO0FBQ25DLGlDQUFrQztBQUNsQywrQkFBK0I7QUFFL0IsOENBQXdEO0FBQ3hELDRDQUEyQztBQUMzQyw4Q0FzQnlCO0FBQ3pCLCtDQUEyRDtBQUMzRCxxQ0FPa0I7QUFFbEIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztBQUV4QyxRQUFRLENBQUMsWUFBWSxFQUFFLEtBQUs7SUFDMUIsSUFBSSxPQUEyQixDQUFDO0lBQ2hDLElBQUksR0FBVSxDQUFDO0lBQ2YsSUFBSSxLQUFhLENBQUM7SUFDbEIsSUFBSSxRQUFrQixDQUFDO0lBQ3ZCLElBQUksVUFBVSxDQUFDO0lBQ2YsSUFBSSxZQUFZLENBQUM7SUFDakIsSUFBSSxXQUFXLENBQUM7SUFDaEIsSUFBSSxLQUF5QixDQUFDO0lBQzlCLElBQUksUUFBa0IsQ0FBQztJQUN2QixJQUFJLE1BQWMsQ0FBQztJQUNuQixJQUFJLGFBQWEsQ0FBQztJQUNsQixNQUFNLEtBQUssR0FBRyxJQUFJLHdCQUFhLEVBQUUsQ0FBQztJQUNsQyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUM7SUFDeEIsTUFBTSx3QkFBd0IsR0FBRztRQUMvQixNQUFNLEVBQUU7WUFDTixDQUFDLEVBQUUsQ0FBQztZQUNKLENBQUMsRUFBRSxDQUFDO1lBQ0osQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsa0VBQWtFO1lBQ3JFLElBQUksRUFBRSxrRUFBa0U7WUFDeEUsU0FBUyxFQUFFLGtFQUFrRTtTQUM5RTtRQUNELGVBQWUsRUFBRSxrRUFBa0U7UUFDbkYsV0FBVyxF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QUFFLGdCQUFnQixFQUFFLENBQUM7YUFDdEQsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQXNCO2dCQUNsQyxJQUFJLEVBQUUsWUFBWTtnQkFDbEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO2dCQUM1QixjQUFjLEVBQUUsT0FBTyxDQUFDLFNBQVM7Z0JBQ2pDLFlBQVksRUFBRSxlQUFlO2FBQzlCLENBQUM7WUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLFdBQVcsUUFBUSxhQUFhLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ2hILE1BQU0sRUFBRSxtQkFBbUIsRUFBRSxHQUFHLE1BQU0sUUFBUSxDQUFDLG9DQUFvQyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQ3JHLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDeEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUVILDBCQUEwQjtBQUM1QixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGFzc2VydCBmcm9tICdhc3NlcnQnO1xuaW1wb3J0ICogYXMgc29kaXVtIGZyb20gJ2xpYnNvZGl1bS13cmFwcGVycy1zdW1vJztcbmltcG9ydCAqIGFzIF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBub2NrID0gcmVxdWlyZSgnbm9jaycpO1xuaW1wb3J0ICogYXMgb3BlbnBncCBmcm9tICdvcGVucGdwJztcbmltcG9ydCBzaG91bGQgPSByZXF1aXJlKCdzaG91bGQnKTtcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcblxuaW1wb3J0IHsgVGVzdGFibGVCRywgVGVzdEJpdEdvIH0gZnJvbSAnQGJpdGdvL3Nkay10ZXN0JztcbmltcG9ydCB7IEJpdEdvIH0gZnJvbSAnLi4vLi4vLi4vLi4vLi4vc3JjJztcbmltcG9ydCB7XG4gIEFkZEtleWNoYWluT3B0aW9ucyxcbiAgQmFzZUNvaW4sXG4gIEJpdGdvR1BHUHVibGljS2V5LFxuICBDb21taXRtZW50U2hhcmVSZWNvcmQsXG4gIENvbW1pdG1lbnRUeXBlLFxuICBjb21tb24sXG4gIGNyZWF0ZVNoYXJlZERhdGFQcm9vZixcbiAgRWQyNTUxOUJJUDMyLFxuICBFRERTQVV0aWxzLFxuICBFZGRzYSxcbiAgRW5jcnlwdGVkU2lnbmVyU2hhcmVUeXBlLFxuICBFeGNoYW5nZUNvbW1pdG1lbnRSZXNwb25zZSxcbiAgS2V5Y2hhaW4sXG4gIEtleVNoYXJlLFxuICBSZXF1ZXN0VHJhY2VyLFxuICBSZXF1ZXN0VHlwZSxcbiAgU2lnbmF0dXJlU2hhcmVSZWNvcmQsXG4gIFNpZ25hdHVyZVNoYXJlVHlwZSxcbiAgVHNzVXRpbHMsXG4gIFR4UmVxdWVzdCxcbiAgV2FsbGV0LFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgY3JlYXRlV2FsbGV0U2lnbmF0dXJlcyB9IGZyb20gJy4uLy4uL3Rzcy9oZWxwZXJzJztcbmltcG9ydCB7XG4gIG5vY2tDcmVhdGVUeFJlcXVlc3QsXG4gIG5vY2tEZWxldGVTaWduYXR1cmVTaGFyZSxcbiAgbm9ja0V4Y2hhbmdlQ29tbWl0bWVudHMsXG4gIG5vY2tHZXRUeFJlcXVlc3QsXG4gIG5vY2tTZW5kU2lnbmF0dXJlU2hhcmUsXG4gIG5vY2tTZW5kVHhSZXF1ZXN0LFxufSBmcm9tICcuL2NvbW1vbic7XG5cbm9wZW5wZ3AuY29uZmlnLnJlamVjdEN1cnZlcyA9IG5ldyBTZXQoKTtcblxuZGVzY3JpYmUoJ1RTUyBVdGlsczonLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gIGxldCBzYW5kYm94OiBzaW5vbi5TaW5vblNhbmRib3g7XG4gIGxldCBNUEM6IEVkZHNhO1xuICBsZXQgYmdVcmw6IHN0cmluZztcbiAgbGV0IHRzc1V0aWxzOiBUc3NVdGlscztcbiAgbGV0IHVzZXJHcGdLZXk7XG4gIGxldCBiYWNrdXBHcGdLZXk7XG4gIGxldCBiaXRnb0dwZ0tleTtcbiAgbGV0IGJpdGdvOiBUZXN0YWJsZUJHICYgQml0R287XG4gIGxldCBiYXNlQ29pbjogQmFzZUNvaW47XG4gIGxldCB3YWxsZXQ6IFdhbGxldDtcbiAgbGV0IGJpdGdvS2V5U2hhcmU7XG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgY29uc3QgY29pbk5hbWUgPSAndHNvbCc7XG4gIGNvbnN0IHZhbGlkVXNlclNpZ25pbmdNYXRlcmlhbCA9IHtcbiAgICB1U2hhcmU6IHtcbiAgICAgIGk6IDEsXG4gICAgICB0OiAyLFxuICAgICAgbjogMyxcbiAgICAgIHk6ICcwOTNjODYwM2FkODZjNDFkNWVlMjVhODE0Yjg4MTg1YjQzNWRkM2E5Y2VjY2Y5YzlmZDY5MWE0NjVhYzRhOGIwJyxcbiAgICAgIHNlZWQ6ICdjYTQwYzc4OTgxMzI1MGMzMzRkZGQyYmExOTA1MGY2ZWQyMGI1YTA4ODUzY2VjYTQ5MjM1OGYyNzExYWQ0YjE1JyxcbiAgICAgIGNoYWluY29kZTogJzU5NmQ1NDA0YTdlYjkxOGVlNzgyNDdiOTUyZDA2NTM5NjE5ODg0MDkxZmRkOWUwZmY1YTY2NWYzNDllMzJmY2EnLFxuICAgIH0sXG4gICAgY29tbW9uQ2hhaW5jb2RlOiAnNTk2ZDU0MDRhN2ViOTE4ZWU3ODI0N2I5NTJkMDY1Mzk2MTk4ODQwOTFmZGQ5ZTBmZjVhNjY1ZjM0OWUzMmZjYScsXG4gICAgYml0Z29ZU2hhcmU6IHtcbiAgICAgIGk6IDEsXG4gICAgICBqOiAzLFxuICAgICAgeTogJzU5ZDgwMDBiYTVlODVmYTQwMmYzOTM4Mjk2MGU3ZDVlZGU4MmIxYjZlMjJiMTQ2YTE4YjdkZjIzOGMzYTMyMjUnLFxuICAgICAgdjogJzAxZWEzZjQyNWIxYWRmOGFlYzZjZmU0ZmM4ZjliOTQ3NTVjMzQ2NTc5NjVmMzIzOTc2NTVkY2Q3ODRmMWI1MTcnLFxuICAgICAgdTogJzljZTMyMDRhOGM5NzU3NzM4OTY3ZjNmODFiNDYzZDg3MjY3YmY2ZjJjMGU1ZWFmMjg0MzE2NzUzN2I4NzJiMGInLFxuICAgICAgY2hhaW5jb2RlOiAnZDIxZGJkOGVhZTVkNDc4OTI5MmVjZWEyZWZhNTNlMDE2NWIyNDM5ZDU3ZjUxNThlYjRkZDU3ZGMyNmI1OTIzNicsXG4gICAgfSxcbiAgICBiYWNrdXBZU2hhcmU6IHtcbiAgICAgIGk6IDEsXG4gICAgICBqOiAyLFxuICAgICAgeTogJ2UwYWU3NTA3NzcxNTY4NmExMjFhY2I0MWIyOWE1NWJkZTQyNjk3MTE1NGY0MGE0MWZjMzE3ZjdmNzc0YTk0MjQnLFxuICAgICAgdjogJ2Y3NmVmNjI5ZGZjMTVhYjVlNDUzMWU1MzJiNWQ2N2YyMTc2NjM3Y2E3NTJiMTk1ODc2YjdlMzE3MjQ1OWM5NjknLFxuICAgICAgdTogJ2ZlNmI4OWZiNmFjZmNkNzM5MmMzNWMwODRmNThiZGUwODQ2Yjg4OGM0ZGY1N2U0NjZjYWYwYTMyNzFiMDZhMDUnLFxuICAgICAgY2hhaW5jb2RlOiAnMWMzNGU1ZGZiYmQ0YTg3MGY0NDc5Y2FhYTVlNmE0NmUzNDM4Zjk3NmFkNWFlZmQ0OTA1YjhmZThiY2ExMTAxZScsXG4gICAgfSxcbiAgfTtcblxuICBjb25zdCB2YWxpZFVzZXJTaWduU2hhcmUgPSB7XG4gICAgeFNoYXJlOiB7XG4gICAgICBpOiAxLFxuICAgICAgeTogJzRkOTM0Mzk4OGU2ODE5MWFhYzk0NWE2OTYzMDMxZGRkZGUzNDkwZjkwMjBkMDU3MWE2ZTZjNmUxNWNjYTAyOTYnLFxuICAgICAgdTogJzFlMTU5ZDZhMGFlM2E4ZGNjYzc0NjE1MTEzZTdjM2UyNWQzMDgwZTVlMGZmZWIwYWUwNGRkNmE5NjcyNjgxMDInLFxuICAgICAgcjogJ2M4ZjY0Y2M0ODkyNjIxNmMzZjYwZTFkOGZmMWUyNGViYTA2MGQ3YzFmZjAyMGQwZmMxZDczNWQ0NTY0ZWZkMDMnLFxuICAgICAgUjogJzliZTIyMDhlZTI4Y2Q0YjI1NzdhOWE2NmY2YWFiMWVkOGIwOGEzMDA5NjllZWI5YjIwM2E1MmFhNTRkMmMyM2MnLFxuICAgIH0sXG4gICAgclNoYXJlczoge1xuICAgICAgMzoge1xuICAgICAgICBpOiAzLFxuICAgICAgICBqOiAxLFxuICAgICAgICB1OiAnZDY3NWY5MDk5ZmJlZjAzYWE5ZmNkY2E0MDA5Mjg2ZjQzNWU1NjM2OWMzNzRkMDA0MmYwM2NjNjBiNDllNjkwYScsXG4gICAgICAgIHY6ICczYzA5MGU4OGVkNDJkYTBkZDBiYWRlMzVjOGQ2Yjg4YmMwNTAyODQ1MzZiOThlNWIyN2QzM2ZmNDVkYTk3NTViJyxcbiAgICAgICAgcjogJzdmMTYyMjRkYmY1YjAyYWRiNmMyMTM4MGZjYjJhOGVlMDAzMjNkYWFlNjJjYWMzNTc1YTRkMzI4ZmQyM2E5MDUnLFxuICAgICAgICBSOiAnOWJlMjIwOGVlMjhjZDRiMjU3N2E5YTY2ZjZhYWIxZWQ4YjA4YTMwMDk2OWVlYjliMjAzYTUyYWE1NGQyYzIzYycsXG4gICAgICAgIGNvbW1pdG1lbnQ6ICc0NDVjOGNiMWRlZTAxNjZiNmJkZDVhZDFkMGE1M2ZiZmU4NmM0ZDNhNDcwZjE4NDc0NTUzMGE4NjNlZWRmZjI4JyxcbiAgICAgIH0sXG4gICAgfSxcbiAgfTtcblxuICBjb25zdCB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlID0ge1xuICAgIHhTaGFyZToge1xuICAgICAgaTogMyxcbiAgICAgIHk6ICc0ZDkzNDM5ODhlNjgxOTFhYWM5NDVhNjk2MzAzMWRkZGRlMzQ5MGY5MDIwZDA1NzFhNmU2YzZlMTVjY2EwMjk2JyxcbiAgICAgIHU6ICcxMzE1ZGJlMTgwNjk4MjViNGEyNzE4OGI4MTNlYWU3ZmYyOTE3YTYxNDQ5OWVkNTUzZTcwZDY1ZDRmYTQ4MjBiJyxcbiAgICAgIHI6ICdkMDUzOTM3NWU2NTY2ZjJmZTU0MGNiYTQ4YzVlNTZiZDFjZGY2OGNmZTFmMGQ1MjdkMmI3MzBmZTRlODc5ODA5JyxcbiAgICAgIFI6ICdjODgzZmUyYWU5YjhkYTE3NjRjYzM2YTUyNmNmYTFhMjFmODFkNjA0MzIwYjIwOTg2N2Y4ZGU5MjIzZjFkZTMyJyxcbiAgICB9LFxuICAgIHJTaGFyZXM6IHtcbiAgICAgIDE6IHtcbiAgICAgICAgaTogMSxcbiAgICAgICAgajogMyxcbiAgICAgICAgdTogJzljZTMyMDRhOGM5NzU3NzM4OTY3ZjNmODFiNDYzZDg3MjY3YmY2ZjJjMGU1ZWFmMjg0MzE2NzUzN2I4NzJiMGInLFxuICAgICAgICB2OiAnMDFlYTNmNDI1YjFhZGY4YWVjNmNmZTRmYzhmOWI5NDc1NWMzNDY1Nzk2NWYzMjM5NzY1NWRjZDc4NGYxYjUxNycsXG4gICAgICAgIHI6ICcwMzc1ZThjNWE1NjkxYTczYzIxZGYwMGQ0OWQ0MjNlM2Y4M2ZlMDhkN2I1ZDVhZjMzYzVjNmFhOWNhZTU5ZDBhJyxcbiAgICAgICAgUjogJ2M4ODNmZTJhZTliOGRhMTc2NGNjMzZhNTI2Y2ZhMWEyMWY4MWQ2MDQzMjBiMjA5ODY3ZjhkZTkyMjNmMWRlMzInLFxuICAgICAgICBjb21taXRtZW50OiAnNjJiMjFmOThiZjg4NTg0MWFkNDY5MTQ1MTkyZDRkZjA2OTdiM2Y0MmM1ODFlM2U5MjYzOTRlYWUwYjEwMWVjYicsXG4gICAgICB9LFxuICAgIH0sXG4gIH07XG5cbiAgY29uc3QgdHhSZXF1ZXN0ID0ge1xuICAgIHR4UmVxdWVzdElkOiAncmFuZG9tSWQnLFxuICAgIHVuc2lnbmVkVHhzOiBbeyBzaWduYWJsZUhleDogJ01QQyBvbiBhIEZyaWRheSBuaWdodCcsIHNlcmlhbGl6ZWRUeEhleDogJ01QQyBvbiBhIEZyaWRheSBuaWdodCcgfV0sXG4gICAgc2lnbmF0dXJlU2hhcmVzOiBbXG4gICAgICB7XG4gICAgICAgIGZyb206ICdiaXRnbycsXG4gICAgICAgIHRvOiAndXNlcicsXG4gICAgICAgIHNoYXJlOiB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlLnJTaGFyZXNbMV0uciArIHZhbGlkQml0Z29Ub1VzZXJTaWduU2hhcmUuclNoYXJlc1sxXS5SLFxuICAgICAgfSxcbiAgICBdLFxuICB9O1xuXG4gIGJlZm9yZUVhY2goZnVuY3Rpb24gKCkge1xuICAgIHNhbmRib3ggPSBzaW5vbi5jcmVhdGVTYW5kYm94KCk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gIH0pO1xuXG4gIGJlZm9yZSgnaW5pdGlhbGl6ZXMgbXBjJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IGhkVHJlZSA9IGF3YWl0IEVkMjU1MTlCSVAzMi5pbml0aWFsaXplKCk7XG4gICAgTVBDID0gYXdhaXQgRWRkc2EuaW5pdGlhbGl6ZShoZFRyZWUpO1xuICB9KTtcblxuICBiZWZvcmUoYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGJpdGdvS2V5U2hhcmUgPSBhd2FpdCBNUEMua2V5U2hhcmUoMywgMiwgMyk7XG5cbiAgICB1c2VyR3BnS2V5ID0gYXdhaXQgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICB1c2VySURzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAndGVzdCcsXG4gICAgICAgICAgZW1haWw6ICd0ZXN0QHRlc3QuY29tJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBjdXJ2ZTogJ3NlY3AyNTZrMScsXG4gICAgfSk7XG5cbiAgICBiYWNrdXBHcGdLZXkgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgIHVzZXJJRHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICd0ZXN0QmFja3VwJyxcbiAgICAgICAgICBlbWFpbDogJ3Rlc3RCYWNrdXBAdGVzdC5jb20nLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGN1cnZlOiAnc2VjcDI1NmsxJyxcbiAgICB9KTtcblxuICAgIGJpdGdvR3BnS2V5ID0gYXdhaXQgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICB1c2VySURzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiAnYml0Z28nLFxuICAgICAgICAgIGVtYWlsOiAnYml0Z29AdGVzdC5jb20nLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGN1cnZlOiAnc2VjcDI1NmsxJyxcbiAgICB9KTtcbiAgICBjb25zdCBjb25zdGFudHMgPSB7XG4gICAgICBtcGM6IHtcbiAgICAgICAgYml0Z29QdWJsaWNLZXk6IGJpdGdvR3BnS2V5LnB1YmxpY0tleSxcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ21vY2snIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuXG4gICAgYmFzZUNvaW4gPSBiaXRnby5jb2luKGNvaW5OYW1lKTtcblxuICAgIGJnVXJsID0gY29tbW9uLkVudmlyb25tZW50c1tiaXRnby5nZXRFbnYoKV0udXJpO1xuXG4gICAgLy8gVE9ETyhXUC0zNDYpOiBzZGstdGVzdCBtb2NrcyBjb25mbGljdCBzbyB3ZSBjYW4ndCB1c2UgcGVyc2lzdFxuICAgIG5vY2soYmdVcmwpLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJykudGltZXMoMjMpLnJlcGx5KDIwMCwgeyB0dGw6IDM2MDAsIGNvbnN0YW50cyB9KTtcblxuICAgIGNvbnN0IHdhbGxldERhdGEgPSB7XG4gICAgICBpZDogJzViMzQyNTJmMWJmMzQ5OTMwZTM0MDIwYTAwMDAwMDAwJyxcbiAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgIGtleXM6IFtcbiAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NTAwMDAwMDAwJyxcbiAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NjAwMDAwMDAwJyxcbiAgICAgICAgJzViMzQyNGY5MWJmMzQ5OTMwZTM0MDE3NzAwMDAwMDAwJyxcbiAgICAgIF0sXG4gICAgICBjb2luU3BlY2lmaWM6IHt9LFxuICAgICAgbXVsdGlzaWdUeXBlOiAndHNzJyxcbiAgICB9O1xuICAgIHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2VDb2luLCB3YWxsZXREYXRhKTtcbiAgICB0c3NVdGlscyA9IG5ldyBUc3NVdGlscyhiaXRnbywgYmFzZUNvaW4sIHdhbGxldCk7XG4gIH0pO1xuXG4gIGFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdUU1Mga2V5IGNoYWluczonLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBUU1Mga2V5IGNoYWlucycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICBjb25zdCBub2NrZWRCaXRHb0tleWNoYWluID0gYXdhaXQgbm9ja0JpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgbm9ja2VkVXNlcktleWNoYWluID0gYXdhaXQgbm9ja1VzZXJLZXljaGFpbih7IGNvaW46IGNvaW5OYW1lIH0pO1xuICAgICAgYXdhaXQgbm9ja0JhY2t1cEtleWNoYWluKHsgY29pbjogY29pbk5hbWUgfSk7XG5cbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB1c2VyS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVVc2VyS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYmFja3VwS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCYWNrdXBLZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnLFxuICAgICAgfSk7XG5cbiAgICAgIGJpdGdvS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRCaXRHb0tleWNoYWluKTtcbiAgICAgIHVzZXJLZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZFVzZXJLZXljaGFpbik7XG5cbiAgICAgIC8vIHVuZW5jcnlwdGVkIGBwcnZgIHByb3BlcnR5IHNob3VsZCBleGlzdCBvbiBiYWNrdXAga2V5Y2hhaW5cbiAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgdVNoYXJlOiBiYWNrdXBLZXlTaGFyZS51U2hhcmUsXG4gICAgICAgIGJpdGdvWVNoYXJlOiBiaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0sXG4gICAgICAgIHVzZXJZU2hhcmU6IHVzZXJLZXlTaGFyZS55U2hhcmVzWzJdLFxuICAgICAgfSkuc2hvdWxkLmVxdWFsKGJhY2t1cEtleWNoYWluLnBydik7XG4gICAgICBzaG91bGQuZXhpc3QoYmFja3VwS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgc2VuZCB3ZWJhdXRobkluZm8gKHdpdGggZW50ZXJwcmlzZUlkKSBvbiB0aGUgdXNlciBrZXljaGFpbiB3aGVuIHdlYmF1dGhuSW5mbyBpcyBwcm92aWRlZCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICAvLyBSZWFsIGNyeXB0byBkZXBzIChjb25zdGFudHMgdy8gYml0Z28gZ3BnIGtleSBmb3IgdmVyaWZ5V2FsbGV0U2lnbmF0dXJlcyArIGJpdGdvIGtleWNoYWluKSxcbiAgICAgIC8vIHRoZW4gY2FwdHVyZSB0aGUgdXNlciBrZXljaGFpbiBhZGQoKSBwYXJhbXMgYnkgc3R1YmJpbmcgYmFzZUNvaW4ua2V5Y2hhaW5zKCkuXG4gICAgICBub2NrLmNsZWFuQWxsKCk7XG4gICAgICBub2NrKGJnVXJsKVxuICAgICAgICAuZ2V0KCcvYXBpL3YxL2NsaWVudC9jb25zdGFudHMnKVxuICAgICAgICAudGltZXMoMjMpXG4gICAgICAgIC5yZXBseSgyMDAsIHsgdHRsOiAzNjAwLCBjb25zdGFudHM6IHsgbXBjOiB7IGJpdGdvUHVibGljS2V5OiBiaXRnb0dwZ0tleS5wdWJsaWNLZXkgfSB9IH0pO1xuICAgICAgYXdhaXQgbm9ja0JpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYml0Z29LZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUJpdGdvS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgYWRkU3R1YiA9IHNhbmRib3guc3R1YigpLnJlc29sdmVzKHsgaWQ6ICcxJywgcHViOiAnJywgdHlwZTogJ3RzcycgfSk7XG4gICAgICBzYW5kYm94LnN0dWIoYmFzZUNvaW4sICdrZXljaGFpbnMnKS5yZXR1cm5zKHsgYWRkOiBhZGRTdHViIH0gYXMgdW5rbm93biBhcyBSZXR1cm5UeXBlPEJhc2VDb2luWydrZXljaGFpbnMnXT4pO1xuXG4gICAgICBjb25zdCBlbnRlcnByaXNlSWQgPSAnZW50ZXJwcmlzZV9pZCc7XG4gICAgICBjb25zdCB3ZWJhdXRobkluZm8gPSB7IG90cERldmljZUlkOiAnZGV2aWNlLTEyMycsIHByZlNhbHQ6ICdzYWx0LWFiYycsIHBhc3NwaHJhc2U6ICdwcmYtZGVyaXZlZC1wYXNzcGhyYXNlJyB9O1xuICAgICAgYXdhaXQgdHNzVXRpbHMuY3JlYXRlVXNlcktleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICBwYXNzcGhyYXNlOiAncGFzc3BocmFzZScsXG4gICAgICAgIHdlYmF1dGhuSW5mbyxcbiAgICAgICAgZW50ZXJwcmlzZTogZW50ZXJwcmlzZUlkLFxuICAgICAgfSk7XG5cbiAgICAgIC8vIFVzZXIga2V5Y2hhaW4gbXVzdCBjYXJyeSB3ZWJhdXRobkluZm8gKHRoZSBmaWVsZCB0aGUgYmFja2VuZCBQT1NUIC9rZXkgY29uc3VtZXMpLCBpbmNsdWRpbmdcbiAgICAgIC8vIGVudGVycHJpc2VJZCwgYW5kIG11c3QgTk9UIHVzZSB0aGUgZGVwcmVjYXRlZCB3ZWJhdXRobkRldmljZXMgYXJyYXkuXG4gICAgICBhc3NlcnQub2soYWRkU3R1Yi5jYWxsZWRPbmNlLCAna2V5Y2hhaW5zKCkuYWRkIHNob3VsZCBoYXZlIGJlZW4gY2FsbGVkIGZvciB0aGUgdXNlciBrZXljaGFpbicpO1xuICAgICAgY29uc3QgYm9keSA9IGFkZFN0dWIuZmlyc3RDYWxsLmFyZ3NbMF0gYXMgQWRkS2V5Y2hhaW5PcHRpb25zO1xuICAgICAgYXNzZXJ0Lm9rKGJvZHkud2ViYXV0aG5JbmZvLCAndXNlciBrZXljaGFpbiBib2R5IHNob3VsZCBpbmNsdWRlIHdlYmF1dGhuSW5mbycpO1xuICAgICAgYXNzZXJ0LmVxdWFsKGJvZHkud2ViYXV0aG5JbmZvLm90cERldmljZUlkLCB3ZWJhdXRobkluZm8ub3RwRGV2aWNlSWQpO1xuICAgICAgYXNzZXJ0LmVxdWFsKGJvZHkud2ViYXV0aG5JbmZvLnByZlNhbHQsIHdlYmF1dGhuSW5mby5wcmZTYWx0KTtcbiAgICAgIGFzc2VydC5lcXVhbChib2R5LndlYmF1dGhuSW5mby5lbnRlcnByaXNlSWQsIGVudGVycHJpc2VJZCk7XG4gICAgICBhc3NlcnQub2soYm9keS53ZWJhdXRobkluZm8uZW5jcnlwdGVkUHJ2LCAnZW5jcnlwdGVkUHJ2IHNob3VsZCBiZSBzZXQnKTtcbiAgICAgIGFzc2VydC5vayhhd2FpdCBiaXRnby5kZWNyeXB0KHsgaW5wdXQ6IGJvZHkud2ViYXV0aG5JbmZvLmVuY3J5cHRlZFBydiwgcGFzc3dvcmQ6IHdlYmF1dGhuSW5mby5wYXNzcGhyYXNlIH0pKTtcbiAgICAgIGFzc2VydC5zdHJpY3RFcXVhbChib2R5LndlYmF1dGhuRGV2aWNlcywgdW5kZWZpbmVkLCAnZGVwcmVjYXRlZCB3ZWJhdXRobkRldmljZXMgc2hvdWxkIG5vdCBiZSBzZW50Jyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGdlbmVyYXRlIFRTUyBrZXkgY2hhaW5zIHdpdGhvdXQgcGFzc3BocmFzZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICBjb25zdCBub2NrZWRCaXRHb0tleWNoYWluID0gYXdhaXQgbm9ja0JpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgLy8gcmV1c2luZyB0aGUgdXNlciBncGcga2V5IGFzIHRoZSBiYWNrdXAgZ3BnIGtleSwgaS5lLiB0aGUgdXNlciBpcyB0aGVpciBvd24gdGhlIGJhY2t1cCBwcm92aWRlclxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIGJpdGdvR3BnS2V5LFxuICAgICAgfSk7XG4gICAgICBjb25zdCBub2NrZWRVc2VyS2V5Y2hhaW4gPSBhd2FpdCBub2NrVXNlcktleWNoYWluKHsgY29pbjogY29pbk5hbWUgfSk7XG4gICAgICBhd2FpdCBub2NrQmFja3VwS2V5Y2hhaW4oeyBjb2luOiBjb2luTmFtZSB9KTtcblxuICAgICAgY29uc3QgYml0Z29LZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUJpdGdvS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHVzZXJLZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZVVzZXJLZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYmFja3VwS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCYWNrdXBLZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgIH0pO1xuXG4gICAgICBiaXRnb0tleWNoYWluLnNob3VsZC5kZWVwRXF1YWwobm9ja2VkQml0R29LZXljaGFpbik7XG4gICAgICB1c2VyS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRVc2VyS2V5Y2hhaW4pO1xuXG4gICAgICAvLyB1bmVuY3J5cHRlZCBgcHJ2YCBwcm9wZXJ0eSBzaG91bGQgZXhpc3Qgb24gYmFja3VwIGtleWNoYWluXG4gICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIHVTaGFyZTogYmFja3VwS2V5U2hhcmUudVNoYXJlLFxuICAgICAgICBiaXRnb1lTaGFyZTogYml0Z29LZXlTaGFyZS55U2hhcmVzWzJdLFxuICAgICAgICB1c2VyWVNoYXJlOiB1c2VyS2V5U2hhcmUueVNoYXJlc1syXSxcbiAgICAgIH0pLnNob3VsZC5lcXVhbChiYWNrdXBLZXljaGFpbi5wcnYpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBnZW5lcmF0ZSBUU1Mga2V5IGNoYWlucyB3aXRoIG9wdGlvbmFsIHBhcmFtcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGVudGVycHJpc2UgPSAnZW50ZXJwcmlzZSc7XG5cbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICBjb25zdCBub2NrZWRCaXRHb0tleWNoYWluID0gYXdhaXQgbm9ja0JpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3Qgbm9ja2VkVXNlcktleWNoYWluID0gYXdhaXQgbm9ja1VzZXJLZXljaGFpbih7IGNvaW46IGNvaW5OYW1lIH0pO1xuICAgICAgYXdhaXQgbm9ja0JhY2t1cEtleWNoYWluKHsgY29pbjogY29pbk5hbWUgfSk7XG5cbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBlbnRlcnByaXNlLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB1c2VyS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVVc2VyS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyxcbiAgICAgICAgb3JpZ2luYWxQYXNzY29kZUVuY3J5cHRpb25Db2RlOiAnb3JpZ2luYWxQYXNzY29kZUVuY3J5cHRpb25Db2RlJyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYmFja3VwS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCYWNrdXBLZXljaGFpbih7XG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnLFxuICAgICAgfSk7XG5cbiAgICAgIGJpdGdvS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRCaXRHb0tleWNoYWluKTtcbiAgICAgIHVzZXJLZXljaGFpbi5zaG91bGQuZGVlcEVxdWFsKG5vY2tlZFVzZXJLZXljaGFpbik7XG5cbiAgICAgIC8vIHVuZW5jcnlwdGVkIGBwcnZgIHByb3BlcnR5IHNob3VsZCBleGlzdCBvbiBiYWNrdXAga2V5Y2hhaW5cbiAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgdVNoYXJlOiBiYWNrdXBLZXlTaGFyZS51U2hhcmUsXG4gICAgICAgIGJpdGdvWVNoYXJlOiBiaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0sXG4gICAgICAgIHVzZXJZU2hhcmU6IHVzZXJLZXlTaGFyZS55U2hhcmVzWzJdLFxuICAgICAgfSkuc2hvdWxkLmVxdWFsKGJhY2t1cEtleWNoYWluLnBydik7XG4gICAgICBzaG91bGQuZXhpc3QoYmFja3VwS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZmFpbCB0byBnZW5lcmF0ZSBUU1Mga2V5Y2hhaW5zIHdoZW4gcmVjZWl2ZWQgaW52YWxpZCBudW1iZXIgb2Ygd2FsbGV0IHNpZ25hdHVyZXMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1c2VyS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMSwgMiwgMyk7XG4gICAgICBjb25zdCBiYWNrdXBLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgyLCAyLCAzKTtcblxuICAgICAgY29uc3QgYml0Z29LZXljaGFpbiA9IGF3YWl0IGdlbmVyYXRlQml0Z29LZXljaGFpbih7XG4gICAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICBiaXRnb0tleVNoYXJlLFxuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIGJpdGdvR3BnS2V5LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGNlcnRzU3RyaW5nID0gYXdhaXQgY3JlYXRlU2hhcmVkRGF0YVByb29mKGJpdGdvR3BnS2V5LnByaXZhdGVLZXksIHVzZXJHcGdLZXkucHVibGljS2V5LCBbXSk7XG4gICAgICBjb25zdCBjZXJ0c0tleSA9IGF3YWl0IG9wZW5wZ3AucmVhZEtleSh7IGFybW9yZWRLZXk6IGNlcnRzU3RyaW5nIH0pO1xuICAgICAgY29uc3QgZmluYWxLZXkgPSBuZXcgb3BlbnBncC5QYWNrZXRMaXN0KCk7XG4gICAgICBjZXJ0c0tleS50b1BhY2tldExpc3QoKS5mb3JFYWNoKChwYWNrZXQpID0+IGZpbmFsS2V5LnB1c2gocGFja2V0KSk7XG4gICAgICAvLyB0aGUgdW5kZXJseWluZyBmdW5jdGlvbiBvbmx5IHJlcXVpcmVzIHR3byBhcmd1bWVudHMgYnV0IHRoZSBhY2NvcmRpbmcgLmQudHMgZmlsZSBmb3Igb3BlbnBncCBoYXMgdGhlIGZ1cnRoZXJcbiAgICAgIC8vIGFyZ3VtZW50cyBtYXJrZWQgYXMgbWFuZGF0b3J5IGFzIHdlbGwuXG4gICAgICAvLyBPbmNlIHRoZSBmb2xsb3dpbmcgUFIgaGFzIGJlZW4gbWVyZ2VkIGFuZCByZWxlYXNlZCB3ZSBubyBsb25nZXIgbmVlZCB0aGUgdHMtaWdub3JlOlxuICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL29wZW5wZ3Bqcy9vcGVucGdwanMvcHVsbC8xNTc2XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gICAgICAvLyBAdHMtaWdub3JlXG4gICAgICBiaXRnb0tleWNoYWluLndhbGxldEhTTUdQR1B1YmxpY0tleVNpZ3MgPSBvcGVucGdwLmFybW9yKG9wZW5wZ3AuZW51bXMuYXJtb3IucHVibGljS2V5LCBmaW5hbEtleS53cml0ZSgpKTtcblxuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLnZlcmlmeVdhbGxldFNpZ25hdHVyZXModXNlckdwZ0tleS5wdWJsaWNLZXksIGJhY2t1cEdwZ0tleS5wdWJsaWNLZXksIGJpdGdvS2V5Y2hhaW4sICcnLCAxKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnSW52YWxpZCB3YWxsZXQgc2lnbmF0dXJlcycpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBmYWlsIHRvIGdlbmVyYXRlIFRTUyBrZXljaGFpbnMgd2hlbiB3YWxsZXQgc2lnbmF0dXJlIGZpbmdlcnByaW50cyBkbyBub3QgbWF0Y2ggcGFzc2VkIHVzZXIvYmFja3VwIGZpbmdlcnByaW50cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgZ2VuZXJhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5U2hhcmUsXG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgYml0Z29HcGdLZXksXG4gICAgICB9KTtcblxuICAgICAgLy8gdXNpbmcgdGhlIGJhY2t1cCBncGcgaGVyZSBpbnN0ZWFkIG9mIHRoZSB1c2VyIGdwZyBrZXkgdG8gc2ltdWxhdGUgdGhhdCB0aGUgZmlyc3Qgc2lnbmF0dXJlIGhhcyBhIGRpZmZlcmVudFxuICAgICAgLy8gZmluZ2VycHJpbnQgZnJvbSB0aGUgcGFzc2VkIGluIGZpcnN0IGdwZyBrZXlcbiAgICAgIGF3YWl0IHRzc1V0aWxzXG4gICAgICAgIC52ZXJpZnlXYWxsZXRTaWduYXR1cmVzKGJhY2t1cEdwZ0tleS5wdWJsaWNLZXksIGJhY2t1cEdwZ0tleS5wdWJsaWNLZXksIGJpdGdvS2V5Y2hhaW4sICcnLCAxKVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aChcbiAgICAgICAgICBgZmlyc3Qgd2FsbGV0IHNpZ25hdHVyZSdzIGZpbmdlcnByaW50IGRvZXMgbm90IG1hdGNoIHBhc3NlZCB1c2VyIGdwZyBrZXkncyBmaW5nZXJwcmludGBcbiAgICAgICAgKTtcblxuICAgICAgLy8gdXNpbmcgdGhlIHVzZXIgZ3BnIGhlcmUgaW5zdGVhZCBvZiB0aGUgYmFja3VwIGdwZyBrZXkgdG8gc2ltdWxhdGUgdGhhdCB0aGUgc2Vjb25kIHNpZ25hdHVyZSBoYXMgYSBkaWZmZXJlbnRcbiAgICAgIC8vIGZpbmdlcnByaW50IGZyb20gdGhlIHBhc3NlZCBpbiBzZWNvbmQgZ3BnIGtleVxuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLnZlcmlmeVdhbGxldFNpZ25hdHVyZXModXNlckdwZ0tleS5wdWJsaWNLZXksIHVzZXJHcGdLZXkucHVibGljS2V5LCBiaXRnb0tleWNoYWluLCAnJywgMSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoXG4gICAgICAgICAgYHNlY29uZCB3YWxsZXQgc2lnbmF0dXJlJ3MgZmluZ2VycHJpbnQgZG9lcyBub3QgbWF0Y2ggcGFzc2VkIGJhY2t1cCBncGcga2V5J3MgZmluZ2VycHJpbnRgXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gZ2VuZXJhdGUgVFNTIGtleWNoYWlucyB3aGVuIHdhbGxldCBzaWduYXR1cmUgaXMgZm9yIGRpZmZlcmVudCBrZXkgc2hhcmUnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCB1c2VyS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMSwgMiwgMyk7XG4gICAgICBjb25zdCBiYWNrdXBLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgyLCAyLCAzKTtcbiAgICAgIGNvbnN0IGN1c3RvbUJpdGdvS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMywgMiwgMyk7XG5cbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4xID0gYXdhaXQgZ2VuZXJhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5U2hhcmUsXG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgYml0Z29HcGdLZXksXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4yID0gYXdhaXQgZ2VuZXJhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5U2hhcmU6IGN1c3RvbUJpdGdvS2V5U2hhcmUsXG4gICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgYml0Z29HcGdLZXksXG4gICAgICB9KTtcblxuICAgICAgLy8gdXNpbmcgdGhlIG90aGVyIGJpdGdvIGtleWNoYWlucyBjb21tb24ga2V5Y2hhaW4gYW5kIHdhbGxldEhTTUdQR1B1YmxpY0tleVNpZ3Mgc28gdGhhdCB0aGUgdmVyaWZpY2F0aW9uIG9mIHRoZVxuICAgICAgLy8gY29tbW1vbiBrZXljaGFpbiBwYXNzZXMgYnV0IGZhaWxzIGZvciB0aGUgYml0Z28gdG8gdXNlci8gYmFja3VwIHNoYXJlc1xuICAgICAgYml0Z29LZXljaGFpbjEuY29tbW9uS2V5Y2hhaW4gPSBiaXRnb0tleWNoYWluMi5jb21tb25LZXljaGFpbjtcbiAgICAgIGJpdGdvS2V5Y2hhaW4xLndhbGxldEhTTUdQR1B1YmxpY0tleVNpZ3MgPSBiaXRnb0tleWNoYWluMi53YWxsZXRIU01HUEdQdWJsaWNLZXlTaWdzO1xuXG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuY3JlYXRlVXNlcktleWNoYWluKHtcbiAgICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgICAgYml0Z29LZXljaGFpbjogYml0Z29LZXljaGFpbjEsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdiaXRnbyBzaGFyZSBtaXNtYXRjaCcpO1xuXG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuY3JlYXRlQmFja3VwS2V5Y2hhaW4oe1xuICAgICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgICBiaXRnb0tleWNoYWluOiBiaXRnb0tleWNoYWluMSxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ2JpdGdvIHNoYXJlIG1pc21hdGNoJyk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIGZhaWwgdG8gZ2VuZXJhdGUgVFNTIGtleSBjaGFpbnMgd2hlbiBjb21tb24ga2V5Y2hhaW5zIGRvIG5vdCBtYXRjaCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICAgIGNvbnN0IGJhY2t1cEtleVNoYXJlID0gTVBDLmtleVNoYXJlKDIsIDIsIDMpO1xuXG4gICAgICBjb25zdCBub2NrZWRCaXRHb0tleWNoYWluID0gYXdhaXQgbm9ja0JpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgYml0Z29LZXljaGFpbiA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZUJpdGdvS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICB9KTtcbiAgICAgIGJpdGdvS2V5Y2hhaW4uc2hvdWxkLmRlZXBFcXVhbChub2NrZWRCaXRHb0tleWNoYWluKTtcblxuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLmNyZWF0ZVVzZXJLZXljaGFpbih7XG4gICAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICAgIGJhY2t1cEtleVNoYXJlOiBNUEMua2V5U2hhcmUoMiwgMiwgMyksXG4gICAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgICBwYXNzcGhyYXNlOiAncGFzc3BocmFzZScsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdGYWlsZWQgdG8gY3JlYXRlIHVzZXIga2V5Y2hhaW4gLSBjb21tb25LZXljaGFpbnMgZG8gbm90IG1hdGNoLicpO1xuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLmNyZWF0ZVVzZXJLZXljaGFpbih7XG4gICAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgICAgdXNlcktleVNoYXJlOiBNUEMua2V5U2hhcmUoMSwgMiwgMyksXG4gICAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgICAgYml0Z29LZXljaGFpbixcbiAgICAgICAgICBwYXNzcGhyYXNlOiAncGFzc3BocmFzZScsXG4gICAgICAgIH0pXG4gICAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdGYWlsZWQgdG8gY3JlYXRlIHVzZXIga2V5Y2hhaW4gLSBjb21tb25LZXljaGFpbnMgZG8gbm90IG1hdGNoLicpO1xuXG4gICAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgICAuY3JlYXRlQmFja3VwS2V5Y2hhaW4oe1xuICAgICAgICAgIHVzZXJHcGdLZXksXG4gICAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICAgIHVzZXJLZXlTaGFyZTogTVBDLmtleVNoYXJlKDEsIDIsIDMpLFxuICAgICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgICAgcGFzc3BocmFzZTogJ3Bhc3NwaHJhc2UnLFxuICAgICAgICB9KVxuICAgICAgICAuc2hvdWxkLmJlLnJlamVjdGVkV2l0aCgnRmFpbGVkIHRvIGNyZWF0ZSBiYWNrdXAga2V5Y2hhaW4gLSBjb21tb25LZXljaGFpbnMgZG8gbm90IG1hdGNoLicpO1xuICAgICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgICAgLmNyZWF0ZUJhY2t1cEtleWNoYWluKHtcbiAgICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICAgIGJhY2t1cEdwZ0tleSxcbiAgICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgICAgYmFja3VwS2V5U2hhcmU6IE1QQy5rZXlTaGFyZSgyLCAyLCAzKSxcbiAgICAgICAgICBiaXRnb0tleWNoYWluLFxuICAgICAgICAgIHBhc3NwaHJhc2U6ICdwYXNzcGhyYXNlJyxcbiAgICAgICAgfSlcbiAgICAgICAgLnNob3VsZC5iZS5yZWplY3RlZFdpdGgoJ0ZhaWxlZCB0byBjcmVhdGUgYmFja3VwIGtleWNoYWluIC0gY29tbW9uS2V5Y2hhaW5zIGRvIG5vdCBtYXRjaC4nKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgZ2VuZXJhdGUgVFNTIGtleSBjaGFpbnMgd2l0aCB2MiBlbmNyeXB0aW9uIGVudmVsb3BlcycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBhc3NwaHJhc2UgPSAncGFzc3BocmFzZSc7XG4gICAgICBjb25zdCB1c2VyS2V5U2hhcmUgPSBNUEMua2V5U2hhcmUoMSwgMiwgMyk7XG4gICAgICBjb25zdCBiYWNrdXBLZXlTaGFyZSA9IE1QQy5rZXlTaGFyZSgyLCAyLCAzKTtcblxuICAgICAgYXdhaXQgbm9ja0JpdGdvS2V5Y2hhaW4oe1xuICAgICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgICAgdXNlcktleVNoYXJlLFxuICAgICAgICBiYWNrdXBLZXlTaGFyZSxcbiAgICAgICAgYml0Z29LZXlTaGFyZSxcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICBiaXRnb0dwZ0tleSxcbiAgICAgIH0pO1xuICAgICAgYXdhaXQgbm9ja1VzZXJLZXljaGFpbih7IGNvaW46IGNvaW5OYW1lIH0pO1xuICAgICAgYXdhaXQgbm9ja0JhY2t1cEtleWNoYWluKHsgY29pbjogY29pbk5hbWUgfSk7XG5cbiAgICAgIGNvbnN0IGJpdGdvS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVCaXRnb0tleWNoYWluKHtcbiAgICAgICAgdXNlckdwZ0tleSxcbiAgICAgICAgYmFja3VwR3BnS2V5LFxuICAgICAgICB1c2VyS2V5U2hhcmUsXG4gICAgICAgIGJhY2t1cEtleVNoYXJlLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB1c2VyS2V5Y2hhaW4gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVVc2VyS2V5Y2hhaW4oe1xuICAgICAgICB1c2VyR3BnS2V5LFxuICAgICAgICBiYWNrdXBHcGdLZXksXG4gICAgICAgIHVzZXJLZXlTaGFyZSxcbiAgICAgICAgYmFja3VwS2V5U2hhcmUsXG4gICAgICAgIGJpdGdvS2V5Y2hhaW4sXG4gICAgICAgIHBhc3NwaHJhc2UsXG4gICAgICAgIGVuY3J5cHRpb25WZXJzaW9uOiAyLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdCh1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2KTtcbiAgICAgIGNvbnN0IGVudmVsb3BlID0gSlNPTi5wYXJzZSh1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2ISk7XG4gICAgICBlbnZlbG9wZS52LnNob3VsZC5lcXVhbCgyKTtcblxuICAgICAgY29uc3QgZGVjcnlwdGVkID0gYXdhaXQgYml0Z28uZGVjcnlwdCh7IGlucHV0OiB1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkUHJ2ISwgcGFzc3dvcmQ6IHBhc3NwaHJhc2UgfSk7XG4gICAgICBzaG91bGQuZXhpc3QoZGVjcnlwdGVkKTtcbiAgICAgIGNvbnN0IHBhcnNlZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSBKU09OLnBhcnNlKGRlY3J5cHRlZCk7XG4gICAgICBzaG91bGQuZXhpc3QocGFyc2VkLnVTaGFyZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCd2MiBlbmNyeXB0aW9uIChFZERTQSBzaWduaW5nIGRpc3BhdGNoKScsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBzaWduaW5nVHhSZXF1ZXN0OiBUeFJlcXVlc3QgPSB7XG4gICAgICB0eFJlcXVlc3RJZDogJ3YyLXNpZ25pbmctdGVzdCcsXG4gICAgICB1bnNpZ25lZFR4czogW1xuICAgICAgICB7XG4gICAgICAgICAgc2VyaWFsaXplZFR4SGV4OiAndGVzdC1wYXlsb2FkJyxcbiAgICAgICAgICBzaWduYWJsZUhleDogJ2RlYWRiZWVmJyxcbiAgICAgICAgICBkZXJpdmF0aW9uUGF0aDogJ20vMCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZGF0ZTogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgaW50ZW50OiB7IGludGVudFR5cGU6ICdwYXltZW50JyB9LFxuICAgICAgbGF0ZXN0OiB0cnVlLFxuICAgICAgc3RhdGU6ICdwZW5kaW5nVXNlclNpZ25hdHVyZScsXG4gICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgIHdhbGxldElkOiAnd2FsbGV0SWQnLFxuICAgICAgcG9saWNpZXNDaGVja2VkOiB0cnVlLFxuICAgICAgdmVyc2lvbjogMSxcbiAgICAgIHVzZXJJZDogJ3VzZXJJZCcsXG4gICAgfTtcblxuICAgIGl0KCd2MiBSLXNoYXJlIHJvdW5kLXRyaXA6IGVuY3J5cHQgdmlhIGNvbW1pdG1lbnQsIHZlcmlmeSBlbnZlbG9wZSwgZGVjcnlwdCB2aWEgY3JlYXRlUlNoYXJlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgcGFzc3BocmFzZSA9ICd0ZXN0LXBhc3NwaHJhc2UnO1xuICAgICAgY29uc3QgcHJ2ID0gSlNPTi5zdHJpbmdpZnkodmFsaWRVc2VyU2lnbmluZ01hdGVyaWFsKTtcblxuICAgICAgLy8gMS4gRW5jcnlwdCBwcnYgd2l0aCB2MlxuICAgICAgY29uc3QgZW5jcnlwdGVkUHJ2ID0gYXdhaXQgYml0Z28uZW5jcnlwdCh7XG4gICAgICAgIGlucHV0OiBwcnYsXG4gICAgICAgIHBhc3N3b3JkOiBwYXNzcGhyYXNlLFxuICAgICAgICBlbmNyeXB0aW9uVmVyc2lvbjogMixcbiAgICAgIH0pO1xuICAgICAgSlNPTi5wYXJzZShlbmNyeXB0ZWRQcnYpLnYuc2hvdWxkLmVxdWFsKDIpO1xuXG4gICAgICAvLyAyLiBDcmVhdGUgY29tbWl0bWVudCAtLSBSLXNoYXJlIHNob3VsZCBiZSBhIHYyIGVudmVsb3BlXG4gICAgICBjb25zdCBjb21taXRSZXN1bHQgPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVDb21taXRtZW50U2hhcmVGcm9tVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0OiBzaWduaW5nVHhSZXF1ZXN0LFxuICAgICAgICBwcnYsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2U6IHBhc3NwaHJhc2UsXG4gICAgICAgIGJpdGdvR3BnUHViS2V5OiBiaXRnb0dwZ0tleS5wdWJsaWNLZXksXG4gICAgICAgIGVuY3J5cHRlZFBydixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByU2hhcmVFbnZlbG9wZSA9IEpTT04ucGFyc2UoY29tbWl0UmVzdWx0LmVuY3J5cHRlZFVzZXJUb0JpdGdvUlNoYXJlLnNoYXJlKTtcbiAgICAgIHJTaGFyZUVudmVsb3BlLnYuc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgclNoYXJlRW52ZWxvcGUuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2hrZGZTYWx0Jyk7XG5cbiAgICAgIC8vIDMuIFJvdW5kLXRyaXA6IGRlY3J5cHQgdGhlIHYyIFItc2hhcmVcbiAgICAgIGNvbnN0IHsgclNoYXJlIH0gPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVSU2hhcmVGcm9tVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0OiBzaWduaW5nVHhSZXF1ZXN0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlOiBwYXNzcGhyYXNlLFxuICAgICAgICBlbmNyeXB0ZWRVc2VyVG9CaXRnb1JTaGFyZTogY29tbWl0UmVzdWx0LmVuY3J5cHRlZFVzZXJUb0JpdGdvUlNoYXJlLFxuICAgICAgfSk7XG5cbiAgICAgIHNob3VsZC5leGlzdChyU2hhcmUueFNoYXJlKTtcbiAgICAgIHNob3VsZC5leGlzdChyU2hhcmUuclNoYXJlcyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdzaWduVHhSZXF1ZXN0OicsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eFJlcXVlc3RJZCA9ICdyYW5kb21pZCc7XG4gICAgY29uc3QgdHhSZXF1ZXN0OiBUeFJlcXVlc3QgPSB7XG4gICAgICB0eFJlcXVlc3RJZCxcbiAgICAgIHRyYW5zYWN0aW9uczogW10sXG4gICAgICB1bnNpZ25lZFR4czogW1xuICAgICAgICB7XG4gICAgICAgICAgc2VyaWFsaXplZFR4SGV4OiAnTVBDIG9uIGEgRnJpZGF5IG5pZ2h0JyxcbiAgICAgICAgICBzaWduYWJsZUhleDogJ01QQyBvbiBhIEZyaWRheSBuaWdodCcsXG4gICAgICAgICAgZGVyaXZhdGlvblBhdGg6ICdtLzAnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGRhdGU6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGludGVudDoge1xuICAgICAgICBpbnRlbnRUeXBlOiAncGF5bWVudCcsXG4gICAgICB9LFxuICAgICAgbGF0ZXN0OiB0cnVlLFxuICAgICAgc3RhdGU6ICdwZW5kaW5nVXNlclNpZ25hdHVyZScsXG4gICAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICAgIHdhbGxldElkOiAnd2FsbGV0SWQnLFxuICAgICAgcG9saWNpZXNDaGVja2VkOiB0cnVlLFxuICAgICAgdmVyc2lvbjogMSxcbiAgICAgIHVzZXJJZDogJ3VzZXJJZCcsXG4gICAgfTtcblxuICAgIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdXNlclNpZ25TaGFyZSA9IHZhbGlkVXNlclNpZ25TaGFyZTtcbiAgICAgIGNvbnN0IHJTaGFyZSA9IHVzZXJTaWduU2hhcmUuclNoYXJlc1szXTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHNoYXJlOiByU2hhcmUuciArIHJTaGFyZS5SLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgbm9ja1NlbmRTaWduYXR1cmVTaGFyZSh7XG4gICAgICAgIHdhbGxldElkOiB3YWxsZXQuaWQoKSxcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgICAgc2lnbmF0dXJlU2hhcmUsXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgc2lnbmF0dXJlU2hhcmUyOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHNoYXJlOiB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlLnJTaGFyZXNbMV0uciArIHZhbGlkQml0Z29Ub1VzZXJTaWduU2hhcmUuclNoYXJlc1sxXS5SLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0geyB0eFJlcXVlc3RzOiBbeyAuLi50eFJlcXVlc3QsIHNpZ25hdHVyZVNoYXJlczogW3NpZ25hdHVyZVNoYXJlMl0gfV0gfTtcbiAgICAgIGF3YWl0IG5vY2tHZXRUeFJlcXVlc3QoeyB3YWxsZXRJZDogd2FsbGV0LmlkKCksIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsIHJlc3BvbnNlIH0pO1xuXG4gICAgICBjb25zdCBiaXRnb1RvVXNlckNvbW1pdG1lbnRTaGFyZTogQ29tbWl0bWVudFNoYXJlUmVjb3JkID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgdHlwZTogQ29tbWl0bWVudFR5cGUuQ09NTUlUTUVOVCxcbiAgICAgICAgc2hhcmU6IHZhbGlkQml0Z29Ub1VzZXJTaWduU2hhcmUuclNoYXJlc1sxXS5jb21taXRtZW50LFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGV4Y2hhbmdlQ29tbWl0UmVzcG9uc2U6IEV4Y2hhbmdlQ29tbWl0bWVudFJlc3BvbnNlID0geyBjb21taXRtZW50U2hhcmU6IGJpdGdvVG9Vc2VyQ29tbWl0bWVudFNoYXJlIH07XG4gICAgICBhd2FpdCBub2NrRXhjaGFuZ2VDb21taXRtZW50cyh7XG4gICAgICAgIHdhbGxldElkOiB3YWxsZXQuaWQoKSxcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgICAgcmVzcG9uc2U6IGV4Y2hhbmdlQ29tbWl0UmVzcG9uc2UsXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBzdWNjZWVkIHdpdGggdHhSZXF1ZXN0IG9iamVjdCBhcyBpbnB1dCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lZFR4UmVxdWVzdCA9IGF3YWl0IHRzc1V0aWxzLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgICB0eFJlcXVlc3QsXG4gICAgICAgIHBydjogSlNPTi5zdHJpbmdpZnkodmFsaWRVc2VyU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgICAgcmVxSWQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4UmVxdWVzdC51bnNpZ25lZFR4cy5zaG91bGQuZGVlcEVxdWFsKHR4UmVxdWVzdC51bnNpZ25lZFR4cyk7XG5cbiAgICAgIHNhbmRib3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NpZ25UeFJlcXVlc3Qgc2hvdWxkIHN1Y2NlZWQgd2l0aCB0eFJlcXVlc3QgaWQgYXMgaW5wdXQnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBnZXRUeFJlcXVlc3QgPSBzYW5kYm94LnN0dWIodHNzVXRpbHMsICdnZXRUeFJlcXVlc3QnKTtcbiAgICAgIGdldFR4UmVxdWVzdC5yZXNvbHZlcyh0eFJlcXVlc3QpO1xuICAgICAgZ2V0VHhSZXF1ZXN0LmNhbGxlZFdpdGgodHhSZXF1ZXN0SWQpO1xuXG4gICAgICBjb25zdCBzaWduZWRUeFJlcXVlc3QgPSBhd2FpdCB0c3NVdGlscy5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0OiB0eFJlcXVlc3RJZCxcbiAgICAgICAgcHJ2OiBKU09OLnN0cmluZ2lmeSh2YWxpZFVzZXJTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgICByZXFJZCxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkVHhSZXF1ZXN0LnVuc2lnbmVkVHhzLnNob3VsZC5kZWVwRXF1YWwodHhSZXF1ZXN0LnVuc2lnbmVkVHhzKTtcblxuICAgICAgc2FuZGJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdzaWduVHhSZXF1ZXN0IFdpdGggQ29tbWl0bWVudDonLCBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdHhSZXF1ZXN0SWQgPSAncmFuZG9taWQnO1xuICAgIGNvbnN0IHR4UmVxdWVzdDogVHhSZXF1ZXN0ID0ge1xuICAgICAgdHhSZXF1ZXN0SWQsXG4gICAgICB0cmFuc2FjdGlvbnM6IFtdLFxuICAgICAgdW5zaWduZWRUeHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHNlcmlhbGl6ZWRUeEhleDogJ01QQyBvbiBhIEZyaWRheSBuaWdodCcsXG4gICAgICAgICAgc2lnbmFibGVIZXg6ICdNUEMgb24gYSBGcmlkYXkgbmlnaHQnLFxuICAgICAgICAgIGRlcml2YXRpb25QYXRoOiAnbS8wJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBkYXRlOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICBpbnRlbnQ6IHtcbiAgICAgICAgaW50ZW50VHlwZTogJ3BheW1lbnQnLFxuICAgICAgfSxcbiAgICAgIGxhdGVzdDogdHJ1ZSxcbiAgICAgIHN0YXRlOiAncGVuZGluZ1VzZXJTaWduYXR1cmUnLFxuICAgICAgd2FsbGV0VHlwZTogJ2hvdCcsXG4gICAgICB3YWxsZXRJZDogJ3dhbGxldElkJyxcbiAgICAgIHBvbGljaWVzQ2hlY2tlZDogdHJ1ZSxcbiAgICAgIHZlcnNpb246IDEsXG4gICAgICB1c2VySWQ6ICd1c2VySWQnLFxuICAgIH07XG5cbiAgICBiZWZvcmVFYWNoKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHVzZXJTaWduU2hhcmUgPSB2YWxpZFVzZXJTaWduU2hhcmU7XG4gICAgICBjb25zdCByU2hhcmUgPSB1c2VyU2lnblNoYXJlLnJTaGFyZXNbM107XG4gICAgICBjb25zdCBzaWduYXR1cmVTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7XG4gICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICBzaGFyZTogclNoYXJlLnIgKyByU2hhcmUuUixcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IG5vY2tTZW5kU2lnbmF0dXJlU2hhcmUoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlLFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlMjogU2lnbmF0dXJlU2hhcmVSZWNvcmQgPSB7XG4gICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICBzaGFyZTogdmFsaWRCaXRnb1RvVXNlclNpZ25TaGFyZS5yU2hhcmVzWzFdLnIgKyB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlLnJTaGFyZXNbMV0uUixcbiAgICAgIH07XG4gICAgICBjb25zdCByZXNwb25zZSA9IHsgdHhSZXF1ZXN0czogW3sgLi4udHhSZXF1ZXN0LCBzaWduYXR1cmVTaGFyZXM6IFtzaWduYXR1cmVTaGFyZTJdIH1dIH07XG4gICAgICBhd2FpdCBub2NrR2V0VHhSZXF1ZXN0KHsgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLCB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLCByZXNwb25zZSB9KTtcbiAgICAgIGNvbnN0IGJpdGdvVG9Vc2VyQ29tbWl0bWVudFNoYXJlOiBDb21taXRtZW50U2hhcmVSZWNvcmQgPSB7XG4gICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICB0eXBlOiBDb21taXRtZW50VHlwZS5DT01NSVRNRU5ULFxuICAgICAgICBzaGFyZTogdmFsaWRCaXRnb1RvVXNlclNpZ25TaGFyZS5yU2hhcmVzWzFdLmNvbW1pdG1lbnQsXG4gICAgICB9O1xuICAgICAgY29uc3QgZXhjaGFuZ2VDb21taXRSZXNwb25zZTogRXhjaGFuZ2VDb21taXRtZW50UmVzcG9uc2UgPSB7IGNvbW1pdG1lbnRTaGFyZTogYml0Z29Ub1VzZXJDb21taXRtZW50U2hhcmUgfTtcbiAgICAgIGF3YWl0IG5vY2tFeGNoYW5nZUNvbW1pdG1lbnRzKHtcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLFxuICAgICAgICByZXNwb25zZTogZXhjaGFuZ2VDb21taXRSZXNwb25zZSxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgaXQoJ3NpZ25UeFJlcXVlc3Qgc2hvdWxkIHN1Y2NlZWQgd2l0aCB0eFJlcXVlc3Qgb2JqZWN0IGFzIGlucHV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnbmVkVHhSZXF1ZXN0ID0gYXdhaXQgdHNzVXRpbHMuc2lnblR4UmVxdWVzdCh7XG4gICAgICAgIHR4UmVxdWVzdCxcbiAgICAgICAgcHJ2OiBKU09OLnN0cmluZ2lmeSh2YWxpZFVzZXJTaWduaW5nTWF0ZXJpYWwpLFxuICAgICAgICByZXFJZCxcbiAgICAgIH0pO1xuICAgICAgc2lnbmVkVHhSZXF1ZXN0LnVuc2lnbmVkVHhzLnNob3VsZC5kZWVwRXF1YWwodHhSZXF1ZXN0LnVuc2lnbmVkVHhzKTtcblxuICAgICAgc2FuZGJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2lnblR4UmVxdWVzdCBzaG91bGQgc3VjY2VlZCB3aXRoIHR4UmVxdWVzdCBpZCBhcyBpbnB1dCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGdldFR4UmVxdWVzdCA9IHNhbmRib3guc3R1Yih0c3NVdGlscywgJ2dldFR4UmVxdWVzdCcpO1xuICAgICAgZ2V0VHhSZXF1ZXN0LnJlc29sdmVzKHR4UmVxdWVzdCk7XG4gICAgICBnZXRUeFJlcXVlc3QuY2FsbGVkV2l0aCh0eFJlcXVlc3RJZCk7XG5cbiAgICAgIGNvbnN0IHNpZ25lZFR4UmVxdWVzdCA9IGF3YWl0IHRzc1V0aWxzLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdElkLFxuICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHZhbGlkVXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICAgIHJlcUlkLFxuICAgICAgfSk7XG4gICAgICBzaWduZWRUeFJlcXVlc3QudW5zaWduZWRUeHMuc2hvdWxkLmRlZXBFcXVhbCh0eFJlcXVlc3QudW5zaWduZWRUeHMpO1xuXG4gICAgICBzYW5kYm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3NpZ25UeFJlcXVlc3RGb3JNZXNzYWdlOicsIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCB0eFJlcXVlc3RJZCA9ICdyYW5kb21pZC1hYmMnO1xuICAgIGNvbnN0IG1lc3NhZ2VSYXcgPSAnaGVsbG8gd29ybGQnO1xuICAgIGNvbnN0IG1lc3NhZ2VFbmNvZGVkID0gQnVmZmVyLmZyb20oYCR7bWVzc2FnZVJhd31gKS50b1N0cmluZygnaGV4Jyk7XG4gICAgY29uc3QgYnVmZmVyVG9TaWduID0gQnVmZmVyLmZyb20obWVzc2FnZUVuY29kZWQsICdoZXgnKTtcbiAgICBjb25zdCB0eFJlcXVlc3Q6IFR4UmVxdWVzdCA9IHtcbiAgICAgIHR4UmVxdWVzdElkLFxuICAgICAgdHJhbnNhY3Rpb25zOiBbXSxcbiAgICAgIG1lc3NhZ2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBzdGF0ZTogJ3BlbmRpbmdTaWduYXR1cmUnLFxuICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogW10sXG4gICAgICAgICAgbWVzc2FnZVJhdyxcbiAgICAgICAgICBtZXNzYWdlRW5jb2RlZCxcbiAgICAgICAgICBkZXJpdmF0aW9uUGF0aDogJ20vMCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgdW5zaWduZWRUeHM6IFtdLFxuICAgICAgZGF0ZTogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgaW50ZW50OiB7XG4gICAgICAgIGludGVudFR5cGU6ICdwYXltZW50JyxcbiAgICAgIH0sXG4gICAgICBsYXRlc3Q6IHRydWUsXG4gICAgICBzdGF0ZTogJ3BlbmRpbmdVc2VyU2lnbmF0dXJlJyxcbiAgICAgIHdhbGxldFR5cGU6ICdob3QnLFxuICAgICAgd2FsbGV0SWQ6ICd3YWxsZXRJZCcsXG4gICAgICBwb2xpY2llc0NoZWNrZWQ6IHRydWUsXG4gICAgICB2ZXJzaW9uOiAxLFxuICAgICAgdXNlcklkOiAndXNlcklkJyxcbiAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICB9O1xuXG4gICAgYmVmb3JlRWFjaChhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCByU2hhcmUgPSB2YWxpZFVzZXJTaWduU2hhcmUuclNoYXJlc1szXTtcbiAgICAgIGNvbnN0IHNpZ25hdHVyZVNoYXJlOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHNoYXJlOiByU2hhcmUuciArIHJTaGFyZS5SLFxuICAgICAgfTtcblxuICAgICAgYXdhaXQgbm9ja1NlbmRTaWduYXR1cmVTaGFyZSh7XG4gICAgICAgIHdhbGxldElkOiB3YWxsZXQuaWQoKSxcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgICAgc2lnbmF0dXJlU2hhcmUsXG4gICAgICAgIHJlcXVlc3RUeXBlOiBSZXF1ZXN0VHlwZS5tZXNzYWdlLFxuICAgICAgICBhcGlNb2RlOiAnZnVsbCcsXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgc2lnbmF0dXJlU2hhcmUyOiBTaWduYXR1cmVTaGFyZVJlY29yZCA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLkJJVEdPLFxuICAgICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHNoYXJlOiB2YWxpZEJpdGdvVG9Vc2VyU2lnblNoYXJlLnJTaGFyZXNbMV0uciArIHZhbGlkQml0Z29Ub1VzZXJTaWduU2hhcmUuclNoYXJlc1sxXS5SLFxuICAgICAgfTtcbiAgICAgIHR4UmVxdWVzdC5tZXNzYWdlcyFbMF0uc2lnbmF0dXJlU2hhcmVzLnB1c2goc2lnbmF0dXJlU2hhcmUyKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0geyB0eFJlcXVlc3RzOiBbeyAuLi50eFJlcXVlc3QsIGFwaVZlcnNpb246ICdmdWxsJyB9XSB9O1xuICAgICAgYXdhaXQgbm9ja0dldFR4UmVxdWVzdCh7IHdhbGxldElkOiB3YWxsZXQuaWQoKSwgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCwgcmVzcG9uc2UgfSk7XG5cbiAgICAgIGNvbnN0IGJpdGdvVG9Vc2VyQ29tbWl0bWVudFNoYXJlOiBDb21taXRtZW50U2hhcmVSZWNvcmQgPSB7XG4gICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgICAgICB0eXBlOiBDb21taXRtZW50VHlwZS5DT01NSVRNRU5ULFxuICAgICAgICBzaGFyZTogdmFsaWRCaXRnb1RvVXNlclNpZ25TaGFyZS5yU2hhcmVzWzFdLmNvbW1pdG1lbnQsXG4gICAgICB9O1xuICAgICAgY29uc3QgZXhjaGFuZ2VDb21taXRSZXNwb25zZTogRXhjaGFuZ2VDb21taXRtZW50UmVzcG9uc2UgPSB7IGNvbW1pdG1lbnRTaGFyZTogYml0Z29Ub1VzZXJDb21taXRtZW50U2hhcmUgfTtcbiAgICAgIGF3YWl0IG5vY2tFeGNoYW5nZUNvbW1pdG1lbnRzKHtcbiAgICAgICAgd2FsbGV0SWQ6IHdhbGxldC5pZCgpLFxuICAgICAgICB0eFJlcXVlc3RJZDogdHhSZXF1ZXN0LnR4UmVxdWVzdElkLFxuICAgICAgICByZXNwb25zZTogZXhjaGFuZ2VDb21taXRSZXNwb25zZSxcbiAgICAgICAgYXBpTW9kZTogJ2Z1bGwnLFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBhZnRlckVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgdHhSZXF1ZXN0Lm1lc3NhZ2VzIVswXS5zaWduYXR1cmVTaGFyZXMgPSBbXTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBzdWNjZWVkIHdpdGggdHhSZXF1ZXN0IG9iamVjdCBhcyBpbnB1dCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHNpZ25lZFR4UmVxdWVzdCA9IGF3YWl0IHRzc1V0aWxzLnNpZ25UeFJlcXVlc3RGb3JNZXNzYWdlKHtcbiAgICAgICAgbWVzc2FnZVJhdyxcbiAgICAgICAgYnVmZmVyVG9TaWduLFxuICAgICAgICB0eFJlcXVlc3QsXG4gICAgICAgIHBydjogSlNPTi5zdHJpbmdpZnkodmFsaWRVc2VyU2lnbmluZ01hdGVyaWFsKSxcbiAgICAgICAgcmVxSWQsXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4UmVxdWVzdC5tZXNzYWdlcyEuc2hvdWxkLmRlZXBFcXVhbCh0eFJlcXVlc3QubWVzc2FnZXMpO1xuXG4gICAgICBzYW5kYm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaWduVHhSZXF1ZXN0IHNob3VsZCBzdWNjZWVkIHdpdGggdHhSZXF1ZXN0IGlkIGFzIGlucHV0JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZ2V0VHhSZXF1ZXN0ID0gc2FuZGJveC5zdHViKHRzc1V0aWxzLCAnZ2V0VHhSZXF1ZXN0Jyk7XG4gICAgICBnZXRUeFJlcXVlc3QucmVzb2x2ZXModHhSZXF1ZXN0KTtcbiAgICAgIGdldFR4UmVxdWVzdC5jYWxsZWRXaXRoKHR4UmVxdWVzdElkKTtcblxuICAgICAgY29uc3Qgc2lnbmVkVHhSZXF1ZXN0ID0gYXdhaXQgdHNzVXRpbHMuc2lnblR4UmVxdWVzdEZvck1lc3NhZ2Uoe1xuICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdElkLFxuICAgICAgICBwcnY6IEpTT04uc3RyaW5naWZ5KHZhbGlkVXNlclNpZ25pbmdNYXRlcmlhbCksXG4gICAgICAgIHJlcUlkLFxuICAgICAgICBtZXNzYWdlUmF3LFxuICAgICAgICBidWZmZXJUb1NpZ24sXG4gICAgICB9KTtcbiAgICAgIHNpZ25lZFR4UmVxdWVzdC5tZXNzYWdlcyEuc2hvdWxkLmRlZXBFcXVhbCh0eFJlcXVlc3QubWVzc2FnZXMpO1xuXG4gICAgICBzYW5kYm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3ByZWJ1aWxkVHhXaXRoSW50ZW50OicsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGJ1aWxkIHNpbmdsZSByZWNpcGllbnQgdHgnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBub2NrZWRDcmVhdGVUeCA9IGF3YWl0IG5vY2tDcmVhdGVUeFJlcXVlc3Qoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHJlcXVlc3RCb2R5OiB7XG4gICAgICAgICAgYXBpVmVyc2lvbjogJ2xpdGUnLFxuICAgICAgICAgIGludGVudDoge1xuICAgICAgICAgICAgaW50ZW50VHlwZTogJ3BheW1lbnQnLFxuICAgICAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgYWRkcmVzczoge1xuICAgICAgICAgICAgICAgICAgYWRkcmVzczogJ3JlY2lwaWVudCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IHtcbiAgICAgICAgICAgICAgICAgIHZhbHVlOiAnMTAwMDAnLFxuICAgICAgICAgICAgICAgICAgc3ltYm9sOiAndHNvbCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gZG9uJ3QgY2FyZSBhYm91dCB0aGUgYWN0dWFsIHJlc3BvbnNlIC0ganVzdCBuZWVkIHRvIG1ha2Ugc3VyZSByZXF1ZXN0IGJvZHkgbWF0Y2hlc1xuICAgICAgICByZXNwb25zZToge30sXG4gICAgICB9KTtcblxuICAgICAgYXdhaXQgdHNzVXRpbHMucHJlYnVpbGRUeFdpdGhJbnRlbnQoe1xuICAgICAgICByZXFJZCxcbiAgICAgICAgcmVjaXBpZW50czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIGFkZHJlc3M6ICdyZWNpcGllbnQnLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGludGVudFR5cGU6ICdwYXltZW50JyxcbiAgICAgIH0pO1xuXG4gICAgICBub2NrZWRDcmVhdGVUeC5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCBidWlsZCBtdWx0aXBsZSByZWNpcGllbnRzIHdpdGggbWVtbyB0eCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vY2tlZENyZWF0ZVR4ID0gYXdhaXQgbm9ja0NyZWF0ZVR4UmVxdWVzdCh7XG4gICAgICAgIHdhbGxldElkOiB3YWxsZXQuaWQoKSxcbiAgICAgICAgcmVxdWVzdEJvZHk6IHtcbiAgICAgICAgICBhcGlWZXJzaW9uOiAnbGl0ZScsXG4gICAgICAgICAgaW50ZW50OiB7XG4gICAgICAgICAgICBpbnRlbnRUeXBlOiAncGF5bWVudCcsXG4gICAgICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiB7XG4gICAgICAgICAgICAgICAgICBhZGRyZXNzOiAncmVjaXBpZW50MScsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhbW91bnQ6IHtcbiAgICAgICAgICAgICAgICAgIHZhbHVlOiAnMTAwMDAnLFxuICAgICAgICAgICAgICAgICAgc3ltYm9sOiAndHNvbCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGFkZHJlc3M6IHtcbiAgICAgICAgICAgICAgICAgIGFkZHJlc3M6ICdyZWNpcGllbnQyJyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGFtb3VudDoge1xuICAgICAgICAgICAgICAgICAgdmFsdWU6ICcyMDAwMCcsXG4gICAgICAgICAgICAgICAgICBzeW1ib2w6ICd0c29sJyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIG1lbW86ICdtZW1vJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICAvLyBkb24ndCBjYXJlIGFib3V0IHRoZSBhY3R1YWwgcmVzcG9uc2UgLSBqdXN0IG5lZWQgdG8gbWFrZSBzdXJlIHJlcXVlc3QgYm9keSBtYXRjaGVzXG4gICAgICAgIHJlc3BvbnNlOiB7fSxcbiAgICAgIH0pO1xuXG4gICAgICBhd2FpdCB0c3NVdGlscy5wcmVidWlsZFR4V2l0aEludGVudCh7XG4gICAgICAgIHJlcUlkLFxuICAgICAgICByZWNpcGllbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJ3JlY2lwaWVudDEnLFxuICAgICAgICAgICAgYW1vdW50OiAnMTAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgICAge1xuICAgICAgICAgICAgYWRkcmVzczogJ3JlY2lwaWVudDInLFxuICAgICAgICAgICAgYW1vdW50OiAnMjAwMDAnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIG1lbW86IHtcbiAgICAgICAgICB2YWx1ZTogJ21lbW8nLFxuICAgICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgICAgfSxcbiAgICAgICAgaW50ZW50VHlwZTogJ3BheW1lbnQnLFxuICAgICAgfSk7XG5cbiAgICAgIG5vY2tlZENyZWF0ZVR4LmlzRG9uZSgpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdkZWxldGUgU2lnbmF0dXJlU2hhcmU6JywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgc3VjY2VlZCB0byBkZWxldGUgU2lnbmF0dXJlIFNoYXJlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnbmF0dXJlU2hhcmUgPSB7IGZyb206ICd1c2VyJywgdG86ICdiaXRnbycsIHNoYXJlOiAnMTI4Ynl0ZXN0cmluZycgfSBhcyBTaWduYXR1cmVTaGFyZVJlY29yZDtcbiAgICAgIGNvbnN0IG5vY2sgPSBhd2FpdCBub2NrRGVsZXRlU2lnbmF0dXJlU2hhcmUoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRzc1V0aWxzLmRlbGV0ZVNpZ25hdHVyZVNoYXJlcyh0eFJlcXVlc3QudHhSZXF1ZXN0SWQpO1xuICAgICAgcmVzcG9uc2Uuc2hvdWxkLmRlZXBFcXVhbChbc2lnbmF0dXJlU2hhcmVdKTtcbiAgICAgIHJlc3BvbnNlLnNob3VsZC5sZW5ndGgoMSk7XG4gICAgICBub2NrLmlzRG9uZSgpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBzZXRSZXF1ZXN0VHJhY2VyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgc2lnbmF0dXJlU2hhcmUgPSB7IGZyb206ICd1c2VyJywgdG86ICdiaXRnbycsIHNoYXJlOiAnMTI4Ynl0ZXN0cmluZycgfSBhcyBTaWduYXR1cmVTaGFyZVJlY29yZDtcbiAgICAgIGNvbnN0IG5vY2sgPSBhd2FpdCBub2NrRGVsZXRlU2lnbmF0dXJlU2hhcmUoe1xuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXFJZCA9IG5ldyBSZXF1ZXN0VHJhY2VyKCk7XG4gICAgICBjb25zdCBzZXRSZXF1ZXN0VHJhY2VyU3B5ID0gc2lub24uc3B5KGJpdGdvLCAnc2V0UmVxdWVzdFRyYWNlcicpO1xuICAgICAgc2V0UmVxdWVzdFRyYWNlclNweS53aXRoQXJncyhyZXFJZCk7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRzc1V0aWxzLmRlbGV0ZVNpZ25hdHVyZVNoYXJlcyh0eFJlcXVlc3QudHhSZXF1ZXN0SWQsIHJlcUlkKTtcbiAgICAgIHJlc3BvbnNlLnNob3VsZC5kZWVwRXF1YWwoW3NpZ25hdHVyZVNoYXJlXSk7XG4gICAgICByZXNwb25zZS5zaG91bGQubGVuZ3RoKDEpO1xuICAgICAgbm9jay5pc0RvbmUoKS5zaG91bGQuZXF1YWwodHJ1ZSk7XG4gICAgICBzaW5vbi5hc3NlcnQuY2FsbGVkT25jZShzZXRSZXF1ZXN0VHJhY2VyU3B5KTtcbiAgICAgIHNldFJlcXVlc3RUcmFjZXJTcHkucmVzdG9yZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc2VuZFR4UmVxdWVzdDonLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ3Nob3VsZCBzdWNjZWVkIHRvIHNlbmQgdHggcmVxdWVzdCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vY2sgPSBhd2FpdCBub2NrU2VuZFR4UmVxdWVzdCh7XG4gICAgICAgIGNvaW46IGNvaW5OYW1lLFxuICAgICAgICB3YWxsZXRJZDogd2FsbGV0LmlkKCksXG4gICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHRzc1V0aWxzLnNlbmRUeFJlcXVlc3QodHhSZXF1ZXN0LnR4UmVxdWVzdElkKS5zaG91bGQuYmUuZnVsZmlsbGVkKCk7XG4gICAgICBub2NrLmlzRG9uZSgpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgY2FsbCBzZXRSZXF1ZXN0VHJhY2VyJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgbm9jayA9IGF3YWl0IG5vY2tTZW5kVHhSZXF1ZXN0KHtcbiAgICAgICAgY29pbjogY29pbk5hbWUsXG4gICAgICAgIHdhbGxldElkOiB3YWxsZXQuaWQoKSxcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmVxSWQgPSBuZXcgUmVxdWVzdFRyYWNlcigpO1xuICAgICAgY29uc3Qgc2V0UmVxdWVzdFRyYWNlclNweSA9IHNpbm9uLnNweShiaXRnbywgJ3NldFJlcXVlc3RUcmFjZXInKTtcbiAgICAgIHNldFJlcXVlc3RUcmFjZXJTcHkud2l0aEFyZ3MocmVxSWQpO1xuICAgICAgYXdhaXQgdHNzVXRpbHMuc2VuZFR4UmVxdWVzdCh0eFJlcXVlc3QudHhSZXF1ZXN0SWQsIHJlcUlkKS5zaG91bGQuYmUuZnVsZmlsbGVkKCk7XG4gICAgICBub2NrLmlzRG9uZSgpLnNob3VsZC5lcXVhbCh0cnVlKTtcbiAgICAgIHNpbm9uLmFzc2VydC5jYWxsZWRPbmNlKHNldFJlcXVlc3RUcmFjZXJTcHkpO1xuICAgICAgc2V0UmVxdWVzdFRyYWNlclNweS5yZXN0b3JlKCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGRlc2NyaWJlKCdjcmVhdGVVc2VyVG9CaXRnb0NvbW1pdG1lbnRTaGFyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBhIHZhbGlkIGNvbW1pdG1lbnRTaGFyZScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gJ3JhbmRvbXN0cmluZyc7XG4gICAgICBjb25zdCB2YWxpZFVzZXJUb0JpdGdvQ29tbWl0bWVudFNoYXJlID0ge1xuICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuVVNFUixcbiAgICAgICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgdHlwZTogQ29tbWl0bWVudFR5cGUuQ09NTUlUTUVOVCxcbiAgICAgICAgc2hhcmU6IHZhbHVlLFxuICAgICAgfTtcbiAgICAgIGNvbnN0IGNvbW1pdG1lbnRTaGFyZSA9IHRzc1V0aWxzLmNyZWF0ZVVzZXJUb0JpdGdvQ29tbWl0bWVudFNoYXJlKHZhbHVlKTtcbiAgICAgIGNvbW1pdG1lbnRTaGFyZS5zaG91bGQuZGVlcEVxdWFsKHZhbGlkVXNlclRvQml0Z29Db21taXRtZW50U2hhcmUpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnY3JlYXRlVXNlclRvQml0Z29FbmNyeXB0ZWRTaWduZXJTaGFyZScsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIGNyZWF0ZSBhIHZhbGlkIGVuY3J5cHRlZFNpZ25lclNoYXJlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdmFsdWUgPSAncmFuZG9tc3RyaW5nJztcbiAgICAgIGNvbnN0IHZhbGlkVXNlclRvQml0Z29FbmNyeXB0ZWRTaWduZXJTaGFyZSA9IHtcbiAgICAgICAgZnJvbTogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgIHR5cGU6IEVuY3J5cHRlZFNpZ25lclNoYXJlVHlwZS5FTkNSWVBURURfU0lHTkVSX1NIQVJFLFxuICAgICAgICBzaGFyZTogdmFsdWUsXG4gICAgICB9O1xuICAgICAgY29uc3QgZW5jcnlwdGVkU2lnbmVyU2hhcmUgPSB0c3NVdGlscy5jcmVhdGVVc2VyVG9CaXRnb0VuY3J5cHRlZFNpZ25lclNoYXJlKHZhbHVlKTtcbiAgICAgIGVuY3J5cHRlZFNpZ25lclNoYXJlLnNob3VsZC5kZWVwRXF1YWwodmFsaWRVc2VyVG9CaXRnb0VuY3J5cHRlZFNpZ25lclNoYXJlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3N1cHBvcnRlZFR4UmVxdWVzdFZlcnNpb25zJywgZnVuY3Rpb24gKCkge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZ1bGwgZm9yIGN1c3RvZGlhbCB3YWxsZXRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgY3VzdG9kaWFsV2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZUNvaW4sIHsgbXVsdGlzaWdUeXBlOiAndHNzJywgdHlwZTogJ2N1c3RvZGlhbCcgfSk7XG4gICAgICBjb25zdCBjdXN0b2RpYWxUc3NVdGlscyA9IG5ldyBUc3NVdGlscyhiaXRnbywgYmFzZUNvaW4sIGN1c3RvZGlhbFdhbGxldCk7XG4gICAgICBjdXN0b2RpYWxUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpLnNob3VsZC5kZWVwRXF1YWwoWydmdWxsJ10pO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZ1bGwgZm9yIGNvbGQgd2FsbGV0cycsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGNvbGRXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwgeyBtdWx0aXNpZ1R5cGU6ICd0c3MnLCB0eXBlOiAnY29sZCcgfSk7XG4gICAgICBjb25zdCBjb2xkV2FsbGV0VHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJhc2VDb2luLCBjb2xkV2FsbGV0KTtcbiAgICAgIGNvbGRXYWxsZXRUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpLnNob3VsZC5kZWVwRXF1YWwoWydmdWxsJ10pO1xuICAgIH0pO1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZ1bGwgYW5kIGxpdGUgZm9yIGhvdCB3YWxsZXRzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaG90V2FsbGV0ID0gbmV3IFdhbGxldChiaXRnbywgYmFzZUNvaW4sIHtcbiAgICAgICAgbXVsdGlzaWdUeXBlOiAndHNzJyxcbiAgICAgICAgbXVsdGlzaWdUeXBlVmVyc2lvbjogdW5kZWZpbmVkLFxuICAgICAgICB0eXBlOiAnaG90JyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgaG90VHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJhc2VDb2luLCBob3RXYWxsZXQpO1xuICAgICAgY29uc3Qgc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMgPSBob3RUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpO1xuICAgICAgc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMuc2hvdWxkLmRlZXBFcXVhbChbJ2xpdGUnLCAnZnVsbCddKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBvbmx5IGZ1bGwgZm9yIGhvdCBNUEN2MiB3YWxsZXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgaG90TVBDdjJXYWxsZXQgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwge1xuICAgICAgICBtdWx0aXNpZ1R5cGU6ICd0c3MnLFxuICAgICAgICBtdWx0aXNpZ1R5cGVWZXJzaW9uOiAnTVBDdjInLFxuICAgICAgICB0eXBlOiAnaG90JyxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgbXBjdjJUc3NVdGlscyA9IG5ldyBFRERTQVV0aWxzLkVkZHNhTVBDdjJVdGlscyhiaXRnbywgYmFzZUNvaW4sIGhvdE1QQ3YyV2FsbGV0KTtcbiAgICAgIG1wY3YyVHNzVXRpbHMuc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMoKS5zaG91bGQuZGVlcEVxdWFsKFsnZnVsbCddKTtcbiAgICB9KTtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBlbXB0eSBmb3IgdHJhZGluZyB3YWxsZXRzJywgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgdHJhZGluZ1dhbGxldHMgPSBuZXcgV2FsbGV0KGJpdGdvLCBiYXNlQ29pbiwgeyBtdWx0aXNpZ1R5cGU6ICd0c3MnLCB0eXBlOiAndHJhZGluZycgfSk7XG4gICAgICBjb25zdCB0cmFkaW5nV2FsbGV0VHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJhc2VDb2luLCB0cmFkaW5nV2FsbGV0cyk7XG4gICAgICBjb25zdCBzdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucyA9IHRyYWRpbmdXYWxsZXRUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpO1xuICAgICAgc3VwcG9ydGVkVHhSZXF1ZXN0VmVyc2lvbnMuc2hvdWxkLmRlZXBFcXVhbChbXSk7XG4gICAgfSk7XG4gICAgaXQoJ3Nob3VsZCByZXR1cm4gZW1wdHkgZm9yIG5vbi10c3Mgd2FsbGV0cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IG5vblRzc1dhbGxldERhdGEgPSB7IGNvaW46ICdidGMnLCBtdWx0aXNpZ1R5cGU6ICdvbmNoYWluJyB9O1xuICAgICAgY29uc3QgYnRjQ29pbiA9IGJpdGdvLmNvaW4oJ3RidGMnKTtcbiAgICAgIGNvbnN0IG5vblRzc1dhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJ0Y0NvaW4sIG5vblRzc1dhbGxldERhdGEpO1xuICAgICAgY29uc3Qgbm9uVHNzV2FsbGV0VHNzVXRpbHMgPSBuZXcgVHNzVXRpbHMoYml0Z28sIGJ0Y0NvaW4sIG5vblRzc1dhbGxldCk7XG4gICAgICBub25Uc3NXYWxsZXRUc3NVdGlscy5zdXBwb3J0ZWRUeFJlcXVlc3RWZXJzaW9ucygpLnNob3VsZC5kZWVwRXF1YWwoW10pO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnaXNQZW5kaW5nQXBwcm92YWxUeFJlcXVlc3RGdWxsJywgKCkgPT4ge1xuICAgIGl0KCdzaG91bGQgcmV0dXJuIHRydWUgZm9yIGZ1bGwgYXBpVmVyc2lvbiBhbmQgcGVuZGluZ0FwcHJvdmFsIHN0YXRlJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhSZXF1ZXN0ID0ge1xuICAgICAgICBhcGlWZXJzaW9uOiAnZnVsbCcsXG4gICAgICAgIHN0YXRlOiAncGVuZGluZ0FwcHJvdmFsJyxcbiAgICAgIH0gYXMgVHhSZXF1ZXN0O1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdHNzVXRpbHMuaXNQZW5kaW5nQXBwcm92YWxUeFJlcXVlc3RGdWxsKHR4UmVxdWVzdCk7XG4gICAgICByZXN1bHQuc2hvdWxkLmJlLnRydWUoKTtcbiAgICB9KTtcblxuICAgIGl0KCdzaG91bGQgcmV0dXJuIGZhbHNlIGZvciBub24tZnVsbCBhcGlWZXJzaW9uJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdHhSZXF1ZXN0ID0ge1xuICAgICAgICBhcGlWZXJzaW9uOiAnbGl0ZScsXG4gICAgICAgIHN0YXRlOiAncGVuZGluZ0FwcHJvdmFsJyxcbiAgICAgIH0gYXMgVHhSZXF1ZXN0O1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdHNzVXRpbHMuaXNQZW5kaW5nQXBwcm92YWxUeFJlcXVlc3RGdWxsKHR4UmVxdWVzdCk7XG4gICAgICByZXN1bHQuc2hvdWxkLmJlLmZhbHNlKCk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiBmYWxzZSBmb3Igbm9uLXBlbmRpbmdBcHByb3ZhbCBzdGF0ZScsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHR4UmVxdWVzdCA9IHtcbiAgICAgICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgICAgICBzdGF0ZTogJ3BlbmRpbmdEZWxpdmVyeScsXG4gICAgICB9IGFzIFR4UmVxdWVzdDtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRzc1V0aWxzLmlzUGVuZGluZ0FwcHJvdmFsVHhSZXF1ZXN0RnVsbCh0eFJlcXVlc3QpO1xuICAgICAgcmVzdWx0LnNob3VsZC5iZS5mYWxzZSgpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyAjcmVnaW9uIE5vY2sgaGVscGVyc1xuICBhc3luYyBmdW5jdGlvbiBnZW5lcmF0ZUJpdGdvS2V5Y2hhaW4ocGFyYW1zOiB7XG4gICAgY29pbjogc3RyaW5nO1xuICAgIHVzZXJLZXlTaGFyZTogS2V5U2hhcmU7XG4gICAgYmFja3VwS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIGJpdGdvS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIHVzZXJHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgICBiYWNrdXBHcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgICBiaXRnb0dwZ0tleTogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+O1xuICB9KTogUHJvbWlzZTxLZXljaGFpbj4ge1xuICAgIGNvbnN0IGJpdGdvQ29tYmluZWQgPSBNUEMua2V5Q29tYmluZShwYXJhbXMuYml0Z29LZXlTaGFyZS51U2hhcmUsIFtcbiAgICAgIHBhcmFtcy51c2VyS2V5U2hhcmUueVNoYXJlc1szXSxcbiAgICAgIHBhcmFtcy5iYWNrdXBLZXlTaGFyZS55U2hhcmVzWzNdLFxuICAgIF0pO1xuICAgIGNvbnN0IHVzZXJHcGdLZXlBY3R1YWwgPSBhd2FpdCBvcGVucGdwLnJlYWRLZXkoeyBhcm1vcmVkS2V5OiBwYXJhbXMudXNlckdwZ0tleS5wdWJsaWNLZXkgfSk7XG4gICAgY29uc3QgYmFja3VwR3BnS2V5QWN0dWFsID0gYXdhaXQgb3BlbnBncC5yZWFkS2V5KHsgYXJtb3JlZEtleTogcGFyYW1zLmJhY2t1cEdwZ0tleS5wdWJsaWNLZXkgfSk7XG5cbiAgICBjb25zdCBiaXRnb1RvVXNlck1lc3NhZ2UgPSBhd2FpdCBvcGVucGdwLmNyZWF0ZU1lc3NhZ2Uoe1xuICAgICAgdGV4dDogQnVmZmVyLmNvbmNhdChbXG4gICAgICAgIEJ1ZmZlci5mcm9tKHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMV0udSwgJ2hleCcpLFxuICAgICAgICBCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS55U2hhcmVzWzFdLmNoYWluY29kZSwgJ2hleCcpLFxuICAgICAgXSkudG9TdHJpbmcoJ2hleCcpLFxuICAgIH0pO1xuICAgIGNvbnN0IGVuY3J5cHRlZEJpdGdvVG9Vc2VyTWVzc2FnZSA9IGF3YWl0IG9wZW5wZ3AuZW5jcnlwdCh7XG4gICAgICBtZXNzYWdlOiBiaXRnb1RvVXNlck1lc3NhZ2UsXG4gICAgICBlbmNyeXB0aW9uS2V5czogW3VzZXJHcGdLZXlBY3R1YWwudG9QdWJsaWMoKV0sXG4gICAgICBmb3JtYXQ6ICdhcm1vcmVkJyxcbiAgICB9KTtcblxuICAgIGNvbnN0IGJpdGdvVG9CYWNrdXBNZXNzYWdlID0gYXdhaXQgb3BlbnBncC5jcmVhdGVNZXNzYWdlKHtcbiAgICAgIHRleHQ6IEJ1ZmZlci5jb25jYXQoW1xuICAgICAgICBCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS55U2hhcmVzWzJdLnUsICdoZXgnKSxcbiAgICAgICAgQnVmZmVyLmZyb20ocGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1syXS5jaGFpbmNvZGUsICdoZXgnKSxcbiAgICAgIF0pLnRvU3RyaW5nKCdoZXgnKSxcbiAgICB9KTtcbiAgICBjb25zdCBlbmNyeXB0ZWRCaXRnb1RvQmFja3VwTWVzc2FnZSA9IGF3YWl0IG9wZW5wZ3AuZW5jcnlwdCh7XG4gICAgICBtZXNzYWdlOiBiaXRnb1RvQmFja3VwTWVzc2FnZSxcbiAgICAgIGVuY3J5cHRpb25LZXlzOiBbYmFja3VwR3BnS2V5QWN0dWFsLnRvUHVibGljKCldLFxuICAgICAgZm9ybWF0OiAnYXJtb3JlZCcsXG4gICAgfSk7XG5cbiAgICBjb25zdCBiaXRnb0tleWNoYWluOiBLZXljaGFpbiA9IHtcbiAgICAgIGlkOiAnMycsXG4gICAgICBwdWI6ICcnLFxuICAgICAgY29tbW9uS2V5Y2hhaW46IGJpdGdvQ29tYmluZWQucFNoYXJlLnkgKyBiaXRnb0NvbWJpbmVkLnBTaGFyZS5jaGFpbmNvZGUsXG4gICAgICBrZXlTaGFyZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGZyb206ICdiaXRnbycsXG4gICAgICAgICAgdG86ICd1c2VyJyxcbiAgICAgICAgICBwdWJsaWNTaGFyZTogcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS55ICsgcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS5jaGFpbmNvZGUsXG4gICAgICAgICAgcHJpdmF0ZVNoYXJlOiBlbmNyeXB0ZWRCaXRnb1RvVXNlck1lc3NhZ2UudG9TdHJpbmcoKSxcbiAgICAgICAgICB2c3NQcm9vZjogcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS52LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgZnJvbTogJ2JpdGdvJyxcbiAgICAgICAgICB0bzogJ2JhY2t1cCcsXG4gICAgICAgICAgcHVibGljU2hhcmU6IHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0ueSArIHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0uY2hhaW5jb2RlLFxuICAgICAgICAgIHByaXZhdGVTaGFyZTogZW5jcnlwdGVkQml0Z29Ub0JhY2t1cE1lc3NhZ2UudG9TdHJpbmcoKSxcbiAgICAgICAgICB2c3NQcm9vZjogcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1syXS52LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHR5cGU6ICd0c3MnLFxuICAgIH07XG5cbiAgICBjb25zdCB1c2VyS2V5SWQgPSB1c2VyR3BnS2V5QWN0dWFsLmtleVBhY2tldC5nZXRGaW5nZXJwcmludCgpO1xuICAgIGNvbnN0IGJhY2t1cEtleUlkID0gYmFja3VwR3BnS2V5QWN0dWFsLmtleVBhY2tldC5nZXRGaW5nZXJwcmludCgpO1xuICAgIGNvbnN0IGJpdGdvVG9Vc2VyUHVibGljU2hhcmUgPVxuICAgICAgQnVmZmVyLmZyb20oXG4gICAgICAgIGF3YWl0IHNvZGl1bS5jcnlwdG9fc2NhbGFybXVsdF9lZDI1NTE5X2Jhc2Vfbm9jbGFtcChCdWZmZXIuZnJvbShwYXJhbXMuYml0Z29LZXlTaGFyZS55U2hhcmVzWzFdLnUsICdoZXgnKSlcbiAgICAgICkudG9TdHJpbmcoJ2hleCcpICsgcGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1sxXS5jaGFpbmNvZGU7XG4gICAgY29uc3QgYml0Z29Ub0JhY2t1cFB1YmxpY1NoYXJlID1cbiAgICAgIEJ1ZmZlci5mcm9tKFxuICAgICAgICBhd2FpdCBzb2RpdW0uY3J5cHRvX3NjYWxhcm11bHRfZWQyNTUxOV9iYXNlX25vY2xhbXAoQnVmZmVyLmZyb20ocGFyYW1zLmJpdGdvS2V5U2hhcmUueVNoYXJlc1syXS51LCAnaGV4JykpXG4gICAgICApLnRvU3RyaW5nKCdoZXgnKSArIHBhcmFtcy5iaXRnb0tleVNoYXJlLnlTaGFyZXNbMl0uY2hhaW5jb2RlO1xuXG4gICAgYml0Z29LZXljaGFpbi53YWxsZXRIU01HUEdQdWJsaWNLZXlTaWdzID0gYXdhaXQgY3JlYXRlV2FsbGV0U2lnbmF0dXJlcyhcbiAgICAgIHBhcmFtcy5iaXRnb0dwZ0tleS5wcml2YXRlS2V5LFxuICAgICAgcGFyYW1zLnVzZXJHcGdLZXkucHVibGljS2V5LFxuICAgICAgcGFyYW1zLmJhY2t1cEdwZ0tleS5wdWJsaWNLZXksXG4gICAgICBbXG4gICAgICAgIHsgbmFtZTogJ2NvbW1vbktleWNoYWluJywgdmFsdWU6IGJpdGdvQ29tYmluZWQucFNoYXJlLnkgKyBiaXRnb0NvbWJpbmVkLnBTaGFyZS5jaGFpbmNvZGUgfSxcbiAgICAgICAgeyBuYW1lOiAndXNlcktleUlkJywgdmFsdWU6IHVzZXJLZXlJZCB9LFxuICAgICAgICB7IG5hbWU6ICdiYWNrdXBLZXlJZCcsIHZhbHVlOiBiYWNrdXBLZXlJZCB9LFxuICAgICAgICB7IG5hbWU6ICdiaXRnb1RvVXNlclB1YmxpY1NoYXJlJywgdmFsdWU6IGJpdGdvVG9Vc2VyUHVibGljU2hhcmUgfSxcbiAgICAgICAgeyBuYW1lOiAnYml0Z29Ub0JhY2t1cFB1YmxpY1NoYXJlJywgdmFsdWU6IGJpdGdvVG9CYWNrdXBQdWJsaWNTaGFyZSB9LFxuICAgICAgXVxuICAgICk7XG5cbiAgICByZXR1cm4gYml0Z29LZXljaGFpbjtcbiAgfVxuXG4gIGFzeW5jIGZ1bmN0aW9uIG5vY2tCaXRnb0tleWNoYWluKHBhcmFtczoge1xuICAgIGNvaW46IHN0cmluZztcbiAgICB1c2VyS2V5U2hhcmU6IEtleVNoYXJlO1xuICAgIGJhY2t1cEtleVNoYXJlOiBLZXlTaGFyZTtcbiAgICBiaXRnb0tleVNoYXJlOiBLZXlTaGFyZTtcbiAgICB1c2VyR3BnS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gICAgYmFja3VwR3BnS2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz47XG4gICAgYml0Z29HcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgfSk6IFByb21pc2U8S2V5Y2hhaW4+IHtcbiAgICBjb25zdCBiaXRnb0tleWNoYWluID0gYXdhaXQgZ2VuZXJhdGVCaXRnb0tleWNoYWluKHBhcmFtcyk7XG5cbiAgICBub2NrKGJnVXJsKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvJHtwYXJhbXMuY29pbn0va2V5YCwgXy5tYXRjaGVzKHsga2V5VHlwZTogJ3RzcycsIHNvdXJjZTogJ2JpdGdvJyB9KSlcbiAgICAgIC5yZXBseSgyMDAsIGJpdGdvS2V5Y2hhaW4pO1xuXG4gICAgcmV0dXJuIGJpdGdvS2V5Y2hhaW47XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBub2NrVXNlcktleWNoYWluKHBhcmFtczogeyBjb2luOiBzdHJpbmcgfSk6IFByb21pc2U8S2V5Y2hhaW4+IHtcbiAgICBjb25zdCB1c2VyS2V5Y2hhaW46IEtleWNoYWluID0ge1xuICAgICAgaWQ6ICcxJyxcbiAgICAgIHB1YjogJycsXG4gICAgICB0eXBlOiAndHNzJyxcbiAgICB9O1xuXG4gICAgbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAgIC5wb3N0KGAvYXBpL3YyLyR7cGFyYW1zLmNvaW59L2tleWAsIF8ubWF0Y2hlcyh7IGtleVR5cGU6ICd0c3MnLCBzb3VyY2U6ICd1c2VyJyB9KSlcbiAgICAgIC5yZXBseSgyMDAsIHVzZXJLZXljaGFpbik7XG5cbiAgICByZXR1cm4gdXNlcktleWNoYWluO1xuICB9XG5cbiAgYXN5bmMgZnVuY3Rpb24gbm9ja0JhY2t1cEtleWNoYWluKHBhcmFtczogeyBjb2luOiBzdHJpbmcgfSk6IFByb21pc2U8S2V5Y2hhaW4+IHtcbiAgICBjb25zdCBiYWNrdXBLZXljaGFpbjogS2V5Y2hhaW4gPSB7XG4gICAgICBpZDogJzInLFxuICAgICAgcHViOiAnJyxcbiAgICAgIHR5cGU6ICd0c3MnLFxuICAgIH07XG5cbiAgICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgICAgLnBvc3QoYC9hcGkvdjIvJHtwYXJhbXMuY29pbn0va2V5YCwgXy5tYXRjaGVzKHsga2V5VHlwZTogJ3RzcycsIHNvdXJjZTogJ2JhY2t1cCcgfSkpXG4gICAgICAucmVwbHkoMjAwLCBiYWNrdXBLZXljaGFpbik7XG5cbiAgICByZXR1cm4gYmFja3VwS2V5Y2hhaW47XG4gIH1cblxuICBkZXNjcmliZSgnZ2V0UHVibGljS2V5RnJvbUNvbW1vbktleWNoYWluJywgZnVuY3Rpb24gKCkge1xuICAgIC8vIDMyLWJ5dGUgZWQyNTUxOSBwdWJsaWMga2V5IGFzIGhleCAoNjQgY2hhcnMpICsgMzItYnl0ZSBjaGFpbmNvZGUgKDY0IGNoYXJzKSA9IDEyOCBjaGFyc1xuICAgIGNvbnN0IHB1YkhleCA9ICdhMzA0NzMzYzE2Y2M4MjFmZTE3MWQ1YzdkYmQ3Mjc2ZmQ5MGRlYWU4MDhiNzU1M2QxN2ExZTU1ZTRhNzZiMjcwJztcbiAgICBjb25zdCBjaGFpbmNvZGUgPSAnOWQ5MWMyZTYzNTMyMDJjZjYxZjhmMjc1MTU4YjM0NjhlOWEwMGY3ODcyZmMyZmQzMTBiNzJjZDAyNmUyZTJmOSc7XG4gICAgY29uc3QgY29tbW9uS2V5Y2hhaW4gPSBwdWJIZXggKyBjaGFpbmNvZGU7XG5cbiAgICBpdCgnc2hvdWxkIGRlY29kZSB0aGUgMzItYnl0ZSBwdWJsaWMga2V5IGZyb20gYSAxMjgtY2hhciBjb21tb25LZXljaGFpbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbW1vbktleWNoYWluLmxlbmd0aC5zaG91bGQuZXF1YWwoMTI4KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IFRzc1V0aWxzLmdldFB1YmxpY0tleUZyb21Db21tb25LZXljaGFpbihjb21tb25LZXljaGFpbik7XG4gICAgICByZXN1bHQuc2hvdWxkLmVxdWFsKCdCeU1QZVZ4czdlOHpHZWN1OG4xTTQzTXE5cWt4QlN5cE5Od0hlRXUyTjZ2YicpO1xuICAgIH0pO1xuXG4gICAgaXQoJ3Nob3VsZCB0aHJvdyBmb3IgYW4gaW52YWxpZCBjb21tb25LZXljaGFpbiBsZW5ndGgnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzaG91bGQudGhyb3dzKFxuICAgICAgICAoKSA9PiBUc3NVdGlscy5nZXRQdWJsaWNLZXlGcm9tQ29tbW9uS2V5Y2hhaW4oJ2FiY2QnKSxcbiAgICAgICAgL0ludmFsaWQgY29tbW9uS2V5Y2hhaW4gbGVuZ3RoLCBleHBlY3RlZCAxMjgsIGdvdCA0L1xuICAgICAgKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2dldEJpdGdvR3BnUHVia2V5QmFzZWRPbkZlYXR1cmVGbGFncycsIGZ1bmN0aW9uICgpIHtcbiAgICBpdCgnc2hvdWxkIHJldHVybiBlZGRzYU1wY3YyUHVibGljS2V5IHdoZW4gcHJlc2VudCBpbiBmZWF0dXJlIGZsYWdzIHJlc3BvbnNlJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgZWQyNTUxOUtleVBhaXIgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgICAgdXNlcklEczogW3sgbmFtZTogJ2JpdGdvIGVkZHNhJywgZW1haWw6ICdiaXRnb0B0ZXN0LmNvbScgfV0sXG4gICAgICAgIGN1cnZlOiAnZWQyNTUxOScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlOiBCaXRnb0dQR1B1YmxpY0tleSA9IHtcbiAgICAgICAgbmFtZTogJ2lycmVsZXZhbnQnLFxuICAgICAgICBwdWJsaWNLZXk6IGVkMjU1MTlLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgbXBjdjJQdWJsaWNLZXk6IGVkMjU1MTlLZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgZWRkc2FNcGN2MlB1YmxpY0tleTogZWQyNTUxOUtleVBhaXIucHVibGljS2V5LFxuICAgICAgICBlbnRlcnByaXNlSWQ6ICdlbnRlcnByaXNlX2lkJyxcbiAgICAgIH07XG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvJHtjb2luTmFtZX0vdHNzL3B1YmtleWApLnF1ZXJ5KHsgZW50ZXJwcmlzZUlkOiAnZW50ZXJwcmlzZV9pZCcgfSkucmVwbHkoMjAwLCByZXNwb25zZSk7XG4gICAgICBjb25zdCB7IGVkZHNhTXBjdjJQdWJsaWNLZXkgfSA9IGF3YWl0IHRzc1V0aWxzLmdldEJpdGdvR3BnUHVia2V5QmFzZWRPbkZlYXR1cmVGbGFncygnZW50ZXJwcmlzZV9pZCcpO1xuICAgICAgc2hvdWxkLmV4aXN0KGVkZHNhTXBjdjJQdWJsaWNLZXkpO1xuICAgICAgc2hvdWxkLmVxdWFsKGVkMjU1MTlLZXlQYWlyLnB1YmxpY0tleSwgZWRkc2FNcGN2MlB1YmxpY0tleSEuYXJtb3IoKSk7XG4gICAgfSk7XG5cbiAgICBpdCgnc2hvdWxkIHJldHVybiB1bmRlZmluZWQgZWRkc2FNcGN2MlB1YmxpY0tleSB3aGVuIGFic2VudCBmcm9tIGZlYXR1cmUgZmxhZ3MgcmVzcG9uc2UnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBrZXlQYWlyID0gYXdhaXQgb3BlbnBncC5nZW5lcmF0ZUtleSh7XG4gICAgICAgIHVzZXJJRHM6IFt7IG5hbWU6ICdiaXRnbycsIGVtYWlsOiAnYml0Z29AdGVzdC5jb20nIH1dLFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXNwb25zZTogQml0Z29HUEdQdWJsaWNLZXkgPSB7XG4gICAgICAgIG5hbWU6ICdpcnJlbGV2YW50JyxcbiAgICAgICAgcHVibGljS2V5OiBrZXlQYWlyLnB1YmxpY0tleSxcbiAgICAgICAgbXBjdjJQdWJsaWNLZXk6IGtleVBhaXIucHVibGljS2V5LFxuICAgICAgICBlbnRlcnByaXNlSWQ6ICdlbnRlcnByaXNlX2lkJyxcbiAgICAgIH07XG4gICAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvJHtjb2luTmFtZX0vdHNzL3B1YmtleWApLnF1ZXJ5KHsgZW50ZXJwcmlzZUlkOiAnZW50ZXJwcmlzZV9pZCcgfSkucmVwbHkoMjAwLCByZXNwb25zZSk7XG4gICAgICBjb25zdCB7IGVkZHNhTXBjdjJQdWJsaWNLZXkgfSA9IGF3YWl0IHRzc1V0aWxzLmdldEJpdGdvR3BnUHVia2V5QmFzZWRPbkZlYXR1cmVGbGFncygnZW50ZXJwcmlzZV9pZCcpO1xuICAgICAgc2hvdWxkLm5vdC5leGlzdChlZGRzYU1wY3YyUHVibGljS2V5KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgLy8gI2VuZHJlZ2lvbiBOb2NrIGhlbHBlcnNcbn0pO1xuIl19