From 1e6a25b6da1c816c2ad4ca43e5f1b8be8259162f Mon Sep 17 00:00:00 2001 From: Vibhav Simha G Date: Wed, 3 Jun 2026 16:44:16 +0530 Subject: [PATCH] fix(sdk-core): pass round to getBitgoSignatureShare helper Ticket: WCI-626 EdDSA MPCv2 signing can receive multiple BitGo-to-signer shares in a txRequest. Selecting only by sender/recipient can pick a stale round-1 output during round 2. - Add shareType param to getBitgoSignatureShare to filter by round output type. - Update EdDSA MPCv2 callers to request round-1 or round-2 output explicitly. - Remove inline reverse().find() in offline round-3 path in favour of the helper. - Update tests to expect round-specific missing share error messages. --- modules/sdk-core/src/bitgo/tss/common.ts | 10 +++++++--- .../src/bitgo/utils/tss/eddsa/eddsaMPCv2.ts | 19 ++++--------------- .../unit/bitgo/utils/tss/eddsa/eddsaMPCv2.ts | 4 ++-- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/modules/sdk-core/src/bitgo/tss/common.ts b/modules/sdk-core/src/bitgo/tss/common.ts index 156729d78d..3eaddbaa58 100644 --- a/modules/sdk-core/src/bitgo/tss/common.ts +++ b/modules/sdk-core/src/bitgo/tss/common.ts @@ -20,12 +20,16 @@ const debug = require('debug')('bitgo:tss:common'); export function getBitgoSignatureShare( signatureShares: SignatureShareRecord[], - signerShareType: SignatureShareType + signerShareType: SignatureShareType, + shareType: 'round1Output' | 'round2Output' | 'round3Output' ): SignatureShareRecord { const bitgoShare = signatureShares.find( - (share) => share.from === SignatureShareType.BITGO && share.to === signerShareType + (share) => + share.from === SignatureShareType.BITGO && + share.to === signerShareType && + JSON.parse(share.share).type === shareType ); - assert(bitgoShare, 'Missing BitGo signature share'); + assert(bitgoShare, `Missing BitGo ${shareType} signature share`); return bitgoShare; } diff --git a/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsaMPCv2.ts b/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsaMPCv2.ts index 8dc3175f48..f11b0f94a5 100644 --- a/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsaMPCv2.ts +++ b/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsaMPCv2.ts @@ -469,7 +469,7 @@ export class EddsaMPCv2Utils extends BaseEddsaUtils { ? latestTxRequest.transactions![0].signatureShares : latestTxRequest.messages![0].signatureShares; - const bitgoShareRoundOne = getBitgoSignatureShare(signatureShares1, signerShareType); + const bitgoShareRoundOne = getBitgoSignatureShare(signatureShares1, signerShareType, 'round1Output'); const parsedBitGoToUserSigShareRoundOne = decodeWithCodec( EddsaMPCv2SignatureShareRound1Output, JSON.parse(bitgoShareRoundOne.share), @@ -508,7 +508,7 @@ export class EddsaMPCv2Utils extends BaseEddsaUtils { ? latestTxRequest.transactions![0].signatureShares : latestTxRequest.messages![0].signatureShares; - const bitgoShareRoundTwo = getBitgoSignatureShare(txRequestSignatureShares, signerShareType); + const bitgoShareRoundTwo = getBitgoSignatureShare(txRequestSignatureShares, signerShareType, 'round2Output'); const parsedBitGoToUserSigShareRoundTwo = decodeWithCodec( EddsaMPCv2SignatureShareRound2Output, JSON.parse(bitgoShareRoundTwo.share), @@ -649,7 +649,7 @@ export class EddsaMPCv2Utils extends BaseEddsaUtils { const signatureShares = transactions[0].signatureShares; assert(signatureShares, 'Missing signature shares in round 1 txRequest'); - const bitgoShareRoundOne = getBitgoSignatureShare(signatureShares, SignatureShareType.USER); + const bitgoShareRoundOne = getBitgoSignatureShare(signatureShares, SignatureShareType.USER, 'round1Output'); const parsedBitGoToUserSigShareRoundOne = decodeWithCodec( EddsaMPCv2SignatureShareRound1Output, JSON.parse(bitgoShareRoundOne.share), @@ -754,18 +754,7 @@ export class EddsaMPCv2Utils extends BaseEddsaUtils { const signatureShares = transactions[0].signatureShares; assert(signatureShares, 'Missing signature shares in round 2 txRequest'); - const bitgoShareRoundTwo = [...signatureShares].reverse().find((share) => { - if (share.from !== SignatureShareType.BITGO || share.to !== SignatureShareType.USER) { - return false; - } - - try { - return JSON.parse(share.share).type === 'round2Output'; - } catch { - return false; - } - }); - assert(bitgoShareRoundTwo, 'Missing BitGo round 2 signature share'); + const bitgoShareRoundTwo = getBitgoSignatureShare(signatureShares, SignatureShareType.USER, 'round2Output'); const parsedBitGoToUserSigShareRoundTwo = decodeWithCodec( EddsaMPCv2SignatureShareRound2Output, diff --git a/modules/sdk-core/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.ts b/modules/sdk-core/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.ts index 77784805b8..ed24af96e3 100644 --- a/modules/sdk-core/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.ts +++ b/modules/sdk-core/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.ts @@ -799,7 +799,7 @@ describe('EddsaMPCv2Utils.createOfflineRound2Share', () => { encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey, encryptedRound1Session: round1.encryptedRound1Session, }), - /Missing BitGo signature share/ + /Missing BitGo round1Output signature share/ ); }); @@ -1114,7 +1114,7 @@ describe('EddsaMPCv2Utils.createOfflineRound3Share', () => { encryptedUserGpgPrvKey: round1.encryptedUserGpgPrvKey, encryptedRound2Session: round2.encryptedRound2Session, }), - /Missing BitGo round 2 signature share/ + /Missing BitGo round2Output signature share/ ); });