From 4956836f2daa844814eadffa6e4aa2c80ca2a7c7 Mon Sep 17 00:00:00 2001 From: Ethan Buchman Date: Thu, 2 Apr 2015 03:06:46 -0700 Subject: [PATCH] rpc: cleanup, use client for tests, rpc-gen fixes --- rpc/client.go | 74 +++------------ rpc/client_methods.go | 84 +++++++++-------- rpc/core/accounts.go | 10 +- rpc/handlers.go | 20 ++++ rpc/test/http_rpc_test.go | 54 ++--------- rpc/test/test.go | 190 +++++++++++++------------------------- 6 files changed, 155 insertions(+), 277 deletions(-) diff --git a/rpc/client.go b/rpc/client.go index 19b32a9b..242dffa1 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -7,7 +7,7 @@ import ( "io/ioutil" "net/http" "net/url" - "reflect" + //"reflect" // Uncomment to use go:generate // _ "github.com/ebuchman/go-rpc-gen" ) @@ -38,67 +38,21 @@ func NewClient(addr, typ string) Client { return nil } -func argsToJson(args ...interface{}) ([][]string, error) { +func argsToJson(args ...interface{}) ([]string, error) { l := len(args) - jsons := make([][]string, l) + jsons := make([]string, l) n, err := new(int64), new(error) for i, a := range args { - //if its a slice, we serliaze separately and pack into a slice of strings - // otherwise its a slice of length 1 - if v := reflect.ValueOf(a); v.Kind() == reflect.Slice { - ty := v.Type() - rt := ty.Elem() - if rt.Kind() == reflect.Uint8 { - buf := new(bytes.Buffer) - binary.WriteJSON(a, buf, n, err) - if *err != nil { - return nil, *err - } - jsons[i] = []string{string(buf.Bytes())} - } else { - slice := make([]string, v.Len()) - for j := 0; j < v.Len(); j++ { - buf := new(bytes.Buffer) - binary.WriteJSON(v.Index(j).Interface(), buf, n, err) - if *err != nil { - return nil, *err - } - slice[j] = string(buf.Bytes()) - } - jsons[i] = slice - } - } else { - buf := new(bytes.Buffer) - binary.WriteJSON(a, buf, n, err) - if *err != nil { - return nil, *err - } - jsons[i] = []string{string(buf.Bytes())} + buf := new(bytes.Buffer) + binary.WriteJSON(a, buf, n, err) + if *err != nil { + return nil, *err } + jsons[i] = string(buf.Bytes()) } return jsons, nil } -func (c *ClientHTTP) RequestResponse(method string, values url.Values) (*Response, error) { - resp, err := http.PostForm(c.addr+method, values) - if err != nil { - return nil, err - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - response := new(Response) - fmt.Println(string(body)) - binary.ReadJSON(response, body, &err) - if err != nil { - return nil, err - } - fmt.Println(response.Data) - return response, nil -} - func (c *ClientJSON) RequestResponse(s RPCRequest) (b []byte, err error) { b = binary.JSONBytes(s) buf := bytes.NewBuffer(b) @@ -153,10 +107,10 @@ func argsToURLValues(argNames []string, args ...interface{}) (url.Values, error) } for i, name := range argNames { s := slice[i] - values.Set(name, s[0]) - for i := 1; i < len(s); i++ { - values.Add(name, s[i]) - } + values.Set(name, s) // s[0] + /*for j := 1; j < len(s); j++ { + values.Add(name, s[j]) + }*/ } return values, nil } @@ -175,7 +129,7 @@ fmt /*rpc-gen:template:*ClientJSON func (c *ClientJSON) {{name}}({{args.def}}) ({{response}}) { request := RPCRequest{ JSONRPC: "2.0", - Method: {{lowername}}, + Method: reverseFuncMap["{{name}}"], Params: []interface{}{ {{args.ident}} }, Id: 0, } @@ -204,7 +158,7 @@ fmt if err != nil{ return nil, err } - resp, err := http.PostForm(c.addr+{{lowername}}, values) + resp, err := http.PostForm(c.addr+reverseFuncMap["{{name}}"], values) if err != nil { return nil, err } diff --git a/rpc/client_methods.go b/rpc/client_methods.go index 1bf5badc..872e723e 100644 --- a/rpc/client_methods.go +++ b/rpc/client_methods.go @@ -1,3 +1,5 @@ +// File generated by github.com/ebuchman/rpc-gen + package rpc import ( @@ -11,14 +13,14 @@ import ( ) type Client interface { - BlockchainInfo(minHeight uint) (*core.ResponseBlockchainInfo, error) + BlockchainInfo(minHeight uint, maxHeight uint) (*core.ResponseBlockchainInfo, error) BroadcastTx(tx types.Tx) (*core.ResponseBroadcastTx, error) - Call(address []byte) (*core.ResponseCall, error) + Call(address []byte, data []byte) (*core.ResponseCall, error) DumpStorage(addr []byte) (*core.ResponseDumpStorage, error) GenPrivAccount() (*core.ResponseGenPrivAccount, error) GetAccount(address []byte) (*core.ResponseGetAccount, error) GetBlock(height uint) (*core.ResponseGetBlock, error) - GetStorage(address []byte) (*core.ResponseGetStorage, error) + GetStorage(address []byte, storage []byte) (*core.ResponseGetStorage, error) ListAccounts() (*core.ResponseListAccounts, error) ListValidators() (*core.ResponseListValidators, error) NetInfo() (*core.ResponseNetInfo, error) @@ -26,12 +28,12 @@ type Client interface { Status() (*core.ResponseStatus, error) } -func (c *ClientHTTP) BlockchainInfo(minHeight uint) (*core.ResponseBlockchainInfo, error) { - values, err := argsToURLValues([]string{"minHeight"}, minHeight) +func (c *ClientHTTP) BlockchainInfo(minHeight uint, maxHeight uint) (*core.ResponseBlockchainInfo, error) { + values, err := argsToURLValues([]string{"minHeight", "maxHeight"}, minHeight, maxHeight) if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"blockchain_info", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["BlockchainInfo"], values) if err != nil { return nil, err } @@ -61,7 +63,7 @@ func (c *ClientHTTP) BroadcastTx(tx types.Tx) (*core.ResponseBroadcastTx, error) if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"broadcast_tx", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["BroadcastTx"], values) if err != nil { return nil, err } @@ -86,12 +88,12 @@ func (c *ClientHTTP) BroadcastTx(tx types.Tx) (*core.ResponseBroadcastTx, error) return response.Result, nil } -func (c *ClientHTTP) Call(address []byte) (*core.ResponseCall, error) { - values, err := argsToURLValues([]string{"address"}, address) +func (c *ClientHTTP) Call(address []byte, data []byte) (*core.ResponseCall, error) { + values, err := argsToURLValues([]string{"address", "data"}, address, data) if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"call", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["Call"], values) if err != nil { return nil, err } @@ -121,7 +123,7 @@ func (c *ClientHTTP) DumpStorage(addr []byte) (*core.ResponseDumpStorage, error) if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"dump_storage", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["DumpStorage"], values) if err != nil { return nil, err } @@ -151,7 +153,7 @@ func (c *ClientHTTP) GenPrivAccount() (*core.ResponseGenPrivAccount, error) { if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"gen_priv_account", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["GenPrivAccount"], values) if err != nil { return nil, err } @@ -181,7 +183,7 @@ func (c *ClientHTTP) GetAccount(address []byte) (*core.ResponseGetAccount, error if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"get_account", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["GetAccount"], values) if err != nil { return nil, err } @@ -211,7 +213,7 @@ func (c *ClientHTTP) GetBlock(height uint) (*core.ResponseGetBlock, error) { if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"get_block", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["GetBlock"], values) if err != nil { return nil, err } @@ -236,12 +238,12 @@ func (c *ClientHTTP) GetBlock(height uint) (*core.ResponseGetBlock, error) { return response.Result, nil } -func (c *ClientHTTP) GetStorage(address []byte) (*core.ResponseGetStorage, error) { - values, err := argsToURLValues([]string{"address"}, address) +func (c *ClientHTTP) GetStorage(address []byte, storage []byte) (*core.ResponseGetStorage, error) { + values, err := argsToURLValues([]string{"address", "storage"}, address, storage) if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"get_storage", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["GetStorage"], values) if err != nil { return nil, err } @@ -271,7 +273,7 @@ func (c *ClientHTTP) ListAccounts() (*core.ResponseListAccounts, error) { if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"list_accounts", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["ListAccounts"], values) if err != nil { return nil, err } @@ -301,7 +303,7 @@ func (c *ClientHTTP) ListValidators() (*core.ResponseListValidators, error) { if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"list_validators", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["ListValidators"], values) if err != nil { return nil, err } @@ -331,7 +333,7 @@ func (c *ClientHTTP) NetInfo() (*core.ResponseNetInfo, error) { if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"net_info", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["NetInfo"], values) if err != nil { return nil, err } @@ -361,7 +363,7 @@ func (c *ClientHTTP) SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (* if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"sign_tx", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["SignTx"], values) if err != nil { return nil, err } @@ -391,7 +393,7 @@ func (c *ClientHTTP) Status() (*core.ResponseStatus, error) { if err != nil { return nil, err } - resp, err := http.PostForm(c.addr+"status", values) + resp, err := http.PostForm(c.addr+reverseFuncMap["Status"], values) if err != nil { return nil, err } @@ -416,11 +418,11 @@ func (c *ClientHTTP) Status() (*core.ResponseStatus, error) { return response.Result, nil } -func (c *ClientJSON) BlockchainInfo(minHeight uint) (*core.ResponseBlockchainInfo, error) { +func (c *ClientJSON) BlockchainInfo(minHeight uint, maxHeight uint) (*core.ResponseBlockchainInfo, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "blockchain_info", - Params: []interface{}{minHeight}, + Method: reverseFuncMap["BlockchainInfo"], + Params: []interface{}{minHeight, maxHeight}, Id: 0, } body, err := c.RequestResponse(request) @@ -446,7 +448,7 @@ func (c *ClientJSON) BlockchainInfo(minHeight uint) (*core.ResponseBlockchainInf func (c *ClientJSON) BroadcastTx(tx types.Tx) (*core.ResponseBroadcastTx, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "broadcast_tx", + Method: reverseFuncMap["BroadcastTx"], Params: []interface{}{tx}, Id: 0, } @@ -470,11 +472,11 @@ func (c *ClientJSON) BroadcastTx(tx types.Tx) (*core.ResponseBroadcastTx, error) return response.Result, nil } -func (c *ClientJSON) Call(address []byte) (*core.ResponseCall, error) { +func (c *ClientJSON) Call(address []byte, data []byte) (*core.ResponseCall, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "call", - Params: []interface{}{address}, + Method: reverseFuncMap["Call"], + Params: []interface{}{address, data}, Id: 0, } body, err := c.RequestResponse(request) @@ -500,7 +502,7 @@ func (c *ClientJSON) Call(address []byte) (*core.ResponseCall, error) { func (c *ClientJSON) DumpStorage(addr []byte) (*core.ResponseDumpStorage, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "dump_storage", + Method: reverseFuncMap["DumpStorage"], Params: []interface{}{addr}, Id: 0, } @@ -527,7 +529,7 @@ func (c *ClientJSON) DumpStorage(addr []byte) (*core.ResponseDumpStorage, error) func (c *ClientJSON) GenPrivAccount() (*core.ResponseGenPrivAccount, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "gen_priv_account", + Method: reverseFuncMap["GenPrivAccount"], Params: []interface{}{nil}, Id: 0, } @@ -554,7 +556,7 @@ func (c *ClientJSON) GenPrivAccount() (*core.ResponseGenPrivAccount, error) { func (c *ClientJSON) GetAccount(address []byte) (*core.ResponseGetAccount, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "get_account", + Method: reverseFuncMap["GetAccount"], Params: []interface{}{address}, Id: 0, } @@ -581,7 +583,7 @@ func (c *ClientJSON) GetAccount(address []byte) (*core.ResponseGetAccount, error func (c *ClientJSON) GetBlock(height uint) (*core.ResponseGetBlock, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "get_block", + Method: reverseFuncMap["GetBlock"], Params: []interface{}{height}, Id: 0, } @@ -605,11 +607,11 @@ func (c *ClientJSON) GetBlock(height uint) (*core.ResponseGetBlock, error) { return response.Result, nil } -func (c *ClientJSON) GetStorage(address []byte) (*core.ResponseGetStorage, error) { +func (c *ClientJSON) GetStorage(address []byte, storage []byte) (*core.ResponseGetStorage, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "get_storage", - Params: []interface{}{address}, + Method: reverseFuncMap["GetStorage"], + Params: []interface{}{address, storage}, Id: 0, } body, err := c.RequestResponse(request) @@ -635,7 +637,7 @@ func (c *ClientJSON) GetStorage(address []byte) (*core.ResponseGetStorage, error func (c *ClientJSON) ListAccounts() (*core.ResponseListAccounts, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "list_accounts", + Method: reverseFuncMap["ListAccounts"], Params: []interface{}{nil}, Id: 0, } @@ -662,7 +664,7 @@ func (c *ClientJSON) ListAccounts() (*core.ResponseListAccounts, error) { func (c *ClientJSON) ListValidators() (*core.ResponseListValidators, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "list_validators", + Method: reverseFuncMap["ListValidators"], Params: []interface{}{nil}, Id: 0, } @@ -689,7 +691,7 @@ func (c *ClientJSON) ListValidators() (*core.ResponseListValidators, error) { func (c *ClientJSON) NetInfo() (*core.ResponseNetInfo, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "net_info", + Method: reverseFuncMap["NetInfo"], Params: []interface{}{nil}, Id: 0, } @@ -716,7 +718,7 @@ func (c *ClientJSON) NetInfo() (*core.ResponseNetInfo, error) { func (c *ClientJSON) SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (*core.ResponseSignTx, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "sign_tx", + Method: reverseFuncMap["SignTx"], Params: []interface{}{tx, privAccounts}, Id: 0, } @@ -743,7 +745,7 @@ func (c *ClientJSON) SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (* func (c *ClientJSON) Status() (*core.ResponseStatus, error) { request := RPCRequest{ JSONRPC: "2.0", - Method: "status", + Method: reverseFuncMap["Status"], Params: []interface{}{nil}, Id: 0, } diff --git a/rpc/core/accounts.go b/rpc/core/accounts.go index 4234656b..2cf2b6a1 100644 --- a/rpc/core/accounts.go +++ b/rpc/core/accounts.go @@ -15,20 +15,20 @@ func GetAccount(address []byte) (*ResponseGetAccount, error) { return &ResponseGetAccount{cache.GetAccount(address)}, nil } -func GetStorage(address, slot []byte) (*ResponseGetStorage, error) { +func GetStorage(address, storage []byte) (*ResponseGetStorage, error) { state := consensusState.GetState() account := state.GetAccount(address) if account == nil { return nil, fmt.Errorf("Unknown address: %X", address) } storageRoot := account.StorageRoot - storage := state.LoadStorage(storageRoot) + storageTree := state.LoadStorage(storageRoot) - _, value := storage.Get(RightPadWord256(slot).Bytes()) + _, value := storageTree.Get(RightPadWord256(storage).Bytes()) if value == nil { - return &ResponseGetStorage{slot, nil}, nil + return &ResponseGetStorage{storage, nil}, nil } - return &ResponseGetStorage{slot, value.([]byte)}, nil + return &ResponseGetStorage{storage, value.([]byte)}, nil } func ListAccounts() (*ResponseListAccounts, error) { diff --git a/rpc/handlers.go b/rpc/handlers.go index 69ead12c..73216401 100644 --- a/rpc/handlers.go +++ b/rpc/handlers.go @@ -12,8 +12,14 @@ import ( "io/ioutil" "net/http" "reflect" + "runtime" + "strings" ) +// maps camel-case function names to lower case rpc version +// populated by calls to funcWrap +var reverseFuncMap = make(map[string]string) + // cache all type information about each function up front // (func, responseStruct, argNames) var funcMap = map[string]*FuncWrapper{ @@ -40,6 +46,16 @@ func initHandlers() { // JSONRPC endpoints http.HandleFunc("/", JSONRPCHandler) + + // fill the map from camelcase to lowercase + for name, f := range funcMap { + camelName := runtime.FuncForPC(f.f.Pointer()).Name() + spl := strings.Split(camelName, ".") + if len(spl) > 1 { + camelName = spl[len(spl)-1] + } + reverseFuncMap[camelName] = name + } } //------------------------------------- @@ -86,6 +102,10 @@ func funcReturnTypes(f interface{}) []reflect.Type { // jsonrpc calls grab the given method's function info and runs reflect.Call func JSONRPCHandler(w http.ResponseWriter, r *http.Request) { + if len(r.URL.Path) > 1 { + WriteRPCResponse(w, NewRPCResponse(nil, fmt.Sprintf("Invalid JSONRPC endpoint %s", r.URL.Path))) + return + } b, _ := ioutil.ReadAll(r.Body) var request RPCRequest err := json.Unmarshal(b, &request) diff --git a/rpc/test/http_rpc_test.go b/rpc/test/http_rpc_test.go index c49683eb..61bafd7f 100644 --- a/rpc/test/http_rpc_test.go +++ b/rpc/test/http_rpc_test.go @@ -4,67 +4,31 @@ import ( "bytes" "encoding/hex" "fmt" - "github.com/tendermint/tendermint/binary" . "github.com/tendermint/tendermint/common" "github.com/tendermint/tendermint/merkle" - "github.com/tendermint/tendermint/rpc/core" "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" - "io/ioutil" - "net/http" "testing" "time" ) func TestHTTPStatus(t *testing.T) { - resp, err := http.Get(requestAddr + "status") + client := clients["HTTP"] + resp, err := client.Status() if err != nil { t.Fatal(err) } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - var response struct { - Result core.ResponseStatus `json:"result"` - Error string `json:"error"` - Id string `json:"id"` - JSONRPC string `json:"jsonrpc"` - } - binary.ReadJSON(&response, body, &err) - if err != nil { - t.Fatal(err) - } - result := response.Result - fmt.Println(">>>", result) + fmt.Println(">>>", resp) return } func TestHTTPGenPriv(t *testing.T) { - resp, err := http.Get(requestAddr + "unsafe/gen_priv_account") + client := clients["HTTP"] + resp, err := client.GenPrivAccount() if err != nil { t.Fatal(err) } - if resp.StatusCode != 200 { - t.Fatal(resp) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - var response struct { - Result core.ResponseGenPrivAccount `json:"result"` - Error string `json:"error"` - Id string `json:"id"` - JSONRPC string `json:"jsonrpc"` - } - binary.ReadJSON(&response, body, &err) - if err != nil { - t.Fatal(err) - } - fmt.Println(">>>", response) + fmt.Println(">>>", resp) } func TestHTTPGetAccount(t *testing.T) { @@ -153,14 +117,10 @@ func TestHTTPGetStorage(t *testing.T) { time.Sleep(time.Second * 20) mempoolCount -= 1 - v := getStorage(t, contractAddr, []byte{0x1}) + v := getStorage(t, "HTTP", contractAddr, []byte{0x1}) got := RightPadWord256(v) expected := RightPadWord256([]byte{0x5}) if got.Compare(expected) != 0 { t.Fatalf("Wrong storage value. Got %x, expected %x", got.Bytes(), expected.Bytes()) } } - -/*tx.Inputs[0].Signature = mint.priv.PrivKey.Sign(account.SignBytes(tx)) -err = mint.MempoolReactor.BroadcastTx(tx) -return hex.EncodeToString(merkle.HashFromBinary(tx)), err*/ diff --git a/rpc/test/test.go b/rpc/test/test.go index 0b31525d..f8253f6c 100644 --- a/rpc/test/test.go +++ b/rpc/test/test.go @@ -30,6 +30,11 @@ var ( userAddr = "D7DFF9806078899C8DA3FE3633CC0BF3C6C2B1BB" userPriv = "FDE3BD94CB327D19464027BA668194C5EFA46AE83E8419D7542CFF41F00C81972239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3" userPub = "2239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3" + + clients = map[string]rpc.Client{ + "JSONRPC": rpc.NewClient(requestAddr, "JSONRPC"), + "HTTP": rpc.NewClient(requestAddr, "HTTP"), + } ) func decodeHex(hexStr string) []byte { @@ -40,6 +45,8 @@ func decodeHex(hexStr string) []byte { return bytes } + +// create a new node and sleep forever func newNode(ready chan struct{}) { // Create & start node node = daemon.NewNode() @@ -56,6 +63,7 @@ func newNode(ready chan struct{}) { <-ch } +// initialize config and create new node func init() { rootDir := ".tendermint" config.Init(rootDir) @@ -84,64 +92,10 @@ func init() { <-ready } -func getAccount(t *testing.T, typ string, addr []byte) *account.Account { - var client rpc.Client - switch typ { - case "JSONRPC": - client = rpc.NewClient(requestAddr, "JSONRPC") - case "HTTP": - client = rpc.NewClient(requestAddr, "HTTP") - } - ac, err := client.GetAccount(addr) - if err != nil { - t.Fatal(err) - } - return ac.Account -} - -/* -func getAccount(t *testing.T, typ string, addr []byte) *account.Account { - var resp *http.Response - var err error - switch typ { - case "JSONRPC": - s := rpc.JSONRPC{ - JSONRPC: "2.0", - Method: "get_account", - Params: []interface{}{hex.EncodeToString(addr)}, - Id: 0, - } - b, err := json.Marshal(s) - if err != nil { - t.Fatal(err) - } - buf := bytes.NewBuffer(b) - resp, err = http.Post(requestAddr, "text/json", buf) - case "HTTP": - resp, err = http.PostForm(requestAddr+"get_account", - url.Values{"address": {"\"" + (hex.EncodeToString(addr)) + "\""}}) - } - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - var response struct { - Result core.ResponseGetAccount `json:"result"` - Error string `json:"error"` - Id string `json:"id"` - JSONRPC string `json:"jsonrpc"` - } - binary.ReadJSON(&response, body, &err) - if err != nil { - t.Fatal(err) - } - return response.Result.Account -}*/ +//------------------------------------------------------------------------------- +// make transactions +// make a send tx (uses get account to figure out the nonce) func makeSendTx(t *testing.T, typ string, from, to []byte, amt uint64) *types.SendTx { acc := getAccount(t, typ, from) nonce := 0 @@ -172,6 +126,7 @@ func makeSendTx(t *testing.T, typ string, from, to []byte, amt uint64) *types.Se return tx } +// make a call tx (uses get account to figure out the nonce) func makeCallTx(t *testing.T, typ string, from, to, data []byte, amt, gaslim, fee uint64) *types.CallTx { acc := getAccount(t, typ, from) nonce := 0 @@ -199,22 +154,21 @@ 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, response interface{}) { - resp, err := http.PostForm(requestAddr+method, values) - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - binary.ReadJSON(response, body, &err) +// make transactions +//------------------------------------------------------------------------------- +// rpc call wrappers + +// get the account +func getAccount(t *testing.T, typ string, addr []byte) *account.Account { + client := clients[typ] + ac, err := client.GetAccount(addr) if err != nil { t.Fatal(err) } + return ac.Account } +// make and sign transaction func signTx(t *testing.T, typ string, fromAddr, toAddr, data []byte, key [64]byte, amt, gaslim, fee uint64) (types.Tx, *account.PrivAccount) { var tx types.Tx if data == nil { @@ -223,64 +177,39 @@ func signTx(t *testing.T, typ string, fromAddr, toAddr, data []byte, key [64]byt tx = makeCallTx(t, typ, fromAddr, toAddr, data, amt, gaslim, fee) } - n, w := new(int64), new(bytes.Buffer) - var err error - binary.WriteJSON(tx, w, n, &err) - if err != nil { - t.Fatal(err) - } - b := w.Bytes() - privAcc := account.GenPrivAccountFromKey(key) if bytes.Compare(privAcc.PubKey.Address(), fromAddr) != 0 { t.Fatal("Faield to generate correct priv acc") } - w = new(bytes.Buffer) - binary.WriteJSON([]*account.PrivAccount{privAcc}, w, n, &err) + + client := clients[typ] + resp, err := client.SignTx(tx, []*account.PrivAccount{privAcc}) if err != nil { t.Fatal(err) } - - var response struct { - Result core.ResponseSignTx `json:"result"` - Error string `json:"error"` - Id string `json:"id"` - JSONRPC string `json:"jsonrpc"` - } - requestResponse(t, "unsafe/sign_tx", url.Values{"tx": {string(b)}, "privAccounts": {string(w.Bytes())}}, &response) - if response.Error != "" { - t.Fatal(response.Error) - } - result := response.Result - return result.Tx, privAcc + return resp.Tx, privAcc } +// create, sign, and broadcast a transaction func broadcastTx(t *testing.T, typ string, fromAddr, toAddr, data []byte, key [64]byte, amt, gaslim, fee uint64) (types.Tx, core.Receipt) { tx, _ := signTx(t, typ, fromAddr, toAddr, data, key, amt, gaslim, fee) - - n, w := new(int64), new(bytes.Buffer) - var err error - binary.WriteJSON(tx, w, n, &err) + client := clients[typ] + resp, err := client.BroadcastTx(tx) if err != nil { t.Fatal(err) } - b := w.Bytes() - - var response struct { - Result core.ResponseBroadcastTx `json:"result"` - Error string `json:"error"` - Id string `json:"id"` - JSONRPC string `json:"jsonrpc"` - } - requestResponse(t, "broadcast_tx", url.Values{"tx": {string(b)}}, &response) - if response.Error != "" { - t.Fatal(response.Error) - } - return tx, response.Result.Receipt + return tx, resp.Receipt } +// dump all storage for an account. currently unused func dumpStorage(t *testing.T, addr []byte) core.ResponseDumpStorage { - addrString := "\"" + hex.EncodeToString(addr) + "\"" + client := clients["HTTP"] + resp, err := client.DumpStorage(addr) + if err != nil { + t.Fatal(err) + } + return *resp + /*addrString := "\"" + hex.EncodeToString(addr) + "\"" var response struct { Result core.ResponseDumpStorage `json:"result"` Error string `json:"error"` @@ -290,26 +219,21 @@ func dumpStorage(t *testing.T, addr []byte) core.ResponseDumpStorage { requestResponse(t, "dump_storage", url.Values{"address": {addrString}}, &response) if response.Error != "" { t.Fatal(response.Error) - } - return response.Result + }*/ } -func getStorage(t *testing.T, addr, slot []byte) []byte { - addrString := "\"" + hex.EncodeToString(addr) + "\"" - slotString := "\"" + hex.EncodeToString(slot) + "\"" - var response struct { - Result core.ResponseGetStorage `json:"result"` - Error string `json:"error"` - Id string `json:"id"` - JSONRPC string `json:"jsonrpc"` +func getStorage(t *testing.T, typ string, addr, slot []byte) []byte { + client := clients[typ] + resp, err := client.GetStorage(addr, slot) + if err != nil { + t.Fatal(err) } - requestResponse(t, "get_storage", url.Values{"address": {addrString}, "storage": {slotString}}, &response) - if response.Error != "" { - t.Fatal(response.Error) - } - return response.Result.Value + return resp.Value } +//-------------------------------------------------------------------------------- +// utility verification function + func checkTx(t *testing.T, fromAddr []byte, priv *account.PrivAccount, tx *types.SendTx) { if bytes.Compare(tx.Inputs[0].Address, fromAddr) != 0 { t.Fatal("Tx input addresses don't match!") @@ -328,3 +252,21 @@ func checkTx(t *testing.T, fromAddr []byte, priv *account.PrivAccount, tx *types t.Fatal(types.ErrTxInvalidSignature) } } + +//-------------------------------------------------------------------------------- + +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) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + binary.ReadJSON(response, body, &err) + if err != nil { + t.Fatal(err) + } +}