roundchange.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // Copyright 2017 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package core
  17. import (
  18. "math/big"
  19. "sync"
  20. "github.com/ethereum/go-ethereum/common"
  21. "github.com/ethereum/go-ethereum/consensus/istanbul"
  22. istanbulcommon "github.com/ethereum/go-ethereum/consensus/istanbul/common"
  23. ibfttypes "github.com/ethereum/go-ethereum/consensus/istanbul/ibft/types"
  24. )
  25. // sendNextRoundChange sends the ROUND CHANGE message with current round + 1
  26. func (c *core) sendNextRoundChange() {
  27. cv := c.currentView()
  28. c.sendRoundChange(new(big.Int).Add(cv.Round, common.Big1))
  29. }
  30. // sendRoundChange sends the ROUND CHANGE message with the given round
  31. func (c *core) sendRoundChange(round *big.Int) {
  32. logger := c.logger.New("state", c.state)
  33. cv := c.currentView()
  34. if cv.Round.Cmp(round) >= 0 {
  35. logger.Error("Cannot send out the round change", "current round", cv.Round, "target round", round)
  36. return
  37. }
  38. c.catchUpRound(&istanbul.View{
  39. // The round number we'd like to transfer to.
  40. Round: new(big.Int).Set(round),
  41. Sequence: new(big.Int).Set(cv.Sequence),
  42. })
  43. // Now we have the new round number and sequence number
  44. cv = c.currentView()
  45. rc := &istanbul.Subject{
  46. View: cv,
  47. Digest: common.Hash{},
  48. }
  49. payload, err := ibfttypes.Encode(rc)
  50. if err != nil {
  51. logger.Error("Failed to encode ROUND CHANGE", "rc", rc, "err", err)
  52. return
  53. }
  54. c.broadcast(&ibfttypes.Message{
  55. Code: ibfttypes.MsgRoundChange,
  56. Msg: payload,
  57. })
  58. }
  59. func (c *core) handleRoundChange(msg *ibfttypes.Message, src istanbul.Validator) error {
  60. logger := c.logger.New("state", c.state, "from", src.Address().Hex())
  61. // Decode ROUND CHANGE message
  62. var rc *istanbul.Subject
  63. if err := msg.Decode(&rc); err != nil {
  64. logger.Error("Failed to decode ROUND CHANGE", "err", err)
  65. return istanbulcommon.ErrInvalidMessage
  66. }
  67. if err := c.checkMessage(ibfttypes.MsgRoundChange, rc.View); err != nil {
  68. return err
  69. }
  70. cv := c.currentView()
  71. roundView := rc.View
  72. // Add the ROUND CHANGE message to its message set and return how many
  73. // messages we've got with the same round number and sequence number.
  74. num, err := c.roundChangeSet.Add(roundView.Round, msg)
  75. if err != nil {
  76. logger.Warn("Failed to add round change message", "from", src, "msg", msg, "err", err)
  77. return err
  78. }
  79. // Once we received f+1 ROUND CHANGE messages, those messages form a weak certificate.
  80. // If our round number is smaller than the certificate's round number, we would
  81. // try to catch up the round number.
  82. if c.waitingForRoundChange && num == c.valSet.F()+1 {
  83. if cv.Round.Cmp(roundView.Round) < 0 {
  84. c.sendRoundChange(roundView.Round)
  85. }
  86. return nil
  87. } else if num == c.QuorumSize() && (c.waitingForRoundChange || cv.Round.Cmp(roundView.Round) < 0) {
  88. // We've received 2f+1/Ceil(2N/3) ROUND CHANGE messages, start a new round immediately.
  89. c.startNewRound(roundView.Round)
  90. return nil
  91. } else if cv.Round.Cmp(roundView.Round) < 0 {
  92. // Only gossip the message with current round to other validators.
  93. return istanbulcommon.ErrIgnored
  94. }
  95. return nil
  96. }
  97. // ----------------------------------------------------------------------------
  98. func newRoundChangeSet(valSet istanbul.ValidatorSet) *roundChangeSet {
  99. return &roundChangeSet{
  100. validatorSet: valSet,
  101. roundChanges: make(map[uint64]*messageSet),
  102. mu: new(sync.Mutex),
  103. }
  104. }
  105. type roundChangeSet struct {
  106. validatorSet istanbul.ValidatorSet
  107. roundChanges map[uint64]*messageSet
  108. mu *sync.Mutex
  109. }
  110. // Add adds the round and message into round change set
  111. func (rcs *roundChangeSet) Add(r *big.Int, msg *ibfttypes.Message) (int, error) {
  112. rcs.mu.Lock()
  113. defer rcs.mu.Unlock()
  114. round := r.Uint64()
  115. if rcs.roundChanges[round] == nil {
  116. rcs.roundChanges[round] = newMessageSet(rcs.validatorSet)
  117. }
  118. err := rcs.roundChanges[round].Add(msg)
  119. if err != nil {
  120. return 0, err
  121. }
  122. return rcs.roundChanges[round].Size(), nil
  123. }
  124. // Clear deletes the messages with smaller round
  125. func (rcs *roundChangeSet) Clear(round *big.Int) {
  126. rcs.mu.Lock()
  127. defer rcs.mu.Unlock()
  128. for k, rms := range rcs.roundChanges {
  129. if len(rms.Values()) == 0 || k < round.Uint64() {
  130. delete(rcs.roundChanges, k)
  131. }
  132. }
  133. }
  134. // MaxRound returns the max round which the number of messages is equal or larger than num
  135. func (rcs *roundChangeSet) MaxRound(num int) *big.Int {
  136. rcs.mu.Lock()
  137. defer rcs.mu.Unlock()
  138. var maxRound *big.Int
  139. for k, rms := range rcs.roundChanges {
  140. if rms.Size() < num {
  141. continue
  142. }
  143. r := big.NewInt(int64(k))
  144. if maxRound == nil || maxRound.Cmp(r) < 0 {
  145. maxRound = r
  146. }
  147. }
  148. return maxRound
  149. }