UNPKG

bitgo

Version:
507 lines • 83.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const sdk_core_1 = require("@bitgo/sdk-core"); const sdk_lib_mpc_1 = require("@bitgo/sdk-lib-mpc"); const openpgp = require("openpgp"); const nock = require("nock"); const sdk_test_1 = require("@bitgo/sdk-test"); const src_1 = require("../../../../../../src"); const MPCv2PartiesEnum = sdk_core_1.ECDSAUtils.MPCv2PartiesEnum; describe('signTxRequest:', function () { let tssUtils; let wallet; let bitgo; let baseCoin; let bitgoGpgKey; let bitgoPrvKeyObj; const coinName = 'sol'; const reqId = new sdk_core_1.RequestTracer(); const txRequestId = 'randomTxReqId'; const signableHex = '02010206c2d5b5f4fb9a9bcd8a2f303e4d06f78d8ded300713f456da2abff0b3ea0185aa051a34bc8acd438763976f96876115050f73828553566d111d7ac8bffebf587c4f5f5987bfe26aa66013efd96d36360f2b4336c91f993259fb56051305614d42f2ea13f8ff9d7958dbf269c6e36bfdf5cb5c43de4b4e1d3efb7dab3d5d028604000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000003a621f6d1cc4b8fb2a739aa08e4034da0fc588ece3bd857630de30f7edde45dd0204030205010404000000040200030c02000000f0a29a3b00000000'; const serializedTxHex = `02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003bc9df0b397bec2ed3b6444a8c33f38267cc08b5fb2a7d37e26b6c487e26d15b7c07830eb78e26a88db5de4aa6986a327f09aed8c01533e5b972748ddf60b80f${signableHex}`; const messageRaw = 'TOO MANY SECRETS'; const messageEncoded = Buffer.from(messageRaw).toString('hex'); const txParams = { recipients: [ { address: 'HMEgbR4S2hLKfst2VZUVpHVUu4FioFPyW5iUuJvZdMvs', amount: '999990000', }, ], }; const txRequest = { txRequestId, enterpriseId: '4517abfb-f567-4b7a-9f91-407509d29403', transactions: [ { unsignedTx: { serializedTxHex, 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, messageEncoded, 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', }; let userKeyShare; let backupKeyShare; let bitgoKeyShare; 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', email: 'bitgo@test.com' }], curve: 'ed25519', format: 'armored', }); bitgoPrvKeyObj = await openpgp.readPrivateKey({ armoredKey: bitgoGpgKey.privateKey }); const constants = { mpc: { bitgoPublicKey: bitgoGpgKey.publicKey, bitgoEddsaMpcv2PublicKey: bitgoGpgKey.publicKey, }, }; nock(bgUrl).get('/api/v1/client/constants').times(20).reply(200, { ttl: 3600, constants }); const [userDkg, backupDkg, bitgoDkg] = await sdk_lib_mpc_1.MPSUtil.generateEdDsaDKGKeyShares(); userKeyShare = userDkg.getKeyShare(); backupKeyShare = backupDkg.getKeyShare(); bitgoKeyShare = bitgoDkg.getKeyShare(); baseCoin = bitgo.coin(coinName); const walletData = { id: txRequest.walletId, enterprise: txRequest.enterpriseId, coin: coinName, coinSpecific: { rootAddress: 'E7Z6pFfUhjx2dFjdB9Ws2KnKepXoq62TeF5uaCVSvqQV', }, multisigType: 'tss', multisigTypeVersion: 'MPCv2', }; wallet = new sdk_core_1.Wallet(bitgo, baseCoin, walletData); tssUtils = new sdk_core_1.EDDSAUtils.EddsaMPCv2Utils(bitgo, baseCoin, wallet); }); beforeEach(async function () { await nockGetBitgoPublicKeyBasedOnFeatureFlags(coinName, txRequest.enterpriseId, bitgoGpgKey); }); after(function () { nock.cleanAll(); }); afterEach(function () { nock.cleanAll(); }); it('successfully signs a txRequest with user key for an mps hot wallet with WP', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequest); await Promise.all(nockPromises); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils.signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams, }); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.true(); nockPromises[2].isDone().should.be.true(); nockPromises[3].isDone().should.be.true(); }); it('successfully signs a txRequest with backup key for an mps hot wallet with WP', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequest, sdk_core_1.RequestType.tx, 0, MPCv2PartiesEnum.BACKUP); await Promise.all(nockPromises); const backupPrvBase64 = Buffer.from(backupKeyShare).toString('base64'); await tssUtils.signTxRequest({ txRequest, prv: backupPrvBase64, mpcv2PartyId: MPCv2PartiesEnum.BACKUP, reqId, txParams, }); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.true(); nockPromises[2].isDone().should.be.true(); nockPromises[3].isDone().should.be.true(); }); it('successfully signs a txRequest with a message for an mps hot wallet with WP', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequestForMessageSigning, sdk_core_1.RequestType.message); await Promise.all(nockPromises); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils.signTxRequestForMessage({ txRequest: txRequestForMessageSigning, prv: userPrvBase64, reqId, messageRaw: txRequestForMessageSigning.messages[0].messageRaw, bufferToSign: Buffer.from(messageEncoded, 'hex'), }); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.true(); nockPromises[2].isDone().should.be.true(); nockPromises[3].isDone().should.be.true(); }); it('should throw if round 1 response has wrong type', async function () { nock('https://bitgo.fakeurl') .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId}/transactions/0/sign`) .reply(200, { txRequestId, transactions: [ { signatureShares: [ { from: sdk_core_1.SignatureShareType.BITGO, to: sdk_core_1.SignatureShareType.USER, share: JSON.stringify({ type: 'round2Output', data: {} }), }, ], }, ], }); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils .signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams }) .should.be.rejectedWith(/Unexpected signature share response/); }); it('should throw if round 2 response has wrong type', async function () { const messageBuffer = Buffer.from(signableHex, 'hex'); const bitgoDsg = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(MPCv2PartiesEnum.BITGO); bitgoDsg.initDsg(bitgoKeyShare, messageBuffer, txRequest.transactions[0].unsignedTx.derivationPath, MPCv2PartiesEnum.USER); const bitgoMsg1 = bitgoDsg.getFirstMessage(); // Round 1: return a valid round1Output so the orchestration can proceed nock('https://bitgo.fakeurl') .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId}/transactions/0/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round1Input') .reply(200, async (_uri, body) => { const parsedShare = JSON.parse(body.signatureShares[0].share); const userMsg1Bytes = Buffer.from(parsedShare.data.msg1.message, 'base64'); const userDeserializedMsg1 = { from: MPCv2PartiesEnum.USER, payload: new Uint8Array(userMsg1Bytes), }; // Advance bitgo session (we don't need bitgoMsg2 for this test) bitgoDsg.handleIncomingMessages([bitgoMsg1, userDeserializedMsg1]); const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoPrvKeyObj); const round1Output = { type: 'round1Output', data: { msg1: bitgoSignedMsg1 }, }; return { txRequestId, transactions: [ { signatureShares: [ { from: sdk_core_1.SignatureShareType.BITGO, to: sdk_core_1.SignatureShareType.USER, share: JSON.stringify(round1Output), }, ], }, ], }; }); // Round 2: return a share with wrong type (round3Output instead of round2Output) nock('https://bitgo.fakeurl') .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId}/transactions/0/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round2Input') .reply(200, { txRequestId, transactions: [ { signatureShares: [ { from: sdk_core_1.SignatureShareType.USER, to: sdk_core_1.SignatureShareType.BITGO, share: 'placeholder', }, { from: sdk_core_1.SignatureShareType.BITGO, to: sdk_core_1.SignatureShareType.USER, share: JSON.stringify({ type: 'round3Output', data: {} }), }, ], }, ], }); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils .signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams }) .should.be.rejectedWith(/Unexpected signature share response. Unable to parse data./); }); it('successfully signs a txRequest after receiving multiple 429 errors in round 2', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequest, sdk_core_1.RequestType.tx, 3); await Promise.all(nockPromises); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils.signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams, }); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.true(); nockPromises[2].isDone().should.be.true(); nockPromises[3].isDone().should.be.true(); }); it('successfully signs a txRequest after receiving multiple 429 errors in round 1', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequest, sdk_core_1.RequestType.tx, 3, MPCv2PartiesEnum.USER, 1); await Promise.all(nockPromises); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils.signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams, }); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.true(); nockPromises[2].isDone().should.be.true(); nockPromises[3].isDone().should.be.true(); }); it('successfully signs a txRequest after receiving multiple 429 errors in round 3', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequest, sdk_core_1.RequestType.tx, 3, MPCv2PartiesEnum.USER, 3); await Promise.all(nockPromises); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils.signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams, }); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.true(); nockPromises[2].isDone().should.be.true(); nockPromises[3].isDone().should.be.true(); }); it('fails to sign a txRequest after receiving over 3 429 errors in round 2', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequest, sdk_core_1.RequestType.tx, 4); await Promise.all(nockPromises); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils .signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams, }) .should.be.rejectedWith('Too many requests, slow down!'); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.false(); nockPromises[2].isDone().should.be.false(); nockPromises[3].isDone().should.be.false(); }); it('should throw if round 3 response is malformed', async function () { const nockPromises = await getNockPromisesForEddsaSigning(txRequest, sdk_core_1.RequestType.tx, 0, MPCv2PartiesEnum.USER, 2, true); await Promise.all(nockPromises); const userPrvBase64 = Buffer.from(userKeyShare).toString('base64'); await tssUtils .signTxRequest({ txRequest, prv: userPrvBase64, reqId, txParams, }) .should.be.rejectedWith('Invalid txRequest object after round 3'); nockPromises[0].isDone().should.be.true(); nockPromises[1].isDone().should.be.true(); nockPromises[2].isDone().should.be.true(); nockPromises[3].isDone().should.be.false(); }); async function getNockPromisesForEddsaSigning(txRequest, requestType = sdk_core_1.RequestType.tx, rateLimitErrorCount = 0, signerPartyId = MPCv2PartiesEnum.USER, rateLimitRound = 2, malformedRound3Response = false) { const txOrMessageToSign = requestType === sdk_core_1.RequestType.message ? txRequest.messages[0].messageEncoded : txRequest.transactions[0].unsignedTx.signableHex; const messageBuffer = Buffer.from(txOrMessageToSign, 'hex'); const bitgoSession = new sdk_lib_mpc_1.EddsaMPSDsg.DSG(MPCv2PartiesEnum.BITGO); bitgoSession.initDsg(bitgoKeyShare, messageBuffer, txRequest.transactions?.[0].unsignedTx.derivationPath || 'm/0', signerPartyId); const bitgoMsg1 = bitgoSession.getFirstMessage(); let bitgoMsg2; return [ await nockTxRequestResponseSignatureShareRoundOne(bitgoSession, txRequest, bitgoMsg1, bitgoPrvKeyObj, (msg) => { bitgoMsg2 = msg; }, requestType, signerPartyId, rateLimitRound === 1 ? rateLimitErrorCount : 0), await nockTxRequestResponseSignatureShareRoundTwo(txRequest, () => bitgoMsg2, bitgoPrvKeyObj, requestType, rateLimitRound === 2 ? rateLimitErrorCount : 0, signerPartyId), await nockTxRequestResponseSignatureShareRoundThree(txRequest, requestType, signerPartyId, rateLimitRound === 3 ? rateLimitErrorCount : 0, malformedRound3Response), await nockSendTxRequest(txRequest, requestType), ]; } }); async function nockGetBitgoPublicKeyBasedOnFeatureFlags(coin, enterpriseId, bitgoGpgKeyPair) { const bitgoGPGPublicKeyResponse = { name: 'irrelevant', publicKey: bitgoGpgKeyPair.publicKey, mpcv2PublicKey: bitgoGpgKeyPair.publicKey, eddsaMpcv2PublicKey: bitgoGpgKeyPair.publicKey, enterpriseId, }; nock('https://bitgo.fakeurl') .get(`/api/v2/${coin}/tss/pubkey`) .times(4) .query({ enterpriseId }) .reply(200, bitgoGPGPublicKeyResponse); return bitgoGPGPublicKeyResponse; } async function nockTxRequestResponseSignatureShareRoundOne(bitgoSession, txRequest, bitgoMsg1, bitgoGpgPrivKey, saveBitgoMsg2, requestType = sdk_core_1.RequestType.tx, signerPartyId = MPCv2PartiesEnum.USER, rateLimitErrorCount = 0) { const route = requestType === sdk_core_1.RequestType.message ? '/messages/0' : '/transactions/0'; const signerShareType = signerPartyId === MPCv2PartiesEnum.USER ? sdk_core_1.SignatureShareType.USER : sdk_core_1.SignatureShareType.BACKUP; const scope = nock('https://bitgo.fakeurl'); if (rateLimitErrorCount > 0) { scope .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId}${route}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round1Input') .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}${route}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round1Input') .reply(200, async (_uri, body) => { const parsedShare = JSON.parse(body.signatureShares[0].share); const userMsg1Bytes = Buffer.from(parsedShare.data.msg1.message, 'base64'); const userDeserializedMsg1 = { from: signerPartyId, payload: new Uint8Array(userMsg1Bytes), }; const [bitgoMsg2] = bitgoSession.handleIncomingMessages([bitgoMsg1, userDeserializedMsg1]); saveBitgoMsg2(bitgoMsg2); const bitgoSignedMsg1 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg1.payload), bitgoGpgPrivKey); const round1Output = { type: 'round1Output', data: { msg1: bitgoSignedMsg1 }, }; const resource = requestType === sdk_core_1.RequestType.message ? 'messages' : 'transactions'; return { txRequestId: txRequest.txRequestId, [resource]: [ { signatureShares: [ { from: sdk_core_1.SignatureShareType.BITGO, to: signerShareType, share: JSON.stringify(round1Output), }, ], }, ], }; }); } async function nockTxRequestResponseSignatureShareRoundTwo(txRequest, getBitgoMsg2, bitgoGpgPrivKey, requestType = sdk_core_1.RequestType.tx, rateLimitErrorCount = 0, signerPartyId = MPCv2PartiesEnum.USER) { const route = requestType === sdk_core_1.RequestType.message ? '/messages/0' : '/transactions/0'; const scope = nock('https://bitgo.fakeurl'); const signerShareType = signerPartyId === MPCv2PartiesEnum.USER ? sdk_core_1.SignatureShareType.USER : sdk_core_1.SignatureShareType.BACKUP; if (rateLimitErrorCount > 0) { scope .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId}${route}/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}${route}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round2Input') .reply(200, async () => { const bitgoMsg2 = getBitgoMsg2(); const bitgoSignedMsg2 = await sdk_lib_mpc_1.MPSComms.detachSignMpsMessage(Buffer.from(bitgoMsg2.payload), bitgoGpgPrivKey); const round2Output = { type: 'round2Output', data: { msg2: bitgoSignedMsg2 }, }; const resource = requestType === sdk_core_1.RequestType.message ? 'messages' : 'transactions'; return { txRequestId: txRequest.txRequestId, [resource]: [ { signatureShares: [ { from: signerShareType, to: sdk_core_1.SignatureShareType.BITGO, share: 'placeholder', }, { from: sdk_core_1.SignatureShareType.BITGO, to: signerShareType, share: JSON.stringify(round2Output), }, ], }, ], }; }); } async function nockTxRequestResponseSignatureShareRoundThree(txRequest, requestType = sdk_core_1.RequestType.tx, signerPartyId = MPCv2PartiesEnum.USER, rateLimitErrorCount = 0, malformedResponse = false) { const route = requestType === sdk_core_1.RequestType.message ? '/messages/0' : '/transactions/0'; const signerShareType = signerPartyId === MPCv2PartiesEnum.USER ? sdk_core_1.SignatureShareType.USER : sdk_core_1.SignatureShareType.BACKUP; const scope = nock('https://bitgo.fakeurl'); if (rateLimitErrorCount > 0) { scope .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId}${route}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round3Input') .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}${route}/sign`, (body) => JSON.parse(body.signatureShares[0].share).type === 'round3Input') .reply(200, malformedResponse ? { txRequestId: `${txRequest.txRequestId}-unexpected` } : { txRequestId: txRequest.txRequestId, signatureShares: [ { from: signerShareType, to: sdk_core_1.SignatureShareType.BITGO, share: 'placeholder', }, ], }); } async function nockSendTxRequest(txRequest, requestType = sdk_core_1.RequestType.tx) { const route = requestType === sdk_core_1.RequestType.message ? '/messages/0' : '/transactions/0'; return nock('https://bitgo.fakeurl') .post(`/api/v2/wallet/${txRequest.walletId}/txrequests/${txRequest.txRequestId}${route}/send`) .reply(200, { txRequestId: txRequest.txRequestId, }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnblR4UmVxdWVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Rlc3QvdjIvdW5pdC9pbnRlcm5hbC90c3NVdGlscy9lZGRzYU1QQ3YyL3NpZ25UeFJlcXVlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw4Q0FZeUI7QUFDekIsb0RBQThFO0FBQzlFLG1DQUFtQztBQUNuQyw2QkFBOEI7QUFDOUIsOENBQXdEO0FBUXhELCtDQUE4QztBQUU5QyxNQUFNLGdCQUFnQixHQUFHLHFCQUFVLENBQUMsZ0JBQWdCLENBQUM7QUFPckQsUUFBUSxDQUFDLGdCQUFnQixFQUFFO0lBQ3pCLElBQUksUUFBb0MsQ0FBQztJQUN6QyxJQUFJLE1BQWMsQ0FBQztJQUNuQixJQUFJLEtBQXlCLENBQUM7SUFDOUIsSUFBSSxRQUFrQixDQUFDO0lBQ3ZCLElBQUksV0FBa0YsQ0FBQztJQUN2RixJQUFJLGNBQWtDLENBQUM7SUFDdkMsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBRXZCLE1BQU0sS0FBSyxHQUFHLElBQUksd0JBQWEsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sV0FBVyxHQUFHLGVBQWUsQ0FBQztJQUNwQyxNQUFNLFdBQVcsR0FDZixrZ0JBQWtnQixDQUFDO0lBQ3JnQixNQUFNLGVBQWUsR0FBRyxxUUFBcVEsV0FBVyxFQUFFLENBQUM7SUFDM1MsTUFBTSxVQUFVLEdBQUcsa0JBQWtCLENBQUM7SUFDdEMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0QsTUFBTSxRQUFRLEdBQUc7UUFDZixVQUFVLEVBQUU7WUFDVjtnQkFDRSxPQUFPLEVBQUUsOENBQThDO2dCQUN2RCxNQUFNLEVBQUUsV0FBVzthQUNwQjtTQUNGO0tBQ0YsQ0FBQztJQUNGLE1BQU0sU0FBUyxHQUFjO1FBQzNCLFdBQVc7UUFDWCxZQUFZ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