mirror of https://github.com/certusone/dc4bc.git
feat: added additional stage
This commit is contained in:
parent
023a9f8d5c
commit
baf120cc66
|
@ -32,23 +32,23 @@ func (m *DKGProposalFSM) actionPubKeyConfirmationReceived(inEvent fsm.Event, arg
|
|||
return
|
||||
}
|
||||
|
||||
dkgProposalParticipant, ok := m.payload.DKGProposalPayload[request.ParticipantId]
|
||||
|
||||
if !ok {
|
||||
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.PubKeyAwaitConfirmation {
|
||||
err = errors.New(fmt.Sprintf("cannot confirm pubkey with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
||||
return
|
||||
}
|
||||
|
||||
copy(dkgProposalParticipant.PubKey, request.PubKey)
|
||||
dkgProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
||||
dkgProposalParticipant.Status = internal.PubKeyConfirmed
|
||||
|
||||
m.payload.DKGProposalPayload[request.ParticipantId] = dkgProposalParticipant
|
||||
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ func (m *DKGProposalFSM) actionValidateDkgProposalPubKeys(inEvent fsm.Event, arg
|
|||
|
||||
tm := time.Now()
|
||||
|
||||
unconfirmedParticipants := len(m.payload.DKGProposalPayload)
|
||||
for _, participant := range m.payload.DKGProposalPayload {
|
||||
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
||||
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
||||
if participant.Status == internal.PubKeyAwaitConfirmation {
|
||||
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
||||
isContainsExpired = true
|
||||
|
@ -95,7 +95,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalPubKeys(inEvent fsm.Event, arg
|
|||
|
||||
outEvent = eventDKGSetPubKeysConfirmedInternal
|
||||
|
||||
for _, participant := range m.payload.DKGProposalPayload {
|
||||
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
||||
participant.Status = internal.CommitAwaitConfirmation
|
||||
}
|
||||
|
||||
|
@ -124,23 +124,23 @@ func (m *DKGProposalFSM) actionCommitConfirmationReceived(inEvent fsm.Event, arg
|
|||
return
|
||||
}
|
||||
|
||||
dkgProposalParticipant, ok := m.payload.DKGProposalPayload[request.ParticipantId]
|
||||
|
||||
if !ok {
|
||||
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.CommitAwaitConfirmation {
|
||||
err = errors.New(fmt.Sprintf("cannot confirm commit with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
||||
return
|
||||
}
|
||||
|
||||
copy(dkgProposalParticipant.Commit, request.Commit)
|
||||
dkgProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
||||
dkgProposalParticipant.Status = internal.CommitConfirmed
|
||||
|
||||
m.payload.DKGProposalPayload[request.ParticipantId] = dkgProposalParticipant
|
||||
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -155,10 +155,10 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event
|
|||
|
||||
tm := time.Now()
|
||||
|
||||
unconfirmedParticipants := len(m.payload.DKGProposalPayload)
|
||||
for _, participant := range m.payload.DKGProposalPayload {
|
||||
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
||||
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
||||
if participant.Status == internal.CommitAwaitConfirmation {
|
||||
if participant.UpdatedAt.Add(config.SignatureProposalConfirmationDeadline).Before(tm) {
|
||||
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
||||
isContainsExpired = true
|
||||
}
|
||||
} else {
|
||||
|
@ -187,7 +187,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event
|
|||
|
||||
outEvent = eventDKGCommitsConfirmedInternal
|
||||
|
||||
for _, participant := range m.payload.DKGProposalPayload {
|
||||
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
||||
participant.Status = internal.DealAwaitConfirmation
|
||||
}
|
||||
|
||||
|
@ -216,23 +216,23 @@ func (m *DKGProposalFSM) actionDealConfirmationReceived(inEvent fsm.Event, args
|
|||
return
|
||||
}
|
||||
|
||||
dkgProposalParticipant, ok := m.payload.DKGProposalPayload[request.ParticipantId]
|
||||
|
||||
if !ok {
|
||||
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.DealAwaitConfirmation {
|
||||
err = errors.New(fmt.Sprintf("cannot confirm deal with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
||||
return
|
||||
}
|
||||
|
||||
copy(dkgProposalParticipant.Deal, request.Deal)
|
||||
dkgProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
||||
dkgProposalParticipant.Status = internal.DealConfirmed
|
||||
|
||||
m.payload.DKGProposalPayload[request.ParticipantId] = dkgProposalParticipant
|
||||
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -247,10 +247,10 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event,
|
|||
|
||||
tm := time.Now()
|
||||
|
||||
unconfirmedParticipants := len(m.payload.DKGProposalPayload)
|
||||
for _, participant := range m.payload.DKGProposalPayload {
|
||||
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
||||
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
||||
if participant.Status == internal.DealAwaitConfirmation {
|
||||
if participant.UpdatedAt.Add(config.SignatureProposalConfirmationDeadline).Before(tm) {
|
||||
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
||||
isContainsExpired = true
|
||||
}
|
||||
} else {
|
||||
|
@ -279,7 +279,7 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event,
|
|||
|
||||
outEvent = eventDKGDealsConfirmedInternal
|
||||
|
||||
for _, participant := range m.payload.DKGProposalPayload {
|
||||
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
||||
participant.Status = internal.ResponseAwaitConfirmation
|
||||
}
|
||||
|
||||
|
@ -308,23 +308,23 @@ func (m *DKGProposalFSM) actionResponseConfirmationReceived(inEvent fsm.Event, a
|
|||
return
|
||||
}
|
||||
|
||||
dkgProposalParticipant, ok := m.payload.DKGProposalPayload[request.ParticipantId]
|
||||
|
||||
if !ok {
|
||||
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.ResponseAwaitConfirmation {
|
||||
err = errors.New(fmt.Sprintf("cannot confirm response with {Status} = {\"%s\"}", dkgProposalParticipant.Status))
|
||||
return
|
||||
}
|
||||
|
||||
copy(dkgProposalParticipant.Response, request.Response)
|
||||
dkgProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
||||
dkgProposalParticipant.Status = internal.ResponseConfirmed
|
||||
|
||||
m.payload.DKGProposalPayload[request.ParticipantId] = dkgProposalParticipant
|
||||
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -339,10 +339,10 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Eve
|
|||
|
||||
tm := time.Now()
|
||||
|
||||
unconfirmedParticipants := len(m.payload.DKGProposalPayload)
|
||||
for _, participant := range m.payload.DKGProposalPayload {
|
||||
unconfirmedParticipants := m.payload.DKGQuorumCount()
|
||||
for _, participant := range m.payload.DKGProposalPayload.Quorum {
|
||||
if participant.Status == internal.ResponseAwaitConfirmation {
|
||||
if participant.UpdatedAt.Add(config.SignatureProposalConfirmationDeadline).Before(tm) {
|
||||
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
|
||||
isContainsExpired = true
|
||||
}
|
||||
} else {
|
||||
|
@ -371,6 +371,98 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Eve
|
|||
|
||||
outEvent = eventDKGResponsesConfirmedInternal
|
||||
|
||||
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
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -395,13 +487,13 @@ func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...inte
|
|||
return
|
||||
}
|
||||
|
||||
dkgProposalParticipant, ok := m.payload.DKGProposalPayload[request.ParticipantId]
|
||||
|
||||
if !ok {
|
||||
if !m.payload.DKGQuorumExists(request.ParticipantId) {
|
||||
err = errors.New("{ParticipantId} not exist in quorum")
|
||||
return
|
||||
}
|
||||
|
||||
dkgProposalParticipant := m.payload.DKGQuorumGet(request.ParticipantId)
|
||||
|
||||
// TODO: Move to methods
|
||||
switch inEvent {
|
||||
case EventDKGPubKeyConfirmationError:
|
||||
|
@ -431,13 +523,13 @@ func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...inte
|
|||
err = errors.New(fmt.Sprintf(
|
||||
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
||||
dkgProposalParticipant.Status,
|
||||
internal.PubKeyConfirmationError,
|
||||
internal.CommitConfirmationError,
|
||||
))
|
||||
}
|
||||
case EventDKGDealConfirmationError:
|
||||
switch dkgProposalParticipant.Status {
|
||||
case internal.DealAwaitConfirmation:
|
||||
dkgProposalParticipant.Status = internal.PubKeyConfirmationError
|
||||
dkgProposalParticipant.Status = internal.DealConfirmationError
|
||||
case internal.DealConfirmed:
|
||||
err = errors.New("{Status} already confirmed")
|
||||
case internal.DealConfirmationError:
|
||||
|
@ -446,13 +538,13 @@ func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...inte
|
|||
err = errors.New(fmt.Sprintf(
|
||||
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
||||
dkgProposalParticipant.Status,
|
||||
internal.PubKeyConfirmationError,
|
||||
internal.DealConfirmationError,
|
||||
))
|
||||
}
|
||||
case EventDKGResponseConfirmationError:
|
||||
switch dkgProposalParticipant.Status {
|
||||
case internal.ResponseAwaitConfirmation:
|
||||
dkgProposalParticipant.Status = internal.PubKeyConfirmationError
|
||||
dkgProposalParticipant.Status = internal.ResponseConfirmationError
|
||||
case internal.ResponseConfirmed:
|
||||
err = errors.New("{Status} already confirmed")
|
||||
case internal.ResponseConfirmationError:
|
||||
|
@ -461,7 +553,22 @@ func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...inte
|
|||
err = errors.New(fmt.Sprintf(
|
||||
"{Status} now is \"%s\" and cannot set to {\"%s\"}",
|
||||
dkgProposalParticipant.Status,
|
||||
internal.PubKeyConfirmationError,
|
||||
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,
|
||||
))
|
||||
}
|
||||
default:
|
||||
|
@ -472,9 +579,10 @@ func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...inte
|
|||
return
|
||||
}
|
||||
|
||||
dkgProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
dkgProposalParticipant.Error = request.Error
|
||||
dkgProposalParticipant.UpdatedAt = &request.CreatedAt
|
||||
|
||||
m.payload.DKGProposalPayload[request.ParticipantId] = dkgProposalParticipant
|
||||
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
|
||||
|
||||
// TODO: Add outEvent
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ const (
|
|||
StateDkgDealsAwaitConfirmations = fsm.State("state_dkg_deals_await_confirmations")
|
||||
// Canceled
|
||||
StateDkgDealsAwaitCanceled = fsm.State("state_dkg_deals_await_canceled")
|
||||
StateDkgDealsAwaitCanceledByTimeout = fsm.State("state_dkg_deals_sending_canceled_by_timeout")
|
||||
StateDkgDealsAwaitCanceledByTimeout = fsm.State("state_dkg_deals_await_canceled_by_timeout")
|
||||
// Confirmed
|
||||
//StateDkgDealsAwaitConfirmed = fsm.State("state_dkg_deals_await_confirmed")
|
||||
|
||||
|
@ -41,6 +41,10 @@ const (
|
|||
// Confirmed
|
||||
StateDkgResponsesAwaitConfirmed = fsm.State("state_dkg_responses_await_confirmed")
|
||||
|
||||
StateDkgMasterKeyAwaitConfirmations = fsm.State("state_dkg_master_key_await_confirmations")
|
||||
StateDkgMasterKeyAwaitCanceled = fsm.State("state_dkg_master_key_await_canceled")
|
||||
StateDkgMasterKeyAwaitCanceledByTimeout = fsm.State("state_dkg_master_key_await_canceled_by_timeout")
|
||||
|
||||
// Events
|
||||
|
||||
eventAutoDKGInitialInternal = fsm.Event("event_dkg_init_internal")
|
||||
|
@ -75,6 +79,13 @@ const (
|
|||
eventDKGResponsesConfirmedInternal = fsm.Event("event_dkg_responses_confirmed_internal")
|
||||
eventAutoDKGValidateResponsesConfirmationInternal = fsm.Event("event_dkg_responses_validate_internal")
|
||||
|
||||
EventDKGMasterKeyConfirmationReceived = fsm.Event("event_dkg_master_key_confirm_received")
|
||||
EventDKGMasterKeyConfirmationError = fsm.Event("event_dkg_master_key_confirm_canceled_by_error")
|
||||
eventDKGMasterKeyConfirmationCancelByTimeoutInternal = fsm.Event("event_dkg_master_key_confirm_canceled_by_timeout_internal")
|
||||
eventDKGMasterKeyConfirmationCancelByErrorInternal = fsm.Event("event_dkg_master_key_confirm_canceled_by_error_internal")
|
||||
eventDKGMasterKeyConfirmedInternal = fsm.Event("event_dkg_master_key_confirmed_internal")
|
||||
eventAutoDKGValidateMasterKeyConfirmationInternal = fsm.Event("event_dkg_master_key_validate_internal")
|
||||
|
||||
EventDKGMasterKeyRequiredInternal = fsm.Event("event_dkg_master_key_required_internal")
|
||||
)
|
||||
|
||||
|
@ -139,7 +150,17 @@ func New() internal.DumpedMachineProvider {
|
|||
|
||||
{Name: eventAutoDKGValidateResponsesConfirmationInternal, SrcState: []fsm.State{StateDkgResponsesAwaitConfirmations}, DstState: StateDkgResponsesAwaitConfirmations, IsInternal: true, IsAuto: true},
|
||||
|
||||
{Name: eventDKGResponsesConfirmedInternal, SrcState: []fsm.State{StateDkgResponsesAwaitConfirmations}, DstState: fsm.StateGlobalDone, IsInternal: true},
|
||||
{Name: eventDKGResponsesConfirmedInternal, SrcState: []fsm.State{StateDkgResponsesAwaitConfirmations}, DstState: StateDkgMasterKeyAwaitConfirmations, IsInternal: true},
|
||||
|
||||
// Master key
|
||||
|
||||
{Name: EventDKGMasterKeyConfirmationReceived, SrcState: []fsm.State{StateDkgMasterKeyAwaitConfirmations}, DstState: StateDkgMasterKeyAwaitConfirmations},
|
||||
{Name: EventDKGMasterKeyConfirmationError, SrcState: []fsm.State{StateDkgMasterKeyAwaitConfirmations}, DstState: StateDkgMasterKeyAwaitCanceled},
|
||||
{Name: eventDKGMasterKeyConfirmationCancelByTimeoutInternal, SrcState: []fsm.State{StateDkgMasterKeyAwaitConfirmations}, DstState: StateDkgMasterKeyAwaitCanceledByTimeout, IsInternal: true},
|
||||
|
||||
{Name: eventAutoDKGValidateMasterKeyConfirmationInternal, SrcState: []fsm.State{StateDkgMasterKeyAwaitConfirmations}, DstState: StateDkgMasterKeyAwaitConfirmations, IsInternal: true, IsAuto: true},
|
||||
|
||||
{Name: eventDKGMasterKeyConfirmedInternal, SrcState: []fsm.State{StateDkgMasterKeyAwaitConfirmations}, DstState: fsm.StateGlobalDone, IsInternal: true},
|
||||
|
||||
// Done
|
||||
// {Name: EventDKGMasterKeyRequiredInternal, SrcState: []fsm.State{StateDkgResponsesAwaitConfirmations}, DstState: fsm.StateGlobalDone, IsInternal: true},
|
||||
|
@ -161,6 +182,10 @@ func New() internal.DumpedMachineProvider {
|
|||
EventDKGResponseConfirmationReceived: machine.actionResponseConfirmationReceived,
|
||||
EventDKGResponseConfirmationError: machine.actionConfirmationError,
|
||||
eventAutoDKGValidateResponsesConfirmationInternal: machine.actionValidateDkgProposalAwaitResponses,
|
||||
|
||||
EventDKGMasterKeyConfirmationReceived: machine.actionMasterKeyConfirmationReceived,
|
||||
EventDKGMasterKeyConfirmationError: machine.actionConfirmationError,
|
||||
eventAutoDKGValidateMasterKeyConfirmationInternal: machine.actionValidateDkgProposalAwaitMasterKey,
|
||||
},
|
||||
)
|
||||
return machine
|
||||
|
|
|
@ -2,13 +2,79 @@ package internal
|
|||
|
||||
import "github.com/depools/dc4bc/fsm/fsm_pool"
|
||||
|
||||
type DumpedMachineStatePayload struct {
|
||||
TransactionId string
|
||||
ConfirmationProposalPayload SignatureProposalQuorum
|
||||
DKGProposalPayload DKGProposalQuorum
|
||||
}
|
||||
|
||||
type DumpedMachineProvider interface {
|
||||
fsm_pool.MachineProvider
|
||||
SetUpPayload(payload *DumpedMachineStatePayload)
|
||||
}
|
||||
|
||||
// DKG and other stages quorums are separated,
|
||||
// because unnecessary data may be unset
|
||||
type DumpedMachineStatePayload struct {
|
||||
TransactionId string
|
||||
SignatureProposalPayload *SignatureConfirmation
|
||||
DKGProposalPayload *DKGConfirmation
|
||||
}
|
||||
|
||||
// Signature quorum
|
||||
|
||||
func (p *DumpedMachineStatePayload) SigQuorumCount() int {
|
||||
var count int
|
||||
if p.SignatureProposalPayload.Quorum != nil {
|
||||
count = len(p.SignatureProposalPayload.Quorum)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (p *DumpedMachineStatePayload) SigQuorumExists(id string) bool {
|
||||
var exists bool
|
||||
if p.SignatureProposalPayload.Quorum != nil {
|
||||
_, exists = p.SignatureProposalPayload.Quorum[id]
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func (p *DumpedMachineStatePayload) SigQuorumGet(id string) (participant *SignatureProposalParticipant) {
|
||||
if p.SignatureProposalPayload.Quorum != nil {
|
||||
participant, _ = p.SignatureProposalPayload.Quorum[id]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *DumpedMachineStatePayload) SigQuorumUpdate(id string, participant *SignatureProposalParticipant) {
|
||||
if p.SignatureProposalPayload.Quorum != nil {
|
||||
p.SignatureProposalPayload.Quorum[id] = participant
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DKG quorum
|
||||
|
||||
func (p *DumpedMachineStatePayload) DKGQuorumCount() int {
|
||||
var count int
|
||||
if p.DKGProposalPayload.Quorum != nil {
|
||||
count = len(p.DKGProposalPayload.Quorum)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
func (p *DumpedMachineStatePayload) DKGQuorumExists(id int) bool {
|
||||
var exists bool
|
||||
if p.DKGProposalPayload.Quorum != nil {
|
||||
_, exists = p.DKGProposalPayload.Quorum[id]
|
||||
}
|
||||
return exists
|
||||
}
|
||||
|
||||
func (p *DumpedMachineStatePayload) DKGQuorumGet(id int) (participant *DKGProposalParticipant) {
|
||||
if p.DKGProposalPayload.Quorum != nil {
|
||||
participant, _ = p.DKGProposalPayload.Quorum[id]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *DumpedMachineStatePayload) DKGQuorumUpdate(id int, participant *DKGProposalParticipant) {
|
||||
if p.DKGProposalPayload.Quorum != nil {
|
||||
p.DKGProposalPayload.Quorum[id] = participant
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
type ConfirmationProposal struct {
|
||||
type SignatureConfirmation struct {
|
||||
Quorum SignatureProposalQuorum
|
||||
CreatedAt *time.Time
|
||||
ExpiresAt *time.Time
|
||||
|
@ -45,6 +45,9 @@ const (
|
|||
ResponseAwaitConfirmation
|
||||
ResponseConfirmed
|
||||
ResponseConfirmationError
|
||||
MasterKeyAwaitConfirmation
|
||||
MasterKeyConfirmed
|
||||
MasterKeyConfirmationError
|
||||
)
|
||||
|
||||
type DKGProposalParticipant struct {
|
||||
|
@ -53,12 +56,20 @@ type DKGProposalParticipant struct {
|
|||
Commit []byte
|
||||
Deal []byte
|
||||
Response []byte
|
||||
MasterKey []byte
|
||||
Status ParticipantStatus
|
||||
Error error
|
||||
UpdatedAt *time.Time
|
||||
}
|
||||
|
||||
type DKGProposalQuorum map[int]*DKGProposalParticipant
|
||||
|
||||
type DKGConfirmation struct {
|
||||
Quorum DKGProposalQuorum
|
||||
CreatedAt *time.Time
|
||||
ExpiresAt *time.Time
|
||||
}
|
||||
|
||||
type DKGProposalParticipantStatus uint8
|
||||
|
||||
func (s ParticipantStatus) String() string {
|
||||
|
|
|
@ -66,7 +66,7 @@ func Create() (*FSMInstance, error) {
|
|||
return i, err
|
||||
}
|
||||
|
||||
// Get fsm from dump
|
||||
// DKGQuorumGet fsm from dump
|
||||
func FromDump(data []byte) (*FSMInstance, error) {
|
||||
var err error
|
||||
|
||||
|
@ -128,7 +128,7 @@ func (i *FSMInstance) InitDump(transactionId string) error {
|
|||
State: fsm.StateGlobalIdle,
|
||||
Payload: &internal.DumpedMachineStatePayload{
|
||||
TransactionId: transactionId,
|
||||
ConfirmationProposalPayload: nil,
|
||||
SignatureProposalPayload: nil,
|
||||
DKGProposalPayload: nil,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ func Test_SignatureProposal_Positive(t *testing.T) {
|
|||
fsmResponse, dump, err = testFSMInstance.Do(dpf.EventDKGPubKeyConfirmationReceived, requests.DKGProposalPubKeyConfirmationRequest{
|
||||
ParticipantId: participant.ParticipantId,
|
||||
PubKey: pubKeyMock,
|
||||
CreatedAt: &tm,
|
||||
CreatedAt: tm,
|
||||
})
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
@ -306,7 +306,7 @@ func Test_SignatureProposal_Positive(t *testing.T) {
|
|||
fsmResponse, dump, err = testFSMInstance.Do(dpf.EventDKGCommitConfirmationReceived, requests.DKGProposalCommitConfirmationRequest{
|
||||
ParticipantId: participant.ParticipantId,
|
||||
Commit: commitMock,
|
||||
CreatedAt: &tm,
|
||||
CreatedAt: tm,
|
||||
})
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
@ -342,7 +342,7 @@ func Test_SignatureProposal_Positive(t *testing.T) {
|
|||
fsmResponse, dump, err = testFSMInstance.Do(dpf.EventDKGDealConfirmationReceived, requests.DKGProposalDealConfirmationRequest{
|
||||
ParticipantId: participant.ParticipantId,
|
||||
Deal: dealMock,
|
||||
CreatedAt: &tm,
|
||||
CreatedAt: tm,
|
||||
})
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
@ -378,7 +378,43 @@ func Test_SignatureProposal_Positive(t *testing.T) {
|
|||
fsmResponse, dump, err = testFSMInstance.Do(dpf.EventDKGResponseConfirmationReceived, requests.DKGProposalResponseConfirmationRequest{
|
||||
ParticipantId: participant.ParticipantId,
|
||||
Response: responseMock,
|
||||
CreatedAt: &tm,
|
||||
CreatedAt: tm,
|
||||
})
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
||||
compareDumpNotZero(t, dump)
|
||||
|
||||
compareFSMResponseNotNil(t, fsmResponse)
|
||||
|
||||
}
|
||||
|
||||
compareState(t, dpf.StateDkgMasterKeyAwaitConfirmations, fsmResponse.State)
|
||||
|
||||
// Master keys
|
||||
|
||||
masterKeyMock := make([]byte, 128)
|
||||
_, err = rand.Read(masterKeyMock)
|
||||
if err != nil {
|
||||
compareErrNil(t, err)
|
||||
}
|
||||
|
||||
for _, participant := range participantsMap {
|
||||
participantCounter--
|
||||
testFSMInstance, err = FromDump(dump)
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
||||
compareFSMInstanceNotNil(t, testFSMInstance)
|
||||
|
||||
if _, ok := testParticipants[participant.PubKeyFingerprint]; !ok {
|
||||
t.Fatalf("not found external user data for response fingerprint")
|
||||
}
|
||||
|
||||
fsmResponse, dump, err = testFSMInstance.Do(dpf.EventDKGMasterKeyConfirmationReceived, requests.DKGProposalMasterKeyConfirmationRequest{
|
||||
ParticipantId: participant.ParticipantId,
|
||||
MasterKey: masterKeyMock,
|
||||
CreatedAt: tm,
|
||||
})
|
||||
|
||||
compareErrNil(t, err)
|
||||
|
@ -391,3 +427,7 @@ func Test_SignatureProposal_Positive(t *testing.T) {
|
|||
|
||||
compareState(t, fsm.StateGlobalDone, fsmResponse.State)
|
||||
}
|
||||
|
||||
func Test_DKGProposal_Positive(t *testing.T) {
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,9 @@ func (m *SignatureProposalFSM) actionInitProposal(inEvent fsm.Event, args ...int
|
|||
return
|
||||
}
|
||||
|
||||
m.payload.ConfirmationProposalPayload = make(internal.SignatureProposalQuorum)
|
||||
m.payload.SignatureProposalPayload = &internal.SignatureConfirmation{
|
||||
Quorum: make(internal.SignatureProposalQuorum),
|
||||
}
|
||||
|
||||
for index, participant := range request.Participants {
|
||||
participantId := createFingerprint(&participant.PubKey)
|
||||
|
@ -49,7 +51,7 @@ func (m *SignatureProposalFSM) actionInitProposal(inEvent fsm.Event, args ...int
|
|||
return inEvent, nil, errors.New("cannot parse {PubKey}")
|
||||
}
|
||||
|
||||
m.payload.ConfirmationProposalPayload[participantId] = &internal.SignatureProposalParticipant{
|
||||
m.payload.SignatureProposalPayload.Quorum[participantId] = &internal.SignatureProposalParticipant{
|
||||
ParticipantId: index,
|
||||
Title: participant.Title,
|
||||
PublicKey: parsedPubKey,
|
||||
|
@ -60,7 +62,7 @@ func (m *SignatureProposalFSM) actionInitProposal(inEvent fsm.Event, args ...int
|
|||
}
|
||||
|
||||
// Checking fo quorum length
|
||||
if len(m.payload.ConfirmationProposalPayload) != len(request.Participants) {
|
||||
if m.payload.SigQuorumCount() != len(request.Participants) {
|
||||
err = errors.New("error with creating {SignatureProposalQuorum}")
|
||||
return
|
||||
}
|
||||
|
@ -69,7 +71,7 @@ func (m *SignatureProposalFSM) actionInitProposal(inEvent fsm.Event, args ...int
|
|||
|
||||
responseData := make(responses.SignatureProposalParticipantInvitationsResponse, 0)
|
||||
|
||||
for pubKeyFingerprint, proposal := range m.payload.ConfirmationProposalPayload {
|
||||
for pubKeyFingerprint, proposal := range m.payload.SignatureProposalPayload.Quorum {
|
||||
encryptedInvitationSecret, err := encryptWithPubKey(proposal.PublicKey, proposal.InvitationSecret)
|
||||
if err != nil {
|
||||
return inEvent, nil, errors.New("cannot encryptWithPubKey")
|
||||
|
@ -108,13 +110,13 @@ func (m *SignatureProposalFSM) actionProposalResponseByParticipant(inEvent fsm.E
|
|||
return
|
||||
}
|
||||
|
||||
signatureProposalParticipant, ok := m.payload.ConfirmationProposalPayload[request.PubKeyFingerprint]
|
||||
|
||||
if !ok {
|
||||
if !m.payload.SigQuorumExists(request.PubKeyFingerprint) {
|
||||
err = errors.New("{PubKeyFingerprint} not exist in quorum")
|
||||
return
|
||||
}
|
||||
|
||||
signatureProposalParticipant := m.payload.SigQuorumGet(request.PubKeyFingerprint)
|
||||
|
||||
if signatureProposalParticipant.InvitationSecret != request.DecryptedInvitation {
|
||||
err = errors.New("{InvitationSecret} not match {DecryptedInvitation}")
|
||||
return
|
||||
|
@ -142,7 +144,7 @@ func (m *SignatureProposalFSM) actionProposalResponseByParticipant(inEvent fsm.E
|
|||
|
||||
signatureProposalParticipant.UpdatedAt = request.CreatedAt
|
||||
|
||||
m.payload.ConfirmationProposalPayload[request.PubKeyFingerprint] = signatureProposalParticipant
|
||||
m.payload.SigQuorumUpdate(request.PubKeyFingerprint, signatureProposalParticipant)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -157,8 +159,8 @@ func (m *SignatureProposalFSM) actionValidateSignatureProposal(inEvent fsm.Event
|
|||
|
||||
tm := time.Now()
|
||||
|
||||
unconfirmedParticipants := len(m.payload.ConfirmationProposalPayload)
|
||||
for _, participant := range m.payload.ConfirmationProposalPayload {
|
||||
unconfirmedParticipants := m.payload.SigQuorumCount()
|
||||
for _, participant := range m.payload.SignatureProposalPayload.Quorum {
|
||||
if participant.Status == internal.SignatureConfirmationAwaitConfirmation {
|
||||
if participant.UpdatedAt.Add(config.SignatureProposalConfirmationDeadline).Before(tm) {
|
||||
isContainsExpired = true
|
||||
|
@ -203,17 +205,19 @@ func (m *SignatureProposalFSM) actionSetValidatedSignatureProposal(inEvent fsm.E
|
|||
return
|
||||
}
|
||||
|
||||
m.payload.DKGProposalPayload = make(internal.DKGProposalQuorum)
|
||||
m.payload.DKGProposalPayload = &internal.DKGConfirmation{
|
||||
Quorum: make(internal.DKGProposalQuorum),
|
||||
}
|
||||
|
||||
for _, participant := range m.payload.ConfirmationProposalPayload {
|
||||
m.payload.DKGProposalPayload[participant.ParticipantId] = &internal.DKGProposalParticipant{
|
||||
for _, participant := range m.payload.SignatureProposalPayload.Quorum {
|
||||
m.payload.DKGProposalPayload.Quorum[participant.ParticipantId] = &internal.DKGProposalParticipant{
|
||||
Title: participant.Title,
|
||||
Status: internal.PubKeyAwaitConfirmation,
|
||||
UpdatedAt: participant.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
// Remove m.payload.ConfirmationProposalPayload?
|
||||
// Remove m.payload.SignatureProposalPayload?
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -224,7 +228,7 @@ func (m *SignatureProposalFSM) actionSignatureProposalCanceledByTimeout(inEvent
|
|||
|
||||
responseData := make(responses.SignatureProposalParticipantStatusResponse, 0)
|
||||
|
||||
for pubKeyFingerprint, participant := range m.payload.ConfirmationProposalPayload {
|
||||
for pubKeyFingerprint, participant := range m.payload.SignatureProposalPayload.Quorum {
|
||||
responseEntry := &responses.SignatureProposalParticipantStatusEntry{
|
||||
ParticipantId: participant.ParticipantId,
|
||||
Title: participant.Title,
|
||||
|
|
|
@ -7,7 +7,7 @@ import "time"
|
|||
type DKGProposalPubKeyConfirmationRequest struct {
|
||||
ParticipantId int
|
||||
PubKey []byte
|
||||
CreatedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// States: "state_dkg_commits_sending_await_confirmations"
|
||||
|
@ -15,7 +15,7 @@ type DKGProposalPubKeyConfirmationRequest struct {
|
|||
type DKGProposalCommitConfirmationRequest struct {
|
||||
ParticipantId int
|
||||
Commit []byte
|
||||
CreatedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// States: "state_dkg_deals_await_confirmations"
|
||||
|
@ -23,7 +23,7 @@ type DKGProposalCommitConfirmationRequest struct {
|
|||
type DKGProposalDealConfirmationRequest struct {
|
||||
ParticipantId int
|
||||
Deal []byte
|
||||
CreatedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// States: "state_dkg_responses_await_confirmations"
|
||||
|
@ -31,19 +31,30 @@ type DKGProposalDealConfirmationRequest struct {
|
|||
type DKGProposalResponseConfirmationRequest struct {
|
||||
ParticipantId int
|
||||
Response []byte
|
||||
CreatedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// States: "state_dkg_master_key_await_confirmations"
|
||||
// Events: "event_dkg_master_key_confirm_received"
|
||||
type DKGProposalMasterKeyConfirmationRequest struct {
|
||||
ParticipantId int
|
||||
MasterKey []byte
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
// States: "state_dkg_pub_keys_await_confirmations"
|
||||
// "state_dkg_commits_sending_await_confirmations"
|
||||
// "state_dkg_deals_await_confirmations"
|
||||
// "state_dkg_responses_await_confirmations"
|
||||
// "state_dkg_master_key_await_confirmations"
|
||||
//
|
||||
// Events: "event_dkg_pub_key_confirm_canceled_by_error",
|
||||
// "event_dkg_commit_confirm_canceled_by_error"
|
||||
// "event_dkg_deal_confirm_canceled_by_error"
|
||||
// "event_dkg_response_confirm_canceled_by_error"
|
||||
// "event_dkg_master_key_confirm_canceled_by_error"
|
||||
type DKGProposalConfirmationErrorRequest struct {
|
||||
ParticipantId int
|
||||
CreatedAt *time.Time
|
||||
Error error
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ func (r *DKGProposalPubKeyConfirmationRequest) Validate() error {
|
|||
return errors.New("{PubKey} cannot zero length")
|
||||
}
|
||||
|
||||
if r.CreatedAt == nil {
|
||||
return errors.New("{CreatedAt} cannot be a nil")
|
||||
if r.CreatedAt.IsZero() {
|
||||
return errors.New("{CreatedAt} is not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -27,8 +27,8 @@ func (r *DKGProposalCommitConfirmationRequest) Validate() error {
|
|||
return errors.New("{Commit} cannot zero length")
|
||||
}
|
||||
|
||||
if r.CreatedAt == nil {
|
||||
return errors.New("{CreatedAt} cannot be a nil")
|
||||
if r.CreatedAt.IsZero() {
|
||||
return errors.New("{CreatedAt} is not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -43,8 +43,8 @@ func (r *DKGProposalDealConfirmationRequest) Validate() error {
|
|||
return errors.New("{Deal} cannot zero length")
|
||||
}
|
||||
|
||||
if r.CreatedAt == nil {
|
||||
return errors.New("{CreatedAt} cannot be a nil")
|
||||
if r.CreatedAt.IsZero() {
|
||||
return errors.New("{CreatedAt} is not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -59,8 +59,24 @@ func (r *DKGProposalResponseConfirmationRequest) Validate() error {
|
|||
return errors.New("{Response} cannot zero length")
|
||||
}
|
||||
|
||||
if r.CreatedAt == nil {
|
||||
return errors.New("{CreatedAt} cannot be a nil")
|
||||
if r.CreatedAt.IsZero() {
|
||||
return errors.New("{CreatedAt} is not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *DKGProposalMasterKeyConfirmationRequest) Validate() error {
|
||||
if r.ParticipantId < 0 {
|
||||
return errors.New("{ParticipantId} cannot be a negative number")
|
||||
}
|
||||
|
||||
if len(r.MasterKey) == 0 {
|
||||
return errors.New("{MasterKey} cannot zero length")
|
||||
}
|
||||
|
||||
if r.CreatedAt.IsZero() {
|
||||
return errors.New("{CreatedAt} is not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -71,8 +87,12 @@ func (r *DKGProposalConfirmationErrorRequest) Validate() error {
|
|||
return errors.New("{ParticipantId} cannot be a negative number")
|
||||
}
|
||||
|
||||
if r.CreatedAt == nil {
|
||||
return errors.New("{CreatedAt} cannot be a nil")
|
||||
if r.Error == nil {
|
||||
return errors.New("{Error} cannot be a nil")
|
||||
}
|
||||
|
||||
if r.CreatedAt.IsZero() {
|
||||
return errors.New("{CreatedAt} is not set")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue