refactor(runtime/v2): use AppI.GetStore() to fetch an initialized RootStore (#22205)

This commit is contained in:
Matt Kocubinski 2024-10-10 09:29:40 -05:00 committed by GitHub
parent 63b1652d98
commit dd2369daf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 25 additions and 86 deletions

View File

@ -229,6 +229,7 @@ func ProvideEnvironment(
// - header.Service
// - comet.Service
// - event.Service
// - store/v2/root.Builder
//
// They are all required. For most use cases these default services bindings should be sufficient.
// Power users (or tests) may wish to provide their own services bindings, in which case they must
@ -244,11 +245,13 @@ func DefaultServiceBindings() depinject.Config {
cometService comet.Service = &services.ContextAwareCometInfoService{}
headerService = services.NewGenesisHeaderService(stf.HeaderService{})
eventService = services.NewGenesisEventService(stf.NewEventService())
storeBuilder = root.NewBuilder()
)
return depinject.Supply(
kvServiceFactory,
headerService,
cometService,
eventService,
storeBuilder,
)
}

View File

@ -3,35 +3,13 @@ package runtime
import (
"errors"
"fmt"
"sync"
"cosmossdk.io/core/store"
"cosmossdk.io/server/v2/stf"
storev2 "cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/proof"
"cosmossdk.io/store/v2/root"
)
var (
storeBuilderSingleton root.Builder
storeBuilderSingletonOnce sync.Once
)
// ProvideSingletonScopedStoreBuilder returns a store builder that is a singleton
// in the scope of the process lifetime.
func ProvideSingletonScopedStoreBuilder() root.Builder {
storeBuilderSingletonOnce.Do(func() {
storeBuilderSingleton = root.NewBuilder()
})
return storeBuilderSingleton
}
// ResetSingletonScopedStoreBuilder resets the singleton store builder. Applications
// should not ever need to call this, but it may be useful in tests.
func ResetSingletonScopedStoreBuilder() {
storeBuilderSingletonOnce = sync.Once{}
}
// NewKVStoreService creates a new KVStoreService.
// This wrapper is kept for backwards compatibility.
// When migrating from runtime to runtime/v2, use runtimev2.NewKVStoreService(storeKey.Name()) instead of runtime.NewKVStoreService(storeKey).

View File

@ -8,9 +8,6 @@ import (
"os"
"path/filepath"
"cosmossdk.io/server/v2/store"
"cosmossdk.io/store/v2/root"
abciserver "github.com/cometbft/cometbft/abci/server"
cmtcmd "github.com/cometbft/cometbft/cmd/cometbft/commands"
cmtcfg "github.com/cometbft/cometbft/config"
@ -45,7 +42,6 @@ type CometBFTServer[T transaction.Tx] struct {
initTxCodec transaction.Codec[T]
logger log.Logger
storeBuilder root.Builder
serverOptions ServerOptions[T]
config Config
cfgOptions []CfgOption
@ -53,13 +49,11 @@ type CometBFTServer[T transaction.Tx] struct {
func New[T transaction.Tx](
txCodec transaction.Codec[T],
storeBuilder root.Builder,
serverOptions ServerOptions[T],
cfgOptions ...CfgOption,
) *CometBFTServer[T] {
return &CometBFTServer[T]{
initTxCodec: txCodec,
storeBuilder: storeBuilder,
serverOptions: serverOptions,
cfgOptions: cfgOptions,
}
@ -106,16 +100,8 @@ func (s *CometBFTServer[T]) Init(appI serverv2.AppI[T], cfg map[string]any, logg
indexEvents[e] = struct{}{}
}
storeCfg, err := store.UnmarshalConfig(cfg)
if err != nil {
return err
}
rs, err := s.storeBuilder.Build(logger, storeCfg)
if err != nil {
return err
}
s.logger = logger.With(log.ModuleKey, s.Name())
rs := appI.GetStore()
consensus := NewConsensus(
s.logger,
appI.Name(),

View File

@ -20,7 +20,6 @@ import (
"cosmossdk.io/server/v2/appmanager"
"cosmossdk.io/server/v2/store"
storev2 "cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/root"
)
type mockInterfaceRegistry struct{}
@ -50,18 +49,10 @@ 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 (*mockApp[T]) GetStore() storev2.RootStore {
return 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)
@ -78,7 +69,7 @@ func TestServer(t *testing.T) {
err = grpcServer.Init(&mockApp[transaction.Tx]{}, cfg, logger)
require.NoError(t, err)
storeServer := store.New[transaction.Tx](&mockStoreBuilder{})
storeServer := store.New[transaction.Tx]()
err = storeServer.Init(&mockApp[transaction.Tx]{}, cfg, logger)
require.NoError(t, err)

View File

@ -24,26 +24,17 @@ const ServerName = "store"
// Server manages store config and contains prune & snapshot commands
type Server[T transaction.Tx] struct {
config *root.Config
builder root.Builder
backend storev2.Backend
}
func New[T transaction.Tx](builder root.Builder) *Server[T] {
return &Server[T]{builder: builder}
func New[T transaction.Tx]() *Server[T] {
return &Server[T]{}
}
func (s *Server[T]) Init(_ serverv2.AppI[T], cfg map[string]any, log log.Logger) error {
var err error
s.config, err = UnmarshalConfig(cfg)
if err != nil {
return fmt.Errorf("failed to unmarshal config: %w", err)
}
s.backend, err = s.builder.Build(log, s.config)
if err != nil {
return fmt.Errorf("failed to create store backend: %w", err)
}
return nil
func (s *Server[T]) Init(app serverv2.AppI[T], v map[string]any, _ log.Logger) (err error) {
s.backend = app.GetStore()
s.config, err = UnmarshalConfig(v)
return err
}
func (s *Server[T]) Name() string {
@ -90,7 +81,7 @@ func UnmarshalConfig(cfg map[string]any) (*root.Config, error) {
Options: root.DefaultStoreOptions(),
}
if err := serverv2.UnmarshalSubConfig(cfg, ServerName, config); err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
return nil, fmt.Errorf("failed to unmarshal store config: %w", err)
}
home := cfg[serverv2.FlagHome]
if home != nil {

View File

@ -8,6 +8,7 @@ import (
"cosmossdk.io/core/transaction"
"cosmossdk.io/log"
"cosmossdk.io/server/v2/appmanager"
"cosmossdk.io/store/v2"
)
type AppCreator[T transaction.Tx] func(log.Logger, *viper.Viper) AppI[T]
@ -17,4 +18,5 @@ type AppI[T transaction.Tx] interface {
InterfaceRegistry() server.InterfaceRegistry
GetAppManager() *appmanager.AppManager[T]
GetQueryHandlers() map[string]appmodulev2.Handler
GetStore() store.RootStore
}

View File

@ -66,7 +66,6 @@ func AppConfig() depinject.Config {
codec.ProvideAddressCodec,
codec.ProvideProtoCodec,
codec.ProvideLegacyAmino,
runtime.ProvideSingletonScopedStoreBuilder,
),
depinject.Invoke(
std.RegisterInterfaces,
@ -83,8 +82,8 @@ func NewSimApp[T transaction.Tx](
var (
app = &SimApp[T]{}
appBuilder *runtime.AppBuilder[T]
storeBuilder root.Builder
err error
storeBuilder root.Builder
// merge the AppConfig and other configuration in one config
appConfig = depinject.Configs(

View File

@ -18,7 +18,6 @@ import (
"cosmossdk.io/core/transaction"
"cosmossdk.io/log"
sdkmath "cosmossdk.io/math"
"cosmossdk.io/runtime/v2"
serverv2 "cosmossdk.io/server/v2"
serverv2store "cosmossdk.io/server/v2/store"
"cosmossdk.io/store/v2/db"
@ -40,7 +39,6 @@ func NewTestApp(t *testing.T) (*SimApp[transaction.Tx], context.Context) {
vp.Set(serverv2store.FlagAppDBBackend, string(db.DBTypeGoLevelDB))
vp.Set(serverv2.FlagHome, t.TempDir())
runtime.ResetSingletonScopedStoreBuilder()
app := NewSimApp[transaction.Tx](logger, vp)
genesis := app.ModuleManager().DefaultGenesis()

View File

@ -19,7 +19,6 @@ import (
"cosmossdk.io/server/v2/cometbft"
serverstore "cosmossdk.io/server/v2/store"
"cosmossdk.io/simapp/v2"
"cosmossdk.io/store/v2/root"
confixcmd "cosmossdk.io/tools/confix/cmd"
"github.com/cosmos/cosmos-sdk/client"
@ -44,7 +43,6 @@ func newApp[T transaction.Tx](logger log.Logger, viper *viper.Viper) serverv2.Ap
func initRootCmd[T transaction.Tx](
rootCmd *cobra.Command,
txConfig client.TxConfig,
storeBuilder root.Builder,
moduleManager *runtimev2.MM[T],
) {
cfg := sdk.GetConfig()
@ -54,7 +52,7 @@ func initRootCmd[T transaction.Tx](
genutilcli.InitCmd(moduleManager),
debug.Cmd(),
confixcmd.ConfigCommand(),
NewTestnetCmd(storeBuilder, moduleManager),
NewTestnetCmd(moduleManager),
)
logger, err := serverv2.NewLogger(viper.New(), rootCmd.OutOrStdout())
@ -79,12 +77,11 @@ func initRootCmd[T transaction.Tx](
initServerConfig(),
cometbft.New(
&genericTxDecoder[T]{txConfig},
storeBuilder,
initCometOptions[T](),
initCometConfig(),
),
grpc.New[T](),
serverstore.New[T](storeBuilder),
serverstore.New[T](),
telemetry.New[T](),
); err != nil {
panic(err)

View File

@ -14,7 +14,6 @@ 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"
@ -32,7 +31,6 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command {
autoCliOpts autocli.AppOptions
moduleManager *runtime.MM[T]
clientCtx client.Context
storeBuilder root.Builder
)
if err := depinject.Inject(
@ -41,7 +39,6 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command {
depinject.Provide(ProvideClientContext),
depinject.Supply(log.NewNopLogger()),
),
&storeBuilder,
&autoCliOpts,
&moduleManager,
&clientCtx,
@ -74,7 +71,7 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command {
},
}
initRootCmd(rootCmd, clientCtx.TxConfig, storeBuilder, moduleManager)
initRootCmd(rootCmd, clientCtx.TxConfig, moduleManager)
nodeCmds := nodeservice.NewNodeCommands()
autoCliOpts.ModuleOptions = make(map[string]*autocliv1.ModuleOptions)

View File

@ -23,7 +23,6 @@ import (
"cosmossdk.io/server/v2/api/grpc"
"cosmossdk.io/server/v2/cometbft"
"cosmossdk.io/server/v2/store"
"cosmossdk.io/store/v2/root"
banktypes "cosmossdk.io/x/bank/types"
bankv2types "cosmossdk.io/x/bank/v2/types"
stakingtypes "cosmossdk.io/x/staking/types"
@ -88,7 +87,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](sb root.Builder, mm *runtimev2.MM[T]) *cobra.Command {
func NewTestnetCmd[T transaction.Tx](mm *runtimev2.MM[T]) *cobra.Command {
testnetCmd := &cobra.Command{
Use: "testnet",
Short: "subcommands for starting or configuring local testnets",
@ -97,13 +96,13 @@ func NewTestnetCmd[T transaction.Tx](sb root.Builder, mm *runtimev2.MM[T]) *cobr
RunE: client.ValidateCmd,
}
testnetCmd.AddCommand(testnetInitFilesCmd(sb, mm))
testnetCmd.AddCommand(testnetInitFilesCmd(mm))
return testnetCmd
}
// testnetInitFilesCmd returns a cmd to initialize all files for CometBFT testnet and application
func testnetInitFilesCmd[T transaction.Tx](sb root.Builder, mm *runtimev2.MM[T]) *cobra.Command {
func testnetInitFilesCmd[T transaction.Tx](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 +143,7 @@ Example:
return err
}
return initTestnetFiles(clientCtx, sb, cmd, config, mm, args)
return initTestnetFiles(clientCtx, cmd, config, mm, args)
},
}
@ -166,7 +165,6 @@ 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,
sb root.Builder,
cmd *cobra.Command,
nodeConfig *cmtconfig.Config,
mm *runtimev2.MM[T],
@ -341,11 +339,10 @@ func initTestnetFiles[T transaction.Tx](
// Write server config
cometServer := cometbft.New[T](
&genericTxDecoder[T]{clientCtx.TxConfig},
sb,
cometbft.ServerOptions[T]{},
cometbft.OverwriteDefaultConfigTomlConfig(nodeConfig),
)
storeServer := store.New[T](sb)
storeServer := store.New[T]()
grpcServer := grpc.New[T](grpc.OverwriteDefaultConfig(grpcConfig))
server := serverv2.NewServer[T](log.NewNopLogger(), serverCfg, cometServer, grpcServer, storeServer)
err = server.WriteConfig(filepath.Join(nodeDir, "config"))