feat: updated flow

This commit is contained in:
x88 2020-08-13 18:22:06 +03:00
parent 4ed9afc8dd
commit 33ecea0a9a
14 changed files with 185 additions and 353 deletions

View File

@ -41,7 +41,7 @@ func (e *Event) String() string {
return string(*e) return string(*e)
} }
func (e *Event) IsEmpty() bool { func (e Event) IsEmpty() bool {
return e.String() == "" return e.String() == ""
} }
@ -63,7 +63,7 @@ type FSM struct {
// May be mapping must require pair source + event? // May be mapping must require pair source + event?
transitions map[trKey]*trEvent transitions map[trKey]*trEvent
autoTransitions map[State]*trEvent autoTransitions map[trAutoKeyEvent]*trEvent
callbacks Callbacks callbacks Callbacks
@ -94,6 +94,11 @@ type trEvent struct {
runMode EventRunMode runMode EventRunMode
} }
type trAutoKeyEvent struct {
state State
runMode EventRunMode
}
type EventDesc struct { type EventDesc struct {
Name Event Name Event
@ -138,7 +143,7 @@ func MustNewFSM(machineName string, initialState State, events []EventDesc, call
currentState: initialState, currentState: initialState,
initialState: initialState, initialState: initialState,
transitions: make(map[trKey]*trEvent), transitions: make(map[trKey]*trEvent),
autoTransitions: make(map[State]*trEvent), autoTransitions: make(map[trAutoKeyEvent]*trEvent),
finStates: make(map[State]bool), finStates: make(map[State]bool),
callbacks: make(map[Event]Callback), callbacks: make(map[Event]Callback),
} }
@ -217,14 +222,15 @@ func MustNewFSM(machineName string, initialState State, events []EventDesc, call
panic("{AutoRunMode} not set for auto event") panic("{AutoRunMode} not set for auto event")
} }
if _, ok := f.autoTransitions[sourceState]; ok { trAutoKey := trAutoKeyEvent{sourceState, event.AutoRunMode}
if _, ok := f.autoTransitions[trAutoKey]; ok {
panic(fmt.Sprintf( panic(fmt.Sprintf(
"auto event \"%s\" already exists for state \"%s\"", "auto event \"%s\" already exists for state \"%s\"",
event.Name, event.Name,
sourceState, sourceState,
)) ))
} }
f.autoTransitions[sourceState] = trEvent f.autoTransitions[trAutoKey] = trEvent
} }
allSources[sourceState] = true allSources[sourceState] = true
@ -247,7 +253,7 @@ func MustNewFSM(machineName string, initialState State, events []EventDesc, call
} }
if _, ok := allEvents[event]; !ok { if _, ok := allEvents[event]; !ok {
panic("callback has empty event") panic(fmt.Sprintf("callback has unused event \"%s\"", event))
} }
f.callbacks[event] = callback f.callbacks[event] = callback
@ -273,7 +279,7 @@ func MustNewFSM(machineName string, initialState State, events []EventDesc, call
func (f *FSM) DoInternal(event Event, args ...interface{}) (resp *Response, err error) { func (f *FSM) DoInternal(event Event, args ...interface{}) (resp *Response, err error) {
trEvent, ok := f.transitions[trKey{f.currentState, event}] trEvent, ok := f.transitions[trKey{f.currentState, event}]
if !ok { if !ok {
return nil, errors.New(fmt.Sprintf("cannot execute event \"%s\" for state \"%s\"", event, f.currentState)) return nil, errors.New(fmt.Sprintf("cannot execute internal event \"%s\" for state \"%s\"", event, f.currentState))
} }
return f.do(trEvent, args...) return f.do(trEvent, args...)
@ -290,41 +296,55 @@ func (f *FSM) Do(event Event, args ...interface{}) (resp *Response, err error) {
return f.do(trEvent, args...) return f.do(trEvent, args...)
} }
// Check and execute auto event
func (f *FSM) processAutoEvent(mode EventRunMode, args ...interface{}) (exists bool, outEvent Event, response interface{}, err error) {
autoEvent, exists := f.autoTransitions[trAutoKeyEvent{f.State(), mode}]
if !exists {
return
}
if f.isCallbackExists(autoEvent.event) {
outEvent, response, err = f.execCallback(autoEvent.event, args...)
// Do not try change state on error
if err != nil {
return exists, "", response, err
}
}
if outEvent.IsEmpty() || autoEvent.event == outEvent {
err = f.SetState(autoEvent.event)
} else {
err = f.SetState(outEvent)
}
return
}
func (f *FSM) do(trEvent *trEvent, args ...interface{}) (resp *Response, err error) { func (f *FSM) do(trEvent *trEvent, args ...interface{}) (resp *Response, err error) {
var outEvent Event var outEvent Event
// f.eventMu.Lock() // f.eventMu.Lock()
// defer f.eventMu.Unlock() // defer f.eventMu.Unlock()
resp = &Response{}
// Process auto event // Process auto event
if autoEvent, ok := f.autoTransitions[f.State()]; ok { isAutoEventExecuted, outEvent, data, err := f.processAutoEvent(EventRunBefore, args...)
autoEventResp := &Response{
State: f.State(), if isAutoEventExecuted {
resp.State = f.State()
if data != nil {
resp.Data = data
} }
if autoEvent.runMode == EventRunBefore {
if callback, ok := f.callbacks[autoEvent.event]; ok { if err != nil {
outEvent, autoEventResp.Data, err = callback(autoEvent.event, args...) return resp, err
if err != nil {
return autoEventResp, err
}
}
if outEvent.IsEmpty() || autoEvent.event == outEvent {
err = f.SetState(autoEvent.event)
} else {
err = f.SetState(outEvent)
}
if err != nil {
return autoEventResp, err
}
} }
outEvent = ""
} }
resp = &Response{ if f.isCallbackExists(trEvent.event) {
State: f.State(), outEvent, resp.Data, err = f.execCallback(trEvent.event, args...)
}
if callback, ok := f.callbacks[trEvent.event]; ok {
outEvent, resp.Data, err = callback(trEvent.event, args...)
// Do not try change state on error // Do not try change state on error
if err != nil { if err != nil {
return resp, err return resp, err
@ -334,36 +354,32 @@ func (f *FSM) do(trEvent *trEvent, args ...interface{}) (resp *Response, err err
// Set state when callback executed // Set state when callback executed
if outEvent.IsEmpty() || trEvent.event == outEvent { if outEvent.IsEmpty() || trEvent.event == outEvent {
err = f.SetState(trEvent.event) err = f.SetState(trEvent.event)
if err != nil {
return resp, err
}
} else { } else {
err = f.SetState(outEvent) err = f.SetState(outEvent)
} if err != nil {
return resp, err
// Process auto event
if autoEvent, ok := f.autoTransitions[f.State()]; ok {
autoEventResp := &Response{
State: f.State(),
} }
if autoEvent.runMode == EventRunAfter {
if callback, ok := f.callbacks[autoEvent.event]; ok {
outEvent, autoEventResp.Data, err = callback(autoEvent.event, args...)
if err != nil {
return autoEventResp, err
}
}
if outEvent.IsEmpty() || autoEvent.event == outEvent {
err = f.SetState(autoEvent.event)
} else {
err = f.SetState(outEvent)
}
if err != nil {
return autoEventResp, err
}
}
outEvent = ""
} }
resp.State = f.State() resp.State = f.State()
// Process auto event
isAutoEventExecuted, outEvent, data, err = f.processAutoEvent(EventRunAfter, args...)
if isAutoEventExecuted {
resp.State = f.State()
if data != nil {
resp.Data = data
}
if err != nil {
return resp, err
}
}
return return
} }
@ -382,7 +398,7 @@ func (f *FSM) SetState(event Event) error {
trEvent, ok := f.transitions[trKey{f.currentState, event}] trEvent, ok := f.transitions[trKey{f.currentState, event}]
if !ok { if !ok {
return errors.New(fmt.Sprintf("cannot execute event \"%s\" for state \"%s\"", event, f.currentState)) return errors.New(fmt.Sprintf("cannot set state by event \"%s\" for state \"%s\"", event, f.currentState))
} }
f.currentState = trEvent.dstState f.currentState = trEvent.dstState
@ -457,6 +473,16 @@ func (f *FSM) StatesSourcesList() (states []State) {
return return
} }
func (f *FSM) isCallbackExists(event Event) bool {
_, exists := f.callbacks[event]
return exists
}
func (f *FSM) execCallback(event Event, args ...interface{}) (Event, interface{}, error) {
callback, _ := f.callbacks[event]
return callback(event, args...)
}
func (f *FSM) IsFinState(state State) bool { func (f *FSM) IsFinState(state State) bool {
_, exists := f.finStates[state] _, exists := f.finStates[state]
return exists return exists

View File

@ -160,17 +160,3 @@ func (p *FSMPool) MachineByState(state fsm.State) (MachineProvider, error) {
} }
return machine, nil return machine, nil
} }
/*func (p *FSMPool) Do(machine MachineProvider, event fsm.Event, args ...interface{}) (resp *fsm.Response, err error) {
panic("llslsl")
resp, err = machine.Do(event, args...)
if err != nil {
return resp, err
}
if machine.IsFinState(resp.State) {
log.Println("Final!!!!")
}
return
}
*/

View File

@ -11,94 +11,27 @@ import (
"time" "time"
) )
// Pub keys // Init
func (m *DKGProposalFSM) actionPubKeyConfirmationReceived(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *DKGProposalFSM) actionInitDKGProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
m.payloadMu.Lock() if m.payload.DKGProposalPayload != nil {
defer m.payloadMu.Unlock()
if len(args) != 1 {
err = errors.New("{arg0} required {DKGProposalPubKeyConfirmationRequest}")
return return
} }
request, ok := args[0].(requests.DKGProposalPubKeyConfirmationRequest) m.payload.DKGProposalPayload = &internal.DKGConfirmation{
Quorum: make(internal.DKGProposalQuorum),
if !ok {
err = errors.New("cannot cast {arg0} to type {DKGProposalPubKeyConfirmationRequest}")
return
} }
if err = request.Validate(); err != nil { for _, participant := range m.payload.SignatureProposalPayload.Quorum {
return m.payload.DKGProposalPayload.Quorum[participant.ParticipantId] = &internal.DKGProposalParticipant{
} Title: participant.Title,
Status: internal.CommitAwaitConfirmation,
if !m.payload.DKGQuorumExists(request.ParticipantId) { UpdatedAt: participant.UpdatedAt,
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.Status = internal.PubKeyConfirmed
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
return
}
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()
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
}
} else {
if participant.Status == internal.PubKeyConfirmationError {
isContainsError = true
} else if participant.Status == internal.PubKeyConfirmed {
unconfirmedParticipants--
}
} }
copy(m.payload.DKGProposalPayload.Quorum[participant.ParticipantId].PubKey, participant.DkgPubKey)
} }
if isContainsError { // Remove m.payload.SignatureProposalPayload?
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
for _, participant := range m.payload.DKGProposalPayload.Quorum {
participant.Status = internal.CommitAwaitConfirmation
}
return return
} }
@ -138,7 +71,7 @@ func (m *DKGProposalFSM) actionCommitConfirmationReceived(inEvent fsm.Event, arg
} }
copy(dkgProposalParticipant.Commit, request.Commit) copy(dkgProposalParticipant.Commit, request.Commit)
dkgProposalParticipant.UpdatedAt = &request.CreatedAt dkgProposalParticipant.UpdatedAt = request.CreatedAt
dkgProposalParticipant.Status = internal.CommitConfirmed dkgProposalParticipant.Status = internal.CommitConfirmed
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant) m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
@ -230,7 +163,7 @@ func (m *DKGProposalFSM) actionDealConfirmationReceived(inEvent fsm.Event, args
} }
copy(dkgProposalParticipant.Deal, request.Deal) copy(dkgProposalParticipant.Deal, request.Deal)
dkgProposalParticipant.UpdatedAt = &request.CreatedAt dkgProposalParticipant.UpdatedAt = request.CreatedAt
dkgProposalParticipant.Status = internal.DealConfirmed dkgProposalParticipant.Status = internal.DealConfirmed
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant) m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
@ -322,7 +255,7 @@ func (m *DKGProposalFSM) actionResponseConfirmationReceived(inEvent fsm.Event, a
} }
copy(dkgProposalParticipant.Response, request.Response) copy(dkgProposalParticipant.Response, request.Response)
dkgProposalParticipant.UpdatedAt = &request.CreatedAt dkgProposalParticipant.UpdatedAt = request.CreatedAt
dkgProposalParticipant.Status = internal.ResponseConfirmed dkgProposalParticipant.Status = internal.ResponseConfirmed
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant) m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
@ -414,7 +347,7 @@ func (m *DKGProposalFSM) actionMasterKeyConfirmationReceived(inEvent fsm.Event,
} }
copy(dkgProposalParticipant.MasterKey, request.MasterKey) copy(dkgProposalParticipant.MasterKey, request.MasterKey)
dkgProposalParticipant.UpdatedAt = &request.CreatedAt dkgProposalParticipant.UpdatedAt = request.CreatedAt
dkgProposalParticipant.Status = internal.MasterKeyConfirmed dkgProposalParticipant.Status = internal.MasterKeyConfirmed
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant) m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)
@ -525,21 +458,6 @@ func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...inte
// TODO: Move to methods // TODO: Move to methods
switch inEvent { switch inEvent {
case EventDKGPubKeyConfirmationError:
switch dkgProposalParticipant.Status {
case internal.PubKeyAwaitConfirmation:
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: case EventDKGCommitConfirmationError:
switch dkgProposalParticipant.Status { switch dkgProposalParticipant.Status {
case internal.CommitAwaitConfirmation: case internal.CommitAwaitConfirmation:
@ -609,7 +527,7 @@ func (m *DKGProposalFSM) actionConfirmationError(inEvent fsm.Event, args ...inte
} }
dkgProposalParticipant.Error = request.Error dkgProposalParticipant.Error = request.Error
dkgProposalParticipant.UpdatedAt = &request.CreatedAt dkgProposalParticipant.UpdatedAt = request.CreatedAt
m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant) m.payload.DKGQuorumUpdate(request.ParticipantId, dkgProposalParticipant)

View File

@ -9,14 +9,7 @@ import (
const ( const (
FsmName = "dkg_proposal_fsm" FsmName = "dkg_proposal_fsm"
StateDkgInitial = StateDkgPubKeysAwaitConfirmations StateDkgInitial = StateDkgCommitsAwaitConfirmations
StateDkgPubKeysAwaitConfirmations = fsm.State("state_dkg_pub_keys_await_confirmations")
// Canceled
StateDkgPubKeysAwaitCanceled = fsm.State("state_dkg_pub_keys_await_canceled")
StateDkgPubKeysAwaitCanceledByTimeout = fsm.State("state_dkg_pub_keys_await_canceled_by_timeout")
// Confirmed
// StateDkgPubKeysAwaitConfirmed = fsm.State("state_dkg_pub_keys_await_confirmed")
// Sending dkg commits // Sending dkg commits
StateDkgCommitsAwaitConfirmations = fsm.State("state_dkg_commits_await_confirmations") StateDkgCommitsAwaitConfirmations = fsm.State("state_dkg_commits_await_confirmations")
@ -24,7 +17,7 @@ const (
StateDkgCommitsAwaitCanceled = fsm.State("state_dkg_commits_await_canceled") StateDkgCommitsAwaitCanceled = fsm.State("state_dkg_commits_await_canceled")
StateDkgCommitsAwaitCanceledByTimeout = fsm.State("state_dkg_commits_await_canceled_by_timeout") StateDkgCommitsAwaitCanceledByTimeout = fsm.State("state_dkg_commits_await_canceled_by_timeout")
// Confirmed // Confirmed
StateDkgCommitsAwaitConfirmed = fsm.State("state_dkg_commits_await_confirmed") StateDkgCommitsCollected = fsm.State("state_dkg_commits_collected")
// Sending dkg deals // Sending dkg deals
StateDkgDealsAwaitConfirmations = fsm.State("state_dkg_deals_await_confirmations") StateDkgDealsAwaitConfirmations = fsm.State("state_dkg_deals_await_confirmations")
@ -32,31 +25,23 @@ const (
StateDkgDealsAwaitCanceled = fsm.State("state_dkg_deals_await_canceled") StateDkgDealsAwaitCanceled = fsm.State("state_dkg_deals_await_canceled")
StateDkgDealsAwaitCanceledByTimeout = fsm.State("state_dkg_deals_await_canceled_by_timeout") StateDkgDealsAwaitCanceledByTimeout = fsm.State("state_dkg_deals_await_canceled_by_timeout")
// Confirmed // Confirmed
//StateDkgDealsAwaitConfirmed = fsm.State("state_dkg_deals_await_confirmed") //StateDkgDealsCollected = fsm.State("state_dkg_deals_collected")
StateDkgResponsesAwaitConfirmations = fsm.State("state_dkg_responses_await_confirmations") StateDkgResponsesAwaitConfirmations = fsm.State("state_dkg_responses_await_confirmations")
// Canceled // Canceled
StateDkgResponsesAwaitCanceled = fsm.State("state_dkg_responses_await_canceled") StateDkgResponsesAwaitCanceled = fsm.State("state_dkg_responses_await_canceled")
StateDkgResponsesAwaitCanceledByTimeout = fsm.State("state_dkg_responses_sending_canceled_by_timeout") StateDkgResponsesAwaitCanceledByTimeout = fsm.State("state_dkg_responses_sending_canceled_by_timeout")
// Confirmed // Confirmed
StateDkgResponsesAwaitConfirmed = fsm.State("state_dkg_responses_await_confirmed") StateDkgResponsesCollected = fsm.State("state_dkg_responses_collected")
StateDkgMasterKeyAwaitConfirmations = fsm.State("state_dkg_master_key_await_confirmations") StateDkgMasterKeyAwaitConfirmations = fsm.State("state_dkg_master_key_await_confirmations")
StateDkgMasterKeyAwaitCanceled = fsm.State("state_dkg_master_key_await_canceled") StateDkgMasterKeyAwaitCanceled = fsm.State("state_dkg_master_key_await_canceled")
StateDkgMasterKeyAwaitCanceledByTimeout = fsm.State("state_dkg_master_key_await_canceled_by_timeout") StateDkgMasterKeyAwaitCanceledByTimeout = fsm.State("state_dkg_master_key_await_canceled_by_timeout")
StateDkgMasterKeyCollected = fsm.State("state_dkg_master_key_collected")
// Events // Events
eventAutoDKGInitialInternal = fsm.Event("event_dkg_init")
eventAutoDKGInitialInternal = fsm.Event("event_dkg_init_internal")
EventDKGPubKeyConfirmationReceived = fsm.Event("event_dkg_pub_key_confirm_received")
EventDKGPubKeyConfirmationError = fsm.Event("event_dkg_pub_key_confirm_canceled_by_error")
eventAutoDKGValidatePubKeysConfirmationInternal = fsm.Event("event_dkg_pub_keys_validate_internal")
eventDKGSetPubKeysConfirmationCanceledByTimeoutInternal = fsm.Event("event_dkg_pub_keys_confirm_canceled_by_timeout_internal")
eventDKGSetPubKeysConfirmationCanceledByErrorInternal = fsm.Event("event_dkg_pub_keys_confirm_canceled_by_error_internal")
eventDKGSetPubKeysConfirmedInternal = fsm.Event("event_dkg_pub_keys_confirmed_internal")
EventDKGCommitConfirmationReceived = fsm.Event("event_dkg_commit_confirm_received") EventDKGCommitConfirmationReceived = fsm.Event("event_dkg_commit_confirm_received")
EventDKGCommitConfirmationError = fsm.Event("event_dkg_commit_confirm_canceled_by_error") EventDKGCommitConfirmationError = fsm.Event("event_dkg_commit_confirm_canceled_by_error")
@ -109,18 +94,11 @@ func New() internal.DumpedMachineProvider {
// {Name: eventAutoDKGInitialInternal, SrcState: []fsm.State{StateDkgPubKeysAwaitConfirmations}, DstState: StateDkgPubKeysAwaitConfirmations, IsInternal: true, IsAuto: true, AutoRunMode: fsm.EventRunBefore}, // {Name: eventAutoDKGInitialInternal, SrcState: []fsm.State{StateDkgPubKeysAwaitConfirmations}, DstState: StateDkgPubKeysAwaitConfirmations, IsInternal: true, IsAuto: true, AutoRunMode: fsm.EventRunBefore},
// Pub keys sending // StateDkgCommitsCollected = fsm.State("state_dkg_commits_collected")
{Name: EventDKGPubKeyConfirmationReceived, SrcState: []fsm.State{StateDkgPubKeysAwaitConfirmations}, DstState: StateDkgPubKeysAwaitConfirmations},
// Canceled
{Name: EventDKGPubKeyConfirmationError, SrcState: []fsm.State{StateDkgPubKeysAwaitConfirmations}, DstState: StateDkgPubKeysAwaitCanceled},
{Name: eventAutoDKGValidatePubKeysConfirmationInternal, SrcState: []fsm.State{StateDkgPubKeysAwaitConfirmations}, DstState: StateDkgPubKeysAwaitConfirmations, IsInternal: true, IsAuto: true}, // {Name: eventAutoDKGInitInternal, SrcState: []fsm.State{StateDkgInitial}, DstState: StateDkgCommitsAwaitConfirmations, IsInternal: true, IsAuto: true, AutoRunMode: fsm.EventRunBefore},
{Name: eventDKGSetPubKeysConfirmationCanceledByTimeoutInternal, SrcState: []fsm.State{StateDkgPubKeysAwaitConfirmations}, DstState: StateDkgPubKeysAwaitCanceledByTimeout, IsInternal: true}, {Name: eventAutoDKGInitialInternal, SrcState: []fsm.State{StateDkgCommitsAwaitConfirmations}, DstState: StateDkgCommitsAwaitConfirmations, IsInternal: true, IsAuto: true, AutoRunMode: fsm.EventRunBefore},
// Confirmed
{Name: eventDKGSetPubKeysConfirmedInternal, SrcState: []fsm.State{StateDkgPubKeysAwaitConfirmations}, DstState: StateDkgCommitsAwaitConfirmations, IsInternal: true},
// Switch to commits required
// Commits // Commits
{Name: EventDKGCommitConfirmationReceived, SrcState: []fsm.State{StateDkgCommitsAwaitConfirmations}, DstState: StateDkgCommitsAwaitConfirmations}, {Name: EventDKGCommitConfirmationReceived, SrcState: []fsm.State{StateDkgCommitsAwaitConfirmations}, DstState: StateDkgCommitsAwaitConfirmations},
@ -166,10 +144,7 @@ func New() internal.DumpedMachineProvider {
// {Name: EventDKGMasterKeyRequiredInternal, SrcState: []fsm.State{StateDkgResponsesAwaitConfirmations}, DstState: fsm.StateGlobalDone, IsInternal: true}, // {Name: EventDKGMasterKeyRequiredInternal, SrcState: []fsm.State{StateDkgResponsesAwaitConfirmations}, DstState: fsm.StateGlobalDone, IsInternal: true},
}, },
fsm.Callbacks{ fsm.Callbacks{
eventAutoDKGInitialInternal: machine.actionInitDKGProposal,
EventDKGPubKeyConfirmationReceived: machine.actionPubKeyConfirmationReceived,
EventDKGPubKeyConfirmationError: machine.actionConfirmationError,
eventAutoDKGValidatePubKeysConfirmationInternal: machine.actionValidateDkgProposalPubKeys,
EventDKGCommitConfirmationReceived: machine.actionCommitConfirmationReceived, EventDKGCommitConfirmationReceived: machine.actionCommitConfirmationReceived,
EventDKGCommitConfirmationError: machine.actionConfirmationError, EventDKGCommitConfirmationError: machine.actionConfirmationError,

View File

@ -7,19 +7,20 @@ import (
type SignatureConfirmation struct { type SignatureConfirmation struct {
Quorum SignatureProposalQuorum Quorum SignatureProposalQuorum
CreatedAt *time.Time CreatedAt time.Time
ExpiresAt *time.Time ExpiresAt time.Time
} }
type SignatureProposalParticipant struct { type SignatureProposalParticipant struct {
// Public title for address, such as name, nickname, organization // Public title for address, such as name, nickname, organization
ParticipantId int ParticipantId int
Title string Title string
PublicKey *rsa.PublicKey PubKey *rsa.PublicKey
// For validation user confirmation: sign(InvitationSecret, PublicKey) => user DkgPubKey []byte
// For validation user confirmation: sign(InvitationSecret, PubKey) => user
InvitationSecret string InvitationSecret string
Status ParticipantStatus Status ParticipantStatus
UpdatedAt *time.Time UpdatedAt time.Time
} }
// Unique alias for map iteration - Public Key Fingerprint // Unique alias for map iteration - Public Key Fingerprint
@ -33,9 +34,6 @@ const (
SignatureConfirmationConfirmed SignatureConfirmationConfirmed
SignatureConfirmationDeclined SignatureConfirmationDeclined
SignatureConfirmationError SignatureConfirmationError
PubKeyAwaitConfirmation
PubKeyConfirmed
PubKeyConfirmationError
CommitAwaitConfirmation CommitAwaitConfirmation
CommitConfirmed CommitConfirmed
CommitConfirmationError CommitConfirmationError
@ -59,7 +57,7 @@ type DKGProposalParticipant struct {
MasterKey []byte MasterKey []byte
Status ParticipantStatus Status ParticipantStatus
Error error Error error
UpdatedAt *time.Time UpdatedAt time.Time
} }
type DKGProposalQuorum map[int]*DKGProposalParticipant type DKGProposalQuorum map[int]*DKGProposalParticipant
@ -83,12 +81,6 @@ func (s ParticipantStatus) String() string {
str = "SignatureConfirmationDeclined" str = "SignatureConfirmationDeclined"
case SignatureConfirmationError: case SignatureConfirmationError:
str = "SignatureConfirmationError" str = "SignatureConfirmationError"
case PubKeyAwaitConfirmation:
str = "PubKeyAwaitConfirmation"
case PubKeyConfirmed:
str = "PubKeyConfirmed"
case PubKeyConfirmationError:
str = "PubKeyConfirmationError"
case CommitAwaitConfirmation: case CommitAwaitConfirmation:
str = "CommitAwaitConfirmation" str = "CommitAwaitConfirmation"
case CommitConfirmed: case CommitConfirmed:

View File

@ -17,14 +17,11 @@ import (
"time" "time"
) )
const (
testTransactionId = "d8a928b2043db77e340b523547bf16cb4aa483f0645fe0a290ed1f20aab76257"
)
type testExternalParticipants struct { type testExternalParticipants struct {
Title string Title string
PrivKey *rsa.PrivateKey PrivKey *rsa.PrivateKey
PubKey *rsa.PublicKey PubKey *rsa.PublicKey
DkgPubKey []byte
} }
var ( var (
@ -34,7 +31,7 @@ var (
testParticipantsListRequest = requests.SignatureProposalParticipantsListRequest{ testParticipantsListRequest = requests.SignatureProposalParticipantsListRequest{
Participants: []*requests.SignatureProposalParticipantsEntry{}, Participants: []*requests.SignatureProposalParticipantsEntry{},
CreatedAt: &tm, CreatedAt: tm,
} }
testFSMDump []byte testFSMDump []byte
@ -59,10 +56,15 @@ func init() {
fingerprint := base64.StdEncoding.EncodeToString(hash[:]) fingerprint := base64.StdEncoding.EncodeToString(hash[:])
pubKeyMock := make([]byte, 128)
rand.Read(pubKeyMock)
participant := &testExternalParticipants{ participant := &testExternalParticipants{
Title: fmt.Sprintf("User %d", i), Title: fmt.Sprintf("User %d", i),
PrivKey: key, PrivKey: key,
PubKey: &key.PublicKey, PubKey: &key.PublicKey,
DkgPubKey: pubKeyMock,
} }
testParticipants[fingerprint] = participant testParticipants[fingerprint] = participant
} }
@ -72,8 +74,9 @@ func init() {
for _, participant := range testParticipants { for _, participant := range testParticipants {
participantsForRequest = append(participantsForRequest, &requests.SignatureProposalParticipantsEntry{ participantsForRequest = append(participantsForRequest, &requests.SignatureProposalParticipantsEntry{
Title: participant.Title, Title: participant.Title,
PubKey: x509.MarshalPKCS1PublicKey(participant.PubKey), PubKey: x509.MarshalPKCS1PublicKey(participant.PubKey),
DkgPubKey: participant.DkgPubKey,
}) })
} }
testParticipantsListRequest.Participants = participantsForRequest testParticipantsListRequest.Participants = participantsForRequest
@ -197,7 +200,7 @@ func Test_SignatureProposal_Positive(t *testing.T) {
participantsMap[participant.ParticipantId] = participant participantsMap[participant.ParticipantId] = participant
} }
tm = tm.Add(10 * time.Hour) tm = tm.Add(1 * time.Hour)
participantsCount := len(participantsMap) participantsCount := len(participantsMap)
@ -222,10 +225,10 @@ func Test_SignatureProposal_Positive(t *testing.T) {
t.Fatalf("cannot encrypt {DecryptedInvitation} with private key") t.Fatalf("cannot encrypt {DecryptedInvitation} with private key")
} }
fsmResponse, dump, err = testFSMInstance.Do(spf.EventConfirmProposal, requests.SignatureProposalParticipantRequest{ fsmResponse, dump, err = testFSMInstance.Do(spf.EventConfirmSignatureProposal, requests.SignatureProposalParticipantRequest{
PubKeyFingerprint: participant.PubKeyFingerprint, PubKeyFingerprint: participant.PubKeyFingerprint,
DecryptedInvitation: string(encrypted), DecryptedInvitation: string(encrypted),
CreatedAt: &tm, CreatedAt: tm,
}) })
compareErrNil(t, err) compareErrNil(t, err)
@ -237,45 +240,11 @@ func Test_SignatureProposal_Positive(t *testing.T) {
if participantCounter > 0 { if participantCounter > 0 {
compareState(t, spf.StateAwaitParticipantsConfirmations, fsmResponse.State) compareState(t, spf.StateAwaitParticipantsConfirmations, fsmResponse.State)
} else { } else {
compareState(t, dpf.StateDkgInitial, fsmResponse.State) compareState(t, spf.StateSignatureProposalCollected, fsmResponse.State)
} }
} }
// PubKeys
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")
}
pubKeyMock := make([]byte, 128)
_, err := rand.Read(pubKeyMock)
if err != nil {
compareErrNil(t, err)
}
fsmResponse, dump, err = testFSMInstance.Do(dpf.EventDKGPubKeyConfirmationReceived, requests.DKGProposalPubKeyConfirmationRequest{
ParticipantId: participant.ParticipantId,
PubKey: pubKeyMock,
CreatedAt: tm,
})
compareErrNil(t, err)
compareDumpNotZero(t, dump)
compareFSMResponseNotNil(t, fsmResponse)
}
compareState(t, dpf.StateDkgCommitsAwaitConfirmations, fsmResponse.State) compareState(t, dpf.StateDkgCommitsAwaitConfirmations, fsmResponse.State)
// Commits // Commits

View File

@ -14,7 +14,7 @@ import (
// init -> awaitingConfirmations // init -> awaitingConfirmations
// args: payload, signing id, participants list // args: payload, signing id, participants list
func (m *SignatureProposalFSM) actionInitProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *SignatureProposalFSM) actionInitSignatureProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
m.payloadMu.Lock() m.payloadMu.Lock()
defer m.payloadMu.Unlock() defer m.payloadMu.Unlock()
@ -54,7 +54,8 @@ func (m *SignatureProposalFSM) actionInitProposal(inEvent fsm.Event, args ...int
m.payload.SignatureProposalPayload.Quorum[participantId] = &internal.SignatureProposalParticipant{ m.payload.SignatureProposalPayload.Quorum[participantId] = &internal.SignatureProposalParticipant{
ParticipantId: index, ParticipantId: index,
Title: participant.Title, Title: participant.Title,
PublicKey: parsedPubKey, PubKey: parsedPubKey,
DkgPubKey: participant.DkgPubKey,
InvitationSecret: secret, InvitationSecret: secret,
Status: internal.SignatureConfirmationAwaitConfirmation, Status: internal.SignatureConfirmationAwaitConfirmation,
UpdatedAt: request.CreatedAt, UpdatedAt: request.CreatedAt,
@ -72,7 +73,7 @@ func (m *SignatureProposalFSM) actionInitProposal(inEvent fsm.Event, args ...int
responseData := make(responses.SignatureProposalParticipantInvitationsResponse, 0) responseData := make(responses.SignatureProposalParticipantInvitationsResponse, 0)
for pubKeyFingerprint, proposal := range m.payload.SignatureProposalPayload.Quorum { for pubKeyFingerprint, proposal := range m.payload.SignatureProposalPayload.Quorum {
encryptedInvitationSecret, err := encryptWithPubKey(proposal.PublicKey, proposal.InvitationSecret) encryptedInvitationSecret, err := encryptWithPubKey(proposal.PubKey, proposal.InvitationSecret)
if err != nil { if err != nil {
return inEvent, nil, errors.New("cannot encryptWithPubKey") return inEvent, nil, errors.New("cannot encryptWithPubKey")
} }
@ -122,7 +123,7 @@ func (m *SignatureProposalFSM) actionProposalResponseByParticipant(inEvent fsm.E
return return
} }
if signatureProposalParticipant.UpdatedAt.Add(config.SignatureProposalConfirmationDeadline).Before(*request.CreatedAt) { if signatureProposalParticipant.UpdatedAt.Add(config.SignatureProposalConfirmationDeadline).Before(request.CreatedAt) {
outEvent = eventSetValidationCanceledByTimeout outEvent = eventSetValidationCanceledByTimeout
return return
} }
@ -133,7 +134,7 @@ func (m *SignatureProposalFSM) actionProposalResponseByParticipant(inEvent fsm.E
} }
switch inEvent { switch inEvent {
case EventConfirmProposal: case EventConfirmSignatureProposal:
signatureProposalParticipant.Status = internal.SignatureConfirmationConfirmed signatureProposalParticipant.Status = internal.SignatureConfirmationConfirmed
case EventDeclineProposal: case EventDeclineProposal:
signatureProposalParticipant.Status = internal.SignatureConfirmationDeclined signatureProposalParticipant.Status = internal.SignatureConfirmationDeclined
@ -189,37 +190,24 @@ func (m *SignatureProposalFSM) actionValidateSignatureProposal(inEvent fsm.Event
return return
} }
outEvent = eventSetProposalValidatedInternal err = m.SetState(eventSetProposalValidatedInternal)
if err != nil {
m.actionSetValidatedSignatureProposal(outEvent)
return
}
func (m *SignatureProposalFSM) actionSetValidatedSignatureProposal(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
// m.payloadMu.Lock()
// defer m.payloadMu.Unlock()
// TODO: Run once after validation
if m.payload.DKGProposalPayload != nil {
return return
} }
m.payload.DKGProposalPayload = &internal.DKGConfirmation{ responseData := make(responses.SignatureProposalParticipantStatusResponse, 0)
Quorum: make(internal.DKGProposalQuorum),
}
for _, participant := range m.payload.SignatureProposalPayload.Quorum { for _, participant := range m.payload.SignatureProposalPayload.Quorum {
m.payload.DKGProposalPayload.Quorum[participant.ParticipantId] = &internal.DKGProposalParticipant{ responseEntry := &responses.SignatureProposalParticipantStatusEntry{
Title: participant.Title, ParticipantId: participant.ParticipantId,
Status: internal.PubKeyAwaitConfirmation, Title: participant.Title,
UpdatedAt: participant.UpdatedAt, DkgPubKey: participant.DkgPubKey,
Status: uint8(participant.Status),
} }
responseData = append(responseData, responseEntry)
} }
// Remove m.payload.SignatureProposalPayload? return eventDoneInternal, responseData, nil
return
} }
func (m *SignatureProposalFSM) actionSignatureProposalCanceledByTimeout(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) { func (m *SignatureProposalFSM) actionSignatureProposalCanceledByTimeout(inEvent fsm.Event, args ...interface{}) (outEvent fsm.Event, response interface{}, err error) {
@ -228,12 +216,11 @@ func (m *SignatureProposalFSM) actionSignatureProposalCanceledByTimeout(inEvent
responseData := make(responses.SignatureProposalParticipantStatusResponse, 0) responseData := make(responses.SignatureProposalParticipantStatusResponse, 0)
for pubKeyFingerprint, participant := range m.payload.SignatureProposalPayload.Quorum { for _, participant := range m.payload.SignatureProposalPayload.Quorum {
responseEntry := &responses.SignatureProposalParticipantStatusEntry{ responseEntry := &responses.SignatureProposalParticipantStatusEntry{
ParticipantId: participant.ParticipantId, ParticipantId: participant.ParticipantId,
Title: participant.Title, Title: participant.Title,
PubKeyFingerprint: pubKeyFingerprint, Status: uint8(participant.Status),
Status: uint8(participant.Status),
} }
responseData = append(responseData, responseEntry) responseData = append(responseData, responseEntry)
} }

View File

@ -2,7 +2,7 @@ package signature_proposal_fsm
import ( import (
"github.com/depools/dc4bc/fsm/fsm" "github.com/depools/dc4bc/fsm/fsm"
"github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm" dpf "github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm"
"github.com/depools/dc4bc/fsm/state_machines/internal" "github.com/depools/dc4bc/fsm/state_machines/internal"
"sync" "sync"
) )
@ -21,14 +21,18 @@ const (
// Out state // Out state
EventInitProposal = fsm.Event("event_sig_proposal_init") EventInitProposal = fsm.Event("event_sig_proposal_init")
EventConfirmProposal = fsm.Event("event_sig_proposal_confirm_by_participant") EventConfirmSignatureProposal = fsm.Event("event_sig_proposal_confirm_by_participant")
EventDeclineProposal = fsm.Event("event_sig_proposal_decline_by_participant") EventDeclineProposal = fsm.Event("event_sig_proposal_decline_by_participant")
eventAutoValidateProposalInternal = fsm.Event("event_sig_proposal_validate") eventAutoValidateProposalInternal = fsm.Event("event_sig_proposal_validate")
eventSetProposalValidatedInternal = fsm.Event("event_sig_proposal_set_validated") eventSetProposalValidatedInternal = fsm.Event("event_sig_proposal_set_validated")
eventDoneInternal = fsm.Event("event_sig_proposal_done")
eventSetValidationCanceledByTimeout = fsm.Event("event_sig_proposal_canceled_timeout") eventSetValidationCanceledByTimeout = fsm.Event("event_sig_proposal_canceled_timeout")
eventSetValidationCanceledByParticipant = fsm.Event("event_sig_proposal_declined_timeout") eventSetValidationCanceledByParticipant = fsm.Event("event_sig_proposal_declined_timeout")
StateSignatureProposalCollected = fsm.State("state_sig_proposal_collected")
// Switch to next fsm // Switch to next fsm
) )
@ -52,7 +56,7 @@ func New() internal.DumpedMachineProvider {
{Name: EventInitProposal, SrcState: []fsm.State{StateParticipantsConfirmationsInit}, DstState: StateAwaitParticipantsConfirmations}, {Name: EventInitProposal, SrcState: []fsm.State{StateParticipantsConfirmationsInit}, DstState: StateAwaitParticipantsConfirmations},
// Validate by participants // Validate by participants
{Name: EventConfirmProposal, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: StateAwaitParticipantsConfirmations}, {Name: EventConfirmSignatureProposal, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: StateAwaitParticipantsConfirmations},
// Is decline event should auto change state to default, or it process will initiated by client (external emit)? // Is decline event should auto change state to default, or it process will initiated by client (external emit)?
// Now set for external emitting. // Now set for external emitting.
{Name: EventDeclineProposal, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: StateAwaitParticipantsConfirmations}, {Name: EventDeclineProposal, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: StateAwaitParticipantsConfirmations},
@ -62,17 +66,19 @@ func New() internal.DumpedMachineProvider {
// eventProposalValidate internal or from client? // eventProposalValidate internal or from client?
// yay // yay
{Name: eventSetProposalValidatedInternal, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: StateSignatureProposalCollected, IsInternal: true},
// Exit point // Exit point
{Name: eventSetProposalValidatedInternal, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: dkg_proposal_fsm.StateDkgPubKeysAwaitConfirmations, IsInternal: true}, {Name: eventDoneInternal, SrcState: []fsm.State{StateSignatureProposalCollected}, DstState: dpf.StateDkgInitial, IsInternal: true},
// nan // nan
{Name: eventSetValidationCanceledByTimeout, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: StateValidationCanceledByTimeout, IsInternal: true}, {Name: eventSetValidationCanceledByTimeout, SrcState: []fsm.State{StateAwaitParticipantsConfirmations}, DstState: StateValidationCanceledByTimeout, IsInternal: true},
}, },
fsm.Callbacks{ fsm.Callbacks{
EventInitProposal: machine.actionInitProposal, EventInitProposal: machine.actionInitSignatureProposal,
EventConfirmProposal: machine.actionProposalResponseByParticipant, EventConfirmSignatureProposal: machine.actionProposalResponseByParticipant,
EventDeclineProposal: machine.actionProposalResponseByParticipant, EventDeclineProposal: machine.actionProposalResponseByParticipant,
eventAutoValidateProposalInternal: machine.actionValidateSignatureProposal, eventAutoValidateProposalInternal: machine.actionValidateSignatureProposal,
eventSetProposalValidatedInternal: machine.actionSetValidatedSignatureProposal,
}, },
) )
return machine return machine

View File

@ -2,14 +2,6 @@ package requests
import "time" import "time"
// States: "state_dkg_pub_keys_await_confirmations"
// Events: "event_dkg_pub_key_confirm_received"
type DKGProposalPubKeyConfirmationRequest struct {
ParticipantId int
PubKey []byte
CreatedAt time.Time
}
// States: "state_dkg_commits_sending_await_confirmations" // States: "state_dkg_commits_sending_await_confirmations"
// Events: "event_dkg_commit_confirm_received" // Events: "event_dkg_commit_confirm_received"
type DKGProposalCommitConfirmationRequest struct { type DKGProposalCommitConfirmationRequest struct {

View File

@ -2,22 +2,6 @@ package requests
import "errors" import "errors"
func (r *DKGProposalPubKeyConfirmationRequest) Validate() error {
if r.ParticipantId < 0 {
return errors.New("{ParticipantId} cannot be a negative number")
}
if len(r.PubKey) == 0 {
return errors.New("{PubKey} cannot zero length")
}
if r.CreatedAt.IsZero() {
return errors.New("{CreatedAt} is not set")
}
return nil
}
func (r *DKGProposalCommitConfirmationRequest) Validate() error { func (r *DKGProposalCommitConfirmationRequest) Validate() error {
if r.ParticipantId < 0 { if r.ParticipantId < 0 {
return errors.New("{ParticipantId} cannot be a negative number") return errors.New("{ParticipantId} cannot be a negative number")

View File

@ -8,13 +8,14 @@ import "time"
// Events: "event_sig_proposal_init" // Events: "event_sig_proposal_init"
type SignatureProposalParticipantsListRequest struct { type SignatureProposalParticipantsListRequest struct {
Participants []*SignatureProposalParticipantsEntry Participants []*SignatureProposalParticipantsEntry
CreatedAt *time.Time CreatedAt time.Time
} }
type SignatureProposalParticipantsEntry struct { type SignatureProposalParticipantsEntry struct {
// Public title for address, such as name, nickname, organization // Public title for address, such as name, nickname, organization
Title string Title string
PubKey []byte PubKey []byte
DkgPubKey []byte
} }
// States: "__idle" // States: "__idle"
@ -24,5 +25,5 @@ type SignatureProposalParticipantRequest struct {
// Key for link invitations to participants // Key for link invitations to participants
PubKeyFingerprint string PubKeyFingerprint string
DecryptedInvitation string DecryptedInvitation string
CreatedAt *time.Time CreatedAt time.Time
} }

View File

@ -23,9 +23,13 @@ func (r *SignatureProposalParticipantsListRequest) Validate() error {
if len(participant.PubKey) < 10 { if len(participant.PubKey) < 10 {
return errors.New("{PubKey} too short") return errors.New("{PubKey} too short")
} }
if len(participant.DkgPubKey) < 10 {
return errors.New("{DkgPubKey} too short")
}
} }
if r.CreatedAt == nil { if r.CreatedAt.IsZero() {
return errors.New("{CreatedAt} cannot be a nil") return errors.New("{CreatedAt} cannot be a nil")
} }
@ -41,7 +45,7 @@ func (r *SignatureProposalParticipantRequest) Validate() error {
return errors.New("{DecryptedInvitation} cannot zero length") return errors.New("{DecryptedInvitation} cannot zero length")
} }
if r.CreatedAt == nil { if r.CreatedAt.IsZero() {
return errors.New("{CreatedAt} cannot be a nil") return errors.New("{CreatedAt} cannot be a nil")
} }
return nil return nil

View File

@ -1,13 +1,5 @@
package responses package responses
type DKGProposalPubKeyParticipantResponse []*DKGProposalPubKeyParticipantEntry
type DKGProposalPubKeyParticipantEntry struct {
ParticipantId int
Title string
PubKey []byte
}
type DKGProposalCommitParticipantResponse []*DKGProposalCommitParticipantEntry type DKGProposalCommitParticipantResponse []*DKGProposalCommitParticipantEntry
type DKGProposalCommitParticipantEntry struct { type DKGProposalCommitParticipantEntry struct {

View File

@ -22,8 +22,8 @@ type SignatureProposalParticipantInvitationEntry struct {
type SignatureProposalParticipantStatusResponse []*SignatureProposalParticipantStatusEntry type SignatureProposalParticipantStatusResponse []*SignatureProposalParticipantStatusEntry
type SignatureProposalParticipantStatusEntry struct { type SignatureProposalParticipantStatusEntry struct {
ParticipantId int ParticipantId int
Title string Title string
PubKeyFingerprint string DkgPubKey []byte
Status uint8 Status uint8
} }