github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/pbft/core/backlog.go (about) 1 // Copyright 2020 The go-simplechain Authors 2 // This file is part of the go-simplechain library. 3 // 4 // The go-simplechain 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-simplechain 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-simplechain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "github.com/bigzoro/my_simplechain/common/prque" 21 "github.com/bigzoro/my_simplechain/consensus/pbft" 22 ) 23 24 var ( 25 // msgPriority is defined for calculating processing priority to speedup consensus 26 // msgPreprepare > msgCommit > msgPrepare 27 msgPriority = map[MsgCode]int{ 28 msgPreprepare: 1, 29 msgCommit: 2, 30 msgPrepare: 3, 31 } 32 ) 33 34 // checkMessage checks the message state 35 // return errInvalidMessage if the message is invalid 36 // return errFutureMessage if the message view is larger than current view 37 // return errOldMessage if the message view is smaller than current view 38 func (c *core) checkMessage(msgCode MsgCode, view *pbft.View) error { 39 if view == nil || view.Sequence == nil || view.Round == nil { 40 return errInvalidMessage 41 } 42 43 if msgCode == msgRoundChange { 44 if view.Sequence.Cmp(c.currentView().Sequence) > 0 { 45 return errFutureMessage 46 } else if view.Cmp(c.currentView()) < 0 { 47 return errOldMessage 48 } 49 return nil 50 } 51 52 if view.Cmp(c.currentView()) > 0 { 53 return errFutureMessage 54 } 55 56 if view.Cmp(c.currentView()) < 0 { 57 return errOldMessage 58 } 59 60 if c.waitingForRoundChange { 61 return errFutureMessage 62 } 63 64 if c.state == StateAcceptRequest { 65 switch { 66 // unsupported light messages node 67 case isLightProposalMsg(msgCode) && !c.config.LightMode: 68 return errInvalidMessage 69 // StateAcceptRequest only accepts msgPreprepare or light proposal messages* 70 // other messages are future messages 71 case msgCode > msgPreprepare && msgCode <= msgRoundChange: 72 return errFutureMessage 73 case msgCode == msgGetMissedTxs: 74 return errFutureMessage 75 } 76 return nil 77 } 78 79 // For states(StatePreprepared, StatePrepared, StateCommitted), 80 // can accept all message types if processing with same view 81 return nil 82 } 83 84 func (c *core) storeBacklog(msg *message, src pbft.Validator) { 85 logger := c.logger.New("from", src, "state", c.state) 86 87 // dont backlog message from self 88 if src.Address() == c.Address() { 89 logger.Warn("Backlog from self") 90 return 91 } 92 93 logger.Trace("Store future message") 94 95 c.backlogsMu.Lock() 96 defer c.backlogsMu.Unlock() 97 98 logger.Debug("Retrieving backlog queue", "for", src.Address(), "backlogs_size", len(c.backlogs)) 99 backlog := c.backlogs[src.Address()] 100 if backlog == nil { 101 backlog = prque.New(nil) 102 } 103 switch msg.Code { 104 case msgPreprepare: 105 var p *pbft.Preprepare 106 err := msg.Decode(&p) 107 if err == nil { 108 backlog.Push(msg, toPriority(msg.Code, p.View)) 109 } 110 // for msgRoundChange, msgPrepare and msgCommit cases 111 case msgLightPreprepare: 112 var p *pbft.LightPreprepare 113 err := msg.Decode(&p) 114 if err == nil { 115 backlog.Push(msg, toPriority(msg.Code, p.View)) 116 } 117 default: 118 var p *pbft.Subject 119 err := msg.Decode(&p) 120 if err == nil { 121 backlog.Push(msg, toPriority(msg.Code, p.View)) 122 } 123 } 124 c.backlogs[src.Address()] = backlog 125 } 126 127 func (c *core) processBacklog() { 128 c.backlogsMu.Lock() 129 defer c.backlogsMu.Unlock() 130 131 for srcAddress, backlog := range c.backlogs { 132 if backlog == nil { 133 continue 134 } 135 _, src := c.valSet.GetByAddress(srcAddress) 136 if src == nil { 137 // validator is not available 138 delete(c.backlogs, srcAddress) 139 continue 140 } 141 logger := c.logger.New("from", src, "state", c.state) 142 isFuture := false 143 144 // We stop processing if 145 // 1. backlog is empty 146 // 2. The first message in queue is a future message 147 for !(backlog.Empty() || isFuture) { 148 m, prio := backlog.Pop() 149 msg := m.(*message) 150 var view *pbft.View 151 switch msg.Code { 152 case msgPreprepare: 153 var m *pbft.Preprepare 154 err := msg.Decode(&m) 155 if err == nil { 156 view = m.View 157 } 158 // for msgRoundChange, msgPrepare and msgCommit cases 159 case msgLightPreprepare: 160 var m *pbft.LightPreprepare 161 err := msg.Decode(&m) 162 if err == nil { 163 view = m.View 164 } 165 default: 166 var sub *pbft.Subject 167 err := msg.Decode(&sub) 168 if err == nil { 169 view = sub.View 170 } 171 } 172 if view == nil { 173 logger.Debug("Nil view", "msg", msg) 174 continue 175 } 176 // Push back if it's a future message 177 err := c.checkMessage(msg.Code, view) 178 if err != nil { 179 if err == errFutureMessage { 180 logger.Trace("Stop processing backlog", "msg", msg) 181 backlog.Push(msg, prio) 182 isFuture = true 183 break 184 } 185 logger.Trace("Skip the backlog event", "msg", msg, "err", err) 186 continue 187 } 188 logger.Trace("Post backlog event", "msg", msg) 189 190 go c.sendEvent(backlogEvent{ 191 src: src, 192 msg: msg, 193 }) 194 } 195 } 196 } 197 198 func toPriority(msgCode MsgCode, view *pbft.View) int64 { 199 if msgCode == msgRoundChange { 200 // For msgRoundChange, set the message priority based on its sequence 201 return -int64(view.Sequence.Uint64() * 1000) 202 } 203 // FIXME: round will be reset as 0 while new sequence 204 // 10 * Round limits the range of message code is from 0 to 9 205 // 1000 * Sequence limits the range of round is from 0 to 99 206 return -int64(view.Sequence.Uint64()*1000 + view.Round.Uint64()*10 + uint64(msgPriority[msgCode])) 207 }