// Decides on the next proposal and sets them onto cs.Proposal* func (cs *ConsensusState) decideProposal(height int, round int) { var block *types.Block var blockParts *types.PartSet // Decide on block if cs.LockedBlock != nil { // If we're locked onto a block, just choose that. block, blockParts = cs.LockedBlock, cs.LockedBlockParts } else { // Create a new proposal block from state/txs from the mempool. block, blockParts = cs.createProposalBlock() } // Make proposal proposal := types.NewProposal(height, round, blockParts.Header(), cs.Votes.POLRound()) err := cs.privValidator.SignProposal(cs.state.ChainID, proposal) if err == nil { log.Notice("Signed and set proposal", "height", height, "round", round, "proposal", proposal) log.Debug(Fmt("Signed and set proposal block: %v", block)) // Set fields cs.Proposal = proposal cs.ProposalBlock = block cs.ProposalBlockParts = blockParts } else { log.Warn("EnterPropose: Error signing proposal", "height", height, "round", round, "error", err) } }
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 copy of the state for staging stateCopy := cs.state.Copy() // reset the event cache and pass it into the state cs.evc = events.NewEventCache(cs.evsw) stateCopy.SetFireable(cs.evc) // Commit block onto the copied state. // NOTE: Basic validation is done in state.AppendBlock(). err := sm.ExecBlock(stateCopy, block, blockParts.Header()) if err != nil { return err } else { cs.stagedBlock = block cs.stagedState = stateCopy return nil } }
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 }
// May block on send if queue is full. func (cs *ConsensusState) SetProposalAndBlock(proposal *types.Proposal, block *types.Block, parts *types.PartSet, peerKey string) error { cs.SetProposal(proposal, peerKey) for i := 0; i < parts.Total(); i++ { part := parts.GetPart(i) cs.AddProposalBlockPart(proposal.Height, proposal.Round, part, peerKey) } return nil // TODO errors }
// blockParts: Must be parts of the block // seenValidation: The +2/3 precommits that were seen which committed at height. // If all the nodes restart after committing a block, // we need this to reload the precommits to catch-up nodes to the // most recent height. Otherwise they'd stall at H-1. func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenValidation *types.Validation) { height := block.Height if height != bs.height+1 { PanicSanity(Fmt("BlockStore can only save contiguous blocks. Wanted %v, got %v", bs.height+1, height)) } if !blockParts.IsComplete() { PanicSanity(Fmt("BlockStore can only save complete block part sets")) } // Save block meta meta := types.NewBlockMeta(block, blockParts) metaBytes := wire.BinaryBytes(meta) bs.db.Set(calcBlockMetaKey(height), metaBytes) // Save block parts for i := 0; i < blockParts.Total(); i++ { bs.saveBlockPart(height, i, blockParts.GetPart(i)) } // Save block validation (duplicate and separate from the Block) blockValidationBytes := wire.BinaryBytes(block.LastValidation) bs.db.Set(calcBlockValidationKey(height-1), blockValidationBytes) // Save seen validation (seen +2/3 precommits for block) seenValidationBytes := wire.BinaryBytes(seenValidation) bs.db.Set(calcSeenValidationKey(height), seenValidationBytes) // Save new BlockStoreStateJSON descriptor BlockStoreStateJSON{Height: height}.Save(bs.db) // Done! bs.height = height }
func (cs *ConsensusState) decideProposal(height, round int) { var block *types.Block var blockParts *types.PartSet // Decide on block if cs.LockedBlock != nil { // If we're locked onto a block, just choose that. block, blockParts = cs.LockedBlock, cs.LockedBlockParts } else { // Create a new proposal block from state/txs from the mempool. block, blockParts = cs.createProposalBlock() if block == nil { // on error return } } // Make proposal proposal := types.NewProposal(height, round, blockParts.Header(), cs.Votes.POLRound()) err := cs.privValidator.SignProposal(cs.state.ChainID, proposal) if err == nil { // Set fields /* fields set by setProposal and addBlockPart cs.Proposal = proposal cs.ProposalBlock = block cs.ProposalBlockParts = blockParts */ // send proposal and block parts on internal msg queue cs.sendInternalMessage(msgInfo{&ProposalMessage{proposal}, ""}) for i := 0; i < blockParts.Total(); i++ { part := blockParts.GetPart(i) cs.sendInternalMessage(msgInfo{&BlockPartMessage{cs.Height, cs.Round, part}, ""}) } log.Info("Signed and sent proposal", "height", height, "round", round, "proposal", proposal) log.Debug(Fmt("Signed and sent proposal block: %v", block)) } else { log.Warn("enterPropose: Error signing proposal", "height", height, "round", round, "error", err) } }