From 88c746a992260a9aabcb57898f77e6eda618ef6a Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 30 Sep 2024 13:58:16 -0500 Subject: [PATCH 1/9] refactor(runtime/v2): use StoreBuilder --- runtime/v2/builder.go | 49 ++++--------------------------------- runtime/v2/module.go | 39 +++++++++++++++++++++++------ runtime/v2/store.go | 57 +++++++++++++++++++++++++++++++++++++++++++ runtime/v2/types.go | 2 +- simapp/v2/app_di.go | 52 +++++++++++++-------------------------- 5 files changed, 112 insertions(+), 87 deletions(-) diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index c6fad39f41aa..b28ddbc741b4 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -6,28 +6,22 @@ import ( "errors" "fmt" "io" - "path/filepath" "cosmossdk.io/core/appmodule" appmodulev2 "cosmossdk.io/core/appmodule/v2" - "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" - "cosmossdk.io/store/v2/db" - rootstore "cosmossdk.io/store/v2/root" ) // AppBuilder is a type that is injected into a container by the runtime/v2 module // (as *AppBuilder) which can be used to create an app which is compatible with // the existing app.go initialization conventions. type AppBuilder[T transaction.Tx] struct { - app *App[T] - config server.DynamicConfig - storeOptions *rootstore.Options + app *App[T] // the following fields are used to overwrite the default branch func(state store.ReaderMap) store.WriterMap @@ -99,6 +93,10 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } } + if a.app.db == nil { + return nil, fmt.Errorf("app.db is not set, it is required to build the app") + } + if err := a.app.moduleManager.RegisterServices(a.app); err != nil { return nil, err } @@ -122,37 +120,6 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } a.app.stf = stf - home := a.config.GetString(FlagHome) - scRawDb, err := db.NewDB( - db.DBType(a.config.GetString("store.app-db-backend")), - "application", - filepath.Join(home, "data"), - nil, - ) - if err != nil { - panic(err) - } - - var storeOptions rootstore.Options - if a.storeOptions != nil { - storeOptions = *a.storeOptions - } else { - storeOptions = rootstore.DefaultStoreOptions() - } - factoryOptions := &rootstore.FactoryOptions{ - Logger: a.app.logger, - RootDir: home, - Options: storeOptions, - StoreKeys: append(a.app.storeKeys, "stf"), - SCRawDB: scRawDb, - } - - rs, err := rootstore.CreateRootStore(factoryOptions) - if err != nil { - return nil, fmt.Errorf("failed to create root store: %w", err) - } - a.app.db = rs - appManagerBuilder := appmanager.Builder[T]{ STF: a.app.stf, DB: a.app.db, @@ -251,9 +218,3 @@ func AppBuilderWithPostTxExec[T transaction.Tx](postTxExec func(ctx context.Cont a.postTxExec = postTxExec } } - -func AppBuilderWithStoreOptions[T transaction.Tx](opts *rootstore.Options) AppBuilderOption[T] { - return func(a *AppBuilder[T]) { - a.storeOptions = opts - } -} diff --git a/runtime/v2/module.go b/runtime/v2/module.go index d4a9b4b534d9..8e8b7e0ce832 100644 --- a/runtime/v2/module.go +++ b/runtime/v2/module.go @@ -16,6 +16,7 @@ import ( reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1" appmodulev2 "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/comet" + "cosmossdk.io/core/event" "cosmossdk.io/core/header" "cosmossdk.io/core/registry" "cosmossdk.io/core/server" @@ -26,6 +27,7 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/stf" + rootstore "cosmossdk.io/store/v2/root" ) var ( @@ -40,19 +42,19 @@ type appModule[T transaction.Tx] struct { func (m appModule[T]) IsOnePerModuleType() {} func (m appModule[T]) IsAppModule() {} -func (m appModule[T]) RegisterServices(registar grpc.ServiceRegistrar) error { +func (m appModule[T]) RegisterServices(registrar grpc.ServiceRegistrar) error { autoCliQueryService, err := services.NewAutoCLIQueryService(m.app.moduleManager.modules) if err != nil { return err } - autocliv1.RegisterQueryServer(registar, autoCliQueryService) + autocliv1.RegisterQueryServer(registrar, autoCliQueryService) reflectionSvc, err := services.NewReflectionService() if err != nil { return err } - reflectionv1.RegisterReflectionServiceServer(registar, reflectionSvc) + reflectionv1.RegisterReflectionServiceServer(registrar, reflectionSvc) return nil } @@ -97,6 +99,7 @@ func init() { ProvideAppBuilder[transaction.Tx], ProvideEnvironment[transaction.Tx], ProvideModuleManager[transaction.Tx], + ProvideStoreBuilder, ), appconfig.Invoke(SetupAppBuilder), ) @@ -146,7 +149,12 @@ type AppInputs struct { InterfaceRegistrar registry.InterfaceRegistrar LegacyAmino registry.AminoRegistrar Logger log.Logger - DynamicConfig server.DynamicConfig `optional:"true"` // can be nil in client wiring + // StoreBuilder is a builder for a store/v2 RootStore satisfying the Store interface + StoreBuilder *StoreBuilder + // StoreOptions are required as input for the StoreBuilder. If not provided, the default options are used. + StoreOptions *rootstore.Options `optional:"true"` + // DynamicConfig can be nil in client wiring, but is required in server wiring. + DynamicConfig server.DynamicConfig `optional:"true"` } func SetupAppBuilder(inputs AppInputs) { @@ -157,8 +165,22 @@ func SetupAppBuilder(inputs AppInputs) { app.moduleManager.RegisterInterfaces(inputs.InterfaceRegistrar) app.moduleManager.RegisterLegacyAminoCodec(inputs.LegacyAmino) - if inputs.DynamicConfig != nil { - inputs.AppBuilder.config = inputs.DynamicConfig + if inputs.DynamicConfig == nil { + return + } + storeOptions := rootstore.DefaultStoreOptions() + if inputs.StoreOptions != nil { + storeOptions = *inputs.StoreOptions + } + var err error + app.db, err = inputs.StoreBuilder.Build( + inputs.Logger, + app.storeKeys, + inputs.DynamicConfig, + storeOptions, + ) + if err != nil { + panic(err) } } @@ -178,6 +200,7 @@ func ProvideEnvironment[T transaction.Tx]( appBuilder *AppBuilder[T], kvFactory store.KVStoreServiceFactory, headerService header.Service, + eventService event.Service, ) ( appmodulev2.Environment, store.KVStoreService, @@ -209,7 +232,7 @@ func ProvideEnvironment[T transaction.Tx]( env := appmodulev2.Environment{ Logger: logger, BranchService: stf.BranchService{}, - EventService: stf.NewEventService(), + EventService: eventService, GasService: stf.NewGasMeterService(), HeaderService: headerService, QueryRouterService: stf.NewQueryRouterService(), @@ -254,10 +277,12 @@ func DefaultServiceBindings() depinject.Config { } headerService header.Service = services.NewGenesisHeaderService(stf.HeaderService{}) cometService comet.Service = &services.ContextAwareCometInfoService{} + eventService = stf.NewEventService() ) return depinject.Supply( kvServiceFactory, headerService, cometService, + eventService, ) } diff --git a/runtime/v2/store.go b/runtime/v2/store.go index 40912ea41f48..6c45dd5e72db 100644 --- a/runtime/v2/store.go +++ b/runtime/v2/store.go @@ -3,11 +3,16 @@ package runtime import ( "errors" "fmt" + "path/filepath" + "cosmossdk.io/core/server" "cosmossdk.io/core/store" + "cosmossdk.io/log" "cosmossdk.io/server/v2/stf" storev2 "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/db" "cosmossdk.io/store/v2/proof" + "cosmossdk.io/store/v2/root" ) // NewKVStoreService creates a new KVStoreService. @@ -59,6 +64,58 @@ type Store interface { LastCommitID() (proof.CommitID, error) } +// StoreBuilder is a builder for a store/v2 RootStore satisfying the Store interface. +type StoreBuilder struct { + store Store +} + +// Build creates a new store/v2 RootStore. +func (sb *StoreBuilder) Build( + logger log.Logger, + storeKeys []string, + config server.DynamicConfig, + options root.Options, +) (Store, error) { + if sb.store != nil { + return sb.store, nil + } + home := config.GetString(flagHome) + scRawDb, err := db.NewDB( + db.DBType(config.GetString("store.app-db-backend")), + "application", + filepath.Join(home, "data"), + nil, + ) + if err != nil { + return nil, fmt.Errorf("failed to create SCRawDB: %w", err) + } + + factoryOptions := &root.FactoryOptions{ + Logger: logger, + RootDir: home, + Options: options, + // STF needs to store a bit of state + StoreKeys: append(storeKeys, "stf"), + SCRawDB: scRawDb, + } + + rs, err := root.CreateRootStore(factoryOptions) + if err != nil { + return nil, fmt.Errorf("failed to create root store: %w", err) + } + sb.store = rs + return sb.store, nil +} + +// Get returns the Store. Build must be called before calling Get or the result will be nil. +func (sb *StoreBuilder) Get() Store { + return sb.store +} + +func ProvideStoreBuilder() *StoreBuilder { + return &StoreBuilder{} +} + // StoreLoader allows for custom loading of the store, this is useful when upgrading the store from a previous version type StoreLoader func(store Store) error diff --git a/runtime/v2/types.go b/runtime/v2/types.go index baa20182b512..9018af921b1c 100644 --- a/runtime/v2/types.go +++ b/runtime/v2/types.go @@ -14,7 +14,7 @@ import ( const ( ModuleName = "runtime" - FlagHome = "home" + flagHome = "home" ) // validateProtoAnnotations validates that the proto annotations are correct. diff --git a/simapp/v2/app_di.go b/simapp/v2/app_di.go index a2fbb958dc0d..ff29df3c98d2 100644 --- a/simapp/v2/app_di.go +++ b/simapp/v2/app_di.go @@ -13,9 +13,6 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2" "cosmossdk.io/store/v2/root" - basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject" - lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject" - multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject" upgradekeeper "cosmossdk.io/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/client" @@ -64,10 +61,9 @@ func NewSimApp[T transaction.Tx]( viper *viper.Viper, ) *SimApp[T] { var ( - app = &SimApp[T]{} - appBuilder *runtime.AppBuilder[T] - err error - storeOptions = &root.Options{} + app = &SimApp[T]{} + appBuilder *runtime.AppBuilder[T] + err error // merge the AppConfig and other configuration in one config appConfig = depinject.Configs( @@ -122,25 +118,6 @@ func NewSimApp[T transaction.Tx]( codec.ProvideAddressCodec, codec.ProvideProtoCodec, codec.ProvideLegacyAmino, - // inject desired account types: - multisigdepinject.ProvideAccount, - basedepinject.ProvideAccount, - lockupdepinject.ProvideAllLockupAccounts, - - // provide base account options - basedepinject.ProvideSecp256K1PubKey, - // if you want to provide a custom public key you - // can do it from here. - // Example: - // basedepinject.ProvideCustomPubkey[Ed25519PublicKey]() - // - // You can also provide a custom public key with a custom validation function: - // - // basedepinject.ProvideCustomPubKeyAndValidationFunc(func(pub Ed25519PublicKey) error { - // if len(pub.Key) != 64 { - // return fmt.Errorf("invalid pub key size") - // } - // }) ), depinject.Invoke( std.RegisterInterfaces, @@ -149,6 +126,19 @@ func NewSimApp[T transaction.Tx]( ) ) + // the subsection of config that contains the store options (in app.toml [store.options] header) + // is unmarshaled into a store.Options struct and passed to the store builder. + // future work may move this specification and retrieval into store/v2. + // If these options are not specified then default values will be used. + if sub := viper.Sub("store.options"); sub != nil { + storeOptions := &root.Options{} + err := sub.Unmarshal(storeOptions) + if err != nil { + panic(err) + } + appConfig = depinject.Configs(appConfig, depinject.Supply(storeOptions)) + } + if err := depinject.Inject(appConfig, &appBuilder, &app.appCodec, @@ -160,15 +150,7 @@ func NewSimApp[T transaction.Tx]( panic(err) } - var builderOpts []runtime.AppBuilderOption[T] - if sub := viper.Sub("store.options"); sub != nil { - err = sub.Unmarshal(storeOptions) - if err != nil { - panic(err) - } - builderOpts = append(builderOpts, runtime.AppBuilderWithStoreOptions[T](storeOptions)) - } - app.App, err = appBuilder.Build(builderOpts...) + app.App, err = appBuilder.Build() if err != nil { panic(err) } From fe2f1226b90274c39550c8d1fe6dff833dc879fc Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Mon, 30 Sep 2024 14:00:48 -0500 Subject: [PATCH 2/9] merge main --- simapp/v2/app_di.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/simapp/v2/app_di.go b/simapp/v2/app_di.go index ff29df3c98d2..43ca45f99aed 100644 --- a/simapp/v2/app_di.go +++ b/simapp/v2/app_di.go @@ -13,6 +13,9 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2" "cosmossdk.io/store/v2/root" + basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject" + lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject" + multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject" upgradekeeper "cosmossdk.io/x/upgrade/keeper" "github.com/cosmos/cosmos-sdk/client" @@ -118,6 +121,25 @@ func NewSimApp[T transaction.Tx]( codec.ProvideAddressCodec, codec.ProvideProtoCodec, codec.ProvideLegacyAmino, + // inject desired account types: + multisigdepinject.ProvideAccount, + basedepinject.ProvideAccount, + lockupdepinject.ProvideAllLockupAccounts, + + // provide base account options + basedepinject.ProvideSecp256K1PubKey, + // if you want to provide a custom public key you + // can do it from here. + // Example: + // basedepinject.ProvideCustomPubkey[Ed25519PublicKey]() + // + // You can also provide a custom public key with a custom validation function: + // + // basedepinject.ProvideCustomPubKeyAndValidationFunc(func(pub Ed25519PublicKey) error { + // if len(pub.Key) != 64 { + // return fmt.Errorf("invalid pub key size") + // } + // }) ), depinject.Invoke( std.RegisterInterfaces, From 5d471b5d31150e89969b344fdd1a7404afa57561 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Tue, 1 Oct 2024 10:32:09 -0500 Subject: [PATCH 3/9] remove GetStore() any from AppI interface --- server/v2/cometbft/server.go | 16 +++++++++++----- server/v2/cometbft/types/store.go | 8 ++------ server/v2/commands.go | 2 +- server/v2/server_test.go | 2 +- server/v2/store/server.go | 16 ++++++++-------- server/v2/store/snapshot.go | 14 +++++++++----- server/v2/types.go | 1 - simapp/v2/simdv2/cmd/commands.go | 7 +++++-- simapp/v2/simdv2/cmd/root_di.go | 5 ++++- store/v2/store.go | 20 ++++++++++++-------- 10 files changed, 53 insertions(+), 38 deletions(-) diff --git a/server/v2/cometbft/server.go b/server/v2/cometbft/server.go index 21b6d59ddc72..484801cc87b4 100644 --- a/server/v2/cometbft/server.go +++ b/server/v2/cometbft/server.go @@ -43,14 +43,21 @@ type CometBFTServer[T transaction.Tx] struct { initTxCodec transaction.Codec[T] logger log.Logger + store types.Store serverOptions ServerOptions[T] config Config cfgOptions []CfgOption } -func New[T transaction.Tx](txCodec transaction.Codec[T], serverOptions ServerOptions[T], cfgOptions ...CfgOption) *CometBFTServer[T] { +func New[T transaction.Tx]( + txCodec transaction.Codec[T], + store types.Store, + serverOptions ServerOptions[T], + cfgOptions ...CfgOption, +) *CometBFTServer[T] { return &CometBFTServer[T]{ initTxCodec: txCodec, + store: store, serverOptions: serverOptions, cfgOptions: cfgOptions, } @@ -98,7 +105,6 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg } s.logger = logger.With(log.ModuleKey, s.Name()) - store := appI.GetStore().(types.Store) consensus := NewConsensus( s.logger, appI.Name(), @@ -106,7 +112,7 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg s.serverOptions.Mempool(cfg), indexEvents, appI.GetGPRCMethodsToMessageMap(), - store, + s.store, s.config, s.initTxCodec, chainID, @@ -118,8 +124,8 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg consensus.addrPeerFilter = s.serverOptions.AddrPeerFilter consensus.idPeerFilter = s.serverOptions.IdPeerFilter - ss := store.GetStateStorage().(snapshots.StorageSnapshotter) - sc := store.GetStateCommitment().(snapshots.CommitSnapshotter) + ss := s.store.GetStateStorage().(snapshots.StorageSnapshotter) + sc := s.store.GetStateCommitment().(snapshots.CommitSnapshotter) snapshotStore, err := GetSnapshotStore(s.config.ConfigTomlConfig.RootDir) if err != nil { diff --git a/server/v2/cometbft/types/store.go b/server/v2/cometbft/types/store.go index ff06163af5ab..3e603ff18ced 100644 --- a/server/v2/cometbft/types/store.go +++ b/server/v2/cometbft/types/store.go @@ -7,6 +7,8 @@ import ( ) type Store interface { + storev2.Backend + // GetLatestVersion returns the latest version that consensus has been made on GetLatestVersion() (uint64, error) // StateLatest returns a readonly view over the latest @@ -30,10 +32,4 @@ type Store interface { // LastCommitID returns a CommitID pertaining to the last commitment. LastCommitID() (proof.CommitID, error) - - // GetStateStorage returns the SS backend. - GetStateStorage() storev2.VersionedDatabase - - // GetStateCommitment returns the SC backend. - GetStateCommitment() storev2.Committer } diff --git a/server/v2/commands.go b/server/v2/commands.go index da8e0ec6e537..0357fe180d93 100644 --- a/server/v2/commands.go +++ b/server/v2/commands.go @@ -33,7 +33,7 @@ func Execute(rootCmd *cobra.Command, envPrefix, defaultHome string) error { } // AddCommands add the server commands to the root command -// It configure the config handling and the logger handling +// It configures the config handling and the logger handling func AddCommands[T transaction.Tx]( rootCmd *cobra.Command, newApp AppCreator[T], diff --git a/server/v2/server_test.go b/server/v2/server_test.go index e84bcd598890..df78f691a9d9 100644 --- a/server/v2/server_test.go +++ b/server/v2/server_test.go @@ -63,7 +63,7 @@ func TestServer(t *testing.T) { err = grpcServer.Init(&mockApp[transaction.Tx]{}, cfg, logger) require.NoError(t, err) - storeServer := store.New[transaction.Tx](nil /* nil appCreator as not using CLI commands */) + storeServer := store.New[transaction.Tx](nil /* nil store is not using CLI commands */) err = storeServer.Init(&mockApp[transaction.Tx]{}, cfg, logger) require.NoError(t, err) diff --git a/server/v2/store/server.go b/server/v2/store/server.go index c50a53dc6e24..6c9e7b23a0af 100644 --- a/server/v2/store/server.go +++ b/server/v2/store/server.go @@ -9,6 +9,7 @@ import ( "cosmossdk.io/core/transaction" "cosmossdk.io/log" serverv2 "cosmossdk.io/server/v2" + storev2 "cosmossdk.io/store/v2" ) var ( @@ -22,15 +23,14 @@ const ServerName = "store" // Server manages store config and contains prune & snapshot commands type Server[T transaction.Tx] struct { config *Config - // saving appCreator for only RestoreSnapshotCmd - appCreator serverv2.AppCreator[T] + store storev2.Backend } -func New[T transaction.Tx](appCreator serverv2.AppCreator[T]) *Server[T] { - return &Server[T]{appCreator: appCreator} +func New[T transaction.Tx](store storev2.Backend) *Server[T] { + return &Server[T]{store: store} } -func (s *Server[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logger log.Logger) error { +func (s *Server[T]) Init(_ serverv2.AppI[T], cfg map[string]any, _ log.Logger) error { serverCfg := s.Config().(*Config) if len(cfg) > 0 { if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &serverCfg); err != nil { @@ -46,11 +46,11 @@ func (s *Server[T]) Name() string { return ServerName } -func (s *Server[T]) Start(ctx context.Context) error { +func (s *Server[T]) Start(context.Context) error { return nil } -func (s *Server[T]) Stop(ctx context.Context) error { +func (s *Server[T]) Stop(context.Context) error { return nil } @@ -63,7 +63,7 @@ func (s *Server[T]) CLICommands() serverv2.CLIConfig { s.ListSnapshotsCmd(), s.DumpArchiveCmd(), s.LoadArchiveCmd(), - s.RestoreSnapshotCmd(s.appCreator), + s.RestoreSnapshotCmd(s.store), }, } } diff --git a/server/v2/store/snapshot.go b/server/v2/store/snapshot.go index b804e34b71c8..e7958068e56a 100644 --- a/server/v2/store/snapshot.go +++ b/server/v2/store/snapshot.go @@ -76,7 +76,7 @@ func (s *Server[T]) ExportSnapshotCmd() *cobra.Command { } // RestoreSnapshotCmd returns a command to restore a snapshot -func (s *Server[T]) RestoreSnapshotCmd(newApp serverv2.AppCreator[T]) *cobra.Command { +func (s *Server[T]) RestoreSnapshotCmd(rootStore storev2.Backend) *cobra.Command { cmd := &cobra.Command{ Use: "restore ", Short: "Restore app state from local snapshot", @@ -95,8 +95,6 @@ func (s *Server[T]) RestoreSnapshotCmd(newApp serverv2.AppCreator[T]) *cobra.Com } logger := log.NewLogger(cmd.OutOrStdout()) - app := newApp(logger, v) - rootStore := app.GetStore().(storev2.RootStore) sm, err := createSnapshotsManager(cmd, v, logger, rootStore) if err != nil { @@ -350,7 +348,9 @@ func (s *Server[T]) LoadArchiveCmd() *cobra.Command { } } -func createSnapshotsManager(cmd *cobra.Command, v *viper.Viper, logger log.Logger, store storev2.RootStore) (*snapshots.Manager, error) { +func createSnapshotsManager( + cmd *cobra.Command, v *viper.Viper, logger log.Logger, store storev2.Backend, +) (*snapshots.Manager, error) { home := v.GetString(serverv2.FlagHome) snapshotStore, err := snapshots.NewStore(filepath.Join(home, "data", "snapshots")) if err != nil { @@ -371,7 +371,11 @@ func createSnapshotsManager(cmd *cobra.Command, v *viper.Viper, logger log.Logge } } - sm := snapshots.NewManager(snapshotStore, snapshots.NewSnapshotOptions(interval, uint32(keepRecent)), store.GetStateCommitment().(snapshots.CommitSnapshotter), store.GetStateStorage().(snapshots.StorageSnapshotter), nil, logger) + sm := snapshots.NewManager( + snapshotStore, snapshots.NewSnapshotOptions(interval, uint32(keepRecent)), + store.GetStateCommitment().(snapshots.CommitSnapshotter), + store.GetStateStorage().(snapshots.StorageSnapshotter), + nil, logger) return sm, nil } diff --git a/server/v2/types.go b/server/v2/types.go index afa82969131a..8ef31eb35ae6 100644 --- a/server/v2/types.go +++ b/server/v2/types.go @@ -17,5 +17,4 @@ type AppI[T transaction.Tx] interface { InterfaceRegistry() server.InterfaceRegistry GetAppManager() *appmanager.AppManager[T] GetGPRCMethodsToMessageMap() map[string]func() gogoproto.Message - GetStore() any } diff --git a/simapp/v2/simdv2/cmd/commands.go b/simapp/v2/simdv2/cmd/commands.go index addc7eeb768b..07bdbf8f5f04 100644 --- a/simapp/v2/simdv2/cmd/commands.go +++ b/simapp/v2/simdv2/cmd/commands.go @@ -17,7 +17,8 @@ import ( "cosmossdk.io/server/v2/api/grpc" "cosmossdk.io/server/v2/api/telemetry" "cosmossdk.io/server/v2/cometbft" - "cosmossdk.io/server/v2/store" + cometbfttypes "cosmossdk.io/server/v2/cometbft/types" + serverstore "cosmossdk.io/server/v2/store" "cosmossdk.io/simapp/v2" confixcmd "cosmossdk.io/tools/confix/cmd" @@ -43,6 +44,7 @@ func newApp[T transaction.Tx](logger log.Logger, viper *viper.Viper) serverv2.Ap func initRootCmd[T transaction.Tx]( rootCmd *cobra.Command, txConfig client.TxConfig, + store cometbfttypes.Store, moduleManager *runtimev2.MM[T], ) { cfg := sdk.GetConfig() @@ -77,11 +79,12 @@ func initRootCmd[T transaction.Tx]( initServerConfig(), cometbft.New( &genericTxDecoder[T]{txConfig}, + store, initCometOptions[T](), initCometConfig(), ), grpc.New[T](), - store.New[T](newApp), + serverstore.New[T](store), telemetry.New[T](), ); err != nil { panic(err) diff --git a/simapp/v2/simdv2/cmd/root_di.go b/simapp/v2/simdv2/cmd/root_di.go index 1ad834b53a5a..fab974e007ad 100644 --- a/simapp/v2/simdv2/cmd/root_di.go +++ b/simapp/v2/simdv2/cmd/root_di.go @@ -32,6 +32,7 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command { autoCliOpts autocli.AppOptions moduleManager *runtime.MM[T] clientCtx client.Context + storeBuilder runtime.StoreBuilder ) if err := depinject.Inject( @@ -51,6 +52,7 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command { std.RegisterLegacyAminoCodec, ), ), + &storeBuilder, &autoCliOpts, &moduleManager, &clientCtx, @@ -83,7 +85,8 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command { }, } - initRootCmd(rootCmd, clientCtx.TxConfig, moduleManager) + store := storeBuilder.Get() + initRootCmd(rootCmd, clientCtx.TxConfig, store, moduleManager) nodeCmds := nodeservice.NewNodeCommands() autoCliOpts.ModuleOptions = make(map[string]*autocliv1.ModuleOptions) diff --git a/store/v2/store.go b/store/v2/store.go index fee3ad39dbf2..1adf44f0b89b 100644 --- a/store/v2/store.go +++ b/store/v2/store.go @@ -12,6 +12,9 @@ import ( // RootStore defines an abstraction layer containing a State Storage (SS) engine // and one or more State Commitment (SC) engines. type RootStore interface { + Pruner + Backend + // StateLatest returns a read-only version of the RootStore at the latest // height, alongside the associated version. StateLatest() (uint64, corestore.ReaderMap, error) @@ -21,12 +24,6 @@ type RootStore interface { // an error must be returned. StateAt(version uint64) (corestore.ReaderMap, error) - // GetStateStorage returns the SS backend. - GetStateStorage() VersionedDatabase - - // GetStateCommitment returns the SC backend. - GetStateCommitment() Committer - // Query performs a query on the RootStore for a given store key, version (height), // and key tuple. Queries should be routed to the underlying SS engine. Query(storeKey []byte, version uint64, key []byte, prove bool) (QueryResult, error) @@ -67,11 +64,18 @@ type RootStore interface { // SetMetrics sets the telemetry handler on the RootStore. SetMetrics(m metrics.Metrics) - Prune(version uint64) error - io.Closer } +// Backend defines the interface for the RootStore backends. +type Backend interface { + // GetStateStorage returns the SS backend. + GetStateStorage() VersionedDatabase + + // GetStateCommitment returns the SC backend. + GetStateCommitment() Committer +} + // UpgradeableStore defines the interface for upgrading store keys. type UpgradeableStore interface { // LoadVersionAndUpgrade behaves identically to LoadVersion except it also From c8c207c72b16a9fc023f29220d8e118756fe335a Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Tue, 1 Oct 2024 13:35:31 -0500 Subject: [PATCH 4/9] fix testnet.go --- simapp/v2/simdv2/cmd/commands.go | 2 +- simapp/v2/simdv2/cmd/testnet.go | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/simapp/v2/simdv2/cmd/commands.go b/simapp/v2/simdv2/cmd/commands.go index 07bdbf8f5f04..8c3575179b20 100644 --- a/simapp/v2/simdv2/cmd/commands.go +++ b/simapp/v2/simdv2/cmd/commands.go @@ -54,7 +54,7 @@ func initRootCmd[T transaction.Tx]( genutilcli.InitCmd(moduleManager), debug.Cmd(), confixcmd.ConfigCommand(), - NewTestnetCmd(moduleManager), + NewTestnetCmd(store, moduleManager), ) logger, err := serverv2.NewLogger(viper.New(), rootCmd.OutOrStdout()) diff --git a/simapp/v2/simdv2/cmd/testnet.go b/simapp/v2/simdv2/cmd/testnet.go index ae01310f9151..67c8b0e85517 100644 --- a/simapp/v2/simdv2/cmd/testnet.go +++ b/simapp/v2/simdv2/cmd/testnet.go @@ -22,6 +22,7 @@ import ( serverv2 "cosmossdk.io/server/v2" "cosmossdk.io/server/v2/api/grpc" "cosmossdk.io/server/v2/cometbft" + cometbfttypes "cosmossdk.io/server/v2/cometbft/types" "cosmossdk.io/server/v2/store" banktypes "cosmossdk.io/x/bank/types" bankv2types "cosmossdk.io/x/bank/v2/types" @@ -87,7 +88,7 @@ func addTestnetFlagsToCmd(cmd *cobra.Command) { // NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize // validator configuration files for running a multi-validator testnet in a separate process -func NewTestnetCmd[T transaction.Tx](mm *runtimev2.MM[T]) *cobra.Command { +func NewTestnetCmd[T transaction.Tx](rs cometbfttypes.Store, mm *runtimev2.MM[T]) *cobra.Command { testnetCmd := &cobra.Command{ Use: "testnet", Short: "subcommands for starting or configuring local testnets", @@ -96,13 +97,13 @@ func NewTestnetCmd[T transaction.Tx](mm *runtimev2.MM[T]) *cobra.Command { RunE: client.ValidateCmd, } - testnetCmd.AddCommand(testnetInitFilesCmd(mm)) + testnetCmd.AddCommand(testnetInitFilesCmd(rs, mm)) return testnetCmd } // testnetInitFilesCmd returns a cmd to initialize all files for CometBFT testnet and application -func testnetInitFilesCmd[T transaction.Tx](mm *runtimev2.MM[T]) *cobra.Command { +func testnetInitFilesCmd[T transaction.Tx](rs cometbfttypes.Store, mm *runtimev2.MM[T]) *cobra.Command { cmd := &cobra.Command{ Use: "init-files", Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)", @@ -143,7 +144,7 @@ Example: return err } - return initTestnetFiles(clientCtx, cmd, config, mm, args) + return initTestnetFiles(clientCtx, rs, cmd, config, mm, args) }, } @@ -165,6 +166,7 @@ const nodeDirPerm = 0o755 // initTestnetFiles initializes testnet files for a testnet to be run in a separate process func initTestnetFiles[T transaction.Tx]( clientCtx client.Context, + rootStore cometbfttypes.Store, cmd *cobra.Command, nodeConfig *cmtconfig.Config, mm *runtimev2.MM[T], @@ -339,10 +341,11 @@ func initTestnetFiles[T transaction.Tx]( // Write server config cometServer := cometbft.New[T]( &genericTxDecoder[T]{clientCtx.TxConfig}, + rootStore, cometbft.ServerOptions[T]{}, cometbft.OverwriteDefaultConfigTomlConfig(nodeConfig), ) - storeServer := store.New[T](newApp) + storeServer := store.New[T](rootStore) grpcServer := grpc.New[T](grpc.OverwriteDefaultConfig(grpcConfig)) server := serverv2.NewServer(log.NewNopLogger(), serverCfg, cometServer, grpcServer, storeServer) err = server.WriteConfig(filepath.Join(nodeDir, "config")) From ddab5ee4d8874e379fbab9b525c41d0302d6cb6e Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Wed, 2 Oct 2024 14:17:36 -0500 Subject: [PATCH 5/9] big store config refactor --- .vscode/launch.json | 3 +- runtime/v2/app.go | 21 ------ runtime/v2/builder.go | 27 +++---- runtime/v2/go.mod | 11 ++- runtime/v2/go.sum | 24 +++---- runtime/v2/module.go | 118 +++++++++++-------------------- runtime/v2/store.go | 57 --------------- server/v2/cometbft/server.go | 17 +++-- server/v2/config_test.go | 7 +- server/v2/go.mod | 1 + server/v2/server.go | 1 + server/v2/store/config.go | 17 ----- server/v2/store/server.go | 36 ++++++---- simapp/v2/app_di.go | 65 ++++++++++------- simapp/v2/go.mod | 6 +- simapp/v2/go.sum | 8 +-- simapp/v2/simdv2/cmd/commands.go | 10 +-- simapp/v2/simdv2/cmd/root_di.go | 20 ++---- simapp/v2/simdv2/cmd/testnet.go | 18 ++--- store/v2/db/db.go | 2 +- store/v2/go.mod | 1 + store/v2/go.sum | 2 + store/v2/root/builder.go | 85 ++++++++++++++++++++++ store/v2/root/config.go | 14 ++++ store/v2/root/factory.go | 2 +- 25 files changed, 284 insertions(+), 289 deletions(-) delete mode 100644 server/v2/store/config.go create mode 100644 store/v2/root/builder.go create mode 100644 store/v2/root/config.go diff --git a/.vscode/launch.json b/.vscode/launch.json index a5e7a729457b..0abc181d7dd6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,7 +18,8 @@ "request": "launch", "mode": "debug", "program": "${workspaceFolder}/simapp/v2/simdv2", - "args": ["start"], + "args": ["config", "set", "client", "simapp-v2-chain"], + // "args": ["start"], "buildFlags": "" }, { diff --git a/runtime/v2/app.go b/runtime/v2/app.go index b7104f9e4774..6d072a0b7215 100644 --- a/runtime/v2/app.go +++ b/runtime/v2/app.go @@ -2,9 +2,6 @@ package runtime import ( "encoding/json" - "errors" - "slices" - gogoproto "github.com/cosmos/gogoproto/proto" runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2" @@ -37,8 +34,6 @@ type App[T transaction.Tx] struct { logger log.Logger config *runtimev2.Module - // modules configuration - storeKeys []string interfaceRegistrar registry.InterfaceRegistrar amino registry.AminoRegistrar moduleManager *MM[T] @@ -95,22 +90,6 @@ func (a *App[T]) Close() error { return nil } -// GetStoreKeys returns all the app store keys. -func (a *App[T]) GetStoreKeys() []string { - return a.storeKeys -} - -// UnsafeFindStoreKey fetches a registered StoreKey from the App in linear time. -// NOTE: This should only be used in testing. -func (a *App[T]) UnsafeFindStoreKey(storeKey string) (string, error) { - i := slices.IndexFunc(a.storeKeys, func(s string) bool { return s == storeKey }) - if i == -1 { - return "", errors.New("store key not found") - } - - return a.storeKeys[i], nil -} - // GetStore returns the app store. func (a *App[T]) GetStore() Store { return a.db diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index b28ddbc741b4..8d8df8fbaf3b 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -2,6 +2,7 @@ package runtime import ( "context" + "cosmossdk.io/store/v2/root" "encoding/json" "errors" "fmt" @@ -21,7 +22,8 @@ import ( // (as *AppBuilder) which can be used to create an app which is compatible with // the existing app.go initialization conventions. type AppBuilder[T transaction.Tx] struct { - app *App[T] + app *App[T] + storeBuilder root.Builder // the following fields are used to overwrite the default branch func(state store.ReaderMap) store.WriterMap @@ -62,14 +64,6 @@ func (a *AppBuilder[T]) RegisterModules(modules map[string]appmodulev2.AppModule return nil } -// RegisterStores registers the provided store keys. -// This method should only be used for registering extra stores -// which is necessary for modules that not registered using the app config. -// To be used in combination of RegisterModules. -func (a *AppBuilder[T]) RegisterStores(keys ...string) { - a.app.storeKeys = append(a.app.storeKeys, keys...) -} - // Build builds an *App instance. func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { for _, opt := range opts { @@ -93,8 +87,9 @@ func (a *AppBuilder[T]) Build(opts ...AppBuilderOption[T]) (*App[T], error) { } } + a.app.db = a.storeBuilder.Get() if a.app.db == nil { - return nil, fmt.Errorf("app.db is not set, it is required to build the app") + return nil, fmt.Errorf("storeBuilder did not return a db") } if err := a.app.moduleManager.RegisterServices(a.app); err != nil { @@ -205,7 +200,11 @@ func AppBuilderWithBranch[T transaction.Tx](branch func(state store.ReaderMap) s // AppBuilderWithTxValidator sets the tx validator for the app. // It overrides all default tx validators defined by modules. -func AppBuilderWithTxValidator[T transaction.Tx](txValidators func(ctx context.Context, tx T) error) AppBuilderOption[T] { +func AppBuilderWithTxValidator[T transaction.Tx]( + txValidators func( + ctx context.Context, tx T, + ) error, +) AppBuilderOption[T] { return func(a *AppBuilder[T]) { a.txValidator = txValidators } @@ -213,7 +212,11 @@ func AppBuilderWithTxValidator[T transaction.Tx](txValidators func(ctx context.C // AppBuilderWithPostTxExec sets logic that will be executed after each transaction. // When not provided, a no-op function will be used. -func AppBuilderWithPostTxExec[T transaction.Tx](postTxExec func(ctx context.Context, tx T, success bool) error) AppBuilderOption[T] { +func AppBuilderWithPostTxExec[T transaction.Tx]( + postTxExec func( + ctx context.Context, tx T, success bool, + ) error, +) AppBuilderOption[T] { return func(a *AppBuilder[T]) { a.postTxExec = postTxExec } diff --git a/runtime/v2/go.mod b/runtime/v2/go.mod index ce6c55b50cc2..c6cfffa7d190 100644 --- a/runtime/v2/go.mod +++ b/runtime/v2/go.mod @@ -5,7 +5,6 @@ go 1.23 // server v2 integration replace ( cosmossdk.io/api => ../../api - cosmossdk.io/core => ../../core cosmossdk.io/server/v2/appmanager => ../../server/v2/appmanager cosmossdk.io/server/v2/stf => ../../server/v2/stf cosmossdk.io/store/v2 => ../../store/v2 @@ -14,7 +13,7 @@ replace ( require ( cosmossdk.io/api v0.7.6 - cosmossdk.io/core v1.0.0-alpha.3 + cosmossdk.io/core v1.0.0-alpha.3.0.20241001191548-a0f96930ab2d cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/server/v2/appmanager v0.0.0-00010101000000-000000000000 @@ -22,7 +21,7 @@ require ( cosmossdk.io/store/v2 v2.0.0-00010101000000-000000000000 cosmossdk.io/x/tx v0.13.3 github.com/cosmos/gogoproto v1.7.0 - google.golang.org/grpc v1.67.0 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.34.2 ) @@ -41,12 +40,13 @@ require ( github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect - github.com/cosmos/iavl v1.3.0 // indirect + github.com/cosmos/iavl v1.0.0-beta.1.0.20240813194616-eb5078efcf9e // indirect github.com/cosmos/ics23/go v0.11.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/dot v1.6.2 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect @@ -61,7 +61,6 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/onsi/gomega v1.28.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.20.4 // indirect @@ -82,7 +81,7 @@ require ( golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.18.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/runtime/v2/go.sum b/runtime/v2/go.sum index bd09e3bf2626..a2e7dd63cfdc 100644 --- a/runtime/v2/go.sum +++ b/runtime/v2/go.sum @@ -2,6 +2,8 @@ buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fed buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.2-20240701160653-fedbb9acfd2f.2/go.mod h1:1+3gJj2NvZ1mTLAtHu+lMhOjGgQPiCKCeo+9MBww0Eo= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2 h1:b7EEYTUHmWSBEyISHlHvXbJPqtKiHRuUignL1tsHnNQ= buf.build/gen/go/cosmos/gogo-proto/protocolbuffers/go v1.34.2-20240130113600-88ef6483f90f.2/go.mod h1:HqcXMSa5qnNuakaMUo+hWhF51mKbcrZxGl9Vp5EeJXc= +cosmossdk.io/core v1.0.0-alpha.3.0.20241001191548-a0f96930ab2d h1:9xHjYe7R9IdYIRrmF7DxioIi65QcoE8qiubsitbjxUg= +cosmossdk.io/core v1.0.0-alpha.3.0.20241001191548-a0f96930ab2d/go.mod h1:3u9cWq1FAVtiiCrDPpo4LhR+9V6k/ycSG4/Y/tREWCY= cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29 h1:NxxUo0GMJUbIuVg0R70e3cbn9eFTEuMr7ev1AFvypdY= cosmossdk.io/core/testing v0.0.0-20240923163230-04da382a9f29/go.mod h1:8s2tPeJtSiQuoyPmr2Ag7meikonISO4Fv4MoO8+ORrs= cosmossdk.io/depinject v1.0.0 h1:dQaTu6+O6askNXO06+jyeUAnF2/ssKwrrszP9t5q050= @@ -48,8 +50,8 @@ github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+R github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= -github.com/cosmos/iavl v1.3.0 h1:Ezaxt8aPA3kbkhsfyqwenChGLQwHDAIif3tG9x1FMV8= -github.com/cosmos/iavl v1.3.0/go.mod h1:T6SfBcyhulVIY2G/ZtAtQm/QiJvsuhIos52V4dWYk88= +github.com/cosmos/iavl v1.0.0-beta.1.0.20240813194616-eb5078efcf9e h1:LEii0v/FxtXa/F7mRn+tijZ0zaXBPn2ZkKwb6Qm4rqE= +github.com/cosmos/iavl v1.0.0-beta.1.0.20240813194616-eb5078efcf9e/go.mod h1:3ywr0wDnWeD7MUH6qu50wZ5bxuKH3LBrGG4/lZX8lVY= github.com/cosmos/ics23/go v0.11.0 h1:jk5skjT0TqX5e5QJbEnwXIS2yI2vnmLOgpQPeM5RtnU= github.com/cosmos/ics23/go v0.11.0/go.mod h1:A8OjxPE67hHST4Icw94hOxxFEJMBG031xIGF/JHNIY0= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -80,8 +82,6 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -94,8 +94,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= @@ -174,8 +174,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.28.1 h1:MijcGUbfYuznzK/5R4CPNoUP/9Xvuo20sXfEm6XxoTA= -github.com/onsi/gomega v1.28.1/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= @@ -315,10 +315,10 @@ golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNq google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 h1:N9BgCIAUvn/M+p4NJccWPWb3BWh88+zyL0ll9HgbEeM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/runtime/v2/module.go b/runtime/v2/module.go index 8e8b7e0ce832..525c3561e81f 100644 --- a/runtime/v2/module.go +++ b/runtime/v2/module.go @@ -1,6 +1,7 @@ package runtime import ( + "cosmossdk.io/store/v2/root" "fmt" "os" "slices" @@ -19,7 +20,6 @@ import ( "cosmossdk.io/core/event" "cosmossdk.io/core/header" "cosmossdk.io/core/registry" - "cosmossdk.io/core/server" "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" "cosmossdk.io/depinject" @@ -27,7 +27,6 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/stf" - rootstore "cosmossdk.io/store/v2/root" ) var ( @@ -97,9 +96,9 @@ func init() { appconfig.Register(&runtimev2.Module{}, appconfig.Provide( ProvideAppBuilder[transaction.Tx], - ProvideEnvironment[transaction.Tx], ProvideModuleManager[transaction.Tx], - ProvideStoreBuilder, + ProvideEnvironment, + ProvideKVService, ), appconfig.Invoke(SetupAppBuilder), ) @@ -127,7 +126,6 @@ func ProvideAppBuilder[T transaction.Tx]( msgRouterBuilder := stf.NewMsgRouterBuilder() app := &App[T]{ - storeKeys: nil, interfaceRegistrar: interfaceRegistrar, amino: amino, msgRouterBuilder: msgRouterBuilder, @@ -149,12 +147,7 @@ type AppInputs struct { InterfaceRegistrar registry.InterfaceRegistrar LegacyAmino registry.AminoRegistrar Logger log.Logger - // StoreBuilder is a builder for a store/v2 RootStore satisfying the Store interface - StoreBuilder *StoreBuilder - // StoreOptions are required as input for the StoreBuilder. If not provided, the default options are used. - StoreOptions *rootstore.Options `optional:"true"` - // DynamicConfig can be nil in client wiring, but is required in server wiring. - DynamicConfig server.DynamicConfig `optional:"true"` + StoreBuilder root.Builder } func SetupAppBuilder(inputs AppInputs) { @@ -164,24 +157,9 @@ func SetupAppBuilder(inputs AppInputs) { app.moduleManager = inputs.ModuleManager app.moduleManager.RegisterInterfaces(inputs.InterfaceRegistrar) app.moduleManager.RegisterLegacyAminoCodec(inputs.LegacyAmino) - - if inputs.DynamicConfig == nil { - return - } - storeOptions := rootstore.DefaultStoreOptions() - if inputs.StoreOptions != nil { - storeOptions = *inputs.StoreOptions - } - var err error - app.db, err = inputs.StoreBuilder.Build( - inputs.Logger, - app.storeKeys, - inputs.DynamicConfig, - storeOptions, - ) - if err != nil { - panic(err) - } + // STF requires some state to run + inputs.StoreBuilder.RegisterKey("stf") + inputs.AppBuilder.storeBuilder = inputs.StoreBuilder } func ProvideModuleManager[T transaction.Tx]( @@ -192,44 +170,50 @@ func ProvideModuleManager[T transaction.Tx]( return NewModuleManager[T](logger, config, modules) } -// ProvideEnvironment provides the environment for keeper modules, while maintaining backward compatibility and provide services directly as well. -func ProvideEnvironment[T transaction.Tx]( - logger log.Logger, +func ProvideKVService( config *runtimev2.Module, key depinject.ModuleKey, - appBuilder *AppBuilder[T], kvFactory store.KVStoreServiceFactory, - headerService header.Service, - eventService event.Service, -) ( - appmodulev2.Environment, - store.KVStoreService, - store.MemoryStoreService, -) { - var ( - kvService store.KVStoreService = failingStoreService{} - memKvService store.MemoryStoreService = failingStoreService{} - ) - + storeBuilder root.Builder, +) (store.KVStoreService, store.MemoryStoreService) { // skips modules that have no store - if !slices.Contains(config.SkipStoreKeys, key.Name()) { - var kvStoreKey string - storeKeyOverride := storeKeyOverride(config, key.Name()) - if storeKeyOverride != nil { - kvStoreKey = storeKeyOverride.KvStoreKey - } else { - kvStoreKey = key.Name() - } + if slices.Contains(config.SkipStoreKeys, key.Name()) { + return nil, nil + } + var kvStoreKey string + override := storeKeyOverride(config, key.Name()) + if override != nil { + kvStoreKey = override.KvStoreKey + } else { + kvStoreKey = key.Name() + } - registerStoreKey(appBuilder, kvStoreKey) - kvService = kvFactory([]byte(kvStoreKey)) + storeBuilder.RegisterKey(kvStoreKey) + fmt.Printf("provision store key=%s", kvStoreKey) - memStoreKey := fmt.Sprintf("memory:%s", key.Name()) - registerStoreKey(appBuilder, memStoreKey) - memKvService = stf.NewMemoryStoreService([]byte(memStoreKey)) + return kvFactory([]byte(kvStoreKey)), + stf.NewMemoryStoreService([]byte(fmt.Sprintf("memory:%s", kvStoreKey))) +} + +func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig { + for _, cfg := range config.OverrideStoreKeys { + if cfg.ModuleName == moduleName { + return cfg + } } + return nil +} - env := appmodulev2.Environment{ +// ProvideEnvironment provides the environment for keeper modules, while maintaining backward compatibility and provide services directly as well. +func ProvideEnvironment( + logger log.Logger, + key depinject.ModuleKey, + kvService store.KVStoreService, + memKvService store.MemoryStoreService, + headerService header.Service, + eventService event.Service, +) appmodulev2.Environment { + return appmodulev2.Environment{ Logger: logger, BranchService: stf.BranchService{}, EventService: eventService, @@ -241,22 +225,6 @@ func ProvideEnvironment[T transaction.Tx]( KVStoreService: kvService, MemStoreService: memKvService, } - - return env, kvService, memKvService -} - -func registerStoreKey[T transaction.Tx](builder *AppBuilder[T], key string) { - builder.app.storeKeys = append(builder.app.storeKeys, key) -} - -func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig { - for _, cfg := range config.OverrideStoreKeys { - if cfg.ModuleName == moduleName { - return cfg - } - } - - return nil } // DefaultServiceBindings provides default services for the following service interfaces: diff --git a/runtime/v2/store.go b/runtime/v2/store.go index 6c45dd5e72db..40912ea41f48 100644 --- a/runtime/v2/store.go +++ b/runtime/v2/store.go @@ -3,16 +3,11 @@ package runtime import ( "errors" "fmt" - "path/filepath" - "cosmossdk.io/core/server" "cosmossdk.io/core/store" - "cosmossdk.io/log" "cosmossdk.io/server/v2/stf" storev2 "cosmossdk.io/store/v2" - "cosmossdk.io/store/v2/db" "cosmossdk.io/store/v2/proof" - "cosmossdk.io/store/v2/root" ) // NewKVStoreService creates a new KVStoreService. @@ -64,58 +59,6 @@ type Store interface { LastCommitID() (proof.CommitID, error) } -// StoreBuilder is a builder for a store/v2 RootStore satisfying the Store interface. -type StoreBuilder struct { - store Store -} - -// Build creates a new store/v2 RootStore. -func (sb *StoreBuilder) Build( - logger log.Logger, - storeKeys []string, - config server.DynamicConfig, - options root.Options, -) (Store, error) { - if sb.store != nil { - return sb.store, nil - } - home := config.GetString(flagHome) - scRawDb, err := db.NewDB( - db.DBType(config.GetString("store.app-db-backend")), - "application", - filepath.Join(home, "data"), - nil, - ) - if err != nil { - return nil, fmt.Errorf("failed to create SCRawDB: %w", err) - } - - factoryOptions := &root.FactoryOptions{ - Logger: logger, - RootDir: home, - Options: options, - // STF needs to store a bit of state - StoreKeys: append(storeKeys, "stf"), - SCRawDB: scRawDb, - } - - rs, err := root.CreateRootStore(factoryOptions) - if err != nil { - return nil, fmt.Errorf("failed to create root store: %w", err) - } - sb.store = rs - return sb.store, nil -} - -// Get returns the Store. Build must be called before calling Get or the result will be nil. -func (sb *StoreBuilder) Get() Store { - return sb.store -} - -func ProvideStoreBuilder() *StoreBuilder { - return &StoreBuilder{} -} - // StoreLoader allows for custom loading of the store, this is useful when upgrading the store from a previous version type StoreLoader func(store Store) error diff --git a/server/v2/cometbft/server.go b/server/v2/cometbft/server.go index 484801cc87b4..b2ba8f194d78 100644 --- a/server/v2/cometbft/server.go +++ b/server/v2/cometbft/server.go @@ -2,6 +2,8 @@ package cometbft import ( "context" + "cosmossdk.io/server/v2/store" + "cosmossdk.io/store/v2/root" "crypto/sha256" "encoding/json" "fmt" @@ -23,7 +25,6 @@ import ( serverv2 "cosmossdk.io/server/v2" cometlog "cosmossdk.io/server/v2/cometbft/log" "cosmossdk.io/server/v2/cometbft/mempool" - "cosmossdk.io/server/v2/cometbft/types" "cosmossdk.io/store/v2/snapshots" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" @@ -43,7 +44,7 @@ type CometBFTServer[T transaction.Tx] struct { initTxCodec transaction.Codec[T] logger log.Logger - store types.Store + storeBuilder root.Builder serverOptions ServerOptions[T] config Config cfgOptions []CfgOption @@ -51,13 +52,13 @@ type CometBFTServer[T transaction.Tx] struct { func New[T transaction.Tx]( txCodec transaction.Codec[T], - store types.Store, + storeBuilder root.Builder, serverOptions ServerOptions[T], cfgOptions ...CfgOption, ) *CometBFTServer[T] { return &CometBFTServer[T]{ initTxCodec: txCodec, - store: store, + storeBuilder: storeBuilder, serverOptions: serverOptions, cfgOptions: cfgOptions, } @@ -104,6 +105,8 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg indexEvents[e] = struct{}{} } + rs, err := s.storeBuilder.Build(logger, store.UnmarshalConfig(cfg)) + s.logger = logger.With(log.ModuleKey, s.Name()) consensus := NewConsensus( s.logger, @@ -112,7 +115,7 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg s.serverOptions.Mempool(cfg), indexEvents, appI.GetGPRCMethodsToMessageMap(), - s.store, + rs, s.config, s.initTxCodec, chainID, @@ -124,8 +127,8 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg consensus.addrPeerFilter = s.serverOptions.AddrPeerFilter consensus.idPeerFilter = s.serverOptions.IdPeerFilter - ss := s.store.GetStateStorage().(snapshots.StorageSnapshotter) - sc := s.store.GetStateCommitment().(snapshots.CommitSnapshotter) + ss := rs.GetStateStorage().(snapshots.StorageSnapshotter) + sc := rs.GetStateCommitment().(snapshots.CommitSnapshotter) snapshotStore, err := GetSnapshotStore(s.config.ConfigTomlConfig.RootDir) if err != nil { diff --git a/server/v2/config_test.go b/server/v2/config_test.go index f69e2ed56769..aac333e47a5a 100644 --- a/server/v2/config_test.go +++ b/server/v2/config_test.go @@ -1,6 +1,7 @@ package serverv2_test import ( + "cosmossdk.io/store/v2/root" "os" "path/filepath" "testing" @@ -21,7 +22,7 @@ func TestReadConfig(t *testing.T) { require.NoError(t, err) require.Equal(t, v.GetString(grpc.FlagAddress), grpc.DefaultConfig().Address) - require.Equal(t, v.GetString(store.FlagAppDBBackend), store.DefaultConfig().AppDBBackend) + require.Equal(t, v.GetString(store.FlagAppDBBackend), root.DefaultConfig().AppDBBackend) } func TestUnmarshalSubConfig(t *testing.T) { @@ -40,8 +41,8 @@ func TestUnmarshalSubConfig(t *testing.T) { require.True(t, grpc.DefaultConfig().Enable) require.False(t, grpcConfig.Enable) - storeConfig := store.Config{} + storeConfig := root.Config{} err = serverv2.UnmarshalSubConfig(cfg, "store", &storeConfig) require.NoError(t, err) - require.Equal(t, *store.DefaultConfig(), storeConfig) + require.Equal(t, *root.DefaultConfig(), storeConfig) } diff --git a/server/v2/go.mod b/server/v2/go.mod index d996ab3d3681..318c95490839 100644 --- a/server/v2/go.mod +++ b/server/v2/go.mod @@ -8,6 +8,7 @@ replace ( cosmossdk.io/server/v2/stf => ./stf cosmossdk.io/store/v2 => ../../store/v2 cosmossdk.io/store/v2/db => ../../store/v2/db + cosmossdk.io/store/v2 => ../../store/v2 cosmossdk.io/x/tx => ../../x/tx ) diff --git a/server/v2/server.go b/server/v2/server.go index 7ee91e649982..f59e1bf7b4b4 100644 --- a/server/v2/server.go +++ b/server/v2/server.go @@ -61,6 +61,7 @@ const ( var _ ServerComponent[transaction.Tx] = (*Server[transaction.Tx])(nil) +// Server is the top-level server component which contains all over server components. type Server[T transaction.Tx] struct { logger log.Logger components []ServerComponent[T] diff --git a/server/v2/store/config.go b/server/v2/store/config.go deleted file mode 100644 index 457bfa9383cb..000000000000 --- a/server/v2/store/config.go +++ /dev/null @@ -1,17 +0,0 @@ -package store - -import ( - "cosmossdk.io/store/v2/root" -) - -func DefaultConfig() *Config { - return &Config{ - AppDBBackend: "goleveldb", - Options: root.DefaultStoreOptions(), - } -} - -type Config struct { - AppDBBackend string `mapstructure:"app-db-backend" toml:"app-db-backend" comment:"The type of database for application and snapshots databases."` - Options root.Options `mapstructure:"options" toml:"options"` -} diff --git a/server/v2/store/server.go b/server/v2/store/server.go index 6c9e7b23a0af..3cbd1ebff7bc 100644 --- a/server/v2/store/server.go +++ b/server/v2/store/server.go @@ -10,6 +10,7 @@ import ( "cosmossdk.io/log" serverv2 "cosmossdk.io/server/v2" storev2 "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/root" ) var ( @@ -22,23 +23,23 @@ const ServerName = "store" // Server manages store config and contains prune & snapshot commands type Server[T transaction.Tx] struct { - config *Config - store storev2.Backend + config *root.Config + builder root.Builder + backend storev2.Backend } -func New[T transaction.Tx](store storev2.Backend) *Server[T] { - return &Server[T]{store: store} +func New[T transaction.Tx](builder root.Builder) *Server[T] { + return &Server[T]{builder: builder} } -func (s *Server[T]) Init(_ serverv2.AppI[T], cfg map[string]any, _ log.Logger) error { - serverCfg := s.Config().(*Config) - if len(cfg) > 0 { - if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &serverCfg); err != nil { - return fmt.Errorf("failed to unmarshal config: %w", err) - } +func (s *Server[T]) Init(_ serverv2.AppI[T], cfg map[string]any, log log.Logger) error { + s.config = UnmarshalConfig(cfg) + var err error + s.backend, err = s.builder.Build(log, s.config) + if err != nil { + return fmt.Errorf("failed to create store backend: %w", err) } - s.config = serverCfg return nil } @@ -63,15 +64,24 @@ func (s *Server[T]) CLICommands() serverv2.CLIConfig { s.ListSnapshotsCmd(), s.DumpArchiveCmd(), s.LoadArchiveCmd(), - s.RestoreSnapshotCmd(s.store), + s.RestoreSnapshotCmd(s.backend), }, } } func (s *Server[T]) Config() any { if s.config == nil || s.config.AppDBBackend == "" { - return DefaultConfig() + return root.DefaultConfig() } return s.config } + +func UnmarshalConfig(cfg map[string]any) *root.Config { + config := &root.Config{} + if err := serverv2.UnmarshalSubConfig(cfg, ServerName, config); err != nil { + panic(fmt.Sprintf("failed to unmarshal config: %v", err)) + } + config.Home = cfg["home"].(string) + return config +} diff --git a/simapp/v2/app_di.go b/simapp/v2/app_di.go index 43ca45f99aed..9ced1df84bbe 100644 --- a/simapp/v2/app_di.go +++ b/simapp/v2/app_di.go @@ -1,7 +1,10 @@ package simapp import ( + serverstore "cosmossdk.io/server/v2/store" + "cosmossdk.io/store/v2/root" _ "embed" + "sync" "github.com/spf13/viper" @@ -12,7 +15,6 @@ import ( "cosmossdk.io/depinject" "cosmossdk.io/log" "cosmossdk.io/runtime/v2" - "cosmossdk.io/store/v2/root" basedepinject "cosmossdk.io/x/accounts/defaults/base/depinject" lockupdepinject "cosmossdk.io/x/accounts/defaults/lockup/depinject" multisigdepinject "cosmossdk.io/x/accounts/defaults/multisig/depinject" @@ -51,10 +53,34 @@ func init() { } } +var ( + singletonScopedStoreBuilder root.Builder + singletonScopedOnce sync.Once +) + +func ProvideSingletonScopedStoreBuilder() root.Builder { + singletonScopedOnce.Do(func() { + singletonScopedStoreBuilder = root.NewBuilder() + }) + return singletonScopedStoreBuilder +} + // AppConfig returns the default app config. func AppConfig() depinject.Config { return depinject.Configs( appConfig, // Alternatively use appconfig.LoadYAML(AppConfigYAML) + runtime.DefaultServiceBindings(), + depinject.Provide( + codec.ProvideInterfaceRegistry, + codec.ProvideAddressCodec, + codec.ProvideProtoCodec, + codec.ProvideLegacyAmino, + ProvideSingletonScopedStoreBuilder, + ), + depinject.Invoke( + std.RegisterInterfaces, + std.RegisterLegacyAminoCodec, + ), ) } @@ -64,14 +90,14 @@ func NewSimApp[T transaction.Tx]( viper *viper.Viper, ) *SimApp[T] { var ( - app = &SimApp[T]{} - appBuilder *runtime.AppBuilder[T] - err error + app = &SimApp[T]{} + appBuilder *runtime.AppBuilder[T] + storeBuilder root.Builder + err error // merge the AppConfig and other configuration in one config appConfig = depinject.Configs( AppConfig(), - runtime.DefaultServiceBindings(), depinject.Supply( logger, viper, @@ -117,10 +143,6 @@ func NewSimApp[T transaction.Tx]( // interface. ), depinject.Provide( - codec.ProvideInterfaceRegistry, - codec.ProvideAddressCodec, - codec.ProvideProtoCodec, - codec.ProvideLegacyAmino, // inject desired account types: multisigdepinject.ProvideAccount, basedepinject.ProvideAccount, @@ -141,27 +163,11 @@ func NewSimApp[T transaction.Tx]( // } // }) ), - depinject.Invoke( - std.RegisterInterfaces, - std.RegisterLegacyAminoCodec, - ), ) ) - // the subsection of config that contains the store options (in app.toml [store.options] header) - // is unmarshaled into a store.Options struct and passed to the store builder. - // future work may move this specification and retrieval into store/v2. - // If these options are not specified then default values will be used. - if sub := viper.Sub("store.options"); sub != nil { - storeOptions := &root.Options{} - err := sub.Unmarshal(storeOptions) - if err != nil { - panic(err) - } - appConfig = depinject.Configs(appConfig, depinject.Supply(storeOptions)) - } - if err := depinject.Inject(appConfig, + &storeBuilder, &appBuilder, &app.appCodec, &app.legacyAmino, @@ -172,6 +178,13 @@ func NewSimApp[T transaction.Tx]( panic(err) } + // store/v2 follows a slightly more eager config life cycle than server components + storeConfig := serverstore.UnmarshalConfig(viper.AllSettings()) + _, err = storeBuilder.Build(logger, storeConfig) + if err != nil { + panic(err) + } + app.App, err = appBuilder.Build() if err != nil { panic(err) diff --git a/simapp/v2/go.mod b/simapp/v2/go.mod index fdbbb0cbf559..7f3e3ff5739b 100644 --- a/simapp/v2/go.mod +++ b/simapp/v2/go.mod @@ -5,7 +5,7 @@ go 1.23.1 require ( cosmossdk.io/api v0.7.6 cosmossdk.io/client/v2 v2.0.0-00010101000000-000000000000 - cosmossdk.io/core v1.0.0-alpha.3 + cosmossdk.io/core v1.0.0-alpha.3.0.20241001191548-a0f96930ab2d cosmossdk.io/depinject v1.0.0 cosmossdk.io/log v1.4.1 cosmossdk.io/math v1.3.0 @@ -230,8 +230,8 @@ require ( google.golang.org/api v0.192.0 // indirect google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect - google.golang.org/grpc v1.67.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/grpc v1.67.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect diff --git a/simapp/v2/go.sum b/simapp/v2/go.sum index b4a90565cd5b..b48326a144f3 100644 --- a/simapp/v2/go.sum +++ b/simapp/v2/go.sum @@ -1340,8 +1340,8 @@ google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142 h1:oLiyxGgE+rt22du google.golang.org/genproto v0.0.0-20240814211410-ddb44dafa142/go.mod h1:G11eXq53iI5Q+kyNOmCvnzBaxEA2Q/Ik5Tj7nqBE8j4= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 h1:N9BgCIAUvn/M+p4NJccWPWb3BWh88+zyL0ll9HgbEeM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1377,8 +1377,8 @@ google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACu google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/simapp/v2/simdv2/cmd/commands.go b/simapp/v2/simdv2/cmd/commands.go index 8c3575179b20..506a2099758c 100644 --- a/simapp/v2/simdv2/cmd/commands.go +++ b/simapp/v2/simdv2/cmd/commands.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "cosmossdk.io/store/v2/root" "errors" "fmt" @@ -17,7 +18,6 @@ import ( "cosmossdk.io/server/v2/api/grpc" "cosmossdk.io/server/v2/api/telemetry" "cosmossdk.io/server/v2/cometbft" - cometbfttypes "cosmossdk.io/server/v2/cometbft/types" serverstore "cosmossdk.io/server/v2/store" "cosmossdk.io/simapp/v2" confixcmd "cosmossdk.io/tools/confix/cmd" @@ -44,7 +44,7 @@ func newApp[T transaction.Tx](logger log.Logger, viper *viper.Viper) serverv2.Ap func initRootCmd[T transaction.Tx]( rootCmd *cobra.Command, txConfig client.TxConfig, - store cometbfttypes.Store, + storeBuilder root.Builder, moduleManager *runtimev2.MM[T], ) { cfg := sdk.GetConfig() @@ -54,7 +54,7 @@ func initRootCmd[T transaction.Tx]( genutilcli.InitCmd(moduleManager), debug.Cmd(), confixcmd.ConfigCommand(), - NewTestnetCmd(store, moduleManager), + NewTestnetCmd(storeBuilder, moduleManager), ) logger, err := serverv2.NewLogger(viper.New(), rootCmd.OutOrStdout()) @@ -79,12 +79,12 @@ func initRootCmd[T transaction.Tx]( initServerConfig(), cometbft.New( &genericTxDecoder[T]{txConfig}, - store, + storeBuilder, initCometOptions[T](), initCometConfig(), ), grpc.New[T](), - serverstore.New[T](store), + serverstore.New[T](storeBuilder), telemetry.New[T](), ); err != nil { panic(err) diff --git a/simapp/v2/simdv2/cmd/root_di.go b/simapp/v2/simdv2/cmd/root_di.go index fab974e007ad..30291b4ecdb3 100644 --- a/simapp/v2/simdv2/cmd/root_di.go +++ b/simapp/v2/simdv2/cmd/root_di.go @@ -14,13 +14,13 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2" "cosmossdk.io/simapp/v2" + "cosmossdk.io/store/v2/root" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/config" nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node" "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/std" "github.com/cosmos/cosmos-sdk/x/auth/tx" authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config" "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -32,25 +32,14 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command { autoCliOpts autocli.AppOptions moduleManager *runtime.MM[T] clientCtx client.Context - storeBuilder runtime.StoreBuilder + storeBuilder root.Builder ) if err := depinject.Inject( depinject.Configs( simapp.AppConfig(), - runtime.DefaultServiceBindings(), + depinject.Provide(ProvideClientContext), depinject.Supply(log.NewNopLogger()), - depinject.Provide( - codec.ProvideInterfaceRegistry, - codec.ProvideAddressCodec, - codec.ProvideProtoCodec, - codec.ProvideLegacyAmino, - ProvideClientContext, - ), - depinject.Invoke( - std.RegisterInterfaces, - std.RegisterLegacyAminoCodec, - ), ), &storeBuilder, &autoCliOpts, @@ -85,8 +74,7 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command { }, } - store := storeBuilder.Get() - initRootCmd(rootCmd, clientCtx.TxConfig, store, moduleManager) + initRootCmd(rootCmd, clientCtx.TxConfig, storeBuilder, moduleManager) nodeCmds := nodeservice.NewNodeCommands() autoCliOpts.ModuleOptions = make(map[string]*autocliv1.ModuleOptions) diff --git a/simapp/v2/simdv2/cmd/testnet.go b/simapp/v2/simdv2/cmd/testnet.go index 67c8b0e85517..add26139324a 100644 --- a/simapp/v2/simdv2/cmd/testnet.go +++ b/simapp/v2/simdv2/cmd/testnet.go @@ -2,6 +2,7 @@ package cmd import ( "bufio" + "cosmossdk.io/store/v2/root" "encoding/json" "fmt" "net" @@ -22,7 +23,6 @@ import ( serverv2 "cosmossdk.io/server/v2" "cosmossdk.io/server/v2/api/grpc" "cosmossdk.io/server/v2/cometbft" - cometbfttypes "cosmossdk.io/server/v2/cometbft/types" "cosmossdk.io/server/v2/store" banktypes "cosmossdk.io/x/bank/types" bankv2types "cosmossdk.io/x/bank/v2/types" @@ -88,7 +88,7 @@ func addTestnetFlagsToCmd(cmd *cobra.Command) { // NewTestnetCmd creates a root testnet command with subcommands to run an in-process testnet or initialize // validator configuration files for running a multi-validator testnet in a separate process -func NewTestnetCmd[T transaction.Tx](rs cometbfttypes.Store, mm *runtimev2.MM[T]) *cobra.Command { +func NewTestnetCmd[T transaction.Tx](sb root.Builder, mm *runtimev2.MM[T]) *cobra.Command { testnetCmd := &cobra.Command{ Use: "testnet", Short: "subcommands for starting or configuring local testnets", @@ -97,13 +97,13 @@ func NewTestnetCmd[T transaction.Tx](rs cometbfttypes.Store, mm *runtimev2.MM[T] RunE: client.ValidateCmd, } - testnetCmd.AddCommand(testnetInitFilesCmd(rs, mm)) + testnetCmd.AddCommand(testnetInitFilesCmd(sb, mm)) return testnetCmd } // testnetInitFilesCmd returns a cmd to initialize all files for CometBFT testnet and application -func testnetInitFilesCmd[T transaction.Tx](rs cometbfttypes.Store, mm *runtimev2.MM[T]) *cobra.Command { +func testnetInitFilesCmd[T transaction.Tx](sb root.Builder, mm *runtimev2.MM[T]) *cobra.Command { cmd := &cobra.Command{ Use: "init-files", Short: "Initialize config directories & files for a multi-validator testnet running locally via separate processes (e.g. Docker Compose or similar)", @@ -144,7 +144,7 @@ Example: return err } - return initTestnetFiles(clientCtx, rs, cmd, config, mm, args) + return initTestnetFiles(clientCtx, sb, cmd, config, mm, args) }, } @@ -166,7 +166,7 @@ const nodeDirPerm = 0o755 // initTestnetFiles initializes testnet files for a testnet to be run in a separate process func initTestnetFiles[T transaction.Tx]( clientCtx client.Context, - rootStore cometbfttypes.Store, + sb root.Builder, cmd *cobra.Command, nodeConfig *cmtconfig.Config, mm *runtimev2.MM[T], @@ -341,13 +341,13 @@ func initTestnetFiles[T transaction.Tx]( // Write server config cometServer := cometbft.New[T]( &genericTxDecoder[T]{clientCtx.TxConfig}, - rootStore, + sb, cometbft.ServerOptions[T]{}, cometbft.OverwriteDefaultConfigTomlConfig(nodeConfig), ) - storeServer := store.New[T](rootStore) + storeServer := store.New[T](sb) grpcServer := grpc.New[T](grpc.OverwriteDefaultConfig(grpcConfig)) - server := serverv2.NewServer(log.NewNopLogger(), serverCfg, cometServer, grpcServer, storeServer) + server := serverv2.NewServer[T](log.NewNopLogger(), serverCfg, cometServer, grpcServer, storeServer) err = server.WriteConfig(filepath.Join(nodeDir, "config")) if err != nil { return err diff --git a/store/v2/db/db.go b/store/v2/db/db.go index a8c741e45424..def90525f1aa 100644 --- a/store/v2/db/db.go +++ b/store/v2/db/db.go @@ -1,10 +1,10 @@ package db import ( + "cosmossdk.io/store/v2" "fmt" corestore "cosmossdk.io/core/store" - "cosmossdk.io/store/v2" ) type DBType string diff --git a/store/v2/go.mod b/store/v2/go.mod index 95d69785d137..f8af3c32dcdc 100644 --- a/store/v2/go.mod +++ b/store/v2/go.mod @@ -16,6 +16,7 @@ require ( github.com/hashicorp/go-metrics v0.5.3 github.com/linxGnu/grocksdb v1.9.3 github.com/mattn/go-sqlite3 v1.14.22 + github.com/mitchellh/mapstructure v1.5.0 github.com/spf13/cast v1.7.0 github.com/stretchr/testify v1.9.0 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d diff --git a/store/v2/go.sum b/store/v2/go.sum index 18861dba214c..837536d4ac6d 100644 --- a/store/v2/go.sum +++ b/store/v2/go.sum @@ -143,6 +143,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= diff --git a/store/v2/root/builder.go b/store/v2/root/builder.go new file mode 100644 index 000000000000..e1cc3260c6d9 --- /dev/null +++ b/store/v2/root/builder.go @@ -0,0 +1,85 @@ +package root + +import ( + "fmt" + "path/filepath" + + "cosmossdk.io/log" + "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/db" +) + +type Builder interface { + Build(log.Logger, *Config) (store.RootStore, error) + RegisterKey(key string) + Get() store.RootStore +} + +var _ Builder = (*builder)(nil) + +// builder is a builder for a store/v2 RootStore satisfying the Store interface +// which is primarily used by depinject to assemble the store/v2 RootStore. Users not using +// depinject should use the Factory called in Build directly. +type builder struct { + // input + storeKeys map[string]struct{} + + // output + store store.RootStore +} + +func NewBuilder() Builder { + return &builder{storeKeys: make(map[string]struct{})} +} + +// Build creates a new store/v2 RootStore. +func (sb *builder) Build( + logger log.Logger, + config *Config, +) (store.RootStore, error) { + if sb.store != nil { + return sb.store, nil + } + if config.Home == "" { + return nil, fmt.Errorf("home directory is required") + } + scRawDb, err := db.NewDB( + db.DBType(config.AppDBBackend), + "application", + filepath.Join(config.Home, "data"), + nil, + ) + fmt.Printf("******* builder.Build config=%+v keys=%+v\n", config, sb.storeKeys) + if err != nil { + return nil, fmt.Errorf("failed to create SCRawDB: %w", err) + } + + var storeKeys []string + for key := range sb.storeKeys { + storeKeys = append(storeKeys, key) + } + + factoryOptions := &FactoryOptions{ + Logger: logger, + RootDir: config.Home, + Options: config.Options, + StoreKeys: storeKeys, + SCRawDB: scRawDb, + } + + rs, err := CreateRootStore(factoryOptions) + if err != nil { + return nil, fmt.Errorf("failed to create root store: %w", err) + } + sb.store = rs + return sb.store, nil +} + +// Get returns the Store. Build must be called before calling Get or the result will be nil. +func (sb *builder) Get() store.RootStore { + return sb.store +} + +func (sb *builder) RegisterKey(key string) { + sb.storeKeys[key] = struct{}{} +} diff --git a/store/v2/root/config.go b/store/v2/root/config.go new file mode 100644 index 000000000000..efabe0c9a97c --- /dev/null +++ b/store/v2/root/config.go @@ -0,0 +1,14 @@ +package root + +func DefaultConfig() *Config { + return &Config{ + AppDBBackend: "goleveldb", + Options: DefaultStoreOptions(), + } +} + +type Config struct { + Home string + AppDBBackend string `mapstructure:"app-db-backend" toml:"app-db-backend" comment:"The type of database for application and snapshots databases."` + Options Options `mapstructure:"options" toml:"options"` +} diff --git a/store/v2/root/factory.go b/store/v2/root/factory.go index e6f86917ab0d..9e1f76a36ceb 100644 --- a/store/v2/root/factory.go +++ b/store/v2/root/factory.go @@ -33,7 +33,7 @@ const ( SCTypeIavlV2 SCType = "iavl-v2" ) -// app.toml config options +// Options are the options for creating a root store. type Options struct { SSType SSType `mapstructure:"ss-type" toml:"ss-type" comment:"SState storage database type. Currently we support: \"sqlite\", \"pebble\" and \"rocksdb\""` SCType SCType `mapstructure:"sc-type" toml:"sc-type" comment:"State commitment database type. Currently we support: \"iavl\" and \"iavl-v2\""` From 06c84bb8af3949ece1da1a8302e457012f193aeb Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Wed, 2 Oct 2024 14:18:36 -0500 Subject: [PATCH 6/9] go mod tidy all --- server/v2/go.mod | 1 - store/v2/go.mod | 1 - store/v2/go.sum | 2 -- 3 files changed, 4 deletions(-) diff --git a/server/v2/go.mod b/server/v2/go.mod index 318c95490839..d996ab3d3681 100644 --- a/server/v2/go.mod +++ b/server/v2/go.mod @@ -8,7 +8,6 @@ replace ( cosmossdk.io/server/v2/stf => ./stf cosmossdk.io/store/v2 => ../../store/v2 cosmossdk.io/store/v2/db => ../../store/v2/db - cosmossdk.io/store/v2 => ../../store/v2 cosmossdk.io/x/tx => ../../x/tx ) diff --git a/store/v2/go.mod b/store/v2/go.mod index f8af3c32dcdc..95d69785d137 100644 --- a/store/v2/go.mod +++ b/store/v2/go.mod @@ -16,7 +16,6 @@ require ( github.com/hashicorp/go-metrics v0.5.3 github.com/linxGnu/grocksdb v1.9.3 github.com/mattn/go-sqlite3 v1.14.22 - github.com/mitchellh/mapstructure v1.5.0 github.com/spf13/cast v1.7.0 github.com/stretchr/testify v1.9.0 github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d diff --git a/store/v2/go.sum b/store/v2/go.sum index 837536d4ac6d..18861dba214c 100644 --- a/store/v2/go.sum +++ b/store/v2/go.sum @@ -143,8 +143,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= From 9faf4dc82353eba33ab8147a01a5dbdd380af348 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Wed, 2 Oct 2024 14:21:53 -0500 Subject: [PATCH 7/9] fix go lint --- store/v2/db/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/store/v2/db/db.go b/store/v2/db/db.go index def90525f1aa..a8c741e45424 100644 --- a/store/v2/db/db.go +++ b/store/v2/db/db.go @@ -1,10 +1,10 @@ package db import ( - "cosmossdk.io/store/v2" "fmt" corestore "cosmossdk.io/core/store" + "cosmossdk.io/store/v2" ) type DBType string From 8da9ef2269313f95b1da628992044bf1b32fcf49 Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Wed, 2 Oct 2024 14:30:17 -0500 Subject: [PATCH 8/9] fix lint --- runtime/v2/app.go | 1 + runtime/v2/builder.go | 2 +- runtime/v2/module.go | 9 +++------ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/runtime/v2/app.go b/runtime/v2/app.go index 6d072a0b7215..ed8d8e327809 100644 --- a/runtime/v2/app.go +++ b/runtime/v2/app.go @@ -2,6 +2,7 @@ package runtime import ( "encoding/json" + gogoproto "github.com/cosmos/gogoproto/proto" runtimev2 "cosmossdk.io/api/cosmos/app/runtime/v2" diff --git a/runtime/v2/builder.go b/runtime/v2/builder.go index 8d8df8fbaf3b..e74d6ff34f22 100644 --- a/runtime/v2/builder.go +++ b/runtime/v2/builder.go @@ -2,7 +2,6 @@ package runtime import ( "context" - "cosmossdk.io/store/v2/root" "encoding/json" "errors" "fmt" @@ -16,6 +15,7 @@ import ( "cosmossdk.io/server/v2/appmanager" "cosmossdk.io/server/v2/stf" "cosmossdk.io/server/v2/stf/branch" + "cosmossdk.io/store/v2/root" ) // AppBuilder is a type that is injected into a container by the runtime/v2 module diff --git a/runtime/v2/module.go b/runtime/v2/module.go index 525c3561e81f..b02b416f3d37 100644 --- a/runtime/v2/module.go +++ b/runtime/v2/module.go @@ -1,7 +1,6 @@ package runtime import ( - "cosmossdk.io/store/v2/root" "fmt" "os" "slices" @@ -27,6 +26,7 @@ import ( "cosmossdk.io/log" "cosmossdk.io/runtime/v2/services" "cosmossdk.io/server/v2/stf" + "cosmossdk.io/store/v2/root" ) var ( @@ -178,7 +178,7 @@ func ProvideKVService( ) (store.KVStoreService, store.MemoryStoreService) { // skips modules that have no store if slices.Contains(config.SkipStoreKeys, key.Name()) { - return nil, nil + return &failingStoreService{}, &failingStoreService{} } var kvStoreKey string override := storeKeyOverride(config, key.Name()) @@ -189,10 +189,7 @@ func ProvideKVService( } storeBuilder.RegisterKey(kvStoreKey) - fmt.Printf("provision store key=%s", kvStoreKey) - - return kvFactory([]byte(kvStoreKey)), - stf.NewMemoryStoreService([]byte(fmt.Sprintf("memory:%s", kvStoreKey))) + return kvFactory([]byte(kvStoreKey)), stf.NewMemoryStoreService([]byte(fmt.Sprintf("memory:%s", kvStoreKey))) } func storeKeyOverride(config *runtimev2.Module, moduleName string) *runtimev2.StoreKeyConfig { From ba09fa0304a05211a015e71ad99916bf04dd405c Mon Sep 17 00:00:00 2001 From: Matt Kocubinski Date: Wed, 2 Oct 2024 14:36:20 -0500 Subject: [PATCH 9/9] fix tests with mocks --- server/v2/server_test.go | 16 +++++++++++++++- server/v2/store/server.go | 5 ++++- server/v2/testdata/app.toml | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/server/v2/server_test.go b/server/v2/server_test.go index df78f691a9d9..42337e796220 100644 --- a/server/v2/server_test.go +++ b/server/v2/server_test.go @@ -2,6 +2,8 @@ package serverv2_test import ( "context" + storev2 "cosmossdk.io/store/v2" + "cosmossdk.io/store/v2/root" "os" "path/filepath" "testing" @@ -47,6 +49,18 @@ func (*mockApp[T]) InterfaceRegistry() coreserver.InterfaceRegistry { return &mockInterfaceRegistry{} } +var _ root.Builder = &mockStoreBuilder{} + +type mockStoreBuilder struct{} + +func (m mockStoreBuilder) Build(logger log.Logger, config *root.Config) (storev2.RootStore, error) { + return nil, nil +} + +func (m mockStoreBuilder) RegisterKey(string) {} + +func (m mockStoreBuilder) Get() storev2.RootStore { return nil } + func TestServer(t *testing.T) { currentDir, err := os.Getwd() require.NoError(t, err) @@ -63,7 +77,7 @@ func TestServer(t *testing.T) { err = grpcServer.Init(&mockApp[transaction.Tx]{}, cfg, logger) require.NoError(t, err) - storeServer := store.New[transaction.Tx](nil /* nil store is not using CLI commands */) + storeServer := store.New[transaction.Tx](&mockStoreBuilder{}) err = storeServer.Init(&mockApp[transaction.Tx]{}, cfg, logger) require.NoError(t, err) diff --git a/server/v2/store/server.go b/server/v2/store/server.go index 3cbd1ebff7bc..f5cfa456d242 100644 --- a/server/v2/store/server.go +++ b/server/v2/store/server.go @@ -82,6 +82,9 @@ func UnmarshalConfig(cfg map[string]any) *root.Config { if err := serverv2.UnmarshalSubConfig(cfg, ServerName, config); err != nil { panic(fmt.Sprintf("failed to unmarshal config: %v", err)) } - config.Home = cfg["home"].(string) + home := cfg["home"] + if home != nil { + config.Home = home.(string) + } return config } diff --git a/server/v2/testdata/app.toml b/server/v2/testdata/app.toml index 094ac068d94a..59ffc9706654 100644 --- a/server/v2/testdata/app.toml +++ b/server/v2/testdata/app.toml @@ -21,6 +21,7 @@ mock_field_two = 1 minimum-gas-prices = '0stake' [store] +Home = '' # The type of database for application and snapshots databases. app-db-backend = 'goleveldb'