fix: improve error message in SendTransaction json-rpc api (#786)

* fix error message in `SendTransaction` json-rpc api

Closes: #785

Solution:
- Remove `stacktrace.Propagate`s, and recover error message in jsonrpc server

changelog

fix error messages

* Update x/evm/keeper/msg_server.go

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
yihuang
2021-11-26 15:19:28 +01:00
committed by GitHub
co-authored by Federico Kunze Küllmer
parent 2d8be4e85b
commit c8d4d3f9a3
14 changed files with 112 additions and 190 deletions
+1 -2
View File
@@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/eth/tracers"
"github.com/palantir/stacktrace"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -313,7 +312,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type
rsp, err = k.ApplyMessageWithConfig(msg, nil, false, cfg)
if err != nil {
if errors.Is(stacktrace.RootCause(err), core.ErrIntrinsicGas) {
if errors.Is(err, core.ErrIntrinsicGas) {
return true, nil, nil // Special case, raise gas limit
}
return true, nil, err // Bail out
+3 -3
View File
@@ -7,12 +7,12 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/palantir/stacktrace"
"github.com/tendermint/tendermint/libs/log"
"github.com/ethereum/go-ethereum/params"
@@ -341,11 +341,11 @@ func (k Keeper) ClearBalance(addr sdk.AccAddress) (prevBalance sdk.Coin, err err
prevBalance = k.bankKeeper.GetBalance(k.Ctx(), addr, params.EvmDenom)
if prevBalance.IsPositive() {
if err := k.bankKeeper.SendCoinsFromAccountToModule(k.Ctx(), addr, types.ModuleName, sdk.Coins{prevBalance}); err != nil {
return sdk.Coin{}, stacktrace.Propagate(err, "failed to transfer to module account")
return sdk.Coin{}, sdkerrors.Wrap(err, "failed to transfer to module account")
}
if err := k.bankKeeper.BurnCoins(k.Ctx(), types.ModuleName, sdk.Coins{prevBalance}); err != nil {
return sdk.Coin{}, stacktrace.Propagate(err, "failed to burn coins from evm module account")
return sdk.Coin{}, sdkerrors.Wrap(err, "failed to burn coins from evm module account")
}
}
+3 -4
View File
@@ -5,12 +5,11 @@ import (
"encoding/json"
"fmt"
"github.com/palantir/stacktrace"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
tmtypes "github.com/tendermint/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/tharsis/ethermint/x/evm/types"
)
@@ -30,7 +29,7 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
response, err := k.ApplyTransaction(tx)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to apply transaction")
return nil, sdkerrors.Wrap(err, "failed to apply transaction")
}
attrs := []sdk.Attribute{
@@ -57,7 +56,7 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t
for _, log := range response.Logs {
value, err := json.Marshal(log)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to encode log")
return nil, sdkerrors.Wrap(err, "failed to encode log")
}
txLogAttrs = append(txLogAttrs, sdk.NewAttribute(types.AttributeKeyTxLog, string(value)))
}
+17 -17
View File
@@ -3,7 +3,6 @@ package keeper
import (
"math/big"
"github.com/palantir/stacktrace"
tmtypes "github.com/tendermint/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
@@ -29,7 +28,7 @@ func (k *Keeper) EVMConfig(ctx sdk.Context) (*types.EVMConfig, error) {
// get the coinbase address from the block proposer
coinbase, err := k.GetCoinbaseAddress(ctx)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to obtain coinbase address")
return nil, sdkerrors.Wrap(err, "failed to obtain coinbase address")
}
var baseFee *big.Int
@@ -176,7 +175,7 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
cfg, err := k.EVMConfig(ctx)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to load evm config")
return nil, sdkerrors.Wrap(err, "failed to load evm config")
}
// get the latest signer according to the chain rules from the config
@@ -189,7 +188,7 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
msg, err := tx.AsMessage(signer, baseFee)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to return ethereum transaction as core message")
return nil, sdkerrors.Wrap(err, "failed to return ethereum transaction as core message")
}
txHash := tx.Hash()
@@ -215,7 +214,7 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
res, err := k.ApplyMessageWithConfig(msg, nil, true, cfg)
if err != nil {
return nil, stacktrace.Propagate(err, "failed to apply ethereum core message")
return nil, sdkerrors.Wrap(err, "failed to apply ethereum core message")
}
res.Hash = txHash.Hex()
@@ -240,7 +239,7 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT
// refund gas according to Ethereum gas accounting rules.
if err := k.RefundGas(msg, msg.Gas()-res.GasUsed, cfg.Params.EvmDenom); err != nil {
return nil, stacktrace.Propagate(err, "failed to refund gas leftover gas to sender %s", msg.From())
return nil, sdkerrors.Wrapf(err, "failed to refund gas leftover gas to sender %s", msg.From())
}
if len(logs) > 0 {
@@ -314,9 +313,9 @@ func (k *Keeper) ApplyMessageWithConfig(msg core.Message, tracer vm.Tracer, comm
// return error if contract creation or call are disabled through governance
if !cfg.Params.EnableCreate && msg.To() == nil {
return nil, stacktrace.Propagate(types.ErrCreateDisabled, "failed to create new contract")
return nil, sdkerrors.Wrap(types.ErrCreateDisabled, "failed to create new contract")
} else if !cfg.Params.EnableCall && msg.To() != nil {
return nil, stacktrace.Propagate(types.ErrCallDisabled, "failed to call contract")
return nil, sdkerrors.Wrap(types.ErrCallDisabled, "failed to call contract")
}
sender := vm.AccountRef(msg.From())
@@ -326,12 +325,12 @@ func (k *Keeper) ApplyMessageWithConfig(msg core.Message, tracer vm.Tracer, comm
intrinsicGas, err := k.GetEthIntrinsicGas(msg, cfg.ChainConfig, contractCreation)
if err != nil {
// should have already been checked on Ante Handler
return nil, stacktrace.Propagate(err, "intrinsic gas failed")
return nil, sdkerrors.Wrap(err, "intrinsic gas failed")
}
// Should check again even if it is checked on Ante Handler, because eth_call don't go through Ante Handler.
if msg.Gas() < intrinsicGas {
// eth_estimateGas will check for this exact error
return nil, stacktrace.Propagate(core.ErrIntrinsicGas, "apply message")
return nil, sdkerrors.Wrap(core.ErrIntrinsicGas, "apply message")
}
leftoverGas := msg.Gas() - intrinsicGas
@@ -356,12 +355,12 @@ func (k *Keeper) ApplyMessageWithConfig(msg core.Message, tracer vm.Tracer, comm
// calculate gas refund
if msg.Gas() < leftoverGas {
return nil, stacktrace.Propagate(types.ErrGasOverflow, "apply message")
return nil, sdkerrors.Wrap(types.ErrGasOverflow, "apply message")
}
gasUsed := msg.Gas() - leftoverGas
refund := k.GasToRefund(gasUsed, refundQuotient)
if refund > gasUsed {
return nil, stacktrace.Propagate(types.ErrGasOverflow, "apply message")
return nil, sdkerrors.Wrap(types.ErrGasOverflow, "apply message")
}
gasUsed -= refund
@@ -390,7 +389,7 @@ func (k *Keeper) ApplyMessageWithConfig(msg core.Message, tracer vm.Tracer, comm
func (k *Keeper) ApplyMessage(msg core.Message, tracer vm.Tracer, commit bool) (*types.MsgEthereumTxResponse, error) {
cfg, err := k.EVMConfig(k.Ctx())
if err != nil {
return nil, stacktrace.Propagate(err, "failed to load evm config")
return nil, sdkerrors.Wrap(err, "failed to load evm config")
}
return k.ApplyMessageWithConfig(msg, tracer, commit, cfg)
}
@@ -438,7 +437,7 @@ func (k *Keeper) RefundGas(msg core.Message, leftoverGas uint64, denom string) e
err := k.bankKeeper.SendCoinsFromModuleToAccount(k.Ctx(), authtypes.FeeCollectorName, msg.From().Bytes(), refundedCoins)
if err != nil {
err = sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "fee collector account failed to refund fees: %s", err.Error())
return stacktrace.Propagate(err, "failed to refund %d leftover gas (%s)", leftoverGas, refundedCoins.String())
return sdkerrors.Wrapf(err, "failed to refund %d leftover gas (%s)", leftoverGas, refundedCoins.String())
}
default:
// no refund, consume gas and update the tx gas meter
@@ -461,9 +460,10 @@ func (k Keeper) GetCoinbaseAddress(ctx sdk.Context) (common.Address, error) {
consAddr := sdk.ConsAddress(ctx.BlockHeader().ProposerAddress)
validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr)
if !found {
return common.Address{}, stacktrace.Propagate(
sdkerrors.Wrap(stakingtypes.ErrNoValidatorFound, consAddr.String()),
"failed to retrieve validator from block proposer address",
return common.Address{}, sdkerrors.Wrapf(
stakingtypes.ErrNoValidatorFound,
"failed to retrieve validator from block proposer address %s",
consAddr.String(),
)
}
+11 -18
View File
@@ -6,7 +6,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/palantir/stacktrace"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
@@ -28,7 +27,7 @@ func (k Keeper) DeductTxCostsFromUserBalance(
// fetch sender account from signature
signerAcc, err := authante.GetSignerAcc(ctx, k.accountKeeper, msgEthTx.GetFrom())
if err != nil {
return nil, stacktrace.Propagate(err, "account not found for sender %s", msgEthTx.From)
return nil, sdkerrors.Wrapf(err, "account not found for sender %s", msgEthTx.From)
}
gasLimit := txData.GetGas()
@@ -40,9 +39,9 @@ func (k Keeper) DeductTxCostsFromUserBalance(
intrinsicGas, err := core.IntrinsicGas(txData.GetData(), accessList, isContractCreation, homestead, istanbul)
if err != nil {
return nil, stacktrace.Propagate(sdkerrors.Wrap(
return nil, sdkerrors.Wrapf(
err,
"failed to compute intrinsic gas cost"), "failed to retrieve intrinsic gas, contract creation = %t; homestead = %t, istanbul = %t",
"failed to retrieve intrinsic gas, contract creation = %t; homestead = %t, istanbul = %t",
isContractCreation, homestead, istanbul,
)
}
@@ -77,7 +76,7 @@ func (k Keeper) DeductTxCostsFromUserBalance(
// deduct the full gas cost from the user balance
if err := authante.DeductFees(k.bankKeeper, ctx, signerAcc, fees); err != nil {
return nil, stacktrace.Propagate(
return nil, sdkerrors.Wrapf(
err,
"failed to deduct full gas cost %s from the user %s balance",
fees, msgEthTx.From,
@@ -99,22 +98,16 @@ func CheckSenderBalance(
cost := txData.Cost()
if cost.Sign() < 0 {
return stacktrace.Propagate(
sdkerrors.Wrapf(
sdkerrors.ErrInvalidCoins,
"tx cost (%s%s) is negative and invalid", cost, denom,
),
"tx cost amount should never be negative")
return sdkerrors.Wrapf(
sdkerrors.ErrInvalidCoins,
"tx cost (%s%s) is negative and invalid", cost, denom,
)
}
if balance.IsNegative() || balance.Amount.BigInt().Cmp(cost) < 0 {
return stacktrace.Propagate(
sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds,
"sender balance < tx cost (%s < %s%s)", balance, txData.Cost(), denom,
),
"sender should have had enough funds to pay for tx cost = fee + amount (%s = %s + %s)",
cost, txData.Fee(), txData.GetValue(),
return sdkerrors.Wrapf(
sdkerrors.ErrInsufficientFunds,
"sender balance < tx cost (%s < %s%s)", balance, txData.Cost(), denom,
)
}
return nil