Merge branch 'rpc_jae' into develop

Conflicts:
	node/node.go
	rpc/core/accounts.go
	rpc/core_client/client.go
	rpc/handlers.go
	rpc/http_server.go
	rpc/test/helpers.go
	rpc/test/http_rpc_test.go
	rpc/test/json_rpc_test.go
This commit is contained in:
Jae Kwon
2015-04-08 14:27:03 -07:00
20 changed files with 892 additions and 657 deletions

View File

@@ -0,0 +1,75 @@
package rpc
import (
"testing"
)
//--------------------------------------------------------------------------------
// Test the HTTP client
func TestHTTPStatus(t *testing.T) {
testStatus(t, "HTTP")
}
func TestHTTPGenPriv(t *testing.T) {
testGenPriv(t, "HTTP")
}
func TestHTTPGetAccount(t *testing.T) {
testGetAccount(t, "HTTP")
}
func TestHTTPSignedTx(t *testing.T) {
testSignedTx(t, "HTTP")
}
func TestHTTPBroadcastTx(t *testing.T) {
testBroadcastTx(t, "HTTP")
}
func TestHTTPGetStorage(t *testing.T) {
testGetStorage(t, "HTTP")
}
func TestHTTPCallCode(t *testing.T) {
testCallCode(t, "HTTP")
}
func TestHTTPCallContract(t *testing.T) {
testCall(t, "HTTP")
}
//--------------------------------------------------------------------------------
// Test the JSONRPC client
func TestJSONStatus(t *testing.T) {
testStatus(t, "JSONRPC")
}
func TestJSONGenPriv(t *testing.T) {
testGenPriv(t, "JSONRPC")
}
func TestJSONGetAccount(t *testing.T) {
testGetAccount(t, "JSONRPC")
}
func TestJSONSignedTx(t *testing.T) {
testSignedTx(t, "JSONRPC")
}
func TestJSONBroadcastTx(t *testing.T) {
testBroadcastTx(t, "JSONRPC")
}
func TestJSONGetStorage(t *testing.T) {
testGetStorage(t, "JSONRPC")
}
func TestJSONCallCode(t *testing.T) {
testCallCode(t, "JSONRPC")
}
func TestJSONCallContract(t *testing.T) {
testCall(t, "JSONRPC")
}

View File

