diff --git a/backend/mpc-system/services/session-coordinator/domain/entities/mpc_session.go b/backend/mpc-system/services/session-coordinator/domain/entities/mpc_session.go index a6976405..69d6d177 100644 --- a/backend/mpc-system/services/session-coordinator/domain/entities/mpc_session.go +++ b/backend/mpc-system/services/session-coordinator/domain/entities/mpc_session.go @@ -142,27 +142,27 @@ func (s *MPCSession) UpdateParticipantStatus(partyID value_objects.PartyID, stat } // CanStart checks if all participants have joined and the session can start -// -// BREAKING CHANGE WARNING (for co-sign feature, commit 99fa003b): -// Original code: len(s.Participants) == s.Threshold.N() && readyCount == s.Threshold.N() -// New code: Check all registered participants are joined (no T/N check) -// This change affects PERSISTENT SIGN flow because we now pass keygenThresholdN -// instead of len(parties) as threshold_n. With original code, sign sessions with -// T+1 participants would fail because T+1 != N. -// If issues arise with persistent sign, REVERT to original N-based check. -// Related files: session_coordinator.go, session_coordinator_client.go, account_handler.go func (s *MPCSession) CanStart() bool { - // Session can start when all registered participants have joined - // The number of participants was determined at session creation time: - // - For keygen: N parties are registered - // - For sign: T or T+1 parties are registered (depending on the signing flow) - // We don't need to check against T or N here - just verify all registered parties have joined + // For keygen sessions (including co-managed keygen): must have exactly N participants + if s.SessionType.IsKeygen() { + if len(s.Participants) != s.Threshold.N() { + return false + } + readyCount := 0 + for _, p := range s.Participants { + if p.IsJoined() || p.IsReady() { + readyCount++ + } + } + return readyCount == s.Threshold.N() + } + + // For sign sessions: check all registered participants have joined + // The number of participants was determined at session creation time (T or T+1) if len(s.Participants) == 0 { return false } - for _, p := range s.Participants { - // All participants must be in joined or ready status if !p.IsJoined() && !p.IsReady() { return false } @@ -272,15 +272,21 @@ func (s *MPCSession) MarkPartyReady(partyID string) error { } // AllPartiesReady checks if all participants are ready -// -// BREAKING CHANGE WARNING (for co-sign feature, commit 99fa003b): -// Original code: len(s.Participants) != s.Threshold.N() would return false -// New code: Check all registered participants are ready (no T/N check) -// This change affects PERSISTENT SIGN flow. See CanStart() for details. -// If issues arise with persistent sign, REVERT to original N-based check. func (s *MPCSession) AllPartiesReady() bool { - // Check that all registered participants are ready or completed - // The participant count was determined at session creation time + // For keygen sessions: must have exactly N participants + if s.SessionType.IsKeygen() { + if len(s.Participants) != s.Threshold.N() { + return false + } + for _, p := range s.Participants { + if !p.IsReady() && !p.IsCompleted() { + return false + } + } + return true + } + + // For sign sessions: check all registered participants are ready if len(s.Participants) == 0 { return false }