github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/dpoa/msgpool.go (about) 1 package dpoa 2 3 import ( 4 "errors" 5 "sync" 6 7 "github.com/sixexorg/magnetic-ring/common" 8 "github.com/sixexorg/magnetic-ring/consense/dpoa/comm" 9 "github.com/sixexorg/magnetic-ring/log" 10 ) 11 12 13 14 var errDropFarFutureMsg = errors.New("msg pool dropped msg for far future") 15 16 type ConsensusRoundMsgs map[comm.MsgType][]comm.ConsensusMsg // indexed by MsgType (proposal, endorsement, ...) 17 18 type ConsensusRound struct { 19 blockNum uint64 20 msgs map[comm.MsgType][]interface{} 21 msgHashs map[common.Hash]interface{} // for msg-dup checking 22 } 23 24 func newConsensusRound(num uint64) *ConsensusRound { 25 26 r := &ConsensusRound{ 27 blockNum: num, 28 msgs: make(map[comm.MsgType][]interface{}), 29 msgHashs: make(map[common.Hash]interface{}), 30 } 31 32 r.msgs[comm.ConsensePrepare] = make([]interface{}, 0) 33 r.msgs[comm.ConsensePromise] = make([]interface{}, 0) 34 r.msgs[comm.ConsenseProposer] = make([]interface{}, 0) 35 r.msgs[comm.ConsenseAccept] = make([]interface{}, 0) 36 r.msgs[comm.EvilEvent] = make([]interface{}, 0) 37 38 return r 39 } 40 41 func (self *ConsensusRound) addMsg(msg comm.ConsensusMsg, msgHash common.Hash) error { 42 if _, present := self.msgHashs[msgHash]; present { 43 return nil 44 } 45 46 msgs := self.msgs[msg.Type()] 47 self.msgs[msg.Type()] = append(msgs, msg) 48 self.msgHashs[msgHash] = nil 49 return nil 50 } 51 52 func (self *ConsensusRound) hasMsg(msg comm.ConsensusMsg, msgHash common.Hash) (bool, error) { 53 if _, present := self.msgHashs[msgHash]; present { 54 return present, nil 55 } 56 return false, nil 57 } 58 59 type timeoutData struct { 60 tmSigs map[string][]byte // pub sigs 61 established bool // 62 } 63 64 type MsgPool struct { 65 lock sync.RWMutex 66 cacheLen uint64 67 rounds map[uint64]*ConsensusRound // indexed by BlockNum 68 earthSigs map[common.Hash]map[string][]byte // hash pub sigs 69 timeoutSigs map[uint64]map[uint32]*timeoutData // blknum view pub 70 msgHashs map[common.Hash]interface{} // for msg-dup checking 71 } 72 73 func newMsgPool(cacheLen uint64) *MsgPool { 74 // TODO 75 return &MsgPool{ 76 lock: sync.RWMutex{}, 77 cacheLen: cacheLen, 78 rounds: make(map[uint64]*ConsensusRound), 79 msgHashs: make(map[common.Hash]interface{}), 80 earthSigs: make(map[common.Hash]map[string][]byte), 81 timeoutSigs: make(map[uint64]map[uint32]*timeoutData), 82 } 83 } 84 85 func (pool *MsgPool) clean() { 86 pool.lock.Lock() 87 defer pool.lock.Unlock() 88 89 pool.rounds = make(map[uint64]*ConsensusRound) 90 } 91 92 func (pool *MsgPool) MarkMsgs(msgHash common.Hash) { 93 pool.lock.Lock() 94 defer pool.lock.Unlock() 95 pool.msgHashs[msgHash] = nil 96 } 97 98 func (pool *MsgPool) CheckMsgs(msgHash common.Hash) bool { 99 pool.lock.RLock() 100 defer pool.lock.RUnlock() 101 if _, ok := pool.msgHashs[msgHash]; ok { 102 return true 103 } 104 return false 105 } 106 107 func (pool *MsgPool) AddMsg(msg comm.ConsensusMsg, msgHash common.Hash, argv ...interface{}) error { 108 pool.lock.Lock() 109 defer pool.lock.Unlock() 110 111 blkNum := msg.GetBlockNum() 112 //if blkNum > pool.server.GetCurrentBlockNo()+pool.cacheLen { 113 // return errDropFarFutureMsg 114 //} 115 116 // TODO: limit #history rounds to cacheLen 117 // Note: we accept msg for future rounds 118 if msg.Type() == comm.EarthFetchRspSigs { 119 pMsg := msg.(*comm.EarthSigsFetchRspMsg) 120 if _, ok := pool.earthSigs[pMsg.BlkHash]; !ok { 121 pool.earthSigs[pMsg.BlkHash] = make(map[string][]byte) 122 } 123 pool.earthSigs[pMsg.BlkHash][pMsg.PubKey] = pMsg.Sigs 124 pool.msgHashs[msgHash] = nil 125 return nil 126 } 127 128 if msg.Type() == comm.ViewTimeout { // Msg type - []list(msglist) 129 var partiCfg *comm.ParticiConfig 130 if len(argv) == 1 { 131 partiCfg = argv[0].(*comm.ParticiConfig) 132 } 133 pMsg := msg.(*comm.ViewtimeoutMsg) 134 if _, ok := pool.timeoutSigs[blkNum]; !ok { 135 pool.timeoutSigs[blkNum] = make(map[uint32]*timeoutData) 136 } 137 if _, ok := pool.timeoutSigs[blkNum][pMsg.RawData.View]; !ok { 138 pool.timeoutSigs[blkNum][pMsg.RawData.View] = &timeoutData{tmSigs: make(map[string][]byte)} 139 } 140 //len(pool.server.dpoaMgr.partiCfg.obserNodes) 141 pool.timeoutSigs[blkNum][pMsg.RawData.View].tmSigs[pMsg.PubKey] = pMsg.Signature 142 if partiCfg.View == pMsg.RawData.View { 143 if len(pool.timeoutSigs[blkNum][pMsg.RawData.View].tmSigs[pMsg.PubKey]) > len(partiCfg.ObserNodes)/2 { 144 pool.timeoutSigs[blkNum][pMsg.RawData.View].established = true 145 } 146 } 147 pool.msgHashs[msgHash] = nil 148 return nil 149 } 150 151 if _, present := pool.rounds[blkNum]; !present { 152 pool.rounds[blkNum] = newConsensusRound(blkNum) 153 } 154 155 return pool.rounds[blkNum].addMsg(msg, msgHash) 156 } 157 158 func (pool *MsgPool) HasMsg(msg comm.ConsensusMsg, msgHash common.Hash) bool { 159 pool.lock.RLock() 160 defer pool.lock.RUnlock() 161 162 if roundMsgs, present := pool.rounds[msg.GetBlockNum()]; !present { 163 return false 164 } else { 165 if present, err := roundMsgs.hasMsg(msg, msgHash); err != nil { 166 log.Error("msgpool failed to check msg avail: %s", err) 167 return false 168 } else { 169 return present 170 } 171 } 172 173 return false 174 } 175 176 func (pool *MsgPool) Persist() error { 177 // TODO 178 return nil 179 } 180 181 func (pool *MsgPool) TimeoutCount(blocknum uint64) int { 182 pool.lock.RLock() 183 defer pool.lock.RUnlock() 184 //fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!&&&&&&&&&&&&&^^^^^^^^^^^^TimeoutCount blocknum:", blocknum) 185 if _, ok := pool.timeoutSigs[blocknum]; !ok { 186 return 0 187 } 188 189 var count int = 0 190 for _, v := range pool.timeoutSigs[blocknum] { //view 191 if v.established { 192 /*for k1, _ := range v.tmSigs { 193 fmt.Println("!!!!!!!!!!!start&&&&&&&&&&&&&^^^^^^^^^^^^TimeoutCount blocknum:", "view", k, "pub", k1) 194 }*/ 195 count++ 196 } 197 } 198 199 //fmt.Println("&&&&&&&&&&&&&^^^^^^^^^^^^TimeoutCount blocknum:", blocknum, "count:", count) 200 return count 201 } 202 203 func (pool *MsgPool) GetTimeoutMsgs(blocknum uint64) map[uint32]*timeoutData { 204 pool.lock.RLock() 205 defer pool.lock.RUnlock() 206 if v, ok := pool.timeoutSigs[blocknum]; !ok { 207 return make(map[uint32]*timeoutData) 208 } else { 209 return v 210 } 211 } 212 213 func (pool *MsgPool) GetEvilMsgs(blocknum uint64) []interface{} { 214 pool.lock.RLock() 215 defer pool.lock.RUnlock() 216 217 roundMsgs, ok := pool.rounds[blocknum] 218 if !ok { 219 return nil 220 } 221 msgs, ok := roundMsgs.msgs[comm.EvilEvent] 222 if !ok { 223 return nil 224 } 225 return msgs 226 } 227 228 func (pool *MsgPool) GetEarthMsgs(prehash common.Hash) map[string][]byte { 229 pool.lock.RLock() 230 defer pool.lock.RUnlock() 231 232 msgs, ok := pool.earthSigs[prehash] 233 if !ok { 234 return nil 235 } 236 237 return msgs 238 } 239 240 func (pool *MsgPool) onBlockSealed(blockNum uint64) { 241 if blockNum <= pool.cacheLen { 242 return 243 } 244 pool.lock.Lock() 245 defer pool.lock.Unlock() 246 247 toFreeRound := make([]uint64, 0) 248 for n := range pool.rounds { 249 if n < blockNum-pool.cacheLen { 250 toFreeRound = append(toFreeRound, n) 251 } 252 } 253 for _, n := range toFreeRound { 254 delete(pool.rounds, n) 255 } 256 } 257 258 func (pool *MsgPool) IncInsert(blockNum uint32, msgtype comm.MsgType, msg interface{}) { 259 }