diff --git a/etherpc/packages.go b/etherpc/packages.go new file mode 100644 index 0000000000..283da1a18f --- /dev/null +++ b/etherpc/packages.go @@ -0,0 +1,185 @@ +package main + +import ( + "encoding/json" + "errors" + "math/big" +) + +type MainPackage struct{} + +type JsonResponse interface { + requirements() error +} + +type BlockResponse struct { + Name string + Id int +} +type GetBlockArgs struct { + JsonResponse + BlockNumber int + Hash string +} + +type ErrorResponse struct { + Error bool + ErrorText string +} + +type SuccessRes struct { + Error bool + Message string +} + +func NewSuccessRes(msg string) string { + e := SuccessRes{Error: true, Message: msg} + res, err := json.Marshal(e) + if err != nil { + // This should never happen + panic("Creating json error response failed, help") + } + return string(res) +} + +func NewErrorResponse(msg string) error { + e := ErrorResponse{Error: true, ErrorText: msg} + res, err := json.Marshal(e) + if err != nil { + // This should never happen + panic("Creating json error response failed, help") + } + newErr := errors.New(string(res)) + return newErr +} + +func (b *GetBlockArgs) requirements() error { + if b.BlockNumber == 0 && b.Hash == "" { + return NewErrorResponse("This call requires either a block 'number' or a block 'hash' as argument") + } + return nil +} + +func (p *MainPackage) GetBlock(args *GetBlockArgs, reply *BlockResponse) error { + err := args.requirements() + if err != nil { + return err + } + // Do something + + return nil +} + +type NewTxArgs struct { + Sec string + Recipient string + Value *big.Int + Gas *big.Int + GasPrice *big.Int + Init string + Body string +} +type TxResponse struct { +} + +func (a *NewTxArgs) requirements() error { + if a.Recipient == "" { + return NewErrorResponse("Transact requires a 'recipient' address as argument") + } + if a.Value == nil { + return NewErrorResponse("Transact requires a 'value' as argument") + } + if a.Gas == nil { + return NewErrorResponse("Transact requires a 'gas' value as argument") + } + if a.GasPrice == nil { + return NewErrorResponse("Transact requires a 'gasprice' value as argument") + } + return nil +} + +func (a *NewTxArgs) requirementsContract() error { + if a.Value == nil { + return NewErrorResponse("Create requires a 'value' as argument") + } + if a.Gas == nil { + return NewErrorResponse("Create requires a 'gas' value as argument") + } + if a.GasPrice == nil { + return NewErrorResponse("Create requires a 'gasprice' value as argument") + } + if a.Init == "" { + return NewErrorResponse("Create requires a 'init' value as argument") + } + if a.Body == "" { + return NewErrorResponse("Create requires a 'body' value as argument") + } + return nil +} + +func (p *MainPackage) Transact(args *NewTxArgs, reply *TxResponse) error { + err := args.requirements() + if err != nil { + return err + } + return nil +} + +func (p *MainPackage) Create(args *NewTxArgs, reply *string) error { + err := args.requirementsContract() + if err != nil { + return err + } + return nil +} + +func (p *MainPackage) getKey(args interface{}, reply *string) error { + return nil +} + +type GetStorageArgs struct { + Address string + Key string +} + +func (a *GetStorageArgs) requirements() error { + if a.Address == "" { + return NewErrorResponse("GetStorageAt requires an 'address' value as argument") + } + if a.Key == "" { + return NewErrorResponse("GetStorageAt requires an 'key' value as argument") + } + return nil +} + +func (p *MainPackage) getStorageAt(args *GetStorageArgs, reply *string) error { + err := args.requirements() + if err != nil { + return err + } + return nil +} + +type GetBalanceArgs struct { + Address string +} + +func (a *GetBalanceArgs) requirements() error { + if a.Address == "" { + return NewErrorResponse("GetBalanceAt requires an 'address' value as argument") + } + return nil +} + +func (p *MainPackage) GetBalanceAt(args *GetBalanceArgs, reply *string) error { + err := args.requirements() + if err != nil { + return err + } + return nil +} + +func (p *MainPackage) Test(args *GetBlockArgs, reply *int) error { + *reply = 15 + return nil +} diff --git a/etherpc/server.go b/etherpc/server.go new file mode 100644 index 0000000000..291ca2d95b --- /dev/null +++ b/etherpc/server.go @@ -0,0 +1,82 @@ +package main + +import ( + "log" + "net" + "net/rpc" + "net/rpc/jsonrpc" +) + +type JsonRpcServer struct { + quit chan bool + listener net.Listener +} + +func (s *JsonRpcServer) exitHandler() { +out: + for { + select { + case <-s.quit: + s.listener.Close() + break out + } + } + + // ethutil.Config.Log.Infoln("[JSON] Shutdown JSON-RPC server") + log.Println("[JSON] Shutdown JSON-RPC server") +} + +func (s *JsonRpcServer) Stop() { + close(s.quit) +} + +func (s *JsonRpcServer) Start() { + // ethutil.Config.Log.Infoln("[JSON] Starting JSON-RPC server") + log.Println("[JSON] Starting JSON-RPC server") + go s.exitHandler() + rpc.Register(new(MainPackage)) + rpc.HandleHTTP() + + for { + conn, err := s.listener.Accept() + if err != nil { + // ethutil.Config.Log.Infoln("[JSON] Error starting JSON-RPC:", err) + log.Println("[JSON] Error starting JSON-RPC:", err) + continue + } + log.Println("Incoming request") + go jsonrpc.ServeConn(conn) + } +} + +func NewJsonRpcServer() *JsonRpcServer { + l, err := net.Listen("tcp", ":30304") + if err != nil { + // ethutil.Config.Log.Infoln("Error starting JSON-RPC") + log.Println("Error starting JSON-RPC") + } + + return &JsonRpcServer{ + listener: l, + quit: make(chan bool), + } +} + +func main() { + s := NewJsonRpcServer() + s.Start() + /* + + conn, err := net.Dial("tcp", "localhost:30304") + + if err != nil { + panic(err) + } + defer conn.Close() + c := jsonrpc.NewClient(conn) + var reply int + err = c.Call("MainPackage.Test", nil, &reply) + log.Println("ERR:", err) + log.Println("result:", reply) + */ +}