From 5f12404be4c6f2ae9d6cb69469bc0ac2bb9ee4f8 Mon Sep 17 00:00:00 2001 From: hailin Date: Sat, 6 Dec 2025 04:54:40 -0800 Subject: [PATCH] fix: remove dynamic participant join to fix concurrent party_index assignment - Remove dynamic participant addition in JoinSession - Participants must be pre-created in CreateSession - Add ErrPartyNotInvited error for unauthorized join attempts - Fix Redis adapter to include version parameter in ReconstructSession - This fixes VSS verification failures caused by inconsistent party indices --- backend/.claude/settings.local.json | 4 +- .../output/redis/session_cache_adapter.go | 1 + .../application/use_cases/join_session.go | 38 ++++++------------- .../domain/entities/mpc_session.go | 1 + 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/backend/.claude/settings.local.json b/backend/.claude/settings.local.json index 92387d00..5a9a367c 100644 --- a/backend/.claude/settings.local.json +++ b/backend/.claude/settings.local.json @@ -24,7 +24,9 @@ "Bash(cat:*)", "Bash(dir:*)", "Bash(copy /Y \"api\\proto\\session_coordinator.pb.go\" \"api\\grpc\\coordinator\\v1\"\" && copy /Y \"apiprotosession_coordinator_grpc.pb.go\" \"apigrpccoordinatorv1\"\")", - "Bash(timeout /t 10 /nobreak)" + "Bash(timeout /t 10 /nobreak)", + "Bash(bash scripts/deploy.sh:*)", + "Bash(go run:*)" ], "deny": [], "ask": [] diff --git a/backend/mpc-system/services/session-coordinator/adapters/output/redis/session_cache_adapter.go b/backend/mpc-system/services/session-coordinator/adapters/output/redis/session_cache_adapter.go index 552a68c5..672bd133 100644 --- a/backend/mpc-system/services/session-coordinator/adapters/output/redis/session_cache_adapter.go +++ b/backend/mpc-system/services/session-coordinator/adapters/output/redis/session_cache_adapter.go @@ -272,6 +272,7 @@ func cacheEntryToSession(entry sessionCacheEntry) (*entities.MPCSession, error) time.UnixMilli(entry.ExpiresAt), completedAt, participants, + 1, // version - default to 1 for cached sessions (not used in cache) ) } diff --git a/backend/mpc-system/services/session-coordinator/application/use_cases/join_session.go b/backend/mpc-system/services/session-coordinator/application/use_cases/join_session.go index 94ff3522..582b6782 100644 --- a/backend/mpc-system/services/session-coordinator/application/use_cases/join_session.go +++ b/backend/mpc-system/services/session-coordinator/application/use_cases/join_session.go @@ -80,38 +80,22 @@ func (uc *JoinSessionUseCase) Execute( return nil, err } - // 5. Check if participant exists, if not, add them (dynamic joining) + // 5. Get participant (must already exist from CreateSession) participant, err := session.GetParticipant(partyID) if err != nil { - // Participant doesn't exist, add them dynamically - if len(session.Participants) >= session.Threshold.N() { - return nil, entities.ErrSessionFull - } - - // Create new participant with index based on current participant count - partyIndex := len(session.Participants) - logger.Info("creating new participant for dynamic join", + // Participant doesn't exist - this party was not invited to this session + logger.Warn("party not found in session participants", + zap.String("session_id", session.ID.String()), zap.String("party_id", inputData.PartyID), - zap.Int("assigned_party_index", partyIndex), - zap.Int("current_participant_count", len(session.Participants))) - - participant, err = entities.NewParticipant(partyID, partyIndex, inputData.DeviceInfo) - if err != nil { - return nil, err - } - - logger.Info("new participant created", - zap.String("party_id", participant.PartyID.String()), - zap.Int("party_index", participant.PartyIndex)) - - if err := session.AddParticipant(participant); err != nil { - return nil, err - } - - logger.Info("participant added to session", - zap.Int("total_participants_after_add", len(session.Participants))) + zap.Int("existing_participant_count", len(session.Participants))) + return nil, entities.ErrPartyNotInvited } + logger.Debug("participant found in session", + zap.String("party_id", participant.PartyID.String()), + zap.Int("party_index", participant.PartyIndex), + zap.String("current_status", participant.Status.String())) + // 6. Update participant status to joined if err := session.UpdateParticipantStatus(partyID, value_objects.ParticipantStatusJoined); err != nil { return nil, err 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 a486375c..376b4454 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 @@ -14,6 +14,7 @@ var ( ErrSessionExpired = errors.New("session expired") ErrSessionNotInProgress = errors.New("session not in progress") ErrParticipantNotFound = errors.New("participant not found") + ErrPartyNotInvited = errors.New("party not invited to this session") ErrInvalidSessionType = errors.New("invalid session type") ErrInvalidStatusTransition = errors.New("invalid status transition") ErrParticipantTimedOut = errors.New("participant timed out")