Skip to content

Commit

Permalink
fix: chain-id in grpc query is not initialized without abci event
Browse files Browse the repository at this point in the history
Closes: evmos#1404

Solution:
- pass the chain-id from caller.
- add unit tests, and fix TraceBlock by the way
  • Loading branch information
yihuang committed Nov 2, 2022
1 parent a8ea4ec commit 11309dd
Show file tree
Hide file tree
Showing 10 changed files with 368 additions and 109 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### API Breaking

* (ante) [#1214](https://github.com/evmos/ethermint/pull/1214) Set mempool priority to EVM transactions.
* (evm) [#1405](https://github.com/evmos/ethermint/pull/1405) Add parameter `chainID` to evm keeper's `EVMConfig` method, so caller can choose to not use the cached `eip155ChainID`.

### Improvements

Expand Down Expand Up @@ -77,6 +78,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (cli) [#1362](https://github.com/evmos/ethermint/pull/1362) Fix `index-eth-tx` error when the indexer db is empty.
* (state) [#1320](https://github.com/evmos/ethermint/pull/1320) Fix codehash check mismatch when the code has been deleted in the evm state.
* (rpc) [#1392](https://github.com/evmos/ethermint/pull/1392) Allow fill the proposer address in json-rpc through tendermint api, and pass explicitly to grpc query handler.
* (rpc) [#1405](https://github.com/evmos/ethermint/pull/1405) Pass chain-id to grpc query through request, otherwise it's not initialized if abci event don't happens.

## [v0.19.3] - 2022-10-14

Expand Down
3 changes: 3 additions & 0 deletions docs/api/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ EthCallRequest defines EthCall request
| `args` | [bytes](#bytes) | | same json format as the json rpc api. |
| `gas_cap` | [uint64](#uint64) | | the default gas cap to be used |
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
| `chain_id` | [string](#string) | | the eip155 chain id parsed from the requested block header |



Expand Down Expand Up @@ -793,6 +794,7 @@ QueryTraceBlockRequest defines TraceTx request
| `block_hash` | [string](#string) | | block hex hash |
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time |
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
| `chain_id` | [string](#string) | | the eip155 chain id parsed from the requested block header |



Expand Down Expand Up @@ -829,6 +831,7 @@ QueryTraceTxRequest defines TraceTx request
| `block_hash` | [string](#string) | | block hex hash of requested transaction |
| `block_time` | [google.protobuf.Timestamp](#google.protobuf.Timestamp) | | block time of requested transaction |
| `proposer_address` | [bytes](#bytes) | | the proposer of the requested block |
| `chain_id` | [string](#string) | | the eip155 chain id parsed from the requested block header |



Expand Down
6 changes: 6 additions & 0 deletions proto/ethermint/evm/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ message EthCallRequest {
uint64 gas_cap = 2;
// the proposer of the requested block
bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
// the eip155 chain id parsed from the requested block header
string chain_id = 4 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
}

// EstimateGasResponse defines EstimateGas response
Expand Down Expand Up @@ -251,6 +253,8 @@ message QueryTraceTxRequest {
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// the proposer of the requested block
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
// the eip155 chain id parsed from the requested block header
string chain_id = 9 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
}

// QueryTraceTxResponse defines TraceTx response
Expand All @@ -273,6 +277,8 @@ message QueryTraceBlockRequest {
google.protobuf.Timestamp block_time = 7 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
// the proposer of the requested block
bytes proposer_address = 8 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
// the eip155 chain id parsed from the requested block header
string chain_id = 9 [(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int"];
}

// QueryTraceBlockResponse defines TraceBlock response
Expand Down
17 changes: 17 additions & 0 deletions rpc/backend/call_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"fmt"
"math/big"

sdkmath "cosmossdk.io/math"

"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -305,10 +307,17 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp
return 0, errors.New("header not found")
}

tmp, err := ethermint.ParseChainID(header.Block.ChainID)
if err != nil {
return 0, sdkerrors.Wrapf(err, "failed to parse chainID: %s", header.Block.ChainID)
}
chainID := sdkmath.NewIntFromBigInt(tmp)

req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ChainId: &chainID,
}

// From ContextWithHeight: if the provided height is 0,
Expand All @@ -335,10 +344,18 @@ func (b *Backend) DoCall(
// the error message imitates geth behavior
return nil, errors.New("header not found")
}

tmp, err := ethermint.ParseChainID(header.Block.ChainID)
if err != nil {
return nil, sdkerrors.Wrapf(err, "failed to parse chainID: %s", header.Block.ChainID)
}
chainID := sdkmath.NewIntFromBigInt(tmp)

req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ChainId: &chainID,
}

// From ContextWithHeight: if the provided height is 0,
Expand Down
18 changes: 18 additions & 0 deletions rpc/backend/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import (
"encoding/json"
"fmt"

sdkmath "cosmossdk.io/math"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common"
rpctypes "github.com/evmos/ethermint/rpc/types"
ethermint "github.com/evmos/ethermint/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
"github.com/pkg/errors"
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
Expand Down Expand Up @@ -77,13 +81,20 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
return nil, fmt.Errorf("invalid transaction type %T", tx)
}

tmp, err := ethermint.ParseChainID(blk.Block.ChainID)
if err != nil {
return nil, sdkerrors.Wrapf(err, "failed to parse chainID: %s", blk.Block.ChainID)
}
chainID := sdkmath.NewIntFromBigInt(tmp)

traceTxRequest := evmtypes.QueryTraceTxRequest{
Msg: ethMessage,
Predecessors: predecessors,
BlockNumber: blk.Block.Height,
BlockTime: blk.Block.Time,
BlockHash: common.Bytes2Hex(blk.BlockID.Hash),
ProposerAddress: sdk.ConsAddress(blk.Block.ProposerAddress),
ChainId: &chainID,
}

if config != nil {
Expand Down Expand Up @@ -155,13 +166,20 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber,
}
ctxWithHeight := rpctypes.ContextWithHeight(int64(contextHeight))

tmp, err := ethermint.ParseChainID(block.Block.ChainID)
if err != nil {
return nil, sdkerrors.Wrapf(err, "failed to parse chainID: %s", block.Block.ChainID)
}
chainID := sdkmath.NewIntFromBigInt(tmp)

traceBlockRequest := &evmtypes.QueryTraceBlockRequest{
Txs: txsMessages,
TraceConfig: config,
BlockNumber: block.Block.Height,
BlockTime: block.Block.Time,
BlockHash: common.Bytes2Hex(block.BlockID.Hash),
ProposerAddress: sdk.ConsAddress(block.Block.ProposerAddress),
ChainId: &chainID,
}

res, err := b.queryClient.TraceBlock(ctxWithHeight, traceBlockRequest)
Expand Down
45 changes: 34 additions & 11 deletions x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (
"math/big"
"time"

"github.com/ethereum/go-ethereum/eth/tracers/logger"

"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/eth/tracers/logger"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand Down Expand Up @@ -223,8 +222,11 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
chainID, err := getChainID(ctx, req.ChainId)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
Expand Down Expand Up @@ -256,13 +258,17 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
}

ctx := sdk.UnwrapSDKContext(c)
chainID, err := getChainID(ctx, req.ChainId)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

if req.GasCap < ethparams.TxGas {
return nil, status.Error(codes.InvalidArgument, "gas cap cannot be lower than 21,000")
}

var args types.TransactionArgs
err := json.Unmarshal(req.Args, &args)
err = json.Unmarshal(req.Args, &args)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
Expand Down Expand Up @@ -294,7 +300,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
hi = req.GasCap
}
cap = hi
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
if err != nil {
return nil, status.Error(codes.Internal, "failed to load evm config")
}
Expand Down Expand Up @@ -374,7 +380,11 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ
ctx = ctx.WithBlockHeight(contextHeight)
ctx = ctx.WithBlockTime(req.BlockTime)
ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash))
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
chainID, err := getChainID(ctx, req.ChainId)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to load evm config: %s", err.Error())
}
Expand Down Expand Up @@ -441,7 +451,12 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest)
ctx = ctx.WithBlockHeight(contextHeight)
ctx = ctx.WithBlockTime(req.BlockTime)
ctx = ctx.WithHeaderHash(common.Hex2Bytes(req.BlockHash))
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
chainID, err := getChainID(ctx, req.ChainId)
if err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress), chainID)
if err != nil {
return nil, status.Error(codes.Internal, "failed to load evm config")
}
Expand All @@ -458,10 +473,10 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest)
traceResult, logIndex, err := k.traceTx(ctx, cfg, txConfig, signer, ethTx, req.TraceConfig, true)
if err != nil {
result.Error = err.Error()
continue
} else {
txConfig.LogIndex = logIndex
result.Result = traceResult
}
txConfig.LogIndex = logIndex
result.Result = traceResult
results = append(results, &result)
}

Expand Down Expand Up @@ -577,3 +592,11 @@ func (k Keeper) BaseFee(c context.Context, _ *types.QueryBaseFeeRequest) (*types

return res, nil
}

// getChainID parse chainID from current context if not provided
func getChainID(ctx sdk.Context, chainID *sdkmath.Int) (*big.Int, error) {
if chainID == nil {
return ethermint.ParseChainID(ctx.ChainID())
}
return chainID.BigInt(), nil
}
29 changes: 28 additions & 1 deletion x/evm/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ func (suite *KeeperTestSuite) TestTraceTx() {
txMsg *types.MsgEthereumTx
traceConfig *types.TraceConfig
predecessors []*types.MsgEthereumTx
chainID *sdkmath.Int
)

testCases := []struct {
Expand Down Expand Up @@ -932,6 +933,16 @@ func (suite *KeeperTestSuite) TestTraceTx() {
expPass: true,
traceResponse: "{\"gas\":34828,\"failed\":false,\"returnValue\":\"0000000000000000000000000000000000000000000000000000000000000001\",\"structLogs\":[{\"pc\":0,\"op\":\"PUSH1\",\"gas\":",
},
{
msg: "invalid chain id",
malleate: func() {
traceConfig = nil
predecessors = []*types.MsgEthereumTx{}
tmp := sdkmath.NewInt(1)
chainID = &tmp
},
expPass: false,
},
}

for _, tc := range testCases {
Expand All @@ -945,11 +956,14 @@ func (suite *KeeperTestSuite) TestTraceTx() {
txMsg = suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
suite.Commit()

chainID = nil

tc.malleate()
traceReq := types.QueryTraceTxRequest{
Msg: txMsg,
TraceConfig: traceConfig,
Predecessors: predecessors,
ChainId: chainID,
}
res, err := suite.queryClient.TraceTx(sdk.WrapSDKContext(suite.ctx), &traceReq)

Expand Down Expand Up @@ -979,6 +993,7 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
var (
txs []*types.MsgEthereumTx
traceConfig *types.TraceConfig
chainID *sdkmath.Int
)

testCases := []struct {
Expand Down Expand Up @@ -1088,7 +1103,17 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
}
},
expPass: true,
traceResponse: "[]",
traceResponse: "[{\"error\":\"rpc error: code = Internal desc = tracer not found\"}]",
},
{
msg: "invalid chain id",
malleate: func() {
traceConfig = nil
tmp := sdkmath.NewInt(1)
chainID = &tmp
},
expPass: true,
traceResponse: "[{\"error\":\"rpc error: code = Internal desc = invalid chain id for signer\"}]",
},
}

Expand All @@ -1103,13 +1128,15 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
// Generate token transfer transaction
txMsg := suite.TransferERC20Token(suite.T(), contractAddr, suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), sdkmath.NewIntWithDecimal(1, 18).BigInt())
suite.Commit()
chainID = nil

txs = append(txs, txMsg)

tc.malleate()
traceReq := types.QueryTraceBlockRequest{
Txs: txs,
TraceConfig: traceConfig,
ChainId: chainID,
}
res, err := suite.queryClient.TraceBlock(sdk.WrapSDKContext(suite.ctx), &traceReq)

Expand Down
8 changes: 4 additions & 4 deletions x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func GasToRefund(availableRefund, gasConsumed, refundQuotient uint64) uint64 {
}

// EVMConfig creates the EVMConfig based on current state
func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress) (*types.EVMConfig, error) {
func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, chainID *big.Int) (*types.EVMConfig, error) {
params := k.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(k.eip155ChainID)
ethCfg := params.ChainConfig.EthereumConfig(chainID)

// get the coinbase address from the block proposer
coinbase, err := k.GetCoinbaseAddress(ctx, proposerAddress)
Expand Down Expand Up @@ -199,7 +199,7 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t
bloomReceipt ethtypes.Bloom
)

cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress))
cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress), k.eip155ChainID)
if err != nil {
return nil, sdkerrors.Wrap(err, "failed to load evm config")
}
Expand Down Expand Up @@ -464,7 +464,7 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context,

// ApplyMessage calls ApplyMessageWithConfig with default EVMConfig
func (k *Keeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLogger, commit bool) (*types.MsgEthereumTxResponse, error) {
cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress))
cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress), k.eip155ChainID)
if err != nil {
return nil, sdkerrors.Wrap(err, "failed to load evm config")
}
Expand Down
Loading

0 comments on commit 11309dd

Please sign in to comment.