Example #1
0
// 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)
	}

}
Example #2
0
func TestBadProposal(t *testing.T) {
	css, privVals := simpleConsensusState(2)
	cs1, cs2 := css[0], css[1]
	cs1.newStepCh = make(chan *RoundState) // so it blocks

	timeoutChan := make(chan struct{})
	evsw := events.NewEventSwitch()
	evsw.OnStart()
	evsw.AddListenerForEvent("tester", types.EventStringTimeoutPropose(), func(data types.EventData) {
		timeoutChan <- struct{}{}
	})
	evsw.AddListenerForEvent("tester", types.EventStringTimeoutWait(), func(data types.EventData) {
		timeoutChan <- struct{}{}
	})
	cs1.SetFireable(evsw)

	// make the second validator the proposer
	propBlock := changeProposer(t, cs1, cs2)

	// make the block bad by tampering with statehash
	stateHash := propBlock.StateHash
	stateHash[0] = byte((stateHash[0] + 1) % 255)
	propBlock.StateHash = stateHash
	propBlockParts := propBlock.MakePartSet()
	proposal := types.NewProposal(cs2.Height, cs2.Round, propBlockParts.Header(), cs2.Votes.POLRound())
	if err := cs2.privValidator.SignProposal(cs2.state.ChainID, proposal); err != nil {
		t.Fatal("failed to sign bad proposal", err)
	}

	// start round
	cs1.EnterNewRound(cs1.Height, 0, false)

	// now we're on a new round and not the proposer
	<-cs1.NewStepCh()
	// so set the proposal block (and fix voting power)
	cs1.mtx.Lock()
	cs1.Proposal, cs1.ProposalBlock, cs1.ProposalBlockParts = proposal, propBlock, propBlockParts
	fixVotingPower(t, cs1, privVals[1].Address)
	cs1.mtx.Unlock()
	// and wait for timeout
	<-timeoutChan

	// go to prevote, prevote for nil (proposal is bad)
	<-cs1.NewStepCh()
	validatePrevote(t, cs1, 0, privVals[0], nil)

	// add bad prevote from cs2. we should precommit nil
	signAddVoteToFrom(types.VoteTypePrevote, cs1, cs2, propBlock.Hash(), propBlock.MakePartSet().Header())
	_, _, _ = <-cs1.NewStepCh(), <-timeoutChan, <-cs1.NewStepCh()
	validatePrecommit(t, cs1, 0, 0, privVals[0], nil, nil)
	signAddVoteToFrom(types.VoteTypePrecommit, cs1, cs2, propBlock.Hash(), propBlock.MakePartSet().Header())
}