cosmos-sdk/store/v2/root/factory.go
Alexander Peters 9a92843c21
store/v2: remove auto migration and fix restore cmd (#23568)
Co-authored-by: mmsqe <mavis@crypto.com>
Co-authored-by: Marko <marko@baricevic.me>
Co-authored-by: marbar3778 <marbar3778@yahoo.com>
2025-01-31 17:34:44 +00:00

144 lines
4.1 KiB
Go

package root
import (
"errors"
"fmt"
iavl_v2 "github.com/cosmos/iavl/v2"
"cosmossdk.io/core/log"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/store/v2"
"cosmossdk.io/store/v2/commitment"
"cosmossdk.io/store/v2/commitment/iavl"
"cosmossdk.io/store/v2/commitment/iavlv2"
"cosmossdk.io/store/v2/commitment/mem"
"cosmossdk.io/store/v2/db"
"cosmossdk.io/store/v2/internal"
"cosmossdk.io/store/v2/metrics"
"cosmossdk.io/store/v2/pruning"
)
type (
SCType string
)
const (
SCTypeIavl SCType = "iavl"
SCTypeIavlV2 SCType = "iavl-v2"
)
const storePrefixTpl = "s/k:%s/" // s/k:<storeKey>
// Options are the options for creating a root store.
type Options struct {
SCType SCType `mapstructure:"sc-type" toml:"sc-type" comment:"State commitment database type. Currently we support: \"iavl\" and \"iavl-v2\""`
SCPruningOption *store.PruningOption `mapstructure:"sc-pruning-option" toml:"sc-pruning-option" comment:"Pruning options for state commitment"`
IavlConfig *iavl.Config `mapstructure:"iavl-config" toml:"iavl-config"`
IavlV2Config iavlv2.Config `mapstructure:"iavl-v2-config" toml:"iavl-v2-config"`
}
// FactoryOptions are the options for creating a root store.
type FactoryOptions struct {
Logger log.Logger
RootDir string
Options Options
StoreKeys []string
SCRawDB corestore.KVStoreWithBatch
}
// DefaultStoreOptions returns the default options for creating a root store.
func DefaultStoreOptions() Options {
return Options{
SCType: SCTypeIavl,
SCPruningOption: &store.PruningOption{
KeepRecent: 2,
Interval: 100,
},
IavlConfig: &iavl.Config{
CacheSize: 500_000,
SkipFastStorageUpgrade: true,
},
}
}
// CreateRootStore is a convenience function to create a root store based on the
// provided FactoryOptions. Strictly speaking app developers can create the root
// store directly by calling root.New, so this function is not
// necessary, but demonstrates the required steps and configuration to create a root store.
func CreateRootStore(opts *FactoryOptions) (store.RootStore, error) {
var (
sc *commitment.CommitStore
err error
)
storeOpts := opts.Options
metadata := commitment.NewMetadataStore(opts.SCRawDB)
latestVersion, err := metadata.GetLatestVersion()
if err != nil {
return nil, err
}
if len(opts.StoreKeys) == 0 {
lastCommitInfo, err := metadata.GetCommitInfo(latestVersion)
if err != nil {
return nil, err
}
if lastCommitInfo == nil {
return nil, fmt.Errorf("tried to construct a root store with no store keys specified but no commit info found for version %d", latestVersion)
}
for _, si := range lastCommitInfo.StoreInfos {
opts.StoreKeys = append(opts.StoreKeys, si.Name)
}
}
removedStoreKeys, err := metadata.GetRemovedStoreKeys(latestVersion)
if err != nil {
return nil, err
}
newTreeFn := func(key string, scType SCType) (commitment.Tree, error) {
if internal.IsMemoryStoreKey(key) {
return mem.New(), nil
} else {
switch scType {
case SCTypeIavl:
return iavl.NewIavlTree(db.NewPrefixDB(opts.SCRawDB, []byte(fmt.Sprintf(storePrefixTpl, key))), opts.Logger, storeOpts.IavlConfig), nil
case SCTypeIavlV2:
dir := fmt.Sprintf("%s/data/iavl-v2/%s", opts.RootDir, key)
return iavlv2.NewTree(opts.Options.IavlV2Config, iavl_v2.SqliteDbOptions{Path: dir}, opts.Logger)
default:
return nil, errors.New("unsupported commitment store type")
}
}
}
// check if we need to migrate the store
scType := storeOpts.SCType
trees := make(map[string]commitment.Tree, len(opts.StoreKeys))
for _, key := range opts.StoreKeys {
tree, err := newTreeFn(key, scType)
if err != nil {
return nil, err
}
trees[key] = tree
}
oldTrees := make(map[string]commitment.Tree, len(opts.StoreKeys))
for _, key := range removedStoreKeys {
tree, err := newTreeFn(string(key), scType)
if err != nil {
return nil, err
}
oldTrees[string(key)] = tree
}
sc, err = commitment.NewCommitStore(trees, oldTrees, opts.SCRawDB, opts.Logger)
if err != nil {
return nil, err
}
pm := pruning.NewManager(sc, storeOpts.SCPruningOption)
return New(opts.SCRawDB, opts.Logger, sc, pm, metrics.NoOpMetrics{})
}