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
This commit is contained in:
hailin 2025-12-06 04:54:40 -08:00
parent b72268c1ce
commit 5f12404be4
4 changed files with 16 additions and 28 deletions

View File

@ -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": []

View File

@ -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)
)
}

View File

@ -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

View File

@ -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")