Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cosmos gas multiplier params #487

Closed
wants to merge 13 commits into from
6 changes: 6 additions & 0 deletions proto/cosmos/params/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ message FeesParams {
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.DecCoins"];
}

message CosmosGasParams {
uint64 cosmos_gas_multiplier_numerator = 1;
uint64 cosmos_gas_multiplier_denominator = 2;
}

message GenesisState {
FeesParams fees_params = 1 [(gogoproto.nullable) = false];
CosmosGasParams cosmos_gas_params = 2 [(gogoproto.nullable) = false];
}
23 changes: 15 additions & 8 deletions store/cachekv/mergeiterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import (
//
// TODO: Optimize by memoizing.
type cacheMergeIterator struct {
parent types.Iterator
cache types.Iterator
ascending bool
storeKey sdktypes.StoreKey
parent types.Iterator
cache types.Iterator
ascending bool
storeKey sdktypes.StoreKey
eventManager *sdktypes.EventManager
}

var _ types.Iterator = (*cacheMergeIterator)(nil)
Expand All @@ -28,12 +29,14 @@ func NewCacheMergeIterator(
parent, cache types.Iterator,
ascending bool,
storeKey sdktypes.StoreKey,
eventManager *sdktypes.EventManager,
) *cacheMergeIterator {
iter := &cacheMergeIterator{
parent: parent,
cache: cache,
ascending: ascending,
storeKey: storeKey,
parent: parent,
cache: cache,
ascending: ascending,
storeKey: storeKey,
eventManager: eventManager,
}

return iter
Expand Down Expand Up @@ -135,12 +138,14 @@ func (iter *cacheMergeIterator) Value() []byte {
// If parent is invalid, get the cache value.
if !iter.parent.Valid() {
value := iter.cache.Value()
iter.eventManager.EmitResourceAccessReadEvent("iterator", iter.storeKey, iter.cache.Key(), value)
return value
}

// If cache is invalid, get the parent value.
if !iter.cache.Valid() {
value := iter.parent.Value()
iter.eventManager.EmitResourceAccessReadEvent("iterator", iter.storeKey, iter.parent.Key(), value)
return value
}

Expand All @@ -151,9 +156,11 @@ func (iter *cacheMergeIterator) Value() []byte {
switch cmp {
case -1: // parent < cache
value := iter.parent.Value()
iter.eventManager.EmitResourceAccessReadEvent("iterator", iter.storeKey, keyP, value)
return value
case 0, 1: // parent >= cache
value := iter.cache.Value()
iter.eventManager.EmitResourceAccessReadEvent("iterator", iter.storeKey, keyC, value)
return value
default:
panic("invalid comparison result")
Expand Down
28 changes: 22 additions & 6 deletions store/cachekv/mergeiterator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import (
"github.com/cosmos/cosmos-sdk/store/cachekv"
"github.com/cosmos/cosmos-sdk/store/dbadapter"
"github.com/cosmos/cosmos-sdk/store/types"
sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
)

func TestMangerIterator(t *testing.T) {
// initiate mock kvstore
mem := dbadapter.Store{DB: dbm.NewMemDB()}
eventManager := sdktypes.NewEventManager()
kvstore := cachekv.NewStore(mem, types.NewKVStoreKey("CacheKvTest"), types.DefaultCacheSizeLimit)
value := randSlice(defaultValueSizeBz)
startKey := randSlice(32)
Expand All @@ -27,13 +29,27 @@ func TestMangerIterator(t *testing.T) {
cache := kvstore.Iterator(nil, nil)
for ; cache.Valid(); cache.Next() {
}
iter := cachekv.NewCacheMergeIterator(parent, cache, true, types.NewKVStoreKey("CacheKvTest"))
iter := cachekv.NewCacheMergeIterator(parent, cache, true, types.NewKVStoreKey("CacheKvTest"), eventManager)

// get the next value and it should not be nil
nextValue := iter.Value()
require.NotNil(t, nextValue)
// get the next value
iter.Value()

// assert the resource access is still emitted correctly when the cache store is unavailable
require.Equal(t, "access_type", string(eventManager.Events()[0].Attributes[0].Key))
require.Equal(t, "read", string(eventManager.Events()[0].Attributes[0].Value))
require.Equal(t, "store_key", string(eventManager.Events()[0].Attributes[1].Key))
require.Equal(t, "CacheKvTest", string(eventManager.Events()[0].Attributes[1].Value))

// assert event emission when cache is available
cache = kvstore.Iterator(keys[1], keys[2])
iter = cachekv.NewCacheMergeIterator(parent, cache, true, types.NewKVStoreKey("CacheKvTest"), eventManager)

// get the next value
nextValue = iter.Value()
require.NotNil(t, nextValue)
iter.Value()

// assert the resource access is still emitted correctly when the cache store is available
require.Equal(t, "access_type", string(eventManager.Events()[0].Attributes[0].Key))
require.Equal(t, "read", string(eventManager.Events()[0].Attributes[0].Value))
require.Equal(t, "store_key", string(eventManager.Events()[0].Attributes[1].Key))
require.Equal(t, "CacheKvTest", string(eventManager.Events()[0].Attributes[1].Value))
}
7 changes: 6 additions & 1 deletion store/cachekv/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func (store *Store) GetEvents() []abci.Event {

// Implements Store
func (store *Store) ResetEvents() {
store.mtx.Lock()
defer store.mtx.Unlock()
store.eventManager = sdktypes.NewEventManager()
}

Expand All @@ -75,6 +77,7 @@ func (store *Store) getFromCache(key []byte) []byte {
// Get implements types.KVStore.
func (store *Store) Get(key []byte) (value []byte) {
types.AssertValidKey(key)
store.eventManager.EmitResourceAccessReadEvent("get", store.storeKey, key, value)
return store.getFromCache(key)
}

Expand All @@ -83,11 +86,13 @@ func (store *Store) Set(key []byte, value []byte) {
types.AssertValidKey(key)
types.AssertValidValue(value)
store.setCacheValue(key, value, false, true)
store.eventManager.EmitResourceAccessWriteEvent("set", store.storeKey, key, value)
}

// Has implements types.KVStore.
func (store *Store) Has(key []byte) bool {
value := store.Get(key)
store.eventManager.EmitResourceAccessReadEvent("has", store.storeKey, key, value)
return value != nil
}

Expand Down Expand Up @@ -189,7 +194,7 @@ func (store *Store) iterator(start, end []byte, ascending bool) types.Iterator {
}()
store.dirtyItems(start, end)
cache = newMemIterator(start, end, store.sortedCache, store.deleted, ascending, store.eventManager, store.storeKey)
return NewCacheMergeIterator(parent, cache, ascending, store.storeKey)
return NewCacheMergeIterator(parent, cache, ascending, store.storeKey, store.eventManager)
}

func (store *Store) VersionExists(version int64) bool {
Expand Down
29 changes: 29 additions & 0 deletions store/types/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,35 @@ func (g *infiniteGasMeter) String() string {
return fmt.Sprintf("InfiniteGasMeter:\n consumed: %d", g.consumed)
}

type infiniteMultiplierGasMeter struct {
infiniteGasMeter
multiplierNumerator uint64
multiplierDenominator uint64
}

func NewInfiniteMultiplierGasMeter(multiplierNumerator uint64, multiplierDenominator uint64) GasMeter {
return &infiniteMultiplierGasMeter{
infiniteGasMeter: infiniteGasMeter{
consumed: 0,
lock: &sync.Mutex{},
},
multiplierNumerator: multiplierNumerator,
multiplierDenominator: multiplierDenominator,
}
}

func (g *infiniteMultiplierGasMeter) adjustGas(original Gas) Gas {
return original * g.multiplierNumerator / g.multiplierDenominator
}

func (g *infiniteMultiplierGasMeter) ConsumeGas(amount Gas, descriptor string) {
g.infiniteGasMeter.ConsumeGas(g.adjustGas(amount), descriptor)
}

func (g *infiniteMultiplierGasMeter) RefundGas(amount Gas, descriptor string) {
g.infiniteGasMeter.RefundGas(g.adjustGas(amount), descriptor)
}

type noConsumptionInfiniteGasMeter struct {
infiniteGasMeter
}
Expand Down
31 changes: 31 additions & 0 deletions store/types/gas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,37 @@ func TestMultiplierGasMeter(t *testing.T) {
}
}

func TestInfiniteMultiplierGasMeter(t *testing.T) {
t.Parallel()
cases := []struct {
usage []Gas
multiplierNumerator uint64
multiplierDenominator uint64
}{
{[]Gas{1, 2, 3, 4}, 1, 1},
{[]Gas{40, 30, 20, 10}, 10, 1},
{[]Gas{99998, 2, 100000}, 1, 2},
{[]Gas{50000000, 40000000, 10000000}, 1, 1},
{[]Gas{32768, 32767}, 1, 1},
{[]Gas{32768, 32767, 1}, 1, 1},
}

for tcnum, tc := range cases {
meter := NewInfiniteMultiplierGasMeter(tc.multiplierNumerator, tc.multiplierDenominator)
used := uint64(0)

for unum, usage := range tc.usage {
usage := usage
used += usage * tc.multiplierNumerator / tc.multiplierDenominator
require.NotPanics(t, func() { meter.ConsumeGas(usage, "") }, "Not exceeded limit but panicked. tc #%d, usage #%d", tcnum, unum)
require.Equal(t, used, meter.GasConsumed(), "Gas consumption not match. tc #%d, usage #%d", tcnum, unum)
require.Equal(t, used, meter.GasConsumedToLimit(), "Gas consumption (to limit) not match. tc #%d, usage #%d", tcnum, unum)
require.False(t, meter.IsPastLimit(), "Not exceeded limit but got IsPastLimit() true")
require.False(t, meter.IsOutOfGas(), "Not yet at limit but got IsOutOfGas() true")
}
}
}

func TestAddUint64Overflow(t *testing.T) {
t.Parallel()
testCases := []struct {
Expand Down
2 changes: 2 additions & 0 deletions x/auth/ante/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ type FeegrantKeeper interface {
type ParamsKeeper interface {
SetFeesParams(ctx sdk.Context, feesParams paramtypes.FeesParams)
GetFeesParams(ctx sdk.Context) paramtypes.FeesParams
SetCosmosGasParams(ctx sdk.Context, cosmosGasParams paramtypes.CosmosGasParams)
GetCosmosGasParams(ctx sdk.Context) paramtypes.CosmosGasParams
}
31 changes: 30 additions & 1 deletion x/params/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func NewQueryCmd() *cobra.Command {

cmd.AddCommand(NewQuerySubspaceParamsCmd())
cmd.AddCommand(NewQueryFeeParamsCmd())
cmd.AddCommand(NewQueryCosmosGasParamsCmd())
cmd.AddCommand(NewQueryBlockParamsCmd())

return cmd
Expand Down Expand Up @@ -57,7 +58,6 @@ func NewQuerySubspaceParamsCmd() *cobra.Command {
return cmd
}


func NewQueryFeeParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "feesparams",
Expand Down Expand Up @@ -87,6 +87,35 @@ func NewQueryFeeParamsCmd() *cobra.Command {
return cmd
}

func NewQueryCosmosGasParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "cosmosgasparams",
Short: "Query for cosmos gas params",
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
queryClient := proposal.NewQueryClient(clientCtx)

params := proposal.QueryParamsRequest{Subspace: "params", Key: string(types.ParamStoreKeyCosmosGasParams)}
res, err := queryClient.Params(cmd.Context(), &params)
if err != nil {
return err
}

cosmosGasParams := types.CosmosGasParams{}
clientCtx.Codec.UnmarshalJSON([]byte(res.Param.Value), &cosmosGasParams)

return clientCtx.PrintProto(&cosmosGasParams)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}

func NewQueryBlockParamsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "blockparams",
Expand Down
22 changes: 22 additions & 0 deletions x/params/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,28 @@ func (k Keeper) GetFeesParams(ctx sdk.Context) types.FeesParams {
return feesParams
}

func (k Keeper) SetCosmosGasParams(ctx sdk.Context, cosmosGasParams types.CosmosGasParams) {
cosmosGasParams.Validate()
subspace, exist := k.GetSubspace(types.ModuleName)
if !exist {
panic("subspace params should exist")
}
subspace.Set(ctx, types.ParamStoreKeyCosmosGasParams, cosmosGasParams)
}

func (k Keeper) GetCosmosGasParams(ctx sdk.Context) types.CosmosGasParams {
subspace, _ := k.GetSubspace(types.ModuleName)

var cosmosGasParams types.CosmosGasParams
if !subspace.Has(ctx, types.ParamStoreKeyCosmosGasParams) {
return cosmosGasParams
}

bz := subspace.GetRaw(ctx, types.ParamStoreKeyCosmosGasParams)
json.Unmarshal(bz, &cosmosGasParams)
return cosmosGasParams
}

// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", "x/"+proposal.ModuleName)
Expand Down
16 changes: 16 additions & 0 deletions x/params/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,19 @@ func TestJSONUpdate(t *testing.T) {
space.Get(ctx, key, &param)
require.Equal(t, paramJSON{40964096, "goodbyeworld"}, param)
}

func TestUpdateCosmosGasParams(t *testing.T) {
_, ctx, _, _, keeper := testComponents()
cosmosGasParams := keeper.GetCosmosGasParams(ctx)
// If not set, gas params set to default
defaultParams := types.DefaultCosmosGasParams()
require.Equal(t, defaultParams.CosmosGasMultiplierNumerator, cosmosGasParams.CosmosGasMultiplierNumerator)
require.Equal(t, defaultParams.CosmosGasMultiplierDenominator, cosmosGasParams.CosmosGasMultiplierDenominator)

// Update to 1/4
keeper.SetCosmosGasParams(ctx, types.NewCosmosGasParams(1, 4))

cosmosGasParams = keeper.GetCosmosGasParams(ctx)
require.Equal(t, uint64(1), cosmosGasParams.CosmosGasMultiplierNumerator)
require.Equal(t, uint64(4), cosmosGasParams.CosmosGasMultiplierDenominator)
}
23 changes: 23 additions & 0 deletions x/params/keeper/migrations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package keeper

import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params/types"
)

// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper Keeper
}

// NewMigrator returns a new Migrator.
func NewMigrator(keeper Keeper) Migrator {
return Migrator{keeper: keeper}
}

// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
defaultGenesis := types.DefaultGenesis()
m.keeper.SetCosmosGasParams(ctx, defaultGenesis.CosmosGasParams)
return nil
}
22 changes: 22 additions & 0 deletions x/params/keeper/migrations_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package keeper_test

import (
"testing"

pk "github.com/cosmos/cosmos-sdk/x/params/keeper"
"github.com/cosmos/cosmos-sdk/x/params/types"

"github.com/stretchr/testify/require"
)

func TestMigrate1to2(t *testing.T) {
_, ctx, _, _, keeper := testComponents()
m := pk.NewMigrator(keeper)
err := m.Migrate1to2(ctx)
require.Nil(t, err)
cosmosGasParams := keeper.GetCosmosGasParams(ctx)
// ensure set to defaults
defaultParams := types.DefaultGenesis()
require.Equal(t, defaultParams.CosmosGasParams.CosmosGasMultiplierNumerator, cosmosGasParams.CosmosGasMultiplierNumerator)
require.Equal(t, defaultParams.CosmosGasParams.CosmosGasMultiplierDenominator, cosmosGasParams.CosmosGasMultiplierDenominator)
}
Loading
Loading