Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

fix: coinbase should not be the current one in traceTransaction execution #1392

Merged
merged 14 commits into from
Oct 21, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (rpc) [#1354](https://github.com/evmos/ethermint/pull/1354) Fix grpc query failure(`BaseFee` and `EthCall`) on legacy block states.
* (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.

## [v0.19.2] - 2022-08-29

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 @@ -562,6 +562,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 |



Expand Down Expand Up @@ -791,6 +792,7 @@ QueryTraceBlockRequest defines TraceTx request
| `block_number` | [int64](#int64) | | block number |
| `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 |



Expand Down Expand Up @@ -826,6 +828,7 @@ QueryTraceTxRequest defines TraceTx request
| `block_number` | [int64](#int64) | | block number of requested transaction |
| `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 |



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 @@ -221,6 +221,8 @@ message EthCallRequest {
bytes args = 1;
// the default gas cap to be used
uint64 gas_cap = 2;
// the proposer of the requested block
bytes proposer_address = 3 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.ConsAddress"];
}

// EstimateGasResponse defines EstimateGas response
Expand All @@ -247,6 +249,8 @@ message QueryTraceTxRequest {
string block_hash = 6;
// block time of requested transaction
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"];
}

// QueryTraceTxResponse defines TraceTx response
Expand All @@ -267,6 +271,8 @@ message QueryTraceBlockRequest {
string block_hash = 6;
// block time
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"];
}

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

"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand Down Expand Up @@ -298,17 +299,18 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp
return 0, err
}

req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
}

_, err = b.TendermintBlockByNumber(blockNr)
header, err := b.TendermintBlockByNumber(blockNr)
if err != nil {
// the error message imitates geth behavior
return 0, errors.New("header not found")
}

req := evmtypes.EthCallRequest{
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
}

// From ContextWithHeight: if the provided height is 0,
// it will return an empty context and the gRPC query will use
// the latest block height for querying.
Expand All @@ -328,10 +330,15 @@ func (b *Backend) DoCall(
if err != nil {
return nil, err
}

header, err := b.TendermintBlockByNumber(blockNr)
if err != nil {
// the error message imitates geth behavior
return nil, errors.New("header not found")
}
req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
}

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

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
rpctypes "github.com/evmos/ethermint/rpc/types"
evmtypes "github.com/evmos/ethermint/x/evm/types"
Expand Down Expand Up @@ -77,11 +78,12 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi
}

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

if config != nil {
Expand Down Expand Up @@ -154,11 +156,12 @@ func (b *Backend) TraceBlock(height rpctypes.BlockNumber,
ctxWithHeight := rpctypes.ContextWithHeight(int64(contextHeight))

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

res, err := b.queryClient.TraceBlock(ctxWithHeight, traceBlockRequest)
Expand Down
11 changes: 4 additions & 7 deletions x/evm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms
return nil, status.Error(codes.InvalidArgument, err.Error())
}

cfg, err := k.EVMConfig(ctx)
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
Expand Down Expand Up @@ -294,8 +294,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
hi = req.GasCap
}
cap = hi

cfg, err := k.EVMConfig(ctx)
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
if err != nil {
return nil, status.Error(codes.Internal, "failed to load evm config")
}
Expand Down Expand Up @@ -375,8 +374,7 @@ 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)
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to load evm config: %s", err.Error())
}
Expand Down Expand Up @@ -443,8 +441,7 @@ 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)
cfg, err := k.EVMConfig(ctx, GetProposerAddress(ctx, req.ProposerAddress))
if err != nil {
return nil, status.Error(codes.Internal, "failed to load evm config")
}
Expand Down
17 changes: 10 additions & 7 deletions x/evm/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,8 +735,9 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
args, err := json.Marshal(&args)
suite.Require().NoError(err)
req := types.EthCallRequest{
Args: args,
GasCap: gasCap,
Args: args,
GasCap: gasCap,
ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
}

rsp, err := suite.queryClient.EstimateGas(sdk.WrapSDKContext(suite.ctx), &req)
Expand Down Expand Up @@ -1145,16 +1146,18 @@ func (suite *KeeperTestSuite) TestNonceInQuery() {
Data: (*hexutil.Bytes)(&data),
})
suite.Require().NoError(err)

