mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-11 20:31:20 +00:00
Make order be decided first; Remove TMSP Commit/Rollback
This commit is contained in:
@ -173,16 +173,14 @@ func (ti *timeoutInfo) String() string {
|
||||
type ConsensusState struct {
|
||||
QuitService
|
||||
|
||||
proxyAppCtx proxy.AppContext
|
||||
proxyAppConn proxy.AppConn
|
||||
blockStore *bc.BlockStore
|
||||
mempool *mempl.Mempool
|
||||
privValidator *types.PrivValidator
|
||||
|
||||
mtx sync.Mutex
|
||||
RoundState
|
||||
state *sm.State // State until height-1.
|
||||
stagedBlock *types.Block // Cache last staged block.
|
||||
stagedState *sm.State // Cache result of staged block.
|
||||
state *sm.State // State until height-1.
|
||||
|
||||
peerMsgQueue chan msgInfo // serializes msgs affecting state (proposals, block parts, votes)
|
||||
internalMsgQueue chan msgInfo // like peerMsgQueue but for our own proposals, parts, votes
|
||||
@ -191,14 +189,13 @@ type ConsensusState struct {
|
||||
tockChan chan timeoutInfo // timeouts are relayed on tockChan to the receiveRoutine
|
||||
|
||||
evsw *events.EventSwitch
|
||||
evc *events.EventCache // set in stageBlock and passed into state
|
||||
|
||||
nSteps int // used for testing to limit the number of transitions the state makes
|
||||
}
|
||||
|
||||
func NewConsensusState(state *sm.State, proxyAppCtx proxy.AppContext, blockStore *bc.BlockStore, mempool *mempl.Mempool) *ConsensusState {
|
||||
func NewConsensusState(state *sm.State, proxyAppConn proxy.AppConn, blockStore *bc.BlockStore, mempool *mempl.Mempool) *ConsensusState {
|
||||
cs := &ConsensusState{
|
||||
proxyAppCtx: proxyAppCtx,
|
||||
proxyAppConn: proxyAppConn,
|
||||
blockStore: blockStore,
|
||||
mempool: mempool,
|
||||
peerMsgQueue: make(chan msgInfo, msgQueueSize),
|
||||
@ -416,7 +413,7 @@ func (cs *ConsensusState) updateToState(state *sm.State) {
|
||||
|
||||
// Reset fields based on state.
|
||||
validators := state.Validators
|
||||
height := state.LastBlockHeight + 1 // next desired block height
|
||||
height := state.LastBlockHeight + 1 // Next desired block height
|
||||
lastPrecommits := (*types.VoteSet)(nil)
|
||||
if cs.CommitRound > -1 && cs.Votes != nil {
|
||||
if !cs.Votes.Precommits(cs.CommitRound).HasTwoThirdsMajority() {
|
||||
@ -452,8 +449,6 @@ func (cs *ConsensusState) updateToState(state *sm.State) {
|
||||
cs.LastValidators = state.LastValidators
|
||||
|
||||
cs.state = state
|
||||
cs.stagedBlock = nil
|
||||
cs.stagedState = nil
|
||||
|
||||
// Finally, broadcast RoundState
|
||||
cs.newStep()
|
||||
@ -795,8 +790,8 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts
|
||||
return
|
||||
}
|
||||
|
||||
// Mempool run transactions and the resulting hash
|
||||
txs, hash, err := cs.mempool.Reap()
|
||||
// Mempool validated transactions
|
||||
txs, err := cs.mempool.Reap()
|
||||
if err != nil {
|
||||
log.Warn("createProposalBlock: Error getting proposal txs", "error", err)
|
||||
return nil, nil
|
||||
@ -812,7 +807,7 @@ func (cs *ConsensusState) createProposalBlock() (block *types.Block, blockParts
|
||||
LastBlockHash: cs.state.LastBlockHash,
|
||||
LastBlockParts: cs.state.LastBlockParts,
|
||||
ValidatorsHash: cs.state.Validators.Hash(),
|
||||
AppHash: hash,
|
||||
AppHash: cs.state.AppHash,
|
||||
},
|
||||
LastValidation: validation,
|
||||
Data: &types.Data{
|
||||
@ -878,8 +873,8 @@ func (cs *ConsensusState) doPrevote(height int, round int) {
|
||||
return
|
||||
}
|
||||
|
||||
// Try staging cs.ProposalBlock
|
||||
err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts)
|
||||
// Valdiate proposal block
|
||||
err := cs.state.ValidateBlock(cs.ProposalBlock)
|
||||
if err != nil {
|
||||
// ProposalBlock is invalid, prevote nil.
|
||||
log.Warn("enterPrevote: ProposalBlock is invalid", "error", err)
|
||||
@ -992,7 +987,7 @@ func (cs *ConsensusState) enterPrecommit(height int, round int) {
|
||||
if cs.ProposalBlock.HashesTo(hash) {
|
||||
log.Info("enterPrecommit: +2/3 prevoted proposal block. Locking", "hash", hash)
|
||||
// Validate the block.
|
||||
if err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts); err != nil {
|
||||
if err := cs.state.ValidateBlock(cs.ProposalBlock); err != nil {
|
||||
PanicConsensus(Fmt("enterPrecommit: +2/3 prevoted for an invalid block: %v", err))
|
||||
}
|
||||
cs.LockedRound = round
|
||||
@ -1120,27 +1115,64 @@ func (cs *ConsensusState) finalizeCommit(height int) {
|
||||
}
|
||||
|
||||
hash, header, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority()
|
||||
block, blockParts := cs.ProposalBlock, cs.ProposalBlockParts
|
||||
|
||||
if !ok {
|
||||
PanicSanity(Fmt("Cannot finalizeCommit, commit does not have two thirds majority"))
|
||||
}
|
||||
if !cs.ProposalBlockParts.HasHeader(header) {
|
||||
if !blockParts.HasHeader(header) {
|
||||
PanicSanity(Fmt("Expected ProposalBlockParts header to be commit header"))
|
||||
}
|
||||
if !cs.ProposalBlock.HashesTo(hash) {
|
||||
if !block.HashesTo(hash) {
|
||||
PanicSanity(Fmt("Cannot finalizeCommit, ProposalBlock does not hash to commit hash"))
|
||||
}
|
||||
if err := cs.stageBlock(cs.ProposalBlock, cs.ProposalBlockParts); err != nil {
|
||||
if err := cs.state.ValidateBlock(block); err != nil {
|
||||
PanicConsensus(Fmt("+2/3 committed an invalid block: %v", err))
|
||||
}
|
||||
|
||||
log.Notice("Finalizing commit of block", "height", cs.ProposalBlock.Height, "hash", cs.ProposalBlock.Hash())
|
||||
log.Info(Fmt("%v", cs.ProposalBlock))
|
||||
// We have the block, so stage/save/commit-vote.
|
||||
cs.saveBlock(cs.ProposalBlock, cs.ProposalBlockParts, cs.Votes.Precommits(cs.CommitRound))
|
||||
log.Notice("Finalizing commit of block", "height", block.Height, "hash", block.Hash())
|
||||
log.Info(Fmt("%v", block))
|
||||
|
||||
// Fire off event for new block.
|
||||
cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block})
|
||||
|
||||
// Create a copy of the state for staging
|
||||
stateCopy := cs.state.Copy()
|
||||
|
||||
// Run the block on the State:
|
||||
// + update validator sets
|
||||
// + first rolls back proxyAppConn
|
||||
// + run txs on the proxyAppConn
|
||||
err := stateCopy.ExecBlock(cs.evsw, cs.proxyAppConn, block, blockParts.Header())
|
||||
if err != nil {
|
||||
// TODO: handle this gracefully.
|
||||
PanicQ(Fmt("Exec failed for application"))
|
||||
}
|
||||
|
||||
// Save to blockStore.
|
||||
if cs.blockStore.Height() < block.Height {
|
||||
commits := cs.Votes.Precommits(cs.CommitRound)
|
||||
seenValidation := commits.MakeValidation()
|
||||
cs.blockStore.SaveBlock(block, blockParts, seenValidation)
|
||||
}
|
||||
|
||||
/*
|
||||
// Commit to proxyAppConn
|
||||
err = cs.proxyAppConn.CommitSync()
|
||||
if err != nil {
|
||||
// TODO: handle this gracefully.
|
||||
PanicQ(Fmt("Commit failed for application"))
|
||||
}
|
||||
*/
|
||||
|
||||
// Save the state.
|
||||
stateCopy.Save()
|
||||
|
||||
// Update mempool.
|
||||
cs.mempool.Update(block.Height, block.Txs)
|
||||
|
||||
// NewHeightStep!
|
||||
cs.updateToState(cs.stagedState)
|
||||
cs.updateToState(stateCopy)
|
||||
|
||||
// cs.StartTime is already set.
|
||||
// Schedule Round0 to start soon.
|
||||
@ -1352,39 +1384,6 @@ func (cs *ConsensusState) addVote(valIndex int, vote *types.Vote, peerKey string
|
||||
return
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) stageBlock(block *types.Block, blockParts *types.PartSet) error {
|
||||
if block == nil {
|
||||
PanicSanity("Cannot stage nil block")
|
||||
}
|
||||
|
||||
// Already staged?
|
||||
blockHash := block.Hash()
|
||||
if cs.stagedBlock != nil && len(blockHash) != 0 && bytes.Equal(cs.stagedBlock.Hash(), blockHash) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a new event cache to cache all events.
|
||||
cs.evc = events.NewEventCache(cs.evsw)
|
||||
|
||||
// Create a copy of the state for staging
|
||||
stateCopy := cs.state.Copy()
|
||||
stateCopy.SetEventCache(cs.evc)
|
||||
|
||||
// Run the block on the State:
|
||||
// + update validator sets
|
||||
// + first rolls back proxyAppCtx
|
||||
// + run txs on the proxyAppCtx or rollback
|
||||
err := stateCopy.ExecBlock(cs.proxyAppCtx, block, blockParts.Header())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Everything looks good!
|
||||
cs.stagedBlock = block
|
||||
cs.stagedState = stateCopy
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ConsensusState) signVote(type_ byte, hash []byte, header types.PartSetHeader) (*types.Vote, error) {
|
||||
vote := &types.Vote{
|
||||
Height: cs.Height,
|
||||
@ -1415,41 +1414,6 @@ func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.Part
|
||||
}
|
||||
}
|
||||
|
||||
// Save Block, save the +2/3 Commits we've seen
|
||||
func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSet, commits *types.VoteSet) {
|
||||
|
||||
// The proposal must be valid.
|
||||
if err := cs.stageBlock(block, blockParts); err != nil {
|
||||
PanicSanity(Fmt("saveBlock() an invalid block: %v", err))
|
||||
}
|
||||
|
||||
// Save to blockStore.
|
||||
if cs.blockStore.Height() < block.Height {
|
||||
seenValidation := commits.MakeValidation()
|
||||
cs.blockStore.SaveBlock(block, blockParts, seenValidation)
|
||||
}
|
||||
|
||||
// Commit to proxyAppCtx
|
||||
err := cs.stagedState.Commit(cs.proxyAppCtx)
|
||||
if err != nil {
|
||||
// TODO: handle this gracefully.
|
||||
PanicQ(Fmt("Commit failed for applicaiton"))
|
||||
}
|
||||
|
||||
// Save the state.
|
||||
cs.stagedState.Save()
|
||||
|
||||
// Update mempool.
|
||||
cs.mempool.Update(block)
|
||||
|
||||
// Fire off event
|
||||
if cs.evsw != nil && cs.evc != nil {
|
||||
cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block})
|
||||
go cs.evc.Flush()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
func CompareHRS(h1, r1 int, s1 RoundStepType, h2, r2 int, s2 RoundStepType) int {
|
||||
|
Reference in New Issue
Block a user