diff --git a/CHANGELOG.md b/CHANGELOG.md index 22a5fb116df2..8e7e96487b31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ ## [v0.50.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.5) - 2024-XX-XX +### Features + +* (baseapp) [#19626](https://github.com/cosmos/cosmos-sdk/pull/19626) Adds `DisableBlockGasMeter` option to `BaseApp`, which removes the block gas meter during transaction execution. + ### Improvements * (x/auth) [#19651](https://github.com/cosmos/cosmos-sdk/pull/19651) Allow empty public keys in `GetSignBytesAdapter`. diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index e7c3b5744d9f..c7e6e616f497 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -186,6 +186,13 @@ type BaseApp struct { // including the goroutine handling.This is experimental and must be enabled // by developers. optimisticExec *oe.OptimisticExecution + + // disableBlockGasMeter will disable the block gas meter if true, block gas meter is tricky to support + // when executing transactions in parallel. + // when disabled, the block gas meter in context is a noop one. + // + // SAFETY: it's safe to do if validators validate the total gas wanted in the `ProcessProposal`, which is the case in the default handler. + disableBlockGasMeter bool } // NewBaseApp returns a reference to an initialized BaseApp. It accepts a @@ -640,6 +647,10 @@ func (app *BaseApp) getState(mode execMode) *state { } func (app *BaseApp) getBlockGasMeter(ctx sdk.Context) storetypes.GasMeter { + if app.disableBlockGasMeter { + return noopGasMeter{} + } + if maxGas := app.GetMaximumBlockGas(ctx); maxGas > 0 { return storetypes.NewGasMeter(maxGas) } diff --git a/baseapp/noopgasmeter.go b/baseapp/noopgasmeter.go new file mode 100644 index 000000000000..c341bcbe7b11 --- /dev/null +++ b/baseapp/noopgasmeter.go @@ -0,0 +1,17 @@ +package baseapp + +import storetypes "cosmossdk.io/store/types" + +type noopGasMeter struct{} + +var _ storetypes.GasMeter = noopGasMeter{} + +func (noopGasMeter) GasConsumed() storetypes.Gas { return 0 } +func (noopGasMeter) GasConsumedToLimit() storetypes.Gas { return 0 } +func (noopGasMeter) GasRemaining() storetypes.Gas { return 0 } +func (noopGasMeter) Limit() storetypes.Gas { return 0 } +func (noopGasMeter) ConsumeGas(storetypes.Gas, string) {} +func (noopGasMeter) RefundGas(storetypes.Gas, string) {} +func (noopGasMeter) IsPastLimit() bool { return false } +func (noopGasMeter) IsOutOfGas() bool { return false } +func (noopGasMeter) String() string { return "noopGasMeter" } diff --git a/baseapp/options.go b/baseapp/options.go index c8cacdd8a4be..08cbf77ee297 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -117,6 +117,11 @@ func SetOptimisticExecution(opts ...func(*oe.OptimisticExecution)) func(*BaseApp } } +// DisableBlockGasMeter disables the block gas meter. +func DisableBlockGasMeter() func(*BaseApp) { + return func(app *BaseApp) { app.SetDisableBlockGasMeter(true) } +} + func (app *BaseApp) SetName(name string) { if app.sealed { panic("SetName() on sealed BaseApp") @@ -362,3 +367,8 @@ func (app *BaseApp) SetStoreMetrics(gatherer metrics.StoreMetrics) { func (app *BaseApp) SetStreamingManager(manager storetypes.StreamingManager) { app.streamingManager = manager } + +// SetDisableBlockGasMeter sets the disableBlockGasMeter flag for the BaseApp. +func (app *BaseApp) SetDisableBlockGasMeter(disableBlockGasMeter bool) { + app.disableBlockGasMeter = disableBlockGasMeter +}