diff --git a/CHANGELOG.md b/CHANGELOG.md index 036e124ef9c5..099090210b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* [#13826](https://github.com/cosmos/cosmos-sdk/pull/13826) Support custom `GasConfig` configuration for applications. * (deps) Bump Tendermint version to [v0.34.23](https://github.com/tendermint/tendermint/releases/tag/v0.34.23). ### Bug Fixes diff --git a/types/context.go b/types/context.go index 8a050a1b0803..da86a8c089fd 100644 --- a/types/context.go +++ b/types/context.go @@ -23,43 +23,47 @@ but please do not over-use it. We try to keep all data structured and standard additions here would be better just to add to the Context struct */ type Context struct { - baseCtx context.Context - ms MultiStore - header tmproto.Header - headerHash tmbytes.HexBytes - chainID string - txBytes []byte - logger log.Logger - voteInfo []abci.VoteInfo - gasMeter GasMeter - blockGasMeter GasMeter - checkTx bool - recheckTx bool // if recheckTx == true, then checkTx must also be true - minGasPrice DecCoins - consParams *abci.ConsensusParams - eventManager *EventManager - priority int64 // The tx priority, only relevant in CheckTx + baseCtx context.Context + ms MultiStore + header tmproto.Header + headerHash tmbytes.HexBytes + chainID string + txBytes []byte + logger log.Logger + voteInfo []abci.VoteInfo + gasMeter GasMeter + blockGasMeter GasMeter + checkTx bool + recheckTx bool // if recheckTx == true, then checkTx must also be true + minGasPrice DecCoins + consParams *abci.ConsensusParams + eventManager *EventManager + priority int64 // The tx priority, only relevant in CheckTx + kvGasConfig storetypes.GasConfig + transientKVGasConfig storetypes.GasConfig } // Proposed rename, not done to avoid API breakage type Request = Context // Read-only accessors -func (c Context) Context() context.Context { return c.baseCtx } -func (c Context) MultiStore() MultiStore { return c.ms } -func (c Context) BlockHeight() int64 { return c.header.Height } -func (c Context) BlockTime() time.Time { return c.header.Time } -func (c Context) ChainID() string { return c.chainID } -func (c Context) TxBytes() []byte { return c.txBytes } -func (c Context) Logger() log.Logger { return c.logger } -func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } -func (c Context) GasMeter() GasMeter { return c.gasMeter } -func (c Context) BlockGasMeter() GasMeter { return c.blockGasMeter } -func (c Context) IsCheckTx() bool { return c.checkTx } -func (c Context) IsReCheckTx() bool { return c.recheckTx } -func (c Context) MinGasPrices() DecCoins { return c.minGasPrice } -func (c Context) EventManager() *EventManager { return c.eventManager } -func (c Context) Priority() int64 { return c.priority } +func (c Context) Context() context.Context { return c.baseCtx } +func (c Context) MultiStore() MultiStore { return c.ms } +func (c Context) BlockHeight() int64 { return c.header.Height } +func (c Context) BlockTime() time.Time { return c.header.Time } +func (c Context) ChainID() string { return c.chainID } +func (c Context) TxBytes() []byte { return c.txBytes } +func (c Context) Logger() log.Logger { return c.logger } +func (c Context) VoteInfos() []abci.VoteInfo { return c.voteInfo } +func (c Context) GasMeter() GasMeter { return c.gasMeter } +func (c Context) BlockGasMeter() GasMeter { return c.blockGasMeter } +func (c Context) IsCheckTx() bool { return c.checkTx } +func (c Context) IsReCheckTx() bool { return c.recheckTx } +func (c Context) MinGasPrices() DecCoins { return c.minGasPrice } +func (c Context) EventManager() *EventManager { return c.eventManager } +func (c Context) Priority() int64 { return c.priority } +func (c Context) KVGasConfig() storetypes.GasConfig { return c.kvGasConfig } +func (c Context) TransientKVGasConfig() storetypes.GasConfig { return c.transientKVGasConfig } // clone the header before returning func (c Context) BlockHeader() tmproto.Header { @@ -95,15 +99,17 @@ func NewContext(ms MultiStore, header tmproto.Header, isCheckTx bool, logger log // https://github.com/gogo/protobuf/issues/519 header.Time = header.Time.UTC() return Context{ - baseCtx: context.Background(), - ms: ms, - header: header, - chainID: header.ChainID, - checkTx: isCheckTx, - logger: logger, - gasMeter: storetypes.NewInfiniteGasMeter(), - minGasPrice: DecCoins{}, - eventManager: NewEventManager(), + baseCtx: context.Background(), + ms: ms, + header: header, + chainID: header.ChainID, + checkTx: isCheckTx, + logger: logger, + gasMeter: storetypes.NewInfiniteGasMeter(), + minGasPrice: DecCoins{}, + eventManager: NewEventManager(), + kvGasConfig: storetypes.KVGasConfig(), + transientKVGasConfig: storetypes.TransientGasConfig(), } } @@ -194,6 +200,20 @@ func (c Context) WithBlockGasMeter(meter GasMeter) Context { return c } +// WithKVGasConfig returns a Context with an updated gas configuration for +// the KVStore +func (c Context) WithKVGasConfig(gasConfig storetypes.GasConfig) Context { + c.kvGasConfig = gasConfig + return c +} + +// WithTransientKVGasConfig returns a Context with an updated gas configuration for +// the transient KVStore +func (c Context) WithTransientKVGasConfig(gasConfig storetypes.GasConfig) Context { + c.transientKVGasConfig = gasConfig + return c +} + // WithIsCheckTx enables or disables CheckTx value for verifying transactions and returns an updated Context func (c Context) WithIsCheckTx(isCheckTx bool) Context { c.checkTx = isCheckTx @@ -258,12 +278,12 @@ func (c Context) Value(key interface{}) interface{} { // KVStore fetches a KVStore from the MultiStore. func (c Context) KVStore(key storetypes.StoreKey) KVStore { - return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), storetypes.KVGasConfig()) + return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), c.kvGasConfig) } // TransientStore fetches a TransientStore from the MultiStore. func (c Context) TransientStore(key storetypes.StoreKey) KVStore { - return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), storetypes.TransientGasConfig()) + return gaskv.NewStore(c.MultiStore().GetKVStore(key), c.GasMeter(), c.transientKVGasConfig) } // CacheContext returns a new Context with the multi-store cached and a new diff --git a/types/context_test.go b/types/context_test.go index f5c7cadeb541..6134e838f2c1 100644 --- a/types/context_test.go +++ b/types/context_test.go @@ -11,6 +11,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/tests/mocks" "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/types" @@ -98,6 +99,7 @@ func (s *contextTestSuite) TestContextWithCustom() { blockGasMeter := types.NewGasMeter(20000) minGasPrices := types.DecCoins{types.NewInt64DecCoin("feetoken", 1)} headerHash := []byte("headerHash") + zeroGasCfg := storetypes.GasConfig{} ctx = types.NewContext(nil, header, ischeck, logger) s.Require().Equal(header, ctx.BlockHeader()) @@ -110,7 +112,10 @@ func (s *contextTestSuite) TestContextWithCustom() { WithGasMeter(meter). WithMinGasPrices(minGasPrices). WithBlockGasMeter(blockGasMeter). - WithHeaderHash(headerHash) + WithHeaderHash(headerHash). + WithKVGasConfig(zeroGasCfg). + WithTransientKVGasConfig(zeroGasCfg) + s.Require().Equal(height, ctx.BlockHeight()) s.Require().Equal(chainid, ctx.ChainID()) s.Require().Equal(ischeck, ctx.IsCheckTx()) @@ -122,6 +127,8 @@ func (s *contextTestSuite) TestContextWithCustom() { s.Require().Equal(blockGasMeter, ctx.BlockGasMeter()) s.Require().Equal(headerHash, ctx.HeaderHash().Bytes()) s.Require().False(ctx.WithIsCheckTx(false).IsCheckTx()) + s.Require().Equal(zeroGasCfg, ctx.KVGasConfig()) + s.Require().Equal(zeroGasCfg, ctx.TransientKVGasConfig()) // test IsReCheckTx s.Require().False(ctx.IsReCheckTx()) diff --git a/x/gov/keeper/msg_server.go b/x/gov/keeper/msg_server.go index 24e809ce31be..d832120dae42 100644 --- a/x/gov/keeper/msg_server.go +++ b/x/gov/keeper/msg_server.go @@ -7,7 +7,6 @@ import ( "github.com/armon/go-metrics" - storetypes "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/telemetry" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -48,7 +47,7 @@ func (k msgServer) SubmitProposal(goCtx context.Context, msg *v1.MsgSubmitPropos // ref: https://github.com/cosmos/cosmos-sdk/issues/9683 ctx.GasMeter().ConsumeGas( - 3*storetypes.KVGasConfig().WriteCostPerByte*uint64(len(bytes)), + 3*ctx.KVGasConfig().WriteCostPerByte*uint64(len(bytes)), "submit proposal", )