diff --git a/consensus/consensus.go b/consensus/consensus.go index 5bc3e70c0..05d96a0d5 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -37,6 +37,7 @@ type consensus struct { valKey *bls.ValidatorKey rewardAddr crypto.Address state state.Facade // TODO: rename `state` to `bcState` (blockchain state) + changeProposer *changeProposer newHeightState consState proposeState consState prepareState consState @@ -86,14 +87,15 @@ func newConsensus( cs.logger = logger.NewSubLogger("_consensus", cs) cs.rewardAddr = rewardAddr + cs.changeProposer = &changeProposer{cs} cs.newHeightState = &newHeightState{cs} cs.proposeState = &proposeState{cs} cs.prepareState = &prepareState{cs, false} cs.precommitState = &precommitState{cs, false} cs.commitState = &commitState{cs} - cs.cpPreVoteState = &cpPreVoteState{cs} - cs.cpMainVoteState = &cpMainVoteState{cs} - cs.cpDecideState = &cpDecideState{cs} + cs.cpPreVoteState = &cpPreVoteState{cs.changeProposer} + cs.cpMainVoteState = &cpMainVoteState{cs.changeProposer} + cs.cpDecideState = &cpDecideState{cs.changeProposer} cs.currentState = cs.newHeightState cs.mediator = mediator @@ -267,6 +269,7 @@ func (cs *consensus) handleTimeout(t *ticker) { return } + cs.logger.Debug("timer expired", "ticker", t) cs.currentState.onTimeout(t) } @@ -286,7 +289,7 @@ func (cs *consensus) AddVote(v *vote.Vote) { if v.Type() == vote.VoteTypeCPPreVote || v.Type() == vote.VoteTypeCPMainVote { - err := cs.checkJust(v) + err := cs.changeProposer.checkJust(v) if err != nil { cs.logger.Error("error on adding a cp vote", "vote", v, "error", err) return @@ -304,304 +307,6 @@ func (cs *consensus) AddVote(v *vote.Vote) { } } -func (cs *consensus) checkCPValue(vote *vote.Vote, allowedValues ...vote.CPValue) error { - for _, v := range allowedValues { - if vote.CPValue() == v { - return nil - } - } - - return invalidJustificationError{ - JustType: vote.CPJust().Type(), - Reason: fmt.Sprintf("invalid value: %v", vote.CPValue()), - } -} - -func (cs *consensus) checkJustInitZero(just vote.Just, blockHash hash.Hash) error { - j, ok := just.(*vote.JustInitZero) - if !ok { - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid just data", - } - } - - sb := certificate.BlockCertificateSignBytes(blockHash, - j.QCert.Height(), - j.QCert.Round()) - sb = append(sb, util.StringToBytes(vote.VoteTypePrepare.String())...) - - err := j.QCert.Validate(cs.height, cs.validators, sb) - if err != nil { - return invalidJustificationError{ - JustType: j.Type(), - Reason: err.Error(), - } - } - return nil -} - -func (cs *consensus) checkJustInitOne(just vote.Just) error { - _, ok := just.(*vote.JustInitOne) - if !ok { - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid just data", - } - } - - return nil -} - -func (cs *consensus) checkJustPreVoteHard(just vote.Just, - blockHash hash.Hash, cpRound int16, cpValue vote.CPValue, -) error { - j, ok := just.(*vote.JustPreVoteHard) - if !ok { - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid just data", - } - } - - sb := certificate.BlockCertificateSignBytes(blockHash, - j.QCert.Height(), - j.QCert.Round()) - sb = append(sb, util.StringToBytes(vote.VoteTypeCPPreVote.String())...) - sb = append(sb, util.Int16ToSlice(cpRound-1)...) - sb = append(sb, byte(cpValue)) - - err := j.QCert.Validate(cs.height, cs.validators, sb) - if err != nil { - return invalidJustificationError{ - JustType: just.Type(), - Reason: err.Error(), - } - } - return nil -} - -func (cs *consensus) checkJustPreVoteSoft(just vote.Just, - blockHash hash.Hash, cpRound int16, -) error { - j, ok := just.(*vote.JustPreVoteSoft) - if !ok { - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid just data", - } - } - - sb := certificate.BlockCertificateSignBytes(blockHash, - j.QCert.Height(), - j.QCert.Round()) - sb = append(sb, util.StringToBytes(vote.VoteTypeCPMainVote.String())...) - sb = append(sb, util.Int16ToSlice(cpRound-1)...) - sb = append(sb, byte(vote.CPValueAbstain)) - - err := j.QCert.Validate(cs.height, cs.validators, sb) - if err != nil { - return invalidJustificationError{ - JustType: just.Type(), - Reason: err.Error(), - } - } - return nil -} - -func (cs *consensus) checkJustMainVoteNoConflict(just vote.Just, - blockHash hash.Hash, cpRound int16, cpValue vote.CPValue, -) error { - j, ok := just.(*vote.JustMainVoteNoConflict) - if !ok { - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid just data", - } - } - - sb := certificate.BlockCertificateSignBytes(blockHash, - j.QCert.Height(), - j.QCert.Round()) - sb = append(sb, util.StringToBytes(vote.VoteTypeCPPreVote.String())...) - sb = append(sb, util.Int16ToSlice(cpRound)...) - sb = append(sb, byte(cpValue)) - - err := j.QCert.Validate(cs.height, cs.validators, sb) - if err != nil { - return invalidJustificationError{ - JustType: j.Type(), - Reason: err.Error(), - } - } - return nil -} - -func (cs *consensus) checkJustMainVoteConflict(just vote.Just, - blockHash hash.Hash, cpRound int16, -) error { - j, ok := just.(*vote.JustMainVoteConflict) - if !ok { - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid just data", - } - } - - if cpRound == 0 { - switch j.Just0.Type() { - case vote.JustTypeInitZero: - err := cs.checkJustInitZero(j.Just0, blockHash) - if err != nil { - return err - } - - default: - return invalidJustificationError{ - JustType: just.Type(), - Reason: fmt.Sprintf("unexpected justification: %s", j.Just0.Type()), - } - } - - switch j.Just1.Type() { - case vote.JustTypeInitOne: - err := cs.checkJustInitOne(j.Just1) - if err != nil { - return err - } - - default: - return invalidJustificationError{ - JustType: just.Type(), - Reason: fmt.Sprintf("unexpected justification: %s", j.Just1.Type()), - } - } - } else { - switch j.Just0.Type() { - case vote.JustTypePreVoteSoft: - err := cs.checkJustPreVoteSoft(j.Just0, blockHash, cpRound) - if err != nil { - return err - } - case vote.JustTypePreVoteHard: - err := cs.checkJustPreVoteHard(j.Just0, blockHash, cpRound, vote.CPValueZero) - if err != nil { - return err - } - default: - return invalidJustificationError{ - JustType: just.Type(), - Reason: fmt.Sprintf("unexpected justification: %s", j.Just0.Type()), - } - } - - switch j.Just1.Type() { - case vote.JustTypePreVoteHard: - err := cs.checkJustPreVoteHard(j.Just1, hash.UndefHash, cpRound, vote.CPValueOne) - if err != nil { - return err - } - - default: - return invalidJustificationError{ - JustType: just.Type(), - Reason: fmt.Sprintf("unexpected justification: %s", j.Just1.Type()), - } - } - } - - return nil -} - -func (cs *consensus) checkJustPreVote(v *vote.Vote) error { - just := v.CPJust() - if v.CPRound() == 0 { - switch just.Type() { - case vote.JustTypeInitZero: - err := cs.checkCPValue(v, vote.CPValueZero) - if err != nil { - return err - } - return cs.checkJustInitZero(just, v.BlockHash()) - - case vote.JustTypeInitOne: - err := cs.checkCPValue(v, vote.CPValueOne) - if err != nil { - return err - } - if v.BlockHash() != hash.UndefHash { - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid block hash", - } - } - return cs.checkJustInitOne(just) - default: - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid pre-vote justification", - } - } - } else { - switch just.Type() { - case vote.JustTypePreVoteSoft: - err := cs.checkCPValue(v, vote.CPValueZero, vote.CPValueOne) - if err != nil { - return err - } - return cs.checkJustPreVoteSoft(just, v.BlockHash(), v.CPRound()) - - case vote.JustTypePreVoteHard: - err := cs.checkCPValue(v, vote.CPValueZero, vote.CPValueOne) - if err != nil { - return err - } - return cs.checkJustPreVoteHard(just, v.BlockHash(), v.CPRound(), v.CPValue()) - - default: - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid pre-vote justification", - } - } - } -} - -func (cs *consensus) checkJustMainVote(v *vote.Vote) error { - just := v.CPJust() - switch just.Type() { - case vote.JustTypeMainVoteNoConflict: - err := cs.checkCPValue(v, vote.CPValueZero, vote.CPValueOne) - if err != nil { - return err - } - return cs.checkJustMainVoteNoConflict(just, v.BlockHash(), v.CPRound(), v.CPValue()) - - case vote.JustTypeMainVoteConflict: - err := cs.checkCPValue(v, vote.CPValueAbstain) - if err != nil { - return err - } - return cs.checkJustMainVoteConflict(just, v.BlockHash(), v.CPRound()) - - default: - return invalidJustificationError{ - JustType: just.Type(), - Reason: "invalid main-vote justification", - } - } -} - -func (cs *consensus) checkJust(v *vote.Vote) error { - if v.Type() == vote.VoteTypeCPPreVote { - return cs.checkJustPreVote(v) - } else if v.Type() == vote.VoteTypeCPMainVote { - return cs.checkJustMainVote(v) - } else { - panic("unreachable") - } -} - func (cs *consensus) proposer(round int16) *validator.Validator { return cs.state.Proposer(round) } diff --git a/consensus/cp.go b/consensus/cp.go new file mode 100644 index 000000000..f88dd19b7 --- /dev/null +++ b/consensus/cp.go @@ -0,0 +1,324 @@ +package consensus + +import ( + "fmt" + + "github.com/pactus-project/pactus/crypto/hash" + "github.com/pactus-project/pactus/types/certificate" + "github.com/pactus-project/pactus/types/proposal" + "github.com/pactus-project/pactus/types/vote" + "github.com/pactus-project/pactus/util" +) + +type changeProposer struct { + *consensus +} + +func (cp *changeProposer) onSetProposal(_ *proposal.Proposal) { + // Ignore proposal +} + +func (cp *changeProposer) onTimeout(t *ticker) { + if t.Target == tickerTargetQueryVotes { + cp.queryVotes() + cp.scheduleTimeout(t.Duration*2, cp.height, cp.round, tickerTargetQueryVotes) + } +} + +func (cp *changeProposer) checkCPValue(vote *vote.Vote, allowedValues ...vote.CPValue) error { + for _, v := range allowedValues { + if vote.CPValue() == v { + return nil + } + } + + return invalidJustificationError{ + JustType: vote.CPJust().Type(), + Reason: fmt.Sprintf("invalid value: %v", vote.CPValue()), + } +} + +func (cp *changeProposer) checkJustInitZero(just vote.Just, blockHash hash.Hash) error { + j, ok := just.(*vote.JustInitZero) + if !ok { + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid just data", + } + } + + sb := certificate.BlockCertificateSignBytes(blockHash, + j.QCert.Height(), + j.QCert.Round()) + sb = append(sb, util.StringToBytes(vote.VoteTypePrepare.String())...) + + err := j.QCert.Validate(cp.height, cp.validators, sb) + if err != nil { + return invalidJustificationError{ + JustType: j.Type(), + Reason: err.Error(), + } + } + return nil +} + +func (cp *changeProposer) checkJustInitOne(just vote.Just) error { + _, ok := just.(*vote.JustInitOne) + if !ok { + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid just data", + } + } + + return nil +} + +func (cp *changeProposer) checkJustPreVoteHard(just vote.Just, + blockHash hash.Hash, cpRound int16, cpValue vote.CPValue, +) error { + j, ok := just.(*vote.JustPreVoteHard) + if !ok { + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid just data", + } + } + + sb := certificate.BlockCertificateSignBytes(blockHash, + j.QCert.Height(), + j.QCert.Round()) + sb = append(sb, util.StringToBytes(vote.VoteTypeCPPreVote.String())...) + sb = append(sb, util.Int16ToSlice(cpRound-1)...) + sb = append(sb, byte(cpValue)) + + err := j.QCert.Validate(cp.height, cp.validators, sb) + if err != nil { + return invalidJustificationError{ + JustType: just.Type(), + Reason: err.Error(), + } + } + return nil +} + +func (cp *changeProposer) checkJustPreVoteSoft(just vote.Just, + blockHash hash.Hash, cpRound int16, +) error { + j, ok := just.(*vote.JustPreVoteSoft) + if !ok { + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid just data", + } + } + + sb := certificate.BlockCertificateSignBytes(blockHash, + j.QCert.Height(), + j.QCert.Round()) + sb = append(sb, util.StringToBytes(vote.VoteTypeCPMainVote.String())...) + sb = append(sb, util.Int16ToSlice(cpRound-1)...) + sb = append(sb, byte(vote.CPValueAbstain)) + + err := j.QCert.Validate(cp.height, cp.validators, sb) + if err != nil { + return invalidJustificationError{ + JustType: just.Type(), + Reason: err.Error(), + } + } + return nil +} + +func (cp *changeProposer) checkJustMainVoteNoConflict(just vote.Just, + blockHash hash.Hash, cpRound int16, cpValue vote.CPValue, +) error { + j, ok := just.(*vote.JustMainVoteNoConflict) + if !ok { + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid just data", + } + } + + sb := certificate.BlockCertificateSignBytes(blockHash, + j.QCert.Height(), + j.QCert.Round()) + sb = append(sb, util.StringToBytes(vote.VoteTypeCPPreVote.String())...) + sb = append(sb, util.Int16ToSlice(cpRound)...) + sb = append(sb, byte(cpValue)) + + err := j.QCert.Validate(cp.height, cp.validators, sb) + if err != nil { + return invalidJustificationError{ + JustType: j.Type(), + Reason: err.Error(), + } + } + return nil +} + +func (cp *changeProposer) checkJustMainVoteConflict(just vote.Just, + blockHash hash.Hash, cpRound int16, +) error { + j, ok := just.(*vote.JustMainVoteConflict) + if !ok { + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid just data", + } + } + + if cpRound == 0 { + switch j.Just0.Type() { + case vote.JustTypeInitZero: + err := cp.checkJustInitZero(j.Just0, blockHash) + if err != nil { + return err + } + + default: + return invalidJustificationError{ + JustType: just.Type(), + Reason: fmt.Sprintf("unexpected justification: %s", j.Just0.Type()), + } + } + + switch j.Just1.Type() { + case vote.JustTypeInitOne: + err := cp.checkJustInitOne(j.Just1) + if err != nil { + return err + } + + default: + return invalidJustificationError{ + JustType: just.Type(), + Reason: fmt.Sprintf("unexpected justification: %s", j.Just1.Type()), + } + } + } else { + switch j.Just0.Type() { + case vote.JustTypePreVoteSoft: + err := cp.checkJustPreVoteSoft(j.Just0, blockHash, cpRound) + if err != nil { + return err + } + case vote.JustTypePreVoteHard: + err := cp.checkJustPreVoteHard(j.Just0, blockHash, cpRound, vote.CPValueZero) + if err != nil { + return err + } + default: + return invalidJustificationError{ + JustType: just.Type(), + Reason: fmt.Sprintf("unexpected justification: %s", j.Just0.Type()), + } + } + + switch j.Just1.Type() { + case vote.JustTypePreVoteHard: + err := cp.checkJustPreVoteHard(j.Just1, hash.UndefHash, cpRound, vote.CPValueOne) + if err != nil { + return err + } + + default: + return invalidJustificationError{ + JustType: just.Type(), + Reason: fmt.Sprintf("unexpected justification: %s", j.Just1.Type()), + } + } + } + + return nil +} + +func (cp *changeProposer) checkJustPreVote(v *vote.Vote) error { + just := v.CPJust() + if v.CPRound() == 0 { + switch just.Type() { + case vote.JustTypeInitZero: + err := cp.checkCPValue(v, vote.CPValueZero) + if err != nil { + return err + } + return cp.checkJustInitZero(just, v.BlockHash()) + + case vote.JustTypeInitOne: + err := cp.checkCPValue(v, vote.CPValueOne) + if err != nil { + return err + } + if v.BlockHash() != hash.UndefHash { + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid block hash", + } + } + return cp.checkJustInitOne(just) + default: + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid pre-vote justification", + } + } + } else { + switch just.Type() { + case vote.JustTypePreVoteSoft: + err := cp.checkCPValue(v, vote.CPValueZero, vote.CPValueOne) + if err != nil { + return err + } + return cp.checkJustPreVoteSoft(just, v.BlockHash(), v.CPRound()) + + case vote.JustTypePreVoteHard: + err := cp.checkCPValue(v, vote.CPValueZero, vote.CPValueOne) + if err != nil { + return err + } + return cp.checkJustPreVoteHard(just, v.BlockHash(), v.CPRound(), v.CPValue()) + + default: + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid pre-vote justification", + } + } + } +} + +func (cp *changeProposer) checkJustMainVote(v *vote.Vote) error { + just := v.CPJust() + switch just.Type() { + case vote.JustTypeMainVoteNoConflict: + err := cp.checkCPValue(v, vote.CPValueZero, vote.CPValueOne) + if err != nil { + return err + } + return cp.checkJustMainVoteNoConflict(just, v.BlockHash(), v.CPRound(), v.CPValue()) + + case vote.JustTypeMainVoteConflict: + err := cp.checkCPValue(v, vote.CPValueAbstain) + if err != nil { + return err + } + return cp.checkJustMainVoteConflict(just, v.BlockHash(), v.CPRound()) + + default: + return invalidJustificationError{ + JustType: just.Type(), + Reason: "invalid main-vote justification", + } + } +} + +func (cp *changeProposer) checkJust(v *vote.Vote) error { + if v.Type() == vote.VoteTypeCPPreVote { + return cp.checkJustPreVote(v) + } else if v.Type() == vote.VoteTypeCPMainVote { + return cp.checkJustMainVote(v) + } else { + panic("unreachable") + } +} diff --git a/consensus/cp_decide.go b/consensus/cp_decide.go index 0e7d0a9f1..6e6dcf1b8 100644 --- a/consensus/cp_decide.go +++ b/consensus/cp_decide.go @@ -1,12 +1,11 @@ package consensus import ( - "github.com/pactus-project/pactus/types/proposal" "github.com/pactus-project/pactus/types/vote" ) type cpDecideState struct { - *consensus + *changeProposer } func (s *cpDecideState) enter() { @@ -53,14 +52,6 @@ func (s *cpDecideState) onAddVote(v *vote.Vote) { } } -func (s *cpDecideState) onSetProposal(_ *proposal.Proposal) { - // Ignore proposal -} - -func (s *cpDecideState) onTimeout(_ *ticker) { - // Ignore timeouts -} - func (s *cpDecideState) name() string { return "cp:decide" } diff --git a/consensus/cp_mainvote.go b/consensus/cp_mainvote.go index 6b060e67a..e6756d72d 100644 --- a/consensus/cp_mainvote.go +++ b/consensus/cp_mainvote.go @@ -2,12 +2,11 @@ package consensus import ( "github.com/pactus-project/pactus/crypto/hash" - "github.com/pactus-project/pactus/types/proposal" "github.com/pactus-project/pactus/types/vote" ) type cpMainVoteState struct { - *consensus + *changeProposer } func (s *cpMainVoteState) enter() { @@ -91,14 +90,6 @@ func (s *cpMainVoteState) onAddVote(v *vote.Vote) { } } -func (s *cpMainVoteState) onSetProposal(_ *proposal.Proposal) { - // Ignore proposal -} - -func (s *cpMainVoteState) onTimeout(_ *ticker) { - // Ignore timeouts -} - func (s *cpMainVoteState) name() string { return "cp:main-vote" } diff --git a/consensus/cp_prevote.go b/consensus/cp_prevote.go index 6ae74a649..48aecfbcd 100644 --- a/consensus/cp_prevote.go +++ b/consensus/cp_prevote.go @@ -1,13 +1,14 @@ package consensus import ( + "time" + "github.com/pactus-project/pactus/crypto/hash" - "github.com/pactus-project/pactus/types/proposal" "github.com/pactus-project/pactus/types/vote" ) type cpPreVoteState struct { - *consensus + *changeProposer } func (s *cpPreVoteState) enter() { @@ -30,6 +31,7 @@ func (s *cpPreVoteState) decide() { just := &vote.JustInitOne{} s.signAddCPPreVote(hash.UndefHash, s.cpRound, 1, just) } + s.scheduleTimeout(2*time.Second, s.height, s.round, tickerTargetQueryVotes) } else { cpMainVotes := s.log.CPMainVoteVoteSet(s.round) if cpMainVotes.HasAnyVoteFor(s.cpRound-1, vote.CPValueOne) { @@ -69,14 +71,6 @@ func (s *cpPreVoteState) onAddVote(_ *vote.Vote) { panic("Unreachable") } -func (s *cpPreVoteState) onSetProposal(_ *proposal.Proposal) { - panic("Unreachable") -} - -func (s *cpPreVoteState) onTimeout(_ *ticker) { - panic("Unreachable") -} - func (s *cpPreVoteState) name() string { return "cp:pre-vote" } diff --git a/consensus/cp_test.go b/consensus/cp_test.go index 63e17ae46..df7bc9805 100644 --- a/consensus/cp_test.go +++ b/consensus/cp_test.go @@ -155,7 +155,7 @@ func TestInvalidJustInitOne(t *testing.T) { t.Run("invalid value: zero", func(t *testing.T) { v := vote.NewCPPreVote(hash.UndefHash, h, r, 0, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid value: zero", @@ -165,7 +165,7 @@ func TestInvalidJustInitOne(t *testing.T) { t.Run("invalid block hash", func(t *testing.T) { v := vote.NewCPPreVote(hash.UndefHash, h, r, 1, vote.CPValueOne, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid pre-vote justification", @@ -175,7 +175,7 @@ func TestInvalidJustInitOne(t *testing.T) { t.Run("cp-round should be zero", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 0, vote.CPValueOne, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid block hash", @@ -186,7 +186,7 @@ func TestInvalidJustInitOne(t *testing.T) { invJust := &vote.JustMainVoteNoConflict{} v := vote.NewCPPreVote(td.RandHash(), h, r, 0, vote.CPValueOne, invJust, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: invJust.Type(), Reason: "invalid pre-vote justification", @@ -207,7 +207,7 @@ func TestInvalidJustInitZero(t *testing.T) { t.Run("invalid value: one", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 0, vote.CPValueOne, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid value: one", @@ -217,7 +217,7 @@ func TestInvalidJustInitZero(t *testing.T) { t.Run("cp-round should be zero", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 1, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid pre-vote justification", @@ -227,7 +227,7 @@ func TestInvalidJustInitZero(t *testing.T) { t.Run("invalid certificate", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 0, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: fmt.Sprintf("certificate has an unexpected committers: %v", just.QCert.Committers()), @@ -248,7 +248,7 @@ func TestInvalidJustPreVoteHard(t *testing.T) { t.Run("invalid value: abstain", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 1, vote.CPValueAbstain, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid value: abstain", @@ -258,7 +258,7 @@ func TestInvalidJustPreVoteHard(t *testing.T) { t.Run("cp-round should not be zero", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 0, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid pre-vote justification", @@ -268,7 +268,7 @@ func TestInvalidJustPreVoteHard(t *testing.T) { t.Run("invalid certificate", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 1, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: fmt.Sprintf("certificate has an unexpected committers: %v", just.QCert.Committers()), @@ -289,7 +289,7 @@ func TestInvalidJustPreVoteSoft(t *testing.T) { t.Run("invalid value: abstain", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 1, vote.CPValueAbstain, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid value: abstain", @@ -299,7 +299,7 @@ func TestInvalidJustPreVoteSoft(t *testing.T) { t.Run("cp-round should not be zero", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 0, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid pre-vote justification", @@ -309,7 +309,7 @@ func TestInvalidJustPreVoteSoft(t *testing.T) { t.Run("invalid certificate", func(t *testing.T) { v := vote.NewCPPreVote(td.RandHash(), h, r, 1, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: fmt.Sprintf("certificate has an unexpected committers: %v", just.QCert.Committers()), @@ -330,7 +330,7 @@ func TestInvalidJustMainVoteNoConflict(t *testing.T) { t.Run("invalid value: abstain", func(t *testing.T) { v := vote.NewCPMainVote(td.RandHash(), h, r, 1, vote.CPValueAbstain, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid value: abstain", @@ -340,7 +340,7 @@ func TestInvalidJustMainVoteNoConflict(t *testing.T) { t.Run("invalid certificate", func(t *testing.T) { v := vote.NewCPMainVote(td.RandHash(), h, r, 1, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: fmt.Sprintf("certificate has an unexpected committers: %v", just.QCert.Committers()), @@ -364,7 +364,7 @@ func TestInvalidJustMainVoteConflict(t *testing.T) { } v := vote.NewCPMainVote(td.RandHash(), h, r, 0, vote.CPValueZero, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid value: zero", @@ -380,7 +380,7 @@ func TestInvalidJustMainVoteConflict(t *testing.T) { } v := vote.NewCPMainVote(td.RandHash(), h, r, 0, vote.CPValueOne, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "invalid value: one", @@ -396,7 +396,7 @@ func TestInvalidJustMainVoteConflict(t *testing.T) { } v := vote.NewCPMainVote(td.RandHash(), h, r, 0, vote.CPValueAbstain, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "unexpected justification: JustPreVoteSoft", @@ -414,7 +414,7 @@ func TestInvalidJustMainVoteConflict(t *testing.T) { } v := vote.NewCPMainVote(td.RandHash(), h, r, 1, vote.CPValueAbstain, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just.Type(), Reason: "unexpected justification: JustInitZero", @@ -431,7 +431,7 @@ func TestInvalidJustMainVoteConflict(t *testing.T) { } v := vote.NewCPMainVote(td.RandHash(), h, r, 0, vote.CPValueAbstain, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just0.Type(), Reason: fmt.Sprintf("certificate has an unexpected committers: %v", just0.QCert.Committers()), @@ -450,7 +450,7 @@ func TestInvalidJustMainVoteConflict(t *testing.T) { } v := vote.NewCPMainVote(td.RandHash(), h, r, 1, vote.CPValueAbstain, just, td.consB.valKey.Address()) - err := td.consX.checkJust(v) + err := td.consX.changeProposer.checkJust(v) assert.ErrorIs(t, err, invalidJustificationError{ JustType: just0.Type(), Reason: fmt.Sprintf("certificate has an unexpected committers: %v", just0.QCert.Committers()), diff --git a/consensus/precommit.go b/consensus/precommit.go index d97ac8310..9e1c41a3c 100644 --- a/consensus/precommit.go +++ b/consensus/precommit.go @@ -87,8 +87,6 @@ func (s *precommitState) onSetProposal(_ *proposal.Proposal) { } func (s *precommitState) onTimeout(t *ticker) { - s.logger.Debug("timer expired") - if t.Target == tickerTargetChangeProposer { s.startChangingProposer() } diff --git a/consensus/prepare.go b/consensus/prepare.go index 7ef93aec6..ab57fca02 100644 --- a/consensus/prepare.go +++ b/consensus/prepare.go @@ -59,8 +59,6 @@ func (s *prepareState) vote() { } func (s *prepareState) onTimeout(t *ticker) { - s.logger.Debug("timer expired", "ticker", t) - if t.Target == tickerTargetQueryProposal { roundProposal := s.log.RoundProposal(s.round) if roundProposal == nil { diff --git a/consensus/ticker.go b/consensus/ticker.go index 2cff792b1..4892a4ed2 100644 --- a/consensus/ticker.go +++ b/consensus/ticker.go @@ -11,6 +11,7 @@ const ( tickerTargetNewHeight = tickerTarget(1) tickerTargetChangeProposer = tickerTarget(2) tickerTargetQueryProposal = tickerTarget(3) + tickerTargetQueryVotes = tickerTarget(4) ) func (rs tickerTarget) String() string { @@ -21,6 +22,8 @@ func (rs tickerTarget) String() string { return "change-proposer" case tickerTargetQueryProposal: return "query-proposal" + case tickerTargetQueryVotes: + return "query-votes" default: return "Unknown" } diff --git a/tests/main_test.go b/tests/main_test.go index 433081cc8..f4c06fa30 100644 --- a/tests/main_test.go +++ b/tests/main_test.go @@ -73,11 +73,11 @@ func TestMain(m *testing.M) { tConfigs[i].Store.Path = util.TempDirPath() tConfigs[i].Consensus.ChangeProposerTimeout = 4 * time.Second tConfigs[i].Logger.Levels["default"] = "warn" - tConfigs[i].Logger.Levels["_state"] = "info" - tConfigs[i].Logger.Levels["_sync"] = "error" - tConfigs[i].Logger.Levels["_consensus"] = "error" - tConfigs[i].Logger.Levels["_network"] = "error" - tConfigs[i].Logger.Levels["_pool"] = "error" + tConfigs[i].Logger.Levels["_state"] = "warn" + tConfigs[i].Logger.Levels["_sync"] = "warn" + tConfigs[i].Logger.Levels["_consensus"] = "warn" + tConfigs[i].Logger.Levels["_network"] = "warn" + tConfigs[i].Logger.Levels["_pool"] = "warn" tConfigs[i].Sync.CacheSize = 1000 tConfigs[i].Sync.NodeNetwork = false tConfigs[i].Sync.Firewall.Enabled = false