PHP WebShell

Текущая директория: /opt/BitGoJS/modules/express/dist/test/unit/clientRoutes

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

"use strict";
/**
 * @prettier
 */
Object.defineProperty(exports, "__esModule", { value: true });
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_test_1 = require("@bitgo/sdk-test");
const should = require("should");
const sinon = require("sinon");
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
const assert = require("assert");
const nock = require("nock");
const fs = require("fs");
require("should-http");
require("should-sinon");
require("../../lib/asserts");
const clientRoutes_1 = require("../../../src/clientRoutes");
const fetchEncryptedPrivKeys_1 = require("../../../src/fetchEncryptedPrivKeys");
const ecdsaNtilde_1 = require("./mocks/ecdsaNtilde");
const bitgo_1 = require("bitgo");
const keyShares_1 = require("./mocks/keyShares");
const gpgKeys_1 = require("./mocks/gpgKeys");
const createKeccakHash = require('keccak');
nock.restore();
describe('External signer', () => {
    let bitgo;
    let bgUrl;
    let MPC;
    let mpcEcdsa;
    let hdTree;
    const walletId = '61f039aad587c2000745c687373e0fa9';
    const walletPassword = 'wDX058%c4plL1@pP';
    const secret = 'xprv9s21ZrQH143K3EuPWCBuqnWxydaQV6et9htQige4EswvcHKEzNmkVmwTwKoadyHzJYppuADB7Us7AbaNLToNvoFoSxuWqndQRYtnNy5DUY2';
    const validPrv = '{"61f039aad587c2000745c687373e0fa9":"{\\"iv\\":\\"+1u1Y9cvsYuRMeyH2slnXQ==\\",\\"v\\":1,\\"iter\\":10000,\\"ks\\":256,\\"ts\\":64,\\"mode\\":\\"ccm\\",\\"adata\\":\\"\\",\\"cipher\\":\\"aes\\",\\"salt\\":\\"54kOXTqJ9mc=\\",\\"ct\\":\\"JF5wQ82wa1dYyFxFlbHCvK4a+A6MTHdhOqc5uXsz2icWhkY2Lin/3Ab8ZwvwDaR1JYKmC/g1gXIGwVZEOl1M/bRHY420h7sDtmTS6Ebse5NWbF0ItfUJlk6HVATGa+C6mkbaVxJ4kQW/ehnT3riqzU069ATPz8E=\\"}"}';
    before(async function () {
        if (!nock.isActive()) {
            nock.activate();
        }
        bitgo = sdk_test_1.TestBitGo.decorate(bitgo_1.BitGo, { env: 'test' });
        bitgo.initializeTestVars();
        bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
        hdTree = await sdk_core_1.Ed25519BIP32.initialize();
        MPC = await sdk_core_1.Eddsa.initialize(hdTree);
        mpcEcdsa = new sdk_core_1.Ecdsa();
        const constants = {
            mpc: {
                bitgoPublicKey: gpgKeys_1.bitgoGpgKey.public,
                bitgoMPCv2PublicKey: gpgKeys_1.bitgoGpgKey.public,
            },
        };
        nock(bgUrl).get('/api/v1/client/constants').times(10).reply(200, { ttl: 3600, constants });
    });
    after(() => {
        if (nock.isActive()) {
            nock.restore();
        }
    });
    it('should read an encrypted prv from signerFileSystemPath and pass it to coin.signTransaction', async () => {
        const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(validPrv);
        const envStub = sinon
            .stub(process, 'env')
            .value({ WALLET_61f039aad587c2000745c687373e0fa9_PASSPHRASE: walletPassword });
        const signTransactionStub = sinon
            .stub(bitgo_1.Coin.Btc.prototype, 'signTransaction')
            .resolves({ txHex: 'signedTx', txRequestId: '' });
        const req = {
            bitgo: bitgo,
            body: {
                txPrebuild: {
                    walletId: walletId,
                },
            },
            params: {
                coin: 'tbtc',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        await (0, clientRoutes_1.handleV2Sign)(req);
        readFileStub.calledOnceWith('signerFileSystemPath').should.be.true();
        signTransactionStub
            .calledOnceWith(sinon.match({
            prv: secret,
        }))
            .should.be.true();
        readFileStub.restore();
        signTransactionStub.restore();
        envStub.restore();
    });
    it('should read an encrypted prv from signerFileSystemPath and pass it to PaillierModulus, K, MuDelta, and S share generators', async () => {
        const walletID = '62fe536a6b4cf70007acb48c0e7bb0b0';
        const user = keyShares_1.keyShareOneEcdsa; // await mpcEcdsa.keyShare(1, 2, 3);
        const backup = keyShares_1.keyShareTwoEcdsa; // await mpcEcdsa.keyShare(2, 2, 3);
        const bitgo = keyShares_1.keyShareThreeEcdsa; // await mpcEcdsa.keyShare(3, 2, 3);
        const bitgoCombinedKey = await mpcEcdsa.keyCombine(bitgo.pShare, [backup.nShares[3], user.nShares[3]]);
        const userChallenge = ecdsaNtilde_1.mockChallengeA;
        const bitgoChallenge = ecdsaNtilde_1.mockChallengeB;
        const userSigningMaterial = {
            pShare: user.pShare,
            bitgoNShare: bitgo.nShares[1],
            backupNShare: backup.nShares[1],
        };
        const bg = new bitgo_1.BitGo({ env: 'test' });
        const walletPassphrase = 'testPass';
        const validPrv = bg.encrypt({ input: JSON.stringify(userSigningMaterial), password: walletPassphrase });
        const output = {};
        output[walletID] = validPrv;
        const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(JSON.stringify(output));
        const envStub = sinon
            .stub(process, 'env')
            .value({ WALLET_62fe536a6b4cf70007acb48c0e7bb0b0_PASSPHRASE: walletPassphrase });
        const tMessage = 'testMessage';
        const bgTest = new bitgo_1.BitGo({ env: 'test' });
        const derivationPath = '';
        const reqPaillierModulus = {
            bitgo: bgTest,
            body: {
                txRequest: {
                    apiVersion: 'full',
                    walletId: walletID,
                    transactions: [
                        {
                            unsignedTx: {
                                derivationPath,
                                signableHex: tMessage,
                            },
                        },
                    ],
                },
            },
            params: {
                coin: 'tbsc',
                sharetype: 'PaillierModulus',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const paillierResult = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqPaillierModulus);
        paillierResult.should.have.property('userPaillierModulus');
        const userPaillierModulus = paillierResult.userPaillierModulus;
        const [bitgoToUserPaillierChallenge, userToBitgoPaillierChallenge] = await Promise.all([
            sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_lib_mpc_1.hexToBigInt)(userPaillierModulus)),
            sdk_lib_mpc_1.EcdsaPaillierProof.generateP((0, sdk_lib_mpc_1.hexToBigInt)(bitgoCombinedKey.yShares[1].n)),
        ]);
        const reqK = {
            bitgo: bgTest,
            body: {
                tssParams: {
                    txRequest: {
                        apiVersion: 'full',
                        walletId: walletID,
                        transactions: [
                            {
                                unsignedTx: {
                                    derivationPath,
                                    signableHex: tMessage,
                                },
                            },
                        ],
                    },
                },
                challenges: {
                    enterpriseChallenge: {
                        ntilde: userChallenge.ntilde,
                        h1: userChallenge.h1,
                        h2: userChallenge.h2,
                        p: sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: userToBitgoPaillierChallenge }).p,
                    },
                    bitgoChallenge: {
                        ntilde: bitgoChallenge.ntilde,
                        h1: bitgoChallenge.h1,
                        h2: bitgoChallenge.h2,
                        p: sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: bitgoToUserPaillierChallenge }).p,
                        n: bitgo.pShare.n,
                    },
                },
                requestType: 0,
            },
            params: {
                coin: 'tbsc',
                sharetype: 'K',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const kResult = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqK);
        kResult.should.have.property('kShare');
        kResult.should.have.property('wShare');
        const aShareFromBitgo = await mpcEcdsa.signConvertStep1({
            xShare: mpcEcdsa.appendChallenge(bitgoCombinedKey.xShare, bitgoChallenge, sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: bitgoToUserPaillierChallenge })),
            yShare: bitgoCombinedKey.yShares[1],
            kShare: kResult.kShare,
        });
        const reqMuDelta = {
            bitgo: bgTest,
            body: {
                txRequest: {
                    apiVersion: 'full',
                    walletId: walletID,
                    transactions: [
                        {
                            unsignedTx: {
                                derivationPath,
                                signableHex: tMessage,
                            },
                        },
                    ],
                },
                aShareFromBitgo: aShareFromBitgo.aShare,
                bitgoChallenge: {
                    ntilde: bitgoChallenge.ntilde,
                    h1: bitgoChallenge.h1,
                    h2: bitgoChallenge.h2,
                    p: sdk_lib_mpc_1.EcdsaTypes.serializePaillierChallenge({ p: bitgoToUserPaillierChallenge }).p,
                    n: bitgo.pShare.n,
                },
                encryptedWShare: kResult.wShare,
            },
            params: {
                coin: 'tbsc',
                sharetype: 'MuDelta',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const muDeltaResult = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqMuDelta);
        muDeltaResult.should.have.property('muDShare');
        muDeltaResult.should.have.property('oShare');
        const bitgoGShare = await mpcEcdsa.signConvertStep3({
            bShare: aShareFromBitgo.bShare,
            muShare: muDeltaResult.muDShare.muShare,
        });
        const bitgoDShare = mpcEcdsa.signCombine({
            gShare: bitgoGShare.gShare,
            signIndex: {
                i: 1,
                j: 3,
            },
        });
        const reqS = {
            bitgo: bgTest,
            body: {
                tssParams: {
                    txRequest: {
                        apiVersion: 'full',
                        walletId: walletID,
                        transactions: [
                            {
                                unsignedTx: {
                                    derivationPath,
                                    signableHex: tMessage,
                                },
                            },
                        ],
                    },
                },
                dShareFromBitgo: bitgoDShare.dShare,
                requestType: 0,
                encryptedOShare: muDeltaResult.oShare,
            },
            params: {
                coin: 'tbsc',
                sharetype: 'S',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const sResult = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqS);
        sResult.should.have.property('R');
        sResult.should.have.property('s');
        sResult.should.have.property('y');
        const bitGoSShare = mpcEcdsa.sign(Buffer.from(tMessage, 'hex'), bitgoDShare.oShare, muDeltaResult.muDShare.dShare, createKeccakHash('keccak256'));
        const signature = mpcEcdsa.constructSignature([bitGoSShare, sResult]);
        mpcEcdsa.verify(Buffer.from(tMessage, 'hex'), signature, createKeccakHash('keccak256')).should.be.true;
        readFileStub.restore();
        envStub.restore();
    });
    it('should read an encrypted prv from signerFileSystemPath and pass it to commitment, R and G share generators', async () => {
        const walletID = '62fe536a6b4cf70007acb48c0e7bb0b0';
        const user = MPC.keyShare(1, 2, 3);
        const backup = MPC.keyShare(2, 2, 3);
        const bitgo = MPC.keyShare(3, 2, 3);
        const userSigningMaterial = {
            uShare: user.uShare,
            bitgoYShare: bitgo.yShares[1],
            backupYShare: backup.yShares[1],
        };
        const bg = new bitgo_1.BitGo({ env: 'test' });
        const walletPassphrase = 'testPass';
        const validPrv = bg.encrypt({ input: JSON.stringify(userSigningMaterial), password: walletPassphrase });
        const output = {};
        output[walletID] = validPrv;
        const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(JSON.stringify(output));
        const envStub = sinon
            .stub(process, 'env')
            .value({ WALLET_62fe536a6b4cf70007acb48c0e7bb0b0_PASSPHRASE: walletPassphrase });
        const tMessage = 'testMessage';
        const bgTest = new bitgo_1.BitGo({ env: 'test' });
        const derivationPath = 'm/0';
        const reqCommitment = {
            bitgo: bgTest,
            body: {
                bitgoGpgPubKey: gpgKeys_1.bitgoGpgKey.public,
                txRequest: {
                    apiVersion: 'full',
                    walletId: walletID,
                    transactions: [
                        {
                            unsignedTx: {
                                derivationPath,
                                signableHex: tMessage,
                            },
                        },
                    ],
                },
            },
            params: {
                coin: 'tsol',
                sharetype: 'commitment',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const cResult = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqCommitment);
        cResult.should.have.property('userToBitgoCommitment');
        cResult.should.have.property('encryptedSignerShare');
        cResult.should.have.property('encryptedUserToBitgoRShare');
        const encryptedUserToBitgoRShare = cResult.encryptedUserToBitgoRShare;
        const reqR = {
            bitgo: bgTest,
            body: {
                txRequest: {
                    apiVersion: 'full',
                    walletId: walletID,
                    transactions: [
                        {
                            unsignedTx: {
                                derivationPath,
                                signableHex: tMessage,
                            },
                        },
                    ],
                },
                encryptedUserToBitgoRShare,
            },
            params: {
                coin: 'tsol',
                sharetype: 'R',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const rResult = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqR);
        rResult.should.have.property('rShare');
        const signingKey = MPC.keyDerive(userSigningMaterial.uShare, [userSigningMaterial.bitgoYShare, userSigningMaterial.backupYShare], derivationPath);
        const bitgoCombine = MPC.keyCombine(bitgo.uShare, [signingKey.yShares[3], backup.yShares[3]]);
        const bitgoSignShare = await MPC.signShare(Buffer.from(tMessage, 'hex'), bitgoCombine.pShare, [
            bitgoCombine.jShares[1],
        ]);
        const signatureShareRec = {
            from: sdk_core_1.SignatureShareType.BITGO,
            to: sdk_core_1.SignatureShareType.USER,
            share: bitgoSignShare.rShares[1].r + bitgoSignShare.rShares[1].R,
        };
        const bitgoToUserCommitmentShare = {
            from: sdk_core_1.SignatureShareType.BITGO,
            to: sdk_core_1.SignatureShareType.USER,
            share: bitgoSignShare.rShares[1].commitment,
            type: 'commitment',
        };
        const reqG = {
            bitgo: bgTest,
            body: {
                txRequest: {
                    apiVersion: 'full',
                    walletId: walletID,
                    transactions: [
                        {
                            unsignedTx: {
                                derivationPath,
                                signableHex: tMessage,
                            },
                        },
                    ],
                },
                userToBitgoRShare: rResult.rShare,
                bitgoToUserRShare: signatureShareRec,
                bitgoToUserCommitment: bitgoToUserCommitmentShare,
            },
            params: {
                coin: 'tsol',
                sharetype: 'G',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const userGShare = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqG);
        userGShare.should.have.property('i');
        userGShare.should.have.property('y');
        userGShare.should.have.property('gamma');
        userGShare.should.have.property('R');
        const userToBitgoRShare = {
            i: sdk_core_1.ShareKeyPosition.BITGO,
            j: sdk_core_1.ShareKeyPosition.USER,
            u: signingKey.yShares[3].u,
            v: rResult.rShare.rShares[3].v,
            r: rResult.rShare.rShares[3].r,
            R: rResult.rShare.rShares[3].R,
            commitment: rResult.rShare.rShares[3].commitment,
        };
        const bitgoGShare = MPC.sign(Buffer.from(tMessage, 'hex'), bitgoSignShare.xShare, [userToBitgoRShare], [backup.yShares[3]]);
        const signature = MPC.signCombine([userGShare, bitgoGShare]);
        const veriResult = MPC.verify(Buffer.from(tMessage, 'hex'), signature);
        veriResult.should.be.true();
        readFileStub.restore();
        envStub.restore();
    });
    it('should read an encrypted prv from signerFileSystemPath and pass it to MPCv2Round1, MPCv2Round2 and MPCv2Round3 share generators', async () => {
        const walletID = '62fe536a6b4cf70007acb48c0e7bb0b0';
        const tMessage = 'testMessage';
        const derivationPath = 'm/0';
        const walletPassphrase = 'testPass';
        const [userShare, backupShare, bitgoShare] = await sdk_lib_mpc_1.DklsUtils.generateDKGKeyShares();
        assert(backupShare, 'backupShare is not defined');
        const bgTest = new bitgo_1.BitGo({ env: 'test' });
        const userKeyShare = userShare.getKeyShare().toString('base64');
        const validPrv = bgTest.encrypt({ input: userKeyShare, password: walletPassphrase });
        const readFileStub = sinon.stub(fs.promises, 'readFile').resolves(JSON.stringify({ [walletID]: validPrv }));
        const envStub = sinon.stub(process, 'env').value({ ['WALLET_' + walletID + '_PASSPHRASE']: walletPassphrase });
        // round 1
        const reqMPCv2Round1 = {
            bitgo: bgTest,
            body: {
                txRequest: {
                    txRequestId: '123456',
                    apiVersion: 'full',
                    walletId: walletID,
                    transactions: [
                        {
                            unsignedTx: {
                                derivationPath,
                                signableHex: tMessage,
                            },
                            signatureShares: [],
                        },
                    ],
                },
            },
            params: {
                coin: 'hteth',
                sharetype: 'MPCv2Round1',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const round1Result = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqMPCv2Round1);
        round1Result.should.have.property('signatureShareRound1');
        round1Result.should.have.property('userGpgPubKey');
        round1Result.should.have.property('encryptedRound1Session');
        round1Result.should.have.property('encryptedUserGpgPrvKey');
        const hashFn = createKeccakHash('keccak256');
        const hashBuffer = hashFn.update(Buffer.from(tMessage, 'hex')).digest();
        const bitgoSession = new sdk_lib_mpc_1.DklsDsg.Dsg(bitgoShare.getKeyShare(), 2, derivationPath, hashBuffer);
        const txRequestRound1 = await signBitgoMPCv2Round1(bitgoSession, reqMPCv2Round1.body.txRequest, round1Result.signatureShareRound1, round1Result.userGpgPubKey);
        assert(txRequestRound1.transactions &&
            txRequestRound1.transactions.length === 1 &&
            txRequestRound1.transactions[0].signatureShares.length === 2, 'txRequestRound2.transactions is not an array of length 1 with 2 signatureShares');
        // round 2
        const reqMPCv2Round2 = {
            bitgo: bgTest,
            body: {
                txRequest: txRequestRound1,
                encryptedRound1Session: round1Result.encryptedRound1Session,
                encryptedUserGpgPrvKey: round1Result.encryptedUserGpgPrvKey,
                bitgoPublicGpgKey: gpgKeys_1.bitgoGpgKey.public,
            },
            params: {
                coin: 'hteth',
                sharetype: 'MPCv2Round2',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const round2Result = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqMPCv2Round2);
        round2Result.should.have.property('signatureShareRound2');
        round2Result.should.have.property('encryptedRound2Session');
        const { txRequest: txRequestRound2, bitgoMsg4 } = await signBitgoMPCv2Round2(bitgoSession, reqMPCv2Round2.body.txRequest, round2Result.signatureShareRound2, round1Result.userGpgPubKey);
        assert(txRequestRound2.transactions &&
            txRequestRound2.transactions.length === 1 &&
            txRequestRound2.transactions[0].signatureShares.length === 4, 'txRequestRound2.transactions is not an array of length 1 with 4 signatureShares');
        // round 3
        const reqMPCv2Round3 = {
            bitgo: bgTest,
            body: {
                txRequest: txRequestRound2,
                encryptedRound2Session: round2Result.encryptedRound2Session,
                encryptedUserGpgPrvKey: round1Result.encryptedUserGpgPrvKey,
                bitgoPublicGpgKey: gpgKeys_1.bitgoGpgKey.public,
            },
            params: {
                coin: 'hteth',
                sharetype: 'MPCv2Round3',
            },
            config: {
                signerFileSystemPath: 'signerFileSystemPath',
            },
        };
        const round3Result = await (0, clientRoutes_1.handleV2GenerateShareTSS)(reqMPCv2Round3);
        round3Result.should.have.property('signatureShareRound3');
        const { userMsg4 } = await signBitgoMPCv2Round3(bitgoSession, round3Result.signatureShareRound3, round1Result.userGpgPubKey);
        // signature generation and validation
        assert(userMsg4.data.msg4.signatureR === bitgoMsg4.signatureR, 'User and BitGo signaturesR do not match');
        const deserializedBitgoMsg4 = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
            p2pMessages: [],
            broadcastMessages: [bitgoMsg4],
        });
        const deserializedUserMsg4 = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
            p2pMessages: [],
            broadcastMessages: [
                {
                    from: userMsg4.data.msg4.from,
                    payload: userMsg4.data.msg4.message,
                },
            ],
        });
        const combinedSigUsingUtil = sdk_lib_mpc_1.DklsUtils.combinePartialSignatures([deserializedUserMsg4.broadcastMessages[0].payload, deserializedBitgoMsg4.broadcastMessages[0].payload], Buffer.from(userMsg4.data.msg4.signatureR, 'base64').toString('hex'));
        const convertedSignature = sdk_lib_mpc_1.DklsUtils.verifyAndConvertDklsSignature(Buffer.from(tMessage, 'hex'), combinedSigUsingUtil, sdk_lib_mpc_1.DklsTypes.getCommonKeychain(userShare.getKeyShare()), derivationPath, createKeccakHash('keccak256'));
        assert(convertedSignature, 'Signature is not valid');
        assert(convertedSignature.split(':').length === 4, 'Signature is not valid');
        readFileStub.restore();
        envStub.restore();
    });
    it('should accept a local secret and password for a wallet', async () => {
        const accessToken = '';
        const walletIds = {
            tbtc: [
                {
                    walletId,
                    walletPassword,
                    secret,
                },
            ],
        };
        const walletResult = {
            walletId,
            keys: [walletId, walletId, walletId],
        };
        const keyResult = {
            walletId,
        };
        nock(bgUrl).get(`/api/v2/tbtc/wallet/${walletId}`).reply(200, walletResult);
        nock(bgUrl).get(`/api/v2/tbtc/key/${walletId}`).reply(200, keyResult);
        const data = await (0, fetchEncryptedPrivKeys_1.fetchKeys)(walletIds, accessToken);
        should.exist(data[walletId]);
        data[walletId].should.startWith('{"iv":"');
    });
});
// #region MPCv2 utils
function getBitGoPartyGpgKeyPrv(bitgoPrvKey) {
    return {
        partyId: 2,
        gpgKey: bitgoPrvKey,
    };
}
function getUserPartyGpgKeyPublic(userPubKey) {
    return {
        partyId: 0,
        gpgKey: userPubKey,
    };
}
async function signBitgoMPCv2Round1(bitgoSession, txRequest, userShare, userGPGPubKey) {
    assert(txRequest.transactions && txRequest.transactions.length === 1, 'txRequest.transactions is not an array of length 1');
    txRequest.transactions[0].signatureShares.push(userShare);
    // Do the actual signing on BitGo's side based on User's messages
    const signatureShare = JSON.parse(userShare.share);
    const deserializedMessages = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
        p2pMessages: [],
        broadcastMessages: [
            {
                from: signatureShare.data.msg1.from,
                payload: signatureShare.data.msg1.message,
            },
        ],
    });
    const bitgoToUserRound1BroadcastMsg = await bitgoSession.init();
    const bitgoToUserRound2Msg = bitgoSession.handleIncomingMessages({
        p2pMessages: [],
        broadcastMessages: deserializedMessages.broadcastMessages,
    });
    const serializedBitGoToUserRound1And2Msgs = sdk_lib_mpc_1.DklsTypes.serializeMessages({
        p2pMessages: bitgoToUserRound2Msg.p2pMessages,
        broadcastMessages: [bitgoToUserRound1BroadcastMsg],
    });
    const authEncMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(serializedBitGoToUserRound1And2Msgs, [getUserPartyGpgKeyPublic(userGPGPubKey)], [getBitGoPartyGpgKeyPrv(gpgKeys_1.bitgoGpgKey.private)]);
    const bitgoToUserSignatureShare = {
        type: 'round1Output',
        data: {
            msg1: {
                from: authEncMessages.broadcastMessages[0].from,
                signature: authEncMessages.broadcastMessages[0].payload.signature,
                message: authEncMessages.broadcastMessages[0].payload.message,
            },
            msg2: {
                from: authEncMessages.p2pMessages[0].from,
                to: authEncMessages.p2pMessages[0].to,
                encryptedMessage: authEncMessages.p2pMessages[0].payload.encryptedMessage,
                signature: authEncMessages.p2pMessages[0].payload.signature,
            },
        },
    };
    txRequest.transactions[0].signatureShares.push({
        from: sdk_core_1.SignatureShareType.BITGO,
        to: sdk_core_1.SignatureShareType.USER,
        share: JSON.stringify(bitgoToUserSignatureShare),
    });
    return txRequest;
}
async function signBitgoMPCv2Round2(bitgoSession, txRequest, userShare, userGPGPubKey) {
    assert(txRequest.transactions && txRequest.transactions.length === 1, 'txRequest.transactions is not an array of length 1');
    txRequest.transactions[0].signatureShares.push(userShare);
    // Do the actual signing on BitGo's side based on User's messages
    const parsedSignatureShare = JSON.parse(userShare.share);
    const serializedMessages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
        p2pMessages: [
            {
                from: parsedSignatureShare.data.msg2.from,
                to: parsedSignatureShare.data.msg2.to,
                payload: {
                    encryptedMessage: parsedSignatureShare.data.msg2.encryptedMessage,
                    signature: parsedSignatureShare.data.msg2.signature,
                },
            },
            {
                from: parsedSignatureShare.data.msg3.from,
                to: parsedSignatureShare.data.msg3.to,
                payload: {
                    encryptedMessage: parsedSignatureShare.data.msg3.encryptedMessage,
                    signature: parsedSignatureShare.data.msg3.signature,
                },
            },
        ],
        broadcastMessages: [],
    }, [getUserPartyGpgKeyPublic(userGPGPubKey)], [getBitGoPartyGpgKeyPrv(gpgKeys_1.bitgoGpgKey.private)]);
    const deserializedMessages2 = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
        p2pMessages: [serializedMessages.p2pMessages[0]],
        broadcastMessages: [],
    });
    const bitgoToUserRound3Msg = bitgoSession.handleIncomingMessages(deserializedMessages2);
    const serializedBitGoToUserRound3Msgs = sdk_lib_mpc_1.DklsTypes.serializeMessages(bitgoToUserRound3Msg);
    const authEncMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(serializedBitGoToUserRound3Msgs, [getUserPartyGpgKeyPublic(userGPGPubKey)], [getBitGoPartyGpgKeyPrv(gpgKeys_1.bitgoGpgKey.private)]);
    const bitgoToUserSignatureShare = {
        type: 'round2Output',
        data: {
            msg3: {
                from: authEncMessages.p2pMessages[0].from,
                to: authEncMessages.p2pMessages[0].to,
                encryptedMessage: authEncMessages.p2pMessages[0].payload.encryptedMessage,
                signature: authEncMessages.p2pMessages[0].payload.signature,
            },
        },
    };
    // handling user msg3 but not returning bitgo msg4 since its stored on bitgo side only
    const deserializedMessages3 = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
        p2pMessages: [serializedMessages.p2pMessages[1]],
        broadcastMessages: [],
    });
    const deserializedBitgoMsg4 = bitgoSession.handleIncomingMessages(deserializedMessages3);
    const serializedBitGoToUserRound4Msgs = sdk_lib_mpc_1.DklsTypes.serializeMessages(deserializedBitgoMsg4);
    txRequest.transactions[0].signatureShares.push({
        from: sdk_core_1.SignatureShareType.BITGO,
        to: sdk_core_1.SignatureShareType.USER,
        share: JSON.stringify(bitgoToUserSignatureShare),
    });
    return { txRequest, bitgoMsg4: serializedBitGoToUserRound4Msgs.broadcastMessages[0] };
}
async function signBitgoMPCv2Round3(bitgoSession, userShare, userGPGPubKey) {
    const parsedSignatureShare = JSON.parse(userShare.share);
    const serializedMessages = await sdk_lib_mpc_1.DklsComms.decryptAndVerifyIncomingMessages({
        p2pMessages: [],
        broadcastMessages: [
            {
                from: parsedSignatureShare.data.msg4.from,
                payload: {
                    message: parsedSignatureShare.data.msg4.message,
                    signature: parsedSignatureShare.data.msg4.signature,
                },
            },
        ],
    }, [getUserPartyGpgKeyPublic(userGPGPubKey)], [getBitGoPartyGpgKeyPrv(gpgKeys_1.bitgoGpgKey.private)]);
    const deserializedMessages = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
        p2pMessages: [],
        broadcastMessages: [serializedMessages.broadcastMessages[0]],
    });
    bitgoSession.handleIncomingMessages(deserializedMessages);
    return {
        userMsg4: parsedSignatureShare,
    };
}
// #endregion
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXh0ZXJuYWxTaWduLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdGVzdC91bml0L2NsaWVudFJvdXRlcy9leHRlcm5hbFNpZ24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOztHQUVHOztBQUVILDhDQVV5QjtBQUV6Qiw4Q0FBMEQ7QUFDMUQsaUNBQWlDO0FBQ2pDLCtCQUErQjtBQUMvQixvREFRNEI7QUFTNUIsaUNBQWlDO0FBQ2pDLDZCQUE2QjtBQUM3Qix5QkFBeUI7QUFHekIsdUJBQXFCO0FBQ3JCLHdCQUFzQjtBQUN0Qiw2QkFBMkI7QUFFM0IsNERBQW1GO0FBQ25GLGdGQUFnRTtBQUNoRSxxREFBcUU7QUFDckUsaUNBQXVEO0FBQ3ZELGlEQUEyRjtBQUMzRiw2Q0FBOEM7QUFFOUMsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDM0MsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBTWYsUUFBUSxDQUFDLGlCQUFpQixFQUFFLEdBQUcsRUFBRTtJQUMvQixJQUFJLEtBQW1CLENBQUM7SUFDeEIsSUFBSSxLQUFLLENBQUM7SUFDVixJQUFJLEdBQVUsQ0FBQztJQUNmLElBQUksUUFBZSxDQUFDO0lBQ3BCLElBQUksTUFBYyxDQUFDO0lBRW5CLE1BQU0sUUFBUSxHQUFHLGtDQUFrQyxDQUFDO0lBQ3BELE1BQU0sY0FBYyxHQUFHLGtCQUFrQixDQUFDO0lBQzFDLE1BQU0sTUFBTSxHQUNWLGlIQUFpSCxDQUFDO0lBQ3BILE1BQU0sUUFBUSxHQUNaLG1aQUFtWixDQUFDO0lBRXRaLE1BQU0sQ0FBQyxLQUFLO1FBQ1YsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRTtZQUNwQixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7U0FDakI7UUFFRCxLQUFLLEdBQUcsb0JBQVMsQ0FBQyxRQUFRLENBQUMsYUFBSyxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxDQUFD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RCxLQUFLLFVBQVUsb0JBQW9CLENBQ2pDLFlBQXlCLEVBQ3pCLFNBQStCLEVBQy9CLGFBQXFCO0lBRXJCLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFtQyxDQUFDO0lBQzNGLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSx1QkFBUyxDQUFDLGdDQUFnQyxDQUN6RTtRQUNFLFdBQVcsRUFBRSxFQUFFO1FBQ2YsaUJBQWlCLEVBQUU7WUFDakI7Z0JBQ0UsSUFBSSxFQUFFLG9CQUFvQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSTtnQkFDekMsT0FBTyxFQUFFO29CQUNQLE9BQU8sRUFBRSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU87b0JBQy9DLFNBQVMsRUFBRSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVM7aUJBQ3BEO2FBQ0Y7U0FDRjtLQUNGLEVBQ0QsQ0FBQyx3QkFBd0IsQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUN6QyxDQUFDLHNCQUFzQixDQUFDLHFCQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FDOUMsQ0FBQztJQUNGLE1BQU0sb0JBQW9CLEdBQUcsdUJBQVMsQ0FBQyxtQkFBbUIsQ0FBQztRQUN6RCxXQUFXLEVBQUUsRUFBRTtRQUNmLGlCQUFpQixFQUFFLENBQUMsa0JBQWtCLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDN0QsQ0FBQyxDQUFDO0lBQ0gsWUFBWSxDQUFDLHNCQUFzQixDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFFMUQsT0FBTztRQUNMLFFBQVEsRUFBRSxvQkFBb0I7S0FDL0IsQ0FBQztBQUNKLENBQUM7QUFDRCxhQUFhIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcHJldHRpZXJcbiAqL1xuXG5pbXBvcnQge1xuICBjb21tb24sXG4gIEVkMjU1MTlCSVAzMixcbiAgRWRkc2EsXG4gIEVjZHNhLFxuICBIRFRyZWUsXG4gIFNpZ25hdHVyZVNoYXJlVHlwZSxcbiAgU2hhcmVLZXlQb3NpdGlvbixcbiAgVHhSZXF1ZXN0LFxuICBTaWduYXR1cmVTaGFyZVJlY29yZCxcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IEhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgVGVzdEJpdEdvLCBUZXN0Qml0R29BUEkgfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0ICogYXMgc2hvdWxkIGZyb20gJ3Nob3VsZCc7XG5pbXBvcnQgKiBhcyBzaW5vbiBmcm9tICdzaW5vbic7XG5pbXBvcnQge1xuICBFY2RzYVBhaWxsaWVyUHJvb2YsXG4gIEVjZHNhVHlwZXMsXG4gIGhleFRvQmlnSW50LFxuICBEa2xzVXRpbHMsXG4gIERrbHNUeXBlcyxcbiAgRGtsc0NvbW1zLFxuICBEa2xzRHNnLFxufSBmcm9tICdAYml0Z28vc2RrLWxpYi1tcGMnO1xuaW1wb3J0IHtcbiAgTVBDdjJQYXJ0eUZyb21TdHJpbmdPck51bWJlcixcbiAgTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMUlucHV0LFxuICBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxT3V0cHV0LFxuICBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQySW5wdXQsXG4gIE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJPdXRwdXQsXG4gIE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDNJbnB1dCxcbn0gZnJvbSAnQGJpdGdvL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcbmltcG9ydCAqIGFzIG5vY2sgZnJvbSAnbm9jayc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuXG5pbXBvcnQgJ3Nob3VsZC1odHRwJztcbmltcG9ydCAnc2hvdWxkLXNpbm9uJztcbmltcG9ydCAnLi4vLi4vbGliL2Fzc2VydHMnO1xuXG5pbXBvcnQgeyBoYW5kbGVWMkdlbmVyYXRlU2hhcmVUU1MsIGhhbmRsZVYyU2lnbiB9IGZyb20gJy4uLy4uLy4uL3NyYy9jbGllbnRSb3V0ZXMnO1xuaW1wb3J0IHsgZmV0Y2hLZXlzIH0gZnJvbSAnLi4vLi4vLi4vc3JjL2ZldGNoRW5jcnlwdGVkUHJpdktleXMnO1xuaW1wb3J0IHsgbW9ja0NoYWxsZW5nZUEsIG1vY2tDaGFsbGVuZ2VCIH0gZnJvbSAnLi9tb2Nrcy9lY2RzYU50aWxkZSc7XG5pbXBvcnQgeyBDb2luLCBCaXRHbywgU2lnbmVkVHJhbnNhY3Rpb24gfSBmcm9tICdiaXRnbyc7XG5pbXBvcnQgeyBrZXlTaGFyZU9uZUVjZHNhLCBrZXlTaGFyZVR3b0VjZHNhLCBrZXlTaGFyZVRocmVlRWNkc2EgfSBmcm9tICcuL21vY2tzL2tleVNoYXJlcyc7XG5pbXBvcnQgeyBiaXRnb0dwZ0tleSB9IGZyb20gJy4vbW9ja3MvZ3BnS2V5cyc7XG5cbmNvbnN0IGNyZWF0ZUtlY2Nha0hhc2ggPSByZXF1aXJlKCdrZWNjYWsnKTtcbm5vY2sucmVzdG9yZSgpO1xuXG50eXBlIE91dHB1dCA9IHtcbiAgW2tleTogc3RyaW5nXTogc3RyaW5nO1xufTtcblxuZGVzY3JpYmUoJ0V4dGVybmFsIHNpZ25lcicsICgpID0+IHtcbiAgbGV0IGJpdGdvOiBUZXN0Qml0R29BUEk7XG4gIGxldCBiZ1VybDtcbiAgbGV0IE1QQzogRWRkc2E7XG4gIGxldCBtcGNFY2RzYTogRWNkc2E7XG4gIGxldCBoZFRyZWU6IEhEVHJlZTtcblxuICBjb25zdCB3YWxsZXRJZCA9ICc2MWYwMzlhYWQ1ODdjMjAwMDc0NWM2ODczNzNlMGZhOSc7XG4gIGNvbnN0IHdhbGxldFBhc3N3b3JkID0gJ3dEWDA1OCVjNHBsTDFAcFAnO1xuICBjb25zdCBzZWNyZXQgPVxuICAgICd4cHJ2OXMyMVpyUUgxNDNLM0V1UFdDQnVxbld4eWRhUVY2ZXQ5aHRRaWdlNEVzd3ZjSEtFek5ta1Ztd1R3S29hZHlIekpZcHB1QURCN1VzN0FiYU5MVG9Odm9Gb1N4dVdxbmRRUll0bk55NURVWTInO1xuICBjb25zdCB2YWxpZFBydiA9XG4gICAgJ3tcIjYxZjAzOWFhZDU4N2MyMDAwNzQ1YzY4NzM3M2UwZmE5XCI6XCJ7XFxcXFwiaXZcXFxcXCI6XFxcXFwiKzF1MVk5Y3ZzWXVSTWV5SDJzbG5YUT09XFxcXFwiLFxcXFxcInZcXFxcXCI6MSxcXFxcXCJpdGVyXFxcXFwiOjEwMDAwLFxcXFxcImtzXFxcXFwiOjI1NixcXFxcXCJ0c1xcXFxcIjo2NCxcXFxcXCJtb2RlXFxcXFwiOlxcXFxcImNjbVxcXFxcIixcXFxcXCJhZGF0YVxcXFxcIjpcXFxcXCJcXFxcXCIsXFxcXFwiY2lwaGVyXFxcXFwiOlxcXFxcImFlc1xcXFxcIixcXFxcXCJzYWx0XFxcXFwiOlxcXFxcIjU0a09YVHFKOW1jPVxcXFxcIixcXFxcXCJjdFxcXFxcIjpcXFxcXCJKRjV3UTgyd2ExZFl5RnhGbGJIQ3ZLNGErQTZNVEhkaE9xYzV1WHN6MmljV2hrWTJMaW4vM0FiOFp3dndEYVIxSllLbUMvZzFnWElHd1ZaRU9sMU0vYlJIWTQyMGg3c0R0bVRTNkVic2U1TldiRjBJdGZVSmxrNkhWQVRHYStDNm1rYmFWeEo0a1FXL2VoblQzcmlxelUwNjlBVFB6OEU9XFxcXFwifVwifSc7XG5cbiAgYmVmb3JlKGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIW5vY2suaXNBY3RpdmUoKSkge1xuICAgICAgbm9jay5hY3RpdmF0ZSgpO1xuICAgIH1cblxuICAgIGJpdGdvID0gVGVzdEJpdEdvLmRlY29yYXRlKEJpdEdvLCB7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGJpdGdvLmluaXRpYWxpemVUZXN0VmFycygpO1xuXG4gICAgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG4gICAgaGRUcmVlID0gYXdhaXQgRWQyNTUxOUJJUDMyLmluaXRpYWxpemUoKTtcbiAgICBNUEMgPSBhd2FpdCBFZGRzYS5pbml0aWFsaXplKGhkVHJlZSk7XG4gICAgbXBjRWNkc2EgPSBuZXcgRWNkc2EoKTtcblxuICAgIGNvbnN0IGNvbnN0YW50cyA9IHtcbiAgICAgIG1wYzoge1xuICAgICAgICBiaXRnb1B1YmxpY0tleTogYml0Z29HcGdLZXkucHVibGljLFxuICAgICAgICBiaXRnb01QQ3YyUHVibGljS2V5OiBiaXRnb0dwZ0tleS5wdWJsaWMsXG4gICAgICB9LFxuICAgIH07XG5cbiAgICBub2NrKGJnVXJsKS5nZXQoJy9hcGkvdjEvY2xpZW50L2NvbnN0YW50cycpLnRpbWVzKDEwKS5yZXBseSgyMDAsIHsgdHRsOiAzNjAwLCBjb25zdGFudHMgfSk7XG4gIH0pO1xuXG4gIGFmdGVyKCgpID0+IHtcbiAgICBpZiAobm9jay5pc0FjdGl2ZSgpKSB7XG4gICAgICBub2NrLnJlc3RvcmUoKTtcbiAgICB9XG4gIH0pO1xuXG4gIGl0KCdzaG91bGQgcmVhZCBhbiBlbmNyeXB0ZWQgcHJ2IGZyb20gc2lnbmVyRmlsZVN5c3RlbVBhdGggYW5kIHBhc3MgaXQgdG8gY29pbi5zaWduVHJhbnNhY3Rpb24nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVhZEZpbGVTdHViID0gc2lub24uc3R1Yihmcy5wcm9taXNlcywgJ3JlYWRGaWxlJykucmVzb2x2ZXModmFsaWRQcnYpO1xuICAgIGNvbnN0IGVudlN0dWIgPSBzaW5vblxuICAgICAgLnN0dWIocHJvY2VzcywgJ2VudicpXG4gICAgICAudmFsdWUoeyBXQUxMRVRfNjFmMDM5YWFkNTg3YzIwMDA3NDVjNjg3MzczZTBmYTlfUEFTU1BIUkFTRTogd2FsbGV0UGFzc3dvcmQgfSk7XG4gICAgY29uc3Qgc2lnblRyYW5zYWN0aW9uU3R1YiA9IHNpbm9uXG4gICAgICAuc3R1YihDb2luLkJ0Yy5wcm90b3R5cGUsICdzaWduVHJhbnNhY3Rpb24nKVxuICAgICAgLnJlc29sdmVzKHsgdHhIZXg6ICdzaWduZWRUeCcsIHR4UmVxdWVzdElkOiAnJyB9IGFzIFNpZ25lZFRyYW5zYWN0aW9uKTtcblxuICAgIGNvbnN0IHJlcSA9IHtcbiAgICAgIGJpdGdvOiBiaXRnbyxcbiAgICAgIGJvZHk6IHtcbiAgICAgICAgdHhQcmVidWlsZDoge1xuICAgICAgICAgIHdhbGxldElkOiB3YWxsZXRJZCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBwYXJhbXM6IHtcbiAgICAgICAgY29pbjogJ3RidGMnLFxuICAgICAgfSxcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBzaWduZXJGaWxlU3lzdGVtUGF0aDogJ3NpZ25lckZpbGVTeXN0ZW1QYXRoJyxcbiAgICAgIH0sXG4gICAgfSBhcyB1bmtub3duIGFzIGV4cHJlc3MuUmVxdWVzdDtcblxuICAgIGF3YWl0IGhhbmRsZVYyU2lnbihyZXEpO1xuXG4gICAgcmVhZEZpbGVTdHViLmNhbGxlZE9uY2VXaXRoKCdzaWduZXJGaWxlU3lzdGVtUGF0aCcpLnNob3VsZC5iZS50cnVlKCk7XG4gICAgc2lnblRyYW5zYWN0aW9uU3R1YlxuICAgICAgLmNhbGxlZE9uY2VXaXRoKFxuICAgICAgICBzaW5vbi5tYXRjaCh7XG4gICAgICAgICAgcHJ2OiBzZWNyZXQsXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuc2hvdWxkLmJlLnRydWUoKTtcbiAgICByZWFkRmlsZVN0dWIucmVzdG9yZSgpO1xuICAgIHNpZ25UcmFuc2FjdGlvblN0dWIucmVzdG9yZSgpO1xuICAgIGVudlN0dWIucmVzdG9yZSgpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlYWQgYW4gZW5jcnlwdGVkIHBydiBmcm9tIHNpZ25lckZpbGVTeXN0ZW1QYXRoIGFuZCBwYXNzIGl0IHRvIFBhaWxsaWVyTW9kdWx1cywgSywgTXVEZWx0YSwgYW5kIFMgc2hhcmUgZ2VuZXJhdG9ycycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB3YWxsZXRJRCA9ICc2MmZlNTM2YTZiNGNmNzAwMDdhY2I0OGMwZTdiYjBiMCc7XG4gICAgY29uc3QgdXNlciA9IGtleVNoYXJlT25lRWNkc2E7IC8vIGF3YWl0IG1wY0VjZHNhLmtleVNoYXJlKDEsIDIsIDMpO1xuICAgIGNvbnN0IGJhY2t1cCA9IGtleVNoYXJlVHdvRWNkc2E7IC8vIGF3YWl0IG1wY0VjZHNhLmtleVNoYXJlKDIsIDIsIDMpO1xuICAgIGNvbnN0IGJpdGdvID0ga2V5U2hhcmVUaHJlZUVjZHNhOyAvLyBhd2FpdCBtcGNFY2RzYS5rZXlTaGFyZSgzLCAyLCAzKTtcbiAgICBjb25zdCBiaXRnb0NvbWJpbmVkS2V5ID0gYXdhaXQgbXBjRWNkc2Eua2V5Q29tYmluZShiaXRnby5wU2hhcmUsIFtiYWNrdXAublNoYXJlc1szXSwgdXNlci5uU2hhcmVzWzNdXSk7XG4gICAgY29uc3QgdXNlckNoYWxsZW5nZSA9IG1vY2tDaGFsbGVuZ2VBO1xuICAgIGNvbnN0IGJpdGdvQ2hhbGxlbmdlID0gbW9ja0NoYWxsZW5nZUI7XG4gICAgY29uc3QgdXNlclNpZ25pbmdNYXRlcmlhbCA9IHtcbiAgICAgIHBTaGFyZTogdXNlci5wU2hhcmUsXG4gICAgICBiaXRnb05TaGFyZTogYml0Z28ublNoYXJlc1sxXSxcbiAgICAgIGJhY2t1cE5TaGFyZTogYmFja3VwLm5TaGFyZXNbMV0sXG4gICAgfTtcbiAgICBjb25zdCBiZyA9IG5ldyBCaXRHbyh7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuICAgIGNvbnN0IHZhbGlkUHJ2ID0gYmcuZW5jcnlwdCh7IGlucHV0OiBKU09OLnN0cmluZ2lmeSh1c2VyU2lnbmluZ01hdGVyaWFsKSwgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgY29uc3Qgb3V0cHV0OiBPdXRwdXQgPSB7fTtcbiAgICBvdXRwdXRbd2FsbGV0SURdID0gdmFsaWRQcnY7XG4gICAgY29uc3QgcmVhZEZpbGVTdHViID0gc2lub24uc3R1Yihmcy5wcm9taXNlcywgJ3JlYWRGaWxlJykucmVzb2x2ZXMoSlNPTi5zdHJpbmdpZnkob3V0cHV0KSk7XG4gICAgY29uc3QgZW52U3R1YiA9IHNpbm9uXG4gICAgICAuc3R1Yihwcm9jZXNzLCAnZW52JylcbiAgICAgIC52YWx1ZSh7IFdBTExFVF82MmZlNTM2YTZiNGNmNzAwMDdhY2I0OGMwZTdiYjBiMF9QQVNTUEhSQVNFOiB3YWxsZXRQYXNzcGhyYXNlIH0pO1xuICAgIGNvbnN0IHRNZXNzYWdlID0gJ3Rlc3RNZXNzYWdlJztcbiAgICBjb25zdCBiZ1Rlc3QgPSBuZXcgQml0R28oeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICcnO1xuICAgIGNvbnN0IHJlcVBhaWxsaWVyTW9kdWx1cyA9IHtcbiAgICAgIGJpdGdvOiBiZ1Rlc3QsXG4gICAgICBib2R5OiB7XG4gICAgICAgIHR4UmVxdWVzdDoge1xuICAgICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgICAgICB3YWxsZXRJZDogd2FsbGV0SUQsXG4gICAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHVuc2lnbmVkVHg6IHtcbiAgICAgICAgICAgICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgICAgICAgICBzaWduYWJsZUhleDogdE1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIGNvaW46ICd0YnNjJyxcbiAgICAgICAgc2hhcmV0eXBlOiAnUGFpbGxpZXJNb2R1bHVzJyxcbiAgICAgIH0sXG4gICAgICBjb25maWc6IHtcbiAgICAgICAgc2lnbmVyRmlsZVN5c3RlbVBhdGg6ICdzaWduZXJGaWxlU3lzdGVtUGF0aCcsXG4gICAgICB9LFxuICAgIH0gYXMgdW5rbm93biBhcyBleHByZXNzLlJlcXVlc3Q7XG4gICAgY29uc3QgcGFpbGxpZXJSZXN1bHQgPSBhd2FpdCBoYW5kbGVWMkdlbmVyYXRlU2hhcmVUU1MocmVxUGFpbGxpZXJNb2R1bHVzKTtcbiAgICBwYWlsbGllclJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndXNlclBhaWxsaWVyTW9kdWx1cycpO1xuICAgIGNvbnN0IHVzZXJQYWlsbGllck1vZHVsdXMgPSBwYWlsbGllclJlc3VsdC51c2VyUGFpbGxpZXJNb2R1bHVzO1xuICAgIGNvbnN0IFtiaXRnb1RvVXNlclBhaWxsaWVyQ2hhbGxlbmdlLCB1c2VyVG9CaXRnb1BhaWxsaWVyQ2hhbGxlbmdlXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIEVjZHNhUGFpbGxpZXJQcm9vZi5nZW5lcmF0ZVAoaGV4VG9CaWdJbnQodXNlclBhaWxsaWVyTW9kdWx1cykpLFxuICAgICAgRWNkc2FQYWlsbGllclByb29mLmdlbmVyYXRlUChoZXhUb0JpZ0ludChiaXRnb0NvbWJpbmVkS2V5LnlTaGFyZXNbMV0ubikpLFxuICAgIF0pO1xuICAgIGNvbnN0IHJlcUsgPSB7XG4gICAgICBiaXRnbzogYmdUZXN0LFxuICAgICAgYm9keToge1xuICAgICAgICB0c3NQYXJhbXM6IHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IHtcbiAgICAgICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgICAgICAgIHdhbGxldElkOiB3YWxsZXRJRCxcbiAgICAgICAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICAgICAgICAgICAgICBzaWduYWJsZUhleDogdE1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgY2hhbGxlbmdlczoge1xuICAgICAgICAgIGVudGVycHJpc2VDaGFsbGVuZ2U6IHtcbiAgICAgICAgICAgIG50aWxkZTogdXNlckNoYWxsZW5nZS5udGlsZGUsXG4gICAgICAgICAgICBoMTogdXNlckNoYWxsZW5nZS5oMSxcbiAgICAgICAgICAgIGgyOiB1c2VyQ2hhbGxlbmdlLmgyLFxuICAgICAgICAgICAgcDogRWNkc2FUeXBlcy5zZXJpYWxpemVQYWlsbGllckNoYWxsZW5nZSh7IHA6IHVzZXJUb0JpdGdvUGFpbGxpZXJDaGFsbGVuZ2UgfSkucCxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGJpdGdvQ2hhbGxlbmdlOiB7XG4gICAgICAgICAgICBudGlsZGU6IGJpdGdvQ2hhbGxlbmdlLm50aWxkZSxcbiAgICAgICAgICAgIGgxOiBiaXRnb0NoYWxsZW5nZS5oMSxcbiAgICAgICAgICAgIGgyOiBiaXRnb0NoYWxsZW5nZS5oMixcbiAgICAgICAgICAgIHA6IEVjZHNhVHlwZXMuc2VyaWFsaXplUGFpbGxpZXJDaGFsbGVuZ2UoeyBwOiBiaXRnb1RvVXNlclBhaWxsaWVyQ2hhbGxlbmdlIH0pLnAsXG4gICAgICAgICAgICBuOiBiaXRnby5wU2hhcmUubixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICByZXF1ZXN0VHlwZTogMCxcbiAgICAgIH0sXG4gICAgICBwYXJhbXM6IHtcbiAgICAgICAgY29pbjogJ3Ric2MnLFxuICAgICAgICBzaGFyZXR5cGU6ICdLJyxcbiAgICAgIH0sXG4gICAgICBjb25maWc6IHtcbiAgICAgICAgc2lnbmVyRmlsZVN5c3RlbVBhdGg6ICdzaWduZXJGaWxlU3lzdGVtUGF0aCcsXG4gICAgICB9LFxuICAgIH0gYXMgdW5rbm93biBhcyBleHByZXNzLlJlcXVlc3Q7XG4gICAgY29uc3Qga1Jlc3VsdCA9IGF3YWl0IGhhbmRsZVYyR2VuZXJhdGVTaGFyZVRTUyhyZXFLKTtcbiAgICBrUmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdrU2hhcmUnKTtcbiAgICBrUmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCd3U2hhcmUnKTtcbiAgICBjb25zdCBhU2hhcmVGcm9tQml0Z28gPSBhd2FpdCBtcGNFY2RzYS5zaWduQ29udmVydFN0ZXAxKHtcbiAgICAgIHhTaGFyZTogbXBjRWNkc2EuYXBwZW5kQ2hhbGxlbmdlKFxuICAgICAgICBiaXRnb0NvbWJpbmVkS2V5LnhTaGFyZSxcbiAgICAgICAgYml0Z29DaGFsbGVuZ2UsXG4gICAgICAgIEVjZHNhVHlwZXMuc2VyaWFsaXplUGFpbGxpZXJDaGFsbGVuZ2UoeyBwOiBiaXRnb1RvVXNlclBhaWxsaWVyQ2hhbGxlbmdlIH0pXG4gICAgICApLFxuICAgICAgeVNoYXJlOiBiaXRnb0NvbWJpbmVkS2V5LnlTaGFyZXNbMV0sXG4gICAgICBrU2hhcmU6IGtSZXN1bHQua1NoYXJlLFxuICAgIH0pO1xuICAgIGNvbnN0IHJlcU11RGVsdGEgPSB7XG4gICAgICBiaXRnbzogYmdUZXN0LFxuICAgICAgYm9keToge1xuICAgICAgICB0eFJlcXVlc3Q6IHtcbiAgICAgICAgICBhcGlWZXJzaW9uOiAnZnVsbCcsXG4gICAgICAgICAgd2FsbGV0SWQ6IHdhbGxldElELFxuICAgICAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB1bnNpZ25lZFR4OiB7XG4gICAgICAgICAgICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICAgICAgICAgICAgc2lnbmFibGVIZXg6IHRNZXNzYWdlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgICBhU2hhcmVGcm9tQml0Z286IGFTaGFyZUZyb21CaXRnby5hU2hhcmUsXG4gICAgICAgIGJpdGdvQ2hhbGxlbmdlOiB7XG4gICAgICAgICAgbnRpbGRlOiBiaXRnb0NoYWxsZW5nZS5udGlsZGUsXG4gICAgICAgICAgaDE6IGJpdGdvQ2hhbGxlbmdlLmgxLFxuICAgICAgICAgIGgyOiBiaXRnb0NoYWxsZW5nZS5oMixcbiAgICAgICAgICBwOiBFY2RzYVR5cGVzLnNlcmlhbGl6ZVBhaWxsaWVyQ2hhbGxlbmdlKHsgcDogYml0Z29Ub1VzZXJQYWlsbGllckNoYWxsZW5nZSB9KS5wLFxuICAgICAgICAgIG46IGJpdGdvLnBTaGFyZS5uLFxuICAgICAgICB9LFxuICAgICAgICBlbmNyeXB0ZWRXU2hhcmU6IGtSZXN1bHQud1NoYXJlLFxuICAgICAgfSxcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBjb2luOiAndGJzYycsXG4gICAgICAgIHNoYXJldHlwZTogJ011RGVsdGEnLFxuICAgICAgfSxcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBzaWduZXJGaWxlU3lzdGVtUGF0aDogJ3NpZ25lckZpbGVTeXN0ZW1QYXRoJyxcbiAgICAgIH0sXG4gICAgfSBhcyB1bmtub3duIGFzIGV4cHJlc3MuUmVxdWVzdDtcbiAgICBjb25zdCBtdURlbHRhUmVzdWx0ID0gYXdhaXQgaGFuZGxlVjJHZW5lcmF0ZVNoYXJlVFNTKHJlcU11RGVsdGEpO1xuICAgIG11RGVsdGFSZXN1bHQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ211RFNoYXJlJyk7XG4gICAgbXVEZWx0YVJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnb1NoYXJlJyk7XG4gICAgY29uc3QgYml0Z29HU2hhcmUgPSBhd2FpdCBtcGNFY2RzYS5zaWduQ29udmVydFN0ZXAzKHtcbiAgICAgIGJTaGFyZTogYVNoYXJlRnJvbUJpdGdvLmJTaGFyZSxcbiAgICAgIG11U2hhcmU6IG11RGVsdGFSZXN1bHQubXVEU2hhcmUubXVTaGFyZSxcbiAgICB9KTtcbiAgICBjb25zdCBiaXRnb0RTaGFyZSA9IG1wY0VjZHNhLnNpZ25Db21iaW5lKHtcbiAgICAgIGdTaGFyZTogYml0Z29HU2hhcmUuZ1NoYXJlLFxuICAgICAgc2lnbkluZGV4OiB7XG4gICAgICAgIGk6IDEsXG4gICAgICAgIGo6IDMsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGNvbnN0IHJlcVMgPSB7XG4gICAgICBiaXRnbzogYmdUZXN0LFxuICAgICAgYm9keToge1xuICAgICAgICB0c3NQYXJhbXM6IHtcbiAgICAgICAgICB0eFJlcXVlc3Q6IHtcbiAgICAgICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgICAgICAgIHdhbGxldElkOiB3YWxsZXRJRCxcbiAgICAgICAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgICAgICAgZGVyaXZhdGlvblBhdGgsXG4gICAgICAgICAgICAgICAgICBzaWduYWJsZUhleDogdE1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgZFNoYXJlRnJvbUJpdGdvOiBiaXRnb0RTaGFyZS5kU2hhcmUsXG4gICAgICAgIHJlcXVlc3RUeXBlOiAwLFxuICAgICAgICBlbmNyeXB0ZWRPU2hhcmU6IG11RGVsdGFSZXN1bHQub1NoYXJlLFxuICAgICAgfSxcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBjb2luOiAndGJzYycsXG4gICAgICAgIHNoYXJldHlwZTogJ1MnLFxuICAgICAgfSxcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBzaWduZXJGaWxlU3lzdGVtUGF0aDogJ3NpZ25lckZpbGVTeXN0ZW1QYXRoJyxcbiAgICAgIH0sXG4gICAgfSBhcyB1bmtub3duIGFzIGV4cHJlc3MuUmVxdWVzdDtcbiAgICBjb25zdCBzUmVzdWx0ID0gYXdhaXQgaGFuZGxlVjJHZW5lcmF0ZVNoYXJlVFNTKHJlcVMpO1xuICAgIHNSZXN1bHQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ1InKTtcbiAgICBzUmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzJyk7XG4gICAgc1Jlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgneScpO1xuICAgIGNvbnN0IGJpdEdvU1NoYXJlID0gbXBjRWNkc2Euc2lnbihcbiAgICAgIEJ1ZmZlci5mcm9tKHRNZXNzYWdlLCAnaGV4JyksXG4gICAgICBiaXRnb0RTaGFyZS5vU2hhcmUsXG4gICAgICBtdURlbHRhUmVzdWx0Lm11RFNoYXJlLmRTaGFyZSxcbiAgICAgIGNyZWF0ZUtlY2Nha0hhc2goJ2tlY2NhazI1NicpIGFzIEhhc2hcbiAgICApO1xuICAgIGNvbnN0IHNpZ25hdHVyZSA9IG1wY0VjZHNhLmNvbnN0cnVjdFNpZ25hdHVyZShbYml0R29TU2hhcmUsIHNSZXN1bHRdKTtcbiAgICBtcGNFY2RzYS52ZXJpZnkoQnVmZmVyLmZyb20odE1lc3NhZ2UsICdoZXgnKSwgc2lnbmF0dXJlLCBjcmVhdGVLZWNjYWtIYXNoKCdrZWNjYWsyNTYnKSBhcyBIYXNoKS5zaG91bGQuYmUudHJ1ZTtcbiAgICByZWFkRmlsZVN0dWIucmVzdG9yZSgpO1xuICAgIGVudlN0dWIucmVzdG9yZSgpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIHJlYWQgYW4gZW5jcnlwdGVkIHBydiBmcm9tIHNpZ25lckZpbGVTeXN0ZW1QYXRoIGFuZCBwYXNzIGl0IHRvIGNvbW1pdG1lbnQsIFIgYW5kIEcgc2hhcmUgZ2VuZXJhdG9ycycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB3YWxsZXRJRCA9ICc2MmZlNTM2YTZiNGNmNzAwMDdhY2I0OGMwZTdiYjBiMCc7XG4gICAgY29uc3QgdXNlciA9IE1QQy5rZXlTaGFyZSgxLCAyLCAzKTtcbiAgICBjb25zdCBiYWNrdXAgPSBNUEMua2V5U2hhcmUoMiwgMiwgMyk7XG4gICAgY29uc3QgYml0Z28gPSBNUEMua2V5U2hhcmUoMywgMiwgMyk7XG4gICAgY29uc3QgdXNlclNpZ25pbmdNYXRlcmlhbCA9IHtcbiAgICAgIHVTaGFyZTogdXNlci51U2hhcmUsXG4gICAgICBiaXRnb1lTaGFyZTogYml0Z28ueVNoYXJlc1sxXSxcbiAgICAgIGJhY2t1cFlTaGFyZTogYmFja3VwLnlTaGFyZXNbMV0sXG4gICAgfTtcbiAgICBjb25zdCBiZyA9IG5ldyBCaXRHbyh7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuICAgIGNvbnN0IHZhbGlkUHJ2ID0gYmcuZW5jcnlwdCh7IGlucHV0OiBKU09OLnN0cmluZ2lmeSh1c2VyU2lnbmluZ01hdGVyaWFsKSwgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgY29uc3Qgb3V0cHV0OiBPdXRwdXQgPSB7fTtcbiAgICBvdXRwdXRbd2FsbGV0SURdID0gdmFsaWRQcnY7XG4gICAgY29uc3QgcmVhZEZpbGVTdHViID0gc2lub24uc3R1Yihmcy5wcm9taXNlcywgJ3JlYWRGaWxlJykucmVzb2x2ZXMoSlNPTi5zdHJpbmdpZnkob3V0cHV0KSk7XG4gICAgY29uc3QgZW52U3R1YiA9IHNpbm9uXG4gICAgICAuc3R1Yihwcm9jZXNzLCAnZW52JylcbiAgICAgIC52YWx1ZSh7IFdBTExFVF82MmZlNTM2YTZiNGNmNzAwMDdhY2I0OGMwZTdiYjBiMF9QQVNTUEhSQVNFOiB3YWxsZXRQYXNzcGhyYXNlIH0pO1xuICAgIGNvbnN0IHRNZXNzYWdlID0gJ3Rlc3RNZXNzYWdlJztcbiAgICBjb25zdCBiZ1Rlc3QgPSBuZXcgQml0R28oeyBlbnY6ICd0ZXN0JyB9KTtcbiAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzAnO1xuXG4gICAgY29uc3QgcmVxQ29tbWl0bWVudCA9IHtcbiAgICAgIGJpdGdvOiBiZ1Rlc3QsXG4gICAgICBib2R5OiB7XG4gICAgICAgIGJpdGdvR3BnUHViS2V5OiBiaXRnb0dwZ0tleS5wdWJsaWMsXG4gICAgICAgIHR4UmVxdWVzdDoge1xuICAgICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgICAgICB3YWxsZXRJZDogd2FsbGV0SUQsXG4gICAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHVuc2lnbmVkVHg6IHtcbiAgICAgICAgICAgICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgICAgICAgICBzaWduYWJsZUhleDogdE1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgICAgc2hhcmV0eXBlOiAnY29tbWl0bWVudCcsXG4gICAgICB9LFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIHNpZ25lckZpbGVTeXN0ZW1QYXRoOiAnc2lnbmVyRmlsZVN5c3RlbVBhdGgnLFxuICAgICAgfSxcbiAgICB9IGFzIHVua25vd24gYXMgZXhwcmVzcy5SZXF1ZXN0O1xuICAgIGNvbnN0IGNSZXN1bHQgPSBhd2FpdCBoYW5kbGVWMkdlbmVyYXRlU2hhcmVUU1MocmVxQ29tbWl0bWVudCk7XG4gICAgY1Jlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgndXNlclRvQml0Z29Db21taXRtZW50Jyk7XG4gICAgY1Jlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZW5jcnlwdGVkU2lnbmVyU2hhcmUnKTtcbiAgICBjUmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdlbmNyeXB0ZWRVc2VyVG9CaXRnb1JTaGFyZScpO1xuICAgIGNvbnN0IGVuY3J5cHRlZFVzZXJUb0JpdGdvUlNoYXJlID0gY1Jlc3VsdC5lbmNyeXB0ZWRVc2VyVG9CaXRnb1JTaGFyZTtcbiAgICBjb25zdCByZXFSID0ge1xuICAgICAgYml0Z286IGJnVGVzdCxcbiAgICAgIGJvZHk6IHtcbiAgICAgICAgdHhSZXF1ZXN0OiB7XG4gICAgICAgICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgICAgICAgIHdhbGxldElkOiB3YWxsZXRJRCxcbiAgICAgICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgICAgIGRlcml2YXRpb25QYXRoLFxuICAgICAgICAgICAgICAgIHNpZ25hYmxlSGV4OiB0TWVzc2FnZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgICAgZW5jcnlwdGVkVXNlclRvQml0Z29SU2hhcmUsXG4gICAgICB9LFxuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIGNvaW46ICd0c29sJyxcbiAgICAgICAgc2hhcmV0eXBlOiAnUicsXG4gICAgICB9LFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIHNpZ25lckZpbGVTeXN0ZW1QYXRoOiAnc2lnbmVyRmlsZVN5c3RlbVBhdGgnLFxuICAgICAgfSxcbiAgICB9IGFzIHVua25vd24gYXMgZXhwcmVzcy5SZXF1ZXN0O1xuICAgIGNvbnN0IHJSZXN1bHQgPSBhd2FpdCBoYW5kbGVWMkdlbmVyYXRlU2hhcmVUU1MocmVxUik7XG4gICAgclJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnclNoYXJlJyk7XG5cbiAgICBjb25zdCBzaWduaW5nS2V5ID0gTVBDLmtleURlcml2ZShcbiAgICAgIHVzZXJTaWduaW5nTWF0ZXJpYWwudVNoYXJlLFxuICAgICAgW3VzZXJTaWduaW5nTWF0ZXJpYWwuYml0Z29ZU2hhcmUsIHVzZXJTaWduaW5nTWF0ZXJpYWwuYmFja3VwWVNoYXJlXSxcbiAgICAgIGRlcml2YXRpb25QYXRoXG4gICAgKTtcblxuICAgIGNvbnN0IGJpdGdvQ29tYmluZSA9IE1QQy5rZXlDb21iaW5lKGJpdGdvLnVTaGFyZSwgW3NpZ25pbmdLZXkueVNoYXJlc1szXSwgYmFja3VwLnlTaGFyZXNbM11dKTtcbiAgICBjb25zdCBiaXRnb1NpZ25TaGFyZSA9IGF3YWl0IE1QQy5zaWduU2hhcmUoQnVmZmVyLmZyb20odE1lc3NhZ2UsICdoZXgnKSwgYml0Z29Db21iaW5lLnBTaGFyZSwgW1xuICAgICAgYml0Z29Db21iaW5lLmpTaGFyZXNbMV0sXG4gICAgXSk7XG4gICAgY29uc3Qgc2lnbmF0dXJlU2hhcmVSZWMgPSB7XG4gICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICBzaGFyZTogYml0Z29TaWduU2hhcmUuclNoYXJlc1sxXS5yICsgYml0Z29TaWduU2hhcmUuclNoYXJlc1sxXS5SLFxuICAgIH07XG4gICAgY29uc3QgYml0Z29Ub1VzZXJDb21taXRtZW50U2hhcmUgPSB7XG4gICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgICBzaGFyZTogYml0Z29TaWduU2hhcmUuclNoYXJlc1sxXS5jb21taXRtZW50LFxuICAgICAgdHlwZTogJ2NvbW1pdG1lbnQnLFxuICAgIH07XG4gICAgY29uc3QgcmVxRyA9IHtcbiAgICAgIGJpdGdvOiBiZ1Rlc3QsXG4gICAgICBib2R5OiB7XG4gICAgICAgIHR4UmVxdWVzdDoge1xuICAgICAgICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgICAgICAgICB3YWxsZXRJZDogd2FsbGV0SUQsXG4gICAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHVuc2lnbmVkVHg6IHtcbiAgICAgICAgICAgICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgICAgICAgICAgICBzaWduYWJsZUhleDogdE1lc3NhZ2UsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICAgIHVzZXJUb0JpdGdvUlNoYXJlOiByUmVzdWx0LnJTaGFyZSxcbiAgICAgICAgYml0Z29Ub1VzZXJSU2hhcmU6IHNpZ25hdHVyZVNoYXJlUmVjLFxuICAgICAgICBiaXRnb1RvVXNlckNvbW1pdG1lbnQ6IGJpdGdvVG9Vc2VyQ29tbWl0bWVudFNoYXJlLFxuICAgICAgfSxcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBjb2luOiAndHNvbCcsXG4gICAgICAgIHNoYXJldHlwZTogJ0cnLFxuICAgICAgfSxcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBzaWduZXJGaWxlU3lzdGVtUGF0aDogJ3NpZ25lckZpbGVTeXN0ZW1QYXRoJyxcbiAgICAgIH0sXG4gICAgfSBhcyB1bmtub3duIGFzIGV4cHJlc3MuUmVxdWVzdDtcbiAgICBjb25zdCB1c2VyR1NoYXJlID0gYXdhaXQgaGFuZGxlVjJHZW5lcmF0ZVNoYXJlVFNTKHJlcUcpO1xuICAgIHVzZXJHU2hhcmUuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2knKTtcbiAgICB1c2VyR1NoYXJlLnNob3VsZC5oYXZlLnByb3BlcnR5KCd5Jyk7XG4gICAgdXNlckdTaGFyZS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZ2FtbWEnKTtcbiAgICB1c2VyR1NoYXJlLnNob3VsZC5oYXZlLnByb3BlcnR5KCdSJyk7XG4gICAgY29uc3QgdXNlclRvQml0Z29SU2hhcmUgPSB7XG4gICAgICBpOiBTaGFyZUtleVBvc2l0aW9uLkJJVEdPLFxuICAgICAgajogU2hhcmVLZXlQb3NpdGlvbi5VU0VSLFxuICAgICAgdTogc2lnbmluZ0tleS55U2hhcmVzWzNdLnUsXG4gICAgICB2OiByUmVzdWx0LnJTaGFyZS5yU2hhcmVzWzNdLnYsXG4gICAgICByOiByUmVzdWx0LnJTaGFyZS5yU2hhcmVzWzNdLnIsXG4gICAgICBSOiByUmVzdWx0LnJTaGFyZS5yU2hhcmVzWzNdLlIsXG4gICAgICBjb21taXRtZW50OiByUmVzdWx0LnJTaGFyZS5yU2hhcmVzWzNdLmNvbW1pdG1lbnQsXG4gICAgfTtcbiAgICBjb25zdCBiaXRnb0dTaGFyZSA9IE1QQy5zaWduKFxuICAgICAgQnVmZmVyLmZyb20odE1lc3NhZ2UsICdoZXgnKSxcbiAgICAgIGJpdGdvU2lnblNoYXJlLnhTaGFyZSxcbiAgICAgIFt1c2VyVG9CaXRnb1JTaGFyZV0sXG4gICAgICBbYmFja3VwLnlTaGFyZXNbM11dXG4gICAgKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBNUEMuc2lnbkNvbWJpbmUoW3VzZXJHU2hhcmUsIGJpdGdvR1NoYXJlXSk7XG4gICAgY29uc3QgdmVyaVJlc3VsdCA9IE1QQy52ZXJpZnkoQnVmZmVyLmZyb20odE1lc3NhZ2UsICdoZXgnKSwgc2lnbmF0dXJlKTtcbiAgICB2ZXJpUmVzdWx0LnNob3VsZC5iZS50cnVlKCk7XG4gICAgcmVhZEZpbGVTdHViLnJlc3RvcmUoKTtcbiAgICBlbnZTdHViLnJlc3RvcmUoKTtcbiAgfSk7XG5cbiAgaXQoJ3Nob3VsZCByZWFkIGFuIGVuY3J5cHRlZCBwcnYgZnJvbSBzaWduZXJGaWxlU3lzdGVtUGF0aCBhbmQgcGFzcyBpdCB0byBNUEN2MlJvdW5kMSwgTVBDdjJSb3VuZDIgYW5kIE1QQ3YyUm91bmQzIHNoYXJlIGdlbmVyYXRvcnMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgd2FsbGV0SUQgPSAnNjJmZTUzNmE2YjRjZjcwMDA3YWNiNDhjMGU3YmIwYjAnO1xuICAgIGNvbnN0IHRNZXNzYWdlID0gJ3Rlc3RNZXNzYWdlJztcbiAgICBjb25zdCBkZXJpdmF0aW9uUGF0aCA9ICdtLzAnO1xuICAgIGNvbnN0IHdhbGxldFBhc3NwaHJhc2UgPSAndGVzdFBhc3MnO1xuXG4gICAgY29uc3QgW3VzZXJTaGFyZSwgYmFja3VwU2hhcmUsIGJpdGdvU2hhcmVdID0gYXdhaXQgRGtsc1V0aWxzLmdlbmVyYXRlREtHS2V5U2hhcmVzKCk7XG4gICAgYXNzZXJ0KGJhY2t1cFNoYXJlLCAnYmFja3VwU2hhcmUgaXMgbm90IGRlZmluZWQnKTtcblxuICAgIGNvbnN0IGJnVGVzdCA9IG5ldyBCaXRHbyh7IGVudjogJ3Rlc3QnIH0pO1xuICAgIGNvbnN0IHVzZXJLZXlTaGFyZSA9IHVzZXJTaGFyZS5nZXRLZXlTaGFyZSgpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICBjb25zdCB2YWxpZFBydiA9IGJnVGVzdC5lbmNyeXB0KHsgaW5wdXQ6IHVzZXJLZXlTaGFyZSwgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UgfSk7XG4gICAgY29uc3QgcmVhZEZpbGVTdHViID0gc2lub24uc3R1Yihmcy5wcm9taXNlcywgJ3JlYWRGaWxlJykucmVzb2x2ZXMoSlNPTi5zdHJpbmdpZnkoeyBbd2FsbGV0SURdOiB2YWxpZFBydiB9KSk7XG4gICAgY29uc3QgZW52U3R1YiA9IHNpbm9uLnN0dWIocHJvY2VzcywgJ2VudicpLnZhbHVlKHsgWydXQUxMRVRfJyArIHdhbGxldElEICsgJ19QQVNTUEhSQVNFJ106IHdhbGxldFBhc3NwaHJhc2UgfSk7XG5cbiAgICAvLyByb3VuZCAxXG4gICAgY29uc3QgcmVxTVBDdjJSb3VuZDEgPSB7XG4gICAgICBiaXRnbzogYmdUZXN0LFxuICAgICAgYm9keToge1xuICAgICAgICB0eFJlcXVlc3Q6IHtcbiAgICAgICAgICB0eFJlcXVlc3RJZDogJzEyMzQ1NicsXG4gICAgICAgICAgYXBpVmVyc2lvbjogJ2Z1bGwnLFxuICAgICAgICAgIHdhbGxldElkOiB3YWxsZXRJRCxcbiAgICAgICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdW5zaWduZWRUeDoge1xuICAgICAgICAgICAgICAgIGRlcml2YXRpb25QYXRoLFxuICAgICAgICAgICAgICAgIHNpZ25hYmxlSGV4OiB0TWVzc2FnZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBwYXJhbXM6IHtcbiAgICAgICAgY29pbjogJ2h0ZXRoJyxcbiAgICAgICAgc2hhcmV0eXBlOiAnTVBDdjJSb3VuZDEnLFxuICAgICAgfSxcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBzaWduZXJGaWxlU3lzdGVtUGF0aDogJ3NpZ25lckZpbGVTeXN0ZW1QYXRoJyxcbiAgICAgIH0sXG4gICAgfSBhcyB1bmtub3duIGFzIGV4cHJlc3MuUmVxdWVzdDtcbiAgICBjb25zdCByb3VuZDFSZXN1bHQgPSBhd2FpdCBoYW5kbGVWMkdlbmVyYXRlU2hhcmVUU1MocmVxTVBDdjJSb3VuZDEpO1xuICAgIHJvdW5kMVJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnc2lnbmF0dXJlU2hhcmVSb3VuZDEnKTtcbiAgICByb3VuZDFSZXN1bHQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3VzZXJHcGdQdWJLZXknKTtcbiAgICByb3VuZDFSZXN1bHQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2VuY3J5cHRlZFJvdW5kMVNlc3Npb24nKTtcbiAgICByb3VuZDFSZXN1bHQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2VuY3J5cHRlZFVzZXJHcGdQcnZLZXknKTtcblxuICAgIGNvbnN0IGhhc2hGbiA9IGNyZWF0ZUtlY2Nha0hhc2goJ2tlY2NhazI1NicpIGFzIEhhc2g7XG4gICAgY29uc3QgaGFzaEJ1ZmZlciA9IGhhc2hGbi51cGRhdGUoQnVmZmVyLmZyb20odE1lc3NhZ2UsICdoZXgnKSkuZGlnZXN0KCk7XG4gICAgY29uc3QgYml0Z29TZXNzaW9uID0gbmV3IERrbHNEc2cuRHNnKGJpdGdvU2hhcmUuZ2V0S2V5U2hhcmUoKSwgMiwgZGVyaXZhdGlvblBhdGgsIGhhc2hCdWZmZXIpO1xuXG4gICAgY29uc3QgdHhSZXF1ZXN0Um91bmQxID0gYXdhaXQgc2lnbkJpdGdvTVBDdjJSb3VuZDEoXG4gICAgICBiaXRnb1Nlc3Npb24sXG4gICAgICByZXFNUEN2MlJvdW5kMS5ib2R5LnR4UmVxdWVzdCxcbiAgICAgIHJvdW5kMVJlc3VsdC5zaWduYXR1cmVTaGFyZVJvdW5kMSxcbiAgICAgIHJvdW5kMVJlc3VsdC51c2VyR3BnUHViS2V5XG4gICAgKTtcbiAgICBhc3NlcnQoXG4gICAgICB0eFJlcXVlc3RSb3VuZDEudHJhbnNhY3Rpb25zICYmXG4gICAgICAgIHR4UmVxdWVzdFJvdW5kMS50cmFuc2FjdGlvbnMubGVuZ3RoID09PSAxICYmXG4gICAgICAgIHR4UmVxdWVzdFJvdW5kMS50cmFuc2FjdGlvbnNbMF0uc2lnbmF0dXJlU2hhcmVzLmxlbmd0aCA9PT0gMixcbiAgICAgICd0eFJlcXVlc3RSb3VuZDIudHJhbnNhY3Rpb25zIGlzIG5vdCBhbiBhcnJheSBvZiBsZW5ndGggMSB3aXRoIDIgc2lnbmF0dXJlU2hhcmVzJ1xuICAgICk7XG5cbiAgICAvLyByb3VuZCAyXG4gICAgY29uc3QgcmVxTVBDdjJSb3VuZDIgPSB7XG4gICAgICBiaXRnbzogYmdUZXN0LFxuICAgICAgYm9keToge1xuICAgICAgICB0eFJlcXVlc3Q6IHR4UmVxdWVzdFJvdW5kMSxcbiAgICAgICAgZW5jcnlwdGVkUm91bmQxU2Vzc2lvbjogcm91bmQxUmVzdWx0LmVuY3J5cHRlZFJvdW5kMVNlc3Npb24sXG4gICAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHJvdW5kMVJlc3VsdC5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICBiaXRnb1B1YmxpY0dwZ0tleTogYml0Z29HcGdLZXkucHVibGljLFxuICAgICAgfSxcbiAgICAgIHBhcmFtczoge1xuICAgICAgICBjb2luOiAnaHRldGgnLFxuICAgICAgICBzaGFyZXR5cGU6ICdNUEN2MlJvdW5kMicsXG4gICAgICB9LFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIHNpZ25lckZpbGVTeXN0ZW1QYXRoOiAnc2lnbmVyRmlsZVN5c3RlbVBhdGgnLFxuICAgICAgfSxcbiAgICB9IGFzIHVua25vd24gYXMgZXhwcmVzcy5SZXF1ZXN0O1xuICAgIGNvbnN0IHJvdW5kMlJlc3VsdCA9IGF3YWl0IGhhbmRsZVYyR2VuZXJhdGVTaGFyZVRTUyhyZXFNUEN2MlJvdW5kMik7XG4gICAgcm91bmQyUmVzdWx0LnNob3VsZC5oYXZlLnByb3BlcnR5KCdzaWduYXR1cmVTaGFyZVJvdW5kMicpO1xuICAgIHJvdW5kMlJlc3VsdC5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnZW5jcnlwdGVkUm91bmQyU2Vzc2lvbicpO1xuXG4gICAgY29uc3QgeyB0eFJlcXVlc3Q6IHR4UmVxdWVzdFJvdW5kMiwgYml0Z29Nc2c0IH0gPSBhd2FpdCBzaWduQml0Z29NUEN2MlJvdW5kMihcbiAgICAgIGJpdGdvU2Vzc2lvbixcbiAgICAgIHJlcU1QQ3YyUm91bmQyLmJvZHkudHhSZXF1ZXN0LFxuICAgICAgcm91bmQyUmVzdWx0LnNpZ25hdHVyZVNoYXJlUm91bmQyLFxuICAgICAgcm91bmQxUmVzdWx0LnVzZXJHcGdQdWJLZXlcbiAgICApO1xuICAgIGFzc2VydChcbiAgICAgIHR4UmVxdWVzdFJvdW5kMi50cmFuc2FjdGlvbnMgJiZcbiAgICAgICAgdHhSZXF1ZXN0Um91bmQyLnRyYW5zYWN0aW9ucy5sZW5ndGggPT09IDEgJiZcbiAgICAgICAgdHhSZXF1ZXN0Um91bmQyLnRyYW5zYWN0aW9uc1swXS5zaWduYXR1cmVTaGFyZXMubGVuZ3RoID09PSA0LFxuICAgICAgJ3R4UmVxdWVzdFJvdW5kMi50cmFuc2FjdGlvbnMgaXMgbm90IGFuIGFycmF5IG9mIGxlbmd0aCAxIHdpdGggNCBzaWduYXR1cmVTaGFyZXMnXG4gICAgKTtcblxuICAgIC8vIHJvdW5kIDNcbiAgICBjb25zdCByZXFNUEN2MlJvdW5kMyA9IHtcbiAgICAgIGJpdGdvOiBiZ1Rlc3QsXG4gICAgICBib2R5OiB7XG4gICAgICAgIHR4UmVxdWVzdDogdHhSZXF1ZXN0Um91bmQyLFxuICAgICAgICBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uOiByb3VuZDJSZXN1bHQuZW5jcnlwdGVkUm91bmQyU2Vzc2lvbixcbiAgICAgICAgZW5jcnlwdGVkVXNlckdwZ1BydktleTogcm91bmQxUmVzdWx0LmVuY3J5cHRlZFVzZXJHcGdQcnZLZXksXG4gICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleS5wdWJsaWMsXG4gICAgICB9LFxuICAgICAgcGFyYW1zOiB7XG4gICAgICAgIGNvaW46ICdodGV0aCcsXG4gICAgICAgIHNoYXJldHlwZTogJ01QQ3YyUm91bmQzJyxcbiAgICAgIH0sXG4gICAgICBjb25maWc6IHtcbiAgICAgICAgc2lnbmVyRmlsZVN5c3RlbVBhdGg6ICdzaWduZXJGaWxlU3lzdGVtUGF0aCcsXG4gICAgICB9LFxuICAgIH0gYXMgdW5rbm93biBhcyBleHByZXNzLlJlcXVlc3Q7XG4gICAgY29uc3Qgcm91bmQzUmVzdWx0ID0gYXdhaXQgaGFuZGxlVjJHZW5lcmF0ZVNoYXJlVFNTKHJlcU1QQ3YyUm91bmQzKTtcbiAgICByb3VuZDNSZXN1bHQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NpZ25hdHVyZVNoYXJlUm91bmQzJyk7XG5cbiAgICBjb25zdCB7IHVzZXJNc2c0IH0gPSBhd2FpdCBzaWduQml0Z29NUEN2MlJvdW5kMyhcbiAgICAgIGJpdGdvU2Vzc2lvbixcbiAgICAgIHJvdW5kM1Jlc3VsdC5zaWduYXR1cmVTaGFyZVJvdW5kMyxcbiAgICAgIHJvdW5kMVJlc3VsdC51c2VyR3BnUHViS2V5XG4gICAgKTtcblxuICAgIC8vIHNpZ25hdHVyZSBnZW5lcmF0aW9uIGFuZCB2YWxpZGF0aW9uXG4gICAgYXNzZXJ0KHVzZXJNc2c0LmRhdGEubXNnNC5zaWduYXR1cmVSID09PSBiaXRnb01zZzQuc2lnbmF0dXJlUiwgJ1VzZXIgYW5kIEJpdEdvIHNpZ25hdHVyZXNSIGRvIG5vdCBtYXRjaCcpO1xuXG4gICAgY29uc3QgZGVzZXJpYWxpemVkQml0Z29Nc2c0ID0gRGtsc1R5cGVzLmRlc2VyaWFsaXplTWVzc2FnZXMoe1xuICAgICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtiaXRnb01zZzRdLFxuICAgIH0pO1xuXG4gICAgY29uc3QgZGVzZXJpYWxpemVkVXNlck1zZzQgPSBEa2xzVHlwZXMuZGVzZXJpYWxpemVNZXNzYWdlcyh7XG4gICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICBicm9hZGNhc3RNZXNzYWdlczogW1xuICAgICAgICB7XG4gICAgICAgICAgZnJvbTogdXNlck1zZzQuZGF0YS5tc2c0LmZyb20sXG4gICAgICAgICAgcGF5bG9hZDogdXNlck1zZzQuZGF0YS5tc2c0Lm1lc3NhZ2UsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuXG4gICAgY29uc3QgY29tYmluZWRTaWdVc2luZ1V0aWwgPSBEa2xzVXRpbHMuY29tYmluZVBhcnRpYWxTaWduYXR1cmVzKFxuICAgICAgW2Rlc2VyaWFsaXplZFVzZXJNc2c0LmJyb2FkY2FzdE1lc3NhZ2VzWzBdLnBheWxvYWQsIGRlc2VyaWFsaXplZEJpdGdvTXNnNC5icm9hZGNhc3RNZXNzYWdlc1swXS5wYXlsb2FkXSxcbiAgICAgIEJ1ZmZlci5mcm9tKHVzZXJNc2c0LmRhdGEubXNnNC5zaWduYXR1cmVSLCAnYmFzZTY0JykudG9TdHJpbmcoJ2hleCcpXG4gICAgKTtcblxuICAgIGNvbnN0IGNvbnZlcnRlZFNpZ25hdHVyZSA9IERrbHNVdGlscy52ZXJpZnlBbmRDb252ZXJ0RGtsc1NpZ25hdHVyZShcbiAgICAgIEJ1ZmZlci5mcm9tKHRNZXNzYWdlLCAnaGV4JyksXG4gICAgICBjb21iaW5lZFNpZ1VzaW5nVXRpbCxcbiAgICAgIERrbHNUeXBlcy5nZXRDb21tb25LZXljaGFpbih1c2VyU2hhcmUuZ2V0S2V5U2hhcmUoKSksXG4gICAgICBkZXJpdmF0aW9uUGF0aCxcbiAgICAgIGNyZWF0ZUtlY2Nha0hhc2goJ2tlY2NhazI1NicpIGFzIEhhc2hcbiAgICApO1xuICAgIGFzc2VydChjb252ZXJ0ZWRTaWduYXR1cmUsICdTaWduYXR1cmUgaXMgbm90IHZhbGlkJyk7XG4gICAgYXNzZXJ0KGNvbnZlcnRlZFNpZ25hdHVyZS5zcGxpdCgnOicpLmxlbmd0aCA9PT0gNCwgJ1NpZ25hdHVyZSBpcyBub3QgdmFsaWQnKTtcbiAgICByZWFkRmlsZVN0dWIucmVzdG9yZSgpO1xuICAgIGVudlN0dWIucmVzdG9yZSgpO1xuICB9KTtcblxuICBpdCgnc2hvdWxkIGFjY2VwdCBhIGxvY2FsIHNlY3JldCBhbmQgcGFzc3dvcmQgZm9yIGEgd2FsbGV0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGFjY2Vzc1Rva2VuID0gJyc7XG4gICAgY29uc3Qgd2FsbGV0SWRzID0ge1xuICAgICAgdGJ0YzogW1xuICAgICAgICB7XG4gICAgICAgICAgd2FsbGV0SWQsXG4gICAgICAgICAgd2FsbGV0UGFzc3dvcmQsXG4gICAgICAgICAgc2VjcmV0LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuXG4gICAgY29uc3Qgd2FsbGV0UmVzdWx0ID0ge1xuICAgICAgd2FsbGV0SWQsXG4gICAgICBrZXlzOiBbd2FsbGV0SWQsIHdhbGxldElkLCB3YWxsZXRJZF0sXG4gICAgfTtcblxuICAgIGNvbnN0IGtleVJlc3VsdCA9IHtcbiAgICAgIHdhbGxldElkLFxuICAgIH07XG5cbiAgICBub2NrKGJnVXJsKS5nZXQoYC9hcGkvdjIvdGJ0Yy93YWxsZXQvJHt3YWxsZXRJZH1gKS5yZXBseSgyMDAsIHdhbGxldFJlc3VsdCk7XG4gICAgbm9jayhiZ1VybCkuZ2V0KGAvYXBpL3YyL3RidGMva2V5LyR7d2FsbGV0SWR9YCkucmVwbHkoMjAwLCBrZXlSZXN1bHQpO1xuXG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IGZldGNoS2V5cyh3YWxsZXRJZHMsIGFjY2Vzc1Rva2VuKTtcblxuICAgIHNob3VsZC5leGlzdChkYXRhW3dhbGxldElkXSk7XG4gICAgZGF0YVt3YWxsZXRJZF0uc2hvdWxkLnN0YXJ0V2l0aCgne1wiaXZcIjpcIicpO1xuICB9KTtcbn0pO1xuXG4vLyAjcmVnaW9uIE1QQ3YyIHV0aWxzXG5mdW5jdGlvbiBnZXRCaXRHb1BhcnR5R3BnS2V5UHJ2KGJpdGdvUHJ2S2V5OiBzdHJpbmcpOiBEa2xzVHlwZXMuUGFydHlHcGdLZXkge1xuICByZXR1cm4ge1xuICAgIHBhcnR5SWQ6IDIsXG4gICAgZ3BnS2V5OiBiaXRnb1BydktleSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0VXNlclBhcnR5R3BnS2V5UHVibGljKHVzZXJQdWJLZXk6IHN0cmluZyk6IERrbHNUeXBlcy5QYXJ0eUdwZ0tleSB7XG4gIHJldHVybiB7XG4gICAgcGFydHlJZDogMCxcbiAgICBncGdLZXk6IHVzZXJQdWJLZXksXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNpZ25CaXRnb01QQ3YyUm91bmQxKFxuICBiaXRnb1Nlc3Npb246IERrbHNEc2cuRHNnLFxuICB0eFJlcXVlc3Q6IFR4UmVxdWVzdCxcbiAgdXNlclNoYXJlOiBTaWduYXR1cmVTaGFyZVJlY29yZCxcbiAgdXNlckdQR1B1YktleTogc3RyaW5nXG4pOiBQcm9taXNlPFR4UmVxdWVzdD4ge1xuICBhc3NlcnQoXG4gICAgdHhSZXF1ZXN0LnRyYW5zYWN0aW9ucyAmJiB0eFJlcXVlc3QudHJhbnNhY3Rpb25zLmxlbmd0aCA9PT0gMSxcbiAgICAndHhSZXF1ZXN0LnRyYW5zYWN0aW9ucyBpcyBub3QgYW4gYXJyYXkgb2YgbGVuZ3RoIDEnXG4gICk7XG4gIHR4UmVxdWVzdC50cmFuc2FjdGlvbnNbMF0uc2lnbmF0dXJlU2hhcmVzLnB1c2godXNlclNoYXJlKTtcbiAgLy8gRG8gdGhlIGFjdHVhbCBzaWduaW5nIG9uIEJpdEdvJ3Mgc2lkZSBiYXNlZCBvbiBVc2VyJ3MgbWVzc2FnZXNcbiAgY29uc3Qgc2lnbmF0dXJlU2hhcmUgPSBKU09OLnBhcnNlKHVzZXJTaGFyZS5zaGFyZSkgYXMgTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMUlucHV0O1xuICBjb25zdCBkZXNlcmlhbGl6ZWRNZXNzYWdlcyA9IERrbHNUeXBlcy5kZXNlcmlhbGl6ZU1lc3NhZ2VzKHtcbiAgICBwMnBNZXNzYWdlczogW10sXG4gICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtcbiAgICAgIHtcbiAgICAgICAgZnJvbTogc2lnbmF0dXJlU2hhcmUuZGF0YS5tc2cxLmZyb20sXG4gICAgICAgIHBheWxvYWQ6IHNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMS5tZXNzYWdlLFxuICAgICAgfSxcbiAgICBdLFxuICB9KTtcbiAgY29uc3QgYml0Z29Ub1VzZXJSb3VuZDFCcm9hZGNhc3RNc2cgPSBhd2FpdCBiaXRnb1Nlc3Npb24uaW5pdCgpO1xuICBjb25zdCBiaXRnb1RvVXNlclJvdW5kMk1zZyA9IGJpdGdvU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKHtcbiAgICBwMnBNZXNzYWdlczogW10sXG4gICAgYnJvYWRjYXN0TWVzc2FnZXM6IGRlc2VyaWFsaXplZE1lc3NhZ2VzLmJyb2FkY2FzdE1lc3NhZ2VzLFxuICB9KTtcbiAgY29uc3Qgc2VyaWFsaXplZEJpdEdvVG9Vc2VyUm91bmQxQW5kMk1zZ3MgPSBEa2xzVHlwZXMuc2VyaWFsaXplTWVzc2FnZXMoe1xuICAgIHAycE1lc3NhZ2VzOiBiaXRnb1RvVXNlclJvdW5kMk1zZy5wMnBNZXNzYWdlcyxcbiAgICBicm9hZGNhc3RNZXNzYWdlczogW2JpdGdvVG9Vc2VyUm91bmQxQnJvYWRjYXN0TXNnXSxcbiAgfSk7XG5cbiAgY29uc3QgYXV0aEVuY01lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICBzZXJpYWxpemVkQml0R29Ub1VzZXJSb3VuZDFBbmQyTXNncyxcbiAgICBbZ2V0VXNlclBhcnR5R3BnS2V5UHVibGljKHVzZXJHUEdQdWJLZXkpXSxcbiAgICBbZ2V0Qml0R29QYXJ0eUdwZ0tleVBydihiaXRnb0dwZ0tleS5wcml2YXRlKV1cbiAgKTtcblxuICBjb25zdCBiaXRnb1RvVXNlclNpZ25hdHVyZVNoYXJlOiBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxT3V0cHV0ID0ge1xuICAgIHR5cGU6ICdyb3VuZDFPdXRwdXQnLFxuICAgIGRhdGE6IHtcbiAgICAgIG1zZzE6IHtcbiAgICAgICAgZnJvbTogYXV0aEVuY01lc3NhZ2VzLmJyb2FkY2FzdE1lc3NhZ2VzWzBdLmZyb20gYXMgTVBDdjJQYXJ0eUZyb21TdHJpbmdPck51bWJlcixcbiAgICAgICAgc2lnbmF0dXJlOiBhdXRoRW5jTWVzc2FnZXMuYnJvYWRjYXN0TWVzc2FnZXNbMF0ucGF5bG9hZC5zaWduYXR1cmUsXG4gICAgICAgIG1lc3NhZ2U6IGF1dGhFbmNNZXNzYWdlcy5icm9hZGNhc3RNZXNzYWdlc1swXS5wYXlsb2FkLm1lc3NhZ2UsXG4gICAgICB9LFxuICAgICAgbXNnMjoge1xuICAgICAgICBmcm9tOiBhdXRoRW5jTWVzc2FnZXMucDJwTWVzc2FnZXNbMF0uZnJvbSBhcyBNUEN2MlBhcnR5RnJvbVN0cmluZ09yTnVtYmVyLFxuICAgICAgICB0bzogYXV0aEVuY01lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdLnRvIGFzIE1QQ3YyUGFydHlGcm9tU3RyaW5nT3JOdW1iZXIsXG4gICAgICAgIGVuY3J5cHRlZE1lc3NhZ2U6IGF1dGhFbmNNZXNzYWdlcy5wMnBNZXNzYWdlc1swXS5wYXlsb2FkLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgIHNpZ25hdHVyZTogYXV0aEVuY01lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdLnBheWxvYWQuc2lnbmF0dXJlLFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xuICB0eFJlcXVlc3QudHJhbnNhY3Rpb25zWzBdLnNpZ25hdHVyZVNoYXJlcy5wdXNoKHtcbiAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgdG86IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSLFxuICAgIHNoYXJlOiBKU09OLnN0cmluZ2lmeShiaXRnb1RvVXNlclNpZ25hdHVyZVNoYXJlKSxcbiAgfSk7XG4gIHJldHVybiB0eFJlcXVlc3Q7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNpZ25CaXRnb01QQ3YyUm91bmQyKFxuICBiaXRnb1Nlc3Npb246IERrbHNEc2cuRHNnLFxuICB0eFJlcXVlc3Q6IFR4UmVxdWVzdCxcbiAgdXNlclNoYXJlOiBTaWduYXR1cmVTaGFyZVJlY29yZCxcbiAgdXNlckdQR1B1YktleTogc3RyaW5nXG4pOiBQcm9taXNlPHsgdHhSZXF1ZXN0OiBUeFJlcXVlc3Q7IGJpdGdvTXNnNDogRGtsc1R5cGVzLlNlcmlhbGl6ZWRCcm9hZGNhc3RNZXNzYWdlIH0+IHtcbiAgYXNzZXJ0KFxuICAgIHR4UmVxdWVzdC50cmFuc2FjdGlvbnMgJiYgdHhSZXF1ZXN0LnRyYW5zYWN0aW9ucy5sZW5ndGggPT09IDEsXG4gICAgJ3R4UmVxdWVzdC50cmFuc2FjdGlvbnMgaXMgbm90IGFuIGFycmF5IG9mIGxlbmd0aCAxJ1xuICApO1xuICB0eFJlcXVlc3QudHJhbnNhY3Rpb25zWzBdLnNpZ25hdHVyZVNoYXJlcy5wdXNoKHVzZXJTaGFyZSk7XG5cbiAgLy8gRG8gdGhlIGFjdHVhbCBzaWduaW5nIG9uIEJpdEdvJ3Mgc2lkZSBiYXNlZCBvbiBVc2VyJ3MgbWVzc2FnZXNcbiAgY29uc3QgcGFyc2VkU2lnbmF0dXJlU2hhcmUgPSBKU09OLnBhcnNlKHVzZXJTaGFyZS5zaGFyZSkgYXMgTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMklucHV0O1xuICBjb25zdCBzZXJpYWxpemVkTWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZGVjcnlwdEFuZFZlcmlmeUluY29taW5nTWVzc2FnZXMoXG4gICAge1xuICAgICAgcDJwTWVzc2FnZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGZyb206IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMi5mcm9tLFxuICAgICAgICAgIHRvOiBwYXJzZWRTaWduYXR1cmVTaGFyZS5kYXRhLm1zZzIudG8sXG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgZW5jcnlwdGVkTWVzc2FnZTogcGFyc2VkU2lnbmF0dXJlU2hhcmUuZGF0YS5tc2cyLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgICAgICBzaWduYXR1cmU6IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMi5zaWduYXR1cmUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGZyb206IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMy5mcm9tLFxuICAgICAgICAgIHRvOiBwYXJzZWRTaWduYXR1cmVTaGFyZS5kYXRhLm1zZzMudG8sXG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgZW5jcnlwdGVkTWVzc2FnZTogcGFyc2VkU2lnbmF0dXJlU2hhcmUuZGF0YS5tc2czLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgICAgICBzaWduYXR1cmU6IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMy5zaWduYXR1cmUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gICAgfSxcbiAgICBbZ2V0VXNlclBhcnR5R3BnS2V5UHVibGljKHVzZXJHUEdQdWJLZXkpXSxcbiAgICBbZ2V0Qml0R29QYXJ0eUdwZ0tleVBydihiaXRnb0dwZ0tleS5wcml2YXRlKV1cbiAgKTtcbiAgY29uc3QgZGVzZXJpYWxpemVkTWVzc2FnZXMyID0gRGtsc1R5cGVzLmRlc2VyaWFsaXplTWVzc2FnZXMoe1xuICAgIHAycE1lc3NhZ2VzOiBbc2VyaWFsaXplZE1lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdXSxcbiAgICBicm9hZGNhc3RNZXNzYWdlczogW10sXG4gIH0pO1xuXG4gIGNvbnN0IGJpdGdvVG9Vc2VyUm91bmQzTXNnID0gYml0Z29TZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoZGVzZXJpYWxpemVkTWVzc2FnZXMyKTtcbiAgY29uc3Qgc2VyaWFsaXplZEJpdEdvVG9Vc2VyUm91bmQzTXNncyA9IERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyhiaXRnb1RvVXNlclJvdW5kM01zZyk7XG5cbiAgY29uc3QgYXV0aEVuY01lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICBzZXJpYWxpemVkQml0R29Ub1VzZXJSb3VuZDNNc2dzLFxuICAgIFtnZXRVc2VyUGFydHlHcGdLZXlQdWJsaWModXNlckdQR1B1YktleSldLFxuICAgIFtnZXRCaXRHb1BhcnR5R3BnS2V5UHJ2KGJpdGdvR3BnS2V5LnByaXZhdGUpXVxuICApO1xuXG4gIGNvbnN0IGJpdGdvVG9Vc2VyU2lnbmF0dXJlU2hhcmU6IE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJPdXRwdXQgPSB7XG4gICAgdHlwZTogJ3JvdW5kMk91dHB1dCcsXG4gICAgZGF0YToge1xuICAgICAgbXNnMzoge1xuICAgICAgICBmcm9tOiBhdXRoRW5jTWVzc2FnZXMucDJwTWVzc2FnZXNbMF0uZnJvbSBhcyBNUEN2MlBhcnR5RnJvbVN0cmluZ09yTnVtYmVyLFxuICAgICAgICB0bzogYXV0aEVuY01lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdLnRvIGFzIE1QQ3YyUGFydHlGcm9tU3RyaW5nT3JOdW1iZXIsXG4gICAgICAgIGVuY3J5cHRlZE1lc3NhZ2U6IGF1dGhFbmNNZXNzYWdlcy5wMnBNZXNzYWdlc1swXS5wYXlsb2FkLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgIHNpZ25hdHVyZTogYXV0aEVuY01lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdLnBheWxvYWQuc2lnbmF0dXJlLFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xuXG4gIC8vIGhhbmRsaW5nIHVzZXIgbXNnMyBidXQgbm90IHJldHVybmluZyBiaXRnbyBtc2c0IHNpbmNlIGl0cyBzdG9yZWQgb24gYml0Z28gc2lkZSBvbmx5XG4gIGNvbnN0IGRlc2VyaWFsaXplZE1lc3NhZ2VzMyA9IERrbHNUeXBlcy5kZXNlcmlhbGl6ZU1lc3NhZ2VzKHtcbiAgICBwMnBNZXNzYWdlczogW3NlcmlhbGl6ZWRNZXNzYWdlcy5wMnBNZXNzYWdlc1sxXV0sXG4gICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICB9KTtcbiAgY29uc3QgZGVzZXJpYWxpemVkQml0Z29Nc2c0ID0gYml0Z29TZXNzaW9uLmhhbmRsZUluY29taW5nTWVzc2FnZXMoZGVzZXJpYWxpemVkTWVzc2FnZXMzKTtcbiAgY29uc3Qgc2VyaWFsaXplZEJpdEdvVG9Vc2VyUm91bmQ0TXNncyA9IERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyhkZXNlcmlhbGl6ZWRCaXRnb01zZzQpO1xuXG4gIHR4UmVxdWVzdC50cmFuc2FjdGlvbnNbMF0uc2lnbmF0dXJlU2hhcmVzLnB1c2goe1xuICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICB0bzogU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIsXG4gICAgc2hhcmU6IEpTT04uc3RyaW5naWZ5KGJpdGdvVG9Vc2VyU2lnbmF0dXJlU2hhcmUpLFxuICB9KTtcbiAgcmV0dXJuIHsgdHhSZXF1ZXN0LCBiaXRnb01zZzQ6IHNlcmlhbGl6ZWRCaXRHb1RvVXNlclJvdW5kNE1zZ3MuYnJvYWRjYXN0TWVzc2FnZXNbMF0gfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2lnbkJpdGdvTVBDdjJSb3VuZDMoXG4gIGJpdGdvU2Vzc2lvbjogRGtsc0RzZy5Ec2csXG4gIHVzZXJTaGFyZTogU2lnbmF0dXJlU2hhcmVSZWNvcmQsXG4gIHVzZXJHUEdQdWJLZXk6IHN0cmluZ1xuKTogUHJvbWlzZTx7IHVzZXJNc2c0OiBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQzSW5wdXQgfT4ge1xuICBjb25zdCBwYXJzZWRTaWduYXR1cmVTaGFyZSA9IEpTT04ucGFyc2UodXNlclNoYXJlLnNoYXJlKSBhcyBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQzSW5wdXQ7XG4gIGNvbnN0IHNlcmlhbGl6ZWRNZXNzYWdlcyA9IGF3YWl0IERrbHNDb21tcy5kZWNyeXB0QW5kVmVyaWZ5SW5jb21pbmdNZXNzYWdlcyhcbiAgICB7XG4gICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICBicm9hZGNhc3RNZXNzYWdlczogW1xuICAgICAgICB7XG4gICAgICAgICAgZnJvbTogcGFyc2VkU2lnbmF0dXJlU2hhcmUuZGF0YS5tc2c0LmZyb20sXG4gICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgbWVzc2FnZTogcGFyc2VkU2lnbmF0dXJlU2hhcmUuZGF0YS5tc2c0Lm1lc3NhZ2UsXG4gICAgICAgICAgICBzaWduYXR1cmU6IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnNC5zaWduYXR1cmUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSxcbiAgICBbZ2V0VXNlclBhcnR5R3BnS2V5UHVibGljKHVzZXJHUEdQdWJLZXkpXSxcbiAgICBbZ2V0Qml0R29QYXJ0eUdwZ0tleVBydihiaXRnb0dwZ0tleS5wcml2YXRlKV1cbiAgKTtcbiAgY29uc3QgZGVzZXJpYWxpemVkTWVzc2FnZXMgPSBEa2xzVHlwZXMuZGVzZXJpYWxpemVNZXNzYWdlcyh7XG4gICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbc2VyaWFsaXplZE1lc3NhZ2VzLmJyb2FkY2FzdE1lc3NhZ2VzWzBdXSxcbiAgfSk7XG4gIGJpdGdvU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKGRlc2VyaWFsaXplZE1lc3NhZ2VzKTtcblxuICByZXR1cm4ge1xuICAgIHVzZXJNc2c0OiBwYXJzZWRTaWduYXR1cmVTaGFyZSxcbiAgfTtcbn1cbi8vICNlbmRyZWdpb25cbiJdfQ==

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


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