diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go index e20dc2b54..148cb84c3 100644 --- a/rpc/core/mempool.go +++ b/rpc/core/mempool.go @@ -12,29 +12,29 @@ import ( type Receipt struct { TxHash []byte - CreatesContract bool + CreatesContract uint8 ContractAddr []byte } // pass pointer? // Note: tx must be signed -func BroadcastTx(tx types.Tx) (*Receipt, error) { +func BroadcastTx(tx types.Tx) (Receipt, error) { err := mempoolReactor.BroadcastTx(tx) if err != nil { - return nil, fmt.Errorf("Error broadcasting transaction: %v", err) + return Receipt{}, fmt.Errorf("Error broadcasting transaction: %v", err) } txHash := merkle.HashFromBinary(tx) - var createsContract bool + var createsContract uint8 var contractAddr []byte // check if creates new contract if callTx, ok := tx.(*types.CallTx); ok { if callTx.Address == nil { - createsContract = true + createsContract = 1 contractAddr = state.NewContractAddress(callTx.Input.Address, uint64(callTx.Input.Sequence)) } } - return &Receipt{txHash, createsContract, contractAddr}, nil + return Receipt{txHash, createsContract, contractAddr}, nil } /* diff --git a/rpc/http_handlers.go b/rpc/http_handlers.go index 7d9576f70..e72e04305 100644 --- a/rpc/http_handlers.go +++ b/rpc/http_handlers.go @@ -1,6 +1,7 @@ package rpc import ( + "encoding/hex" "encoding/json" "fmt" "github.com/tendermint/tendermint/binary" @@ -11,46 +12,20 @@ import ( "strconv" ) -// map each function to the argument names -var argsMap = map[string][]string{ - "status": []string{}, - "net_info": []string{}, - "blockchain": []string{"min_height", "max_height"}, - "get_block": []string{"height"}, - "get_account": []string{"address"}, - "list_validators": []string{}, - "broadcast_tx": []string{"tx"}, - "list_accounts": []string{}, - "gen_priv_account": []string{}, - "sign_tx": []string{"tx", "privAccounts"}, -} - // cache all type information about each function up front +// (func, responseStruct, argNames) +// XXX: response structs are allocated once and reused - will this cause an issue eg. if a field ever not overwritten? var funcMap = map[string]*FuncWrapper{ - "status": funcWrap("status", core.Status), - "net_info": funcWrap("net_info", core.NetInfo), - "blockchain": funcWrap("blockchain", core.BlockchainInfo), - "get_block": funcWrap("get_block", core.GetBlock), - "get_account": funcWrap("get_account", core.GetAccount), - "list_validators": funcWrap("list_validators", core.ListValidators), - "broadcast_tx": funcWrap("broadcast_tx", core.BroadcastTx), - "list_accounts": funcWrap("list_accounts", core.ListAccounts), - "gen_priv_account": funcWrap("gen_priv_account", core.GenPrivAccount), - "sign_tx": funcWrap("sign_tx", core.SignTx), -} - -// map each function to an empty struct which can hold its return values -var responseMap = map[string]reflect.Value{ - "status": reflect.ValueOf(&ResponseStatus{}), - "net_info": reflect.ValueOf(&ResponseNetInfo{}), - "blockchain": reflect.ValueOf(&ResponseBlockchainInfo{}), - "get_block": reflect.ValueOf(&ResponseGetBlock{}), - "get_account": reflect.ValueOf(&ResponseGetAccount{}), - "list_validators": reflect.ValueOf(&ResponseListValidators{}), - "broadcast_tx": reflect.ValueOf(&ResponseBroadcastTx{}), - "list_accounts": reflect.ValueOf(&ResponseListAccounts{}), - "gen_priv_account": reflect.ValueOf(&ResponseGenPrivAccount{}), - "sign_tx": reflect.ValueOf(&ResponseSignTx{}), + "status": funcWrap(core.Status, &ResponseStatus{}, []string{}), + "net_info": funcWrap(core.NetInfo, &ResponseNetInfo{}, []string{}), + "blockchain": funcWrap(core.BlockchainInfo, &ResponseBlockchainInfo{}, []string{"min_height", "max_height"}), + "get_block": funcWrap(core.GetBlock, &ResponseGetBlock{}, []string{"height"}), + "get_account": funcWrap(core.GetAccount, &ResponseGetAccount{}, []string{"address"}), + "list_validators": funcWrap(core.ListValidators, &ResponseListValidators{}, []string{}), + "broadcast_tx": funcWrap(core.BroadcastTx, &ResponseBroadcastTx{}, []string{"tx"}), + "list_accounts": funcWrap(core.ListAccounts, &ResponseListAccounts{}, []string{}), + "unsafe/gen_priv_account": funcWrap(core.GenPrivAccount, &ResponseGenPrivAccount{}, []string{}), + "unsafe/sign_tx": funcWrap(core.SignTx, &ResponseSignTx{}, []string{"tx", "privAccounts"}), } // holds all type information for each function @@ -62,13 +37,13 @@ type FuncWrapper struct { response reflect.Value // response struct (to be filled with "returns") } -func funcWrap(name string, f interface{}) *FuncWrapper { +func funcWrap(f interface{}, response interface{}, args []string) *FuncWrapper { return &FuncWrapper{ f: reflect.ValueOf(f), args: funcArgTypes(f), returns: funcReturnTypes(f), - argNames: argsMap[name], - response: responseMap[name], + argNames: args, + response: reflect.ValueOf(response), } } @@ -91,8 +66,78 @@ func toHandler(funcName string) func(http.ResponseWriter, *http.Request) { } } -// covert an http query to a list of properly typed values -// to be properly decoded the arg must be a concrete type from tendermint +// 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) + 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) + 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 +} + +// covert an http query to a list of properly typed values. +// to be properly decoded the arg must be a concrete type from tendermint (if its an interface). func queryToValues(funcInfo *FuncWrapper, r *http.Request) ([]reflect.Value, error) { argTypes := funcInfo.args argNames := funcInfo.argNames @@ -101,72 +146,26 @@ func queryToValues(funcInfo *FuncWrapper, r *http.Request) ([]reflect.Value, err values := make([]reflect.Value, len(argNames)) for i, name := range argNames { ty := argTypes[i] - v := reflect.New(ty).Elem() - kind := v.Kind() arg := GetParam(r, name) - switch kind { - case reflect.Interface: - v = reflect.New(ty) - binary.ReadJSON(v.Interface(), []byte(arg), &err) - if err != nil { - return nil, err - } - v = v.Elem() - case reflect.Struct: - binary.ReadJSON(v.Interface(), []byte(arg), &err) - if err != nil { - return nil, err - } - case reflect.Slice: - rt := ty.Elem() - if rt.Kind() == reflect.Uint8 { - v = reflect.ValueOf([]byte(arg)) - } else { - v = reflect.New(ty) - binary.ReadJSON(v.Interface(), []byte(arg), &err) - if err != nil { - return nil, err - } - v = v.Elem() - } - case reflect.Int64: - u, err := strconv.ParseInt(arg, 10, 64) - if err != nil { - return nil, err - } - v = reflect.ValueOf(u) - case reflect.Int32: - u, err := strconv.ParseInt(arg, 10, 32) - if err != nil { - return nil, err - } - v = reflect.ValueOf(u) - case reflect.Uint64: - u, err := strconv.ParseUint(arg, 10, 64) - if err != nil { - return nil, err - } - v = reflect.ValueOf(u) - case reflect.Uint: - u, err := strconv.ParseUint(arg, 10, 32) - if err != nil { - return nil, err - } - v = reflect.ValueOf(u) - default: - v = reflect.ValueOf(arg) + values[i], err = jsonToArg(ty, arg) + if err != nil { + return nil, err } - values[i] = v } return values, nil } // covert a list of interfaces to properly typed values // TODO! -func paramsToValues(funcInfo *FuncWrapper, params []interface{}) ([]reflect.Value, error) { +func paramsToValues(funcInfo *FuncWrapper, params []string) ([]reflect.Value, error) { values := make([]reflect.Value, len(params)) for i, p := range params { - values[i] = reflect.ValueOf(p) + ty := funcInfo.args[i] + v, err := jsonToArg(ty, p) + if err != nil { + return nil, err + } + values[i] = v } return values, nil } @@ -228,8 +227,8 @@ func initHandlers() { http.HandleFunc("/list_validators", toHandler("list_validators")) http.HandleFunc("/broadcast_tx", toHandler("broadcast_tx")) http.HandleFunc("/list_accounts", toHandler("list_accounts")) - http.HandleFunc("/unsafe/gen_priv_account", toHandler("gen_priv_account")) - http.HandleFunc("/unsafe/sign_tx", toHandler("sign_tx")) + http.HandleFunc("/unsafe/gen_priv_account", toHandler("unsafe/gen_priv_account")) + http.HandleFunc("/unsafe/sign_tx", toHandler("unsafe/sign_tx")) //http.HandleFunc("/call", CallHandler) //http.HandleFunc("/get_storage", GetStorageHandler) @@ -241,10 +240,10 @@ func initHandlers() { } type JsonRpc struct { - JsonRpc string `json:"jsonrpc"` - Method string `json:"method"` - Params []interface{} `json:"params"` - Id int `json:"id"` + JsonRpc string `json:"jsonrpc"` + Method string `json:"method"` + Params []string `json:"params"` + Id int `json:"id"` } // this will panic if not passed a function diff --git a/rpc/responses.go b/rpc/responses.go index cc77ff794..11360c004 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -2,6 +2,7 @@ package rpc import ( "github.com/tendermint/tendermint/account" + "github.com/tendermint/tendermint/rpc/core" sm "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/types" ) @@ -31,9 +32,7 @@ type ResponseGetBlock struct { // curl -H 'content-type: text/plain;' http://127.0.0.1:8888/submit_tx?tx=... type ResponseBroadcastTx struct { - TxHash []byte - CreatesContract bool - ContractAddr []byte + Receipt core.Receipt } type ResponseStatus struct { diff --git a/rpc/test/http_rpc_test.go b/rpc/test/http_rpc_test.go new file mode 100644 index 000000000..31e37b482 --- /dev/null +++ b/rpc/test/http_rpc_test.go @@ -0,0 +1,149 @@ +package rpc + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/tendermint/tendermint/binary" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/merkle" + "github.com/tendermint/tendermint/rpc" + "github.com/tendermint/tendermint/types" + "io/ioutil" + "net/http" + "net/url" + "testing" +) + +func TestHTTPStatus(t *testing.T) { + resp, err := http.Get(requestAddr + "status") + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + var status struct { + Status string + Data rpc.ResponseStatus + Error string + } + err = json.Unmarshal(body, &status) + 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"))) + } +} + +func TestHTTPGenPriv(t *testing.T) { + resp, err := http.Get(requestAddr + "unsafe/gen_priv_account") + 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 status struct { + Status string + Data rpc.ResponseGenPrivAccount + Error string + } + binary.ReadJSON(&status, body, &err) + if err != nil { + t.Fatal(err) + } + if len(status.Data.PrivAccount.Address) == 0 { + t.Fatal("Failed to generate an address") + } +} + +func TestHTTPGetAccount(t *testing.T) { + byteAddr, _ := hex.DecodeString(userAddr) + acc := getAccount(t, "HTTP", byteAddr) + if bytes.Compare(acc.Address, byteAddr) != 0 { + t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, byteAddr) + } + +} + +func TestHTTPSignedTx(t *testing.T) { + byteAddr, _ := hex.DecodeString(userAddr) + var byteKey [64]byte + oh, _ := hex.DecodeString(userPriv) + copy(byteKey[:], oh) + + amt := uint64(100) + toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54} + tx, priv := signTx(t, "HTTP", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) + + toAddr = []byte{20, 143, 24, 63, 16, 17, 83, 29, 90, 91, 52, 2, 0, 41, 190, 121, 122, 34, 86, 54} + tx, priv = signTx(t, "HTTP", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) + + toAddr = []byte{0, 0, 4, 0, 0, 4, 0, 0, 4, 91, 52, 2, 0, 41, 190, 121, 122, 34, 86, 54} + tx, priv = signTx(t, "HTTP", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) +} + +func TestHTTPBroadcastTx(t *testing.T) { + byteAddr, _ := hex.DecodeString(userAddr) + var byteKey [64]byte + oh, _ := hex.DecodeString(userPriv) + copy(byteKey[:], oh) + + amt := uint64(100) + toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54} + tx, priv := signTx(t, "HTTP", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) + + 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() + + var status struct { + Status string + Data rpc.ResponseBroadcastTx + Error string + } + requestResponse(t, "broadcast_tx", url.Values{"tx": {string(b)}}, &status) + if status.Status == "ERROR" { + t.Fatal(status.Error) + } + receipt := status.Data.Receipt + if receipt.CreatesContract > 0 { + t.Fatal("This tx does not create a contract") + } + if len(receipt.TxHash) == 0 { + t.Fatal("Failed to compute tx hash") + } + pool := node.MempoolReactor().Mempool + txs := pool.GetProposalTxs() + if len(txs) != 1 { + t.Fatal("The mem pool has %d txs. Expected 1", len(txs)) + } + tx2 := txs[0].(*types.SendTx) + if bytes.Compare(merkle.HashFromBinary(tx), merkle.HashFromBinary(tx2)) != 0 { + t.Fatal("inconsistent hashes for mempool tx and sent tx") + } + +} + +/*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/json_rpc_test.go b/rpc/test/json_rpc_test.go new file mode 100644 index 000000000..c8cafa302 --- /dev/null +++ b/rpc/test/json_rpc_test.go @@ -0,0 +1,170 @@ +package rpc + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "github.com/tendermint/tendermint/binary" + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/merkle" + "github.com/tendermint/tendermint/rpc" + "github.com/tendermint/tendermint/types" + "io/ioutil" + "net/http" + "net/url" + "testing" +) + +func TestJSONStatus(t *testing.T) { + s := rpc.JsonRpc{ + JsonRpc: "2.0", + Method: "status", + Params: []string{}, + 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) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + status := new(struct { + Status string + Data rpc.ResponseStatus + Error string + }) + err = json.Unmarshal(body, status) + 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"))) + } +} + +func TestJSONGenPriv(t *testing.T) { + s := rpc.JsonRpc{ + JsonRpc: "2.0", + Method: "unsafe/gen_priv_account", + Params: []string{}, + 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) + 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 status struct { + Status string + Data rpc.ResponseGenPrivAccount + Error string + } + binary.ReadJSON(&status, body, &err) + if err != nil { + t.Fatal(err) + } + if len(status.Data.PrivAccount.Address) == 0 { + t.Fatal("Failed to generate an address") + } +} + +func TestJSONGetAccount(t *testing.T) { + byteAddr, _ := hex.DecodeString(userAddr) + acc := getAccount(t, "JSONRPC", byteAddr) + if bytes.Compare(acc.Address, byteAddr) != 0 { + t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, byteAddr) + } + +} + +func TestJSONSignedTx(t *testing.T) { + byteAddr, _ := hex.DecodeString(userAddr) + var byteKey [64]byte + oh, _ := hex.DecodeString(userPriv) + copy(byteKey[:], oh) + + amt := uint64(100) + toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54} + tx, priv := signTx(t, "JSONRPC", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) + + toAddr = []byte{20, 143, 24, 63, 16, 17, 83, 29, 90, 91, 52, 2, 0, 41, 190, 121, 122, 34, 86, 54} + tx, priv = signTx(t, "JSONRPC", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) + + toAddr = []byte{0, 0, 4, 0, 0, 4, 0, 0, 4, 91, 52, 2, 0, 41, 190, 121, 122, 34, 86, 54} + tx, priv = signTx(t, "JSONRPC", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) +} + +func TestJSONBroadcastTx(t *testing.T) { + byteAddr, _ := hex.DecodeString(userAddr) + var byteKey [64]byte + oh, _ := hex.DecodeString(userPriv) + copy(byteKey[:], oh) + + amt := uint64(100) + toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54} + tx, priv := signTx(t, "JSONRPC", byteAddr, toAddr, byteKey, amt) + checkTx(t, byteAddr, priv, tx) + + 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() + + var status struct { + Status string + Data rpc.ResponseBroadcastTx + Error string + } + requestResponse(t, "broadcast_tx", url.Values{"tx": {string(b)}}, &status) + if status.Status == "ERROR" { + t.Fatal(status.Error) + } + receipt := status.Data.Receipt + if receipt.CreatesContract > 0 { + t.Fatal("This tx does not create a contract") + } + if len(receipt.TxHash) == 0 { + t.Fatal("Failed to compute tx hash") + } + pool := node.MempoolReactor().Mempool + txs := pool.GetProposalTxs() + if len(txs) != 1 { + t.Fatal("The mem pool has %d txs. Expected 1", len(txs)) + } + tx2 := txs[0].(*types.SendTx) + if bytes.Compare(merkle.HashFromBinary(tx), merkle.HashFromBinary(tx2)) != 0 { + t.Fatal("inconsistent hashes for mempool tx and sent tx") + } + +} + +/*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/rpc_test.go b/rpc/test/test.go similarity index 57% rename from rpc/test/rpc_test.go rename to rpc/test/test.go index aa8090ece..50a3ba0d3 100644 --- a/rpc/test/rpc_test.go +++ b/rpc/test/test.go @@ -64,58 +64,28 @@ func init() { <-ready } -func TestSayHello(t *testing.T) { - resp, err := http.Get(requestAddr + "status") - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - t.Fatal(err) - } - var status struct { - Status string - Data rpc.ResponseStatus - } - err = json.Unmarshal(body, &status) - 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"))) - } -} - -func TestGenPriv(t *testing.T) { - resp, err := http.Get(requestAddr + "unsafe/gen_priv_account") - 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 status struct { - Status string - Data rpc.ResponseGenPrivAccount - } - binary.ReadJSON(&status, body, &err) - if err != nil { - t.Fatal(err) - } - if len(status.Data.PrivAccount.Address) == 0 { - t.Fatal("Failed to generate an address") +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: []string{"0x" + 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": {string(addr)}}) } -} - -func getAccount(t *testing.T, addr []byte) *account.Account { - resp, err := http.PostForm(requestAddr+"get_account", - url.Values{"address": {string(addr)}}) + fmt.Println("RESPONSE:", resp) if err != nil { t.Fatal(err) } @@ -137,17 +107,8 @@ func getAccount(t *testing.T, addr []byte) *account.Account { return status.Data.Account } -func TestGetAccount(t *testing.T) { - byteAddr, _ := hex.DecodeString(userAddr) - acc := getAccount(t, byteAddr) - if bytes.Compare(acc.Address, byteAddr) != 0 { - t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, byteAddr) - } - -} - -func makeTx(t *testing.T, from, to []byte, amt uint64) *types.SendTx { - acc := getAccount(t, from) +func makeTx(t *testing.T, typ string, from, to []byte, amt uint64) *types.SendTx { + acc := getAccount(t, typ, from) nonce := 0 if acc != nil { nonce = int(acc.Sequence) + 1 @@ -193,32 +154,19 @@ func requestResponse(t *testing.T, method string, values url.Values, status inte } } -func TestSignedTx(t *testing.T) { - byteAddr, _ := hex.DecodeString(userAddr) - var byteKey [64]byte - oh, _ := hex.DecodeString(userPriv) - copy(byteKey[:], oh) - - amt := uint64(100) - toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54} - tx := makeTx(t, byteAddr, toAddr, amt) - - /*b, err := json.Marshal(rpc.InterfaceType{types.TxTypeSend, tx}) - if err != nil { - t.Fatal(err) - }*/ +func signTx(t *testing.T, typ string, fromAddr, toAddr []byte, key [64]byte, amt uint64) (*types.SendTx, *account.PrivAccount) { + tx := makeTx(t, typ, fromAddr, toAddr, amt) - n := new(int64) + n, w := new(int64), new(bytes.Buffer) var err error - w := new(bytes.Buffer) binary.WriteJSON(tx, w, n, &err) if err != nil { t.Fatal(err) } b := w.Bytes() - privAcc := account.GenPrivAccountFromKey(byteKey) - if bytes.Compare(privAcc.PubKey.Address(), byteAddr) != 0 { + privAcc := account.GenPrivAccountFromKey(key) + if bytes.Compare(privAcc.PubKey.Address(), fromAddr) != 0 { t.Fatal("Faield to generate correct priv acc") } w = new(bytes.Buffer) @@ -233,14 +181,16 @@ func TestSignedTx(t *testing.T) { Error string } requestResponse(t, "unsafe/sign_tx", url.Values{"tx": {string(b)}, "privAccounts": {string(w.Bytes())}}, &status) - if status.Status == "ERROR" { t.Fatal(status.Error) } response := status.Data - //tx = status.Data.(rpc.ResponseSignTx).Tx.(*types.SendTx) tx = response.Tx.(*types.SendTx) - if bytes.Compare(tx.Inputs[0].Address, byteAddr) != 0 { + return tx, privAcc +} + +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!") } @@ -250,7 +200,7 @@ func TestSignedTx(t *testing.T) { if err := in.ValidateBasic(); err != nil { t.Fatal(err) } - fmt.Println(privAcc.PubKey, in.PubKey) + fmt.Println(priv.PubKey, in.PubKey) // Check signatures // acc := getAccount(t, byteAddr) // NOTE: using the acc here instead of the in fails; its PubKeyNil ... ? @@ -258,28 +208,3 @@ func TestSignedTx(t *testing.T) { t.Fatal(types.ErrTxInvalidSignature) } } - -func TestBroadcastTx(t *testing.T) { - /* - byteAddr, _ := hex.DecodeString(userAddr) - - amt := uint64(100) - toAddr := []byte{20, 143, 25, 63, 16, 177, 83, 29, 91, 91, 54, 23, 233, 46, 190, 121, 122, 34, 86, 54} - tx := makeTx(t, byteAddr, toAddr, amt) - - b, err := json.Marshal([]interface{}{types.TxTypeSend, tx}) - if err != nil { - t.Fatal(err) - } - - var status struct { - Status string - Data rpc.ResponseSignTx - } - // TODO ... - */ -} - -/*tx.Inputs[0].Signature = mint.priv.PrivKey.Sign(account.SignBytes(tx)) -err = mint.MempoolReactor.BroadcastTx(tx) -return hex.EncodeToString(merkle.HashFromBinary(tx)), err*/