Sync from fork #74
@ -51,10 +51,10 @@ type EVMBackend interface {
|
|||||||
|
|
||||||
// Blockchain API
|
// Blockchain API
|
||||||
BlockNumber() (hexutil.Uint64, error)
|
BlockNumber() (hexutil.Uint64, error)
|
||||||
|
GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
||||||
GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error)
|
GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error)
|
||||||
GetTendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error)
|
GetTendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error)
|
||||||
GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error)
|
GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error)
|
||||||
GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
|
||||||
GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error)
|
GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error)
|
||||||
BlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error)
|
BlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, error)
|
||||||
BlockByHash(blockHash common.Hash) (*ethtypes.Block, error)
|
BlockByHash(blockHash common.Hash) (*ethtypes.Block, error)
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
package backend
|
package backend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/client"
|
"github.com/cosmos/cosmos-sdk/client"
|
||||||
"github.com/cosmos/cosmos-sdk/server"
|
"github.com/cosmos/cosmos-sdk/server"
|
||||||
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
mock "github.com/stretchr/testify/mock"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/stretchr/testify/require"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
"google.golang.org/grpc"
|
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
"google.golang.org/grpc/metadata"
|
|
||||||
|
|
||||||
|
"github.com/evmos/ethermint/app"
|
||||||
|
"github.com/evmos/ethermint/encoding"
|
||||||
"github.com/evmos/ethermint/rpc/backend/mocks"
|
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||||
|
ethrpc "github.com/evmos/ethermint/rpc/types"
|
||||||
rpc "github.com/evmos/ethermint/rpc/types"
|
rpc "github.com/evmos/ethermint/rpc/types"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
@ -30,44 +33,89 @@ func TestBackendTestSuite(t *testing.T) {
|
|||||||
func (suite *BackendTestSuite) SetupTest() {
|
func (suite *BackendTestSuite) SetupTest() {
|
||||||
ctx := server.NewDefaultContext()
|
ctx := server.NewDefaultContext()
|
||||||
ctx.Viper.Set("telemetry.global-labels", []interface{}{})
|
ctx.Viper.Set("telemetry.global-labels", []interface{}{})
|
||||||
clientCtx := client.Context{}.WithChainID("ethermint_9000-1").WithHeight(1)
|
|
||||||
|
encodingConfig := encoding.MakeConfig(app.ModuleBasics)
|
||||||
|
clientCtx := client.Context{}.WithChainID("ethermint_9000-1").
|
||||||
|
WithHeight(1).
|
||||||
|
WithTxConfig(encodingConfig.TxConfig)
|
||||||
|
|
||||||
allowUnprotectedTxs := false
|
allowUnprotectedTxs := false
|
||||||
|
|
||||||
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs)
|
suite.backend = NewBackend(ctx, ctx.Logger, clientCtx, allowUnprotectedTxs)
|
||||||
|
suite.backend.queryClient.QueryClient = mocks.NewQueryClient(suite.T())
|
||||||
queryClient := mocks.NewQueryClient(suite.T())
|
suite.backend.clientCtx.Client = mocks.NewClient(suite.T())
|
||||||
var header metadata.MD
|
|
||||||
RegisterMockQueries(queryClient, &header)
|
|
||||||
|
|
||||||
suite.backend.queryClient.QueryClient = queryClient
|
|
||||||
suite.backend.ctx = rpc.ContextWithHeight(1)
|
suite.backend.ctx = rpc.ContextWithHeight(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryClient defines a mocked object that implements the grpc QueryCLient
|
// buildEthereumTx returns an example legacy Ethereum transaction
|
||||||
// interface. It's used on tests to test the JSON-RPC without running a grpc
|
func (suite *BackendTestSuite) buildEthereumTx() (*evmtypes.MsgEthereumTx, []byte) {
|
||||||
// client server. E.g. JSON-PRC-CLIENT -> BACKEND -> Mock GRPC CLIENT -> APP
|
msgEthereumTx := evmtypes.NewTx(
|
||||||
var _ evmtypes.QueryClient = &mocks.QueryClient{}
|
big.NewInt(1),
|
||||||
|
uint64(0),
|
||||||
|
&common.Address{},
|
||||||
|
big.NewInt(0),
|
||||||
|
100000,
|
||||||
|
big.NewInt(1),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
// RegisterMockQueries registers the queries and their respective responses,
|
// A valid msg should have empty `From`
|
||||||
// so that they can be called in tests using the queryClient
|
msgEthereumTx.From = ""
|
||||||
func RegisterMockQueries(queryClient *mocks.QueryClient, header *metadata.MD) {
|
|
||||||
queryClient.On("Params", rpc.ContextWithHeight(1), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
txBuilder := suite.backend.clientCtx.TxConfig.NewTxBuilder()
|
||||||
Return(&evmtypes.QueryParamsResponse{}, nil).
|
err := txBuilder.SetMsgs(msgEthereumTx)
|
||||||
Run(func(args mock.Arguments) {
|
suite.Require().NoError(err)
|
||||||
// If Params call is successful, also update the header height
|
|
||||||
arg := args.Get(2).(grpc.HeaderCallOption)
|
bz, err := suite.backend.clientCtx.TxConfig.TxEncoder()(txBuilder.GetTx())
|
||||||
h := metadata.MD{}
|
suite.Require().NoError(err)
|
||||||
h.Set(grpctypes.GRPCBlockHeightHeader, "1")
|
return msgEthereumTx, bz
|
||||||
*arg.HeaderAddr = h
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQueryClient(t *testing.T) {
|
// buildFormattedBlock returns a formatted block for testing
|
||||||
queryClient := mocks.NewQueryClient(t)
|
func (suite *BackendTestSuite) buildFormattedBlock(
|
||||||
var header metadata.MD
|
blockRes *tmrpctypes.ResultBlockResults,
|
||||||
RegisterMockQueries(queryClient, &header)
|
resBlock *tmrpctypes.ResultBlock,
|
||||||
|
fullTx bool,
|
||||||
|
tx *evmtypes.MsgEthereumTx,
|
||||||
|
validator sdk.AccAddress,
|
||||||
|
baseFee *big.Int,
|
||||||
|
) map[string]interface{} {
|
||||||
|
header := resBlock.Block.Header
|
||||||
|
gasLimit := int64(^uint32(0)) // for `MaxGas = -1` (DefaultConsensusParams)
|
||||||
|
gasUsed := new(big.Int).SetUint64(uint64(blockRes.TxsResults[0].GasUsed))
|
||||||
|
|
||||||
// mock calls for abstraction
|
root := common.Hash{}.Bytes()
|
||||||
_, err := queryClient.Params(rpc.ContextWithHeight(1), &evmtypes.QueryParamsRequest{}, grpc.Header(&header))
|
receipt := ethtypes.NewReceipt(root, false, gasUsed.Uint64())
|
||||||
require.NoError(t, err)
|
bloom := ethtypes.CreateBloom(ethtypes.Receipts{receipt})
|
||||||
|
|
||||||
|
ethRPCTxs := []interface{}{}
|
||||||
|
if tx != nil {
|
||||||
|
if fullTx {
|
||||||
|
rpcTx, err := ethrpc.NewRPCTransaction(
|
||||||
|
tx.AsTransaction(),
|
||||||
|
common.BytesToHash(header.Hash()),
|
||||||
|
uint64(header.Height),
|
||||||
|
uint64(0),
|
||||||
|
baseFee,
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
ethRPCTxs = []interface{}{rpcTx}
|
||||||
|
} else {
|
||||||
|
ethRPCTxs = []interface{}{common.HexToHash(tx.Hash)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ethrpc.FormatBlock(
|
||||||
|
header,
|
||||||
|
resBlock.Block.Size(),
|
||||||
|
gasLimit,
|
||||||
|
gasUsed,
|
||||||
|
ethRPCTxs,
|
||||||
|
bloom,
|
||||||
|
common.BytesToAddress(validator.Bytes()),
|
||||||
|
baseFee,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
147
rpc/backend/client_test.go
Normal file
147
rpc/backend/client_test.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package backend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||||
|
rpc "github.com/evmos/ethermint/rpc/types"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
|
tmrpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||||
|
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client defines a mocked object that implements the Tendermint JSON-RPC Client
|
||||||
|
// interface. It allows for performing Client queries without having to run a
|
||||||
|
// Tendermint RPC Client server.
|
||||||
|
//
|
||||||
|
// To use a mock method it has to be registered in a given test.
|
||||||
|
var _ tmrpcclient.Client = &mocks.Client{}
|
||||||
|
|
||||||
|
// Block
|
||||||
|
func RegisterBlock(
|
||||||
|
client *mocks.Client,
|
||||||
|
height int64,
|
||||||
|
tx []byte,
|
||||||
|
) (*tmrpctypes.ResultBlock, error) {
|
||||||
|
// without tx
|
||||||
|
if tx == nil {
|
||||||
|
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
||||||
|
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
||||||
|
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(resBlock, nil)
|
||||||
|
return resBlock, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// with tx
|
||||||
|
block := types.MakeBlock(height, []types.Tx{tx}, nil, nil)
|
||||||
|
res := &tmrpctypes.ResultBlock{Block: block}
|
||||||
|
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(res, nil)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block returns error
|
||||||
|
func RegisterBlockError(client *mocks.Client, height int64) {
|
||||||
|
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block not found
|
||||||
|
func RegisterBlockNotFound(
|
||||||
|
client *mocks.Client,
|
||||||
|
height int64,
|
||||||
|
) (*tmrpctypes.ResultBlock, error) {
|
||||||
|
client.On("Block", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(&tmrpctypes.ResultBlock{Block: nil}, nil)
|
||||||
|
|
||||||
|
return &tmrpctypes.ResultBlock{Block: nil}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterBlock(t *testing.T) {
|
||||||
|
client := mocks.NewClient(t)
|
||||||
|
height := rpc.BlockNumber(1).Int64()
|
||||||
|
RegisterBlock(client, height, nil)
|
||||||
|
|
||||||
|
res, err := client.Block(rpc.ContextWithHeight(height), &height)
|
||||||
|
|
||||||
|
emptyBlock := types.MakeBlock(height, []types.Tx{}, nil, nil)
|
||||||
|
resBlock := &tmrpctypes.ResultBlock{Block: emptyBlock}
|
||||||
|
require.Equal(t, resBlock, res)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsensusParams
|
||||||
|
func RegisterConsensusParams(client *mocks.Client, height int64) {
|
||||||
|
consensusParams := types.DefaultConsensusParams()
|
||||||
|
client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(&tmrpctypes.ResultConsensusParams{ConsensusParams: *consensusParams}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterConsensusParamsError(client *mocks.Client, height int64) {
|
||||||
|
client.On("ConsensusParams", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterConsensusParams(t *testing.T) {
|
||||||
|
client := mocks.NewClient(t)
|
||||||
|
height := int64(1)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
|
||||||
|
res, err := client.ConsensusParams(rpc.ContextWithHeight(height), &height)
|
||||||
|
consensusParams := types.DefaultConsensusParams()
|
||||||
|
require.Equal(t, &tmrpctypes.ResultConsensusParams{ConsensusParams: *consensusParams}, res)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockResults
|
||||||
|
func RegisterBlockResults(
|
||||||
|
client *mocks.Client,
|
||||||
|
height int64,
|
||||||
|
) (*tmrpctypes.ResultBlockResults, error) {
|
||||||
|
res := &tmrpctypes.ResultBlockResults{
|
||||||
|
Height: height,
|
||||||
|
TxsResults: []*abci.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
}
|
||||||
|
|
||||||
|
client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(res, nil)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterBlockResultsError(client *mocks.Client, height int64) {
|
||||||
|
client.On("BlockResults", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")).
|
||||||
|
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterBlockResults(t *testing.T) {
|
||||||
|
client := mocks.NewClient(t)
|
||||||
|
height := int64(1)
|
||||||
|
RegisterBlockResults(client, height)
|
||||||
|
|
||||||
|
res, err := client.BlockResults(rpc.ContextWithHeight(height), &height)
|
||||||
|
expRes := &tmrpctypes.ResultBlockResults{
|
||||||
|
Height: height,
|
||||||
|
TxsResults: []*abci.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
}
|
||||||
|
require.Equal(t, expRes, res)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockByHash
|
||||||
|
func RegisterBlockByHash(
|
||||||
|
client *mocks.Client,
|
||||||
|
hash common.Hash,
|
||||||
|
tx []byte,
|
||||||
|
) (*tmrpctypes.ResultBlock, error) {
|
||||||
|
block := types.MakeBlock(1, []types.Tx{tx}, nil, nil)
|
||||||
|
resBlock := &tmrpctypes.ResultBlock{Block: block}
|
||||||
|
|
||||||
|
client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}).
|
||||||
|
Return(resBlock, nil)
|
||||||
|
return resBlock, nil
|
||||||
|
}
|
@ -103,7 +103,13 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.EthBlockFromTendermint(resBlock, blockRes, fullTx)
|
res, err := b.EthBlockFromTendermint(resBlock, blockRes, fullTx)
|
||||||
|
if err != nil {
|
||||||
|
b.logger.Debug("EthBlockFromTendermint failed", "hash", hash, "error", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockByNumber returns the block identified by number.
|
// BlockByNumber returns the block identified by number.
|
||||||
@ -177,7 +183,8 @@ func (b *Backend) EthBlockFromTm(resBlock *tmrpctypes.ResultBlock, blockRes *tmr
|
|||||||
return ethBlock, nil
|
return ethBlock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTendermintBlockByNumber returns a Tendermint format block by block number
|
// GetTendermintBlockByNumber returns a Tendermint formatted block for a given
|
||||||
|
// block number
|
||||||
func (b *Backend) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) {
|
func (b *Backend) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error) {
|
||||||
height := blockNum.Int64()
|
height := blockNum.Int64()
|
||||||
if height <= 0 {
|
if height <= 0 {
|
||||||
@ -239,7 +246,8 @@ func (b *Backend) BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.
|
|||||||
return ethtypes.Bloom{}, errors.New("block bloom event is not found")
|
return ethtypes.Bloom{}, errors.New("block bloom event is not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a given Tendermint block and its block result.
|
// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a
|
||||||
|
// given Tendermint block and its block result.
|
||||||
func (b *Backend) EthBlockFromTendermint(
|
func (b *Backend) EthBlockFromTendermint(
|
||||||
resBlock *tmrpctypes.ResultBlock,
|
resBlock *tmrpctypes.ResultBlock,
|
||||||
blockRes *tmrpctypes.ResultBlockResults,
|
blockRes *tmrpctypes.ResultBlockResults,
|
||||||
@ -981,17 +989,22 @@ func (b *Backend) FeeHistory(
|
|||||||
return &feeHistory, nil
|
return &feeHistory, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEthereumMsgsFromTendermintBlock returns all real MsgEthereumTxs from a Tendermint block.
|
// GetEthereumMsgsFromTendermintBlock returns all real MsgEthereumTxs from a
|
||||||
// It also ensures consistency over the correct txs indexes across RPC endpoints
|
// Tendermint block. It also ensures consistency over the correct txs indexes
|
||||||
func (b *Backend) GetEthereumMsgsFromTendermintBlock(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx {
|
// across RPC endpoints
|
||||||
|
func (b *Backend) GetEthereumMsgsFromTendermintBlock(
|
||||||
|
resBlock *tmrpctypes.ResultBlock,
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults,
|
||||||
|
) []*evmtypes.MsgEthereumTx {
|
||||||
var result []*evmtypes.MsgEthereumTx
|
var result []*evmtypes.MsgEthereumTx
|
||||||
block := resBlock.Block
|
block := resBlock.Block
|
||||||
|
|
||||||
txResults := blockRes.TxsResults
|
txResults := blockRes.TxsResults
|
||||||
|
|
||||||
for i, tx := range block.Txs {
|
for i, tx := range block.Txs {
|
||||||
// check tx exists on EVM by cross checking with blockResults
|
// Check if tx exists on EVM by cross checking with blockResults:
|
||||||
// include the tx that exceeds block gas limit
|
// - Include unsuccessful tx that exceeds block gas limit
|
||||||
|
// - Exclude unsuccessful tx with any other error but ExceedBlockGasLimit
|
||||||
if !TxSuccessOrExceedsBlockGasLimit(txResults[i]) {
|
if !TxSuccessOrExceedsBlockGasLimit(txResults[i]) {
|
||||||
b.logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash()))
|
b.logger.Debug("invalid tx result code", "cosmos-hash", hexutil.Encode(tx.Hash()))
|
||||||
continue
|
continue
|
||||||
|
@ -1,30 +1,983 @@
|
|||||||
package backend
|
package backend
|
||||||
|
|
||||||
import "github.com/ethereum/go-ethereum/common/hexutil"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/tendermint/tendermint/abci/types"
|
||||||
|
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
|
tmtypes "github.com/tendermint/tendermint/types"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
|
||||||
|
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||||
|
ethrpc "github.com/evmos/ethermint/rpc/types"
|
||||||
|
"github.com/evmos/ethermint/tests"
|
||||||
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
|
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
|
||||||
|
)
|
||||||
|
|
||||||
func (suite *BackendTestSuite) TestBlockNumber() {
|
func (suite *BackendTestSuite) TestBlockNumber() {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
mame string
|
name string
|
||||||
malleate func()
|
registerMock func()
|
||||||
expBlockNumber hexutil.Uint64
|
expBlockNumber hexutil.Uint64
|
||||||
expPass bool
|
expPass bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"pass",
|
"fail - invalid block header height",
|
||||||
func() {
|
func() {
|
||||||
|
height := int64(1)
|
||||||
|
var header metadata.MD
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterParamsInvalidHeight(queryClient, &header, int64(height))
|
||||||
|
},
|
||||||
|
0x0,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - invalid block header",
|
||||||
|
func() {
|
||||||
|
height := int64(1)
|
||||||
|
var header metadata.MD
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterParamsInvalidHeader(queryClient, &header, int64(height))
|
||||||
|
},
|
||||||
|
0x0,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - app state header height 1",
|
||||||
|
func() {
|
||||||
|
height := int64(1)
|
||||||
|
var header metadata.MD
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterParams(queryClient, &header, int64(height))
|
||||||
},
|
},
|
||||||
0x1,
|
0x1,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
blockNumber, err := suite.backend.BlockNumber()
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
tc.registerMock()
|
||||||
|
|
||||||
if tc.expPass {
|
blockNumber, err := suite.backend.BlockNumber()
|
||||||
suite.Require().NoError(err)
|
|
||||||
suite.Require().Equal(tc.expBlockNumber, blockNumber)
|
if tc.expPass {
|
||||||
} else {
|
suite.Require().NoError(err)
|
||||||
suite.Require().Error(err)
|
suite.Require().Equal(tc.expBlockNumber, blockNumber)
|
||||||
}
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestGetBlockByNumber() {
|
||||||
|
var (
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults
|
||||||
|
resBlock *tmrpctypes.ResultBlock
|
||||||
|
)
|
||||||
|
msgEthereumTx, bz := suite.buildEthereumTx()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
blockNumber ethrpc.BlockNumber
|
||||||
|
fullTx bool
|
||||||
|
baseFee *big.Int
|
||||||
|
validator sdk.AccAddress
|
||||||
|
tx *evmtypes.MsgEthereumTx
|
||||||
|
txBz []byte
|
||||||
|
registerMock func(ethrpc.BlockNumber, sdk.Int, sdk.AccAddress, []byte)
|
||||||
|
expNoop bool
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fail - tendermint block error",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
true,
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
func(blockNum ethrpc.BlockNumber, _ sdk.Int, _ sdk.AccAddress, _ []byte) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterBlockError(client, height)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block not found (e.g. request block height that is greater than current one)",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
true,
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
resBlock, _ = RegisterBlockNotFound(client, height)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block results error",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
true,
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
resBlock, _ = RegisterBlock(client, height, txBz)
|
||||||
|
RegisterBlockResultsError(client, blockNum.Int64())
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - without tx",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
true,
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
resBlock, _ = RegisterBlock(client, height, txBz)
|
||||||
|
blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - with tx",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
true,
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
msgEthereumTx,
|
||||||
|
bz,
|
||||||
|
func(blockNum ethrpc.BlockNumber, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
resBlock, _ = RegisterBlock(client, height, txBz)
|
||||||
|
blockRes, _ = RegisterBlockResults(client, blockNum.Int64())
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
tc.registerMock(tc.blockNumber, sdk.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz)
|
||||||
|
|
||||||
|
block, err := suite.backend.GetBlockByNumber(tc.blockNumber, tc.fullTx)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
if tc.expNoop {
|
||||||
|
suite.Require().Nil(block)
|
||||||
|
} else {
|
||||||
|
expBlock := suite.buildFormattedBlock(
|
||||||
|
blockRes,
|
||||||
|
resBlock,
|
||||||
|
tc.fullTx,
|
||||||
|
tc.tx,
|
||||||
|
tc.validator,
|
||||||
|
tc.baseFee,
|
||||||
|
)
|
||||||
|
suite.Require().Equal(expBlock, block)
|
||||||
|
}
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestGetBlockByHash() {
|
||||||
|
var (
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults
|
||||||
|
resBlock *tmrpctypes.ResultBlock
|
||||||
|
)
|
||||||
|
msgEthereumTx, bz := suite.buildEthereumTx()
|
||||||
|
|
||||||
|
block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
hash common.Hash
|
||||||
|
fullTx bool
|
||||||
|
baseFee *big.Int
|
||||||
|
validator sdk.AccAddress
|
||||||
|
tx *evmtypes.MsgEthereumTx
|
||||||
|
txBz []byte
|
||||||
|
registerMock func(common.Hash, sdk.Int, sdk.AccAddress, []byte)
|
||||||
|
expNoop bool
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"pass - without tx",
|
||||||
|
common.BytesToHash(block.Hash()),
|
||||||
|
true,
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
func(hash common.Hash, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
|
||||||
|
height := int64(1)
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
resBlock, _ = RegisterBlockByHash(client, hash, txBz)
|
||||||
|
|
||||||
|
blockRes, _ = RegisterBlockResults(client, height)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - with tx",
|
||||||
|
common.BytesToHash(block.Hash()),
|
||||||
|
true,
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
msgEthereumTx,
|
||||||
|
bz,
|
||||||
|
func(hash common.Hash, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) {
|
||||||
|
height := int64(1)
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
resBlock, _ = RegisterBlockByHash(client, hash, txBz)
|
||||||
|
|
||||||
|
blockRes, _ = RegisterBlockResults(client, height)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
tc.registerMock(tc.hash, sdk.NewIntFromBigInt(tc.baseFee), tc.validator, tc.txBz)
|
||||||
|
|
||||||
|
block, err := suite.backend.GetBlockByHash(tc.hash, tc.fullTx)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
if tc.expNoop {
|
||||||
|
suite.Require().Nil(block)
|
||||||
|
} else {
|
||||||
|
expBlock := suite.buildFormattedBlock(
|
||||||
|
blockRes,
|
||||||
|
resBlock,
|
||||||
|
tc.fullTx,
|
||||||
|
tc.tx,
|
||||||
|
tc.validator,
|
||||||
|
tc.baseFee,
|
||||||
|
)
|
||||||
|
suite.Require().Equal(expBlock, block)
|
||||||
|
}
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestGetTendermintBlockByNumber() {
|
||||||
|
var expResultBlock *tmrpctypes.ResultBlock
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
blockNumber ethrpc.BlockNumber
|
||||||
|
registerMock func(ethrpc.BlockNumber)
|
||||||
|
found bool
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fail - client error",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
func(blockNum ethrpc.BlockNumber) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterBlockError(client, height)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"noop - block not found",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
func(blockNum ethrpc.BlockNumber) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterBlockNotFound(client, height)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - blockNum < 0 with app state height error",
|
||||||
|
ethrpc.BlockNumber(-1),
|
||||||
|
func(_ ethrpc.BlockNumber) {
|
||||||
|
appHeight := int64(1)
|
||||||
|
var header metadata.MD
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterParamsError(queryClient, &header, appHeight)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - blockNum < 0 with app state height >= 1",
|
||||||
|
ethrpc.BlockNumber(-1),
|
||||||
|
func(blockNum ethrpc.BlockNumber) {
|
||||||
|
appHeight := int64(1)
|
||||||
|
var header metadata.MD
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterParams(queryClient, &header, appHeight)
|
||||||
|
|
||||||
|
tmHeight := appHeight
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
expResultBlock, _ = RegisterBlock(client, tmHeight, nil)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - blockNum = 0 (defaults to blockNum = 1 due to a difference between tendermint heights and geth heights",
|
||||||
|
ethrpc.BlockNumber(0),
|
||||||
|
func(blockNum ethrpc.BlockNumber) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
expResultBlock, _ = RegisterBlock(client, height, nil)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - blockNum = 1",
|
||||||
|
ethrpc.BlockNumber(1),
|
||||||
|
func(blockNum ethrpc.BlockNumber) {
|
||||||
|
height := blockNum.Int64()
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
expResultBlock, _ = RegisterBlock(client, height, nil)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
|
||||||
|
tc.registerMock(tc.blockNumber)
|
||||||
|
resultBlock, err := suite.backend.GetTendermintBlockByNumber(tc.blockNumber)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
|
if !tc.found {
|
||||||
|
suite.Require().Nil(resultBlock)
|
||||||
|
} else {
|
||||||
|
suite.Require().Equal(expResultBlock, resultBlock)
|
||||||
|
suite.Require().Equal(expResultBlock.Block.Header.Height, resultBlock.Block.Header.Height)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestGetTendermintBlockResultByNumber() {
|
||||||
|
var expBlockRes *tmrpctypes.ResultBlockResults
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
blockNumber int64
|
||||||
|
registerMock func(int64)
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fail",
|
||||||
|
1,
|
||||||
|
func(blockNum int64) {
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterBlockResultsError(client, blockNum)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass",
|
||||||
|
1,
|
||||||
|
func(blockNum int64) {
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterBlockResults(client, blockNum)
|
||||||
|
|
||||||
|
expBlockRes = &tmrpctypes.ResultBlockResults{
|
||||||
|
Height: blockNum,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
tc.registerMock(tc.blockNumber)
|
||||||
|
|
||||||
|
blockRes, err := suite.backend.GetTendermintBlockResultByNumber(&tc.blockNumber)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().Equal(expBlockRes, blockRes)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestBlockBloom() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults
|
||||||
|
expBlockBloom ethtypes.Bloom
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fail - empty block result",
|
||||||
|
&tmrpctypes.ResultBlockResults{},
|
||||||
|
ethtypes.Bloom{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - non block bloom event type",
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
EndBlockEvents: []types.Event{{Type: evmtypes.EventTypeEthereumTx}},
|
||||||
|
},
|
||||||
|
ethtypes.Bloom{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - nonblock bloom attribute key",
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
EndBlockEvents: []types.Event{
|
||||||
|
{
|
||||||
|
Type: evmtypes.EventTypeBlockBloom,
|
||||||
|
Attributes: []types.EventAttribute{
|
||||||
|
{Key: []byte(evmtypes.AttributeKeyEthereumTxHash)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ethtypes.Bloom{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - nonblock bloom attribute key",
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
EndBlockEvents: []types.Event{
|
||||||
|
{
|
||||||
|
Type: evmtypes.EventTypeBlockBloom,
|
||||||
|
Attributes: []types.EventAttribute{
|
||||||
|
{Key: []byte(bAttributeKeyEthereumBloom)},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ethtypes.Bloom{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
blockBloom, err := suite.backend.BlockBloom(tc.blockRes)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().Equal(tc.expBlockBloom, blockBloom)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestEthBlockFromTendermint() {
|
||||||
|
msgEthereumTx, bz := suite.buildEthereumTx()
|
||||||
|
emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
baseFee *big.Int
|
||||||
|
validator sdk.AccAddress
|
||||||
|
height int64
|
||||||
|
resBlock *tmrpctypes.ResultBlock
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults
|
||||||
|
fullTx bool
|
||||||
|
registerMock func(sdk.Int, sdk.AccAddress, int64)
|
||||||
|
expTxs bool
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"pass - block without tx",
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(common.Address{}.Bytes()),
|
||||||
|
int64(1),
|
||||||
|
&tmrpctypes.ResultBlock{Block: emptyBlock},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block with tx - with BaseFee error",
|
||||||
|
nil,
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
int64(1),
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block with tx - with ValidatorAccount error",
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(common.Address{}.Bytes()),
|
||||||
|
int64(1),
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccountError(queryClient)
|
||||||
|
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block with tx - with ConsensusParams error - BlockMaxGas defaults to max uint32",
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
int64(1),
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterConsensusParamsError(client, height)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block with tx - with ShouldIgnoreGasUsed - empty txs",
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
int64(1),
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{
|
||||||
|
{
|
||||||
|
Code: 11,
|
||||||
|
GasUsed: 0,
|
||||||
|
Log: "no block gas left to run tx: out of gas",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block with tx - non fullTx",
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
int64(1),
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass - block with tx",
|
||||||
|
sdk.NewInt(1).BigInt(),
|
||||||
|
sdk.AccAddress(tests.GenerateAddress().Bytes()),
|
||||||
|
int64(1),
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
func(baseFee sdk.Int, validator sdk.AccAddress, height int64) {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
|
||||||
|
client := suite.backend.clientCtx.Client.(*mocks.Client)
|
||||||
|
RegisterConsensusParams(client, height)
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
tc.registerMock(sdk.NewIntFromBigInt(tc.baseFee), tc.validator, tc.height)
|
||||||
|
|
||||||
|
block, err := suite.backend.EthBlockFromTendermint(tc.resBlock, tc.blockRes, tc.fullTx)
|
||||||
|
|
||||||
|
var expBlock map[string]interface{}
|
||||||
|
header := tc.resBlock.Block.Header
|
||||||
|
gasLimit := int64(^uint32(0)) // for `MaxGas = -1` (DefaultConsensusParams)
|
||||||
|
gasUsed := new(big.Int).SetUint64(uint64(tc.blockRes.TxsResults[0].GasUsed))
|
||||||
|
|
||||||
|
root := common.Hash{}.Bytes()
|
||||||
|
receipt := ethtypes.NewReceipt(root, false, gasUsed.Uint64())
|
||||||
|
bloom := ethtypes.CreateBloom(ethtypes.Receipts{receipt})
|
||||||
|
|
||||||
|
ethRPCTxs := []interface{}{}
|
||||||
|
|
||||||
|
if tc.expTxs {
|
||||||
|
if tc.fullTx {
|
||||||
|
rpcTx, err := ethrpc.NewRPCTransaction(
|
||||||
|
msgEthereumTx.AsTransaction(),
|
||||||
|
common.BytesToHash(header.Hash()),
|
||||||
|
uint64(header.Height),
|
||||||
|
uint64(0),
|
||||||
|
tc.baseFee,
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
ethRPCTxs = []interface{}{rpcTx}
|
||||||
|
} else {
|
||||||
|
ethRPCTxs = []interface{}{common.HexToHash(msgEthereumTx.Hash)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expBlock = ethrpc.FormatBlock(
|
||||||
|
header,
|
||||||
|
tc.resBlock.Block.Size(),
|
||||||
|
gasLimit,
|
||||||
|
gasUsed,
|
||||||
|
ethRPCTxs,
|
||||||
|
bloom,
|
||||||
|
common.BytesToAddress(tc.validator.Bytes()),
|
||||||
|
tc.baseFee,
|
||||||
|
)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().Equal(expBlock, block)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestBaseFee() {
|
||||||
|
baseFee := sdk.NewInt(1)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults
|
||||||
|
registerMock func()
|
||||||
|
expBaseFee *big.Int
|
||||||
|
expPass bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"fail - grpc BaseFee error",
|
||||||
|
&tmrpctypes.ResultBlockResults{Height: 1},
|
||||||
|
func() {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - grpc BaseFee error - with non feemarket block event",
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
BeginBlockEvents: []types.Event{
|
||||||
|
{
|
||||||
|
Type: evmtypes.EventTypeBlockBloom,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
func() {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - grpc BaseFee error - with feemarket block event",
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
BeginBlockEvents: []types.Event{
|
||||||
|
{
|
||||||
|
Type: feemarkettypes.EventTypeFeeMarket,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
func() {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - grpc BaseFee error - with feemarket block event with wrong attribute value",
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
BeginBlockEvents: []types.Event{
|
||||||
|
{
|
||||||
|
Type: feemarkettypes.EventTypeFeeMarket,
|
||||||
|
Attributes: []types.EventAttribute{
|
||||||
|
{Value: []byte{0x1}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
func() {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - grpc baseFee error - with feemarket block event with baseFee attribute value",
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
Height: 1,
|
||||||
|
BeginBlockEvents: []types.Event{
|
||||||
|
{
|
||||||
|
Type: feemarkettypes.EventTypeFeeMarket,
|
||||||
|
Attributes: []types.EventAttribute{
|
||||||
|
{Value: []byte(baseFee.String())},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
func() {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
},
|
||||||
|
baseFee.BigInt(),
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - base fee or london fork not enabled",
|
||||||
|
&tmrpctypes.ResultBlockResults{Height: 1},
|
||||||
|
func() {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFeeDisabled(queryClient)
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass",
|
||||||
|
&tmrpctypes.ResultBlockResults{Height: 1},
|
||||||
|
func() {
|
||||||
|
queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
},
|
||||||
|
baseFee.BigInt(),
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
tc.registerMock()
|
||||||
|
|
||||||
|
baseFee, err := suite.backend.BaseFee(tc.blockRes)
|
||||||
|
|
||||||
|
if tc.expPass {
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().Equal(tc.expBaseFee, baseFee)
|
||||||
|
} else {
|
||||||
|
suite.Require().Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *BackendTestSuite) TestGetEthereumMsgsFromTendermintBlock() {
|
||||||
|
msgEthereumTx, bz := suite.buildEthereumTx()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
resBlock *tmrpctypes.ResultBlock
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults
|
||||||
|
expMsgs []*evmtypes.MsgEthereumTx
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"tx in not included in block - unsuccessful tx without ExceedBlockGasLimit error",
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{
|
||||||
|
{
|
||||||
|
Code: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]*evmtypes.MsgEthereumTx(nil),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tx included in block - unsuccessful tx with ExceedBlockGasLimit error",
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{
|
||||||
|
{
|
||||||
|
Code: 1,
|
||||||
|
Log: ExceedBlockGasLimitError,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]*evmtypes.MsgEthereumTx{msgEthereumTx},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pass",
|
||||||
|
&tmrpctypes.ResultBlock{
|
||||||
|
Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil),
|
||||||
|
},
|
||||||
|
&tmrpctypes.ResultBlockResults{
|
||||||
|
TxsResults: []*types.ResponseDeliverTx{
|
||||||
|
{
|
||||||
|
Code: 0,
|
||||||
|
Log: ExceedBlockGasLimitError,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]*evmtypes.MsgEthereumTx{msgEthereumTx},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
|
||||||
|
|
||||||
|
suite.SetupTest() // reset test and queries
|
||||||
|
|
||||||
|
msgs := suite.backend.GetEthereumMsgsFromTendermintBlock(tc.resBlock, tc.blockRes)
|
||||||
|
suite.Require().Equal(tc.expMsgs, msgs)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
841
rpc/backend/mocks/client.go
Normal file
841
rpc/backend/mocks/client.go
Normal file
@ -0,0 +1,841 @@
|
|||||||
|
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
bytes "github.com/tendermint/tendermint/libs/bytes"
|
||||||
|
client "github.com/tendermint/tendermint/rpc/client"
|
||||||
|
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
coretypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
|
|
||||||
|
log "github.com/tendermint/tendermint/libs/log"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
types "github.com/tendermint/tendermint/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client is an autogenerated mock type for the Client type
|
||||||
|
type Client struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABCIInfo provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) ABCIInfo(_a0 context.Context) (*coretypes.ResultABCIInfo, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultABCIInfo
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultABCIInfo); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultABCIInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABCIQuery provides a mock function with given fields: ctx, path, data
|
||||||
|
func (_m *Client) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes) (*coretypes.ResultABCIQuery, error) {
|
||||||
|
ret := _m.Called(ctx, path, data)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultABCIQuery
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, bytes.HexBytes) *coretypes.ResultABCIQuery); ok {
|
||||||
|
r0 = rf(ctx, path, data)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultABCIQuery)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, bytes.HexBytes) error); ok {
|
||||||
|
r1 = rf(ctx, path, data)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ABCIQueryWithOptions provides a mock function with given fields: ctx, path, data, opts
|
||||||
|
func (_m *Client) ABCIQueryWithOptions(ctx context.Context, path string, data bytes.HexBytes, opts client.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error) {
|
||||||
|
ret := _m.Called(ctx, path, data, opts)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultABCIQuery
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, bytes.HexBytes, client.ABCIQueryOptions) *coretypes.ResultABCIQuery); ok {
|
||||||
|
r0 = rf(ctx, path, data, opts)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultABCIQuery)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, bytes.HexBytes, client.ABCIQueryOptions) error); ok {
|
||||||
|
r1 = rf(ctx, path, data, opts)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block provides a mock function with given fields: ctx, height
|
||||||
|
func (_m *Client) Block(ctx context.Context, height *int64) (*coretypes.ResultBlock, error) {
|
||||||
|
ret := _m.Called(ctx, height)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBlock
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultBlock); ok {
|
||||||
|
r0 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok {
|
||||||
|
r1 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockByHash provides a mock function with given fields: ctx, hash
|
||||||
|
func (_m *Client) BlockByHash(ctx context.Context, hash []byte) (*coretypes.ResultBlock, error) {
|
||||||
|
ret := _m.Called(ctx, hash)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBlock
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, []byte) *coretypes.ResultBlock); ok {
|
||||||
|
r0 = rf(ctx, hash)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, []byte) error); ok {
|
||||||
|
r1 = rf(ctx, hash)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockResults provides a mock function with given fields: ctx, height
|
||||||
|
func (_m *Client) BlockResults(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error) {
|
||||||
|
ret := _m.Called(ctx, height)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBlockResults
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultBlockResults); ok {
|
||||||
|
r0 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBlockResults)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok {
|
||||||
|
r1 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockSearch provides a mock function with given fields: ctx, query, page, perPage, orderBy
|
||||||
|
func (_m *Client) BlockSearch(ctx context.Context, query string, page *int, perPage *int, orderBy string) (*coretypes.ResultBlockSearch, error) {
|
||||||
|
ret := _m.Called(ctx, query, page, perPage, orderBy)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBlockSearch
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, *int, *int, string) *coretypes.ResultBlockSearch); ok {
|
||||||
|
r0 = rf(ctx, query, page, perPage, orderBy)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBlockSearch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, *int, *int, string) error); ok {
|
||||||
|
r1 = rf(ctx, query, page, perPage, orderBy)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockchainInfo provides a mock function with given fields: ctx, minHeight, maxHeight
|
||||||
|
func (_m *Client) BlockchainInfo(ctx context.Context, minHeight int64, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) {
|
||||||
|
ret := _m.Called(ctx, minHeight, maxHeight)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBlockchainInfo
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, int64, int64) *coretypes.ResultBlockchainInfo); ok {
|
||||||
|
r0 = rf(ctx, minHeight, maxHeight)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBlockchainInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, int64, int64) error); ok {
|
||||||
|
r1 = rf(ctx, minHeight, maxHeight)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastEvidence provides a mock function with given fields: _a0, _a1
|
||||||
|
func (_m *Client) BroadcastEvidence(_a0 context.Context, _a1 types.Evidence) (*coretypes.ResultBroadcastEvidence, error) {
|
||||||
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBroadcastEvidence
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, types.Evidence) *coretypes.ResultBroadcastEvidence); ok {
|
||||||
|
r0 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBroadcastEvidence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, types.Evidence) error); ok {
|
||||||
|
r1 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastTxAsync provides a mock function with given fields: _a0, _a1
|
||||||
|
func (_m *Client) BroadcastTxAsync(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultBroadcastTx, error) {
|
||||||
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBroadcastTx
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultBroadcastTx); ok {
|
||||||
|
r0 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBroadcastTx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok {
|
||||||
|
r1 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastTxCommit provides a mock function with given fields: _a0, _a1
|
||||||
|
func (_m *Client) BroadcastTxCommit(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
|
||||||
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBroadcastTxCommit
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultBroadcastTxCommit); ok {
|
||||||
|
r0 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBroadcastTxCommit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok {
|
||||||
|
r1 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// BroadcastTxSync provides a mock function with given fields: _a0, _a1
|
||||||
|
func (_m *Client) BroadcastTxSync(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultBroadcastTx, error) {
|
||||||
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultBroadcastTx
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultBroadcastTx); ok {
|
||||||
|
r0 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultBroadcastTx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok {
|
||||||
|
r1 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// CheckTx provides a mock function with given fields: _a0, _a1
|
||||||
|
func (_m *Client) CheckTx(_a0 context.Context, _a1 types.Tx) (*coretypes.ResultCheckTx, error) {
|
||||||
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultCheckTx
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, types.Tx) *coretypes.ResultCheckTx); ok {
|
||||||
|
r0 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultCheckTx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, types.Tx) error); ok {
|
||||||
|
r1 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit provides a mock function with given fields: ctx, height
|
||||||
|
func (_m *Client) Commit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error) {
|
||||||
|
ret := _m.Called(ctx, height)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultCommit
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultCommit); ok {
|
||||||
|
r0 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultCommit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok {
|
||||||
|
r1 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsensusParams provides a mock function with given fields: ctx, height
|
||||||
|
func (_m *Client) ConsensusParams(ctx context.Context, height *int64) (*coretypes.ResultConsensusParams, error) {
|
||||||
|
ret := _m.Called(ctx, height)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultConsensusParams
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *int64) *coretypes.ResultConsensusParams); ok {
|
||||||
|
r0 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultConsensusParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *int64) error); ok {
|
||||||
|
r1 = rf(ctx, height)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConsensusState provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) ConsensusState(_a0 context.Context) (*coretypes.ResultConsensusState, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultConsensusState
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultConsensusState); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultConsensusState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DumpConsensusState provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) DumpConsensusState(_a0 context.Context) (*coretypes.ResultDumpConsensusState, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultDumpConsensusState
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultDumpConsensusState); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultDumpConsensusState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Genesis provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) Genesis(_a0 context.Context) (*coretypes.ResultGenesis, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultGenesis
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultGenesis); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultGenesis)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenesisChunked provides a mock function with given fields: _a0, _a1
|
||||||
|
func (_m *Client) GenesisChunked(_a0 context.Context, _a1 uint) (*coretypes.ResultGenesisChunk, error) {
|
||||||
|
ret := _m.Called(_a0, _a1)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultGenesisChunk
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, uint) *coretypes.ResultGenesisChunk); ok {
|
||||||
|
r0 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultGenesisChunk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok {
|
||||||
|
r1 = rf(_a0, _a1)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Health provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) Health(_a0 context.Context) (*coretypes.ResultHealth, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultHealth
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultHealth); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultHealth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRunning provides a mock function with given fields:
|
||||||
|
func (_m *Client) IsRunning() bool {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 bool
|
||||||
|
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetInfo provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) NetInfo(_a0 context.Context) (*coretypes.ResultNetInfo, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultNetInfo
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultNetInfo); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultNetInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumUnconfirmedTxs provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) NumUnconfirmedTxs(_a0 context.Context) (*coretypes.ResultUnconfirmedTxs, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultUnconfirmedTxs
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultUnconfirmedTxs); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultUnconfirmedTxs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnReset provides a mock function with given fields:
|
||||||
|
func (_m *Client) OnReset() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnStart provides a mock function with given fields:
|
||||||
|
func (_m *Client) OnStart() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnStop provides a mock function with given fields:
|
||||||
|
func (_m *Client) OnStop() {
|
||||||
|
_m.Called()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quit provides a mock function with given fields:
|
||||||
|
func (_m *Client) Quit() <-chan struct{} {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 <-chan struct{}
|
||||||
|
if rf, ok := ret.Get(0).(func() <-chan struct{}); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(<-chan struct{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset provides a mock function with given fields:
|
||||||
|
func (_m *Client) Reset() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLogger provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) SetLogger(_a0 log.Logger) {
|
||||||
|
_m.Called(_a0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start provides a mock function with given fields:
|
||||||
|
func (_m *Client) Start() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status provides a mock function with given fields: _a0
|
||||||
|
func (_m *Client) Status(_a0 context.Context) (*coretypes.ResultStatus, error) {
|
||||||
|
ret := _m.Called(_a0)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultStatus
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultStatus); ok {
|
||||||
|
r0 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||||
|
r1 = rf(_a0)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop provides a mock function with given fields:
|
||||||
|
func (_m *Client) Stop() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// String provides a mock function with given fields:
|
||||||
|
func (_m *Client) String() string {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 string
|
||||||
|
if rf, ok := ret.Get(0).(func() string); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe provides a mock function with given fields: ctx, subscriber, query, outCapacity
|
||||||
|
func (_m *Client) Subscribe(ctx context.Context, subscriber string, query string, outCapacity ...int) (<-chan coretypes.ResultEvent, error) {
|
||||||
|
_va := make([]interface{}, len(outCapacity))
|
||||||
|
for _i := range outCapacity {
|
||||||
|
_va[_i] = outCapacity[_i]
|
||||||
|
}
|
||||||
|
var _ca []interface{}
|
||||||
|
_ca = append(_ca, ctx, subscriber, query)
|
||||||
|
_ca = append(_ca, _va...)
|
||||||
|
ret := _m.Called(_ca...)
|
||||||
|
|
||||||
|
var r0 <-chan coretypes.ResultEvent
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string, ...int) <-chan coretypes.ResultEvent); ok {
|
||||||
|
r0 = rf(ctx, subscriber, query, outCapacity...)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(<-chan coretypes.ResultEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, string, ...int) error); ok {
|
||||||
|
r1 = rf(ctx, subscriber, query, outCapacity...)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tx provides a mock function with given fields: ctx, hash, prove
|
||||||
|
func (_m *Client) Tx(ctx context.Context, hash []byte, prove bool) (*coretypes.ResultTx, error) {
|
||||||
|
ret := _m.Called(ctx, hash, prove)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultTx
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, []byte, bool) *coretypes.ResultTx); ok {
|
||||||
|
r0 = rf(ctx, hash, prove)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultTx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, []byte, bool) error); ok {
|
||||||
|
r1 = rf(ctx, hash, prove)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxSearch provides a mock function with given fields: ctx, query, prove, page, perPage, orderBy
|
||||||
|
func (_m *Client) TxSearch(ctx context.Context, query string, prove bool, page *int, perPage *int, orderBy string) (*coretypes.ResultTxSearch, error) {
|
||||||
|
ret := _m.Called(ctx, query, prove, page, perPage, orderBy)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultTxSearch
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, bool, *int, *int, string) *coretypes.ResultTxSearch); ok {
|
||||||
|
r0 = rf(ctx, query, prove, page, perPage, orderBy)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultTxSearch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, string, bool, *int, *int, string) error); ok {
|
||||||
|
r1 = rf(ctx, query, prove, page, perPage, orderBy)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnconfirmedTxs provides a mock function with given fields: ctx, limit
|
||||||
|
func (_m *Client) UnconfirmedTxs(ctx context.Context, limit *int) (*coretypes.ResultUnconfirmedTxs, error) {
|
||||||
|
ret := _m.Called(ctx, limit)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultUnconfirmedTxs
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *int) *coretypes.ResultUnconfirmedTxs); ok {
|
||||||
|
r0 = rf(ctx, limit)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultUnconfirmedTxs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *int) error); ok {
|
||||||
|
r1 = rf(ctx, limit)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsubscribe provides a mock function with given fields: ctx, subscriber, query
|
||||||
|
func (_m *Client) Unsubscribe(ctx context.Context, subscriber string, query string) error {
|
||||||
|
ret := _m.Called(ctx, subscriber, query)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||||
|
r0 = rf(ctx, subscriber, query)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnsubscribeAll provides a mock function with given fields: ctx, subscriber
|
||||||
|
func (_m *Client) UnsubscribeAll(ctx context.Context, subscriber string) error {
|
||||||
|
ret := _m.Called(ctx, subscriber)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||||
|
r0 = rf(ctx, subscriber)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validators provides a mock function with given fields: ctx, height, page, perPage
|
||||||
|
func (_m *Client) Validators(ctx context.Context, height *int64, page *int, perPage *int) (*coretypes.ResultValidators, error) {
|
||||||
|
ret := _m.Called(ctx, height, page, perPage)
|
||||||
|
|
||||||
|
var r0 *coretypes.ResultValidators
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *int64, *int, *int) *coretypes.ResultValidators); ok {
|
||||||
|
r0 = rf(ctx, height, page, perPage)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*coretypes.ResultValidators)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *int64, *int, *int) error); ok {
|
||||||
|
r1 = rf(ctx, height, page, perPage)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockConstructorTestingTNewClient interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient creates a new instance of Client. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
func NewClient(t mockConstructorTestingTNewClient) *Client {
|
||||||
|
mock := &Client{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
160
rpc/backend/query_client_test.go
Normal file
160
rpc/backend/query_client_test.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package backend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
|
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
|
||||||
|
"github.com/evmos/ethermint/rpc/backend/mocks"
|
||||||
|
rpc "github.com/evmos/ethermint/rpc/types"
|
||||||
|
"github.com/evmos/ethermint/tests"
|
||||||
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QueryClient defines a mocked object that implements the ethermint GRPC
|
||||||
|
// QueryClient interface. It allows for performing QueryClient queries without having
|
||||||
|
// to run a ethermint GRPC server.
|
||||||
|
//
|
||||||
|
// To use a mock method it has to be registered in a given test.
|
||||||
|
var _ evmtypes.QueryClient = &mocks.QueryClient{}
|
||||||
|
|
||||||
|
// Params
|
||||||
|
func RegisterParams(queryClient *mocks.QueryClient, header *metadata.MD, height int64) {
|
||||||
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
||||||
|
Return(&evmtypes.QueryParamsResponse{}, nil).
|
||||||
|
Run(func(args mock.Arguments) {
|
||||||
|
// If Params call is successful, also update the header height
|
||||||
|
arg := args.Get(2).(grpc.HeaderCallOption)
|
||||||
|
h := metadata.MD{}
|
||||||
|
h.Set(grpctypes.GRPCBlockHeightHeader, fmt.Sprint(height))
|
||||||
|
*arg.HeaderAddr = h
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterParamsInvalidHeader(queryClient *mocks.QueryClient, header *metadata.MD, height int64) {
|
||||||
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
||||||
|
Return(&evmtypes.QueryParamsResponse{}, nil).
|
||||||
|
Run(func(args mock.Arguments) {
|
||||||
|
// If Params call is successful, also update the header height
|
||||||
|
arg := args.Get(2).(grpc.HeaderCallOption)
|
||||||
|
h := metadata.MD{}
|
||||||
|
*arg.HeaderAddr = h
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterParamsInvalidHeight(queryClient *mocks.QueryClient, header *metadata.MD, height int64) {
|
||||||
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
||||||
|
Return(&evmtypes.QueryParamsResponse{}, nil).
|
||||||
|
Run(func(args mock.Arguments) {
|
||||||
|
// If Params call is successful, also update the header height
|
||||||
|
arg := args.Get(2).(grpc.HeaderCallOption)
|
||||||
|
h := metadata.MD{}
|
||||||
|
h.Set(grpctypes.GRPCBlockHeightHeader, "invalid")
|
||||||
|
*arg.HeaderAddr = h
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Params returns error
|
||||||
|
func RegisterParamsError(queryClient *mocks.QueryClient, header *metadata.MD, height int64) {
|
||||||
|
queryClient.On("Params", rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(header)).
|
||||||
|
Return(nil, sdkerrors.ErrInvalidRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterParams(t *testing.T) {
|
||||||
|
queryClient := mocks.NewQueryClient(t)
|
||||||
|
var header metadata.MD
|
||||||
|
height := int64(1)
|
||||||
|
RegisterParams(queryClient, &header, height)
|
||||||
|
|
||||||
|
_, err := queryClient.Params(rpc.ContextWithHeight(height), &evmtypes.QueryParamsRequest{}, grpc.Header(&header))
|
||||||
|
require.NoError(t, err)
|
||||||
|
blockHeightHeader := header.Get(grpctypes.GRPCBlockHeightHeader)
|
||||||
|
headerHeight, err := strconv.ParseInt(blockHeightHeader[0], 10, 64)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, height, headerHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterParamsError(t *testing.T) {
|
||||||
|
queryClient := mocks.NewQueryClient(t)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
_, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BaseFee
|
||||||
|
func RegisterBaseFee(queryClient *mocks.QueryClient, baseFee sdk.Int) {
|
||||||
|
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
||||||
|
Return(&evmtypes.QueryBaseFeeResponse{BaseFee: &baseFee}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base fee returns error
|
||||||
|
func RegisterBaseFeeError(queryClient *mocks.QueryClient) {
|
||||||
|
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
||||||
|
Return(&evmtypes.QueryBaseFeeResponse{}, evmtypes.ErrInvalidBaseFee)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base fee not enabled
|
||||||
|
func RegisterBaseFeeDisabled(queryClient *mocks.QueryClient) {
|
||||||
|
queryClient.On("BaseFee", rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{}).
|
||||||
|
Return(&evmtypes.QueryBaseFeeResponse{}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterBaseFee(t *testing.T) {
|
||||||
|
baseFee := sdk.NewInt(1)
|
||||||
|
queryClient := mocks.NewQueryClient(t)
|
||||||
|
RegisterBaseFee(queryClient, baseFee)
|
||||||
|
res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
||||||
|
require.Equal(t, &evmtypes.QueryBaseFeeResponse{BaseFee: &baseFee}, res)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterBaseFeeError(t *testing.T) {
|
||||||
|
queryClient := mocks.NewQueryClient(t)
|
||||||
|
RegisterBaseFeeError(queryClient)
|
||||||
|
res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
||||||
|
require.Equal(t, &evmtypes.QueryBaseFeeResponse{}, res)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterBaseFeeDisabled(t *testing.T) {
|
||||||
|
queryClient := mocks.NewQueryClient(t)
|
||||||
|
RegisterBaseFeeDisabled(queryClient)
|
||||||
|
res, err := queryClient.BaseFee(rpc.ContextWithHeight(1), &evmtypes.QueryBaseFeeRequest{})
|
||||||
|
require.Equal(t, &evmtypes.QueryBaseFeeResponse{}, res)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidatorAccount
|
||||||
|
func RegisterValidatorAccount(queryClient *mocks.QueryClient, validator sdk.AccAddress) {
|
||||||
|
queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}).
|
||||||
|
Return(
|
||||||
|
&evmtypes.QueryValidatorAccountResponse{
|
||||||
|
AccountAddress: validator.String(),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterValidatorAccountError(queryClient *mocks.QueryClient) {
|
||||||
|
queryClient.On("ValidatorAccount", rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{}).
|
||||||
|
Return(nil, status.Error(codes.InvalidArgument, "empty request"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegisterValidatorAccount(t *testing.T) {
|
||||||
|
queryClient := mocks.NewQueryClient(t)
|
||||||
|
|
||||||
|
validator := sdk.AccAddress(tests.GenerateAddress().Bytes())
|
||||||
|
RegisterValidatorAccount(queryClient, validator)
|
||||||
|
res, err := queryClient.ValidatorAccount(rpc.ContextWithHeight(1), &evmtypes.QueryValidatorAccountRequest{})
|
||||||
|
require.Equal(t, &evmtypes.QueryValidatorAccountResponse{AccountAddress: validator.String()}, res)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
@ -380,7 +380,8 @@ func TxExceedBlockGasLimit(res *abci.ResponseDeliverTx) bool {
|
|||||||
return strings.Contains(res.Log, ExceedBlockGasLimitError)
|
return strings.Contains(res.Log, ExceedBlockGasLimitError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxSuccessOrExceedsBlockGasLimit returns if the tx should be included in json-rpc responses
|
// TxSuccessOrExceedsBlockGasLimit returnsrue if the transaction was successful
|
||||||
|
// or if it failed with an ExceedBlockGasLimit error
|
||||||
func TxSuccessOrExceedsBlockGasLimit(res *abci.ResponseDeliverTx) bool {
|
func TxSuccessOrExceedsBlockGasLimit(res *abci.ResponseDeliverTx) bool {
|
||||||
return res.Code == 0 || TxExceedBlockGasLimit(res)
|
return res.Code == 0 || TxExceedBlockGasLimit(res)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
@ -38,6 +37,7 @@ import (
|
|||||||
|
|
||||||
"github.com/evmos/ethermint/crypto/hd"
|
"github.com/evmos/ethermint/crypto/hd"
|
||||||
"github.com/evmos/ethermint/rpc/backend"
|
"github.com/evmos/ethermint/rpc/backend"
|
||||||
|
|
||||||
rpctypes "github.com/evmos/ethermint/rpc/types"
|
rpctypes "github.com/evmos/ethermint/rpc/types"
|
||||||
ethermint "github.com/evmos/ethermint/types"
|
ethermint "github.com/evmos/ethermint/types"
|
||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
@ -583,26 +583,6 @@ func (e *PublicAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error)
|
|||||||
return txHash, nil
|
return txHash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkTxFee is an internal function used to check whether the fee of
|
|
||||||
// the given transaction is _reasonable_(under the cap).
|
|
||||||
func checkTxFee(gasPrice *big.Int, gas uint64, cap float64) error {
|
|
||||||
// Short circuit if there is no cap for transaction fee at all.
|
|
||||||
if cap == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
totalfee := new(big.Float).SetInt(new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(gas)))
|
|
||||||
// 1 photon in 10^18 aphoton
|
|
||||||
oneToken := new(big.Float).SetInt(big.NewInt(params.Ether))
|
|
||||||
// quo = rounded(x/y)
|
|
||||||
feeEth := new(big.Float).Quo(totalfee, oneToken)
|
|
||||||
// no need to check error from parsing
|
|
||||||
feeFloat, _ := feeEth.Float64()
|
|
||||||
if feeFloat > cap {
|
|
||||||
return fmt.Errorf("tx fee (%.2f ether) exceeds the configured cap (%.2f ether)", feeFloat, cap)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resend accepts an existing transaction and a new gas price and limit. It will remove
|
// Resend accepts an existing transaction and a new gas price and limit. It will remove
|
||||||
// the given transaction from the pool and reinsert it with the new gas price and limit.
|
// the given transaction from the pool and reinsert it with the new gas price and limit.
|
||||||
func (e *PublicAPI) Resend(ctx context.Context, args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
|
func (e *PublicAPI) Resend(ctx context.Context, args evmtypes.TransactionArgs, gasPrice *hexutil.Big, gasLimit *hexutil.Uint64) (common.Hash, error) {
|
||||||
@ -627,7 +607,7 @@ func (e *PublicAPI) Resend(ctx context.Context, args evmtypes.TransactionArgs, g
|
|||||||
if gasLimit != nil {
|
if gasLimit != nil {
|
||||||
gas = uint64(*gasLimit)
|
gas = uint64(*gasLimit)
|
||||||
}
|
}
|
||||||
if err := checkTxFee(price, gas, e.backend.RPCTxFeeCap()); err != nil {
|
if err := rpctypes.CheckTxFee(price, gas, e.backend.RPCTxFeeCap()); err != nil {
|
||||||
return common.Hash{}, err
|
return common.Hash{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,6 +737,42 @@ func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransac
|
|||||||
return e.backend.GetTransactionByHash(hash)
|
return e.backend.GetTransactionByHash(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index.
|
||||||
|
func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
||||||
|
e.logger.Debug("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx)
|
||||||
|
|
||||||
|
block, err := e.clientCtx.Client.BlockByHash(e.ctx, hash.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
e.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if block.Block == nil {
|
||||||
|
e.logger.Debug("block not found", "hash", hash.Hex())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.getTransactionByBlockAndIndex(block, idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index.
|
||||||
|
func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
||||||
|
e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx)
|
||||||
|
|
||||||
|
block, err := e.backend.GetTendermintBlockByNumber(blockNum)
|
||||||
|
if err != nil {
|
||||||
|
e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if block.Block == nil {
|
||||||
|
e.logger.Debug("block not found", "height", blockNum.Int64())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.getTransactionByBlockAndIndex(block, idx)
|
||||||
|
}
|
||||||
|
|
||||||
// getTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`.
|
// getTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`.
|
||||||
func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
||||||
blockRes, err := e.backend.GetTendermintBlockResultByNumber(&block.Block.Height)
|
blockRes, err := e.backend.GetTendermintBlockResultByNumber(&block.Block.Height)
|
||||||
@ -817,42 +833,6 @@ func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index.
|
|
||||||
func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
|
||||||
e.logger.Debug("eth_getTransactionByBlockHashAndIndex", "hash", hash.Hex(), "index", idx)
|
|
||||||
|
|
||||||
block, err := e.clientCtx.Client.BlockByHash(e.ctx, hash.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
e.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error())
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if block.Block == nil {
|
|
||||||
e.logger.Debug("block not found", "hash", hash.Hex())
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.getTransactionByBlockAndIndex(block, idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index.
|
|
||||||
func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
|
||||||
e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx)
|
|
||||||
|
|
||||||
block, err := e.backend.GetTendermintBlockByNumber(blockNum)
|
|
||||||
if err != nil {
|
|
||||||
e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error())
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if block.Block == nil {
|
|
||||||
e.logger.Debug("block not found", "height", blockNum.Int64())
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return e.getTransactionByBlockAndIndex(block, idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTransactionReceipt returns the transaction receipt identified by hash.
|
// GetTransactionReceipt returns the transaction receipt identified by hash.
|
||||||
func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
|
func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
|
||||||
hexTx := hash.Hex()
|
hexTx := hash.Hex()
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes.
|
// RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes.
|
||||||
@ -222,3 +223,23 @@ func BaseFeeFromEvents(events []abci.Event) *big.Int {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckTxFee is an internal function used to check whether the fee of
|
||||||
|
// the given transaction is _reasonable_(under the cap).
|
||||||
|
func CheckTxFee(gasPrice *big.Int, gas uint64, cap float64) error {
|
||||||
|
// Short circuit if there is no cap for transaction fee at all.
|
||||||
|
if cap == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
totalfee := new(big.Float).SetInt(new(big.Int).Mul(gasPrice, new(big.Int).SetUint64(gas)))
|
||||||
|
// 1 photon in 10^18 aphoton
|
||||||
|
oneToken := new(big.Float).SetInt(big.NewInt(params.Ether))
|
||||||
|
// quo = rounded(x/y)
|
||||||
|
feeEth := new(big.Float).Quo(totalfee, oneToken)
|
||||||
|
// no need to check error from parsing
|
||||||
|
feeFloat, _ := feeEth.Float64()
|
||||||
|
if feeFloat > cap {
|
||||||
|
return fmt.Errorf("tx fee (%.2f ether) exceeds the configured cap (%.2f ether)", feeFloat, cap)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -89,6 +89,7 @@ func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRe
|
|||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidatorAccount implements the Query/Balance gRPC method
|
||||||
func (k Keeper) ValidatorAccount(c context.Context, req *types.QueryValidatorAccountRequest) (*types.QueryValidatorAccountResponse, error) {
|
func (k Keeper) ValidatorAccount(c context.Context, req *types.QueryValidatorAccountRequest) (*types.QueryValidatorAccountResponse, error) {
|
||||||
if req == nil {
|
if req == nil {
|
||||||
return nil, status.Error(codes.InvalidArgument, "empty request")
|
return nil, status.Error(codes.InvalidArgument, "empty request")
|
||||||
|
Loading…
Reference in New Issue
Block a user