Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(server/v2): clean up storage use and config #22008

Merged
merged 31 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
88c746a
refactor(runtime/v2): use StoreBuilder
kocubinski Sep 30, 2024
fe2f122
merge main
kocubinski Sep 30, 2024
5d471b5
remove GetStore() any from AppI interface
kocubinski Oct 1, 2024
058248a
Merge branch 'main' of github.com:cosmos/cosmos-sdk into kocu/store-b…
kocubinski Oct 1, 2024
c8c207c
fix testnet.go
kocubinski Oct 1, 2024
ddab5ee
big store config refactor
kocubinski Oct 2, 2024
06c84bb
go mod tidy all
kocubinski Oct 2, 2024
3d96b52
Merge branch 'main' of github.com:cosmos/cosmos-sdk into kocu/store-b…
kocubinski Oct 2, 2024
9faf4dc
fix go lint
kocubinski Oct 2, 2024
8da9ef2
fix lint
kocubinski Oct 2, 2024
ba09fa0
fix tests with mocks
kocubinski Oct 2, 2024
e1856ab
supply default values
kocubinski Oct 2, 2024
ad5b9ca
revert
kocubinski Oct 3, 2024
70c7598
error handling and omit Home field in TOML
kocubinski Oct 3, 2024
f75ecbf
fix typo
kocubinski Oct 3, 2024
90ed108
Merge branch 'main' of github.com:cosmos/cosmos-sdk into kocu/store-b…
kocubinski Oct 3, 2024
25e8991
add godoc
kocubinski Oct 3, 2024
7decd50
move provider to runtime
kocubinski Oct 3, 2024
84a6198
lint fixes
kocubinski Oct 3, 2024
56c8472
minor nit
kocubinski Oct 3, 2024
eb50987
add docs
kocubinski Oct 3, 2024
ecd1b48
revert go.mod changes
kocubinski Oct 3, 2024
85b2975
delete unused struct
kocubinski Oct 3, 2024
327e74c
sort imports
kocubinski Oct 4, 2024
afc1eca
Merge branch 'main' of github.com:cosmos/cosmos-sdk into kocu/store-b…
kocubinski Oct 4, 2024
5a114e8
Merge branch 'main' into kocu/store-builder
kocubinski Oct 6, 2024
84d319d
Merge branch 'main' of github.com:cosmos/cosmos-sdk into kocu/store-b…
kocubinski Oct 7, 2024
1589f13
Merge branch 'main' of github.com:cosmos/cosmos-sdk into kocu/store-b…
kocubinski Oct 8, 2024
80f819f
fix for tests
kocubinski Oct 8, 2024
d23d13a
fix comment
kocubinski Oct 8, 2024
a857bbd
Merge branch 'main' into kocu/store-builder
kocubinski Oct 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions server/v2/cometbft/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down Expand Up @@ -98,15 +105,14 @@ 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(),
appI.GetAppManager(),
s.serverOptions.Mempool(cfg),
indexEvents,
appI.GetGPRCMethodsToMessageMap(),
store,
s.store,
s.config,
s.initTxCodec,
chainID,
Expand All @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle unchecked type assertions to prevent potential panics

The type assertions on s.store.GetStateStorage() and s.store.GetStateCommitment() are unchecked and could lead to a panic if the assertions fail. It is recommended to perform type assertion checks to handle potential failures gracefully.

Apply the following changes to handle potential type assertion failures:

- ss := s.store.GetStateStorage().(snapshots.StorageSnapshotter)
- sc := s.store.GetStateCommitment().(snapshots.CommitSnapshotter)
+ ssInterface := s.store.GetStateStorage()
+ ss, ok := ssInterface.(snapshots.StorageSnapshotter)
+ if !ok {
+     return fmt.Errorf("failed to assert s.store.GetStateStorage() to snapshots.StorageSnapshotter")
+ }
+ scInterface := s.store.GetStateCommitment()
+ sc, ok := scInterface.(snapshots.CommitSnapshotter)
+ if !ok {
+     return fmt.Errorf("failed to assert s.store.GetStateCommitment() to snapshots.CommitSnapshotter")
+ }

This change ensures that the type assertions are checked, and appropriate error handling is in place to prevent unexpected panics.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ss := s.store.GetStateStorage().(snapshots.StorageSnapshotter)
sc := s.store.GetStateCommitment().(snapshots.CommitSnapshotter)
ssInterface := s.store.GetStateStorage()
ss, ok := ssInterface.(snapshots.StorageSnapshotter)
if !ok {
return fmt.Errorf("failed to assert s.store.GetStateStorage() to snapshots.StorageSnapshotter")
}
scInterface := s.store.GetStateCommitment()
sc, ok := scInterface.(snapshots.CommitSnapshotter)
if !ok {
return fmt.Errorf("failed to assert s.store.GetStateCommitment() to snapshots.CommitSnapshotter")
}


