From acd3a7352dd4884deacb93e2ca01e4312347d17b Mon Sep 17 00:00:00 2001 From: Thomas Nguy Date: Mon, 28 Jun 2021 14:50:42 +0900 Subject: [PATCH 1/6] consider mempool tx when computing account nonce --- ethereum/rpc/namespaces/eth/api.go | 54 ++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/ethereum/rpc/namespaces/eth/api.go b/ethereum/rpc/namespaces/eth/api.go index 7815089e42..c610e82dfd 100644 --- a/ethereum/rpc/namespaces/eth/api.go +++ b/ethereum/rpc/namespaces/eth/api.go @@ -256,9 +256,11 @@ func (e *PublicAPI) GetTransactionCount(address common.Address, blockNum rpctype return &n, nil } - _, nonce, err := accRet.GetAccountNumberSequence(e.clientCtx, from) - if err != nil { - return nil, err + includePending := blockNum == rpctypes.EthPendingBlockNumber + + nonce, error := getAccountNonce(e.clientCtx, e.backend, address, includePending) + if error != nil { + return nil, error } n := hexutil.Uint64(nonce) @@ -565,16 +567,11 @@ func (e *PublicAPI) doCall( accessList = args.AccessList } - // Set destination address for call - var fromAddr sdk.AccAddress - if args.From != nil { - fromAddr = sdk.AccAddress(args.From.Bytes()) - } else { - fromAddr = sdk.AccAddress(common.Address{}.Bytes()) + if args.From == nil { args.From = &common.Address{} } - _, seq, err := e.clientCtx.AccountRetriever.GetAccountNumberSequence(e.clientCtx, fromAddr) + seq, err := getAccountNonce(e.clientCtx, e.backend, *args.From, true) if err != nil { return nil, err } @@ -1018,9 +1015,6 @@ func (e *PublicAPI) GetProof(address common.Address, storageKeys []string, block // provided on the args func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs, error) { - // Get nonce (sequence) from sender account - from := sdk.AccAddress(args.From.Bytes()) - if args.GasPrice == nil { // TODO: Change to either: // - min gas price from context once available through server/daemon, or @@ -1031,7 +1025,7 @@ func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs if args.Nonce == nil { // get the nonce from the account retriever // ignore error in case tge account doesn't exist yet - _, nonce, _ := e.clientCtx.AccountRetriever.GetAccountNumberSequence(e.clientCtx, from) + nonce, _ := getAccountNonce(e.clientCtx, e.backend, args.From, true) args.Nonce = (*hexutil.Uint64)(&nonce) } @@ -1084,3 +1078,35 @@ func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs return args, nil } + +// getAccountNonce return the account nonce +// Todo: include the ability to specify a blockNumber +func getAccountNonce(ctx client.Context, backend backend.Backend, accAddr common.Address, pending bool) (uint64, error) { + _, nonce, err := ctx.AccountRetriever.GetAccountNumberSequence(ctx, accAddr.Bytes()) + if err != nil { + return 0, err + } + + if pending { + // the account retriever doesn't include the uncommitted transactions on the nonce so we need to + // to manually add them. + pendingTxs, err := 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 == accAddr { + nonce++ + } + } + } + } + + return nonce, nil +} \ No newline at end of file From 1f06f3a1b38867c2d5724af7c68ccf6d4ff81d14 Mon Sep 17 00:00:00 2001 From: Thomas Nguy Date: Mon, 28 Jun 2021 14:54:22 +0900 Subject: [PATCH 2/6] fix lint --- ethereum/rpc/namespaces/eth/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/rpc/namespaces/eth/api.go b/ethereum/rpc/namespaces/eth/api.go index c610e82dfd..de98292dae 100644 --- a/ethereum/rpc/namespaces/eth/api.go +++ b/ethereum/rpc/namespaces/eth/api.go @@ -1109,4 +1109,4 @@ func getAccountNonce(ctx client.Context, backend backend.Backend, accAddr common } return nonce, nil -} \ No newline at end of file +} From 6fda16d8603f2778dab51926a609e9099fc86f00 Mon Sep 17 00:00:00 2001 From: Thomas Nguy Date: Tue, 29 Jun 2021 16:30:26 +0900 Subject: [PATCH 3/6] add condition on blocknbr --- ethereum/rpc/namespaces/eth/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethereum/rpc/namespaces/eth/api.go b/ethereum/rpc/namespaces/eth/api.go index de98292dae..ad08a1c5bb 100644 --- a/ethereum/rpc/namespaces/eth/api.go +++ b/ethereum/rpc/namespaces/eth/api.go @@ -257,7 +257,6 @@ func (e *PublicAPI) GetTransactionCount(address common.Address, blockNum rpctype } includePending := blockNum == rpctypes.EthPendingBlockNumber - nonce, error := getAccountNonce(e.clientCtx, e.backend, address, includePending) if error != nil { return nil, error @@ -571,7 +570,8 @@ func (e *PublicAPI) doCall( args.From = &common.Address{} } - seq, err := getAccountNonce(e.clientCtx, e.backend, *args.From, true) + includePending := blockNr == rpctypes.EthPendingBlockNumber + seq, err := getAccountNonce(e.clientCtx, e.backend, *args.From, includePending) if err != nil { return nil, err } From bc1145fcbf8c93d79d1656e8a85ff4011139bfc4 Mon Sep 17 00:00:00 2001 From: Thomas Nguy Date: Tue, 29 Jun 2021 16:34:01 +0900 Subject: [PATCH 4/6] add log --- ethereum/rpc/namespaces/eth/api.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ethereum/rpc/namespaces/eth/api.go b/ethereum/rpc/namespaces/eth/api.go index ad08a1c5bb..2c95cfa83b 100644 --- a/ethereum/rpc/namespaces/eth/api.go +++ b/ethereum/rpc/namespaces/eth/api.go @@ -257,7 +257,7 @@ func (e *PublicAPI) GetTransactionCount(address common.Address, blockNum rpctype } includePending := blockNum == rpctypes.EthPendingBlockNumber - nonce, error := getAccountNonce(e.clientCtx, e.backend, address, includePending) + nonce, error := getAccountNonce(e.clientCtx, e.backend, address, includePending, e.logger) if error != nil { return nil, error } @@ -571,7 +571,7 @@ func (e *PublicAPI) doCall( } includePending := blockNr == rpctypes.EthPendingBlockNumber - seq, err := getAccountNonce(e.clientCtx, e.backend, *args.From, includePending) + seq, err := getAccountNonce(e.clientCtx, e.backend, *args.From, includePending, e.logger) if err != nil { return nil, err } @@ -1025,7 +1025,7 @@ func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs if args.Nonce == nil { // get the nonce from the account retriever // ignore error in case tge account doesn't exist yet - nonce, _ := getAccountNonce(e.clientCtx, e.backend, args.From, true) + nonce, _ := getAccountNonce(e.clientCtx, e.backend, args.From, true, e.logger) args.Nonce = (*hexutil.Uint64)(&nonce) } @@ -1079,9 +1079,11 @@ func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs return args, nil } -// getAccountNonce return the account nonce +// getAccountNonce returns the account nonce for the given account address. +// If the pending value is true, it will iterate over the mempool (pending) +// txs in order to compute and return the pending tx sequence. // Todo: include the ability to specify a blockNumber -func getAccountNonce(ctx client.Context, backend backend.Backend, accAddr common.Address, pending bool) (uint64, error) { +func getAccountNonce(ctx client.Context, backend backend.Backend, accAddr common.Address, pending bool, logger log.Logger) (uint64, error) { _, nonce, err := ctx.AccountRetriever.GetAccountNumberSequence(ctx, accAddr.Bytes()) if err != nil { return 0, err @@ -1092,7 +1094,8 @@ func getAccountNonce(ctx client.Context, backend backend.Backend, accAddr common // to manually add them. pendingTxs, err := backend.PendingTransactions() if err != nil { - return 0, err + logger.Errorln("fails to fetch pending transactions") + return nonce, nil } // add the uncommitted txs to the nonce counter From b79be170ddf0a71814b5f95b9e02c499259eb8bc Mon Sep 17 00:00:00 2001 From: Thomas Nguy Date: Tue, 29 Jun 2021 16:41:39 +0900 Subject: [PATCH 5/6] update changelog : --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec2d88647..a3c4dcbff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (evm) [tharsis#24](https://github.com/tharsis/ethermint/pull/24) Implement metrics for `MsgEthereumTx`, state transitions, `BeginBlock` and `EndBlock`. * (rpc) [#124](https://github.com/tharsis/ethermint/issues/124) Implement `txpool_content`, `txpool_inspect` and `txpool_status` RPC methods * (rpc) [tharsis#112](https://github.com/tharsis/ethermint/pull/153) Fix `eth_coinbase` to return the ethereum address of the validator +* (rpc) [tharsis#176](https://github.com/tharsis/ethermint/issues/176) Support fetching pending nonce ### Bug Fixes From 378ce554e555d679daa22a5b9ccbf600d21b2fb1 Mon Sep 17 00:00:00 2001 From: Thomas Nguy Date: Wed, 30 Jun 2021 11:02:37 +0900 Subject: [PATCH 6/6] cleanup --- ethereum/rpc/namespaces/eth/api.go | 42 ++++++++++++++++-------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/ethereum/rpc/namespaces/eth/api.go b/ethereum/rpc/namespaces/eth/api.go index 2c95cfa83b..7fe3cbd726 100644 --- a/ethereum/rpc/namespaces/eth/api.go +++ b/ethereum/rpc/namespaces/eth/api.go @@ -257,9 +257,9 @@ func (e *PublicAPI) GetTransactionCount(address common.Address, blockNum rpctype } includePending := blockNum == rpctypes.EthPendingBlockNumber - nonce, error := getAccountNonce(e.clientCtx, e.backend, address, includePending, e.logger) - if error != nil { - return nil, error + nonce, err := getAccountNonce(e.clientCtx, e.backend, address, includePending, e.logger) + if err != nil { + return nil, err } n := hexutil.Uint64(nonce) @@ -1089,24 +1089,26 @@ func getAccountNonce(ctx client.Context, backend backend.Backend, accAddr common return 0, err } - if pending { - // the account retriever doesn't include the uncommitted transactions on the nonce so we need to - // to manually add them. - pendingTxs, err := backend.PendingTransactions() - if err != nil { - logger.Errorln("fails to fetch pending transactions") - return nonce, nil - } + if !pending { + return nonce, nil + } - // 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 == accAddr { - nonce++ - } + // the account retriever doesn't include the uncommitted transactions on the nonce so we need to + // to manually add them. + pendingTxs, err := backend.PendingTransactions() + if err != nil { + logger.Errorln("fails to fetch pending transactions") + return nonce, nil + } + + // 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 == accAddr { + nonce++ } } }