|
|
- package state
-
- import (
- "errors"
- "fmt"
-
- tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
- tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
- "github.com/tendermint/tendermint/version"
- )
-
- // Rollback overwrites the current Tendermint state (height n) with the most
- // recent previous state (height n - 1).
- // Note that this function does not affect application state.
- func Rollback(bs BlockStore, ss Store) (int64, []byte, error) {
- invalidState, err := ss.Load()
- if err != nil {
- return -1, nil, err
- }
- if invalidState.IsEmpty() {
- return -1, nil, errors.New("no state found")
- }
-
- rollbackHeight := invalidState.LastBlockHeight
- rollbackBlock := bs.LoadBlockMeta(rollbackHeight)
- if rollbackBlock == nil {
- return -1, nil, fmt.Errorf("block at height %d not found", rollbackHeight)
- }
-
- previousValidatorSet, err := ss.LoadValidators(rollbackHeight - 1)
- if err != nil {
- return -1, nil, err
- }
-
- previousParams, err := ss.LoadConsensusParams(rollbackHeight)
- if err != nil {
- return -1, nil, err
- }
-
- valChangeHeight := invalidState.LastHeightValidatorsChanged
- // this can only happen if the validator set changed since the last block
- if valChangeHeight > rollbackHeight {
- valChangeHeight = rollbackHeight
- }
-
- paramsChangeHeight := invalidState.LastHeightConsensusParamsChanged
- // this can only happen if params changed from the last block
- if paramsChangeHeight > rollbackHeight {
- paramsChangeHeight = rollbackHeight
- }
-
- // build the new state from the old state and the prior block
- rolledBackState := State{
- Version: tmstate.Version{
- Consensus: tmversion.Consensus{
- Block: version.BlockProtocol,
- App: previousParams.Version.AppVersion,
- },
- Software: version.TMCoreSemVer,
- },
- // immutable fields
- ChainID: invalidState.ChainID,
- InitialHeight: invalidState.InitialHeight,
-
- LastBlockHeight: invalidState.LastBlockHeight - 1,
- LastBlockID: rollbackBlock.Header.LastBlockID,
- LastBlockTime: rollbackBlock.Header.Time,
-
- NextValidators: invalidState.Validators,
- Validators: invalidState.LastValidators,
- LastValidators: previousValidatorSet,
- LastHeightValidatorsChanged: valChangeHeight,
-
- ConsensusParams: previousParams,
- LastHeightConsensusParamsChanged: paramsChangeHeight,
-
- LastResultsHash: rollbackBlock.Header.LastResultsHash,
- AppHash: rollbackBlock.Header.AppHash,
- }
-
- // persist the new state. This overrides the invalid one. NOTE: this will also
- // persist the validator set and consensus params over the existing structures,
- // but both should be the same
- if err := ss.Save(rolledBackState); err != nil {
- return -1, nil, fmt.Errorf("failed to save rolled back state: %w", err)
- }
-
- return rolledBackState.LastBlockHeight, rolledBackState.AppHash, nil
- }
|