From 7eb9b15bd92b2d1a0ca81c0187853be014807c85 Mon Sep 17 00:00:00 2001 From: programmer10110 Date: Tue, 25 Aug 2020 15:56:27 +0300 Subject: [PATCH] refactoring --- airgapped/airgapped.go | 49 +++++++++++++-------------------- airgapped/airgapped_test.go | 49 ++++++++++++++++----------------- airgapped/dkg.go | 47 ++++++++++++++++++-------------- client/client.go | 54 +++++++++++++++++-------------------- client/types/types.go | 2 +- 5 files changed, 96 insertions(+), 105 deletions(-) diff --git a/airgapped/airgapped.go b/airgapped/airgapped.go index 1f058b1..2b2c072 100644 --- a/airgapped/airgapped.go +++ b/airgapped/airgapped.go @@ -169,11 +169,9 @@ func (am *AirgappedMachine) decryptData(data []byte) ([]byte, error) { return decryptedData, nil } -func (am *AirgappedMachine) HandleOperation(operation client.Operation) ([]client.Operation, error) { +func (am *AirgappedMachine) HandleOperation(operation client.Operation) (client.Operation, error) { var ( err error - // output operations (cause of deals) - operations []client.Operation ) am.Lock() @@ -187,7 +185,7 @@ func (am *AirgappedMachine) HandleOperation(operation client.Operation) ([]clien case dkg_proposal_fsm.StateDkgCommitsAwaitConfirmations: err = am.handleStateDkgCommitsAwaitConfirmations(&operation) case dkg_proposal_fsm.StateDkgDealsAwaitConfirmations: - operations, err = am.handleStateDkgDealsAwaitConfirmations(operation) + err = am.handleStateDkgDealsAwaitConfirmations(&operation) case dkg_proposal_fsm.StateDkgResponsesAwaitConfirmations: err = am.handleStateDkgResponsesAwaitConfirmations(&operation) case dkg_proposal_fsm.StateDkgMasterKeyAwaitConfirmations: @@ -205,15 +203,11 @@ func (am *AirgappedMachine) HandleOperation(operation client.Operation) ([]clien //} } - if len(operation.Result) > 0 { - operations = append(operations, operation) - } - - return operations, nil + return operation, nil } // HandleQR - gets an operation from a QR code, do necessary things for the operation and returns paths to QR-code images -func (am *AirgappedMachine) HandleQR() ([]string, error) { +func (am *AirgappedMachine) HandleQR() (string, error) { var ( err error @@ -221,36 +215,31 @@ func (am *AirgappedMachine) HandleQR() ([]string, error) { operation client.Operation qrData []byte - // output operations (cause of deals) - operations []client.Operation + resultOperation client.Operation ) if qrData, err = am.qrProcessor.ReadQR(); err != nil { - return nil, fmt.Errorf("failed to read QR: %w", err) + return "", fmt.Errorf("failed to read QR: %w", err) } if err = json.Unmarshal(qrData, &operation); err != nil { - return nil, fmt.Errorf("failed to unmarshal operation: %w", err) + return "", fmt.Errorf("failed to unmarshal operation: %w", err) } - if operations, err = am.HandleOperation(operation); err != nil { - return nil, err + if resultOperation, err = am.HandleOperation(operation); err != nil { + return "", err } - qrPath := "%s/%s_%s_%s.png" - qrPaths := make([]string, 0, len(operations)) - for _, o := range operations { - operationBz, err := json.Marshal(o) - if err != nil { - return nil, fmt.Errorf("failed to marshal operation: %w", err) - } - - if err = am.qrProcessor.WriteQR(fmt.Sprintf(qrPath, resultQRFolder, o.Type, o.ID, o.To), operationBz); err != nil { - return nil, fmt.Errorf("failed to write QR") - } - qrPaths = append(qrPaths, qrPath) + qrPath := fmt.Sprintf("%s/%s_%s_%s.png", resultQRFolder, resultOperation.Type, resultOperation.ID, resultOperation.To) + operationBz, err := json.Marshal(resultOperation) + if err != nil { + return "", fmt.Errorf("failed to marshal operation: %w", err) } - return qrPaths, nil + if err = am.qrProcessor.WriteQR(qrPath, operationBz); err != nil { + return "", fmt.Errorf("failed to write QR") + } + + return qrPath, nil } func (am *AirgappedMachine) writeErrorRequestToOperation(o *client.Operation, handlerError error) error { @@ -276,7 +265,7 @@ func (am *AirgappedMachine) writeErrorRequestToOperation(o *client.Operation, ha if err != nil { return fmt.Errorf("failed to generate fsm request: %w", err) } - o.Result = reqBz o.Event = errorEvent + o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz)) return nil } diff --git a/airgapped/airgapped_test.go b/airgapped/airgapped_test.go index e75def7..d51ab2b 100644 --- a/airgapped/airgapped_test.go +++ b/airgapped/airgapped_test.go @@ -5,9 +5,11 @@ import ( "encoding/json" "fmt" client "github.com/depools/dc4bc/client/types" + "github.com/depools/dc4bc/fsm/fsm" "github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm" "github.com/depools/dc4bc/fsm/types/requests" "github.com/depools/dc4bc/fsm/types/responses" + "github.com/depools/dc4bc/storage" "github.com/google/uuid" "sync" "testing" @@ -29,34 +31,34 @@ type Node struct { masterKeys []requests.DKGProposalMasterKeyConfirmationRequest } -func (n *Node) storeOperation(t *testing.T, o client.Operation) { - switch o.Event { +func (n *Node) storeOperation(t *testing.T, msg storage.Message) { + switch fsm.Event(msg.Event) { case dkg_proposal_fsm.EventDKGCommitConfirmationReceived: var req requests.DKGProposalCommitConfirmationRequest - if err := json.Unmarshal(o.Result, &req); err != nil { + if err := json.Unmarshal(msg.Data, &req); err != nil { t.Fatalf("failed to unmarshal fsm req: %v", err) } n.commits = append(n.commits, req) case dkg_proposal_fsm.EventDKGDealConfirmationReceived: var req requests.DKGProposalDealConfirmationRequest - if err := json.Unmarshal(o.Result, &req); err != nil { + if err := json.Unmarshal(msg.Data, &req); err != nil { t.Fatalf("failed to unmarshal fsm req: %v", err) } n.deals = append(n.deals, req) case dkg_proposal_fsm.EventDKGResponseConfirmationReceived: var req requests.DKGProposalResponseConfirmationRequest - if err := json.Unmarshal(o.Result, &req); err != nil { + if err := json.Unmarshal(msg.Data, &req); err != nil { t.Fatalf("failed to unmarshal fsm req: %v", err) } n.responses = append(n.responses, req) case dkg_proposal_fsm.EventDKGMasterKeyConfirmationReceived: var req requests.DKGProposalMasterKeyConfirmationRequest - if err := json.Unmarshal(o.Result, &req); err != nil { + if err := json.Unmarshal(msg.Data, &req); err != nil { t.Fatalf("failed to unmarshal fsm req: %v", err) } n.masterKeys = append(n.masterKeys, req) default: - t.Fatalf("invalid event: %s", o.Event) + t.Fatalf("invalid event: %s", msg.Event) } } @@ -64,10 +66,10 @@ type Transport struct { nodes []*Node } -func (tr *Transport) BroadcastOperation(t *testing.T, operation client.Operation) { +func (tr *Transport) BroadcastMessage(t *testing.T, msg storage.Message) { for _, node := range tr.nodes { - if operation.To == "" || operation.To == node.Participant { - node.storeOperation(t, operation) + if msg.RecipientAddr == "" || msg.RecipientAddr == node.Participant { + node.storeOperation(t, msg) } } } @@ -81,7 +83,6 @@ func createOperation(t *testing.T, opType string, to string, req interface{}) cl ID: uuid.New().String(), Type: client.OperationType(opType), Payload: reqBz, - Result: nil, CreatedAt: time.Now(), DKGIdentifier: DKGIdentifier, To: to, @@ -90,7 +91,7 @@ func createOperation(t *testing.T, opType string, to string, req interface{}) cl } func TestAirgappedAllSteps(t *testing.T) { - nodesCount := 13 + nodesCount := 25 participants := make([]string, nodesCount) for i := 0; i < nodesCount; i++ { participants[i] = fmt.Sprintf("Participant#%d", i) @@ -147,12 +148,12 @@ func TestAirgappedAllSteps(t *testing.T) { runStep(tr, func(n *Node, wg *sync.WaitGroup) { defer wg.Done() - operations, err := n.Machine.HandleOperation(op) + operation, err := n.Machine.HandleOperation(op) if err != nil { t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err) } - for _, op := range operations { - tr.BroadcastOperation(t, op) + for _, msg := range operation.ResultMsgs { + tr.BroadcastMessage(t, msg) } }) @@ -171,12 +172,12 @@ func TestAirgappedAllSteps(t *testing.T) { } op := createOperation(t, string(dkg_proposal_fsm.StateDkgDealsAwaitConfirmations), "", payload) - operations, err := n.Machine.HandleOperation(op) + operation, err := n.Machine.HandleOperation(op) if err != nil { t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err) } - for _, op := range operations { - tr.BroadcastOperation(t, op) + for _, msg := range operation.ResultMsgs { + tr.BroadcastMessage(t, msg) } }) @@ -195,12 +196,12 @@ func TestAirgappedAllSteps(t *testing.T) { } op := createOperation(t, string(dkg_proposal_fsm.StateDkgResponsesAwaitConfirmations), "", payload) - operations, err := n.Machine.HandleOperation(op) + operation, err := n.Machine.HandleOperation(op) if err != nil { t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err) } - for _, op := range operations { - tr.BroadcastOperation(t, op) + for _, msg := range operation.ResultMsgs { + tr.BroadcastMessage(t, msg) } }) @@ -219,12 +220,12 @@ func TestAirgappedAllSteps(t *testing.T) { } op := createOperation(t, string(dkg_proposal_fsm.StateDkgMasterKeyAwaitConfirmations), "", payload) - operations, err := n.Machine.HandleOperation(op) + operation, err := n.Machine.HandleOperation(op) if err != nil { t.Fatalf("%s: failed to handle operation %s: %v", n.Participant, op.Type, err) } - for _, op := range operations { - tr.BroadcastOperation(t, op) + for _, msg := range operation.ResultMsgs { + tr.BroadcastMessage(t, msg) } }) diff --git a/airgapped/dkg.go b/airgapped/dkg.go index f7ce5b3..4800c61 100644 --- a/airgapped/dkg.go +++ b/airgapped/dkg.go @@ -9,11 +9,21 @@ import ( "github.com/depools/dc4bc/fsm/state_machines/signature_proposal_fsm" "github.com/depools/dc4bc/fsm/types/requests" "github.com/depools/dc4bc/fsm/types/responses" + "github.com/depools/dc4bc/storage" "go.dedis.ch/kyber/v3" "go.dedis.ch/kyber/v3/pairing/bn256" dkgPedersen "go.dedis.ch/kyber/v3/share/dkg/pedersen" ) +func createMessage(o client.Operation, data []byte) storage.Message { + return storage.Message{ + Event: string(o.Event), + Data: data, + DkgRoundID: o.DKGIdentifier, + RecipientAddr: o.To, + } +} + func (am *AirgappedMachine) handleStateAwaitParticipantsConfirmations(o *client.Operation) error { var ( payload responses.SignatureProposalParticipantInvitationsResponse @@ -53,9 +63,9 @@ func (am *AirgappedMachine) handleStateAwaitParticipantsConfirmations(o *client. if err != nil { return fmt.Errorf("failed to generate fsm request: %w", err) } - o.Result = reqBz - o.Event = signature_proposal_fsm.EventConfirmSignatureProposal + o.Event = signature_proposal_fsm.EventConfirmSignatureProposal + o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz)) return nil } @@ -114,13 +124,13 @@ func (am *AirgappedMachine) handleStateDkgCommitsAwaitConfirmations(o *client.Op if err != nil { return fmt.Errorf("failed to generate fsm request: %w", err) } - o.Result = reqBz + o.Event = dkg_proposal_fsm.EventDKGCommitConfirmationReceived + o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz)) return nil } -// We have many deals which should be sent privately to a required participant, so func returns a slice of operations -func (am *AirgappedMachine) handleStateDkgDealsAwaitConfirmations(o client.Operation) ([]client.Operation, error) { +func (am *AirgappedMachine) handleStateDkgDealsAwaitConfirmations(o *client.Operation) error { var ( payload responses.DKGProposalCommitParticipantResponse err error @@ -128,23 +138,23 @@ func (am *AirgappedMachine) handleStateDkgDealsAwaitConfirmations(o client.Opera dkgInstance, ok := am.dkgInstances[o.DKGIdentifier] if !ok { - return nil, fmt.Errorf("dkg instance with identifier %s does not exist", o.DKGIdentifier) + return fmt.Errorf("dkg instance with identifier %s does not exist", o.DKGIdentifier) } if err = json.Unmarshal(o.Payload, &payload); err != nil { - return nil, fmt.Errorf("failed to unmarshal payload: %w", err) + return fmt.Errorf("failed to unmarshal payload: %w", err) } for _, entry := range payload { var commitsBz [][]byte if err = json.Unmarshal(entry.DkgCommit, &commitsBz); err != nil { - return nil, fmt.Errorf("failed to unmarshal commits: %w", err) + return fmt.Errorf("failed to unmarshal commits: %w", err) } dkgCommits := make([]kyber.Point, 0, len(commitsBz)) for _, commitBz := range commitsBz { commit := am.suite.Point() if err = commit.UnmarshalBinary(commitBz); err != nil { - return nil, fmt.Errorf("failed to unmarshal commit: %w", err) + return fmt.Errorf("failed to unmarshal commit: %w", err) } dkgCommits = append(dkgCommits, commit) } @@ -153,23 +163,21 @@ func (am *AirgappedMachine) handleStateDkgDealsAwaitConfirmations(o client.Opera deals, err := dkgInstance.GetDeals() if err != nil { - return nil, fmt.Errorf("failed to get deals: %w", err) + return fmt.Errorf("failed to get deals: %w", err) } - operations := make([]client.Operation, 0, len(deals)) - am.dkgInstances[o.DKGIdentifier] = dkgInstance // deals variable is a map, so every key is an index of participant we should send a deal for index, deal := range deals { dealBz, err := json.Marshal(deal) if err != nil { - return nil, fmt.Errorf("failed to marshal deal: %w", err) + return fmt.Errorf("failed to marshal deal: %w", err) } toParticipant := dkgInstance.GetParticipantByIndex(index) encryptedDeal, err := am.encryptData(o.DKGIdentifier, toParticipant, dealBz) if err != nil { - return nil, fmt.Errorf("failed to encrypt deal: %w", err) + return fmt.Errorf("failed to encrypt deal: %w", err) } req := requests.DKGProposalDealConfirmationRequest{ ParticipantId: dkgInstance.ParticipantID, @@ -179,13 +187,12 @@ func (am *AirgappedMachine) handleStateDkgDealsAwaitConfirmations(o client.Opera o.To = toParticipant reqBz, err := json.Marshal(req) if err != nil { - return nil, fmt.Errorf("failed to generate fsm request: %w", err) + return fmt.Errorf("failed to generate fsm request: %w", err) } - o.Result = reqBz o.Event = dkg_proposal_fsm.EventDKGDealConfirmationReceived - operations = append(operations, o) + o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz)) } - return operations, nil + return nil } func (am *AirgappedMachine) handleStateDkgResponsesAwaitConfirmations(o *client.Operation) error { @@ -238,8 +245,8 @@ func (am *AirgappedMachine) handleStateDkgResponsesAwaitConfirmations(o *client. return fmt.Errorf("failed to generate fsm request: %w", err) } - o.Result = reqBz o.Event = dkg_proposal_fsm.EventDKGResponseConfirmationReceived + o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz)) return nil } @@ -301,8 +308,8 @@ func (am *AirgappedMachine) handleStateDkgMasterKeyAwaitConfirmations(o *client. return fmt.Errorf("failed to generate fsm request: %w", err) } - o.Result = reqBz o.Event = dkg_proposal_fsm.EventDKGMasterKeyConfirmationReceived + o.ResultMsgs = append(o.ResultMsgs, createMessage(*o, reqBz)) fmt.Println(dkgInstance.ParticipantID, pubKey.String()) diff --git a/client/client.go b/client/client.go index c49d5d7..0361019 100644 --- a/client/client.go +++ b/client/client.go @@ -118,19 +118,17 @@ func (c *Client) Poll() error { c.logger.Log("Got %d Operations from pool", len(operations)) for _, operation := range operations { c.logger.Log("Handling operation %s in airgapped", operation.Type) - processedOperations, err := c.Airgapped.HandleOperation(*operation) + processedOperation, err := c.Airgapped.HandleOperation(*operation) if err != nil { c.logger.Log("Failed to handle operation: %v", err) } c.logger.Log("Got %d Processed Operations from Airgapped", len(operations)) - for _, processedOperation := range processedOperations { - c.logger.Log("Operation %s handled in airgapped, result event is %s", operation.Event, processedOperation.Event) - if err = c.handleProcessedOperation(processedOperation); err != nil { - c.logger.Log("Failed to handle processed operation: %v", err) - } else { - c.logger.Log("Successfully handled processed operation %s", processedOperation.Event) - } + c.logger.Log("Operation %s handled in airgapped, result event is %s", operation.Event, processedOperation.Event) + if err = c.handleProcessedOperation(processedOperation); err != nil { + c.logger.Log("Failed to handle processed operation: %v", err) + } else { + c.logger.Log("Successfully handled processed operation %s", processedOperation.Event) } } case <-c.ctx.Done(): @@ -281,31 +279,27 @@ func (c *Client) ReadProcessedOperation() error { } func (c *Client) handleProcessedOperation(operation types.Operation) error { - //storedOperation, err := c.state.GetOperationByID(operation.ID) - //if err != nil { - // return fmt.Errorf("failed to find matching operation: %w", err) - //} - // - //if err := storedOperation.Check(&operation); err != nil { - // return fmt.Errorf("processed operation does not match stored operation: %w", err) - //} - - message := storage.Message{ - Event: string(operation.Event), - Data: operation.Result, - DkgRoundID: operation.DKGIdentifier, - SenderAddr: c.GetAddr(), - RecipientAddr: operation.To, - } - - sig, err := c.signMessage(message.Bytes()) + storedOperation, err := c.state.GetOperationByID(operation.ID) if err != nil { - return fmt.Errorf("failed to sign a message: %w", err) + return fmt.Errorf("failed to find matching operation: %w", err) } - message.Signature = sig - if _, err := c.storage.Send(message); err != nil { - return fmt.Errorf("failed to post message: %w", err) + if err := storedOperation.Check(&operation); err != nil { + return fmt.Errorf("processed operation does not match stored operation: %w", err) + } + + for _, message := range operation.ResultMsgs { + message.SenderAddr = c.GetAddr() + + sig, err := c.signMessage(message.Bytes()) + if err != nil { + return fmt.Errorf("failed to sign a message: %w", err) + } + message.Signature = sig + + if _, err := c.storage.Send(message); err != nil { + return fmt.Errorf("failed to post message: %w", err) + } } if err := c.state.DeleteOperation(operation.ID); err != nil { diff --git a/client/types/types.go b/client/types/types.go index 98123fb..20f89fc 100644 --- a/client/types/types.go +++ b/client/types/types.go @@ -23,7 +23,7 @@ type Operation struct { ID string // UUID4 Type OperationType Payload []byte - Result []byte + ResultMsgs []storage.Message CreatedAt time.Time DKGIdentifier string To string