When using JSONRPC, do not double-encode JSON.
This commit is contained in:
parent
ffa82b5c61
commit
1a4aab4c35
|
@ -25,19 +25,23 @@ func WriteBinary(o interface{}, w io.Writer, n *int64, err *error) {
|
|||
}
|
||||
|
||||
func ReadJSON(o interface{}, bytes []byte, err *error) interface{} {
|
||||
var parsed interface{}
|
||||
*err = json.Unmarshal(bytes, &parsed)
|
||||
var object interface{}
|
||||
*err = json.Unmarshal(bytes, &object)
|
||||
if *err != nil {
|
||||
return o
|
||||
}
|
||||
|
||||
return ReadJSONFromObject(o, object, err)
|
||||
}
|
||||
|
||||
func ReadJSONFromObject(o interface{}, object interface{}, err *error) interface{} {
|
||||
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
|
||||
if rv.Kind() == reflect.Ptr {
|
||||
readReflectJSON(rv.Elem(), rt.Elem(), parsed, err)
|
||||
readReflectJSON(rv.Elem(), rt.Elem(), object, err)
|
||||
return o
|
||||
} else {
|
||||
ptrRv := reflect.New(rt)
|
||||
readReflectJSON(ptrRv.Elem(), rt, parsed, err)
|
||||
readReflectJSON(ptrRv.Elem(), rt, object, err)
|
||||
return ptrRv.Elem().Interface()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -237,7 +237,7 @@ func DecodeMessage(bz []byte) (msg interface{}, err error) {
|
|||
}
|
||||
|
||||
/*
|
||||
A pexHandshakeMessage contains the peer's chainId
|
||||
A pexHandshakeMessage contains the network identifier.
|
||||
*/
|
||||
type pexHandshakeMessage struct {
|
||||
Network string
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/tendermint/tendermint/binary"
|
||||
|
@ -9,7 +8,6 @@ import (
|
|||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// cache all type information about each function up front
|
||||
|
@ -66,71 +64,24 @@ func toHandler(funcName string) func(http.ResponseWriter, *http.Request) {
|
|||
|
||||
// convert a (json) string to a given type
|
||||
func jsonToArg(ty reflect.Type, arg string) (reflect.Value, error) {
|
||||
v := reflect.New(ty).Elem()
|
||||
kind := v.Kind()
|
||||
var err error
|
||||
switch kind {
|
||||
case reflect.Interface:
|
||||
v = reflect.New(ty)
|
||||
v := reflect.New(ty)
|
||||
binary.ReadJSON(v.Interface(), []byte(arg), &err)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v = v.Elem()
|
||||
case reflect.Struct:
|
||||
binary.ReadJSON(v.Interface(), []byte(arg), &err)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
case reflect.Slice:
|
||||
rt := ty.Elem()
|
||||
if rt.Kind() == reflect.Uint8 {
|
||||
// if hex, decode
|
||||
if len(arg) > 2 && arg[:2] == "0x" {
|
||||
arg = arg[2:]
|
||||
b, err := hex.DecodeString(arg)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v = reflect.ValueOf(b)
|
||||
} else {
|
||||
v = reflect.ValueOf([]byte(arg))
|
||||
}
|
||||
} else {
|
||||
v = reflect.New(ty)
|
||||
binary.ReadJSON(v.Interface(), []byte(arg), &err)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func jsonObjectToArg(ty reflect.Type, object interface{}) (reflect.Value, error) {
|
||||
var err error
|
||||
v := reflect.New(ty)
|
||||
binary.ReadJSONFromObject(v.Interface(), object, &err)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
case reflect.Int64:
|
||||
u, err := strconv.ParseInt(arg, 10, 64)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v = reflect.ValueOf(u)
|
||||
case reflect.Int32:
|
||||
u, err := strconv.ParseInt(arg, 10, 32)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v = reflect.ValueOf(u)
|
||||
case reflect.Uint64:
|
||||
u, err := strconv.ParseUint(arg, 10, 64)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v = reflect.ValueOf(u)
|
||||
case reflect.Uint:
|
||||
u, err := strconv.ParseUint(arg, 10, 32)
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v = reflect.ValueOf(u)
|
||||
default:
|
||||
v = reflect.ValueOf(arg)
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
|
@ -145,6 +96,7 @@ func queryToValues(funcInfo *FuncWrapper, r *http.Request) ([]reflect.Value, err
|
|||
for i, name := range argNames {
|
||||
ty := argTypes[i]
|
||||
arg := GetParam(r, name)
|
||||
//fmt.Println("GetParam()", r, name, arg)
|
||||
values[i], err = jsonToArg(ty, arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -154,12 +106,11 @@ func queryToValues(funcInfo *FuncWrapper, r *http.Request) ([]reflect.Value, err
|
|||
}
|
||||
|
||||
// covert a list of interfaces to properly typed values
|
||||
// TODO!
|
||||
func paramsToValues(funcInfo *FuncWrapper, params []string) ([]reflect.Value, error) {
|
||||
func paramsToValues(funcInfo *FuncWrapper, params []interface{}) ([]reflect.Value, error) {
|
||||
values := make([]reflect.Value, len(params))
|
||||
for i, p := range params {
|
||||
ty := funcInfo.args[i]
|
||||
v, err := jsonToArg(ty, p)
|
||||
v, err := jsonObjectToArg(ty, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -251,7 +202,7 @@ func initHandlers() {
|
|||
type JsonRpc struct {
|
||||
JsonRpc string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
Params []string `json:"params"`
|
||||
Params []interface{} `json:"params"`
|
||||
Id int `json:"id"`
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,9 @@ func TestHTTPGenPriv(t *testing.T) {
|
|||
func TestHTTPGetAccount(t *testing.T) {
|
||||
byteAddr, _ := hex.DecodeString(userAddr)
|
||||
acc := getAccount(t, "HTTP", byteAddr)
|
||||
if acc == nil {
|
||||
t.Fatalf("Account was nil")
|
||||
}
|
||||
if bytes.Compare(acc.Address, byteAddr) != 0 {
|
||||
t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, byteAddr)
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func TestJSONStatus(t *testing.T) {
|
|||
s := rpc.JsonRpc{
|
||||
JsonRpc: "2.0",
|
||||
Method: "status",
|
||||
Params: []string{},
|
||||
Params: []interface{}{},
|
||||
Id: 0,
|
||||
}
|
||||
b, err := json.Marshal(s)
|
||||
|
@ -56,7 +56,7 @@ func TestJSONGenPriv(t *testing.T) {
|
|||
s := rpc.JsonRpc{
|
||||
JsonRpc: "2.0",
|
||||
Method: "unsafe/gen_priv_account",
|
||||
Params: []string{},
|
||||
Params: []interface{}{},
|
||||
Id: 0,
|
||||
}
|
||||
b, err := json.Marshal(s)
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/tendermint/tendermint/account"
|
||||
"github.com/tendermint/tendermint/binary"
|
||||
"github.com/tendermint/tendermint/config"
|
||||
|
@ -24,8 +23,6 @@ var (
|
|||
rpcAddr = "127.0.0.1:8089"
|
||||
requestAddr = "http://" + rpcAddr + "/"
|
||||
|
||||
chainId string
|
||||
|
||||
node *daemon.Node
|
||||
|
||||
mempoolCount = 0
|
||||
|
@ -78,7 +75,7 @@ func getAccount(t *testing.T, typ string, addr []byte) *account.Account {
|
|||
s := rpc.JsonRpc{
|
||||
JsonRpc: "2.0",
|
||||
Method: "get_account",
|
||||
Params: []string{"0x" + hex.EncodeToString(addr)},
|
||||
Params: []interface{}{hex.EncodeToString(addr)},
|
||||
Id: 0,
|
||||
}
|
||||
b, err := json.Marshal(s)
|
||||
|
@ -89,9 +86,8 @@ func getAccount(t *testing.T, typ string, addr []byte) *account.Account {
|
|||
resp, err = http.Post(requestAddr, "text/json", buf)
|
||||
case "HTTP":
|
||||
resp, err = http.PostForm(requestAddr+"get_account",
|
||||
url.Values{"address": {string(addr)}})
|
||||
url.Values{"address": {"\"" + (hex.EncodeToString(addr)) + "\""}})
|
||||
}
|
||||
fmt.Println("RESPONSE:", resp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -105,7 +101,6 @@ func getAccount(t *testing.T, typ string, addr []byte) *account.Account {
|
|||
Data core.ResponseGetAccount
|
||||
Error string
|
||||
}
|
||||
fmt.Println(string(body))
|
||||
binary.ReadJSON(&status, body, &err)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -153,7 +148,6 @@ func requestResponse(t *testing.T, method string, values url.Values, status inte
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(body))
|
||||
binary.ReadJSON(status, body, &err)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -206,7 +200,6 @@ func checkTx(t *testing.T, fromAddr []byte, priv *account.PrivAccount, tx *types
|
|||
if err := in.ValidateBasic(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fmt.Println(priv.PubKey, in.PubKey)
|
||||
// Check signatures
|
||||
// acc := getAccount(t, byteAddr)
|
||||
// NOTE: using the acc here instead of the in fails; its PubKeyNil ... ?
|
||||
|
|
Loading…
Reference in New Issue