diff --git a/airgapped/airgapped.go b/airgapped/airgapped.go index 1f44b3f..a6583b7 100644 --- a/airgapped/airgapped.go +++ b/airgapped/airgapped.go @@ -3,7 +3,7 @@ package airgapped import ( "encoding/json" "fmt" - "github.com/depools/dc4bc/client" + client "github.com/depools/dc4bc/client/types" "github.com/depools/dc4bc/dkg" "github.com/depools/dc4bc/fsm/fsm" "github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm" diff --git a/airgapped/airgapped_test.go b/airgapped/airgapped_test.go index aba96e4..6d9a9d3 100644 --- a/airgapped/airgapped_test.go +++ b/airgapped/airgapped_test.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/json" "fmt" - "github.com/depools/dc4bc/client" + client "github.com/depools/dc4bc/client/types" "github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm" "github.com/depools/dc4bc/fsm/types/requests" "github.com/depools/dc4bc/fsm/types/responses" @@ -138,7 +138,7 @@ func TestAirgappedAllSteps(t *testing.T) { } entry := &responses.SignatureProposalParticipantStatusEntry{ ParticipantId: n.ParticipantID, - Addr: n.Participant, + Addr: n.Participant, DkgPubKey: pubKey, } getCommitsRequest = append(getCommitsRequest, entry) diff --git a/airgapped/bls.go b/airgapped/bls.go index 2190800..d52f259 100644 --- a/airgapped/bls.go +++ b/airgapped/bls.go @@ -3,7 +3,7 @@ package airgapped import ( "encoding/json" "fmt" - "github.com/depools/dc4bc/client" + client "github.com/depools/dc4bc/client/types" "github.com/depools/dc4bc/fsm/state_machines/signing_proposal_fsm" "github.com/depools/dc4bc/fsm/types/requests" "github.com/depools/dc4bc/fsm/types/responses" diff --git a/airgapped/dkg.go b/airgapped/dkg.go index f89ea1e..9fe36ab 100644 --- a/airgapped/dkg.go +++ b/airgapped/dkg.go @@ -3,7 +3,7 @@ package airgapped import ( "encoding/json" "fmt" - "github.com/depools/dc4bc/client" + client "github.com/depools/dc4bc/client/types" "github.com/depools/dc4bc/dkg" "github.com/depools/dc4bc/fsm/state_machines/dkg_proposal_fsm" "github.com/depools/dc4bc/fsm/types/requests" diff --git a/client/client.go b/client/client.go index 04f9bbb..d91bc64 100644 --- a/client/client.go +++ b/client/client.go @@ -6,6 +6,8 @@ import ( "encoding/json" "errors" "fmt" + "github.com/depools/dc4bc/airgapped" + "github.com/depools/dc4bc/client/types" "log" "path/filepath" "sync" @@ -37,6 +39,7 @@ type Client struct { storage storage.Storage keyStore KeyStore qrProcessor qr.Processor + airgapped *airgapped.AirgappedMachine } func NewClient( @@ -46,6 +49,7 @@ func NewClient( storage storage.Storage, keyStore KeyStore, qrProcessor qr.Processor, + airgappedMachine *airgapped.AirgappedMachine, ) (*Client, error) { keyPair, err := keyStore.LoadKeys(userName, "") if err != nil { @@ -61,6 +65,7 @@ func NewClient( storage: storage, keyStore: keyStore, qrProcessor: qrProcessor, + airgapped: airgappedMachine, }, nil } @@ -92,6 +97,22 @@ func (c *Client) Poll() error { log.Println("Failed to process message:", err) } } + + operations, err := c.GetOperations() + if err != nil { + log.Println("Failed to get operations: %v", err) + } + for _, operation := range operations { + processedOperations, err := c.airgapped.HandleOperation(*operation) + if err != nil { + return fmt.Errorf("failed to process operation in airgapped: %w", err) + } + for _, po := range processedOperations { + if err = c.handleProcessedOperation(po); err != nil { + return fmt.Errorf("failed to handle processed operation") + } + } + } case <-c.ctx.Done(): log.Println("Context closed, stop polling...") return nil @@ -119,7 +140,7 @@ func (c *Client) ProcessMessage(message storage.Message) error { } } - fsmReq, err := FSMRequestFromMessage(message) + fsmReq, err := types.FSMRequestFromMessage(message) if err != nil { return fmt.Errorf("failed to get FSMRequestFromMessage: %v", err) } @@ -129,7 +150,7 @@ func (c *Client) ProcessMessage(message storage.Message) error { return fmt.Errorf("failed to Do operation in FSM: %w", err) } - var operation *Operation + var operation *types.Operation switch resp.State { // if the new state is waiting for RPC to airgapped machine case @@ -142,8 +163,8 @@ func (c *Client) ProcessMessage(message storage.Message) error { return fmt.Errorf("failed to marshal FSM response: %w", err) } - operation = &Operation{ - Type: OperationType(resp.State), + operation = &types.Operation{ + Type: types.OperationType(resp.State), Payload: bz, } default: @@ -167,7 +188,7 @@ func (c *Client) ProcessMessage(message storage.Message) error { return nil } -func (c *Client) GetOperations() (map[string]*Operation, error) { +func (c *Client) GetOperations() (map[string]*types.Operation, error) { return c.state.GetOperations() } @@ -210,7 +231,7 @@ func (c *Client) ReadProcessedOperation() error { return fmt.Errorf("failed to ReadQR: %s", err) } - var operation Operation + var operation types.Operation if err = json.Unmarshal(bz, &operation); err != nil { return fmt.Errorf("failed to unmarshal processed operation") } @@ -218,7 +239,7 @@ func (c *Client) ReadProcessedOperation() error { return c.handleProcessedOperation(operation) } -func (c *Client) handleProcessedOperation(operation Operation) 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) @@ -295,4 +316,4 @@ func (c *Client) verifyMessage(fsmInstance *state_machines.FSMInstance, message } return nil -} \ No newline at end of file +} diff --git a/client/client_test.go b/client/client_test.go index e8e36cc..1edd684 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -5,6 +5,7 @@ import ( "crypto/ed25519" "encoding/json" "errors" + "github.com/depools/dc4bc/client/types" "os" "path/filepath" "testing" @@ -48,6 +49,7 @@ func TestClient_ProcessMessage(t *testing.T) { stg, keyStore, qrProcessor, + nil, ) req.NoError(err) @@ -125,22 +127,23 @@ func TestClient_GetOperationsList(t *testing.T) { stg, keyStore, qrProcessor, + nil, ) req.NoError(err) - state.EXPECT().GetOperations().Times(1).Return(map[string]*client.Operation{}, nil) + state.EXPECT().GetOperations().Times(1).Return(map[string]*types.Operation{}, nil) operations, err := clt.GetOperations() req.NoError(err) req.Len(operations, 0) - operation := &client.Operation{ + operation := &types.Operation{ ID: "operation_id", - Type: client.DKGCommits, + Type: types.DKGCommits, Payload: []byte("operation_payload"), CreatedAt: time.Now(), } state.EXPECT().GetOperations().Times(1).Return( - map[string]*client.Operation{operation.ID: operation}, nil) + map[string]*types.Operation{operation.ID: operation}, nil) operations, err = clt.GetOperations() req.NoError(err) req.Len(operations, 1) @@ -167,12 +170,13 @@ func TestClient_GetOperationQRPath(t *testing.T) { stg, keyStore, qrProcessor, + nil, ) req.NoError(err) - operation := &client.Operation{ + operation := &types.Operation{ ID: "operation_id", - Type: client.DKGCommits, + Type: types.DKGCommits, Payload: []byte("operation_payload"), CreatedAt: time.Now(), } @@ -213,19 +217,20 @@ func TestClient_ReadProcessedOperation(t *testing.T) { stg, keyStore, qrProcessor, + nil, ) req.NoError(err) - operation := &client.Operation{ + operation := &types.Operation{ ID: "operation_id", - Type: client.DKGCommits, + Type: types.DKGCommits, Payload: []byte("operation_payload"), Result: []byte("operation_result"), CreatedAt: time.Now(), } - processedOperation := &client.Operation{ + processedOperation := &types.Operation{ ID: "operation_id", - Type: client.DKGCommits, + Type: types.DKGCommits, Payload: []byte("operation_payload"), Result: []byte("operation_result"), CreatedAt: time.Now(), diff --git a/client/http_server.go b/client/http_server.go index 560dfa4..f6782ea 100644 --- a/client/http_server.go +++ b/client/http_server.go @@ -3,6 +3,7 @@ package client import ( "encoding/json" "fmt" + "github.com/depools/dc4bc/client/types" "image" "io/ioutil" "log" @@ -168,7 +169,7 @@ func (c *Client) readProcessedOperationFromBodyHandler(w http.ResponseWriter, r return } - var operation Operation + var operation types.Operation if err = json.Unmarshal(qrData, &operation); err != nil { errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to unmarshal processed operation: %v", err)) diff --git a/client/state.go b/client/state.go index 7707b4e..c7b3ed8 100644 --- a/client/state.go +++ b/client/state.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/depools/dc4bc/client/types" "sync" "github.com/depools/dc4bc/fsm/state_machines" @@ -25,10 +26,10 @@ type State interface { SaveFSM(dkgRoundID string, dump []byte) error LoadFSM(dkgRoundID string) (*state_machines.FSMInstance, bool, error) - PutOperation(operation *Operation) error + PutOperation(operation *types.Operation) error DeleteOperation(operationID string) error - GetOperations() (map[string]*Operation, error) - GetOperationByID(operationID string) (*Operation, error) + GetOperations() (map[string]*types.Operation, error) + GetOperationByID(operationID string) (*types.Operation, error) } type LevelDBState struct { @@ -48,7 +49,7 @@ func NewLevelDBState(stateDbPath string) (State, error) { // Init state key for operations JSON. if _, err := state.stateDb.Get([]byte(operationsKey), nil); err != nil { - if err := state.initJsonKey(operationsKey, map[string]*Operation{}); err != nil { + if err := state.initJsonKey(operationsKey, map[string]*types.Operation{}); err != nil { return nil, fmt.Errorf("failed to init %s storage: %w", operationsKey, err) } } @@ -151,7 +152,7 @@ func (s *LevelDBState) LoadFSM(dkgRoundID string) (*state_machines.FSMInstance, return fsmInstance, ok, nil } -func (s *LevelDBState) PutOperation(operation *Operation) error { +func (s *LevelDBState) PutOperation(operation *types.Operation) error { s.Lock() defer s.Unlock() @@ -200,14 +201,14 @@ func (s *LevelDBState) DeleteOperation(operationID string) error { return nil } -func (s *LevelDBState) GetOperations() (map[string]*Operation, error) { +func (s *LevelDBState) GetOperations() (map[string]*types.Operation, error) { s.Lock() defer s.Unlock() return s.getOperations() } -func (s *LevelDBState) GetOperationByID(operationID string) (*Operation, error) { +func (s *LevelDBState) GetOperationByID(operationID string) (*types.Operation, error) { s.Lock() defer s.Unlock() @@ -224,13 +225,13 @@ func (s *LevelDBState) GetOperationByID(operationID string) (*Operation, error) return operation, nil } -func (s *LevelDBState) getOperations() (map[string]*Operation, error) { +func (s *LevelDBState) getOperations() (map[string]*types.Operation, error) { bz, err := s.stateDb.Get([]byte(operationsKey), nil) if err != nil { return nil, fmt.Errorf("failed to get Operations (key: %s): %w", operationsKey, err) } - var operations map[string]*Operation + var operations map[string]*types.Operation if err := json.Unmarshal(bz, &operations); err != nil { return nil, fmt.Errorf("failed to unmarshal Operations: %w", err) } diff --git a/client/state_test.go b/client/state_test.go index 018752e..0a4e83d 100644 --- a/client/state_test.go +++ b/client/state_test.go @@ -1,6 +1,7 @@ package client_test import ( + "github.com/depools/dc4bc/client/types" "os" "testing" "time" @@ -38,9 +39,9 @@ func TestLevelDBState_PutOperation(t *testing.T) { stg, err := client.NewLevelDBState(dbPath) req.NoError(err) - operation := &client.Operation{ + operation := &types.Operation{ ID: "operation_id", - Type: client.DKGCommits, + Type: types.DKGCommits, Payload: []byte("operation_payload"), Result: []byte("operation_result"), CreatedAt: time.Now(), @@ -69,9 +70,9 @@ func TestLevelDBState_GetOperations(t *testing.T) { stg, err := client.NewLevelDBState(dbPath) req.NoError(err) - operation := &client.Operation{ + operation := &types.Operation{ ID: "operation_1", - Type: client.DKGCommits, + Type: types.DKGCommits, Payload: []byte("operation_payload"), Result: []byte("operation_result"), CreatedAt: time.Now(), @@ -98,9 +99,9 @@ func TestLevelDBState_DeleteOperation(t *testing.T) { stg, err := client.NewLevelDBState(dbPath) req.NoError(err) - operation := &client.Operation{ + operation := &types.Operation{ ID: "operation_id", - Type: client.DKGCommits, + Type: types.DKGCommits, Payload: []byte("operation_payload"), Result: []byte("operation_result"), CreatedAt: time.Now(), diff --git a/client/types.go b/client/types/types.go similarity index 99% rename from client/types.go rename to client/types/types.go index b3ca95c..30eca3c 100644 --- a/client/types.go +++ b/client/types/types.go @@ -1,4 +1,4 @@ -package client +package types import ( "bytes" diff --git a/main.go b/main.go index 4353091..1114c8b 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "crypto/md5" "encoding/json" "fmt" + "github.com/depools/dc4bc/airgapped" _ "image/jpeg" "log" "sync" @@ -65,6 +66,11 @@ func main() { log.Fatalf("Failed to PutKeys: %v\n", err) } + airgappedMachine, err := airgapped.NewAirgappedMachine(fmt.Sprintf("/tmp/dc4bc_node_%d_airgapped_db", nodeID)) + if err != nil { + log.Fatalf("Failed to create airgapped machine: %v", err) + } + clt, err := client.NewClient( ctx, userName, @@ -72,6 +78,7 @@ func main() { stg, keyStore, qr.NewCameraProcessor(), + airgappedMachine, ) if err != nil { log.Fatalf("node %d failed to init client: %v\n", nodeID, err) diff --git a/mocks/clientMocks/keystore_mock.go b/mocks/clientMocks/keystore_mock.go index 11a4de1..ad3c39c 100644 --- a/mocks/clientMocks/keystore_mock.go +++ b/mocks/clientMocks/keystore_mock.go @@ -33,6 +33,10 @@ func (m *MockKeyStore) EXPECT() *MockKeyStoreMockRecorder { return m.recorder } +func (mr *MockKeyStore) PutKeys(userName string, keyPair *client.KeyPair) error { + return nil +} + // LoadKeys mocks base method func (m *MockKeyStore) LoadKeys(userName, password string) (*client.KeyPair, error) { m.ctrl.T.Helper()