mirror of https://github.com/certusone/dc4bc.git
Merge pull request #14 from depools/feat-updated-fsm-pool
feat: updated machines pool
This commit is contained in:
commit
cc139a4abe
|
@ -10,11 +10,10 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
fsmMachine, err := state_machines.New([]byte{})
|
||||
fsmMachine, err := state_machines.Create("d8a928b2043db77e340b523547bf16cb4aa483f0645fe0a290ed1f20aab76257")
|
||||
log.Println(fsmMachine, err)
|
||||
resp, dump, err := fsmMachine.Do(
|
||||
"event_proposal_init",
|
||||
"d8a928b2043db77e340b523547bf16cb4aa483f0645fe0a290ed1f20aab76257",
|
||||
requests.SignatureProposalParticipantsListRequest{
|
||||
{
|
||||
"John Doe",
|
||||
|
@ -40,7 +39,7 @@ func main() {
|
|||
func processResponse(resp *fsm.Response) {
|
||||
switch resp.State {
|
||||
// Await proposals
|
||||
case fsm.State("validate_proposal"):
|
||||
case fsm.State("state_validation_await_participants_confirmations"):
|
||||
data, ok := resp.Data.(responses.SignatureProposalParticipantInvitationsResponse)
|
||||
if !ok {
|
||||
log.Printf("undefined response type for state \"%s\"\n", resp.State)
|
||||
|
|
|
@ -6,49 +6,49 @@ import (
|
|||
)
|
||||
|
||||
// Pub keys
|
||||
func (s *DKGProposalFSM) actionDKGPubKeysSent(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGPubKeysSent(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGPubKeysSent")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DKGProposalFSM) actionDKGPubKeyConfirmationReceived(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGPubKeyConfirmationReceived(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGPubKeyConfirmationReceived")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DKGProposalFSM) actionDKGPubKeyConfirmationError(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGPubKeyConfirmationError(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGPubKeyConfirmationError")
|
||||
return
|
||||
}
|
||||
|
||||
// Commits
|
||||
func (s *DKGProposalFSM) actionDKGCommitsSent(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGCommitsSent(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGCommitsSent")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DKGProposalFSM) actionDKGCommitConfirmationReceived(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGCommitConfirmationReceived(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGCommitConfirmationReceived")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DKGProposalFSM) actionDKGCommitConfirmationError(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGCommitConfirmationError(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGCommitConfirmationError")
|
||||
return
|
||||
}
|
||||
|
||||
// Deals
|
||||
func (s *DKGProposalFSM) actionDKGDealsSent(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGDealsSent(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGDealsSent")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DKGProposalFSM) actionDKGDealConfirmationReceived(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGDealConfirmationReceived(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGDealConfirmationReceived")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *DKGProposalFSM) actionDKGDealConfirmationError(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *DKGProposalFSM) actionDKGDealConfirmationError(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDKGDealConfirmationError")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,8 +2,9 @@ package dkg_proposal_fsm
|
|||
|
||||
import (
|
||||
"github.com/depools/dc4bc/fsm/fsm"
|
||||
"github.com/depools/dc4bc/fsm/fsm_pool"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/internal"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/signature_proposal_fsm"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -67,9 +68,11 @@ const (
|
|||
|
||||
type DKGProposalFSM struct {
|
||||
*fsm.FSM
|
||||
payload *internal.DumpedMachineStatePayload
|
||||
payloadMu sync.RWMutex
|
||||
}
|
||||
|
||||
func New() fsm_pool.MachineProvider {
|
||||
func New() internal.DumpedMachineProvider {
|
||||
machine := &DKGProposalFSM{}
|
||||
|
||||
machine.FSM = fsm.MustNewFSM(
|
||||
|
@ -131,3 +134,10 @@ func New() fsm_pool.MachineProvider {
|
|||
)
|
||||
return machine
|
||||
}
|
||||
|
||||
func (m *DKGProposalFSM) SetUpPayload(payload *internal.DumpedMachineStatePayload) {
|
||||
m.payloadMu.Lock()
|
||||
defer m.payloadMu.Unlock()
|
||||
|
||||
m.payload = payload
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package internal
|
||||
|
||||
type MachineStatePayload struct {
|
||||
ConfirmationProposalPayload ConfirmationProposalPrivateQuorum
|
||||
DKGProposalPayload DKGProposalPrivateQuorum
|
||||
import "github.com/depools/dc4bc/fsm/fsm_pool"
|
||||
|
||||
type DumpedMachineStatePayload struct {
|
||||
TransactionId string
|
||||
ConfirmationProposalPayload SignatureProposalQuorum
|
||||
DKGProposalPayload DKGProposalQuorum
|
||||
}
|
||||
|
||||
// Using combine response for modify data with chain
|
||||
// User value or pointer? How about memory state?
|
||||
type MachineCombinedResponse struct {
|
||||
Response interface{}
|
||||
Payload *MachineStatePayload
|
||||
type DumpedMachineProvider interface {
|
||||
fsm_pool.MachineProvider
|
||||
SetUpPayload(payload *DumpedMachineStatePayload)
|
||||
}
|
||||
|
|
|
@ -2,27 +2,58 @@ package internal
|
|||
|
||||
import "time"
|
||||
|
||||
type ProposalParticipantPrivate struct {
|
||||
const (
|
||||
SignatureAwaitConfirmation SignatureProposalParticipantStatus = iota
|
||||
SignatureConfirmed
|
||||
)
|
||||
|
||||
type ConfirmationProposal struct {
|
||||
Quorum SignatureProposalQuorum
|
||||
CreatedAt *time.Time
|
||||
ExpiresAt *time.Time
|
||||
}
|
||||
|
||||
type SignatureProposalParticipant struct {
|
||||
// Public title for address, such as name, nickname, organization
|
||||
ParticipantId int
|
||||
Title string
|
||||
PublicKey []byte
|
||||
// For validation user confirmation: sign(InvitationSecret, PublicKey) => user
|
||||
InvitationSecret string
|
||||
ConfirmedAt *time.Time
|
||||
Status SignatureProposalParticipantStatus
|
||||
UpdatedAt *time.Time
|
||||
}
|
||||
|
||||
// Unique alias for map iteration - Public Key Fingerprint
|
||||
// Excludes array merge and rotate operations
|
||||
type SignatureProposalQuorum map[string]SignatureProposalParticipant
|
||||
|
||||
type ConfirmationProposalPrivateQuorum map[string]ProposalParticipantPrivate
|
||||
type SignatureProposalParticipantStatus uint8
|
||||
|
||||
type ProposalDKGParticipantPrivate struct {
|
||||
const (
|
||||
PubKeyConAwaitConfirmation DKGProposalParticipantStatus = iota
|
||||
PubKeyConfirmed
|
||||
CommitAwaitConfirmation
|
||||
CommitConfirmed
|
||||
DealAwaitConfirmation
|
||||
DealConfirmed
|
||||
)
|
||||
|
||||
type DKGProposal struct {
|
||||
Quorum map[int]DKGProposalParticipant
|
||||
CreatedAt *time.Time
|
||||
ExpiresAt *time.Time
|
||||
}
|
||||
|
||||
type DKGProposalParticipant struct {
|
||||
Title string
|
||||
PublicKey []byte
|
||||
Commit []byte
|
||||
Deal []byte
|
||||
Status DKGProposalParticipantStatus
|
||||
UpdatedAt *time.Time
|
||||
}
|
||||
|
||||
type DKGProposalPrivateQuorum map[int]ProposalParticipantPrivate
|
||||
type DKGProposalQuorum map[int]DKGProposalParticipant
|
||||
|
||||
type DKGProposalParticipantStatus uint8
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm"
|
||||
"strings"
|
||||
|
||||
"github.com/depools/dc4bc/fsm/fsm"
|
||||
"github.com/depools/dc4bc/fsm/fsm_pool"
|
||||
|
@ -13,13 +14,13 @@ import (
|
|||
|
||||
// Is machine state scope dump will be locked?
|
||||
type FSMDump struct {
|
||||
Id string
|
||||
TransactionId string
|
||||
State fsm.State
|
||||
Payload internal.MachineStatePayload
|
||||
Payload *internal.DumpedMachineStatePayload
|
||||
}
|
||||
|
||||
type FSMInstance struct {
|
||||
machine fsm_pool.MachineProvider
|
||||
machine internal.DumpedMachineProvider
|
||||
dump *FSMDump
|
||||
}
|
||||
|
||||
|
@ -34,58 +35,76 @@ func init() {
|
|||
)
|
||||
}
|
||||
|
||||
func New(data []byte) (*FSMInstance, error) {
|
||||
// Transaction id required for unique identify dump
|
||||
func Create(tid string) (*FSMInstance, error) {
|
||||
var err error
|
||||
i := &FSMInstance{}
|
||||
if len(data) == 0 {
|
||||
i.InitDump()
|
||||
i.machine, err = fsmPoolProvider.EntryPointMachine()
|
||||
return i, err // Create machine
|
||||
err = i.InitDump(tid)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
machine, err := fsmPoolProvider.EntryPointMachine()
|
||||
i.machine = machine.(internal.DumpedMachineProvider)
|
||||
i.machine.SetUpPayload(i.dump.Payload)
|
||||
return i, err
|
||||
}
|
||||
|
||||
func FromDump(data []byte) (*FSMInstance, error) {
|
||||
var err error
|
||||
|
||||
i := &FSMInstance{}
|
||||
err = i.dump.Unmarshal(data)
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.New("cannot read machine dump")
|
||||
}
|
||||
|
||||
i.machine, err = fsmPoolProvider.MachineByState(i.dump.State)
|
||||
machine, err := fsmPoolProvider.MachineByState(i.dump.State)
|
||||
i.machine = machine.(internal.DumpedMachineProvider)
|
||||
i.machine.SetUpPayload(i.dump.Payload)
|
||||
return i, err
|
||||
}
|
||||
|
||||
func (i *FSMInstance) Do(event fsm.Event, args ...interface{}) (*fsm.Response, []byte, error) {
|
||||
// Provide payload as first argument ever
|
||||
result, err := i.machine.Do(event, append([]interface{}{i.dump.Payload}, args...)...)
|
||||
func (i *FSMInstance) Do(event fsm.Event, args ...interface{}) (result *fsm.Response, dump []byte, err error) {
|
||||
var dumpErr error
|
||||
|
||||
result, err = i.machine.Do(event, args...)
|
||||
|
||||
// On route errors result will be nil
|
||||
if result != nil {
|
||||
|
||||
// Proxying combined response, separate payload and data
|
||||
if result.Data != nil {
|
||||
if r, ok := result.Data.(internal.MachineCombinedResponse); ok {
|
||||
i.dump.Payload = *r.Payload
|
||||
result.Data = r.Response
|
||||
} else {
|
||||
return nil, []byte{}, errors.New("cannot cast callback response")
|
||||
}
|
||||
}
|
||||
|
||||
i.dump.State = result.State
|
||||
}
|
||||
dump, dumpErr := i.dump.Marshal()
|
||||
|
||||
dump, dumpErr = i.dump.Marshal()
|
||||
if dumpErr != nil {
|
||||
return result, []byte{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return result, dump, err
|
||||
}
|
||||
|
||||
func (i *FSMInstance) InitDump() {
|
||||
if i.dump == nil {
|
||||
func (i *FSMInstance) InitDump(tid string) error {
|
||||
if i.dump != nil {
|
||||
return errors.New("dump already initialized")
|
||||
}
|
||||
|
||||
tid = strings.TrimSpace(tid)
|
||||
|
||||
if tid == "" {
|
||||
return errors.New("empty transaction id")
|
||||
}
|
||||
|
||||
i.dump = &FSMDump{
|
||||
State: fsm.StateGlobalIdle,
|
||||
Payload: &internal.DumpedMachineStatePayload{
|
||||
TransactionId: tid,
|
||||
ConfirmationProposalPayload: nil,
|
||||
DKGProposalPayload: nil,
|
||||
},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Add encryption
|
||||
|
|
|
@ -12,40 +12,16 @@ import (
|
|||
|
||||
// init -> awaitingConfirmations
|
||||
// args: payload, signing id, participants list
|
||||
func (s *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
var payload internal.MachineStatePayload
|
||||
// Init proposal
|
||||
log.Println("I'm actionInitProposal")
|
||||
func (m *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
m.payloadMu.Lock()
|
||||
defer m.payloadMu.Unlock()
|
||||
|
||||
if len(args) < 3 {
|
||||
err = errors.New("payload and signing id required and participants list required")
|
||||
if len(args) != 1 {
|
||||
err = errors.New("participants list required")
|
||||
return
|
||||
}
|
||||
|
||||
if len(args) > 3 {
|
||||
err = errors.New("too many arguments")
|
||||
return
|
||||
}
|
||||
|
||||
payload, ok := args[0].(internal.MachineStatePayload)
|
||||
|
||||
if !ok {
|
||||
err = errors.New("cannot cast payload")
|
||||
return
|
||||
}
|
||||
|
||||
signingId, ok := args[1].(string)
|
||||
if !ok {
|
||||
err = errors.New("cannot cast signing id, awaiting string value")
|
||||
return
|
||||
}
|
||||
|
||||
if len(signingId) < signingIdLen {
|
||||
err = errors.New("signing id to short ")
|
||||
return
|
||||
}
|
||||
|
||||
request, ok := args[2].(requests.SignatureProposalParticipantsListRequest)
|
||||
request, ok := args[0].(requests.SignatureProposalParticipantsListRequest)
|
||||
|
||||
if !ok {
|
||||
err = errors.New("cannot cast participants list")
|
||||
|
@ -56,7 +32,7 @@ func (s *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...inter
|
|||
return
|
||||
}
|
||||
|
||||
payload.ConfirmationProposalPayload = make(internal.ConfirmationProposalPrivateQuorum)
|
||||
m.payload.ConfirmationProposalPayload = make(internal.SignatureProposalQuorum)
|
||||
|
||||
for participantIntId, participant := range request {
|
||||
participantId := createFingerprint(&participant.PublicKey)
|
||||
|
@ -64,12 +40,12 @@ func (s *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...inter
|
|||
if err != nil {
|
||||
return nil, errors.New("cannot generateRandomString")
|
||||
}
|
||||
payload.ConfirmationProposalPayload[participantId] = internal.ProposalParticipantPrivate{
|
||||
m.payload.ConfirmationProposalPayload[participantId] = internal.SignatureProposalParticipant{
|
||||
ParticipantId: participantIntId,
|
||||
Title: participant.Title,
|
||||
PublicKey: participant.PublicKey,
|
||||
InvitationSecret: secret,
|
||||
ConfirmedAt: nil,
|
||||
UpdatedAt: nil,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +53,7 @@ func (s *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...inter
|
|||
|
||||
responseData := make(responses.SignatureProposalParticipantInvitationsResponse, 0)
|
||||
|
||||
for pubKeyFingerprint, proposal := range payload.ConfirmationProposalPayload {
|
||||
for pubKeyFingerprint, proposal := range m.payload.ConfirmationProposalPayload {
|
||||
encryptedInvitationSecret, err := encryptWithPubKey(proposal.PublicKey, proposal.InvitationSecret)
|
||||
if err != nil {
|
||||
return nil, errors.New("cannot encryptWithPubKey")
|
||||
|
@ -92,24 +68,21 @@ func (s *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...inter
|
|||
|
||||
// Change state
|
||||
|
||||
return internal.MachineCombinedResponse{
|
||||
Response: responseData,
|
||||
Payload: &payload,
|
||||
}, nil
|
||||
return responseData, nil
|
||||
}
|
||||
|
||||
//
|
||||
func (s *SignatureProposalFSM) actionConfirmProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *SignatureProposalFSM) actionConfirmProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionConfirmProposalByParticipant")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SignatureProposalFSM) actionDeclineProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *SignatureProposalFSM) actionDeclineProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDeclineProposalByParticipant")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SignatureProposalFSM) actionValidateProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
func (m *SignatureProposalFSM) actionValidateProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionValidateProposal")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
// Request and response mutators
|
||||
|
||||
func ProposalParticipantsQuorumToResponse(list *internal.ConfirmationProposalPrivateQuorum) responses.SignatureProposalParticipantInvitationsResponse {
|
||||
func ProposalParticipantsQuorumToResponse(list *internal.SignatureProposalQuorum) responses.SignatureProposalParticipantInvitationsResponse {
|
||||
var response responses.SignatureProposalParticipantInvitationsResponse
|
||||
for quorumId, parcipant := range *list {
|
||||
response = append(response, &responses.SignatureProposalParticipantInvitationEntry{
|
||||
|
|
|
@ -2,7 +2,8 @@ package signature_proposal_fsm
|
|||
|
||||
import (
|
||||
"github.com/depools/dc4bc/fsm/fsm"
|
||||
"github.com/depools/dc4bc/fsm/fsm_pool"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/internal"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -30,9 +31,11 @@ const (
|
|||
|
||||
type SignatureProposalFSM struct {
|
||||
*fsm.FSM
|
||||
payload *internal.DumpedMachineStatePayload
|
||||
payloadMu sync.RWMutex
|
||||
}
|
||||
|
||||
func New() fsm_pool.MachineProvider {
|
||||
func New() internal.DumpedMachineProvider {
|
||||
machine := &SignatureProposalFSM{}
|
||||
|
||||
machine.FSM = fsm.MustNewFSM(
|
||||
|
@ -68,3 +71,10 @@ func New() fsm_pool.MachineProvider {
|
|||
)
|
||||
return machine
|
||||
}
|
||||
|
||||
func (m *SignatureProposalFSM) SetUpPayload(payload *internal.DumpedMachineStatePayload) {
|
||||
m.payloadMu.Lock()
|
||||
defer m.payloadMu.Unlock()
|
||||
|
||||
m.payload = payload
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue