aboutsummaryrefslogtreecommitdiffstats
path: root/core/agreement.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/agreement.go')
-rw-r--r--core/agreement.go37
1 files changed, 29 insertions, 8 deletions
diff --git a/core/agreement.go b/core/agreement.go
index e741145..86cb6fc 100644
--- a/core/agreement.go
+++ b/core/agreement.go
@@ -32,7 +32,6 @@ import (
var (
ErrNotValidator = fmt.Errorf("not a validaotr")
ErrIncorrectVoteSignature = fmt.Errorf("incorrect vote signature")
- ErrForkVote = fmt.Errorf("fork vote")
)
// ErrFork for fork error in agreement.
@@ -46,6 +45,17 @@ func (e *ErrFork) Error() string {
e.vID.String(), e.old, e.new)
}
+// ErrForkVote for fork vote error in agreement.
+type ErrForkVote struct {
+ vID types.ValidatorID
+ old, new *types.Vote
+}
+
+func (e *ErrForkVote) Error() string {
+ return fmt.Sprintf("fork vote is found for %s, old %s, new %s",
+ e.vID.String(), e.old, e.new)
+}
+
type blockProposerFn func() *types.Block
func newVoteListMap() []map[types.ValidatorID]*types.Vote {
@@ -148,6 +158,7 @@ func (a *agreement) restart(validators types.ValidatorIDs, aID types.Position) {
a.data.blocks = make(map[types.ValidatorID]*types.Block)
a.data.requiredVote = len(validators)/3*2 + 1
a.data.leader.restart()
+ a.data.defaultBlock = common.Hash{}
a.hasOutput = false
a.state = newPrepareState(a.data)
a.validators = make(map[types.ValidatorID]struct{})
@@ -210,6 +221,9 @@ func (a *agreement) agreementID() types.Position {
// nextState is called at the spcifi clock time.
func (a *agreement) nextState() (err error) {
+ if err = a.state.receiveVote(); err != nil {
+ return
+ }
a.state, err = a.state.nextState()
return
}
@@ -230,14 +244,17 @@ func (a *agreement) sanityCheck(vote *types.Vote) error {
if !ok {
return ErrIncorrectVoteSignature
}
+ return nil
+}
+func (a *agreement) checkForkVote(vote *types.Vote) error {
if err := func() error {
a.data.votesLock.RLock()
defer a.data.votesLock.RUnlock()
if votes, exist := a.data.votes[vote.Period]; exist {
if oldVote, exist := votes[vote.Type][vote.ProposerID]; exist {
if vote.BlockHash != oldVote.BlockHash {
- return ErrForkVote
+ return &ErrForkVote{vote.ProposerID, oldVote, vote}
}
}
}
@@ -272,6 +289,10 @@ func (a *agreement) processVote(vote *types.Vote) error {
})
return nil
}
+ if err := a.checkForkVote(vote); err != nil {
+ return err
+ }
+
if func() bool {
a.data.votesLock.Lock()
defer a.data.votesLock.Unlock()
@@ -303,12 +324,6 @@ func (a *agreement) prepareBlock(
func (a *agreement) processBlock(block *types.Block) error {
a.data.blocksLock.Lock()
defer a.data.blocksLock.Unlock()
- if b, exist := a.data.blocks[block.ProposerID]; exist {
- if b.Hash != block.Hash {
- return &ErrFork{block.ProposerID, b.Hash, block.Hash}
- }
- return nil
- }
if block.Position != a.agreementID() {
a.pendingBlock = append(a.pendingBlock, pendingBlock{
block: block,
@@ -316,6 +331,12 @@ func (a *agreement) processBlock(block *types.Block) error {
})
return nil
}
+ if b, exist := a.data.blocks[block.ProposerID]; exist {
+ if b.Hash != block.Hash {
+ return &ErrFork{block.ProposerID, b.Hash, block.Hash}
+ }
+ return nil
+ }
if err := a.data.leader.processBlock(block); err != nil {
return err
}