feat!: migrate x/group to store service (#19410)
This commit is contained in:
parent
869c96c403
commit
c57dde2f34
@ -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
|
||||
}
|
||||
|
||||
@ -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{}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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"
|
||||
)
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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{
|
||||
{
|
||||
|
||||
@ -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{}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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)
|
||||
|
||||
223
x/group/internal/orm/prefixstore/prefixstore.go
Normal file
223
x/group/internal/orm/prefixstore/prefixstore.go
Normal file
@ -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
|
||||
}
|
||||
@ -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"
|
||||
)
|
||||
|
||||
@ -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)
|
||||
|
||||
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 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)
|
||||
|
||||
// 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.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)
|
||||
|
||||
t.Logf("pk: %v", pk)
|
||||
t.Logf("state: %v", state)
|
||||
err := table.Create(store, g)
|
||||
|
||||
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)
|
||||
|
||||
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")
|
||||
// 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")
|
||||
|
||||
newName := rapid.StringN(1, 100, 150).Draw(t, "newName")
|
||||
tm.Name = newName
|
||||
// Perform the real Delete
|
||||
err := table.Delete(store, tm)
|
||||
|
||||
// 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)
|
||||
|
||||
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)))
|
||||
}
|
||||
},
|
||||
|
||||
// Update the model with the new value
|
||||
state[string(PrimaryKey(tm))] = 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"))
|
||||
|
||||
// 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))
|
||||
realHas := table.Has(store, pk)
|
||||
modelHas := state[string(pk)] != nil
|
||||
|
||||
err := table.Set(store, g)
|
||||
require.Equal(t, realHas, modelHas)
|
||||
},
|
||||
|
||||
require.NoError(t, err)
|
||||
state[pk] = g
|
||||
},
|
||||
// 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"))
|
||||
|
||||
// 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")
|
||||
var tm testdata.TableModel
|
||||
|
||||
// Perform the real Delete
|
||||
err := table.Delete(store, tm)
|
||||
err := table.GetOne(store, pk, &tm)
|
||||
t.Logf("tm: %v", 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)
|
||||
if state[string(pk)] == nil {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, *state[string(pk)], tm)
|
||||
}
|
||||
},
|
||||
|
||||
// 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)
|
||||
}
|
||||
},
|
||||
// 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)
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
}
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
// 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)
|
||||
|
||||
// Choose initial sequence value
|
||||
initSeqVal := rapid.Uint64().Draw(t, "initSeqVal")
|
||||
err := seq.InitVal(store, initSeqVal)
|
||||
require.NoError(t, err)
|
||||
// Create model state
|
||||
state := initSeqVal
|
||||
|
||||
// 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))
|
||||
},
|
||||
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))
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"))
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user