Skip to content

Commit

Permalink
Cosmos Gas Multiplier Params (#489)
Browse files Browse the repository at this point in the history
## Describe your changes and provide context
- Create cosmos gas multiplier params
- Add back eventManager to cachekv

## Testing performed to validate your change
- Validated on chain

---------

Co-authored-by: Uday Patil <[email protected]>
  • Loading branch information
Kbhat1 and udpatil authored Apr 19, 2024
1 parent 4e37eb4 commit 7567a55
Show file tree
Hide file tree
Showing 20 changed files with 723 additions and 58 deletions.
19 changes: 11 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,13 @@ require (
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
github.com/cosmos/gorocksdb v1.2.0 // indirect
github.com/creachadair/taskgroup v0.3.2 // indirect
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgraph-io/badger/v3 v3.2103.2 // indirect
github.com/dgraph-io/ristretto v0.1.1 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gin-gonic/gin v1.7.7 // indirect
github.com/go-kit/kit v0.12.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
Expand All @@ -97,10 +94,8 @@ require (
github.com/golang/glog v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/google/flatbuffers v1.12.1 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/orderedcode v0.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
Expand All @@ -126,7 +121,6 @@ require (
github.com/mtibben/percent v0.2.1 // indirect
github.com/oasisprotocol/curve25519-voi v0.0.0-20210609091139-0a56a4bca00b // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
Expand All @@ -150,13 +144,11 @@ require (
go.opencensus.io v0.23.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/uint128 v1.2.0 // indirect
Expand All @@ -172,6 +164,17 @@ require (
nhooyr.io/websocket v1.8.6 // indirect
)

require (
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
github.com/gin-gonic/gin v1.7.7 // indirect
github.com/google/btree v1.1.2
github.com/google/gofuzz v1.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
golang.org/x/sync v0.4.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect
)

replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
Expand Down
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 findStartIndex(strL []string, startQ string) int {
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
19 changes: 19 additions & 0 deletions x/params/keeper/genesis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package keeper

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

// InitGenesis new mint genesis.
func (k Keeper) InitGenesis(ctx sdk.Context, data *types.GenesisState) {
k.SetFeesParams(ctx, data.FeesParams)
k.SetCosmosGasParams(ctx, data.CosmosGasParams)
}

// ExportGenesis returns a GenesisState for a given context and keeper.
func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState {
feesParams := k.GetFeesParams(ctx)
cosmosGasParams := k.GetCosmosGasParams(ctx)
return types.NewGenesisState(feesParams, cosmosGasParams)
}
Loading

0 comments on commit 7567a55

Please sign in to comment.