Browse Source

cleanup ReplayBlocks

pull/319/head
Ethan Buchman 8 years ago
parent
commit
e1e2c1c740
1 changed files with 31 additions and 48 deletions
  1. +31
    -48
      state/execution.go

+ 31
- 48
state/execution.go View File

@ -381,24 +381,11 @@ func (h *Handshaker) ReplayBlocks(appHash []byte, header *types.Header, partsHea
// it should save all eg. valset changes before calling Commit.
// then, if tm state is behind app state, the only thing missing can be app hash
// get a fresh state and reset to the apps latest
stateCopy := h.state.Copy()
// TODO: put validators in iavl tree so we can set the state with an older validator set
lastVals, nextVals := stateCopy.GetValidators()
if header == nil {
stateCopy.LastBlockHeight = 0
stateCopy.LastBlockID = types.BlockID{}
// stateCopy.LastBlockTime = ... doesnt matter
stateCopy.Validators = nextVals
stateCopy.LastValidators = lastVals
} else {
stateCopy.SetBlockAndValidators(header, partsHeader, lastVals, nextVals)
var appBlockHeight int
if header != nil {
appBlockHeight = header.Height
}
stateCopy.Stale = false
stateCopy.AppHash = appHash
appBlockHeight := stateCopy.LastBlockHeight
coreBlockHeight := h.store.Height()
if coreBlockHeight < appBlockHeight {
// if the app is ahead, there's nothing we can do
@ -412,7 +399,7 @@ func (h *Handshaker) ReplayBlocks(appHash []byte, header *types.Header, partsHea
h.state.Stale = false
h.state.AppHash = appHash
}
return checkState(h.state, stateCopy)
return nil
} else if h.state.LastBlockHeight == appBlockHeight {
// core is ahead of app but core's state height is at apps height
@ -428,42 +415,38 @@ func (h *Handshaker) ReplayBlocks(appHash []byte, header *types.Header, partsHea
return ErrLastStateMismatch{coreBlockHeight, block.Header.AppHash, appHash}
}
// replay the block against the actual tendermint state (not the copy)
return h.loadApplyBlock(coreBlockHeight, h.state, appConnConsensus)
h.nBlocks += 1
var eventCache types.Fireable // nil
// replay the block against the actual tendermint state
return h.state.ApplyBlock(eventCache, appConnConsensus, block, block.MakePartSet(h.config.GetInt("block_part_size")).Header(), mockMempool{})
} else {
// either we're caught up or there's blocks to replay
// replay all blocks starting with appBlockHeight+1
var eventCache types.Fireable // nil
var appHash []byte
for i := appBlockHeight + 1; i <= coreBlockHeight; i++ {
h.loadApplyBlock(i, stateCopy, appConnConsensus)
h.nBlocks += 1
block := h.store.LoadBlock(i)
_, err := execBlockOnProxyApp(eventCache, appConnConsensus, block)
if err != nil {
// ...
}
// Commit block, get hash back
res := appConnConsensus.CommitSync()
if res.IsErr() {
log.Warn("Error in proxyAppConn.CommitSync", "error", res)
return res
}
if res.Log != "" {
log.Info("Commit.Log: " + res.Log)
}
appHash = res.Data
}
if !bytes.Equal(h.state.AppHash, appHash) {
return errors.New(Fmt("Tendermint state.AppHash does not match AppHash after replay", "expected", h.state.AppHash, "got", appHash))
}
return checkState(h.state, stateCopy)
}
}
func checkState(s, stateCopy *State) error {
// The computed state and the previously set state should be identical
if !s.Equals(stateCopy) {
return ErrStateMismatch{stateCopy, s}
}
return nil
}
func (h *Handshaker) loadApplyBlock(blockIndex int, state *State, appConnConsensus proxy.AppConnConsensus) error {
h.nBlocks += 1
block := h.store.LoadBlock(blockIndex)
panicOnNilBlock(blockIndex, h.store.Height(), block) // XXX
var eventCache types.Fireable // nil
return state.ApplyBlock(eventCache, appConnConsensus, block, block.MakePartSet(h.config.GetInt("block_part_size")).Header(), mockMempool{})
}
func panicOnNilBlock(height, bsHeight int, block *types.Block) {
if block == nil {
// Sanity?
PanicCrisis(Fmt(`
block is nil for height <= blockStore.Height() (%d <= %d).
Block: %v,
`, height, bsHeight, block))
}
return nil // should never happen
}

Loading…
Cancel
Save