UNPKG

bitgo

Version:
573 lines • 86.3 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBitGoPartyGpgKeyPrv = getBitGoPartyGpgKeyPrv;
exports.getUserPartyGpgKeyPublic = getUserPartyGpgKeyPublic;
const sdk_core_1 = require("@bitgo/sdk-core");
const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc");
const fs = require("fs");
const common_1 = require("../common");
const openpgp = require("openpgp");
const nock = require("nock");
const sdk_test_1 = require("@bitgo/sdk-test");
const src_1 = require("../../../../../../src");
const createKeccakHash = require('keccak');
describe('signTxRequest:', function () {
    let tssUtils;
    let wallet;
    let bitgo;
    let baseCoin;
    let bitgoGpgKey;
    const coinName = 'hteth';
    const reqId = new sdk_core_1.RequestTracer();
    const txRequestId = 'randomTxReqId';
    const signableHex = 'e27aecaea559fbedc9ae8a22b0ab6654c2d686403c2aeb434b302545c94eed3b';
    const txRequest = {
        txRequestId,
        enterpriseId: '4517abfb-f567-4b7a-9f91-407509d29403',
        transactions: [
            {
                unsignedTx: {
                    serializedTxHex: 'TOO MANY SECRETS',
                    signableHex,
                    derivationPath: 'm/0', // Needs this when key derivation is supported
                },
                state: 'pendingSignature',
                signatureShares: [],
            },
        ],
        unsignedTxs: [],
        date: new Date().toISOString(),
        intent: {
            intentType: 'payment',
        },
        latest: true,
        state: 'pendingUserSignature',
        walletType: 'hot',
        walletId: 'walletId',
        policiesChecked: true,
        version: 1,
        userId: 'userId',
        apiVersion: 'full',
    };
    const txRequestForMessageSigning = {
        txRequestId,
        enterpriseId: '4517abfb-f567-4b7a-9f91-407509d29403',
        messages: [
            {
                messageRaw: 'TOO MANY SECRETS',
                derivationPath: 'm/0',
                state: 'pendingSignature',
                signatureShares: [],
            },
        ],
        unsignedTxs: [],
        date: new Date().toISOString(),
        intent: {
            intentType: 'payment',
        },
        latest: true,
        state: 'pendingUserSignature',
        walletType: 'hot',
        walletId: 'walletId',
        policiesChecked: true,
        version: 1,
        userId: 'userId',
        apiVersion: 'full',
    };
    const vector = {
        party1: 0,
        party2: 2,
        party3: 1,
    };
    // To generate the fixtures, run DKG as in the dklsDkg.ts tests and save the resulting party.getKeyShare in a file by doing fs.writeSync(party.getKeyShare()).
    const shareFiles = [
        `${__dirname}/fixtures/userShare`,
        `${__dirname}/fixtures/backupShare`,
        `${__dirname}/fixtures/bitgoShare`,
    ];
    let bitgoParty;
    before(async () => {
        bitgo = sdk_test_1.TestBitGo.decorate(src_1.BitGo, { env: 'mock' });
        bitgo.initializeTestVars();
        const bgUrl = sdk_core_1.common.Environments[bitgo.getEnv()].uri;
        bitgoGpgKey = await openpgp.generateKey({
            userIDs: [
                {
                    name: 'bitgo',
                },
            ],
            curve: 'secp256k1',
            config: {
                rejectCurves: new Set(),
            },
        });
        const constants = {
            mpc: {
                bitgoPublicKey: bitgoGpgKey.publicKey,
                bitgoMPCv2PublicKey: bitgoGpgKey.publicKey,
            },
        };
        nock(bgUrl).get('/api/v1/client/constants').times(20).reply(200, { ttl: 3600, constants });
        baseCoin = bitgo.coin(coinName);
        let hashFn;
        try {
            hashFn = baseCoin.getHashFunction();
        }
        catch (err) {
            hashFn = createKeccakHash('keccak256');
        }
        const hashBuffer = hashFn.update(Buffer.from(signableHex, 'hex')).digest();
        // Nock out both the user and bitgo side responses to create valid signatures
        bitgoParty = new sdk_lib_mpc_1.DklsDsg.Dsg(fs.readFileSync(shareFiles[vector.party2]), vector.party2, txRequest.transactions[0].unsignedTx.derivationPath, hashBuffer);
        // // Round 1 ////
        const walletData = {
            id: txRequest.walletId,
            enterprise: txRequest.enterpriseId,
            coin: coinName,
            coinSpecific: {},
            multisigType: 'tss',
            multisigTypeVersion: 'MPCv2',
        };
        wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData);
        tssUtils = new sdk_core_1.ECDSAUtils.EcdsaMPCv2Utils(bitgo, baseCoin, wallet);
    });
    beforeEach(async function () {
        await nockGetBitgoPublicKeyBasedOnFeatureFlags(coinName, txRequest.enterpriseId, bitgoGpgKey);
    });
    after(function () {
        nock.cleanAll();
    });
    afterEach(function () {
        bitgoParty.endSession();
        nock.cleanAll();
    });
    it('successfully signs a txRequest with user key for a dkls hot wallet with WP', async function () {
        const nockPromises = [
            await nockTxRequestResponseSignatureShareRoundOne(bitgoParty, txRequest, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundTwo(bitgoParty, txRequest, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundThree(txRequest),
            await nockSendTxRequest(txRequest),
        ];
        await Promise.all(nockPromises);
        const userShare = fs.readFileSync(shareFiles[vector.party1]);
        const userPrvBase64 = Buffer.from(userShare).toString('base64');
        await tssUtils.signTxRequest({
            txRequest,
            prv: userPrvBase64,
            reqId,
        });
        nockPromises[0].isDone().should.be.true();
        nockPromises[1].isDone().should.be.true();
        nockPromises[2].isDone().should.be.true();
    });
    it('successfully signs when recipientSource is explicit and txParams.recipients is non-empty', async function () {
        const nockPromises = [
            await nockTxRequestResponseSignatureShareRoundOne(bitgoParty, txRequest, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundTwo(bitgoParty, txRequest, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundThree(txRequest),
            await nockSendTxRequest(txRequest),
        ];
        await Promise.all(nockPromises);
        const userShare = fs.readFileSync(shareFiles[vector.party1]);
        const userPrvBase64 = Buffer.from(userShare).toString('base64');
        await tssUtils.signTxRequest({
            txRequest,
            prv: userPrvBase64,
            reqId,
            recipientSource: sdk_core_1.TssTxRecipientSource.Explicit,
            txParams: {
                recipients: [{ address: '0x0000000000000000000000000000000000000001', amount: '1' }],
            },
        });
        nockPromises[0].isDone().should.be.true();
        nockPromises[1].isDone().should.be.true();
        nockPromises[2].isDone().should.be.true();
    });
    it('rejects when recipientSource is explicit and txParams.recipients is empty', async function () {
        const userShare = fs.readFileSync(shareFiles[vector.party1]);
        const userPrvBase64 = Buffer.from(userShare).toString('base64');
        // Cast bypasses the compile-time non-empty recipients constraint to exercise the runtime guard.
        await tssUtils
            .signTxRequest({
            txRequest,
            prv: userPrvBase64,
            reqId,
            recipientSource: sdk_core_1.TssTxRecipientSource.Explicit,
            txParams: { recipients: [] },
        })
            .should.be.rejectedWith('recipientSource "explicit" requires txParams.recipients with at least one recipient.');
    });
    it('successfully signs a txRequest with backup key for a dkls hot wallet with WP', async function () {
        const nockPromises = [
            await nockTxRequestResponseSignatureShareRoundOne(bitgoParty, txRequest, bitgoGpgKey, 1),
            await nockTxRequestResponseSignatureShareRoundTwo(bitgoParty, txRequest, bitgoGpgKey, 1),
            await nockTxRequestResponseSignatureShareRoundThree(txRequest),
            await nockSendTxRequest(txRequest),
        ];
        await Promise.all(nockPromises);
        const backupShare = fs.readFileSync(shareFiles[vector.party3]);
        const backupPrvBase64 = Buffer.from(backupShare).toString('base64');
        await tssUtils.signTxRequest({
            txRequest,
            prv: backupPrvBase64,
            mpcv2PartyId: 1,
            reqId,
        });
        nockPromises[0].isDone().should.be.true();
        nockPromises[1].isDone().should.be.true();
        nockPromises[2].isDone().should.be.true();
    });
    it('successfully signs a txRequest with a message for a dkls hot wallet with WP', async function () {
        const nockPromises = [
            await nockTxRequestResponseSignatureShareRoundOne(bitgoParty, txRequestForMessageSigning, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundTwo(bitgoParty, txRequestForMessageSigning, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundThree(txRequestForMessageSigning),
            await nockSendTxRequest(txRequestForMessageSigning),
        ];
        await Promise.all(nockPromises);
        const userShare = fs.readFileSync(shareFiles[vector.party1]);
        const userPrvBase64 = Buffer.from(userShare).toString('base64');
        await tssUtils.signTxRequest({
            txRequest,
            prv: userPrvBase64,
            reqId,
        });
        nockPromises[0].isDone().should.be.true();
        nockPromises[1].isDone().should.be.true();
        nockPromises[2].isDone().should.be.true();
    });
    it('successfully signs a txRequest for a dkls hot wallet after receiving multiple 429 errors', async function () {
        const nockPromises = [
            await nockTxRequestResponseSignatureShareRoundOne(bitgoParty, txRequest, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundTwo(bitgoParty, txRequest, bitgoGpgKey, 0, 3),
            await nockTxRequestResponseSignatureShareRoundThree(txRequest),
            await nockSendTxRequest(txRequest),
        ];
        await Promise.all(nockPromises);
        const userShare = fs.readFileSync(shareFiles[vector.party1]);
        const userPrvBase64 = Buffer.from(userShare).toString('base64');
        await tssUtils.signTxRequest({
            txRequest,
            prv: userPrvBase64,
            reqId,
        });
        nockPromises[0].isDone().should.be.true();
        nockPromises[1].isDone().should.be.true();
        nockPromises[2].isDone().should.be.true();
    });
    describe('v2 encryption (offline rounds with adata)', function () {
        it('e2e: 3-round offline signing with v2 encrypted keys preserves adata context binding', async function () {
            const walletPassphrase = 'testpassphrase';
            const userShare = fs.readFileSync(shareFiles[vector.party1]);
            const userPrvBase64 = Buffer.from(userShare).toString('base64');
            const encryptedPrv = await bitgo.encrypt({
                input: userPrvBase64,
                password: walletPassphrase,
                encryptionVersion: 2,
            });
            JSON.parse(encryptedPrv).v.should.equal(2);
            const round1Result = await tssUtils.createOfflineRound1Share({
                txRequest,
                prv: userPrvBase64,
                walletPassphrase,
                encryptedPrv,
            });
            const r1SessionEnvelope = JSON.parse(round1Result.encryptedRound1Session);
            r1SessionEnvelope.v.should.equal(2);
            r1SessionEnvelope.should.have.property('adata');
            r1SessionEnvelope.should.have.property('hkdfSalt');
            r1SessionEnvelope.adata.should.containEql('DKLS23_SIGNING_ROUND1_STATE');
            const r1GpgEnvelope = JSON.parse(round1Result.encryptedUserGpgPrvKey);
            r1GpgEnvelope.v.should.equal(2);
            r1GpgEnvelope.should.have.property('adata');
            r1GpgEnvelope.adata.should.containEql('DKLS23_SIGNING_USER_GPG_KEY');
            await nockTxRequestResponseSignatureShareRoundOne(bitgoParty, txRequest, bitgoGpgKey);
            const transactions = (0, common_1.getRoute)('ecdsa');
            const round1TxRequestResponse = await bitgo
                .post(bitgo.url(`/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId + transactions}/sign`, 2))
                .send({
                signatureShares: [round1Result.signatureShareRound1],
                signerGpgPublicKey: round1Result.userGpgPubKey,
            })
                .result();
            const round1TxReq = {
                ...txRequest,
                transactions: [
                    {
                        ...txRequest.transactions[0],
                        signatureShares: round1TxRequestResponse.transactions[0].signatureShares,
                    },
                ],
            };
            const round2Result = await tssUtils.createOfflineRound2Share({
                txRequest: round1TxReq,
                prv: userPrvBase64,
                walletPassphrase,
                bitgoPublicGpgKey: bitgoGpgKey.publicKey,
                encryptedUserGpgPrvKey: round1Result.encryptedUserGpgPrvKey,
                encryptedRound1Session: round1Result.encryptedRound1Session,
            });
            const r2Envelope = JSON.parse(round2Result.encryptedRound2Session);
            r2Envelope.v.should.equal(2);
            r2Envelope.should.have.property('adata');
            r2Envelope.adata.should.containEql('DKLS23_SIGNING_ROUND2_STATE');
            await nockTxRequestResponseSignatureShareRoundTwo(bitgoParty, txRequest, bitgoGpgKey);
            const round2TxRequestResponse = await bitgo
                .post(bitgo.url(`/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId + transactions}/sign`, 2))
                .send({
                signatureShares: [round2Result.signatureShareRound2],
                signerGpgPublicKey: round1Result.userGpgPubKey,
            })
                .result();
            const round2TxReq = {
                ...txRequest,
                transactions: [
                    {
                        ...txRequest.transactions[0],
                        signatureShares: round2TxRequestResponse.transactions[0].signatureShares,
                    },
                ],
            };
            const round3Result = await tssUtils.createOfflineRound3Share({
                txRequest: round2TxReq,
                prv: userPrvBase64,
                walletPassphrase,
                bitgoPublicGpgKey: bitgoGpgKey.publicKey,
                encryptedUserGpgPrvKey: round1Result.encryptedUserGpgPrvKey,
                encryptedRound2Session: round2Result.encryptedRound2Session,
            });
            round3Result.should.have.property('signatureShareRound3');
        });
        it('validateAdata accepts v2 envelopes with matching adata and domain separator', async function () {
            const adata = 'txhash:m/0/1';
            const domainSep = 'DKLS23_SIGNING_ROUND1_STATE';
            const ct = await bitgo.encrypt({
                input: 'test-data',
                password: 'testpass',
                encryptionVersion: 2,
                adata: `${domainSep}:${adata}`,
            });
            tssUtils.validateAdata(adata, ct, domainSep);
        });
        it('validateAdata rejects v2 envelopes with mismatched adata', async function () {
            const domainSep = 'DKLS23_SIGNING_ROUND1_STATE';
            const ct = await bitgo.encrypt({
                input: 'test-data',
                password: 'testpass',
                encryptionVersion: 2,
                adata: `${domainSep}:context-A`,
            });
            (() => tssUtils.validateAdata('context-B', ct, domainSep)).should.throw(/Adata does not match/);
        });
    });
    it('fails to signs a txRequest for a dkls hot wallet after receiving over 3 429 errors', async function () {
        const nockPromises = [
            await nockTxRequestResponseSignatureShareRoundOne(bitgoParty, txRequest, bitgoGpgKey),
            await nockTxRequestResponseSignatureShareRoundTwo(bitgoParty, txRequest, bitgoGpgKey, 0, 4),
        ];
        await Promise.all(nockPromises);
        const userShare = fs.readFileSync(shareFiles[vector.party1]);
        const userPrvBase64 = Buffer.from(userShare).toString('base64');
        await tssUtils
            .signTxRequest({
            txRequest,
            prv: userPrvBase64,
            reqId,
        })
            .should.be.rejectedWith('Too many requests, slow down!');
        nockPromises[0].isDone().should.be.true();
        nockPromises[1].isDone().should.be.false();
    });
});
function getBitGoPartyGpgKeyPrv(key) {
    return {
        partyId: 2,
        gpgKey: key.privateKey,
    };
}
function getUserPartyGpgKeyPublic(userPubKey, partyId = 0) {
    return {
        partyId: partyId,
        gpgKey: userPubKey,
    };
}
async function nockTxRequestResponseSignatureShareRoundOne(bitgoSession, txRequest, bitgoGpgKey, partyId = 0) {
    const transactions = (0, common_1.getRoute)('ecdsa');
    return nock('https://bitgo.fakeurl')
        .persist(true)
        .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId + transactions}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round1Input')
        .times(1)
        .reply(200, async (uri, body) => {
        // Do the actual signing on BitGo's side based on User's messages
        const signatureShare = JSON.parse(body.signatureShares[0].share);
        const deserializedMessages = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
            p2pMessages: [],
            broadcastMessages: [
                {
                    from: signatureShare.data.msg1.from,
                    payload: signatureShare.data.msg1.message,
                },
            ],
        });
        if (signatureShare.type === 'round1Input') {
            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(body.signerGpgPublicKey, partyId)], [getBitGoPartyGpgKeyPrv(bitgoGpgKey)]);
            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,
                    },
                },
            };
            return {
                txRequestId: txRequest.txRequestId,
                transactions: [
                    {
                        signatureShares: [
                            {
                                from: sdk_core_1.SignatureShareType.BITGO,
                                to: partyId === 0 ? sdk_core_1.SignatureShareType.USER : sdk_core_1.SignatureShareType.BACKUP,
                                share: JSON.stringify(bitgoToUserSignatureShare),
                            },
                        ],
                    },
                ],
            };
        }
    });
}
async function nockTxRequestResponseSignatureShareRoundTwo(bitgoSession, txRequest, bitgoGpgKey, partyId = 0, rateLimitErrorCount = 0) {
    const transactions = (0, common_1.getRoute)('ecdsa');
    const scope = nock('https://bitgo.fakeurl');
    if (rateLimitErrorCount > 0) {
        scope
            .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId + transactions}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round2Input')
            .times(rateLimitErrorCount)
            .reply(429, {
            error: 'Too many requests, slow down!',
            name: 'TooManyRequests',
            requestId: 'cm5qx01lh0013b2ek2sxl4w00',
            context: {},
        });
    }
    return scope
        .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId + transactions}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round2Input')
        .times(1)
        .reply(200, async (uri, body) => {
        // Do the actual signing on BitGo's side based on User's messages
        const parsedSignatureShare = JSON.parse(body.signatureShares[0].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(body.signerGpgPublicKey, partyId)], [getBitGoPartyGpgKeyPrv(bitgoGpgKey)]);
        const deserializedMessages = sdk_lib_mpc_1.DklsTypes.deserializeMessages({
            p2pMessages: [serializedMessages.p2pMessages[0]],
            broadcastMessages: [],
        });
        if (parsedSignatureShare.type === 'round2Input') {
            const bitgoToUserRound3Msg = bitgoSession.handleIncomingMessages(deserializedMessages);
            const serializedBitGoToUserRound3Msgs = sdk_lib_mpc_1.DklsTypes.serializeMessages(bitgoToUserRound3Msg);
            const authEncMessages = await sdk_lib_mpc_1.DklsComms.encryptAndAuthOutgoingMessages(serializedBitGoToUserRound3Msgs, [getUserPartyGpgKeyPublic(body.signerGpgPublicKey, partyId)], [getBitGoPartyGpgKeyPrv(bitgoGpgKey)]);
            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,
                    },
                },
            };
            return {
                txRequestId: txRequest.txRequestId,
                transactions: [
                    {
                        signatureShares: [
                            {
                                from: partyId === 0 ? sdk_core_1.SignatureShareType.USER : sdk_core_1.SignatureShareType.BACKUP,
                                to: sdk_core_1.SignatureShareType.BITGO,
                                share: 'some old share we dont care about',
                            },
                            {
                                from: sdk_core_1.SignatureShareType.BITGO,
                                to: partyId === 0 ? sdk_core_1.SignatureShareType.USER : sdk_core_1.SignatureShareType.BACKUP,
                                share: JSON.stringify(bitgoToUserSignatureShare),
                            },
                        ],
                    },
                ],
            };
        }
    });
}
async function nockTxRequestResponseSignatureShareRoundThree(txRequest) {
    const transactions = (0, common_1.getRoute)('ecdsa');
    return nock('https://bitgo.fakeurl')
        .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId + transactions}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round3Input')
        .times(1)
        .reply(200, async (uri, body) => {
        // Do the actual signing on BitGo's side based on User's messages
        return {
            txRequestId: txRequest.txRequestId,
        };
    });
}
async function nockSendTxRequest(txRequest) {
    const transactions = (0, common_1.getRoute)('ecdsa');
    return nock('https://bitgo.fakeurl')
        .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId + transactions}/send`)
        .times(1)
        .reply(200, {
        txRequestId: txRequest.txRequestId,
    });
}
async function nockGetBitgoPublicKeyBasedOnFeatureFlags(coin, enterpriseId, bitgoGpgKeyPair) {
    const bitgoGPGPublicKeyResponse = {
        name: 'irrelevant',
        publicKey: bitgoGpgKeyPair.publicKey,
        mpcv2PublicKey: bitgoGpgKeyPair.publicKey,
        enterpriseId,
    };
    nock('https://bitgo.fakeurl')
        .get(`/api/v2/${coin}/tss/pubkey`)
        .times(4)
        .query({ enterpriseId })
        .reply(200, bitgoGPGPublicKeyResponse);
    return bitgoGPGPublicKeyResponse;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnblR4UmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Rlc3QvdjIvdW5pdC9pbnRlcm5hbC90c3NVdGlscy9lY2RzYU1QQ3YyL3NpZ25UeFJlcXVlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFpY0Esd0RBS0M7QUFFRCw0REFLQztBQTVjRCw4Q0FXeUI7QUFDekIsb0RBQW1FO0FBQ25FLHlCQUF5QjtBQUN6QixzQ0FBcUM7QUFTckMsbUNBQW1DO0FBQ25DLDZCQUE4QjtBQUM5Qiw4Q0FBd0Q7QUFDeEQsK0NBQThDO0FBQzlDLE1BQU0sZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBTzNDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRTtJQUN6QixJQUFJLFFBQW9DLENBQUM7SUFDekMsSUFBSSxNQUFjLENBQUM7SUFDbkIsSUFBSSxLQUF5QixDQUFDO0lBQzlCLElBQUksUUFBa0IsQ0FBQztJQUN2QixJQUFJLFdBQThDLENBQUM7SUFDbkQsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDO0lBRXpCLE1BQU0sS0FBSyxHQUFHLElBQUksd0JBQWEsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sV0FBVyxHQUFHLGVBQWUsQ0FBQztJQUNwQyxNQUFNLFdBQVcsR0FBRyxrRUFBa0UsQ0FBQztJQUN2RixNQUFNLFNBQVMsR0FBYztRQUMzQixXQUFXO1FBQ1gsWUFBWSxFQUFFLHNDQUFzQztRQUNwRCxZQUFZLEVBQUU7WUFDWjtnQkFDRSxVQUFVLEVBQUU7b0JBQ1YsZUFBZSxFQUFFLGtCQUFrQjtvQkFDbkMsV0FBVztvQkFDWCxjQUFjLEVBQUUsS0FBSyxFQUFFLDhDQUE4QztpQkFDdEU7Z0JBQ0QsS0FBSyxFQUFFLGtCQUFrQjtnQkFDekIsZUFBZSxFQUFFLEVBQUU7YUFDcEI7U0FDRjtRQUNELFdBQVcsRUFBRSxFQUFFO1FBQ2YsSUFBSSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMs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Q0FBQyxrQkFBa0IsU0FBUyxDQUFDLFFBQVEsZUFBZSxTQUFTLENBQUMsV0FBVyxHQUFHLFlBQVksT0FBTyxDQUFDO1NBQ3BHLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDUixLQUFLLENBQUMsR0FBRyxFQUFFO1FBQ1YsV0FBVyxFQUFFLFNBQVMsQ0FBQyxXQUFXO0tBQ25DLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRCxLQUFLLFVBQVUsd0NBQXdDLENBQ3JELElBQVksRUFDWixZQUFvQixFQUNwQixlQUFrRDtJQUVsRCxNQUFNLHlCQUF5QixHQUFzQjtRQUNuRCxJQUFJLEVBQUUsWUFBWTtRQUNsQixTQUFTLEVBQUUsZUFBZSxDQUFDLFNBQVM7UUFDcEMsY0FBYyxFQUFFLGVBQWUsQ0FBQyxTQUFTO1FBQ3pDLFlBQVk7S0FDYixDQUFDO0lBQ0YsSUFBSSxDQUFDLHVCQUF1QixDQUFDO1NBQzFCLEdBQUcsQ0FBQyxXQUFXLElBQUksYUFBYSxDQUFDO1NBQ2pDLEtBQUssQ0FBQyxDQUFDLENBQUM7U0FDUixLQUFLLENBQUMsRUFBRSxZQUFZLEVBQUUsQ0FBQztTQUN2QixLQUFLLENBQUMsR0FBRyxFQUFFLHlCQUF5QixDQUFDLENBQUM7SUFDekMsT0FBTyx5QkFBeUIsQ0FBQztBQUNuQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSGFzaCB9IGZyb20gJ2NyeXB0byc7XG5pbXBvcnQge1xuICBCYXNlQ29pbixcbiAgQml0Z29HUEdQdWJsaWNLZXksXG4gIGNvbW1vbixcbiAgRUNEU0FVdGlscyxcbiAgUmVxdWVzdFRyYWNlcixcbiAgU2lnbmF0dXJlU2hhcmVSZWNvcmQsXG4gIFNpZ25hdHVyZVNoYXJlVHlwZSxcbiAgVHNzVHhSZWNpcGllbnRTb3VyY2UsXG4gIFR4UmVxdWVzdCxcbiAgV2FsbGV0LFxufSBmcm9tICdAYml0Z28vc2RrLWNvcmUnO1xuaW1wb3J0IHsgRGtsc0RzZywgRGtsc1R5cGVzLCBEa2xzQ29tbXMgfSBmcm9tICdAYml0Z28vc2RrLWxpYi1tcGMnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHsgZ2V0Um91dGUgfSBmcm9tICcuLi9jb21tb24nO1xuaW1wb3J0IHtcbiAgTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMU91dHB1dCxcbiAgTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMUlucHV0LFxuICBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQySW5wdXQsXG4gIE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJPdXRwdXQsXG4gIE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDNJbnB1dCxcbiAgTVBDdjJQYXJ0eUZyb21TdHJpbmdPck51bWJlcixcbn0gZnJvbSAnQGJpdGdvL3B1YmxpYy10eXBlcyc7XG5pbXBvcnQgKiBhcyBvcGVucGdwIGZyb20gJ29wZW5wZ3AnO1xuaW1wb3J0IG5vY2sgPSByZXF1aXJlKCdub2NrJyk7XG5pbXBvcnQgeyBUZXN0YWJsZUJHLCBUZXN0Qml0R28gfSBmcm9tICdAYml0Z28vc2RrLXRlc3QnO1xuaW1wb3J0IHsgQml0R28gfSBmcm9tICcuLi8uLi8uLi8uLi8uLi8uLi9zcmMnO1xuY29uc3QgY3JlYXRlS2VjY2FrSGFzaCA9IHJlcXVpcmUoJ2tlY2NhaycpO1xuXG5pbnRlcmZhY2UgU2lnbmF0dXJlU2hhcmVBcGlCb2R5IHtcbiAgc2lnbmF0dXJlU2hhcmVzOiBTaWduYXR1cmVTaGFyZVJlY29yZFtdO1xuICBzaWduZXJHcGdQdWJsaWNLZXk6IHN0cmluZztcbn1cblxuZGVzY3JpYmUoJ3NpZ25UeFJlcXVlc3Q6JywgZnVuY3Rpb24gKCkge1xuICBsZXQgdHNzVXRpbHM6IEVDRFNBVXRpbHMuRWNkc2FNUEN2MlV0aWxzO1xuICBsZXQgd2FsbGV0OiBXYWxsZXQ7XG4gIGxldCBiaXRnbzogVGVzdGFibGVCRyAmIEJpdEdvO1xuICBsZXQgYmFzZUNvaW46IEJhc2VDb2luO1xuICBsZXQgYml0Z29HcGdLZXk6IG9wZW5wZ3AuU2VyaWFsaXplZEtleVBhaXI8c3RyaW5nPjtcbiAgY29uc3QgY29pbk5hbWUgPSAnaHRldGgnO1xuXG4gIGNvbnN0IHJlcUlkID0gbmV3IFJlcXVlc3RUcmFjZXIoKTtcbiAgY29uc3QgdHhSZXF1ZXN0SWQgPSAncmFuZG9tVHhSZXFJZCc7XG4gIGNvbnN0IHNpZ25hYmxlSGV4ID0gJ2UyN2FlY2FlYTU1OWZiZWRjOWFlOGEyMmIwYWI2NjU0YzJkNjg2NDAzYzJhZWI0MzRiMzAyNTQ1Yzk0ZWVkM2InO1xuICBjb25zdCB0eFJlcXVlc3Q6IFR4UmVxdWVzdCA9IHtcbiAgICB0eFJlcXVlc3RJZCxcbiAgICBlbnRlcnByaXNlSWQ6ICc0NTE3YWJmYi1mNTY3LTRiN2EtOWY5MS00MDc1MDlkMjk0MDMnLFxuICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAge1xuICAgICAgICB1bnNpZ25lZFR4OiB7XG4gICAgICAgICAgc2VyaWFsaXplZFR4SGV4OiAnVE9PIE1BTlkgU0VDUkVUUycsXG4gICAgICAgICAgc2lnbmFibGVIZXgsXG4gICAgICAgICAgZGVyaXZhdGlvblBhdGg6ICdtLzAnLCAvLyBOZWVkcyB0aGlzIHdoZW4ga2V5IGRlcml2YXRpb24gaXMgc3VwcG9ydGVkXG4gICAgICAgIH0sXG4gICAgICAgIHN0YXRlOiAncGVuZGluZ1NpZ25hdHVyZScsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlczogW10sXG4gICAgICB9LFxuICAgIF0sXG4gICAgdW5zaWduZWRUeHM6IFtdLFxuICAgIGRhdGU6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICBpbnRlbnQ6IHtcbiAgICAgIGludGVudFR5cGU6ICdwYXltZW50JyxcbiAgICB9LFxuICAgIGxhdGVzdDogdHJ1ZSxcbiAgICBzdGF0ZTogJ3BlbmRpbmdVc2VyU2lnbmF0dXJlJyxcbiAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICB3YWxsZXRJZDogJ3dhbGxldElkJyxcbiAgICBwb2xpY2llc0NoZWNrZWQ6IHRydWUsXG4gICAgdmVyc2lvbjogMSxcbiAgICB1c2VySWQ6ICd1c2VySWQnLFxuICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgfTtcblxuICBjb25zdCB0eFJlcXVlc3RGb3JNZXNzYWdlU2lnbmluZzogVHhSZXF1ZXN0ID0ge1xuICAgIHR4UmVxdWVzdElkLFxuICAgIGVudGVycHJpc2VJZDogJzQ1MTdhYmZiLWY1NjctNGI3YS05ZjkxLTQwNzUwOWQyOTQwMycsXG4gICAgbWVzc2FnZXM6IFtcbiAgICAgIHtcbiAgICAgICAgbWVzc2FnZVJhdzogJ1RPTyBNQU5ZIFNFQ1JFVFMnLFxuICAgICAgICBkZXJpdmF0aW9uUGF0aDogJ20vMCcsXG4gICAgICAgIHN0YXRlOiAncGVuZGluZ1NpZ25hdHVyZScsXG4gICAgICAgIHNpZ25hdHVyZVNoYXJlczogW10sXG4gICAgICB9LFxuICAgIF0sXG4gICAgdW5zaWduZWRUeHM6IFtdLFxuICAgIGRhdGU6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICBpbnRlbnQ6IHtcbiAgICAgIGludGVudFR5cGU6ICdwYXltZW50JyxcbiAgICB9LFxuICAgIGxhdGVzdDogdHJ1ZSxcbiAgICBzdGF0ZTogJ3BlbmRpbmdVc2VyU2lnbmF0dXJlJyxcbiAgICB3YWxsZXRUeXBlOiAnaG90JyxcbiAgICB3YWxsZXRJZDogJ3dhbGxldElkJyxcbiAgICBwb2xpY2llc0NoZWNrZWQ6IHRydWUsXG4gICAgdmVyc2lvbjogMSxcbiAgICB1c2VySWQ6ICd1c2VySWQnLFxuICAgIGFwaVZlcnNpb246ICdmdWxsJyxcbiAgfTtcblxuICBjb25zdCB2ZWN0b3IgPSB7XG4gICAgcGFydHkxOiAwLFxuICAgIHBhcnR5MjogMixcbiAgICBwYXJ0eTM6IDEsXG4gIH07XG4gIC8vIFRvIGdlbmVyYXRlIHRoZSBmaXh0dXJlcywgcnVuIERLRyBhcyBpbiB0aGUgZGtsc0RrZy50cyB0ZXN0cyBhbmQgc2F2ZSB0aGUgcmVzdWx0aW5nIHBhcnR5LmdldEtleVNoYXJlIGluIGEgZmlsZSBieSBkb2luZyBmcy53cml0ZVN5bmMocGFydHkuZ2V0S2V5U2hhcmUoKSkuXG4gIGNvbnN0IHNoYXJlRmlsZXMgPSBbXG4gICAgYCR7X19kaXJuYW1lfS9maXh0dXJlcy91c2VyU2hhcmVgLFxuICAgIGAke19fZGlybmFtZX0vZml4dHVyZXMvYmFja3VwU2hhcmVgLFxuICAgIGAke19fZGlybmFtZX0vZml4dHVyZXMvYml0Z29TaGFyZWAsXG4gIF07XG5cbiAgbGV0IGJpdGdvUGFydHk6IERrbHNEc2cuRHNnO1xuXG4gIGJlZm9yZShhc3luYyAoKSA9PiB7XG4gICAgYml0Z28gPSBUZXN0Qml0R28uZGVjb3JhdGUoQml0R28sIHsgZW52OiAnbW9jaycgfSk7XG4gICAgYml0Z28uaW5pdGlhbGl6ZVRlc3RWYXJzKCk7XG4gICAgY29uc3QgYmdVcmwgPSBjb21tb24uRW52aXJvbm1lbnRzW2JpdGdvLmdldEVudigpXS51cmk7XG4gICAgYml0Z29HcGdLZXkgPSBhd2FpdCBvcGVucGdwLmdlbmVyYXRlS2V5KHtcbiAgICAgIHVzZXJJRHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6ICdiaXRnbycsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgY3VydmU6ICdzZWNwMjU2azEnLFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIHJlamVjdEN1cnZlczogbmV3IFNldCgpLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBjb25zdCBjb25zdGFudHMgPSB7XG4gICAgICBtcGM6IHtcbiAgICAgICAgYml0Z29QdWJsaWNLZXk6IGJpdGdvR3BnS2V5LnB1YmxpY0tleSxcbiAgICAgICAgYml0Z29NUEN2MlB1YmxpY0tleTogYml0Z29HcGdLZXkucHVibGljS2V5LFxuICAgICAgfSxcbiAgICB9O1xuICAgIG5vY2soYmdVcmwpLmdldCgnL2FwaS92MS9jbGllbnQvY29uc3RhbnRzJykudGltZXMoMjApLnJlcGx5KDIwMCwgeyB0dGw6IDM2MDAsIGNvbnN0YW50cyB9KTtcblxuICAgIGJhc2VDb2luID0gYml0Z28uY29pbihjb2luTmFtZSk7XG5cbiAgICBsZXQgaGFzaEZuOiBIYXNoO1xuICAgIHRyeSB7XG4gICAgICBoYXNoRm4gPSBiYXNlQ29pbi5nZXRIYXNoRnVuY3Rpb24oKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGhhc2hGbiA9IGNyZWF0ZUtlY2Nha0hhc2goJ2tlY2NhazI1NicpIGFzIEhhc2g7XG4gICAgfVxuICAgIGNvbnN0IGhhc2hCdWZmZXIgPSBoYXNoRm4udXBkYXRlKEJ1ZmZlci5mcm9tKHNpZ25hYmxlSGV4LCAnaGV4JykpLmRpZ2VzdCgpO1xuXG4gICAgLy8gTm9jayBvdXQgYm90aCB0aGUgdXNlciBhbmQgYml0Z28gc2lkZSByZXNwb25zZXMgdG8gY3JlYXRlIHZhbGlkIHNpZ25hdHVyZXNcbiAgICBiaXRnb1BhcnR5ID0gbmV3IERrbHNEc2cuRHNnKFxuICAgICAgZnMucmVhZEZpbGVTeW5jKHNoYXJlRmlsZXNbdmVjdG9yLnBhcnR5Ml0pLFxuICAgICAgdmVjdG9yLnBhcnR5MixcbiAgICAgIHR4UmVxdWVzdC50cmFuc2FjdGlvbnMhWzBdLnVuc2lnbmVkVHguZGVyaXZhdGlvblBhdGgsXG4gICAgICBoYXNoQnVmZmVyXG4gICAgKTtcbiAgICAvLyAvLyBSb3VuZCAxIC8vLy9cbiAgICBjb25zdCB3YWxsZXREYXRhID0ge1xuICAgICAgaWQ6IHR4UmVxdWVzdC53YWxsZXRJZCxcbiAgICAgIGVudGVycHJpc2U6IHR4UmVxdWVzdC5lbnRlcnByaXNlSWQsXG4gICAgICBjb2luOiBjb2luTmFtZSxcbiAgICAgIGNvaW5TcGVjaWZpYzoge30sXG4gICAgICBtdWx0aXNpZ1R5cGU6ICd0c3MnLFxuICAgICAgbXVsdGlzaWdUeXBlVmVyc2lvbjogJ01QQ3YyJyxcbiAgICB9O1xuICAgIHdhbGxldCA9IG5ldyBXYWxsZXQoYml0Z28sIGJhc2VDb2luLCB3YWxsZXREYXRhKTtcbiAgICB0c3NVdGlscyA9IG5ldyBFQ0RTQVV0aWxzLkVjZHNhTVBDdjJVdGlscyhiaXRnbywgYmFzZUNvaW4sIHdhbGxldCk7XG4gIH0pO1xuXG4gIGJlZm9yZUVhY2goYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGF3YWl0IG5vY2tHZXRCaXRnb1B1YmxpY0tleUJhc2VkT25GZWF0dXJlRmxhZ3MoY29pbk5hbWUsIHR4UmVxdWVzdC5lbnRlcnByaXNlSWQhLCBiaXRnb0dwZ0tleSk7XG4gIH0pO1xuXG4gIGFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICBub2NrLmNsZWFuQWxsKCk7XG4gIH0pO1xuXG4gIGFmdGVyRWFjaChmdW5jdGlvbiAoKSB7XG4gICAgYml0Z29QYXJ0eS5lbmRTZXNzaW9uKCk7XG4gICAgbm9jay5jbGVhbkFsbCgpO1xuICB9KTtcblxuICBpdCgnc3VjY2Vzc2Z1bGx5IHNpZ25zIGEgdHhSZXF1ZXN0IHdpdGggdXNlciBrZXkgZm9yIGEgZGtscyBob3Qgd2FsbGV0IHdpdGggV1AnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgbm9ja1Byb21pc2VzID0gW1xuICAgICAgYXdhaXQgbm9ja1R4UmVxdWVzdFJlc3BvbnNlU2lnbmF0dXJlU2hhcmVSb3VuZE9uZShiaXRnb1BhcnR5LCB0eFJlcXVlc3QsIGJpdGdvR3BnS2V5KSxcbiAgICAgIGF3YWl0IG5vY2tUeFJlcXVlc3RSZXNwb25zZVNpZ25hdHVyZVNoYXJlUm91bmRUd28oYml0Z29QYXJ0eSwgdHhSZXF1ZXN0LCBiaXRnb0dwZ0tleSksXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kVGhyZWUodHhSZXF1ZXN0KSxcbiAgICAgIGF3YWl0IG5vY2tTZW5kVHhSZXF1ZXN0KHR4UmVxdWVzdCksXG4gICAgXTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChub2NrUHJvbWlzZXMpO1xuXG4gICAgY29uc3QgdXNlclNoYXJlID0gZnMucmVhZEZpbGVTeW5jKHNoYXJlRmlsZXNbdmVjdG9yLnBhcnR5MV0pO1xuICAgIGNvbnN0IHVzZXJQcnZCYXNlNjQgPSBCdWZmZXIuZnJvbSh1c2VyU2hhcmUpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICBhd2FpdCB0c3NVdGlscy5zaWduVHhSZXF1ZXN0KHtcbiAgICAgIHR4UmVxdWVzdCxcbiAgICAgIHBydjogdXNlclBydkJhc2U2NCxcbiAgICAgIHJlcUlkLFxuICAgIH0pO1xuICAgIG5vY2tQcm9taXNlc1swXS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIG5vY2tQcm9taXNlc1sxXS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIG5vY2tQcm9taXNlc1syXS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICB9KTtcblxuICBpdCgnc3VjY2Vzc2Z1bGx5IHNpZ25zIHdoZW4gcmVjaXBpZW50U291cmNlIGlzIGV4cGxpY2l0IGFuZCB0eFBhcmFtcy5yZWNpcGllbnRzIGlzIG5vbi1lbXB0eScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBub2NrUHJvbWlzZXMgPSBbXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kT25lKGJpdGdvUGFydHksIHR4UmVxdWVzdCwgYml0Z29HcGdLZXkpLFxuICAgICAgYXdhaXQgbm9ja1R4UmVxdWVzdFJlc3BvbnNlU2lnbmF0dXJlU2hhcmVSb3VuZFR3byhiaXRnb1BhcnR5LCB0eFJlcXVlc3QsIGJpdGdvR3BnS2V5KSxcbiAgICAgIGF3YWl0IG5vY2tUeFJlcXVlc3RSZXNwb25zZVNpZ25hdHVyZVNoYXJlUm91bmRUaHJlZSh0eFJlcXVlc3QpLFxuICAgICAgYXdhaXQgbm9ja1NlbmRUeFJlcXVlc3QodHhSZXF1ZXN0KSxcbiAgICBdO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKG5vY2tQcm9taXNlcyk7XG5cbiAgICBjb25zdCB1c2VyU2hhcmUgPSBmcy5yZWFkRmlsZVN5bmMoc2hhcmVGaWxlc1t2ZWN0b3IucGFydHkxXSk7XG4gICAgY29uc3QgdXNlclBydkJhc2U2NCA9IEJ1ZmZlci5mcm9tKHVzZXJTaGFyZSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgIGF3YWl0IHRzc1V0aWxzLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgdHhSZXF1ZXN0LFxuICAgICAgcHJ2OiB1c2VyUHJ2QmFzZTY0LFxuICAgICAgcmVxSWQsXG4gICAgICByZWNpcGllbnRTb3VyY2U6IFRzc1R4UmVjaXBpZW50U291cmNlLkV4cGxpY2l0LFxuICAgICAgdHhQYXJhbXM6IHtcbiAgICAgICAgcmVjaXBpZW50czogW3sgYWRkcmVzczogJzB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMScsIGFtb3VudDogJzEnIH1dLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBub2NrUHJvbWlzZXNbMF0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICBub2NrUHJvbWlzZXNbMV0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICBub2NrUHJvbWlzZXNbMl0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgfSk7XG5cbiAgaXQoJ3JlamVjdHMgd2hlbiByZWNpcGllbnRTb3VyY2UgaXMgZXhwbGljaXQgYW5kIHR4UGFyYW1zLnJlY2lwaWVudHMgaXMgZW1wdHknLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3QgdXNlclNoYXJlID0gZnMucmVhZEZpbGVTeW5jKHNoYXJlRmlsZXNbdmVjdG9yLnBhcnR5MV0pO1xuICAgIGNvbnN0IHVzZXJQcnZCYXNlNjQgPSBCdWZmZXIuZnJvbSh1c2VyU2hhcmUpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICAvLyBDYXN0IGJ5cGFzc2VzIHRoZSBjb21waWxlLXRpbWUgbm9uLWVtcHR5IHJlY2lwaWVudHMgY29uc3RyYWludCB0byBleGVyY2lzZSB0aGUgcnVudGltZSBndWFyZC5cbiAgICBhd2FpdCB0c3NVdGlsc1xuICAgICAgLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgICB0eFJlcXVlc3QsXG4gICAgICAgIHBydjogdXNlclBydkJhc2U2NCxcbiAgICAgICAgcmVxSWQsXG4gICAgICAgIHJlY2lwaWVudFNvdXJjZTogVHNzVHhSZWNpcGllbnRTb3VyY2UuRXhwbGljaXQsXG4gICAgICAgIHR4UGFyYW1zOiB7IHJlY2lwaWVudHM6IFtdIH0sXG4gICAgICB9IGFzIGFueSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdyZWNpcGllbnRTb3VyY2UgXCJleHBsaWNpdFwiIHJlcXVpcmVzIHR4UGFyYW1zLnJlY2lwaWVudHMgd2l0aCBhdCBsZWFzdCBvbmUgcmVjaXBpZW50LicpO1xuICB9KTtcblxuICBpdCgnc3VjY2Vzc2Z1bGx5IHNpZ25zIGEgdHhSZXF1ZXN0IHdpdGggYmFja3VwIGtleSBmb3IgYSBka2xzIGhvdCB3YWxsZXQgd2l0aCBXUCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBub2NrUHJvbWlzZXMgPSBbXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kT25lKGJpdGdvUGFydHksIHR4UmVxdWVzdCwgYml0Z29HcGdLZXksIDEpLFxuICAgICAgYXdhaXQgbm9ja1R4UmVxdWVzdFJlc3BvbnNlU2lnbmF0dXJlU2hhcmVSb3VuZFR3byhiaXRnb1BhcnR5LCB0eFJlcXVlc3QsIGJpdGdvR3BnS2V5LCAxKSxcbiAgICAgIGF3YWl0IG5vY2tUeFJlcXVlc3RSZXNwb25zZVNpZ25hdHVyZVNoYXJlUm91bmRUaHJlZSh0eFJlcXVlc3QpLFxuICAgICAgYXdhaXQgbm9ja1NlbmRUeFJlcXVlc3QodHhSZXF1ZXN0KSxcbiAgICBdO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKG5vY2tQcm9taXNlcyk7XG5cbiAgICBjb25zdCBiYWNrdXBTaGFyZSA9IGZzLnJlYWRGaWxlU3luYyhzaGFyZUZpbGVzW3ZlY3Rvci5wYXJ0eTNdKTtcbiAgICBjb25zdCBiYWNrdXBQcnZCYXNlNjQgPSBCdWZmZXIuZnJvbShiYWNrdXBTaGFyZSkudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgIGF3YWl0IHRzc1V0aWxzLnNpZ25UeFJlcXVlc3Qoe1xuICAgICAgdHhSZXF1ZXN0LFxuICAgICAgcHJ2OiBiYWNrdXBQcnZCYXNlNjQsXG4gICAgICBtcGN2MlBhcnR5SWQ6IDEsXG4gICAgICByZXFJZCxcbiAgICB9KTtcbiAgICBub2NrUHJvbWlzZXNbMF0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICBub2NrUHJvbWlzZXNbMV0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICBub2NrUHJvbWlzZXNbMl0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgfSk7XG5cbiAgaXQoJ3N1Y2Nlc3NmdWxseSBzaWducyBhIHR4UmVxdWVzdCB3aXRoIGEgbWVzc2FnZSBmb3IgYSBka2xzIGhvdCB3YWxsZXQgd2l0aCBXUCcsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBub2NrUHJvbWlzZXMgPSBbXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kT25lKGJpdGdvUGFydHksIHR4UmVxdWVzdEZvck1lc3NhZ2VTaWduaW5nLCBiaXRnb0dwZ0tleSksXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kVHdvKGJpdGdvUGFydHksIHR4UmVxdWVzdEZvck1lc3NhZ2VTaWduaW5nLCBiaXRnb0dwZ0tleSksXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kVGhyZWUodHhSZXF1ZXN0Rm9yTWVzc2FnZVNpZ25pbmcpLFxuICAgICAgYXdhaXQgbm9ja1NlbmRUeFJlcXVlc3QodHhSZXF1ZXN0Rm9yTWVzc2FnZVNpZ25pbmcpLFxuICAgIF07XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwobm9ja1Byb21pc2VzKTtcblxuICAgIGNvbnN0IHVzZXJTaGFyZSA9IGZzLnJlYWRGaWxlU3luYyhzaGFyZUZpbGVzW3ZlY3Rvci5wYXJ0eTFdKTtcbiAgICBjb25zdCB1c2VyUHJ2QmFzZTY0ID0gQnVmZmVyLmZyb20odXNlclNoYXJlKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgYXdhaXQgdHNzVXRpbHMuc2lnblR4UmVxdWVzdCh7XG4gICAgICB0eFJlcXVlc3QsXG4gICAgICBwcnY6IHVzZXJQcnZCYXNlNjQsXG4gICAgICByZXFJZCxcbiAgICB9KTtcbiAgICBub2NrUHJvbWlzZXNbMF0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICBub2NrUHJvbWlzZXNbMV0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgICBub2NrUHJvbWlzZXNbMl0uaXNEb25lKCkuc2hvdWxkLmJlLnRydWUoKTtcbiAgfSk7XG5cbiAgaXQoJ3N1Y2Nlc3NmdWxseSBzaWducyBhIHR4UmVxdWVzdCBmb3IgYSBka2xzIGhvdCB3YWxsZXQgYWZ0ZXIgcmVjZWl2aW5nIG11bHRpcGxlIDQyOSBlcnJvcnMnLCBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgY29uc3Qgbm9ja1Byb21pc2VzID0gW1xuICAgICAgYXdhaXQgbm9ja1R4UmVxdWVzdFJlc3BvbnNlU2lnbmF0dXJlU2hhcmVSb3VuZE9uZShiaXRnb1BhcnR5LCB0eFJlcXVlc3QsIGJpdGdvR3BnS2V5KSxcbiAgICAgIGF3YWl0IG5vY2tUeFJlcXVlc3RSZXNwb25zZVNpZ25hdHVyZVNoYXJlUm91bmRUd28oYml0Z29QYXJ0eSwgdHhSZXF1ZXN0LCBiaXRnb0dwZ0tleSwgMCwgMyksXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kVGhyZWUodHhSZXF1ZXN0KSxcbiAgICAgIGF3YWl0IG5vY2tTZW5kVHhSZXF1ZXN0KHR4UmVxdWVzdCksXG4gICAgXTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChub2NrUHJvbWlzZXMpO1xuXG4gICAgY29uc3QgdXNlclNoYXJlID0gZnMucmVhZEZpbGVTeW5jKHNoYXJlRmlsZXNbdmVjdG9yLnBhcnR5MV0pO1xuICAgIGNvbnN0IHVzZXJQcnZCYXNlNjQgPSBCdWZmZXIuZnJvbSh1c2VyU2hhcmUpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICBhd2FpdCB0c3NVdGlscy5zaWduVHhSZXF1ZXN0KHtcbiAgICAgIHR4UmVxdWVzdCxcbiAgICAgIHBydjogdXNlclBydkJhc2U2NCxcbiAgICAgIHJlcUlkLFxuICAgIH0pO1xuICAgIG5vY2tQcm9taXNlc1swXS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIG5vY2tQcm9taXNlc1sxXS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIG5vY2tQcm9taXNlc1syXS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICB9KTtcblxuICBkZXNjcmliZSgndjIgZW5jcnlwdGlvbiAob2ZmbGluZSByb3VuZHMgd2l0aCBhZGF0YSknLCBmdW5jdGlvbiAoKSB7XG4gICAgaXQoJ2UyZTogMy1yb3VuZCBvZmZsaW5lIHNpZ25pbmcgd2l0aCB2MiBlbmNyeXB0ZWQga2V5cyBwcmVzZXJ2ZXMgYWRhdGEgY29udGV4dCBiaW5kaW5nJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3Qgd2FsbGV0UGFzc3BocmFzZSA9ICd0ZXN0cGFzc3BocmFzZSc7XG4gICAgICBjb25zdCB1c2VyU2hhcmUgPSBmcy5yZWFkRmlsZVN5bmMoc2hhcmVGaWxlc1t2ZWN0b3IucGFydHkxXSk7XG4gICAgICBjb25zdCB1c2VyUHJ2QmFzZTY0ID0gQnVmZmVyLmZyb20odXNlclNoYXJlKS50b1N0cmluZygnYmFzZTY0Jyk7XG5cbiAgICAgIGNvbnN0IGVuY3J5cHRlZFBydiA9IGF3YWl0IGJpdGdvLmVuY3J5cHQoe1xuICAgICAgICBpbnB1dDogdXNlclBydkJhc2U2NCxcbiAgICAgICAgcGFzc3dvcmQ6IHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIGVuY3J5cHRpb25WZXJzaW9uOiAyLFxuICAgICAgfSk7XG4gICAgICBKU09OLnBhcnNlKGVuY3J5cHRlZFBydikudi5zaG91bGQuZXF1YWwoMik7XG5cbiAgICAgIGNvbnN0IHJvdW5kMVJlc3VsdCA9IGF3YWl0IHRzc1V0aWxzLmNyZWF0ZU9mZmxpbmVSb3VuZDFTaGFyZSh7XG4gICAgICAgIHR4UmVxdWVzdCxcbiAgICAgICAgcHJ2OiB1c2VyUHJ2QmFzZTY0LFxuICAgICAgICB3YWxsZXRQYXNzcGhyYXNlLFxuICAgICAgICBlbmNyeXB0ZWRQcnYsXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcjFTZXNzaW9uRW52ZWxvcGUgPSBKU09OLnBhcnNlKHJvdW5kMVJlc3VsdC5lbmNyeXB0ZWRSb3VuZDFTZXNzaW9uKTtcbiAgICAgIHIxU2Vzc2lvbkVudmVsb3BlLnYuc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgcjFTZXNzaW9uRW52ZWxvcGUuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2FkYXRhJyk7XG4gICAgICByMVNlc3Npb25FbnZlbG9wZS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnaGtkZlNhbHQnKTtcbiAgICAgIHIxU2Vzc2lvbkVudmVsb3BlLmFkYXRhLnNob3VsZC5jb250YWluRXFsKCdES0xTMjNfU0lHTklOR19ST1VORDFfU1RBVEUnKTtcblxuICAgICAgY29uc3QgcjFHcGdFbnZlbG9wZSA9IEpTT04ucGFyc2Uocm91bmQxUmVzdWx0LmVuY3J5cHRlZFVzZXJHcGdQcnZLZXkpO1xuICAgICAgcjFHcGdFbnZlbG9wZS52LnNob3VsZC5lcXVhbCgyKTtcbiAgICAgIHIxR3BnRW52ZWxvcGUuc2hvdWxkLmhhdmUucHJvcGVydHkoJ2FkYXRhJyk7XG4gICAgICByMUdwZ0VudmVsb3BlLmFkYXRhLnNob3VsZC5jb250YWluRXFsKCdES0xTMjNfU0lHTklOR19VU0VSX0dQR19LRVknKTtcblxuICAgICAgYXdhaXQgbm9ja1R4UmVxdWVzdFJlc3BvbnNlU2lnbmF0dXJlU2hhcmVSb3VuZE9uZShiaXRnb1BhcnR5LCB0eFJlcXVlc3QsIGJpdGdvR3BnS2V5KTtcbiAgICAgIGNvbnN0IHRyYW5zYWN0aW9ucyA9IGdldFJvdXRlKCdlY2RzYScpO1xuICAgICAgY29uc3Qgcm91bmQxVHhSZXF1ZXN0UmVzcG9uc2UgPSBhd2FpdCBiaXRnb1xuICAgICAgICAucG9zdChiaXRnby51cmwoYC93YWxsZXQvJHt0eFJlcXVlc3Qud2FsbGV0SWR9L3R4cmVxdWVzdHMvJHt0eFJlcXVlc3QudHhSZXF1ZXN0SWQgKyB0cmFuc2FjdGlvbnN9L3NpZ25gLCAyKSlcbiAgICAgICAgLnNlbmQoe1xuICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogW3JvdW5kMVJlc3VsdC5zaWduYXR1cmVTaGFyZVJvdW5kMV0sXG4gICAgICAgICAgc2lnbmVyR3BnUHVibGljS2V5OiByb3VuZDFSZXN1bHQudXNlckdwZ1B1YktleSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3VsdCgpO1xuXG4gICAgICBjb25zdCByb3VuZDFUeFJlcTogVHhSZXF1ZXN0ID0ge1xuICAgICAgICAuLi50eFJlcXVlc3QsXG4gICAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIC4uLnR4UmVxdWVzdC50cmFuc2FjdGlvbnMhWzBdLFxuICAgICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiByb3VuZDFUeFJlcXVlc3RSZXNwb25zZS50cmFuc2FjdGlvbnNbMF0uc2lnbmF0dXJlU2hhcmVzLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByb3VuZDJSZXN1bHQgPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQyU2hhcmUoe1xuICAgICAgICB0eFJlcXVlc3Q6IHJvdW5kMVR4UmVxLFxuICAgICAgICBwcnY6IHVzZXJQcnZCYXNlNjQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleS5wdWJsaWNLZXksXG4gICAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHJvdW5kMVJlc3VsdC5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICBlbmNyeXB0ZWRSb3VuZDFTZXNzaW9uOiByb3VuZDFSZXN1bHQuZW5jcnlwdGVkUm91bmQxU2Vzc2lvbixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByMkVudmVsb3BlID0gSlNPTi5wYXJzZShyb3VuZDJSZXN1bHQuZW5jcnlwdGVkUm91bmQyU2Vzc2lvbik7XG4gICAgICByMkVudmVsb3BlLnYuc2hvdWxkLmVxdWFsKDIpO1xuICAgICAgcjJFbnZlbG9wZS5zaG91bGQuaGF2ZS5wcm9wZXJ0eSgnYWRhdGEnKTtcbiAgICAgIHIyRW52ZWxvcGUuYWRhdGEuc2hvdWxkLmNvbnRhaW5FcWwoJ0RLTFMyM19TSUdOSU5HX1JPVU5EMl9TVEFURScpO1xuXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kVHdvKGJpdGdvUGFydHksIHR4UmVxdWVzdCwgYml0Z29HcGdLZXkpO1xuICAgICAgY29uc3Qgcm91bmQyVHhSZXF1ZXN0UmVzcG9uc2UgPSBhd2FpdCBiaXRnb1xuICAgICAgICAucG9zdChiaXRnby51cmwoYC93YWxsZXQvJHt0eFJlcXVlc3Qud2FsbGV0SWR9L3R4cmVxdWVzdHMvJHt0eFJlcXVlc3QudHhSZXF1ZXN0SWQgKyB0cmFuc2FjdGlvbnN9L3NpZ25gLCAyKSlcbiAgICAgICAgLnNlbmQoe1xuICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogW3JvdW5kMlJlc3VsdC5zaWduYXR1cmVTaGFyZVJvdW5kMl0sXG4gICAgICAgICAgc2lnbmVyR3BnUHVibGljS2V5OiByb3VuZDFSZXN1bHQudXNlckdwZ1B1YktleSxcbiAgICAgICAgfSlcbiAgICAgICAgLnJlc3VsdCgpO1xuXG4gICAgICBjb25zdCByb3VuZDJUeFJlcTogVHhSZXF1ZXN0ID0ge1xuICAgICAgICAuLi50eFJlcXVlc3QsXG4gICAgICAgIHRyYW5zYWN0aW9uczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIC4uLnR4UmVxdWVzdC50cmFuc2FjdGlvbnMhWzBdLFxuICAgICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiByb3VuZDJUeFJlcXVlc3RSZXNwb25zZS50cmFuc2FjdGlvbnNbMF0uc2lnbmF0dXJlU2hhcmVzLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCByb3VuZDNSZXN1bHQgPSBhd2FpdCB0c3NVdGlscy5jcmVhdGVPZmZsaW5lUm91bmQzU2hhcmUoe1xuICAgICAgICB0eFJlcXVlc3Q6IHJvdW5kMlR4UmVxLFxuICAgICAgICBwcnY6IHVzZXJQcnZCYXNlNjQsXG4gICAgICAgIHdhbGxldFBhc3NwaHJhc2UsXG4gICAgICAgIGJpdGdvUHVibGljR3BnS2V5OiBiaXRnb0dwZ0tleS5wdWJsaWNLZXksXG4gICAgICAgIGVuY3J5cHRlZFVzZXJHcGdQcnZLZXk6IHJvdW5kMVJlc3VsdC5lbmNyeXB0ZWRVc2VyR3BnUHJ2S2V5LFxuICAgICAgICBlbmNyeXB0ZWRSb3VuZDJTZXNzaW9uOiByb3VuZDJSZXN1bHQuZW5jcnlwdGVkUm91bmQyU2Vzc2lvbixcbiAgICAgIH0pO1xuXG4gICAgICByb3VuZDNSZXN1bHQuc2hvdWxkLmhhdmUucHJvcGVydHkoJ3NpZ25hdHVyZVNoYXJlUm91bmQzJyk7XG4gICAgfSk7XG5cbiAgICBpdCgndmFsaWRhdGVBZGF0YSBhY2NlcHRzIHYyIGVudmVsb3BlcyB3aXRoIG1hdGNoaW5nIGFkYXRhIGFuZCBkb21haW4gc2VwYXJhdG9yJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgICAgY29uc3QgYWRhdGEgPSAndHhoYXNoOm0vMC8xJztcbiAgICAgIGNvbnN0IGRvbWFpblNlcCA9ICdES0xTMjNfU0lHTklOR19ST1VORDFfU1RBVEUnO1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBiaXRnby5lbmNyeXB0KHtcbiAgICAgICAgaW5wdXQ6ICd0ZXN0LWRhdGEnLFxuICAgICAgICBwYXNzd29yZDogJ3Rlc3RwYXNzJyxcbiAgICAgICAgZW5jcnlwdGlvblZlcnNpb246IDIsXG4gICAgICAgIGFkYXRhOiBgJHtkb21haW5TZXB9OiR7YWRhdGF9YCxcbiAgICAgIH0pO1xuXG4gICAgICAodHNzVXRpbHMgYXMgYW55KS52YWxpZGF0ZUFkYXRhKGFkYXRhLCBjdCwgZG9tYWluU2VwKTtcbiAgICB9KTtcblxuICAgIGl0KCd2YWxpZGF0ZUFkYXRhIHJlamVjdHMgdjIgZW52ZWxvcGVzIHdpdGggbWlzbWF0Y2hlZCBhZGF0YScsIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IGRvbWFpblNlcCA9ICdES0xTMjNfU0lHTklOR19ST1VORDFfU1RBVEUnO1xuICAgICAgY29uc3QgY3QgPSBhd2FpdCBiaXRnby5lbmNyeXB0KHtcbiAgICAgICAgaW5wdXQ6ICd0ZXN0LWRhdGEnLFxuICAgICAgICBwYXNzd29yZDogJ3Rlc3RwYXNzJyxcbiAgICAgICAgZW5jcnlwdGlvblZlcnNpb246IDIsXG4gICAgICAgIGFkYXRhOiBgJHtkb21haW5TZXB9OmNvbnRleHQtQWAsXG4gICAgICB9KTtcblxuICAgICAgKCgpID0+ICh0c3NVdGlscyBhcyBhbnkpLnZhbGlkYXRlQWRhdGEoJ2NvbnRleHQtQicsIGN0LCBkb21haW5TZXApKS5zaG91bGQudGhyb3coL0FkYXRhIGRvZXMgbm90IG1hdGNoLyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGl0KCdmYWlscyB0byBzaWducyBhIHR4UmVxdWVzdCBmb3IgYSBka2xzIGhvdCB3YWxsZXQgYWZ0ZXIgcmVjZWl2aW5nIG92ZXIgMyA0MjkgZXJyb3JzJywgYXN5bmMgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IG5vY2tQcm9taXNlcyA9IFtcbiAgICAgIGF3YWl0IG5vY2tUeFJlcXVlc3RSZXNwb25zZVNpZ25hdHVyZVNoYXJlUm91bmRPbmUoYml0Z29QYXJ0eSwgdHhSZXF1ZXN0LCBiaXRnb0dwZ0tleSksXG4gICAgICBhd2FpdCBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kVHdvKGJpdGdvUGFydHksIHR4UmVxdWVzdCwgYml0Z29HcGdLZXksIDAsIDQpLFxuICAgIF07XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwobm9ja1Byb21pc2VzKTtcblxuICAgIGNvbnN0IHVzZXJTaGFyZSA9IGZzLnJlYWRGaWxlU3luYyhzaGFyZUZpbGVzW3ZlY3Rvci5wYXJ0eTFdKTtcbiAgICBjb25zdCB1c2VyUHJ2QmFzZTY0ID0gQnVmZmVyLmZyb20odXNlclNoYXJlKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgYXdhaXQgdHNzVXRpbHNcbiAgICAgIC5zaWduVHhSZXF1ZXN0KHtcbiAgICAgICAgdHhSZXF1ZXN0LFxuICAgICAgICBwcnY6IHVzZXJQcnZCYXNlNjQsXG4gICAgICAgIHJlcUlkLFxuICAgICAgfSlcbiAgICAgIC5zaG91bGQuYmUucmVqZWN0ZWRXaXRoKCdUb28gbWFueSByZXF1ZXN0cywgc2xvdyBkb3duIScpO1xuICAgIG5vY2tQcm9taXNlc1swXS5pc0RvbmUoKS5zaG91bGQuYmUudHJ1ZSgpO1xuICAgIG5vY2tQcm9taXNlc1sxXS5pc0RvbmUoKS5zaG91bGQuYmUuZmFsc2UoKTtcbiAgfSk7XG59KTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJpdEdvUGFydHlHcGdLZXlQcnYoa2V5OiBvcGVucGdwLlNlcmlhbGl6ZWRLZXlQYWlyPHN0cmluZz4pOiBEa2xzVHlwZXMuUGFydHlHcGdLZXkge1xuICByZXR1cm4ge1xuICAgIHBhcnR5SWQ6IDIsXG4gICAgZ3BnS2V5OiBrZXkucHJpdmF0ZUtleSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVzZXJQYXJ0eUdwZ0tleVB1YmxpYyh1c2VyUHViS2V5OiBzdHJpbmcsIHBhcnR5SWQ6IDAgfCAxID0gMCk6IERrbHNUeXBlcy5QYXJ0eUdwZ0tleSB7XG4gIHJldHVybiB7XG4gICAgcGFydHlJZDogcGFydHlJZCxcbiAgICBncGdLZXk6IHVzZXJQdWJLZXksXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG5vY2tUeFJlcXVlc3RSZXNwb25zZVNpZ25hdHVyZVNoYXJlUm91bmRPbmUoXG4gIGJpdGdvU2Vzc2lvbjogRGtsc0RzZy5Ec2csXG4gIHR4UmVxdWVzdDogVHhSZXF1ZXN0LFxuICBiaXRnb0dwZ0tleTogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+LFxuICBwYXJ0eUlkOiAwIHwgMSA9IDBcbik6IFByb21pc2U8bm9jay5TY29wZT4ge1xuICBjb25zdCB0cmFuc2FjdGlvbnMgPSBnZXRSb3V0ZSgnZWNkc2EnKTtcbiAgcmV0dXJuIG5vY2soJ2h0dHBzOi8vYml0Z28uZmFrZXVybCcpXG4gICAgLnBlcnNpc3QodHJ1ZSlcbiAgICAucG9zdChcbiAgICAgIGAvYXBpL3YyL3dhbGxldC8ke3R4UmVxdWVzdC53YWxsZXRJZH0vdHhyZXF1ZXN0cy8ke3R4UmVxdWVzdC50eFJlcXVlc3RJZCArIHRyYW5zYWN0aW9uc30vc2lnbmAsXG4gICAgICAoYm9keSkgPT4gKEpTT04ucGFyc2UoYm9keS5zaWduYXR1cmVTaGFyZXNbMF0uc2hhcmUpIGFzIE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDFJbnB1dCkudHlwZSA9PT0gJ3JvdW5kMUlucHV0J1xuICAgIClcbiAgICAudGltZXMoMSlcbiAgICAucmVwbHkoMjAwLCBhc3luYyAodXJpLCBib2R5OiBTaWduYXR1cmVTaGFyZUFwaUJvZHkpID0+IHtcbiAgICAgIC8vIERvIHRoZSBhY3R1YWwgc2lnbmluZyBvbiBCaXRHbydzIHNpZGUgYmFzZWQgb24gVXNlcidzIG1lc3NhZ2VzXG4gICAgICBjb25zdCBzaWduYXR1cmVTaGFyZSA9IEpTT04ucGFyc2UoYm9keS5zaWduYXR1cmVTaGFyZXNbMF0uc2hhcmUpIGFzIE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDFJbnB1dDtcbiAgICAgIGNvbnN0IGRlc2VyaWFsaXplZE1lc3NhZ2VzID0gRGtsc1R5cGVzLmRlc2VyaWFsaXplTWVzc2FnZXMoe1xuICAgICAgICBwMnBNZXNzYWdlczogW10sXG4gICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgZnJvbTogc2lnbmF0dXJlU2hhcmUuZGF0YS5tc2cxLmZyb20sXG4gICAgICAgICAgICBwYXlsb2FkOiBzaWduYXR1cmVTaGFyZS5kYXRhLm1zZzEubWVzc2FnZSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSk7XG4gICAgICBpZiAoc2lnbmF0dXJlU2hhcmUudHlwZSA9PT0gJ3JvdW5kMUlucHV0Jykge1xuICAgICAgICBjb25zdCBiaXRnb1RvVXNlclJvdW5kMUJyb2FkY2FzdE1zZyA9IGF3YWl0IGJpdGdvU2Vzc2lvbi5pbml0KCk7XG5cbiAgICAgICAgY29uc3QgYml0Z29Ub1VzZXJSb3VuZDJNc2cgPSBiaXRnb1Nlc3Npb24uaGFuZGxlSW5jb21pbmdNZXNzYWdlcyh7XG4gICAgICAgICAgcDJwTWVzc2FnZXM6IFtdLFxuICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBkZXNlcmlhbGl6ZWRNZXNzYWdlcy5icm9hZGNhc3RNZXNzYWdlcyxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHNlcmlhbGl6ZWRCaXRHb1RvVXNlclJvdW5kMUFuZDJNc2dzID0gRGtsc1R5cGVzLnNlcmlhbGl6ZU1lc3NhZ2VzKHtcbiAgICAgICAgICBwMnBNZXNzYWdlczogYml0Z29Ub1VzZXJSb3VuZDJNc2cucDJwTWVzc2FnZXMsXG4gICAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtiaXRnb1RvVXNlclJvdW5kMUJyb2FkY2FzdE1zZ10sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGF1dGhFbmNNZXNzYWdlcyA9IGF3YWl0IERrbHNDb21tcy5lbmNyeXB0QW5kQXV0aE91dGdvaW5nTWVzc2FnZXMoXG4gICAgICAgICAgc2VyaWFsaXplZEJpdEdvVG9Vc2VyUm91bmQxQW5kMk1zZ3MsXG4gICAgICAgICAgW2dldFVzZXJQYXJ0eUdwZ0tleVB1YmxpYyhib2R5LnNpZ25lckdwZ1B1YmxpY0tleSwgcGFydHlJZCldLFxuICAgICAgICAgIFtnZXRCaXRHb1BhcnR5R3BnS2V5UHJ2KGJpdGdvR3BnS2V5KV1cbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBiaXRnb1RvVXNlclNpZ25hdHVyZVNoYXJlOiBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQxT3V0cHV0ID0ge1xuICAgICAgICAgIHR5cGU6ICdyb3VuZDFPdXRwdXQnLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIG1zZzE6IHtcbiAgICAgICAgICAgICAgZnJvbTogYXV0aEVuY01lc3NhZ2VzLmJyb2FkY2FzdE1lc3NhZ2VzWzBdLmZyb20gYXMgTVBDdjJQYXJ0eUZyb21TdHJpbmdPck51bWJlcixcbiAgICAgICAgICAgICAgc2lnbmF0dXJlOiBhdXRoRW5jTWVzc2FnZXMuYnJvYWRjYXN0TWVzc2FnZXNbMF0ucGF5bG9hZC5zaWduYXR1cmUsXG4gICAgICAgICAgICAgIG1lc3NhZ2U6IGF1dGhFbmNNZXNzYWdlcy5icm9hZGNhc3RNZXNzYWdlc1swXS5wYXlsb2FkLm1lc3NhZ2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbXNnMjoge1xuICAgICAgICAgICAgICBmcm9tOiBhdXRoRW5jTWVzc2FnZXMucDJwTWVzc2FnZXNbMF0uZnJvbSBhcyBNUEN2MlBhcnR5RnJvbVN0cmluZ09yTnVtYmVyLFxuICAgICAgICAgICAgICB0bzogYXV0aEVuY01lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdLnRvIGFzIE1QQ3YyUGFydHlGcm9tU3RyaW5nT3JOdW1iZXIsXG4gICAgICAgICAgICAgIGVuY3J5cHRlZE1lc3NhZ2U6IGF1dGhFbmNNZXNzYWdlcy5wMnBNZXNzYWdlc1swXS5wYXlsb2FkLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgICAgICAgIHNpZ25hdHVyZTogYXV0aEVuY01lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdLnBheWxvYWQuc2lnbmF0dXJlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgICAgICAgdHJhbnNhY3Rpb25zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHNpZ25hdHVyZVNoYXJlczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIGZyb206IFNpZ25hdHVyZVNoYXJlVHlwZS5CSVRHTyxcbiAgICAgICAgICAgICAgICAgIHRvOiBwYXJ0eUlkID09PSAwID8gU2lnbmF0dXJlU2hhcmVUeXBlLlVTRVIgOiBTaWduYXR1cmVTaGFyZVR5cGUuQkFDS1VQLFxuICAgICAgICAgICAgICAgICAgc2hhcmU6IEpTT04uc3RyaW5naWZ5KGJpdGdvVG9Vc2VyU2lnbmF0dXJlU2hhcmUpLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG5vY2tUeFJlcXVlc3RSZXNwb25zZVNpZ25hdHVyZVNoYXJlUm91bmRUd28oXG4gIGJpdGdvU2Vzc2lvbjogRGtsc0RzZy5Ec2csXG4gIHR4UmVxdWVzdDogVHhSZXF1ZXN0LFxuICBiaXRnb0dwZ0tleTogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+LFxuICBwYXJ0eUlkOiAwIHwgMSA9IDAsXG4gIHJhdGVMaW1pdEVycm9yQ291bnQgPSAwXG4pOiBQcm9taXNlPG5vY2suU2NvcGU+IHtcbiAgY29uc3QgdHJhbnNhY3Rpb25zID0gZ2V0Um91dGUoJ2VjZHNhJyk7XG4gIGNvbnN0IHNjb3BlID0gbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJyk7XG5cbiAgaWYgKHJhdGVMaW1pdEVycm9yQ291bnQgPiAwKSB7XG4gICAgc2NvcGVcbiAgICAgIC5wb3N0KFxuICAgICAgICBgL2FwaS92Mi93YWxsZXQvJHt0eFJlcXVlc3Qud2FsbGV0SWR9L3R4cmVxdWVzdHMvJHt0eFJlcXVlc3QudHhSZXF1ZXN0SWQgKyB0cmFuc2FjdGlvbnN9L3NpZ25gLFxuICAgICAgICAoYm9keSkgPT4gKEpTT04ucGFyc2UoYm9keS5zaWduYXR1cmVTaGFyZXNbMF0uc2hhcmUpIGFzIE1QQ3YyU2lnbmF0dXJlU2hhcmVSb3VuZDJJbnB1dCkudHlwZSA9PT0gJ3JvdW5kMklucHV0J1xuICAgICAgKVxuICAgICAgLnRpbWVzKHJhdGVMaW1pdEVycm9yQ291bnQpXG4gICAgICAucmVwbHkoNDI5LCB7XG4gICAgICAgIGVycm9yOiAnVG9vIG1hbnkgcmVxdWVzdHMsIHNsb3cgZG93biEnLFxuICAgICAgICBuYW1lOiAnVG9vTWFueVJlcXVlc3RzJyxcbiAgICAgICAgcmVxdWVzdElkOiAnY201cXgwMWxoMDAxM2IyZWsyc3hsNHcwMCcsXG4gICAgICAgIGNvbnRleHQ6IHt9LFxuICAgICAgfSk7XG4gIH1cbiAgcmV0dXJuIHNjb3BlXG4gICAgLnBvc3QoXG4gICAgICBgL2FwaS92Mi93YWxsZXQvJHt0eFJlcXVlc3Qud2FsbGV0SWR9L3R4cmVxdWVzdHMvJHt0eFJlcXVlc3QudHhSZXF1ZXN0SWQgKyB0cmFuc2FjdGlvbnN9L3NpZ25gLFxuICAgICAgKGJvZHkpID0+IChKU09OLnBhcnNlKGJvZHkuc2lnbmF0dXJlU2hhcmVzWzBdLnNoYXJlKSBhcyBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQySW5wdXQpLnR5cGUgPT09ICdyb3VuZDJJbnB1dCdcbiAgICApXG4gICAgLnRpbWVzKDEpXG4gICAgLnJlcGx5KDIwMCwgYXN5bmMgKHVyaSwgYm9keTogU2lnbmF0dXJlU2hhcmVBcGlCb2R5KSA9PiB7XG4gICAgICAvLyBEbyB0aGUgYWN0dWFsIHNpZ25pbmcgb24gQml0R28ncyBzaWRlIGJhc2VkIG9uIFVzZXIncyBtZXNzYWdlc1xuICAgICAgY29uc3QgcGFyc2VkU2lnbmF0dXJlU2hhcmUgPSBKU09OLnBhcnNlKGJvZHkuc2lnbmF0dXJlU2hhcmVzWzBdLnNoYXJlKSBhcyBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQySW5wdXQ7XG4gICAgICBjb25zdCBzZXJpYWxpemVkTWVzc2FnZXMgPSBhd2FpdCBEa2xzQ29tbXMuZGVjcnlwdEFuZFZlcmlmeUluY29taW5nTWVzc2FnZXMoXG4gICAgICAgIHtcbiAgICAgICAgICBwMnBNZXNzYWdlczogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBmcm9tOiBwYXJzZWRTaWduYXR1cmVTaGFyZS5kYXRhLm1zZzIuZnJvbSxcbiAgICAgICAgICAgICAgdG86IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMi50byxcbiAgICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICAgIGVuY3J5cHRlZE1lc3NhZ2U6IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMi5lbmNyeXB0ZWRNZXNzYWdlLFxuICAgICAgICAgICAgICAgIHNpZ25hdHVyZTogcGFyc2VkU2lnbmF0dXJlU2hhcmUuZGF0YS5tc2cyLnNpZ25hdHVyZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGZyb206IHBhcnNlZFNpZ25hdHVyZVNoYXJlLmRhdGEubXNnMy5mcm9tLFxuICAgICAgICAgICAgICB0bzogcGFyc2VkU2lnbmF0dXJlU2hhcmUuZGF0YS5tc2czLnRvLFxuICAgICAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICAgICAgZW5jcnlwdGVkTWVzc2FnZTogcGFyc2VkU2lnbmF0dXJlU2hhcmUuZGF0YS5tc2czLmVuY3J5cHRlZE1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgc2lnbmF0dXJlOiBwYXJzZWRTaWduYXR1cmVTaGFyZS5kYXRhLm1zZzMuc2lnbmF0dXJlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGJyb2FkY2FzdE1lc3NhZ2VzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgW2dldFVzZXJQYXJ0eUdwZ0tleVB1YmxpYyhib2R5LnNpZ25lckdwZ1B1YmxpY0tleSwgcGFydHlJZCldLFxuICAgICAgICBbZ2V0Qml0R29QYXJ0eUdwZ0tleVBydihiaXRnb0dwZ0tleSldXG4gICAgICApO1xuICAgICAgY29uc3QgZGVzZXJpYWxpemVkTWVzc2FnZXMgPSBEa2xzVHlwZXMuZGVzZXJpYWxpemVNZXNzYWdlcyh7XG4gICAgICAgIHAycE1lc3NhZ2VzOiBbc2VyaWFsaXplZE1lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdXSxcbiAgICAgICAgYnJvYWRjYXN0TWVzc2FnZXM6IFtdLFxuICAgICAgfSk7XG4gICAgICBpZiAocGFyc2VkU2lnbmF0dXJlU2hhcmUudHlwZSA9PT0gJ3JvdW5kMklucHV0Jykge1xuICAgICAgICBjb25zdCBiaXRnb1RvVXNlclJvdW5kM01zZyA9IGJpdGdvU2Vzc2lvbi5oYW5kbGVJbmNvbWluZ01lc3NhZ2VzKGRlc2VyaWFsaXplZE1lc3NhZ2VzKTtcbiAgICAgICAgY29uc3Qgc2VyaWFsaXplZEJpdEdvVG9Vc2VyUm91bmQzTXNncyA9IERrbHNUeXBlcy5zZXJpYWxpemVNZXNzYWdlcyhiaXRnb1RvVXNlclJvdW5kM01zZyk7XG5cbiAgICAgICAgY29uc3QgYXV0aEVuY01lc3NhZ2VzID0gYXdhaXQgRGtsc0NvbW1zLmVuY3J5cHRBbmRBdXRoT3V0Z29pbmdNZXNzYWdlcyhcbiAgICAgICAgICBzZXJpYWxpemVkQml0R29Ub1VzZXJSb3VuZDNNc2dzLFxuICAgICAgICAgIFtnZXRVc2VyUGFydHlHcGdLZXlQdWJsaWMoYm9keS5zaWduZXJHcGdQdWJsaWNLZXksIHBhcnR5SWQpXSxcbiAgICAgICAgICBbZ2V0Qml0R29QYXJ0eUdwZ0tleVBydihiaXRnb0dwZ0tleSldXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgYml0Z29Ub1VzZXJTaWduYXR1cmVTaGFyZTogTVBDdjJTaWduYXR1cmVTaGFyZVJvdW5kMk91dHB1dCA9IHtcbiAgICAgICAgICB0eXBlOiAncm91bmQyT3V0cHV0JyxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBtc2czOiB7XG4gICAgICAgICAgICAgIGZyb206IGF1dGhFbmNNZXNzYWdlcy5wMnBNZXNzYWdlc1swXS5mcm9tIGFzIE1QQ3YyUGFydHlGcm9tU3RyaW5nT3JOdW1iZXIsXG4gICAgICAgICAgICAgIHRvOiBhdXRoRW5jTWVzc2FnZXMucDJwTWVzc2FnZXNbMF0udG8gYXMgTVBDdjJQYXJ0eUZyb21TdHJpbmdPck51bWJlcixcbiAgICAgICAgICAgICAgZW5jcnlwdGVkTWVzc2FnZTogYXV0aEVuY01lc3NhZ2VzLnAycE1lc3NhZ2VzWzBdLnBheWxvYWQuZW5jcnlwdGVkTWVzc2FnZSxcbiAgICAgICAgICAgICAgc2lnbmF0dXJlOiBhdXRoRW5jTWVzc2FnZXMucDJwTWVzc2FnZXNbMF0ucGF5bG9hZC5zaWduYXR1cmUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgICAgICB0cmFuc2FjdGlvbnM6IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgc2lnbmF0dXJlU2hhcmVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgZnJvbTogcGFydHlJZCA9PT0gMCA/IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSIDogU2lnbmF0dXJlU2hhcmVUeXBlLkJBQ0tVUCxcbiAgICAgICAgICAgICAgICAgIHRvOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgICAgICAgICAgICBzaGFyZTogJ3NvbWUgb2xkIHNoYXJlIHdlIGRvbnQgY2FyZSBhYm91dCcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBmcm9tOiBTaWduYXR1cmVTaGFyZVR5cGUuQklUR08sXG4gICAgICAgICAgICAgICAgICB0bzogcGFydHlJZCA9PT0gMCA/IFNpZ25hdHVyZVNoYXJlVHlwZS5VU0VSIDogU2lnbmF0dXJlU2hhcmVUeXBlLkJBQ0tVUCxcbiAgICAgICAgICAgICAgICAgIHNoYXJlOiBKU09OLnN0cmluZ2lmeShiaXRnb1RvVXNlclNpZ25hdHVyZVNoYXJlKSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBub2NrVHhSZXF1ZXN0UmVzcG9uc2VTaWduYXR1cmVTaGFyZVJvdW5kVGhyZWUodHhSZXF1ZXN0OiBUeFJlcXVlc3QpOiBQcm9taXNlPG5vY2suU2NvcGU+IHtcbiAgY29uc3QgdHJhbnNhY3Rpb25zID0gZ2V0Um91dGUoJ2VjZHNhJyk7XG4gIHJldHVybiBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgIC5wb3N0KFxuICAgICAgYC9hcGkvdjIvd2FsbGV0LyR7dHhSZXF1ZXN0LndhbGxldElkfS90eHJlcXVlc3RzLyR7dHhSZXF1ZXN0LnR4UmVxdWVzdElkICsgdHJhbnNhY3Rpb25zfS9zaWduYCxcbiAgICAgIChib2R5OiBTaWduYXR1cmVTaGFyZUFwaUJvZHkpID0+XG4gICAgICAgIChKU09OLnBhcnNlKGJvZHkuc2lnbmF0dXJlU2hhcmVzWzBdLnNoYXJlKSBhcyBNUEN2MlNpZ25hdHVyZVNoYXJlUm91bmQzSW5wdXQpLnR5cGUgPT09ICdyb3VuZDNJbnB1dCdcbiAgICApXG4gICAgLnRpbWVzKDEpXG4gICAgLnJlcGx5KDIwMCwgYXN5bmMgKHVyaSwgYm9keSkgPT4ge1xuICAgICAgLy8gRG8gdGhlIGFjdHVhbCBzaWduaW5nIG9uIEJpdEdvJ3Mgc2lkZSBiYXNlZCBvbiBVc2VyJ3MgbWVzc2FnZXNcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHhSZXF1ZXN0SWQ6IHR4UmVxdWVzdC50eFJlcXVlc3RJZCxcbiAgICAgIH07XG4gICAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG5vY2tTZW5kVHhSZXF1ZXN0KHR4UmVxdWVzdDogVHhSZXF1ZXN0KTogUHJvbWlzZTxub2NrLlNjb3BlPiB7XG4gIGNvbnN0IHRyYW5zYWN0aW9ucyA9IGdldFJvdXRlKCdlY2RzYScpO1xuICByZXR1cm4gbm9jaygnaHR0cHM6Ly9iaXRnby5mYWtldXJsJylcbiAgICAucG9zdChgL2FwaS92Mi93YWxsZXQvJHt0eFJlcXVlc3Qud2FsbGV0SWR9L3R4cmVxdWVzdHMvJHt0eFJlcXVlc3QudHhSZXF1ZXN0SWQgKyB0cmFuc2FjdGlvbnN9L3NlbmRgKVxuICAgIC50aW1lcygxKVxuICAgIC5yZXBseSgyMDAsIHtcbiAgICAgIHR4UmVxdWVzdElkOiB0eFJlcXVlc3QudHhSZXF1ZXN0SWQsXG4gICAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG5vY2tHZXRCaXRnb1B1YmxpY0tleUJhc2VkT25GZWF0dXJlRmxhZ3MoXG4gIGNvaW46IHN0cmluZyxcbiAgZW50ZXJwcmlzZUlkOiBzdHJpbmcsXG4gIGJpdGdvR3BnS2V5UGFpcjogb3BlbnBncC5TZXJpYWxpemVkS2V5UGFpcjxzdHJpbmc+XG4pOiBQcm9taXNlPEJpdGdvR1BHUHVibGljS2V5PiB7XG4gIGNvbnN0IGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2U6IEJpdGdvR1BHUHVibGljS2V5ID0ge1xuICAgIG5hbWU6ICdpcnJlbGV2YW50JyxcbiAgICBwdWJsaWNLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgbXBjdjJQdWJsaWNLZXk6IGJpdGdvR3BnS2V5UGFpci5wdWJsaWNLZXksXG4gICAgZW50ZXJwcmlzZUlkLFxuICB9O1xuICBub2NrKCdodHRwczovL2JpdGdvLmZha2V1cmwnKVxuICAgIC5nZXQoYC9hcGkvdjIvJHtjb2lufS90c3MvcHVia2V5YClcbiAgICAudGltZXMoNClcbiAgICAucXVlcnkoeyBlbnRlcnByaXNlSWQgfSlcbiAgICAucmVwbHkoMjAwLCBiaXRnb0dQR1B1YmxpY0tleVJlc3BvbnNlKTtcbiAgcmV0dXJuIGJpdGdvR1BHUHVibGljS2V5UmVzcG9uc2U7XG59XG4iXX0=