This commit is contained in:
x88 2020-08-19 17:26:10 +03:00
parent 9fbc54cf34
commit 0037421ff0
4 changed files with 69 additions and 99 deletions

View File

@ -8,7 +8,6 @@ import (
"github.com/depools/dc4bc/fsm/state_machines/internal" "github.com/depools/dc4bc/fsm/state_machines/internal"
"github.com/depools/dc4bc/fsm/types/requests" "github.com/depools/dc4bc/fsm/types/requests"
"reflect" "reflect"
"time"
) )
// Init // Init
@ -100,39 +99,31 @@ func (m *DKGProposalFSM) actionCommitConfirmationReceived(inEvent fsm.Event, arg
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *DKGProposalFSM) actionValidateDkgProposalAwaitCommits(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
var ( var (
isContainsError, isContainsExpired bool isContainsError bool
) )
m.payloadMu.Lock() m.payloadMu.Lock()
defer m.payloadMu.Unlock() defer m.payloadMu.Unlock()
tm := time.Now() if m.payload.DKGProposalPayload.IsExpired() {
outEvent = eventDKGCommitsConfirmationCancelByErrorInternal
return
}
unconfirmedParticipants := m.payload.DKGQuorumCount() unconfirmedParticipants := m.payload.DKGQuorumCount()
for _, participant := range m.payload.DKGProposalPayload.Quorum { for _, participant := range m.payload.DKGProposalPayload.Quorum {
if participant.Status == internal.CommitAwaitConfirmation {
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
isContainsExpired = true
}
} else {
if participant.Status == internal.CommitConfirmationError { if participant.Status == internal.CommitConfirmationError {
isContainsError = true isContainsError = true
} else if participant.Status == internal.CommitConfirmed { } else if participant.Status == internal.CommitConfirmed {
unconfirmedParticipants-- unconfirmedParticipants--
} }
} }
}
if isContainsError { if isContainsError {
outEvent = eventDKGCommitsConfirmationCancelByTimeoutInternal outEvent = eventDKGCommitsConfirmationCancelByTimeoutInternal
return return
} }
if isContainsExpired {
outEvent = eventDKGCommitsConfirmationCancelByErrorInternal
return
}
// The are no declined and timed out participants, check for all confirmations // The are no declined and timed out participants, check for all confirmations
if unconfirmedParticipants > 0 { if unconfirmedParticipants > 0 {
return return
@ -194,39 +185,31 @@ func (m *DKGProposalFSM) actionDealConfirmationReceived(inEvent fsm.Event, args
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *DKGProposalFSM) actionValidateDkgProposalAwaitDeals(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
var ( var (
isContainsError, isContainsExpired bool isContainsError bool
) )
m.payloadMu.Lock() m.payloadMu.Lock()
defer m.payloadMu.Unlock() defer m.payloadMu.Unlock()
tm := time.Now() if m.payload.DKGProposalPayload.IsExpired() {
outEvent = eventDKGDealsConfirmationCancelByTimeoutInternal
return
}
unconfirmedParticipants := m.payload.DKGQuorumCount() unconfirmedParticipants := m.payload.DKGQuorumCount()
for _, participant := range m.payload.DKGProposalPayload.Quorum { for _, participant := range m.payload.DKGProposalPayload.Quorum {
if participant.Status == internal.DealAwaitConfirmation {
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
isContainsExpired = true
}
} else {
if participant.Status == internal.DealConfirmationError { if participant.Status == internal.DealConfirmationError {
isContainsError = true isContainsError = true
} else if participant.Status == internal.DealConfirmed { } else if participant.Status == internal.DealConfirmed {
unconfirmedParticipants-- unconfirmedParticipants--
} }
} }
}
if isContainsError { if isContainsError {
outEvent = eventDKGDealsConfirmationCancelByErrorInternal outEvent = eventDKGDealsConfirmationCancelByErrorInternal
return return
} }
if isContainsExpired {
outEvent = eventDKGDealsConfirmationCancelByTimeoutInternal
return
}
// The are no declined and timed out participants, check for all confirmations // The are no declined and timed out participants, check for all confirmations
if unconfirmedParticipants > 0 { if unconfirmedParticipants > 0 {
return return
@ -288,39 +271,31 @@ func (m *DKGProposalFSM) actionResponseConfirmationReceived(inEvent fsm.Event, a
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *DKGProposalFSM) actionValidateDkgProposalAwaitResponses(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
var ( var (
isContainsError, isContainsExpired bool isContainsError bool
) )
m.payloadMu.Lock() m.payloadMu.Lock()
defer m.payloadMu.Unlock() defer m.payloadMu.Unlock()
tm := time.Now() if m.payload.DKGProposalPayload.IsExpired() {
outEvent = eventDKGResponseConfirmationCancelByTimeoutInternal
return
}
unconfirmedParticipants := m.payload.DKGQuorumCount() unconfirmedParticipants := m.payload.DKGQuorumCount()
for _, participant := range m.payload.DKGProposalPayload.Quorum { for _, participant := range m.payload.DKGProposalPayload.Quorum {
if participant.Status == internal.ResponseAwaitConfirmation {
if participant.UpdatedAt.Add(config.DkgConfirmationDeadline).Before(tm) {
isContainsExpired = true
}
} else {
if participant.Status == internal.ResponseConfirmationError { if participant.Status == internal.ResponseConfirmationError {
isContainsError = true isContainsError = true
} else if participant.Status == internal.ResponseConfirmed { } else if participant.Status == internal.ResponseConfirmed {
unconfirmedParticipants-- unconfirmedParticipants--
} }
} }
}
if isContainsError { if isContainsError {
outEvent = eventDKGResponseConfirmationCancelByErrorInternal outEvent = eventDKGResponseConfirmationCancelByErrorInternal
return return
} }
if isContainsExpired {
outEvent = eventDKGResponseConfirmationCancelByTimeoutInternal
return
}
// The are no declined and timed out participants, check for all confirmations // The are no declined and timed out participants, check for all confirmations
if unconfirmedParticipants > 0 { if unconfirmedParticipants > 0 {
return return
@ -382,23 +357,21 @@ func (m *DKGProposalFSM) actionMasterKeyConfirmationReceived(inEvent fsm.Event,
func (m *DKGProposalFSM) actionValidateDkgProposalAwaitMasterKey(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *DKGProposalFSM) actionValidateDkgProposalAwaitMasterKey(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
var ( var (
isContainsError, isContainsExpired bool isContainsError bool
masterKeys [][]byte masterKeys [][]byte
) )
m.payloadMu.Lock() m.payloadMu.Lock()
defer m.payloadMu.Unlock() defer m.payloadMu.Unlock()
tm := time.Now() if m.payload.DKGProposalPayload.IsExpired() {
outEvent = eventDKGMasterKeyConfirmationCancelByTimeoutInternal
return
}
unconfirmedParticipants := m.payload.DKGQuorumCount() unconfirmedParticipants := m.payload.DKGQuorumCount()
for _, participant := range m.payload.DKGProposalPayload.Quorum { 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 { if participant.Status == internal.MasterKeyConfirmationError {
isContainsError = true isContainsError = true
} else if participant.Status == internal.MasterKeyConfirmed { } else if participant.Status == internal.MasterKeyConfirmed {
@ -406,18 +379,12 @@ func (m *DKGProposalFSM) actionValidateDkgProposalAwaitMasterKey(inEvent fsm.Eve
unconfirmedParticipants-- unconfirmedParticipants--
} }
} }
}
if isContainsError { if isContainsError {
outEvent = eventDKGMasterKeyConfirmationCancelByErrorInternal outEvent = eventDKGMasterKeyConfirmationCancelByErrorInternal
return return
} }
if isContainsExpired {
outEvent = eventDKGMasterKeyConfirmationCancelByTimeoutInternal
return
}
// Temporary simplest match master keys // Temporary simplest match master keys
if len(masterKeys) > 1 { if len(masterKeys) > 1 {
for i, masterKey := range masterKeys { for i, masterKey := range masterKeys {

View File

@ -19,7 +19,7 @@ type DumpedMachineStatePayload struct {
SignatureProposalPayload *SignatureConfirmation SignatureProposalPayload *SignatureConfirmation
DKGProposalPayload *DKGConfirmation DKGProposalPayload *DKGConfirmation
SigningProposalPayload *SigningConfirmation SigningProposalPayload *SigningConfirmation
pubKeys map[string]ed25519.PublicKey PubKeys map[string]ed25519.PublicKey
} }
// Signature quorum // Signature quorum
@ -118,23 +118,23 @@ func (p *DumpedMachineStatePayload) SigningQuorumUpdate(id int, participant *Sig
return return
} }
func (p *DumpedMachineStatePayload) SetAddrHexPubKey(addr string, key ed25519.PublicKey) { func (p *DumpedMachineStatePayload) SetAddrHexPubKey(addr string, pubKey ed25519.PublicKey) {
if p.pubKeys == nil { if p.PubKeys == nil {
p.pubKeys = make(map[string]ed25519.PublicKey) p.PubKeys = make(map[string]ed25519.PublicKey)
} }
hexKey := hex.EncodeToString([]byte(addr)) hexAddr := hex.EncodeToString([]byte(addr))
p.pubKeys[hexKey] = key p.PubKeys[hexAddr] = pubKey
return return
} }
func (p *DumpedMachineStatePayload) GetPubKeyByAddr(addr string) (ed25519.PublicKey, error) { func (p *DumpedMachineStatePayload) GetPubKeyByAddr(addr string) (ed25519.PublicKey, error) {
if p.pubKeys == nil { if p.PubKeys == nil {
return nil, errors.New("{pubKeys} not initialized") return nil, errors.New("{PubKeys} not initialized")
} }
if addr == "" { if addr == "" {
return nil, errors.New("{addr} cannot be empty") return nil, errors.New("{addr} cannot be empty")
} }
pubKey, ok := p.pubKeys[addr] pubKey, ok := p.PubKeys[addr]
if !ok { if !ok {
return nil, errors.New("cannot find public key by {addr}") return nil, errors.New("cannot find public key by {addr}")
} }

View File

@ -46,6 +46,10 @@ type SignatureProposalParticipant struct {
UpdatedAt time.Time UpdatedAt time.Time
} }
func (c *SignatureConfirmation) IsExpired() bool {
return c.ExpiresAt.Before(c.UpdatedAt)
}
// Unique alias for map iteration - Public Key Fingerprint // Unique alias for map iteration - Public Key Fingerprint
// Excludes array merge and rotate operations // Excludes array merge and rotate operations
type SignatureProposalQuorum map[int]*SignatureProposalParticipant type SignatureProposalQuorum map[int]*SignatureProposalParticipant
@ -90,6 +94,10 @@ type DKGConfirmation struct {
ExpiresAt time.Time ExpiresAt time.Time
} }
func (c *DKGConfirmation) IsExpired() bool {
return c.ExpiresAt.Before(c.UpdatedAt)
}
type DKGProposalParticipantStatus uint8 type DKGProposalParticipantStatus uint8
func (s DKGParticipantStatus) String() string { func (s DKGParticipantStatus) String() string {
@ -135,6 +143,10 @@ type SigningConfirmation struct {
ExpiresAt time.Time ExpiresAt time.Time
} }
func (c *SigningConfirmation) IsExpired() bool {
return c.ExpiresAt.Before(c.UpdatedAt)
}
type SigningProposalQuorum map[int]*SigningProposalParticipant type SigningProposalQuorum map[int]*SigningProposalParticipant
type SigningParticipantStatus uint8 type SigningParticipantStatus uint8

View File

@ -3,8 +3,6 @@ package signature_proposal_fsm
import ( import (
"errors" "errors"
"fmt" "fmt"
"time"
"github.com/depools/dc4bc/fsm/config" "github.com/depools/dc4bc/fsm/config"
"github.com/depools/dc4bc/fsm/fsm" "github.com/depools/dc4bc/fsm/fsm"
"github.com/depools/dc4bc/fsm/state_machines/internal" "github.com/depools/dc4bc/fsm/state_machines/internal"
@ -131,39 +129,32 @@ func (m *SignatureProposalFSM) actionProposalResponseByParticipant(inEvent fsm.E
func (m *SignatureProposalFSM) actionValidateSignatureProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *SignatureProposalFSM) actionValidateSignatureProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
var ( var (
isContainsDeclined, isContainsExpired bool isContainsDeclined bool
) )
m.payloadMu.Lock() m.payloadMu.Lock()
defer m.payloadMu.Unlock() defer m.payloadMu.Unlock()
tm := time.Now() if m.payload.SignatureProposalPayload.IsExpired() {
outEvent = eventSetValidationCanceledByTimeout
return
}
unconfirmedParticipants := m.payload.SigQuorumCount() unconfirmedParticipants := m.payload.SigQuorumCount()
for _, participant := range m.payload.SignatureProposalPayload.Quorum { for _, participant := range m.payload.SignatureProposalPayload.Quorum {
if participant.Status == internal.SigConfirmationAwaitConfirmation {
if participant.UpdatedAt.Add(config.SignatureProposalConfirmationDeadline).Before(tm) {
isContainsExpired = true
}
} else {
if participant.Status == internal.SigConfirmationConfirmed { if participant.Status == internal.SigConfirmationConfirmed {
unconfirmedParticipants-- unconfirmedParticipants--
} else if participant.Status == internal.SigConfirmationDeclined { } else if participant.Status == internal.SigConfirmationDeclined {
isContainsDeclined = true isContainsDeclined = true
} }
} }
}
if isContainsDeclined { if isContainsDeclined {
outEvent = eventSetValidationCanceledByParticipant outEvent = eventSetValidationCanceledByParticipant
return return
} }
if isContainsExpired {
outEvent = eventSetValidationCanceledByTimeout
return
}
// The are no declined and timed out participants, check for all confirmations // The are no declined and timed out participants, check for all confirmations
if unconfirmedParticipants > 0 { if unconfirmedParticipants > 0 {
return return