proposerAddress := suite.ctx.BlockHeader().ProposerAddress
_, err = suite.queryClient.EstimateGas(sdk.WrapSDKContext(suite.ctx), &types.EthCallRequest{
Args: args,
GasCap: uint64(config.DefaultGasCap),
Args: args,
GasCap: uint64(config.DefaultGasCap),
ProposerAddress: proposerAddress,
})
suite.Require().NoError(err)

_, err = suite.queryClient.EthCall(sdk.WrapSDKContext(suite.ctx), &types.EthCallRequest{
Args: args,
GasCap: uint64(config.DefaultGasCap),
Args: args,
GasCap: uint64(config.DefaultGasCap),
ProposerAddress: proposerAddress,
})
suite.Require().NoError(err)
}
Expand Down
16 changes: 9 additions & 7 deletions x/evm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,10 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, owner commo
Data: (*hexutil.Bytes)(&data),
})
require.NoError(t, err)

res, err := suite.queryClient.EstimateGas(ctx, &types.EthCallRequest{
Args: args,
GasCap: uint64(config.DefaultGasCap),
Args: args,
GasCap: uint64(config.DefaultGasCap),
ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
})
require.NoError(t, err)

Expand Down Expand Up @@ -308,8 +308,9 @@ func (suite *KeeperTestSuite) TransferERC20Token(t require.TestingT, contractAdd
args, err := json.Marshal(&types.TransactionArgs{To: &contractAddr, From: &from, Data: (*hexutil.Bytes)(&transferData)})
require.NoError(t, err)
res, err := suite.queryClient.EstimateGas(ctx, &types.EthCallRequest{
Args: args,
GasCap: 25_000_000,
Args: args,
GasCap: 25_000_000,
ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
})
require.NoError(t, err)

Expand Down Expand Up @@ -365,8 +366,9 @@ func (suite *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.A
require.NoError(t, err)

res, err := suite.queryClient.EstimateGas(ctx, &types.EthCallRequest{
Args: args,
GasCap: uint64(config.DefaultGasCap),
Args: args,
GasCap: uint64(config.DefaultGasCap),
ProposerAddress: suite.ctx.BlockHeader().ProposerAddress,
})
require.NoError(t, err)

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

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

// get the coinbase address from the block proposer
coinbase, err := k.GetCoinbaseAddress(ctx)
coinbase, err := k.GetCoinbaseAddress(ctx, proposerAddress)
if err != nil {
return nil, sdkerrors.Wrap(err, "failed to obtain coinbase address")
}
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)
cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress))
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)
cfg, err := k.EVMConfig(ctx, sdk.ConsAddress(ctx.BlockHeader().ProposerAddress))
if err != nil {
return nil, sdkerrors.Wrap(err, "failed to load evm config")
}
Expand Down Expand Up @@ -519,15 +519,22 @@ func (k *Keeper) ResetGasMeterAndConsumeGas(ctx sdk.Context, gasUsed uint64) {
ctx.GasMeter().ConsumeGas(gasUsed, "apply evm transaction")
}

// GetProposerAddress returns current block proposer's address when provided proposer address is empty.
func GetProposerAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) sdk.ConsAddress {
if len(proposerAddress) == 0 {
proposerAddress = ctx.BlockHeader().ProposerAddress
}
return proposerAddress
}

// GetCoinbaseAddress returns the block proposer's validator operator address.
func (k Keeper) GetCoinbaseAddress(ctx sdk.Context) (common.Address, error) {
consAddr := sdk.ConsAddress(ctx.BlockHeader().ProposerAddress)
validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
func (k Keeper) GetCoinbaseAddress(ctx sdk.Context, proposerAddress sdk.ConsAddress) (common.Address, error) {
validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, GetProposerAddress(ctx, proposerAddress))
if !found {
return common.Address{}, sdkerrors.Wrapf(
stakingtypes.ErrNoValidatorFound,
"failed to retrieve validator from block proposer address %s",
consAddr.String(),
proposerAddress.String(),
)
}

Expand Down
Loading