Skip to content

Commit

Permalink
test(systemtests): fix export v2 (#22799)
Browse files Browse the repository at this point in the history
(cherry picked from commit 34f407d)

# Conflicts:
#	server/v2/store/server.go
#	store/db/prefixdb_test.go
#	store/v2/root/builder.go
#	tests/integration/v2/distribution/fixture_test.go
#	tests/systemtests/go.sum
  • Loading branch information
julienrbrt authored and mergify[bot] committed Dec 9, 2024
1 parent d65bc30 commit 0eceef7
Show file tree
Hide file tree
Showing 9 changed files with 417 additions and 4 deletions.
90 changes: 90 additions & 0 deletions server/v2/store/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package store

import (
"context"
"fmt"

"github.com/spf13/cobra"

"cosmossdk.io/core/server"
"cosmossdk.io/core/transaction"
serverv2 "cosmossdk.io/server/v2"

Check failure on line 11 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / split-test-files

no required module provides package cosmossdk.io/server/v2; to add it:

Check failure on line 11 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

no required module provides package cosmossdk.io/server/v2; to add it:

Check failure on line 11 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

no required module provides package cosmossdk.io/server/v2; to add it:

Check failure on line 11 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

could not import cosmossdk.io/server/v2 (invalid package name: "")
storev2 "cosmossdk.io/store/v2"

Check failure on line 12 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / split-test-files

no required module provides package cosmossdk.io/store/v2; to add it:

Check failure on line 12 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

no required module provides package cosmossdk.io/store/v2; to add it:

Check failure on line 12 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

no required module provides package cosmossdk.io/store/v2; to add it:

Check failure on line 12 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

could not import cosmossdk.io/store/v2 (invalid package name: "")
"cosmossdk.io/store/v2/root"

Check failure on line 13 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / split-test-files

no required module provides package cosmossdk.io/store/v2/root; to add it:

Check failure on line 13 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

no required module provides package cosmossdk.io/store/v2/root; to add it:

Check failure on line 13 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

no required module provides package cosmossdk.io/store/v2/root; to add it:

Check failure on line 13 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

could not import cosmossdk.io/store/v2/root (invalid package name: "")
)

var (
_ serverv2.ServerComponent[transaction.Tx] = (*Server[transaction.Tx])(nil)
_ serverv2.HasConfig = (*Server[transaction.Tx])(nil)
_ serverv2.HasCLICommands = (*Server[transaction.Tx])(nil)
)

const ServerName = "store"

// Server manages store config and contains prune & snapshot commands
type Server[T transaction.Tx] struct {
config *root.Config
store storev2.Backend
}

func New[T transaction.Tx](store storev2.Backend, cfg server.ConfigMap) (*Server[T], error) {
config, err := UnmarshalConfig(cfg)
if err != nil {
return nil, err
}
return &Server[T]{
store: store,
config: config,
}, nil
}

func (s *Server[T]) Name() string {
return ServerName
}

func (s *Server[T]) Start(context.Context) error {
return nil
}

func (s *Server[T]) Stop(context.Context) error {
return nil
}

func (s *Server[T]) CLICommands() serverv2.CLIConfig {
return serverv2.CLIConfig{
Commands: []*cobra.Command{
s.PrunesCmd(),

Check failure on line 56 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

s.PrunesCmd undefined (type *Server[T] has no field or method PrunesCmd)

Check failure on line 56 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

s.PrunesCmd undefined (type *Server[T] has no field or method PrunesCmd) (typecheck)
s.ExportSnapshotCmd(),

Check failure on line 57 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

s.ExportSnapshotCmd undefined (type *Server[T] has no field or method ExportSnapshotCmd)

Check failure on line 57 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

s.ExportSnapshotCmd undefined (type *Server[T] has no field or method ExportSnapshotCmd) (typecheck)
s.DeleteSnapshotCmd(),

Check failure on line 58 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

s.DeleteSnapshotCmd undefined (type *Server[T] has no field or method DeleteSnapshotCmd)

Check failure on line 58 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

s.DeleteSnapshotCmd undefined (type *Server[T] has no field or method DeleteSnapshotCmd) (typecheck)
s.ListSnapshotsCmd(),

Check failure on line 59 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / dependency-review

s.ListSnapshotsCmd undefined (type *Server[T] has no field or method ListSnapshotsCmd)

Check failure on line 59 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

s.ListSnapshotsCmd undefined (type *Server[T] has no field or method ListSnapshotsCmd) (typecheck)
s.DumpArchiveCmd(),

Check failure on line 60 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

s.DumpArchiveCmd undefined (type *Server[T] has no field or method DumpArchiveCmd) (typecheck)
s.LoadArchiveCmd(),

Check failure on line 61 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

s.LoadArchiveCmd undefined (type *Server[T] has no field or method LoadArchiveCmd) (typecheck)
s.RestoreSnapshotCmd(),

Check failure on line 62 in server/v2/store/server.go

View workflow job for this annotation

GitHub Actions / golangci-lint

s.RestoreSnapshotCmd undefined (type *Server[T] has no field or method RestoreSnapshotCmd) (typecheck)
},
}
}

func (s *Server[T]) Config() any {
if s.config == nil || s.config.AppDBBackend == "" {
return root.DefaultConfig()
}

return s.config
}

// UnmarshalConfig unmarshals the store config from the given map.
// If the config is not found in the map, the default config is returned.
// If the home directory is found in the map, it sets the home directory in the config.
// An empty home directory *is* permitted at this stage, but attempting to build
// the store with an empty home directory will fail.
func UnmarshalConfig(cfg map[string]any) (*root.Config, error) {
config := root.DefaultConfig()
if err := serverv2.UnmarshalSubConfig(cfg, ServerName, config); err != nil {
return nil, fmt.Errorf("failed to unmarshal store config: %w", err)
}
home := cfg[serverv2.FlagHome]
if home != nil {
config.Home = home.(string)
}
return config, nil
}
4 changes: 2 additions & 2 deletions simapp/v2/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ func TestSimAppExportAndBlockedAddrs_WithOneBlockProduced(t *testing.T) {

MoveNextBlock(t, app, ctx)

_, err := app.ExportAppStateAndValidators(nil)
_, err := app.ExportAppStateAndValidators(false, nil)
require.NoError(t, err)
}

func TestSimAppExportAndBlockedAddrs_NoBlocksProduced(t *testing.T) {
app, _ := NewTestApp(t)

_, err := app.ExportAppStateAndValidators(nil)
_, err := app.ExportAppStateAndValidators(false, nil)
require.NoError(t, err)
}
6 changes: 6 additions & 0 deletions simapp/v2/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
// file.
// This is a demonstation of how to export a genesis file. Export may need extended at
// the user discretion for cleaning the genesis state at the end provided with jailAllowedAddrs
// Same applies for forZeroHeight preprocessing.
func (app *SimApp[T]) ExportAppStateAndValidators(
forZeroHeight bool,
jailAllowedAddrs []string,
) (v2.ExportedApp, error) {
ctx := context.Background()
Expand Down Expand Up @@ -44,5 +46,9 @@ func (app *SimApp[T]) ExportAppStateAndValidators(

exportedApp.AppState = genesis
exportedApp.Height = int64(latestHeight)
if forZeroHeight {
exportedApp.Height = 0
}

return exportedApp, nil
}
50 changes: 50 additions & 0 deletions store/db/prefixdb_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package db_test

import (
"testing"

"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"

"cosmossdk.io/store/db"
"cosmossdk.io/store/mock"
)

func TestPrefixDB(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

mockDB := mock.NewMockKVStoreWithBatch(mockCtrl)
prefix := []byte("test:")
pdb := db.NewPrefixDB(mockDB, prefix)

key := []byte("key1")
value := []byte("value1")
mockDB.EXPECT().Set(gomock.Eq(append(prefix, key...)), gomock.Eq(value)).Return(nil)

err := pdb.Set(key, value)
require.NoError(t, err)

mockDB.EXPECT().Get(gomock.Eq(append(prefix, key...))).Return(value, nil)

returnedValue, err := pdb.Get(key)
require.NoError(t, err)
require.Equal(t, value, returnedValue)

mockDB.EXPECT().Has(gomock.Eq(append(prefix, key...))).Return(true, nil)

has, err := pdb.Has(key)
require.NoError(t, err)
require.True(t, has)

mockDB.EXPECT().Delete(gomock.Eq(append(prefix, key...))).Return(nil)

err = pdb.Delete(key)
require.NoError(t, err)

mockDB.EXPECT().Has(gomock.Eq(append(prefix, key...))).Return(false, nil)

has, err = pdb.Has(key)
require.NoError(t, err)
require.False(t, has)
}
100 changes: 100 additions & 0 deletions store/v2/root/builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package root

import (
"fmt"
"path/filepath"

"cosmossdk.io/log"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/db"

Check failure on line 9 in store/v2/root/builder.go

View workflow job for this annotation

GitHub Actions / split-test-files

no required module provides package cosmossdk.io/store/v2/db; to add it:

Check failure on line 9 in store/v2/root/builder.go

View workflow job for this annotation

GitHub Actions / dependency-review

no required module provides package cosmossdk.io/store/v2/db; to add it:
)

// Builder is the interface for a store/v2 RootStore builder.
// RootStores built by the Cosmos SDK typically involve a 2 phase initialization:
// 1. Namespace registration
// 2. Configuration and loading
//
// The Builder interface is used to facilitate this pattern. Namespaces (store keys) are registered
// by calling RegisterKey before Build is called. Build is then called with a Config
// object and a RootStore is returned. Calls to Get may return the `RootStore` if Build
// was successful, but that's left up to the implementation.
type Builder interface {
// Build creates a new store/v2 RootStore from the given Config.
Build(log.Logger, *Config) (store.RootStore, error)

Check failure on line 23 in store/v2/root/builder.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: Config (typecheck)
// RegisterKey registers a store key (namespace) to be used when building the RootStore.
RegisterKey(string)
// Get returns the Store. Build should be called before calling Get or the result will be nil.
Get() store.RootStore

Check failure on line 27 in store/v2/root/builder.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: store (typecheck)
}

var _ Builder = (*builder)(nil)

// builder is the default builder for a store/v2 RootStore satisfying the Store interface.
// Tangibly it combines store key registration and a top-level Config to create a RootStore by calling
// the CreateRootStore factory function.
type builder struct {
// input
storeKeys map[string]struct{}

// output
store store.RootStore

Check failure on line 40 in store/v2/root/builder.go

View workflow job for this annotation

GitHub Actions / golangci-lint

undefined: store (typecheck)
}

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")
}

if len(config.AppDBBackend) == 0 {
return nil, fmt.Errorf("application db backend is required")
}

scRawDb, err := db.NewDB(
db.DBType(config.AppDBBackend),
"application",
filepath.Join(config.Home, "data"),
nil,
)
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.With("module", "store"),
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
}

func (sb *builder) Get() store.RootStore {
return sb.store
}

func (sb *builder) RegisterKey(key string) {
sb.storeKeys[key] = struct{}{}
}
Loading

0 comments on commit 0eceef7

Please sign in to comment.