diff --git a/manager/eris-mint/eris-mint.go b/manager/eris-mint/eris-mint.go index 809540879b1d262b843adadcd544dff5126e609e..55d7374d175569234d9254301204f180e2502229 100644 --- a/manager/eris-mint/eris-mint.go +++ b/manager/eris-mint/eris-mint.go @@ -124,8 +124,7 @@ func (app *ErisMint) SetOption(key string, value string) (log string) { } // Implements manager/types.Application -func (app *ErisMint) AppendTx(txBytes []byte) (res tmsp.Result) { - +func (app *ErisMint) AppendTx(txBytes []byte) tmsp.Result { app.nTxs += 1 // XXX: if we had tx ids we could cache the decoded txs on CheckTx @@ -149,7 +148,7 @@ func (app *ErisMint) AppendTx(txBytes []byte) (res tmsp.Result) { } // Implements manager/types.Application -func (app *ErisMint) CheckTx(txBytes []byte) (res tmsp.Result) { +func (app *ErisMint) CheckTx(txBytes []byte) tmsp.Result { var n int var err error tx := new(txs.Tx) diff --git a/rpc/tendermint/client/client.go b/rpc/tendermint/client/client.go index 0758eb20f487ea230557acf905fe6a55738b6a3b..6be71caa662d34786d9e0ec7841e6652ca7f8725 100644 --- a/rpc/tendermint/client/client.go +++ b/rpc/tendermint/client/client.go @@ -137,6 +137,9 @@ func performCall(client rpcclient.Client, method string, _, err = cli.Call(method, paramsSlice, &res) case *rpcclient.ClientURI: _, err = cli.Call(method, paramsMap, &res) + default: + panic(fmt.Errorf("peformCall called against an unknown rpcclient.Client %v", + cli)) } return diff --git a/rpc/tendermint/test/client_rpc_test.go b/rpc/tendermint/test/client_rpc_test.go deleted file mode 100644 index 1a0a725df29d089b1180435a74e9df380f243a96..0000000000000000000000000000000000000000 --- a/rpc/tendermint/test/client_rpc_test.go +++ /dev/null @@ -1,118 +0,0 @@ -// +build integration - -// Space above here matters -package test - -import ( - "testing" - - // ctypes "github.com/eris-ltd/eris-db/rpc/core/types" - _ "github.com/tendermint/tendermint/config/tendermint_test" -) - -// When run with `-test.short` we only run: -// TestHTTPStatus, TestHTTPBroadcast, TestJSONStatus, TestJSONBroadcast, TestWSConnect, TestWSSend - -//-------------------------------------------------------------------------------- -func TestHTTPStatus(t *testing.T) { - testStatus(t, "HTTP") -} - -func TestHTTPGetAccount(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testGetAccount(t, "HTTP") -} - -func TestHTTPBroadcastTx(t *testing.T) { - testBroadcastTx(t, "HTTP") -} - -func TestHTTPGetStorage(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testGetStorage(t, "HTTP") -} - -func TestHTTPCallCode(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testCallCode(t, "HTTP") -} - -func TestHTTPCallContract(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testCall(t, "HTTP") -} - -func TestHTTPNameReg(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testNameReg(t, "HTTP") -} - -func TestHTTPBlockchainInfo(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testBlockchainInfo(t, "HTTP") -} - -//-------------------------------------------------------------------------------- -// Test the JSONRPC client - -func TestJSONStatus(t *testing.T) { - testStatus(t, "JSONRPC") -} - -func TestJSONGetAccount(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testGetAccount(t, "JSONRPC") -} - -func TestJSONBroadcastTx(t *testing.T) { - testBroadcastTx(t, "JSONRPC") -} - -func TestJSONGetStorage(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testGetStorage(t, "JSONRPC") -} - -func TestJSONCallCode(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testCallCode(t, "JSONRPC") -} - -func TestJSONCallContract(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testCall(t, "JSONRPC") -} - -func TestJSONNameReg(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testNameReg(t, "JSONRPC") -} - -func TestJSONBlockchainInfo(t *testing.T) { - if testing.Short() { - t.Skip("skipping test in short mode.") - } - testBlockchainInfo(t, "JSONRPC") -} diff --git a/rpc/tendermint/test/common.go b/rpc/tendermint/test/common.go index 211d3549991fccb6d68a0754f254609311a0591a..76909182df98801eab3e08db5b5c4bbfd03617cf 100644 --- a/rpc/tendermint/test/common.go +++ b/rpc/tendermint/test/common.go @@ -4,10 +4,10 @@ package test import ( - "github.com/eris-ltd/eris-db/test/fixtures" - rpc_core "github.com/eris-ltd/eris-db/rpc/tendermint/core" - "testing" "fmt" + + rpc_core "github.com/eris-ltd/eris-db/rpc/tendermint/core" + "github.com/eris-ltd/eris-db/test/fixtures" ) // Needs to be referenced by a *_test.go file to be picked up @@ -26,7 +26,7 @@ func TestWrapper(runner func() int) int { // start a node ready := make(chan error) server := make(chan *rpc_core.TendermintWebsocketServer) - defer func(){ + defer func() { // Shutdown -- make sure we don't hit a race on ffs.RemoveAll tmServer := <-server tmServer.Shutdown() @@ -48,9 +48,9 @@ func TestWrapper(runner func() int) int { // inconsequential, so feel free to insert your own code if you want to use it // as an application entry point for delve debugging. func DebugMain() { - t := &testing.T{} + //t := &testing.T{} TestWrapper(func() int { - testNameReg(t, "JSONRPC") + //testNameReg(t, "JSONRPC") return 0 }) } diff --git a/rpc/tendermint/test/rpc_client_test.go b/rpc/tendermint/test/rpc_client_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6c3b5887cd5e535bdd70520c3ecd637f6784f5f6 --- /dev/null +++ b/rpc/tendermint/test/rpc_client_test.go @@ -0,0 +1,329 @@ +// +build integration + +// Space above here matters +package test + +import ( + "bytes" + "fmt" + "testing" + + "golang.org/x/crypto/ripemd160" + + edbcli "github.com/eris-ltd/eris-db/rpc/tendermint/client" + "github.com/eris-ltd/eris-db/txs" + "github.com/stretchr/testify/assert" + tm_common "github.com/tendermint/go-common" + rpcclient "github.com/tendermint/go-rpc/client" + _ "github.com/tendermint/tendermint/config/tendermint_test" +) + +// When run with `-test.short` we only run: +// TestHTTPStatus, TestHTTPBroadcast, TestJSONStatus, TestJSONBroadcast, TestWSConnect, TestWSSend + +// Note: the reason that we have tests implemented in tests.go is I believe +// due to weirdness with go-wire's interface registration, and those global +// registrations not being available within a *_test.go runtime context. +func testWithAllClients(t *testing.T, + testFunction func(*testing.T, string, rpcclient.Client)) { + for clientName, client := range clients { + fmt.Printf("\x1b[47m\x1b[31mMARMOT DEBUG: Loop \x1b[0m\n") + testFunction(t, clientName, client) + } +} + +//-------------------------------------------------------------------------------- +func TestStatus(t *testing.T) { + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + resp, err := edbcli.Status(client) + if err != nil { + t.Fatal(err) + } + fmt.Println(resp) + if resp.NodeInfo.Network != chainID { + t.Fatal(fmt.Errorf("ChainID mismatch: got %s expected %s", + resp.NodeInfo.Network, chainID)) + } + }) +} + +func TestBroadcastTx(t *testing.T) { + wsc := newWSClient(t) + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + // Avoid duplicate Tx in mempool + amt := hashString(clientName) % 1000 + toAddr := user[1].Address + tx := makeDefaultSendTxSigned(t, client, toAddr, amt) + //receipt := broadcastTx(t, client, tx) + receipt, err := broadcastTxAndWaitForBlock(t, client,wsc, tx) + if err != nil { + t.Fatal(err) + } + 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") + } + n, errp := new(int), new(error) + buf := new(bytes.Buffer) + hasher := ripemd160.New() + tx.WriteSignBytes(chainID, buf, n, errp) + if *errp != nil { + t.Fatal(*errp) + } + txSignBytes := buf.Bytes() + hasher.Write(txSignBytes) + txHashExpected := hasher.Sum(nil) + if bytes.Compare(receipt.TxHash, txHashExpected) != 0 { + t.Fatalf("The receipt hash '%x' does not equal the ripemd160 hash of the "+ + "transaction signed bytes calculated in the test: '%x'", + receipt.TxHash, txHashExpected) + } + }) +} + +func TestGetAccount(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + acc := getAccount(t, client, user[0].Address) + if acc == nil { + t.Fatal("Account was nil") + } + if bytes.Compare(acc.Address, user[0].Address) != 0 { + t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, user[0].Address) + } + }) +} + +func TestGetStorage(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + wsc := newWSClient(t) + eid := txs.EventStringNewBlock() + subscribe(t, wsc, eid) + defer func() { + unsubscribe(t, wsc, eid) + wsc.Stop() + }() + + amt, gasLim, fee := int64(1100), int64(1000), int64(1000) + code := []byte{0x60, 0x5, 0x60, 0x1, 0x55} + // Call with nil address will create a contract + tx := makeDefaultCallTx(t, client, nil, code, amt, gasLim, fee) + receipt, err := broadcastTxAndWaitForBlock(t, client, wsc, tx) + if err != nil { + t.Fatalf("Problem broadcasting transaction: %v", err) + } + assert.Equal(t, uint8(1), receipt.CreatesContract, "This transaction should"+ + " create a contract") + assert.NotEqual(t, 0, len(receipt.TxHash), "Receipt should contain a"+ + " transaction hash") + contractAddr := receipt.ContractAddr + assert.NotEqual(t, 0, len(contractAddr), "Transactions claims to have"+ + " created a contract but the contract address is empty") + + v := getStorage(t, client, contractAddr, []byte{0x1}) + got := tm_common.LeftPadWord256(v) + expected := tm_common.LeftPadWord256([]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) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + // 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, user[0].PubKey.Address(), 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(tm_common.LeftPadWord256([]byte{0x5}).Bytes(), + tm_common.LeftPadWord256([]byte{0x6}).Bytes()...) + expected = []byte{0xb} + callCode(t, client, user[0].PubKey.Address(), code, data, expected) + }) +} + +func TestCallContract(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + wsc := newWSClient(t) + eid := txs.EventStringNewBlock() + subscribe(t, wsc, eid) + defer func() { + unsubscribe(t, wsc, eid) + wsc.Stop() + }() + + // create the contract + amt, gasLim, fee := int64(6969), int64(1000), int64(1000) + code, _, _ := simpleContract() + tx := makeDefaultCallTx(t, client, nil, code, amt, gasLim, fee) + receipt, err := broadcastTxAndWaitForBlock(t, client, wsc, tx) + if err != nil { + t.Fatalf("Problem broadcasting transaction: %v", err) + } + assert.Equal(t, uint8(1), receipt.CreatesContract, "This transaction should"+ + " create a contract") + assert.NotEqual(t, 0, len(receipt.TxHash), "Receipt should contain a"+ + " transaction hash") + contractAddr := receipt.ContractAddr + assert.NotEqual(t, 0, len(contractAddr), "Transactions claims to have"+ + " created a contract but the contract address is empty") + + // run a call through the contract + data := []byte{} + expected := []byte{0xb} + callContract(t, client, user[0].PubKey.Address(), contractAddr, data, expected) + }) +} + +func TestNameReg(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + wsc := newWSClient(t) + + txs.MinNameRegistrationPeriod = 1 + + // register a new name, check if its there + // since entries ought to be unique and these run against different clients, we append the client + name := "ye_old_domain_name_" + clientName + const data = "if not now, when" + fee := int64(1000) + numDesiredBlocks := int64(2) + amt := fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data) + + tx := makeDefaultNameTx(t, client, name, data, amt, fee) + // verify the name by both using the event and by checking get_name + subscribeAndWaitForNext(t, wsc, txs.EventStringNameReg(name), + func() { + broadcastTxAndWaitForBlock(t, client, wsc, tx) + }, + func(eid string, eventData txs.EventData) (bool, error) { + eventDataTx := asEventDataTx(t, eventData) + tx, ok := eventDataTx.Tx.(*txs.NameTx) + if !ok { + t.Fatalf("Could not convert %v to *NameTx", eventDataTx) + } + assert.Equal(t, name, tx.Name) + assert.Equal(t, data, tx.Data) + return true, nil + }) + mempoolCount = 0 + + entry := getNameRegEntry(t, client, name) + assert.Equal(t, data, entry.Data) + assert.Equal(t, user[0].Address, entry.Owner) + + // update the data as the owner, make sure still there + numDesiredBlocks = int64(5) + const updatedData = "these are amongst the things I wish to bestow upon " + + "the youth of generations come: a safe supply of honey, and a better " + + "money. For what else shall they need" + amt = fee + numDesiredBlocks*txs.NameByteCostMultiplier* + txs.NameBlockCostMultiplier*txs.NameBaseCost(name, updatedData) + tx = makeDefaultNameTx(t, client, name, updatedData, amt, fee) + broadcastTxAndWaitForBlock(t, client, wsc, tx) + mempoolCount = 0 + entry = getNameRegEntry(t, client, name) + + assert.Equal(t, updatedData, entry.Data) + + // try to update as non owner, should fail + tx = txs.NewNameTxWithNonce(user[1].PubKey, name, "never mind", amt, fee, + getNonce(t, client, user[1].Address)+1) + tx.Sign(chainID, user[1]) + + _, err := broadcastTxAndWaitForBlock(t, client, wsc, tx) + assert.Error(t, err, "Expected error when updating someone else's unexpired"+ + " name registry entry") + if err != nil { + assert.Contains(t, err.Error(), "permission denied", "Error should be "+ + "permission denied") + } + + // Wait a couple of blocks to make sure name registration expires + waitNBlocks(t, wsc, 3) + + //now the entry should be expired, so we can update as non owner + const data2 = "this is not my beautiful house" + tx = txs.NewNameTxWithNonce(user[1].PubKey, name, data2, amt, fee, + getNonce(t, client, user[1].Address)+1) + tx.Sign(chainID, user[1]) + _, err = broadcastTxAndWaitForBlock(t, client, wsc, tx) + assert.NoError(t, err, "Should be able to update a previously expired name"+ + " registry entry as a different address") + mempoolCount = 0 + entry = getNameRegEntry(t, client, name) + assert.Equal(t, data2, entry.Data) + assert.Equal(t, user[1].Address, entry.Owner) + }) +} + +func TestBlockchainInfo(t *testing.T) { + testWithAllClients(t, func(t *testing.T, clientName string, client rpcclient.Client) { + wsc := newWSClient(t) + nBlocks := 4 + waitNBlocks(t, wsc, nBlocks) + + resp, err := edbcli.BlockchainInfo(client, 0, 0) + if err != nil { + t.Fatalf("Failed to get blockchain info: %v", err) + } + //TODO: [Silas] reintroduce this when Tendermint changes logic to fire + // NewBlock after saving a block + // see https://github.com/tendermint/tendermint/issues/273 + //assert.Equal(t, 4, resp.LastHeight, "Last height should be 4 after waiting for first 4 blocks") + assert.True(t, nBlocks <= len(resp.BlockMetas), + "Should see at least 4 BlockMetas after waiting for first 4 blocks") + + lastBlockHash := resp.BlockMetas[nBlocks-1].Hash + for i := nBlocks - 2; i >= 0; i-- { + assert.Equal(t, lastBlockHash, resp.BlockMetas[i].Header.LastBlockHash, + "Blockchain should be a hash tree!") + lastBlockHash = resp.BlockMetas[i].Hash + } + + resp, err = edbcli.BlockchainInfo(client, 1, 2) + if err != nil { + t.Fatalf("Failed to get blockchain info: %v", err) + } + + assert.Equal(t, 2, len(resp.BlockMetas), + "Should see 2 BlockMetas after extracting 2 blocks") + }) +} + +func TestListUnconfirmedTxs(t *testing.T) { + if testing.Short() { + t.Skip("skipping test in short mode.") + } +} + +func asEventDataTx(t *testing.T, eventData txs.EventData) txs.EventDataTx { + eventDataTx, ok := eventData.(txs.EventDataTx) + if !ok { + t.Fatalf("Expected eventData to be EventDataTx was %v", eventData) + } + return eventDataTx +} diff --git a/rpc/tendermint/test/shared.go b/rpc/tendermint/test/shared.go index d705d27857ecc5db7223f5ecddf5cb3d31a91c5b..0b9254f7a1aeb99f2cab905e1be55df91465900e 100644 --- a/rpc/tendermint/test/shared.go +++ b/rpc/tendermint/test/shared.go @@ -2,6 +2,7 @@ package test import ( "bytes" + "hash/fnv" "strconv" "testing" @@ -34,8 +35,10 @@ var ( websocketAddr string websocketEndpoint string - user = makeUsers(5) // make keys - clients map[string]rpcclient.Client + user = makeUsers(5) // make keys + jsonRpcClient rpcclient.Client + httpClient rpcclient.Client + clients map[string]rpcclient.Client testCore *core.Core ) @@ -85,9 +88,12 @@ func initGlobalVariables(ffs *fixtures.FileFixtures) error { return err } + jsonRpcClient = rpcclient.NewClientJSONRPC(rpcAddr) + httpClient = rpcclient.NewClientURI(rpcAddr) + clients = map[string]rpcclient.Client{ - "JSONRPC": rpcclient.NewClientURI(rpcAddr), - "HTTP": rpcclient.NewClientJSONRPC(rpcAddr), + "JSONRPC": jsonRpcClient, + "HTTP": httpClient, } return nil } @@ -125,34 +131,34 @@ func saveNewPriv() { //------------------------------------------------------------------------------- // some default transaction functions -func makeDefaultSendTx(t *testing.T, typ string, addr []byte, +func makeDefaultSendTx(t *testing.T, client rpcclient.Client, addr []byte, amt int64) *txs.SendTx { - nonce := getNonce(t, typ, user[0].Address) + nonce := getNonce(t, client, user[0].Address) tx := txs.NewSendTx() tx.AddInputWithNonce(user[0].PubKey, amt, nonce+1) tx.AddOutput(addr, amt) return tx } -func makeDefaultSendTxSigned(t *testing.T, typ string, addr []byte, +func makeDefaultSendTxSigned(t *testing.T, client rpcclient.Client, addr []byte, amt int64) *txs.SendTx { - tx := makeDefaultSendTx(t, typ, addr, amt) + tx := makeDefaultSendTx(t, client, addr, amt) tx.SignInput(chainID, 0, user[0]) return tx } -func makeDefaultCallTx(t *testing.T, typ string, addr, code []byte, amt, gasLim, +func makeDefaultCallTx(t *testing.T, client rpcclient.Client, addr, code []byte, amt, gasLim, fee int64) *txs.CallTx { - nonce := getNonce(t, typ, user[0].Address) + nonce := getNonce(t, client, user[0].Address) tx := txs.NewCallTxWithNonce(user[0].PubKey, addr, code, amt, gasLim, fee, nonce+1) tx.Sign(chainID, user[0]) return tx } -func makeDefaultNameTx(t *testing.T, typ string, name, value string, amt, +func makeDefaultNameTx(t *testing.T, client rpcclient.Client, name, value string, amt, fee int64) *txs.NameTx { - nonce := getNonce(t, typ, user[0].Address) + nonce := getNonce(t, client, user[0].Address) tx := txs.NewNameTxWithNonce(user[0].PubKey, name, value, amt, fee, nonce+1) tx.Sign(chainID, user[0]) return tx @@ -162,8 +168,7 @@ func makeDefaultNameTx(t *testing.T, typ string, name, value string, amt, // rpc call wrappers (fail on err) // get an account's nonce -func getNonce(t *testing.T, typ string, addr []byte) int { - client := clients[typ] +func getNonce(t *testing.T, client rpcclient.Client, addr []byte) int { ac, err := edbcli.GetAccount(client, addr) if err != nil { t.Fatal(err) @@ -175,8 +180,7 @@ func getNonce(t *testing.T, typ string, addr []byte) int { } // get the account -func getAccount(t *testing.T, typ string, addr []byte) *acm.Account { - client := clients[typ] +func getAccount(t *testing.T, client rpcclient.Client, addr []byte) *acm.Account { ac, err := edbcli.GetAccount(client, addr) if err != nil { t.Fatal(err) @@ -185,9 +189,8 @@ func getAccount(t *testing.T, typ string, addr []byte) *acm.Account { } // sign transaction -func signTx(t *testing.T, typ string, tx txs.Tx, +func signTx(t *testing.T, client rpcclient.Client, tx txs.Tx, privAcc *acm.PrivAccount) txs.Tx { - client := clients[typ] signedTx, err := edbcli.SignTx(client, tx, []*acm.PrivAccount{privAcc}) if err != nil { t.Fatal(err) @@ -196,8 +199,7 @@ func signTx(t *testing.T, typ string, tx txs.Tx, } // broadcast transaction -func broadcastTx(t *testing.T, typ string, tx txs.Tx) txs.Receipt { - client := clients[typ] +func broadcastTx(t *testing.T, client rpcclient.Client, tx txs.Tx) txs.Receipt { rec, err := edbcli.BroadcastTx(client, tx) if err != nil { t.Fatal(err) @@ -216,8 +218,7 @@ func dumpStorage(t *testing.T, addr []byte) *rpc_types.ResultDumpStorage { return resp } -func getStorage(t *testing.T, typ string, addr, key []byte) []byte { - client := clients[typ] +func getStorage(t *testing.T, client rpcclient.Client, addr, key []byte) []byte { resp, err := edbcli.GetStorage(client, addr, key) if err != nil { t.Fatal(err) @@ -252,8 +253,7 @@ func callContract(t *testing.T, client rpcclient.Client, fromAddress, toAddress, } // get the namereg entry -func getNameRegEntry(t *testing.T, typ string, name string) *core_types.NameRegEntry { - client := clients[typ] +func getNameRegEntry(t *testing.T, client rpcclient.Client, name string) *core_types.NameRegEntry { entry, err := edbcli.GetName(client, name) if err != nil { t.Fatal(err) @@ -261,29 +261,21 @@ func getNameRegEntry(t *testing.T, typ string, name string) *core_types.NameRegE return entry } -//-------------------------------------------------------------------------------- -// utility verification function - -func checkTx(t *testing.T, fromAddr []byte, priv *acm.PrivAccount, - tx *txs.SendTx) { - if bytes.Compare(tx.Inputs[0].Address, fromAddr) != 0 { - t.Fatal("Tx input addresses don't match!") - } - - signBytes := acm.SignBytes(chainID, tx) - in := tx.Inputs[0] //(*types.SendTx).Inputs[0] - - if err := in.ValidateBasic(); err != nil { - t.Fatal(err) - } - // Check signatures - // acc := getAccount(t, byteAddr) - // NOTE: using the acc here instead of the in fails; it is nil. - if !in.PubKey.VerifyBytes(signBytes, in.Signature) { - t.Fatal(txs.ErrTxInvalidSignature) +// Returns a positive int64 hash of text (consumers want int64 instead of uint64) +func hashString(text string) int64 { + hasher := fnv.New64() + hasher.Write([]byte(text)) + value := int64(hasher.Sum64()) + // Flip the sign if we wrapped + if value < 0 { + return -value } + return value } +//-------------------------------------------------------------------------------- +// utility verification function + // simple contract returns 5 + 6 = 0xb func simpleContract() ([]byte, []byte, []byte) { // this is the code we want to run when the contract is called diff --git a/rpc/tendermint/test/tests.go b/rpc/tendermint/test/tests.go deleted file mode 100644 index 43769b4b0f6f972c151b41c35ed2269ab9ad7a40..0000000000000000000000000000000000000000 --- a/rpc/tendermint/test/tests.go +++ /dev/null @@ -1,342 +0,0 @@ -package test - -import ( - "bytes" - "fmt" - "testing" - - edbcli "github.com/eris-ltd/eris-db/rpc/tendermint/client" - core_types "github.com/eris-ltd/eris-db/rpc/tendermint/core/types" - "github.com/eris-ltd/eris-db/txs" - "github.com/stretchr/testify/assert" - - "time" - - tm_common "github.com/tendermint/go-common" - "golang.org/x/crypto/ripemd160" -) - -func testStatus(t *testing.T, typ string) { - client := clients[typ] - resp, err := edbcli.Status(client) - if err != nil { - t.Fatal(err) - } - fmt.Println(resp) - if resp.NodeInfo.Network != chainID { - t.Fatal(fmt.Errorf("ChainID mismatch: got %s expected %s", - resp.NodeInfo.Network, chainID)) - } -} - -func testGetAccount(t *testing.T, typ string) { - acc := getAccount(t, typ, user[0].Address) - if acc == nil { - t.Fatal("Account was nil") - } - if bytes.Compare(acc.Address, user[0].Address) != 0 { - t.Fatalf("Failed to get correct account. Got %x, expected %x", acc.Address, user[0].Address) - } -} - -func testOneSignTx(t *testing.T, typ string, addr []byte, amt int64) { - tx := makeDefaultSendTx(t, typ, addr, amt) - tx2 := signTx(t, typ, tx, user[0]) - tx2hash := txs.TxHash(chainID, tx2) - tx.SignInput(chainID, 0, user[0]) - txhash := txs.TxHash(chainID, tx) - if bytes.Compare(txhash, tx2hash) != 0 { - t.Fatal("Got different signatures for signing via rpc vs tx_utils") - } - - tx_ := signTx(t, typ, tx, user[0]) - tx = tx_.(*txs.SendTx) - checkTx(t, user[0].Address, user[0], tx) -} - -func testBroadcastTx(t *testing.T, typ string) { - amt := int64(100) - toAddr := user[1].Address - tx := makeDefaultSendTxSigned(t, typ, toAddr, amt) - receipt := broadcastTx(t, typ, tx) - 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") - } - n, err := new(int), new(error) - buf := new(bytes.Buffer) - hasher := ripemd160.New() - tx.WriteSignBytes(chainID, buf, n, err) - // [Silas] Currently tx.TxHash uses go-wire, we we drop that we can drop the prefix here - goWireBytes := append([]byte{0x01, 0xcf}, buf.Bytes()...) - hasher.Write(goWireBytes) - txHashExpected := hasher.Sum(nil) - if bytes.Compare(receipt.TxHash, txHashExpected) != 0 { - t.Fatalf("The receipt hash '%x' does not equal the ripemd160 hash of the "+ - "transaction signed bytes calculated in the test: '%x'", - receipt.TxHash, txHashExpected) - } -} - -func testGetStorage(t *testing.T, typ string) { - wsc := newWSClient(t) - eid := txs.EventStringNewBlock() - subscribe(t, wsc, eid) - defer func() { - unsubscribe(t, wsc, eid) - wsc.Stop() - }() - - amt, gasLim, fee := int64(1100), int64(1000), int64(1000) - code := []byte{0x60, 0x5, 0x60, 0x1, 0x55} - // Call with nil address will create a contract - tx := makeDefaultCallTx(t, typ, nil, code, amt, gasLim, fee) - receipt, err := broadcastTxAndWaitForBlock(t, typ, wsc, tx) - if err != nil { - t.Fatalf("Problem broadcasting transaction: %v", err) - } - assert.Equal(t, uint8(1), receipt.CreatesContract, "This transaction should"+ - " create a contract") - assert.NotEqual(t, 0, len(receipt.TxHash), "Receipt should contain a"+ - " transaction hash") - contractAddr := receipt.ContractAddr - assert.NotEqual(t, 0, len(contractAddr), "Transactions claims to have"+ - " created a contract but the contract address is empty") - - v := getStorage(t, typ, contractAddr, []byte{0x1}) - got := tm_common.LeftPadWord256(v) - expected := tm_common.LeftPadWord256([]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, user[0].PubKey.Address(), 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(tm_common.LeftPadWord256([]byte{0x5}).Bytes(), - tm_common.LeftPadWord256([]byte{0x6}).Bytes()...) - expected = []byte{0xb} - callCode(t, client, user[0].PubKey.Address(), code, data, expected) -} - -func testCall(t *testing.T, typ string) { - wsc := newWSClient(t) - eid := txs.EventStringNewBlock() - subscribe(t, wsc, eid) - defer func() { - unsubscribe(t, wsc, eid) - wsc.Stop() - }() - - client := clients[typ] - - // create the contract - amt, gasLim, fee := int64(6969), int64(1000), int64(1000) - code, _, _ := simpleContract() - tx := makeDefaultCallTx(t, typ, nil, code, amt, gasLim, fee) - receipt, err := broadcastTxAndWaitForBlock(t, typ, wsc, tx) - if err != nil { - t.Fatalf("Problem broadcasting transaction: %v", err) - } - assert.Equal(t, uint8(1), receipt.CreatesContract, "This transaction should"+ - " create a contract") - assert.NotEqual(t, 0, len(receipt.TxHash), "Receipt should contain a"+ - " transaction hash") - contractAddr := receipt.ContractAddr - assert.NotEqual(t, 0, len(contractAddr), "Transactions claims to have"+ - " created a contract but the contract address is empty") - - // run a call through the contract - data := []byte{} - expected := []byte{0xb} - callContract(t, client, user[0].PubKey.Address(), contractAddr, data, expected) -} - -func testNameReg(t *testing.T, typ string) { - wsc := newWSClient(t) - - txs.MinNameRegistrationPeriod = 1 - - // register a new name, check if its there - // since entries ought to be unique and these run against different clients, we append the typ - name := "ye_old_domain_name_" + typ - const data = "if not now, when" - fee := int64(1000) - numDesiredBlocks := int64(2) - amt := fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data) - - tx := makeDefaultNameTx(t, typ, name, data, amt, fee) - // verify the name by both using the event and by checking get_name - subscribeAndWaitForNext(t, wsc, txs.EventStringNameReg(name), - func() { - broadcastTxAndWaitForBlock(t, typ, wsc, tx) - }, - func(eid string, eventData txs.EventData) (bool, error) { - eventDataTx := asEventDataTx(t, eventData) - tx, ok := eventDataTx.Tx.(*txs.NameTx) - if !ok { - t.Fatalf("Could not convert %v to *NameTx", eventDataTx) - } - assert.Equal(t, name, tx.Name) - assert.Equal(t, data, tx.Data) - return true, nil - }) - mempoolCount = 0 - - entry := getNameRegEntry(t, typ, name) - assert.Equal(t, data, entry.Data) - assert.Equal(t, user[0].Address, entry.Owner) - - // update the data as the owner, make sure still there - numDesiredBlocks = int64(5) - const updatedData = "these are amongst the things I wish to bestow upon the youth of generations come: a safe supply of honey, and a better money. For what else shall they need" - amt = fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, updatedData) - tx = makeDefaultNameTx(t, typ, name, updatedData, amt, fee) - broadcastTxAndWaitForBlock(t, typ, wsc, tx) - mempoolCount = 0 - entry = getNameRegEntry(t, typ, name) - - assert.Equal(t, updatedData, entry.Data) - - // try to update as non owner, should fail - tx = txs.NewNameTxWithNonce(user[1].PubKey, name, "never mind", amt, fee, - getNonce(t, typ, user[1].Address)+1) - tx.Sign(chainID, user[1]) - - _, err := broadcastTxAndWaitForBlock(t, typ, wsc, tx) - assert.Error(t, err, "Expected error when updating someone else's unexpired"+ - " name registry entry") - assert.Contains(t, err.Error(), "permission denied", "Error should be " + - "permission denied") - - // Wait a couple of blocks to make sure name registration expires - waitNBlocks(t, wsc, 3) - - //now the entry should be expired, so we can update as non owner - const data2 = "this is not my beautiful house" - tx = txs.NewNameTxWithNonce(user[1].PubKey, name, data2, amt, fee, - getNonce(t, typ, user[1].Address)+1) - tx.Sign(chainID, user[1]) - _, err = broadcastTxAndWaitForBlock(t, typ, wsc, tx) - assert.NoError(t, err, "Should be able to update a previously expired name"+ - " registry entry as a different address") - mempoolCount = 0 - entry = getNameRegEntry(t, typ, name) - assert.Equal(t, data2, entry.Data) - assert.Equal(t, user[1].Address, entry.Owner) -} - -// ------ Test Utils ------- - -func asEventDataTx(t *testing.T, eventData txs.EventData) txs.EventDataTx { - eventDataTx, ok := eventData.(txs.EventDataTx) - if !ok { - t.Fatalf("Expected eventData to be EventDataTx was %v", eventData) - } - return eventDataTx -} - -func doNothing(_ string, _ txs.EventData) (bool, error) { - // And ask waitForEvent to stop waiting - return true, nil -} - -func testSubscribe(t *testing.T) { - var subId string - wsc := newWSClient(t) - subscribe(t, wsc, txs.EventStringNewBlock()) - - timeout := time.NewTimer(timeoutSeconds * time.Second) -Subscribe: - for { - select { - case <-timeout.C: - t.Fatal("Timed out waiting for subscription result") - - case bs := <-wsc.ResultsCh: - resultSubscribe, ok := readResult(t, bs).(*core_types.ResultSubscribe) - if ok { - assert.Equal(t, txs.EventStringNewBlock(), resultSubscribe.Event) - subId = resultSubscribe.SubscriptionId - break Subscribe - } - } - } - - seenBlock := false - timeout = time.NewTimer(timeoutSeconds * time.Second) - for { - select { - case <-timeout.C: - if !seenBlock { - t.Fatal("Timed out without seeing a NewBlock event") - } - return - - case bs := <-wsc.ResultsCh: - resultEvent, ok := readResult(t, bs).(*core_types.ResultEvent) - if ok { - _, ok := resultEvent.Data.(txs.EventDataNewBlock) - if ok { - if seenBlock { - // There's a mild race here, but when we enter we've just seen a block - // so we should be able to unsubscribe before we see another block - t.Fatal("Continued to see NewBlock event after unsubscribing") - } else { - seenBlock = true - unsubscribe(t, wsc, subId) - } - } - } - } - } -} - -func testBlockchainInfo(t *testing.T, typ string) { - client := clients[typ] - wsc := newWSClient(t) - nBlocks := 4 - waitNBlocks(t, wsc, nBlocks) - - resp, err := edbcli.BlockchainInfo(client, 0, 0) - if err != nil { - t.Fatalf("Failed to get blockchain info: %v", err) - } - //TODO: [Silas] reintroduce this when Tendermint changes logic to fire - // NewBlock after saving a block - // see https://github.com/tendermint/tendermint/issues/273 - //assert.Equal(t, 4, resp.LastHeight, "Last height should be 4 after waiting for first 4 blocks") - assert.True(t, nBlocks <= len(resp.BlockMetas), - "Should see at least 4 BlockMetas after waiting for first 4 blocks") - - lastBlockHash := resp.BlockMetas[nBlocks-1].Hash - for i := nBlocks - 2; i >= 0; i-- { - assert.Equal(t, lastBlockHash, resp.BlockMetas[i].Header.LastBlockHash, - "Blockchain should be a hash tree!") - lastBlockHash = resp.BlockMetas[i].Hash - } - - resp, err = edbcli.BlockchainInfo(client, 1, 2) - if err != nil { - t.Fatalf("Failed to get blockchain info: %v", err) - } - - assert.Equal(t, 2, len(resp.BlockMetas), - "Should see 2 BlockMetas after extracting 2 blocks") - - fmt.Printf("%v\n", resp) -} diff --git a/rpc/tendermint/test/client_ws_test.go b/rpc/tendermint/test/websocket_client_test.go similarity index 72% rename from rpc/tendermint/test/client_ws_test.go rename to rpc/tendermint/test/websocket_client_test.go index 76c61fde59a4bf39d5973a3981c14333f3433e37..f10ae1e68687c49da1f712a8a7614c83c85713f4 100644 --- a/rpc/tendermint/test/client_ws_test.go +++ b/rpc/tendermint/test/websocket_client_test.go @@ -7,13 +7,14 @@ import ( "fmt" "testing" + "time" + + core_types "github.com/eris-ltd/eris-db/rpc/tendermint/core/types" "github.com/eris-ltd/eris-db/txs" "github.com/stretchr/testify/assert" _ "github.com/tendermint/tendermint/config/tendermint_test" ) -var wsTyp = "JSONRPC" - //-------------------------------------------------------------------------------- // Test the websocket service @@ -91,8 +92,8 @@ func TestWSSend(t *testing.T) { wsc.Stop() }() waitForEvent(t, wsc, eidInput, func() { - tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt) - broadcastTx(t, wsTyp, tx) + tx := makeDefaultSendTxSigned(t, jsonRpcClient, toAddr, amt) + broadcastTx(t, jsonRpcClient, tx) }, unmarshalValidateSend(amt, toAddr)) waitForEvent(t, wsc, eidOutput, func() {}, @@ -115,8 +116,8 @@ func TestWSDoubleFire(t *testing.T) { toAddr := user[1].Address // broadcast the transaction, wait to hear about it waitForEvent(t, wsc, eid, func() { - tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt) - broadcastTx(t, wsTyp, tx) + tx := makeDefaultSendTxSigned(t, jsonRpcClient, toAddr, amt) + broadcastTx(t, jsonRpcClient, tx) }, func(eid string, b txs.EventData) (bool, error) { return true, nil }) @@ -147,8 +148,8 @@ func TestWSCallWait(t *testing.T) { var contractAddr []byte // wait for the contract to be created waitForEvent(t, wsc, eid1, func() { - tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) - receipt := broadcastTx(t, wsTyp, tx) + tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee) + receipt := broadcastTx(t, jsonRpcClient, tx) contractAddr = receipt.ContractAddr }, unmarshalValidateTx(amt, returnCode)) @@ -162,8 +163,8 @@ func TestWSCallWait(t *testing.T) { // get the return value from a call data := []byte{0x1} waitForEvent(t, wsc, eid2, func() { - tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee) - receipt := broadcastTx(t, wsTyp, tx) + tx := makeDefaultCallTx(t, jsonRpcClient, contractAddr, data, amt, gasLim, fee) + receipt := broadcastTx(t, jsonRpcClient, tx) contractAddr = receipt.ContractAddr }, unmarshalValidateTx(amt, returnVal)) } @@ -178,8 +179,8 @@ func TestWSCallNoWait(t *testing.T) { amt, gasLim, fee := int64(10000), int64(1000), int64(1000) code, _, returnVal := simpleContract() - tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) - receipt := broadcastTx(t, wsTyp, tx) + tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee) + receipt := broadcastTx(t, jsonRpcClient, tx) contractAddr := receipt.ContractAddr // susbscribe to the new contract @@ -193,8 +194,8 @@ func TestWSCallNoWait(t *testing.T) { // get the return value from a call data := []byte{0x1} waitForEvent(t, wsc, eid, func() { - tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee) - broadcastTx(t, wsTyp, tx) + tx := makeDefaultCallTx(t, jsonRpcClient, contractAddr, data, amt, gasLim, fee) + broadcastTx(t, jsonRpcClient, tx) }, unmarshalValidateTx(amt, returnVal)) } @@ -209,13 +210,13 @@ func TestWSCallCall(t *testing.T) { txid := new([]byte) // deploy the two contracts - tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) - receipt := broadcastTx(t, wsTyp, tx) + tx := makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee) + receipt := broadcastTx(t, jsonRpcClient, tx) contractAddr1 := receipt.ContractAddr code, _, _ = simpleCallContract(contractAddr1) - tx = makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee) - receipt = broadcastTx(t, wsTyp, tx) + tx = makeDefaultCallTx(t, jsonRpcClient, nil, code, amt, gasLim, fee) + receipt = broadcastTx(t, jsonRpcClient, tx) contractAddr2 := receipt.ContractAddr // subscribe to the new contracts @@ -235,12 +236,59 @@ func TestWSCallCall(t *testing.T) { }) // call it waitForEvent(t, wsc, eid, func() { - tx := makeDefaultCallTx(t, wsTyp, contractAddr2, nil, amt, gasLim, fee) - broadcastTx(t, wsTyp, tx) + tx := makeDefaultCallTx(t, jsonRpcClient, contractAddr2, nil, amt, gasLim, fee) + broadcastTx(t, jsonRpcClient, tx) *txid = txs.TxHash(chainID, tx) }, unmarshalValidateCall(user[0].Address, returnVal, txid)) } func TestSubscribe(t *testing.T) { - testSubscribe(t) + var subId string + wsc := newWSClient(t) + subscribe(t, wsc, txs.EventStringNewBlock()) + + timeout := time.NewTimer(timeoutSeconds * time.Second) +Subscribe: + for { + select { + case <-timeout.C: + t.Fatal("Timed out waiting for subscription result") + + case bs := <-wsc.ResultsCh: + resultSubscribe, ok := readResult(t, bs).(*core_types.ResultSubscribe) + if ok { + assert.Equal(t, txs.EventStringNewBlock(), resultSubscribe.Event) + subId = resultSubscribe.SubscriptionId + break Subscribe + } + } + } + + seenBlock := false + timeout = time.NewTimer(timeoutSeconds * time.Second) + for { + select { + case <-timeout.C: + if !seenBlock { + t.Fatal("Timed out without seeing a NewBlock event") + } + return + + case bs := <-wsc.ResultsCh: + resultEvent, ok := readResult(t, bs).(*core_types.ResultEvent) + if ok { + _, ok := resultEvent.Data.(txs.EventDataNewBlock) + if ok { + if seenBlock { + // There's a mild race here, but when we enter we've just seen a block + // so we should be able to unsubscribe before we see another block + t.Fatal("Continued to see NewBlock event after unsubscribing") + } else { + seenBlock = true + unsubscribe(t, wsc, subId) + } + } + } + } + } } diff --git a/rpc/tendermint/test/ws_helpers.go b/rpc/tendermint/test/websocket_helpers.go similarity index 75% rename from rpc/tendermint/test/ws_helpers.go rename to rpc/tendermint/test/websocket_helpers.go index 1c71a72b812193f75004e8886e562b090c2f6d83..ef34569c31c100fdd4ba9712fef7d86ab7d7286b 100644 --- a/rpc/tendermint/test/ws_helpers.go +++ b/rpc/tendermint/test/websocket_helpers.go @@ -2,20 +2,16 @@ package test import ( "bytes" - "encoding/json" "fmt" "testing" "time" ctypes "github.com/eris-ltd/eris-db/rpc/tendermint/core/types" "github.com/eris-ltd/eris-db/txs" - "github.com/tendermint/tendermint/types" tm_types "github.com/tendermint/tendermint/types" edbcli "github.com/eris-ltd/eris-db/rpc/tendermint/client" - "github.com/tendermint/go-events" - client "github.com/tendermint/go-rpc/client" - rpctypes "github.com/tendermint/go-rpc/types" + rpcclient "github.com/tendermint/go-rpc/client" "github.com/tendermint/go-wire" ) @@ -27,8 +23,8 @@ const ( // Utilities for testing the websocket service // create a new connection -func newWSClient(t *testing.T) *client.WSClient { - wsc := client.NewWSClient(websocketAddr, websocketEndpoint) +func newWSClient(t *testing.T) *rpcclient.WSClient { + wsc := rpcclient.NewWSClient(websocketAddr, websocketEndpoint) if _, err := wsc.Start(); err != nil { t.Fatal(err) } @@ -36,13 +32,13 @@ func newWSClient(t *testing.T) *client.WSClient { } // subscribe to an event -func subscribe(t *testing.T, wsc *client.WSClient, eventId string) { +func subscribe(t *testing.T, wsc *rpcclient.WSClient, eventId string) { if err := wsc.Subscribe(eventId); err != nil { t.Fatal(err) } } -func subscribeAndGetSubscriptionId(t *testing.T, wsc *client.WSClient, +func subscribeAndGetSubscriptionId(t *testing.T, wsc *rpcclient.WSClient, eventId string) string { if err := wsc.Subscribe(eventId); err != nil { t.Fatal(err) @@ -63,14 +59,14 @@ func subscribeAndGetSubscriptionId(t *testing.T, wsc *client.WSClient, } // unsubscribe from an event -func unsubscribe(t *testing.T, wsc *client.WSClient, subscriptionId string) { +func unsubscribe(t *testing.T, wsc *rpcclient.WSClient, subscriptionId string) { if err := wsc.Unsubscribe(subscriptionId); err != nil { t.Fatal(err) } } // broadcast transaction and wait for new block -func broadcastTxAndWaitForBlock(t *testing.T, typ string, wsc *client.WSClient, +func broadcastTxAndWaitForBlock(t *testing.T, client rpcclient.Client, wsc *rpcclient.WSClient, tx txs.Tx) (txs.Receipt, error) { var rec txs.Receipt var err error @@ -86,17 +82,17 @@ func broadcastTxAndWaitForBlock(t *testing.T, typ string, wsc *client.WSClient, // state updates, so we have to wait for the block after the block we // want in order for the Tx to be genuinely final. // This should be addressed by: https://github.com/tendermint/tendermint/pull/265 - return block.Height > initialHeight + 1 + return block.Height > initialHeight+1 } }, func() { - rec, err = edbcli.BroadcastTx(clients[typ], tx) + rec, err = edbcli.BroadcastTx(client, tx) mempoolCount += 1 }) return rec, err } -func waitNBlocks(t *testing.T, wsc *client.WSClient, n int) { +func waitNBlocks(t *testing.T, wsc *rpcclient.WSClient, n int) { i := 0 runThenWaitForBlock(t, wsc, func(block *tm_types.Block) bool { @@ -106,7 +102,7 @@ func waitNBlocks(t *testing.T, wsc *client.WSClient, n int) { func() {}) } -func runThenWaitForBlock(t *testing.T, wsc *client.WSClient, +func runThenWaitForBlock(t *testing.T, wsc *rpcclient.WSClient, blockPredicate func(*tm_types.Block) bool, runner func()) { subscribeAndWaitForNext(t, wsc, txs.EventStringNewBlock(), runner, @@ -115,7 +111,7 @@ func runThenWaitForBlock(t *testing.T, wsc *client.WSClient, }) } -func subscribeAndWaitForNext(t *testing.T, wsc *client.WSClient, event string, +func subscribeAndWaitForNext(t *testing.T, wsc *rpcclient.WSClient, event string, runner func(), eventDataChecker func(string, txs.EventData) (bool, error)) { subId := subscribeAndGetSubscriptionId(t, wsc, event) @@ -134,7 +130,7 @@ func subscribeAndWaitForNext(t *testing.T, wsc *client.WSClient, event string, // stopWaiting is true waitForEvent will return or if stopWaiting is false // waitForEvent will keep listening for new events. If an error is returned // waitForEvent will fail the test. -func waitForEvent(t *testing.T, wsc *client.WSClient, eventid string, +func waitForEvent(t *testing.T, wsc *rpcclient.WSClient, eventid string, runner func(), eventDataChecker func(string, txs.EventData) (bool, error)) waitForEventResult { @@ -207,45 +203,8 @@ func (err waitForEventResult) Timeout() bool { return err.timeout } -func acceptFirstBlock(_ *tm_types.Block) bool { - return true -} - //-------------------------------------------------------------------------------- -func unmarshalResponseNewBlock(b []byte) (*types.Block, error) { - // unmarshall and assert somethings - var response rpctypes.RPCResponse - var err error - wire.ReadJSON(&response, b, &err) - if err != nil { - return nil, err - } - if response.Error != "" { - return nil, fmt.Errorf(response.Error) - } - // TODO - //block := response.Result.(*ctypes.ResultEvent).Data.(types.EventDataNewBlock).Block - // return block, nil - return nil, nil -} - -func unmarshalResponseNameReg(b []byte) (*txs.NameTx, error) { - // unmarshall and assert somethings - var response rpctypes.RPCResponse - var err error - wire.ReadJSON(&response, b, &err) - if err != nil { - return nil, err - } - if response.Error != "" { - return nil, fmt.Errorf(response.Error) - } - _, val := UnmarshalEvent(*response.Result) - tx := txs.DecodeTx(val.(types.EventDataTx).Tx).(*txs.NameTx) - return tx, nil -} - func unmarshalValidateSend(amt int64, toAddr []byte) func(string, txs.EventData) (bool, error) { return func(eid string, eventData txs.EventData) (bool, error) { @@ -314,22 +273,6 @@ func unmarshalValidateCall(origin, } } -// Unmarshal a json event -func UnmarshalEvent(b json.RawMessage) (string, events.EventData) { - var err error - result := new(ctypes.ErisDBResult) - wire.ReadJSONPtr(result, b, &err) - if err != nil { - panic(err) - } - event, ok := (*result).(*ctypes.ResultEvent) - if !ok { - return "", nil // TODO: handle non-event messages (ie. return from subscribe/unsubscribe) - // fmt.Errorf("Result is not type *ctypes.ResultEvent. Got %v", reflect.TypeOf(*result)) - } - return event.Event, event.Data -} - func readResult(t *testing.T, bs []byte) ctypes.ErisDBResult { var err error result := new(ctypes.ErisDBResult) diff --git a/test/mock/pipe.go b/test/mock/pipe.go index 78ba9d38783445c94f85e70f6871ca71dffd91c6..b8394ad9ad9e73db7cd0aa46d04bf86f40456f40 100644 --- a/test/mock/pipe.go +++ b/test/mock/pipe.go @@ -208,6 +208,23 @@ func (cons *consensusEngine) Events() event.EventEmitter { return nil } +func (cons *consensusEngine) ListUnconfirmedTxs(maxTxs int) ([]txs.Tx, error) { + return nil, nil + +} + +func (cons *consensusEngine) ListValidators() []consensus_types.Validator { + return nil +} + +func (cons *consensusEngine) ConsensusState() *consensus_types.ConsensusState { + return &consensus_types.ConsensusState{} +} + +func (cons *consensusEngine) PeerConsensusStates() map[string]string { + return map[string]string{} +} + // Events type eventer struct { testData *td.TestData diff --git a/test/testdata/testdata/testdata.go b/test/testdata/testdata/testdata.go index 56894ecb5a55601ba90f8d542e458dfce66f7442..f42cdccdcf595cc1133d647b247ddc0c00c54d25 100644 --- a/test/testdata/testdata/testdata.go +++ b/test/testdata/testdata/testdata.go @@ -2,16 +2,22 @@ package testdata import ( account "github.com/eris-ltd/eris-db/account" + consensus_types "github.com/eris-ltd/eris-db/consensus/types" core_types "github.com/eris-ltd/eris-db/core/types" event "github.com/eris-ltd/eris-db/event" stypes "github.com/eris-ltd/eris-db/manager/eris-mint/state/types" rpc_v0 "github.com/eris-ltd/eris-db/rpc/v0" transaction "github.com/eris-ltd/eris-db/txs" - mintTypes "github.com/tendermint/tendermint/types" ) -var testDataJson = `{ +// TODO: [Silas] This would really be much better as a composite literal in go +// where the compiler/type system/IDE would make it easier to maintain +// not entirely straightforward to convert it, but shouldn't be that hard either +// with recursive use of fmt.Printf("%#v", subStruct) on the decoded in-memory +// object +var testDataJson = ` +{ "chain_data": { "priv_validator": { "address": "37236DF251AB70022B1DA351F08A20FB52443E37", @@ -53,7 +59,10 @@ var testDataJson = `{ ], "validators": [ { - "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], + "pub_key": [ + 1, + "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906" + ], "amount": 5000000000, "unbond_to": [ { @@ -92,20 +101,20 @@ var testDataJson = `{ "output": { "accounts": [ { - "address": "0000000000000000000000000000000000000000", - "pub_key": null, - "sequence": 0, - "balance": 1337, - "code": "", - "storage_root": "", - "permissions": { - "base": { - "perms": 2302, - "set": 16383 - }, - "roles": [] - } - }, + "address": "0000000000000000000000000000000000000000", + "pub_key": null, + "sequence": 0, + "balance": 1337, + "code": "", + "storage_root": "", + "permissions": { + "base": { + "perms": 2302, + "set": 16383 + }, + "roles": [] + } + }, { "address": "0000000000000000000000000000000000000002", "pub_key": null, @@ -243,7 +252,9 @@ var testDataJson = `{ "output": {} }, "GetBlock": { - "input": {"height": 0}, + "input": { + "height": 0 + }, "output": null }, "GetBlocks": { @@ -264,15 +275,23 @@ var testDataJson = `{ "start_time": "", "commit_time": "0001-01-01 00:00:00 +0000 UTC", "validators": [ - { - "address": "37236DF251AB70022B1DA351F08A20FB52443E37", - "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], - "bond_height": 0, - "unbond_height": 0, - "last_commit_height": 0, - "voting_power": 5000000000, - "accum": 0 - } + [ + 1, + { + "validator": { + "address": "37236DF251AB70022B1DA351F08A20FB52443E37", + "pub_key": [ + 1, + "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906" + ], + "bond_height": 0, + "unbond_height": 0, + "last_commit_height": 0, + "voting_power": 5000000000, + "accum": 0 + } + } + ] ], "proposal": null } @@ -283,7 +302,10 @@ var testDataJson = `{ "bonded_validators": [ { "address": "37236DF251AB70022B1DA351F08A20FB52443E37", - "pub_key": [1, "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906"], + "pub_key": [ + 1, + "CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906" + ], "bond_height": 0, "unbond_height": 0, "last_commit_height": 0, @@ -327,7 +349,9 @@ var testDataJson = `{ "output": [] }, "GetPeer": { - "input": {"address": "127.0.0.1:30000"}, + "input": { + "address": "127.0.0.1:30000" + }, "output": { "is_outbound": false, "node_info": null @@ -420,7 +444,11 @@ var testDataJson = `{ } }, "Call": { - "input": {"address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", "from": "DEADBEEF", "data": ""}, + "input": { + "address": "9FC1ECFCAE2A554D4D1A000D0D80F748E66359E3", + "from": "DEADBEEF", + "data": "" + }, "output": { "return": "6000357c01000000000000000000000000000000000000000000000000000000009004806337f428411461004557806340c10f191461005a578063d0679d341461006e57005b610050600435610244565b8060005260206000f35b610068600435602435610082565b60006000f35b61007c600435602435610123565b60006000f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156100dd576100e2565b61011f565b80600160005060008473ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055505b5050565b80600160005060003373ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600050541061015e57610163565b610240565b80600160005060003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282825054039250508190555080600160005060008473ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828282505401925050819055507f93eb3c629eb575edaf0252e4f9fc0c5ccada50496f8c1d32f0f93a65a8257eb560003373ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020016000a15b5050565b6000600160005060008373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060005054905061027d565b91905056", "gas_used": 0 @@ -484,7 +512,8 @@ var testDataJson = `{ "name": "testKey", "owner": "37236DF251AB70022B1DA351F08A20FB52443E37", "data": "testData", - "expires": 250 } + "expires": 250 + } }, "GetNameRegEntries": { "input": { @@ -492,15 +521,18 @@ var testDataJson = `{ }, "output": { "block_height": 1, - "names":[ { - "name": "testKey", - "owner": "37236DF251AB70022B1DA351F08A20FB52443E37", - "data": "testData", - "expires": 250 - } ] + "names": [ + { + "name": "testKey", + "owner": "37236DF251AB70022B1DA351F08A20FB52443E37", + "data": "testData", + "expires": 250 + } + ] } } -}` +} +` var serverDuration uint = 100 @@ -565,7 +597,7 @@ type ( } GetConsensusStateData struct { - Output *core_types.ConsensusState `json:"output"` + Output *consensus_types.ConsensusState `json:"output"` } GetValidatorsData struct {