bitgo
Version:
BitGo JavaScript SDK
507 lines • 83.9 kB
JavaScript
"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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