// This is a test utility for Ethermint's Web3 JSON-RPC services. // // To run these tests please first ensure you have the ethermintd running // // You can configure the desired HOST and MODE as well in integration-test-all.sh package rpc import ( "encoding/json" "fmt" "math/big" "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/require" rpctypes "github.com/tharsis/ethermint/rpc/ethereum/types" ) // func TestMain(m *testing.M) { // if MODE != "pending" { // _, _ = fmt.Fprintln(os.Stdout, "Skipping pending RPC test") // return // } // var err error // from, err = GetAddress() // if err != nil { // fmt.Printf("failed to get account: %s\n", err) // os.Exit(1) // } // // Start all tests // code := m.Run() // os.Exit(code) // } func TestEth_Pending_GetBalance(t *testing.T) { // There is no pending block concept in Ethermint t.Skip("skipping TestEth_Pending_GetBalance") var res hexutil.Big var resTxHash common.Hash rpcRes := Call(t, "eth_getBalance", []string{addrA, "latest"}) err := res.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) preTxLatestBalance := res.ToInt() rpcRes = Call(t, "eth_getBalance", []string{addrA, "pending"}) err = res.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) preTxPendingBalance := res.ToInt() t.Logf("Got pending balance %s for %s pre tx\n", preTxPendingBalance, addrA) t.Logf("Got latest balance %s for %s pre tx\n", preTxLatestBalance, addrA) param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["to"] = addrA param[0]["value"] = "0xA" param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" txRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""}) require.Nil(t, txRes.Error) rpcRes = Call(t, "eth_sendTransaction", param) require.Nil(t, rpcRes.Error) err = resTxHash.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) rpcRes = Call(t, "eth_getTransactionByHash", []string{resTxHash.Hex()}) require.Nil(t, rpcRes.Error) rpcRes = Call(t, "eth_getBalance", []string{addrA, "pending"}) err = res.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) postTxPendingBalance := res.ToInt() t.Logf("Got pending balance %s for %s post tx\n", postTxPendingBalance, addrA) require.Equal(t, preTxPendingBalance.Add(preTxPendingBalance, big.NewInt(10)), postTxPendingBalance) rpcRes = Call(t, "eth_getBalance", []string{addrA, "latest"}) err = res.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) postTxLatestBalance := res.ToInt() t.Logf("Got latest balance %s for %s post tx\n", postTxLatestBalance, addrA) require.Equal(t, preTxLatestBalance, postTxLatestBalance) } func TestEth_Pending_GetTransactionCount(t *testing.T) { prePendingNonce := GetNonce(t, "pending") t.Logf("Pending nonce before tx is %d", prePendingNonce) currentNonce := GetNonce(t, "latest") t.Logf("Current nonce is %d", currentNonce) require.Equal(t, prePendingNonce, currentNonce) param := makePendingTxParams() txRes := Call(t, "eth_sendTransaction", param) require.Nil(t, txRes.Error) var hash hexutil.Bytes err := json.Unmarshal(txRes.Result, &hash) require.NoError(t, err) receipt := waitForReceipt(t, hash) require.NotNil(t, receipt) require.Equal(t, "0x1", receipt["status"].(string)) pendingNonce := GetNonce(t, "pending") latestNonce := GetNonce(t, "latest") t.Logf("Latest nonce is %d", latestNonce) require.Equal(t, currentNonce+1, latestNonce) t.Logf("Pending nonce is %d", pendingNonce) require.Equal(t, latestNonce, pendingNonce) require.Equal(t, uint64(prePendingNonce)+uint64(1), uint64(pendingNonce)) } func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { // There is no pending block concept in Ethermint t.Skip("skipping TestEth_Pending_GetBlockTransactionCountByNumber") rpcRes := Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) var preTxPendingTxCount hexutil.Uint err := json.Unmarshal(rpcRes.Result, &preTxPendingTxCount) require.NoError(t, err) t.Logf("Pre tx pending nonce is %d", preTxPendingTxCount) rpcRes = Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"latest"}) var preTxLatestTxCount hexutil.Uint err = json.Unmarshal(rpcRes.Result, &preTxLatestTxCount) require.NoError(t, err) t.Logf("Pre tx latest nonce is %d", preTxLatestTxCount) require.Equal(t, preTxPendingTxCount, preTxLatestTxCount) param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["to"] = addrA param[0]["value"] = "0xA" param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" txRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""}) require.Nil(t, txRes.Error) txRes = Call(t, "eth_sendTransaction", param) require.Nil(t, txRes.Error) rpcRes = Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) var postTxPendingTxCount hexutil.Uint err = json.Unmarshal(rpcRes.Result, &postTxPendingTxCount) require.NoError(t, err) t.Logf("Post tx pending nonce is %d", postTxPendingTxCount) rpcRes = Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"latest"}) var postTxLatestTxCount hexutil.Uint err = json.Unmarshal(rpcRes.Result, &postTxLatestTxCount) require.NoError(t, err) t.Logf("Post tx latest nonce is %d", postTxLatestTxCount) require.Equal(t, postTxPendingTxCount, postTxLatestTxCount) require.Equal(t, uint64(preTxPendingTxCount), uint64(postTxPendingTxCount)) require.Equal(t, uint64(postTxPendingTxCount)-uint64(preTxPendingTxCount), uint64(postTxLatestTxCount)-uint64(preTxLatestTxCount)) } func TestEth_Pending_GetBlockByNumber(t *testing.T) { // There is no pending block concept in Ethermint t.Skip("skipping TestEth_Pending_GetBlockByNumber") rpcRes := Call(t, "eth_getBlockByNumber", []interface{}{"latest", true}) var preTxLatestBlock map[string]interface{} err := json.Unmarshal(rpcRes.Result, &preTxLatestBlock) require.NoError(t, err) preTxLatestTxs := len(preTxLatestBlock["transactions"].([]interface{})) rpcRes = Call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) var preTxPendingBlock map[string]interface{} err = json.Unmarshal(rpcRes.Result, &preTxPendingBlock) require.NoError(t, err) preTxPendingTxs := len(preTxPendingBlock["transactions"].([]interface{})) param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["to"] = addrA param[0]["value"] = "0xA" param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" txRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""}) require.Nil(t, txRes.Error) txRes = Call(t, "eth_sendTransaction", param) require.Nil(t, txRes.Error) rpcRes = Call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) var postTxPendingBlock map[string]interface{} err = json.Unmarshal(rpcRes.Result, &postTxPendingBlock) require.NoError(t, err) postTxPendingTxs := len(postTxPendingBlock["transactions"].([]interface{})) require.Equal(t, postTxPendingTxs, preTxPendingTxs) rpcRes = Call(t, "eth_getBlockByNumber", []interface{}{"latest", true}) var postTxLatestBlock map[string]interface{} err = json.Unmarshal(rpcRes.Result, &postTxLatestBlock) require.NoError(t, err) postTxLatestTxs := len(postTxLatestBlock["transactions"].([]interface{})) require.Equal(t, preTxLatestTxs, postTxLatestTxs) require.Equal(t, postTxPendingTxs, preTxPendingTxs) } func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { // There is no pending block concept in Ethermint t.Skip("skipping TestEth_Pending_GetTransactionByBlockNumberAndIndex") var pendingTx []*rpctypes.RPCTransaction resPendingTxs := Call(t, "eth_pendingTransactions", []string{}) err := json.Unmarshal(resPendingTxs.Result, &pendingTx) require.NoError(t, err) pendingTxCount := len(pendingTx) data := "0x608060405234801561001057600080fd5b5061011e806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063bc9c707d14602d575b600080fd5b603360ab565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101560715780820151818401526020810190506058565b50505050905090810190601f168015609d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60606040518060400160405280600681526020017f617261736b61000000000000000000000000000000000000000000000000000081525090509056fea2646970667358221220a31fa4c1ce0b3651fbf5401c511b483c43570c7de4735b5c3b0ad0db30d2573164736f6c63430007050033" param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["to"] = addrA param[0]["value"] = "0xA" param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" param[0]["data"] = data txRes := Call(t, "personal_unlockAccount", []interface{}{param[0]["from"], ""}) require.Nil(t, txRes.Error) txRes = Call(t, "eth_sendTransaction", param) require.Nil(t, txRes.Error) // test will be blocked here until tx gets confirmed var txHash common.Hash err = json.Unmarshal(txRes.Result, &txHash) require.NoError(t, err) rpcRes := Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"latest", "0x" + fmt.Sprintf("%X", pendingTxCount)}) var latestBlockTx map[string]interface{} err = json.Unmarshal(rpcRes.Result, &latestBlockTx) require.NoError(t, err) // verify the pending tx has all the correct fields from the tx sent. require.NotEmpty(t, latestBlockTx["hash"]) require.Equal(t, latestBlockTx["value"], "0xa") require.Equal(t, data, latestBlockTx["input"]) rpcRes = Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x" + fmt.Sprintf("%X", pendingTxCount)}) var pendingBlock map[string]interface{} err = json.Unmarshal(rpcRes.Result, &pendingBlock) require.NoError(t, err) // verify the transaction does not exist in the pending block info. require.Empty(t, pendingBlock) } func TestEth_Pending_GetTransactionByHash(t *testing.T) { // negative case, check that it returns empty. rpcRes := Call(t, "eth_getTransactionByHash", []interface{}{"0xec5fa15e1368d6ac314f9f64118c5794f076f63c02e66f97ea5fe1de761a8973"}) var tx map[string]interface{} err := json.Unmarshal(rpcRes.Result, &tx) require.NoError(t, err) require.Nil(t, tx) // create a transaction. data := "0x608060405234801561001057600080fd5b5061011e806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806302eb691b14602d575b600080fd5b603360ab565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101560715780820151818401526020810190506058565b50505050905090810190601f168015609d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60606040518060400160405280600d81526020017f617261736b61776173686572650000000000000000000000000000000000000081525090509056fea264697066735822122060917c5c2fab8c058a17afa6d3c1d23a7883b918ea3c7157131ea5b396e1aa7564736f6c63430007050033" param := makePendingTxParams() param[0]["data"] = data txRes := Call(t, "eth_sendTransaction", param) var txHash common.Hash err = txHash.UnmarshalJSON(txRes.Result) require.NoError(t, err) rpcRes = Call(t, "eth_getTransactionByHash", []interface{}{txHash}) var pendingTx map[string]interface{} err = json.Unmarshal(rpcRes.Result, &pendingTx) require.NoError(t, err) txsRes := Call(t, "eth_getPendingTransactions", []interface{}{}) var pendingTxs []map[string]interface{} err = json.Unmarshal(txsRes.Result, &pendingTxs) require.NoError(t, err) require.NotEmpty(t, pendingTxs) // verify the pending tx has all the correct fields from the tx sent. require.NotEmpty(t, pendingTx) require.NotEmpty(t, pendingTx["hash"]) require.Equal(t, pendingTx["value"], "0xa") require.Equal(t, pendingTx["input"], data) } func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { currNonce := GetNonce(t, "latest") param := makePendingTxParams() // first transaction txRes1 := Call(t, "eth_sendTransaction", param) require.Nil(t, txRes1.Error) pendingNonce1 := GetNonce(t, "pending") require.Greater(t, uint64(pendingNonce1), uint64(currNonce)) // second transaction param[0]["to"] = "0x7f0f463c4d57b1bd3e3b79051e6c5ab703e803d9" txRes2 := Call(t, "eth_sendTransaction", param) require.Nil(t, txRes2.Error) pendingNonce2 := GetNonce(t, "pending") require.Greater(t, uint64(pendingNonce2), uint64(currNonce)) require.Greater(t, uint64(pendingNonce2), uint64(pendingNonce1)) // third transaction param[0]["to"] = "0x7fb24493808b3f10527e3e0870afeb8a953052d2" txRes3 := Call(t, "eth_sendTransaction", param) require.Nil(t, txRes3.Error) pendingNonce3 := GetNonce(t, "pending") require.Greater(t, uint64(pendingNonce3), uint64(currNonce)) require.Greater(t, uint64(pendingNonce3), uint64(pendingNonce2)) } func makePendingTxParams() []map[string]string { param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["to"] = addrA param[0]["value"] = "0xA" param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" return param }