gitlab.com/gpdionisio/tendermint@v0.34.19-dev2/cmd/tendermint/commands/rollback.go (about) 1 package commands 2 3 import ( 4 "fmt" 5 6 "github.com/spf13/cobra" 7 8 dbm "github.com/tendermint/tm-db" 9 10 cfg "github.com/tendermint/tendermint/config" 11 "github.com/tendermint/tendermint/state" 12 "github.com/tendermint/tendermint/store" 13 ) 14 15 var RollbackStateCmd = &cobra.Command{ 16 Use: "rollback", 17 Short: "rollback tendermint state by one height", 18 Long: ` 19 A state rollback is performed to recover from an incorrect application state transition, 20 when Tendermint has persisted an incorrect app hash and is thus unable to make 21 progress. Rollback overwrites a state at height n with the state at height n - 1. 22 The application should also roll back to height n - 1. No blocks are removed, so upon 23 restarting Tendermint the transactions in block n will be re-executed against the 24 application. 25 `, 26 RunE: func(cmd *cobra.Command, args []string) error { 27 height, hash, err := RollbackState(config) 28 if err != nil { 29 return fmt.Errorf("failed to rollback state: %w", err) 30 } 31 32 fmt.Printf("Rolled back state to height %d and hash %v", height, hash) 33 return nil 34 }, 35 } 36 37 // RollbackState takes the state at the current height n and overwrites it with the state 38 // at height n - 1. Note state here refers to tendermint state not application state. 39 // Returns the latest state height and app hash alongside an error if there was one. 40 func RollbackState(config *cfg.Config) (int64, []byte, error) { 41 // use the parsed config to load the block and state store 42 blockStore, stateStore, err := loadStateAndBlockStore(config) 43 if err != nil { 44 return -1, nil, err 45 } 46 defer func() { 47 _ = blockStore.Close() 48 _ = stateStore.Close() 49 }() 50 51 // rollback the last state 52 return state.Rollback(blockStore, stateStore) 53 } 54 55 func loadStateAndBlockStore(config *cfg.Config) (*store.BlockStore, state.Store, error) { 56 dbType := dbm.BackendType(config.DBBackend) 57 58 // Get BlockStore 59 blockStoreDB, err := dbm.NewDB("blockstore", dbType, config.DBDir()) 60 if err != nil { 61 return nil, nil, err 62 } 63 blockStore := store.NewBlockStore(blockStoreDB) 64 65 // Get StateStore 66 stateDB, err := dbm.NewDB("state", dbType, config.DBDir()) 67 if err != nil { 68 return nil, nil, err 69 } 70 stateStore := state.NewStore(stateDB) 71 72 return blockStore, stateStore, nil 73 }