@@ -4,7 +4,7 @@ import (
"bytes"
"encoding/hex"
"github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/logger"
nm "github.com/tendermint/tendermint/node"
@@ -13,12 +13,10 @@ import (
cclient "github.com/tendermint/tendermint/rpc/core_client"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
"io/ioutil"
"net/http"
"net/url"
"testing"
)
// global variables for use across all tests
var (
rpcAddr = "127.0.0.1:8089"
requestAddr = "http://" + rpcAddr + "/"
@@ -30,6 +28,11 @@ var (
userAddr = "D7DFF9806078899C8DA3FE3633CC0BF3C6C2B1BB"
userPriv = "FDE3BD94CB327D19464027BA668194C5EFA46AE83E8419D7542CFF41F00C81972239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"
userPub = "2239C21C81EA7173A6C489145490C015E05D4B97448933B708A7EC5B7B4921E3"
clients = map[string]cclient.Client{
"JSONRPC": cclient.NewClient(requestAddr, "JSONRPC"),
"HTTP": cclient.NewClient(requestAddr, "HTTP"),
}
)
func decodeHex(hexStr string) []byte {
@@ -40,6 +43,7 @@ func decodeHex(hexStr string) []byte {
return bytes
}
// create a new node and sleep forever
func newNode(ready chan struct{}) {
// Create & start node
node = nm.NewNode()
@@ -56,6 +60,7 @@ func newNode(ready chan struct{}) {
<-ch
}
// initialize config and create new node
func init() {
rootDir := ".tendermint"
config.Init(rootDir)
@@ -84,64 +89,10 @@ func init() {
<-ready
}
func getAccount(t *testing.T, typ string, addr []byte) *account.Account {
var client cclient.Client
switch typ {
case "JSONRPC":
client = cclient.NewClient(requestAddr, "JSONRPC")
case "HTTP":
client = cclient.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 ctypes.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 +123,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 +151,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,93 +174,77 @@ 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 ctypes.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, ctypes.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 ctypes.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
mempoolCount += 1
return tx, resp.Receipt
}
// dump all storage for an account. currently unused
func dumpStorage(t *testing.T, addr []byte) ctypes.ResponseDumpStorage {
addrString := "\"" + hex.EncodeToString(addr) + "\""
var response struct {
Result ctypes.ResponseDumpStorage `json:"result"`
Error string `json:"error"`
Id string `json:"id"`
JSONRPC string `json:"jsonrpc"`
client := clients["HTTP"]
resp, err := client.DumpStorage(addr)
if err != nil {
t.Fatal(err)
}
requestResponse(t, "dump_storage", url.Values{"address": {addrString}}, &response)
if response.Error != "" {
t.Fatal(response.Error)
}
return response.Result
return *resp
}
func getStorage(t *testing.T, addr, slot []byte) []byte {
addrString := "\"" + hex.EncodeToString(addr) + "\""
slotString := "\"" + hex.EncodeToString(slot) + "\""
var response struct {
Result ctypes.ResponseGetStorage `json:"result"`
Error string `json:"error"`
Id string `json:"id"`
JSONRPC string `json:"jsonrpc"`
func getStorage(t *testing.T, typ string, addr, key []byte) []byte {
client := clients[typ]
resp, err := client.GetStorage(addr, key)
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
}
func callCode(t *testing.T, client cclient.Client, code, data, expected []byte) {
resp, err := client.CallCode(code, data)
if err != nil {
t.Fatal(err)
}
ret := resp.Return
// NOTE: we don't flip memory when it comes out of RETURN (?!)
if bytes.Compare(ret, LeftPadWord256(expected).Bytes()) != 0 {
t.Fatalf("Conflicting return value. Got %x, expected %x", ret, expected)
}
}
func callContract(t *testing.T, client cclient.Client, address, data, expected []byte) {
resp, err := client.Call(address, data)
if err != nil {
t.Fatal(err)
}
ret := resp.Return
// NOTE: we don't flip memory when it comes out of RETURN (?!)
if bytes.Compare(ret, LeftPadWord256(expected).Bytes()) != 0 {
t.Fatalf("Conflicting return value. Got %x, expected %x", ret, expected)
}
}
//--------------------------------------------------------------------------------
// 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!")

View File

@@ -1,166 +0,0 @@
package rpc
import (
"bytes"
"encoding/hex"
"fmt"
"github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/merkle"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"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")
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 ctypes.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)
return
}
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 response struct {
Result ctypes.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)
}
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)
}
}
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, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
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, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
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, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
}
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, receipt := broadcastTx(t, "HTTP", byteAddr, toAddr, nil, byteKey, amt, 0, 0)
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) != mempoolCount+1 {
t.Fatalf("The mem pool has %d txs. Expected %d", len(txs), mempoolCount+1)
}
tx2 := txs[mempoolCount].(*types.SendTx)
mempoolCount += 1
if bytes.Compare(merkle.HashFromBinary(tx), merkle.HashFromBinary(tx2)) != 0 {
t.Fatal("inconsistent hashes for mempool tx and sent tx")
}
}
func TestHTTPGetStorage(t *testing.T) {
priv := state.LoadPrivValidator(".tendermint/priv_validator.json")
_ = priv
//ctypes.SetPrivValidator(priv)
byteAddr, _ := hex.DecodeString(userAddr)
var byteKey [64]byte
oh, _ := hex.DecodeString(userPriv)
copy(byteKey[:], oh)
amt := uint64(1100)
code := []byte{0x60, 0x5, 0x60, 0x1, 0x55}
_, receipt := broadcastTx(t, "HTTP", byteAddr, nil, code, byteKey, amt, 1000, 1000)
if receipt.CreatesContract == 0 {
t.Fatal("This tx creates a contract")
}
if len(receipt.TxHash) == 0 {
t.Fatal("Failed to compute tx hash")
}
contractAddr := receipt.ContractAddr
if len(contractAddr) == 0 {
t.Fatal("Creates contract but resulting address is empty")
}
time.Sleep(time.Second * 20)
mempoolCount -= 1
v := getStorage(t, 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*/

View File

@@ -1,177 +0,0 @@
package rpc
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/tendermint/tendermint/binary"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/rpc"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/tendermint/tendermint/types"
"io/ioutil"
"net/http"
"net/url"
"testing"
)
func TestJSONStatus(t *testing.T) {
s := rpc.RPCRequest{
JSONRPC: "2.0",
Method: "status",
Params: []interface{}{},
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)
}
var response struct {
Result ctypes.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)
}
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")))
}
}
func TestJSONGenPriv(t *testing.T) {
s := rpc.RPCRequest{
JSONRPC: "2.0",
Method: "unsafe/gen_priv_account",
Params: []interface{}{},
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 response struct {
Result ctypes.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)
}
if len(response.Result.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, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
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, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
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, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
}
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, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
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 response struct {
Result ctypes.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)
}
receipt := response.Result.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) != mempoolCount+1 {
t.Fatalf("The mem pool has %d txs. Expected %d", len(txs), mempoolCount+1)
}
tx2 := txs[mempoolCount].(*types.SendTx)
mempoolCount += 1
if bytes.Compare(types.TxId(tx), types.TxId(tx2)) != 0 {
t.Fatal(Fmt("inconsistent hashes for mempool tx and sent tx: %v vs %v", tx, tx2))
}
}
/*tx.Inputs[0].Signature = mint.priv.PrivKey.Sign(account.SignBytes(tx))
err = mint.MempoolReactor.BroadcastTx(tx)
return hex.EncodeToString(merkle.HashFromBinary(tx)), err*/

