Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

fix(rpc): align query result of future block for eth_getTransactionCount #1638

Merged
merged 12 commits into from
Jan 27, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (rpc) [#1613](https://github.com/evmos/ethermint/pull/1613) Change the default json-rpc listen address to localhost.
* (rpc) [#1611](https://github.com/evmos/ethermint/pull/1611) Add missing next fee in fee history, fix wrong oldestBlock and align earliest input as ethereum.
* (proto) [#1586](https://github.com/evmos/ethermint/pull/1586) Avoid duplicate register proto type in `evm` & `feemarket`
* (rpc) [#1638](https://github.com/evmos/ethermint/pull/1638) Align results when querying `eth_getTransactionCount` for future blocks for accounts with zero and non-zero transaction counts.
* (rpc) [#1639](https://github.com/evmos/ethermint/pull/1639) Align block number input behaviour for `eth_getProof` as Ethereum.

## [v0.20.0] - 2022-12-28
Expand Down
33 changes: 15 additions & 18 deletions gomod2nix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ schema = 3
version = "v0.0.0-20140422174119-9fd32a8b3d3d"
hash = "sha256-NDxQzO5C5M/aDz5/pjUHfZUh4VwIXovbb3irtxWCwjY="
[mod."github.com/bgentry/speakeasy"]
version = "v0.1.0"
hash = "sha256-Gt1vj6CFovLnO6wX5u2O4UfecY9V2J9WGw1ez4HMrgk="
version = "v0.1.1-0.20220910012023-760eaf8b6816"
hash = "sha256-Tx3sPuhsoVwrCfJdIwf4ipn7pD92OQNYvpCxl1Z9Wt0="
[mod."github.com/btcsuite/btcd"]
version = "v0.22.1"
hash = "sha256-hBU+roIELcmbW2Gz7eGZzL9qNA1bakq5wNxqCgs4TKc="
version = "v0.22.2"
hash = "sha256-TPX7GIArd+bwOdwgPnkHyptpEVGhpkqiAydsO4srOCQ="
[mod."github.com/btcsuite/btcd/btcec/v2"]
version = "v2.3.2"
hash = "sha256-natWs+yIAuD1UI07iZtjPilroQLfXizFn3lNOiOT83U="
Expand Down Expand Up @@ -96,8 +96,8 @@ schema = 3
version = "v1.0.0-beta.1"
hash = "sha256-oATkuj+fM5eBn+ywO+w/tL0AFSIEkx0J3Yz+VhVe0QA="
[mod."github.com/cosmos/cosmos-sdk"]
version = "v0.46.7"
hash = "sha256-54DCF8lrnA1oUmBJlbUlWXOP5UbenRInUROn5P5I9qI="
version = "v0.46.8"
hash = "sha256-jETbixsZq5XJ1pl1XaVJvD5jkcygBrEcHRK/L0+XI68="
[mod."github.com/cosmos/go-bip39"]
version = "v1.0.0"
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
Expand All @@ -114,8 +114,8 @@ schema = 3
version = "v6.1.0"
hash = "sha256-mHYCqLedcveDjfm1EiO2EMMNJqLm9u4WHwQTy1muOoc="
[mod."github.com/cosmos/ledger-cosmos-go"]
version = "v0.12.1"
hash = "sha256-9+nr+/r4MyiogddS0JcXOuriPqXP4nxln8ts+mYQRcg="
version = "v0.12.2"
hash = "sha256-fLkveUWxn0nZzvgsY0KTU/T1TUUQ8Ap6XTYSnJs6XXo="
[mod."github.com/creachadair/taskgroup"]
version = "v0.3.2"
hash = "sha256-Y261IO/d9xjV0UScqHvo31broxvnKn4IQQC9Mu6jNkE="
Expand Down Expand Up @@ -361,8 +361,8 @@ schema = 3
version = "v2.7.0"
hash = "sha256-BKqQKCsPA73FaQwYpAY+QsWFHIncrG5jgRhC2IiNmCk="
[mod."github.com/onsi/gomega"]
version = "v1.25.0"
hash = "sha256-knaJppfBzKSMD4Gsqzx22SGrti7G5UyDBYrothAqsrs="
version = "v1.26.0"
hash = "sha256-B18jsoJHK/oE+wudT0dOsUb41s5+ZIAu/ZBzQ5djOLE="
[mod."github.com/pelletier/go-toml/v2"]
version = "v2.0.6"
hash = "sha256-BxAeApnn5H+OLlH3TXGvIbtC6LmbRnjwbcfT1qMZ4PE="
Expand Down Expand Up @@ -447,12 +447,6 @@ schema = 3
[mod."github.com/syndtr/goleveldb"]
version = "v1.0.1-0.20210819022825-2ae1ddf74ef7"
hash = "sha256-36a4hgVQfwtS2zhylKpQuFhrjdc/Y8pF0dxc26jcZIU="
[mod."github.com/tendermint/btcd"]
version = "v0.1.1"
hash = "sha256-QQl2GWZaKQtd+LQrgx2unkTLI1qye57fCWwJcmCXT/0="
[mod."github.com/tendermint/crypto"]
version = "v0.0.0-20191022145703-50d29ede1e15"
hash = "sha256-NkoZ3hKWZt5Hca49I+1g81x1m6aQGELZ/QGLdb3uHm4="
[mod."github.com/tendermint/go-amino"]
version = "v0.16.0"
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
Expand All @@ -462,6 +456,9 @@ schema = 3
[mod."github.com/tendermint/tm-db"]
version = "v0.6.7"
hash = "sha256-hl/3RrBrpkk2zA6dmrNlIYKs1/GfqegSscDSkA5Pjlo="
[mod."github.com/tidwall/btree"]
version = "v1.5.0"
hash = "sha256-iWll4/+ADLVse3VAHxXYLprILugX/+3u0ZIk0YlLv/Q="
[mod."github.com/tklauser/go-sysconf"]
version = "v0.3.10"
hash = "sha256-Zf2NsgM9+HeM949vCce4HQtSbfUiFpeiQ716yKcFyx4="
Expand All @@ -478,8 +475,8 @@ schema = 3
version = "v0.9.1"
hash = "sha256-hSVmN/f/lQHFhF60o6ej78ELC0MMoqQgqIX2hHjdTXg="
[mod."github.com/zondax/ledger-go"]
version = "v0.14.0"
hash = "sha256-RozTPSNs4RerZ4DQMBcGmvREjoRtH1G69xjhccYjIOk="
version = "v0.14.1"
hash = "sha256-iQmShSaty50yYTbYPNd4fnOyrcEG7P2fWmj+fLJQW4s="
[mod."go.etcd.io/bbolt"]
version = "v1.3.6"
hash = "sha256-DenVAmyN22xUiivk6fdJp4C9ZnUJXCMDUf8E0goRRV4="
Expand Down
20 changes: 17 additions & 3 deletions rpc/backend/account_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -187,14 +188,27 @@ func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.Bloc

// GetTransactionCount returns the number of transactions at the given address up to the given block number.
func (b *Backend) GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error) {
n := hexutil.Uint64(0)
bn, err := b.BlockNumber()
if err != nil {
return &n, err
}
height := blockNum.Int64()
currentHeight := int64(bn)
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed

Check failure

Code scanning / gosec

Potential integer overflow by integer type conversion

Potential integer overflow by integer type conversion

Check failure

Code scanning / gosec

Potential integer overflow by integer type conversion

Potential integer overflow by integer type conversion
if height > currentHeight {
return &n, sdkerrors.Wrapf(
sdkerrors.ErrInvalidHeight,
"cannot query with height in the future (current: %d, queried: %d); please provide a valid height",
currentHeight, height,
)
}
// Get nonce (sequence) from account
from := sdk.AccAddress(address.Bytes())
accRet := b.clientCtx.AccountRetriever

err := accRet.EnsureExists(b.clientCtx, from)
err = accRet.EnsureExists(b.clientCtx, from)
if err != nil {
// account doesn't exist yet, return 0
n := hexutil.Uint64(0)
return &n, nil
}

Expand All @@ -204,6 +218,6 @@ func (b *Backend) GetTransactionCount(address common.Address, blockNum rpctypes.
return nil, err
}

n := hexutil.Uint64(nonce)
n = hexutil.Uint64(nonce)
return &n, nil
}
7 changes: 6 additions & 1 deletion rpc/backend/account_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
"google.golang.org/grpc/metadata"

"github.com/evmos/ethermint/rpc/backend/mocks"
rpctypes "github.com/evmos/ethermint/rpc/types"
Expand Down Expand Up @@ -359,7 +360,11 @@ func (suite *BackendTestSuite) TestGetTransactionCount() {
"pass - account doesn't exist",
false,
rpctypes.NewBlockNumber(big.NewInt(1)),
func(addr common.Address, bn rpctypes.BlockNumber) {},
func(addr common.Address, bn rpctypes.BlockNumber) {
var header metadata.MD
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterParams(queryClient, &header, 1)
},
true,
hexutil.Uint64(0),
},
Expand Down
3 changes: 3 additions & 0 deletions rpc/backend/node_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
ethermint "github.com/evmos/ethermint/types"
"github.com/spf13/viper"
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
"google.golang.org/grpc/metadata"
)

func (suite *BackendTestSuite) TestRPCMinGasPrice() {
Expand Down Expand Up @@ -247,10 +248,12 @@ func (suite *BackendTestSuite) TestSetEtherbase() {
{
"fail - error querying for account ",
func() {
var header metadata.MD
client := suite.backend.clientCtx.Client.(*mocks.Client)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterStatus(client)
RegisterValidatorAccount(queryClient, suite.acc)
RegisterParams(queryClient, &header, 1)
c := sdk.NewDecCoin("aphoton", sdk.NewIntFromBigInt(big.NewInt(1)))
suite.backend.cfg.SetMinGasPrices(sdk.DecCoins{c})
delAddr, _ := suite.backend.GetCoinbase()
Expand Down
91 changes: 66 additions & 25 deletions tests/integration_tests/test_account.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,73 @@
import os

import pytest
from eth_account import Account
from web3 import Web3

from .network import setup_ethermint
from .utils import ADDRS, w3_wait_for_new_blocks


def test_get_transaction_count(ethermint_rpc_ws, geth):
for p in [ethermint_rpc_ws, geth]:
w3 = p.w3
blk = hex(w3.eth.block_number)
sender = ADDRS["validator"]

# derive a new address
account_path = "m/44'/60'/0'/0/1"
mnemonic = os.getenv("COMMUNITY_MNEMONIC")
receiver = (Account.from_mnemonic(mnemonic, account_path=account_path)).address
n0 = w3.eth.get_transaction_count(receiver, blk)
# ensure transaction send in new block
w3_wait_for_new_blocks(w3, 1, sleep=0.1)
txhash = w3.eth.send_transaction(
{
"from": sender,
"to": receiver,
"value": 1000,
}
)
receipt = w3.eth.wait_for_transaction_receipt(txhash)
assert receipt.status == 1
[n1, n2] = [w3.eth.get_transaction_count(receiver, b) for b in [blk, "latest"]]
assert n0 == n1
assert n0 == n2
@pytest.fixture(scope="module")
def custom_ethermint(tmp_path_factory):
path = tmp_path_factory.mktemp("account")
yield from setup_ethermint(path, 26700, long_timeout_commit=True)


@pytest.fixture(scope="module", params=["ethermint", "ethermint-ws", "geth"])
def cluster(request, custom_ethermint, geth):
"""
run on ethermint, ethermint websocket and geth
"""
provider = request.param
if provider == "ethermint":
yield custom_ethermint
elif provider == "ethermint-ws":
ethermint_ws = custom_ethermint.copy()
ethermint_ws.use_websocket()
yield ethermint_ws
elif provider == "geth":
yield geth
else:
raise NotImplementedError


def derive_new_address(n=1):
# derive a new address
account_path = f"m/44'/60'/0'/0/{n}"
mnemonic = os.getenv("COMMUNITY_MNEMONIC")
return (Account.from_mnemonic(mnemonic, account_path=account_path)).address


def test_get_transaction_count(cluster):
w3: Web3 = cluster.w3
blk = hex(w3.eth.block_number)
sender = ADDRS["validator"]

receiver = derive_new_address()
n0 = w3.eth.get_transaction_count(receiver, blk)
# ensure transaction send in new block
w3_wait_for_new_blocks(w3, 1, sleep=0.1)
txhash = w3.eth.send_transaction(
{
"from": sender,
"to": receiver,
"value": 1000,
}
)
receipt = w3.eth.wait_for_transaction_receipt(txhash)
assert receipt.status == 1
[n1, n2] = [w3.eth.get_transaction_count(receiver, b) for b in [blk, "latest"]]
assert n0 == n1
assert n0 == n2


def test_query_future_blk(cluster):
w3: Web3 = cluster.w3
acc = derive_new_address(2)
current = w3.eth.block_number
future = current + 1000
with pytest.raises(ValueError) as exc:
w3.eth.get_transaction_count(acc, hex(future))
print(acc, str(exc))
assert "-32000" in str(exc)