aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2019-03-27 15:02:27 +0800
committerJimmy Hu <jimmy.hu@dexon.org>2019-03-27 15:25:10 +0800
commitf848ee5128563138b1757034ea7d387c77679728 (patch)
treece9083e8ae66ea7234d36241a3b1cf8b65fca2a8 /core
parent495b3737414685d609f7b41355928c699189d6ad (diff)
downloadtangerine-consensus-f848ee5128563138b1757034ea7d387c77679728.tar
tangerine-consensus-f848ee5128563138b1757034ea7d387c77679728.tar.gz
tangerine-consensus-f848ee5128563138b1757034ea7d387c77679728.tar.bz2
tangerine-consensus-f848ee5128563138b1757034ea7d387c77679728.tar.lz
tangerine-consensus-f848ee5128563138b1757034ea7d387c77679728.tar.xz
tangerine-consensus-f848ee5128563138b1757034ea7d387c77679728.tar.zst
tangerine-consensus-f848ee5128563138b1757034ea7d387c77679728.zip
core: Update BA to the latest version (#519)
* core: fastPreCom should not propose fastCom in RBA * add test for fix * core: update BA * core: fix test
Diffstat (limited to 'core')
-rw-r--r--core/agreement-state.go22
-rw-r--r--core/agreement-state_test.go53
-rw-r--r--core/agreement.go26
-rw-r--r--core/agreement_test.go30
-rw-r--r--core/leader-selector.go2
5 files changed, 59 insertions, 74 deletions
diff --git a/core/agreement-state.go b/core/agreement-state.go
index 73d7b7a..0d1ae58 100644
--- a/core/agreement-state.go
+++ b/core/agreement-state.go
@@ -132,11 +132,14 @@ func (s *preCommitState) clocks() int { return 2 }
func (s *preCommitState) nextState() (agreementState, error) {
s.a.lock.RLock()
defer s.a.lock.RUnlock()
- hash := s.a.lockValue
- if hash == types.NullBlockHash {
- hash = s.a.leader.leaderBlockHash()
+ if s.a.lockValue == types.SkipBlockHash ||
+ s.a.lockValue == types.NullBlockHash {
+ hash := s.a.leader.leaderBlockHash()
+ s.a.recv.ProposeVote(types.NewVote(types.VotePreCom, hash, s.a.period))
+ } else {
+ s.a.recv.ProposeVote(types.NewVote(
+ types.VotePreCom, s.a.lockValue, s.a.period))
}
- s.a.recv.ProposeVote(types.NewVote(types.VotePreCom, hash, s.a.period))
return newCommitState(s.a), nil
}
@@ -154,16 +157,7 @@ func (s *commitState) clocks() int { return 2 }
func (s *commitState) nextState() (agreementState, error) {
s.a.lock.Lock()
defer s.a.lock.Unlock()
- hash, ok := s.a.countVoteNoLock(s.a.period, types.VotePreCom)
- if ok && hash != types.SkipBlockHash {
- if s.a.period > s.a.lockIter {
- s.a.lockValue = hash
- s.a.lockIter = s.a.period
- }
- } else {
- hash = types.SkipBlockHash
- }
- s.a.recv.ProposeVote(types.NewVote(types.VoteCom, hash, s.a.period))
+ s.a.recv.ProposeVote(types.NewVote(types.VoteCom, s.a.lockValue, s.a.period))
return newForwardState(s.a), nil
}
diff --git a/core/agreement-state_test.go b/core/agreement-state_test.go
index c4197b5..b3dcd67 100644
--- a/core/agreement-state_test.go
+++ b/core/agreement-state_test.go
@@ -221,11 +221,22 @@ func (s *AgreementStateTestSuite) TestPreCommitState() {
s.Require().Len(s.voteChan, 1)
vote := <-s.voteChan
s.Equal(types.VotePreCom, vote.Type)
- s.NotEqual(common.Hash{}, vote.BlockHash)
+ s.NotEqual(types.SkipBlockHash, vote.BlockHash)
s.Equal(stateCommit, newState.state())
- // Else, preCom-vote on lockValue.
+ // If lockvalue == SKIP, propose preCom-vote for the leader block.
+ a.data.lockValue = types.SkipBlockHash
a.data.period = 2
+ newState, err = state.nextState()
+ s.Require().NoError(err)
+ s.Require().Len(s.voteChan, 1)
+ vote = <-s.voteChan
+ s.Equal(types.VotePreCom, vote.Type)
+ s.NotEqual(types.SkipBlockHash, vote.BlockHash)
+ s.Equal(stateCommit, newState.state())
+
+ // Else, preCom-vote on lockValue.
+ a.data.period = 3
hash := common.NewRandomHash()
a.data.lockValue = hash
newState, err = state.nextState()
@@ -243,47 +254,15 @@ func (s *AgreementStateTestSuite) TestCommitState() {
s.Equal(stateCommit, state.state())
s.Equal(2, state.clocks())
- // If there are 2f+1 preCom-votes for block v or null,
- // propose a com-vote for block v.
+ // Commit on lock value.
a.data.period = 1
- block := s.proposeBlock(a.data.leader)
- s.Require().NoError(a.processBlock(block))
- for nID := range a.notarySet {
- vote := s.prepareVote(nID, types.VotePreCom, block.Hash, 1)
- s.Require().NoError(a.processVote(vote))
- }
+ a.data.lockValue = common.NewRandomHash()
newState, err := state.nextState()
s.Require().NoError(err)
s.Require().Len(s.voteChan, 1)
- s.Equal(block.Hash, a.data.lockValue)
- s.Equal(uint64(1), a.data.lockIter)
vote := <-s.voteChan
s.Equal(types.VoteCom, vote.Type)
- s.Equal(block.Hash, vote.BlockHash)
- s.Equal(stateForward, newState.state())
-
- // Else, com-vote on SKIP.
- a.data.period = 2
- newState, err = state.nextState()
- s.Require().NoError(err)
- s.Require().Len(s.voteChan, 1)
- vote = <-s.voteChan
- s.Equal(types.VoteCom, vote.Type)
- s.Equal(types.SkipBlockHash, vote.BlockHash)
- s.Equal(stateForward, newState.state())
-
- // If there are 2f+1 preCom-votes for SKIP, it's same as the 'else' condition.
- a.data.period = 3
- for nID := range a.notarySet {
- vote := s.prepareVote(nID, types.VotePreCom, types.SkipBlockHash, 3)
- s.Require().NoError(a.processVote(vote))
- }
- newState, err = state.nextState()
- s.Require().NoError(err)
- s.Require().Len(s.voteChan, 1)
- vote = <-s.voteChan
- s.Equal(types.VoteCom, vote.Type)
- s.Equal(types.SkipBlockHash, vote.BlockHash)
+ s.Equal(a.data.lockValue, vote.BlockHash)
s.Equal(stateForward, newState.state())
}
diff --git a/core/agreement.go b/core/agreement.go
index d53440b..d4f1bbd 100644
--- a/core/agreement.go
+++ b/core/agreement.go
@@ -181,7 +181,7 @@ func (a *agreement) restart(
a.data.blocks = make(map[types.NodeID]*types.Block)
a.data.requiredVote = len(notarySet)*2/3 + 1
a.data.leader.restart(crs)
- a.data.lockValue = types.NullBlockHash
+ a.data.lockValue = types.SkipBlockHash
a.data.lockIter = 0
a.data.isLeader = a.data.ID == leader
if a.doneChan != nil {
@@ -461,11 +461,17 @@ func (a *agreement) processVote(vote *types.Vote) error {
hash != types.SkipBlockHash {
if vote.Type == types.VoteFast {
if !a.hasVoteFast {
- a.data.recv.ProposeVote(
- types.NewVote(types.VoteFastCom, hash, vote.Period))
- a.data.lockValue = hash
- a.data.lockIter = 1
- a.hasVoteFast = true
+ if a.state.state() == stateFast ||
+ a.state.state() == stateFastVote {
+ a.data.recv.ProposeVote(
+ types.NewVote(types.VoteFastCom, hash, vote.Period))
+ a.hasVoteFast = true
+
+ }
+ if a.data.lockIter == 0 {
+ a.data.lockValue = hash
+ a.data.lockIter = 1
+ }
}
} else {
a.hasOutput = true
@@ -494,18 +500,12 @@ func (a *agreement) processVote(vote *types.Vote) error {
if hash, ok := a.data.countVoteNoLock(vote.Period, vote.Type); ok &&
hash != types.SkipBlockHash {
// Condition 1.
- if a.data.period >= vote.Period && vote.Period > a.data.lockIter &&
- vote.BlockHash != a.data.lockValue {
+ if vote.Period > a.data.lockIter {
a.data.lockValue = hash
a.data.lockIter = vote.Period
- return nil
}
// Condition 2.
if vote.Period > a.data.period {
- if vote.Period > a.data.lockIter {
- a.data.lockValue = hash
- a.data.lockIter = vote.Period
- }
a.fastForward <- vote.Period
if a.doneChan != nil {
close(a.doneChan)
diff --git a/core/agreement_test.go b/core/agreement_test.go
index 175249f..cb4b2a9 100644
--- a/core/agreement_test.go
+++ b/core/agreement_test.go
@@ -176,31 +176,43 @@ func (s *AgreementTestSuite) prepareVote(
}
func (s *AgreementTestSuite) TestSimpleConfirm() {
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
+ a, leaderNode := s.newAgreement(4, 0, func(*types.Block) (bool, error) {
return true, nil
})
+ s.Require().Equal(s.ID, leaderNode)
// FastState
a.nextState()
// FastVoteState
- a.nextState()
- // InitialState
- a.nextState()
- // PreCommitState
s.Require().Len(s.blockChan, 1)
blockHash := <-s.blockChan
block, exist := s.block[blockHash]
s.Require().True(exist)
+ s.Require().Equal(s.ID, block.ProposerID)
s.Require().NoError(a.processBlock(block))
+ // Wait some time for go routine in processBlock to finish.
+ time.Sleep(500 * time.Millisecond)
s.Require().Len(s.voteChan, 1)
- vote := <-s.voteChan
- s.Equal(types.VoteInit, vote.Type)
- s.Equal(blockHash, vote.BlockHash)
+ fastVote := <-s.voteChan
+ s.Equal(types.VoteFast, fastVote.Type)
+ s.Equal(blockHash, fastVote.BlockHash)
+ s.Require().Len(s.voteChan, 0)
+ a.nextState()
+ // InitialState
+ a.nextState()
+ // PreCommitState
a.nextState()
// CommitState
s.Require().Len(s.voteChan, 1)
- vote = <-s.voteChan
+ vote := <-s.voteChan
s.Equal(types.VotePreCom, vote.Type)
s.Equal(blockHash, vote.BlockHash)
+ // Fast-votes should be ignored.
+ for nID := range s.signers {
+ v := s.copyVote(fastVote, nID)
+ s.Require().NoError(a.processVote(v))
+ }
+ s.Require().Len(s.voteChan, 0)
+ s.Equal(uint64(1), a.data.lockIter)
for nID := range s.signers {
v := s.copyVote(vote, nID)
s.Require().NoError(a.processVote(v))
diff --git a/core/leader-selector.go b/core/leader-selector.go
index 214b4cb..8c06328 100644
--- a/core/leader-selector.go
+++ b/core/leader-selector.go
@@ -93,7 +93,7 @@ func (l *leaderSelector) restart(crs common.Hash) {
l.numCRS = numCRS
l.hashCRS = crs
l.minCRSBlock = maxHash
- l.minBlockHash = common.Hash{}
+ l.minBlockHash = types.NullBlockHash
l.pendingBlocks = make(map[common.Hash]*types.Block)
}