forked from cerc-io/laconicd-deprecated
rpc, evm: gRPC tests (#28)
* rpc, evm: grpc tests * address validation * update rpc * test cleanup * additional tests
This commit is contained in:
@@ -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
@@ -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: ðHash,
|
||||
Simulate: ctx.IsCheckTx(),
|
||||
Debug: false,
|
||||
}
|
||||
|
||||
config, found := k.GetChainConfig(ctx)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 := ðermint.EthAccount{
|
||||
BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0),
|
||||
|
||||
Reference in New Issue
Block a user