snapshotStore, err := GetSnapshotStore(s.config.ConfigTomlConfig.RootDir)
if err != nil {
Expand Down
8 changes: 2 additions & 6 deletions server/v2/cometbft/types/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
)

type Store interface {
storev2.Backend

kocubinski marked this conversation as resolved.
Show resolved Hide resolved
// GetLatestVersion returns the latest version that consensus has been made on
GetLatestVersion() (uint64, error)
// StateLatest returns a readonly view over the latest
Expand All @@ -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
}
2 changes: 1 addition & 1 deletion server/v2/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down
2 changes: 1 addition & 1 deletion server/v2/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
16 changes: 8 additions & 8 deletions server/v2/store/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"cosmossdk.io/core/transaction"
"cosmossdk.io/log"
serverv2 "cosmossdk.io/server/v2"
storev2 "cosmossdk.io/store/v2"
)

var (
Expand All @@ -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 {
Expand All @@ -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
}

Expand All @@ -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),
},
}
}
Expand Down
14 changes: 9 additions & 5 deletions server/v2/store/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 <height> <format>",
Short: "Restore app state from local snapshot",
Expand All @@ -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 {
Expand Down Expand Up @@ -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) {
kocubinski marked this conversation as resolved.
Show resolved Hide resolved
home := v.GetString(serverv2.FlagHome)
snapshotStore, err := snapshots.NewStore(filepath.Join(home, "data", "snapshots"))
if err != nil {
Expand All @@ -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)
Comment on lines +374 to +378
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle type assertions to prevent potential panics.

At lines 376-377, the code uses unchecked type assertions. The Uber Go Style Guide recommends using the two-value form to handle cases where the assertion might fail, preventing runtime panics.

Modify the code to handle type assertion failures:

commitSnapshotter, ok := store.GetStateCommitment().(snapshots.CommitSnapshotter)
if !ok {
	return nil, fmt.Errorf("store does not implement snapshots.CommitSnapshotter")
}
storageSnapshotter, ok := store.GetStateStorage().(snapshots.StorageSnapshotter)
if !ok {
	return nil, fmt.Errorf("store does not implement snapshots.StorageSnapshotter")
}

sm := snapshots.NewManager(
	snapshotStore,
	snapshots.NewSnapshotOptions(interval, uint32(keepRecent)),
	commitSnapshotter,
	storageSnapshotter,
	nil,
	logger,
)

Comment on lines +374 to +378
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent potential runtime panic due to unchecked type assertions

In the call to snapshots.NewManager, the code performs unchecked type assertions:

store.GetStateCommitment().(snapshots.CommitSnapshotter),
store.GetStateStorage().(snapshots.StorageSnapshotter),

If store.GetStateCommitment() or store.GetStateStorage() do not return types that implement the expected interfaces, this will cause a runtime panic.

Consider using the comma-ok idiom to safely perform the type assertions and handle any errors appropriately. Here's how you can modify the code:

+	commitSnapshotter, ok := store.GetStateCommitment().(snapshots.CommitSnapshotter)
+	if !ok {
+		return nil, fmt.Errorf("store's state commitment does not implement snapshots.CommitSnapshotter")
+	}
+	storageSnapshotter, ok := store.GetStateStorage().(snapshots.StorageSnapshotter)
+	if !ok {
+		return nil, fmt.Errorf("store's state storage does not implement snapshots.StorageSnapshotter")
+	}
-	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)),
+		commitSnapshotter,
+		storageSnapshotter,
+		nil, logger)

This change ensures that if the type assertions fail, a meaningful error is returned instead of causing a panic.

return sm, nil
}

Expand Down
1 change: 0 additions & 1 deletion server/v2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
7 changes: 5 additions & 2 deletions simapp/v2/simdv2/cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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,
kocubinski marked this conversation as resolved.
Show resolved Hide resolved
moduleManager *runtimev2.MM[T],
) {
cfg := sdk.GetConfig()
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion simapp/v2/simdv2/cmd/root_di.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -51,6 +52,7 @@ func NewRootCmd[T transaction.Tx]() *cobra.Command {
std.RegisterLegacyAminoCodec,
),
),
&storeBuilder,
&autoCliOpts,
&moduleManager,
&clientCtx,
Expand Down Expand Up @@ -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)
Expand Down
20 changes: 12 additions & 8 deletions store/v2/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Loading