diff --git a/CHANGELOG.md b/CHANGELOG.md index 92abdd2a6..192c3f4cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ ### FEATURES +- [\#589](https://github.com/cosmos/evm/pull/589) Remove parallelization blockers via migration from transient to object store, refactoring of gas, indexing, and bloom utilities. + ### BUG FIXES - [\#748](https://github.com/cosmos/evm/pull/748) Fix DynamicFeeChecker in Cosmos ante handler to respect NoBaseFee feemarkets' parameter. @@ -104,7 +106,6 @@ - [\#577](https://github.com/cosmos/evm/pull/577) Changed the way to create a stateful precompile based on the cmn.Precompile, change `NewPrecompile` to not return error. - [\#661](https://github.com/cosmos/evm/pull/661) Removes evmAppOptions from the repository and moves initialization to genesis. Chains must now have a display and denom metadata set for the defined EVM denom in the bank module's metadata. - ## v0.4.1 ### DEPENDENCIES diff --git a/ante/cosmos.go b/ante/cosmos.go index 1820bd79b..a83be2042 100644 --- a/ante/cosmos.go +++ b/ante/cosmos.go @@ -40,6 +40,5 @@ func newCosmosAnteHandler(ctx sdk.Context, options HandlerOptions) sdk.AnteHandl ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler), ante.NewIncrementSequenceDecorator(options.AccountKeeper), ibcante.NewRedundantRelayDecorator(options.IBCKeeper), - evmante.NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper, &feemarketParams), ) } diff --git a/ante/evm/01_setup_ctx.go b/ante/evm/01_setup_ctx.go index 6357e7eb3..9394df2d3 100644 --- a/ante/evm/01_setup_ctx.go +++ b/ante/evm/01_setup_ctx.go @@ -1,7 +1,6 @@ package evm import ( - anteinterfaces "github.com/cosmos/evm/ante/interfaces" evmante "github.com/cosmos/evm/x/vm/ante" errorsmod "cosmossdk.io/errors" @@ -16,18 +15,10 @@ var _ sdktypes.AnteDecorator = &EthSetupContextDecorator{} // EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption // by setting the gas meter to infinite -type EthSetupContextDecorator struct { - evmKeeper anteinterfaces.EVMKeeper -} - -func NewEthSetUpContextDecorator(evmKeeper anteinterfaces.EVMKeeper) EthSetupContextDecorator { - return EthSetupContextDecorator{ - evmKeeper: evmKeeper, - } -} +type EthSetupContextDecorator struct{} func (esc EthSetupContextDecorator) AnteHandle(ctx sdktypes.Context, tx sdktypes.Tx, simulate bool, next sdktypes.AnteHandler) (newCtx sdktypes.Context, err error) { - newCtx, err = SetupContextAndResetTransientGas(ctx, tx, esc.evmKeeper) + newCtx, err = SetupContextAndResetTransientGas(ctx, tx) if err != nil { return ctx, err } @@ -37,7 +28,7 @@ func (esc EthSetupContextDecorator) AnteHandle(ctx sdktypes.Context, tx sdktypes // SetupContextAndResetTransientGas modifies the context to be used in the // execution of the ante handler associated with an EVM transaction. Previous // gas consumed is reset in the transient store. -func SetupContextAndResetTransientGas(ctx sdktypes.Context, tx sdktypes.Tx, evmKeeper anteinterfaces.EVMKeeper) (sdktypes.Context, error) { +func SetupContextAndResetTransientGas(ctx sdktypes.Context, tx sdktypes.Tx) (sdktypes.Context, error) { // all transactions must implement GasTx _, ok := tx.(authante.GasTx) if !ok { @@ -50,12 +41,5 @@ func SetupContextAndResetTransientGas(ctx sdktypes.Context, tx sdktypes.Tx, evmK newCtx := evmante.BuildEvmExecutionCtx(ctx). WithGasMeter(storetypes.NewInfiniteGasMeter()) - // Reset transient gas used to prepare the execution of current cosmos tx. - // Transient gas-used is necessary to sum the gas-used of cosmos tx, when it contains multiple eth msgs. - // - // TODO: add more context here to explain why gas used is reset. Not clear - // from docstring. - evmKeeper.ResetTransientGasUsed(ctx) - return newCtx, nil } diff --git a/ante/evm/10_gas_wanted.go b/ante/evm/10_gas_wanted.go deleted file mode 100644 index ef07c0ec7..000000000 --- a/ante/evm/10_gas_wanted.go +++ /dev/null @@ -1,85 +0,0 @@ -package evm - -import ( - "math/big" - - anteinterfaces "github.com/cosmos/evm/ante/interfaces" - "github.com/cosmos/evm/ante/types" - feemarkettypes "github.com/cosmos/evm/x/feemarket/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - - errorsmod "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" -) - -// GasWantedDecorator keeps track of the gasWanted amount on the current block in transient store -// for BaseFee calculation. -// NOTE: This decorator does not perform any validation -type GasWantedDecorator struct { - evmKeeper anteinterfaces.EVMKeeper - feeMarketKeeper anteinterfaces.FeeMarketKeeper - feemarketParams *feemarkettypes.Params -} - -// NewGasWantedDecorator creates a new NewGasWantedDecorator -func NewGasWantedDecorator( - evmKeeper anteinterfaces.EVMKeeper, - feeMarketKeeper anteinterfaces.FeeMarketKeeper, - feemarketParams *feemarkettypes.Params, -) GasWantedDecorator { - return GasWantedDecorator{ - evmKeeper, - feeMarketKeeper, - feemarketParams, - } -} - -func (gwd GasWantedDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - ethCfg := evmtypes.GetEthChainConfig() - - blockHeight := big.NewInt(ctx.BlockHeight()) - isLondon := ethCfg.IsLondon(blockHeight) - - if err := CheckGasWanted(ctx, gwd.feeMarketKeeper, tx, isLondon, gwd.feemarketParams); err != nil { - return ctx, err - } - - return next(ctx, tx, simulate) -} - -func CheckGasWanted(ctx sdk.Context, feeMarketKeeper anteinterfaces.FeeMarketKeeper, tx sdk.Tx, isLondon bool, feemarketParams *feemarkettypes.Params) error { - if !isLondon { - return nil - } - - feeTx, ok := tx.(sdk.FeeTx) - if !ok { - return nil - } - - gasWanted := feeTx.GetGas() - - // return error if the tx gas is greater than the block limit (max gas) - blockGasLimit := types.BlockGasLimit(ctx) - if gasWanted > blockGasLimit { - return errorsmod.Wrapf( - errortypes.ErrOutOfGas, - "tx gas (%d) exceeds block gas limit (%d)", - gasWanted, - blockGasLimit, - ) - } - - if !feemarketParams.IsBaseFeeEnabled(ctx.BlockHeight()) { - return nil - } - - // Add total gasWanted to cumulative in block transientStore in FeeMarket module - if _, err := feeMarketKeeper.AddTransientGasWanted(ctx, gasWanted); err != nil { - return errorsmod.Wrapf(err, "failed to add gas wanted to transient store") - } - - return nil -} diff --git a/ante/evm/11_emit_event.go b/ante/evm/11_emit_event.go index 26431302b..d3541d883 100644 --- a/ante/evm/11_emit_event.go +++ b/ante/evm/11_emit_event.go @@ -3,62 +3,23 @@ package evm import ( "strconv" - anteinterfaces "github.com/cosmos/evm/ante/interfaces" evmtypes "github.com/cosmos/evm/x/vm/types" - errorsmod "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" ) -// EthEmitEventDecorator emit events in ante handler in case of tx execution failed (out of block gas limit). -type EthEmitEventDecorator struct { - evmKeeper anteinterfaces.EVMKeeper -} - -// NewEthEmitEventDecorator creates a new EthEmitEventDecorator -func NewEthEmitEventDecorator(evmKeeper anteinterfaces.EVMKeeper) EthEmitEventDecorator { - return EthEmitEventDecorator{evmKeeper} -} - -// AnteHandle emits some basic events for the eth messages -func (eeed EthEmitEventDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { - // After eth tx passed ante handler, the fee is deducted and nonce increased, it shouldn't be ignored by json-rpc, - // we need to emit some basic events at the very end of ante handler to be indexed by CometBFT. - blockTxIndex := eeed.evmKeeper.GetTxIndexTransient(ctx) - - msgs := tx.GetMsgs() - if msgs == nil { - return ctx, errorsmod.Wrap(errortypes.ErrUnknownRequest, "invalid transaction. Transaction without messages") - } - - for i, msg := range msgs { - msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx) - if !ok { - return ctx, errorsmod.Wrapf(errortypes.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil)) - } - - txIdx := uint64(i) //nolint:gosec // G115 // won't exceed uint64 - EmitTxHashEvent(ctx, msgEthTx, blockTxIndex, txIdx) - } - - return next(ctx, tx, simulate) -} - // EmitTxHashEvent emits the Ethereum tx // // FIXME: This is Technical debt. Ideally the sdk.Tx hash should be the Ethereum // tx hash (msg.Hash) instead of using events for indexing Eth txs. -// TxIndex should be included in the header vote extension as part of ABCI++ -func EmitTxHashEvent(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, blockTxIndex, msgIndex uint64) { +func EmitTxHashEvent(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, blockTxIndex uint64) { // emit ethereum tx hash as an event so that it can be indexed by CometBFT for query purposes // it's emitted in ante handler, so we can query failed transaction (out of block gas limit). ctx.EventManager().EmitEvent( sdk.NewEvent( evmtypes.EventTypeEthereumTx, sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msg.Hash().String()), - sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(blockTxIndex+msgIndex, 10)), // #nosec G115 + sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(blockTxIndex, 10)), // #nosec G115 ), ) } diff --git a/ante/evm/mono_decorator.go b/ante/evm/mono_decorator.go index ba4601557..f25ac91db 100644 --- a/ante/evm/mono_decorator.go +++ b/ante/evm/mono_decorator.go @@ -79,7 +79,7 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne evmDenom := evmtypes.GetEVMCoinDenom() // 1. setup ctx - ctx, err = SetupContextAndResetTransientGas(ctx, tx, md.evmKeeper) + ctx, err = SetupContextAndResetTransientGas(ctx, tx) if err != nil { return ctx, err } @@ -265,14 +265,8 @@ func (md MonoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, ne return ctx, err } - // 10. gas wanted - if err := CheckGasWanted(ctx, md.feeMarketKeeper, tx, decUtils.Rules.IsLondon, md.feemarketParams); err != nil { - return ctx, err - } - - // 11. emit events - txIdx := uint64(msgIndex) //nolint:gosec // G115 - EmitTxHashEvent(ctx, ethMsg, decUtils.BlockTxIndex, txIdx) + // Emit event unconditionally - ctx.TxIndex() will be valid during block execution + EmitTxHashEvent(ctx, ethMsg, uint64(ctx.TxIndex())) // #nosec G115 -- no overlfow here if err := CheckTxFee(txFeeInfo, decUtils.TxFee, decUtils.TxGasLimit); err != nil { return ctx, err diff --git a/ante/evm/mono_decorator_test.go b/ante/evm/mono_decorator_test.go index 20d3e1358..7a9e4156e 100644 --- a/ante/evm/mono_decorator_test.go +++ b/ante/evm/mono_decorator_test.go @@ -62,13 +62,11 @@ func (k *ExtendedEVMKeeper) SpendableCoin(ctx sdk.Context, addr common.Address) return uint256.NewInt(0) } -func (k *ExtendedEVMKeeper) ResetTransientGasUsed(_ sdk.Context) {} func (k *ExtendedEVMKeeper) GetParams(_ sdk.Context) evmsdktypes.Params { return evmsdktypes.DefaultParams() } func (k *ExtendedEVMKeeper) GetBaseFee(_ sdk.Context) *big.Int { return big.NewInt(0) } func (k *ExtendedEVMKeeper) GetMinGasPrice(_ sdk.Context) math.LegacyDec { return math.LegacyZeroDec() } -func (k *ExtendedEVMKeeper) GetTxIndexTransient(_ sdk.Context) uint64 { return 0 } // only methods called by EVMMonoDecorator type MockFeeMarketKeeper struct{} @@ -79,9 +77,6 @@ func (m MockFeeMarketKeeper) GetParams(ctx sdk.Context) feemarkettypes.Params { return param } -func (m MockFeeMarketKeeper) AddTransientGasWanted(_ sdk.Context, _ uint64) (uint64, error) { - return 0, nil -} func (m MockFeeMarketKeeper) GetBaseFeeEnabled(_ sdk.Context) bool { return true } func (m MockFeeMarketKeeper) GetBaseFee(_ sdk.Context) math.LegacyDec { return math.LegacyZeroDec() } @@ -222,6 +217,12 @@ func TestMonoDecorator(t *testing.T) { monoDec := evm.NewEVMMonoDecorator(accountKeeper, feeMarketKeeper, keeper, 0, ¶ms, &feemarketParams) ctx := sdk.NewContext(nil, tmproto.Header{}, false, log.NewNopLogger()) ctx = ctx.WithBlockGasMeter(storetypes.NewGasMeter(1e19)) + blockParams := tmproto.BlockParams{ + MaxBytes: 200000, + MaxGas: 81500000, // default limit + } + consParams := tmproto.ConsensusParams{Block: &blockParams} + ctx = ctx.WithConsensusParams(consParams) msgs := tc.buildMsgs(privKey) tx, err := utiltx.PrepareEthTx(cfg.TxConfig, nil, toMsgSlice(msgs)...) diff --git a/ante/evm/nonce_limit_test.go b/ante/evm/nonce_limit_test.go index a6c3b8c36..b8403724e 100644 --- a/ante/evm/nonce_limit_test.go +++ b/ante/evm/nonce_limit_test.go @@ -34,7 +34,7 @@ func (m *mockAccountKeeper) GetAccount(ctx context.Context, addr sdk.AccAddress) } func (m *mockAccountKeeper) SetAccount(ctx context.Context, account sdk.AccountI) { m.last = account } func (m *mockAccountKeeper) RemoveAccount(ctx context.Context, account sdk.AccountI) {} -func (m *mockAccountKeeper) GetParams(ctx context.Context) (params authtypes.Params) { return } +func (m *mockAccountKeeper) GetParams(ctx context.Context) (params authtypes.Params) { return params } func (m *mockAccountKeeper) GetSequence(ctx context.Context, addr sdk.AccAddress) (uint64, error) { if m.last == nil { return 0, nil diff --git a/ante/evm/utils.go b/ante/evm/utils.go index 48e45ebee..68368c7a9 100644 --- a/ante/evm/utils.go +++ b/ante/evm/utils.go @@ -26,7 +26,6 @@ type DecoratorUtils struct { BaseFee *big.Int MempoolMinGasPrice sdkmath.LegacyDec GlobalMinGasPrice sdkmath.LegacyDec - BlockTxIndex uint64 TxGasLimit uint64 GasWanted uint64 MinPriority int64 @@ -73,7 +72,6 @@ func NewMonoDecoratorUtils( BaseFee: baseFee, MempoolMinGasPrice: mempoolMinGasPrice, GlobalMinGasPrice: globalMinGasPrice, - BlockTxIndex: ek.GetTxIndexTransient(ctx), GasWanted: 0, MinPriority: int64(math.MaxInt64), // TxGasLimit and TxFee are set to zero because they are updated diff --git a/ante/interfaces/evm.go b/ante/interfaces/evm.go index d296e7b7d..d64779129 100644 --- a/ante/interfaces/evm.go +++ b/ante/interfaces/evm.go @@ -23,15 +23,12 @@ type EVMKeeper interface { stateDB vm.StateDB) *vm.EVM DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error SpendableCoin(ctx sdk.Context, addr common.Address) *uint256.Int - ResetTransientGasUsed(ctx sdk.Context) - GetTxIndexTransient(ctx sdk.Context) uint64 GetParams(ctx sdk.Context) evmtypes.Params } // FeeMarketKeeper exposes the required feemarket keeper interface required for ante handlers type FeeMarketKeeper interface { GetParams(ctx sdk.Context) (params feemarkettypes.Params) - AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) } type ProtoTxProvider interface { diff --git a/ante/types/block.go b/ante/types/block.go index b235da526..0fc686424 100644 --- a/ante/types/block.go +++ b/ante/types/block.go @@ -10,13 +10,6 @@ import ( // set, it returns the max gas from the application consensus params. // NOTE: see https://github.com/cosmos/cosmos-sdk/issues/9514 for full reference func BlockGasLimit(ctx sdk.Context) uint64 { - blockGasMeter := ctx.BlockGasMeter() - - // Get the limit from the gas meter only if its not null and not an InfiniteGasMeter - if blockGasMeter != nil && blockGasMeter.Limit() != 0 { - return blockGasMeter.Limit() - } - // Otherwise get from the consensus parameters cp := ctx.ConsensusParams() if cp.Block == nil { diff --git a/ante/utils_test.go b/ante/utils_test.go index dd31c792d..00890aa94 100644 --- a/ante/utils_test.go +++ b/ante/utils_test.go @@ -19,7 +19,7 @@ func generatePubKeysAndSignatures(n int, msg []byte, _ bool) (pubkeys []cryptoty pubkeys[i] = privkey.PubKey() signatures[i], _ = privkey.Sign(msg) } - return + return pubkeys, signatures } func expectedGasCostByKeys(pubkeys []cryptotypes.PubKey) uint64 { diff --git a/evmd/app.go b/evmd/app.go index 732c25e52..a192087a3 100644 --- a/evmd/app.go +++ b/evmd/app.go @@ -7,7 +7,6 @@ import ( "io" "os" - "github.com/spf13/cast" // Force-load the tracer engines to trigger registration due to Go-Ethereum v1.10.15 changes @@ -162,9 +161,9 @@ type EVMD struct { pendingTxListeners []evmante.PendingTxListener // keys to access the substores - keys map[string]*storetypes.KVStoreKey - tkeys map[string]*storetypes.TransientStoreKey - memKeys map[string]*storetypes.MemoryStoreKey + keys map[string]*storetypes.KVStoreKey + tkeys map[string]*storetypes.TransientStoreKey + okeys map[string]*storetypes.ObjectStoreKey // keepers AccountKeeper authkeeper.AccountKeeper @@ -243,12 +242,15 @@ func NewExampleApp( // Cosmos EVM store keys evmtypes.StoreKey, feemarkettypes.StoreKey, erc20types.StoreKey, precisebanktypes.StoreKey, ) + okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey, evmtypes.ObjectKey) - tkeys := storetypes.NewTransientStoreKeys(evmtypes.TransientKey, feemarkettypes.TransientKey) var nonTransientKeys []storetypes.StoreKey for _, k := range keys { nonTransientKeys = append(nonTransientKeys, k) } + for _, k := range okeys { + nonTransientKeys = append(nonTransientKeys, k) + } // load state streaming if enabled if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil { @@ -268,7 +270,7 @@ func NewExampleApp( txConfig: txConfig, interfaceRegistry: interfaceRegistry, keys: keys, - tkeys: tkeys, + okeys: okeys, } // removed x/params: no ParamsKeeper initialization @@ -302,6 +304,7 @@ func NewExampleApp( authAddr, logger, ) + app.BankKeeper = app.BankKeeper.WithObjStoreKey(okeys[banktypes.ObjectStoreKey]) // optional: enable sign mode textual by overwriting the default tx config (after setting the bank keeper) enabledSignModes := append(authtx.DefaultSignModes, signingtypes.SignMode_SIGN_MODE_TEXTUAL) //nolint:gocritic @@ -427,7 +430,6 @@ func NewExampleApp( app.FeeMarketKeeper = feemarketkeeper.NewKeeper( appCodec, authtypes.NewModuleAddress(govtypes.ModuleName), keys[feemarkettypes.StoreKey], - tkeys[feemarkettypes.TransientKey], ) // Set up PreciseBank keeper @@ -446,7 +448,7 @@ func NewExampleApp( // NOTE: it's required to set up the EVM keeper before the ERC-20 keeper, because it is used in its instantiation. app.EVMKeeper = evmkeeper.NewKeeper( // TODO: check why this is not adjusted to use the runtime module methods like SDK native keepers - appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], nonTransientKeys, + appCodec, keys[evmtypes.StoreKey], okeys[evmtypes.ObjectKey], nonTransientKeys, authtypes.NewModuleAddress(govtypes.ModuleName), app.AccountKeeper, app.PreciseBankKeeper, @@ -631,8 +633,10 @@ func NewExampleApp( // NOTE: the feemarket module should go last in order of end blockers that are actually doing something, // to get the full block gas used. app.ModuleManager.SetOrderEndBlockers( - govtypes.ModuleName, stakingtypes.ModuleName, - authtypes.ModuleName, banktypes.ModuleName, + banktypes.ModuleName, + govtypes.ModuleName, + stakingtypes.ModuleName, + authtypes.ModuleName, // Cosmos EVM EndBlockers evmtypes.ModuleName, erc20types.ModuleName, feemarkettypes.ModuleName, @@ -708,7 +712,7 @@ func NewExampleApp( // initialize stores app.MountKVStores(keys) - app.MountTransientStores(tkeys) + app.MountObjectStores(okeys) maxGasWanted := cast.ToUint64(appOpts.Get(srvflags.EVMMaxTxGasWanted)) @@ -916,13 +920,6 @@ func (app *EVMD) GetTKey(storeKey string) *storetypes.TransientStoreKey { return app.tkeys[storeKey] } -// GetMemKey returns the MemStoreKey for the provided mem key. -// -// NOTE: This is solely used for testing purposes. -func (app *EVMD) GetMemKey(storeKey string) *storetypes.MemoryStoreKey { - return app.memKeys[storeKey] -} - // SimulationManager implements the SimulationApp interface func (app *EVMD) SimulationManager() *module.SimulationManager { return app.sm diff --git a/evmd/cmd/evmd/cmd/root.go b/evmd/cmd/evmd/cmd/root.go index 44e579231..948dd39e2 100644 --- a/evmd/cmd/evmd/cmd/root.go +++ b/evmd/cmd/evmd/cmd/root.go @@ -378,5 +378,5 @@ func getChainIDFromOpts(appOpts servertypes.AppOptions) (chainID string, err err } } - return + return chainID, err } diff --git a/evmd/go.mod b/evmd/go.mod index feec0ef90..e8d859c10 100644 --- a/evmd/go.mod +++ b/evmd/go.mod @@ -297,4 +297,6 @@ replace ( github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1 // replace broken goleveldb github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + // use btree fork for bstm + github.com/tidwall/btree => github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 ) diff --git a/evmd/go.sum b/evmd/go.sum index f5e8ffb9d..21ecc4617 100644 --- a/evmd/go.sum +++ b/evmd/go.sum @@ -266,6 +266,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 h1:dC3GJcS8bJiSEe7VAFDDFgFnVM1G9nBdGOgqJsmsZwM= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -970,8 +972,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tidwall/btree v1.8.1 h1:27ehoXvm5AG/g+1VxLS1SD3vRhp/H7LuEfwNvddEdmA= -github.com/tidwall/btree v1.8.1/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= diff --git a/evmd/tests/network/util.go b/evmd/tests/network/util.go index fc4a538d4..b99fb2248 100644 --- a/evmd/tests/network/util.go +++ b/evmd/tests/network/util.go @@ -226,7 +226,6 @@ func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalance inflationGenState.Params.MintDenom = cfg.BondDenom cfg.GenesisState[minttypes.ModuleName] = cfg.Codec.MustMarshalJSON(&inflationGenState) - var evmGenState evmtypes.GenesisState cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[evmtypes.ModuleName], &evmGenState) diff --git a/go.mod b/go.mod index 0f45ded5e..fa0d4e078 100644 --- a/go.mod +++ b/go.mod @@ -290,6 +290,8 @@ replace ( github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.1 // replace broken goleveldb github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 + // use btree fork for bstm + github.com/tidwall/btree => github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 ) retract v0.4.0 diff --git a/go.sum b/go.sum index d7a8bc8d0..99ba9a26d 100644 --- a/go.sum +++ b/go.sum @@ -261,6 +261,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951 h1:dC3GJcS8bJiSEe7VAFDDFgFnVM1G9nBdGOgqJsmsZwM= +github.com/cosmos/btree v0.0.0-20250924232609-2c6195d95951/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= github.com/cosmos/cosmos-db v1.1.3 h1:7QNT77+vkefostcKkhrzDK9uoIEryzFrU9eoMeaQOPY= github.com/cosmos/cosmos-db v1.1.3/go.mod h1:kN+wGsnwUJZYn8Sy5Q2O0vCYA99MJllkKASbs6Unb9U= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= @@ -950,8 +952,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tidwall/btree v1.8.1 h1:27ehoXvm5AG/g+1VxLS1SD3vRhp/H7LuEfwNvddEdmA= -github.com/tidwall/btree v1.8.1/go.mod h1:jBbTdUWhSZClZWoDg54VnvV7/54modSOzDN7VXftj1A= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= diff --git a/mempool/txpool/legacypool/reset_testing.go b/mempool/txpool/legacypool/reset_testing.go index 16a11a2a5..b24088c3d 100644 --- a/mempool/txpool/legacypool/reset_testing.go +++ b/mempool/txpool/legacypool/reset_testing.go @@ -22,17 +22,17 @@ func (pool *LegacyPool) reset(oldHead, newHead *types.Header) { log.Debug("Skipping reorg on Cosmos chain (testing mode)", "oldHead", oldHead.Hash(), "newHead", newHead.Hash(), "newParent", newHead.ParentHash) reinject = nil // No transactions to reinject } - + // Initialize the internal state to the current head if newHead == nil { newHead = pool.chain.CurrentBlock() // Special case during testing } - + // Ensure BaseFee is set for EIP-1559 compatibility in tests if newHead.BaseFee == nil && pool.chainconfig.IsLondon(newHead.Number) { // Set a default base fee for testing newHead.BaseFee = big.NewInt(1000000000) // 1 gwei default } - + pool.resetInternalState(newHead, reinject) -} \ No newline at end of file +} diff --git a/precompiles/common/mocks/BankKeeper.go b/precompiles/common/mocks/BankKeeper.go index a3c72593c..6f92fb5ea 100644 --- a/precompiles/common/mocks/BankKeeper.go +++ b/precompiles/common/mocks/BankKeeper.go @@ -155,7 +155,8 @@ func (_m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, func NewBankKeeper(t interface { mock.TestingT Cleanup(func()) -}) *BankKeeper { +}, +) *BankKeeper { mock := &BankKeeper{} mock.Mock.Test(t) diff --git a/precompiles/ics20/types.go b/precompiles/ics20/types.go index 56b45331a..62b992adc 100644 --- a/precompiles/ics20/types.go +++ b/precompiles/ics20/types.go @@ -239,5 +239,5 @@ func safeCopyInputs(method *abi.Method, args []interface{}, pageRequest *PageReq } }() err = method.Inputs.Copy(pageRequest, args) - return + return err } diff --git a/rpc/backend/comet_to_eth.go b/rpc/backend/comet_to_eth.go index 8b4847726..55c261517 100644 --- a/rpc/backend/comet_to_eth.go +++ b/rpc/backend/comet_to_eth.go @@ -296,7 +296,7 @@ func (b *Backend) ReceiptsFromCometBlock( // transaction corresponding to this receipt. BlockHash: blockHash, BlockNumber: big.NewInt(resBlock.Block.Height), - TransactionIndex: uint(txResult.EthTxIndex), // #nosec G115 -- checked for int overflow already + TransactionIndex: uint(i), // #nosec G115 -- no overflow here } receipts[i] = receipt diff --git a/rpc/backend/tx_info_test.go b/rpc/backend/tx_info_test.go index 01bc77791..7a1bf7926 100644 --- a/rpc/backend/tx_info_test.go +++ b/rpc/backend/tx_info_test.go @@ -467,20 +467,21 @@ func TestReceiptsFromCometBlock(t *testing.T) { } tcs := []struct { name string - ethTxIndex int32 + ethTxIndex int }{ {"tx_with_index_5", 5}, {"tx_with_index_10", 10}, } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - msgs := []*evmtypes.MsgEthereumTx{ - buildMsgEthereumTx(t), + var msgs []*evmtypes.MsgEthereumTx + for range tc.ethTxIndex + 1 { + msgs = append(msgs, buildMsgEthereumTx(t)) } expectedTxResult := &servertypes.TxResult{ Height: height, TxIndex: 0, - EthTxIndex: tc.ethTxIndex, + EthTxIndex: int32(tc.ethTxIndex), // #nosec G115 -- no overflow here MsgIndex: 0, } mockIndexer := &MockIndexer{ @@ -493,13 +494,13 @@ func TestReceiptsFromCometBlock(t *testing.T) { mockEVMQueryClient.On("BaseFee", mock.Anything, mock.Anything).Return(&evmtypes.QueryBaseFeeResponse{}, nil) receipts, err := backend.ReceiptsFromCometBlock(resBlock, blockRes, msgs) require.NoError(t, err) - require.Len(t, receipts, 1) - actualTxIndex := receipts[0].TransactionIndex + require.Len(t, receipts, tc.ethTxIndex+1) + actualTxIndex := receipts[tc.ethTxIndex].TransactionIndex require.NotEqual(t, uint(0), actualTxIndex) require.Equal(t, uint(tc.ethTxIndex), actualTxIndex) // #nosec G115 - require.Equal(t, msgs[0].Hash(), receipts[0].TxHash) - require.Equal(t, big.NewInt(height), receipts[0].BlockNumber) - require.Equal(t, ethtypes.ReceiptStatusSuccessful, receipts[0].Status) + require.Equal(t, msgs[tc.ethTxIndex].Hash(), receipts[tc.ethTxIndex].TxHash) + require.Equal(t, big.NewInt(height), receipts[tc.ethTxIndex].BlockNumber) + require.Equal(t, ethtypes.ReceiptStatusSuccessful, receipts[tc.ethTxIndex].Status) }) } } diff --git a/scripts/compile_smart_contracts/compile_smart_contracts.py b/scripts/compile_smart_contracts/compile_smart_contracts.py index df47af417..eacc1d374 100644 --- a/scripts/compile_smart_contracts/compile_smart_contracts.py +++ b/scripts/compile_smart_contracts/compile_smart_contracts.py @@ -154,17 +154,17 @@ def is_ignored_file(file_path: Path, repo_path: Path) -> bool: """ relative_path = file_path.relative_to(repo_path) file_name = file_path.name - + for ignored_pattern in IGNORED_FILES: # Check if it's a regex pattern (contains regex metacharacters) - if any(char in ignored_pattern for char in r'.*+?^${}[]|()\\'): + if any(char in ignored_pattern for char in r".*+?^${}[]|()\\"): if re.search(ignored_pattern, str(relative_path)): return True else: # Simple filename match if file_name == ignored_pattern: return True - + return False diff --git a/server/start.go b/server/start.go index 725778857..96061cada 100644 --- a/server/start.go +++ b/server/start.go @@ -569,7 +569,7 @@ func OpenIndexerDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) // - traceWriterFile: The path to the trace store file. If this is an empty string, no file will be opened. func openTraceWriter(traceWriterFile string) (w io.Writer, err error) { if traceWriterFile == "" { - return + return w, err } filePath := filepath.Clean(traceWriterFile) diff --git a/tests/integration/ante/test_evm_01_setup_ctx.go b/tests/integration/ante/test_evm_01_setup_ctx.go index 259e601f5..09a499326 100644 --- a/tests/integration/ante/test_evm_01_setup_ctx.go +++ b/tests/integration/ante/test_evm_01_setup_ctx.go @@ -14,7 +14,7 @@ import ( ) func (s *EvmAnteTestSuite) TestEthSetupContextDecorator() { - dec := evmante.NewEthSetUpContextDecorator(s.GetNetwork().App.GetEVMKeeper()) + dec := evmante.EthSetupContextDecorator{} ethContractCreationTxParams := &evmtypes.EvmTxArgs{ ChainID: evmtypes.GetEthChainConfig().ChainID, Nonce: 1, diff --git a/tests/integration/ante/test_evm_fee_market.go b/tests/integration/ante/test_evm_fee_market.go deleted file mode 100644 index 13053b162..000000000 --- a/tests/integration/ante/test_evm_fee_market.go +++ /dev/null @@ -1,150 +0,0 @@ -package ante - -import ( - "math/big" - - ethtypes "github.com/ethereum/go-ethereum/core/types" - - "github.com/cosmos/evm/ante/evm" - "github.com/cosmos/evm/ante/types" - "github.com/cosmos/evm/server/config" - "github.com/cosmos/evm/testutil" - testconstants "github.com/cosmos/evm/testutil/constants" - utiltx "github.com/cosmos/evm/testutil/tx" - evmtypes "github.com/cosmos/evm/x/vm/types" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -) - -func (s *EvmAnteTestSuite) TestGasWantedDecorator() { - s.WithFeemarketEnabled(true) - s.SetupTest() - ctx := s.GetNetwork().GetContext() - feeMarketKeeper := s.GetNetwork().App.GetFeeMarketKeeper() - params := feeMarketKeeper.GetParams(ctx) - dec := evm.NewGasWantedDecorator(s.GetNetwork().App.GetEVMKeeper(), feeMarketKeeper, ¶ms) - from, fromPrivKey := utiltx.NewAddrKey() - to := utiltx.GenerateAddress() - denom := evmtypes.GetEVMCoinDenom() - - testCases := []struct { - name string - expectedGasWanted uint64 - malleate func() sdk.Tx - expPass bool - }{ - { - "Cosmos Tx", - TestGasLimit, - func() sdk.Tx { - testMsg := banktypes.MsgSend{ - FromAddress: "cosmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp", - ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", - Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}}, - } - txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), denom, &testMsg) - return txBuilder.GetTx() - }, - true, - }, - { - "Ethereum Legacy Tx", - TestGasLimit, - func() sdk.Tx { - txArgs := evmtypes.EvmTxArgs{ - To: &to, - GasPrice: big.NewInt(0), - GasLimit: TestGasLimit, - } - return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() - }, - true, - }, - { - "Ethereum Access List Tx", - TestGasLimit, - func() sdk.Tx { - emptyAccessList := ethtypes.AccessList{} - txArgs := evmtypes.EvmTxArgs{ - To: &to, - GasPrice: big.NewInt(0), - GasLimit: TestGasLimit, - Accesses: &emptyAccessList, - } - return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() - }, - true, - }, - { - "Ethereum Dynamic Fee Tx (EIP1559)", - TestGasLimit, - func() sdk.Tx { - emptyAccessList := ethtypes.AccessList{} - txArgs := evmtypes.EvmTxArgs{ - To: &to, - GasPrice: big.NewInt(0), - GasFeeCap: big.NewInt(100), - GasLimit: TestGasLimit, - GasTipCap: big.NewInt(50), - Accesses: &emptyAccessList, - } - return s.CreateTxBuilder(fromPrivKey, txArgs).GetTx() - }, - true, - }, - { - "EIP712 message", - 200000, - func() sdk.Tx { - amount := sdk.NewCoins(sdk.NewCoin(testconstants.ExampleAttoDenom, sdkmath.NewInt(20))) - gas := uint64(200000) - acc := s.GetNetwork().App.GetAccountKeeper().NewAccountWithAddress(ctx, from.Bytes()) - s.Require().NoError(acc.SetSequence(1)) - s.GetNetwork().App.GetAccountKeeper().SetAccount(ctx, acc) - builder, err := s.CreateTestEIP712TxBuilderMsgSend(acc.GetAddress(), fromPrivKey, ctx.ChainID(), config.DefaultEVMChainID, gas, amount) - s.Require().NoError(err) - return builder.GetTx() - }, - true, - }, - { - "Cosmos Tx - gasWanted > max block gas", - TestGasLimit, - func() sdk.Tx { - denom := testconstants.ExampleAttoDenom - testMsg := banktypes.MsgSend{ - FromAddress: "cosmos1x8fhpj9nmhqk8z9kpgjt95ck2xwyue0ptzkucp", - ToAddress: "cosmos1dx67l23hz9l0k9hcher8xz04uj7wf3yu26l2yn", - Amount: sdk.Coins{sdk.Coin{Amount: sdkmath.NewInt(10), Denom: denom}}, - } - txBuilder := s.CreateTestCosmosTxBuilder(sdkmath.NewInt(10), testconstants.ExampleAttoDenom, &testMsg) - limit := types.BlockGasLimit(ctx) - txBuilder.SetGasLimit(limit + 5) - return txBuilder.GetTx() - }, - false, - }, - } - - // cumulative gas wanted from all test transactions in the same block - var expectedGasWanted uint64 - - for _, tc := range testCases { - s.Run(tc.name, func() { - _, err := dec.AnteHandle(ctx, tc.malleate(), false, testutil.NoOpNextFn) - if tc.expPass { - s.Require().NoError(err) - - gasWanted := s.GetNetwork().App.GetFeeMarketKeeper().GetTransientGasWanted(ctx) - expectedGasWanted += tc.expectedGasWanted - s.Require().Equal(expectedGasWanted, gasWanted) - } else { - // TODO: check for specific error message - s.Require().Error(err) - } - }) - } -} diff --git a/tests/integration/ante/test_evm_unit_10_gas_wanted.go b/tests/integration/ante/test_evm_unit_10_gas_wanted.go deleted file mode 100644 index c0f4fb187..000000000 --- a/tests/integration/ante/test_evm_unit_10_gas_wanted.go +++ /dev/null @@ -1,138 +0,0 @@ -package ante - -import ( - "fmt" - - "github.com/cosmos/evm/ante/evm" - testconstants "github.com/cosmos/evm/testutil/constants" - "github.com/cosmos/evm/testutil/integration/evm/factory" - "github.com/cosmos/evm/testutil/integration/evm/grpc" - "github.com/cosmos/evm/testutil/integration/evm/network" - "github.com/cosmos/evm/testutil/integration/evm/utils" - testkeyring "github.com/cosmos/evm/testutil/keyring" - evmtypes "github.com/cosmos/evm/x/vm/types" - - storetypes "cosmossdk.io/store/types" - - sdktypes "github.com/cosmos/cosmos-sdk/types" - errortypes "github.com/cosmos/cosmos-sdk/types/errors" -) - -func (s *EvmUnitAnteTestSuite) TestCheckGasWanted() { - keyring := testkeyring.New(1) - unitNetwork := network.NewUnitTestNetwork( - s.create, - network.WithChainID(testconstants.ChainID{ - ChainID: s.ChainID, - EVMChainID: s.EvmChainID, - }), - network.WithPreFundedAccounts(keyring.GetAllAccAddrs()...), - ) - grpcHandler := grpc.NewIntegrationHandler(unitNetwork) - txFactory := factory.New(unitNetwork, grpcHandler) - commonGasLimit := uint64(100_000) - - testCases := []struct { - name string - expectedError error - getCtx func() sdktypes.Context - isLondon bool - expectedTransientGasWanted uint64 - }{ - { - name: "success: if isLondon false it should not error", - expectedError: nil, - getCtx: func() sdktypes.Context { - // Even if the gasWanted is more than the blockGasLimit, it should not error - blockMeter := storetypes.NewGasMeter(commonGasLimit - 10000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: false, - expectedTransientGasWanted: 0, - }, - { - name: "success: gasWanted is less than blockGasLimit", - expectedError: nil, - getCtx: func() sdktypes.Context { - blockMeter := storetypes.NewGasMeter(commonGasLimit + 10000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: true, - expectedTransientGasWanted: commonGasLimit, - }, - { - name: "fail: gasWanted is more than blockGasLimit", - expectedError: errortypes.ErrOutOfGas, - getCtx: func() sdktypes.Context { - blockMeter := storetypes.NewGasMeter(commonGasLimit - 10000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: true, - expectedTransientGasWanted: 0, - }, - { - name: "success: gasWanted is less than blockGasLimit and basefee param is disabled", - expectedError: nil, - getCtx: func() sdktypes.Context { - // Set basefee param to false - feeMarketParams, err := grpcHandler.GetFeeMarketParams() - s.Require().NoError(err) - - feeMarketParams.Params.NoBaseFee = true - err = utils.UpdateFeeMarketParams(utils.UpdateParamsInput{ - Tf: txFactory, - Network: unitNetwork, - Pk: keyring.GetPrivKey(0), - Params: feeMarketParams.Params, - }) - s.Require().NoError(err, "expected no error when updating fee market params") - - blockMeter := storetypes.NewGasMeter(commonGasLimit + 10_000) - return unitNetwork.GetContext().WithBlockGasMeter(blockMeter) - }, - isLondon: true, - expectedTransientGasWanted: 0, - }, - } - - for _, tc := range testCases { - s.Run(fmt.Sprintf("%v_%v_%v", evmtypes.GetTxTypeName(s.EthTxType), s.ChainID, tc.name), func() { - sender := keyring.GetKey(0) - txArgs, err := txFactory.GenerateDefaultTxTypeArgs( - sender.Addr, - s.EthTxType, - ) - s.Require().NoError(err) - txArgs.GasLimit = commonGasLimit - tx, err := txFactory.GenerateSignedEthTx(sender.Priv, txArgs) - s.Require().NoError(err) - - ctx := tc.getCtx() - feemarketkeeper := unitNetwork.App.GetFeeMarketKeeper() - feemarketParam := feemarketkeeper.GetParams(ctx) - // Function under test - err = evm.CheckGasWanted( - ctx, - feemarketkeeper, - tx, - tc.isLondon, - &feemarketParam, - ) - - if tc.expectedError != nil { - s.Require().Error(err) - s.Contains(err.Error(), tc.expectedError.Error()) - } else { - s.Require().NoError(err) - transientGasWanted := feemarketkeeper.GetTransientGasWanted( - unitNetwork.GetContext(), - ) - s.Require().Equal(tc.expectedTransientGasWanted, transientGasWanted) - } - - // Start from a fresh block and ctx - err = unitNetwork.NextBlock() - s.Require().NoError(err) - }) - } -} diff --git a/tests/integration/x/feemarket/test_abci.go b/tests/integration/x/feemarket/test_abci.go index df7a0f5eb..60ba31c27 100644 --- a/tests/integration/x/feemarket/test_abci.go +++ b/tests/integration/x/feemarket/test_abci.go @@ -31,8 +31,7 @@ func (s *KeeperTestSuite) TestEndBlock() { false, func() { meter := storetypes.NewGasMeter(uint64(1000000000)) - ctx = ctx.WithBlockGasMeter(meter) - nw.App.GetFeeMarketKeeper().SetTransientBlockGasWanted(ctx, 5000000) + ctx = ctx.WithBlockGasMeter(meter).WithBlockGasWanted(5000000) }, uint64(2500000), }, diff --git a/tests/integration/x/vm/test_benchmark.go b/tests/integration/x/vm/test_benchmark.go index 77847f070..d3ed7b55e 100644 --- a/tests/integration/x/vm/test_benchmark.go +++ b/tests/integration/x/vm/test_benchmark.go @@ -10,13 +10,13 @@ import ( testconstants "github.com/cosmos/evm/testutil/constants" utiltx "github.com/cosmos/evm/testutil/tx" + vmkeeper "github.com/cosmos/evm/x/vm/keeper" "github.com/cosmos/evm/x/vm/keeper/testdata" "github.com/cosmos/evm/x/vm/types" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - authante "github.com/cosmos/cosmos-sdk/x/auth/ante" ) func SetupContract(b *testing.B) (*KeeperTestSuite, common.Address) { @@ -73,7 +73,7 @@ func DoBenchmark(b *testing.B, txBuilder TxBuilder) { ctx, _ := suite.Network.GetContext().CacheContext() fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(msg.GetFee()))} - err = authante.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) + err = vmkeeper.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) require.NoError(b, err) rsp, err := suite.Network.App.GetEVMKeeper().EthereumTx(ctx, msg) @@ -198,7 +198,7 @@ func BenchmarkMessageCall(b *testing.B) { ctx, _ := suite.Network.GetContext().CacheContext() fees := sdk.Coins{sdk.NewCoin(suite.EvmDenom(), sdkmath.NewIntFromBigInt(msg.GetFee()))} - err = authante.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) + err = vmkeeper.DeductFees(suite.Network.App.GetBankKeeper(), suite.Network.GetContext(), suite.Network.App.GetAccountKeeper().GetAccount(ctx, msg.GetFrom()), fees) require.NoError(b, err) rsp, err := suite.Network.App.GetEVMKeeper().EthereumTx(ctx, msg) diff --git a/tests/integration/x/vm/test_hooks.go b/tests/integration/x/vm/test_hooks.go index 23aef41ac..66b58bfd1 100644 --- a/tests/integration/x/vm/test_hooks.go +++ b/tests/integration/x/vm/test_hooks.go @@ -110,10 +110,6 @@ func (s *KeeperTestSuite) TestPostTxProcessingFailureLogReversion() { err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToAccount(ctx, "mint", sender.AccAddr, coins) s.Require().NoError(err) - // Store original transient state - originalBloom := k.GetBlockBloomTransient(ctx) - originalLogSize := k.GetLogSizeTransient(ctx) - // Create a simple transfer transaction transferArgs := types.EvmTxArgs{ To: &recipient, @@ -136,13 +132,4 @@ func (s *KeeperTestSuite) TestPostTxProcessingFailureLogReversion() { // Critical test: Verify logs are completely cleared s.Require().Nil(res.Logs, "res.Logs should be nil after PostTxProcessing failure") - - // Critical test: Verify transient state was not updated when PostTx failed - finalBloom := k.GetBlockBloomTransient(ctx) - finalLogSize := k.GetLogSizeTransient(ctx) - - s.Require().Equal(originalBloom.String(), finalBloom.String(), - "BlockBloomTransient should not be updated when PostTxProcessing fails") - s.Require().Equal(originalLogSize, finalLogSize, - "LogSizeTransient should not be updated when PostTxProcessing fails") } diff --git a/tests/jsonrpc/simulator/namespaces/eth.go b/tests/jsonrpc/simulator/namespaces/eth.go index aaa9fc332..162752001 100644 --- a/tests/jsonrpc/simulator/namespaces/eth.go +++ b/tests/jsonrpc/simulator/namespaces/eth.go @@ -1697,7 +1697,6 @@ func EthEstimateGas(rCtx *types.RPCContext) (*types.RpcResult, error) { func EthFeeHistory(rCtx *types.RPCContext) (*types.RpcResult, error) { var result interface{} err := rCtx.Evmd.RPCClient().Call(&result, string(MethodNameEthFeeHistory), "0x2", "latest", []float64{25.0, 50.0, 75.0}) - if err != nil { if err.Error() == "the method "+string(MethodNameEthFeeHistory)+" does not exist/is not available" || err.Error() == types.ErrorMethodNotFound { @@ -1942,7 +1941,6 @@ func EthGetHeaderByHash(rCtx *types.RPCContext) (*types.RpcResult, error) { var header any err = rCtx.Evmd.RPCClient().Call(&header, string(MethodNameEthGetHeaderByHash), receipt.BlockHash.Hex()) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") { @@ -2013,7 +2011,6 @@ func EthGetHeaderByNumber(rCtx *types.RPCContext) (*types.RpcResult, error) { var header any err = rCtx.Evmd.RPCClient().Call(&header, string(MethodNameEthGetHeaderByNumber), blockNumberHex) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") { @@ -2093,7 +2090,6 @@ func EthSimulateV1(rCtx *types.RPCContext) (*types.RpcResult, error) { var result any err := rCtx.Evmd.RPCClient().Call(&result, string(MethodNameEthSimulateV1), simulationReq) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") || @@ -2153,7 +2149,6 @@ func EthPendingTransactions(rCtx *types.RPCContext) (*types.RpcResult, error) { var pendingTxs any err := rCtx.Evmd.RPCClient().Call(&pendingTxs, string(MethodNameEthPendingTransactions)) - if err != nil { if strings.Contains(err.Error(), "does not exist/is not available") || strings.Contains(err.Error(), "Method not found") || diff --git a/tests/jsonrpc/simulator/report/report.go b/tests/jsonrpc/simulator/report/report.go index d1f668bc7..20b664b2e 100644 --- a/tests/jsonrpc/simulator/report/report.go +++ b/tests/jsonrpc/simulator/report/report.go @@ -359,7 +359,6 @@ func PrintCategoryMatrix(summary *types.TestSummary) { catSummary.Total) } } - } func PrintSummary(summary *types.TestSummary) { diff --git a/tests/jsonrpc/simulator/types/context.go b/tests/jsonrpc/simulator/types/context.go index dadd52df3..21e3e9442 100644 --- a/tests/jsonrpc/simulator/types/context.go +++ b/tests/jsonrpc/simulator/types/context.go @@ -74,7 +74,6 @@ type RPCContext struct { // Dual API testing fields EnableComparison bool // Enable dual API comparison ComparisonResults []*ComparisonResult // Store comparison results - } func NewRPCContext(conf *config.Config) (*RPCContext, error) { diff --git a/tests/jsonrpc/simulator/utils/test_helpers.go b/tests/jsonrpc/simulator/utils/test_helpers.go index d584b116d..ea0bda5de 100644 --- a/tests/jsonrpc/simulator/utils/test_helpers.go +++ b/tests/jsonrpc/simulator/utils/test_helpers.go @@ -390,7 +390,6 @@ func Legacy(rCtx *types.RPCContext, methodName types.RpcName, category string, r // First test if the API is actually implemented var result interface{} err := rCtx.Evmd.RPCClient().Call(&result, string(methodName)) - if err != nil { // Check if it's a "method not found" error (API not implemented) if err.Error() == "the method "+string(methodName)+" does not exist/is not available" || diff --git a/tests/systemtests/go.mod b/tests/systemtests/go.mod index d57a40c85..2e5f77b93 100644 --- a/tests/systemtests/go.mod +++ b/tests/systemtests/go.mod @@ -134,6 +134,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/nxadm/tail v1.4.11 // indirect github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/oklog/run v1.1.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect @@ -208,5 +209,7 @@ require ( replace ( github.com/cosmos/evm => ../.. + // TODO replace this once we no longer pull in an ibc-go version which points to old groups module path + github.com/cosmos/ibc-go/v10 => github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250914234212-a3bb228db358 github.com/ethereum/go-ethereum => github.com/cosmos/go-ethereum v1.16.2-cosmos-1 ) diff --git a/tests/systemtests/go.sum b/tests/systemtests/go.sum index 6a7f1b970..6b94ad63b 100644 --- a/tests/systemtests/go.sum +++ b/tests/systemtests/go.sum @@ -243,8 +243,8 @@ github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fr github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= github.com/cosmos/iavl v1.2.6 h1:Hs3LndJbkIB+rEvToKJFXZvKo6Vy0Ex1SJ54hhtioIs= github.com/cosmos/iavl v1.2.6/go.mod h1:GiM43q0pB+uG53mLxLDzimxM9l/5N9UuSY3/D0huuVw= -github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20251027215440-22f0033d0aee h1:zGsni85/bBwWW6uQh0NEEXaUAliFgo1dBIoHfAqNHRk= -github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20251027215440-22f0033d0aee/go.mod h1:kbhNmgk/OlNfeLUX9ieOvBv1Y0dRa9lUwx+jb4zc7Nc= +github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250914234212-a3bb228db358 h1:B+U7FAGx//QlqMxzDZp5a4UjWxXAhocGxOT6VfekPkA= +github.com/cosmos/ibc-go/v10 v10.0.0-beta.0.0.20250914234212-a3bb228db358/go.mod h1:D+cnapoXeOgXkXudzRMydpd0ddVq3yRZibbB6sBsVuQ= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/cosmos/ledger-cosmos-go v0.16.0 h1:YKlWPG9NnGZIEUb2bEfZ6zhON1CHlNTg0QKRRGcNEd0= @@ -331,6 +331,7 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/getsentry/sentry-go v0.35.0 h1:+FJNlnjJsZMG3g0/rmmP7GiKjQoUF5EXfEtBwtPtkzY= @@ -669,8 +670,9 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= @@ -1099,6 +1101,7 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/testutil/integration/evm/network/config.go b/testutil/integration/evm/network/config.go index d92cd80ec..c49cee125 100644 --- a/testutil/integration/evm/network/config.go +++ b/testutil/integration/evm/network/config.go @@ -107,7 +107,7 @@ func getGenAccountsAndBalances(cfg Config, validators []stakingtypes.Validator) } genAccounts = append(genAccounts, createGenesisAccounts(valAccs)...) - return + return genAccounts, balances } // ConfigOption defines a function that can modify the NetworkConfig. diff --git a/x/feemarket/keeper/abci.go b/x/feemarket/keeper/abci.go index ec807fa77..395801614 100644 --- a/x/feemarket/keeper/abci.go +++ b/x/feemarket/keeper/abci.go @@ -3,6 +3,7 @@ package keeper import ( "errors" "fmt" + gomath "math" "github.com/cosmos/evm/x/feemarket/types" @@ -54,17 +55,17 @@ func (k *Keeper) EndBlock(ctx sdk.Context) error { return err } - gasWanted := math.NewIntFromUint64(k.GetTransientGasWanted(ctx)) - gasUsed := math.NewIntFromUint64(ctx.BlockGasMeter().GasConsumedToLimit()) + gasWanted := ctx.BlockGasWanted() + gasUsed := ctx.BlockGasUsed() - if !gasWanted.IsInt64() { - err := fmt.Errorf("integer overflow by integer type conversion. Gas wanted > MaxInt64. Gas wanted: %s", gasWanted) + if gasWanted > gomath.MaxInt64 { + err := fmt.Errorf("integer overflow by integer type conversion. Gas wanted > MaxInt64. Gas wanted: %d", gasWanted) k.Logger(ctx).Error(err.Error()) return err } - if !gasUsed.IsInt64() { - err := fmt.Errorf("integer overflow by integer type conversion. Gas used > MaxInt64. Gas used: %s", gasUsed) + if gasUsed > gomath.MaxInt64 { + err := fmt.Errorf("integer overflow by integer type conversion. Gas used > MaxInt64. Gas used: %d", gasUsed) k.Logger(ctx).Error(err.Error()) return err } @@ -74,8 +75,8 @@ func (k *Keeper) EndBlock(ctx sdk.Context) error { // this will be keep BaseFee protected from un-penalized manipulation // more info here https://github.com/evmos/ethermint/pull/1105#discussion_r888798925 minGasMultiplier := k.GetParams(ctx).MinGasMultiplier - limitedGasWanted := math.LegacyNewDec(gasWanted.Int64()).Mul(minGasMultiplier) - updatedGasWanted := math.LegacyMaxDec(limitedGasWanted, math.LegacyNewDec(gasUsed.Int64())).TruncateInt().Uint64() + limitedGasWanted := math.LegacyNewDec(int64(gasWanted)).Mul(minGasMultiplier) + updatedGasWanted := math.LegacyMaxDec(limitedGasWanted, math.LegacyNewDec(int64(gasUsed))).TruncateInt().Uint64() k.SetBlockGasWanted(ctx, updatedGasWanted) defer func() { diff --git a/x/feemarket/keeper/keeper.go b/x/feemarket/keeper/keeper.go index b43b21c14..0f32c3b15 100644 --- a/x/feemarket/keeper/keeper.go +++ b/x/feemarket/keeper/keeper.go @@ -15,15 +15,14 @@ type Keeper struct { // Protobuf codec cdc codec.BinaryCodec // Store key required for the Fee Market Prefix KVStore. - storeKey storetypes.StoreKey - transientKey storetypes.StoreKey + storeKey storetypes.StoreKey // the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account. authority sdk.AccAddress } // NewKeeper generates new fee market module keeper func NewKeeper( - cdc codec.BinaryCodec, authority sdk.AccAddress, storeKey, transientKey storetypes.StoreKey, + cdc codec.BinaryCodec, authority sdk.AccAddress, storeKey storetypes.StoreKey, ) Keeper { // ensure authority account is correctly formatted if err := sdk.VerifyAddressFormat(authority); err != nil { @@ -31,10 +30,9 @@ func NewKeeper( } return Keeper{ - cdc: cdc, - storeKey: storeKey, - authority: authority, - transientKey: transientKey, + cdc: cdc, + storeKey: storeKey, + authority: authority, } } @@ -61,23 +59,3 @@ func (k Keeper) GetBlockGasWanted(ctx sdk.Context) uint64 { store := ctx.KVStore(k.storeKey) return sdk.BigEndianToUint64(store.Get(types.KeyPrefixBlockGasWanted)) } - -// GetTransientGasWanted returns the gas wanted in the current block from transient store. -func (k Keeper) GetTransientGasWanted(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientBlockGasWanted)) -} - -// SetTransientBlockGasWanted sets the block gas wanted to the transient store. -func (k Keeper) SetTransientBlockGasWanted(ctx sdk.Context, gasWanted uint64) { - store := ctx.TransientStore(k.transientKey) - gasBz := sdk.Uint64ToBigEndian(gasWanted) - store.Set(types.KeyPrefixTransientBlockGasWanted, gasBz) -} - -// AddTransientGasWanted adds the cumulative gas wanted in the transient store -func (k Keeper) AddTransientGasWanted(ctx sdk.Context, gasWanted uint64) (uint64, error) { - result := k.GetTransientGasWanted(ctx) + gasWanted - k.SetTransientBlockGasWanted(ctx, result) - return result, nil -} diff --git a/x/feemarket/types/keys.go b/x/feemarket/types/keys.go index 055fc5138..d2e0c4029 100644 --- a/x/feemarket/types/keys.go +++ b/x/feemarket/types/keys.go @@ -10,10 +10,6 @@ const ( // RouterKey uses module name for routing RouterKey = ModuleName - - // TransientKey is the key to access the FeeMarket transient store, that is reset - // during the Commit phase. - TransientKey = "transient_" + ModuleName ) // prefix bytes for the feemarket persistent store diff --git a/x/precisebank/keeper/keeper.go b/x/precisebank/keeper/keeper.go index 1185ea518..c6e740eaa 100644 --- a/x/precisebank/keeper/keeper.go +++ b/x/precisebank/keeper/keeper.go @@ -40,6 +40,13 @@ func NewKeeper( } // BANK KEEPER INTERFACE PASSTHROUGHS +func (k Keeper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error { + return k.bk.SendCoinsFromModuleToAccountVirtual(ctx, senderModule, recipientAddr, amt) +} + +func (k Keeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error { + return k.bk.SendCoinsFromAccountToModuleVirtual(ctx, senderAddr, recipientModule, amt) +} func (k Keeper) IterateTotalSupply(ctx context.Context, cb func(coin sdk.Coin) bool) { k.bk.IterateTotalSupply(ctx, cb) diff --git a/x/precisebank/types/interfaces.go b/x/precisebank/types/interfaces.go index bcae3df14..c30ad4933 100644 --- a/x/precisebank/types/interfaces.go +++ b/x/precisebank/types/interfaces.go @@ -32,6 +32,8 @@ type BankKeeper interface { SendCoinsFromAccountToModule(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error SendCoinsFromModuleToModule(ctx context.Context, senderModule string, recipientModule string, amt sdk.Coins) error + SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error MintCoins(ctx context.Context, moduleName string, amt sdk.Coins) error BurnCoins(ctx context.Context, moduleName string, amt sdk.Coins) error diff --git a/x/precisebank/types/mocks/MockBankKeeper.go b/x/precisebank/types/mocks/MockBankKeeper.go index c82096a1d..28405dcd1 100644 --- a/x/precisebank/types/mocks/MockBankKeeper.go +++ b/x/precisebank/types/mocks/MockBankKeeper.go @@ -677,6 +677,55 @@ func (_c *BankKeeper_SendCoinsFromAccountToModule_Call) RunAndReturn(run func(co return _c } +// SendCoinsFromAccountToModuleVirtual provides a mock function with given fields: ctx, senderAddr, recipientModule, amt +func (_m *BankKeeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + ret := _m.Called(ctx, senderAddr, recipientModule, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromAccountToModuleVirtual") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress, string, types.Coins) error); ok { + r0 = rf(ctx, senderAddr, recipientModule, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// BankKeeper_SendCoinsFromAccountToModuleVirtual_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromAccountToModuleVirtual' +type BankKeeper_SendCoinsFromAccountToModuleVirtual_Call struct { + *mock.Call +} + +// SendCoinsFromAccountToModuleVirtual is a helper method to define mock.On call +// - ctx context.Context +// - senderAddr types.AccAddress +// - recipientModule string +// - amt types.Coins +func (_e *BankKeeper_Expecter) SendCoinsFromAccountToModuleVirtual(ctx interface{}, senderAddr interface{}, recipientModule interface{}, amt interface{}) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + return &BankKeeper_SendCoinsFromAccountToModuleVirtual_Call{Call: _e.mock.On("SendCoinsFromAccountToModuleVirtual", ctx, senderAddr, recipientModule, amt)} +} + +func (_c *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call) Run(run func(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins)) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(types.AccAddress), args[2].(string), args[3].(types.Coins)) + }) + return _c +} + +func (_c *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call) Return(_a0 error) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call) RunAndReturn(run func(context.Context, types.AccAddress, string, types.Coins) error) *BankKeeper_SendCoinsFromAccountToModuleVirtual_Call { + _c.Call.Return(run) + return _c +} + // SendCoinsFromModuleToAccount provides a mock function with given fields: ctx, senderModule, recipientAddr, amt func (_m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { ret := _m.Called(ctx, senderModule, recipientAddr, amt) @@ -726,6 +775,55 @@ func (_c *BankKeeper_SendCoinsFromModuleToAccount_Call) RunAndReturn(run func(co return _c } +// SendCoinsFromModuleToAccountVirtual provides a mock function with given fields: ctx, senderModule, recipientAddr, amt +func (_m *BankKeeper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + ret := _m.Called(ctx, senderModule, recipientAddr, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromModuleToAccountVirtual") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, types.AccAddress, types.Coins) error); ok { + r0 = rf(ctx, senderModule, recipientAddr, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// BankKeeper_SendCoinsFromModuleToAccountVirtual_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendCoinsFromModuleToAccountVirtual' +type BankKeeper_SendCoinsFromModuleToAccountVirtual_Call struct { + *mock.Call +} + +// SendCoinsFromModuleToAccountVirtual is a helper method to define mock.On call +// - ctx context.Context +// - senderModule string +// - recipientAddr types.AccAddress +// - amt types.Coins +func (_e *BankKeeper_Expecter) SendCoinsFromModuleToAccountVirtual(ctx interface{}, senderModule interface{}, recipientAddr interface{}, amt interface{}) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + return &BankKeeper_SendCoinsFromModuleToAccountVirtual_Call{Call: _e.mock.On("SendCoinsFromModuleToAccountVirtual", ctx, senderModule, recipientAddr, amt)} +} + +func (_c *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call) Run(run func(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins)) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(types.AccAddress), args[3].(types.Coins)) + }) + return _c +} + +func (_c *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call) Return(_a0 error) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call) RunAndReturn(run func(context.Context, string, types.AccAddress, types.Coins) error) *BankKeeper_SendCoinsFromModuleToAccountVirtual_Call { + _c.Call.Return(run) + return _c +} + // SendCoinsFromModuleToModule provides a mock function with given fields: ctx, senderModule, recipientModule, amt func (_m *BankKeeper) SendCoinsFromModuleToModule(ctx context.Context, senderModule string, recipientModule string, amt types.Coins) error { ret := _m.Called(ctx, senderModule, recipientModule, amt) @@ -862,7 +960,8 @@ func (_c *BankKeeper_SpendableCoin_Call) RunAndReturn(run func(context.Context, func NewBankKeeper(t interface { mock.TestingT Cleanup(func()) -}) *BankKeeper { +}, +) *BankKeeper { mock := &BankKeeper{} mock.Mock.Test(t) diff --git a/x/vm/keeper/abci.go b/x/vm/keeper/abci.go index 558c230be..ce4f39404 100644 --- a/x/vm/keeper/abci.go +++ b/x/vm/keeper/abci.go @@ -1,12 +1,8 @@ package keeper import ( - ethtypes "github.com/ethereum/go-ethereum/core/types" - evmtypes "github.com/cosmos/evm/x/vm/types" - storetypes "cosmossdk.io/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -40,15 +36,12 @@ func (k *Keeper) BeginBlock(ctx sdk.Context) error { // KVStore. The EVM end block logic doesn't update the validator set, thus it returns // an empty slice. func (k *Keeper) EndBlock(ctx sdk.Context) error { - // Gas costs are handled within msg handler so costs should be ignored - infCtx := ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) - if k.evmMempool != nil && !k.evmMempool.HasEventBus() { k.evmMempool.GetBlockchain().NotifyNewBlock() } - bloom := ethtypes.BytesToBloom(k.GetBlockBloomTransient(infCtx).Bytes()) - k.EmitBlockBloomEvent(infCtx, bloom) + k.CollectTxBloom(ctx) + k.ResetTransientGasUsed(ctx) return nil } diff --git a/x/vm/keeper/config.go b/x/vm/keeper/config.go index 530050869..39bb07f7c 100644 --- a/x/vm/keeper/config.go +++ b/x/vm/keeper/config.go @@ -38,9 +38,9 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress) (*s // TxConfig loads `TxConfig` from current transient storage func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) statedb.TxConfig { return statedb.NewTxConfig( - txHash, // TxHash - uint(k.GetTxIndexTransient(ctx)), // TxIndex - uint(k.GetLogSizeTransient(ctx)), // LogIndex + txHash, // TxHash + 0, // TxIndex + 0, // LogIndex ) } diff --git a/x/vm/keeper/fees.go b/x/vm/keeper/fees.go index a5569fa18..9df02230a 100644 --- a/x/vm/keeper/fees.go +++ b/x/vm/keeper/fees.go @@ -7,12 +7,15 @@ import ( "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/cosmos/evm/x/vm/types" + errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" errortypes "github.com/cosmos/cosmos-sdk/types/errors" authante "github.com/cosmos/cosmos-sdk/x/auth/ante" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) // CheckSenderBalance validates that the tx cost value is positive and that the @@ -54,7 +57,12 @@ func (k *Keeper) DeductTxCostsFromUserBalance( // Deduct fees from the user balance. Notice that it is used // the bankWrapper to properly convert fees from the 18 decimals // representation to the original one before calling into the bank keeper. - if err := authante.DeductFees(k.bankWrapper, ctx, signerAcc, fees); err != nil { + if k.virtualFeeCollection { + err = DeductFees(k.bankWrapper, ctx, signerAcc, fees) + } else { + err = authante.DeductFees(k.bankWrapper, ctx, signerAcc, fees) + } + if err != nil { return errorsmod.Wrapf(err, "failed to deduct full gas cost %s from the user %s balance", fees, from) } @@ -116,3 +124,17 @@ func VerifyFee( return sdk.Coins{{Denom: denom, Amount: sdkmath.NewIntFromBigInt(feeAmt)}}, nil } + +// DeductFees deducts fees from the given account. +func DeductFees(bankKeeper types.BankKeeper, ctx sdk.Context, acc sdk.AccountI, fees sdk.Coins) error { + if !fees.IsValid() { + return errorsmod.Wrapf(errortypes.ErrInsufficientFee, "invalid fee amount: %s", fees) + } + + err := bankKeeper.SendCoinsFromAccountToModuleVirtual(ctx, acc.GetAddress(), authtypes.FeeCollectorName, fees) + if err != nil { + return errorsmod.Wrap(errortypes.ErrInsufficientFunds, err.Error()) + } + + return nil +} diff --git a/x/vm/keeper/gas.go b/x/vm/keeper/gas.go index ab5dcf08d..caf495e7f 100644 --- a/x/vm/keeper/gas.go +++ b/x/vm/keeper/gas.go @@ -45,7 +45,12 @@ func (k *Keeper) RefundGas(ctx sdk.Context, msg core.Message, leftoverGas uint64 refundedCoins := sdk.Coins{sdk.NewCoin(denom, sdkmath.NewIntFromBigInt(remaining))} // refund to sender from the fee collector module account, which is the escrow account in charge of collecting tx fees - err := k.bankWrapper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, msg.From.Bytes(), refundedCoins) + var err error + if k.virtualFeeCollection { + err = k.bankWrapper.SendCoinsFromModuleToAccountVirtual(ctx, authtypes.FeeCollectorName, msg.From.Bytes(), refundedCoins) + } else { + err = k.bankWrapper.SendCoinsFromModuleToAccount(ctx, authtypes.FeeCollectorName, msg.From.Bytes(), refundedCoins) + } if err != nil { err = errorsmod.Wrapf(errortypes.ErrInsufficientFunds, "fee collector account failed to refund fees: %s", err.Error()) return errorsmod.Wrapf(err, "failed to refund %d leftover gas (%s)", leftoverGas, refundedCoins.String()) diff --git a/x/vm/keeper/keeper.go b/x/vm/keeper/keeper.go index c93bee600..4fa8ca3ea 100644 --- a/x/vm/keeper/keeper.go +++ b/x/vm/keeper/keeper.go @@ -39,10 +39,10 @@ type Keeper struct { // - storing Bloom filters by block height. Needed for the Web3 API. storeKey storetypes.StoreKey - // key to access the transient store, which is reset on every block during Commit - transientKey storetypes.StoreKey + // key to access the object store, which is reset on every block during Commit + objectKey storetypes.StoreKey - // KVStore Keys for modules wired to app + // Store Keys for modules wired to app storeKeys map[string]storetypes.StoreKey // the address capable of executing a MsgUpdateParams message. Typically, this should be the x/gov module account. @@ -81,12 +81,16 @@ type Keeper struct { // evmMempool is the custom EVM appside mempool // if it is nil, the default comet mempool will be used evmMempool *evmmempool.ExperimentalEVMMempool + + // virtualFeeCollection enabling will use "Virtual" methods from the bank module to accumulate + // fees to the fee collector module in the endBlocker instead of using regular sends during tx execution. + virtualFeeCollection bool } // NewKeeper generates new evm module keeper func NewKeeper( cdc codec.BinaryCodec, - storeKey, transientKey storetypes.StoreKey, + storeKey, objectKey storetypes.StoreKey, keys []storetypes.StoreKey, authority sdk.AccAddress, ak types.AccountKeeper, @@ -130,7 +134,7 @@ func NewKeeper( stakingKeeper: sk, feeMarketWrapper: feeMarketWrapper, storeKey: storeKey, - transientKey: transientKey, + objectKey: objectKey, tracer: tracer, consensusKeeper: consensusKeeper, erc20Keeper: erc20Keeper, @@ -138,6 +142,13 @@ func NewKeeper( } } +// EnableVirtualFeeCollection switches fee deduction for evm transactions to use the virtual fee collection of the +// bank keeper via the object store. +// Note: Do NOT use this if your chain does not have an 18 decimal point precision gas token. +func (k *Keeper) EnableVirtualFeeCollection() { + k.virtualFeeCollection = true +} + // Logger returns a module-specific logger. func (k Keeper) Logger(ctx sdk.Context) log.Logger { return ctx.Logger().With("module", types.ModuleName) @@ -149,11 +160,11 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // ---------------------------------------------------------------------------- // EmitBlockBloomEvent emit block bloom events -func (k Keeper) EmitBlockBloomEvent(ctx sdk.Context, bloom ethtypes.Bloom) { +func (k Keeper) EmitBlockBloomEvent(ctx sdk.Context, bloom []byte) { ctx.EventManager().EmitEvent( sdk.NewEvent( types.EventTypeBlockBloom, - sdk.NewAttribute(types.AttributeKeyEthereumBloom, string(bloom.Bytes())), + sdk.NewAttribute(types.AttributeKeyEthereumBloom, string(bloom)), ), ) } @@ -163,40 +174,26 @@ func (k Keeper) GetAuthority() sdk.AccAddress { return k.authority } -// GetBlockBloomTransient returns bloom bytes for the current block height -func (k Keeper) GetBlockBloomTransient(ctx sdk.Context) *big.Int { - store := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientBloom) - heightBz := sdk.Uint64ToBigEndian(uint64(ctx.BlockHeight())) //nolint:gosec // G115 // won't exceed uint64 - bz := store.Get(heightBz) - if len(bz) == 0 { - return big.NewInt(0) +// CollectTxBloom collects all tx blooms and emit a single block bloom event +func (k Keeper) CollectTxBloom(ctx sdk.Context) { + store := prefix.NewObjStore(ctx.ObjectStore(k.objectKey), types.KeyPrefixObjectBloom) + it := store.Iterator(nil, nil) + defer it.Close() + + bloom := new(big.Int) + for ; it.Valid(); it.Next() { + bloom.Or(bloom, it.Value().(*big.Int)) + store.Delete(it.Key()) } - return new(big.Int).SetBytes(bz) + k.EmitBlockBloomEvent(ctx, bloom.Bytes()) } -// SetBlockBloomTransient sets the given bloom bytes to the transient store. This value is reset on +// SetTxBloom sets the given bloom bytes to the object store. This value is reset on // every block. -func (k Keeper) SetBlockBloomTransient(ctx sdk.Context, bloom *big.Int) { - store := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientBloom) - heightBz := sdk.Uint64ToBigEndian(uint64(ctx.BlockHeight())) //nolint:gosec // G115 // won't exceed uint64 - store.Set(heightBz, bloom.Bytes()) -} - -// ---------------------------------------------------------------------------- -// Tx -// ---------------------------------------------------------------------------- - -// SetTxIndexTransient set the index of processing transaction -func (k Keeper) SetTxIndexTransient(ctx sdk.Context, index uint64) { - store := ctx.TransientStore(k.transientKey) - store.Set(types.KeyPrefixTransientTxIndex, sdk.Uint64ToBigEndian(index)) -} - -// GetTxIndexTransient returns EVM transaction index on the current block. -func (k Keeper) GetTxIndexTransient(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientTxIndex)) +func (k Keeper) SetTxBloom(ctx sdk.Context, bloom *big.Int) { + store := ctx.ObjectStore(k.objectKey) + store.Set(types.ObjectBloomKey(ctx.TxIndex(), ctx.MsgIndex()), bloom) } // ---------------------------------------------------------------------------- @@ -233,23 +230,6 @@ func (k *Keeper) HasHooks() bool { return k.hooks != nil } -// ---------------------------------------------------------------------------- -// Log -// ---------------------------------------------------------------------------- - -// GetLogSizeTransient returns EVM log index on the current block. -func (k Keeper) GetLogSizeTransient(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientLogSize)) -} - -// SetLogSizeTransient fetches the current EVM log index from the transient store, increases its -// value by one and then sets the new index back to the transient store. -func (k Keeper) SetLogSizeTransient(ctx sdk.Context, logSize uint64) { - store := ctx.TransientStore(k.transientKey) - store.Set(types.KeyPrefixTransientLogSize, sdk.Uint64ToBigEndian(logSize)) -} - // ---------------------------------------------------------------------------- // Storage // ---------------------------------------------------------------------------- @@ -371,23 +351,33 @@ func (k Keeper) GetMinGasPrice(ctx sdk.Context) math.LegacyDec { return k.feeMarketWrapper.GetParams(ctx).MinGasPrice } -// ResetTransientGasUsed reset gas used to prepare for execution of current cosmos tx, called in ante handler. +// ResetTransientGasUsed reset gas used to prepare for execution of cosmos tx, called in EndBlocker. func (k Keeper) ResetTransientGasUsed(ctx sdk.Context) { - store := ctx.TransientStore(k.transientKey) - store.Delete(types.KeyPrefixTransientGasUsed) + store := prefix.NewObjStore(ctx.ObjectStore(k.objectKey), + types.KeyPrefixObjectGasUsed) + it := store.Iterator(nil, nil) + + defer it.Close() + + for ; it.Valid(); it.Next() { + store.Delete(it.Key()) + } } // GetTransientGasUsed returns the gas used by current cosmos tx. func (k Keeper) GetTransientGasUsed(ctx sdk.Context) uint64 { - store := ctx.TransientStore(k.transientKey) - return sdk.BigEndianToUint64(store.Get(types.KeyPrefixTransientGasUsed)) + store := ctx.ObjectStore(k.objectKey) + v := store.Get(types.ObjectGasUsedKey(ctx.TxIndex())) + if v == nil { + return 0 + } + return v.(uint64) } // SetTransientGasUsed sets the gas used by current cosmos tx. func (k Keeper) SetTransientGasUsed(ctx sdk.Context, gasUsed uint64) { - store := ctx.TransientStore(k.transientKey) - bz := sdk.Uint64ToBigEndian(gasUsed) - store.Set(types.KeyPrefixTransientGasUsed, bz) + store := ctx.ObjectStore(k.objectKey) + store.Set(types.ObjectGasUsedKey(ctx.TxIndex()), gasUsed) } // AddTransientGasUsed accumulate gas used by each eth msgs included in current cosmos tx. diff --git a/x/vm/keeper/keeper_test.go b/x/vm/keeper/keeper_test.go index ad94876f1..2babd054a 100644 --- a/x/vm/keeper/keeper_test.go +++ b/x/vm/keeper/keeper_test.go @@ -41,8 +41,10 @@ func TestKeeperTestSuite(t *testing.T) { func (suite *KeeperTestSuite) SetupTest() { key := storetypes.NewKVStoreKey(vmtypes.StoreKey) - transientKey := storetypes.NewTransientStoreKey(vmtypes.TransientKey) - testCtx := testutil.DefaultContextWithDB(suite.T(), key, storetypes.NewTransientStoreKey("transient_test")) + okey := storetypes.NewObjectStoreKey(vmtypes.ObjectKey) + allKeys := []storetypes.StoreKey{key, okey} + testCtx := testutil.DefaultContextWithObjectStore(suite.T(), key, + storetypes.NewTransientStoreKey("store_test"), okey) ctx := testCtx.Ctx.WithBlockHeader(cmtproto.Header{Time: cmttime.Now()}) encCfg := moduletestutil.MakeTestEncodingConfig() @@ -61,8 +63,8 @@ func (suite *KeeperTestSuite) SetupTest() { suite.vmKeeper = vmkeeper.NewKeeper( encCfg.Codec, key, - transientKey, - []storetypes.StoreKey{key}, + okey, + allKeys, authority, suite.accKeeper, suite.bankKeeper, diff --git a/x/vm/keeper/msg_server.go b/x/vm/keeper/msg_server.go index 27cebf57a..4217fee90 100644 --- a/x/vm/keeper/msg_server.go +++ b/x/vm/keeper/msg_server.go @@ -30,7 +30,6 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t ctx := sdk.UnwrapSDKContext(goCtx) tx := msg.AsTransaction() - txIndex := k.GetTxIndexTransient(ctx) labels := []metrics.Label{ telemetry.NewLabel("tx_type", fmt.Sprintf("%d", tx.Type())), @@ -78,8 +77,6 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t sdk.NewAttribute(sdk.AttributeKeyAmount, tx.Value().String()), // add event for ethereum transaction hash format sdk.NewAttribute(types.AttributeKeyEthereumTxHash, response.Hash), - // add event for index of valid ethereum tx - sdk.NewAttribute(types.AttributeKeyTxIndex, strconv.FormatUint(txIndex, 10)), // add event for eth tx gas used, we can't get it from cosmos tx result when it contains multiple eth tx msgs. sdk.NewAttribute(types.AttributeKeyTxGasUsed, strconv.FormatUint(response.GasUsed, 10)), } diff --git a/x/vm/keeper/params.go b/x/vm/keeper/params.go index b5892ad4d..aaea3b467 100644 --- a/x/vm/keeper/params.go +++ b/x/vm/keeper/params.go @@ -21,7 +21,7 @@ func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { return params } k.cdc.MustUnmarshal(bz, ¶ms) - return + return params } // SetParams sets the EVM params each in their individual key for better get performance diff --git a/x/vm/keeper/state_transition.go b/x/vm/keeper/state_transition.go index eb8975cf2..dcbc2be38 100644 --- a/x/vm/keeper/state_transition.go +++ b/x/vm/keeper/state_transition.go @@ -22,7 +22,6 @@ import ( errorsmod "cosmossdk.io/errors" "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" sdk "github.com/cosmos/cosmos-sdk/types" consensustypes "github.com/cosmos/cosmos-sdk/x/consensus/types" @@ -154,27 +153,16 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { } } -func (k *Keeper) initializeBloomFromLogs(ctx sdk.Context, ethLogs []*ethtypes.Log) (bloom *big.Int, bloomReceipt ethtypes.Bloom) { - // Compute block bloom filter - if len(ethLogs) > 0 { - bloom = k.GetBlockBloomTransient(ctx) - bloom.Or(bloom, big.NewInt(0).SetBytes(ethtypes.CreateBloom(ðtypes.Receipt{Logs: ethLogs}).Bytes())) - bloomReceipt = ethtypes.BytesToBloom(bloom.Bytes()) - } - - return -} - -func calculateCumulativeGasFromEthResponse(meter storetypes.GasMeter, res *types.MsgEthereumTxResponse) uint64 { - cumulativeGasUsed := res.GasUsed - if meter != nil { - limit := meter.Limit() - cumulativeGasUsed += meter.GasConsumed() - if cumulativeGasUsed > limit { - cumulativeGasUsed = limit +// logsBloom returns the bloom bytes for the given logs +func logsBloom(logs []*ethtypes.Log) []byte { + var bin ethtypes.Bloom + for _, log := range logs { + bin.Add(log.Address.Bytes()) + for _, b := range log.Topics { + bin.Add(b[:]) } } - return cumulativeGasUsed + return bin[:] } // ApplyTransaction runs and attempts to perform a state transition with the given transaction (i.e Message), that will @@ -223,7 +211,10 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t } ethLogs := types.LogsToEthereum(res.Logs) - _, bloomReceipt := k.initializeBloomFromLogs(ctx, ethLogs) + // Compute block bloom filter + if len(ethLogs) > 0 { + k.SetTxBloom(tmpCtx, new(big.Int).SetBytes(logsBloom(ethLogs))) + } var contractAddr common.Address if msg.To == nil { @@ -231,17 +222,14 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t } receipt := ðtypes.Receipt{ - Type: tx.Type(), - PostState: nil, - CumulativeGasUsed: calculateCumulativeGasFromEthResponse(ctx.GasMeter(), res), - Bloom: bloomReceipt, - Logs: ethLogs, - TxHash: txConfig.TxHash, - ContractAddress: contractAddr, - GasUsed: res.GasUsed, - BlockHash: common.BytesToHash(ctx.HeaderHash()), - BlockNumber: big.NewInt(ctx.BlockHeight()), - TransactionIndex: txConfig.TxIndex, + Type: tx.Type(), + PostState: nil, + Logs: ethLogs, + TxHash: txConfig.TxHash, + ContractAddress: contractAddr, + GasUsed: res.GasUsed, + BlockHash: common.BytesToHash(ctx.HeaderHash()), + BlockNumber: big.NewInt(ctx.BlockHeight()), } if res.Failed() { @@ -302,27 +290,15 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t } } - // update logs and bloom for full view if post processing updated them - ethLogs = types.LogsToEthereum(res.Logs) - bloom, _ := k.initializeBloomFromLogs(ctx, ethLogs) - // refund gas to match the Ethereum gas consumption instead of the default SDK one. remainingGas := uint64(0) if msg.GasLimit > res.GasUsed { remainingGas = msg.GasLimit - res.GasUsed } if err = k.RefundGas(ctx, *msg, remainingGas, types.GetEVMCoinDenom()); err != nil { - return nil, errorsmod.Wrapf(err, "failed to refund gas leftover gas to sender %s", msg.From) + return nil, errorsmod.Wrapf(err, "failed to refund leftover gas to sender %s", msg.From) } - if len(ethLogs) > 0 { - // Update transient block bloom filter - k.SetBlockBloomTransient(ctx, bloom) - k.SetLogSizeTransient(ctx, uint64(txConfig.LogIndex)+uint64(len(ethLogs))) - } - - k.SetTxIndexTransient(ctx, uint64(txConfig.TxIndex)+1) - totalGasUsed, err := k.AddTransientGasUsed(ctx, res.GasUsed) if err != nil { return nil, errorsmod.Wrap(err, "failed to add transient gas used") diff --git a/x/vm/store/snapshotmulti/store.go b/x/vm/store/snapshotmulti/store.go index f49a7bea6..f8e5a8383 100644 --- a/x/vm/store/snapshotmulti/store.go +++ b/x/vm/store/snapshotmulti/store.go @@ -139,7 +139,7 @@ func (s *Store) GetObjKVStore(key storetypes.StoreKey) storetypes.ObjKVStore { if key == nil || store == nil { panic(fmt.Sprintf("kv store with key %v has not been registered in stores", key)) } - objStore, ok := store.(storetypes.ObjKVStore) + objStore, ok := store.CurrentStore().(storetypes.ObjKVStore) if !ok { panic(fmt.Sprintf("store with key %v is not ObjKVStore", key)) } diff --git a/x/vm/types/interfaces.go b/x/vm/types/interfaces.go index 75d358673..e36fb0ee0 100644 --- a/x/vm/types/interfaces.go +++ b/x/vm/types/interfaces.go @@ -51,6 +51,8 @@ type BankKeeper interface { GetSupply(ctx context.Context, denom string) sdk.Coin GetDenomMetaData(ctx context.Context, denom string) (banktypes.Metadata, bool) SetDenomMetaData(ctx context.Context, denomMetaData banktypes.Metadata) + SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error } // StakingKeeper returns the historical headers kept in store. diff --git a/x/vm/types/key.go b/x/vm/types/key.go index 45226c8d5..d1caf8d25 100644 --- a/x/vm/types/key.go +++ b/x/vm/types/key.go @@ -1,6 +1,8 @@ package types import ( + "encoding/binary" + "github.com/ethereum/go-ethereum/common" ) @@ -13,9 +15,9 @@ const ( // The EVM module should use a prefix store. StoreKey = ModuleName - // TransientKey is the key to access the EVM transient store, that is reset + // ObjectKey is the key to access the EVM object store, that is reset // during the Commit phase. - TransientKey = "transient_" + ModuleName + ObjectKey = "object:" + ModuleName // RouterKey uses module name for routing RouterKey = ModuleName @@ -30,12 +32,10 @@ const ( prefixEvmCoinInfo ) -// prefix bytes for the EVM transient store +// prefix bytes for the EVM object store const ( - prefixTransientBloom = iota + 1 - prefixTransientTxIndex - prefixTransientLogSize - prefixTransientGasUsed + prefixObjectBloom = iota + 1 + prefixObjectGasUsed ) // KVStore key prefixes @@ -47,12 +47,10 @@ var ( KeyPrefixEvmCoinInfo = []byte{prefixEvmCoinInfo} ) -// Transient Store key prefixes +// Object Store key prefixes var ( - KeyPrefixTransientBloom = []byte{prefixTransientBloom} - KeyPrefixTransientTxIndex = []byte{prefixTransientTxIndex} - KeyPrefixTransientLogSize = []byte{prefixTransientLogSize} - KeyPrefixTransientGasUsed = []byte{prefixTransientGasUsed} + KeyPrefixObjectBloom = []byte{prefixObjectBloom} + KeyPrefixObjectGasUsed = []byte{prefixObjectGasUsed} ) // AddressStoragePrefix returns a prefix to iterate over a given account storage. @@ -64,3 +62,18 @@ func AddressStoragePrefix(address common.Address) []byte { func StateKey(address common.Address, key []byte) []byte { return append(AddressStoragePrefix(address), key...) } + +func ObjectGasUsedKey(txIndex int) []byte { + var key [1 + 8]byte + key[0] = prefixObjectGasUsed + binary.BigEndian.PutUint64(key[1:], uint64(txIndex)) //nolint:gosec + return key[:] +} + +func ObjectBloomKey(txIndex, msgIndex int) []byte { + var key [1 + 8 + 8]byte + key[0] = prefixObjectBloom + binary.BigEndian.PutUint64(key[1:], uint64(txIndex)) //nolint:gosec + binary.BigEndian.PutUint64(key[9:], uint64(msgIndex)) //nolint:gosec + return key[:] +} diff --git a/x/vm/types/mocks/BankKeeper.go b/x/vm/types/mocks/BankKeeper.go index 31c4ba983..4ecd110d1 100644 --- a/x/vm/types/mocks/BankKeeper.go +++ b/x/vm/types/mocks/BankKeeper.go @@ -188,6 +188,24 @@ func (_m *BankKeeper) SendCoinsFromAccountToModule(ctx context.Context, senderAd return r0 } +// SendCoinsFromAccountToModuleVirtual provides a mock function with given fields: ctx, senderAddr, recipientModule, amt +func (_m *BankKeeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + ret := _m.Called(ctx, senderAddr, recipientModule, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromAccountToModuleVirtual") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, types.AccAddress, string, types.Coins) error); ok { + r0 = rf(ctx, senderAddr, recipientModule, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SendCoinsFromModuleToAccount provides a mock function with given fields: ctx, senderModule, recipientAddr, amt func (_m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { ret := _m.Called(ctx, senderModule, recipientAddr, amt) @@ -206,6 +224,24 @@ func (_m *BankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderMo return r0 } +// SendCoinsFromModuleToAccountVirtual provides a mock function with given fields: ctx, senderModule, recipientAddr, amt +func (_m *BankKeeper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + ret := _m.Called(ctx, senderModule, recipientAddr, amt) + + if len(ret) == 0 { + panic("no return value specified for SendCoinsFromModuleToAccountVirtual") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, types.AccAddress, types.Coins) error); ok { + r0 = rf(ctx, senderModule, recipientAddr, amt) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SetDenomMetaData provides a mock function with given fields: ctx, denomMetaData func (_m *BankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData banktypes.Metadata) { _m.Called(ctx, denomMetaData) @@ -234,7 +270,8 @@ func (_m *BankKeeper) SpendableCoin(ctx context.Context, addr types.AccAddress, func NewBankKeeper(t interface { mock.TestingT Cleanup(func()) -}) *BankKeeper { +}, +) *BankKeeper { mock := &BankKeeper{} mock.Mock.Test(t) diff --git a/x/vm/wrappers/testutil/mock.go b/x/vm/wrappers/testutil/mock.go index ff3ce949f..9bd1a2d8a 100644 --- a/x/vm/wrappers/testutil/mock.go +++ b/x/vm/wrappers/testutil/mock.go @@ -20,11 +20,12 @@ import ( types "github.com/cosmos/cosmos-sdk/types" types0 "github.com/cosmos/cosmos-sdk/x/auth/types" types1 "github.com/cosmos/cosmos-sdk/x/bank/types" - types2 "github.com/cosmos/cosmos-sdk/x/staking/types" - types3 "github.com/cosmos/evm/x/feemarket/types" + types2 "github.com/cosmos/cosmos-sdk/x/consensus/types" + types3 "github.com/cosmos/cosmos-sdk/x/staking/types" + types4 "github.com/cosmos/evm/x/feemarket/types" common "github.com/ethereum/go-ethereum/common" core "github.com/ethereum/go-ethereum/core" - types4 "github.com/ethereum/go-ethereum/core/types" + types5 "github.com/ethereum/go-ethereum/core/types" vm "github.com/ethereum/go-ethereum/core/vm" gomock "go.uber.org/mock/gomock" ) @@ -384,6 +385,20 @@ func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModule(ctx, senderAd return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) } +// SendCoinsFromAccountToModuleVirtual mocks base method. +func (m *MockBankKeeper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromAccountToModuleVirtual", ctx, senderAddr, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromAccountToModuleVirtual indicates an expected call of SendCoinsFromAccountToModuleVirtual. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromAccountToModuleVirtual(ctx, senderAddr, recipientModule, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModuleVirtual", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromAccountToModuleVirtual), ctx, senderAddr, recipientModule, amt) +} + // SendCoinsFromModuleToAccount mocks base method. func (m *MockBankKeeper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { m.ctrl.T.Helper() @@ -398,6 +413,20 @@ func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderMo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) } +// SendCoinsFromModuleToAccountVirtual mocks base method. +func (m *MockBankKeeper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccountVirtual", ctx, senderModule, recipientAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromModuleToAccountVirtual indicates an expected call of SendCoinsFromModuleToAccountVirtual. +func (mr *MockBankKeeperMockRecorder) SendCoinsFromModuleToAccountVirtual(ctx, senderModule, recipientAddr, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccountVirtual", reflect.TypeOf((*MockBankKeeper)(nil).SendCoinsFromModuleToAccountVirtual), ctx, senderModule, recipientAddr, amt) +} + // SetDenomMetaData mocks base method. func (m *MockBankKeeper) SetDenomMetaData(ctx context.Context, denomMetaData types1.Metadata) { m.ctrl.T.Helper() @@ -449,10 +478,10 @@ func (m *MockStakingKeeper) EXPECT() *MockStakingKeeperMockRecorder { } // GetHistoricalInfo mocks base method. -func (m *MockStakingKeeper) GetHistoricalInfo(ctx context.Context, height int64) (types2.HistoricalInfo, error) { +func (m *MockStakingKeeper) GetHistoricalInfo(ctx context.Context, height int64) (types3.HistoricalInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetHistoricalInfo", ctx, height) - ret0, _ := ret[0].(types2.HistoricalInfo) + ret0, _ := ret[0].(types3.HistoricalInfo) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -464,10 +493,10 @@ func (mr *MockStakingKeeperMockRecorder) GetHistoricalInfo(ctx, height any) *gom } // GetValidatorByConsAddr mocks base method. -func (m *MockStakingKeeper) GetValidatorByConsAddr(ctx context.Context, consAddr types.ConsAddress) (types2.Validator, error) { +func (m *MockStakingKeeper) GetValidatorByConsAddr(ctx context.Context, consAddr types.ConsAddress) (types3.Validator, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetValidatorByConsAddr", ctx, consAddr) - ret0, _ := ret[0].(types2.Validator) + ret0, _ := ret[0].(types3.Validator) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -545,10 +574,10 @@ func (mr *MockFeeMarketKeeperMockRecorder) GetBaseFee(ctx any) *gomock.Call { } // GetParams mocks base method. -func (m *MockFeeMarketKeeper) GetParams(ctx types.Context) types3.Params { +func (m *MockFeeMarketKeeper) GetParams(ctx types.Context) types4.Params { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetParams", ctx) - ret0, _ := ret[0].(types3.Params) + ret0, _ := ret[0].(types4.Params) return ret0 } @@ -623,7 +652,7 @@ func (m *MockEvmHooks) EXPECT() *MockEvmHooksMockRecorder { } // PostTxProcessing mocks base method. -func (m *MockEvmHooks) PostTxProcessing(ctx types.Context, sender common.Address, msg core.Message, receipt *types4.Receipt) error { +func (m *MockEvmHooks) PostTxProcessing(ctx types.Context, sender common.Address, msg core.Message, receipt *types5.Receipt) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PostTxProcessing", ctx, sender, msg, receipt) ret0, _ := ret[0].(error) @@ -830,6 +859,20 @@ func (mr *MockBankWrapperMockRecorder) SendCoinsFromAccountToModule(ctx, senderA return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModule", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromAccountToModule), ctx, senderAddr, recipientModule, amt) } +// SendCoinsFromAccountToModuleVirtual mocks base method. +func (m *MockBankWrapper) SendCoinsFromAccountToModuleVirtual(ctx context.Context, senderAddr types.AccAddress, recipientModule string, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromAccountToModuleVirtual", ctx, senderAddr, recipientModule, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromAccountToModuleVirtual indicates an expected call of SendCoinsFromAccountToModuleVirtual. +func (mr *MockBankWrapperMockRecorder) SendCoinsFromAccountToModuleVirtual(ctx, senderAddr, recipientModule, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromAccountToModuleVirtual", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromAccountToModuleVirtual), ctx, senderAddr, recipientModule, amt) +} + // SendCoinsFromModuleToAccount mocks base method. func (m *MockBankWrapper) SendCoinsFromModuleToAccount(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { m.ctrl.T.Helper() @@ -844,6 +887,20 @@ func (mr *MockBankWrapperMockRecorder) SendCoinsFromModuleToAccount(ctx, senderM return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccount", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromModuleToAccount), ctx, senderModule, recipientAddr, amt) } +// SendCoinsFromModuleToAccountVirtual mocks base method. +func (m *MockBankWrapper) SendCoinsFromModuleToAccountVirtual(ctx context.Context, senderModule string, recipientAddr types.AccAddress, amt types.Coins) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SendCoinsFromModuleToAccountVirtual", ctx, senderModule, recipientAddr, amt) + ret0, _ := ret[0].(error) + return ret0 +} + +// SendCoinsFromModuleToAccountVirtual indicates an expected call of SendCoinsFromModuleToAccountVirtual. +func (mr *MockBankWrapperMockRecorder) SendCoinsFromModuleToAccountVirtual(ctx, senderModule, recipientAddr, amt any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendCoinsFromModuleToAccountVirtual", reflect.TypeOf((*MockBankWrapper)(nil).SendCoinsFromModuleToAccountVirtual), ctx, senderModule, recipientAddr, amt) +} + // SetDenomMetaData mocks base method. func (m *MockBankWrapper) SetDenomMetaData(ctx context.Context, denomMetaData types1.Metadata) { m.ctrl.T.Helper() @@ -869,3 +926,42 @@ func (mr *MockBankWrapperMockRecorder) SpendableCoin(ctx, addr, denom any) *gomo mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoin", reflect.TypeOf((*MockBankWrapper)(nil).SpendableCoin), ctx, addr, denom) } + +// MockConsensusParamsKeeper is a mock of ConsensusParamsKeeper interface. +type MockConsensusParamsKeeper struct { + ctrl *gomock.Controller + recorder *MockConsensusParamsKeeperMockRecorder + isgomock struct{} +} + +// MockConsensusParamsKeeperMockRecorder is the mock recorder for MockConsensusParamsKeeper. +type MockConsensusParamsKeeperMockRecorder struct { + mock *MockConsensusParamsKeeper +} + +// NewMockConsensusParamsKeeper creates a new mock instance. +func NewMockConsensusParamsKeeper(ctrl *gomock.Controller) *MockConsensusParamsKeeper { + mock := &MockConsensusParamsKeeper{ctrl: ctrl} + mock.recorder = &MockConsensusParamsKeeperMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockConsensusParamsKeeper) EXPECT() *MockConsensusParamsKeeperMockRecorder { + return m.recorder +} + +// Params mocks base method. +func (m *MockConsensusParamsKeeper) Params(arg0 context.Context, arg1 *types2.QueryParamsRequest) (*types2.QueryParamsResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Params", arg0, arg1) + ret0, _ := ret[0].(*types2.QueryParamsResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Params indicates an expected call of Params. +func (mr *MockConsensusParamsKeeperMockRecorder) Params(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Params", reflect.TypeOf((*MockConsensusParamsKeeper)(nil).Params), arg0, arg1) +}