diff --git a/backend/mpc-system/pkg/tss/signing.go b/backend/mpc-system/pkg/tss/signing.go index b22a7156..3dc5eab9 100644 --- a/backend/mpc-system/pkg/tss/signing.go +++ b/backend/mpc-system/pkg/tss/signing.go @@ -132,10 +132,13 @@ func NewSigningSession( keygenIndexToSortedIndex, selfParty.PartyID) // Create peer context and parameters - // IMPORTANT: Use TotalParties from keygen, not len(sortedPartyIDs) which is current signers - // For 2-of-3: threshold=2, TotalParties=3, but only 2 parties might participate in signing + // IMPORTANT: Use len(sortedPartyIDs) as partyCount - this is the number of CURRENT signers + // For 2-of-3 threshold signing with only 2 parties participating: + // - partyCount = 2 (current signers) + // - threshold = 2 (minimum required from keygen) + // The BuildLocalSaveDataSubset call in Start() will filter the save data to match peerCtx := tss.NewPeerContext(sortedPartyIDs) - params := tss.NewParameters(tss.S256(), peerCtx, selfTSSID, config.TotalParties, config.Threshold) + params := tss.NewParameters(tss.S256(), peerCtx, selfTSSID, len(sortedPartyIDs), config.Threshold) // Convert message hash to big.Int msgHash := new(big.Int).SetBytes(messageHash) @@ -167,8 +170,17 @@ func (s *SigningSession) Start(ctx context.Context) (*SigningResult, error) { s.started = true s.mu.Unlock() - // Create local party for signing - s.localParty = signing.NewLocalParty(s.messageHash, s.params, *s.saveData, s.outCh, s.endCh) + // CRITICAL: Build a subset of the save data for the current signing parties + // When signing with fewer parties than keygen (e.g., 2-of-3 signing with only 2 parties), + // we must filter the save data to only include the participating parties' data. + // This ensures TSS-lib's internal indices match the actual signers. + subsetSaveData := keygen.BuildLocalSaveDataSubset(*s.saveData, s.tssPartyIDs) + + fmt.Printf("[TSS-SIGN] Built save data subset for %d signing parties (original keygen had %d parties) party_id=%s\n", + len(s.tssPartyIDs), len(s.saveData.Ks), s.selfParty.PartyID) + + // Create local party for signing with the SUBSET save data + s.localParty = signing.NewLocalParty(s.messageHash, s.params, subsetSaveData, s.outCh, s.endCh) // Start the local party go func() { diff --git a/backend/mpc-system/services/service-party-app/tss-party/main.go b/backend/mpc-system/services/service-party-app/tss-party/main.go index 287fb233..2d227420 100644 --- a/backend/mpc-system/services/service-party-app/tss-party/main.go +++ b/backend/mpc-system/services/service-party-app/tss-party/main.go @@ -607,13 +607,19 @@ func executeSign( peerCtx := tss.NewPeerContext(sortedPartyIDs) params := tss.NewParameters(tss.S256(), peerCtx, selfTSSID, len(sortedPartyIDs), thresholdT-1) + // CRITICAL: Build a subset of the keygen save data for the current signing parties + // This is required when signing with a subset of the original keygen participants. + // BuildLocalSaveDataSubset filters the Ks, BigXj, NTildej, H1j, H2j, and PaillierPKs + // arrays to only include data for the participating signers. + subsetKeygenData := keygen.BuildLocalSaveDataSubset(keygenData, sortedPartyIDs) + // Create channels outCh := make(chan tss.Message, thresholdT*10) endCh := make(chan *common.SignatureData, 1) errCh := make(chan error, 1) - // Create local party for signing - localParty := signing.NewLocalParty(msgBigInt, params, keygenData, outCh, endCh) + // Create local party for signing with the SUBSET keygen data + localParty := signing.NewLocalParty(msgBigInt, params, subsetKeygenData, outCh, endCh) // Build party index map for incoming messages partyIndexMap := make(map[int]*tss.PartyID) diff --git a/backend/mpc-system/services/tss-wasm/main.go b/backend/mpc-system/services/tss-wasm/main.go index e5a63bdf..b7cd1ad1 100644 --- a/backend/mpc-system/services/tss-wasm/main.go +++ b/backend/mpc-system/services/tss-wasm/main.go @@ -298,8 +298,12 @@ func startSigning(this js.Value, args []js.Value) interface{} { // Create message hash as big.Int msgHashBig := new(big.Int).SetBytes(messageHash) - // Create local signing party - session.LocalParty = signing.NewLocalParty(msgHashBig, params, saveData, session.OutCh, session.EndChSign) + // CRITICAL: Build a subset of the keygen save data for the current signing parties + // This is required when signing with a subset of the original keygen participants. + subsetSaveData := keygen.BuildLocalSaveDataSubset(saveData, sortedPartyIDs) + + // Create local signing party with the SUBSET save data + session.LocalParty = signing.NewLocalParty(msgHashBig, params, subsetSaveData, session.OutCh, session.EndChSign) // Store session sessionMutex.Lock()