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  }