fix(co-sign): fix session start logic to check all registered participants

- CanStart(): Check if all registered participants have joined, not based on T/N
- AddParticipant(): Keep N as max limit (API handles T vs T+1 validation)
- AllPartiesReady(): Check all registered participants, not based on T/N
- This approach works for both co-managed (T parties) and persistent (T+1 parties) signing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-31 06:03:13 -08:00
parent a09e163704
commit 99fa003b12
1 changed files with 16 additions and 15 deletions

View File

@ -98,6 +98,9 @@ func NewMPCSession(
// AddParticipant adds a participant to the session
func (s *MPCSession) AddParticipant(p *Participant) error {
// For sign sessions, the max participant check is handled at the API level
// (co-managed uses T, persistent uses T+1)
// Here we just prevent exceeding N which is the absolute maximum
if len(s.Participants) >= s.Threshold.N() {
return ErrSessionFull
}
@ -140,26 +143,22 @@ func (s *MPCSession) UpdateParticipantStatus(partyID value_objects.PartyID, stat
// CanStart checks if all participants have joined and the session can start
func (s *MPCSession) CanStart() bool {
// Determine required participant count based on session type
// For keygen: all N parties must participate
// For sign: only T parties participate
requiredCount := s.Threshold.N()
if s.SessionType == SessionTypeSign {
requiredCount = s.Threshold.T()
}
if len(s.Participants) != requiredCount {
// 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
if len(s.Participants) == 0 {
return false
}
readyCount := 0
for _, p := range s.Participants {
// Accept participants in either joined or ready status
if p.IsJoined() || p.IsReady() {
readyCount++
// All participants must be in joined or ready status
if !p.IsJoined() && !p.IsReady() {
return false
}
}
return readyCount == requiredCount
return true
}
// Start transitions the session to in_progress
@ -265,7 +264,9 @@ func (s *MPCSession) MarkPartyReady(partyID string) error {
// AllPartiesReady checks if all participants are ready
func (s *MPCSession) AllPartiesReady() bool {
if len(s.Participants) != s.Threshold.N() {
// Check that all registered participants are ready or completed
// The participant count was determined at session creation time
if len(s.Participants) == 0 {
return false
}
for _, p := range s.Participants {