diff --git a/math/int_test.go b/math/int_test.go index 197f75ab6104..714ef5e65e50 100644 --- a/math/int_test.go +++ b/math/int_test.go @@ -689,7 +689,7 @@ func BenchmarkIntSize(b *testing.B) { } func BenchmarkIntOverflowCheckTime(b *testing.B) { - var ints = []*big.Int{} + ints := []*big.Int{} for _, st := range sizeTests { ii, _ := math.NewIntFromString(st.s) @@ -699,7 +699,7 @@ func BenchmarkIntOverflowCheckTime(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - for j, _ := range sizeTests { + for j := range sizeTests { got := math.NewIntFromBigIntMut(ints[j]) sink = got } diff --git a/simapp/app.go b/simapp/app.go index cf19ae6fc0b0..8533a40f725b 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -366,7 +366,7 @@ func NewSimApp( config.MaxProposalTitleLen = 255 // example max title length in characters config.MaxProposalSummaryLen = 10200 // example max summary length in characters */ - app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AuthKeeper, groupConfig) + app.GroupKeeper = groupkeeper.NewKeeper(runtime.NewKVStoreService(keys[group.StoreKey]), appCodec, app.MsgServiceRouter(), app.AuthKeeper, groupConfig) // get skipUpgradeHeights from the app options skipUpgradeHeights := map[int64]bool{} diff --git a/x/group/CHANGELOG.md b/x/group/CHANGELOG.md index 32cc0c27ee28..dc2f41fe69bc 100644 --- a/x/group/CHANGELOG.md +++ b/x/group/CHANGELOG.md @@ -33,3 +33,5 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features ### API Breaking Changes + +* [#19410](https://github.com/cosmos/cosmos-sdk/pull/19410) Migrate to Store Service. diff --git a/x/group/internal/orm/auto_uint64.go b/x/group/internal/orm/auto_uint64.go index b3b6d22fc731..3af49eff4cad 100644 --- a/x/group/internal/orm/auto_uint64.go +++ b/x/group/internal/orm/auto_uint64.go @@ -3,8 +3,8 @@ package orm import ( "github.com/cosmos/gogoproto/proto" + storetypes "cosmossdk.io/core/store" "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/codec" ) diff --git a/x/group/internal/orm/auto_uint64_test.go b/x/group/internal/orm/auto_uint64_test.go index ce64fd324efc..efb15bf5a46a 100644 --- a/x/group/internal/orm/auto_uint64_test.go +++ b/x/group/internal/orm/auto_uint64_test.go @@ -7,12 +7,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + corestore "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" ) @@ -23,8 +26,9 @@ func TestAutoUInt64PrefixScan(t *testing.T) { tb, err := NewAutoUInt64Table(AutoUInt64TablePrefix, AutoUInt64TableSeqPrefix, &testdata.TableModel{}, cdc) require.NoError(t, err) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) metadata := []byte("metadata") t1 := testdata.TableModel{ @@ -53,7 +57,7 @@ func TestAutoUInt64PrefixScan(t *testing.T) { expResult []testdata.TableModel expRowIDs []RowID expError *errorsmod.Error - method func(store storetypes.KVStore, start, end uint64) (Iterator, error) + method func(store corestore.KVStore, start, end uint64) (Iterator, error) }{ "first element": { start: 1, diff --git a/x/group/internal/orm/genesis.go b/x/group/internal/orm/genesis.go index 1f9a693e9b5a..368e2b14ba85 100644 --- a/x/group/internal/orm/genesis.go +++ b/x/group/internal/orm/genesis.go @@ -1,6 +1,6 @@ package orm -import storetypes "cosmossdk.io/store/types" +import storetypes "cosmossdk.io/core/store" // TableExportable defines the methods to import and export a table. type TableExportable interface { diff --git a/x/group/internal/orm/genesis_test.go b/x/group/internal/orm/genesis_test.go index 72128c9e595c..e2e5685a2d33 100644 --- a/x/group/internal/orm/genesis_test.go +++ b/x/group/internal/orm/genesis_test.go @@ -9,6 +9,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" ) @@ -19,8 +21,9 @@ func TestImportExportTableData(t *testing.T) { table, err := NewAutoUInt64Table(AutoUInt64TablePrefix, AutoUInt64TableSeqPrefix, &testdata.TableModel{}, cdc) require.NoError(t, err) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) tms := []*testdata.TableModel{ { diff --git a/x/group/internal/orm/index.go b/x/group/internal/orm/index.go index 5227684327e6..5fabcbac529c 100644 --- a/x/group/internal/orm/index.go +++ b/x/group/internal/orm/index.go @@ -5,19 +5,20 @@ import ( "github.com/cosmos/gogoproto/proto" + storetypes "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" + "cosmossdk.io/x/group/internal/orm/prefixstore" "github.com/cosmos/cosmos-sdk/types/query" ) // indexer creates and modifies the second MultiKeyIndex based on the operations and changes on the primary object. type indexer interface { - OnCreate(store types.KVStore, rowID RowID, value interface{}) error - OnDelete(store types.KVStore, rowID RowID, value interface{}) error - OnUpdate(store types.KVStore, rowID RowID, newValue, oldValue interface{}) error + OnCreate(store storetypes.KVStore, rowID RowID, value interface{}) error + OnDelete(store storetypes.KVStore, rowID RowID, value interface{}) error + OnUpdate(store storetypes.KVStore, rowID RowID, newValue, oldValue interface{}) error } var _ Index = &MultiKeyIndex{} @@ -72,34 +73,40 @@ func newIndex(tb Indexable, prefix byte, indexer *Indexer, indexerF IndexerFunc, } // Has checks if a key exists. Returns an error on nil key. -func (i MultiKeyIndex) Has(store types.KVStore, key interface{}) (bool, error) { +func (i MultiKeyIndex) Has(store storetypes.KVStore, key interface{}) (bool, error) { encodedKey, err := keyPartBytes(key, false) if err != nil { return false, err } - pStore := prefix.NewStore(store, []byte{i.prefix}) - it := pStore.Iterator(PrefixRange(encodedKey)) + pStore := prefixstore.New(store, []byte{i.prefix}) + it, err := pStore.Iterator(PrefixRange(encodedKey)) + if err != nil { + return false, err + } defer it.Close() return it.Valid(), nil } // Get returns a result iterator for the searchKey. Parameters must not be nil. -func (i MultiKeyIndex) Get(store types.KVStore, searchKey interface{}) (Iterator, error) { +func (i MultiKeyIndex) Get(store storetypes.KVStore, searchKey interface{}) (Iterator, error) { encodedKey, err := keyPartBytes(searchKey, false) if err != nil { return nil, err } - pStore := prefix.NewStore(store, []byte{i.prefix}) - it := pStore.Iterator(PrefixRange(encodedKey)) + pStore := prefixstore.New(store, []byte{i.prefix}) + it, err := pStore.Iterator(PrefixRange(encodedKey)) + if err != nil { + return nil, err + } return indexIterator{store: store, it: it, rowGetter: i.rowGetter, indexKey: i.indexKey}, nil } // GetPaginated creates an iterator for the searchKey // starting from pageRequest.Key if provided. // The pageRequest.Key is the rowID while searchKey is a MultiKeyIndex key. -func (i MultiKeyIndex) GetPaginated(store types.KVStore, searchKey interface{}, pageRequest *query.PageRequest) (Iterator, error) { +func (i MultiKeyIndex) GetPaginated(store storetypes.KVStore, searchKey interface{}, pageRequest *query.PageRequest) (Iterator, error) { encodedKey, err := keyPartBytes(searchKey, false) if err != nil { return nil, err @@ -114,8 +121,11 @@ func (i MultiKeyIndex) GetPaginated(store types.KVStore, searchKey interface{}, } } - pStore := prefix.NewStore(store, []byte{i.prefix}) - it := pStore.Iterator(start, end) + pStore := prefixstore.New(store, []byte{i.prefix}) + it, err := pStore.Iterator(start, end) + if err != nil { + return nil, err + } return indexIterator{store: store, it: it, rowGetter: i.rowGetter, indexKey: i.indexKey}, nil } @@ -136,14 +146,18 @@ func (i MultiKeyIndex) GetPaginated(store types.KVStore, searchKey interface{}, // it = LimitIterator(it, defaultLimit) // // CONTRACT: No writes may happen within a domain while an iterator exists over it. -func (i MultiKeyIndex) PrefixScan(store types.KVStore, startI, endI interface{}) (Iterator, error) { +func (i MultiKeyIndex) PrefixScan(store storetypes.KVStore, startI, endI interface{}) (Iterator, error) { start, end, err := getStartEndBz(startI, endI) if err != nil { return nil, err } - pStore := prefix.NewStore(store, []byte{i.prefix}) - it := pStore.Iterator(start, end) + pStore := prefixstore.New(store, []byte{i.prefix}) + it, err := pStore.Iterator(start, end) + if err != nil { + return nil, err + } + return indexIterator{store: store, it: it, rowGetter: i.rowGetter, indexKey: i.indexKey}, nil } @@ -156,14 +170,18 @@ func (i MultiKeyIndex) PrefixScan(store types.KVStore, startI, endI interface{}) // this as an endpoint to the public without further limits. See `LimitIterator` // // CONTRACT: No writes may happen within a domain while an iterator exists over it. -func (i MultiKeyIndex) ReversePrefixScan(store types.KVStore, startI, endI interface{}) (Iterator, error) { +func (i MultiKeyIndex) ReversePrefixScan(store storetypes.KVStore, startI, endI interface{}) (Iterator, error) { start, end, err := getStartEndBz(startI, endI) if err != nil { return nil, err } - pStore := prefix.NewStore(store, []byte{i.prefix}) - it := pStore.ReverseIterator(start, end) + pStore := prefixstore.New(store, []byte{i.prefix}) + it, err := pStore.ReverseIterator(start, end) + if err != nil { + return nil, err + } + return indexIterator{store: store, it: it, rowGetter: i.rowGetter, indexKey: i.indexKey}, nil } @@ -202,16 +220,16 @@ func getPrefixScanKeyBytes(keyI interface{}) ([]byte, error) { return key, nil } -func (i MultiKeyIndex) onSet(store types.KVStore, rowID RowID, newValue, oldValue proto.Message) error { - pStore := prefix.NewStore(store, []byte{i.prefix}) +func (i MultiKeyIndex) onSet(store storetypes.KVStore, rowID RowID, newValue, oldValue proto.Message) error { + pStore := prefixstore.New(store, []byte{i.prefix}) if oldValue == nil { return i.indexer.OnCreate(pStore, rowID, newValue) } return i.indexer.OnUpdate(pStore, rowID, newValue, oldValue) } -func (i MultiKeyIndex) onDelete(store types.KVStore, rowID RowID, oldValue proto.Message) error { - pStore := prefix.NewStore(store, []byte{i.prefix}) +func (i MultiKeyIndex) onDelete(store storetypes.KVStore, rowID RowID, oldValue proto.Message) error { + pStore := prefixstore.New(store, []byte{i.prefix}) return i.indexer.OnDelete(pStore, rowID, oldValue) } @@ -236,7 +254,7 @@ func NewUniqueIndex(tb Indexable, prefix byte, uniqueIndexerFunc UniqueIndexerFu // indexIterator uses rowGetter to lazy load new model values on request. type indexIterator struct { - store types.KVStore + store storetypes.KVStore rowGetter RowGetter it types.Iterator indexKey interface{} diff --git a/x/group/internal/orm/index_test.go b/x/group/internal/orm/index_test.go index f2194011fb0c..423373b962a7 100644 --- a/x/group/internal/orm/index_test.go +++ b/x/group/internal/orm/index_test.go @@ -6,12 +6,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + corestore "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" "github.com/cosmos/cosmos-sdk/types/query" ) @@ -101,8 +104,9 @@ func TestIndexPrefixScan(t *testing.T) { }, testdata.TableModel{}.Name) require.NoError(t, err) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) g1 := testdata.TableModel{ Id: 1, @@ -130,7 +134,7 @@ func TestIndexPrefixScan(t *testing.T) { expResult []testdata.TableModel expRowIDs []RowID expError *errorsmod.Error - method func(store storetypes.KVStore, start, end interface{}) (Iterator, error) + method func(store corestore.KVStore, start, end interface{}) (Iterator, error) }{ "exact match with a single result": { start: []byte("metadata-a"), @@ -301,8 +305,9 @@ func TestUniqueIndex(t *testing.T) { }, []byte{}) require.NoError(t, err) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) m := testdata.TableModel{ Id: 1, diff --git a/x/group/internal/orm/indexer.go b/x/group/internal/orm/indexer.go index 16d44d8cfbb4..e8dc212ec71b 100644 --- a/x/group/internal/orm/indexer.go +++ b/x/group/internal/orm/indexer.go @@ -1,8 +1,8 @@ package orm import ( + storetypes "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" - storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" ) @@ -81,7 +81,9 @@ func (i Indexer) OnDelete(store storetypes.KVStore, rowID RowID, value interface if err != nil { return err } - store.Delete(indexKey) + if err := store.Delete(indexKey); err != nil { + return err + } } return nil } @@ -105,7 +107,9 @@ func (i Indexer) OnUpdate(store storetypes.KVStore, rowID RowID, newValue, oldVa if err != nil { return err } - store.Delete(indexKey) + if err := store.Delete(indexKey); err != nil { + return err + } } newKeys, err := difference(newSecIdxKeys, oldSecIdxKeys) if err != nil { @@ -138,13 +142,15 @@ func uniqueKeysAddFunc(store storetypes.KVStore, secondaryIndexKey interface{}, return err } - store.Set(indexKey, []byte{}) - return nil + return store.Set(indexKey, []byte{}) } // checkUniqueIndexKey checks that the given secondary index key is unique func checkUniqueIndexKey(store storetypes.KVStore, secondaryIndexKeyBytes []byte) error { - it := store.Iterator(PrefixRange(secondaryIndexKeyBytes)) + it, err := store.Iterator(PrefixRange(secondaryIndexKeyBytes)) + if err != nil { + return err + } defer it.Close() if it.Valid() { return errors.ErrORMUniqueConstraint @@ -170,8 +176,7 @@ func multiKeyAddFunc(store storetypes.KVStore, secondaryIndexKey interface{}, ro return errorsmod.Wrap(errors.ErrORMInvalidArgument, "empty index key") } - store.Set(encodedKey, []byte{}) - return nil + return store.Set(encodedKey, []byte{}) } // difference returns the list of elements that are in a but not in b. diff --git a/x/group/internal/orm/indexer_test.go b/x/group/internal/orm/indexer_test.go index ae86711fcc24..d043f95c453d 100644 --- a/x/group/internal/orm/indexer_test.go +++ b/x/group/internal/orm/indexer_test.go @@ -8,10 +8,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + corestore "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" + "cosmossdk.io/x/group/internal/orm/prefixstore" + + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" ) func TestNewIndexer(t *testing.T) { @@ -163,9 +167,9 @@ func TestIndexerOnDelete(t *testing.T) { myRowID := EncodeSequence(1) var multiKeyIndex MultiKeyIndex - ctx := NewMockContext() - storeKey := storetypes.NewKVStoreKey("test") - store := prefix.NewStore(ctx.KVStore(storeKey), []byte{multiKeyIndex.prefix}) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := prefixstore.New(runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx), []byte{multiKeyIndex.prefix}) specs := map[string]struct { srcFunc IndexerFunc @@ -224,7 +228,9 @@ func TestIndexerOnDelete(t *testing.T) { err = idx.OnCreate(store, myRowID, nil) require.NoError(t, err) for _, key := range spec.expDeletedKeys { - require.Equal(t, true, store.Has(key)) + has, err := store.Has(key) + require.NoError(t, err) + require.True(t, has) } } @@ -235,7 +241,9 @@ func TestIndexerOnDelete(t *testing.T) { } require.NoError(t, err) for _, key := range spec.expDeletedKeys { - require.Equal(t, false, store.Has(key)) + has, err := store.Has(key) + require.NoError(t, err) + require.False(t, has) } }) } @@ -245,16 +253,16 @@ func TestIndexerOnUpdate(t *testing.T) { myRowID := EncodeSequence(1) var multiKeyIndex MultiKeyIndex - ctx := NewMockContext() - storeKey := storetypes.NewKVStoreKey("test") - store := prefix.NewStore(ctx.KVStore(storeKey), []byte{multiKeyIndex.prefix}) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := prefixstore.New(runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx), []byte{multiKeyIndex.prefix}) specs := map[string]struct { srcFunc IndexerFunc expAddedKeys []RowID expDeletedKeys []RowID expErr error - addFunc func(storetypes.KVStore, interface{}, RowID) error + addFunc func(corestore.KVStore, interface{}, RowID) error }{ "single key - same key, no update": { srcFunc: func(value interface{}) ([]interface{}, error) { @@ -334,7 +342,7 @@ func TestIndexerOnUpdate(t *testing.T) { keys := []uint64{1, 2} return []interface{}{keys[value.(int)]}, nil }, - addFunc: func(_ storetypes.KVStore, _ interface{}, _ RowID) error { + addFunc: func(_ corestore.KVStore, _ interface{}, _ RowID) error { return stdErrors.New("test") }, expErr: stdErrors.New("test"), @@ -360,10 +368,14 @@ func TestIndexerOnUpdate(t *testing.T) { } require.NoError(t, err) for _, key := range spec.expAddedKeys { - require.Equal(t, true, store.Has(key)) + has, err := store.Has(key) + assert.NoError(t, err) + assert.True(t, has) } for _, key := range spec.expDeletedKeys { - require.Equal(t, false, store.Has(key)) + has, err := store.Has(key) + assert.NoError(t, err) + assert.False(t, has) } }) } @@ -398,16 +410,20 @@ func TestUniqueKeyAddFunc(t *testing.T) { } for msg, spec := range specs { t.Run(msg, func(t *testing.T) { - storeKey := storetypes.NewKVStoreKey("test") - store := NewMockContext().KVStore(storeKey) - store.Set(presetKey, []byte{}) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) + require.NoError(t, store.Set(presetKey, []byte{})) err := uniqueKeysAddFunc(store, spec.srcKey, myRowID) require.True(t, spec.expErr.Is(err)) if spec.expErr != nil { return } - assert.True(t, store.Has(spec.expExistingEntry), "not found") + + has, err := store.Has(spec.expExistingEntry) + assert.NoError(t, err) + assert.True(t, has, "not found") }) } } @@ -441,16 +457,20 @@ func TestMultiKeyAddFunc(t *testing.T) { } for msg, spec := range specs { t.Run(msg, func(t *testing.T) { - storeKey := storetypes.NewKVStoreKey("test") - store := NewMockContext().KVStore(storeKey) - store.Set(presetKey, []byte{}) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) + require.NoError(t, store.Set(presetKey, []byte{})) err := multiKeyAddFunc(store, spec.srcKey, myRowID) require.True(t, spec.expErr.Is(err)) if spec.expErr != nil { return } - assert.True(t, store.Has(spec.expExistingEntry)) + + has, err := store.Has(spec.expExistingEntry) + assert.NoError(t, err) + assert.True(t, has) }) } } @@ -562,7 +582,7 @@ type addFuncRecorder struct { called bool } -func (c *addFuncRecorder) add(_ storetypes.KVStore, key interface{}, rowID RowID) error { +func (c *addFuncRecorder) add(_ corestore.KVStore, key interface{}, rowID RowID) error { c.secondaryIndexKeys = append(c.secondaryIndexKeys, key) c.rowIDs = append(c.rowIDs, rowID) c.called = true diff --git a/x/group/internal/orm/iterator_test.go b/x/group/internal/orm/iterator_test.go index dcb892143a86..af9d78733278 100644 --- a/x/group/internal/orm/iterator_test.go +++ b/x/group/internal/orm/iterator_test.go @@ -13,6 +13,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" @@ -209,8 +211,9 @@ func TestPaginate(t *testing.T) { }, testdata.TableModel{}.Metadata) require.NoError(t, err) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) metadata := []byte("metadata") t1 := testdata.TableModel{ diff --git a/x/group/internal/orm/orm_scenario_test.go b/x/group/internal/orm/orm_scenario_test.go index 3505b11c9ece..30c656a5699a 100644 --- a/x/group/internal/orm/orm_scenario_test.go +++ b/x/group/internal/orm/orm_scenario_test.go @@ -9,11 +9,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + corestore "cosmossdk.io/core/store" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" ) @@ -24,8 +27,9 @@ func TestKeeperEndToEndWithAutoUInt64Table(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) k := NewTestKeeper(cdc) @@ -102,8 +106,9 @@ func TestKeeperEndToEndWithPrimaryKeyTable(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) k := NewTestKeeper(cdc) @@ -188,8 +193,9 @@ func TestGasCostsPrimaryKeyTable(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) k := NewTestKeeper(cdc) @@ -203,82 +209,81 @@ func TestGasCostsPrimaryKeyTable(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(1), rowID) - gCtx := NewGasCountingMockContext() - err = k.primaryKeyTable.Create(gCtx.KVStore(store), &tm) + err = k.primaryKeyTable.Create(store, &tm) require.NoError(t, err) - t.Logf("gas consumed on create: %d", gCtx.GasConsumed()) + t.Logf("gas consumed on create: %d", testCtx.Ctx.GasMeter().GasConsumed()) // get by primary key - gCtx.ResetGasMeter() + testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) var loaded testdata.TableModel - err = k.primaryKeyTable.GetOne(gCtx.KVStore(store), PrimaryKey(&tm), &loaded) + err = k.primaryKeyTable.GetOne(store, PrimaryKey(&tm), &loaded) require.NoError(t, err) - t.Logf("gas consumed on get by primary key: %d", gCtx.GasConsumed()) + t.Logf("gas consumed on get by primary key: %d", testCtx.Ctx.GasMeter().GasConsumed()) // get by secondary index - gCtx.ResetGasMeter() + testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) // and when loaded from MultiKeyIndex - it, err := k.primaryKeyTableModelByNumberIndex.Get(gCtx.KVStore(store), tm.Number) + it, err := k.primaryKeyTableModelByNumberIndex.Get(store, tm.Number) require.NoError(t, err) var loadedSlice []testdata.TableModel _, err = ReadAll(it, &loadedSlice) require.NoError(t, err) - t.Logf("gas consumed on get by multi index key: %d", gCtx.GasConsumed()) + t.Logf("gas consumed on get by multi index key: %d", testCtx.Ctx.GasMeter().GasConsumed()) // delete - gCtx.ResetGasMeter() - err = k.primaryKeyTable.Delete(gCtx.KVStore(store), &tm) + testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) + err = k.primaryKeyTable.Delete(store, &tm) require.NoError(t, err) - t.Logf("gas consumed on delete by primary key: %d", gCtx.GasConsumed()) + t.Logf("gas consumed on delete by primary key: %d", testCtx.Ctx.GasMeter().GasConsumed()) // with 3 elements var tms []testdata.TableModel for i := 1; i < 4; i++ { - gCtx.ResetGasMeter() + testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) tm := testdata.TableModel{ Id: uint64(i), Name: fmt.Sprintf("name%d", i), Number: 123, Metadata: []byte("metadata"), } - err = k.primaryKeyTable.Create(gCtx.KVStore(store), &tm) + err = k.primaryKeyTable.Create(store, &tm) require.NoError(t, err) - t.Logf("%d: gas consumed on create: %d", i, gCtx.GasConsumed()) + t.Logf("%d: gas consumed on create: %d", i, testCtx.Ctx.GasMeter().GasConsumed()) tms = append(tms, tm) } for i := 1; i < 4; i++ { - gCtx.ResetGasMeter() + testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) tm := testdata.TableModel{ Id: uint64(i), Name: fmt.Sprintf("name%d", i), Number: 123, Metadata: []byte("metadata"), } - err = k.primaryKeyTable.GetOne(gCtx.KVStore(store), PrimaryKey(&tm), &loaded) + err = k.primaryKeyTable.GetOne(store, PrimaryKey(&tm), &loaded) require.NoError(t, err) - t.Logf("%d: gas consumed on get by primary key: %d", i, gCtx.GasConsumed()) + t.Logf("%d: gas consumed on get by primary key: %d", i, testCtx.Ctx.GasMeter().GasConsumed()) } // get by secondary index - gCtx.ResetGasMeter() + testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) // and when loaded from MultiKeyIndex - it, err = k.primaryKeyTableModelByNumberIndex.Get(gCtx.KVStore(store), tm.Number) + it, err = k.primaryKeyTableModelByNumberIndex.Get(store, tm.Number) require.NoError(t, err) _, err = ReadAll(it, &loadedSlice) require.NoError(t, err) require.Len(t, loadedSlice, 3) - t.Logf("gas consumed on get by multi index key: %d", gCtx.GasConsumed()) + t.Logf("gas consumed on get by multi index key: %d", testCtx.Ctx.GasMeter().GasConsumed()) // delete for i, m := range tms { - gCtx.ResetGasMeter() + testCtx.Ctx = testCtx.Ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) m := m - err = k.primaryKeyTable.Delete(gCtx.KVStore(store), &m) + err = k.primaryKeyTable.Delete(store, &m) require.NoError(t, err) - t.Logf("%d: gas consumed on delete: %d", i, gCtx.GasConsumed()) + t.Logf("%d: gas consumed on delete: %d", i, testCtx.Ctx.GasMeter().GasConsumed()) } } @@ -286,8 +291,9 @@ func TestExportImportStateAutoUInt64Table(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) k := NewTestKeeper(cdc) @@ -309,8 +315,8 @@ func TestExportImportStateAutoUInt64Table(t *testing.T) { require.Equal(t, seqVal, uint64(testRecordsNum)) // when a new db seeded - ctx = NewMockContext() - store = ctx.KVStore(storetypes.NewKVStoreKey("test")) + testCtx = testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store = runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) err = k.autoUInt64Table.Import(store, tms, seqVal) require.NoError(t, err) @@ -347,8 +353,9 @@ func TestExportImportStatePrimaryKeyTable(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) k := NewTestKeeper(cdc) @@ -371,8 +378,8 @@ func TestExportImportStatePrimaryKeyTable(t *testing.T) { require.NoError(t, err) // when a new db seeded - ctx = NewMockContext() - store = ctx.KVStore(storetypes.NewKVStoreKey("test")) + testCtx = testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store = runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) err = k.primaryKeyTable.Import(store, tms, 0) require.NoError(t, err) @@ -396,7 +403,7 @@ func TestExportImportStatePrimaryKeyTable(t *testing.T) { } } -func assertIndex(t *testing.T, store storetypes.KVStore, index Index, v testdata.TableModel, searchKey interface{}) { +func assertIndex(t *testing.T, store corestore.KVStore, index Index, v testdata.TableModel, searchKey interface{}) { t.Helper() it, err := index.Get(store, searchKey) require.NoError(t, err) diff --git a/x/group/internal/orm/prefixstore/prefixstore.go b/x/group/internal/orm/prefixstore/prefixstore.go new file mode 100644 index 000000000000..5ac697756260 --- /dev/null +++ b/x/group/internal/orm/prefixstore/prefixstore.go @@ -0,0 +1,223 @@ +// Package prefixstore provides a store that prefixes all keys with a given +// prefix. +// Implementation taken from cosmossdk.io/store/prefix, and adapted to +// the cosmossdk.io/core/store.KVStore interface. +package prefixstore + +import ( + "bytes" + "errors" + + "cosmossdk.io/core/store" +) + +// New creates a new prefix store using the provided bytes prefix. +func New(store store.KVStore, prefix []byte) store.KVStore { + return Store{ + parent: store, + prefix: prefix, + } +} + +var _ store.KVStore = Store{} + +// Store is similar with cometbft/cometbft/libs/db/prefix_db +// both gives access only to the limited subset of the store +// for convenience or safety +type Store struct { + parent store.KVStore + prefix []byte +} + +func cloneAppend(bz, tail []byte) (res []byte) { + res = make([]byte, len(bz)+len(tail)) + copy(res, bz) + copy(res[len(bz):], tail) + return +} + +func (s Store) key(key []byte) (res []byte) { + if key == nil { + panic("nil key on Store") + } + res = cloneAppend(s.prefix, key) + return +} + +// Implements KVStore +func (s Store) Get(key []byte) ([]byte, error) { + return s.parent.Get(s.key(key)) +} + +// Implements KVStore +func (s Store) Has(key []byte) (bool, error) { + return s.parent.Has(s.key(key)) +} + +// Implements KVStore +func (s Store) Set(key, value []byte) error { + return s.parent.Set(s.key(key), value) +} + +// Implements KVStore +func (s Store) Delete(key []byte) error { return s.parent.Delete(s.key(key)) } + +// Implements KVStore +// Check https://github.com/cometbft/cometbft/blob/master/libs/db/prefix_db.go#L106 +func (s Store) Iterator(start, end []byte) (store.Iterator, error) { + newstart := cloneAppend(s.prefix, start) + + var newend []byte + if end == nil { + newend = cpIncr(s.prefix) + } else { + newend = cloneAppend(s.prefix, end) + } + + iter, err := s.parent.Iterator(newstart, newend) + if err != nil { + return nil, err + } + + return newPrefixIterator(s.prefix, start, end, iter), nil +} + +// ReverseIterator implements KVStore +// Check https://github.com/cometbft/cometbft/blob/master/libs/db/prefix_db.go#L129 +func (s Store) ReverseIterator(start, end []byte) (store.Iterator, error) { + newstart := cloneAppend(s.prefix, start) + + var newend []byte + if end == nil { + newend = cpIncr(s.prefix) + } else { + newend = cloneAppend(s.prefix, end) + } + + iter, err := s.parent.ReverseIterator(newstart, newend) + if err != nil { + return nil, err + } + + return newPrefixIterator(s.prefix, start, end, iter), nil +} + +var _ store.Iterator = (*prefixIterator)(nil) + +type prefixIterator struct { + prefix []byte + start []byte + end []byte + iter store.Iterator + valid bool +} + +func newPrefixIterator(prefix, start, end []byte, parent store.Iterator) *prefixIterator { + return &prefixIterator{ + prefix: prefix, + start: start, + end: end, + iter: parent, + valid: parent.Valid() && bytes.HasPrefix(parent.Key(), prefix), + } +} + +// Implements Iterator +func (pi *prefixIterator) Domain() ([]byte, []byte) { + return pi.start, pi.end +} + +// Implements Iterator +func (pi *prefixIterator) Valid() bool { + return pi.valid && pi.iter.Valid() +} + +// Implements Iterator +func (pi *prefixIterator) Next() { + if !pi.valid { + panic("prefixIterator invalid, cannot call Next()") + } + + if pi.iter.Next(); !pi.iter.Valid() || !bytes.HasPrefix(pi.iter.Key(), pi.prefix) { + // TODO: shouldn't pi be set to nil instead? + pi.valid = false + } +} + +// Implements Iterator +func (pi *prefixIterator) Key() (key []byte) { + if !pi.valid { + panic("prefixIterator invalid, cannot call Key()") + } + + key = pi.iter.Key() + key = stripPrefix(key, pi.prefix) + + return +} + +// Implements Iterator +func (pi *prefixIterator) Value() []byte { + if !pi.valid { + panic("prefixIterator invalid, cannot call Value()") + } + + return pi.iter.Value() +} + +// Implements Iterator +func (pi *prefixIterator) Close() error { + return pi.iter.Close() +} + +// Error returns an error if the prefixIterator is invalid defined by the Valid +// method. +func (pi *prefixIterator) Error() error { + if !pi.Valid() { + return errors.New("invalid prefixIterator") + } + + return nil +} + +// copied from github.com/cometbft/cometbft/libs/db/prefix_db.go +func stripPrefix(key, prefix []byte) []byte { + if len(key) < len(prefix) || !bytes.Equal(key[:len(prefix)], prefix) { + panic("should not happen") + } + + return key[len(prefix):] +} + +// wrapping types.PrefixEndBytes +func cpIncr(bz []byte) []byte { + return prefixEndBytes(bz) +} + +// prefixEndBytes returns the []byte that would end a +// range query for all []byte with a certain prefix +// Deals with last byte of prefix being FF without overflowing +func prefixEndBytes(prefix []byte) []byte { + if len(prefix) == 0 { + return nil + } + + end := make([]byte, len(prefix)) + copy(end, prefix) + + for { + if end[len(end)-1] != byte(255) { + end[len(end)-1]++ + break + } + + end = end[:len(end)-1] + + if len(end) == 0 { + end = nil + break + } + } + + return end +} diff --git a/x/group/internal/orm/primary_key.go b/x/group/internal/orm/primary_key.go index 5bf6a2b83995..c4216a8b59cd 100644 --- a/x/group/internal/orm/primary_key.go +++ b/x/group/internal/orm/primary_key.go @@ -3,7 +3,7 @@ package orm import ( "github.com/cosmos/gogoproto/proto" - storetypes "cosmossdk.io/store/types" + storetypes "cosmossdk.io/core/store" "github.com/cosmos/cosmos-sdk/codec" ) diff --git a/x/group/internal/orm/primary_key_property_test.go b/x/group/internal/orm/primary_key_property_test.go index 2cdc39b2b4ce..e69177e60406 100644 --- a/x/group/internal/orm/primary_key_property_test.go +++ b/x/group/internal/orm/primary_key_property_test.go @@ -10,145 +10,146 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" ) func TestPrimaryKeyTable(t *testing.T) { - rapid.Check(t, testPrimaryKeyMachine) -} + rapid.Check(t, func(rt *rapid.T) { + // Init creates a new instance of the state machine model by building the real + // table and making the empty model map + // Create context + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) + + // Create primary key table + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + table, err := NewPrimaryKeyTable( + [2]byte{0x1}, + &testdata.TableModel{}, + cdc, + ) + require.NoError(t, err) + + // Create model state + state := make(map[string]*testdata.TableModel) + + rt.Repeat(map[string]func(*rapid.T){ + // Create is one of the model commands. It adds an object to the table, creating + // an error if it already exists. + "Create": func(t *rapid.T) { + g := genTableModel.Draw(t, "g") + pk := string(PrimaryKey(g)) + + t.Logf("pk: %v", pk) + t.Logf("state: %v", state) + + err := table.Create(store, g) + + if state[pk] != nil { + require.Error(t, err) + } else { + require.NoError(t, err) + state[pk] = g + } + }, + + // Update is one of the model commands. It updates the value at a given primary + // key and fails if that primary key doesn't already exist in the table. + "Update": func(t *rapid.T) { + tm := generateTableModel(state).Draw(t, "tm") + + newName := rapid.StringN(1, 100, 150).Draw(t, "newName") + tm.Name = newName + + // Perform the real Update + err := table.Update(store, tm) + + if state[string(PrimaryKey(tm))] == nil { + // If there's no value in the model, we expect an error + require.Error(t, err) + } else { + // If we have a value in the model, expect no error + require.NoError(t, err) + + // Update the model with the new value + state[string(PrimaryKey(tm))] = tm + } + }, + + // Set is one of the model commands. It sets the value at a key in the table + // whether it exists or not. + "Set": func(t *rapid.T) { + g := genTableModel.Draw(t, "g") + pk := string(PrimaryKey(g)) + + err := table.Set(store, g) -func testPrimaryKeyMachine(t *rapid.T) { - // Init creates a new instance of the state machine model by building the real - // table and making the empty model map - // Create context - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) - - // Create primary key table - interfaceRegistry := types.NewInterfaceRegistry() - cdc := codec.NewProtoCodec(interfaceRegistry) - table, err := NewPrimaryKeyTable( - [2]byte{0x1}, - &testdata.TableModel{}, - cdc, - ) - require.NoError(t, err) - - // Create model state - state := make(map[string]*testdata.TableModel) - - t.Repeat(map[string]func(*rapid.T){ - // Create is one of the model commands. It adds an object to the table, creating - // an error if it already exists. - "Create": func(t *rapid.T) { - g := genTableModel.Draw(t, "g") - pk := string(PrimaryKey(g)) - - t.Logf("pk: %v", pk) - t.Logf("state: %v", state) - - err := table.Create(store, g) - - if state[pk] != nil { - require.Error(t, err) - } else { require.NoError(t, err) state[pk] = g - } - }, - - // Update is one of the model commands. It updates the value at a given primary - // key and fails if that primary key doesn't already exist in the table. - "Update": func(t *rapid.T) { - tm := generateTableModel(state).Draw(t, "tm") - - newName := rapid.StringN(1, 100, 150).Draw(t, "newName") - tm.Name = newName - - // Perform the real Update - err := table.Update(store, tm) - - if state[string(PrimaryKey(tm))] == nil { - // If there's no value in the model, we expect an error - require.Error(t, err) - } else { - // If we have a value in the model, expect no error - require.NoError(t, err) - - // Update the model with the new value - state[string(PrimaryKey(tm))] = tm - } - }, - - // Set is one of the model commands. It sets the value at a key in the table - // whether it exists or not. - "Set": func(t *rapid.T) { - g := genTableModel.Draw(t, "g") - pk := string(PrimaryKey(g)) - - err := table.Set(store, g) - - require.NoError(t, err) - state[pk] = g - }, - - // Delete is one of the model commands. It removes the object with the given - // primary key from the table and returns an error if that primary key doesn't - // already exist in the table. - "Delete": func(t *rapid.T) { - tm := generateTableModel(state).Draw(t, "tm") - - // Perform the real Delete - err := table.Delete(store, tm) - - if state[string(PrimaryKey(tm))] == nil { - // If there's no value in the model, we expect an error - require.Error(t, err) - } else { - // If we have a value in the model, expect no error - require.NoError(t, err) - - // Delete the value from the model - delete(state, string(PrimaryKey(tm))) - } - }, - - // Has is one of the model commands. It checks whether a key already exists in - // the table. - "Has": func(t *rapid.T) { - pk := PrimaryKey(generateTableModel(state).Draw(t, "g")) - - realHas := table.Has(store, pk) - modelHas := state[string(pk)] != nil - - require.Equal(t, realHas, modelHas) - }, - - // GetOne is one of the model commands. It fetches an object from the table by - // its primary key and returns an error if that primary key isn't in the table. - "GetOne": func(t *rapid.T) { - pk := PrimaryKey(generateTableModel(state).Draw(t, "tm")) - - var tm testdata.TableModel - - err := table.GetOne(store, pk, &tm) - t.Logf("tm: %v", tm) - - if state[string(pk)] == nil { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, *state[string(pk)], tm) - } - }, - - // Check that the real values match the state values. - "": func(t *rapid.T) { - for i := range state { - has := table.Has(store, []byte(i)) - require.Equal(t, true, has) - } - }, + }, + + // Delete is one of the model commands. It removes the object with the given + // primary key from the table and returns an error if that primary key doesn't + // already exist in the table. + "Delete": func(t *rapid.T) { + tm := generateTableModel(state).Draw(t, "tm") + + // Perform the real Delete + err := table.Delete(store, tm) + + if state[string(PrimaryKey(tm))] == nil { + // If there's no value in the model, we expect an error + require.Error(t, err) + } else { + // If we have a value in the model, expect no error + require.NoError(t, err) + + // Delete the value from the model + delete(state, string(PrimaryKey(tm))) + } + }, + + // Has is one of the model commands. It checks whether a key already exists in + // the table. + "Has": func(t *rapid.T) { + pk := PrimaryKey(generateTableModel(state).Draw(t, "g")) + + realHas := table.Has(store, pk) + modelHas := state[string(pk)] != nil + + require.Equal(t, realHas, modelHas) + }, + + // GetOne is one of the model commands. It fetches an object from the table by + // its primary key and returns an error if that primary key isn't in the table. + "GetOne": func(t *rapid.T) { + pk := PrimaryKey(generateTableModel(state).Draw(t, "tm")) + + var tm testdata.TableModel + + err := table.GetOne(store, pk, &tm) + t.Logf("tm: %v", tm) + + if state[string(pk)] == nil { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, *state[string(pk)], tm) + } + }, + + // Check that the real values match the state values. + "": func(t *rapid.T) { + for i := range state { + has := table.Has(store, []byte(i)) + require.Equal(t, true, has) + } + }, + }) }) } diff --git a/x/group/internal/orm/primary_key_test.go b/x/group/internal/orm/primary_key_test.go index e8cb94602e83..87b296b15b89 100644 --- a/x/group/internal/orm/primary_key_test.go +++ b/x/group/internal/orm/primary_key_test.go @@ -6,12 +6,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + corestore "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" ) @@ -22,8 +25,9 @@ func TestPrimaryKeyTablePrefixScan(t *testing.T) { tb, err := NewPrimaryKeyTable(PrimaryKeyTablePrefix, &testdata.TableModel{}, cdc) require.NoError(t, err) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) metadata := []byte("metadata") t1 := testdata.TableModel{ @@ -51,7 +55,7 @@ func TestPrimaryKeyTablePrefixScan(t *testing.T) { expResult []testdata.TableModel expRowIDs []RowID expError *errorsmod.Error - method func(store storetypes.KVStore, start, end []byte) (Iterator, error) + method func(store corestore.KVStore, start, end []byte) (Iterator, error) }{ "exact match with a single result": { start: EncodeSequence(1), // == PrimaryKey(&t1) @@ -208,8 +212,9 @@ func TestContains(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) tb, err := NewPrimaryKeyTable(PrimaryKeyTablePrefix, &testdata.TableModel{}, cdc) require.NoError(t, err) diff --git a/x/group/internal/orm/sequence.go b/x/group/internal/orm/sequence.go index 44925423ffb7..361f2e460aee 100644 --- a/x/group/internal/orm/sequence.go +++ b/x/group/internal/orm/sequence.go @@ -3,10 +3,10 @@ package orm import ( "encoding/binary" + storetypes "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" - storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" + "cosmossdk.io/x/group/internal/orm/prefixstore" ) // sequenceStorageKey is a fix key to read/ write data on the storage layer @@ -25,25 +25,37 @@ func NewSequence(prefix byte) Sequence { // NextVal increments and persists the counter by one and returns the value. func (s Sequence) NextVal(store storetypes.KVStore) uint64 { - pStore := prefix.NewStore(store, []byte{s.prefix}) - v := pStore.Get(sequenceStorageKey) + pStore := prefixstore.New(store, []byte{s.prefix}) + v, err := pStore.Get(sequenceStorageKey) + if err != nil { + panic(err) + } seq := DecodeSequence(v) seq++ - pStore.Set(sequenceStorageKey, EncodeSequence(seq)) + err = pStore.Set(sequenceStorageKey, EncodeSequence(seq)) + if err != nil { + panic(err) + } return seq } // CurVal returns the last value used. 0 if none. func (s Sequence) CurVal(store storetypes.KVStore) uint64 { - pStore := prefix.NewStore(store, []byte{s.prefix}) - v := pStore.Get(sequenceStorageKey) + pStore := prefixstore.New(store, []byte{s.prefix}) + v, err := pStore.Get(sequenceStorageKey) + if err != nil { + panic(err) + } return DecodeSequence(v) } // PeekNextVal returns the CurVal + increment step. Not persistent. func (s Sequence) PeekNextVal(store storetypes.KVStore) uint64 { - pStore := prefix.NewStore(store, []byte{s.prefix}) - v := pStore.Get(sequenceStorageKey) + pStore := prefixstore.New(store, []byte{s.prefix}) + v, err := pStore.Get(sequenceStorageKey) + if err != nil { + panic(err) + } return DecodeSequence(v) + 1 } @@ -54,12 +66,16 @@ func (s Sequence) PeekNextVal(store storetypes.KVStore) uint64 { // It is recommended to call this method only for a sequence start value other than `1` as the // method consumes unnecessary gas otherwise. A scenario would be an import from genesis. func (s Sequence) InitVal(store storetypes.KVStore, seq uint64) error { - pStore := prefix.NewStore(store, []byte{s.prefix}) - if pStore.Has(sequenceStorageKey) { + pStore := prefixstore.New(store, []byte{s.prefix}) + has, err := pStore.Has(sequenceStorageKey) + if err != nil { + return err + } + + if has { return errorsmod.Wrap(errors.ErrORMUniqueConstraint, "already initialized") } - pStore.Set(sequenceStorageKey, EncodeSequence(seq)) - return nil + return pStore.Set(sequenceStorageKey, EncodeSequence(seq)) } // DecodeSequence converts the binary representation into an Uint64 value. diff --git a/x/group/internal/orm/sequence_property_test.go b/x/group/internal/orm/sequence_property_test.go index 87aa0a65dbfb..6a7814155d69 100644 --- a/x/group/internal/orm/sequence_property_test.go +++ b/x/group/internal/orm/sequence_property_test.go @@ -7,49 +7,51 @@ import ( "pgregory.net/rapid" storetypes "cosmossdk.io/store/types" + + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" ) func TestSequence(t *testing.T) { - rapid.Check(t, testSequenceMachine) -} - -func testSequenceMachine(t *rapid.T) { - // Init sets up the real Sequence, including choosing a random initial value, - // and initializes the model state - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) - - // Create primary key table - seq := NewSequence(0x1) - - // Choose initial sequence value - initSeqVal := rapid.Uint64().Draw(t, "initSeqVal") - err := seq.InitVal(store, initSeqVal) - require.NoError(t, err) - - // Create model state - state := initSeqVal - - t.Repeat(map[string]func(*rapid.T){ - // NextVal is one of the model commands. It checks that the next value of the - // sequence matches the model and increments the model state. - "NextVal": func(t *rapid.T) { - // Check that the next value in the sequence matches the model - require.Equal(t, state+1, seq.NextVal(store)) - // Increment the model state - state++ - }, - // CurVal is one of the model commands. It checks that the current value of the - // sequence matches the model. - "CurVal": func(t *rapid.T) { - // Check the current value matches the model - require.Equal(t, state, seq.CurVal(store)) - }, - // PeekNextVal is one of the model commands. It checks that the next value of - // the sequence matches the model without modifying the state. - "PeekNextVal": func(t *rapid.T) { - // Check that the next value in the sequence matches the model - require.Equal(t, state+1, seq.PeekNextVal(store)) - }, + rapid.Check(t, func(rt *rapid.T) { + // Init sets up the real Sequence, including choosing a random initial value, + // and initializes the model state + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) + + // Create primary key table + seq := NewSequence(0x1) + + // Choose initial sequence value + initSeqVal := rapid.Uint64().Draw(rt, "initSeqVal") + err := seq.InitVal(store, initSeqVal) + require.NoError(t, err) + + // Create model state + state := initSeqVal + + rt.Repeat(map[string]func(*rapid.T){ + // NextVal is one of the model commands. It checks that the next value of the + // sequence matches the model and increments the model state. + "NextVal": func(t *rapid.T) { + // Check that the next value in the sequence matches the model + require.Equal(t, state+1, seq.NextVal(store)) + // Increment the model state + state++ + }, + // CurVal is one of the model commands. It checks that the current value of the + // sequence matches the model. + "CurVal": func(t *rapid.T) { + // Check the current value matches the model + require.Equal(t, state, seq.CurVal(store)) + }, + // PeekNextVal is one of the model commands. It checks that the next value of + // the sequence matches the model without modifying the state. + "PeekNextVal": func(t *rapid.T) { + // Check that the next value in the sequence matches the model + require.Equal(t, state+1, seq.PeekNextVal(store)) + }, + }) }) } diff --git a/x/group/internal/orm/sequence_test.go b/x/group/internal/orm/sequence_test.go index 5ad6223c29bf..cb0e77bafe9d 100644 --- a/x/group/internal/orm/sequence_test.go +++ b/x/group/internal/orm/sequence_test.go @@ -8,11 +8,15 @@ import ( storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" + + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" ) func TestSequenceUniqueConstraint(t *testing.T) { - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) seq := NewSequence(0x1) err := seq.InitVal(store, 2) @@ -22,8 +26,9 @@ func TestSequenceUniqueConstraint(t *testing.T) { } func TestSequenceIncrements(t *testing.T) { - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) seq := NewSequence(0x1) var i uint64 diff --git a/x/group/internal/orm/table.go b/x/group/internal/orm/table.go index 34de1c3a295a..82b93458cd9e 100644 --- a/x/group/internal/orm/table.go +++ b/x/group/internal/orm/table.go @@ -6,10 +6,11 @@ import ( "github.com/cosmos/gogoproto/proto" + storetypes "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" + "cosmossdk.io/x/group/internal/orm/prefixstore" "github.com/cosmos/cosmos-sdk/codec" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -74,7 +75,7 @@ func (a *table) AddAfterDeleteInterceptor(interceptor AfterDeleteInterceptor) { // // Create iterates through the registered callbacks that may add secondary index // keys. -func (a table) Create(store types.KVStore, rowID RowID, obj proto.Message) error { +func (a table) Create(store storetypes.KVStore, rowID RowID, obj proto.Message) error { if a.Has(store, rowID) { return errors.ErrORMUniqueConstraint } @@ -88,7 +89,7 @@ func (a table) Create(store types.KVStore, rowID RowID, obj proto.Message) error // nil. // // Update triggers all "after set" hooks that may add or remove secondary index keys. -func (a table) Update(store types.KVStore, rowID RowID, newValue proto.Message) error { +func (a table) Update(store storetypes.KVStore, rowID RowID, newValue proto.Message) error { if !a.Has(store, rowID) { return sdkerrors.ErrNotFound } @@ -101,7 +102,7 @@ func (a table) Update(store types.KVStore, rowID RowID, newValue proto.Message) // // Set iterates through the registered callbacks that may add secondary index // keys. -func (a table) Set(store types.KVStore, rowID RowID, newValue proto.Message) error { +func (a table) Set(store storetypes.KVStore, rowID RowID, newValue proto.Message) error { if len(rowID) == 0 { return errors.ErrORMEmptyKey } @@ -127,8 +128,11 @@ func (a table) Set(store types.KVStore, rowID RowID, newValue proto.Message) err return errorsmod.Wrapf(err, "failed to serialize %T", newValue) } - pStore := prefix.NewStore(store, a.prefix[:]) - pStore.Set(rowID, newValueEncoded) + pStore := prefixstore.New(store, a.prefix[:]) + err = pStore.Set(rowID, newValueEncoded) + if err != nil { + return err + } for i, itc := range a.afterSet { if err := itc(store, rowID, newValue, oldValue); err != nil { return errorsmod.Wrapf(err, "interceptor %d failed", i) @@ -152,14 +156,17 @@ func assertValid(obj proto.Message) error { // // Delete iterates through the registered callbacks that remove secondary index // keys. -func (a table) Delete(store types.KVStore, rowID RowID) error { +func (a table) Delete(store storetypes.KVStore, rowID RowID) error { oldValue := reflect.New(a.model).Interface().(proto.Message) if err := a.GetOne(store, rowID, oldValue); err != nil { return errorsmod.Wrap(err, "load old value") } - pStore := prefix.NewStore(store, a.prefix[:]) - pStore.Delete(rowID) + pStore := prefixstore.New(store, a.prefix[:]) + err := pStore.Delete(rowID) + if err != nil { + return err + } for i, itc := range a.afterDelete { if err := itc(store, rowID, oldValue); err != nil { @@ -171,18 +178,22 @@ func (a table) Delete(store types.KVStore, rowID RowID) error { // Has checks if a key exists. Returns false when the key is empty or nil // because we don't allow creation of values without a key. -func (a table) Has(store types.KVStore, key RowID) bool { +func (a table) Has(store storetypes.KVStore, key RowID) bool { if len(key) == 0 { return false } - pStore := prefix.NewStore(store, a.prefix[:]) - return pStore.Has(key) + pStore := prefixstore.New(store, a.prefix[:]) + has, err := pStore.Has(key) + if err != nil { + panic(err) + } + return has } // GetOne load the object persisted for the given RowID into the dest parameter. // If none exists or `rowID==nil` then `sdkerrors.ErrNotFound` is returned instead. // Parameters must not be nil - we don't allow creation of values with empty keys. -func (a table) GetOne(store types.KVStore, rowID RowID, dest proto.Message) error { +func (a table) GetOne(store storetypes.KVStore, rowID RowID, dest proto.Message) error { if len(rowID) == 0 { return sdkerrors.ErrNotFound } @@ -207,15 +218,21 @@ func (a table) GetOne(store types.KVStore, rowID RowID, dest proto.Message) erro // it = LimitIterator(it, defaultLimit) // // CONTRACT: No writes may happen within a domain while an iterator exists over it. -func (a table) PrefixScan(store types.KVStore, start, end RowID) (Iterator, error) { +func (a table) PrefixScan(store storetypes.KVStore, start, end RowID) (Iterator, error) { if start != nil && end != nil && bytes.Compare(start, end) >= 0 { return NewInvalidIterator(), errorsmod.Wrap(errors.ErrORMInvalidArgument, "start must be before end") } - pStore := prefix.NewStore(store, a.prefix[:]) + + pStore := prefixstore.New(store, a.prefix[:]) + it, err := pStore.Iterator(start, end) + if err != nil { + return nil, err + } + return &typeSafeIterator{ store: store, rowGetter: NewTypeSafeRowGetter(a.prefix, a.model, a.cdc), - it: pStore.Iterator(start, end), + it: it, }, nil } @@ -228,20 +245,26 @@ func (a table) PrefixScan(store types.KVStore, start, end RowID) (Iterator, erro // this as an endpoint to the public without further limits. See `LimitIterator` // // CONTRACT: No writes may happen within a domain while an iterator exists over it. -func (a table) ReversePrefixScan(store types.KVStore, start, end RowID) (Iterator, error) { +func (a table) ReversePrefixScan(store storetypes.KVStore, start, end RowID) (Iterator, error) { if start != nil && end != nil && bytes.Compare(start, end) >= 0 { return NewInvalidIterator(), errorsmod.Wrap(errors.ErrORMInvalidArgument, "start must be before end") } - pStore := prefix.NewStore(store, a.prefix[:]) + + pStore := prefixstore.New(store, a.prefix[:]) + it, err := pStore.ReverseIterator(start, end) + if err != nil { + return nil, err + } + return &typeSafeIterator{ store: store, rowGetter: NewTypeSafeRowGetter(a.prefix, a.model, a.cdc), - it: pStore.ReverseIterator(start, end), + it: it, }, nil } // Export stores all the values in the table in the passed ModelSlicePtr. -func (a table) Export(store types.KVStore, dest ModelSlicePtr) (uint64, error) { +func (a table) Export(store storetypes.KVStore, dest ModelSlicePtr) (uint64, error) { it, err := a.PrefixScan(store, nil, nil) if err != nil { return 0, errorsmod.Wrap(err, "table Export failure when exporting table data") @@ -255,7 +278,7 @@ func (a table) Export(store types.KVStore, dest ModelSlicePtr) (uint64, error) { // Import clears the table and initializes it from the given data interface{}. // data should be a slice of structs that implement PrimaryKeyed. -func (a table) Import(store types.KVStore, data interface{}, _ uint64) error { +func (a table) Import(store storetypes.KVStore, data interface{}, _ uint64) error { // Clear all data keys := a.keys(store) for _, key := range keys { @@ -285,9 +308,12 @@ func (a table) Import(store types.KVStore, data interface{}, _ uint64) error { return nil } -func (a table) keys(store types.KVStore) [][]byte { - pStore := prefix.NewStore(store, a.prefix[:]) - it := pStore.Iterator(nil, nil) +func (a table) keys(store storetypes.KVStore) [][]byte { + pStore := prefixstore.New(store, a.prefix[:]) + it, err := pStore.ReverseIterator(nil, nil) + if err != nil { + panic(err) + } defer it.Close() var keys [][]byte @@ -299,7 +325,7 @@ func (a table) keys(store types.KVStore) [][]byte { // typeSafeIterator is initialized with a type safe RowGetter only. type typeSafeIterator struct { - store types.KVStore + store storetypes.KVStore rowGetter RowGetter it types.Iterator } diff --git a/x/group/internal/orm/table_test.go b/x/group/internal/orm/table_test.go index 988cb72aa5bc..63aa78bcb329 100644 --- a/x/group/internal/orm/table_test.go +++ b/x/group/internal/orm/table_test.go @@ -14,6 +14,8 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -98,8 +100,9 @@ func TestCreate(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) anyPrefix := [2]byte{0x10} myTable, err := newTable(anyPrefix, &testdata.TableModel{}, cdc) @@ -155,8 +158,9 @@ func TestUpdate(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) anyPrefix := [2]byte{0x10} myTable, err := newTable(anyPrefix, &testdata.TableModel{}, cdc) @@ -204,8 +208,9 @@ func TestDelete(t *testing.T) { interfaceRegistry := types.NewInterfaceRegistry() cdc := codec.NewProtoCodec(interfaceRegistry) - ctx := NewMockContext() - store := ctx.KVStore(storetypes.NewKVStoreKey("test")) + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) + store := runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx) anyPrefix := [2]byte{0x10} myTable, err := newTable(anyPrefix, &testdata.TableModel{}, cdc) diff --git a/x/group/internal/orm/testsupport.go b/x/group/internal/orm/testsupport.go deleted file mode 100644 index b4fe3d0354ee..000000000000 --- a/x/group/internal/orm/testsupport.go +++ /dev/null @@ -1,104 +0,0 @@ -package orm - -import ( - "fmt" - - dbm "github.com/cosmos/cosmos-db" - - "cosmossdk.io/log" - "cosmossdk.io/store" - "cosmossdk.io/store/gaskv" - "cosmossdk.io/store/metrics" - storetypes "cosmossdk.io/store/types" -) - -type MockContext struct { - db *dbm.MemDB - store storetypes.CommitMultiStore -} - -func NewMockContext() *MockContext { - db := dbm.NewMemDB() - return &MockContext{ - db: dbm.NewMemDB(), - store: store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics()), - } -} - -func (m MockContext) KVStore(key storetypes.StoreKey) storetypes.KVStore { - if s := m.store.GetCommitKVStore(key); s != nil { - return s - } - m.store.MountStoreWithDB(key, storetypes.StoreTypeIAVL, m.db) - if err := m.store.LoadLatestVersion(); err != nil { - panic(err) - } - return m.store.GetCommitKVStore(key) -} - -type debuggingGasMeter struct { - g storetypes.GasMeter -} - -func (d debuggingGasMeter) GasConsumed() storetypes.Gas { - return d.g.GasConsumed() -} - -func (d debuggingGasMeter) GasRemaining() storetypes.Gas { - return d.g.GasRemaining() -} - -func (d debuggingGasMeter) GasConsumedToLimit() storetypes.Gas { - return d.g.GasConsumedToLimit() -} - -func (d debuggingGasMeter) RefundGas(amount uint64, descriptor string) { - d.g.RefundGas(amount, descriptor) -} - -func (d debuggingGasMeter) Limit() storetypes.Gas { - return d.g.Limit() -} - -func (d debuggingGasMeter) ConsumeGas(amount storetypes.Gas, descriptor string) { - fmt.Printf("++ Consuming gas: %q :%d\n", descriptor, amount) - d.g.ConsumeGas(amount, descriptor) -} - -func (d debuggingGasMeter) IsPastLimit() bool { - return d.g.IsPastLimit() -} - -func (d debuggingGasMeter) IsOutOfGas() bool { - return d.g.IsOutOfGas() -} - -func (d debuggingGasMeter) String() string { - return d.g.String() -} - -type GasCountingMockContext struct { - GasMeter storetypes.GasMeter -} - -func NewGasCountingMockContext() *GasCountingMockContext { - return &GasCountingMockContext{ - GasMeter: &debuggingGasMeter{storetypes.NewInfiniteGasMeter()}, - } -} - -func (g GasCountingMockContext) KVStore(store storetypes.KVStore) storetypes.KVStore { - return gaskv.NewStore(store, g.GasMeter, storetypes.KVGasConfig()) -} - -func (g GasCountingMockContext) GasConsumed() storetypes.Gas { - return g.GasMeter.GasConsumed() -} - -func (g GasCountingMockContext) GasRemaining() storetypes.Gas { - return g.GasMeter.GasRemaining() -} - -func (g *GasCountingMockContext) ResetGasMeter() { - g.GasMeter = storetypes.NewInfiniteGasMeter() -} diff --git a/x/group/internal/orm/types.go b/x/group/internal/orm/types.go index c5e82a02cf15..11d113cd68a9 100644 --- a/x/group/internal/orm/types.go +++ b/x/group/internal/orm/types.go @@ -9,10 +9,10 @@ import ( "github.com/cosmos/gogoproto/proto" + storetypes "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" - storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" + "cosmossdk.io/x/group/internal/orm/prefixstore" "github.com/cosmos/cosmos-sdk/codec" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -116,8 +116,12 @@ func NewTypeSafeRowGetter(prefixKey [2]byte, model reflect.Type, cdc codec.Codec return err } - pStore := prefix.NewStore(store, prefixKey[:]) - bz := pStore.Get(rowID) + pStore := prefixstore.New(store, prefixKey[:]) + bz, err := pStore.Get(rowID) + if err != nil { + return err + } + if len(bz) == 0 { return sdkerrors.ErrNotFound } diff --git a/x/group/internal/orm/types_test.go b/x/group/internal/orm/types_test.go index b0f313efd2db..d915c4ff36ab 100644 --- a/x/group/internal/orm/types_test.go +++ b/x/group/internal/orm/types_test.go @@ -8,28 +8,31 @@ import ( "github.com/stretchr/testify/require" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/store/prefix" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group/errors" + "cosmossdk.io/x/group/internal/orm/prefixstore" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) func TestTypeSafeRowGetter(t *testing.T) { - storeKey := storetypes.NewKVStoreKey("test") - ctx := NewMockContext() + key := storetypes.NewKVStoreKey("test") + testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) prefixKey := [2]byte{0x2} - store := prefix.NewStore(ctx.KVStore(storeKey), prefixKey[:]) + store := prefixstore.New(runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx), prefixKey[:]) + md := testdata.TableModel{ Id: 1, Name: "some name", } bz, err := md.Marshal() require.NoError(t, err) - store.Set(EncodeSequence(1), bz) + require.NoError(t, store.Set(EncodeSequence(1), bz)) specs := map[string]struct { srcRowID RowID @@ -70,7 +73,7 @@ func TestTypeSafeRowGetter(t *testing.T) { getter := NewTypeSafeRowGetter(prefixKey, spec.srcModelType, cdc) var loadedObj testdata.TableModel - err := getter(ctx.KVStore(storeKey), spec.srcRowID, &loadedObj) + err := getter(runtime.NewKVStoreService(key).OpenKVStore(testCtx.Ctx), spec.srcRowID, &loadedObj) if spec.expErr != nil { require.True(t, spec.expErr.Is(err), err) return diff --git a/x/group/keeper/genesis.go b/x/group/keeper/genesis.go index 577f3e88393b..700bacd2f86c 100644 --- a/x/group/keeper/genesis.go +++ b/x/group/keeper/genesis.go @@ -10,7 +10,6 @@ import ( "cosmossdk.io/x/group" "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" ) // InitGenesis initializes the group module's genesis state. @@ -18,29 +17,29 @@ func (k Keeper) InitGenesis(ctx context.Context, cdc codec.JSONCodec, data json. var genesisState group.GenesisState cdc.MustUnmarshalJSON(data, &genesisState) - sdkCtx := sdk.UnwrapSDKContext(ctx) + store := k.storeService.OpenKVStore(ctx) - if err := k.groupTable.Import(sdkCtx.KVStore(k.key), genesisState.Groups, genesisState.GroupSeq); err != nil { + if err := k.groupTable.Import(store, genesisState.Groups, genesisState.GroupSeq); err != nil { panic(errors.Wrap(err, "groups")) } - if err := k.groupMemberTable.Import(sdkCtx.KVStore(k.key), genesisState.GroupMembers, 0); err != nil { + if err := k.groupMemberTable.Import(store, genesisState.GroupMembers, 0); err != nil { panic(errors.Wrap(err, "group members")) } - if err := k.groupPolicyTable.Import(sdkCtx.KVStore(k.key), genesisState.GroupPolicies, 0); err != nil { + if err := k.groupPolicyTable.Import(store, genesisState.GroupPolicies, 0); err != nil { panic(errors.Wrap(err, "group policies")) } - if err := k.groupPolicySeq.InitVal(sdkCtx.KVStore(k.key), genesisState.GroupPolicySeq); err != nil { + if err := k.groupPolicySeq.InitVal(store, genesisState.GroupPolicySeq); err != nil { panic(errors.Wrap(err, "group policy account seq")) } - if err := k.proposalTable.Import(sdkCtx.KVStore(k.key), genesisState.Proposals, genesisState.ProposalSeq); err != nil { + if err := k.proposalTable.Import(store, genesisState.Proposals, genesisState.ProposalSeq); err != nil { panic(errors.Wrap(err, "proposals")) } - if err := k.voteTable.Import(sdkCtx.KVStore(k.key), genesisState.Votes, 0); err != nil { + if err := k.voteTable.Import(store, genesisState.Votes, 0); err != nil { panic(errors.Wrap(err, "votes")) } @@ -53,9 +52,9 @@ func (k Keeper) ExportGenesis(ctx context.Context, _ codec.JSONCodec) *group.Gen var groups []*group.GroupInfo - sdkCtx := sdk.UnwrapSDKContext(ctx) + store := k.storeService.OpenKVStore(ctx) - groupSeq, err := k.groupTable.Export(sdkCtx.KVStore(k.key), &groups) + groupSeq, err := k.groupTable.Export(store, &groups) if err != nil { panic(errors.Wrap(err, "groups")) } @@ -63,22 +62,22 @@ func (k Keeper) ExportGenesis(ctx context.Context, _ codec.JSONCodec) *group.Gen genesisState.GroupSeq = groupSeq var groupMembers []*group.GroupMember - _, err = k.groupMemberTable.Export(sdkCtx.KVStore(k.key), &groupMembers) + _, err = k.groupMemberTable.Export(store, &groupMembers) if err != nil { panic(errors.Wrap(err, "group members")) } genesisState.GroupMembers = groupMembers var groupPolicies []*group.GroupPolicyInfo - _, err = k.groupPolicyTable.Export(sdkCtx.KVStore(k.key), &groupPolicies) + _, err = k.groupPolicyTable.Export(store, &groupPolicies) if err != nil { panic(errors.Wrap(err, "group policies")) } genesisState.GroupPolicies = groupPolicies - genesisState.GroupPolicySeq = k.groupPolicySeq.CurVal(sdkCtx.KVStore(k.key)) + genesisState.GroupPolicySeq = k.groupPolicySeq.CurVal(store) var proposals []*group.Proposal - proposalSeq, err := k.proposalTable.Export(sdkCtx.KVStore(k.key), &proposals) + proposalSeq, err := k.proposalTable.Export(store, &proposals) if err != nil { panic(errors.Wrap(err, "proposals")) } @@ -86,7 +85,7 @@ func (k Keeper) ExportGenesis(ctx context.Context, _ codec.JSONCodec) *group.Gen genesisState.ProposalSeq = proposalSeq var votes []*group.Vote - _, err = k.voteTable.Export(sdkCtx.KVStore(k.key), &votes) + _, err = k.voteTable.Export(store, &votes) if err != nil { panic(errors.Wrap(err, "votes")) } diff --git a/x/group/keeper/genesis_test.go b/x/group/keeper/genesis_test.go index 39640d04710d..c9e3c44640b1 100644 --- a/x/group/keeper/genesis_test.go +++ b/x/group/keeper/genesis_test.go @@ -22,6 +22,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil" sdk "github.com/cosmos/cosmos-sdk/types" moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil" @@ -49,6 +50,7 @@ var ( func (s *GenesisTestSuite) SetupTest() { key := storetypes.NewKVStoreKey(group.StoreKey) + storeService := runtime.NewKVStoreService(key) testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test")) encCfg := moduletestutil.MakeTestEncodingConfig(module.AppModuleBasic{}) @@ -71,7 +73,7 @@ func (s *GenesisTestSuite) SetupTest() { s.cdc = codec.NewProtoCodec(encCfg.InterfaceRegistry) s.ctx = s.sdkCtx - s.keeper = keeper.NewKeeper(key, s.cdc, bApp.MsgServiceRouter(), accountKeeper, group.DefaultConfig()) + s.keeper = keeper.NewKeeper(storeService, s.cdc, bApp.MsgServiceRouter(), accountKeeper, group.DefaultConfig()) } func (s *GenesisTestSuite) TestInitExportGenesis() { diff --git a/x/group/keeper/grpc_query.go b/x/group/keeper/grpc_query.go index 9a48ede2fcf7..e15b2fcf5ecc 100644 --- a/x/group/keeper/grpc_query.go +++ b/x/group/keeper/grpc_query.go @@ -33,7 +33,7 @@ func (k Keeper) GroupInfo(goCtx context.Context, request *group.QueryGroupInfoRe // getGroupInfo gets the group info of the given group id. func (k Keeper) getGroupInfo(ctx sdk.Context, id uint64) (group.GroupInfo, error) { var obj group.GroupInfo - _, err := k.groupTable.GetOne(ctx.KVStore(k.key), id, &obj) + _, err := k.groupTable.GetOne(k.storeService.OpenKVStore(ctx), id, &obj) return obj, err } @@ -56,7 +56,7 @@ func (k Keeper) GroupPolicyInfo(goCtx context.Context, request *group.QueryGroup // getGroupPolicyInfo gets the group policy info of the given account address. func (k Keeper) getGroupPolicyInfo(ctx sdk.Context, accountAddress string) (group.GroupPolicyInfo, error) { var obj group.GroupPolicyInfo - return obj, k.groupPolicyTable.GetOne(ctx.KVStore(k.key), orm.PrimaryKey(&group.GroupPolicyInfo{Address: accountAddress}), &obj) + return obj, k.groupPolicyTable.GetOne(k.storeService.OpenKVStore(ctx), orm.PrimaryKey(&group.GroupPolicyInfo{Address: accountAddress}), &obj) } // GroupMembers queries all members of a group. @@ -82,7 +82,7 @@ func (k Keeper) GroupMembers(goCtx context.Context, request *group.QueryGroupMem // getGroupMembers returns an iterator for the given group id and page request. func (k Keeper) getGroupMembers(ctx sdk.Context, id uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { - return k.groupMemberByGroupIndex.GetPaginated(ctx.KVStore(k.key), id, pageRequest) + return k.groupMemberByGroupIndex.GetPaginated(k.storeService.OpenKVStore(ctx), id, pageRequest) } // GroupsByAdmin queries all groups where a given address is admin. @@ -111,7 +111,7 @@ func (k Keeper) GroupsByAdmin(goCtx context.Context, request *group.QueryGroupsB // getGroupsByAdmin returns an iterator for the given admin account address and page request. func (k Keeper) getGroupsByAdmin(ctx sdk.Context, admin sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { - return k.groupByAdminIndex.GetPaginated(ctx.KVStore(k.key), admin.Bytes(), pageRequest) + return k.groupByAdminIndex.GetPaginated(k.storeService.OpenKVStore(ctx), admin.Bytes(), pageRequest) } // GroupPoliciesByGroup queries all groups policies of a given group. @@ -137,7 +137,7 @@ func (k Keeper) GroupPoliciesByGroup(goCtx context.Context, request *group.Query // getGroupPoliciesByGroup returns an iterator for the given group id and page request. func (k Keeper) getGroupPoliciesByGroup(ctx sdk.Context, id uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { - return k.groupPolicyByGroupIndex.GetPaginated(ctx.KVStore(k.key), id, pageRequest) + return k.groupPolicyByGroupIndex.GetPaginated(k.storeService.OpenKVStore(ctx), id, pageRequest) } // GroupPoliciesByAdmin queries all groups policies where a given address is @@ -167,7 +167,7 @@ func (k Keeper) GroupPoliciesByAdmin(goCtx context.Context, request *group.Query // getGroupPoliciesByAdmin returns an iterator for the given admin account address and page request. func (k Keeper) getGroupPoliciesByAdmin(ctx sdk.Context, admin sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { - return k.groupPolicyByAdminIndex.GetPaginated(ctx.KVStore(k.key), admin.Bytes(), pageRequest) + return k.groupPolicyByAdminIndex.GetPaginated(k.storeService.OpenKVStore(ctx), admin.Bytes(), pageRequest) } // Proposal queries a proposal. @@ -208,13 +208,13 @@ func (k Keeper) ProposalsByGroupPolicy(goCtx context.Context, request *group.Que // getProposalsByGroupPolicy returns an iterator for the given account address and page request. func (k Keeper) getProposalsByGroupPolicy(ctx sdk.Context, account sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { - return k.proposalByGroupPolicyIndex.GetPaginated(ctx.KVStore(k.key), account.Bytes(), pageRequest) + return k.proposalByGroupPolicyIndex.GetPaginated(k.storeService.OpenKVStore(ctx), account.Bytes(), pageRequest) } // getProposal gets the proposal info of the given proposal id. func (k Keeper) getProposal(ctx sdk.Context, proposalID uint64) (group.Proposal, error) { var p group.Proposal - if _, err := k.proposalTable.GetOne(ctx.KVStore(k.key), proposalID, &p); err != nil { + if _, err := k.proposalTable.GetOne(k.storeService.OpenKVStore(ctx), proposalID, &p); err != nil { return group.Proposal{}, errorsmod.Wrap(err, "load proposal") } return p, nil @@ -294,7 +294,7 @@ func (k Keeper) GroupsByMember(goCtx context.Context, request *group.QueryGroups return nil, err } - iter, err := k.groupMemberByMemberIndex.GetPaginated(ctx.KVStore(k.key), member, request.Pagination) + iter, err := k.groupMemberByMemberIndex.GetPaginated(k.storeService.OpenKVStore(ctx), member, request.Pagination) if err != nil { return nil, err } @@ -323,17 +323,17 @@ func (k Keeper) GroupsByMember(goCtx context.Context, request *group.QueryGroups // getVote gets the vote info for the given proposal id and voter address. func (k Keeper) getVote(ctx sdk.Context, proposalID uint64, voter sdk.AccAddress) (group.Vote, error) { var v group.Vote - return v, k.voteTable.GetOne(ctx.KVStore(k.key), orm.PrimaryKey(&group.Vote{ProposalId: proposalID, Voter: voter.String()}), &v) + return v, k.voteTable.GetOne(k.storeService.OpenKVStore(ctx), orm.PrimaryKey(&group.Vote{ProposalId: proposalID, Voter: voter.String()}), &v) } // getVotesByProposal returns an iterator for the given proposal id and page request. func (k Keeper) getVotesByProposal(ctx sdk.Context, proposalID uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { - return k.voteByProposalIndex.GetPaginated(ctx.KVStore(k.key), proposalID, pageRequest) + return k.voteByProposalIndex.GetPaginated(k.storeService.OpenKVStore(ctx), proposalID, pageRequest) } // getVotesByVoter returns an iterator for the given voter address and page request. func (k Keeper) getVotesByVoter(ctx sdk.Context, voter sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { - return k.voteByVoterIndex.GetPaginated(ctx.KVStore(k.key), voter.Bytes(), pageRequest) + return k.voteByVoterIndex.GetPaginated(k.storeService.OpenKVStore(ctx), voter.Bytes(), pageRequest) } // TallyResult computes the live tally result of a proposal. @@ -369,7 +369,7 @@ func (k Keeper) TallyResult(goCtx context.Context, request *group.QueryTallyResu func (k Keeper) Groups(goCtx context.Context, request *group.QueryGroupsRequest) (*group.QueryGroupsResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - it, err := k.groupTable.PrefixScan(ctx.KVStore(k.key), 1, math.MaxUint64) + it, err := k.groupTable.PrefixScan(k.storeService.OpenKVStore(ctx), 1, math.MaxUint64) if err != nil { return nil, err } diff --git a/x/group/keeper/grpc_query_test.go b/x/group/keeper/grpc_query_test.go index 79a8e9cc765f..dafc811a9f5e 100644 --- a/x/group/keeper/grpc_query_test.go +++ b/x/group/keeper/grpc_query_test.go @@ -19,6 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec/address" codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" "github.com/cosmos/cosmos-sdk/types" @@ -42,6 +43,7 @@ func initKeeper(t *testing.T) *fixture { ) key := storetypes.NewKVStoreKey(group.StoreKey) + storeService := runtime.NewKVStoreService(key) testCtx := testutil.DefaultContextWithDB(t, key, storetypes.NewTransientStoreKey("transient_test")) encCfg := moduletestutil.MakeTestEncodingConfig(module.AppModuleBasic{}) @@ -67,7 +69,7 @@ func initKeeper(t *testing.T) *fixture { accountKeeper.EXPECT().NewAccount(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() accountKeeper.EXPECT().SetAccount(gomock.Any(), gomock.Any()).AnyTimes() - groupKeeper = groupkeeper.NewKeeper(key, encCfg.Codec, bApp.MsgServiceRouter(), accountKeeper, group.DefaultConfig()) + groupKeeper = groupkeeper.NewKeeper(storeService, encCfg.Codec, bApp.MsgServiceRouter(), accountKeeper, group.DefaultConfig()) queryHelper := baseapp.NewQueryServerTestHelper(ctx, interfaceRegistry) group.RegisterQueryServer(queryHelper, groupKeeper) queryClient := group.NewQueryClient(queryHelper) diff --git a/x/group/keeper/invariants.go b/x/group/keeper/invariants.go index ec8f9eb0420b..060f9fef899a 100644 --- a/x/group/keeper/invariants.go +++ b/x/group/keeper/invariants.go @@ -7,7 +7,7 @@ import ( "golang.org/x/exp/maps" - storetypes "cosmossdk.io/store/types" + storetypes "cosmossdk.io/core/store" "cosmossdk.io/x/group" "cosmossdk.io/x/group/errors" groupmath "cosmossdk.io/x/group/internal/math" @@ -26,16 +26,18 @@ func RegisterInvariants(ir sdk.InvariantRegistry, keeper Keeper) { // GroupTotalWeightInvariant checks that group's TotalWeight must be equal to the sum of its members. func GroupTotalWeightInvariant(keeper Keeper) sdk.Invariant { return func(ctx sdk.Context) (string, bool) { - msg, broken := GroupTotalWeightInvariantHelper(ctx, keeper.key, keeper.groupTable, keeper.groupMemberByGroupIndex) + msg, broken := GroupTotalWeightInvariantHelper(ctx, keeper.storeService, keeper.groupTable, keeper.groupMemberByGroupIndex) return sdk.FormatInvariant(group.ModuleName, weightInvariant, msg), broken } } -func GroupTotalWeightInvariantHelper(ctx sdk.Context, key storetypes.StoreKey, groupTable orm.AutoUInt64Table, groupMemberByGroupIndex orm.Index) (string, bool) { +func GroupTotalWeightInvariantHelper(ctx sdk.Context, storeService storetypes.KVStoreService, groupTable orm.AutoUInt64Table, groupMemberByGroupIndex orm.Index) (string, bool) { var msg string var broken bool - groupIt, err := groupTable.PrefixScan(ctx.KVStore(key), 1, math.MaxUint64) + kvStore := storeService.OpenKVStore(ctx) + + groupIt, err := groupTable.PrefixScan(kvStore, 1, math.MaxUint64) if err != nil { msg += fmt.Sprintf("PrefixScan failure on group table\n%v\n", err) return msg, broken @@ -69,7 +71,7 @@ func GroupTotalWeightInvariantHelper(ctx sdk.Context, key storetypes.StoreKey, g return msg, broken } - memIt, err := groupMemberByGroupIndex.Get(ctx.KVStore(key), groupInfo.Id) + memIt, err := groupMemberByGroupIndex.Get(kvStore, groupInfo.Id) if err != nil { msg += fmt.Sprintf("error while returning group member iterator for group with ID %d\n%v\n", groupInfo.Id, err) return msg, broken diff --git a/x/group/keeper/invariants_test.go b/x/group/keeper/invariants_test.go index 0f77489fff91..d452fcc9157d 100644 --- a/x/group/keeper/invariants_test.go +++ b/x/group/keeper/invariants_test.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -131,16 +132,17 @@ func (s *invariantTestSuite) TestGroupTotalWeightInvariant() { cacheCurCtx, _ := curCtx.CacheContext() groupsInfo := spec.groupsInfo groupMembers := spec.groupMembers - - _, err := groupTable.Create(cacheCurCtx.KVStore(key), groupsInfo) + storeService := runtime.NewKVStoreService(key) + kvStore := storeService.OpenKVStore(cacheCurCtx) + _, err := groupTable.Create(kvStore, groupsInfo) s.Require().NoError(err) for i := 0; i < len(groupMembers); i++ { - err := groupMemberTable.Create(cacheCurCtx.KVStore(key), groupMembers[i]) + err := groupMemberTable.Create(kvStore, groupMembers[i]) s.Require().NoError(err) } - _, broken := keeper.GroupTotalWeightInvariantHelper(cacheCurCtx, key, *groupTable, groupMemberByGroupIndex) + _, broken := keeper.GroupTotalWeightInvariantHelper(cacheCurCtx, storeService, *groupTable, groupMemberByGroupIndex) s.Require().Equal(spec.expBroken, broken) } diff --git a/x/group/keeper/keeper.go b/x/group/keeper/keeper.go index 192d708ef8d1..88ac69a7772a 100644 --- a/x/group/keeper/keeper.go +++ b/x/group/keeper/keeper.go @@ -4,9 +4,9 @@ import ( "fmt" "time" + corestoretypes "cosmossdk.io/core/store" errorsmod "cosmossdk.io/errors" "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/group" "cosmossdk.io/x/group/errors" "cosmossdk.io/x/group/internal/orm" @@ -46,7 +46,7 @@ const ( ) type Keeper struct { - key storetypes.StoreKey + storeService corestoretypes.KVStoreService accKeeper group.AccountKeeper @@ -83,12 +83,12 @@ type Keeper struct { } // NewKeeper creates a new group keeper. -func NewKeeper(storeKey storetypes.StoreKey, cdc codec.Codec, router baseapp.MessageRouter, accKeeper group.AccountKeeper, config group.Config) Keeper { +func NewKeeper(storeService corestoretypes.KVStoreService, cdc codec.Codec, router baseapp.MessageRouter, accKeeper group.AccountKeeper, config group.Config) Keeper { k := Keeper{ - key: storeKey, - router: router, - accKeeper: accKeeper, - cdc: cdc, + storeService: storeService, + router: router, + accKeeper: accKeeper, + cdc: cdc, } /* @@ -242,18 +242,18 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // GetGroupSequence returns the current value of the group table sequence func (k Keeper) GetGroupSequence(ctx sdk.Context) uint64 { - return k.groupTable.Sequence().CurVal(ctx.KVStore(k.key)) + return k.groupTable.Sequence().CurVal(k.storeService.OpenKVStore(ctx)) } // GetGroupPolicySeq returns the current value of the group policy table sequence func (k Keeper) GetGroupPolicySeq(ctx sdk.Context) uint64 { - return k.groupPolicySeq.CurVal(ctx.KVStore(k.key)) + return k.groupPolicySeq.CurVal(k.storeService.OpenKVStore(ctx)) } // proposalsByVPEnd returns all proposals whose voting_period_end is after the `endTime` time argument. func (k Keeper) proposalsByVPEnd(ctx sdk.Context, endTime time.Time) (proposals []group.Proposal, err error) { timeBytes := sdk.FormatTimeBytes(endTime) - it, err := k.proposalsByVotingPeriodEnd.PrefixScan(ctx.KVStore(k.key), nil, timeBytes) + it, err := k.proposalsByVotingPeriodEnd.PrefixScan(k.storeService.OpenKVStore(ctx), nil, timeBytes) if err != nil { return proposals, err } @@ -285,9 +285,7 @@ func (k Keeper) proposalsByVPEnd(ctx sdk.Context, endTime time.Time) (proposals // pruneProposal deletes a proposal from state. func (k Keeper) pruneProposal(ctx sdk.Context, proposalID uint64) error { - store := ctx.KVStore(k.key) - - err := k.proposalTable.Delete(store, proposalID) + err := k.proposalTable.Delete(k.storeService.OpenKVStore(ctx), proposalID) if err != nil { return err } @@ -310,7 +308,7 @@ func (k Keeper) abortProposals(ctx sdk.Context, groupPolicyAddr sdk.AccAddress) if proposalInfo.Status == group.PROPOSAL_STATUS_SUBMITTED { proposalInfo.Status = group.PROPOSAL_STATUS_ABORTED - if err := k.proposalTable.Update(ctx.KVStore(k.key), proposalInfo.Id, &proposalInfo); err != nil { + if err := k.proposalTable.Update(k.storeService.OpenKVStore(ctx), proposalInfo.Id, &proposalInfo); err != nil { return err } } @@ -320,7 +318,7 @@ func (k Keeper) abortProposals(ctx sdk.Context, groupPolicyAddr sdk.AccAddress) // proposalsByGroupPolicy returns all proposals for a given group policy. func (k Keeper) proposalsByGroupPolicy(ctx sdk.Context, groupPolicyAddr sdk.AccAddress) ([]group.Proposal, error) { - proposalIt, err := k.proposalByGroupPolicyIndex.Get(ctx.KVStore(k.key), groupPolicyAddr.Bytes()) + proposalIt, err := k.proposalByGroupPolicyIndex.Get(k.storeService.OpenKVStore(ctx), groupPolicyAddr.Bytes()) if err != nil { return nil, err } @@ -351,7 +349,7 @@ func (k Keeper) pruneVotes(ctx sdk.Context, proposalID uint64) error { //nolint:gosec // "implicit memory aliasing in the for loop (because of the pointer on &v)" for _, v := range votes { - err = k.voteTable.Delete(ctx.KVStore(k.key), &v) + err = k.voteTable.Delete(k.storeService.OpenKVStore(ctx), &v) if err != nil { return err } @@ -362,7 +360,7 @@ func (k Keeper) pruneVotes(ctx sdk.Context, proposalID uint64) error { // votesByProposal returns all votes for a given proposal. func (k Keeper) votesByProposal(ctx sdk.Context, proposalID uint64) ([]group.Vote, error) { - it, err := k.voteByProposalIndex.Get(ctx.KVStore(k.key), proposalID) + it, err := k.voteByProposalIndex.Get(k.storeService.OpenKVStore(ctx), proposalID) if err != nil { return nil, err } @@ -453,7 +451,7 @@ func (k Keeper) TallyProposalsAtVPEnd(ctx sdk.Context) error { return errorsmod.Wrap(err, "doTallyAndUpdate") } - if err := k.proposalTable.Update(ctx.KVStore(k.key), proposal.Id, &proposal); err != nil { + if err := k.proposalTable.Update(k.storeService.OpenKVStore(ctx), proposal.Id, &proposal); err != nil { return errorsmod.Wrap(err, "proposal update") } } diff --git a/x/group/keeper/keeper_test.go b/x/group/keeper/keeper_test.go index d9fd9dac708f..e5d82073399c 100644 --- a/x/group/keeper/keeper_test.go +++ b/x/group/keeper/keeper_test.go @@ -23,6 +23,7 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/runtime" "github.com/cosmos/cosmos-sdk/testutil" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" @@ -49,6 +50,7 @@ type TestSuite struct { func (s *TestSuite) SetupTest() { s.blockTime = time.Now().Round(0).UTC() key := storetypes.NewKVStoreKey(group.StoreKey) + storeService := runtime.NewKVStoreService(key) testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test")) encCfg := moduletestutil.MakeTestEncodingConfig(module.AppModuleBasic{}, bank.AppModuleBasic{}) @@ -74,7 +76,7 @@ func (s *TestSuite) SetupTest() { banktypes.RegisterMsgServer(bApp.MsgServiceRouter(), s.bankKeeper) config := group.DefaultConfig() - s.groupKeeper = keeper.NewKeeper(key, encCfg.Codec, bApp.MsgServiceRouter(), s.accountKeeper, config) + s.groupKeeper = keeper.NewKeeper(storeService, encCfg.Codec, bApp.MsgServiceRouter(), s.accountKeeper, config) s.ctx = testCtx.Ctx.WithHeaderInfo(header.Info{Time: s.blockTime}) s.sdkCtx = sdk.UnwrapSDKContext(s.ctx) diff --git a/x/group/keeper/migrations.go b/x/group/keeper/migrations.go index 0f5b40e6c6fa..bb53b3bfc191 100644 --- a/x/group/keeper/migrations.go +++ b/x/group/keeper/migrations.go @@ -20,7 +20,7 @@ func NewMigrator(keeper Keeper) Migrator { func (m Migrator) Migrate1to2(ctx sdk.Context) error { return v2.Migrate( ctx, - m.keeper.key, + m.keeper.storeService, m.keeper.accKeeper, m.keeper.groupPolicySeq, m.keeper.groupPolicyTable, diff --git a/x/group/keeper/msg_server.go b/x/group/keeper/msg_server.go index f59d85ec56a5..06cf6c79368e 100644 --- a/x/group/keeper/msg_server.go +++ b/x/group/keeper/msg_server.go @@ -62,22 +62,23 @@ func (k Keeper) CreateGroup(goCtx context.Context, msg *group.MsgCreateGroup) (* // Create a new group in the groupTable. ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) groupInfo := &group.GroupInfo{ - Id: k.groupTable.Sequence().PeekNextVal(ctx.KVStore(k.key)), + Id: k.groupTable.Sequence().PeekNextVal(kvStore), Admin: msg.Admin, Metadata: msg.Metadata, Version: 1, TotalWeight: totalWeight.String(), CreatedAt: ctx.HeaderInfo().Time, } - groupID, err := k.groupTable.Create(ctx.KVStore(k.key), groupInfo) + groupID, err := k.groupTable.Create(kvStore, groupInfo) if err != nil { return nil, errorsmod.Wrap(err, "could not create group") } // Create new group members in the groupMemberTable. for i, m := range msg.Members { - err := k.groupMemberTable.Create(ctx.KVStore(k.key), &group.GroupMember{ + err := k.groupMemberTable.Create(kvStore, &group.GroupMember{ GroupId: groupID, Member: &group.Member{ Address: m.Address, @@ -112,6 +113,7 @@ func (k Keeper) UpdateGroupMembers(goCtx context.Context, msg *group.MsgUpdateGr } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) action := func(g *group.GroupInfo) error { totalWeight, err := math.NewNonNegativeDecFromString(g.TotalWeight) if err != nil { @@ -134,7 +136,7 @@ func (k Keeper) UpdateGroupMembers(goCtx context.Context, msg *group.MsgUpdateGr // Checking if the group member is already part of the group var found bool var prevGroupMember group.GroupMember - switch err := k.groupMemberTable.GetOne(ctx.KVStore(k.key), orm.PrimaryKey(&groupMember), &prevGroupMember); { + switch err := k.groupMemberTable.GetOne(kvStore, orm.PrimaryKey(&groupMember), &prevGroupMember); { case err == nil: found = true case sdkerrors.ErrNotFound.Is(err): @@ -167,7 +169,7 @@ func (k Keeper) UpdateGroupMembers(goCtx context.Context, msg *group.MsgUpdateGr } // Delete group member in the groupMemberTable. - if err := k.groupMemberTable.Delete(ctx.KVStore(k.key), &groupMember); err != nil { + if err := k.groupMemberTable.Delete(kvStore, &groupMember); err != nil { return errorsmod.Wrap(err, "delete member") } continue @@ -185,12 +187,12 @@ func (k Keeper) UpdateGroupMembers(goCtx context.Context, msg *group.MsgUpdateGr } // Save updated group member in the groupMemberTable. groupMember.Member.AddedAt = prevGroupMember.Member.AddedAt - if err := k.groupMemberTable.Update(ctx.KVStore(k.key), &groupMember); err != nil { + if err := k.groupMemberTable.Update(kvStore, &groupMember); err != nil { return errorsmod.Wrap(err, "add member") } } else { // else handle create. groupMember.Member.AddedAt = ctx.HeaderInfo().Time - if err := k.groupMemberTable.Create(ctx.KVStore(k.key), &groupMember); err != nil { + if err := k.groupMemberTable.Create(kvStore, &groupMember); err != nil { return errorsmod.Wrap(err, "add member") } } @@ -208,7 +210,7 @@ func (k Keeper) UpdateGroupMembers(goCtx context.Context, msg *group.MsgUpdateGr return err } - return k.groupTable.Update(ctx.KVStore(k.key), g.Id, g) + return k.groupTable.Update(kvStore, g.Id, g) } if err := k.doUpdateGroup(ctx, msg.GetGroupID(), msg.GetAdmin(), action, "members updated"); err != nil { @@ -236,11 +238,12 @@ func (k Keeper) UpdateGroupAdmin(goCtx context.Context, msg *group.MsgUpdateGrou } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) action := func(g *group.GroupInfo) error { g.Admin = msg.NewAdmin g.Version++ - return k.groupTable.Update(ctx.KVStore(k.key), g.Id, g) + return k.groupTable.Update(kvStore, g.Id, g) } if err := k.doUpdateGroup(ctx, msg.GetGroupID(), msg.GetAdmin(), action, "admin updated"); err != nil { @@ -264,10 +267,11 @@ func (k Keeper) UpdateGroupMetadata(goCtx context.Context, msg *group.MsgUpdateG } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) action := func(g *group.GroupInfo) error { g.Metadata = msg.Metadata g.Version++ - return k.groupTable.Update(ctx.KVStore(k.key), g.Id, g) + return k.groupTable.Update(kvStore, g.Id, g) } if err := k.doUpdateGroup(ctx, msg.GetGroupID(), msg.GetAdmin(), action, "metadata updated"); err != nil { @@ -368,12 +372,14 @@ func (k Keeper) CreateGroupPolicy(goCtx context.Context, msg *group.MsgCreateGro return nil, err } + kvStore := k.storeService.OpenKVStore(goCtx) + // Generate account address of group policy. var accountAddr sdk.AccAddress // loop here in the rare case where a ADR-028-derived address creates a // collision with an existing address. for { - nextAccVal := k.groupPolicySeq.NextVal(ctx.KVStore(k.key)) + nextAccVal := k.groupPolicySeq.NextVal(kvStore) derivationKey := make([]byte, 8) binary.BigEndian.PutUint64(derivationKey, nextAccVal) @@ -413,7 +419,7 @@ func (k Keeper) CreateGroupPolicy(goCtx context.Context, msg *group.MsgCreateGro return nil, err } - if err := k.groupPolicyTable.Create(ctx.KVStore(k.key), &groupPolicy); err != nil { + if err := k.groupPolicyTable.Create(kvStore, &groupPolicy); err != nil { return nil, errorsmod.Wrap(err, "could not create group policy") } @@ -434,10 +440,11 @@ func (k Keeper) UpdateGroupPolicyAdmin(goCtx context.Context, msg *group.MsgUpda } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) action := func(groupPolicy *group.GroupPolicyInfo) error { groupPolicy.Admin = msg.NewAdmin groupPolicy.Version++ - return k.groupPolicyTable.Update(ctx.KVStore(k.key), groupPolicy) + return k.groupPolicyTable.Update(kvStore, groupPolicy) } if err := k.doUpdateGroupPolicy(ctx, msg.GroupPolicyAddress, msg.Admin, action, "group policy admin updated"); err != nil { @@ -458,6 +465,7 @@ func (k Keeper) UpdateGroupPolicyDecisionPolicy(goCtx context.Context, msg *grou } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) action := func(groupPolicy *group.GroupPolicyInfo) error { groupInfo, err := k.getGroupInfo(ctx, groupPolicy.GroupId) if err != nil { @@ -475,7 +483,7 @@ func (k Keeper) UpdateGroupPolicyDecisionPolicy(goCtx context.Context, msg *grou } groupPolicy.Version++ - return k.groupPolicyTable.Update(ctx.KVStore(k.key), groupPolicy) + return k.groupPolicyTable.Update(kvStore, groupPolicy) } if err = k.doUpdateGroupPolicy(ctx, msg.GroupPolicyAddress, msg.Admin, action, "group policy's decision policy updated"); err != nil { @@ -488,11 +496,12 @@ func (k Keeper) UpdateGroupPolicyDecisionPolicy(goCtx context.Context, msg *grou func (k Keeper) UpdateGroupPolicyMetadata(goCtx context.Context, msg *group.MsgUpdateGroupPolicyMetadata) (*group.MsgUpdateGroupPolicyMetadataResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) metadata := msg.GetMetadata() + kvStore := k.storeService.OpenKVStore(goCtx) action := func(groupPolicy *group.GroupPolicyInfo) error { groupPolicy.Metadata = metadata groupPolicy.Version++ - return k.groupPolicyTable.Update(ctx.KVStore(k.key), groupPolicy) + return k.groupPolicyTable.Update(kvStore, groupPolicy) } if err := k.assertMetadataLength(metadata, "group policy metadata"); err != nil { @@ -560,6 +569,7 @@ func (k Keeper) SubmitProposal(goCtx context.Context, msg *group.MsgSubmitPropos } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) policyAcc, err := k.getGroupPolicyInfo(ctx, msg.GroupPolicyAddress) if err != nil { return nil, errorsmod.Wrapf(err, "load group policy: %s", msg.GroupPolicyAddress) @@ -572,7 +582,7 @@ func (k Keeper) SubmitProposal(goCtx context.Context, msg *group.MsgSubmitPropos // Only members of the group can submit a new proposal. for _, proposer := range msg.Proposers { - if !k.groupMemberTable.Has(ctx.KVStore(k.key), orm.PrimaryKey(&group.GroupMember{GroupId: groupInfo.Id, Member: &group.Member{Address: proposer}})) { + if !k.groupMemberTable.Has(kvStore, orm.PrimaryKey(&group.GroupMember{GroupId: groupInfo.Id, Member: &group.Member{Address: proposer}})) { return nil, errorsmod.Wrapf(errors.ErrUnauthorized, "not in group: %s", proposer) } } @@ -593,7 +603,7 @@ func (k Keeper) SubmitProposal(goCtx context.Context, msg *group.MsgSubmitPropos } m := &group.Proposal{ - Id: k.proposalTable.Sequence().PeekNextVal(ctx.KVStore(k.key)), + Id: k.proposalTable.Sequence().PeekNextVal(kvStore), GroupPolicyAddress: msg.GroupPolicyAddress, Metadata: msg.Metadata, Proposers: msg.Proposers, @@ -612,7 +622,7 @@ func (k Keeper) SubmitProposal(goCtx context.Context, msg *group.MsgSubmitPropos return nil, errorsmod.Wrap(err, "create proposal") } - id, err := k.proposalTable.Create(ctx.KVStore(k.key), m) + id, err := k.proposalTable.Create(kvStore, m) if err != nil { return nil, errorsmod.Wrap(err, "create proposal") } @@ -661,6 +671,7 @@ func (k Keeper) WithdrawProposal(goCtx context.Context, msg *group.MsgWithdrawPr } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) proposal, err := k.getProposal(ctx, msg.ProposalId) if err != nil { return nil, err @@ -682,7 +693,7 @@ func (k Keeper) WithdrawProposal(goCtx context.Context, msg *group.MsgWithdrawPr } proposal.Status = group.PROPOSAL_STATUS_WITHDRAWN - if err := k.proposalTable.Update(ctx.KVStore(k.key), msg.ProposalId, &proposal); err != nil { + if err := k.proposalTable.Update(kvStore, msg.ProposalId, &proposal); err != nil { return nil, err } @@ -716,6 +727,7 @@ func (k Keeper) Vote(goCtx context.Context, msg *group.MsgVote) (*group.MsgVoteR } ctx := sdk.UnwrapSDKContext(goCtx) + kvStore := k.storeService.OpenKVStore(goCtx) proposal, err := k.getProposal(ctx, msg.ProposalId) if err != nil { return nil, err @@ -742,7 +754,7 @@ func (k Keeper) Vote(goCtx context.Context, msg *group.MsgVote) (*group.MsgVoteR // Count and store votes. voter := group.GroupMember{GroupId: groupInfo.Id, Member: &group.Member{Address: msg.Voter}} - if err := k.groupMemberTable.GetOne(ctx.KVStore(k.key), orm.PrimaryKey(&voter), &voter); err != nil { + if err := k.groupMemberTable.GetOne(kvStore, orm.PrimaryKey(&voter), &voter); err != nil { return nil, errorsmod.Wrapf(err, "voter address: %s", msg.Voter) } newVote := group.Vote{ @@ -755,7 +767,7 @@ func (k Keeper) Vote(goCtx context.Context, msg *group.MsgVote) (*group.MsgVoteR // The ORM will return an error if the vote already exists, // making sure than a voter hasn't already voted. - if err := k.voteTable.Create(ctx.KVStore(k.key), &newVote); err != nil { + if err := k.voteTable.Create(kvStore, &newVote); err != nil { return nil, errorsmod.Wrap(err, "store vote") } @@ -890,7 +902,7 @@ func (k Keeper) Exec(goCtx context.Context, msg *group.MsgExec) (*group.MsgExecR return nil, err } } else { - store := ctx.KVStore(k.key) + store := k.storeService.OpenKVStore(goCtx) if err := k.proposalTable.Update(store, proposal.Id, &proposal); err != nil { return nil, err } @@ -949,8 +961,10 @@ func (k Keeper) LeaveGroup(goCtx context.Context, msg *group.MsgLeaveGroup) (*gr return nil, err } + kvStore := k.storeService.OpenKVStore(goCtx) + // delete group member in the groupMemberTable. - if err := k.groupMemberTable.Delete(ctx.KVStore(k.key), gm); err != nil { + if err := k.groupMemberTable.Delete(kvStore, gm); err != nil { return nil, errorsmod.Wrap(err, "group member") } @@ -962,7 +976,7 @@ func (k Keeper) LeaveGroup(goCtx context.Context, msg *group.MsgLeaveGroup) (*gr return nil, err } - if err := k.groupTable.Update(ctx.KVStore(k.key), groupInfo.Id, &groupInfo); err != nil { + if err := k.groupTable.Update(kvStore, groupInfo.Id, &groupInfo); err != nil { return nil, err } @@ -977,8 +991,9 @@ func (k Keeper) LeaveGroup(goCtx context.Context, msg *group.MsgLeaveGroup) (*gr } func (k Keeper) getGroupMember(ctx sdk.Context, member *group.GroupMember) (*group.GroupMember, error) { + kvStore := k.storeService.OpenKVStore(ctx) var groupMember group.GroupMember - switch err := k.groupMemberTable.GetOne(ctx.KVStore(k.key), + switch err := k.groupMemberTable.GetOne(kvStore, orm.PrimaryKey(member), &groupMember); { case err == nil: break @@ -1060,7 +1075,8 @@ func (k Keeper) doUpdateGroup(ctx sdk.Context, groupID uint64, reqGroupAdmin str // validateDecisionPolicies loops through all decision policies from the group, // and calls each of their Validate() method. func (k Keeper) validateDecisionPolicies(ctx sdk.Context, g group.GroupInfo) error { - it, err := k.groupPolicyByGroupIndex.Get(ctx.KVStore(k.key), g.Id) + kvStore := k.storeService.OpenKVStore(ctx) + it, err := k.groupPolicyByGroupIndex.Get(kvStore, g.Id) if err != nil { return err } diff --git a/x/group/keeper/tally.go b/x/group/keeper/tally.go index 55e50db6976a..4f567f72ef37 100644 --- a/x/group/keeper/tally.go +++ b/x/group/keeper/tally.go @@ -22,7 +22,9 @@ func (k Keeper) Tally(ctx sdk.Context, p group.Proposal, groupID uint64) (group. return p.FinalTallyResult, nil } - it, err := k.voteByProposalIndex.Get(ctx.KVStore(k.key), p.Id) + kvStore := k.storeService.OpenKVStore(ctx) + + it, err := k.voteByProposalIndex.Get(kvStore, p.Id) if err != nil { return group.TallyResult{}, err } @@ -41,7 +43,7 @@ func (k Keeper) Tally(ctx sdk.Context, p group.Proposal, groupID uint64) (group. } var member group.GroupMember - err := k.groupMemberTable.GetOne(ctx.KVStore(k.key), orm.PrimaryKey(&group.GroupMember{ + err := k.groupMemberTable.GetOne(kvStore, orm.PrimaryKey(&group.GroupMember{ GroupId: groupID, Member: &group.Member{Address: vote.Voter}, }), &member) diff --git a/x/group/migrations/v2/migrate.go b/x/group/migrations/v2/migrate.go index 511e628f55b6..3738866ba996 100644 --- a/x/group/migrations/v2/migrate.go +++ b/x/group/migrations/v2/migrate.go @@ -4,7 +4,7 @@ import ( "encoding/binary" "fmt" - storetypes "cosmossdk.io/store/types" + "cosmossdk.io/core/store" authtypes "cosmossdk.io/x/auth/types" "cosmossdk.io/x/group" "cosmossdk.io/x/group/internal/orm" @@ -25,12 +25,12 @@ const ( // Specifically, it changes the group policy account from module account to base account. func Migrate( ctx sdk.Context, - storeKey storetypes.StoreKey, + storeService store.KVStoreService, accountKeeper group.AccountKeeper, groupPolicySeq orm.Sequence, groupPolicyTable orm.PrimaryKeyTable, ) error { - store := ctx.KVStore(storeKey) + store := storeService.OpenKVStore(ctx) curAccVal := groupPolicySeq.CurVal(store) groupPolicyAccountDerivationKey := make(map[string][]byte, 0) policyKey := []byte{GroupPolicyTablePrefix} diff --git a/x/group/migrations/v2/migrate_test.go b/x/group/migrations/v2/migrate_test.go index 2df8204de4bd..ed60eab541b0 100644 --- a/x/group/migrations/v2/migrate_test.go +++ b/x/group/migrations/v2/migrate_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/require" + corestore "cosmossdk.io/core/store" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/auth" authkeeper "cosmossdk.io/x/auth/keeper" @@ -34,14 +35,15 @@ var ( func TestMigrate(t *testing.T) { cdc := moduletestutil.MakeTestEncodingConfig(auth.AppModuleBasic{}, groupmodule.AppModuleBasic{}).Codec storeKey := storetypes.NewKVStoreKey(v2.ModuleName) + storeService := runtime.NewKVStoreService(storeKey) tKey := storetypes.NewTransientStoreKey("transient_test") ctx := testutil.DefaultContext(storeKey, tKey) oldAccs, accountKeeper := createOldPolicyAccount(ctx, storeKey, cdc, policies) - groupPolicyTable, groupPolicySeq, err := createGroupPolicies(ctx, storeKey, cdc, policies) + groupPolicyTable, groupPolicySeq, err := createGroupPolicies(ctx, storeService, cdc, policies) require.NoError(t, err) - require.NoError(t, v2.Migrate(ctx, storeKey, accountKeeper, groupPolicySeq, groupPolicyTable)) + require.NoError(t, v2.Migrate(ctx, storeService, accountKeeper, groupPolicySeq, groupPolicyTable)) for i, policyAddr := range policies { oldAcc := oldAccs[i] newAcc := accountKeeper.GetAccount(ctx, policyAddr) @@ -53,13 +55,14 @@ func TestMigrate(t *testing.T) { } } -func createGroupPolicies(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.Codec, policies []sdk.AccAddress) (orm.PrimaryKeyTable, orm.Sequence, error) { +func createGroupPolicies(ctx sdk.Context, storeService corestore.KVStoreService, cdc codec.Codec, policies []sdk.AccAddress) (orm.PrimaryKeyTable, orm.Sequence, error) { groupPolicyTable, err := orm.NewPrimaryKeyTable([2]byte{groupkeeper.GroupPolicyTablePrefix}, &group.GroupPolicyInfo{}, cdc) if err != nil { panic(err.Error()) } groupPolicySeq := orm.NewSequence(v2.GroupPolicyTableSeqPrefix) + kvStore := storeService.OpenKVStore(ctx) for _, policyAddr := range policies { groupPolicyInfo, err := group.NewGroupPolicyInfo(policyAddr, 1, authorityAddr, "", 1, group.NewPercentageDecisionPolicy("1", 1, 1), ctx.HeaderInfo().Time) @@ -67,11 +70,11 @@ func createGroupPolicies(ctx sdk.Context, storeKey storetypes.StoreKey, cdc code return orm.PrimaryKeyTable{}, orm.Sequence{}, err } - if err := groupPolicyTable.Create(ctx.KVStore(storeKey), &groupPolicyInfo); err != nil { + if err := groupPolicyTable.Create(kvStore, &groupPolicyInfo); err != nil { return orm.PrimaryKeyTable{}, orm.Sequence{}, err } - groupPolicySeq.NextVal(ctx.KVStore(storeKey)) + groupPolicySeq.NextVal(kvStore) } return *groupPolicyTable, groupPolicySeq, nil diff --git a/x/group/module/depinject.go b/x/group/module/depinject.go index f006df24f345..21ff996905fd 100644 --- a/x/group/module/depinject.go +++ b/x/group/module/depinject.go @@ -3,9 +3,9 @@ package module import ( modulev1 "cosmossdk.io/api/cosmos/group/module/v1" "cosmossdk.io/core/appmodule" + "cosmossdk.io/core/store" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" - store "cosmossdk.io/store/types" "cosmossdk.io/x/group" "cosmossdk.io/x/group/keeper" @@ -30,7 +30,7 @@ type GroupInputs struct { depinject.In Config *modulev1.Module - Key *store.KVStoreKey + StoreService store.KVStoreService Cdc codec.Codec AccountKeeper group.AccountKeeper BankKeeper group.BankKeeper @@ -46,7 +46,7 @@ type GroupOutputs struct { } func ProvideModule(in GroupInputs) GroupOutputs { - k := keeper.NewKeeper(in.Key, + k := keeper.NewKeeper(in.StoreService, in.Cdc, in.MsgServiceRouter, in.AccountKeeper,