Browse Source

fix app hash in state rollback (backport #7837) (#7881)

When testing rollback feature in the Cosmos SDK, we found that the app hash
in Tendermint after rollback was the value after the latest block, rather than
before it.

Co-authored-by: Callum Waters <cmwaters19@gmail.com>
Co-authored-by: yihuang <huang@crypto.com>

(cherry picked from commit 8a238fdcb4)

Inline factory function that does not exist in this branch.

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>
pull/7902/head
mergify[bot] 2 years ago
committed by GitHub
parent
commit
89bb82617a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 4 deletions
  1. +2
    -0
      CHANGELOG_PENDING.md
  2. +8
    -2
      state/rollback.go
  3. +14
    -2
      state/rollback_test.go

+ 2
- 0
CHANGELOG_PENDING.md View File

@ -23,3 +23,5 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
### IMPROVEMENTS
### BUG FIXES
- [cli] [#7837](https://github.com/tendermint/tendermint/pull/7837) fix app hash in state rollback. (@yihuang)

+ 8
- 2
state/rollback.go View File

@ -43,6 +43,12 @@ func Rollback(bs BlockStore, ss Store) (int64, []byte, error) {
if rollbackBlock == nil {
return -1, nil, fmt.Errorf("block at height %d not found", rollbackHeight)
}
// We also need to retrieve the latest block because the app hash and last
// results hash is only agreed upon in the following block.
latestBlock := bs.LoadBlockMeta(invalidState.LastBlockHeight)
if latestBlock == nil {
return -1, nil, fmt.Errorf("block at height %d not found", invalidState.LastBlockHeight)
}
previousLastValidatorSet, err := ss.LoadValidators(rollbackHeight)
if err != nil {
@ -91,8 +97,8 @@ func Rollback(bs BlockStore, ss Store) (int64, []byte, error) {
ConsensusParams: previousParams,
LastHeightConsensusParamsChanged: paramsChangeHeight,
LastResultsHash: rollbackBlock.Header.LastResultsHash,
AppHash: rollbackBlock.Header.AppHash,
LastResultsHash: latestBlock.Header.LastResultsHash,
AppHash: latestBlock.Header.AppHash,
}
// persist the new state. This overrides the invalid one. NOTE: this will also


+ 14
- 2
state/rollback_test.go View File

@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"
dbm "github.com/tendermint/tm-db"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/tmhash"
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
@ -49,12 +50,22 @@ func TestRollback(t *testing.T) {
BlockID: initialState.LastBlockID,
Header: types.Header{
Height: initialState.LastBlockHeight,
AppHash: initialState.AppHash,
AppHash: crypto.CRandBytes(tmhash.Size),
LastBlockID: makeBlockIDRandom(),
LastResultsHash: initialState.LastResultsHash,
},
}
blockStore.On("LoadBlockMeta", initialState.LastBlockHeight).Return(block)
nextBlock := &types.BlockMeta{
BlockID: initialState.LastBlockID,
Header: types.Header{
Height: nextState.LastBlockHeight,
AppHash: initialState.AppHash,
LastBlockID: block.BlockID,
LastResultsHash: nextState.LastResultsHash,
},
}
blockStore.On("LoadBlockMeta", height).Return(block)
blockStore.On("LoadBlockMeta", nextHeight).Return(nextBlock)
blockStore.On("Height").Return(nextHeight)
// rollback the state
@ -84,6 +95,7 @@ func TestRollbackNoBlocks(t *testing.T) {
stateStore := setupStateStore(t, height)
blockStore := &mocks.BlockStore{}
blockStore.On("Height").Return(height)
blockStore.On("LoadBlockMeta", height).Return(nil)
blockStore.On("LoadBlockMeta", height-1).Return(nil)
_, _, err := state.Rollback(blockStore, stateStore)


Loading…
Cancel
Save