From edb9d4bcba1e43b58205208a6724e084125b9ceb Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 6 Oct 2020 11:09:30 -0700 Subject: [PATCH 01/61] add PendingBlockNumber -1 --- rpc/types.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rpc/types.go b/rpc/types.go index 935947a29..f73abca34 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -18,6 +18,9 @@ const ( // EarliestBlockNumber mapping from "earliest" to 1 for tm query (earliest query not supported) EarliestBlockNumber = BlockNumber(1) + + //PendingBlockNumber mapping from "pending" to -1 for tm query + PendingBlockNumber = BlockNumber(-1) ) // NewBlockNumber creates a new BlockNumber instance. From f44ddf9ddde09ce1442a840e6756f271e9fa8138 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 6 Oct 2020 13:02:56 -0700 Subject: [PATCH 02/61] increase block times --- init.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/init.sh b/init.sh index 17223d4f7..b438b4192 100755 --- a/init.sh +++ b/init.sh @@ -32,6 +32,19 @@ cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["mint"]["params"]["mi # Enable faucet cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["faucet"]["enable_faucet"]=true' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json +# increase block time (?) +cat $HOME/.ethermintd/config/genesis.json | jq '.consensus_params["block"]["time_iota_ms"]="30000"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json + +sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermintd/config/config.toml + +sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermintd/config/config.toml +sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermintd/config/config.toml +sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermintd/config/config.toml +sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermintd/config/config.toml +sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermintd/config/config.toml +sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermintd/config/config.toml +sed -i 's/timeout_commit = "5s"/timeout_commit = "50s"/g' $HOME/.ethermintd/config/config.toml + # Allocate genesis accounts (cosmos formatted addresses) ethermintd add-genesis-account $(ethermintcli keys show $KEY -a) 100000000000000000000aphoton From feb7a8470fc3352d1e0eef6fd6997fd4818a079e Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 6 Oct 2020 13:03:13 -0700 Subject: [PATCH 03/61] update bn --- rpc/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/types.go b/rpc/types.go index f73abca34..7d44451de 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -48,7 +48,7 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error { *bn = LatestBlockNumber return nil case "pending": - *bn = LatestBlockNumber + *bn = PendingBlockNumber return nil } From 0922cbbf9222336455e0428f2071f1e496ad4586 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Thu, 8 Oct 2020 17:19:36 -0700 Subject: [PATCH 04/61] get pending balance --- rpc/eth_api.go | 23 +++++++++++++++++++++++ rpc/types.go | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 6c602df82..40ebd3496 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -225,6 +225,29 @@ func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) return nil, err } + if blockNum.Int64() == int64(1) { + pendingtx, err := e.backend.PendingTransactions() + if err != nil { + return nil, err + } + + for i := range pendingtx { + fmt.Println(pendingtx[i]) + if pendingtx[i] == nil { + continue + } + if pendingtx[i].From == address { + pendingBalance := big.NewInt(0) + pendingBalance = pendingBalance.Add(val, pendingtx[i].Value.ToInt()) + val = pendingBalance + } else if *pendingtx[i].To == address { + pendingBalance := big.NewInt(0) + pendingBalance = pendingBalance.Sub(val, pendingtx[i].Value.ToInt()) + val = pendingBalance + } + } + } + return (*hexutil.Big)(val), nil } diff --git a/rpc/types.go b/rpc/types.go index 7d44451de..66040c85b 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -19,8 +19,8 @@ const ( // EarliestBlockNumber mapping from "earliest" to 1 for tm query (earliest query not supported) EarliestBlockNumber = BlockNumber(1) - //PendingBlockNumber mapping from "pending" to -1 for tm query - PendingBlockNumber = BlockNumber(-1) + // PendingBlockNumber mapping from "pending" to 1 for tm query -- repeating 1 for now, TDB + PendingBlockNumber = BlockNumber(1) ) // NewBlockNumber creates a new BlockNumber instance. From 1ea22eae41d10e3b8ebd80f00305d48e942651ce Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 12 Oct 2020 15:32:06 -0700 Subject: [PATCH 05/61] additional logic to check for pending state --- rpc/eth_api.go | 17 ++++++++++++++--- rpc/types.go | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 40ebd3496..0e1da5a00 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -212,7 +212,16 @@ func (e *PublicEthAPI) BlockNumber() (hexutil.Uint64, error) { // GetBalance returns the provided account's balance up to the provided block number. func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) (*hexutil.Big, error) { e.logger.Debug("eth_getBalance", "address", address, "block number", blockNum) - ctx := e.cliCtx.WithHeight(blockNum.Int64()) + pendingQuery := false + var ctx context.CLIContext + if blockNum.Int64() == int64(-1) { + // uses latest block number: -1 -> 0 + ctx = e.cliCtx.WithHeight(int64(0)) + pendingQuery = true + } else { + ctx = e.cliCtx.WithHeight(blockNum.Int64()) + } + fmt.Println("query ctx height: ", ctx.Height) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) if err != nil { return nil, err @@ -225,14 +234,13 @@ func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) return nil, err } - if blockNum.Int64() == int64(1) { + if pendingQuery { pendingtx, err := e.backend.PendingTransactions() if err != nil { return nil, err } for i := range pendingtx { - fmt.Println(pendingtx[i]) if pendingtx[i] == nil { continue } @@ -344,6 +352,9 @@ func (e *PublicEthAPI) GetCode(address common.Address, blockNumber BlockNumber) var out evmtypes.QueryResCode e.cliCtx.Codec.MustUnmarshalJSON(res, &out) return out.Code, nil + // issue with pending state query is that we cannot get pending because the tx will return a txhash + // this request requires the contract address to query its code + // if the user only has the txhash, and assuming they don't know how to construct a tx manually, they cannot query this anyway } // GetTransactionLogs returns the logs given a transaction hash. diff --git a/rpc/types.go b/rpc/types.go index 66040c85b..001bb6086 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -20,7 +20,7 @@ const ( EarliestBlockNumber = BlockNumber(1) // PendingBlockNumber mapping from "pending" to 1 for tm query -- repeating 1 for now, TDB - PendingBlockNumber = BlockNumber(1) + PendingBlockNumber = BlockNumber(-1) ) // NewBlockNumber creates a new BlockNumber instance. From b2b54ba3469e186c1ef3c09feb56974523625a0a Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 12 Oct 2020 15:32:40 -0700 Subject: [PATCH 06/61] add multiple balance query --- tests/rpc_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/rpc_test.go b/tests/rpc_test.go index 28bf81d61..214a97558 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -311,6 +311,48 @@ func TestEth_GetBalance(t *testing.T) { } } +func TestEth_GetBalancex60(t *testing.T) { + 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"] = "0x55ae82600" + + fmt.Println("FROM ADDR: ", fmt.Sprintf("%x", from)) + + rpcRes := call(t, "eth_sendTransaction", param) + + var hash hexutil.Bytes + err := json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) + + receipt := waitForReceipt(t, hash) + require.NotNil(t, receipt) + require.Equal(t, "0x1", receipt["status"].(string)) + + for i := 0; i <= 60; i++ { + time.Sleep(1 * time.Second) + + // will query balance from blocks 0 thru 5 + blockNum := i % 6 + fmt.Println("querying blocknumber: ", blockNum) + rpcRes := call(t, "eth_getBalance", []string{addrA, "0x" + fmt.Sprintf("%x", blockNum)}) + + var res hexutil.Big + err := res.UnmarshalJSON(rpcRes.Result) + require.NoError(t, err) + + t.Logf("Got balance %s for %s\n", res.String(), addrA) + + // 0 if x == y; where x is res, y is 0 + if res.ToInt().Cmp(big.NewInt(10)) != 0 { + t.Logf("expected balance: %s, got: %s", "0xa", res.String()) + } + } +} + func TestEth_GetStorageAt(t *testing.T) { expectedRes := hexutil.Bytes{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} rpcRes := call(t, "eth_getStorageAt", []string{addrA, fmt.Sprint(addrAStoreKey), zeroString}) From f8456502ac41790df008199cc9a4731eb89e7e9d Mon Sep 17 00:00:00 2001 From: araskachoi Date: Wed, 14 Oct 2020 13:42:51 -0700 Subject: [PATCH 07/61] pending state for getTransactionCount --- rpc/eth_api.go | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 0e1da5a00..08d01c587 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -215,13 +215,12 @@ func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) pendingQuery := false var ctx context.CLIContext if blockNum.Int64() == int64(-1) { - // uses latest block number: -1 -> 0 + // uses latest block number for pending: -1 -> 0 ctx = e.cliCtx.WithHeight(int64(0)) pendingQuery = true } else { ctx = e.cliCtx.WithHeight(blockNum.Int64()) } - fmt.Println("query ctx height: ", ctx.Height) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) if err != nil { return nil, err @@ -276,7 +275,15 @@ func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum // GetTransactionCount returns the number of transactions at the given address up to the given block number. func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum BlockNumber) (*hexutil.Uint64, error) { e.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum) - ctx := e.cliCtx.WithHeight(blockNum.Int64()) + pendingQuery := false + var ctx context.CLIContext + if blockNum.Int64() == int64(-1) { + // uses latest block number for pending: -1 -> 0 + ctx = e.cliCtx.WithHeight(int64(0)) + pendingQuery = true + } else { + ctx = e.cliCtx.WithHeight(blockNum.Int64()) + } // Get nonce (sequence) from account from := sdk.AccAddress(address.Bytes()) @@ -294,6 +301,24 @@ func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum Bloc return nil, err } + pendingNonce := uint64(0) + if pendingQuery { + pendingtx, err := e.backend.PendingTransactions() + if err != nil { + return nil, err + } + + for i := range pendingtx { + if pendingtx[i] == nil { + continue + } + if pendingtx[i].From == address { + pendingNonce++ + } + } + nonce = nonce + pendingNonce + } + n := hexutil.Uint64(nonce) return &n, nil } From 274a999b38014673532b1b6a97ff22c5b2fe75f7 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Wed, 14 Oct 2020 13:46:37 -0700 Subject: [PATCH 08/61] fix lint --- rpc/eth_api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 08d01c587..6370ec408 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -316,7 +316,7 @@ func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum Bloc pendingNonce++ } } - nonce = nonce + pendingNonce + nonce += pendingNonce } n := hexutil.Uint64(nonce) From f70136ab822c46183ba80f9c84a7945b800b470f Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 19 Oct 2020 09:26:31 -0700 Subject: [PATCH 09/61] add getBlockTransactionCountByNumber code - commented --- rpc/eth_api.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 6370ec408..dcf2756af 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -339,8 +339,59 @@ func (e *PublicEthAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number. func (e *PublicEthAPI) GetBlockTransactionCountByNumber(blockNum BlockNumber) *hexutil.Uint { + fmt.Println("blockNum", blockNum) e.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) + + var ctx context.CLIContext + if blockNum.Int64() == int64(0) || blockNum.Int64() == int64(1) { + // uses latest block number for pending: -1 -> 0 + ctx = e.cliCtx.WithHeight(int64(0)) + fmt.Println("HEIGHT AT CTX!: ", ctx.Height) + } + height := blockNum.Int64() + // pendingQuery := false + // if height == int64(-1) { + // // uses latest block number for pending: -1 -> 0 + // height = int64(0) + // pendingQuery = true + // } + + // fmt.Println("height: ", height) + + // txCount := e.getBlockTransactionCountByNumber(height) + // if txCount == nil { + // fmt.Println("invalid block!") + // return nil + // } + + // totalTxCountCleaned := strings.Replace(txCount.String(), "0x", "", -1) + // fmt.Println("totalTxCountCleaned: ", totalTxCountCleaned) + // totalTxCount, err := strconv.ParseUint(totalTxCountCleaned, 16, 64) + // if err != nil { + // return nil + // } + // fmt.Println("totalTxCount: ", totalTxCount) + + // if pendingQuery { + // pendingtx, err := e.backend.PendingTransactions() + // if err != nil { + // return nil + // } + + // for i := range pendingtx { + // if pendingtx[i] == nil { + // continue + // } + // totalTxCount++ + // } + // } + // fmt.Println("end totalTxCount: ", totalTxCount) + + // total := hexutil.Uint(totalTxCount) + + // return &total + return e.getBlockTransactionCountByNumber(height) } @@ -351,6 +402,8 @@ func (e *PublicEthAPI) getBlockTransactionCountByNumber(number int64) *hexutil.U return nil } + fmt.Println(block) + n := hexutil.Uint(len(block.Block.Txs)) return &n } From f0b49845d291bda7f139b754abc0673e051844d5 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 19 Oct 2020 09:28:56 -0700 Subject: [PATCH 10/61] cleanup test --- tests/rpc_test.go | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/tests/rpc_test.go b/tests/rpc_test.go index 214a97558..28bf81d61 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -311,48 +311,6 @@ func TestEth_GetBalance(t *testing.T) { } } -func TestEth_GetBalancex60(t *testing.T) { - 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"] = "0x55ae82600" - - fmt.Println("FROM ADDR: ", fmt.Sprintf("%x", from)) - - rpcRes := call(t, "eth_sendTransaction", param) - - var hash hexutil.Bytes - err := json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) - - receipt := waitForReceipt(t, hash) - require.NotNil(t, receipt) - require.Equal(t, "0x1", receipt["status"].(string)) - - for i := 0; i <= 60; i++ { - time.Sleep(1 * time.Second) - - // will query balance from blocks 0 thru 5 - blockNum := i % 6 - fmt.Println("querying blocknumber: ", blockNum) - rpcRes := call(t, "eth_getBalance", []string{addrA, "0x" + fmt.Sprintf("%x", blockNum)}) - - var res hexutil.Big - err := res.UnmarshalJSON(rpcRes.Result) - require.NoError(t, err) - - t.Logf("Got balance %s for %s\n", res.String(), addrA) - - // 0 if x == y; where x is res, y is 0 - if res.ToInt().Cmp(big.NewInt(10)) != 0 { - t.Logf("expected balance: %s, got: %s", "0xa", res.String()) - } - } -} - func TestEth_GetStorageAt(t *testing.T) { expectedRes := hexutil.Bytes{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} rpcRes := call(t, "eth_getStorageAt", []string{addrA, fmt.Sprint(addrAStoreKey), zeroString}) From 7b49761f382e83a2a5b0a66354db302441aa226c Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 20 Oct 2020 14:01:26 -0700 Subject: [PATCH 11/61] GetBlockTransactionCountByNumber --- rpc/eth_api.go | 106 +++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index dcf2756af..95052a8af 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -6,6 +6,8 @@ import ( "fmt" "math/big" "os" + "strconv" + "strings" "sync" "github.com/spf13/viper" @@ -339,60 +341,60 @@ func (e *PublicEthAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number. func (e *PublicEthAPI) GetBlockTransactionCountByNumber(blockNum BlockNumber) *hexutil.Uint { - fmt.Println("blockNum", blockNum) e.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) - var ctx context.CLIContext - if blockNum.Int64() == int64(0) || blockNum.Int64() == int64(1) { - // uses latest block number for pending: -1 -> 0 - ctx = e.cliCtx.WithHeight(int64(0)) - fmt.Println("HEIGHT AT CTX!: ", ctx.Height) - } - - height := blockNum.Int64() - // pendingQuery := false - // if height == int64(-1) { - // // uses latest block number for pending: -1 -> 0 - // height = int64(0) - // pendingQuery = true - // } - - // fmt.Println("height: ", height) - - // txCount := e.getBlockTransactionCountByNumber(height) - // if txCount == nil { - // fmt.Println("invalid block!") - // return nil - // } - - // totalTxCountCleaned := strings.Replace(txCount.String(), "0x", "", -1) - // fmt.Println("totalTxCountCleaned: ", totalTxCountCleaned) - // totalTxCount, err := strconv.ParseUint(totalTxCountCleaned, 16, 64) - // if err != nil { - // return nil - // } - // fmt.Println("totalTxCount: ", totalTxCount) - - // if pendingQuery { - // pendingtx, err := e.backend.PendingTransactions() - // if err != nil { - // return nil - // } - - // for i := range pendingtx { - // if pendingtx[i] == nil { - // continue - // } - // totalTxCount++ - // } - // } - // fmt.Println("end totalTxCount: ", totalTxCount) - - // total := hexutil.Uint(totalTxCount) - - // return &total - - return e.getBlockTransactionCountByNumber(height) + var blockNumber hexutil.Uint64 + pendingQuery := false + switch bn := blockNum.Int64(); bn { + case int64(0): + bn, err := e.backend.BlockNumber() + if err != nil { + return nil + } + blockNumber = bn + case int64(-1): + bn, err := e.backend.BlockNumber() + if err != nil { + return nil + } + blockNumber = bn + pendingQuery = true + } + + heightCleaned := strings.Replace(blockNumber.String(), "0x", "", -1) + height, err := strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil + } + + txCount := e.getBlockTransactionCountByNumber(height) + if txCount == nil { + fmt.Println("invalid block!") + return nil + } + + totalTxCountCleaned := strings.Replace(txCount.String(), "0x", "", -1) + totalTxCount, err := strconv.ParseUint(totalTxCountCleaned, 16, 64) + if err != nil { + return nil + } + + if pendingQuery { + pendingtx, err := e.backend.PendingTransactions() + if err != nil { + return nil + } + + for i := range pendingtx { + if pendingtx[i] == nil { + continue + } + totalTxCount++ + } + } + + total := hexutil.Uint(totalTxCount) + return &total } func (e *PublicEthAPI) getBlockTransactionCountByNumber(number int64) *hexutil.Uint { From f6550be255450ce0ad74a05221de71aba35ce611 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 20 Oct 2020 14:41:29 -0700 Subject: [PATCH 12/61] cleanup --- rpc/eth_api.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 95052a8af..22b9e2ef2 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -216,9 +216,9 @@ func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) e.logger.Debug("eth_getBalance", "address", address, "block number", blockNum) pendingQuery := false var ctx context.CLIContext - if blockNum.Int64() == int64(-1) { + if blockNum == PendingBlockNumber { // uses latest block number for pending: -1 -> 0 - ctx = e.cliCtx.WithHeight(int64(0)) + ctx = e.cliCtx.WithHeight(LatestBlockNumber.Int64()) pendingQuery = true } else { ctx = e.cliCtx.WithHeight(blockNum.Int64()) @@ -279,9 +279,9 @@ func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum Bloc e.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum) pendingQuery := false var ctx context.CLIContext - if blockNum.Int64() == int64(-1) { + if blockNum == PendingBlockNumber { // uses latest block number for pending: -1 -> 0 - ctx = e.cliCtx.WithHeight(int64(0)) + ctx = e.cliCtx.WithHeight(LatestBlockNumber.Int64()) pendingQuery = true } else { ctx = e.cliCtx.WithHeight(blockNum.Int64()) From 04486f48942ff3187206f28030bbd241ac91d654 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Wed, 21 Oct 2020 12:17:49 -0700 Subject: [PATCH 13/61] getBlockByNumber --- rpc/eth_api.go | 85 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 22b9e2ef2..8a4eda79d 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" "sync" + "time" "github.com/spf13/viper" @@ -733,7 +734,89 @@ func (e *PublicEthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string // GetBlockByNumber returns the block identified by number. func (e *PublicEthAPI) GetBlockByNumber(blockNum BlockNumber, fullTx bool) (map[string]interface{}, error) { e.logger.Debug("eth_getBlockByNumber", "number", blockNum, "full", fullTx) - return e.backend.GetBlockByNumber(blockNum, fullTx) + + var blockNumber hexutil.Uint64 + switch blockNum { + case LatestBlockNumber: + bn, err := e.backend.BlockNumber() + if err != nil { + return nil, err + } + blockNumber = bn + case PendingBlockNumber: + bn, err := e.backend.BlockNumber() + if err != nil { + return nil, abci.ErrInvalidLengthTypes + } + + heightCleaned := strings.Replace(bn.String(), "0x", "", -1) + height, err := strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil, err + } + + //latest block info + latestBlock, err := e.cliCtx.Client.Block(&height) + if err != nil { + return nil, err + } + header := latestBlock.Block.Header + + unconfirmedTxs, err := e.cliCtx.Client.UnconfirmedTxs(100) + if err != nil { + return nil, err + } + + var pendingTxs []common.Hash + var gasUsed *big.Int + if fullTx { + pendingTxs, gasUsed, err = convertTransactionsToRPC( + e.cliCtx, unconfirmedTxs.Txs, common.BytesToHash(header.Hash()), uint64(header.Height)+1, + ) + if err != nil { + return nil, err + } + } else { + pendingTxs = make([]common.Hash, len(unconfirmedTxs.Txs)) + for i, tx := range unconfirmedTxs.Txs { + pendingTxs[i] = common.BytesToHash(tx.Hash()) + } + } + + return formatBlock( + tmtypes.Header{ + Version: header.Version, + ChainID: header.ChainID, + Height: height + 1, + Time: time.Time{}, + LastBlockID: latestBlock.BlockID, + LastCommitHash: nil, + DataHash: nil, + ValidatorsHash: nil, + NextValidatorsHash: nil, + ConsensusHash: header.ConsensusHash, + AppHash: nil, + LastResultsHash: nil, + EvidenceHash: nil, + ProposerAddress: nil, + }, + 0, + 0, + gasUsed, + pendingTxs, + ethtypes.Bloom{}, + ), nil + default: + blockNumber = hexutil.Uint64(blockNum.Int64()) + } + + heightCleaned := strings.Replace(blockNumber.String(), "0x", "", -1) + height, err := strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil, err + } + + return e.backend.GetBlockByNumber(BlockNumber(height), fullTx) } func formatBlock( From 9dd81663d8aa2976121c6fc61b2848ef69ed3e47 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Thu, 22 Oct 2020 16:42:28 -0700 Subject: [PATCH 14/61] GetTransactionByBlockNumberAndIndex --- rpc/eth_api.go | 57 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index 8a4eda79d..75ae248c8 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -746,7 +746,7 @@ func (e *PublicEthAPI) GetBlockByNumber(blockNum BlockNumber, fullTx bool) (map[ case PendingBlockNumber: bn, err := e.backend.BlockNumber() if err != nil { - return nil, abci.ErrInvalidLengthTypes + return nil, err } heightCleaned := strings.Replace(bn.String(), "0x", "", -1) @@ -964,7 +964,7 @@ func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*Transaction, err } // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. -func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*Transaction, error) { +func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint64) (*Transaction, error) { e.logger.Debug("eth_getTransactionByHashAndIndex", "hash", hash, "index", idx) res, _, err := e.cliCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, hash.Hex())) if err != nil { @@ -977,13 +977,58 @@ func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx h } // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. -func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum BlockNumber, idx hexutil.Uint) (*Transaction, error) { +func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum BlockNumber, idx hexutil.Uint64) (*Transaction, error) { e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - value := blockNum.Int64() - return e.getTransactionByBlockNumberAndIndex(value, idx) + var blockNumber int64 + pendingQuery := false + + switch blockNum { + case LatestBlockNumber: + bn, err := e.backend.BlockNumber() + if err != nil { + return nil, err + } + bnCleaned := strings.Replace(bn.String(), "0x", "", -1) + blockNumber, err = strconv.ParseInt(bnCleaned, 16, 64) + if err != nil { + return nil, err + } + case PendingBlockNumber: + bn, err := e.backend.BlockNumber() + if err != nil { + return nil, err + } + bnCleaned := strings.Replace(bn.String(), "0x", "", -1) + blockNumber, err = strconv.ParseInt(bnCleaned, 16, 64) + if err != nil { + return nil, err + } + pendingQuery = true + } + + if pendingQuery { + pendingtx, err := e.backend.PendingTransactions() + if err != nil { + return nil, err + } + index := hexutil.Uint64(0) + for i := range pendingtx { + if pendingtx[i] == nil { + continue + } + if index == idx { + return pendingtx[i], nil + } + index++ + + } + return nil, nil + } + + return e.getTransactionByBlockNumberAndIndex(blockNumber, idx) } -func (e *PublicEthAPI) getTransactionByBlockNumberAndIndex(number int64, idx hexutil.Uint) (*Transaction, error) { +func (e *PublicEthAPI) getTransactionByBlockNumberAndIndex(number int64, idx hexutil.Uint64) (*Transaction, error) { block, err := e.cliCtx.Client.Block(&number) if err != nil { return nil, err From 676f254b0dda5dbd4391e88296ebd5a21d873f65 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Fri, 23 Oct 2020 10:54:45 -0700 Subject: [PATCH 15/61] conform to namespace changes --- rpc/namespaces/eth/api.go | 220 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 9 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 71af7b6c3..d6aec43dc 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -7,7 +7,10 @@ import ( "fmt" "math/big" "os" + "strconv" + "strings" "sync" + "time" "github.com/spf13/viper" @@ -223,8 +226,16 @@ func (api *PublicEthereumAPI) BlockNumber() (hexutil.Uint64, error) { // GetBalance returns the provided account's balance up to the provided block number. func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Big, error) { api.logger.Debug("eth_getBalance", "address", address, "block number", blockNum) - clientCtx := api.clientCtx.WithHeight(blockNum.Int64()) - res, _, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) + pendingQuery := false + var ctx clientcontext.CLIContext + if blockNum == rpctypes.PendingBlockNumber { + // uses latest block number for pending: -1 -> 0 + ctx = api.clientCtx.WithHeight(rpctypes.LatestBlockNumber.Int64()) + pendingQuery = true + } else { + ctx = api.clientCtx.WithHeight(blockNum.Int64()) + } + res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) if err != nil { return nil, err } @@ -236,6 +247,28 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp return nil, err } + if pendingQuery { + pendingtx, err := api.backend.PendingTransactions() + if err != nil { + return nil, err + } + + for i := range pendingtx { + if pendingtx[i] == nil { + continue + } + if pendingtx[i].From == address { + pendingBalance := big.NewInt(0) + pendingBalance = pendingBalance.Add(val, pendingtx[i].Value.ToInt()) + val = pendingBalance + } else if *pendingtx[i].To == address { + pendingBalance := big.NewInt(0) + pendingBalance = pendingBalance.Sub(val, pendingtx[i].Value.ToInt()) + val = pendingBalance + } + } + } + return (*hexutil.Big)(val), nil } @@ -256,11 +289,19 @@ func (api *PublicEthereumAPI) GetStorageAt(address common.Address, key string, b // GetTransactionCount returns the number of transactions at the given address up to the given block number. func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error) { api.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum) - clientCtx := api.clientCtx.WithHeight(blockNum.Int64()) + pendingQuery := false + var ctx clientcontext.CLIContext + if blockNum == rpctypes.PendingBlockNumber { + // uses latest block number for pending: -1 -> 0 + ctx = api.clientCtx.WithHeight(rpctypes.LatestBlockNumber.Int64()) + pendingQuery = true + } else { + ctx = api.clientCtx.WithHeight(blockNum.Int64()) + } // Get nonce (sequence) from account from := sdk.AccAddress(address.Bytes()) - accRet := authtypes.NewAccountRetriever(clientCtx) + accRet := authtypes.NewAccountRetriever(ctx) err := accRet.EnsureExists(from) if err != nil { @@ -274,6 +315,24 @@ func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockN return nil, err } + pendingNonce := uint64(0) + if pendingQuery { + pendingtx, err := api.backend.PendingTransactions() + if err != nil { + return nil, err + } + + for i := range pendingtx { + if pendingtx[i] == nil { + continue + } + if pendingtx[i].From == address { + pendingNonce++ + } + } + nonce += pendingNonce + } + n := hexutil.Uint64(nonce) return &n, nil } @@ -300,17 +359,56 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) * return &n } -// GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number. func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { api.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) - height := blockNum.Int64() + + var blockNumber hexutil.Uint64 + pendingQuery := false + switch bn := blockNum.Int64(); bn { + case int64(0): + bn, err := api.backend.BlockNumber() + if err != nil { + return nil + } + blockNumber = bn + case int64(-1): + bn, err := api.backend.BlockNumber() + if err != nil { + return nil + } + blockNumber = bn + pendingQuery = true + } + + heightCleaned := strings.Replace(blockNumber.String(), "0x", "", -1) + height, err := strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil + } + resBlock, err := api.clientCtx.Client.Block(&height) if err != nil { return nil } + txCount := hexutil.Uint(len(resBlock.Block.Txs)) - n := hexutil.Uint(len(resBlock.Block.Txs)) - return &n + txCountCleaned := strings.Replace(txCount.String(), "0x", "", -1) + totalTxCount, err := strconv.ParseUint(txCountCleaned, 16, 32) + if err != nil { + return nil + } + + if pendingQuery { + pendingtx, err := api.backend.PendingTransactions() + if err != nil { + return nil + } + pendingTxCount := len(pendingtx) / 2 + totalTxCount += uint64(pendingTxCount) + } + + total := hexutil.Uint(totalTxCount) + return &total } // GetUncleCountByBlockHash returns the number of uncles in the block idenfied by hash. Always zero. @@ -573,7 +671,111 @@ func (api *PublicEthereumAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map // GetBlockByNumber returns the block identified by number. func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { api.logger.Debug("eth_getBlockByNumber", "number", blockNum, "full", fullTx) - return api.backend.GetBlockByNumber(blockNum, fullTx) + + var blockNumber hexutil.Uint64 + switch blockNum { + case rpctypes.LatestBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, err + } + blockNumber = bn + case rpctypes.PendingBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, err + } + + heightCleaned := strings.Replace(bn.String(), "0x", "", -1) + height, err := strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil, err + } + + //latest block info + latestBlock, err := api.clientCtx.Client.Block(&height) + if err != nil { + return nil, err + } + header := latestBlock.Block.Header + + unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(100) + if err != nil { + return nil, err + } + + var pendingTxs []common.Hash + var gasUsed *big.Int + if fullTx { + pendingTxs, gasUsed, err = convertTransactionsToRPC( + api.clientCtx, unconfirmedTxs.Txs, common.BytesToHash(header.Hash()), uint64(header.Height)+1, + ) + if err != nil { + return nil, err + } + } else { + pendingTxs = make([]common.Hash, len(unconfirmedTxs.Txs)) + for i, tx := range unconfirmedTxs.Txs { + pendingTxs[i] = common.BytesToHash(tx.Hash()) + } + } + + return rpctypes.FormatBlock( + tmtypes.Header{ + Version: header.Version, + ChainID: header.ChainID, + Height: height + 1, + Time: time.Time{}, + LastBlockID: latestBlock.BlockID, + LastCommitHash: nil, + DataHash: nil, + ValidatorsHash: nil, + NextValidatorsHash: nil, + ConsensusHash: header.ConsensusHash, + AppHash: nil, + LastResultsHash: nil, + EvidenceHash: nil, + ProposerAddress: nil, + }, + 0, + 0, + gasUsed, + pendingTxs, + ethtypes.Bloom{}, + ), nil + default: + blockNumber = hexutil.Uint64(blockNum.Int64()) + } + + heightCleaned := strings.Replace(blockNumber.String(), "0x", "", -1) + height, err := strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil, err + } + + return api.backend.GetBlockByNumber(rpctypes.BlockNumber(height), fullTx) +} + +func convertTransactionsToRPC(cliCtx clientcontext.CLIContext, txs []tmtypes.Tx, blockHash common.Hash, height uint64) ([]common.Hash, *big.Int, error) { + transactions := make([]common.Hash, len(txs)) + gasUsed := big.NewInt(0) + + for i, tx := range txs { + ethTx, err := rpctypes.RawTxToEthTx(cliCtx, tx) + if err != nil { + // continue to next transaction in case it's not a MsgEthereumTx + continue + } + // TODO: Remove gas usage calculation if saving gasUsed per block + gasUsed.Add(gasUsed, ethTx.Fee()) + tx, err := rpctypes.NewTransaction(ethTx, common.BytesToHash(tx.Hash()), blockHash, height, uint64(i)) + if err != nil { + return nil, nil, err + } + transactions[i] = tx.Hash + } + + return transactions, gasUsed, nil } // GetTransactionByHash returns the transaction identified by hash. From d7142255dc1d24fc0c8aa0b6eb8ce30b2aea18b7 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Fri, 23 Oct 2020 10:55:10 -0700 Subject: [PATCH 16/61] exportable FormatBlock method --- rpc/types/utils.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/types/utils.go b/rpc/types/utils.go index e1bbaec7b..6eab952b3 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -88,7 +88,7 @@ func EthBlockFromTendermint(clientCtx clientcontext.CLIContext, block *tmtypes.B bloom := bloomRes.Bloom - return formatBlock(block.Header, block.Size(), gasLimit, gasUsed, transactions, bloom), nil + return FormatBlock(block.Header, block.Size(), gasLimit, gasUsed, transactions, bloom), nil } // EthHeaderFromTendermint is an util function that returns an Ethereum Header @@ -148,7 +148,7 @@ func BlockMaxGasFromConsensusParams(_ context.Context, clientCtx clientcontext.C return gasLimit, nil } -func formatBlock( +func FormatBlock( header tmtypes.Header, size int, gasLimit int64, gasUsed *big.Int, transactions interface{}, bloom ethtypes.Bloom, ) map[string]interface{} { From fa7cc7db52381765ede5135c9ebf68365ab4cc2e Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 26 Oct 2020 12:00:43 -0700 Subject: [PATCH 17/61] eth_getTransactionByHash --- rpc/namespaces/eth/api.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index d6aec43dc..85e02b458 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -781,6 +781,22 @@ func convertTransactionsToRPC(cliCtx clientcontext.CLIContext, txs []tmtypes.Tx, // GetTransactionByHash returns the transaction identified by hash. func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.Transaction, error) { api.logger.Debug("eth_getTransactionByHash", "hash", hash) + pendingTxs, err := api.PendingTransactions() + if err != nil { + return nil, err + } + + if len(pendingTxs) != 0 { + for _, pendingTx := range pendingTxs { + if pendingTx == nil { + continue + } + if hash == pendingTx.Hash { + return pendingTx, nil + } + } + } + tx, err := api.clientCtx.Client.Tx(hash.Bytes(), false) if err != nil { // Return nil for transaction when not found From d9e8b3a6fe3be43cf160f99cb3534527ed9237ab Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 26 Oct 2020 13:35:53 -0700 Subject: [PATCH 18/61] eth_getTransactionByBlockNumberAndIndex --- rpc/namespaces/eth/api.go | 47 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 85e02b458..624fa9aaa 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -842,12 +842,57 @@ func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) { api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - height := blockNum.Int64() + var height int64 + pendingQuery := false + switch blockNum { + case rpctypes.LatestBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, err + } + heightCleaned := strings.Replace(bn.String(), "0x", "", -1) + height, err = strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil, err + } + case rpctypes.PendingBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, err + } + heightCleaned := strings.Replace(bn.String(), "0x", "", -1) + height, err = strconv.ParseInt(heightCleaned, 16, 64) + if err != nil { + return nil, err + } + pendingQuery = true + default: + height = blockNum.Int64() + } + resBlock, err := api.clientCtx.Client.Block(&height) if err != nil { return nil, err } + if pendingQuery { + pendingtx, err := api.backend.PendingTransactions() + if err != nil { + return nil, err + } + index := hexutil.Uint64(0) + for i := range pendingtx { + if pendingtx[i] == nil { + continue + } + if index.String() == idx.String() { + return pendingtx[i], nil + } + index++ + } + return nil, nil + } + return api.getTransactionByBlockAndIndex(resBlock.Block, idx) } From 32e99a5441e31ef1b2de5bc5d866cf0d83ec4421 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 26 Oct 2020 15:49:16 -0700 Subject: [PATCH 19/61] pending nonce --- rpc/namespaces/eth/api.go | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 624fa9aaa..35a548ea6 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -248,22 +248,22 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp } if pendingQuery { - pendingtx, err := api.backend.PendingTransactions() + pendingTxs, err := api.backend.PendingTransactions() if err != nil { return nil, err } - for i := range pendingtx { - if pendingtx[i] == nil { + for i := range pendingTxs { + if pendingTxs[i] == nil { continue } - if pendingtx[i].From == address { + if pendingTxs[i].From == address { pendingBalance := big.NewInt(0) - pendingBalance = pendingBalance.Add(val, pendingtx[i].Value.ToInt()) + pendingBalance = pendingBalance.Add(val, pendingTxs[i].Value.ToInt()) val = pendingBalance - } else if *pendingtx[i].To == address { + } else if *pendingTxs[i].To == address { pendingBalance := big.NewInt(0) - pendingBalance = pendingBalance.Sub(val, pendingtx[i].Value.ToInt()) + pendingBalance = pendingBalance.Sub(val, pendingTxs[i].Value.ToInt()) val = pendingBalance } } @@ -1090,7 +1090,6 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty gasPrice := (*big.Int)(args.GasPrice) if args.GasPrice == nil { - // Set default gas price // TODO: Change to min gas price from context once available through server/daemon gasPrice = big.NewInt(ethermint.DefaultGasPrice) @@ -1109,6 +1108,26 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty if err != nil { return nil, err } + + pendingTxs, err := api.backend.PendingTransactions() + if err != nil { + return nil, err + } + fmt.Println("nonce before pending: ", nonce) + if len(pendingTxs) != 0 { + fmt.Println("pending transactions found!") + fmt.Println("accounting for pending tx into nonce") + for i := range pendingTxs { + if pendingTxs[i] == nil { + continue + } + if pendingTxs[i].From == args.From { + nonce++ + } + } + } + fmt.Println("nonce after: ", nonce) + } else { nonce = (uint64)(*args.Nonce) } From 0bc623d26c8cd58eaaeed048e09123c3a4f7a896 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 26 Oct 2020 18:25:16 -0700 Subject: [PATCH 20/61] set nonce for pending and check for invalid --- rpc/namespaces/eth/api.go | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 35a548ea6..c66407238 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -39,6 +39,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth" authclient "github.com/cosmos/cosmos-sdk/x/auth/client/utils" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -1095,28 +1096,24 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty gasPrice = big.NewInt(ethermint.DefaultGasPrice) } - if args.Nonce == nil { - // Get nonce (sequence) from account - from := sdk.AccAddress(args.From.Bytes()) - accRet := authtypes.NewAccountRetriever(api.clientCtx) - - if api.clientCtx.Keybase == nil { - return nil, fmt.Errorf("clientCtx.Keybase is nil") - } + // Get nonce (sequence) from account + from := sdk.AccAddress(args.From.Bytes()) + accRet := authtypes.NewAccountRetriever(api.clientCtx) + if api.clientCtx.Keybase == nil { + return nil, fmt.Errorf("clientCtx.Keybase is nil") + } - _, nonce, err = accRet.GetAccountNumberSequence(from) - if err != nil { - return nil, err - } + _, nonce, err = accRet.GetAccountNumberSequence(from) + if err != nil { + return nil, err + } + if args.Nonce == nil { pendingTxs, err := api.backend.PendingTransactions() if err != nil { return nil, err } - fmt.Println("nonce before pending: ", nonce) if len(pendingTxs) != 0 { - fmt.Println("pending transactions found!") - fmt.Println("accounting for pending tx into nonce") for i := range pendingTxs { if pendingTxs[i] == nil { continue @@ -1126,9 +1123,11 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty } } } - fmt.Println("nonce after: ", nonce) - } else { + if (uint64)(*args.Nonce) <= nonce { + return nil, sdkerrors.ErrInvalidSequence + } + nonce = (uint64)(*args.Nonce) } From bbace88abf8142ea0473fab2459b4ef29c4c4b36 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Wed, 28 Oct 2020 16:05:50 -0700 Subject: [PATCH 21/61] WIP: doCall --- rpc/namespaces/eth/api.go | 108 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index c66407238..5a1d99691 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -560,11 +560,47 @@ func (api *PublicEthereumAPI) Call(args rpctypes.CallArgs, blockNr rpctypes.Bloc func (api *PublicEthereumAPI) doCall( args rpctypes.CallArgs, blockNr rpctypes.BlockNumber, globalGasCap *big.Int, ) (*sdk.SimulationResponse, error) { + + var blockNumber rpctypes.BlockNumber + var pending bool + switch blockNr { + case rpctypes.LatestBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, err + } + bnCleaned := strings.Replace(bn.String(), "0x", "", -1) + height, err := strconv.ParseInt(bnCleaned, 16, 64) + if err != nil { + return nil, err + } + blockNumber = rpctypes.BlockNumber(height) + case rpctypes.PendingBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, err + } + bnCleaned := strings.Replace(bn.String(), "0x", "", -1) + height, err := strconv.ParseInt(bnCleaned, 16, 64) + if err != nil { + return nil, err + } + blockNumber = rpctypes.BlockNumber(height) + pending = true + default: + blockNumber = blockNr + } + + fmt.Println("blockNumber: ", blockNumber) + fmt.Println("pending:", pending) + + fmt.Println("args: ", args) + // Set height for historical queries clientCtx := api.clientCtx - if blockNr.Int64() != 0 { - clientCtx = api.clientCtx.WithHeight(blockNr.Int64()) + if blockNumber.Int64() != 0 { + clientCtx = api.clientCtx.WithHeight(blockNumber.Int64()) } // Set sender address or use a default if none specified @@ -614,17 +650,81 @@ func (api *PublicEthereumAPI) doCall( toAddr = sdk.AccAddress(args.To.Bytes()) } + var ethermintMsgs []sdk.Msg // Create new call message msg := evmtypes.NewMsgEthermint(0, &toAddr, sdk.NewIntFromBigInt(value), gas, sdk.NewIntFromBigInt(gasPrice), data, sdk.AccAddress(addr.Bytes())) - if err := msg.ValidateBasic(); err != nil { return nil, err } + ethermintMsgs = append(ethermintMsgs, msg) + + fmt.Println("ethermintMsgs before pending: ", ethermintMsgs) + + // convert the pending transactions into ethermint msgs + if pending { + fmt.Println("converting pending tx to emintmsg!") + pendingTxs, err := api.PendingTransactions() + if err != nil { + return nil, err + } + fmt.Println("pendingTxs: ", pendingTxs) + if len(pendingTxs) > 0 { + for _, pendingTx := range pendingTxs { + if pendingTx == nil { + fmt.Println("nil pending tx found!") + continue + } + + pendingTo, err := sdk.AccAddressFromHex(strings.Replace(pendingTx.To.Hex(), "0x", "", -1)) + if err != nil { + fmt.Println("broke at pendingTo!") + return nil, err + } + + pendingFrom, err := sdk.AccAddressFromHex(strings.Replace(pendingTx.From.Hex(), "0x", "", -1)) + if err != nil { + fmt.Println("broke at pendingFrom!") + return nil, err + } + + pendingGasCleaned := strings.Replace(pendingTx.Gas.String(), "0x", "", -1) + pendingGas, err := strconv.ParseUint(pendingGasCleaned, 16, 64) + if err != nil { + fmt.Println("broke at pendingGas!") + return nil, err + } + + pendingVal := pendingTx.Value.ToInt() + pendingGasPrice := new(big.Int).SetUint64(ethermint.DefaultGasPrice) + if args.GasPrice != nil { + pendingGasPrice = pendingTx.GasPrice.ToInt() + } + + pendingData := pendingTx.Input + + msg := evmtypes.NewMsgEthermint(0, &pendingTo, sdk.NewIntFromBigInt(pendingVal), pendingGas, + sdk.NewIntFromBigInt(pendingGasPrice), pendingData, pendingFrom) + if err := msg.ValidateBasic(); err != nil { + fmt.Println("broke at converting to msgEthermint!") + return nil, err + } + + ethermintMsgs = append(ethermintMsgs, msg) + } + } + } + + fmt.Println("ethermintMsgs after pending: ", ethermintMsgs) + // Generate tx to be used to simulate (signature isn't needed) var stdSig authtypes.StdSignature - tx := authtypes.NewStdTx([]sdk.Msg{msg}, authtypes.StdFee{}, []authtypes.StdSignature{stdSig}, "") + stdSigs := []authtypes.StdSignature{stdSig} + fmt.Println("stdSigs: ", stdSigs) + tx := authtypes.NewStdTx(ethermintMsgs, authtypes.StdFee{}, stdSigs, "") + + fmt.Println() txEncoder := authclient.GetTxEncoder(clientCtx.Codec) txBytes, err := txEncoder(tx) From 15769e8c59ea3b3407eb00cc9f1f8796c4ba9d55 Mon Sep 17 00:00:00 2001 From: noot Date: Wed, 28 Oct 2020 20:51:27 -0400 Subject: [PATCH 22/61] add pending tx test --- rpc/namespaces/eth/api.go | 4 ++++ tests/rpc_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 5a1d99691..a7997f638 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -729,20 +729,24 @@ func (api *PublicEthereumAPI) doCall( txEncoder := authclient.GetTxEncoder(clientCtx.Codec) txBytes, err := txEncoder(tx) if err != nil { + fmt.Println("failed to encode") return nil, err } // Transaction simulation through query res, _, err := clientCtx.QueryWithData("app/simulate", txBytes) if err != nil { + fmt.Println("failed to query") return nil, err } var simResponse sdk.SimulationResponse if err := clientCtx.Codec.UnmarshalBinaryBare(res, &simResponse); err != nil { + fmt.Println("failed to simulate") return nil, err } + fmt.Println(simResponse) return &simResponse, nil } diff --git a/tests/rpc_test.go b/tests/rpc_test.go index fe3ae2906..b0a7aca75 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -794,3 +794,31 @@ func TestEth_GetBlockByNumber(t *testing.T) { require.Equal(t, "0x0", block["extraData"].(string)) require.Equal(t, []interface{}{}, block["uncles"].([]interface{})) } + +func TestEth_Call_Pending(t *testing.T) { + param := make([]map[string]string, 1) + param[0] = make(map[string]string) + param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["to"] = "0x0000000000000000000000000000000012341234" + param[0]["value"] = "0xA" + param[0]["gasLimit"] = "0x5208" + param[0]["gasPrice"] = "0x1" + + rpcRes := call(t, "eth_sendTransaction", param) + + var hash hexutil.Bytes + err := json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) + + param = make([]map[string]string, 1) + param[0] = make(map[string]string) + param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["to"] = "0x0000000000000000000000000000000012341234" + param[0]["value"] = "0xA" + param[0]["gasLimit"] = "0x5208" + param[0]["gasPrice"] = "0x1" + + rpcRes = call(t, "eth_call", []interface{}{param[0], "pending"}) + err = json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) +} From 9826b1ce1cdc1883a736828d243985f7d72fbd90 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Thu, 29 Oct 2020 13:34:04 -0700 Subject: [PATCH 23/61] cleanup + refactor --- rpc/namespaces/eth/api.go | 206 +++++++++++++------------------------- 1 file changed, 70 insertions(+), 136 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 5a1d99691..97106d73a 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -227,15 +227,12 @@ func (api *PublicEthereumAPI) BlockNumber() (hexutil.Uint64, error) { // GetBalance returns the provided account's balance up to the provided block number. func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Big, error) { api.logger.Debug("eth_getBalance", "address", address, "block number", blockNum) - pendingQuery := false - var ctx clientcontext.CLIContext - if blockNum == rpctypes.PendingBlockNumber { - // uses latest block number for pending: -1 -> 0 - ctx = api.clientCtx.WithHeight(rpctypes.LatestBlockNumber.Int64()) - pendingQuery = true - } else { - ctx = api.clientCtx.WithHeight(blockNum.Int64()) + blockNumber, pending, err := api.getPendingBlock(blockNum) + if err != nil { + return nil, err } + + ctx := api.clientCtx.WithHeight(*blockNumber) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) if err != nil { return nil, err @@ -248,7 +245,7 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp return nil, err } - if pendingQuery { + if pending { pendingTxs, err := api.backend.PendingTransactions() if err != nil { return nil, err @@ -260,11 +257,11 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp } if pendingTxs[i].From == address { pendingBalance := big.NewInt(0) - pendingBalance = pendingBalance.Add(val, pendingTxs[i].Value.ToInt()) + pendingBalance = pendingBalance.Sub(val, pendingTxs[i].Value.ToInt()) val = pendingBalance } else if *pendingTxs[i].To == address { pendingBalance := big.NewInt(0) - pendingBalance = pendingBalance.Sub(val, pendingTxs[i].Value.ToInt()) + pendingBalance = pendingBalance.Add(val, pendingTxs[i].Value.ToInt()) val = pendingBalance } } @@ -290,21 +287,17 @@ func (api *PublicEthereumAPI) GetStorageAt(address common.Address, key string, b // GetTransactionCount returns the number of transactions at the given address up to the given block number. func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error) { api.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum) - pendingQuery := false - var ctx clientcontext.CLIContext - if blockNum == rpctypes.PendingBlockNumber { - // uses latest block number for pending: -1 -> 0 - ctx = api.clientCtx.WithHeight(rpctypes.LatestBlockNumber.Int64()) - pendingQuery = true - } else { - ctx = api.clientCtx.WithHeight(blockNum.Int64()) + blockNumber, pending, err := api.getPendingBlock(blockNum) + if err != nil { + return nil, err } + ctx := api.clientCtx.WithHeight(*blockNumber) // Get nonce (sequence) from account from := sdk.AccAddress(address.Bytes()) accRet := authtypes.NewAccountRetriever(ctx) - err := accRet.EnsureExists(from) + err = accRet.EnsureExists(from) if err != nil { // account doesn't exist yet, return 0 n := hexutil.Uint64(0) @@ -317,7 +310,7 @@ func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockN } pendingNonce := uint64(0) - if pendingQuery { + if pending { pendingtx, err := api.backend.PendingTransactions() if err != nil { return nil, err @@ -363,31 +356,12 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) * func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { api.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) - var blockNumber hexutil.Uint64 - pendingQuery := false - switch bn := blockNum.Int64(); bn { - case int64(0): - bn, err := api.backend.BlockNumber() - if err != nil { - return nil - } - blockNumber = bn - case int64(-1): - bn, err := api.backend.BlockNumber() - if err != nil { - return nil - } - blockNumber = bn - pendingQuery = true - } - - heightCleaned := strings.Replace(blockNumber.String(), "0x", "", -1) - height, err := strconv.ParseInt(heightCleaned, 16, 64) + blockNumber, pending, err := api.getPendingBlock(blockNum) if err != nil { return nil } - resBlock, err := api.clientCtx.Client.Block(&height) + resBlock, err := api.clientCtx.Client.Block(blockNumber) if err != nil { return nil } @@ -399,7 +373,7 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes return nil } - if pendingQuery { + if pending { pendingtx, err := api.backend.PendingTransactions() if err != nil { return nil @@ -558,38 +532,10 @@ func (api *PublicEthereumAPI) Call(args rpctypes.CallArgs, blockNr rpctypes.Bloc // DoCall performs a simulated call operation through the evmtypes. It returns the // estimated gas used on the operation or an error if fails. func (api *PublicEthereumAPI) doCall( - args rpctypes.CallArgs, blockNr rpctypes.BlockNumber, globalGasCap *big.Int, + args rpctypes.CallArgs, blockNum rpctypes.BlockNumber, globalGasCap *big.Int, ) (*sdk.SimulationResponse, error) { - var blockNumber rpctypes.BlockNumber - var pending bool - switch blockNr { - case rpctypes.LatestBlockNumber: - bn, err := api.backend.BlockNumber() - if err != nil { - return nil, err - } - bnCleaned := strings.Replace(bn.String(), "0x", "", -1) - height, err := strconv.ParseInt(bnCleaned, 16, 64) - if err != nil { - return nil, err - } - blockNumber = rpctypes.BlockNumber(height) - case rpctypes.PendingBlockNumber: - bn, err := api.backend.BlockNumber() - if err != nil { - return nil, err - } - bnCleaned := strings.Replace(bn.String(), "0x", "", -1) - height, err := strconv.ParseInt(bnCleaned, 16, 64) - if err != nil { - return nil, err - } - blockNumber = rpctypes.BlockNumber(height) - pending = true - default: - blockNumber = blockNr - } + blockNumber, pending, err := api.getPendingBlock(blockNum) fmt.Println("blockNumber: ", blockNumber) fmt.Println("pending:", pending) @@ -599,8 +545,8 @@ func (api *PublicEthereumAPI) doCall( // Set height for historical queries clientCtx := api.clientCtx - if blockNumber.Int64() != 0 { - clientCtx = api.clientCtx.WithHeight(blockNumber.Int64()) + if *blockNumber != 0 { + clientCtx = api.clientCtx.WithHeight(*blockNumber) } // Set sender address or use a default if none specified @@ -772,34 +718,18 @@ func (api *PublicEthereumAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map // GetBlockByNumber returns the block identified by number. func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { api.logger.Debug("eth_getBlockByNumber", "number", blockNum, "full", fullTx) + blockNumber, pending, err := api.getPendingBlock(blockNum) + if err != nil { + return nil, err + } - var blockNumber hexutil.Uint64 - switch blockNum { - case rpctypes.LatestBlockNumber: - bn, err := api.backend.BlockNumber() - if err != nil { - return nil, err - } - blockNumber = bn - case rpctypes.PendingBlockNumber: - bn, err := api.backend.BlockNumber() - if err != nil { - return nil, err - } - - heightCleaned := strings.Replace(bn.String(), "0x", "", -1) - height, err := strconv.ParseInt(heightCleaned, 16, 64) - if err != nil { - return nil, err - } - - //latest block info - latestBlock, err := api.clientCtx.Client.Block(&height) + if pending { + // latest block info + latestBlock, err := api.clientCtx.Client.Block(blockNumber) if err != nil { return nil, err } header := latestBlock.Block.Header - unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(100) if err != nil { return nil, err @@ -825,7 +755,7 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu tmtypes.Header{ Version: header.Version, ChainID: header.ChainID, - Height: height + 1, + Height: *blockNumber + 1, Time: time.Time{}, LastBlockID: latestBlock.BlockID, LastCommitHash: nil, @@ -844,17 +774,9 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu pendingTxs, ethtypes.Bloom{}, ), nil - default: - blockNumber = hexutil.Uint64(blockNum.Int64()) - } - - heightCleaned := strings.Replace(blockNumber.String(), "0x", "", -1) - height, err := strconv.ParseInt(heightCleaned, 16, 64) - if err != nil { - return nil, err } - return api.backend.GetBlockByNumber(rpctypes.BlockNumber(height), fullTx) + return api.backend.GetBlockByNumber(rpctypes.BlockNumber(*blockNumber), fullTx) } func convertTransactionsToRPC(cliCtx clientcontext.CLIContext, txs []tmtypes.Tx, blockHash common.Hash, height uint64) ([]common.Hash, *big.Int, error) { @@ -943,40 +865,17 @@ func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) { api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - var height int64 - pendingQuery := false - switch blockNum { - case rpctypes.LatestBlockNumber: - bn, err := api.backend.BlockNumber() - if err != nil { - return nil, err - } - heightCleaned := strings.Replace(bn.String(), "0x", "", -1) - height, err = strconv.ParseInt(heightCleaned, 16, 64) - if err != nil { - return nil, err - } - case rpctypes.PendingBlockNumber: - bn, err := api.backend.BlockNumber() - if err != nil { - return nil, err - } - heightCleaned := strings.Replace(bn.String(), "0x", "", -1) - height, err = strconv.ParseInt(heightCleaned, 16, 64) - if err != nil { - return nil, err - } - pendingQuery = true - default: - height = blockNum.Int64() + blockNumber, pending, err := api.getPendingBlock(blockNum) + if err != nil { + return nil, err } - resBlock, err := api.clientCtx.Client.Block(&height) + resBlock, err := api.clientCtx.Client.Block(blockNumber) if err != nil { return nil, err } - if pendingQuery { + if pending { pendingtx, err := api.backend.PendingTransactions() if err != nil { return nil, err @@ -1269,3 +1168,38 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty return &msg, nil } + +// getPendingBlock returns the blocknumber and pending +// if -1, returns latest blocknumber and pending is set to true +// if 0, returns latest blocknumber and pending is set to false +// if not 0 or -1, returns blocknumber and pendisng is set to false +func (api *PublicEthereumAPI) getPendingBlock(blockNum rpctypes.BlockNumber) (*int64, bool, error) { + var blockNumber int64 + pending := false + switch blockNum { + case rpctypes.LatestBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, pending, err + } + bnCleaned := strings.Replace(bn.String(), "0x", "", -1) + blockNumber, err = strconv.ParseInt(bnCleaned, 16, 64) + if err != nil { + return nil, pending, err + } + case rpctypes.PendingBlockNumber: + bn, err := api.backend.BlockNumber() + if err != nil { + return nil, pending, err + } + bnCleaned := strings.Replace(bn.String(), "0x", "", -1) + blockNumber, err = strconv.ParseInt(bnCleaned, 16, 64) + if err != nil { + return nil, pending, err + } + pending = true + default: + blockNumber = blockNum.Int64() + } + return &blockNumber, pending, nil +} From 77957fd97bc4889449ed71dea5989844b54a7fe5 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Fri, 13 Nov 2020 09:25:59 -0800 Subject: [PATCH 24/61] push first tests and init pending --- init.sh | 26 +-- tests/rpc_pending_test.go | 323 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 339 insertions(+), 10 deletions(-) create mode 100644 tests/rpc_pending_test.go diff --git a/init.sh b/init.sh index b438b4192..1c193c8da 100755 --- a/init.sh +++ b/init.sh @@ -35,15 +35,17 @@ cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["faucet"]["enable_fau # increase block time (?) cat $HOME/.ethermintd/config/genesis.json | jq '.consensus_params["block"]["time_iota_ms"]="30000"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json -sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermintd/config/config.toml - -sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermintd/config/config.toml -sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermintd/config/config.toml -sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermintd/config/config.toml -sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermintd/config/config.toml -sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermintd/config/config.toml -sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermintd/config/config.toml -sed -i 's/timeout_commit = "5s"/timeout_commit = "50s"/g' $HOME/.ethermintd/config/config.toml +if [[ $1 == "pending" ]]; then + echo "pending mode on; block times will be set to ~60s." + sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_commit = "5s"/timeout_commit = "50s"/g' $HOME/.ethermintd/config/config.toml +fi # Allocate genesis accounts (cosmos formatted addresses) ethermintd add-genesis-account $(ethermintcli keys show $KEY -a) 100000000000000000000aphoton @@ -67,4 +69,8 @@ echo -e '\nrun the following command in a different terminal/window to run the R echo -e "ethermintcli rest-server --laddr \"tcp://localhost:8545\" --unlock-key $KEY --chain-id $CHAINID --trace\n" # Start the node (remove the --pruning=nothing flag if historical queries are not needed) -ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" --trace +ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" --trace > d.log & + +sleep 1 + +ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key $KEY --chain-id $CHAINID --trace > cli.log & diff --git a/tests/rpc_pending_test.go b/tests/rpc_pending_test.go new file mode 100644 index 000000000..6952e2133 --- /dev/null +++ b/tests/rpc_pending_test.go @@ -0,0 +1,323 @@ +// This is a test utility for Ethermint's Web3 JSON-RPC services. +// +// To run these tests please first ensure you have the ethermintd running +// and have started the RPC service with `ethermintcli rest-server`. +// +// You can configure the desired HOST and MODE as well +package tests + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "net/http" + "os" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +const ( + addrA = "0xc94770007dda54cF92009BFF0dE90c06F603a09f" + addrAStoreKey = 0 +) + +var ( + MODE = os.Getenv("MODE") + HOST = os.Getenv("HOST") + + zeroString = "0x0" + from = []byte{} +) + +type Request struct { + Version string `json:"jsonrpc"` + Method string `json:"method"` + Params interface{} `json:"params"` + ID int `json:"id"` +} + +type RPCError struct { + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data,omitempty"` +} + +type Response struct { + Error *RPCError `json:"error"` + ID int `json:"id"` + Result json.RawMessage `json:"result,omitempty"` +} + +func TestMain(m *testing.M) { + if MODE != "pending" { + _, _ = fmt.Fprintln(os.Stdout, "Skipping pending RPC test") + return + } + + if HOST == "" { + HOST = "http://localhost:8545" + } + + 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 getAddress() ([]byte, error) { + rpcRes, err := callWithError("eth_accounts", []string{}) + if err != nil { + return nil, err + } + + var res []hexutil.Bytes + err = json.Unmarshal(rpcRes.Result, &res) + if err != nil { + return nil, err + } + + return res[0], nil +} + +func createRequest(method string, params interface{}) Request { + return Request{ + Version: "2.0", + Method: method, + Params: params, + ID: 1, + } +} + +func call(t *testing.T, method string, params interface{}) *Response { + req, err := json.Marshal(createRequest(method, params)) + require.NoError(t, err) + + var rpcRes *Response + time.Sleep(1 * time.Second) + /* #nosec */ + res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) + require.NoError(t, err) + + decoder := json.NewDecoder(res.Body) + rpcRes = new(Response) + err = decoder.Decode(&rpcRes) + require.NoError(t, err) + + err = res.Body.Close() + require.NoError(t, err) + require.Nil(t, rpcRes.Error) + + return rpcRes +} + +func callWithError(method string, params interface{}) (*Response, error) { + req, err := json.Marshal(createRequest(method, params)) + if err != nil { + return nil, err + } + + var rpcRes *Response + time.Sleep(1 * time.Second) + /* #nosec */ + res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) + if err != nil { + return nil, err + } + + decoder := json.NewDecoder(res.Body) + rpcRes = new(Response) + err = decoder.Decode(&rpcRes) + if err != nil { + return nil, err + } + + err = res.Body.Close() + if err != nil { + return nil, err + } + + if rpcRes.Error != nil { + return nil, fmt.Errorf(rpcRes.Error.Message) + } + + return rpcRes, nil +} + +// turns a 0x prefixed hex string to a big.Int +func hexToBigInt(t *testing.T, in string) *big.Int { + s := in[2:] + b, err := hex.DecodeString(s) + require.NoError(t, err) + return big.NewInt(0).SetBytes(b) +} + +// sendTestTransaction sends a dummy transaction +func sendTestTransaction(t *testing.T) hexutil.Bytes { + param := make([]map[string]string, 1) + param[0] = make(map[string]string) + param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["to"] = "0x1122334455667788990011223344556677889900" + param[0]["value"] = "0x1" + rpcRes := call(t, "eth_sendTransaction", param) + + var hash hexutil.Bytes + err := json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) + return hash +} + +// deployTestContract deploys a contract that emits an event in the constructor +func deployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) { + param := make([]map[string]string, 1) + param[0] = make(map[string]string) + param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" + param[0]["gas"] = "0x200000" + + rpcRes := call(t, "eth_sendTransaction", param) + + var hash hexutil.Bytes + err := json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) + + receipt := waitForReceipt(t, hash) + require.NotNil(t, receipt, "transaction failed") + require.Equal(t, "0x1", receipt["status"].(string)) + + return hash, receipt +} + +func getTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { + param := []string{hash.String()} + rpcRes := call(t, "eth_getTransactionReceipt", param) + + receipt := make(map[string]interface{}) + err := json.Unmarshal(rpcRes.Result, &receipt) + require.NoError(t, err) + + return receipt +} + +func waitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { + for i := 0; i < 12; i++ { + receipt := getTransactionReceipt(t, hash) + if receipt != nil { + return receipt + } + + time.Sleep(time.Second) + } + + return nil +} + +func TestEth_Pending_GetBalance(t *testing.T) { + 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" + + rpcRes := call(t, "eth_sendTransaction", param) + + var res hexutil.Big + + rpcRes = call(t, "eth_getBalance", []string{addrA, "pending"}) + err := res.UnmarshalJSON(rpcRes.Result) + require.NoError(t, err) + t.Logf("Got balance %s for %s\n", res.String(), addrA) + + if res.ToInt().Cmp(big.NewInt(10)) != 0 { + t.Errorf("expected balance: %d, got: %s", 10, res.String()) + } + + rpcRes = call(t, "eth_getBalance", []string{addrA, "latest"}) + err = res.UnmarshalJSON(rpcRes.Result) + require.NoError(t, err) + t.Logf("Got balance %s for %s\n", res.String(), addrA) + + if res.ToInt().Cmp(big.NewInt(0)) != 0 { + t.Errorf("expected balance: %d, got: %s", 0, res.String()) + } +} + +func TestEth_Pending_GetTransactionCount(t *testing.T) { + currentNonce := getNonce(t, "latest") + t.Logf("Current nonce is %d", currentNonce) + + 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" + + _ = call(t, "eth_sendTransaction", param) + + pendingNonce := getNonce(t, "pending") + latestNonce := getNonce(t, "latest") + t.Logf("Latest nonce is %d", latestNonce) + require.Equal(t, currentNonce, latestNonce) + t.Logf("Pending nonce is %d", pendingNonce) + require.NotEqual(t, latestNonce, pendingNonce) +} + +func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { + 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" + + _ = call(t, "eth_sendTransaction", param) + + rpcRes := call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) + var pendingTxCount hexutil.Uint + err := json.Unmarshal(rpcRes.Result, &pendingTxCount) + require.NoError(t, err) + t.Logf("Pending nonce is %d", pendingTxCount) + + rpcRes = call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"latest"}) + var latestTxCount hexutil.Uint + err = json.Unmarshal(rpcRes.Result, &latestTxCount) + require.NoError(t, err) + t.Logf("Latest nonce is %d", latestTxCount) + + require.NotEqual(t, pendingTxCount, latestTxCount) +} + +func TestEth_Pending_GetBlockByNumber(t *testing.T) { + 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" + + _ = call(t, "eth_sendTransaction", param) + + rpcRes := call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) + var pendingBlock map[string]interface{} + err := json.Unmarshal(rpcRes.Result, &pendingTxCount) + require.NoError(t, err) + t.Logf("Pending nonce is %d", pendingTxCount) + +} From 1a47621b36c464a81bc9a12826866070b5f08284 Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Mon, 16 Nov 2020 21:16:42 +0100 Subject: [PATCH 25/61] pending changes (#600) * cleanup * updates * more fixes * lint --- rpc/backend/backend.go | 17 +- rpc/namespaces/eth/api.go | 418 ++++++++++++++++---------------------- 2 files changed, 184 insertions(+), 251 deletions(-) diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 99d711747..6d0508ce9 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -22,6 +22,7 @@ import ( type Backend interface { // Used by block filter; also used for polling BlockNumber() (hexutil.Uint64, error) + LatestBlockNumber() (int64, error) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) @@ -60,13 +61,12 @@ func New(clientCtx clientcontext.CLIContext) *EthermintBackend { // BlockNumber returns the current block number. func (b *EthermintBackend) BlockNumber() (hexutil.Uint64, error) { - // NOTE: using 0 as min and max height returns the blockchain info up to the latest block. - info, err := b.clientCtx.Client.BlockchainInfo(0, 0) + blockNumber, err := b.LatestBlockNumber() if err != nil { return hexutil.Uint64(0), err } - return hexutil.Uint64(info.LastHeight), nil + return hexutil.Uint64(blockNumber), nil } // GetBlockByNumber returns the block identified by number. @@ -257,3 +257,14 @@ func (b *EthermintBackend) GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, er func (b *EthermintBackend) BloomStatus() (uint64, uint64) { return 4096, 0 } + +// latestBlockNumber gets the latest block height in int64 format. +func (b *EthermintBackend) LatestBlockNumber() (int64, error) { + // NOTE: using 0 as min and max height returns the blockchain info up to the latest block. + info, err := b.clientCtx.Client.BlockchainInfo(0, 0) + if err != nil { + return 0, err + } + + return info.LastHeight, nil +} diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 2cf728e6b..5e37bdd75 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -7,8 +7,6 @@ import ( "fmt" "math/big" "os" - "strconv" - "strings" "sync" "time" @@ -218,7 +216,7 @@ func (api *PublicEthereumAPI) Accounts() ([]common.Address, error) { return addresses, nil } -// rpctypes.BlockNumber returns the current block number. +// BlockNumber returns the current block number. func (api *PublicEthereumAPI) BlockNumber() (hexutil.Uint64, error) { api.logger.Debug("eth_blockNumber") return api.backend.BlockNumber() @@ -227,13 +225,13 @@ func (api *PublicEthereumAPI) BlockNumber() (hexutil.Uint64, error) { // GetBalance returns the provided account's balance up to the provided block number. func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Big, error) { api.logger.Debug("eth_getBalance", "address", address, "block number", blockNum) - blockNumber, pending, err := api.getPendingBlock(blockNum) - if err != nil { - return nil, err + + clientCtx := api.clientCtx + if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) { + clientCtx = api.clientCtx.WithHeight(blockNum.Int64()) } - ctx := api.clientCtx.WithHeight(*blockNumber) - res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) + res, _, err := clientCtx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) if err != nil { return nil, err } @@ -245,25 +243,25 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp return nil, err } - if pending { - pendingTxs, err := api.backend.PendingTransactions() - if err != nil { - return nil, err + if blockNum != rpctypes.PendingBlockNumber { + return (*hexutil.Big)(val), nil + } + + // update the address balance with the pending transactions value (if applicable) + pendingTxs, err := api.backend.PendingTransactions() + if err != nil { + return nil, err + } + + for _, tx := range pendingTxs { + if tx == nil { + continue } - for i := range pendingTxs { - if pendingTxs[i] == nil { - continue - } - if pendingTxs[i].From == address { - pendingBalance := big.NewInt(0) - pendingBalance = pendingBalance.Sub(val, pendingTxs[i].Value.ToInt()) - val = pendingBalance - } else if *pendingTxs[i].To == address { - pendingBalance := big.NewInt(0) - pendingBalance = pendingBalance.Add(val, pendingTxs[i].Value.ToInt()) - val = pendingBalance - } + if tx.From == address { + val = new(big.Int).Sub(val, tx.Value.ToInt()) + } else if *tx.To == address { + val = new(big.Int).Add(val, tx.Value.ToInt()) } } @@ -287,17 +285,19 @@ func (api *PublicEthereumAPI) GetStorageAt(address common.Address, key string, b // GetTransactionCount returns the number of transactions at the given address up to the given block number. func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error) { api.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum) - blockNumber, pending, err := api.getPendingBlock(blockNum) - if err != nil { - return nil, err + + clientCtx := api.clientCtx + + // pass the given block height to the context if the height is not pending or latest + if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) { + clientCtx = api.clientCtx.WithHeight(blockNum.Int64()) } - ctx := api.clientCtx.WithHeight(*blockNumber) // Get nonce (sequence) from account from := sdk.AccAddress(address.Bytes()) - accRet := authtypes.NewAccountRetriever(ctx) + accRet := authtypes.NewAccountRetriever(clientCtx) - err = accRet.EnsureExists(from) + err := accRet.EnsureExists(from) if err != nil { // account doesn't exist yet, return 0 n := hexutil.Uint64(0) @@ -309,22 +309,24 @@ func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockN return nil, err } - pendingNonce := uint64(0) - if pending { - pendingtx, err := api.backend.PendingTransactions() + // the account retriever doesn't include the uncommitted transactions on the nonce so we need to + // manually add them + if blockNum == rpctypes.PendingBlockNumber { + pendingTxs, err := api.backend.PendingTransactions() if err != nil { return nil, err } - for i := range pendingtx { - if pendingtx[i] == nil { + for _, tx := range pendingTxs { + if tx == nil { continue } - if pendingtx[i].From == address { - pendingNonce++ + + // update the nonce if the sender matches the given address + if tx.From == address { + nonce++ } } - nonce += pendingNonce } n := hexutil.Uint64(nonce) @@ -353,37 +355,28 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) * return &n } +// GetBlockTransactionCountByNumber returns the number of transactions in the block identified by its height. func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { api.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) - blockNumber, pending, err := api.getPendingBlock(blockNum) - if err != nil { - return nil - } - - resBlock, err := api.clientCtx.Client.Block(blockNumber) - if err != nil { - return nil + if blockNum != rpctypes.PendingBlockNumber { + height := blockNum.Int64() + resBlock, err := api.clientCtx.Client.Block(&height) + if err != nil { + return nil + } + txCount := hexutil.Uint(len(resBlock.Block.Txs)) + return &txCount } - txCount := hexutil.Uint(len(resBlock.Block.Txs)) - txCountCleaned := strings.Replace(txCount.String(), "0x", "", -1) - totalTxCount, err := strconv.ParseUint(txCountCleaned, 16, 32) + // get the pending transaction count + pendingTxs, err := api.backend.PendingTransactions() if err != nil { return nil } - if pending { - pendingtx, err := api.backend.PendingTransactions() - if err != nil { - return nil - } - pendingTxCount := len(pendingtx) / 2 - totalTxCount += uint64(pendingTxCount) - } - - total := hexutil.Uint(totalTxCount) - return &total + txCount := hexutil.Uint(len(pendingTxs)) + return &txCount } // GetUncleCountByBlockHash returns the number of uncles in the block idenfied by hash. Always zero. @@ -535,18 +528,10 @@ func (api *PublicEthereumAPI) doCall( args rpctypes.CallArgs, blockNum rpctypes.BlockNumber, globalGasCap *big.Int, ) (*sdk.SimulationResponse, error) { - blockNumber, pending, err := api.getPendingBlock(blockNum) - - fmt.Println("blockNumber: ", blockNumber) - fmt.Println("pending:", pending) - - fmt.Println("args: ", args) - - // Set height for historical queries clientCtx := api.clientCtx - - if *blockNumber != 0 { - clientCtx = api.clientCtx.WithHeight(*blockNumber) + // pass the given block height to the context if the height is not pending or latest + if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) { + clientCtx = api.clientCtx.WithHeight(blockNum.Int64()) } // Set sender address or use a default if none specified @@ -600,95 +585,40 @@ func (api *PublicEthereumAPI) doCall( // Create new call message msg := evmtypes.NewMsgEthermint(0, &toAddr, sdk.NewIntFromBigInt(value), gas, sdk.NewIntFromBigInt(gasPrice), data, sdk.AccAddress(addr.Bytes())) - if err := msg.ValidateBasic(); err != nil { - return nil, err - } - ethermintMsgs = append(ethermintMsgs, msg) - fmt.Println("ethermintMsgs before pending: ", ethermintMsgs) - // convert the pending transactions into ethermint msgs - if pending { - fmt.Println("converting pending tx to emintmsg!") - pendingTxs, err := api.PendingTransactions() + if blockNum == rpctypes.PendingBlockNumber { + msgs, err := api.pendingMsgs() if err != nil { return nil, err } - fmt.Println("pendingTxs: ", pendingTxs) - if len(pendingTxs) > 0 { - for _, pendingTx := range pendingTxs { - if pendingTx == nil { - fmt.Println("nil pending tx found!") - continue - } - - pendingTo, err := sdk.AccAddressFromHex(strings.Replace(pendingTx.To.Hex(), "0x", "", -1)) - if err != nil { - fmt.Println("broke at pendingTo!") - return nil, err - } - - pendingFrom, err := sdk.AccAddressFromHex(strings.Replace(pendingTx.From.Hex(), "0x", "", -1)) - if err != nil { - fmt.Println("broke at pendingFrom!") - return nil, err - } - - pendingGasCleaned := strings.Replace(pendingTx.Gas.String(), "0x", "", -1) - pendingGas, err := strconv.ParseUint(pendingGasCleaned, 16, 64) - if err != nil { - fmt.Println("broke at pendingGas!") - return nil, err - } - - pendingVal := pendingTx.Value.ToInt() - pendingGasPrice := new(big.Int).SetUint64(ethermint.DefaultGasPrice) - if args.GasPrice != nil { - pendingGasPrice = pendingTx.GasPrice.ToInt() - } - - pendingData := pendingTx.Input - - msg := evmtypes.NewMsgEthermint(0, &pendingTo, sdk.NewIntFromBigInt(pendingVal), pendingGas, - sdk.NewIntFromBigInt(pendingGasPrice), pendingData, pendingFrom) - if err := msg.ValidateBasic(); err != nil { - fmt.Println("broke at converting to msgEthermint!") - return nil, err - } - - ethermintMsgs = append(ethermintMsgs, msg) - } - } + ethermintMsgs = append(ethermintMsgs, msgs...) } - fmt.Println("ethermintMsgs after pending: ", ethermintMsgs) - // Generate tx to be used to simulate (signature isn't needed) var stdSig authtypes.StdSignature stdSigs := []authtypes.StdSignature{stdSig} - fmt.Println("stdSigs: ", stdSigs) - tx := authtypes.NewStdTx(ethermintMsgs, authtypes.StdFee{}, stdSigs, "") - fmt.Println() + tx := authtypes.NewStdTx(ethermintMsgs, authtypes.StdFee{}, stdSigs, "") + if err := tx.ValidateBasic(); err != nil { + return nil, err + } txEncoder := authclient.GetTxEncoder(clientCtx.Codec) txBytes, err := txEncoder(tx) if err != nil { - fmt.Println("failed to encode") return nil, err } // Transaction simulation through query res, _, err := clientCtx.QueryWithData("app/simulate", txBytes) if err != nil { - fmt.Println("failed to query") return nil, err } var simResponse sdk.SimulationResponse if err := clientCtx.Codec.UnmarshalBinaryBare(res, &simResponse); err != nil { - fmt.Println("failed to simulate") return nil, err } @@ -722,65 +652,63 @@ func (api *PublicEthereumAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map // GetBlockByNumber returns the block identified by number. func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { api.logger.Debug("eth_getBlockByNumber", "number", blockNum, "full", fullTx) - blockNumber, pending, err := api.getPendingBlock(blockNum) + + if blockNum != rpctypes.PendingBlockNumber { + return api.backend.GetBlockByNumber(blockNum, fullTx) + } + + height, err := api.backend.LatestBlockNumber() if err != nil { return nil, err } - if pending { - // latest block info - latestBlock, err := api.clientCtx.Client.Block(blockNumber) - if err != nil { - return nil, err - } - header := latestBlock.Block.Header - unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(100) - if err != nil { - return nil, err - } + // latest block info + latestBlock, err := api.clientCtx.Client.Block(&height) + if err != nil { + return nil, err + } - var pendingTxs []common.Hash - var gasUsed *big.Int - if fullTx { - pendingTxs, gasUsed, err = convertTransactionsToRPC( - api.clientCtx, unconfirmedTxs.Txs, common.BytesToHash(header.Hash()), uint64(header.Height)+1, - ) - if err != nil { - return nil, err - } - } else { - pendingTxs = make([]common.Hash, len(unconfirmedTxs.Txs)) - for i, tx := range unconfirmedTxs.Txs { - pendingTxs[i] = common.BytesToHash(tx.Hash()) - } + unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(100) + if err != nil { + return nil, err + } + + var ( + pendingTxs []common.Hash + gasUsed *big.Int + ) + + if fullTx { + pendingTxs, gasUsed, err = convertTransactionsToRPC( + api.clientCtx, unconfirmedTxs.Txs, common.Hash{}, uint64(height+1), + ) + } else { + pendingTxs = make([]common.Hash, len(unconfirmedTxs.Txs)) + for i, tx := range unconfirmedTxs.Txs { + pendingTxs[i] = common.BytesToHash(tx.Hash()) } + } + + if err != nil { + return nil, err + } + + return rpctypes.FormatBlock( + tmtypes.Header{ + Version: latestBlock.Block.Version, + ChainID: api.clientCtx.ChainID, + Height: height + 1, + Time: time.Unix(0, 0), + LastBlockID: latestBlock.BlockID, + ValidatorsHash: latestBlock.Block.NextValidatorsHash, + }, + 0, + 0, + gasUsed, + pendingTxs, + ethtypes.Bloom{}, + ), nil - return rpctypes.FormatBlock( - tmtypes.Header{ - Version: header.Version, - ChainID: header.ChainID, - Height: *blockNumber + 1, - Time: time.Time{}, - LastBlockID: latestBlock.BlockID, - LastCommitHash: nil, - DataHash: nil, - ValidatorsHash: nil, - NextValidatorsHash: nil, - ConsensusHash: header.ConsensusHash, - AppHash: nil, - LastResultsHash: nil, - EvidenceHash: nil, - ProposerAddress: nil, - }, - 0, - 0, - gasUsed, - pendingTxs, - ethtypes.Bloom{}, - ), nil - } - - return api.backend.GetBlockByNumber(rpctypes.BlockNumber(*blockNumber), fullTx) } func convertTransactionsToRPC(cliCtx clientcontext.CLIContext, txs []tmtypes.Tx, blockHash common.Hash, height uint64) ([]common.Hash, *big.Int, error) { @@ -808,24 +736,23 @@ func convertTransactionsToRPC(cliCtx clientcontext.CLIContext, txs []tmtypes.Tx, // GetTransactionByHash returns the transaction identified by hash. func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.Transaction, error) { api.logger.Debug("eth_getTransactionByHash", "hash", hash) - pendingTxs, err := api.PendingTransactions() + + tx, err := api.clientCtx.Client.Tx(hash.Bytes(), false) if err != nil { - return nil, err - } + // check if the tx is on the mempool + pendingTxs, err := api.PendingTransactions() + if err != nil { + return nil, err + } - if len(pendingTxs) != 0 { - for _, pendingTx := range pendingTxs { - if pendingTx == nil { - continue - } - if hash == pendingTx.Hash { - return pendingTx, nil + if len(pendingTxs) != 0 { + for _, tx := range pendingTxs { + if tx != nil && hash == tx.Hash { + return tx, nil + } } } - } - tx, err := api.clientCtx.Client.Tx(hash.Bytes(), false) - if err != nil { // Return nil for transaction when not found return nil, nil } @@ -869,35 +796,28 @@ func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) { api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - blockNumber, pending, err := api.getPendingBlock(blockNum) - if err != nil { - return nil, err + if blockNum != rpctypes.PendingBlockNumber { + height := blockNum.Int64() + resBlock, err := api.clientCtx.Client.Block(&height) + if err != nil { + return nil, err + } + + return api.getTransactionByBlockAndIndex(resBlock.Block, idx) } - resBlock, err := api.clientCtx.Client.Block(blockNumber) + // get all the EVM pending txs + pendingTxs, err := api.backend.PendingTransactions() if err != nil { return nil, err } - if pending { - pendingtx, err := api.backend.PendingTransactions() - if err != nil { - return nil, err - } - index := hexutil.Uint64(0) - for i := range pendingtx { - if pendingtx[i] == nil { - continue - } - if index.String() == idx.String() { - return pendingtx[i], nil - } - index++ - } + // return if index out of bounds + if uint64(idx) >= uint64(len(pendingTxs)) { return nil, nil } - return api.getTransactionByBlockAndIndex(resBlock.Block, idx) + return pendingTxs[idx], nil } func (api *PublicEthereumAPI) getTransactionByBlockAndIndex(block *tmtypes.Block, idx hexutil.Uint) (*rpctypes.Transaction, error) { @@ -984,7 +904,7 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin "blockNumber": hexutil.Uint64(tx.Height), "transactionIndex": hexutil.Uint64(tx.Index), - // sender and receiver (contract or EOA) addreses + // sender and receiver (contract or EOA) addresses "from": from, "to": ethTx.To(), } @@ -1173,37 +1093,39 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty return &msg, nil } -// getPendingBlock returns the blocknumber and pending -// if -1, returns latest blocknumber and pending is set to true -// if 0, returns latest blocknumber and pending is set to false -// if not 0 or -1, returns blocknumber and pendisng is set to false -func (api *PublicEthereumAPI) getPendingBlock(blockNum rpctypes.BlockNumber) (*int64, bool, error) { - var blockNumber int64 - pending := false - switch blockNum { - case rpctypes.LatestBlockNumber: - bn, err := api.backend.BlockNumber() - if err != nil { - return nil, pending, err - } - bnCleaned := strings.Replace(bn.String(), "0x", "", -1) - blockNumber, err = strconv.ParseInt(bnCleaned, 16, 64) - if err != nil { - return nil, pending, err +func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) { + pendingTxs, err := api.PendingTransactions() + if err != nil { + return nil, err + } + + // nolint: prealloc + var msgs []sdk.Msg + + for _, pendingTx := range pendingTxs { + if pendingTx == nil { + continue } - case rpctypes.PendingBlockNumber: - bn, err := api.backend.BlockNumber() + + pendingTo := sdk.AccAddress(pendingTx.To.Bytes()) + pendingFrom := sdk.AccAddress(pendingTx.From.Bytes()) + pendingGas, err := hexutil.DecodeUint64(pendingTx.Gas.String()) if err != nil { - return nil, pending, err + return nil, err } - bnCleaned := strings.Replace(bn.String(), "0x", "", -1) - blockNumber, err = strconv.ParseInt(bnCleaned, 16, 64) - if err != nil { - return nil, pending, err + + pendingValue := pendingTx.Value.ToInt() + pendingGasPrice := new(big.Int).SetUint64(ethermint.DefaultGasPrice) + if pendingTx.GasPrice != nil { + pendingGasPrice = pendingTx.GasPrice.ToInt() } - pending = true - default: - blockNumber = blockNum.Int64() + + pendingData := pendingTx.Input + + msg := evmtypes.NewMsgEthermint(0, &pendingTo, sdk.NewIntFromBigInt(pendingValue), pendingGas, + sdk.NewIntFromBigInt(pendingGasPrice), pendingData, pendingFrom) + + msgs = append(msgs, msg) } - return &blockNumber, pending, nil + return msgs, nil } From 0972017cc0e3aa0ad05e3d3a4c3cf817aa7bdd12 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 17 Nov 2020 12:19:55 +0100 Subject: [PATCH 26/61] update call and send --- rpc/backend/backend.go | 2 +- rpc/namespaces/eth/api.go | 127 +++++++++++++++----------------------- rpc/types/utils.go | 2 + 3 files changed, 52 insertions(+), 79 deletions(-) diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 6d0508ce9..90ca6d118 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -258,7 +258,7 @@ func (b *EthermintBackend) BloomStatus() (uint64, uint64) { return 4096, 0 } -// latestBlockNumber gets the latest block height in int64 format. +// LatestBlockNumber gets the latest block height in int64 format. func (b *EthermintBackend) LatestBlockNumber() (int64, error) { // NOTE: using 0 as min and max height returns the blockchain info up to the latest block. info, err := b.clientCtx.Client.BlockchainInfo(0, 0) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 5e37bdd75..45806d22b 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -37,7 +37,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/x/auth" authclient "github.com/cosmos/cosmos-sdk/x/auth/client/utils" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -453,6 +452,11 @@ func (api *PublicEthereumAPI) SendTransaction(args rpctypes.SendTxArgs) (common. return common.Hash{}, err } + if tx.ValidateBasic(); err != nil { + api.logger.Debug("tx failed basic validation", "error", err) + return common.Hash{}, err + } + // Sign transaction if err := tx.Sign(api.chainIDEpoch, key.ToECDSA()); err != nil { api.logger.Debug("failed to sign tx", "error", err) @@ -581,26 +585,26 @@ func (api *PublicEthereumAPI) doCall( toAddr = sdk.AccAddress(args.To.Bytes()) } - var ethermintMsgs []sdk.Msg + var msgs []sdk.Msg // Create new call message msg := evmtypes.NewMsgEthermint(0, &toAddr, sdk.NewIntFromBigInt(value), gas, sdk.NewIntFromBigInt(gasPrice), data, sdk.AccAddress(addr.Bytes())) - ethermintMsgs = append(ethermintMsgs, msg) + msgs = append(msgs, msg) // convert the pending transactions into ethermint msgs if blockNum == rpctypes.PendingBlockNumber { - msgs, err := api.pendingMsgs() + pendingMsgs, err := api.pendingMsgs() if err != nil { return nil, err } - ethermintMsgs = append(ethermintMsgs, msgs...) + msgs = append(msgs, pendingMsgs...) } // Generate tx to be used to simulate (signature isn't needed) var stdSig authtypes.StdSignature stdSigs := []authtypes.StdSignature{stdSig} - tx := authtypes.NewStdTx(ethermintMsgs, authtypes.StdFee{}, stdSigs, "") + tx := authtypes.NewStdTx(msgs, authtypes.StdFee{}, stdSigs, "") if err := tx.ValidateBasic(); err != nil { return nil, err } @@ -622,7 +626,6 @@ func (api *PublicEthereumAPI) doCall( return nil, err } - fmt.Println(simResponse) return &simResponse, nil } @@ -673,22 +676,7 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu return nil, err } - var ( - pendingTxs []common.Hash - gasUsed *big.Int - ) - - if fullTx { - pendingTxs, gasUsed, err = convertTransactionsToRPC( - api.clientCtx, unconfirmedTxs.Txs, common.Hash{}, uint64(height+1), - ) - } else { - pendingTxs = make([]common.Hash, len(unconfirmedTxs.Txs)) - for i, tx := range unconfirmedTxs.Txs { - pendingTxs[i] = common.BytesToHash(tx.Hash()) - } - } - + pendingTxs, gasUsed, err := rpctypes.EthTransactionsFromTendermint(api.clientCtx, unconfirmedTxs.Txs) if err != nil { return nil, err } @@ -711,28 +699,6 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu } -func convertTransactionsToRPC(cliCtx clientcontext.CLIContext, txs []tmtypes.Tx, blockHash common.Hash, height uint64) ([]common.Hash, *big.Int, error) { - transactions := make([]common.Hash, len(txs)) - gasUsed := big.NewInt(0) - - for i, tx := range txs { - ethTx, err := rpctypes.RawTxToEthTx(cliCtx, tx) - if err != nil { - // continue to next transaction in case it's not a MsgEthereumTx - continue - } - // TODO: Remove gas usage calculation if saving gasUsed per block - gasUsed.Add(gasUsed, ethTx.Fee()) - tx, err := rpctypes.NewTransaction(ethTx, common.BytesToHash(tx.Hash()), blockHash, height, uint64(i)) - if err != nil { - return nil, nil, err - } - transactions[i] = tx.Hash - } - - return transactions, gasUsed, nil -} - // GetTransactionByHash returns the transaction identified by hash. func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.Transaction, error) { api.logger.Debug("eth_getTransactionByHash", "hash", hash) @@ -1005,9 +971,8 @@ func (api *PublicEthereumAPI) GetProof(address common.Address, storageKeys []str // generateFromArgs populates tx message with args (used in RPC API) func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmtypes.MsgEthereumTx, error) { var ( - nonce uint64 - gasLimit uint64 - err error + nonce, gasLimit uint64 + err error ) amount := (*big.Int)(args.Value) @@ -1019,43 +984,19 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty gasPrice = big.NewInt(ethermint.DefaultGasPrice) } - // Get nonce (sequence) from account - from := sdk.AccAddress(args.From.Bytes()) - accRet := authtypes.NewAccountRetriever(api.clientCtx) - if api.clientCtx.Keybase == nil { - return nil, fmt.Errorf("clientCtx.Keybase is nil") + if args.Nonce == nil { + // get the nonce from the account retriever and the pending transactions + nonce, err = api.pendingAccountNonce(args.From) + } else { + nonce = (uint64)(*args.Nonce) } - _, nonce, err = accRet.GetAccountNumberSequence(from) if err != nil { return nil, err } - if args.Nonce == nil { - pendingTxs, err := api.backend.PendingTransactions() - if err != nil { - return nil, err - } - if len(pendingTxs) != 0 { - for i := range pendingTxs { - if pendingTxs[i] == nil { - continue - } - if pendingTxs[i].From == args.From { - nonce++ - } - } - } - } else { - if (uint64)(*args.Nonce) <= nonce { - return nil, sdkerrors.ErrInvalidSequence - } - - nonce = (uint64)(*args.Nonce) - } - if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) { - return nil, errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`) + return nil, errors.New("both 'data' and 'input' are set and not equal. Please use 'input' to pass transaction call data") } // Sets input to either Input or Data, if both are set and not equal error above returns @@ -1129,3 +1070,33 @@ func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) { } return msgs, nil } + +func (api *PublicEthereumAPI) pendingAccountNonce(from common.Address) (uint64, error) { + // Get nonce (sequence) from sender account + sender := sdk.AccAddress(from.Bytes()) + accRet := authtypes.NewAccountRetriever(api.clientCtx) + + _, nonce, err := accRet.GetAccountNumberSequence(sender) + if err != nil { + return 0, err + } + + pendingTxs, err := api.backend.PendingTransactions() + if err != nil { + return 0, err + } + + // add the uncommitted txs to the nonce counter + if len(pendingTxs) != 0 { + for i := range pendingTxs { + if pendingTxs[i] == nil { + continue + } + if pendingTxs[i].From == from { + nonce++ + } + } + } + + return nonce, nil +} diff --git a/rpc/types/utils.go b/rpc/types/utils.go index 6eab952b3..d435b65f9 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -148,6 +148,8 @@ func BlockMaxGasFromConsensusParams(_ context.Context, clientCtx clientcontext.C return gasLimit, nil } +// FormatBlock creates an ethereum block from a tendermint header and ethereum-formatted +// transactions. func FormatBlock( header tmtypes.Header, size int, gasLimit int64, gasUsed *big.Int, transactions interface{}, bloom ethtypes.Bloom, From 4947fa7460e34c68756c4a2f377dd8fefa4d0eac Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 17 Nov 2020 13:33:16 +0100 Subject: [PATCH 27/61] comments and minor changes --- rpc/namespaces/eth/api.go | 78 ++++++++++++++++++--------------------- rpc/types/utils.go | 2 +- 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 45806d22b..4e7720b8f 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -286,48 +286,18 @@ func (api *PublicEthereumAPI) GetTransactionCount(address common.Address, blockN api.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum) clientCtx := api.clientCtx + pending := blockNum == rpctypes.PendingBlockNumber // pass the given block height to the context if the height is not pending or latest - if !(blockNum == rpctypes.PendingBlockNumber || blockNum == rpctypes.LatestBlockNumber) { + if !pending && blockNum != rpctypes.LatestBlockNumber { clientCtx = api.clientCtx.WithHeight(blockNum.Int64()) } - // Get nonce (sequence) from account - from := sdk.AccAddress(address.Bytes()) - accRet := authtypes.NewAccountRetriever(clientCtx) - - err := accRet.EnsureExists(from) - if err != nil { - // account doesn't exist yet, return 0 - n := hexutil.Uint64(0) - return &n, nil - } - - _, nonce, err := accRet.GetAccountNumberSequence(from) + nonce, err := api.accountNonce(clientCtx, address, pending) if err != nil { return nil, err } - // the account retriever doesn't include the uncommitted transactions on the nonce so we need to - // manually add them - if blockNum == rpctypes.PendingBlockNumber { - pendingTxs, err := api.backend.PendingTransactions() - if err != nil { - return nil, err - } - - for _, tx := range pendingTxs { - if tx == nil { - continue - } - - // update the nonce if the sender matches the given address - if tx.From == address { - nonce++ - } - } - } - n := hexutil.Uint64(nonce) return &n, nil } @@ -452,7 +422,7 @@ func (api *PublicEthereumAPI) SendTransaction(args rpctypes.SendTxArgs) (common. return common.Hash{}, err } - if tx.ValidateBasic(); err != nil { + if err := tx.ValidateBasic(); err != nil { api.logger.Debug("tx failed basic validation", "error", err) return common.Hash{}, err } @@ -986,7 +956,7 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty if args.Nonce == nil { // get the nonce from the account retriever and the pending transactions - nonce, err = api.pendingAccountNonce(args.From) + nonce, err = api.accountNonce(api.clientCtx, args.From, true) } else { nonce = (uint64)(*args.Nonce) } @@ -1034,20 +1004,24 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty return &msg, nil } +// pendingMsgs constructs func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) { + // nolint: prealloc + var msgs []sdk.Msg + pendingTxs, err := api.PendingTransactions() if err != nil { return nil, err } - // nolint: prealloc - var msgs []sdk.Msg - for _, pendingTx := range pendingTxs { if pendingTx == nil { continue } + // NOTE: we have to construct the EVM transaction instead of just casting from the tendermint + // transactions because PendingTransactions only checks for MsgEthereumTx messages. + pendingTo := sdk.AccAddress(pendingTx.To.Bytes()) pendingFrom := sdk.AccAddress(pendingTx.From.Bytes()) pendingGas, err := hexutil.DecodeUint64(pendingTx.Gas.String()) @@ -1071,16 +1045,34 @@ func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) { return msgs, nil } -func (api *PublicEthereumAPI) pendingAccountNonce(from common.Address) (uint64, error) { +// accountNonce returns looks up the transaction nonce count for a given address. If the pending boolean +// is set to true, it will add to the counter all the uncommitted EVM transactions sent from the address. +// NOTE: The function returns no error if the account doesn't exist. +func (api *PublicEthereumAPI) accountNonce( + clientCtx clientcontext.CLIContext, address common.Address, pending bool, +) (uint64, error) { // Get nonce (sequence) from sender account - sender := sdk.AccAddress(from.Bytes()) - accRet := authtypes.NewAccountRetriever(api.clientCtx) + from := sdk.AccAddress(address.Bytes()) + + // use a the given client context in case its wrapped with a custom height + accRet := authtypes.NewAccountRetriever(clientCtx) + + if err := accRet.EnsureExists(from); err != nil { + // account doesn't exist yet, return 0 + return 0, nil + } - _, nonce, err := accRet.GetAccountNumberSequence(sender) + _, nonce, err := accRet.GetAccountNumberSequence(from) if err != nil { return 0, err } + if !pending { + return nonce, nil + } + + // the account retriever doesn't include the uncommitted transactions on the nonce so we need to + // to manually add them. pendingTxs, err := api.backend.PendingTransactions() if err != nil { return 0, err @@ -1092,7 +1084,7 @@ func (api *PublicEthereumAPI) pendingAccountNonce(from common.Address) (uint64, if pendingTxs[i] == nil { continue } - if pendingTxs[i].From == from { + if pendingTxs[i].From == address { nonce++ } } diff --git a/rpc/types/utils.go b/rpc/types/utils.go index d435b65f9..44e5f124d 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -29,7 +29,7 @@ func RawTxToEthTx(clientCtx clientcontext.CLIContext, bz []byte) (*evmtypes.MsgE ethTx, ok := tx.(evmtypes.MsgEthereumTx) if !ok { - return nil, fmt.Errorf("invalid transaction type %T, expected %T", tx, &evmtypes.MsgEthereumTx{}) + return nil, fmt.Errorf("invalid transaction type %T, expected %T", tx, evmtypes.MsgEthereumTx{}) } return ðTx, nil } From 27ed027cdc368fc9d8d4078432b7fd57e673dcfb Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 17 Nov 2020 12:41:08 -0800 Subject: [PATCH 28/61] add pending tests into sep package --- rpc/namespaces/eth/api.go | 3 + tests-pending/rpc_pending_test.go | 279 ++++++++++++++++++++++++ tests-solidity/suites/basic/main.go | 2 +- tests/personal_test.go | 30 +-- tests/rpc_pending_test.go | 323 ---------------------------- tests/rpc_test.go | 317 +++++---------------------- tests/utils.go | 272 +++++++++++++++++++++++ 7 files changed, 627 insertions(+), 599 deletions(-) create mode 100644 tests-pending/rpc_pending_test.go delete mode 100644 tests/rpc_pending_test.go create mode 100644 tests/utils.go diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 2cf728e6b..ede6c6540 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -536,6 +536,9 @@ func (api *PublicEthereumAPI) doCall( ) (*sdk.SimulationResponse, error) { blockNumber, pending, err := api.getPendingBlock(blockNum) + if err != nil { + return nil, err + } fmt.Println("blockNumber: ", blockNumber) fmt.Println("pending:", pending) diff --git a/tests-pending/rpc_pending_test.go b/tests-pending/rpc_pending_test.go new file mode 100644 index 000000000..469fde49e --- /dev/null +++ b/tests-pending/rpc_pending_test.go @@ -0,0 +1,279 @@ +// This is a test utility for Ethermint's Web3 JSON-RPC services. +// +// To run these tests please first ensure you have the ethermintd running +// and have started the RPC service with `ethermintcli rest-server`. +// +// You can configure the desired HOST and MODE as well +package pending + +import ( + "encoding/json" + "fmt" + "math/big" + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + + util "github.com/cosmos/ethermint/tests" +) + +const ( + addrA = "0xc94770007dda54cF92009BFF0dE90c06F603a09f" + addrAStoreKey = 0 +) + +var ( + MODE = os.Getenv("MODE") + + zeroString = "0x0" + from = []byte{} +) + +type Request struct { + Version string `json:"jsonrpc"` + Method string `json:"method"` + Params interface{} `json:"params"` + ID int `json:"id"` +} + +type RPCError struct { + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data,omitempty"` +} + +type Response struct { + Error *RPCError `json:"error"` + ID int `json:"id"` + Result json.RawMessage `json:"result,omitempty"` +} + +func TestMain(m *testing.M) { + if MODE != "pending" { + _, _ = fmt.Fprintln(os.Stdout, "Skipping pending RPC test") + return + } + + var err error + from, err = util.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) { + var res hexutil.Big + rpcRes := util.Call(t, "eth_getBalance", []string{addrA, "latest"}) + err := res.UnmarshalJSON(rpcRes.Result) + require.NoError(t, err) + preTxBalance := res.ToInt() + t.Logf("Got balance %s for %s before sending tx\n", preTxBalance, 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" + + _ = util.Call(t, "eth_sendTransaction", param) + + rpcRes = util.Call(t, "eth_getBalance", []string{addrA, "pending"}) + err = res.UnmarshalJSON(rpcRes.Result) + require.NoError(t, err) + t.Logf("Got pending balance %s for %s post tx\n", res.String(), addrA) + + if res.ToInt().Cmp(preTxBalance.Add(preTxBalance, big.NewInt(10))) != 0 { + t.Errorf("expected balance: %d, got: %s", 10, res.String()) + } + + rpcRes = util.Call(t, "eth_getBalance", []string{addrA, "latest"}) + err = res.UnmarshalJSON(rpcRes.Result) + require.NoError(t, err) + t.Logf("Got latest balance %s for %s post tx\n", res.String(), addrA) + + if res.ToInt().Cmp(preTxBalance) != 0 { + t.Errorf("expected balance: %d, got: %s", 0, res.String()) + } +} + +func TestEth_Pending_GetTransactionCount(t *testing.T) { + currentNonce := util.GetNonce(t, "latest") + t.Logf("Current nonce is %d", currentNonce) + + 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" + + _ = util.Call(t, "eth_sendTransaction", param) + + pendingNonce := util.GetNonce(t, "pending") + latestNonce := util.GetNonce(t, "latest") + t.Logf("Latest nonce is %d", latestNonce) + require.Equal(t, currentNonce, latestNonce) + t.Logf("Pending nonce is %d", pendingNonce) + require.NotEqual(t, latestNonce, pendingNonce) + + require.Greater(t, uint64(pendingNonce), uint64(latestNonce)) +} + +func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { + 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" + + _ = util.Call(t, "eth_sendTransaction", param) + + rpcRes := util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) + var pendingTxCount hexutil.Uint + err := json.Unmarshal(rpcRes.Result, &pendingTxCount) + require.NoError(t, err) + t.Logf("Pending nonce is %d", pendingTxCount) + + rpcRes = util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"latest"}) + var latestTxCount hexutil.Uint + err = json.Unmarshal(rpcRes.Result, &latestTxCount) + require.NoError(t, err) + t.Logf("Latest nonce is %d", latestTxCount) + + require.NotEqual(t, uint64(pendingTxCount), uint64(latestTxCount)) + require.Greater(t, uint64(pendingTxCount), uint64(latestTxCount)) +} + +func TestEth_Pending_GetBlockByNumber(t *testing.T) { + 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" + + _ = util.Call(t, "eth_sendTransaction", param) + + rpcRes := util.Call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) + var pendingBlock map[string]interface{} + err := json.Unmarshal(rpcRes.Result, &pendingBlock) + require.NoError(t, err) + pendingBlockArr := len(pendingBlock["transactions"].([]interface{})) + // in case there are other tx's inside the pending queue from prev test + require.NotEqual(t, pendingBlockArr, 0) + + rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"latest", true}) + var latestBlock map[string]interface{} + err = json.Unmarshal(rpcRes.Result, &latestBlock) + require.NoError(t, err) + latestBlockArr := len(latestBlock["transactions"].([]interface{})) + require.Equal(t, latestBlockArr, 0) + + require.Greater(t, pendingBlockArr, latestBlockArr) +} + +func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { + 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" + + _ = util.Call(t, "eth_sendTransaction", param) + + rpcRes := util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x1"}) + var pendingBlock map[string]interface{} + err := json.Unmarshal(rpcRes.Result, &pendingBlock) + require.NoError(t, err) + + require.Equal(t, pendingBlock["blockHash"], nil) + require.Equal(t, pendingBlock["blockNumber"], nil) + require.Equal(t, pendingBlock["transactionIndex"], nil) + require.NotEmpty(t, pendingBlock["hash"]) + + rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"latest", true}) + var latestBlock map[string]interface{} + err = json.Unmarshal(rpcRes.Result, &latestBlock) + fmt.Println("latestBlock: ", latestBlock) + require.NoError(t, err) + + require.NotEmpty(t, latestBlock["timestamp"]) + require.NotEmpty(t, latestBlock["gasUsed"]) + require.Equal(t, latestBlock["logsBloom"], "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") +} + +func TestEth_Pending_GetTransactionByHash(t *testing.T) { + 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 := util.Call(t, "eth_sendTransaction", param) + var txHash common.Hash + err := txHash.UnmarshalJSON(txRes.Result) + require.NoError(t, err) + + rpcRes := util.Call(t, "eth_getTransactionByHash", []interface{}{txHash}) + var pendingBlock map[string]interface{} + err = json.Unmarshal(rpcRes.Result, &pendingBlock) + require.NoError(t, err) + + require.NotEmpty(t, pendingBlock) + require.Equal(t, pendingBlock["blockHash"], nil) + require.Equal(t, pendingBlock["blockNumber"], nil) + require.Equal(t, pendingBlock["transactionIndex"], nil) + require.NotEmpty(t, pendingBlock["hash"]) + require.NotEmpty(t, pendingBlock["value"], "0xa") +} + +func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { + currNonce := util.GetNonce(t, "latest") + 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" + + t.Logf("currNonce: %d", currNonce) + + // first transaction + _ = util.Call(t, "eth_sendTransaction", param) + pendingNonce1 := util.GetNonce(t, "pending") + require.Greater(t, pendingNonce1, currNonce) + + // second transaction + param[0]["to"] = "0x7f0f463c4d57b1bd3e3b79051e6c5ab703e803d9" + _ = util.Call(t, "eth_sendTransaction", param) + pendingNonce2 := util.GetNonce(t, "pending") + require.Greater(t, pendingNonce2, currNonce) + require.Equal(t, pendingNonce1+hexutil.Uint64(1), pendingNonce2) + + // third transaction + param[0]["to"] = "0x7fb24493808b3f10527e3e0870afeb8a953052d2" + _ = util.Call(t, "eth_sendTransaction", param) + pendingNonce3 := util.GetNonce(t, "pending") + require.Greater(t, pendingNonce3, currNonce) + require.Equal(t, pendingNonce1+hexutil.Uint64(2), pendingNonce3) +} diff --git a/tests-solidity/suites/basic/main.go b/tests-solidity/suites/basic/main.go index 93d327682..7975b6ffc 100644 --- a/tests-solidity/suites/basic/main.go +++ b/tests-solidity/suites/basic/main.go @@ -82,7 +82,7 @@ func call(method string, params interface{}) (*Response, error) { HOST = "http://localhost:8545" } - req, err := json.Marshal(createRequest(method, params)) + req, err := json.Marshal(CreateRequest(method, params)) if err != nil { return nil, err } diff --git a/tests/personal_test.go b/tests/personal_test.go index 8f4cf9237..4e90aee5c 100644 --- a/tests/personal_test.go +++ b/tests/personal_test.go @@ -12,7 +12,7 @@ import ( ) func TestPersonal_ListAccounts(t *testing.T) { - rpcRes := call(t, "personal_listAccounts", []string{}) + rpcRes := Call(t, "personal_listAccounts", []string{}) var res []hexutil.Bytes err := json.Unmarshal(rpcRes.Result, &res) @@ -21,12 +21,12 @@ func TestPersonal_ListAccounts(t *testing.T) { } func TestPersonal_NewAccount(t *testing.T) { - rpcRes := call(t, "personal_newAccount", []string{"password"}) + rpcRes := Call(t, "personal_newAccount", []string{"password"}) var addr common.Address err := json.Unmarshal(rpcRes.Result, &addr) require.NoError(t, err) - rpcRes = call(t, "personal_listAccounts", []string{}) + rpcRes = Call(t, "personal_listAccounts", []string{}) var res []hexutil.Bytes err = json.Unmarshal(rpcRes.Result, &res) require.NoError(t, err) @@ -34,7 +34,7 @@ func TestPersonal_NewAccount(t *testing.T) { } func TestPersonal_Sign(t *testing.T) { - rpcRes := call(t, "personal_sign", []interface{}{hexutil.Bytes{0x88}, hexutil.Bytes(from), ""}) + rpcRes := Call(t, "personal_sign", []interface{}{hexutil.Bytes{0x88}, hexutil.Bytes(from), ""}) var res hexutil.Bytes err := json.Unmarshal(rpcRes.Result, &res) @@ -49,7 +49,7 @@ func TestPersonal_ImportRawKey(t *testing.T) { // parse priv key to hex hexPriv := common.Bytes2Hex(ethcrypto.FromECDSA(privkey)) - rpcRes := call(t, "personal_importRawKey", []string{hexPriv, "password"}) + rpcRes := Call(t, "personal_importRawKey", []string{hexPriv, "password"}) var res hexutil.Bytes err = json.Unmarshal(rpcRes.Result, &res) @@ -63,14 +63,14 @@ func TestPersonal_ImportRawKey(t *testing.T) { func TestPersonal_EcRecover(t *testing.T) { data := hexutil.Bytes{0x88} - rpcRes := call(t, "personal_sign", []interface{}{data, hexutil.Bytes(from), ""}) + rpcRes := Call(t, "personal_sign", []interface{}{data, hexutil.Bytes(from), ""}) var res hexutil.Bytes err := json.Unmarshal(rpcRes.Result, &res) require.NoError(t, err) require.Equal(t, 65, len(res)) - rpcRes = call(t, "personal_ecRecover", []interface{}{data, res}) + rpcRes = Call(t, "personal_ecRecover", []interface{}{data, res}) var ecrecoverRes common.Address err = json.Unmarshal(rpcRes.Result, &ecrecoverRes) require.NoError(t, err) @@ -79,23 +79,23 @@ func TestPersonal_EcRecover(t *testing.T) { func TestPersonal_UnlockAccount(t *testing.T) { pswd := "nootwashere" - rpcRes := call(t, "personal_newAccount", []string{pswd}) + rpcRes := Call(t, "personal_newAccount", []string{pswd}) var addr common.Address err := json.Unmarshal(rpcRes.Result, &addr) require.NoError(t, err) // try to sign, should be locked - _, err = callWithError("personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, ""}) + _, err = CallWithError("personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, ""}) require.Error(t, err) - rpcRes = call(t, "personal_unlockAccount", []interface{}{addr, ""}) + rpcRes = Call(t, "personal_unlockAccount", []interface{}{addr, ""}) var unlocked bool err = json.Unmarshal(rpcRes.Result, &unlocked) require.NoError(t, err) require.True(t, unlocked) // try to sign, should work now - rpcRes = call(t, "personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, pswd}) + rpcRes = Call(t, "personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, pswd}) var res hexutil.Bytes err = json.Unmarshal(rpcRes.Result, &res) require.NoError(t, err) @@ -104,24 +104,24 @@ func TestPersonal_UnlockAccount(t *testing.T) { func TestPersonal_LockAccount(t *testing.T) { pswd := "nootwashere" - rpcRes := call(t, "personal_newAccount", []string{pswd}) + rpcRes := Call(t, "personal_newAccount", []string{pswd}) var addr common.Address err := json.Unmarshal(rpcRes.Result, &addr) require.NoError(t, err) - rpcRes = call(t, "personal_unlockAccount", []interface{}{addr, ""}) + rpcRes = Call(t, "personal_unlockAccount", []interface{}{addr, ""}) var unlocked bool err = json.Unmarshal(rpcRes.Result, &unlocked) require.NoError(t, err) require.True(t, unlocked) - rpcRes = call(t, "personal_lockAccount", []interface{}{addr}) + rpcRes = Call(t, "personal_lockAccount", []interface{}{addr}) var locked bool err = json.Unmarshal(rpcRes.Result, &locked) require.NoError(t, err) require.True(t, locked) // try to sign, should be locked - _, err = callWithError("personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, ""}) + _, err = CallWithError("personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, ""}) require.Error(t, err) } diff --git a/tests/rpc_pending_test.go b/tests/rpc_pending_test.go deleted file mode 100644 index 6952e2133..000000000 --- a/tests/rpc_pending_test.go +++ /dev/null @@ -1,323 +0,0 @@ -// This is a test utility for Ethermint's Web3 JSON-RPC services. -// -// To run these tests please first ensure you have the ethermintd running -// and have started the RPC service with `ethermintcli rest-server`. -// -// You can configure the desired HOST and MODE as well -package tests - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - "net/http" - "os" - "testing" - "time" - - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/common/hexutil" -) - -const ( - addrA = "0xc94770007dda54cF92009BFF0dE90c06F603a09f" - addrAStoreKey = 0 -) - -var ( - MODE = os.Getenv("MODE") - HOST = os.Getenv("HOST") - - zeroString = "0x0" - from = []byte{} -) - -type Request struct { - Version string `json:"jsonrpc"` - Method string `json:"method"` - Params interface{} `json:"params"` - ID int `json:"id"` -} - -type RPCError struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` -} - -type Response struct { - Error *RPCError `json:"error"` - ID int `json:"id"` - Result json.RawMessage `json:"result,omitempty"` -} - -func TestMain(m *testing.M) { - if MODE != "pending" { - _, _ = fmt.Fprintln(os.Stdout, "Skipping pending RPC test") - return - } - - if HOST == "" { - HOST = "http://localhost:8545" - } - - 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 getAddress() ([]byte, error) { - rpcRes, err := callWithError("eth_accounts", []string{}) - if err != nil { - return nil, err - } - - var res []hexutil.Bytes - err = json.Unmarshal(rpcRes.Result, &res) - if err != nil { - return nil, err - } - - return res[0], nil -} - -func createRequest(method string, params interface{}) Request { - return Request{ - Version: "2.0", - Method: method, - Params: params, - ID: 1, - } -} - -func call(t *testing.T, method string, params interface{}) *Response { - req, err := json.Marshal(createRequest(method, params)) - require.NoError(t, err) - - var rpcRes *Response - time.Sleep(1 * time.Second) - /* #nosec */ - res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) - require.NoError(t, err) - - decoder := json.NewDecoder(res.Body) - rpcRes = new(Response) - err = decoder.Decode(&rpcRes) - require.NoError(t, err) - - err = res.Body.Close() - require.NoError(t, err) - require.Nil(t, rpcRes.Error) - - return rpcRes -} - -func callWithError(method string, params interface{}) (*Response, error) { - req, err := json.Marshal(createRequest(method, params)) - if err != nil { - return nil, err - } - - var rpcRes *Response - time.Sleep(1 * time.Second) - /* #nosec */ - res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) - if err != nil { - return nil, err - } - - decoder := json.NewDecoder(res.Body) - rpcRes = new(Response) - err = decoder.Decode(&rpcRes) - if err != nil { - return nil, err - } - - err = res.Body.Close() - if err != nil { - return nil, err - } - - if rpcRes.Error != nil { - return nil, fmt.Errorf(rpcRes.Error.Message) - } - - return rpcRes, nil -} - -// turns a 0x prefixed hex string to a big.Int -func hexToBigInt(t *testing.T, in string) *big.Int { - s := in[2:] - b, err := hex.DecodeString(s) - require.NoError(t, err) - return big.NewInt(0).SetBytes(b) -} - -// sendTestTransaction sends a dummy transaction -func sendTestTransaction(t *testing.T) hexutil.Bytes { - param := make([]map[string]string, 1) - param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) - param[0]["to"] = "0x1122334455667788990011223344556677889900" - param[0]["value"] = "0x1" - rpcRes := call(t, "eth_sendTransaction", param) - - var hash hexutil.Bytes - err := json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) - return hash -} - -// deployTestContract deploys a contract that emits an event in the constructor -func deployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) { - param := make([]map[string]string, 1) - param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) - param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" - param[0]["gas"] = "0x200000" - - rpcRes := call(t, "eth_sendTransaction", param) - - var hash hexutil.Bytes - err := json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) - - receipt := waitForReceipt(t, hash) - require.NotNil(t, receipt, "transaction failed") - require.Equal(t, "0x1", receipt["status"].(string)) - - return hash, receipt -} - -func getTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { - param := []string{hash.String()} - rpcRes := call(t, "eth_getTransactionReceipt", param) - - receipt := make(map[string]interface{}) - err := json.Unmarshal(rpcRes.Result, &receipt) - require.NoError(t, err) - - return receipt -} - -func waitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { - for i := 0; i < 12; i++ { - receipt := getTransactionReceipt(t, hash) - if receipt != nil { - return receipt - } - - time.Sleep(time.Second) - } - - return nil -} - -func TestEth_Pending_GetBalance(t *testing.T) { - 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" - - rpcRes := call(t, "eth_sendTransaction", param) - - var res hexutil.Big - - rpcRes = call(t, "eth_getBalance", []string{addrA, "pending"}) - err := res.UnmarshalJSON(rpcRes.Result) - require.NoError(t, err) - t.Logf("Got balance %s for %s\n", res.String(), addrA) - - if res.ToInt().Cmp(big.NewInt(10)) != 0 { - t.Errorf("expected balance: %d, got: %s", 10, res.String()) - } - - rpcRes = call(t, "eth_getBalance", []string{addrA, "latest"}) - err = res.UnmarshalJSON(rpcRes.Result) - require.NoError(t, err) - t.Logf("Got balance %s for %s\n", res.String(), addrA) - - if res.ToInt().Cmp(big.NewInt(0)) != 0 { - t.Errorf("expected balance: %d, got: %s", 0, res.String()) - } -} - -func TestEth_Pending_GetTransactionCount(t *testing.T) { - currentNonce := getNonce(t, "latest") - t.Logf("Current nonce is %d", currentNonce) - - 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" - - _ = call(t, "eth_sendTransaction", param) - - pendingNonce := getNonce(t, "pending") - latestNonce := getNonce(t, "latest") - t.Logf("Latest nonce is %d", latestNonce) - require.Equal(t, currentNonce, latestNonce) - t.Logf("Pending nonce is %d", pendingNonce) - require.NotEqual(t, latestNonce, pendingNonce) -} - -func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { - 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" - - _ = call(t, "eth_sendTransaction", param) - - rpcRes := call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) - var pendingTxCount hexutil.Uint - err := json.Unmarshal(rpcRes.Result, &pendingTxCount) - require.NoError(t, err) - t.Logf("Pending nonce is %d", pendingTxCount) - - rpcRes = call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"latest"}) - var latestTxCount hexutil.Uint - err = json.Unmarshal(rpcRes.Result, &latestTxCount) - require.NoError(t, err) - t.Logf("Latest nonce is %d", latestTxCount) - - require.NotEqual(t, pendingTxCount, latestTxCount) -} - -func TestEth_Pending_GetBlockByNumber(t *testing.T) { - 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" - - _ = call(t, "eth_sendTransaction", param) - - rpcRes := call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) - var pendingBlock map[string]interface{} - err := json.Unmarshal(rpcRes.Result, &pendingTxCount) - require.NoError(t, err) - t.Logf("Pending nonce is %d", pendingTxCount) - -} diff --git a/tests/rpc_test.go b/tests/rpc_test.go index b0a7aca75..151353f98 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -8,7 +8,6 @@ package tests import ( "bytes" - "encoding/hex" "encoding/json" "fmt" "math/big" @@ -34,7 +33,6 @@ const ( var ( MODE = os.Getenv("MODE") - HOST = os.Getenv("HOST") zeroString = "0x0" from = []byte{} @@ -65,12 +63,8 @@ func TestMain(m *testing.M) { return } - if HOST == "" { - HOST = "http://localhost:8545" - } - var err error - from, err = getAddress() + from, err = GetAddress() if err != nil { fmt.Printf("failed to get account: %s\n", err) os.Exit(1) @@ -81,106 +75,19 @@ func TestMain(m *testing.M) { os.Exit(code) } -func getAddress() ([]byte, error) { - rpcRes, err := callWithError("eth_accounts", []string{}) - if err != nil { - return nil, err - } - - var res []hexutil.Bytes - err = json.Unmarshal(rpcRes.Result, &res) - if err != nil { - return nil, err - } - - return res[0], nil -} - -func createRequest(method string, params interface{}) Request { - return Request{ - Version: "2.0", - Method: method, - Params: params, - ID: 1, - } -} - -func call(t *testing.T, method string, params interface{}) *Response { - req, err := json.Marshal(createRequest(method, params)) - require.NoError(t, err) - - var rpcRes *Response - time.Sleep(1 * time.Second) - /* #nosec */ - res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) - require.NoError(t, err) - - decoder := json.NewDecoder(res.Body) - rpcRes = new(Response) - err = decoder.Decode(&rpcRes) - require.NoError(t, err) - - err = res.Body.Close() - require.NoError(t, err) - require.Nil(t, rpcRes.Error) - - return rpcRes -} - -func callWithError(method string, params interface{}) (*Response, error) { - req, err := json.Marshal(createRequest(method, params)) - if err != nil { - return nil, err - } - - var rpcRes *Response - time.Sleep(1 * time.Second) - /* #nosec */ - res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) - if err != nil { - return nil, err - } - - decoder := json.NewDecoder(res.Body) - rpcRes = new(Response) - err = decoder.Decode(&rpcRes) - if err != nil { - return nil, err - } - - err = res.Body.Close() - if err != nil { - return nil, err - } - - if rpcRes.Error != nil { - return nil, fmt.Errorf(rpcRes.Error.Message) - } - - return rpcRes, nil -} - -// turns a 0x prefixed hex string to a big.Int -func hexToBigInt(t *testing.T, in string) *big.Int { - s := in[2:] - b, err := hex.DecodeString(s) - require.NoError(t, err) - return big.NewInt(0).SetBytes(b) -} - func TestBlockBloom(t *testing.T) { - hash := deployTestContractWithFunction(t) - receipt := waitForReceipt(t, hash) + hash := DeployTestContractWithFunction(t) + receipt := WaitForReceipt(t, hash) number := receipt["blockNumber"].(string) param := []interface{}{number, false} - rpcRes := call(t, "eth_getBlockByNumber", param) + rpcRes := Call(t, "eth_getBlockByNumber", param) block := make(map[string]interface{}) err := json.Unmarshal(rpcRes.Result, &block) require.NoError(t, err) - lb := hexToBigInt(t, block["logsBloom"].(string)) + lb := HexToBigInt(t, block["logsBloom"].(string)) require.NotEqual(t, big.NewInt(0), lb) require.Equal(t, hash.String(), block["transactions"].([]interface{})[0]) } @@ -189,7 +96,7 @@ func TestEth_GetLogs_NoLogs(t *testing.T) { param := make([]map[string][]string, 1) param[0] = make(map[string][]string) param[0]["topics"] = []string{} - rpcRes := call(t, "eth_getLogs", param) + rpcRes := Call(t, "eth_getLogs", param) require.NotNil(t, rpcRes) require.Nil(t, rpcRes.Error) @@ -205,7 +112,7 @@ func TestEth_GetLogs_Topics_AB(t *testing.T) { t.Skip("skipping TestEth_GetLogs_Topics_AB") } - rpcRes := call(t, "eth_blockNumber", []string{}) + rpcRes := Call(t, "eth_blockNumber", []string{}) var res hexutil.Uint64 err := res.UnmarshalJSON(rpcRes.Result) @@ -216,10 +123,10 @@ func TestEth_GetLogs_Topics_AB(t *testing.T) { param[0]["topics"] = []string{helloTopic, worldTopic} param[0]["fromBlock"] = res.String() - hash := deployTestContractWithFunction(t) - waitForReceipt(t, hash) + hash := DeployTestContractWithFunction(t) + WaitForReceipt(t, hash) - rpcRes = call(t, "eth_getLogs", param) + rpcRes = Call(t, "eth_getLogs", param) var logs []*ethtypes.Log err = json.Unmarshal(rpcRes.Result, &logs) @@ -234,9 +141,9 @@ func TestEth_GetTransactionCount(t *testing.T) { t.Skip("skipping TestEth_GetTransactionCount") } - prev := getNonce(t) - sendTestTransaction(t) - post := getNonce(t) + prev := GetNonce(t, "latest") + SendTestTransaction(t) + post := GetNonce(t, "latest") require.Equal(t, prev, post-1) } @@ -246,10 +153,10 @@ func TestEth_GetTransactionLogs(t *testing.T) { t.Skip("skipping TestEth_GetTransactionLogs") } - hash, _ := deployTestContract(t) + hash, _ := DeployTestContract(t) param := []string{hash.String()} - rpcRes := call(t, "eth_getTransactionLogs", param) + rpcRes := Call(t, "eth_getTransactionLogs", param) logs := new([]*ethtypes.Log) err := json.Unmarshal(rpcRes.Result, logs) @@ -260,7 +167,7 @@ func TestEth_GetTransactionLogs(t *testing.T) { func TestEth_protocolVersion(t *testing.T) { expectedRes := hexutil.Uint(version.ProtocolVersion) - rpcRes := call(t, "eth_protocolVersion", []string{}) + rpcRes := Call(t, "eth_protocolVersion", []string{}) var res hexutil.Uint err := res.UnmarshalJSON(rpcRes.Result) @@ -271,7 +178,7 @@ func TestEth_protocolVersion(t *testing.T) { } func TestEth_chainId(t *testing.T) { - rpcRes := call(t, "eth_chainId", []string{}) + rpcRes := Call(t, "eth_chainId", []string{}) var res hexutil.Uint err := res.UnmarshalJSON(rpcRes.Result) @@ -280,7 +187,7 @@ func TestEth_chainId(t *testing.T) { } func TestEth_blockNumber(t *testing.T) { - rpcRes := call(t, "eth_blockNumber", []string{}) + rpcRes := Call(t, "eth_blockNumber", []string{}) var res hexutil.Uint64 err := res.UnmarshalJSON(rpcRes.Result) @@ -291,7 +198,7 @@ func TestEth_blockNumber(t *testing.T) { func TestEth_coinbase(t *testing.T) { zeroAddress := hexutil.Bytes(ethcmn.Address{}.Bytes()) - rpcRes := call(t, "eth_coinbase", []string{}) + rpcRes := Call(t, "eth_coinbase", []string{}) var res hexutil.Bytes err := res.UnmarshalJSON(rpcRes.Result) @@ -302,7 +209,7 @@ func TestEth_coinbase(t *testing.T) { } func TestEth_GetBalance(t *testing.T) { - rpcRes := call(t, "eth_getBalance", []string{addrA, zeroString}) + rpcRes := Call(t, "eth_getBalance", []string{addrA, zeroString}) var res hexutil.Big err := res.UnmarshalJSON(rpcRes.Result) @@ -318,7 +225,7 @@ func TestEth_GetBalance(t *testing.T) { func TestEth_GetStorageAt(t *testing.T) { expectedRes := hexutil.Bytes{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - rpcRes := call(t, "eth_getStorageAt", []string{addrA, fmt.Sprint(addrAStoreKey), zeroString}) + rpcRes := Call(t, "eth_getStorageAt", []string{addrA, fmt.Sprint(addrAStoreKey), zeroString}) var storage hexutil.Bytes err := storage.UnmarshalJSON(rpcRes.Result) @@ -334,7 +241,7 @@ func TestEth_GetProof(t *testing.T) { params[0] = addrA params[1] = []string{fmt.Sprint(addrAStoreKey)} params[2] = "latest" - rpcRes := call(t, "eth_getProof", params) + rpcRes := Call(t, "eth_getProof", params) require.NotNil(t, rpcRes) var accRes rpctypes.AccountResult @@ -348,7 +255,7 @@ func TestEth_GetProof(t *testing.T) { func TestEth_GetCode(t *testing.T) { expectedRes := hexutil.Bytes{} - rpcRes := call(t, "eth_getCode", []string{addrA, zeroString}) + rpcRes := Call(t, "eth_getCode", []string{addrA, zeroString}) var code hexutil.Bytes err := code.UnmarshalJSON(rpcRes.Result) @@ -368,13 +275,13 @@ func TestEth_SendTransaction_Transfer(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x55ae82600" - rpcRes := call(t, "eth_sendTransaction", param) + rpcRes := Call(t, "eth_sendTransaction", param) var hash hexutil.Bytes err := json.Unmarshal(rpcRes.Result, &hash) require.NoError(t, err) - receipt := waitForReceipt(t, hash) + receipt := WaitForReceipt(t, hash) require.NotNil(t, receipt) require.Equal(t, "0x1", receipt["status"].(string)) } @@ -385,7 +292,7 @@ func TestEth_SendTransaction_ContractDeploy(t *testing.T) { param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" - rpcRes := call(t, "eth_sendTransaction", param) + rpcRes := Call(t, "eth_sendTransaction", param) var hash hexutil.Bytes err := json.Unmarshal(rpcRes.Result, &hash) @@ -396,7 +303,7 @@ func TestEth_NewFilter(t *testing.T) { param := make([]map[string][]string, 1) param[0] = make(map[string][]string) param[0]["topics"] = []string{"0x0000000000000000000000000000000000000000000000000000000012341234"} - rpcRes := call(t, "eth_newFilter", param) + rpcRes := Call(t, "eth_newFilter", param) var ID string err := json.Unmarshal(rpcRes.Result, &ID) @@ -404,7 +311,7 @@ func TestEth_NewFilter(t *testing.T) { } func TestEth_NewBlockFilter(t *testing.T) { - rpcRes := call(t, "eth_newBlockFilter", []string{}) + rpcRes := Call(t, "eth_newBlockFilter", []string{}) var ID string err := json.Unmarshal(rpcRes.Result, &ID) @@ -412,7 +319,7 @@ func TestEth_NewBlockFilter(t *testing.T) { } func TestEth_GetFilterChanges_BlockFilter(t *testing.T) { - rpcRes := call(t, "eth_newBlockFilter", []string{}) + rpcRes := Call(t, "eth_newBlockFilter", []string{}) var ID string err := json.Unmarshal(rpcRes.Result, &ID) @@ -420,7 +327,7 @@ func TestEth_GetFilterChanges_BlockFilter(t *testing.T) { time.Sleep(5 * time.Second) - changesRes := call(t, "eth_getFilterChanges", []string{ID}) + changesRes := Call(t, "eth_getFilterChanges", []string{ID}) var hashes []ethcmn.Hash err = json.Unmarshal(changesRes.Result, &hashes) require.NoError(t, err) @@ -431,13 +338,13 @@ func TestEth_GetFilterChanges_NoLogs(t *testing.T) { param := make([]map[string][]string, 1) param[0] = make(map[string][]string) param[0]["topics"] = []string{} - rpcRes := call(t, "eth_newFilter", param) + rpcRes := Call(t, "eth_newFilter", param) var ID string err := json.Unmarshal(rpcRes.Result, &ID) require.NoError(t, err) - changesRes := call(t, "eth_getFilterChanges", []string{ID}) + changesRes := Call(t, "eth_getFilterChanges", []string{ID}) var logs []*ethtypes.Log err = json.Unmarshal(changesRes.Result, &logs) @@ -445,7 +352,7 @@ func TestEth_GetFilterChanges_NoLogs(t *testing.T) { } func TestEth_GetFilterChanges_WrongID(t *testing.T) { - req, err := json.Marshal(createRequest("eth_getFilterChanges", []string{"0x1122334400000077"})) + req, err := json.Marshal(CreateRequest("eth_getFilterChanges", []string{"0x1122334400000077"})) require.NoError(t, err) var rpcRes *Response @@ -464,28 +371,13 @@ func TestEth_GetFilterChanges_WrongID(t *testing.T) { require.NotNil(t, "invalid filter ID", rpcRes.Error.Message) } -// sendTestTransaction sends a dummy transaction -func sendTestTransaction(t *testing.T) hexutil.Bytes { - param := make([]map[string]string, 1) - param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) - param[0]["to"] = "0x1122334455667788990011223344556677889900" - param[0]["value"] = "0x1" - rpcRes := call(t, "eth_sendTransaction", param) - - var hash hexutil.Bytes - err := json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) - return hash -} - func TestEth_GetTransactionReceipt(t *testing.T) { - hash := sendTestTransaction(t) + hash := SendTestTransaction(t) time.Sleep(time.Second * 5) param := []string{hash.String()} - rpcRes := call(t, "eth_getTransactionReceipt", param) + rpcRes := Call(t, "eth_getTransactionReceipt", param) require.Nil(t, rpcRes.Error) receipt := make(map[string]interface{}) @@ -496,34 +388,13 @@ func TestEth_GetTransactionReceipt(t *testing.T) { require.Equal(t, []interface{}{}, receipt["logs"].([]interface{})) } -// deployTestContract deploys a contract that emits an event in the constructor -func deployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) { - param := make([]map[string]string, 1) - param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) - param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" - param[0]["gas"] = "0x200000" - - rpcRes := call(t, "eth_sendTransaction", param) - - var hash hexutil.Bytes - err := json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) - - receipt := waitForReceipt(t, hash) - require.NotNil(t, receipt, "transaction failed") - require.Equal(t, "0x1", receipt["status"].(string)) - - return hash, receipt -} - func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) { - hash, _ := deployTestContract(t) + hash, _ := DeployTestContract(t) time.Sleep(time.Second * 5) param := []string{hash.String()} - rpcRes := call(t, "eth_getTransactionReceipt", param) + rpcRes := Call(t, "eth_getTransactionReceipt", param) receipt := make(map[string]interface{}) err := json.Unmarshal(rpcRes.Result, &receipt) @@ -535,32 +406,8 @@ func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) { } -func getTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { - param := []string{hash.String()} - rpcRes := call(t, "eth_getTransactionReceipt", param) - - receipt := make(map[string]interface{}) - err := json.Unmarshal(rpcRes.Result, &receipt) - require.NoError(t, err) - - return receipt -} - -func waitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { - for i := 0; i < 12; i++ { - receipt := getTransactionReceipt(t, hash) - if receipt != nil { - return receipt - } - - time.Sleep(time.Second) - } - - return nil -} - func TestEth_GetFilterChanges_NoTopics(t *testing.T) { - rpcRes := call(t, "eth_blockNumber", []string{}) + rpcRes := Call(t, "eth_blockNumber", []string{}) var res hexutil.Uint64 err := res.UnmarshalJSON(rpcRes.Result) @@ -572,17 +419,17 @@ func TestEth_GetFilterChanges_NoTopics(t *testing.T) { param[0]["fromBlock"] = res.String() // instantiate new filter - rpcRes = call(t, "eth_newFilter", param) + rpcRes = Call(t, "eth_newFilter", param) require.Nil(t, rpcRes.Error) var ID string err = json.Unmarshal(rpcRes.Result, &ID) require.NoError(t, err) // deploy contract, emitting some event - deployTestContract(t) + DeployTestContract(t) // get filter changes - changesRes := call(t, "eth_getFilterChanges", []string{ID}) + changesRes := Call(t, "eth_getFilterChanges", []string{ID}) var logs []*ethtypes.Log err = json.Unmarshal(changesRes.Result, &logs) @@ -606,51 +453,11 @@ var helloTopic = "0x775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73 // world parameter in Hello event var worldTopic = "0x0000000000000000000000000000000000000000000000000000000000000011" -func deployTestContractWithFunction(t *testing.T) hexutil.Bytes { - // pragma solidity ^0.5.1; - - // contract Test { - // event Hello(uint256 indexed world); - // event TestEvent(uint256 indexed a, uint256 indexed b); - - // uint256 myStorage; - - // constructor() public { - // emit Hello(17); - // } - - // function test(uint256 a, uint256 b) public { - // myStorage = a; - // emit TestEvent(a, b); - // } - // } - - bytecode := "0x608060405234801561001057600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a260d08061004d6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063eb8ac92114602d575b600080fd5b606060048036036040811015604157600080fd5b8101908080359060200190929190803590602001909291905050506062565b005b8160008190555080827ff3ca124a697ba07e8c5e80bebcfcc48991fc16a63170e8a9206e30508960d00360405160405180910390a3505056fea265627a7a723158201d94d2187aaf3a6790527b615fcc40970febf0385fa6d72a2344848ebd0df3e964736f6c63430005110032" - - param := make([]map[string]string, 1) - param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) - param[0]["data"] = bytecode - param[0]["gas"] = "0x200000" - - rpcRes := call(t, "eth_sendTransaction", param) - - var hash hexutil.Bytes - err := json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) - - receipt := waitForReceipt(t, hash) - require.NotNil(t, receipt, "transaction failed") - require.Equal(t, "0x1", receipt["status"].(string)) - - return hash -} - // Tests topics case where there are topics in first two positions func TestEth_GetFilterChanges_Topics_AB(t *testing.T) { time.Sleep(time.Second) - rpcRes := call(t, "eth_blockNumber", []string{}) + rpcRes := Call(t, "eth_blockNumber", []string{}) var res hexutil.Uint64 err := res.UnmarshalJSON(rpcRes.Result) @@ -662,15 +469,15 @@ func TestEth_GetFilterChanges_Topics_AB(t *testing.T) { param[0]["fromBlock"] = res.String() // instantiate new filter - rpcRes = call(t, "eth_newFilter", param) + rpcRes = Call(t, "eth_newFilter", param) var ID string err = json.Unmarshal(rpcRes.Result, &ID) require.NoError(t, err, string(rpcRes.Result)) - deployTestContractWithFunction(t) + DeployTestContractWithFunction(t) // get filter changes - changesRes := call(t, "eth_getFilterChanges", []string{ID}) + changesRes := Call(t, "eth_getFilterChanges", []string{ID}) var logs []*ethtypes.Log err = json.Unmarshal(changesRes.Result, &logs) @@ -680,7 +487,7 @@ func TestEth_GetFilterChanges_Topics_AB(t *testing.T) { } func TestEth_GetFilterChanges_Topics_XB(t *testing.T) { - rpcRes := call(t, "eth_blockNumber", []string{}) + rpcRes := Call(t, "eth_blockNumber", []string{}) var res hexutil.Uint64 err := res.UnmarshalJSON(rpcRes.Result) @@ -692,15 +499,15 @@ func TestEth_GetFilterChanges_Topics_XB(t *testing.T) { param[0]["fromBlock"] = res.String() // instantiate new filter - rpcRes = call(t, "eth_newFilter", param) + rpcRes = Call(t, "eth_newFilter", param) var ID string err = json.Unmarshal(rpcRes.Result, &ID) require.NoError(t, err) - deployTestContractWithFunction(t) + DeployTestContractWithFunction(t) // get filter changes - changesRes := call(t, "eth_getFilterChanges", []string{ID}) + changesRes := Call(t, "eth_getFilterChanges", []string{ID}) var logs []*ethtypes.Log err = json.Unmarshal(changesRes.Result, &logs) @@ -715,20 +522,20 @@ func TestEth_GetFilterChanges_Topics_XXC(t *testing.T) { } func TestEth_PendingTransactionFilter(t *testing.T) { - rpcRes := call(t, "eth_newPendingTransactionFilter", []string{}) + rpcRes := Call(t, "eth_newPendingTransactionFilter", []string{}) var ID string err := json.Unmarshal(rpcRes.Result, &ID) require.NoError(t, err) for i := 0; i < 5; i++ { - deployTestContractWithFunction(t) + DeployTestContractWithFunction(t) } time.Sleep(10 * time.Second) // get filter changes - changesRes := call(t, "eth_getFilterChanges", []string{ID}) + changesRes := Call(t, "eth_getFilterChanges", []string{ID}) require.NotNil(t, changesRes) var txs []*hexutil.Bytes @@ -738,23 +545,13 @@ func TestEth_PendingTransactionFilter(t *testing.T) { require.True(t, len(txs) >= 2, "could not get any txs", "changesRes.Result", string(changesRes.Result)) } -func getNonce(t *testing.T) hexutil.Uint64 { - param := []interface{}{hexutil.Bytes(from), "latest"} - rpcRes := call(t, "eth_getTransactionCount", param) - - var nonce hexutil.Uint64 - err := json.Unmarshal(rpcRes.Result, &nonce) - require.NoError(t, err) - return nonce -} - func TestEth_EstimateGas(t *testing.T) { param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["to"] = "0x1122334455667788990011223344556677889900" param[0]["value"] = "0x1" - rpcRes := call(t, "eth_estimateGas", param) + rpcRes := Call(t, "eth_estimateGas", param) require.NotNil(t, rpcRes) require.NotEmpty(t, rpcRes.Result) @@ -773,7 +570,7 @@ func TestEth_EstimateGas_ContractDeployment(t *testing.T) { param[0]["from"] = "0x" + fmt.Sprintf("%x", from) param[0]["data"] = bytecode - rpcRes := call(t, "eth_estimateGas", param) + rpcRes := Call(t, "eth_estimateGas", param) require.NotNil(t, rpcRes) require.NotEmpty(t, rpcRes.Result) @@ -786,7 +583,7 @@ func TestEth_EstimateGas_ContractDeployment(t *testing.T) { func TestEth_GetBlockByNumber(t *testing.T) { param := []interface{}{"0x1", false} - rpcRes := call(t, "eth_getBlockByNumber", param) + rpcRes := Call(t, "eth_getBlockByNumber", param) block := make(map[string]interface{}) err := json.Unmarshal(rpcRes.Result, &block) @@ -804,7 +601,7 @@ func TestEth_Call_Pending(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" - rpcRes := call(t, "eth_sendTransaction", param) + rpcRes := Call(t, "eth_sendTransaction", param) var hash hexutil.Bytes err := json.Unmarshal(rpcRes.Result, &hash) @@ -818,7 +615,7 @@ func TestEth_Call_Pending(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" - rpcRes = call(t, "eth_call", []interface{}{param[0], "pending"}) + rpcRes = Call(t, "eth_call", []interface{}{param[0], "pending"}) err = json.Unmarshal(rpcRes.Result, &hash) require.NoError(t, err) } diff --git a/tests/utils.go b/tests/utils.go new file mode 100644 index 000000000..7b80786ea --- /dev/null +++ b/tests/utils.go @@ -0,0 +1,272 @@ +package tests + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "net/http" + "os" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +) + +type Request struct { + Version string `json:"jsonrpc"` + Method string `json:"method"` + Params interface{} `json:"params"` + ID int `json:"id"` +} + +type RPCError struct { + Code int `json:"code"` + Message string `json:"message"` + Data interface{} `json:"data,omitempty"` +} + +type Response struct { + Error *RPCError `json:"error"` + ID int `json:"id"` + Result json.RawMessage `json:"result,omitempty"` +} + +var ( + MODE = os.Getenv("MODE") + HOST = os.Getenv("HOST") + + zeroString = "0x0" + from = []byte{} +) + +func GetAddress() ([]byte, error) { + rpcRes, err := CallWithError("eth_accounts", []string{}) + if err != nil { + return nil, err + } + + var res []hexutil.Bytes + err = json.Unmarshal(rpcRes.Result, &res) + if err != nil { + return nil, err + } + + return res[0], nil +} + +func CreateRequest(method string, params interface{}) Request { + return Request{ + Version: "2.0", + Method: method, + Params: params, + ID: 1, + } +} + +func Call(t *testing.T, method string, params interface{}) *Response { + req, err := json.Marshal(CreateRequest(method, params)) + require.NoError(t, err) + + var rpcRes *Response + time.Sleep(1 * time.Second) + /* #nosec */ + + if HOST == "" { + HOST = "http://localhost:8545" + } + res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) + require.NoError(t, err) + + decoder := json.NewDecoder(res.Body) + rpcRes = new(Response) + err = decoder.Decode(&rpcRes) + require.NoError(t, err) + + err = res.Body.Close() + require.NoError(t, err) + require.Nil(t, rpcRes.Error) + + return rpcRes +} + +func CallWithError(method string, params interface{}) (*Response, error) { + req, err := json.Marshal(CreateRequest(method, params)) + if err != nil { + return nil, err + } + + var rpcRes *Response + time.Sleep(1 * time.Second) + /* #nosec */ + + if HOST == "" { + HOST = "http://localhost:8545" + } + res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) + if err != nil { + return nil, err + } + + decoder := json.NewDecoder(res.Body) + rpcRes = new(Response) + err = decoder.Decode(&rpcRes) + if err != nil { + return nil, err + } + + err = res.Body.Close() + if err != nil { + return nil, err + } + + if rpcRes.Error != nil { + return nil, fmt.Errorf(rpcRes.Error.Message) + } + + return rpcRes, nil +} + +// turns a 0x prefixed hex string to a big.Int +func HexToBigInt(t *testing.T, in string) *big.Int { + s := in[2:] + b, err := hex.DecodeString(s) + require.NoError(t, err) + return big.NewInt(0).SetBytes(b) +} + +// sendTestTransaction sends a dummy transaction +func SendTestTransaction(t *testing.T) hexutil.Bytes { + from, err := GetAddress() + if err != nil { + fmt.Printf("failed to get account: %s\n", err) + os.Exit(1) + } + + param := make([]map[string]string, 1) + param[0] = make(map[string]string) + param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["to"] = "0x1122334455667788990011223344556677889900" + param[0]["value"] = "0x1" + rpcRes := Call(t, "eth_sendTransaction", param) + + var hash hexutil.Bytes + err = json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) + return hash +} + +// deployTestContract deploys a contract that emits an event in the constructor +func DeployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) { + from, err := GetAddress() + if err != nil { + fmt.Printf("failed to get account: %s\n", err) + os.Exit(1) + } + + param := make([]map[string]string, 1) + param[0] = make(map[string]string) + param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" + param[0]["gas"] = "0x200000" + + rpcRes := Call(t, "eth_sendTransaction", param) + + var hash hexutil.Bytes + err = json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) + + receipt := WaitForReceipt(t, hash) + require.NotNil(t, receipt, "transaction failed") + require.Equal(t, "0x1", receipt["status"].(string)) + + return hash, receipt +} + +func DeployTestContractWithFunction(t *testing.T) hexutil.Bytes { + // pragma solidity ^0.5.1; + + // contract Test { + // event Hello(uint256 indexed world); + // event TestEvent(uint256 indexed a, uint256 indexed b); + + // uint256 myStorage; + + // constructor() public { + // emit Hello(17); + // } + + // function test(uint256 a, uint256 b) public { + // myStorage = a; + // emit TestEvent(a, b); + // } + // } + + bytecode := "0x608060405234801561001057600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a260d08061004d6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063eb8ac92114602d575b600080fd5b606060048036036040811015604157600080fd5b8101908080359060200190929190803590602001909291905050506062565b005b8160008190555080827ff3ca124a697ba07e8c5e80bebcfcc48991fc16a63170e8a9206e30508960d00360405160405180910390a3505056fea265627a7a723158201d94d2187aaf3a6790527b615fcc40970febf0385fa6d72a2344848ebd0df3e964736f6c63430005110032" + + from, err := GetAddress() + if err != nil { + fmt.Printf("failed to get account: %s\n", err) + os.Exit(1) + } + + param := make([]map[string]string, 1) + param[0] = make(map[string]string) + param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["data"] = bytecode + param[0]["gas"] = "0x200000" + + rpcRes := Call(t, "eth_sendTransaction", param) + + var hash hexutil.Bytes + err = json.Unmarshal(rpcRes.Result, &hash) + require.NoError(t, err) + + receipt := WaitForReceipt(t, hash) + require.NotNil(t, receipt, "transaction failed") + require.Equal(t, "0x1", receipt["status"].(string)) + + return hash +} + +func GetTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { + param := []string{hash.String()} + rpcRes := Call(t, "eth_getTransactionReceipt", param) + + receipt := make(map[string]interface{}) + err := json.Unmarshal(rpcRes.Result, &receipt) + require.NoError(t, err) + + return receipt +} + +func WaitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { + for i := 0; i < 12; i++ { + receipt := GetTransactionReceipt(t, hash) + if receipt != nil { + return receipt + } + + time.Sleep(time.Second) + } + + return nil +} + +func GetNonce(t *testing.T, block string) hexutil.Uint64 { + from, err := GetAddress() + if err != nil { + fmt.Printf("failed to get account: %s\n", err) + os.Exit(1) + } + + param := []interface{}{hexutil.Bytes(from), block} + rpcRes := Call(t, "eth_getTransactionCount", param) + + var nonce hexutil.Uint64 + err = json.Unmarshal(rpcRes.Result, &nonce) + require.NoError(t, err) + return nonce +} From ea5be6b3881ea71d51d3d84a72edd8aa7ed6892d Mon Sep 17 00:00:00 2001 From: araskachoi Date: Fri, 20 Nov 2020 10:56:28 -0800 Subject: [PATCH 29/61] fix latest case for eth_GetBlockTransactionCountByNumber --- rpc/namespaces/eth/api.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 4e7720b8f..84f60b2fc 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -7,6 +7,8 @@ import ( "fmt" "math/big" "os" + "strconv" + "strings" "sync" "time" @@ -328,8 +330,18 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) * func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { api.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) + var height int64 if blockNum != rpctypes.PendingBlockNumber { - height := blockNum.Int64() + if blockNum == rpctypes.LatestBlockNumber { + bn, err := api.backend.BlockNumber() + if err != nil { + return nil + } + bnCleaned := strings.Replace(bn.String(), "0x", "", -1) + height, err = strconv.ParseInt(bnCleaned, 16, 64) + } else { + height = blockNum.Int64() + } resBlock, err := api.clientCtx.Client.Block(&height) if err != nil { return nil @@ -344,7 +356,7 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes return nil } - txCount := hexutil.Uint(len(pendingTxs)) + txCount := hexutil.Uint(len(pendingTxs) / 2) return &txCount } From 227adf81828e60188b49f5c5aa2490fff1e8b9a3 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 12:49:50 -0800 Subject: [PATCH 30/61] fix repeating null transactions in queue --- rpc/backend/backend.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 90ca6d118..a8b2eae38 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -196,7 +196,7 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error return nil, err } - transactions := make([]*rpctypes.Transaction, pendingTxs.Count) + transactions := make([]*rpctypes.Transaction, 0) for _, tx := range pendingTxs.Txs { ethTx, err := rpctypes.RawTxToEthTx(b.clientCtx, tx) if err != nil { @@ -209,10 +209,8 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error if err != nil { return nil, err } - transactions = append(transactions, rpcTx) } - return transactions, nil } From f3e6cf9c66a2a006dd99545484118b98d275b94c Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 17:44:57 -0800 Subject: [PATCH 31/61] remove repeated structs --- tests/rpc_test.go | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/tests/rpc_test.go b/tests/rpc_test.go index 151353f98..be04f80e7 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -31,32 +31,6 @@ const ( addrAStoreKey = 0 ) -var ( - MODE = os.Getenv("MODE") - - zeroString = "0x0" - from = []byte{} -) - -type Request struct { - Version string `json:"jsonrpc"` - Method string `json:"method"` - Params interface{} `json:"params"` - ID int `json:"id"` -} - -type RPCError struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data,omitempty"` -} - -type Response struct { - Error *RPCError `json:"error"` - ID int `json:"id"` - Result json.RawMessage `json:"result,omitempty"` -} - func TestMain(m *testing.M) { if MODE != "rpc" { _, _ = fmt.Fprintln(os.Stdout, "Skipping RPC test") From 0dd8d0e159c718c4494997d85a4216785c61331e Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 17:45:41 -0800 Subject: [PATCH 32/61] latestblock case --- rpc/namespaces/eth/api.go | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index 84f60b2fc..b81091319 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -7,8 +7,6 @@ import ( "fmt" "math/big" "os" - "strconv" - "strings" "sync" "time" @@ -330,15 +328,16 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByHash(hash common.Hash) * func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { api.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) - var height int64 + var ( + height int64 + err error + ) if blockNum != rpctypes.PendingBlockNumber { if blockNum == rpctypes.LatestBlockNumber { - bn, err := api.backend.BlockNumber() + height, err = api.backend.LatestBlockNumber() if err != nil { return nil } - bnCleaned := strings.Replace(bn.String(), "0x", "", -1) - height, err = strconv.ParseInt(bnCleaned, 16, 64) } else { height = blockNum.Int64() } @@ -356,7 +355,7 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes return nil } - txCount := hexutil.Uint(len(pendingTxs) / 2) + txCount := hexutil.Uint(len(pendingTxs)) return &txCount } @@ -688,8 +687,8 @@ func (api *PublicEthereumAPI) GetTransactionByHash(hash common.Hash) (*rpctypes. tx, err := api.clientCtx.Client.Tx(hash.Bytes(), false) if err != nil { // check if the tx is on the mempool - pendingTxs, err := api.PendingTransactions() - if err != nil { + pendingTxs, pendingErr := api.PendingTransactions() + if pendingErr != nil { return nil, err } @@ -744,8 +743,20 @@ func (api *PublicEthereumAPI) GetTransactionByBlockHashAndIndex(hash common.Hash // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.Transaction, error) { api.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) + var ( + height int64 + err error + ) if blockNum != rpctypes.PendingBlockNumber { - height := blockNum.Int64() + if blockNum == rpctypes.LatestBlockNumber { + height, err = api.backend.LatestBlockNumber() + if err != nil { + return nil, err + } + } else { + height = blockNum.Int64() + } + resBlock, err := api.clientCtx.Client.Block(&height) if err != nil { return nil, err @@ -765,7 +776,8 @@ func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpcty return nil, nil } - return pendingTxs[idx], nil + // change back to pendingTxs[idx] once pending queue is fixed. + return pendingTxs[int(idx)], nil } func (api *PublicEthereumAPI) getTransactionByBlockAndIndex(block *tmtypes.Block, idx hexutil.Uint) (*rpctypes.Transaction, error) { From 75d52ad5a8fa59a8b8a119d6c6898eb377b8b45e Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 17:46:56 -0800 Subject: [PATCH 33/61] revert init script back --- init.sh | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/init.sh b/init.sh index 1c193c8da..46acda794 100755 --- a/init.sh +++ b/init.sh @@ -36,15 +36,15 @@ cat $HOME/.ethermintd/config/genesis.json | jq '.app_state["faucet"]["enable_fau cat $HOME/.ethermintd/config/genesis.json | jq '.consensus_params["block"]["time_iota_ms"]="30000"' > $HOME/.ethermintd/config/tmp_genesis.json && mv $HOME/.ethermintd/config/tmp_genesis.json $HOME/.ethermintd/config/genesis.json if [[ $1 == "pending" ]]; then - echo "pending mode on; block times will be set to ~60s." - sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermintd/config/config.toml + echo "pending mode on; block times will be set to 30s." + # sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.ethermintd/config/config.toml sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.ethermintd/config/config.toml sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.ethermintd/config/config.toml sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.ethermintd/config/config.toml sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.ethermintd/config/config.toml sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.ethermintd/config/config.toml sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.ethermintd/config/config.toml - sed -i 's/timeout_commit = "5s"/timeout_commit = "50s"/g' $HOME/.ethermintd/config/config.toml + sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.ethermintd/config/config.toml fi # Allocate genesis accounts (cosmos formatted addresses) @@ -69,8 +69,4 @@ echo -e '\nrun the following command in a different terminal/window to run the R echo -e "ethermintcli rest-server --laddr \"tcp://localhost:8545\" --unlock-key $KEY --chain-id $CHAINID --trace\n" # Start the node (remove the --pruning=nothing flag if historical queries are not needed) -ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" --trace > d.log & - -sleep 1 - -ethermintcli rest-server --laddr "tcp://localhost:8545" --unlock-key $KEY --chain-id $CHAINID --trace > cli.log & +ethermintd start --pruning=nothing --rpc.unsafe --log_level "main:info,state:info,mempool:info" --trace From 639c47dc20a85a0e93fe1406ba17333237d382bf Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 17:47:45 -0800 Subject: [PATCH 34/61] fix to exportable method --- tests-solidity/suites/basic/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests-solidity/suites/basic/main.go b/tests-solidity/suites/basic/main.go index 7975b6ffc..93d327682 100644 --- a/tests-solidity/suites/basic/main.go +++ b/tests-solidity/suites/basic/main.go @@ -82,7 +82,7 @@ func call(method string, params interface{}) (*Response, error) { HOST = "http://localhost:8545" } - req, err := json.Marshal(CreateRequest(method, params)) + req, err := json.Marshal(createRequest(method, params)) if err != nil { return nil, err } From 533b443102f64383b1a3d87fa594716214a6aed4 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 17:48:28 -0800 Subject: [PATCH 35/61] automate pending tests; add make cmd --- Makefile | 5 +- scripts/integration-test-all.sh | 27 +++++-- tests-pending/rpc_pending_test.go | 113 ++++++++++++++++++------------ 3 files changed, 96 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index c33bed084..c101b2ad9 100644 --- a/Makefile +++ b/Makefile @@ -266,7 +266,10 @@ test-import: rm -rf importer/tmp test-rpc: - ./scripts/integration-test-all.sh -q 1 -z 1 -s 2 + ./scripts/integration-test-all.sh -t "rpc" -q 1 -z 1 -s 2 -m "rpc" + +test-rpc-pending: + ./scripts/integration-test-all.sh -t "pending" -q 1 -z 1 -s 2 -m "pending" test-contract: @type "npm" 2> /dev/null || (echo 'Npm does not exist. Please install node.js and npm."' && exit 1) diff --git a/scripts/integration-test-all.sh b/scripts/integration-test-all.sh index 0001f4aab..b556f8659 100755 --- a/scripts/integration-test-all.sh +++ b/scripts/integration-test-all.sh @@ -12,7 +12,6 @@ TEST_QTD=1 #PORT AND RPC_PORT 3 initial digits, to be concat with a suffix later when node is initialized RPC_PORT="854" IP_ADDR="0.0.0.0" -MODE="rpc" KEY="mykey" CHAINID="ethermint-2" @@ -33,7 +32,7 @@ usage() { exit 1 } -while getopts "h?t:q:z:s:" args; do +while getopts "h?t:q:z:s:m:" args; do case $args in h|\?) usage; @@ -42,6 +41,7 @@ while getopts "h?t:q:z:s:" args; do q ) QTD=${OPTARG};; z ) TEST_QTD=${OPTARG};; s ) SLEEP_TIMEOUT=${OPTARG};; + m ) MODE=${OPTARG};; esac done @@ -92,6 +92,18 @@ init_func() { "$PWD"/build/ethermintd collect-gentxs --home "$DATA_DIR$i" echo "prepare genesis: Run validate-genesis to ensure everything worked and that the genesis file is setup correctly" "$PWD"/build/ethermintd validate-genesis --home "$DATA_DIR$i" + + if [[ $MODE == "pending" ]]; then + ls $DATA_DIR$i + # sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $DATA_DIR$i/config/config.toml + sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $DATA_DIR$i/config/config.toml + sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "2s"/g' $DATA_DIR$i/config/config.toml + sed -i 's/timeout_prevote = "1s"/timeout_prevote = "120s"/g' $DATA_DIR$i/config/config.toml + sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "2s"/g' $DATA_DIR$i/config/config.toml + sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $DATA_DIR$i/config/config.toml + sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "2s"/g' $DATA_DIR$i/config/config.toml + sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $DATA_DIR$i/config/config.toml + fi } start_func() { @@ -138,12 +150,17 @@ echo "done sleeping" set +e -if [[ -z $TEST || $TEST == "rpc" ]]; then - +if [[ -z $TEST || $TEST == "rpc" || $TEST == "pending" ]]; then + for i in $(seq 1 "$TEST_QTD"); do HOST_RPC=http://$IP_ADDR:$RPC_PORT"$i" echo "going to test ethermint node $HOST_RPC ..." - MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=300s -v -short + if [[ $MODE == "pending" ]]; then + sleep 150 + MODE=$MODE HOST=$HOST_RPC go test -v ./tests-pending/rpc_pending_test.go + else + MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=300s -v -short + fi RPC_FAIL=$? done diff --git a/tests-pending/rpc_pending_test.go b/tests-pending/rpc_pending_test.go index 469fde49e..99ebc81ee 100644 --- a/tests-pending/rpc_pending_test.go +++ b/tests-pending/rpc_pending_test.go @@ -75,8 +75,15 @@ func TestEth_Pending_GetBalance(t *testing.T) { rpcRes := util.Call(t, "eth_getBalance", []string{addrA, "latest"}) err := res.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) - preTxBalance := res.ToInt() - t.Logf("Got balance %s for %s before sending tx\n", preTxBalance, addrA) + preTxLatestBalance := res.ToInt() + + rpcRes = util.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) @@ -91,18 +98,20 @@ func TestEth_Pending_GetBalance(t *testing.T) { rpcRes = util.Call(t, "eth_getBalance", []string{addrA, "pending"}) err = res.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) - t.Logf("Got pending balance %s for %s post tx\n", res.String(), addrA) + postTxPendingBalance := res.ToInt() + t.Logf("Got pending balance %s for %s post tx\n", postTxPendingBalance, addrA) - if res.ToInt().Cmp(preTxBalance.Add(preTxBalance, big.NewInt(10))) != 0 { - t.Errorf("expected balance: %d, got: %s", 10, res.String()) - } + require.Equal(t, preTxPendingBalance.Add(preTxPendingBalance, big.NewInt(10)), postTxPendingBalance) rpcRes = util.Call(t, "eth_getBalance", []string{addrA, "latest"}) err = res.UnmarshalJSON(rpcRes.Result) require.NoError(t, err) - t.Logf("Got latest balance %s for %s post tx\n", res.String(), addrA) + postTxLatestBalance := res.ToInt() + t.Logf("Got latest balance %s for %s post tx\n", postTxLatestBalance, addrA) - if res.ToInt().Cmp(preTxBalance) != 0 { + require.Equal(t, preTxLatestBalance, postTxLatestBalance) + // 1 if x > y; where x is postTxPendingBalance, y is preTxPendingBalance + if postTxLatestBalance.Cmp(preTxPendingBalance) != 0 { t.Errorf("expected balance: %d, got: %s", 0, res.String()) } } @@ -132,6 +141,18 @@ func TestEth_Pending_GetTransactionCount(t *testing.T) { } func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { + rpcRes := util.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 = util.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) + param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) @@ -142,23 +163,35 @@ func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { _ = util.Call(t, "eth_sendTransaction", param) - rpcRes := util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) - var pendingTxCount hexutil.Uint - err := json.Unmarshal(rpcRes.Result, &pendingTxCount) + rpcRes = util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) + var postTxPendingTxCount hexutil.Uint + err = json.Unmarshal(rpcRes.Result, &postTxPendingTxCount) require.NoError(t, err) - t.Logf("Pending nonce is %d", pendingTxCount) + t.Logf("Post tx pending nonce is %d", postTxPendingTxCount) rpcRes = util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"latest"}) - var latestTxCount hexutil.Uint - err = json.Unmarshal(rpcRes.Result, &latestTxCount) + var postTxLatestTxCount hexutil.Uint + err = json.Unmarshal(rpcRes.Result, &postTxLatestTxCount) require.NoError(t, err) - t.Logf("Latest nonce is %d", latestTxCount) + t.Logf("Post tx latest nonce is %d", postTxLatestTxCount) - require.NotEqual(t, uint64(pendingTxCount), uint64(latestTxCount)) - require.Greater(t, uint64(pendingTxCount), uint64(latestTxCount)) + require.Equal(t, uint64(preTxPendingTxCount)+uint64(1), uint64(postTxPendingTxCount)) + require.NotEqual(t, uint64(postTxPendingTxCount)-uint64(preTxPendingTxCount), uint64(postTxLatestTxCount)-uint64(preTxLatestTxCount)) } func TestEth_Pending_GetBlockByNumber(t *testing.T) { + rpcRes := util.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 = util.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) @@ -169,22 +202,21 @@ func TestEth_Pending_GetBlockByNumber(t *testing.T) { _ = util.Call(t, "eth_sendTransaction", param) - rpcRes := util.Call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) - var pendingBlock map[string]interface{} - err := json.Unmarshal(rpcRes.Result, &pendingBlock) + rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) + var postTxPendingBlock map[string]interface{} + err = json.Unmarshal(rpcRes.Result, &postTxPendingBlock) require.NoError(t, err) - pendingBlockArr := len(pendingBlock["transactions"].([]interface{})) - // in case there are other tx's inside the pending queue from prev test - require.NotEqual(t, pendingBlockArr, 0) + postTxPendingTxs := len(postTxPendingBlock["transactions"].([]interface{})) + require.Greater(t, postTxPendingTxs, preTxPendingTxs) rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"latest", true}) - var latestBlock map[string]interface{} - err = json.Unmarshal(rpcRes.Result, &latestBlock) + var postTxLatestBlock map[string]interface{} + err = json.Unmarshal(rpcRes.Result, &postTxLatestBlock) require.NoError(t, err) - latestBlockArr := len(latestBlock["transactions"].([]interface{})) - require.Equal(t, latestBlockArr, 0) + postTxLatestTxs := len(postTxLatestBlock["transactions"].([]interface{})) + require.Equal(t, preTxLatestTxs, postTxLatestTxs) - require.Greater(t, pendingBlockArr, latestBlockArr) + require.Greater(t, postTxPendingTxs, preTxPendingTxs) } func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { @@ -208,15 +240,12 @@ func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { require.Equal(t, pendingBlock["transactionIndex"], nil) require.NotEmpty(t, pendingBlock["hash"]) - rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"latest", true}) + rpcRes = util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"latest", "0x1"}) var latestBlock map[string]interface{} err = json.Unmarshal(rpcRes.Result, &latestBlock) - fmt.Println("latestBlock: ", latestBlock) require.NoError(t, err) - require.NotEmpty(t, latestBlock["timestamp"]) - require.NotEmpty(t, latestBlock["gasUsed"]) - require.Equal(t, latestBlock["logsBloom"], "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + require.Empty(t, latestBlock) } func TestEth_Pending_GetTransactionByHash(t *testing.T) { @@ -239,9 +268,9 @@ func TestEth_Pending_GetTransactionByHash(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, pendingBlock) - require.Equal(t, pendingBlock["blockHash"], nil) - require.Equal(t, pendingBlock["blockNumber"], nil) - require.Equal(t, pendingBlock["transactionIndex"], nil) + require.Equal(t, nil, pendingBlock["blockHash"]) + require.Equal(t, nil, pendingBlock["blockNumber"]) + require.Equal(t, nil, pendingBlock["transactionIndex"]) require.NotEmpty(t, pendingBlock["hash"]) require.NotEmpty(t, pendingBlock["value"], "0xa") } @@ -256,24 +285,22 @@ func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" - t.Logf("currNonce: %d", currNonce) - // first transaction _ = util.Call(t, "eth_sendTransaction", param) pendingNonce1 := util.GetNonce(t, "pending") - require.Greater(t, pendingNonce1, currNonce) + require.Greater(t, uint64(pendingNonce1), uint64(currNonce)) // second transaction param[0]["to"] = "0x7f0f463c4d57b1bd3e3b79051e6c5ab703e803d9" _ = util.Call(t, "eth_sendTransaction", param) pendingNonce2 := util.GetNonce(t, "pending") - require.Greater(t, pendingNonce2, currNonce) - require.Equal(t, pendingNonce1+hexutil.Uint64(1), pendingNonce2) + require.Greater(t, uint64(pendingNonce2), uint64(currNonce)) + require.Greater(t, uint64(pendingNonce2), uint64(pendingNonce1)) // third transaction param[0]["to"] = "0x7fb24493808b3f10527e3e0870afeb8a953052d2" _ = util.Call(t, "eth_sendTransaction", param) pendingNonce3 := util.GetNonce(t, "pending") - require.Greater(t, pendingNonce3, currNonce) - require.Equal(t, pendingNonce1+hexutil.Uint64(2), pendingNonce3) + require.Greater(t, uint64(pendingNonce3), uint64(currNonce)) + require.Greater(t, uint64(pendingNonce3), uint64(pendingNonce2)) } From e5675bf8815b3e3953cedaba66aa80f753f50674 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 18:08:51 -0800 Subject: [PATCH 36/61] move and comment out pending call test --- tests-pending/rpc_pending_test.go | 28 ++++++++++++++++++++++++++++ tests/rpc_test.go | 28 ---------------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests-pending/rpc_pending_test.go b/tests-pending/rpc_pending_test.go index 99ebc81ee..1143231c7 100644 --- a/tests-pending/rpc_pending_test.go +++ b/tests-pending/rpc_pending_test.go @@ -304,3 +304,31 @@ func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { require.Greater(t, uint64(pendingNonce3), uint64(currNonce)) require.Greater(t, uint64(pendingNonce3), uint64(pendingNonce2)) } + +// func TestEth_Call_Pending(t *testing.T) { +// param := make([]map[string]string, 1) +// param[0] = make(map[string]string) +// param[0]["from"] = "0x" + fmt.Sprintf("%x", from) +// param[0]["to"] = "0x0000000000000000000000000000000012341234" +// param[0]["value"] = "0xA" +// param[0]["gasLimit"] = "0x5208" +// param[0]["gasPrice"] = "0x1" + +// rpcRes := util.Call(t, "eth_sendTransaction", param) + +// var hash hexutil.Bytes +// err := json.Unmarshal(rpcRes.Result, &hash) +// require.NoError(t, err) + +// param = make([]map[string]string, 1) +// param[0] = make(map[string]string) +// param[0]["from"] = "0x" + fmt.Sprintf("%x", from) +// param[0]["to"] = "0x0000000000000000000000000000000012341234" +// param[0]["value"] = "0xA" +// param[0]["gasLimit"] = "0x5208" +// param[0]["gasPrice"] = "0x1" + +// rpcRes = util.Call(t, "eth_call", []interface{}{param[0], "pending"}) +// err = json.Unmarshal(rpcRes.Result, &hash) +// require.NoError(t, err) +// } diff --git a/tests/rpc_test.go b/tests/rpc_test.go index be04f80e7..f2c1e7f03 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -565,31 +565,3 @@ func TestEth_GetBlockByNumber(t *testing.T) { require.Equal(t, "0x0", block["extraData"].(string)) require.Equal(t, []interface{}{}, block["uncles"].([]interface{})) } - -func TestEth_Call_Pending(t *testing.T) { - param := make([]map[string]string, 1) - param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) - param[0]["to"] = "0x0000000000000000000000000000000012341234" - param[0]["value"] = "0xA" - param[0]["gasLimit"] = "0x5208" - param[0]["gasPrice"] = "0x1" - - rpcRes := Call(t, "eth_sendTransaction", param) - - var hash hexutil.Bytes - err := json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) - - param = make([]map[string]string, 1) - param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) - param[0]["to"] = "0x0000000000000000000000000000000012341234" - param[0]["value"] = "0xA" - param[0]["gasLimit"] = "0x5208" - param[0]["gasPrice"] = "0x1" - - rpcRes = Call(t, "eth_call", []interface{}{param[0], "pending"}) - err = json.Unmarshal(rpcRes.Result, &hash) - require.NoError(t, err) -} From 7d1ced4ab1dca213eeb37f3eecd0569d0670e413 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 23 Nov 2020 18:34:29 -0800 Subject: [PATCH 37/61] fix some golint --- tests-pending/rpc_pending_test.go | 4 +--- tests/rpc_test.go | 5 +++++ tests/utils.go | 7 ++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests-pending/rpc_pending_test.go b/tests-pending/rpc_pending_test.go index 1143231c7..2752c624d 100644 --- a/tests-pending/rpc_pending_test.go +++ b/tests-pending/rpc_pending_test.go @@ -28,9 +28,7 @@ const ( var ( MODE = os.Getenv("MODE") - - zeroString = "0x0" - from = []byte{} + from = []byte{} ) type Request struct { diff --git a/tests/rpc_test.go b/tests/rpc_test.go index f2c1e7f03..971d28214 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -31,6 +31,11 @@ const ( addrAStoreKey = 0 ) +var ( + from = []byte{} + zeroString = "0x0" +) + func TestMain(m *testing.M) { if MODE != "rpc" { _, _ = fmt.Fprintln(os.Stdout, "Skipping RPC test") diff --git a/tests/utils.go b/tests/utils.go index 7b80786ea..932d10782 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -37,9 +37,6 @@ type Response struct { var ( MODE = os.Getenv("MODE") HOST = os.Getenv("HOST") - - zeroString = "0x0" - from = []byte{} ) func GetAddress() ([]byte, error) { @@ -77,7 +74,7 @@ func Call(t *testing.T, method string, params interface{}) *Response { if HOST == "" { HOST = "http://localhost:8545" } - res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) + res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) //nolint:gosec require.NoError(t, err) decoder := json.NewDecoder(res.Body) @@ -105,7 +102,7 @@ func CallWithError(method string, params interface{}) (*Response, error) { if HOST == "" { HOST = "http://localhost:8545" } - res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) + res, err := http.Post(HOST, "application/json", bytes.NewBuffer(req)) //nolint:gosec if err != nil { return nil, err } From e4ffeae9436e6beb782b149b756349e0bef244e9 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 30 Nov 2020 13:22:34 -0800 Subject: [PATCH 38/61] fix unlock issue --- tests/rpc_test.go | 21 +++++++++-------- tests/utils.go | 58 +++++++++++++++++++++++------------------------ 2 files changed, 40 insertions(+), 39 deletions(-) diff --git a/tests/rpc_test.go b/tests/rpc_test.go index 971d28214..38d8bc857 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -32,6 +32,7 @@ const ( ) var ( + MODE = os.Getenv("MODE") from = []byte{} zeroString = "0x0" ) @@ -55,7 +56,7 @@ func TestMain(m *testing.M) { } func TestBlockBloom(t *testing.T) { - hash := DeployTestContractWithFunction(t) + hash := DeployTestContractWithFunction(t, from) receipt := WaitForReceipt(t, hash) number := receipt["blockNumber"].(string) @@ -102,7 +103,7 @@ func TestEth_GetLogs_Topics_AB(t *testing.T) { param[0]["topics"] = []string{helloTopic, worldTopic} param[0]["fromBlock"] = res.String() - hash := DeployTestContractWithFunction(t) + hash := DeployTestContractWithFunction(t, from) WaitForReceipt(t, hash) rpcRes = Call(t, "eth_getLogs", param) @@ -121,7 +122,7 @@ func TestEth_GetTransactionCount(t *testing.T) { } prev := GetNonce(t, "latest") - SendTestTransaction(t) + SendTestTransaction(t, from) post := GetNonce(t, "latest") require.Equal(t, prev, post-1) } @@ -132,7 +133,7 @@ func TestEth_GetTransactionLogs(t *testing.T) { t.Skip("skipping TestEth_GetTransactionLogs") } - hash, _ := DeployTestContract(t) + hash, _ := DeployTestContract(t, from) param := []string{hash.String()} rpcRes := Call(t, "eth_getTransactionLogs", param) @@ -351,7 +352,7 @@ func TestEth_GetFilterChanges_WrongID(t *testing.T) { } func TestEth_GetTransactionReceipt(t *testing.T) { - hash := SendTestTransaction(t) + hash := SendTestTransaction(t, from) time.Sleep(time.Second * 5) @@ -368,7 +369,7 @@ func TestEth_GetTransactionReceipt(t *testing.T) { } func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) { - hash, _ := DeployTestContract(t) + hash, _ := DeployTestContract(t, from) time.Sleep(time.Second * 5) @@ -405,7 +406,7 @@ func TestEth_GetFilterChanges_NoTopics(t *testing.T) { require.NoError(t, err) // deploy contract, emitting some event - DeployTestContract(t) + DeployTestContract(t, from) // get filter changes changesRes := Call(t, "eth_getFilterChanges", []string{ID}) @@ -453,7 +454,7 @@ func TestEth_GetFilterChanges_Topics_AB(t *testing.T) { err = json.Unmarshal(rpcRes.Result, &ID) require.NoError(t, err, string(rpcRes.Result)) - DeployTestContractWithFunction(t) + DeployTestContractWithFunction(t, from) // get filter changes changesRes := Call(t, "eth_getFilterChanges", []string{ID}) @@ -483,7 +484,7 @@ func TestEth_GetFilterChanges_Topics_XB(t *testing.T) { err = json.Unmarshal(rpcRes.Result, &ID) require.NoError(t, err) - DeployTestContractWithFunction(t) + DeployTestContractWithFunction(t, from) // get filter changes changesRes := Call(t, "eth_getFilterChanges", []string{ID}) @@ -508,7 +509,7 @@ func TestEth_PendingTransactionFilter(t *testing.T) { require.NoError(t, err) for i := 0; i < 5; i++ { - DeployTestContractWithFunction(t) + DeployTestContractWithFunction(t, from) } time.Sleep(10 * time.Second) diff --git a/tests/utils.go b/tests/utils.go index 932d10782..fc8fcd4b3 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/stretchr/testify/require" ) @@ -35,7 +36,6 @@ type Response struct { } var ( - MODE = os.Getenv("MODE") HOST = os.Getenv("HOST") ) @@ -135,44 +135,32 @@ func HexToBigInt(t *testing.T, in string) *big.Int { } // sendTestTransaction sends a dummy transaction -func SendTestTransaction(t *testing.T) hexutil.Bytes { - from, err := GetAddress() - if err != nil { - fmt.Printf("failed to get account: %s\n", err) - os.Exit(1) - } - +func SendTestTransaction(t *testing.T, addr []byte) hexutil.Bytes { param := make([]map[string]string, 1) param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["from"] = "0x" + fmt.Sprintf("%x", addr) param[0]["to"] = "0x1122334455667788990011223344556677889900" param[0]["value"] = "0x1" rpcRes := Call(t, "eth_sendTransaction", param) var hash hexutil.Bytes - err = json.Unmarshal(rpcRes.Result, &hash) + err := json.Unmarshal(rpcRes.Result, &hash) require.NoError(t, err) return hash } // deployTestContract deploys a contract that emits an event in the constructor -func DeployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) { - from, err := GetAddress() - if err != nil { - fmt.Printf("failed to get account: %s\n", err) - os.Exit(1) - } - +func DeployTestContract(t *testing.T, addr []byte) (hexutil.Bytes, map[string]interface{}) { param := make([]map[string]string, 1) param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["from"] = "0x" + fmt.Sprintf("%x", addr) param[0]["data"] = "0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029" param[0]["gas"] = "0x200000" rpcRes := Call(t, "eth_sendTransaction", param) var hash hexutil.Bytes - err = json.Unmarshal(rpcRes.Result, &hash) + err := json.Unmarshal(rpcRes.Result, &hash) require.NoError(t, err) receipt := WaitForReceipt(t, hash) @@ -182,7 +170,7 @@ func DeployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) { return hash, receipt } -func DeployTestContractWithFunction(t *testing.T) hexutil.Bytes { +func DeployTestContractWithFunction(t *testing.T, addr []byte) hexutil.Bytes { // pragma solidity ^0.5.1; // contract Test { @@ -203,22 +191,16 @@ func DeployTestContractWithFunction(t *testing.T) hexutil.Bytes { bytecode := "0x608060405234801561001057600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a260d08061004d6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063eb8ac92114602d575b600080fd5b606060048036036040811015604157600080fd5b8101908080359060200190929190803590602001909291905050506062565b005b8160008190555080827ff3ca124a697ba07e8c5e80bebcfcc48991fc16a63170e8a9206e30508960d00360405160405180910390a3505056fea265627a7a723158201d94d2187aaf3a6790527b615fcc40970febf0385fa6d72a2344848ebd0df3e964736f6c63430005110032" - from, err := GetAddress() - if err != nil { - fmt.Printf("failed to get account: %s\n", err) - os.Exit(1) - } - param := make([]map[string]string, 1) param[0] = make(map[string]string) - param[0]["from"] = "0x" + fmt.Sprintf("%x", from) + param[0]["from"] = "0x" + fmt.Sprintf("%x", addr) param[0]["data"] = bytecode param[0]["gas"] = "0x200000" rpcRes := Call(t, "eth_sendTransaction", param) var hash hexutil.Bytes - err = json.Unmarshal(rpcRes.Result, &hash) + err := json.Unmarshal(rpcRes.Result, &hash) require.NoError(t, err) receipt := WaitForReceipt(t, hash) @@ -229,7 +211,7 @@ func DeployTestContractWithFunction(t *testing.T) hexutil.Bytes { } func GetTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { - param := []string{hash.String()} + param := []string{fmt.Stringer.String(hash)} rpcRes := Call(t, "eth_getTransactionReceipt", param) receipt := make(map[string]interface{}) @@ -267,3 +249,21 @@ func GetNonce(t *testing.T, block string) hexutil.Uint64 { require.NoError(t, err) return nonce } + +func UnlockAllAccounts(t *testing.T) bool { + var accts []common.Address + rpcRes := Call(t, "eth_accounts", []map[string]string{}) + err := json.Unmarshal(rpcRes.Result, &accts) + if err != nil { + return false + } + for _, acct := range accts { + fmt.Println("account: ", acct) + rpcRes = Call(t, "personal_unlockAccount", []interface{}{acct, ""}) + var unlocked bool + err = json.Unmarshal(rpcRes.Result, &unlocked) + require.NoError(t, err) + require.True(t, unlocked) + } + return true +} From c8c34647b2e9a6351dfc1f50229e50301499f928 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 30 Nov 2020 15:24:33 -0800 Subject: [PATCH 39/61] wip: linter stringer fix? --- tests/rpc_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/rpc_test.go b/tests/rpc_test.go index 38d8bc857..4a7a2729a 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -69,7 +69,7 @@ func TestBlockBloom(t *testing.T) { lb := HexToBigInt(t, block["logsBloom"].(string)) require.NotEqual(t, big.NewInt(0), lb) - require.Equal(t, hash.String(), block["transactions"].([]interface{})[0]) + require.Equal(t, fmt.Stringer.String(hash), block["transactions"].([]interface{})[0]) } func TestEth_GetLogs_NoLogs(t *testing.T) { @@ -135,7 +135,7 @@ func TestEth_GetTransactionLogs(t *testing.T) { hash, _ := DeployTestContract(t, from) - param := []string{hash.String()} + param := []string{fmt.Stringer.String(hash)} rpcRes := Call(t, "eth_getTransactionLogs", param) logs := new([]*ethtypes.Log) @@ -356,7 +356,7 @@ func TestEth_GetTransactionReceipt(t *testing.T) { time.Sleep(time.Second * 5) - param := []string{hash.String()} + param := []string{fmt.Stringer.String(hash)} rpcRes := Call(t, "eth_getTransactionReceipt", param) require.Nil(t, rpcRes.Error) @@ -373,7 +373,7 @@ func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) { time.Sleep(time.Second * 5) - param := []string{hash.String()} + param := []string{fmt.Stringer.String(hash)} rpcRes := Call(t, "eth_getTransactionReceipt", param) receipt := make(map[string]interface{}) From 19610d3202d7e863a2f5d18ddd7dac3d16720609 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Mon, 30 Nov 2020 15:38:45 -0800 Subject: [PATCH 40/61] stringer lint --- tests/rpc_test.go | 8 ++++---- tests/utils.go | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/rpc_test.go b/tests/rpc_test.go index 4a7a2729a..38d8bc857 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -69,7 +69,7 @@ func TestBlockBloom(t *testing.T) { lb := HexToBigInt(t, block["logsBloom"].(string)) require.NotEqual(t, big.NewInt(0), lb) - require.Equal(t, fmt.Stringer.String(hash), block["transactions"].([]interface{})[0]) + require.Equal(t, hash.String(), block["transactions"].([]interface{})[0]) } func TestEth_GetLogs_NoLogs(t *testing.T) { @@ -135,7 +135,7 @@ func TestEth_GetTransactionLogs(t *testing.T) { hash, _ := DeployTestContract(t, from) - param := []string{fmt.Stringer.String(hash)} + param := []string{hash.String()} rpcRes := Call(t, "eth_getTransactionLogs", param) logs := new([]*ethtypes.Log) @@ -356,7 +356,7 @@ func TestEth_GetTransactionReceipt(t *testing.T) { time.Sleep(time.Second * 5) - param := []string{fmt.Stringer.String(hash)} + param := []string{hash.String()} rpcRes := Call(t, "eth_getTransactionReceipt", param) require.Nil(t, rpcRes.Error) @@ -373,7 +373,7 @@ func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) { time.Sleep(time.Second * 5) - param := []string{fmt.Stringer.String(hash)} + param := []string{hash.String()} rpcRes := Call(t, "eth_getTransactionReceipt", param) receipt := make(map[string]interface{}) diff --git a/tests/utils.go b/tests/utils.go index fc8fcd4b3..79938aef2 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -210,8 +210,9 @@ func DeployTestContractWithFunction(t *testing.T, addr []byte) hexutil.Bytes { return hash } +//nolint func GetTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { - param := []string{fmt.Stringer.String(hash)} + param := []string{hash.String()} rpcRes := Call(t, "eth_getTransactionReceipt", param) receipt := make(map[string]interface{}) From b5de4783c675d980f9b86527106de4b1522e780c Mon Sep 17 00:00:00 2001 From: araskachoi Date: Wed, 9 Dec 2020 13:08:11 -0800 Subject: [PATCH 41/61] set arr instead of append --- rpc/backend/backend.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index a8b2eae38..f4de48879 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -197,7 +197,7 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error } transactions := make([]*rpctypes.Transaction, 0) - for _, tx := range pendingTxs.Txs { + for i, tx := range pendingTxs.Txs { ethTx, err := rpctypes.RawTxToEthTx(b.clientCtx, tx) if err != nil { // ignore non Ethermint EVM transactions @@ -209,7 +209,7 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error if err != nil { return nil, err } - transactions = append(transactions, rpcTx) + transactions[i] = rpcTx } return transactions, nil } From 139cf966db52d033b66fda14d98df01516e20c91 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Wed, 9 Dec 2020 14:13:25 -0800 Subject: [PATCH 42/61] instantiate with length --- rpc/backend/backend.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index f4de48879..2c78e4603 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -196,7 +196,7 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error return nil, err } - transactions := make([]*rpctypes.Transaction, 0) + transactions := make([]*rpctypes.Transaction, pendingTxs.Count) for i, tx := range pendingTxs.Txs { ethTx, err := rpctypes.RawTxToEthTx(b.clientCtx, tx) if err != nil { From 5bdd6ec1c6a9eeb73b82c19fe905e79e539ed07a Mon Sep 17 00:00:00 2001 From: araskachoi Date: Wed, 9 Dec 2020 14:14:08 -0800 Subject: [PATCH 43/61] sep if statement --- rpc/namespaces/eth/api.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index adea221f6..bc3d3b926 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -257,7 +257,8 @@ func (api *PublicEthereumAPI) GetBalance(address common.Address, blockNum rpctyp if tx.From == address { val = new(big.Int).Sub(val, tx.Value.ToInt()) - } else if *tx.To == address { + } + if *tx.To == address { val = new(big.Int).Add(val, tx.Value.ToInt()) } } From 3aebb8ae0fda45ad8a7db08613cca725f82e9350 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Thu, 10 Dec 2020 11:05:56 -0800 Subject: [PATCH 44/61] edit pendingblocknumber note --- rpc/types/block.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/types/block.go b/rpc/types/block.go index f30fa8596..a6168b43b 100644 --- a/rpc/types/block.go +++ b/rpc/types/block.go @@ -19,7 +19,7 @@ const ( // EarliestBlockNumber mapping from "earliest" to 1 for tm query (earliest query not supported) EarliestBlockNumber = BlockNumber(1) - // PendingBlockNumber mapping from "pending" to 1 for tm query -- repeating 1 for now, TDB + // PendingBlockNumber mapping from "pending" to -1 for tm query PendingBlockNumber = BlockNumber(-1) ) From 621ee71610f3f0631af3c018fcf46883c7b7ac97 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Thu, 10 Dec 2020 11:06:47 -0800 Subject: [PATCH 45/61] switch statement --- rpc/namespaces/eth/api.go | 105 ++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/rpc/namespaces/eth/api.go b/rpc/namespaces/eth/api.go index bc3d3b926..bf626b3a4 100644 --- a/rpc/namespaces/eth/api.go +++ b/rpc/namespaces/eth/api.go @@ -328,33 +328,48 @@ func (api *PublicEthereumAPI) GetBlockTransactionCountByNumber(blockNum rpctypes api.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) var ( - height int64 - err error + height int64 + err error + txCount hexutil.Uint + txs int ) - if blockNum != rpctypes.PendingBlockNumber { - if blockNum == rpctypes.LatestBlockNumber { - height, err = api.backend.LatestBlockNumber() - if err != nil { - return nil - } - } else { - height = blockNum.Int64() + + switch blockNum { + case rpctypes.PendingBlockNumber: + height, err = api.backend.LatestBlockNumber() + if err != nil { + return nil } resBlock, err := api.clientCtx.Client.Block(&height) if err != nil { return nil } - txCount := hexutil.Uint(len(resBlock.Block.Txs)) - return &txCount - } - - // get the pending transaction count - pendingTxs, err := api.backend.PendingTransactions() - if err != nil { - return nil + // get the pending transaction count + pendingTxs, err := api.backend.PendingTransactions() + if err != nil { + return nil + } + txs = len(resBlock.Block.Txs) + len(pendingTxs) + case rpctypes.LatestBlockNumber: + height, err = api.backend.LatestBlockNumber() + if err != nil { + return nil + } + resBlock, err := api.clientCtx.Client.Block(&height) + if err != nil { + return nil + } + txs = len(resBlock.Block.Txs) + default: + height = blockNum.Int64() + resBlock, err := api.clientCtx.Client.Block(&height) + if err != nil { + return nil + } + txs = len(resBlock.Block.Txs) } - txCount := hexutil.Uint(len(pendingTxs)) + txCount = hexutil.Uint(txs) return &txCount } @@ -651,7 +666,8 @@ func (api *PublicEthereumAPI) GetBlockByNumber(blockNum rpctypes.BlockNumber, fu return nil, err } - unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(100) + // number of pending txs queried from the mempool + unconfirmedTxs, err := api.clientCtx.Client.UnconfirmedTxs(1000) if err != nil { return nil, err } @@ -746,37 +762,39 @@ func (api *PublicEthereumAPI) GetTransactionByBlockNumberAndIndex(blockNum rpcty height int64 err error ) - if blockNum != rpctypes.PendingBlockNumber { - if blockNum == rpctypes.LatestBlockNumber { - height, err = api.backend.LatestBlockNumber() - if err != nil { - return nil, err - } - } else { - height = blockNum.Int64() + + switch blockNum { + case rpctypes.PendingBlockNumber: + // get all the EVM pending txs + pendingTxs, err := api.backend.PendingTransactions() + if err != nil { + return nil, err } - resBlock, err := api.clientCtx.Client.Block(&height) + // return if index out of bounds + if uint64(idx) >= uint64(len(pendingTxs)) { + return nil, nil + } + + // change back to pendingTxs[idx] once pending queue is fixed. + return pendingTxs[int(idx)], nil + + case rpctypes.LatestBlockNumber: + height, err = api.backend.LatestBlockNumber() if err != nil { return nil, err } - return api.getTransactionByBlockAndIndex(resBlock.Block, idx) + default: + height = blockNum.Int64() } - // get all the EVM pending txs - pendingTxs, err := api.backend.PendingTransactions() + resBlock, err := api.clientCtx.Client.Block(&height) if err != nil { return nil, err } - // return if index out of bounds - if uint64(idx) >= uint64(len(pendingTxs)) { - return nil, nil - } - - // change back to pendingTxs[idx] once pending queue is fixed. - return pendingTxs[int(idx)], nil + return api.getTransactionByBlockAndIndex(resBlock.Block, idx) } func (api *PublicEthereumAPI) getTransactionByBlockAndIndex(block *tmtypes.Block, idx hexutil.Uint) (*rpctypes.Transaction, error) { @@ -874,7 +892,7 @@ func (api *PublicEthereumAPI) GetTransactionReceipt(hash common.Hash) (map[strin // PendingTransactions returns the transactions that are in the transaction pool // and have a from address that is one of the accounts this node manages. func (api *PublicEthereumAPI) PendingTransactions() ([]*rpctypes.Transaction, error) { - api.logger.Debug("eth_getPendingTransactions") + api.logger.Debug("eth_pendingTransactions") return api.backend.PendingTransactions() } @@ -1027,7 +1045,8 @@ func (api *PublicEthereumAPI) generateFromArgs(args rpctypes.SendTxArgs) (*evmty return &msg, nil } -// pendingMsgs constructs +// pendingMsgs constructs an array of sdk.Msg. This method will check pending transactions and convert +// those transactions into ethermint messages. func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) { // nolint: prealloc var msgs []sdk.Msg @@ -1038,10 +1057,6 @@ func (api *PublicEthereumAPI) pendingMsgs() ([]sdk.Msg, error) { } for _, pendingTx := range pendingTxs { - if pendingTx == nil { - continue - } - // NOTE: we have to construct the EVM transaction instead of just casting from the tendermint // transactions because PendingTransactions only checks for MsgEthereumTx messages. From cd67495909bafe53de85693101682c3b3ba9156b Mon Sep 17 00:00:00 2001 From: araskachoi Date: Thu, 10 Dec 2020 11:30:50 -0800 Subject: [PATCH 46/61] fix and update tests --- tests-pending/rpc_pending_test.go | 35 ++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/tests-pending/rpc_pending_test.go b/tests-pending/rpc_pending_test.go index 2752c624d..9b02fbe80 100644 --- a/tests-pending/rpc_pending_test.go +++ b/tests-pending/rpc_pending_test.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + rpctypes "github.com/cosmos/ethermint/rpc/types" util "github.com/cosmos/ethermint/tests" ) @@ -115,6 +116,9 @@ func TestEth_Pending_GetBalance(t *testing.T) { } func TestEth_Pending_GetTransactionCount(t *testing.T) { + prePendingNonce := util.GetNonce(t, "pending") + t.Logf("Pending nonce before tx is %d", prePendingNonce) + currentNonce := util.GetNonce(t, "latest") t.Logf("Current nonce is %d", currentNonce) @@ -136,6 +140,7 @@ func TestEth_Pending_GetTransactionCount(t *testing.T) { require.NotEqual(t, latestNonce, pendingNonce) require.Greater(t, uint64(pendingNonce), uint64(latestNonce)) + require.Equal(t, uint64(prePendingNonce)+uint64(1), uint64(pendingNonce)) } func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { @@ -218,6 +223,13 @@ func TestEth_Pending_GetBlockByNumber(t *testing.T) { } func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { + var pendingTx []*rpctypes.Transaction + resPendingTxs := util.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) @@ -225,28 +237,31 @@ func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { param[0]["value"] = "0xA" param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" + param[0]["data"] = data _ = util.Call(t, "eth_sendTransaction", param) - rpcRes := util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x1"}) + rpcRes := util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x" + fmt.Sprintf("%X", pendingTxCount)}) var pendingBlock map[string]interface{} - err := json.Unmarshal(rpcRes.Result, &pendingBlock) + err = json.Unmarshal(rpcRes.Result, &pendingBlock) require.NoError(t, err) - require.Equal(t, pendingBlock["blockHash"], nil) - require.Equal(t, pendingBlock["blockNumber"], nil) - require.Equal(t, pendingBlock["transactionIndex"], nil) + // verify the pending tx has all the correct fields from the tx sent. require.NotEmpty(t, pendingBlock["hash"]) + require.Equal(t, pendingBlock["value"], "0xa") + require.Equal(t, data, pendingBlock["input"]) - rpcRes = util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"latest", "0x1"}) + rpcRes = util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"latest", "0x" + fmt.Sprintf("%X", pendingTxCount)}) var latestBlock map[string]interface{} err = json.Unmarshal(rpcRes.Result, &latestBlock) require.NoError(t, err) + // verify the pending trasnaction does not exist in the latest block info. require.Empty(t, latestBlock) } func TestEth_Pending_GetTransactionByHash(t *testing.T) { + data := "0x608060405234801561001057600080fd5b5061011e806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806302eb691b14602d575b600080fd5b603360ab565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101560715780820151818401526020810190506058565b50505050905090810190601f168015609d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60606040518060400160405280600d81526020017f617261736b61776173686572650000000000000000000000000000000000000081525090509056fea264697066735822122060917c5c2fab8c058a17afa6d3c1d23a7883b918ea3c7157131ea5b396e1aa7564736f6c63430007050033" param := make([]map[string]string, 1) param[0] = make(map[string]string) param[0]["from"] = "0x" + fmt.Sprintf("%x", from) @@ -254,6 +269,7 @@ func TestEth_Pending_GetTransactionByHash(t *testing.T) { param[0]["value"] = "0xA" param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" + param[0]["data"] = data txRes := util.Call(t, "eth_sendTransaction", param) var txHash common.Hash @@ -265,12 +281,11 @@ func TestEth_Pending_GetTransactionByHash(t *testing.T) { err = json.Unmarshal(rpcRes.Result, &pendingBlock) require.NoError(t, err) + // verify the pending tx has all the correct fields from the tx sent. require.NotEmpty(t, pendingBlock) - require.Equal(t, nil, pendingBlock["blockHash"]) - require.Equal(t, nil, pendingBlock["blockNumber"]) - require.Equal(t, nil, pendingBlock["transactionIndex"]) require.NotEmpty(t, pendingBlock["hash"]) - require.NotEmpty(t, pendingBlock["value"], "0xa") + require.Equal(t, pendingBlock["value"], "0xa") + require.Equal(t, pendingBlock["input"], data) } func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { From a144b52e6a07adaed82ea9bdc3993902d9b570b2 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Thu, 10 Dec 2020 11:59:33 -0800 Subject: [PATCH 47/61] move tests-pending into tests dir --- scripts/integration-test-all.sh | 2 +- {tests-pending => tests/tests-pending}/rpc_pending_test.go | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {tests-pending => tests/tests-pending}/rpc_pending_test.go (100%) diff --git a/scripts/integration-test-all.sh b/scripts/integration-test-all.sh index b556f8659..c148ab545 100755 --- a/scripts/integration-test-all.sh +++ b/scripts/integration-test-all.sh @@ -157,7 +157,7 @@ if [[ -z $TEST || $TEST == "rpc" || $TEST == "pending" ]]; then echo "going to test ethermint node $HOST_RPC ..." if [[ $MODE == "pending" ]]; then sleep 150 - MODE=$MODE HOST=$HOST_RPC go test -v ./tests-pending/rpc_pending_test.go + MODE=$MODE HOST=$HOST_RPC go test -v ./tests/tests-pending/rpc_pending_test.go else MODE=$MODE HOST=$HOST_RPC go test ./tests/... -timeout=300s -v -short fi diff --git a/tests-pending/rpc_pending_test.go b/tests/tests-pending/rpc_pending_test.go similarity index 100% rename from tests-pending/rpc_pending_test.go rename to tests/tests-pending/rpc_pending_test.go From 555d056a34c6ccc515b776d6d05ad0960ecf03c1 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 10:31:54 -0800 Subject: [PATCH 48/61] remove commented test --- tests/tests-pending/rpc_pending_test.go | 28 ------------------------- 1 file changed, 28 deletions(-) diff --git a/tests/tests-pending/rpc_pending_test.go b/tests/tests-pending/rpc_pending_test.go index 9b02fbe80..25a738523 100644 --- a/tests/tests-pending/rpc_pending_test.go +++ b/tests/tests-pending/rpc_pending_test.go @@ -317,31 +317,3 @@ func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { require.Greater(t, uint64(pendingNonce3), uint64(currNonce)) require.Greater(t, uint64(pendingNonce3), uint64(pendingNonce2)) } - -// func TestEth_Call_Pending(t *testing.T) { -// param := make([]map[string]string, 1) -// param[0] = make(map[string]string) -// param[0]["from"] = "0x" + fmt.Sprintf("%x", from) -// param[0]["to"] = "0x0000000000000000000000000000000012341234" -// param[0]["value"] = "0xA" -// param[0]["gasLimit"] = "0x5208" -// param[0]["gasPrice"] = "0x1" - -// rpcRes := util.Call(t, "eth_sendTransaction", param) - -// var hash hexutil.Bytes -// err := json.Unmarshal(rpcRes.Result, &hash) -// require.NoError(t, err) - -// param = make([]map[string]string, 1) -// param[0] = make(map[string]string) -// param[0]["from"] = "0x" + fmt.Sprintf("%x", from) -// param[0]["to"] = "0x0000000000000000000000000000000012341234" -// param[0]["value"] = "0xA" -// param[0]["gasLimit"] = "0x5208" -// param[0]["gasPrice"] = "0x1" - -// rpcRes = util.Call(t, "eth_call", []interface{}{param[0], "pending"}) -// err = json.Unmarshal(rpcRes.Result, &hash) -// require.NoError(t, err) -// } From 66ba65843b36498d1c4a4062c1dd86c4f7521943 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 10:32:21 -0800 Subject: [PATCH 49/61] revert to appending pendingtx --- rpc/backend/backend.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 2c78e4603..a8b2eae38 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -196,8 +196,8 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error return nil, err } - transactions := make([]*rpctypes.Transaction, pendingTxs.Count) - for i, tx := range pendingTxs.Txs { + transactions := make([]*rpctypes.Transaction, 0) + for _, tx := range pendingTxs.Txs { ethTx, err := rpctypes.RawTxToEthTx(b.clientCtx, tx) if err != nil { // ignore non Ethermint EVM transactions @@ -209,7 +209,7 @@ func (b *EthermintBackend) PendingTransactions() ([]*rpctypes.Transaction, error if err != nil { return nil, err } - transactions[i] = rpcTx + transactions = append(transactions, rpcTx) } return transactions, nil } From 2ffad823eaac1ee759edbac3259e159e06029b39 Mon Sep 17 00:00:00 2001 From: Daniel Choi Date: Tue, 15 Dec 2020 10:35:10 -0800 Subject: [PATCH 50/61] Update tests/utils.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- tests/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils.go b/tests/utils.go index 79938aef2..750602c39 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -251,7 +251,7 @@ func GetNonce(t *testing.T, block string) hexutil.Uint64 { return nonce } -func UnlockAllAccounts(t *testing.T) bool { +func UnlockAllAccounts(t *testing.T) { var accts []common.Address rpcRes := Call(t, "eth_accounts", []map[string]string{}) err := json.Unmarshal(rpcRes.Result, &accts) From 6180a111dbb95af3aff8e75b1861a95d247dd6aa Mon Sep 17 00:00:00 2001 From: Daniel Choi Date: Tue, 15 Dec 2020 10:35:34 -0800 Subject: [PATCH 51/61] Update tests/utils.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- tests/utils.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/utils.go b/tests/utils.go index 750602c39..2a949e023 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -255,9 +255,8 @@ func UnlockAllAccounts(t *testing.T) { var accts []common.Address rpcRes := Call(t, "eth_accounts", []map[string]string{}) err := json.Unmarshal(rpcRes.Result, &accts) - if err != nil { - return false - } + require.NoError(t, err) + for _, acct := range accts { fmt.Println("account: ", acct) rpcRes = Call(t, "personal_unlockAccount", []interface{}{acct, ""}) From a664c65db892530ba11ac80704f3ec179ff07d75 Mon Sep 17 00:00:00 2001 From: Daniel Choi Date: Tue, 15 Dec 2020 10:35:43 -0800 Subject: [PATCH 52/61] Update tests/utils.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- tests/utils.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/utils.go b/tests/utils.go index 2a949e023..1f771866c 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -265,5 +265,4 @@ func UnlockAllAccounts(t *testing.T) { require.NoError(t, err) require.True(t, unlocked) } - return true } From c237e5990f3e99ce2bbab9fbec85b27b76638b80 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 10:38:45 -0800 Subject: [PATCH 53/61] require no err --- tests/utils.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/utils.go b/tests/utils.go index 1f771866c..3c49ba67a 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -237,10 +237,7 @@ func WaitForReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { func GetNonce(t *testing.T, block string) hexutil.Uint64 { from, err := GetAddress() - if err != nil { - fmt.Printf("failed to get account: %s\n", err) - os.Exit(1) - } + require.NoError(t, err) param := []interface{}{hexutil.Bytes(from), block} rpcRes := Call(t, "eth_getTransactionCount", param) From 6fb1f71f3140dca74b4beeeaa3827fe6f195cf39 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 10:51:59 -0800 Subject: [PATCH 54/61] rename var --- tests/tests-pending/rpc_pending_test.go | 26 +++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/tests-pending/rpc_pending_test.go b/tests/tests-pending/rpc_pending_test.go index 25a738523..d0dfc18bf 100644 --- a/tests/tests-pending/rpc_pending_test.go +++ b/tests/tests-pending/rpc_pending_test.go @@ -130,7 +130,9 @@ func TestEth_Pending_GetTransactionCount(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" - _ = util.Call(t, "eth_sendTransaction", param) + txRes := util.Call(t, "eth_sendTransaction", param) + fmt.Println("txRes: ", txRes) + fmt.Println("txRes.err: ", txRes.Error) pendingNonce := util.GetNonce(t, "pending") latestNonce := util.GetNonce(t, "latest") @@ -242,14 +244,14 @@ func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { _ = util.Call(t, "eth_sendTransaction", param) rpcRes := util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x" + fmt.Sprintf("%X", pendingTxCount)}) - var pendingBlock map[string]interface{} - err = json.Unmarshal(rpcRes.Result, &pendingBlock) + var pendingBlockTx map[string]interface{} + err = json.Unmarshal(rpcRes.Result, &pendingBlockTx) require.NoError(t, err) // verify the pending tx has all the correct fields from the tx sent. - require.NotEmpty(t, pendingBlock["hash"]) - require.Equal(t, pendingBlock["value"], "0xa") - require.Equal(t, data, pendingBlock["input"]) + require.NotEmpty(t, pendingBlockTx["hash"]) + require.Equal(t, pendingBlockTx["value"], "0xa") + require.Equal(t, data, pendingBlockTx["input"]) rpcRes = util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"latest", "0x" + fmt.Sprintf("%X", pendingTxCount)}) var latestBlock map[string]interface{} @@ -277,15 +279,15 @@ func TestEth_Pending_GetTransactionByHash(t *testing.T) { require.NoError(t, err) rpcRes := util.Call(t, "eth_getTransactionByHash", []interface{}{txHash}) - var pendingBlock map[string]interface{} - err = json.Unmarshal(rpcRes.Result, &pendingBlock) + var pendingBlockTx map[string]interface{} + err = json.Unmarshal(rpcRes.Result, &pendingBlockTx) require.NoError(t, err) // verify the pending tx has all the correct fields from the tx sent. - require.NotEmpty(t, pendingBlock) - require.NotEmpty(t, pendingBlock["hash"]) - require.Equal(t, pendingBlock["value"], "0xa") - require.Equal(t, pendingBlock["input"], data) + require.NotEmpty(t, pendingBlockTx) + require.NotEmpty(t, pendingBlockTx["hash"]) + require.Equal(t, pendingBlockTx["value"], "0xa") + require.Equal(t, pendingBlockTx["input"], data) } func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { From ad91a12fe4853ab49205703b13104c59b0125fbd Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 11:07:20 -0800 Subject: [PATCH 55/61] check result for eth_sendTransaction --- tests/tests-pending/rpc_pending_test.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/tests-pending/rpc_pending_test.go b/tests/tests-pending/rpc_pending_test.go index d0dfc18bf..b8ea81975 100644 --- a/tests/tests-pending/rpc_pending_test.go +++ b/tests/tests-pending/rpc_pending_test.go @@ -131,8 +131,7 @@ func TestEth_Pending_GetTransactionCount(t *testing.T) { param[0]["gasPrice"] = "0x1" txRes := util.Call(t, "eth_sendTransaction", param) - fmt.Println("txRes: ", txRes) - fmt.Println("txRes.err: ", txRes.Error) + require.Nil(t, txRes.Error) pendingNonce := util.GetNonce(t, "pending") latestNonce := util.GetNonce(t, "latest") @@ -166,7 +165,8 @@ func TestEth_Pending_GetBlockTransactionCountByNumber(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" - _ = util.Call(t, "eth_sendTransaction", param) + txRes := util.Call(t, "eth_sendTransaction", param) + require.Nil(t, txRes.Error) rpcRes = util.Call(t, "eth_getBlockTransactionCountByNumber", []interface{}{"pending"}) var postTxPendingTxCount hexutil.Uint @@ -205,7 +205,8 @@ func TestEth_Pending_GetBlockByNumber(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" - _ = util.Call(t, "eth_sendTransaction", param) + txRes := util.Call(t, "eth_sendTransaction", param) + require.Nil(t, txRes.Error) rpcRes = util.Call(t, "eth_getBlockByNumber", []interface{}{"pending", true}) var postTxPendingBlock map[string]interface{} @@ -241,7 +242,8 @@ func TestEth_Pending_GetTransactionByBlockNumberAndIndex(t *testing.T) { param[0]["gasPrice"] = "0x1" param[0]["data"] = data - _ = util.Call(t, "eth_sendTransaction", param) + txRes := util.Call(t, "eth_sendTransaction", param) + require.Nil(t, txRes.Error) rpcRes := util.Call(t, "eth_getTransactionByBlockNumberAndIndex", []interface{}{"pending", "0x" + fmt.Sprintf("%X", pendingTxCount)}) var pendingBlockTx map[string]interface{} @@ -301,20 +303,23 @@ func TestEth_Pending_SendTransaction_PendingNonce(t *testing.T) { param[0]["gasPrice"] = "0x1" // first transaction - _ = util.Call(t, "eth_sendTransaction", param) + txRes1 := util.Call(t, "eth_sendTransaction", param) + require.Nil(t, txRes1.Error) pendingNonce1 := util.GetNonce(t, "pending") require.Greater(t, uint64(pendingNonce1), uint64(currNonce)) // second transaction param[0]["to"] = "0x7f0f463c4d57b1bd3e3b79051e6c5ab703e803d9" - _ = util.Call(t, "eth_sendTransaction", param) + txRes2 := util.Call(t, "eth_sendTransaction", param) + require.Nil(t, txRes2.Error) pendingNonce2 := util.GetNonce(t, "pending") require.Greater(t, uint64(pendingNonce2), uint64(currNonce)) require.Greater(t, uint64(pendingNonce2), uint64(pendingNonce1)) // third transaction param[0]["to"] = "0x7fb24493808b3f10527e3e0870afeb8a953052d2" - _ = util.Call(t, "eth_sendTransaction", param) + txRes3 := util.Call(t, "eth_sendTransaction", param) + require.Nil(t, txRes3.Error) pendingNonce3 := util.GetNonce(t, "pending") require.Greater(t, uint64(pendingNonce3), uint64(currNonce)) require.Greater(t, uint64(pendingNonce3), uint64(pendingNonce2)) From 4adb1f3577fb9155c1086f660fa616df95450522 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 11:19:02 -0800 Subject: [PATCH 56/61] update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63505b772..d16f0a129 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -169,6 +169,15 @@ corresponding Ethereum API namespace: * `eth_getLogs` and `eth_getFilterChanges` for log filters use the same underlying method as `eth_getFilterLogs` * update `HandleMsgEthereumTx` to store logs using the ethereum hash * (app) [\#187](https://github.com/cosmos/ethermint/issues/187) Add support for simulations. +* (rpc) [\#571](https://github.com/cosmos/ethermint/pull/571) Add pending queries to rpc calls. This allows for the querying of pending transactions and other relevant information that pertains to the pending state. + * `eth_getBalance` + * `eth_getTransactionCount` + * `eth_getBlockTransactionCountByNumber` + * `eth_getBlockByNumber` + * `eth_getTransactionByHash` + * `eth_getTransactionByBlockNumberAndIndex` + * `eth_sendTransaction` - the nonce will automatically update to its pending nonce (when none is explicitly provided) + ### Bug Fixes From 2cb7f48ac8994605776750d1f47076feb01942b6 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 11:36:06 -0800 Subject: [PATCH 57/61] update --- CHANGELOG.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b7ce6fe4..aa6699206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,15 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased +* (rpc) [\#571](https://github.com/cosmos/ethermint/pull/571) Add pending queries to rpc calls. This allows for the querying of pending transactions and other relevant information that pertains to the pending state. + * `eth_getBalance` + * `eth_getTransactionCount` + * `eth_getBlockTransactionCountByNumber` + * `eth_getBlockByNumber` + * `eth_getTransactionByHash` + * `eth_getTransactionByBlockNumberAndIndex` + * `eth_sendTransaction` - the nonce will automatically update to its pending nonce (when none is explicitly provided) + ### API Breaking * (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`. @@ -176,15 +185,6 @@ corresponding Ethereum API namespace: * `eth_getLogs` and `eth_getFilterChanges` for log filters use the same underlying method as `eth_getFilterLogs` * update `HandleMsgEthereumTx` to store logs using the ethereum hash * (app) [\#187](https://github.com/cosmos/ethermint/issues/187) Add support for simulations. -* (rpc) [\#571](https://github.com/cosmos/ethermint/pull/571) Add pending queries to rpc calls. This allows for the querying of pending transactions and other relevant information that pertains to the pending state. - * `eth_getBalance` - * `eth_getTransactionCount` - * `eth_getBlockTransactionCountByNumber` - * `eth_getBlockByNumber` - * `eth_getTransactionByHash` - * `eth_getTransactionByBlockNumberAndIndex` - * `eth_sendTransaction` - the nonce will automatically update to its pending nonce (when none is explicitly provided) - ### Bug Fixes From 0c5dd2e0c8088c036d40ed37bc69a8a6be1acf64 Mon Sep 17 00:00:00 2001 From: Daniel Choi Date: Tue, 15 Dec 2020 11:43:36 -0800 Subject: [PATCH 58/61] Update tests/utils.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- tests/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils.go b/tests/utils.go index 3c49ba67a..fc459be1d 100644 --- a/tests/utils.go +++ b/tests/utils.go @@ -255,7 +255,7 @@ func UnlockAllAccounts(t *testing.T) { require.NoError(t, err) for _, acct := range accts { - fmt.Println("account: ", acct) + t.Logf("account: %v", acct) rpcRes = Call(t, "personal_unlockAccount", []interface{}{acct, ""}) var unlocked bool err = json.Unmarshal(rpcRes.Result, &unlocked) From 2eae733826985777504e14d8cac38c8822376437 Mon Sep 17 00:00:00 2001 From: Daniel Choi Date: Tue, 15 Dec 2020 11:43:46 -0800 Subject: [PATCH 59/61] Update tests/tests-pending/rpc_pending_test.go Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> --- tests/tests-pending/rpc_pending_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/tests-pending/rpc_pending_test.go b/tests/tests-pending/rpc_pending_test.go index b8ea81975..e5f9ba650 100644 --- a/tests/tests-pending/rpc_pending_test.go +++ b/tests/tests-pending/rpc_pending_test.go @@ -92,7 +92,8 @@ func TestEth_Pending_GetBalance(t *testing.T) { param[0]["gasLimit"] = "0x5208" param[0]["gasPrice"] = "0x1" - _ = util.Call(t, "eth_sendTransaction", param) + rpcRes = util.Call(t, "eth_sendTransaction", param) + require.Nil(t, rpcRes.Error) rpcRes = util.Call(t, "eth_getBalance", []string{addrA, "pending"}) err = res.UnmarshalJSON(rpcRes.Result) From 87383986452241dfbe6c857a30e4c0b15d852c33 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 15 Dec 2020 16:44:39 -0300 Subject: [PATCH 60/61] changelog --- CHANGELOG.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa6699206..81ea1bbff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,13 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## Unreleased -* (rpc) [\#571](https://github.com/cosmos/ethermint/pull/571) Add pending queries to rpc calls. This allows for the querying of pending transactions and other relevant information that pertains to the pending state. +### API Breaking + +* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`. + +### Features + +* (rpc) [\#571](https://github.com/cosmos/ethermint/pull/571) Add pending queries to JSON-RPC calls. This allows for the querying of pending transactions and other relevant information that pertains to the pending state: * `eth_getBalance` * `eth_getTransactionCount` * `eth_getBlockTransactionCountByNumber` @@ -46,10 +52,6 @@ Ref: https://keepachangelog.com/en/1.0.0/ * `eth_getTransactionByBlockNumberAndIndex` * `eth_sendTransaction` - the nonce will automatically update to its pending nonce (when none is explicitly provided) -### API Breaking - -* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`. - ### Improvements * (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) Add invariant check for account balance and account nonce. From ab9093ee22161fe44cc05e62028946f3d3f36291 Mon Sep 17 00:00:00 2001 From: araskachoi Date: Tue, 15 Dec 2020 11:45:01 -0800 Subject: [PATCH 61/61] remove redundant check --- tests/tests-pending/rpc_pending_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/tests-pending/rpc_pending_test.go b/tests/tests-pending/rpc_pending_test.go index e5f9ba650..a7679dc6f 100644 --- a/tests/tests-pending/rpc_pending_test.go +++ b/tests/tests-pending/rpc_pending_test.go @@ -110,10 +110,6 @@ func TestEth_Pending_GetBalance(t *testing.T) { t.Logf("Got latest balance %s for %s post tx\n", postTxLatestBalance, addrA) require.Equal(t, preTxLatestBalance, postTxLatestBalance) - // 1 if x > y; where x is postTxPendingBalance, y is preTxPendingBalance - if postTxLatestBalance.Cmp(preTxPendingBalance) != 0 { - t.Errorf("expected balance: %d, got: %s", 0, res.String()) - } } func TestEth_Pending_GetTransactionCount(t *testing.T) {