diff --git a/backend/mpc-system/services/account/adapters/input/http/account_handler.go b/backend/mpc-system/services/account/adapters/input/http/account_handler.go index 3de31549..3271b66f 100644 --- a/backend/mpc-system/services/account/adapters/input/http/account_handler.go +++ b/backend/mpc-system/services/account/adapters/input/http/account_handler.go @@ -778,11 +778,12 @@ func (h *AccountHTTPHandler) CreateSigningSession(c *gin.Context) { // Use the selected delegate for signing (not necessarily the account's delegate) delegateShare = selectedDelegateShare - // Validate we have enough parties - if len(partyIDs) < accountOutput.Account.ThresholdT { + // Validate we have enough parties (T+1 required for TSS signing) + requiredSigners := accountOutput.Account.ThresholdT + 1 + if len(partyIDs) < requiredSigners { c.JSON(http.StatusBadRequest, gin.H{ "error": "insufficient parties for signing", - "required": accountOutput.Account.ThresholdT, + "required": requiredSigners, "selected": len(partyIDs), }) return diff --git a/backend/mpc-system/services/account/domain/entities/account.go b/backend/mpc-system/services/account/domain/entities/account.go index a717a809..1c6950f3 100644 --- a/backend/mpc-system/services/account/domain/entities/account.go +++ b/backend/mpc-system/services/account/domain/entities/account.go @@ -140,9 +140,11 @@ func (a *Account) Validate() error { } // SetSigningParties sets the designated signing parties for this account -// partyIDs must contain exactly ThresholdT parties +// partyIDs must contain exactly ThresholdT + 1 parties (required signers for TSS) +// For 2-of-3: ThresholdT=1, so T+1=2 signers required func (a *Account) SetSigningParties(partyIDs []string) error { - if len(partyIDs) != a.ThresholdT { + requiredSigners := a.ThresholdT + 1 + if len(partyIDs) != requiredSigners { return ErrInvalidSigningPartiesCount } // Check for duplicates @@ -197,7 +199,7 @@ var ( ErrAccountNotFound = &AccountError{Code: "ACCOUNT_NOT_FOUND", Message: "account not found"} ErrDuplicateUsername = &AccountError{Code: "DUPLICATE_USERNAME", Message: "username already exists"} ErrDuplicateEmail = &AccountError{Code: "DUPLICATE_EMAIL", Message: "email already exists"} - ErrInvalidSigningPartiesCount = &AccountError{Code: "INVALID_SIGNING_PARTIES_COUNT", Message: "signing parties count must equal threshold T"} + ErrInvalidSigningPartiesCount = &AccountError{Code: "INVALID_SIGNING_PARTIES_COUNT", Message: "signing parties count must equal threshold T + 1 (required signers)"} ErrInvalidPartyID = &AccountError{Code: "INVALID_PARTY_ID", Message: "party ID cannot be empty"} ErrDuplicatePartyID = &AccountError{Code: "DUPLICATE_PARTY_ID", Message: "duplicate party ID in signing parties"} )