diff --git a/api/proto/message/client.go b/api/proto/message/client.go index 2ae9a817e..ed012f0b6 100644 --- a/api/proto/message/client.go +++ b/api/proto/message/client.go @@ -37,12 +37,9 @@ func (client *Client) Close() { } // Process processes message. -func (client *Client) Process(message *Message) *Response { +func (client *Client) Process(message *Message) (*Response, error) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() response, err := client.clientServiceClient.Process(ctx, message) - if err != nil { - log.Fatalf("Getting error when processing message: %s", err) - } - return response + return response, err } diff --git a/api/proto/message/client_test.go b/api/proto/message/client_test.go index 605717f03..aa1c4bf55 100644 --- a/api/proto/message/client_test.go +++ b/api/proto/message/client_test.go @@ -9,10 +9,13 @@ const ( ) func TestClient(t *testing.T) { - s := NewServer() + s := NewServer(nil, nil) s.Start() client := NewClient(testIP) - client.Process(&Message{}) + _, err := client.Process(&Message{}) + if err == nil { + t.Errorf("Not expected.") + } s.Stop() } diff --git a/api/proto/message/errors.go b/api/proto/message/errors.go new file mode 100644 index 000000000..4e08acad3 --- /dev/null +++ b/api/proto/message/errors.go @@ -0,0 +1,11 @@ +package message + +import "errors" + +// Error of host package +var ( + ErrWrongMessage = errors.New("Error as receiving wrong message") + ErrEnterMethod = errors.New("Error when processing enter method") + ErrResultMethod = errors.New("Error when processing result/getPlayers method") + ErrEnterProcessorNotReady = errors.New("Error because enter processor is not ready") +) diff --git a/api/proto/message/message.pb.go b/api/proto/message/message.pb.go index 96e9f9687..e7f1298f2 100644 --- a/api/proto/message/message.pb.go +++ b/api/proto/message/message.pb.go @@ -6,9 +6,10 @@ package message import ( context "context" fmt "fmt" + math "math" + proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" - math "math" ) // Reference imports to suppress errors if they are not otherwise used. @@ -23,13 +24,15 @@ var _ = math.Inf const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package // ReceiverType indicates who is the receiver of this message. +// TODO(minhdoan): Why LEADER_OR_VALIDATOR, think of a better design. type ReceiverType int32 const ( - ReceiverType_NEWNODE ReceiverType = 0 - ReceiverType_LEADER ReceiverType = 1 - ReceiverType_VALIDATOR ReceiverType = 2 - ReceiverType_CLIENT ReceiverType = 3 + ReceiverType_NEWNODE ReceiverType = 0 + ReceiverType_LEADER ReceiverType = 1 + ReceiverType_VALIDATOR ReceiverType = 2 + ReceiverType_CLIENT ReceiverType = 3 + ReceiverType_LEADER_OR_VALIDATOR ReceiverType = 4 ) var ReceiverType_name = map[int32]string{ @@ -37,13 +40,15 @@ var ReceiverType_name = map[int32]string{ 1: "LEADER", 2: "VALIDATOR", 3: "CLIENT", + 4: "LEADER_OR_VALIDATOR", } var ReceiverType_value = map[string]int32{ - "NEWNODE": 0, - "LEADER": 1, - "VALIDATOR": 2, - "CLIENT": 3, + "NEWNODE": 0, + "LEADER": 1, + "VALIDATOR": 2, + "CLIENT": 3, + "LEADER_OR_VALIDATOR": 4, } func (x ReceiverType) String() string { @@ -58,21 +63,24 @@ func (ReceiverType) EnumDescriptor() ([]byte, []int) { type ServiceType int32 const ( - ServiceType_CONSENSUS ServiceType = 0 - ServiceType_STAKING ServiceType = 1 - ServiceType_DRAND ServiceType = 2 + ServiceType_CONSENSUS ServiceType = 0 + ServiceType_STAKING ServiceType = 1 + ServiceType_DRAND ServiceType = 2 + ServiceType_CLIENT_SUPPORT ServiceType = 3 ) var ServiceType_name = map[int32]string{ 0: "CONSENSUS", 1: "STAKING", 2: "DRAND", + 3: "CLIENT_SUPPORT", } var ServiceType_value = map[string]int32{ - "CONSENSUS": 0, - "STAKING": 1, - "DRAND": 2, + "CONSENSUS": 0, + "STAKING": 1, + "DRAND": 2, + "CLIENT_SUPPORT": 3, } func (x ServiceType) String() string { @@ -95,6 +103,7 @@ const ( MessageType_COMMITTED MessageType = 5 MessageType_DRAND_INIT MessageType = 6 MessageType_DRAND_COMMIT MessageType = 7 + MessageType_LOTTERY_REQUEST MessageType = 8 ) var MessageType_name = map[int32]string{ @@ -106,6 +115,7 @@ var MessageType_name = map[int32]string{ 5: "COMMITTED", 6: "DRAND_INIT", 7: "DRAND_COMMIT", + 8: "LOTTERY_REQUEST", } var MessageType_value = map[string]int32{ @@ -117,6 +127,7 @@ var MessageType_value = map[string]int32{ "COMMITTED": 5, "DRAND_INIT": 6, "DRAND_COMMIT": 7, + "LOTTERY_REQUEST": 8, } func (x MessageType) String() string { @@ -389,7 +400,7 @@ func (*Response) XXX_OneofWrappers() []interface{} { } type LotteryResponse struct { - Players []string `protobuf:"bytes,1,rep,name=players,proto3" json:"players,omitempty"` + Players []string `protobuf:"bytes,2,rep,name=players,proto3" json:"players,omitempty"` Balances []uint64 `protobuf:"varint,3,rep,packed,name=balances,proto3" json:"balances,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -438,6 +449,7 @@ func (m *LotteryResponse) GetBalances() []uint64 { type LotteryRequest struct { Type LotteryRequest_Type `protobuf:"varint,1,opt,name=type,proto3,enum=message.LotteryRequest_Type" json:"type,omitempty"` PrivateKey string `protobuf:"bytes,2,opt,name=private_key,json=privateKey,proto3" json:"private_key,omitempty"` + Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -482,6 +494,13 @@ func (m *LotteryRequest) GetPrivateKey() string { return "" } +func (m *LotteryRequest) GetAmount() int64 { + if m != nil { + return m.Amount + } + return 0 +} + // Staking Request from new node to beacon node. type StakingRequest struct { Transaction []byte `protobuf:"bytes,1,opt,name=transaction,proto3" json:"transaction,omitempty"` diff --git a/api/proto/message/message.proto b/api/proto/message/message.proto index 9ec1f66e7..cc3440dfe 100644 --- a/api/proto/message/message.proto +++ b/api/proto/message/message.proto @@ -8,11 +8,13 @@ service ClientService { } // ReceiverType indicates who is the receiver of this message. +// TODO(minhdoan): Why LEADER_OR_VALIDATOR, think of a better design. enum ReceiverType { NEWNODE = 0; LEADER = 1; VALIDATOR = 2; CLIENT = 3; + LEADER_OR_VALIDATOR = 4; } // ServiceType indicates which service used to generate this message. @@ -20,6 +22,7 @@ enum ServiceType { CONSENSUS = 0; STAKING = 1; DRAND = 2; + CLIENT_SUPPORT = 3; } // MessageType indicates what is the type of this message. @@ -32,6 +35,7 @@ enum MessageType { COMMITTED = 5; DRAND_INIT = 6; DRAND_COMMIT = 7; + LOTTERY_REQUEST = 8; // it should be either ENTER or GETPLAYERS but it will be removed later. } // This is universal message for all communication protocols. @@ -63,7 +67,7 @@ message Response { } message LotteryResponse { - repeated string players = 1; + repeated string players = 2; repeated uint64 balances = 3; } @@ -74,6 +78,7 @@ message LotteryRequest { } Type type = 1; string private_key = 2; + int64 amount = 3; } // Staking Request from new node to beacon node. diff --git a/api/proto/message/server.go b/api/proto/message/server.go index 95dcf4f3a..0506391a5 100644 --- a/api/proto/message/server.go +++ b/api/proto/message/server.go @@ -4,7 +4,7 @@ package message // This client service will use unified Message. // TODO(minhdoan): Refactor and clean up the other client service. import ( - context "context" + "context" "log" "net" @@ -19,11 +19,35 @@ const ( // Server is the Server struct for client service package. type Server struct { - server *grpc.Server + server *grpc.Server + CreateTransactionForEnterMethod func(int64, string) error + GetResult func() ([]string, []uint64) } // Process processes the Message and returns Response func (s *Server) Process(ctx context.Context, message *Message) (*Response, error) { + if message.GetType() != MessageType_LOTTERY_REQUEST { + return &Response{}, ErrWrongMessage + } + lotteryRequest := message.GetLotteryRequest() + if lotteryRequest.GetType() == LotteryRequest_ENTER { + if s.CreateTransactionForEnterMethod == nil { + return nil, ErrEnterProcessorNotReady + } + amount := lotteryRequest.Amount + priKey := lotteryRequest.PrivateKey + if err := s.CreateTransactionForEnterMethod(amount, priKey); err != nil { + return nil, ErrEnterMethod + } + return &Response{}, nil + + } else if lotteryRequest.GetType() == LotteryRequest_RESULT { + // if err := s.GetResult(); err != nil { + // return &Response{}, ErrResultMethod + // } else { + // return &Response{}, nil + // } + } return &Response{}, nil } @@ -47,6 +71,11 @@ func (s *Server) Stop() { } // NewServer creates new Server which implements ClientServiceServer interface. -func NewServer() *Server { - return &Server{} +func NewServer( + CreateTransactionForEnterMethod func(int64, string) error, + GetResult func() ([]string, []uint64)) *Server { + return &Server{ + CreateTransactionForEnterMethod: CreateTransactionForEnterMethod, + GetResult: GetResult, + } } diff --git a/api/proto/message/server_test.go b/api/proto/message/server_test.go index 342249352..ec3e616cf 100644 --- a/api/proto/message/server_test.go +++ b/api/proto/message/server_test.go @@ -6,7 +6,7 @@ import ( ) func TestServerStart(t *testing.T) { - s := NewServer() + s := NewServer(nil, nil) s.Start() time.Sleep(time.Second) s.Stop() diff --git a/api/service/newclientsupport/service.go b/api/service/newclientsupport/service.go index 54a47625e..1f31bb575 100644 --- a/api/service/newclientsupport/service.go +++ b/api/service/newclientsupport/service.go @@ -11,8 +11,13 @@ type Service struct { } // New returns new client support service. -func New() *Service { - return &Service{server: msg_pb.NewServer()} +func New( + CreateTransactionForEnterMethod func(int64, string) error, + GetResult func() ([]string, []uint64), +) *Service { + return &Service{ + server: msg_pb.NewServer(CreateTransactionForEnterMethod, GetResult), + } } // StartService starts client support service. diff --git a/node/demo_contract.go b/node/demo_contract.go index 3e6842a4d..076f3350e 100644 --- a/node/demo_contract.go +++ b/node/demo_contract.go @@ -47,17 +47,19 @@ func (node *Node) AddLotteryContract() { } // CreateTransactionForEnterMethod generates transaction for enter method and add it into pending tx list. -func (node *Node) CreateTransactionForEnterMethod(amount int64, priKey string) { +func (node *Node) CreateTransactionForEnterMethod(amount int64, priKey string) error { var err error toAddress := node.DemoContractAddress abi, err := abi.JSON(strings.NewReader(contracts.LotteryABI)) if err != nil { utils.GetLogInstance().Error("Failed to generate staking contract's ABI", "error", err) + return err } bytesData, err := abi.Pack(Enter) if err != nil { utils.GetLogInstance().Error("Failed to generate ABI function bytes data", "error", err) + return err } key, err := crypto.HexToECDSA(priKey) @@ -74,10 +76,17 @@ func (node *Node) CreateTransactionForEnterMethod(amount int64, priKey string) { if err != nil { utils.GetLogInstance().Error("Failed to get private key", "error", err) + return err } if signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, key); err == nil { node.addPendingTransactions(types.Transactions{signedTx}) - } else { - utils.GetLogInstance().Error("Unable to call enter method", "error", err) + return nil } + utils.GetLogInstance().Error("Unable to call enter method", "error", err) + return err +} + +// GetResult get current players and their balances. +func (node *Node) GetResult() (players []string, balances []uint64) { + return []string{}, []uint64{} } diff --git a/node/service_setup.go b/node/service_setup.go index c33da5bac..0daa120ee 100644 --- a/node/service_setup.go +++ b/node/service_setup.go @@ -63,7 +63,8 @@ func (node *Node) setupForBeaconLeader() { node.serviceManager.RegisterService(service.ClientSupport, clientsupport.New(node.blockchain.State, node.CallFaucetContract, node.getDeployedStakingContract, node.SelfPeer.IP, node.SelfPeer.Port)) // TODO(minhdoan): We will remove the old client support and use the new client support which uses new message protocol. // Register client new support service. - node.serviceManager.RegisterService(service.NewClientSupport, newclientsupport.New()) + node.serviceManager.RegisterService(service.NewClientSupport, newclientsupport.New( + node.CreateTransactionForEnterMethod, node.GetResult)) // Register randomness service node.serviceManager.RegisterService(service.Randomness, randomness.New(node.DRand)) // Register explorer service.