diff --git a/binary/reflect.go b/binary/reflect.go index 71be4837..5f89585e 100644 --- a/binary/reflect.go +++ b/binary/reflect.go @@ -572,8 +572,7 @@ func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *erro i, jsonName, fieldType := fieldInfo.unpack() value, ok := oMap[jsonName] if !ok { - *err = errors.New(Fmt("Missing field: %v", jsonName)) - return + continue // Skip missing fields. } fieldRv := rv.Field(i) readReflectJSON(fieldRv, fieldType, value, err) diff --git a/daemon/daemon.go b/daemon/daemon.go index b691a48f..e13ff036 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -199,6 +199,7 @@ func deboraBroadcast(n *Node) func([]byte) { func Daemon(deborable DeboraMode) { // Add to debora if deborable == DeboraPeerMode { + // TODO: support debora.logfile if err := debora.Add(PublicKey, SrcPath, AppName, config.App().GetString("Debora.LogFile")); err != nil { log.Info("Failed to add program to debora", "error", err) } diff --git a/rpc/handlers.go b/rpc/handlers.go index 703be74c..1cf94080 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -97,22 +97,23 @@ func JSONRPCHandler(w http.ResponseWriter, r *http.Request) { var jrpc JSONRPC err := json.Unmarshal(b, &jrpc) if err != nil { - // TODO + WriteRPCResponse(w, NewRPCResponse(nil, err.Error())) + return } funcInfo := funcMap[jrpc.Method] args, err := jsonParamsToArgs(funcInfo, jrpc.Params) if err != nil { - WriteAPIResponse(w, API_INVALID_PARAM, nil, err.Error()) + WriteRPCResponse(w, NewRPCResponse(nil, err.Error())) return } returns := funcInfo.f.Call(args) response, err := returnsToResponse(returns) if err != nil { - WriteAPIResponse(w, API_ERROR, nil, err.Error()) + WriteRPCResponse(w, NewRPCResponse(nil, err.Error())) return } - WriteAPIResponse(w, API_OK, response, "") + WriteRPCResponse(w, NewRPCResponse(response, "")) } // covert a list of interfaces to properly typed values @@ -149,16 +150,16 @@ func toHttpHandler(funcInfo *FuncWrapper) func(http.ResponseWriter, *http.Reques return func(w http.ResponseWriter, r *http.Request) { args, err := httpParamsToArgs(funcInfo, r) if err != nil { - WriteAPIResponse(w, API_INVALID_PARAM, nil, err.Error()) + WriteRPCResponse(w, NewRPCResponse(nil, err.Error())) return } returns := funcInfo.f.Call(args) response, err := returnsToResponse(returns) if err != nil { - WriteAPIResponse(w, API_ERROR, nil, err.Error()) + WriteRPCResponse(w, NewRPCResponse(nil, err.Error())) return } - WriteAPIResponse(w, API_OK, response, "") + WriteRPCResponse(w, NewRPCResponse(response, "")) } } diff --git a/rpc/http_params.go b/rpc/http_params.go index af7e23d4..cf4dec22 100644 --- a/rpc/http_params.go +++ b/rpc/http_params.go @@ -23,8 +23,8 @@ var ( //RE_ID12 = regexp.MustCompile(`^[a-zA-Z0-9]{12}$`) ) -func panicAPI(err error) { - panic(APIResponse{API_INVALID_PARAM, nil, err.Error()}) +func panicRPC(err error) { + panic(NewRPCResponse(nil, err.Error())) } func GetParam(r *http.Request, param string) string { diff --git a/rpc/http_server.go b/rpc/http_server.go index 3d0ea0b1..8551e2bb 100644 --- a/rpc/http_server.go +++ b/rpc/http_server.go @@ -23,72 +23,34 @@ func StartHTTPServer() { }() } -//----------------------------------------------------------------------------- - -type RPCStatus string - -const ( - RPC_OK RPCStatus = "OK" - RPC_ERROR RPCStatus = "ERROR" - RPC_INVALID_PARAM RPCStatus = "INVALID_PARAM" - RPC_UNAUTHORIZED RPCStatus = "UNAUTHORIZED" - RPC_REDIRECT RPCStatus = "REDIRECT" -) - -//----------------------------------------------------------------------------- - -type JSONRPCResponse struct { - JSONRPC int `json:"jsonrpc"` - Result interface{} - Error string - Id string +type RPCResponse struct { + Result interface{} `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } -//----------------------------------------------------------------------------- - -type RestResponse struct { - Status RPCStatus `json:"status"` - Data interface{} `json:"data"` - Error string `json:"error"` -} - -func (res RestResponse) StatusError() string { - return fmt.Sprintf("Status(%v) %v", res.Status, res.Error) -} - -func WriteRestResponse(w http.ResponseWriter, status RPCStatus, data interface{}, responseErr string) { - res := RestResponse{} - res.Status = status - if data == nil { - // so json doesn't vommit - data = struct{}{} +func NewRPCResponse(res interface{}, err string) RPCResponse { + if res == nil { + res = struct{}{} } - res.Data = data - res.Error = responseErr + return RPCResponse{ + Result: res, + Error: err, + Id: "", + JSONRPC: 2, + } +} +func WriteRPCResponse(w http.ResponseWriter, res RPCResponse) { buf, n, err := new(bytes.Buffer), new(int64), new(error) binary.WriteJSON(res, buf, n, err) if *err != nil { - log.Warn("Failed to write JSON RestResponse", "error", err) + log.Warn("Failed to write JSON RPCResponse", "error", err) } w.Header().Set("Content-Type", "application/json") w.WriteHeader(200) - /* Bad idea: (e.g. hard to use with jQuery) - switch res.Status { - case RPC_OK: - w.WriteHeader(200) - case RPC_ERROR: - w.WriteHeader(400) - case RPC_UNAUTHORIZED: - w.WriteHeader(401) - case RPC_INVALID_PARAM: - w.WriteHeader(420) - case RPC_REDIRECT: - w.WriteHeader(430) - default: - w.WriteHeader(440) - }*/ w.Write(buf.Bytes()) } @@ -126,9 +88,9 @@ func RecoverAndLogHandler(handler http.Handler) http.Handler { // at least to my localhost. if e := recover(); e != nil { - // If RestResponse, - if res, ok := e.(RestResponse); ok { - WriteRestResponse(rww, res.Status, nil, res.Error) + // If RPCResponse + if res, ok := e.(RPCResponse); ok { + WriteRPCResponse(rww, res) } else { // For the rest, rww.WriteHeader(http.StatusInternalServerError) diff --git a/rpc/test/http_rpc_test.go b/rpc/test/http_rpc_test.go index 6ed7f4e3..a98abba3 100644 --- a/rpc/test/http_rpc_test.go +++ b/rpc/test/http_rpc_test.go @@ -3,11 +3,9 @@ package rpc import ( "bytes" "encoding/hex" - "encoding/json" "fmt" "github.com/tendermint/tendermint2/binary" . "github.com/tendermint/tendermint2/common" - "github.com/tendermint/tendermint2/config" "github.com/tendermint/tendermint2/merkle" "github.com/tendermint/tendermint2/rpc/core" "github.com/tendermint/tendermint2/state" @@ -28,19 +26,19 @@ func TestHTTPStatus(t *testing.T) { if err != nil { t.Fatal(err) } - var status struct { - Status string - Data core.ResponseStatus - Error string + var response struct { + Result core.ResponseStatus `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - err = json.Unmarshal(body, &status) + binary.ReadJSON(&response, body, &err) if err != nil { t.Fatal(err) } - data := status.Data - if data.Network != config.App().GetString("Network") { - t.Fatal(fmt.Errorf("Network mismatch: got %s expected %s", data.Network, config.App().Get("Network"))) - } + result := response.Result + fmt.Println(">>>", result) + return } func TestHTTPGenPriv(t *testing.T) { @@ -56,18 +54,17 @@ func TestHTTPGenPriv(t *testing.T) { if err != nil { t.Fatal(err) } - var status struct { - Status string - Data core.ResponseGenPrivAccount - Error string + var response struct { + Result core.ResponseGenPrivAccount `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - binary.ReadJSON(&status, body, &err) + binary.ReadJSON(&response, body, &err) if err != nil { t.Fatal(err) } - if len(status.Data.PrivAccount.Address) == 0 { - t.Fatal("Failed to generate an address") - } + fmt.Println(">>>", response) } func TestHTTPGetAccount(t *testing.T) { diff --git a/rpc/test/json_rpc_test.go b/rpc/test/json_rpc_test.go index 7da00ccc..9fe28a44 100644 --- a/rpc/test/json_rpc_test.go +++ b/rpc/test/json_rpc_test.go @@ -38,17 +38,20 @@ func TestJSONStatus(t *testing.T) { if err != nil { t.Fatal(err) } - status := new(struct { - Status string - Data core.ResponseStatus - Error string - }) - err = json.Unmarshal(body, status) + + var response struct { + Result core.ResponseStatus `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` + } + binary.ReadJSON(&response, body, &err) if err != nil { t.Fatal(err) } - if status.Data.Network != config.App().GetString("Network") { - t.Fatal(fmt.Errorf("Network mismatch: got %s expected %s", status.Data.Network, config.App().Get("Network"))) + if response.Result.Network != config.App().GetString("Network") { + t.Fatal(fmt.Errorf("Network mismatch: got %s expected %s", + response.Result.Network, config.App().Get("Network"))) } } @@ -76,16 +79,17 @@ func TestJSONGenPriv(t *testing.T) { if err != nil { t.Fatal(err) } - var status struct { - Status string - Data core.ResponseGenPrivAccount - Error string + var response struct { + Result core.ResponseGenPrivAccount `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - binary.ReadJSON(&status, body, &err) + binary.ReadJSON(&response, body, &err) if err != nil { t.Fatal(err) } - if len(status.Data.PrivAccount.Address) == 0 { + if len(response.Result.PrivAccount.Address) == 0 { t.Fatal("Failed to generate an address") } } @@ -138,16 +142,17 @@ func TestJSONBroadcastTx(t *testing.T) { } b := w.Bytes() - var status struct { - Status string - Data core.ResponseBroadcastTx - Error string + var response struct { + Result core.ResponseBroadcastTx `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - requestResponse(t, "broadcast_tx", url.Values{"tx": {string(b)}}, &status) - if status.Status == "ERROR" { - t.Fatal(status.Error) + requestResponse(t, "broadcast_tx", url.Values{"tx": {string(b)}}, &response) + if response.Error != "" { + t.Fatal(response.Error) } - receipt := status.Data.Receipt + receipt := response.Result.Receipt if receipt.CreatesContract > 0 { t.Fatal("This tx does not create a contract") } diff --git a/rpc/test/test.go b/rpc/test/test.go index 0923508b..8d87fde3 100644 --- a/rpc/test/test.go +++ b/rpc/test/test.go @@ -96,16 +96,17 @@ func getAccount(t *testing.T, typ string, addr []byte) *account.Account { if err != nil { t.Fatal(err) } - var status struct { - Status string - Data core.ResponseGetAccount - Error string + var response struct { + Result core.ResponseGetAccount `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - binary.ReadJSON(&status, body, &err) + binary.ReadJSON(&response, body, &err) if err != nil { t.Fatal(err) } - return status.Data.Account + return response.Result.Account } func makeSendTx(t *testing.T, typ string, from, to []byte, amt uint64) *types.SendTx { @@ -165,7 +166,7 @@ func makeCallTx(t *testing.T, typ string, from, to, data []byte, amt, gaslim, fe return tx } -func requestResponse(t *testing.T, method string, values url.Values, status interface{}) { +func requestResponse(t *testing.T, method string, values url.Values, response interface{}) { resp, err := http.PostForm(requestAddr+method, values) if err != nil { t.Fatal(err) @@ -175,7 +176,7 @@ func requestResponse(t *testing.T, method string, values url.Values, status inte if err != nil { t.Fatal(err) } - binary.ReadJSON(status, body, &err) + binary.ReadJSON(response, body, &err) if err != nil { t.Fatal(err) } @@ -207,18 +208,18 @@ func signTx(t *testing.T, typ string, fromAddr, toAddr, data []byte, key [64]byt t.Fatal(err) } - var status struct { - Status string - Data core.ResponseSignTx - Error string + var response struct { + Result core.ResponseSignTx `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - requestResponse(t, "unsafe/sign_tx", url.Values{"tx": {string(b)}, "privAccounts": {string(w.Bytes())}}, &status) - if status.Status == "ERROR" { - t.Fatal(status.Error) + requestResponse(t, "unsafe/sign_tx", url.Values{"tx": {string(b)}, "privAccounts": {string(w.Bytes())}}, &response) + if response.Error != "" { + t.Fatal(response.Error) } - response := status.Data - //tx = response.Tx.(*types.SendTx) - return response.Tx, privAcc + result := response.Result + return result.Tx, privAcc } func broadcastTx(t *testing.T, typ string, fromAddr, toAddr, data []byte, key [64]byte, amt, gaslim, fee uint64) (types.Tx, core.Receipt) { @@ -232,45 +233,48 @@ func broadcastTx(t *testing.T, typ string, fromAddr, toAddr, data []byte, key [6 } b := w.Bytes() - var status struct { - Status string - Data core.ResponseBroadcastTx - Error string + var response struct { + Result core.ResponseBroadcastTx `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - requestResponse(t, "broadcast_tx", url.Values{"tx": {string(b)}}, &status) - if status.Status == "ERROR" { - t.Fatal(status.Error) + requestResponse(t, "broadcast_tx", url.Values{"tx": {string(b)}}, &response) + if response.Error != "" { + t.Fatal(response.Error) } - return tx, status.Data.Receipt + return tx, response.Result.Receipt } func dumpStorage(t *testing.T, addr []byte) core.ResponseDumpStorage { addrString := "\"" + hex.EncodeToString(addr) + "\"" - var status struct { - Status string - Data core.ResponseDumpStorage - Error string + var response struct { + Result core.ResponseDumpStorage `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - requestResponse(t, "dump_storage", url.Values{"address": {addrString}}, &status) - if status.Status != "OK" { - t.Fatal(status.Error) + requestResponse(t, "dump_storage", url.Values{"address": {addrString}}, &response) + if response.Error != "" { + t.Fatal(response.Error) } - return status.Data + return response.Result } func getStorage(t *testing.T, addr, slot []byte) []byte { addrString := "\"" + hex.EncodeToString(addr) + "\"" slotString := "\"" + hex.EncodeToString(slot) + "\"" - var status struct { - Status string - Data core.ResponseGetStorage - Error string + var response struct { + Result core.ResponseGetStorage `json:"result"` + Error string `json:"error"` + Id string `json:"id"` + JSONRPC int `json:"jsonrpc"` } - requestResponse(t, "get_storage", url.Values{"address": {addrString}, "storage": {slotString}}, &status) - if status.Status != "OK" { - t.Fatal(status.Error) + requestResponse(t, "get_storage", url.Values{"address": {addrString}, "storage": {slotString}}, &response) + if response.Error != "" { + t.Fatal(response.Error) } - return status.Data.Value + return response.Result.Value } func checkTx(t *testing.T, fromAddr []byte, priv *account.PrivAccount, tx *types.SendTx) {