rpc, evm: gRPC tests (#28)

* rpc, evm: grpc tests

* address validation

* update rpc

* test cleanup

* additional tests
This commit is contained in:
Federico Kunze
2021-05-17 06:13:08 -04:00
committed by GitHub
parent 7c206554b7
commit 2c722d03ce
18 changed files with 982 additions and 376 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
// TODO: why do we have so many hash -> height mappings
k.SetBlockHash(ctx, req.Hash, req.Header.Height)
k.SetBlockHeightToHash(ctx, req.Hash, req.Header.Height)
k.SetBlockHeightToHash(ctx, common.BytesToHash(req.Hash), req.Header.Height)
// special setter for csdb
k.SetHeightHash(ctx, uint64(req.Header.Height), common.BytesToHash(req.Hash))
+32 -52
View File
@@ -25,10 +25,9 @@ func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsZeroAddress(req.Address) {
if err := ethermint.ValidateAddress(req.Address); err != nil {
return nil, status.Error(
codes.InvalidArgument,
types.ErrZeroAddress.Error(),
codes.InvalidArgument, err.Error(),
)
}
@@ -47,34 +46,31 @@ func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ
}
func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRequest) (*types.QueryCosmosAccountResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsZeroAddress(req.Address) {
if err := ethermint.ValidateAddress(req.Address); err != nil {
return nil, status.Error(
codes.InvalidArgument,
types.ErrZeroAddress.Error(),
codes.InvalidArgument, err.Error(),
)
}
ctx := sdk.UnwrapSDKContext(c)
ethStr := req.Address
ethAddr := ethcmn.FromHex(ethStr)
ethAddr := ethcmn.HexToAddress(req.Address)
cosmosAddr := sdk.AccAddress(ethAddr.Bytes())
ethToCosmosAddr := sdk.AccAddress(ethAddr[:]).String()
cosmosToEthAddr, _ := sdk.AccAddressFromBech32(ethToCosmosAddr)
acc := k.accountKeeper.GetAccount(ctx, cosmosToEthAddr)
account := k.accountKeeper.GetAccount(ctx, cosmosAddr)
res := types.QueryCosmosAccountResponse{
CosmosAddress: cosmosToEthAddr.String(),
CosmosAddress: cosmosAddr.String(),
}
if acc != nil {
res.Sequence = acc.GetSequence()
res.AccountNumber = acc.GetAccountNumber()
if account != nil {
res.Sequence = account.GetSequence()
res.AccountNumber = account.GetAccountNumber()
}
return &res, nil
}
@@ -84,7 +80,7 @@ func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*typ
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsZeroAddress(req.Address) {
if err := ethermint.ValidateAddress(req.Address); err != nil {
return nil, status.Error(
codes.InvalidArgument,
types.ErrZeroAddress.Error(),
@@ -109,12 +105,11 @@ func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*typ
// Storage implements the Query/Storage gRPC method
func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*types.QueryStorageResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsZeroAddress(req.Address) {
if err := ethermint.ValidateAddress(req.Address); err != nil {
return nil, status.Error(
codes.InvalidArgument,
types.ErrZeroAddress.Error(),
@@ -139,7 +134,7 @@ func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsZeroAddress(req.Address) {
if err := ethermint.ValidateAddress(req.Address); err != nil {
return nil, status.Error(
codes.InvalidArgument,
types.ErrZeroAddress.Error(),
@@ -162,7 +157,7 @@ func (k Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsEmptyHash(req.Hash) {
if ethermint.IsEmptyHash(req.Hash) {
return nil, status.Error(
codes.InvalidArgument,
types.ErrEmptyHash.Error(),
@@ -187,12 +182,11 @@ func (k Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types
// TxReceipt implements the Query/TxReceipt gRPC method
func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) (*types.QueryTxReceiptResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsEmptyHash(req.Hash) {
if ethermint.IsEmptyHash(req.Hash) {
return nil, status.Error(
codes.InvalidArgument,
types.ErrEmptyHash.Error(),
@@ -204,8 +198,8 @@ func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) (
hash := ethcmn.HexToHash(req.Hash)
receipt, found := k.GetTxReceiptFromHash(ctx, hash)
if !found {
return nil, status.Error(
codes.NotFound, types.ErrTxReceiptNotFound.Error(),
return nil, status.Errorf(
codes.NotFound, "%s: %s", types.ErrTxReceiptNotFound.Error(), req.Hash,
)
}
@@ -215,14 +209,10 @@ func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) (
}
// TxReceiptsByBlockHeight implements the Query/TxReceiptsByBlockHeight gRPC method
func (k Keeper) TxReceiptsByBlockHeight(c context.Context, req *types.QueryTxReceiptsByBlockHeightRequest) (*types.QueryTxReceiptsByBlockHeightResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
func (k Keeper) TxReceiptsByBlockHeight(c context.Context, _ *types.QueryTxReceiptsByBlockHeightRequest) (*types.QueryTxReceiptsByBlockHeightResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
receipts := k.GetTxReceiptsByBlockHeight(ctx, req.Height)
receipts := k.GetTxReceiptsByBlockHeight(ctx, ctx.BlockHeight())
return &types.QueryTxReceiptsByBlockHeightResponse{
Receipts: receipts,
}, nil
@@ -234,7 +224,7 @@ func (k Keeper) TxReceiptsByBlockHash(c context.Context, req *types.QueryTxRecei
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsEmptyHash(req.Hash) {
if ethermint.IsEmptyHash(req.Hash) {
return nil, status.Error(
codes.InvalidArgument,
types.ErrEmptyHash.Error(),
@@ -253,12 +243,11 @@ func (k Keeper) TxReceiptsByBlockHash(c context.Context, req *types.QueryTxRecei
// BlockLogs implements the Query/BlockLogs gRPC method
func (k Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (*types.QueryBlockLogsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
if types.IsEmptyHash(req.Hash) {
if ethermint.IsEmptyHash(req.Hash) {
return nil, status.Error(
codes.InvalidArgument,
types.ErrEmptyHash.Error(),
@@ -275,19 +264,10 @@ func (k Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (
}
// BlockBloom implements the Query/BlockBloom gRPC method
func (k Keeper) BlockBloom(c context.Context, req *types.QueryBlockBloomRequest) (*types.QueryBlockBloomResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
func (k Keeper) BlockBloom(c context.Context, _ *types.QueryBlockBloomRequest) (*types.QueryBlockBloomResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
height := ctx.BlockHeight()
if setHeight := req.Height; setHeight > 0 {
height = setHeight
}
bloom, found := k.GetBlockBloom(ctx, height)
bloom, found := k.GetBlockBloom(ctx, ctx.BlockHeight())
if !found {
return nil, status.Error(
codes.NotFound, types.ErrBloomNotFound.Error(),
@@ -300,11 +280,7 @@ func (k Keeper) BlockBloom(c context.Context, req *types.QueryBlockBloomRequest)
}
// Params implements the Query/Params gRPC method
func (k Keeper) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}
func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
ctx := sdk.UnwrapSDKContext(c)
params := k.GetParams(ctx)
@@ -342,9 +318,12 @@ func (k Keeper) StaticCall(c context.Context, req *types.QueryStaticCallRequest)
msg := types.NewMsgEthereumTx(
chainIDEpoch, so.Nonce(), recipient, big.NewInt(0), 100000000, big.NewInt(0), req.Input, nil,
)
msg.From = sender.Hex()
if err := msg.ValidateBasic(); err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
ethMsg, err := msg.AsMessage()
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
@@ -356,6 +335,7 @@ func (k Keeper) StaticCall(c context.Context, req *types.QueryStaticCallRequest)
ChainID: chainIDEpoch,
TxHash: &ethHash,
Simulate: ctx.IsCheckTx(),
Debug: false,
}
config, found := k.GetChainConfig(ctx)
+786
View File
@@ -0,0 +1,786 @@
package keeper_test
import (
"fmt"
"google.golang.org/grpc/metadata"
ethcmn "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm/types"
grpctypes "github.com/cosmos/cosmos-sdk/types/grpc"
)
func (suite *KeeperTestSuite) TestQueryAccount() {
var (
req *types.QueryAccountRequest
expAccount *types.QueryAccountResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"zero address",
func() {
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0))
expAccount = &types.QueryAccountResponse{
Balance: "0",
CodeHash: ethcrypto.Keccak256(nil),
Nonce: 0,
}
req = &types.QueryAccountRequest{
Address: ethcmn.Address{}.String(),
}
},
false,
},
{
"success",
func() {
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(100))
expAccount = &types.QueryAccountResponse{
Balance: "100",
CodeHash: ethcrypto.Keccak256(nil),
Nonce: 0,
}
req = &types.QueryAccountRequest{
Address: suite.address.String(),
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.Account(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expAccount, res)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryCosmosAccount() {
var (
req *types.QueryCosmosAccountRequest
expAccount *types.QueryCosmosAccountResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"zero address",
func() {
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0))
expAccount = &types.QueryCosmosAccountResponse{
CosmosAddress: sdk.AccAddress(ethcmn.Address{}.Bytes()).String(),
}
req = &types.QueryCosmosAccountRequest{
Address: ethcmn.Address{}.String(),
}
},
false,
},
{
"success",
func() {
expAccount = &types.QueryCosmosAccountResponse{
CosmosAddress: sdk.AccAddress(suite.address.Bytes()).String(),
Sequence: 0,
AccountNumber: 0,
}
req = &types.QueryCosmosAccountRequest{
Address: suite.address.String(),
}
},
true,
},
{
"success with seq and account number",
func() {
acc := suite.app.AccountKeeper.GetAccount(suite.ctx, suite.address.Bytes())
suite.Require().NoError(acc.SetSequence(10))
suite.Require().NoError(acc.SetAccountNumber(1))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
expAccount = &types.QueryCosmosAccountResponse{
CosmosAddress: sdk.AccAddress(suite.address.Bytes()).String(),
Sequence: 10,
AccountNumber: 1,
}
req = &types.QueryCosmosAccountRequest{
Address: suite.address.String(),
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.CosmosAccount(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expAccount, res)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryBalance() {
var (
req *types.QueryBalanceRequest
expBalance string
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"zero address",
func() {
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0))
expBalance = "0"
req = &types.QueryBalanceRequest{
Address: ethcmn.Address{}.String(),
}
},
false,
},
{
"success",
func() {
suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(100))
expBalance = "100"
req = &types.QueryBalanceRequest{
Address: suite.address.String(),
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.Balance(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expBalance, res.Balance)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryStorage() {
var (
req *types.QueryStorageRequest
expValue string
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"zero address",
func() {
req = &types.QueryStorageRequest{
Address: ethcmn.Address{}.String(),
}
},
false,
},
{"empty hash",
func() {
req = &types.QueryStorageRequest{
Address: suite.address.String(),
Key: ethcmn.Hash{}.String(),
}
exp := &types.QueryStorageResponse{Value: "0x0000000000000000000000000000000000000000000000000000000000000000"}
expValue = exp.Value
},
true,
},
{
"success",
func() {
key := ethcmn.BytesToHash([]byte("key"))
value := ethcmn.BytesToHash([]byte("value"))
expValue = value.String()
suite.app.EvmKeeper.SetState(suite.ctx, suite.address, key, value)
req = &types.QueryStorageRequest{
Address: suite.address.String(),
Key: key.String(),
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.Storage(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expValue, res.Value)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryCode() {
var (
req *types.QueryCodeRequest
expCode []byte
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"zero address",
func() {
req = &types.QueryCodeRequest{
Address: ethcmn.Address{}.String(),
}
exp := &types.QueryCodeResponse{}
expCode = exp.Code
},
false,
},
{
"success",
func() {
expCode = []byte("code")
suite.app.EvmKeeper.SetCode(suite.ctx, suite.address, expCode)
req = &types.QueryCodeRequest{
Address: suite.address.String(),
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.Code(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expCode, res.Code)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryTxLogs() {
var (
req *types.QueryTxLogsRequest
expLogs []*types.Log
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"empty hash",
func() {
req = &types.QueryTxLogsRequest{
Hash: ethcmn.Hash{}.String(),
}
},
false,
},
{"logs not found",
func() {
hash := ethcmn.BytesToHash([]byte("hash"))
req = &types.QueryTxLogsRequest{
Hash: hash.String(),
}
},
true,
},
{
"success",
func() {
hash := ethcmn.BytesToHash([]byte("tx_hash"))
expLogs = []*types.Log{
{
Address: suite.address.String(),
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
Data: []byte("data"),
BlockNumber: 1,
TxHash: hash.String(),
TxIndex: 1,
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
Index: 0,
Removed: false,
},
}
suite.app.EvmKeeper.SetLogs(suite.ctx, hash, types.LogsToEthereum(expLogs))
req = &types.QueryTxLogsRequest{
Hash: hash.String(),
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.TxLogs(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expLogs, res.Logs)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryBlockLogs() {
var (
req *types.QueryBlockLogsRequest
expLogs []types.TransactionLogs
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"empty hash",
func() {
req = &types.QueryBlockLogsRequest{
Hash: ethcmn.Hash{}.String(),
}
},
false,
},
{"logs not found",
func() {
hash := ethcmn.BytesToHash([]byte("hash"))
req = &types.QueryBlockLogsRequest{
Hash: hash.String(),
}
},
true,
},
{
"success",
func() {
hash := ethcmn.BytesToHash([]byte("block_hash"))
expLogs = []types.TransactionLogs{
{
Hash: ethcmn.BytesToHash([]byte("tx_hash_0")).String(),
Logs: []*types.Log{
{
Address: suite.address.String(),
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
Data: []byte("data"),
BlockNumber: 1,
TxHash: ethcmn.BytesToHash([]byte("tx_hash_0")).String(),
TxIndex: 1,
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
Index: 0,
Removed: false,
},
},
},
{
Hash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(),
Logs: []*types.Log{
{
Address: suite.address.String(),
Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()},
Data: []byte("data"),
BlockNumber: 1,
TxHash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(),
TxIndex: 1,
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
Index: 0,
Removed: false,
},
{
Address: suite.address.String(),
Topics: []string{ethcmn.BytesToHash([]byte("topic_1")).String()},
Data: []byte("data_1"),
BlockNumber: 1,
TxHash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(),
TxIndex: 1,
BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(),
Index: 0,
Removed: false,
},
},
},
}
suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash([]byte("tx_hash_0")), types.LogsToEthereum(expLogs[0].Logs))
suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash([]byte("tx_hash_1")), types.LogsToEthereum(expLogs[1].Logs))
req = &types.QueryBlockLogsRequest{
Hash: hash.String(),
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.BlockLogs(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expLogs, res.TxLogs)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryTxReceipt() {
var (
req *types.QueryTxReceiptRequest
expRes *types.QueryTxReceiptResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"empty hash",
func() {
req = &types.QueryTxReceiptRequest{}
},
false,
},
{"tx receipt not found for hash",
func() {
hash := ethcmn.BytesToHash([]byte("thash"))
req = &types.QueryTxReceiptRequest{
Hash: hash.Hex(),
}
},
false,
},
{"success",
func() {
hash := ethcmn.BytesToHash([]byte("thash"))
receipt := &types.TxReceipt{
Hash: hash.Hex(),
From: suite.address.Hex(),
BlockHeight: uint64(suite.ctx.BlockHeight()),
BlockHash: ethcmn.BytesToHash(suite.ctx.BlockHeader().DataHash).Hex(),
}
suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt)
req = &types.QueryTxReceiptRequest{
Hash: hash.Hex(),
}
expRes = &types.QueryTxReceiptResponse{
Receipt: receipt,
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.TxReceipt(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expRes, res)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryTxReceiptByBlockHeight() {
var (
req = &types.QueryTxReceiptsByBlockHeightRequest{}
expRes *types.QueryTxReceiptsByBlockHeightResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"empty response",
func() {
expRes = &types.QueryTxReceiptsByBlockHeightResponse{
Receipts: nil,
}
},
true,
},
{"success",
func() {
hash := ethcmn.BytesToHash([]byte("thash"))
receipt := &types.TxReceipt{
Hash: hash.Hex(),
From: suite.address.Hex(),
BlockHeight: uint64(suite.ctx.BlockHeight()),
BlockHash: ethcmn.BytesToHash(suite.ctx.BlockHeader().DataHash).Hex(),
}
suite.app.EvmKeeper.AddTxHashToBlock(suite.ctx, suite.ctx.BlockHeight(), hash)
suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt)
expRes = &types.QueryTxReceiptsByBlockHeightResponse{
Receipts: []*types.TxReceipt{receipt},
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", suite.ctx.BlockHeight()))
res, err := suite.queryClient.TxReceiptsByBlockHeight(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expRes, res)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryTxReceiptByBlockHash() {
var (
req *types.QueryTxReceiptsByBlockHashRequest
expRes *types.QueryTxReceiptsByBlockHashResponse
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"empty block hash",
func() {
req = &types.QueryTxReceiptsByBlockHashRequest{
Hash: "",
}
},
false,
},
{"success",
func() {
hash := ethcmn.BytesToHash([]byte("thash"))
blockHash := ethcmn.BytesToHash([]byte("bhash"))
receipt := &types.TxReceipt{
Hash: hash.Hex(),
From: suite.address.Hex(),
BlockHeight: uint64(suite.ctx.BlockHeight()),
BlockHash: blockHash.Hex(),
}
suite.app.EvmKeeper.SetBlockHash(suite.ctx, blockHash.Bytes(), suite.ctx.BlockHeight())
suite.app.EvmKeeper.AddTxHashToBlock(suite.ctx, suite.ctx.BlockHeight(), hash)
suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt)
req = &types.QueryTxReceiptsByBlockHashRequest{
Hash: blockHash.Hex(),
}
expRes = &types.QueryTxReceiptsByBlockHashResponse{
Receipts: []*types.TxReceipt{receipt},
}
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.TxReceiptsByBlockHash(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expRes, res)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryBlockBloom() {
var (
req *types.QueryBlockBloomRequest
expBloom []byte
)
testCases := []struct {
msg string
malleate func()
expPass bool
}{
{"marshal error",
func() {},
false,
},
{"bloom not found for height",
func() {
req = &types.QueryBlockBloomRequest{}
bloom := ethtypes.BytesToBloom([]byte("bloom"))
expBloom = bloom.Bytes()
suite.ctx = suite.ctx.WithBlockHeight(10)
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 2, bloom)
},
false,
},
{
"success",
func() {
req = &types.QueryBlockBloomRequest{}
bloom := ethtypes.BytesToBloom([]byte("bloom"))
expBloom = bloom.Bytes()
suite.ctx = suite.ctx.WithBlockHeight(1)
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 1, bloom)
},
true,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", suite.ctx.BlockHeight()))
res, err := suite.queryClient.BlockBloom(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().Equal(expBloom, res.Bloom)
} else {
suite.Require().Error(err)
}
})
}
}
func (suite *KeeperTestSuite) TestQueryParams() {
ctx := sdk.WrapSDKContext(suite.ctx)
expParams := types.DefaultParams()
res, err := suite.queryClient.Params(ctx, &types.QueryParamsRequest{})
suite.Require().NoError(err)
suite.Require().Equal(expParams, res.Params)
}
+5 -8
View File
@@ -78,14 +78,11 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger {
// GetBlockBloom gets bloombits from block height
func (k Keeper) GetBlockBloom(ctx sdk.Context, height int64) (ethtypes.Bloom, bool) {
store := ctx.KVStore(k.storeKey)
key := types.BloomKey(height)
has := store.Has(key)
if !has {
return ethtypes.Bloom{}, true // sometimes bloom not found, fix this
bz := store.Get(types.BloomKey(height))
if len(bz) == 0 {
return ethtypes.Bloom{}, false
}
bz := store.Get(key)
return ethtypes.BytesToBloom(bz), true
}
@@ -128,9 +125,9 @@ func (k Keeper) GetBlockHeightByHash(ctx sdk.Context, hash common.Hash) (int64,
}
// SetBlockHash sets the mapping from block consensus hash to block height
func (k Keeper) SetBlockHeightToHash(ctx sdk.Context, hash []byte, height int64) {
func (k Keeper) SetBlockHeightToHash(ctx sdk.Context, hash common.Hash, height int64) {
store := ctx.KVStore(k.storeKey)
store.Set(types.KeyBlockHeightHash(uint64(height)), hash)
store.Set(types.KeyBlockHeightHash(uint64(height)), hash.Bytes())
}
// SetTxReceiptToHash sets the mapping from tx hash to tx receipt
+10 -5
View File
@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@@ -31,19 +32,23 @@ var (
type KeeperTestSuite struct {
suite.Suite
ctx sdk.Context
querier sdk.Querier
app *app.EthermintApp
address ethcmn.Address
ctx sdk.Context
app *app.EthermintApp
queryClient types.QueryClient
address ethcmn.Address
}
func (suite *KeeperTestSuite) SetupTest() {
checkTx := false
suite.app = app.Setup(checkTx)
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()})
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()})
suite.address = ethcmn.HexToAddress(addrHex)
queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper)
suite.queryClient = types.NewQueryClient(queryHelper)
balance := ethermint.NewPhotonCoin(sdk.ZeroInt())
acc := &ethermint.EthAccount{
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),