github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/core/roundchange.go (about) 1 // Copyright 2017 AMIS Technologies 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 "sync" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/consensus/podc" 25 ) 26 27 // sendNextRoundChange sends the round change message with current round + 1 28 func (c *core) sendNextRoundChange() { 29 30 cv := c.currentView() 31 c.sendRoundChange(new(big.Int).Add(cv.Round, common.Big1)) 32 33 } 34 35 // sendRoundChange sends the round change message with the given round 36 func (c *core) sendRoundChange(round *big.Int) { 37 logger := c.logger.New("state", c.state) 38 39 cv := c.currentView() 40 if cv.Round.Cmp(round) >= 0 { 41 logger.Error("Cannot send out the round change", "current round", cv.Round, "target round", round) 42 return 43 } 44 45 c.catchUpRound(&podc.View{ 46 // The round number we'd like to transfer to. 47 Round: new(big.Int).Set(round), 48 Sequence: new(big.Int).Set(cv.Sequence), 49 }) 50 51 // Now we have the new round number and sequence number 52 cv = c.currentView() 53 rc := &roundChange{ 54 Round: new(big.Int).Set(cv.Round), 55 Sequence: new(big.Int).Set(cv.Sequence), 56 Digest: common.Hash{}, 57 } 58 59 payload, err := Encode(rc) 60 if err != nil { 61 logger.Error("Failed to encode round change", "rc", rc, "err", err) 62 return 63 } 64 65 c.broadcast(&message{ 66 Code: msgRoundChange, 67 Msg: payload, 68 }) 69 } 70 71 func (c *core) handleRoundChange(msg *message, src podc.Validator) error { 72 logger := c.logger.New("state", c.state) 73 // Decode round change message 74 var rc *roundChange 75 //startsync := make (chan int) 76 //if( !global.QManConnected) { // if i'm not Qman and general geth. then roundchange and start new round. for qman, don't roundchange, it is not necessary. 77 78 if err := msg.Decode(&rc); err != nil { 79 logger.Error("Failed to decode round change", "err", err) 80 return errInvalidMessage 81 } 82 83 cv := c.currentView() 84 //log.Info("I'm not the Qmanager(handleRoundChange) ") 85 86 // We never accept round change message with different sequence number 87 if rc.Sequence.Cmp(cv.Sequence) != 0 { 88 logger.Warn("Inconsistent sequence number(handleRoundChange)", "expected", cv.Sequence, "got", rc.Sequence) 89 // sequence no가 틀리면, 블럭 싱크 다시 맞춰주기 위해서, 싱크로나이즈 동작 수행 해주면 됨. 여기서, 90 // 싱크로나이즈를 수행하기 위해서 여기서 싱크코드 넣고, 시퀀스 맞춰지면,, 다시 startNewRound. 수행 91 // 메시지 fail 나는 경우, remove peer를 하기 때문에 쓸모없는 peer로,, 에러메시지 나오고, EOF,, 등등. 92 // 싱크 에러와, fetcher를,, 여기서 채널로,, fetcher or sync hanlder로,, 채널을 통해서 메시지르 보내면, 93 // eth/handler.go 의 synloop()에서,, 처리되게할 것. 94 95 //c.startNewRound(&podc.View{ 96 // Round: new(big.Int).Set(rc.Round), 97 // Sequence: new(big.Int).Set(rc.Sequence), 98 //}, true) 99 // startsync <- 1 100 101 return errInvalidMessage 102 } 103 104 // We never accept round change message with smaller round number 105 if rc.Round.Cmp(cv.Round) < 0 { 106 logger.Warn("Old round change", "from", src, "expected", cv.Round, "got", rc.Round) 107 return errOldMessage 108 } 109 110 num, err := c.roundChangeSet.Add(rc.Round, msg) 111 112 if err != nil { 113 logger.Warn("Failed to add round change message", "from", src, "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 == int(c.valSet.F()+1) { 121 if cv.Round.Cmp(rc.Round) < 0 { 122 c.sendRoundChange(rc.Round) 123 } 124 } 125 126 // We've received 2f+1 round change messages, start a new round immediately. 127 if num == int(2*c.valSet.F()+1) { 128 c.startNewRound(&podc.View{ 129 Round: new(big.Int).Set(rc.Round), 130 Sequence: new(big.Int).Set(rc.Sequence), 131 }, true) 132 } 133 134 //} 135 //} 136 137 return nil 138 } 139 140 // ---------------------------------------------------------------------------- 141 142 func newRoundChangeSet(valSet podc.ValidatorSet) *roundChangeSet { 143 return &roundChangeSet{ 144 validatorSet: valSet, 145 roundChanges: make(map[uint64]*messageSet), 146 mu: new(sync.Mutex), 147 } 148 } 149 150 type roundChangeSet struct { 151 validatorSet podc.ValidatorSet 152 roundChanges map[uint64]*messageSet 153 mu *sync.Mutex 154 } 155 156 // Add adds the round and message into round change set 157 func (rcs *roundChangeSet) Add(r *big.Int, msg *message) (int, error) { 158 rcs.mu.Lock() 159 defer rcs.mu.Unlock() 160 161 round := r.Uint64() 162 if rcs.roundChanges[round] == nil { 163 rcs.roundChanges[round] = newMessageSet(rcs.validatorSet) 164 } 165 err := rcs.roundChanges[round].Add(msg) //? 166 if err != nil { 167 return 0, err 168 } 169 return rcs.roundChanges[round].Size(), nil 170 } 171 // Add adds the round and message into round change set 172 func (rcs *roundChangeSet) Set(r *big.Int, msg *message) (int, error) { 173 rcs.mu.Lock() 174 defer rcs.mu.Unlock() 175 176 round := r.Uint64() 177 //log.Info("round in Set =", "round", round ) //added by yichoi 178 if rcs.roundChanges[round] == nil { 179 rcs.roundChanges[round] = newMessageSet(rcs.validatorSet) 180 } 181 //err := rcs.roundChanges[round].Add(msg) 182 //if err != nil { 183 // return 0, err 184 //} 185 return rcs.roundChanges[round].Size(), nil 186 } 187 188 // Clear deletes the messages with smaller round 189 func (rcs *roundChangeSet) Clear(round *big.Int) { 190 rcs.mu.Lock() 191 defer rcs.mu.Unlock() 192 193 for k, rms := range rcs.roundChanges { 194 if len(rms.Values()) == 0 || k < round.Uint64() { 195 delete(rcs.roundChanges, k) 196 } 197 } 198 } 199 200 // MaxRound returns the max round which the number of messages is equal or larger than num 201 func (rcs *roundChangeSet) MaxRound(num int) *big.Int { 202 rcs.mu.Lock() 203 defer rcs.mu.Unlock() 204 205 var maxRound *big.Int 206 for k, rms := range rcs.roundChanges { 207 if rms.Size() < num { 208 continue 209 } 210 r := big.NewInt(int64(k)) 211 if maxRound == nil || maxRound.Cmp(r) < 0 { 212 maxRound = r 213 } 214 } 215 return maxRound 216 }