Skip to content

Commit

Permalink
feat(server): make rollback command generic (#23321)
Browse files Browse the repository at this point in the history
Co-authored-by: Julien Robert <[email protected]>
  • Loading branch information
tac0turtle and julienrbrt authored Jan 14, 2025
1 parent a05ca78 commit a40ade9
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i

* (sims) [#23013](https://github.com/cosmos/cosmos-sdk/pull/23013) Integration with app v2
* (x/auth/ante) [#23128](https://github.com/cosmos/cosmos-sdk/pull/23128) Allow custom verifyIsOnCurve when validate tx for public key like ethsecp256k1.
* (server) [#23128](https://github.com/cosmos/cosmos-sdk/pull/23128) Add custom rollback command option. In order to use it, you need to implement the Rollback interface and remove the default rollback command with `cmd.RemoveCommand(cmd.RollbackCmd)` and then add it back with `cmd.AddCommand(cmd.NewCustomRollbackCmd(appCreator, rollbackable))`.

### Improvements

Expand Down
43 changes: 43 additions & 0 deletions server/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,46 @@ application.
cmd.Flags().BoolVar(&removeBlock, "hard", false, "remove last block as well as state")
return cmd
}

// NewRollbackCmdRollback creates a command to set custom rollback functionality and multistore state by one height.
func NewRollbackCmdRollback[T types.Application, R Rollback](appCreator types.AppCreator[T], rollbackable R) *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 := rollbackable.RollbackToVersion(ctx, 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
}
22 changes: 22 additions & 0 deletions server/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,3 +580,25 @@ func GetSnapshotStore(appOpts types.AppOptions) (*snapshots.Store, error) {

return snapshotStore, nil
}

// Rollbackable is an interface that allows for rollback operations.
// It is used to allow for custom rollback operations, such as those provided by the
// DefaultRollbackable implementation.
type Rollback interface {
RollbackToVersion(ctx *Context, removeBlock bool) (int64, []byte, error)
}

// DefaultRollbackable is a default implementation of the Rollbackable interface.
type DefaultRollbackable[T types.Application] struct {
appCreator types.AppCreator[T]
}

// NewDefaultRollbackable creates a new DefaultRollbackable instance.
func NewDefaultRollbackable[T types.Application](appCreator types.AppCreator[T]) *DefaultRollbackable[T] {
return &DefaultRollbackable[T]{appCreator}
}

// RollbackToVersion implements the Rollbackable interface.
func (d DefaultRollbackable[T]) RollbackToVersion(ctx *Context, removeBlock bool) (int64, []byte, error) {
return cmtcmd.RollbackState(ctx.Config, removeBlock)
}

0 comments on commit a40ade9

Please sign in to comment.