2020-08-06 17:20:13 -07:00
|
|
|
package dkg_proposal_fsm
|
|
|
|
|
|
|
|
import (
|
2020-08-07 16:20:20 -07:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
2020-08-11 09:46:18 -07:00
|
|
|
"github.com/depools/dc4bc/fsm/config"
|
2020-08-06 17:20:13 -07:00
|
|
|
"github.com/depools/dc4bc/fsm/fsm"
|
2020-08-07 16:20:20 -07:00
|
|
|
"github.com/depools/dc4bc/fsm/state_machines/internal"
|
|
|
|
"github.com/depools/dc4bc/fsm/types/requests"
|
2020-08-11 09:46:18 -07:00
|
|
|
"time"
|
2020-08-06 17:20:13 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// Pub keys
|
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
func (m *DKGProposalFSM) actionPubKeyConfirmationReceived(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
2020-08-07 16:20:20 -07:00
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
if len(args) != 1 {
|
|
|
|
err = errors.New("{arg0} required {DKGProposalPubKeyConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
request, ok := args[0].(requests.DKGProposalPubKeyConfirmationRequest)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
err = errors.New("cannot cast {arg0} to type {DKGProposalPubKeyConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = request.Validate(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
if !m.payload.DKGQuorumExists(request.ParticipantId) {
|
2020-08-07 16:20:20 -07:00
|
|
|
err = errors.New("{ParticipantId} not exist in quorum")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant := m.payload.DKGQuorumGet(request.ParticipantId)
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
if dkgProposalParticipant.Status != internal.PubKeyAwaitConfirmation {
|
|
|
|
err = errors.New(fmt.Sprintf("cannot confirm pubkey with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
copy(dkgProposalParticipant.PubKey, request.PubKey)
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
2020-08-07 16:20:20 -07:00
|
|
|
dkgProposalParticipant.Status = internal.PubKeyConfirmed
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
2020-08-07 16:20:20 -07:00
|
|
|
|
2020-08-06 17:20:13 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
func (m *DKGProposalFSM) actionValidateDkgProposalPubKeys(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
|
|
|
var (
|
|
|
|
isContainsError, isContainsExpired bool
|
|
|
|
)
|
|
|
|
|
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
tm := time.Now()
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
2020-08-11 09:46:18 -07:00
|
|
|
if participant.Status == internal.PubKeyAwaitConfirmation {
|
|
|
|
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
|
|
|
isContainsExpired = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if participant.Status == internal.PubKeyConfirmationError {
|
|
|
|
isContainsError = true
|
|
|
|
} else if participant.Status == internal.PubKeyConfirmed {
|
|
|
|
unconfirmedParticipants--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsError {
|
|
|
|
outEvent = eventDKGSetPubKeysConfirmationCanceledByErrorInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsExpired {
|
|
|
|
outEvent = eventDKGSetPubKeysConfirmationCanceledByTimeoutInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// The are no declined and timed out participants, check for all confirmations
|
|
|
|
if unconfirmedParticipants > 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
outEvent = eventDKGSetPubKeysConfirmedInternal
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
2020-08-11 09:46:18 -07:00
|
|
|
participant.Status = internal.CommitAwaitConfirmation
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-06 17:20:13 -07:00
|
|
|
// Commits
|
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
func (m *DKGProposalFSM) actionCommitConfirmationReceived(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
2020-08-07 16:20:20 -07:00
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
if len(args) != 1 {
|
|
|
|
err = errors.New("{arg0} required {DKGProposalCommitConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
request, ok := args[0].(requests.DKGProposalCommitConfirmationRequest)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
err = errors.New("cannot cast {arg0} to type {DKGProposalCommitConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = request.Validate(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
if !m.payload.DKGQuorumExists(request.ParticipantId) {
|
2020-08-07 16:20:20 -07:00
|
|
|
err = errors.New("{ParticipantId} not exist in quorum")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant := m.payload.DKGQuorumGet(request.ParticipantId)
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
if dkgProposalParticipant.Status != internal.CommitAwaitConfirmation {
|
|
|
|
err = errors.New(fmt.Sprintf("cannot confirm commit with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
copy(dkgProposalParticipant.Commit, request.Commit)
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
2020-08-07 16:20:20 -07:00
|
|
|
dkgProposalParticipant.Status = internal.CommitConfirmed
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
2020-08-06 17:20:13 -07:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
|
|
|
var (
|
|
|
|
isContainsError, isContainsExpired bool
|
|
|
|
)
|
|
|
|
|
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
tm := time.Now()
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
2020-08-11 09:46:18 -07:00
|
|
|
if participant.Status == internal.CommitAwaitConfirmation {
|
2020-08-12 06:40:03 -07:00
|
|
|
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
2020-08-11 09:46:18 -07:00
|
|
|
isContainsExpired = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if participant.Status == internal.CommitConfirmationError {
|
|
|
|
isContainsError = true
|
|
|
|
} else if participant.Status == internal.CommitConfirmed {
|
|
|
|
unconfirmedParticipants--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsError {
|
|
|
|
outEvent = eventDKGCommitsConfirmationCancelByTimeoutInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsExpired {
|
|
|
|
outEvent = eventDKGCommitsConfirmationCancelByErrorInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// The are no declined and timed out participants, check for all confirmations
|
|
|
|
if unconfirmedParticipants > 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
outEvent = eventDKGCommitsConfirmedInternal
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
2020-08-11 09:46:18 -07:00
|
|
|
participant.Status = internal.DealAwaitConfirmation
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-06 17:20:13 -07:00
|
|
|
// Deals
|
2020-08-07 16:20:20 -07:00
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
func (m *DKGProposalFSM) actionDealConfirmationReceived(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
2020-08-07 16:20:20 -07:00
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
if len(args) != 1 {
|
|
|
|
err = errors.New("{arg0} required {DKGProposalDealConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
request, ok := args[0].(requests.DKGProposalDealConfirmationRequest)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
err = errors.New("cannot cast {arg0} to type {DKGProposalDealConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = request.Validate(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
if !m.payload.DKGQuorumExists(request.ParticipantId) {
|
2020-08-07 16:20:20 -07:00
|
|
|
err = errors.New("{ParticipantId} not exist in quorum")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant := m.payload.DKGQuorumGet(request.ParticipantId)
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
if dkgProposalParticipant.Status != internal.DealAwaitConfirmation {
|
|
|
|
err = errors.New(fmt.Sprintf("cannot confirm deal with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
copy(dkgProposalParticipant.Deal, request.Deal)
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
2020-08-07 16:20:20 -07:00
|
|
|
dkgProposalParticipant.Status = internal.DealConfirmed
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
2020-08-07 16:20:20 -07:00
|
|
|
|
2020-08-06 17:20:13 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
|
|
|
var (
|
|
|
|
isContainsError, isContainsExpired bool
|
|
|
|
)
|
|
|
|
|
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
tm := time.Now()
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
2020-08-11 09:46:18 -07:00
|
|
|
if participant.Status == internal.DealAwaitConfirmation {
|
2020-08-12 06:40:03 -07:00
|
|
|
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
2020-08-11 09:46:18 -07:00
|
|
|
isContainsExpired = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if participant.Status == internal.DealConfirmationError {
|
|
|
|
isContainsError = true
|
|
|
|
} else if participant.Status == internal.DealConfirmed {
|
|
|
|
unconfirmedParticipants--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsError {
|
|
|
|
outEvent = eventDKGDealsConfirmationCancelByErrorInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsExpired {
|
|
|
|
outEvent = eventDKGDealsConfirmationCancelByTimeoutInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// The are no declined and timed out participants, check for all confirmations
|
|
|
|
if unconfirmedParticipants > 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
outEvent = eventDKGDealsConfirmedInternal
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
2020-08-11 09:46:18 -07:00
|
|
|
participant.Status = internal.ResponseAwaitConfirmation
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-07 16:20:20 -07:00
|
|
|
// Responses
|
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
func (m *DKGProposalFSM) actionResponseConfirmationReceived(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
2020-08-07 16:20:20 -07:00
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
if len(args) != 1 {
|
|
|
|
err = errors.New("{arg0} required {DKGProposalResponseConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
request, ok := args[0].(requests.DKGProposalResponseConfirmationRequest)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
err = errors.New("cannot cast {arg0} to type {DKGProposalResponseConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = request.Validate(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
if !m.payload.DKGQuorumExists(request.ParticipantId) {
|
2020-08-07 16:20:20 -07:00
|
|
|
err = errors.New("{ParticipantId} not exist in quorum")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant := m.payload.DKGQuorumGet(request.ParticipantId)
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
if dkgProposalParticipant.Status != internal.ResponseAwaitConfirmation {
|
|
|
|
err = errors.New(fmt.Sprintf("cannot confirm response with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
copy(dkgProposalParticipant.Response, request.Response)
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
2020-08-07 16:20:20 -07:00
|
|
|
dkgProposalParticipant.Status = internal.ResponseConfirmed
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
2020-08-07 16:20:20 -07:00
|
|
|
|
2020-08-06 17:20:13 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
|
|
|
var (
|
|
|
|
isContainsError, isContainsExpired bool
|
|
|
|
)
|
|
|
|
|
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
tm := time.Now()
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
2020-08-11 09:46:18 -07:00
|
|
|
if participant.Status == internal.ResponseAwaitConfirmation {
|
2020-08-12 06:40:03 -07:00
|
|
|
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
2020-08-11 09:46:18 -07:00
|
|
|
isContainsExpired = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if participant.Status == internal.ResponseConfirmationError {
|
|
|
|
isContainsError = true
|
|
|
|
} else if participant.Status == internal.ResponseConfirmed {
|
|
|
|
unconfirmedParticipants--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsError {
|
|
|
|
outEvent = eventDKGResponseConfirmationCancelByErrorInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsExpired {
|
|
|
|
outEvent = eventDKGResponseConfirmationCancelByTimeoutInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// The are no declined and timed out participants, check for all confirmations
|
|
|
|
if unconfirmedParticipants > 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
outEvent = eventDKGResponsesConfirmedInternal
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
|
|
|
participant.Status = internal.MasterKeyAwaitConfirmation
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Master key
|
|
|
|
|
|
|
|
func (m *DKGProposalFSM) actionMasterKeyConfirmationReceived(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
if len(args) != 1 {
|
|
|
|
err = errors.New("{arg0} required {DKGProposalMasterKeyConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
request, ok := args[0].(requests.DKGProposalMasterKeyConfirmationRequest)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
err = errors.New("cannot cast {arg0} to type {DKGProposalMasterKeyConfirmationRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = request.Validate(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !m.payload.DKGQuorumExists(request.ParticipantId) {
|
|
|
|
err = errors.New("{ParticipantId} not exist in quorum")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
dkgProposalParticipant := m.payload.DKGQuorumGet(request.ParticipantId)
|
|
|
|
|
|
|
|
if dkgProposalParticipant.Status != internal.MasterKeyAwaitConfirmation {
|
|
|
|
err = errors.New(fmt.Sprintf("cannot confirm response with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
copy(dkgProposalParticipant.MasterKey, request.MasterKey)
|
|
|
|
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
|
|
|
dkgProposalParticipant.Status = internal.MasterKeyConfirmed
|
|
|
|
|
|
|
|
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitMasterKey(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
|
|
|
var (
|
|
|
|
isContainsError, isContainsExpired bool
|
|
|
|
)
|
|
|
|
|
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
tm := time.Now()
|
|
|
|
|
|
|
|
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
|
|
|
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
|
|
|
if participant.Status == internal.MasterKeyAwaitConfirmation {
|
|
|
|
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
|
|
|
isContainsExpired = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if participant.Status == internal.MasterKeyConfirmationError {
|
|
|
|
isContainsError = true
|
|
|
|
} else if participant.Status == internal.MasterKeyConfirmed {
|
|
|
|
unconfirmedParticipants--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsError {
|
|
|
|
outEvent = eventDKGMasterKeyConfirmationCancelByErrorInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if isContainsExpired {
|
|
|
|
outEvent = eventDKGMasterKeyConfirmationCancelByTimeoutInternal
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// The are no declined and timed out participants, check for all confirmations
|
|
|
|
if unconfirmedParticipants > 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
outEvent = eventDKGMasterKeyConfirmedInternal
|
|
|
|
|
2020-08-11 09:46:18 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-07 16:20:20 -07:00
|
|
|
// Errors
|
2020-08-08 14:44:52 -07:00
|
|
|
func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
|
2020-08-07 16:20:20 -07:00
|
|
|
m.payloadMu.Lock()
|
|
|
|
defer m.payloadMu.Unlock()
|
|
|
|
|
|
|
|
if len(args) != 1 {
|
|
|
|
err = errors.New("{arg0} required {DKGProposalConfirmationErrorRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
request, ok := args[0].(requests.DKGProposalConfirmationErrorRequest)
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
err = errors.New("cannot cast {arg0} to type {DKGProposalConfirmationErrorRequest}")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = request.Validate(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
if !m.payload.DKGQuorumExists(request.ParticipantId) {
|
2020-08-07 16:20:20 -07:00
|
|
|
err = errors.New("{ParticipantId} not exist in quorum")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant := m.payload.DKGQuorumGet(request.ParticipantId)
|
|
|
|
|
2020-08-07 16:20:20 -07:00
|
|
|
// TODO: Move to methods
|
2020-08-08 14:44:52 -07:00
|
|
|
switch inEvent {
|
2020-08-07 16:20:20 -07:00
|
|
|
case EventDKGPubKeyConfirmationError:
|
|
|
|
switch dkgProposalParticipant.Status {
|
2020-08-11 09:46:18 -07:00
|
|
|
case internal.PubKeyAwaitConfirmation:
|
2020-08-07 16:20:20 -07:00
|
|
|
dkgProposalParticipant.Status = internal.PubKeyConfirmationError
|
|
|
|
case internal.PubKeyConfirmed:
|
|
|
|
err = errors.New("{Status} already confirmed")
|
|
|
|
case internal.PubKeyConfirmationError:
|
|
|
|
err = errors.New(fmt.Sprintf("{Status} already has {\"%s\"}", internal.PubKeyConfirmationError))
|
|
|
|
default:
|
|
|
|
err = errors.New(fmt.Sprintf(
|
|
|
|
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
|
|
|
dkgProposalParticipant.Status,
|
|
|
|
internal.PubKeyConfirmationError,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
case EventDKGCommitConfirmationError:
|
|
|
|
switch dkgProposalParticipant.Status {
|
|
|
|
case internal.CommitAwaitConfirmation:
|
|
|
|
dkgProposalParticipant.Status = internal.CommitConfirmationError
|
|
|
|
case internal.CommitConfirmed:
|
|
|
|
err = errors.New("{Status} already confirmed")
|
|
|
|
case internal.CommitConfirmationError:
|
|
|
|
err = errors.New(fmt.Sprintf("{Status} already has {\"%s\"}", internal.CommitConfirmationError))
|
|
|
|
default:
|
|
|
|
err = errors.New(fmt.Sprintf(
|
|
|
|
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
|
|
|
dkgProposalParticipant.Status,
|
2020-08-12 06:40:03 -07:00
|
|
|
internal.CommitConfirmationError,
|
2020-08-07 16:20:20 -07:00
|
|
|
))
|
|
|
|
}
|
|
|
|
case EventDKGDealConfirmationError:
|
|
|
|
switch dkgProposalParticipant.Status {
|
|
|
|
case internal.DealAwaitConfirmation:
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant.Status = internal.DealConfirmationError
|
2020-08-07 16:20:20 -07:00
|
|
|
case internal.DealConfirmed:
|
|
|
|
err = errors.New("{Status} already confirmed")
|
|
|
|
case internal.DealConfirmationError:
|
|
|
|
err = errors.New(fmt.Sprintf("{Status} already has {\"%s\"}", internal.DealConfirmationError))
|
|
|
|
default:
|
|
|
|
err = errors.New(fmt.Sprintf(
|
|
|
|
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
|
|
|
dkgProposalParticipant.Status,
|
2020-08-12 06:40:03 -07:00
|
|
|
internal.DealConfirmationError,
|
2020-08-07 16:20:20 -07:00
|
|
|
))
|
|
|
|
}
|
|
|
|
case EventDKGResponseConfirmationError:
|
|
|
|
switch dkgProposalParticipant.Status {
|
|
|
|
case internal.ResponseAwaitConfirmation:
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant.Status = internal.ResponseConfirmationError
|
2020-08-07 16:20:20 -07:00
|
|
|
case internal.ResponseConfirmed:
|
|
|
|
err = errors.New("{Status} already confirmed")
|
|
|
|
case internal.ResponseConfirmationError:
|
|
|
|
err = errors.New(fmt.Sprintf("{Status} already has {\"%s\"}", internal.ResponseConfirmationError))
|
|
|
|
default:
|
|
|
|
err = errors.New(fmt.Sprintf(
|
|
|
|
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
|
|
|
dkgProposalParticipant.Status,
|
2020-08-12 06:40:03 -07:00
|
|
|
internal.ResponseConfirmationError,
|
|
|
|
))
|
|
|
|
}
|
|
|
|
case EventDKGMasterKeyConfirmationError:
|
|
|
|
switch dkgProposalParticipant.Status {
|
|
|
|
case internal.MasterKeyAwaitConfirmation:
|
|
|
|
dkgProposalParticipant.Status = internal.MasterKeyConfirmationError
|
|
|
|
case internal.MasterKeyConfirmed:
|
|
|
|
err = errors.New("{Status} already confirmed")
|
|
|
|
case internal.MasterKeyConfirmationError:
|
|
|
|
err = errors.New(fmt.Sprintf("{Status} already has {\"%s\"}", internal.MasterKeyConfirmationError))
|
|
|
|
default:
|
|
|
|
err = errors.New(fmt.Sprintf(
|
|
|
|
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
|
|
|
dkgProposalParticipant.Status,
|
|
|
|
internal.MasterKeyConfirmationError,
|
2020-08-07 16:20:20 -07:00
|
|
|
))
|
|
|
|
}
|
|
|
|
default:
|
2020-08-08 14:44:52 -07:00
|
|
|
err = errors.New(fmt.Sprintf("{%s} event cannot be used for action {actionConfirmationError}", inEvent))
|
2020-08-07 16:20:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
dkgProposalParticipant.Error = request.Error
|
|
|
|
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
2020-08-07 16:20:20 -07:00
|
|
|
|
2020-08-12 06:40:03 -07:00
|
|
|
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
2020-08-07 16:20:20 -07:00
|
|
|
|
2020-08-08 14:44:52 -07:00
|
|
|
// TODO: Add outEvent
|
|
|
|
|
2020-08-06 17:20:13 -07:00
|
|
|
return
|
|
|
|
}
|