more fixes

This commit is contained in:
Federico Kunze
2021-04-18 18:39:15 +02:00
parent 614e62fb7e
commit cb2ab3d95d
63 changed files with 83570 additions and 3393 deletions
+82 -18
View File
@@ -2,6 +2,9 @@ package ante
import (
"fmt"
"runtime/debug"
log "github.com/xlab/suplog"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
@@ -14,7 +17,6 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
)
const (
@@ -28,6 +30,8 @@ const (
type AccountKeeper interface {
authante.AccountKeeper
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI
SetAccount(ctx sdk.Context, account authtypes.AccountI)
}
// BankKeeper defines an expected keeper interface for the bank module's Keeper
@@ -42,26 +46,73 @@ type BankKeeper interface {
// transaction-level processing (e.g. fee payment, signature verification) before
// being passed onto it's respective handler.
func NewAnteHandler(
ak AccountKeeper, bankKeeper BankKeeper, evmKeeper EVMKeeper, signModeHandler authsigning.SignModeHandler,
ak AccountKeeper,
bankKeeper BankKeeper,
evmKeeper EVMKeeper,
signModeHandler authsigning.SignModeHandler,
) sdk.AnteHandler {
return func(
ctx sdk.Context, tx sdk.Tx, sim bool,
) (newCtx sdk.Context, err error) {
var anteHandler sdk.AnteHandler
switch tx.(type) {
case *evmtypes.MsgEthereumTx:
anteHandler = sdk.ChainAnteDecorators(
NewEthSetupContextDecorator(), // outermost AnteDecorator. EthSetUpContext must be called first
authante.NewRejectExtensionOptionsDecorator(),
NewEthMempoolFeeDecorator(evmKeeper),
authante.NewValidateBasicDecorator(),
NewEthSigVerificationDecorator(),
NewAccountVerificationDecorator(ak, bankKeeper, evmKeeper),
NewNonceVerificationDecorator(ak),
NewEthGasConsumeDecorator(ak, bankKeeper, evmKeeper),
NewIncrementSenderSequenceDecorator(ak), // innermost AnteDecorator.
)
defer Recover(&err)
txWithExtensions, ok := tx.(authante.HasExtensionOptionsTx)
if ok {
opts := txWithExtensions.GetExtensionOptions()
if len(opts) > 0 {
switch typeURL := opts[0].GetTypeUrl(); typeURL {
case "/injective.evm.v1beta1.ExtensionOptionsEthereumTx":
// handle as *evmtypes.MsgEthereumTx
anteHandler = sdk.ChainAnteDecorators(
NewEthSetupContextDecorator(), // outermost AnteDecorator. EthSetUpContext must be called first
NewEthMempoolFeeDecorator(evmKeeper),
NewEthValidateBasicDecorator(),
authante.TxTimeoutHeightDecorator{},
NewEthSigVerificationDecorator(),
NewEthAccountSetupDecorator(ak),
NewEthAccountVerificationDecorator(ak, bankKeeper, evmKeeper),
NewEthNonceVerificationDecorator(ak),
NewEthGasConsumeDecorator(ak, bankKeeper, evmKeeper),
NewEthIncrementSenderSequenceDecorator(ak), // innermost AnteDecorator.
)
case "/injective.evm.v1beta1.ExtensionOptionsWeb3Tx":
// handle as normal Cosmos SDK tx, except signature is checked for EIP712 representation
switch tx.(type) {
case sdk.Tx:
anteHandler = sdk.ChainAnteDecorators(
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
authante.NewMempoolFeeDecorator(),
authante.NewValidateBasicDecorator(),
authante.TxTimeoutHeightDecorator{},
authante.NewValidateMemoDecorator(ak),
authante.NewConsumeGasForTxSizeDecorator(ak),
authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
authante.NewValidateSigCountDecorator(ak),
authante.NewDeductFeeDecorator(ak, bankKeeper),
authante.NewSigGasConsumeDecorator(ak, DefaultSigVerificationGasConsumer),
authante.NewIncrementSequenceDecorator(ak), // innermost AnteDecorator
)
default:
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
}
default:
log.WithField("type_url", typeURL).Errorln("rejecting tx with unsupported extension option")
return ctx, sdkerrors.ErrUnknownExtensionOptions
}
return anteHandler(ctx, tx, sim)
}
}
// handle as totally normal Cosmos SDK tx
switch tx.(type) {
case sdk.Tx:
anteHandler = sdk.ChainAnteDecorators(
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
@@ -71,7 +122,6 @@ func NewAnteHandler(
authante.TxTimeoutHeightDecorator{},
authante.NewValidateMemoDecorator(ak),
authante.NewConsumeGasForTxSizeDecorator(ak),
authante.NewRejectFeeGranterDecorator(),
authante.NewSetPubKeyDecorator(ak), // SetPubKeyDecorator must be called before all signature verification decorators
authante.NewValidateSigCountDecorator(ak),
authante.NewDeductFeeDecorator(ak, bankKeeper),
@@ -87,7 +137,20 @@ func NewAnteHandler(
}
}
var _ = DefaultSigVerificationGasConsumer
func Recover(err *error) {
if r := recover(); r != nil {
*err = sdkerrors.Wrapf(sdkerrors.ErrPanic, "%v", r)
if e, ok := r.(error); ok {
log.WithError(e).Errorln("ante handler panicked with an error")
log.Debugln(string(debug.Stack()))
} else {
log.Errorln(r)
}
}
}
var _ authante.SignatureVerificationGasConsumer = DefaultSigVerificationGasConsumer
// DefaultSigVerificationGasConsumer is the default implementation of SignatureVerificationGasConsumer. It consumes gas
// for signature verification based upon the public key type. The cost is fetched from the given params and is matched
@@ -105,7 +168,7 @@ func DefaultSigVerificationGasConsumer(
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
return nil
// support for etherum ECDSA secp256k1 keys
// support for ethereum ECDSA secp256k1 keys
case *ethsecp256k1.PubKey:
meter.ConsumeGas(secp256k1VerifyCost, "ante verify: eth_secp256k1")
return nil
@@ -120,6 +183,7 @@ func DefaultSigVerificationGasConsumer(
return err
}
return nil
default:
return sdkerrors.Wrapf(sdkerrors.ErrInvalidPubKey, "unrecognized public key type: %T", pubkey)
}
+8 -9
View File
@@ -9,9 +9,9 @@ import (
ethcmn "github.com/ethereum/go-ethereum/common"
tmcrypto "github.com/tendermint/tendermint/crypto"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/app"
@@ -62,8 +62,7 @@ func (suite *AnteTestSuite) TestValidEthTx() {
requireValidTx(suite.T(), suite.anteHandler, suite.ctx, tx, false)
}
// the legacytx.NewStdTx has been deprecated and It only works with Amino now
func (suite *AnteTestSuite) TestInValidTx() {
func (suite *AnteTestSuite) TestValidTx() {
suite.ctx = suite.ctx.WithBlockHeight(1)
addr1, priv1 := newTestAddrKey()
@@ -84,13 +83,13 @@ func (suite *AnteTestSuite) TestInValidTx() {
msg1 := newTestMsg(addr1, addr2)
msgs := []sdk.Msg{msg1}
privKeys := []cryptotypes.PrivKey{priv1, priv2}
privKeys := []tmcrypto.PrivKey{priv1, priv2}
accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()}
tx := newTestSDKTx(suite.ctx, msgs, privKeys, accNums, accSeqs, fee)
requireInvalidTx(suite.T(), suite.anteHandler, suite.ctx, tx, false)
requireValidTx(suite.T(), suite.anteHandler, suite.ctx, tx, false)
}
func (suite *AnteTestSuite) TestSDKInvalidSigs() {
@@ -116,7 +115,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
// require validation failure with no signers
msgs := []sdk.Msg{msg1}
privKeys := []cryptotypes.PrivKey{}
privKeys := []tmcrypto.PrivKey{}
accNums := []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs := []uint64{acc1.GetSequence(), acc2.GetSequence()}
@@ -126,7 +125,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
// require validation failure with invalid number of signers
msgs = []sdk.Msg{msg1}
privKeys = []cryptotypes.PrivKey{priv1}
privKeys = []tmcrypto.PrivKey{priv1}
accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber()}
accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence()}
@@ -137,7 +136,7 @@ func (suite *AnteTestSuite) TestSDKInvalidSigs() {
msg2 := newTestMsg(addr1, addr3)
msgs = []sdk.Msg{msg1, msg2}
privKeys = []cryptotypes.PrivKey{priv1, priv2, priv3}
privKeys = []tmcrypto.PrivKey{priv1, priv2, priv3}
accNums = []uint64{acc1.GetAccountNumber(), acc2.GetAccountNumber(), 0}
accSeqs = []uint64{acc1.GetSequence(), acc2.GetSequence(), 0}
@@ -158,7 +157,7 @@ func (suite *AnteTestSuite) TestSDKInvalidAcc() {
fee := newTestStdFee()
msg1 := newTestMsg(addr1)
msgs := []sdk.Msg{msg1}
privKeys := []cryptotypes.PrivKey{priv1}
privKeys := []tmcrypto.PrivKey{priv1}
// require validation failure with invalid account number
accNums := []uint64{1}
+159 -51
View File
@@ -4,11 +4,14 @@ import (
"fmt"
"math/big"
log "github.com/xlab/suplog"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
authante "github.com/cosmos/cosmos-sdk/x/auth/ante"
ethermint "github.com/cosmos/ethermint/types"
sidechain "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
"github.com/ethereum/go-ethereum/common"
@@ -37,6 +40,8 @@ func NewEthSetupContextDecorator() EthSetupContextDecorator {
// This is undone at the EthGasConsumeDecorator, where the context is set with the
// ethereum tx GasLimit.
func (escd EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
// all transactions must implement GasTx
gasTx, ok := tx.(authante.GasTx)
if !ok {
@@ -58,6 +63,7 @@ func (escd EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
)
err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log)
default:
log.Errorln(r)
panic(r)
}
}
@@ -89,41 +95,77 @@ func (emfd EthMempoolFeeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
return next(ctx, tx, simulate)
}
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
msgEthTx, ok := tx.(sdk.FeeTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type, not implements sdk.FeeTx: %T", tx)
}
evmDenom := emfd.evmKeeper.GetParams(ctx).EvmDenom
txFee := msgEthTx.GetFee().AmountOf(evmDenom).Int64()
if txFee < 0 {
return ctx, sdkerrors.Wrap(
sdkerrors.ErrInsufficientFee,
"negative fee not allowed",
)
}
// fee = gas price * gas limit
fee := sdk.NewDecCoin(evmDenom, sdk.NewIntFromBigInt(msgEthTx.Fee()))
// txFee = GP * GL
fee := sdk.NewInt64DecCoin(evmDenom, txFee)
minGasPrices := ctx.MinGasPrices()
minFees := minGasPrices.AmountOf(evmDenom).MulInt64(int64(msgEthTx.Data.GasLimit))
// check that fee provided is greater than the minimum defined by the validator node
// NOTE: we only check if the evm denom tokens are present in min gas prices. It is up to the
// check that fee provided is greater than the minimum
// NOTE: we only check if injs are present in min gas prices. It is up to the
// sender if they want to send additional fees in other denominations.
var hasEnoughFees bool
if fee.Amount.GTE(minFees) {
if fee.Amount.GTE(minGasPrices.AmountOf(evmDenom)) {
hasEnoughFees = true
}
// reject transaction if minimum gas price is not zero and the transaction does not
// reject transaction if minimum gas price is positive and the transaction does not
// meet the minimum fee
if !ctx.MinGasPrices().IsZero() && !hasEnoughFees {
return ctx, sdkerrors.Wrap(
sdkerrors.ErrInsufficientFee,
fmt.Sprintf("insufficient fee, got: %q required: %q", fee, minFees),
fmt.Sprintf("insufficient fee, got: %q required: %q", fee, ctx.MinGasPrices()),
)
}
return next(ctx, tx, simulate)
}
// EthValidateBasicDecorator will call tx.ValidateBasic and return any non-nil error.
// If ValidateBasic passes, decorator calls next AnteHandler in chain. Note,
// EthValidateBasicDecorator decorator will not get executed on ReCheckTx since it
// is not dependent on application state.
type EthValidateBasicDecorator struct{}
func NewEthValidateBasicDecorator() EthValidateBasicDecorator {
return EthValidateBasicDecorator{}
}
func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
// no need to validate basic on recheck tx, call next antehandler
if ctx.IsReCheckTx() {
return next(ctx, tx, simulate)
}
msgEthTx, ok := getTxMsg(tx).(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", getTxMsg(tx))
}
if err := msgEthTx.ValidateBasic(); err != nil {
return ctx, err
}
return next(ctx, tx, simulate)
}
// EthSigVerificationDecorator validates an ethereum signature
type EthSigVerificationDecorator struct{}
type EthSigVerificationDecorator struct {
interfaceRegistry codectypes.InterfaceRegistry
}
// NewEthSigVerificationDecorator creates a new EthSigVerificationDecorator
func NewEthSigVerificationDecorator() EthSigVerificationDecorator {
@@ -132,39 +174,63 @@ func NewEthSigVerificationDecorator() EthSigVerificationDecorator {
// AnteHandle validates the signature and returns sender address
func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
if simulate {
// when simulating, no signatures required and the from address is explicitly set
return next(ctx, tx, simulate)
}
msgEthTx, ok := getTxMsg(tx).(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", getTxMsg(tx))
}
// parse the chainID from a string to a base-10 integer
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
chainIDEpoch, err := sidechain.ParseChainID(ctx.ChainID())
if err != nil {
fmt.Println("chain id parsing failed")
return ctx, err
}
// validate sender/signature and cache the address
_, err = msgEthTx.VerifySig(chainIDEpoch)
if err != nil {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "signature verification failed: %s", err.Error())
// validate sender/signature
_, eip155Err := msgEthTx.VerifySig(chainIDEpoch)
if eip155Err != nil {
_, homesteadErr := msgEthTx.VerifySigHomestead()
if homesteadErr != nil {
errMsg := fmt.Sprintf("signature verification failed for both EIP155 and Homestead signers: (%s, %s)",
eip155Err.Error(), homesteadErr.Error())
err := sdkerrors.Wrap(sdkerrors.ErrUnauthorized, errMsg)
return ctx, err
}
}
// NOTE: when signature verification succeeds, a non-empty signer address can be
// retrieved from the transaction on the next AnteDecorators.
return next(ctx, msgEthTx, simulate)
return next(ctx, tx, simulate)
}
// AccountVerificationDecorator validates an account balance checks
type AccountVerificationDecorator struct {
type noMessages struct{}
func getTxMsg(tx sdk.Tx) interface{} {
msgs := tx.GetMsgs()
if len(msgs) == 0 {
return &noMessages{}
}
return msgs[0]
}
// EthAccountVerificationDecorator validates an account balance checks
type EthAccountVerificationDecorator struct {
ak AccountKeeper
bankKeeper BankKeeper
evmKeeper EVMKeeper
}
// NewAccountVerificationDecorator creates a new AccountVerificationDecorator
func NewAccountVerificationDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek EVMKeeper) AccountVerificationDecorator {
return AccountVerificationDecorator{
// NewEthAccountVerificationDecorator creates a new EthAccountVerificationDecorator
func NewEthAccountVerificationDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek EVMKeeper) EthAccountVerificationDecorator {
return EthAccountVerificationDecorator{
ak: ak,
bankKeeper: bankKeeper,
evmKeeper: ek,
@@ -172,20 +238,20 @@ func NewAccountVerificationDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek
}
// AnteHandle validates the signature and returns sender address
func (avd AccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
if !ctx.IsCheckTx() {
return next(ctx, tx, simulate)
}
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
msgEthTx, ok := getTxMsg(tx).(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", getTxMsg(tx))
}
// sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.GetFrom()
if address.Empty() {
panic("sender address cannot be empty")
log.Panicln("sender address cannot be empty")
}
acc := avd.ak.GetAccount(ctx, address)
@@ -216,31 +282,31 @@ func (avd AccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
return next(ctx, tx, simulate)
}
// NonceVerificationDecorator checks that the account nonce from the transaction matches
// EthNonceVerificationDecorator checks that the account nonce from the transaction matches
// the sender account sequence.
type NonceVerificationDecorator struct {
type EthNonceVerificationDecorator struct {
ak AccountKeeper
}
// NewNonceVerificationDecorator creates a new NonceVerificationDecorator
func NewNonceVerificationDecorator(ak AccountKeeper) NonceVerificationDecorator {
return NonceVerificationDecorator{
// NewEthNonceVerificationDecorator creates a new EthNonceVerificationDecorator
func NewEthNonceVerificationDecorator(ak AccountKeeper) EthNonceVerificationDecorator {
return EthNonceVerificationDecorator{
ak: ak,
}
}
// AnteHandle validates that the transaction nonce is valid (equivalent to the sender accounts
// current nonce).
func (nvd NonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
func (nvd EthNonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgEthTx, ok := getTxMsg(tx).(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", getTxMsg(tx))
}
// sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.GetFrom()
if address.Empty() {
panic("sender address cannot be empty")
log.Panicln("sender address cannot be empty")
}
acc := nvd.ak.GetAccount(ctx, address)
@@ -290,15 +356,15 @@ func NewEthGasConsumeDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek EVMKe
// constant value of 21000 plus any cost inccured by additional bytes of data
// supplied with the transaction.
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
msgEthTx, ok := getTxMsg(tx).(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", getTxMsg(tx))
}
// sender address should be in the tx cache from the previous AnteHandle call
address := msgEthTx.GetFrom()
if address.Empty() {
panic("sender address cannot be empty")
log.Panicln("sender address cannot be empty")
}
// fetch sender account from signature
@@ -328,7 +394,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
// Charge sender for gas up to limit
if gasLimit != 0 {
// Cost calculates the fees paid to validators based on gas limit and price
cost := new(big.Int).Mul(msgEthTx.Data.Price.BigInt(), new(big.Int).SetUint64(gasLimit))
cost := new(big.Int).Mul(new(big.Int).SetBytes(msgEthTx.Data.Price), new(big.Int).SetUint64(gasLimit))
evmDenom := egcd.evmKeeper.GetParams(ctx).EvmDenom
@@ -347,40 +413,40 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
return next(newCtx, tx, simulate)
}
// IncrementSenderSequenceDecorator increments the sequence of the signers. The
// EthIncrementSenderSequenceDecorator increments the sequence of the signers. The
// main difference with the SDK's IncrementSequenceDecorator is that the MsgEthereumTx
// doesn't implement the SigVerifiableTx interface.
//
// CONTRACT: must be called after msg.VerifySig in order to cache the sender address.
type IncrementSenderSequenceDecorator struct {
type EthIncrementSenderSequenceDecorator struct {
ak AccountKeeper
}
// NewIncrementSenderSequenceDecorator creates a new IncrementSenderSequenceDecorator.
func NewIncrementSenderSequenceDecorator(ak AccountKeeper) IncrementSenderSequenceDecorator {
return IncrementSenderSequenceDecorator{
// NewEthIncrementSenderSequenceDecorator creates a new EthIncrementSenderSequenceDecorator.
func NewEthIncrementSenderSequenceDecorator(ak AccountKeeper) EthIncrementSenderSequenceDecorator {
return EthIncrementSenderSequenceDecorator{
ak: ak,
}
}
// AnteHandle handles incrementing the sequence of the sender.
func (issd IncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
// get and set account must be called with an infinite gas meter in order to prevent
// additional gas from being deducted.
gasMeter := ctx.GasMeter()
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx)
msgEthTx, ok := getTxMsg(tx).(*evmtypes.MsgEthereumTx)
if !ok {
ctx = ctx.WithGasMeter(gasMeter)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", getTxMsg(tx))
}
// increment sequence of all signers
for _, addr := range msgEthTx.GetSigners() {
acc := issd.ak.GetAccount(ctx, addr)
if err := acc.SetSequence(acc.GetSequence() + 1); err != nil {
panic(err)
log.WithError(err).Panicln("failed to set acc sequence")
}
issd.ak.SetAccount(ctx, acc)
}
@@ -389,3 +455,45 @@ func (issd IncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.
ctx = ctx.WithGasMeter(gasMeter)
return next(ctx, tx, simulate)
}
// EthAccountSetupDecorator sets an account to state if it's not stored already. This only applies for MsgEthermint.
type EthAccountSetupDecorator struct {
ak AccountKeeper
}
// NewEthAccountSetupDecorator creates a new EthAccountSetupDecorator instance
func NewEthAccountSetupDecorator(ak AccountKeeper) EthAccountSetupDecorator {
return EthAccountSetupDecorator{
ak: ak,
}
}
// AnteHandle sets an account for MsgEthereumTx (evm) if the sender is registered.
func (asd EthAccountSetupDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
// get and set account must be called with an infinite gas meter in order to prevent
// additional gas from being deducted.
gasMeter := ctx.GasMeter()
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
msgEthTx, ok := getTxMsg(tx).(*evmtypes.MsgEthereumTx)
if !ok {
ctx = ctx.WithGasMeter(gasMeter)
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", getTxMsg(tx))
}
setupAccount(asd.ak, ctx, msgEthTx.GetFrom())
// set the original gas meter
ctx = ctx.WithGasMeter(gasMeter)
return next(ctx, tx, simulate)
}
func setupAccount(ak AccountKeeper, ctx sdk.Context, addr sdk.AccAddress) {
acc := ak.GetAccount(ctx, addr)
if acc != nil {
return
}
acc = ak.NewAccountWithAddress(ctx, addr)
ak.SetAccount(ctx, acc)
}
+20 -20
View File
@@ -6,22 +6,22 @@ import (
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/simapp/params"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
"github.com/cosmos/cosmos-sdk/x/auth"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/ethermint/app"
ante "github.com/cosmos/ethermint/app/ante"
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
ethermint "github.com/cosmos/ethermint/types"
sidechain "github.com/cosmos/ethermint/types"
evmtypes "github.com/cosmos/ethermint/x/evm/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
tmcrypto "github.com/tendermint/tendermint/crypto"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)
@@ -39,11 +39,11 @@ func (suite *AnteTestSuite) SetupTest() {
suite.app = app.Setup(checkTx)
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 2, ChainID: "ethermint-3", Time: time.Now().UTC()})
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 2, ChainID: "injective-3", Time: time.Now().UTC()})
suite.app.AccountKeeper.SetParams(suite.ctx, authtypes.DefaultParams())
suite.app.EvmKeeper.SetParams(suite.ctx, evmtypes.DefaultParams())
suite.encodingConfig = app.MakeEncodingConfig()
suite.encodingConfig = simapp.MakeEncodingConfig()
// We're using TestMsg amino encoding in some tests, so register it here.
suite.encodingConfig.Amino.RegisterConcrete(&testdata.TestMsg{}, "testdata.TestMsg", nil)
@@ -54,20 +54,20 @@ func TestAnteTestSuite(t *testing.T) {
suite.Run(t, new(AnteTestSuite))
}
func newTestMsg(addrs ...sdk.AccAddress) *testdata.TestMsg {
return testdata.NewTestMsg(addrs...)
func newTestMsg(addrs ...sdk.AccAddress) *sdk.TestMsg {
return sdk.NewTestMsg(addrs...)
}
func newTestCoins() sdk.Coins {
return sdk.NewCoins(ethermint.NewPhotonCoinInt64(500000000))
return sdk.NewCoins(sidechain.NewPhotonCoinInt64(500000000))
}
func newTestStdFee() legacytx.StdFee {
return legacytx.NewStdFee(220000, sdk.NewCoins(ethermint.NewPhotonCoinInt64(150)))
func newTestStdFee() auth.StdFee {
return auth.NewStdFee(220000, sdk.NewCoins(sidechain.NewPhotonCoinInt64(150)))
}
// GenerateAddress generates an Ethereum address.
func newTestAddrKey() (sdk.AccAddress, cryptotypes.PrivKey) {
func newTestAddrKey() (sdk.AccAddress, tmcrypto.PrivKey) {
privkey, _ := ethsecp256k1.GenerateKey()
addr := ethcrypto.PubkeyToAddress(privkey.ToECDSA().PublicKey)
@@ -75,30 +75,30 @@ func newTestAddrKey() (sdk.AccAddress, cryptotypes.PrivKey) {
}
func newTestSDKTx(
ctx sdk.Context, msgs []sdk.Msg, privs []cryptotypes.PrivKey,
accNums []uint64, seqs []uint64, fee legacytx.StdFee,
ctx sdk.Context, msgs []sdk.Msg, privs []tmcrypto.PrivKey,
accNums []uint64, seqs []uint64, fee auth.StdFee,
) sdk.Tx {
sigs := make([]legacytx.StdSignature, len(privs))
sigs := make([]auth.StdSignature, len(privs))
for i, priv := range privs {
signBytes := legacytx.StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], 0, fee, msgs, "")
signBytes := auth.StdSignBytes(ctx.ChainID(), accNums[i], seqs[i], fee, msgs, "")
sig, err := priv.Sign(signBytes)
if err != nil {
panic(err)
}
sigs[i] = legacytx.StdSignature{
sigs[i] = auth.StdSignature{
PubKey: priv.PubKey(),
Signature: sig,
}
}
return legacytx.NewStdTx(msgs, fee, sigs, "")
return auth.NewStdTx(msgs, fee, sigs, "")
}
func newTestEthTx(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, priv cryptotypes.PrivKey) (sdk.Tx, error) {
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
func newTestEthTx(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, priv tmcrypto.PrivKey) (sdk.Tx, error) {
chainIDEpoch, err := sidechain.ParseChainID(ctx.ChainID())
if err != nil {
return nil, err
}