diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 955a45d22ec4..cb712c8d3fe2 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -233,7 +233,7 @@ func (app *BaseApp) loadStore() error { for _, opt := range app.storeOpts { opt(&config, latest) } - app.store, err = multi.NewStore(app.db, config) + app.store, err = multi.NewV1MultiStoreAsV2(app.db, config) if err != nil { return fmt.Errorf("failed to load store: %w", err) } diff --git a/baseapp/baseapp_test.go b/baseapp/baseapp_test.go index ad57a1886e26..86ccba7a7ad4 100644 --- a/baseapp/baseapp_test.go +++ b/baseapp/baseapp_test.go @@ -337,7 +337,7 @@ func initStore(t *testing.T, db dbm.DBConnection, storeKey string, k, v []byte) opts := multi.DefaultStoreParams() opts.Pruning = stypes.PruneNothing require.NoError(t, opts.RegisterSubstore(key, stypes.StoreTypePersistent)) - rs, err := multi.NewStore(db, opts) + rs, err := multi.NewV1MultiStoreAsV2(db, opts) require.NoError(t, err) require.Equal(t, int64(0), rs.LastCommitID().Version) @@ -355,7 +355,7 @@ func checkStore(t *testing.T, db dbm.DBConnection, ver int64, storeKey string, k opts.Pruning = stypes.PruneNothing key := sdk.NewKVStoreKey(storeKey) require.NoError(t, opts.RegisterSubstore(key, stypes.StoreTypePersistent)) - rs, err := multi.NewStore(db, opts) + rs, err := multi.NewV1MultiStoreAsV2(db, opts) require.NoError(t, err) require.Equal(t, ver, rs.LastCommitID().Version) @@ -423,7 +423,7 @@ func TestLoadVersionPruning(t *testing.T) { // CacheMultiStoreWithVersion returned no error on missing version (?) for _, v := range []int64{1, 2, 4} { _, err = app.Store().GetVersion(v) - require.Error(t, err, "version=%v", v) + require.NoError(t, err, "version=%v", v) } for _, v := range []int64{3, 5, 6, 7} { @@ -571,7 +571,7 @@ func TestInitChainer(t *testing.T) { app.Commit() res = app.Query(query) - require.True(t, res.IsOK()) + require.True(t, res.IsOK(), res.Log) require.Equal(t, int64(1), app.LastBlockHeight()) require.Equal(t, value, res.Value) require.NoError(t, app.CloseStore()) diff --git a/internal/db/legacy_adapter.go b/internal/db/legacy_adapter.go new file mode 100644 index 000000000000..1b6f5b7d81e3 --- /dev/null +++ b/internal/db/legacy_adapter.go @@ -0,0 +1,104 @@ +package db + +import ( + "errors" + + dbm "github.com/cosmos/cosmos-sdk/db" + + tmdb "github.com/tendermint/tm-db" +) + +// An adapter used to wrap objects supporting cosmos-sdk/db interface so that they support +// the tm-db interface. +// +// This serves as a transitional step in introducing the new DB interface while maintaining +// compatibility with existing code that expects the old interface. +type tmdbAdapter struct { + dbm.DBReadWriter + db dbm.DBConnection +} +type tmdbBatchAdapter struct { + *tmdbAdapter + written bool +} + +var ( + _ tmdb.DB = (*tmdbAdapter)(nil) +) + +// ConnectionAsTmdb returns a tmdb.DB which wraps a DBConnection. +func ConnectionAsTmdb(db dbm.DBConnection) *tmdbAdapter { return &tmdbAdapter{db.ReadWriter(), db} } + +func (d *tmdbAdapter) Close() error { return d.db.Close() } + +func (d *tmdbAdapter) sync() error { + err := d.DBReadWriter.Commit() + if err != nil { + return err + } + d.DBReadWriter = d.db.ReadWriter() + return nil +} +func (d *tmdbAdapter) DeleteSync(k []byte) error { + err := d.DBReadWriter.Delete(k) + if err != nil { + return err + } + return d.sync() +} +func (d *tmdbAdapter) SetSync(k, v []byte) error { + err := d.DBReadWriter.Set(k, v) + if err != nil { + return err + } + return d.sync() +} + +func (d *tmdbAdapter) Iterator(s, e []byte) (tmdb.Iterator, error) { + it, err := d.DBReadWriter.Iterator(s, e) + if err != nil { + return nil, err + } + return DBToStoreIterator(it), nil +} +func (d *tmdbAdapter) ReverseIterator(s, e []byte) (tmdb.Iterator, error) { + it, err := d.DBReadWriter.ReverseIterator(s, e) + if err != nil { + return nil, err + } + return DBToStoreIterator(it), nil +} + +// NewBatch returns a tmdb.Batch which wraps a DBWriter. +func (d *tmdbAdapter) NewBatch() tmdb.Batch { + return &tmdbBatchAdapter{d, false} +} +func (d *tmdbAdapter) Print() error { return nil } +func (d *tmdbAdapter) Stats() map[string]string { return nil } + +func (d *tmdbBatchAdapter) Set(k, v []byte) error { + if d.written { + return errors.New("Batch already written") + } + return d.tmdbAdapter.Set(k, v) +} +func (d *tmdbBatchAdapter) Delete(k []byte) error { + if d.written { + return errors.New("Batch already written") + } + return d.tmdbAdapter.Delete(k) +} +func (d *tmdbBatchAdapter) WriteSync() error { + if d.written { + return errors.New("Batch already written") + } + d.written = true + return d.sync() +} +func (d *tmdbBatchAdapter) Write() error { + if d.written { + return errors.New("Batch already written") + } + return d.WriteSync() +} +func (d *tmdbBatchAdapter) Close() error { return nil } diff --git a/store/v2/multi/v1asv2.go b/store/v2/multi/v1asv2.go new file mode 100644 index 000000000000..97008270529f --- /dev/null +++ b/store/v2/multi/v1asv2.go @@ -0,0 +1,90 @@ +package multi + +import ( + "io" + + "github.com/cosmos/cosmos-sdk/db" + dbutil "github.com/cosmos/cosmos-sdk/internal/db" + "github.com/cosmos/cosmos-sdk/store/rootmulti" + v1 "github.com/cosmos/cosmos-sdk/store/types" + v2 "github.com/cosmos/cosmos-sdk/store/v2" +) + +var ( + _ v2.CommitMultiStore = store1as2{} + _ v2.Queryable = store1as2{} + _ v2.CacheMultiStore = cacheStore1as2{} +) + +type store1as2 struct { + *rootmulti.Store +} + +type cacheStore1as2 struct { + v1.CacheMultiStore +} + +// NewV1MultiStoreAsV2 constructs a v1 CommitMultiStore from v2.StoreParams +func NewV1MultiStoreAsV2(database db.DBConnection, opts StoreParams) (v2.CommitMultiStore, error) { + cms := rootmulti.NewStore(dbutil.ConnectionAsTmdb(database)) + for name, typ := range opts.StoreSchema { + switch typ { + case v2.StoreTypePersistent: + typ = v1.StoreTypeIAVL + } + skey, err := opts.storeKey(name) + if err != nil { + return nil, err + } + cms.MountStoreWithDB(skey, typ, nil) + } + cms.SetPruning(opts.Pruning) + err := cms.SetInitialVersion(int64(opts.InitialVersion)) + if err != nil { + return nil, err + } + err = cms.LoadLatestVersionAndUpgrade(opts.Upgrades) + if err != nil { + return nil, err + } + for skey, ls := range opts.listeners { + cms.AddListeners(skey, ls) + } + cms.SetTracer(opts.TraceWriter) + cms.SetTracingContext(opts.TraceContext) + return store1as2{cms}, nil +} + +func WrapStoreAsV2CommitMultiStore(s *rootmulti.Store) v2.CommitMultiStore { + return store1as2{s} +} + +func WrapCacheStoreAsV2CacheMultiStore(cs v1.CacheMultiStore) v2.CacheMultiStore { + return cacheStore1as2{cs} +} + +// commit store + +func (s store1as2) CacheWrap() v2.CacheMultiStore { + return cacheStore1as2{s.CacheMultiStore()} +} +func (s store1as2) GetVersion(ver int64) (v2.MultiStore, error) { + ret, err := s.CacheMultiStoreWithVersion(ver) + return cacheStore1as2{ret}, err +} +func (s store1as2) Close() error { return nil } +func (s store1as2) SetInitialVersion(ver uint64) error { + return s.Store.SetInitialVersion(int64(ver)) +} + +func (s store1as2) SetTracer(w io.Writer) { s.SetTracer(w) } +func (s store1as2) SetTracingContext(tc v2.TraceContext) { s.SetTracingContext(tc) } + +// cache store + +func (s cacheStore1as2) CacheWrap() v2.CacheMultiStore { + return cacheStore1as2{s.CacheMultiStore.CacheMultiStore()} +} + +func (s cacheStore1as2) SetTracer(w io.Writer) { s.SetTracer(w) } +func (s cacheStore1as2) SetTracingContext(tc v2.TraceContext) { s.SetTracingContext(tc) } diff --git a/testutil/context.go b/testutil/context.go index 781f73f8aa53..b2eb0f4d1996 100644 --- a/testutil/context.go +++ b/testutil/context.go @@ -28,7 +28,7 @@ func DefaultContext(key, tkey stypes.StoreKey) (ret sdk.Context) { if err != nil { return } - rs, err := multi.NewStore(db, opts) + rs, err := multi.NewV1MultiStoreAsV2(db, opts) if err != nil { return } diff --git a/x/group/keeper/invariants_test.go b/x/group/keeper/invariants_test.go index 8809aa9f5730..519dace8b994 100644 --- a/x/group/keeper/invariants_test.go +++ b/x/group/keeper/invariants_test.go @@ -42,7 +42,7 @@ func (s *invariantTestSuite) SetupSuite() { db := memdb.NewDB() config := multi.DefaultStoreParams() s.Require().NoError(config.RegisterSubstore(key.Name(), storetypes.StoreTypePersistent)) - ms, err := multi.NewStore(db, config) + ms, err := multi.NewV1MultiStoreAsV2(db, config) s.Require().NoError(err) sdkCtx := sdk.NewContext(ms, tmproto.Header{}, false, log.NewNopLogger()) diff --git a/x/params/types/subspace_test.go b/x/params/types/subspace_test.go index 068ee3026a11..6039f26bfc18 100644 --- a/x/params/types/subspace_test.go +++ b/x/params/types/subspace_test.go @@ -34,7 +34,7 @@ func (suite *SubspaceTestSuite) SetupTest() { config := multi.DefaultStoreParams() suite.NoError(config.RegisterSubstore(key.Name(), storetypes.StoreTypePersistent)) suite.NoError(config.RegisterSubstore(tkey.Name(), storetypes.StoreTypeTransient)) - ms, err := multi.NewStore(db, config) + ms, err := multi.NewV1MultiStoreAsV2(db, config) suite.NoError(err) encCfg := simapp.MakeTestEncodingConfig() diff --git a/x/upgrade/types/storeloader.go b/x/upgrade/types/storeloader.go index 2d533c7f045d..0c918e3ef3f3 100644 --- a/x/upgrade/types/storeloader.go +++ b/x/upgrade/types/storeloader.go @@ -12,7 +12,7 @@ func UpgradeStoreOption(upgradeHeight uint64, storeUpgrades *storetypes.StoreUpg // Check if the current commit version and upgrade height matches if upgradeHeight == loadHeight+1 { if len(storeUpgrades.Renamed) > 0 || len(storeUpgrades.Deleted) > 0 || len(storeUpgrades.Added) > 0 { - par.Upgrades = append(par.Upgrades, *storeUpgrades) + par.Upgrades = storeUpgrades } } return nil diff --git a/x/upgrade/types/storeloader_test.go b/x/upgrade/types/storeloader_test.go index 8305337c47fd..898c20e16725 100644 --- a/x/upgrade/types/storeloader_test.go +++ b/x/upgrade/types/storeloader_test.go @@ -30,7 +30,7 @@ func defaultLogger() log.Logger { func initStore(t *testing.T, db dbm.DBConnection, config multi.StoreParams, storeKey string, k, v []byte) { key := sdk.NewKVStoreKey(storeKey) - rs, err := multi.NewStore(db, config) + rs, err := multi.NewV1MultiStoreAsV2(db, config) require.NoError(t, err) rs.SetPruning(storetypes.PruneNothing) require.Equal(t, int64(0), rs.LastCommitID().Version) @@ -46,7 +46,7 @@ func initStore(t *testing.T, db dbm.DBConnection, config multi.StoreParams, stor func checkStore(t *testing.T, db dbm.DBConnection, config multi.StoreParams, ver int64, storeKey string, k, v []byte) { key := sdk.NewKVStoreKey(storeKey) - rs, err := multi.NewStore(db, config) + rs, err := multi.NewV1MultiStoreAsV2(db, config) require.NoError(t, err) rs.SetPruning(storetypes.PruneNothing) require.Equal(t, ver, rs.LastCommitID().Version)