Skip to content

Commit

Permalink
feat: add local snapshots management commands
Browse files Browse the repository at this point in the history
- `appd snapshots list`
  list local snapshots
- `appd snapshots restore`
  restore from a local snapshot
  • Loading branch information
yihuang committed May 9, 2023
1 parent 2f21cb5 commit 5d167e7
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/bank) [#15764](https://github.com/cosmos/cosmos-sdk/pull/15764) Speedup x/bank InitGenesis
* (x/auth) [#15867](https://github.com/cosmos/cosmos-sdk/pull/15867) Support better logging for signature verification failure.
* (types/query) [#16041](https://github.com/cosmos/cosmos-sdk/pull/16041) change pagination max limit to a variable in order to be modifed by application devs
* (store) [#]() Add local snapshots management commands.

### State Machine Breaking

Expand Down
20 changes: 20 additions & 0 deletions client/snapshot/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package snapshot

import (
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/spf13/cobra"
)

// Cmd returns the snapshots group command
func Cmd(appCreator servertypes.AppCreator) *cobra.Command {
cmd := &cobra.Command{
Use: "snapshots",
Short: "Manage local snapshots",
Long: "Manage local snapshots",
}
cmd.AddCommand(
ListSnapshotsCmd(appCreator),
RestoreSnapshotCmd(appCreator),
)
return cmd
}
39 changes: 39 additions & 0 deletions client/snapshot/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package snapshot

import (
"fmt"

"cosmossdk.io/log"
"github.com/spf13/cobra"

abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
)

// ListSnapshotsCmd returns the command to list local snapshots
func ListSnapshotsCmd(appCreator servertypes.AppCreator) *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List snapshots",
Long: "List snapshots",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := server.GetServerContextFromCmd(cmd)

home := ctx.Config.RootDir
db, err := openDB(home, server.GetAppDBBackend(ctx.Viper))
if err != nil {
return err
}
logger := log.NewLogger(cmd.OutOrStdout())
app := appCreator(logger, db, nil, ctx.Viper)

resp := app.ListSnapshots(abci.RequestListSnapshots{})
for _, snapshot := range resp.Snapshots {
fmt.Println("height:", snapshot.Height, "format:", snapshot.Format, "chunks:", snapshot.Chunks)
}

return nil
},
}
}
51 changes: 51 additions & 0 deletions client/snapshot/restore.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package snapshot

import (
"path/filepath"
"strconv"

"cosmossdk.io/log"
"github.com/spf13/cobra"

dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/cosmos-sdk/server"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
)

// RestoreSnapshotCmd returns a command to restore a snapshot
func RestoreSnapshotCmd(appCreator servertypes.AppCreator) *cobra.Command {
cmd := &cobra.Command{
Use: "restore <height> <format>",
Short: "Restore app state from local snapshot",
Long: "Restore app state from local snapshot",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := server.GetServerContextFromCmd(cmd)

height, err := strconv.ParseUint(args[0], 10, 64)
if err != nil {
return err
}
format, err := strconv.ParseUint(args[1], 10, 32)
if err != nil {
return err
}

home := ctx.Config.RootDir
db, err := openDB(home, server.GetAppDBBackend(ctx.Viper))
if err != nil {
return err
}
logger := log.NewLogger(cmd.OutOrStdout())
app := appCreator(logger, db, nil, ctx.Viper)

sm := app.SnapshotManager()
return sm.RestoreLocalSnapshot(height, uint32(format))
},
}
return cmd
}

func openDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) {
dataDir := filepath.Join(rootDir, "data")
return dbm.NewDB("application", backendType, dataDir)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ require (
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mtibben/percent v0.2.1 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -636,8 +636,9 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
Expand Down
4 changes: 4 additions & 0 deletions server/types/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"

"cosmossdk.io/log"
"cosmossdk.io/store/snapshots"
storetypes "cosmossdk.io/store/types"
abci "github.com/cometbft/cometbft/abci/types"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
Expand Down Expand Up @@ -54,6 +55,9 @@ type (

// CommitMultiStore return the multistore instance
CommitMultiStore() storetypes.CommitMultiStore

// Return the snapshot manager
SnapshotManager() *snapshots.Manager
}

// AppCreator is a function that allows us to lazily initialize an
Expand Down
2 changes: 2 additions & 0 deletions simapp/simd/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/pruning"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/snapshot"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/server"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
Expand Down Expand Up @@ -191,6 +192,7 @@ func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig, b
debug.Cmd(),
confixcmd.ConfigCommand(),
pruning.Cmd(newApp),
snapshot.Cmd(newApp),
)

server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, appExport, addModuleInitFlags)
Expand Down
2 changes: 2 additions & 0 deletions simapp/simd/cmd/root_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/pruning"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/client/snapshot"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/server"
Expand Down Expand Up @@ -207,6 +208,7 @@ func initRootCmd(
debug.Cmd(),
confixcmd.ConfigCommand(),
pruning.Cmd(newApp),
snapshot.Cmd(newApp),
)

server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, appExport, addModuleInitFlags)
Expand Down
9 changes: 9 additions & 0 deletions store/snapshots/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,15 @@ func (m *Manager) RestoreChunk(chunk []byte) (bool, error) {
return false, nil
}

// RestoreLocalSnapshot restores app state from a local snapshot.
func (m *Manager) RestoreLocalSnapshot(height uint64, format uint32) error {
snapshot, ch, err := m.store.Load(height, format)
if err != nil {
return err
}
return m.restoreSnapshot(*snapshot, ch)
}

// sortedExtensionNames sort extension names for deterministic iteration.
func (m *Manager) sortedExtensionNames() []string {
names := make([]string, 0, len(m.extensions))
Expand Down

0 comments on commit 5d167e7

Please sign in to comment.