200
rpc/test/tests.go Normal file
View File

@@ -0,0 +1,200 @@
package rpc
import (
"bytes"
"encoding/hex"
"fmt"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
"testing"
"time"
)
func testStatus(t *testing.T, typ string) {
client := clients[typ]
resp, err := client.Status()
if err != nil {
t.Fatal(err)
}
fmt.Println(">>>", resp)
if resp.Network != config.App().GetString("Network") {
t.Fatal(fmt.Errorf("Network mismatch: got %s expected %s",
resp.Network, config.App().Get("Network")))
}
}
func testGenPriv(t *testing.T, typ string) {
client := clients[typ]
resp, err := client.GenPrivAccount()
if err != nil {
t.Fatal(err)
}
fmt.Println(">>>", resp)
if len(resp.PrivAccount.Address) == 0 {
t.Fatal("Failed to generate an address")
}
}
func testGetAccount(t *testing.T, typ string) {
byteAddr, _ := hex.DecodeString(userAddr)
acc := getAccount(t, typ, 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)
}
}
func testSignedTx(t *testing.T, typ string) {
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, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
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, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
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, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
checkTx(t, byteAddr, priv, tx.(*types.SendTx))
}
func testBroadcastTx(t *testing.T, typ string) {
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, receipt := broadcastTx(t, typ, byteAddr, toAddr, nil, byteKey, amt, 0, 0)
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) != mempoolCount {
t.Fatalf("The mem pool has %d txs. Expected %d", len(txs), mempoolCount)
}
tx2 := txs[mempoolCount-1].(*types.SendTx)
n, err := new(int64), new(error)
buf1, buf2 := new(bytes.Buffer), new(bytes.Buffer)
tx.WriteSignBytes(buf1, n, err)
tx2.WriteSignBytes(buf2, n, err)
if bytes.Compare(buf1.Bytes(), buf2.Bytes()) != 0 {
t.Fatal("inconsistent hashes for mempool tx and sent tx")
}
}
func testGetStorage(t *testing.T, typ string) {
priv := state.LoadPrivValidator(".tendermint/priv_validator.json")
_ = priv
//core.SetPrivValidator(priv)
byteAddr, _ := hex.DecodeString(userAddr)
var byteKey [64]byte
oh, _ := hex.DecodeString(userPriv)
copy(byteKey[:], oh)
amt := uint64(1100)
code := []byte{0x60, 0x5, 0x60, 0x1, 0x55}
_, receipt := broadcastTx(t, typ, byteAddr, nil, code, byteKey, amt, 1000, 1000)
if receipt.CreatesContract == 0 {
t.Fatal("This tx creates a contract")
}
if len(receipt.TxHash) == 0 {
t.Fatal("Failed to compute tx hash")
}
contractAddr := receipt.ContractAddr
if len(contractAddr) == 0 {
t.Fatal("Creates contract but resulting address is empty")
}
// allow it to get mined
time.Sleep(time.Second * 20)
mempoolCount = 0
v := getStorage(t, typ, 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())
}
}
func testCallCode(t *testing.T, typ string) {
client := clients[typ]
// add two integers and return the result
code := []byte{0x60, 0x5, 0x60, 0x6, 0x1, 0x60, 0x0, 0x52, 0x60, 0x20, 0x60, 0x0, 0xf3}
data := []byte{}
expected := []byte{0xb}
callCode(t, client, code, data, expected)
// pass two ints as calldata, add, and return the result
code = []byte{0x60, 0x0, 0x35, 0x60, 0x20, 0x35, 0x1, 0x60, 0x0, 0x52, 0x60, 0x20, 0x60, 0x0, 0xf3}
data = append(LeftPadWord256([]byte{0x5}).Bytes(), LeftPadWord256([]byte{0x6}).Bytes()...)
expected = []byte{0xb}
callCode(t, client, code, data, expected)
}
func testCall(t *testing.T, typ string) {
client := clients[typ]
priv := state.LoadPrivValidator(".tendermint/priv_validator.json")
_ = priv
//core.SetPrivValidator(priv)
byteAddr, _ := hex.DecodeString(userAddr)
var byteKey [64]byte
oh, _ := hex.DecodeString(userPriv)
copy(byteKey[:], oh)
// create the contract
amt := uint64(6969)
// this is the code we want to run when the contract is called
contractCode := []byte{0x60, 0x5, 0x60, 0x6, 0x1, 0x60, 0x0, 0x52, 0x60, 0x20, 0x60, 0x0, 0xf3}
// the is the code we need to return the contractCode when the contract is initialized
lenCode := len(contractCode)
// push code to the stack
//code := append([]byte{byte(0x60 + lenCode - 1)}, LeftPadWord256(contractCode).Bytes()...)
code := append([]byte{0x7f}, RightPadWord256(contractCode).Bytes()...)
// store it in memory
code = append(code, []byte{0x60, 0x0, 0x52}...)
// return whats in memory
//code = append(code, []byte{0x60, byte(32 - lenCode), 0x60, byte(lenCode), 0xf3}...)
code = append(code, []byte{0x60, byte(lenCode), 0x60, 0x0, 0xf3}...)
_, receipt := broadcastTx(t, typ, byteAddr, nil, code, byteKey, amt, 1000, 1000)
if receipt.CreatesContract == 0 {
t.Fatal("This tx creates a contract")
}
if len(receipt.TxHash) == 0 {
t.Fatal("Failed to compute tx hash")
}
contractAddr := receipt.ContractAddr
if len(contractAddr) == 0 {
t.Fatal("Creates contract but resulting address is empty")
}
// allow it to get mined
time.Sleep(time.Second * 20)
mempoolCount = 0
// run a call through the contract
data := []byte{}
expected := []byte{0xb}
callContract(t, client, contractAddr, data, expected)
}