github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/pbft/core/roundchange.go (about) 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 17 package core 18 19 import ( 20 "math/big" 21 22 "github.com/bigzoro/my_simplechain/common" 23 "github.com/bigzoro/my_simplechain/consensus/pbft" 24 ) 25 26 // sends the ROUND CHANGE message with current round + 1 27 func (c *core) sendNextRoundChange() { 28 cv := c.currentView() 29 c.sendRoundChange(new(big.Int).Add(cv.Round, common.Big1)) 30 } 31 32 // sends the ROUND CHANGE message with the given round 33 func (c *core) sendRoundChange(round *big.Int) { 34 logger := c.logger.New("state", c.state) 35 36 cv := c.currentView() 37 if cv.Round.Cmp(round) >= 0 { 38 logger.Error("Cannot send out the round change", "current round", cv.Round, "target round", round) 39 return 40 } 41 42 c.catchUpRound(&pbft.View{ 43 // The round number we'd like to transfer to. 44 Round: new(big.Int).Set(round), 45 Sequence: new(big.Int).Set(cv.Sequence), 46 }) 47 48 // Now we have the new round number and sequence number 49 cv = c.currentView() 50 rc := &pbft.Subject{ 51 View: cv, 52 } 53 54 payload, err := Encode(rc) 55 if err != nil { 56 logger.Error("Failed to encode ROUND CHANGE", "rc", rc, "err", err) 57 return 58 } 59 60 rcMsg := &message{ 61 Code: msgRoundChange, 62 Msg: payload, 63 } 64 65 logger.Trace("send roundChange message", "view", cv) 66 //logger.Error("[report] send roundChange message", "view", cv) 67 68 //c.broadcast(rcMsg, true) 69 c.broadcast(rcMsg, false) 70 c.acceptAndCheckRoundChange(rcMsg, rc) 71 } 72 73 func (c *core) handleRoundChange(msg *message, src pbft.Validator) error { 74 logger := c.logger.New("state", c.state, "from", src.Address().Hex()) 75 76 // Decode ROUND CHANGE message 77 var rc *pbft.Subject 78 if err := msg.Decode(&rc); err != nil { 79 logger.Error("Failed to decode ROUND CHANGE", "err", err) 80 return errInvalidMessage 81 } 82 83 logger.Trace("handle roundChange message", "rcView", rc.View, "waitingForRoundChange", c.waitingForRoundChange) 84 //logger.Error("[report] handle roundChange message", "rcView", rc.View, "waitingForRoundChange", c.waitingForRoundChange) 85 86 if err := c.checkMessage(msgRoundChange, rc.View); err != nil { 87 switch err { 88 case errOldMessage: 89 if commitHash, ok := c.backend.HasProposal(rc.Pending, rc.View.Sequence); ok { 90 c.backend.AnnounceCommittedProposal(commitHash, rc.View.Sequence, src) 91 } 92 } 93 return err 94 } 95 96 return c.acceptAndCheckRoundChange(msg, rc) 97 } 98 99 func (c *core) acceptAndCheckRoundChange(msg *message, rc *pbft.Subject) error { 100 logger := c.logger.New("state", c.state, "from", msg.Address) 101 102 cv := c.currentView() 103 roundView := rc.View 104 105 logger.Trace("accept round change", "cv", cv, "rv", roundView) 106 //logger.Error("[report] ^^ accept round change", "cv", cv, "rv", roundView) 107 108 // Add the ROUND CHANGE message to its message set and return how many 109 // messages we've got with the same round number and sequence number. 110 num, err := c.roundChangeSet.Add(roundView.Round, msg) 111 112 if err != nil { 113 logger.Warn("Failed to add round change message", "msg", msg, "err", err) 114 return err 115 } 116 117 // Once we received f+1 ROUND CHANGE messages, those messages form a weak certificate. 118 // If our round number is smaller than the certificate's round number, we would 119 // try to catch up the round number. 120 if c.waitingForRoundChange && num == c.valSet.F()+1 { 121 if cv.Round.Cmp(roundView.Round) < 0 { 122 c.sendRoundChange(roundView.Round) 123 } 124 return nil 125 126 } else if num == c.Confirmations() && (c.waitingForRoundChange || cv.Round.Cmp(roundView.Round) < 0) { 127 // We've received 2f+1/Ceil(2N/3) ROUND CHANGE messages, start a new round immediately. 128 c.startNewRound(roundView.Round) 129 return nil 130 131 } else if cv.Round.Cmp(roundView.Round) < 0 { 132 // Only gossip the message with current round to other validators. 133 return errIgnored 134 } 135 136 return nil 137 }