github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/cmd/qman-new/qmanager.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "io/ioutil" 6 "math/rand" 7 "net/http" 8 "sync" 9 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/config" 12 "github.com/ethereum/go-ethereum/ethdb" 13 "github.com/ethereum/go-ethereum/log" 14 "github.com/ethereum/go-ethereum/qmanager" 15 "github.com/ethereum/go-ethereum/qmanager/global" 16 ) 17 18 type roundInfo struct { 19 // coordinator common.Address 20 // cQrnd int 21 divisor int 22 validators []common.ValidatorInfo 23 } 24 25 type Qmanager struct { 26 // seq uint64 27 // round uint64 28 addr string 29 // port uint64 30 // dir string 31 32 all map[common.Address]common.Tag 33 // senators map[common.Address]int 34 // candidates map[common.Address]int 35 //alive map[common.Address]int 36 current roundInfo 37 38 config *config.EnvConfig 39 db ethdb.Database // Block chain database 40 //p2pServer *p2p.Server 41 //server *http.Server 42 43 lock sync.RWMutex 44 } 45 46 func NewQmanager(db ethdb.Database, config *config.EnvConfig, addr string) *Qmanager { 47 log.Info("NewQmanager") 48 qman := &Qmanager{ 49 config: config, 50 db: db, 51 addr: addr, 52 all: make(map[common.Address]common.Tag), 53 } 54 55 //load latest validators from db 56 senators := ReadSenators(qman.db) 57 if len(senators) != 0 { 58 for i, senator := range senators { 59 qman.all[senator] = common.Senator 60 log.Debug("db senator", "i", i, "addr", senator.Hex()) 61 } 62 } else { 63 for _, senator := range config.Senatornodes { 64 qman.all[common.HexToAddress(senator)] = common.Senator 65 if err := WriteSenator(qman.db, common.HexToAddress(senator), int(common.Senator)); err != nil { 66 continue 67 } 68 log.Debug("config.json senator", "addr", senator, "value", common.Senator) 69 } 70 } 71 candidates := ReadCandidates(qman.db) 72 if len(candidates) != 0 { 73 for i, candidate := range candidates { 74 qman.all[candidate] = common.Candidate 75 log.Debug("db candidate", "i", i, "addr", candidate.Hex()) 76 } 77 } else { 78 for _, candidate := range config.Candidatenodes { 79 qman.all[common.HexToAddress(candidate)] = common.Candidate 80 if err := WriteCandidate(qman.db, common.HexToAddress(candidate), int(common.Candidate)); err != nil { 81 continue 82 } 83 log.Debug("config.json candidate", "addr", candidate, "value", common.Candidate) 84 } 85 } 86 87 qman.printInfo() 88 89 qmanager.CheckQRNGStatus() 90 91 http.HandleFunc("/Ping", qmanager.Ping) 92 //http.HandleFunc("/GovernanceSendList", qman.GovernanceSendList) 93 http.HandleFunc("/GovernanceAddValidators", qman.AddValidators) 94 http.HandleFunc("/GovernanceRemoveValidators", qman.RemoveValidators) 95 http.HandleFunc("/GovernanceGetValidatorList", qman.GetValidatorList) 96 http.HandleFunc("/ExtraData", qman.HandleExtraData) 97 http.HandleFunc("/BootNodeSendData", qman.BootNodeSendData) 98 http.HandleFunc("/CoordinatorConfirmation", qman.CoordinatorConfirmation) 99 100 return qman 101 } 102 103 func (qm *Qmanager) Start() { 104 http.ListenAndServe(qm.addr, nil) 105 log.Info("Qmanager started") 106 } 107 108 // func (qm *Qmanager) GovernanceSendList(w http.ResponseWriter, req *http.Request) { 109 // w.Header().Set("Content-Type", "application/json") 110 // body, err := ioutil.ReadAll(req.Body) 111 // if err != nil { 112 // panic(err) 113 // } 114 // var govStruct []global.GovStruct 115 // err = json.Unmarshal(body, &govStruct) 116 // if err != nil { 117 // m := global.Message{ 118 // Message: "Error", 119 // Code: http.StatusBadRequest, 120 // } 121 // json.NewEncoder(w).Encode(m) 122 // return 123 // } 124 // global.GovernanceList = govStruct 125 // m := global.Message{ 126 // Message: "Success", 127 // Code: http.StatusOK, 128 // } 129 // json.NewEncoder(w).Encode(m) 130 // go qmanager.UpdateSenatorCandidateNodes() 131 // } 132 133 func (qm *Qmanager) AddValidators(w http.ResponseWriter, req *http.Request) { 134 w.Header().Set("Content-Type", "application/json") 135 body, err := ioutil.ReadAll(req.Body) 136 if err != nil { 137 log.Warn("http request fail", "err", err) 138 qm.responseFail(w, http.StatusBadRequest) 139 return 140 } 141 var validators []global.GovStruct 142 err = json.Unmarshal(body, &validators) 143 if err != nil { 144 log.Warn("json unmarshal error", "err", err) 145 qm.responseFail(w, http.StatusBadRequest) 146 return 147 } 148 for _, validator := range validators { 149 if validator.Tag != common.Senator && validator.Tag != common.Candidate { 150 log.Warn("invalid tag", "addr", validator.Validator, "tag", validator.Tag) 151 continue 152 } 153 if validator.Tag == common.Senator { 154 if err := WriteSenator(qm.db, common.HexToAddress(validator.Validator), int(validator.Tag)); err != nil { 155 continue 156 } 157 } else if validator.Tag == common.Candidate { 158 if err := WriteCandidate(qm.db, common.HexToAddress(validator.Validator), int(validator.Tag)); err != nil { 159 continue 160 } 161 } 162 qm.all[common.HexToAddress(validator.Validator)] = validator.Tag 163 log.Info("add validator", "addr", validator.Validator, "tag", validator.Tag) 164 } 165 166 m := global.Message{ 167 Message: "Success", 168 Code: http.StatusOK, 169 } 170 json.NewEncoder(w).Encode(m) 171 172 qm.printInfo() 173 } 174 175 func (qm *Qmanager) RemoveValidators(w http.ResponseWriter, req *http.Request) { 176 w.Header().Set("Content-Type", "application/json") 177 body, err := ioutil.ReadAll(req.Body) 178 if err != nil { 179 log.Warn("http request fail", "err", err) 180 qm.responseFail(w, http.StatusBadRequest) 181 return 182 } 183 var validators []global.GovStruct 184 err = json.Unmarshal(body, &validators) 185 if err != nil { 186 log.Warn("json unmarshal error", "err", err) 187 qm.responseFail(w, http.StatusBadRequest) 188 return 189 } 190 for _, validator := range validators { 191 if validator.Tag != common.Senator && validator.Tag != common.Candidate { 192 log.Warn("invalid tag", "addr", validator.Validator, "tag", validator.Tag) 193 continue 194 } 195 if validator.Tag == common.Senator { 196 if err := RemoveSenator(qm.db, common.HexToAddress(validator.Validator)); err != nil { 197 continue 198 } 199 } else if validator.Tag == common.Candidate { 200 if err := RemoveCandidate(qm.db, common.HexToAddress(validator.Validator)); err != nil { 201 continue 202 } 203 } 204 delete(qm.all, common.HexToAddress(validator.Validator)) 205 log.Info("remove validator", "addr", validator.Validator, "tag", validator.Tag) 206 } 207 208 m := global.Message{ 209 Message: "Success", 210 Code: http.StatusOK, 211 } 212 json.NewEncoder(w).Encode(m) 213 214 qm.printInfo() 215 } 216 217 func (qm *Qmanager) GetValidatorList(w http.ResponseWriter, req *http.Request) { 218 w.Header().Set("Content-Type", "application/json") 219 body, err := ioutil.ReadAll(req.Body) 220 if err != nil { 221 log.Warn("http request fail", "err", err) 222 qm.responseFail(w, http.StatusBadRequest) 223 return 224 } 225 226 var addrs []string 227 err = json.Unmarshal(body, &addrs) 228 if err != nil { 229 log.Warn("json unmarshal error", "err", err) 230 qm.responseFail(w, http.StatusBadRequest) 231 return 232 } 233 234 // var retList []global.QManDBStruct 235 var retList []global.GovStruct 236 if len(addrs) != 0 { 237 for _, addr := range addrs { 238 if tag, ok := qm.all[common.HexToAddress(addr)]; ok { 239 retList = append(retList, global.GovStruct{Validator: addr, Tag: tag}) 240 } else { 241 //read db, if success, return data and update qm.all 242 } 243 } 244 } else { 245 for addr, tag := range qm.all { 246 retList = append(retList, global.GovStruct{Validator: addr.Hex(), Tag: tag}) 247 } 248 } 249 log.Info("Get validator list", "count", len(retList)) 250 251 //qm.responseSuccess(w) 252 //json.NewEncoder(w).Encode(retList) 253 qm.responseData(w, retList) 254 255 qm.printInfo() 256 } 257 258 func (qm *Qmanager) Ping(w http.ResponseWriter, req *http.Request) { 259 w.Header().Set("Content-Type", "application/json") 260 m := global.Message{ 261 Message: "Success", 262 Code: http.StatusOK, 263 } 264 json.NewEncoder(w).Encode(m) 265 } 266 267 func (qm *Qmanager) HandleExtraData(w http.ResponseWriter, req *http.Request) { 268 w.Header().Set("Content-Type", "application/json") 269 body, err := ioutil.ReadAll(req.Body) 270 if err != nil { 271 log.Warn("http request fail", "err", err) 272 qm.responseFail(w, http.StatusBadRequest) 273 return 274 } 275 log.Info(string(body)) 276 277 var reqStruct global.RequestStruct 278 err = json.Unmarshal(body, &reqStruct) 279 if err != nil { 280 log.Warn("json unmarshal error", "err", err) 281 qm.responseFail(w, http.StatusBadRequest) 282 return 283 } 284 285 proposerAddress := common.HexToAddress(reqStruct.Proposer) 286 287 log.Info("Received EXTRA DATA REQUEST from geth") 288 if global.QRNGDeviceStat == true { 289 log.Info("Random Number Generator ", "Using - ", "Quantum Device") 290 } else { 291 log.Info("Random Number Generator ", "Using - ", "Pusedo Random") 292 } 293 294 var extra []common.ValidatorInfo 295 296 outerLoop := 0 297 for { 298 //log.Print("Qmanager ", "Generating Random Numbers ", "Outerloop") 299 extra = qm.generateExtraData() 300 completed := false 301 divisor := rand.Intn(50) + 1 302 303 index := 0 304 log.Debug("handleExtraData", "len(extra)", len(extra)) 305 for index < len(extra) { 306 if proposerAddress != extra[index].Address { 307 if extra[index].Tag == common.Senator { 308 randomNumber := extra[index].Qrnd 309 if randomNumber%uint64(divisor) == 0 { 310 extra[index].Tag = common.Coordinator 311 log.Debug("Qmanager ", "Random Coordinator Selected ", extra[index].Address.String()) 312 index = len(extra) 313 completed = true 314 qm.current = roundInfo{ 315 divisor: divisor, 316 validators: extra, 317 } 318 } 319 } 320 } 321 index++ 322 } 323 outerLoop++ 324 if completed { 325 log.Info("QManager ExtraData ", "For Loop Index: ", outerLoop) 326 break 327 } 328 if outerLoop == 30 { 329 log.Error("QManager ExtraData ", "Error", "Cannot Select Coordinator") 330 break 331 } 332 333 } 334 log.Info("QManager ", "ExtraData Length: ", len(extra)) 335 log.Info("QManager ", "ExtraData: ", extra) 336 json.NewEncoder(w).Encode(extra) 337 } 338 339 func (qm *Qmanager) generateExtraData() []common.ValidatorInfo { 340 var extra []common.ValidatorInfo 341 for addr, tag := range qm.all { 342 log.Debug("generateExtraData", "validator.Address", addr, "tag", tag) 343 344 var num uint64 345 if global.QRNGDeviceStat == true { 346 randomIndex := rand.Intn(12280) + 1 347 num = global.RandomNumbers[randomIndex] 348 } else { 349 num = rand.Uint64() 350 } 351 validatorInfo := common.ValidatorInfo{ 352 Address: addr, 353 Qrnd: num, 354 Tag: tag, 355 } 356 extra = append(extra, validatorInfo) 357 } 358 return extra 359 } 360 361 func (qm *Qmanager) CoordinatorConfirmation(w http.ResponseWriter, req *http.Request) { 362 w.Header().Set("Content-Type", "application/json") 363 body, err := ioutil.ReadAll(req.Body) 364 if err != nil { 365 log.Warn("http request fail", "err", err) 366 qm.responseFail(w, http.StatusBadRequest) 367 return 368 } 369 log.Info("COORDINATOR CONFIRMATION") 370 log.Debug(string(body)) 371 372 var coordiStruct global.RequestCoordiStruct 373 err = json.Unmarshal(body, &coordiStruct) 374 if err != nil { 375 log.Warn("json unmarshal error", "err", err) 376 qm.responseFail(w, http.StatusBadRequest) 377 return 378 } 379 log.Info("QMAN ", "DIVISOR: ", qm.current.divisor) 380 381 if coordiStruct.QRND%uint64(qm.current.divisor) == 0 { 382 log.Info("QMAN COORDI TRUE") 383 decideStruct := global.CoordiDecideStruct{Status: true} 384 json.NewEncoder(w).Encode(decideStruct) 385 } else { 386 log.Info("QMAN COORDI FALSE") 387 decideStruct := global.CoordiDecideStruct{Status: false} 388 json.NewEncoder(w).Encode(decideStruct) 389 } 390 } 391 392 func (qm *Qmanager) BootNodeSendData(w http.ResponseWriter, req *http.Request) { 393 w.Header().Set("Content-Type", "application/json") 394 body, err := ioutil.ReadAll(req.Body) 395 if err != nil { 396 log.Warn("http request fail", "err", err) 397 qm.responseFail(w, http.StatusBadRequest) 398 return 399 } 400 var nodeStruct global.QManDBStruct 401 err = json.Unmarshal(body, &nodeStruct) 402 if err != nil { 403 log.Warn("json unmarshal error", "err", err) 404 qm.responseFail(w, http.StatusBadRequest) 405 return 406 } 407 408 log.Info("Bootnode Data ", "Addr: ", nodeStruct.Address, "Tag", nodeStruct.Tag) 409 410 // if nodeStruct.Address != "" { 411 // if !FindNode(nodeStruct.Address) { 412 // Save(nodeStruct) 413 // } 414 // } 415 416 m := global.Message{ 417 Message: "Success", 418 Code: http.StatusOK, 419 } 420 421 json.NewEncoder(w).Encode(m) 422 } 423 424 func (qm *Qmanager) printInfo() { 425 for addr, tag := range qm.all { 426 log.Debug("print all node infos", "addr", addr.Hex(), "tag", tag) 427 } 428 } 429 430 // func (qm *Qmanager) response(w http.ResponseWriter, msg string, code int) { 431 // m := global.Message{ 432 // Message: msg, 433 // Code: code, 434 // } 435 // json.NewEncoder(w).Encode(m) 436 // } 437 438 func (qm *Qmanager) responseFail(w http.ResponseWriter, code int) { 439 m := global.Message{ 440 Message: "Fail", 441 Code: code, 442 } 443 json.NewEncoder(w).Encode(m) 444 } 445 446 func (qm *Qmanager) responseSuccess(w http.ResponseWriter) { 447 m := global.Message{ 448 Message: "Success", 449 Code: http.StatusOK, 450 } 451 json.NewEncoder(w).Encode(m) 452 } 453 454 func (qm *Qmanager) responseData(w http.ResponseWriter, data interface{}) { 455 json.NewEncoder(w).Encode(data) 456 }