Merge branch 'master' into feat/client-http

# Conflicts:
#	fsm/cmd/test/test.go
#	fsm/fsm_pool/fsm_pool.go
#	fsm/state_machines/provider.go
#	fsm/state_machines/signature_proposal_fsm/actions.go
#	fsm/state_machines/signature_proposal_fsm/helpers.go
#	fsm/types/requests/signature_proposal.go
#	mocks/clientMocks/state_mock.go
#	mocks/storageMocks/storage_mock.go
This commit is contained in:
Andrej Zavgorodnij 2020-08-04 09:38:55 +03:00
commit 533dc9375c
11 changed files with 204 additions and 161 deletions

View File

@ -19,33 +19,45 @@ import (
// Temporary global finish state for deprecating operations // Temporary global finish state for deprecating operations
const ( const (
StateGlobalIdle = "__idle" StateGlobalIdle = State("__idle")
StateGlobalDone = "__done" StateGlobalDone = State("__done")
) )
// FSMResponse returns result for processing with clientMocks events type State string
type FSMResponse struct {
func (s *State) String() string {
return string(*s)
}
type Event string
func (e *Event) String() string {
return string(*e)
}
// Response returns result for processing with clientMocks events
type Response struct {
// Returns machine execution result state // Returns machine execution result state
State string State State
// Must be cast, according to mapper event_name->response_type // Must be cast, according to mapper event_name->response_type
Data interface{} Data interface{}
} }
type FSM struct { type FSM struct {
name string name string
initialState string initialState State
currentState string currentState State
// May be mapping must require pair source + event? // May be mapping must require pair source + event?
transitions map[trKey]*trEvent transitions map[trKey]*trEvent
callbacks Callbacks callbacks Callbacks
initialEvent string initialEvent Event
// Finish states, for switch machine or fin, // Finish states, for switch machine or fin,
// These states cannot be linked as SrcState in this machine // These states cannot be linked as SrcState in this machine
finStates map[string]bool finStates map[State]bool
// stateMu guards access to the currentState state. // stateMu guards access to the currentState state.
stateMu sync.RWMutex stateMu sync.RWMutex
@ -55,36 +67,36 @@ type FSM struct {
// Transition key source + dst // Transition key source + dst
type trKey struct { type trKey struct {
source string source State
event string event Event
} }
// Transition lightweight event description // Transition lightweight event description
type trEvent struct { type trEvent struct {
dstState string dstState State
isInternal bool isInternal bool
} }
type Event struct { type EventDesc struct {
Name string Name Event
SrcState []string SrcState []State
// Dst state changes after callback // Dst state changes after callback
DstState string DstState State
// Internal events, cannot be emitted from external call // Internal events, cannot be emitted from external call
IsInternal bool IsInternal bool
} }
type Callback func(event string, args ...interface{}) (interface{}, error) type Callback func(event Event, args ...interface{}) (interface{}, error)
type Callbacks map[string]Callback type Callbacks map[Event]Callback
// TODO: Exports // TODO: Exports
func MustNewFSM(machineName, initialState string, events []Event, callbacks map[string]Callback) *FSM { func MustNewFSM(machineName string, initialState State, events []EventDesc, callbacks Callbacks) *FSM {
machineName = strings.TrimSpace(machineName) machineName = strings.TrimSpace(machineName)
initialState = strings.TrimSpace(initialState) initialState = State(strings.TrimSpace(initialState.String()))
if machineName == "" { if machineName == "" {
panic("machine name cannot be empty") panic("machine name cannot be empty")
@ -104,20 +116,20 @@ func MustNewFSM(machineName, initialState string, events []Event, callbacks map[
currentState: initialState, currentState: initialState,
initialState: initialState, initialState: initialState,
transitions: make(map[trKey]*trEvent), transitions: make(map[trKey]*trEvent),
finStates: make(map[string]bool), finStates: make(map[State]bool),
callbacks: make(map[string]Callback), callbacks: make(map[Event]Callback),
} }
allEvents := make(map[string]bool) allEvents := make(map[Event]bool)
// Required for find finStates // Required for find finStates
allSources := make(map[string]bool) allSources := make(map[State]bool)
allStates := make(map[string]bool) allStates := make(map[State]bool)
// Validate events // Validate events
for _, event := range events { for _, event := range events {
event.Name = strings.TrimSpace(event.Name) event.Name = Event(strings.TrimSpace(event.Name.String()))
event.DstState = strings.TrimSpace(event.DstState) event.DstState = State(strings.TrimSpace(event.DstState.String()))
if event.Name == "" { if event.Name == "" {
panic("cannot init empty event") panic("cannot init empty event")
@ -137,7 +149,7 @@ func MustNewFSM(machineName, initialState string, events []Event, callbacks map[
trimmedSourcesCounter := 0 trimmedSourcesCounter := 0
for _, sourceState := range event.SrcState { for _, sourceState := range event.SrcState {
sourceState := strings.TrimSpace(sourceState) sourceState := State(strings.TrimSpace(sourceState.String()))
if sourceState == "" { if sourceState == "" {
continue continue
@ -209,7 +221,7 @@ func MustNewFSM(machineName, initialState string, events []Event, callbacks map[
return f return f
} }
func (f *FSM) Do(event string, args ...interface{}) (resp *FSMResponse, err error) { func (f *FSM) Do(event Event, args ...interface{}) (resp *Response, err error) {
f.eventMu.Lock() f.eventMu.Lock()
defer f.eventMu.Unlock() defer f.eventMu.Unlock()
@ -221,7 +233,7 @@ func (f *FSM) Do(event string, args ...interface{}) (resp *FSMResponse, err erro
return nil, errors.New("event is internal") return nil, errors.New("event is internal")
} }
resp = &FSMResponse{ resp = &Response{
State: f.State(), State: f.State(),
} }
@ -238,7 +250,7 @@ func (f *FSM) Do(event string, args ...interface{}) (resp *FSMResponse, err erro
} }
// State returns the currentState state of the FSM. // State returns the currentState state of the FSM.
func (f *FSM) State() string { func (f *FSM) State() State {
f.stateMu.RLock() f.stateMu.RLock()
defer f.stateMu.RUnlock() defer f.stateMu.RUnlock()
return f.currentState return f.currentState
@ -246,7 +258,7 @@ func (f *FSM) State() string {
// setState allows the user to move to the given state from currentState state. // setState allows the user to move to the given state from currentState state.
// The call does not trigger any callbacks, if defined. // The call does not trigger any callbacks, if defined.
func (f *FSM) setState(event string) error { func (f *FSM) setState(event Event) error {
f.stateMu.Lock() f.stateMu.Lock()
defer f.stateMu.Unlock() defer f.stateMu.Unlock()
@ -264,12 +276,12 @@ func (f *FSM) Name() string {
return f.name return f.name
} }
func (f *FSM) InitialState() string { func (f *FSM) InitialState() State {
return f.initialState return f.initialState
} }
// Check entry event for available emitting as global entry event // Check entry event for available emitting as global entry event
func (f *FSM) GlobalInitialEvent() (event string) { func (f *FSM) GlobalInitialEvent() (event Event) {
if initialEvent, exists := f.transitions[trKey{StateGlobalIdle, f.initialEvent}]; exists { if initialEvent, exists := f.transitions[trKey{StateGlobalIdle, f.initialEvent}]; exists {
if !initialEvent.isInternal { if !initialEvent.isInternal {
event = f.initialEvent event = f.initialEvent
@ -278,7 +290,7 @@ func (f *FSM) GlobalInitialEvent() (event string) {
return return
} }
func (f *FSM) EntryEvent() (event string) { func (f *FSM) EntryEvent() (event Event) {
if entryEvent, exists := f.transitions[trKey{f.initialState, f.initialEvent}]; exists { if entryEvent, exists := f.transitions[trKey{f.initialState, f.initialEvent}]; exists {
if !entryEvent.isInternal { if !entryEvent.isInternal {
event = f.initialEvent event = f.initialEvent
@ -287,8 +299,8 @@ func (f *FSM) EntryEvent() (event string) {
return return
} }
func (f *FSM) EventsList() (events []string) { func (f *FSM) EventsList() (events []Event) {
var eventsMap = map[string]bool{} var eventsMap = map[Event]bool{}
if len(f.transitions) > 0 { if len(f.transitions) > 0 {
for trKey, trEvent := range f.transitions { for trKey, trEvent := range f.transitions {
if !trEvent.isInternal { if !trEvent.isInternal {
@ -310,8 +322,8 @@ func (f *FSM) EventsList() (events []string) {
return return
} }
func (f *FSM) StatesSourcesList() (states []string) { func (f *FSM) StatesSourcesList() (states []State) {
var allStates = map[string]bool{} var allStates = map[State]bool{}
if len(f.transitions) > 0 { if len(f.transitions) > 0 {
for trKey, _ := range f.transitions { for trKey, _ := range f.transitions {
allStates[trKey.source] = true allStates[trKey.source] = true
@ -327,7 +339,7 @@ func (f *FSM) StatesSourcesList() (states []string) {
return return
} }
func (f *FSM) IsFinState(state string) bool { func (f *FSM) IsFinState(state State) bool {
_, exists := f.finStates[state] _, exists := f.finStates[state]
return exists return exists
} }

View File

@ -1,77 +1,66 @@
package fsm package fsm
type testMachineFSM struct {
*FSM
}
const ( const (
FSM1Name = "fsm1" FSM1Name = "fsm1"
// Init process from global idle state // Init process from global idle state
FSM1StateInit = StateGlobalIdle FSM1StateInit = StateGlobalIdle
// Set up data // Set up data
FSM1StateStage1 = "state_fsm1_stage1" FSM1StateStage1 = State("state_fsm1_stage1")
// Process data // Process data
FSM1StateStage2 = "state_fsm1_stage2" FSM1StateStage2 = State("state_fsm1_stage2")
// Cancelled with internal event // Cancelled with internal event
FSM1StateCanceledByInternal = "state_fsm1_canceled1" FSM1StateCanceledByInternal = State("state_fsm1_canceled")
// Cancelled with external event // Cancelled with external event
FSM1StateCanceled2 = "state_fsm1_canceled2" FSM1StateCanceled2 = State("state_fsm1_canceled2")
// Out endpoint to switch // Out endpoint to switch
FSM1StateOutToFSM2 = "state_fsm1_out_to_fsm2" FSM1StateOutToFSM2 = State("state_fsm1_out_to_fsm2")
FSM1StateOutToFSM3 = "state_fsm1_out_to_fsm3" FSM1StateOutToFSM3 = State("state_fsm1_out_to_fsm3")
// Events // Events
EventFSM1Init = "event_fsm1_init" EventFSM1Init = Event("event_fsm1_init")
EventFSM1Cancel = "event_fsm1_cancel" EventFSM1Cancel = Event("event_fsm1_cancel")
EventFSM1Process = "event_fsm1_process" EventFSM1Process = Event("event_fsm1_process")
// Internal events // Internal events
EventFSM1Internal = "event_internal_fsm1" EventFSM1Internal = Event("event_internal_fsm1")
EventFSM1CancelByInternal = "event_internal_fsm1_cancel" EventFSM1CancelByInternal = Event("event_internal_fsm1_cancel")
EventFSM1InternalOut2 = "event_internal_fsm1_out" EventFSM1InternalOut2 = Event("event_internal_fsm1_out")
) )
var ( var (
testingEvents = []Event{ testing1Events = []EventDesc{
// Init // Init
{Name: EventFSM1Init, SrcState: []string{FSM1StateInit}, DstState: FSM1StateStage1}, {Name: EventFSM1Init, SrcState: []State{FSM2StateInit}, DstState: FSM1StateStage1},
{Name: EventFSM1Internal, SrcState: []string{FSM1StateStage1}, DstState: FSM1StateStage2, IsInternal: true}, {Name: EventFSM1Internal, SrcState: []State{FSM1StateStage1}, DstState: FSM1StateStage2, IsInternal: true},
// Cancellation events // Cancellation events
{Name: EventFSM1CancelByInternal, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateCanceledByInternal, IsInternal: true}, {Name: EventFSM1CancelByInternal, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateCanceledByInternal, IsInternal: true},
{Name: EventFSM1Cancel, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateCanceled2}, {Name: EventFSM1Cancel, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateCanceled2},
// Out // Out
{Name: EventFSM1Process, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateOutToFSM2}, {Name: EventFSM1Process, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateOutToFSM2},
{Name: EventFSM1InternalOut2, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateOutToFSM3, IsInternal: true}, {Name: EventFSM1InternalOut2, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateOutToFSM3, IsInternal: true},
} }
testingCallbacks = Callbacks{ testing1Callbacks = Callbacks{
EventFSM1Init: actionSetUpData, EventFSM1Init: actionSetUpData,
EventFSM1InternalOut2: actionEmitOut2, EventFSM1InternalOut2: actionEmitOut2,
EventFSM1Process: actionProcessData, EventFSM1Process: actionProcessData,
} }
) )
type testMachineFSM struct { func actionSetUpData(event Event, args ...interface{}) (response interface{}, err error) {
*FSM
}
/*func new() fsm_pool.IStateMachine {
machine := &testMachineFSM{}
machine.FSM = MustNewFSM(
FSM1Name,
FSM1StateInit,
testingEvents,
testingCallbacks,
)
return machine
}*/
func actionSetUpData(event string, args ...interface{}) (response interface{}, err error) {
return return
} }
func actionProcessData(event string, args ...interface{}) (response interface{}, err error) { func actionProcessData(event Event, args ...interface{}) (response interface{}, err error) {
return return
} }
func actionEmitOut2(event string, args ...interface{}) (response interface{}, err error) { func actionEmitOut2(event Event, args ...interface{}) (response interface{}, err error) {
return return
} }

View File

@ -1,7 +1,6 @@
package fsm package fsm
import ( import (
"log"
"testing" "testing"
) )
@ -11,8 +10,8 @@ func init() {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
FSM1Name, FSM1Name,
FSM1StateInit, FSM1StateInit,
testingEvents, testing1Events,
testingCallbacks, testing1Callbacks,
) )
} }
@ -29,12 +28,38 @@ func compareRecoverStr(t *testing.T, r interface{}, assertion string) {
} }
} }
func compareArrays(src, dst []string) bool { func compareStatesArr(src, dst []State) bool {
if len(src) != len(dst) { if len(src) != len(dst) {
return false return false
} }
// create a map of string -> int // create a map of string -> int
diff := make(map[string]int, len(src)) diff := make(map[State]int, len(src))
for _, _x := range src {
// 0 value for int is 0, so just increment a counter for the string
diff[_x]++
}
for _, _y := range dst {
// If the string _y is not in diff bail out early
if _, ok := diff[_y]; !ok {
return false
}
diff[_y] -= 1
if diff[_y] == 0 {
delete(diff, _y)
}
}
if len(diff) == 0 {
return true
}
return false
}
func compareEventsArr(src, dst []Event) bool {
if len(src) != len(dst) {
return false
}
// create a map of string -> int
diff := make(map[Event]int, len(src))
for _, _x := range src { for _, _x := range src {
// 0 value for int is 0, so just increment a counter for the string // 0 value for int is 0, so just increment a counter for the string
diff[_x]++ diff[_x]++
@ -62,7 +87,7 @@ func TestMustNewFSM_Empty_Name_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"", "",
"init_state", "init_state",
[]Event{}, []EventDesc{},
nil, nil,
) )
@ -77,7 +102,7 @@ func TestMustNewFSM_Empty_Initial_State_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"fsm", "fsm",
"", "",
[]Event{}, []EventDesc{},
nil, nil,
) )
@ -92,7 +117,7 @@ func TestMustNewFSM_Empty_Events_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"fsm", "fsm",
"init_state", "init_state",
[]Event{}, []EventDesc{},
nil, nil,
) )
@ -107,8 +132,8 @@ func TestMustNewFSM_Event_Empty_Name_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"fsm", "fsm",
"init_state", "init_state",
[]Event{ []EventDesc{
{Name: "", SrcState: []string{"init_state"}, DstState: StateGlobalDone}, {Name: "", SrcState: []State{"init_state"}, DstState: StateGlobalDone},
}, },
nil, nil,
) )
@ -124,8 +149,8 @@ func TestMustNewFSM_Event_Empty_Source_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"fsm", "fsm",
"init_state", "init_state",
[]Event{ []EventDesc{
{Name: "event", SrcState: []string{}, DstState: StateGlobalDone}, {Name: "event", SrcState: []State{}, DstState: StateGlobalDone},
}, },
nil, nil,
) )
@ -141,8 +166,8 @@ func TestMustNewFSM_States_Min_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"fsm", "fsm",
"init_state", "init_state",
[]Event{ []EventDesc{
{Name: "event", SrcState: []string{"init_state"}, DstState: StateGlobalDone}, {Name: "event", SrcState: []State{"init_state"}, DstState: StateGlobalDone},
}, },
nil, nil,
) )
@ -158,9 +183,9 @@ func TestMustNewFSM_State_Entry_Conflict_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"fsm", "fsm",
"init_state", "init_state",
[]Event{ []EventDesc{
{Name: "event1", SrcState: []string{"init_state"}, DstState: "state"}, {Name: "event1", SrcState: []State{"init_state"}, DstState: "state"},
{Name: "event2", SrcState: []string{"init_state"}, DstState: "state"}, {Name: "event2", SrcState: []State{"init_state"}, DstState: "state"},
}, },
nil, nil,
) )
@ -176,9 +201,9 @@ func TestMustNewFSM_State_Final_Not_Found_Panic(t *testing.T) {
testingFSM = MustNewFSM( testingFSM = MustNewFSM(
"fsm", "fsm",
"init_state", "init_state",
[]Event{ []EventDesc{
{Name: "event1", SrcState: []string{"init_state"}, DstState: "state2"}, {Name: "event1", SrcState: []State{"init_state"}, DstState: "state2"},
{Name: "event2", SrcState: []string{"state2"}, DstState: "init_state"}, {Name: "event2", SrcState: []State{"state2"}, DstState: "init_state"},
}, },
nil, nil,
) )
@ -199,27 +224,26 @@ func TestFSM_EntryEvent(t *testing.T) {
} }
func TestFSM_EventsList(t *testing.T) { func TestFSM_EventsList(t *testing.T) {
eventsList := []string{ eventsList := []Event{
EventFSM1Init, EventFSM1Init,
EventFSM1Cancel, EventFSM1Cancel,
EventFSM1Process, EventFSM1Process,
} }
if !compareArrays(testingFSM.EventsList(), eventsList) { if !compareEventsArr(testingFSM.EventsList(), eventsList) {
t.Error("expected public events", eventsList) t.Error("expected public events", eventsList)
} }
} }
func TestFSM_StatesList(t *testing.T) { func TestFSM_StatesList(t *testing.T) {
log.Println(testingFSM.StatesSourcesList()) statesList := []State{
statesList := []string{
FSM1StateInit, FSM1StateInit,
FSM1StateStage1, FSM1StateStage1,
FSM1StateStage2, FSM1StateStage2,
} }
if !compareArrays(testingFSM.StatesSourcesList(), statesList) { if !compareStatesArr(testingFSM.StatesSourcesList(), statesList) {
t.Error("expected states", statesList) t.Error("expected states", statesList)
} }
} }

View File

@ -6,50 +6,52 @@ import (
"github.com/depools/dc4bc/fsm/fsm" "github.com/depools/dc4bc/fsm/fsm"
) )
type IStateMachine interface { type MachineProvider interface {
// Returns machine state from scope dump // Returns machine state from scope dump
// For nil argument returns fsm with process initiation // For nil argument returns fsm with process initiation
// Get() IStateMachine // Get() MachineProvider
Name() string Name() string
InitialState() string InitialState() fsm.State
// Process event // Process event
Do(event string, args ...interface{}) (*fsm.FSMResponse, error) Do(event fsm.Event, args ...interface{}) (*fsm.Response, error)
GlobalInitialEvent() string GlobalInitialEvent() fsm.Event
EventsList() []string EventsList() []fsm.Event
StatesSourcesList() []string StatesSourcesList() []fsm.State
IsFinState(state string) bool IsFinState(state fsm.State) bool
} }
type FSMMapper map[string]IStateMachine type FSMMapper map[string]MachineProvider
type FSMRouteMapper map[string]string type FSMEventsMapper map[fsm.Event]string
type FSMPoolProvider struct { type FSMStatesMapper map[fsm.State]string
fsmInitialEvent string
type FSMPool struct {
fsmInitialEvent fsm.Event
// Pool mapper by names // Pool mapper by names
mapper FSMMapper mapper FSMMapper
events FSMRouteMapper events FSMEventsMapper
states FSMRouteMapper states FSMStatesMapper
} }
func Init(machines ...IStateMachine) *FSMPoolProvider { func Init(machines ...MachineProvider) *FSMPool {
if len(machines) == 0 { if len(machines) == 0 {
panic("cannot initialize empty pool") panic("cannot initialize empty pool")
} }
p := &FSMPoolProvider{ p := &FSMPool{
mapper: make(FSMMapper), mapper: make(FSMMapper),
events: make(FSMRouteMapper), events: make(FSMEventsMapper),
states: make(FSMRouteMapper), states: make(FSMStatesMapper),
} }
allInitStatesMap := make(map[string]string) allInitStatesMap := make(map[fsm.State]string)
// Fill up mapper // Fill up mapper
for _, machine := range machines { for _, machine := range machines {
@ -99,7 +101,7 @@ func Init(machines ...IStateMachine) *FSMPoolProvider {
if machine.IsFinState(state) { if machine.IsFinState(state) {
// If state is initial for another machine, // If state is initial for another machine,
if initMachineName, exists := allInitStatesMap[state]; exists { if initMachineName, exists := allInitStatesMap[state]; exists {
p.states[allInitStatesMap[state]] = initMachineName p.states[state] = initMachineName
continue continue
} }
} }
@ -117,7 +119,7 @@ func Init(machines ...IStateMachine) *FSMPoolProvider {
return p return p
} }
func (p *FSMPoolProvider) EntryPointMachine() (IStateMachine, error) { func (p *FSMPool) EntryPointMachine() (MachineProvider, error) {
// StateGlobalIdle // StateGlobalIdle
// TODO: Short code // TODO: Short code
entryStateMachineName := p.events[p.fsmInitialEvent] entryStateMachineName := p.events[p.fsmInitialEvent]
@ -130,7 +132,7 @@ func (p *FSMPoolProvider) EntryPointMachine() (IStateMachine, error) {
return machine, nil return machine, nil
} }
func (p *FSMPoolProvider) MachineByEvent(event string) (IStateMachine, error) { func (p *FSMPool) MachineByEvent(event fsm.Event) (MachineProvider, error) {
eventMachineName := p.events[event] eventMachineName := p.events[event]
machine, exists := p.mapper[eventMachineName] machine, exists := p.mapper[eventMachineName]
@ -140,7 +142,7 @@ func (p *FSMPoolProvider) MachineByEvent(event string) (IStateMachine, error) {
return machine, nil return machine, nil
} }
func (p *FSMPoolProvider) MachineByState(state string) (IStateMachine, error) { func (p *FSMPool) MachineByState(state fsm.State) (MachineProvider, error) {
eventMachineName := p.states[state] eventMachineName := p.states[state]
machine, exists := p.mapper[eventMachineName] machine, exists := p.mapper[eventMachineName]

View File

@ -0,0 +1,18 @@
package fsm_pool
/*
import (
"testing"
)
var (
)
func init() {
}
func Test_InitPool(t *testing.T) {
} */

View File

@ -14,17 +14,17 @@ import (
// Is machine state scope dump will be locked? // Is machine state scope dump will be locked?
type FSMDump struct { type FSMDump struct {
Id string Id string
State string State fsm.State
Payload internal.MachineStatePayload Payload internal.MachineStatePayload
} }
type FSMInstance struct { type FSMInstance struct {
machine fsm_pool.IStateMachine machine fsm_pool.MachineProvider
dump *FSMDump dump *FSMDump
} }
var ( var (
fsmPoolProvider *fsm_pool.FSMPoolProvider fsmPoolProvider *fsm_pool.FSMPool
) )
func init() { func init() {
@ -53,7 +53,7 @@ func New(data []byte) (*FSMInstance, error) {
return i, err return i, err
} }
func (i *FSMInstance) Do(event string, args ...interface{}) (*fsm.FSMResponse, []byte, error) { func (i *FSMInstance) Do(event fsm.Event, args ...interface{}) (*fsm.Response, []byte, error) {
// Provide payload as first argument ever // Provide payload as first argument ever
result, err := i.machine.Do(event, append([]interface{}{i.dump.Payload}, args...)...) result, err := i.machine.Do(event, append([]interface{}{i.dump.Payload}, args...)...)

View File

@ -19,18 +19,18 @@ type SignatureConstructFSM struct {
*fsm.FSM *fsm.FSM
} }
func New() fsm_pool.IStateMachine { func New() fsm_pool.MachineProvider {
machine := &SignatureConstructFSM{} machine := &SignatureConstructFSM{}
machine.FSM = fsm.MustNewFSM( machine.FSM = fsm.MustNewFSM(
fsmName, fsmName,
stateConstructorEntryPoint, stateConstructorEntryPoint,
[]fsm.Event{ []fsm.EventDesc{
// {Name: "", SrcState: []string{""}, DstState: ""}, // {Name: "", SrcState: []string{""}, DstState: ""},
// Init // Init
{Name: eventInitSignatureConstructor, SrcState: []string{stateConstructorEntryPoint}, DstState: awaitConstructor}, {Name: eventInitSignatureConstructor, SrcState: []fsm.State{stateConstructorEntryPoint}, DstState: awaitConstructor},
{Name: eventInitSignatureFinishTmp, SrcState: []string{awaitConstructor}, DstState: "dkg_proposal_fsm"}, {Name: eventInitSignatureFinishTmp, SrcState: []fsm.State{awaitConstructor}, DstState: "dkg_proposal_fsm"},
}, },
fsm.Callbacks{}, fsm.Callbacks{},
) )

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"log" "log"
"github.com/depools/dc4bc/fsm/fsm"
"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"
"github.com/depools/dc4bc/fsm/types/responses" "github.com/depools/dc4bc/fsm/types/responses"
@ -11,7 +12,7 @@ import (
// init -> awaitingConfirmations // init -> awaitingConfirmations
// args: payload, signing id, participants list // args: payload, signing id, participants list
func (s *SignatureProposalFSM) actionInitProposal(event string, args ...interface{}) (response interface{}, err error) { func (s *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
var payload internal.MachineStatePayload var payload internal.MachineStatePayload
// Init proposal // Init proposal
log.Println("I'm actionInitProposal") log.Println("I'm actionInitProposal")
@ -83,17 +84,17 @@ func (s *SignatureProposalFSM) actionInitProposal(event string, args ...interfac
} }
// //
func (s *SignatureProposalFSM) actionConfirmProposalByParticipant(event string, args ...interface{}) (response interface{}, err error) { func (s *SignatureProposalFSM) actionConfirmProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
log.Println("I'm actionConfirmProposalByParticipant") log.Println("I'm actionConfirmProposalByParticipant")
return return
} }
func (s *SignatureProposalFSM) actionDeclineProposalByParticipant(event string, args ...interface{}) (response interface{}, err error) { func (s *SignatureProposalFSM) actionDeclineProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
log.Println("I'm actionDeclineProposalByParticipant") log.Println("I'm actionDeclineProposalByParticipant")
return return
} }
func (s *SignatureProposalFSM) actionValidateProposal(event string, args ...interface{}) (response interface{}, err error) { func (s *SignatureProposalFSM) actionValidateProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
log.Println("I'm actionValidateProposal") log.Println("I'm actionValidateProposal")
return return
} }

View File

@ -9,53 +9,53 @@ const (
fsmName = "signature_proposal_fsm" fsmName = "signature_proposal_fsm"
signingIdLen = 32 signingIdLen = 32
stateAwaitProposalConfirmation = "validate_proposal" // waiting participants stateAwaitProposalConfirmation = fsm.State("validate_proposal") // waiting participants
stateValidationCanceledByParticipant = "validation_canceled_by_participant" stateValidationCanceledByParticipant = fsm.State("validation_canceled_by_participant")
stateValidationCanceledByTimeout = "validation_canceled_by_timeout" stateValidationCanceledByTimeout = fsm.State("validation_canceled_by_timeout")
stateProposed = "proposed" stateProposed = "proposed"
eventInitProposal = "proposal_init" eventInitProposal = fsm.Event("proposal_init")
eventConfirmProposal = "proposal_confirm_by_participant" eventConfirmProposal = fsm.Event("proposal_confirm_by_participant")
eventDeclineProposal = "proposal_decline_by_participant" eventDeclineProposal = fsm.Event("proposal_decline_by_participant")
eventValidateProposal = "proposal_validate" eventValidateProposal = fsm.Event("proposal_validate")
eventSetProposalValidated = "proposal_set_validated" eventSetProposalValidated = fsm.Event("proposal_set_validated")
eventSetValidationCanceledByTimeout = "proposal_canceled_timeout" eventSetValidationCanceledByTimeout = fsm.Event("proposal_canceled_timeout")
eventSwitchProposedToSigning = "switch_state_to_signing" eventSwitchProposedToSigning = fsm.Event("switch_state_to_signing")
) )
type SignatureProposalFSM struct { type SignatureProposalFSM struct {
*fsm.FSM *fsm.FSM
} }
func New() fsm_pool.IStateMachine { func New() fsm_pool.MachineProvider {
machine := &SignatureProposalFSM{} machine := &SignatureProposalFSM{}
machine.FSM = fsm.MustNewFSM( machine.FSM = fsm.MustNewFSM(
fsmName, fsmName,
fsm.StateGlobalIdle, fsm.StateGlobalIdle,
[]fsm.Event{ []fsm.EventDesc{
// {Name: "", SrcState: []string{""}, DstState: ""}, // {Name: "", SrcState: []string{""}, DstState: ""},
// Init // Init
{Name: eventInitProposal, SrcState: []string{fsm.StateGlobalIdle}, DstState: stateAwaitProposalConfirmation}, {Name: eventInitProposal, SrcState: []fsm.State{fsm.StateGlobalIdle}, DstState: stateAwaitProposalConfirmation},
// Validate by participants // Validate by participants
{Name: eventConfirmProposal, SrcState: []string{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation}, {Name: eventConfirmProposal, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation},
// 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: []string{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByParticipant}, {Name: eventDeclineProposal, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByParticipant},
{Name: eventValidateProposal, SrcState: []string{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation}, {Name: eventValidateProposal, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation},
// eventProposalValidate internal or from client? // eventProposalValidate internal or from client?
// yay // yay
// Exit point // Exit point
{Name: eventSetProposalValidated, SrcState: []string{stateAwaitProposalConfirmation}, DstState: "process_sig", IsInternal: true}, {Name: eventSetProposalValidated, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: "process_sig", IsInternal: true},
// nan // nan
{Name: eventSetValidationCanceledByTimeout, SrcState: []string{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByTimeout, IsInternal: true}, {Name: eventSetValidationCanceledByTimeout, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByTimeout, IsInternal: true},
}, },
fsm.Callbacks{ fsm.Callbacks{
eventInitProposal: machine.actionInitProposal, eventInitProposal: machine.actionInitProposal,

1
go.mod
View File

@ -8,7 +8,6 @@ require (
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b
github.com/looplab/fsm v0.1.0 github.com/looplab/fsm v0.1.0
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7 github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.6.1
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0

6
go.sum
View File

@ -20,10 +20,6 @@ github.com/looplab/fsm v0.1.0 h1:Qte7Zdn/5hBNbXzP7yxVU4OIFHWXBovyTT2LaBTyC20=
github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI= github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI=
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7 h1:CfWnkHgRG8zmxQI7RAhLIUFPkg+RfDdWiEtoE3y1+4w= github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7 h1:CfWnkHgRG8zmxQI7RAhLIUFPkg+RfDdWiEtoE3y1+4w=
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7/go.mod h1:WoI7z45M7ZNA5BJxiJHaB+x7+k8S/3phW5Y13IR4yWY= github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7/go.mod h1:WoI7z45M7ZNA5BJxiJHaB+x7+k8S/3phW5Y13IR4yWY=
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5 h1:GMB3MVJnxysGrSvjWGsgK8L3XGI3F4etQQq37Py6W5A=
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5/go.mod h1:PwzwfeB5syFHXORC3MtPylVcjIoTDT/9cvkKpEndGVI=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f h1:QTRRO+ozoYgT3CQRIzNVYJRU3DB8HRnkZv6mr4ISmMA=
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -51,9 +47,11 @@ golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI=