diff --git a/fsm/state_machines/dkg_proposal_fsm/actions.go b/fsm/state_machines/dkg_proposal_fsm/actions.go index 2985d691..ff68c4b3 100644 --- a/fsm/state_machines/dkg_proposal_fsm/actions.go +++ b/fsm/state_machines/dkg_proposal_fsm/actions.go @@ -56,9 +56,9 @@ func (m *DKGProposalFSM) actionInitDKGProposal(inEvent fsm.Event, args ...interf responseData := make(responses.DKGProposalPubKeysParticipantResponse, 0) - for participantId, participant := range m.payload.DKGProposalPayload.Quorum { + for _, participant := range m.payload.DKGProposalPayload.Quorum.GetOrderedParticipants() { responseEntry := &responses.DKGProposalPubKeysParticipantEntry{ - ParticipantId: participantId, + ParticipantId: participant.ParticipantID, Username: participant.Username, DkgPubKey: participant.DkgPubKey, } @@ -155,9 +155,9 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event responseData := make(responses.DKGProposalCommitParticipantResponse, 0) - for participantId, participant := range m.payload.DKGProposalPayload.Quorum { + for _, participant := range m.payload.DKGProposalPayload.Quorum.GetOrderedParticipants() { responseEntry := &responses.DKGProposalCommitParticipantEntry{ - ParticipantId: participantId, + ParticipantId: participant.ParticipantID, Username: participant.Username, DkgCommit: participant.DkgCommit, } @@ -257,12 +257,12 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event, responseData := make(responses.DKGProposalDealParticipantResponse, 0) - for participantId, participant := range m.payload.DKGProposalPayload.Quorum { + for _, participant := range m.payload.DKGProposalPayload.Quorum.GetOrderedParticipants() { if len(participant.DkgDeal) == 0 { continue } responseEntry := &responses.DKGProposalDealParticipantEntry{ - ParticipantId: participantId, + ParticipantId: participant.ParticipantID, Username: participant.Username, DkgDeal: participant.DkgDeal, } @@ -362,9 +362,9 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Eve responseData := make(responses.DKGProposalResponseParticipantResponse, 0) - for participantId, participant := range m.payload.DKGProposalPayload.Quorum { + for _, participant := range m.payload.DKGProposalPayload.Quorum.GetOrderedParticipants() { responseEntry := &responses.DKGProposalResponseParticipantEntry{ - ParticipantId: participantId, + ParticipantId: participant.ParticipantID, Username: participant.Username, DkgResponse: participant.DkgResponse, } diff --git a/fsm/state_machines/internal/types.go b/fsm/state_machines/internal/types.go index 790b9670..e02063c9 100644 --- a/fsm/state_machines/internal/types.go +++ b/fsm/state_machines/internal/types.go @@ -2,8 +2,10 @@ package internal import ( "crypto/ed25519" - "github.com/lidofinance/dc4bc/fsm/types/requests" + "sort" "time" + + "github.com/lidofinance/dc4bc/fsm/types/requests" ) type ParticipantStatus interface { @@ -42,9 +44,10 @@ type SignatureConfirmation struct { } type SignatureProposalParticipant struct { - Username string - PubKey ed25519.PublicKey - DkgPubKey []byte + ParticipantID int + Username string + PubKey ed25519.PublicKey + DkgPubKey []byte // For validation user confirmation: sign(InvitationSecret, PubKey) => user InvitationSecret string Status ConfirmationParticipantStatus @@ -68,6 +71,24 @@ func (c *SignatureConfirmation) IsExpired() bool { // Excludes array merge and rotate operations type SignatureProposalQuorum map[int]*SignatureProposalParticipant +func (q SignatureProposalQuorum) GetOrderedParticipants() []*SignatureProposalParticipant { + var sortedParticipantIDs []int + for participantID := range q { + sortedParticipantIDs = append(sortedParticipantIDs, participantID) + } + + sort.Ints(sortedParticipantIDs) + + var out []*SignatureProposalParticipant + for _, participantID := range sortedParticipantIDs { + var participant = q[participantID] + participant.ParticipantID = participantID + out = append(out, participant) + } + + return out +} + // DKG proposal type DKGParticipantStatus uint8 @@ -88,15 +109,16 @@ const ( ) type DKGProposalParticipant struct { - Username string - DkgPubKey []byte - DkgCommit []byte - DkgDeal []byte - DkgResponse []byte - DkgMasterKey []byte - Status DKGParticipantStatus - Error *requests.FSMError - UpdatedAt time.Time + ParticipantID int + Username string + DkgPubKey []byte + DkgCommit []byte + DkgDeal []byte + DkgResponse []byte + DkgMasterKey []byte + Status DKGParticipantStatus + Error *requests.FSMError + UpdatedAt time.Time } func (dkgP DKGProposalParticipant) GetStatus() ParticipantStatus { @@ -109,6 +131,24 @@ func (dkgP DKGProposalParticipant) GetUsername() string { type DKGProposalQuorum map[int]*DKGProposalParticipant +func (q DKGProposalQuorum) GetOrderedParticipants() []*DKGProposalParticipant { + var sortedParticipantIDs []int + for participantID := range q { + sortedParticipantIDs = append(sortedParticipantIDs, participantID) + } + + sort.Ints(sortedParticipantIDs) + + var out []*DKGProposalParticipant + for _, participantID := range sortedParticipantIDs { + var participant = q[participantID] + participant.ParticipantID = participantID + out = append(out, participant) + } + + return out +} + type DKGConfirmation struct { Quorum DKGProposalQuorum CreatedAt time.Time @@ -173,6 +213,24 @@ func (c *SigningConfirmation) IsExpired() bool { type SigningProposalQuorum map[int]*SigningProposalParticipant +func (q SigningProposalQuorum) GetOrderedParticipants() []*SigningProposalParticipant { + var sortedParticipantIDs []int + for participantID := range q { + sortedParticipantIDs = append(sortedParticipantIDs, participantID) + } + + sort.Ints(sortedParticipantIDs) + + var out []*SigningProposalParticipant + for _, participantID := range sortedParticipantIDs { + var participant = q[participantID] + participant.ParticipantID = participantID + out = append(out, participant) + } + + return out +} + type SigningParticipantStatus uint8 const ( @@ -205,11 +263,12 @@ func (s SigningParticipantStatus) String() string { } type SigningProposalParticipant struct { - Username string - Status SigningParticipantStatus - PartialSign []byte - Error *requests.FSMError - UpdatedAt time.Time + ParticipantID int + Username string + Status SigningParticipantStatus + PartialSign []byte + Error *requests.FSMError + UpdatedAt time.Time } func (signingP SigningProposalParticipant) GetStatus() ParticipantStatus { diff --git a/fsm/state_machines/signature_proposal_fsm/actions.go b/fsm/state_machines/signature_proposal_fsm/actions.go index 64aae33c..d31214b4 100644 --- a/fsm/state_machines/signature_proposal_fsm/actions.go +++ b/fsm/state_machines/signature_proposal_fsm/actions.go @@ -64,9 +64,9 @@ func (m *SignatureProposalFSM) actionInitSignatureProposal(inEvent fsm.Event, ar responseData := make(responses.SignatureProposalParticipantInvitationsResponse, 0) - for participantId, participant := range m.payload.SignatureProposalPayload.Quorum { + for _, participant := range m.payload.SignatureProposalPayload.Quorum.GetOrderedParticipants() { responseEntry := &responses.SignatureProposalParticipantInvitationEntry{ - ParticipantId: participantId, + ParticipantId: participant.ParticipantID, Username: participant.Username, Threshold: participant.Threshold, DkgPubKey: participant.DkgPubKey, diff --git a/fsm/state_machines/signing_proposal_fsm/actions.go b/fsm/state_machines/signing_proposal_fsm/actions.go index 83929587..391cb0d8 100644 --- a/fsm/state_machines/signing_proposal_fsm/actions.go +++ b/fsm/state_machines/signing_proposal_fsm/actions.go @@ -68,8 +68,8 @@ func (m *SigningProposalFSM) actionStartSigningProposal(inEvent fsm.Event, args m.payload.SigningProposalPayload.Quorum = make(internal.SigningProposalQuorum) // Initialize new quorum - for id, dkgEntry := range m.payload.DKGProposalPayload.Quorum { - m.payload.SigningProposalPayload.Quorum[id] = &internal.SigningProposalParticipant{ + for _, dkgEntry := range m.payload.DKGProposalPayload.Quorum.GetOrderedParticipants() { + m.payload.SigningProposalPayload.Quorum[dkgEntry.ParticipantID] = &internal.SigningProposalParticipant{ Username: dkgEntry.Username, Status: internal.SigningAwaitConfirmation, UpdatedAt: request.CreatedAt, @@ -87,9 +87,9 @@ func (m *SigningProposalFSM) actionStartSigningProposal(inEvent fsm.Event, args Participants: make([]*responses.SigningProposalParticipantInvitationEntry, 0), } - for participantId, participant := range m.payload.SigningProposalPayload.Quorum { + for _, participant := range m.payload.SigningProposalPayload.Quorum.GetOrderedParticipants() { responseEntry := &responses.SigningProposalParticipantInvitationEntry{ - ParticipantId: participantId, + ParticipantId: participant.ParticipantID, Username: participant.Username, Status: uint8(participant.Status), } @@ -282,13 +282,13 @@ func (m *SigningProposalFSM) actionValidateSigningPartialSignsAwaitConfirmations Participants: make([]*responses.SigningProcessParticipantEntry, 0), } - for participantId, participant := range m.payload.SigningProposalPayload.Quorum { + for _, participant := range m.payload.SigningProposalPayload.Quorum.GetOrderedParticipants() { // don't return participants who didn't broadcast partial signature if len(participant.PartialSign) == 0 { continue } responseEntry := &responses.SigningProcessParticipantEntry{ - ParticipantId: participantId, + ParticipantId: participant.ParticipantID, Username: participant.Username, PartialSign: participant.PartialSign, }