package server import ( "fmt" cmtcmd "github.com/cometbft/cometbft/cmd/cometbft/commands" "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/server/types" ) // NewRollbackCmd creates a command to rollback CometBFT and multistore state by one height. func NewRollbackCmd[T types.Application](appCreator types.AppCreator[T]) *cobra.Command { var removeBlock bool cmd := &cobra.Command{ Use: "rollback", Short: "rollback Cosmos SDK and CometBFT state by one height", Long: ` A state rollback is performed to recover from an incorrect application state transition, when CometBFT 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 rolls back to height n - 1. No blocks are removed, so upon restarting CometBFT the transactions in block n will be re-executed against the application. `, RunE: func(cmd *cobra.Command, args []string) error { ctx := GetServerContextFromCmd(cmd) db, err := OpenDB(ctx.Config.RootDir, GetAppDBBackend(ctx.Viper)) if err != nil { return err } app := appCreator(ctx.Logger, db, nil, ctx.Viper) // rollback CometBFT state height, hash, err := cmtcmd.RollbackState(ctx.Config, removeBlock) if err != nil { return fmt.Errorf("failed to rollback CometBFT state: %w", err) } // rollback the multistore if err := app.CommitMultiStore().RollbackToVersion(height); err != nil { return fmt.Errorf("failed to rollback to version: %w", err) } fmt.Printf("Rolled back state to height %d and hash %X\n", height, hash) return nil }, } cmd.Flags().BoolVar(&removeBlock, "hard", false, "remove last block as well as state") return cmd }