mirror of https://github.com/poanetwork/quorum.git
Added preprepareSent variable to roundstate so that preprepare message is sent only once and updated justifyRoundChange to not return false, if prepared value or round does not match the values in prepared messages part of round change messages
This commit is contained in:
parent
614e3d5b94
commit
1d8a952fa5
|
@ -47,7 +47,7 @@ func newBlockChain(n int) (*core.BlockChain, *backend) {
|
|||
// Use the first key as private key
|
||||
b, _ := New(config, nodeKeys[0], memDB).(*backend)
|
||||
// set the qibft consensus enabled to true
|
||||
b.qibftConsensusEnabled = true
|
||||
b.qibftConsensusEnabled = false
|
||||
genesis.MustCommit(memDB)
|
||||
blockchain, err := core.NewBlockChain(memDB, nil, genesis.Config, b, vm.Config{}, nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -29,10 +29,7 @@ func (c *core) sendPreprepare(request *Request) {
|
|||
if rcMessages == nil {
|
||||
rcMessages = newMessageSet(c.valSet)
|
||||
}
|
||||
preparedMessages := request.PrepareMessages
|
||||
if preparedMessages == nil {
|
||||
preparedMessages = newMessageSet(c.valSet)
|
||||
}
|
||||
|
||||
// If I'm the proposer and I have the same sequence with the proposal
|
||||
if c.current.Sequence().Cmp(request.Proposal.Number()) == 0 && c.IsProposer() {
|
||||
curView := c.currentView()
|
||||
|
@ -40,7 +37,7 @@ func (c *core) sendPreprepare(request *Request) {
|
|||
View: curView,
|
||||
Proposal: request.Proposal,
|
||||
RCMessages: rcMessages,
|
||||
PreparedMessages: preparedMessages,
|
||||
PreparedMessages: request.PrepareMessages,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("Failed to encode", "view", curView)
|
||||
|
@ -50,6 +47,8 @@ func (c *core) sendPreprepare(request *Request) {
|
|||
Code: msgPreprepare,
|
||||
Msg: preprepare,
|
||||
})
|
||||
// Set the preprepareSent to the current round
|
||||
c.current.preprepareSent = curView.Round
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -126,16 +126,23 @@ func (c *core) handleRoundChange(msg *message, src istanbul.Validator) error {
|
|||
c.newRoundChangeTimer()
|
||||
c.sendRoundChange(newRound)
|
||||
|
||||
} else if currentRoundMessages == c.QuorumSize() && c.IsProposer() && c.justifyRoundChange(cv.Round) {
|
||||
} else if currentRoundMessages >= c.QuorumSize() && c.IsProposer() && c.justifyRoundChange(cv.Round) && c.current.preprepareSent.Cmp(cv.Round) < 0 {
|
||||
preparedRound, proposal := c.highestPrepared(cv.Round)
|
||||
if proposal == nil {
|
||||
proposal = c.current.pendingRequest.Proposal
|
||||
}
|
||||
|
||||
var preparedMessages *messageSet
|
||||
if preparedRound == nil {
|
||||
preparedMessages = newMessageSet(c.valSet)
|
||||
} else {
|
||||
preparedMessages = c.roundChangeSet.preparedMessages[preparedRound.Uint64()]
|
||||
}
|
||||
|
||||
r := &Request{
|
||||
Proposal: proposal,
|
||||
RCMessages: c.roundChangeSet.roundChanges[cv.Round.Uint64()],
|
||||
PrepareMessages: c.roundChangeSet.preparedMessages[preparedRound.Uint64()],
|
||||
PrepareMessages: preparedMessages,
|
||||
}
|
||||
|
||||
c.sendPreprepare(r)
|
||||
|
@ -153,19 +160,19 @@ func (c *core) justifyRoundChange(round *big.Int) bool {
|
|||
// Check if the block in each prepared message is the one that is being proposed
|
||||
// To handle the case where a byzantine node can send an empty prepared block, check atleast Quorum of prepared blocks match the condition and not all
|
||||
i := 0
|
||||
for addr, msg := range c.roundChangeSet.preparedMessages[pr.Uint64()].messages {
|
||||
for addr, msg := range c.roundChangeSet.preparedMessages[round.Uint64()].messages {
|
||||
var prepare *Subject
|
||||
if err := msg.Decode(&prepare); err != nil {
|
||||
c.logger.Error("Failed to decode Prepared Message", "err", err)
|
||||
return false
|
||||
continue
|
||||
}
|
||||
if prepare.Digest.Hash() != pv.Hash() {
|
||||
c.logger.Error("Highest Prepared Block does not match the Proposal", "Address", addr)
|
||||
return false
|
||||
continue
|
||||
}
|
||||
if prepare.View.Round.Uint64() != pr.Uint64() {
|
||||
c.logger.Error("Round in Prepared Block does not match the Highest Prepared Round", "Address", addr)
|
||||
return false
|
||||
continue
|
||||
}
|
||||
i++
|
||||
if i == c.QuorumSize() {
|
||||
|
@ -214,8 +221,6 @@ func (rcs *roundChangeSet) Add(r *big.Int, msg *message, preparedRound *big.Int,
|
|||
return err
|
||||
}
|
||||
|
||||
rcs.preparedMessages[round] = preparedMessages
|
||||
|
||||
if rcs.preparedRounds == nil {
|
||||
rcs.preparedRounds = make(map[uint64]*big.Int)
|
||||
}
|
||||
|
@ -223,12 +228,10 @@ func (rcs *roundChangeSet) Add(r *big.Int, msg *message, preparedRound *big.Int,
|
|||
rcs.preparedBlocks = make(map[uint64]istanbul.Proposal)
|
||||
}
|
||||
|
||||
if rcs.preparedRounds[round] == nil {
|
||||
rcs.preparedRounds[round] = preparedRound
|
||||
rcs.preparedBlocks[round] = preparedBlock
|
||||
} else if preparedRound.Cmp(rcs.preparedRounds[round]) > 0 {
|
||||
if rcs.preparedRounds[round] == nil || preparedRound.Cmp(rcs.preparedRounds[round]) > 0 {
|
||||
rcs.preparedRounds[round] = preparedRound
|
||||
rcs.preparedBlocks[round] = preparedBlock
|
||||
rcs.preparedMessages[round] = preparedMessages
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -47,7 +47,7 @@ func TestRoundChangeSet(t *testing.T) {
|
|||
Msg: m,
|
||||
Address: v.Address(),
|
||||
}
|
||||
rc.Add(view.Round, msg, r.PreparedRound, r.PreparedBlock)
|
||||
rc.Add(view.Round, msg, r.PreparedRound, r.PreparedBlock, newMessageSet(vset))
|
||||
if rc.roundChanges[view.Round.Uint64()].Size() != i+1 {
|
||||
t.Errorf("the size of round change messages mismatch: have %v, want %v", rc.roundChanges[view.Round.Uint64()].Size(), i+1)
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func TestRoundChangeSet(t *testing.T) {
|
|||
Msg: m,
|
||||
Address: v.Address(),
|
||||
}
|
||||
rc.Add(view.Round, msg, r.PreparedRound, r.PreparedBlock)
|
||||
rc.Add(view.Round, msg, r.PreparedRound, r.PreparedBlock, newMessageSet(vset))
|
||||
if rc.roundChanges[view.Round.Uint64()].Size() != vset.Size() {
|
||||
t.Errorf("the size of round change messages mismatch: have %v, want %v", rc.roundChanges[view.Round.Uint64()].Size(), vset.Size())
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ func newRoundState(view *View, validatorSet istanbul.ValidatorSet, preprepare *P
|
|||
pendingRequest: pendingRequest,
|
||||
hasBadProposal: hasBadProposal,
|
||||
rcMsgSentInRound: big.NewInt(0),
|
||||
preprepareSent: big.NewInt(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +56,9 @@ type roundState struct {
|
|||
|
||||
mu *sync.RWMutex
|
||||
hasBadProposal func(hash common.Hash) bool
|
||||
|
||||
// Keep track of preprepare sent messages
|
||||
preprepareSent *big.Int
|
||||
}
|
||||
|
||||
func (s *roundState) GetPrepareOrCommitSize() int {
|
||||
|
|
Loading…
Reference in New Issue