Skip to content

Commit

Permalink
Implement rollback command (cosmos#11179) (cosmos#11314)
Browse files Browse the repository at this point in the history
Closes: cosmos#10281

fix tendermint rollback

changelog

update tendermint to recent v0.35.x branch

(cherry picked from commit 8296ad9)

Co-authored-by: yihuang <huang@crypto.com>
  • Loading branch information
2 people authored and tomtau committed Sep 2, 2022
1 parent 27c41e9 commit f4edf99
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
49 changes: 49 additions & 0 deletions server/rollback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package server

import (
"fmt"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/store/rootmulti"
"github.com/spf13/cobra"
tmcmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
)

// NewRollbackCmd creates a command to rollback tendermint and multistore state by one height.
func NewRollbackCmd(defaultNodeHome string) *cobra.Command {
cmd := &cobra.Command{
Use: "rollback",
Short: "rollback cosmos-sdk and tendermint state by one height",
Long: `
A state rollback is performed to recover from an incorrect application state transition,
when Tendermint has persisted an incorrect app hash and is thus unable to make
progress. Rollback overwrites a state at height n with the state at height n - 1.
The application also roll back to height n - 1. No blocks are removed, so upon
restarting Tendermint the transactions in block n will be re-executed against the
application.
`,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := GetServerContextFromCmd(cmd)
cfg := ctx.Config
home := cfg.RootDir
db, err := openDB(home)
if err != nil {
return err
}
// rollback tendermint state
height, hash, err := tmcmd.RollbackState(ctx.Config)
if err != nil {
return fmt.Errorf("failed to rollback tendermint state: %w", err)
}
// rollback the multistore
cms := rootmulti.NewStore(db)
cms.RollbackToVersion(height)

fmt.Printf("Rolled back state to height %d and hash %X", height, hash)
return nil
},
}

cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
return cmd
}
1 change: 1 addition & 0 deletions server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ func AddCommands(rootCmd *cobra.Command, defaultNodeHome string, appCreator type
tendermintCmd,
ExportCmd(appExport, defaultNodeHome),
version.NewVersionCommand(),
NewRollbackCmd(defaultNodeHome),
)
}

Expand Down
24 changes: 24 additions & 0 deletions store/rootmulti/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,30 @@ func (rs *Store) buildCommitInfo(version int64) *types.CommitInfo {
}
}

// RollbackToVersion delete the versions after `target` and update the latest version.
func (rs *Store) RollbackToVersion(target int64) int64 {
if target < 0 {
panic("Negative rollback target")
}
current := getLatestVersion(rs.db)
if target >= current {
return current
}
for ; current > target; current-- {
rs.pruneHeights = append(rs.pruneHeights, current)
}
rs.pruneStores()

// update latest height
bz, err := gogotypes.StdInt64Marshal(current)
if err != nil {
panic(err)
}

rs.db.Set([]byte(latestVersionKey), bz)
return current
}

type storeParams struct {
key types.StoreKey
db dbm.DB
Expand Down

0 comments on commit f4edf99

Please sign in to comment.