Commit e014eeaa authored by caopingcp's avatar caopingcp Committed by vipwzw

fix qbft vote issue

parent 3d7831eb
......@@ -299,7 +299,15 @@ func (cs *ConsensusState) reconstructLastCommit(state State) {
seenCommit := cs.client.csStore.LoadSeenCommit(state.LastBlockHeight)
commit := ttypes.Commit{QbftCommit: seenCommit}
voteType := byte(commit.VoteType)
lastCommit := ttypes.NewVoteSet(state.ChainID, state.LastBlockHeight, commit.Round(), voteType, state.LastValidators)
round := commit.Round()
validators := state.LastValidators
// Increment validators if necessary
if round > 0 {
validators.IncrementAccum(round)
qbftlog.Info("reconstructLastCommit validator change", "round", round,
"proposer", fmt.Sprintf("%X", ttypes.Fingerprint(validators.Proposer.Address)))
}
lastCommit := ttypes.NewVoteSet(state.ChainID, state.LastBlockHeight, round, voteType, validators, state.LastSequence)
if state.LastSequence == 0 {
if voteType != ttypes.VoteTypePrecommit {
panic("reconstructLastCommit: voteType not Precommit")
......@@ -391,7 +399,7 @@ func (cs *ConsensusState) updateToState(state State) {
cs.LockedBlock = nil
cs.ValidRound = -1
cs.ValidBlock = nil
cs.Votes = ttypes.NewHeightVoteSet(state.ChainID, height, validators)
cs.Votes = ttypes.NewHeightVoteSet(state.ChainID, height, validators, state.Sequence)
cs.CommitRound = -1
cs.LastCommit = lastCommit
cs.LastValidators = state.LastValidators
......@@ -635,6 +643,7 @@ func (cs *ConsensusState) enterNewRound(height int64, round int) {
cs.ProposalBlock = nil
cs.ProposalBlockHash = nil
}
cs.Votes.SetValSet(validators)
cs.Votes.SetRound(round + 1) // also track next round (round+1) to allow round-skipping
//cs.eventBus.PublishEventNewRound(cs.RoundStateEvent())
......
......@@ -26,7 +26,7 @@ import (
)
const (
qbftVersion = "0.2.0"
qbftVersion = "0.2.1"
// DefaultQbftPort 默认端口
DefaultQbftPort = 33001
......@@ -114,7 +114,7 @@ type subConfig struct {
MessageInterval int32 `json:"messageInterval"`
}
func applyConfig(sub []byte) {
func applyConfig(cfg *types.Consensus, sub []byte) {
var subcfg subConfig
if sub != nil {
types.MustDecode(sub, &subcfg)
......@@ -122,6 +122,9 @@ func applyConfig(sub []byte) {
genesis = subcfg.Genesis
genesisAmount = subcfg.GenesisAmount
genesisBlockTime = subcfg.GenesisBlockTime
if !cfg.Minerstart {
return
}
timeoutTxAvail.Store(subcfg.TimeoutTxAvail)
timeoutPropose.Store(subcfg.TimeoutPropose)
......@@ -182,6 +185,7 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
qbftlog.Info("create qbft client")
genesis = cfg.Genesis
genesisBlockTime = cfg.GenesisBlockTime
applyConfig(cfg, sub)
if !cfg.Minerstart {
qbftlog.Info("This node only sync block")
c := drivers.NewBaseClient(cfg)
......@@ -189,7 +193,6 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
c.SetChild(client)
return client
}
applyConfig(sub)
//init rand
ttypes.Init()
......@@ -226,8 +229,8 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
return nil
}
qbftlog.Info("show qbft info", "sign", ttypes.CryptoName, "useAggSig", UseAggSig(), "genesisFile", genesisFile,
"privFile", privFile)
qbftlog.Info("show qbft info", "version", qbftVersion, "sign", ttypes.CryptoName, "useAggSig", UseAggSig(),
"genesisFile", genesisFile, "privFile", privFile)
ttypes.InitMessageMap()
......
......@@ -129,6 +129,7 @@ func (s State) StringIndented(indent string) string {
%s LastBlockTotalTx: %v
%s LastBlockID: %X
%s Validators: %v
%s LastProposer: %v
%s Sequence: %v
%s LastSequence: %v
%s LastCommitRound: %v
......@@ -138,6 +139,7 @@ func (s State) StringIndented(indent string) string {
indent, s.LastBlockTotalTx,
indent, s.LastBlockID,
indent, s.Validators.StringIndented(indent),
indent, s.LastValidators.GetProposer().String(),
indent, s.Sequence,
indent, s.LastSequence,
indent, s.LastCommitRound,
......
......@@ -5,6 +5,7 @@
package types
import (
"bytes"
"errors"
"strings"
"sync"
......@@ -37,6 +38,7 @@ One for their LastCommit round, and another for the official commit round.
type HeightVoteSet struct {
chainID string
height int64
seq int64
valSet *ValidatorSet
mtx sync.Mutex
......@@ -46,9 +48,10 @@ type HeightVoteSet struct {
}
// NewHeightVoteSet ...
func NewHeightVoteSet(chainID string, height int64, valSet *ValidatorSet) *HeightVoteSet {
func NewHeightVoteSet(chainID string, height int64, valSet *ValidatorSet, seq int64) *HeightVoteSet {
hvs := &HeightVoteSet{
chainID: chainID,
seq: seq,
}
hvs.Reset(height, valSet)
return hvs
......@@ -82,15 +85,25 @@ func (hvs *HeightVoteSet) Round() int {
return hvs.round
}
// SetValSet update ValidatorSet
func (hvs *HeightVoteSet) SetValSet(valSet *ValidatorSet) {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
hvs.valSet = valSet
}
// SetRound Create more RoundVoteSets up to round.
func (hvs *HeightVoteSet) SetRound(round int) {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
if hvs.round != 0 && (round < hvs.round+1) {
panic(Fmt("Panicked on a Sanity Check: %v", "SetRound() must increment hvs.round"))
if hvs.round != 0 && (round < hvs.round-1) {
panic(Fmt("SetRound() must increment hvs.round %v, round %v", hvs.round, round))
}
for r := hvs.round + 1; r <= round; r++ {
if _, ok := hvs.roundVoteSets[r]; ok {
for r := hvs.round - 1; r <= round; r++ {
if rvs, ok := hvs.roundVoteSets[r]; ok {
if r == round-1 {
hvs.updateValSet(rvs)
}
continue // Already exists because peerCatchupRounds.
}
hvs.addRound(r)
......@@ -102,12 +115,24 @@ func (hvs *HeightVoteSet) addRound(round int) {
if _, ok := hvs.roundVoteSets[round]; ok {
panic("addRound() for an existing round")
}
prevotes := NewVoteSet(hvs.chainID, hvs.height, round, VoteTypePrevote, hvs.valSet)
precommits := NewVoteSet(hvs.chainID, hvs.height, round, VoteTypePrecommit, hvs.valSet)
prevotes := NewVoteSet(hvs.chainID, hvs.height, round, VoteTypePrevote, hvs.valSet, hvs.seq)
precommits := NewVoteSet(hvs.chainID, hvs.height, round, VoteTypePrecommit, hvs.valSet, hvs.seq)
hvs.roundVoteSets[round] = RoundVoteSet{
Prevotes: prevotes,
Precommits: precommits,
}
ttlog.Debug("addRound", "round", round, "proposer", hvs.valSet.Proposer.String())
}
func (hvs *HeightVoteSet) updateValSet(rvs RoundVoteSet) {
hvsAddr := hvs.valSet.GetProposer().Address
rvsAddr := rvs.Prevotes.valSet.GetProposer().Address
if !bytes.Equal(hvsAddr, rvsAddr) {
ttlog.Info("update RoundVoteSet proposer", "round", rvs.Prevotes.Round(),
"old", Fmt("%X", Fingerprint(rvsAddr)), "new", Fmt("%X", Fingerprint(hvsAddr)))
rvs.Prevotes.valSet = hvs.valSet
rvs.Precommits.valSet = hvs.valSet
}
}
// AddVote Duplicate votes return added=false, err=nil.
......
......@@ -66,7 +66,7 @@ func (v *Validator) String() string {
if v == nil {
return "nil-Validator"
}
return Fmt("Validator{ADDR:%X PUB:%X VP:%v A:%v}",
return Fmt("{ADDR:%X PUB:%X VP:%v A:%v}",
v.Address,
v.PubKey,
v.VotingPower,
......
......@@ -56,6 +56,7 @@ type VoteSet struct {
height int64
round int
voteType byte
seq int64
mtx sync.Mutex
valSet *ValidatorSet
......@@ -69,7 +70,7 @@ type VoteSet struct {
}
// NewVoteSet Constructs a new VoteSet struct used to accumulate votes for given height/round.
func NewVoteSet(chainID string, height int64, round int, voteType byte, valSet *ValidatorSet) *VoteSet {
func NewVoteSet(chainID string, height int64, round int, voteType byte, valSet *ValidatorSet, seq int64) *VoteSet {
if height == 0 {
PanicSanity("Cannot make VoteSet for height == 0, doesn't make sense.")
}
......@@ -78,6 +79,7 @@ func NewVoteSet(chainID string, height int64, round int, voteType byte, valSet *
height: height,
round: round,
voteType: voteType,
seq: seq,
valSet: valSet,
votesBitArray: NewBitArray(valSet.Size()),
votes: make([]*Vote, valSet.Size()),
......@@ -323,9 +325,8 @@ func (voteSet *VoteSet) AddAggVote(vote *AggVote) (bool, error) {
// Ensure that signer is proposer
propAddr := valset.Proposer.Address
if !bytes.Equal(valAddr, propAddr) {
return false, errors.Wrapf(ErrVoteInvalidValidatorAddress,
"aggVote.ValidatorAddress (%X) does not match proposer address (%X)",
valAddr, propAddr)
ttlog.Info("odd aggregate vote", "reason",
Fmt("ValidatorAddress: %X; Proposer: %X", Fingerprint(valAddr), Fingerprint(propAddr)))
}
// If we already know of this vote, return false
if voteSet.aggVote != nil {
......@@ -536,7 +537,7 @@ func (voteSet *VoteSet) IsCommit() bool {
if voteSet == nil {
return false
}
if voteSet.voteType != VoteTypePrecommit {
if (voteSet.voteType != VoteTypePrevote || voteSet.seq == 0) && voteSet.voteType != VoteTypePrecommit {
return false
}
voteSet.mtx.Lock()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment