rpc: implement pending nonce with UnconfirmedTx (#243)

* implement pending nonce with UnconfirmedTx

Closes #242

fix lint

* return early on error
This commit is contained in:
yihuang 2021-07-09 16:34:49 +08:00 committed by GitHub
parent d0b890b794
commit 7951852bb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 25 deletions

View File

@ -13,6 +13,7 @@ import (
log "github.com/xlab/suplog" log "github.com/xlab/suplog"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
@ -36,7 +37,7 @@ type Backend interface {
GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error)
// Used by pending transaction filter // Used by pending transaction filter
PendingTransactions() ([]*types.RPCTransaction, error) PendingTransactions() ([]*sdk.Tx, error)
// Used by log filter // Used by log filter
GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error)
@ -294,8 +295,22 @@ func (e *EVMBackend) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, er
// PendingTransactions returns the transactions that are in the transaction pool // PendingTransactions returns the transactions that are in the transaction pool
// and have a from address that is one of the accounts this node manages. // and have a from address that is one of the accounts this node manages.
func (e *EVMBackend) PendingTransactions() ([]*types.RPCTransaction, error) { func (e *EVMBackend) PendingTransactions() ([]*sdk.Tx, error) {
return []*types.RPCTransaction{}, nil res, err := e.clientCtx.Client.UnconfirmedTxs(e.ctx, nil)
if err != nil {
return nil, err
}
result := make([]*sdk.Tx, 0, len(res.Txs))
for _, txBz := range res.Txs {
tx, err := e.clientCtx.TxConfig.TxDecoder()(txBz)
if err != nil {
return nil, err
}
result = append(result, &tx)
}
return result, nil
} }
// GetLogs returns all the logs from all the ethereum transactions in a block. // GetLogs returns all the logs from all the ethereum transactions in a block.

View File

@ -5,21 +5,18 @@ import (
"context" "context"
"fmt" "fmt"
"math/big" "math/big"
"strconv"
"strings" "strings"
"github.com/gogo/protobuf/jsonpb" "github.com/gogo/protobuf/jsonpb"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/spf13/viper" "github.com/spf13/viper"
log "github.com/xlab/suplog" log "github.com/xlab/suplog"
"google.golang.org/grpc/metadata"
"github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/flags"
codectypes "github.com/cosmos/cosmos-sdk/codec/types" codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -260,7 +257,7 @@ func (e *PublicAPI) GetTransactionCount(address common.Address, blockNum rpctype
} }
includePending := blockNum == rpctypes.EthPendingBlockNumber includePending := blockNum == rpctypes.EthPendingBlockNumber
nonce, err := e.getAccountNonce(address, includePending, blockNum.TmHeight(), e.logger) nonce, err := e.getAccountNonce(address, includePending, blockNum.Int64(), e.logger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -585,7 +582,7 @@ func (e *PublicAPI) doCall(
} }
includePending := blockNr == rpctypes.EthPendingBlockNumber includePending := blockNr == rpctypes.EthPendingBlockNumber
seq, err := e.getAccountNonce(*args.From, includePending, blockNr.TmHeight(), e.logger) seq, err := e.getAccountNonce(*args.From, includePending, 0, e.logger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -985,7 +982,9 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
// and have a from address that is one of the accounts this node manages. // and have a from address that is one of the accounts this node manages.
func (e *PublicAPI) PendingTransactions() ([]*rpctypes.RPCTransaction, error) { func (e *PublicAPI) PendingTransactions() ([]*rpctypes.RPCTransaction, error) {
e.logger.Debugln("eth_getPendingTransactions") e.logger.Debugln("eth_getPendingTransactions")
return e.backend.PendingTransactions()
// FIXME https://github.com/tharsis/ethermint/issues/244
return []*rpctypes.RPCTransaction{}, nil
} }
// GetUncleByBlockHashAndIndex returns the uncle identified by hash and index. Always returns nil. // GetUncleByBlockHashAndIndex returns the uncle identified by hash and index. Always returns nil.
@ -1082,7 +1081,7 @@ func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs
if args.Nonce == nil { if args.Nonce == nil {
// get the nonce from the account retriever // get the nonce from the account retriever
// ignore error in case tge account doesn't exist yet // ignore error in case tge account doesn't exist yet
nonce, _ := e.getAccountNonce(args.From, true, nil, e.logger) nonce, _ := e.getAccountNonce(args.From, true, 0, e.logger)
args.Nonce = (*hexutil.Uint64)(&nonce) args.Nonce = (*hexutil.Uint64)(&nonce)
} }
@ -1140,13 +1139,9 @@ func (e *PublicAPI) setTxDefaults(args rpctypes.SendTxArgs) (rpctypes.SendTxArgs
// If the pending value is true, it will iterate over the mempool (pending) // If the pending value is true, it will iterate over the mempool (pending)
// txs in order to compute and return the pending tx sequence. // txs in order to compute and return the pending tx sequence.
// Todo: include the ability to specify a blockNumber // Todo: include the ability to specify a blockNumber
func (e *PublicAPI) getAccountNonce(accAddr common.Address, pending bool, height *int64, logger log.Logger) (uint64, error) { func (e *PublicAPI) getAccountNonce(accAddr common.Address, pending bool, height int64, logger log.Logger) (uint64, error) {
ctx := e.ctx
if height != nil {
ctx = metadata.AppendToOutgoingContext(e.ctx, grpctypes.GRPCBlockHeightHeader, strconv.FormatInt(*height, 10))
}
queryClient := authtypes.NewQueryClient(e.clientCtx) queryClient := authtypes.NewQueryClient(e.clientCtx)
res, err := queryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: sdk.AccAddress(accAddr.Bytes()).String()}) res, err := queryClient.Account(rpctypes.ContextWithHeight(height), &authtypes.QueryAccountRequest{Address: sdk.AccAddress(accAddr.Bytes()).String()})
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -1165,19 +1160,29 @@ func (e *PublicAPI) getAccountNonce(accAddr common.Address, pending bool, height
// to manually add them. // to manually add them.
pendingTxs, err := e.backend.PendingTransactions() pendingTxs, err := e.backend.PendingTransactions()
if err != nil { if err != nil {
logger.Errorln("fails to fetch pending transactions") logger.WithError(err).Errorln("fails to fetch pending transactions")
return nonce, nil return nonce, nil
} }
// add the uncommitted txs to the nonce counter // add the uncommitted txs to the nonce counter
if len(pendingTxs) != 0 { // only supports `MsgEthereumTx` style tx
for i := range pendingTxs { for _, tx := range pendingTxs {
if pendingTxs[i] == nil { if tx == nil {
continue continue
} }
if pendingTxs[i].From == accAddr { if len((*tx).GetMsgs()) != 1 {
nonce++ continue
} }
msg, ok := (*tx).GetMsgs()[0].(*evmtypes.MsgEthereumTx)
if !ok {
continue
}
sender, err := msg.GetSender(e.chainIDEpoch)
if err != nil {
continue
}
if sender == accAddr {
nonce++
} }
} }