github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/contracts/chief/service.go (about)

     1  package chief
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"math/big"
     7  	"time"
     8  
     9  	"github.com/SmartMeshFoundation/Spectrum/contracts/statute"
    10  
    11  	"fmt"
    12  
    13  	"github.com/SmartMeshFoundation/Spectrum/accounts/abi/bind"
    14  	"github.com/SmartMeshFoundation/Spectrum/common"
    15  	chieflib "github.com/SmartMeshFoundation/Spectrum/contracts/chief/lib"
    16  	"github.com/SmartMeshFoundation/Spectrum/eth"
    17  	"github.com/SmartMeshFoundation/Spectrum/internal/ethapi"
    18  	"github.com/SmartMeshFoundation/Spectrum/les"
    19  	"github.com/SmartMeshFoundation/Spectrum/log"
    20  	"github.com/SmartMeshFoundation/Spectrum/node"
    21  	"github.com/SmartMeshFoundation/Spectrum/p2p"
    22  	"github.com/SmartMeshFoundation/Spectrum/params"
    23  	"github.com/SmartMeshFoundation/Spectrum/rpc"
    24  )
    25  
    26  /*
    27  type Service interface {
    28  	Protocols() []p2p.Protocol
    29  	APIs() []rpc.API
    30  	Start(server *p2p.Server) error
    31  	Stop() error
    32  }
    33  */
    34  
    35  const DEF_TIMEOUT = time.Second * 3
    36  
    37  // volunteer : peer.td - current.td < 200
    38  var (
    39  	min_td = big.NewInt(200)
    40  )
    41  
    42  //implements node.Service
    43  type TribeService struct {
    44  	tribeChief_0_0_2 *chieflib.TribeChief
    45  	tribeChief_0_0_3 *chieflib.TribeChief_0_0_3
    46  	tribeChief_0_0_4 *chieflib.TribeChief_0_0_4
    47  	tribeChief_0_0_5 *chieflib.TribeChief_0_0_5
    48  	tribeChief_0_0_6 *chieflib.TribeChief_0_0_6
    49  	tribeChief_0_0_7 *chieflib.TribeChief_0_0_7
    50  	tribeChief_1_0_0 *chieflib.TribeChief_1_0_0
    51  	poc              *chieflib.POC_1_0_0
    52  	base             *chieflib.ChiefBase_1_0_0
    53  	quit             chan int
    54  	server           *p2p.Server // peers and nodekey ...
    55  	ethereum         *eth.Ethereum
    56  	ctx              *node.ServiceContext
    57  }
    58  
    59  func NewTribeService(ctx *node.ServiceContext) (node.Service, error) {
    60  	var (
    61  		apiBackend ethapi.Backend
    62  		ethereum   *eth.Ethereum
    63  	)
    64  	if err := ctx.Service(&ethereum); err == nil {
    65  		apiBackend = ethereum.ApiBackend
    66  	} else {
    67  		var ethereum *les.LightEthereum
    68  		if err := ctx.Service(&ethereum); err == nil {
    69  			apiBackend = ethereum.ApiBackend
    70  		} else {
    71  			return nil, err
    72  		}
    73  	}
    74  
    75  	ts := &TribeService{
    76  		quit:     make(chan int),
    77  		ethereum: ethereum,
    78  		ctx:      ctx,
    79  	}
    80  	if v0_0_2 := params.GetChiefInfoByVsn("0.0.2"); v0_0_2 != nil {
    81  		contract_0_0_2, err := chieflib.NewTribeChief(v0_0_2.Addr, eth.NewContractBackend(apiBackend))
    82  		if err != nil {
    83  			return nil, err
    84  		}
    85  		ts.tribeChief_0_0_2 = contract_0_0_2
    86  	}
    87  	if v0_0_3 := params.GetChiefInfoByVsn("0.0.3"); v0_0_3 != nil {
    88  		contract_0_0_3, err := chieflib.NewTribeChief_0_0_3(v0_0_3.Addr, eth.NewContractBackend(apiBackend))
    89  		if err != nil {
    90  			return nil, err
    91  		}
    92  		ts.tribeChief_0_0_3 = contract_0_0_3
    93  	}
    94  	if v0_0_4 := params.GetChiefInfoByVsn("0.0.4"); v0_0_4 != nil {
    95  		contract_0_0_4, err := chieflib.NewTribeChief_0_0_4(v0_0_4.Addr, eth.NewContractBackend(apiBackend))
    96  		if err != nil {
    97  			return nil, err
    98  		}
    99  		ts.tribeChief_0_0_4 = contract_0_0_4
   100  	}
   101  	if v0_0_5 := params.GetChiefInfoByVsn("0.0.5"); v0_0_5 != nil {
   102  		contract_0_0_5, err := chieflib.NewTribeChief_0_0_5(v0_0_5.Addr, eth.NewContractBackend(apiBackend))
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  		ts.tribeChief_0_0_5 = contract_0_0_5
   107  	}
   108  	if v0_0_6 := params.GetChiefInfoByVsn("0.0.6"); v0_0_6 != nil {
   109  		contract_0_0_6, err := chieflib.NewTribeChief_0_0_6(v0_0_6.Addr, eth.NewContractBackend(apiBackend))
   110  		if err != nil {
   111  			return nil, err
   112  		}
   113  		ts.tribeChief_0_0_6 = contract_0_0_6
   114  	}
   115  	if v0_0_7 := params.GetChiefInfoByVsn("0.0.7"); v0_0_7 != nil {
   116  		contract_0_0_7, err := chieflib.NewTribeChief_0_0_7(v0_0_7.Addr, eth.NewContractBackend(apiBackend))
   117  		if err != nil {
   118  			return nil, err
   119  		}
   120  		ts.tribeChief_0_0_7 = contract_0_0_7
   121  	}
   122  	if v1_0_0 := params.GetChiefInfoByVsn("1.0.0"); v1_0_0 != nil {
   123  		ab := eth.NewContractBackend(apiBackend)
   124  		contract_1_0_0, err := chieflib.NewTribeChief_1_0_0(v1_0_0.Addr, ab)
   125  		if err != nil {
   126  			return nil, err
   127  		}
   128  
   129  		ts.tribeChief_1_0_0 = contract_1_0_0
   130  		poc, err := chieflib.NewPOC_1_0_0(v1_0_0.PocAddr, ab)
   131  		if err != nil {
   132  			return nil, err
   133  		}
   134  		ts.poc = poc
   135  
   136  		base, err := chieflib.NewChiefBase_1_0_0(v1_0_0.BaseAddr, ab)
   137  		if err != nil {
   138  			return nil, err
   139  		}
   140  		ts.base = base
   141  
   142  		log.Info("<<TribeService>> chief-1.0.0 and poc init success.")
   143  	}
   144  	return ts, nil
   145  }
   146  
   147  func (self *TribeService) Protocols() []p2p.Protocol { return nil }
   148  func (self *TribeService) APIs() []rpc.API           { return nil }
   149  
   150  func (self *TribeService) Start(server *p2p.Server) error {
   151  	self.server = server
   152  	go self.loop()
   153  	close(params.InitTribeStatus)
   154  	return nil
   155  }
   156  func (self *TribeService) loop() {
   157  	for {
   158  		select {
   159  		case <-self.quit:
   160  			break
   161  		case mbox := <-params.MboxChan:
   162  			switch mbox.Method {
   163  			case "GetStatus":
   164  				self.getstatus(mbox)
   165  			case "GetNodeKey":
   166  				self.getnodekey(mbox)
   167  			case params.Chief100Update:
   168  				self.chief100FetchNextRoundSigner(mbox)
   169  			case "FilterVolunteer":
   170  				self.filterVolunteer(mbox)
   171  			case "GetVolunteers":
   172  				self.getVolunteers(mbox)
   173  			case "VerifyMiner": // for 1.0.0 vrf selected
   174  				self.VerifyMiner(mbox)
   175  
   176  			}
   177  		}
   178  	}
   179  }
   180  
   181  func (self *TribeService) Stop() error {
   182  	close(self.quit)
   183  	return nil
   184  }
   185  
   186  func (self *TribeService) _getVolunteers(blockNumber *big.Int, blockHash common.Hash) (params.ChiefVolunteers, error) {
   187  	var (
   188  		empty     = params.ChiefVolunteers{}
   189  		chiefInfo = params.GetChiefInfo(blockNumber)
   190  	)
   191  	if chiefInfo == nil {
   192  		log.Debug("=>TribeService.getVolunteers", "empty_chief", chiefInfo.Version, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   193  		return empty, errors.New("can_not_empty_chiefInfo")
   194  	} else {
   195  		ctx, cancel := context.WithTimeout(context.Background(), DEF_TIMEOUT)
   196  		defer cancel()
   197  		opts := new(bind.CallOptsWithNumber)
   198  		opts.Context = ctx
   199  		opts.Hash = &blockHash
   200  		switch chiefInfo.Version {
   201  		case "0.0.6":
   202  			v, err := self.tribeChief_0_0_6.GetVolunteers(opts)
   203  			if err != nil {
   204  				log.Error("=>TribeService.getVolunteers", "err", err, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   205  				return empty, err
   206  			}
   207  			return params.ChiefVolunteers{
   208  				VolunteerList: v.VolunteerList,
   209  				WeightList:    v.WeightList,
   210  				Length:        v.Length,
   211  			}, nil
   212  		case "0.0.7":
   213  			v, err := self.tribeChief_0_0_7.GetVolunteers(opts)
   214  			if err != nil {
   215  				log.Error("=>TribeService.getVolunteers", "err", err, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   216  				return empty, err
   217  			}
   218  			return params.ChiefVolunteers{
   219  				VolunteerList: v.VolunteerList,
   220  				WeightList:    v.WeightList,
   221  				Length:        v.Length,
   222  			}, nil
   223  		case "1.0.0":
   224  			// TODO
   225  			v, err := self.tribeChief_1_0_0.GetVolunteers(opts)
   226  			if err != nil {
   227  				log.Error("=>TribeService.getVolunteers", "err", err, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   228  				return empty, err
   229  			}
   230  			return params.ChiefVolunteers{
   231  				VolunteerList: v.VolunteerList,
   232  				WeightList:    v.WeightList,
   233  				Length:        v.Length,
   234  			}, nil
   235  		default:
   236  			log.Error("=>TribeService.getVolunteers", "fail_vsn", chiefInfo.Version, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   237  			return empty, errors.New("fail_vsn_now")
   238  		}
   239  	}
   240  }
   241  
   242  func (self *TribeService) getVolunteers(mbox params.Mbox) {
   243  	var (
   244  		blockNumber *big.Int
   245  		blockHash   common.Hash
   246  		success     = params.MBoxSuccess{Success: true}
   247  	)
   248  	// hash and number can not nil
   249  	if h, ok := mbox.Params["hash"]; ok {
   250  		bh := h.(common.Hash)
   251  		blockHash = bh
   252  	}
   253  	if n, ok := mbox.Params["number"]; ok {
   254  		blockNumber = n.(*big.Int)
   255  	}
   256  	entity, err := self._getVolunteers(blockNumber, blockHash)
   257  	if err == nil {
   258  		success.Entity = entity
   259  	} else {
   260  		success.Success = false
   261  		success.Entity = err
   262  	}
   263  	mbox.Rtn <- success
   264  }
   265  
   266  func (self *TribeService) filterVolunteer(mbox params.Mbox) {
   267  	var (
   268  		blockNumber *big.Int
   269  		blockHash   *common.Hash
   270  		addr        common.Address
   271  		vlist       = make([]common.Address, 0, 1)
   272  		success     = params.MBoxSuccess{Success: true}
   273  	)
   274  	// hash and number can not nil
   275  	if h, ok := mbox.Params["hash"]; ok {
   276  		bh := h.(common.Hash)
   277  		blockHash = &bh
   278  	}
   279  	if n, ok := mbox.Params["number"]; ok {
   280  		blockNumber = n.(*big.Int)
   281  	}
   282  	if a, ok := mbox.Params["address"]; ok {
   283  		addr = a.(common.Address)
   284  		vlist = append(vlist[:], addr)
   285  	}
   286  	log.Debug("=>TribeService.filterVolunteer", "blockNumber", blockNumber, "blockHash", blockHash.Hex(), "addr", addr.Hex())
   287  
   288  	chiefInfo := params.GetChiefInfo(blockNumber)
   289  	if chiefInfo == nil {
   290  		log.Error("=>TribeService.filterVolunteer", "empty_chief", chiefInfo.Version, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   291  		success.Success = false
   292  		success.Entity = errors.New("cchiefInfo_can_not_empty")
   293  	} else {
   294  		ctx, cancel := context.WithTimeout(context.Background(), DEF_TIMEOUT)
   295  		defer cancel()
   296  		opts := new(bind.CallOptsWithNumber)
   297  		opts.Context = ctx
   298  		opts.Hash = blockHash
   299  		switch chiefInfo.Version {
   300  		case "0.0.6":
   301  			rlist, err := self.tribeChief_0_0_6.FilterVolunteer(opts, vlist)
   302  			if err != nil {
   303  				log.Error("=>TribeService.filterVolunteer", "err", err, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   304  				success.Success = false
   305  				success.Entity = err
   306  			}
   307  			success.Entity = rlist[0]
   308  		case "0.0.7":
   309  			rlist, err := self.tribeChief_0_0_7.FilterVolunteer(opts, vlist)
   310  			if err != nil {
   311  				log.Error("=>TribeService.filterVolunteer", "err", err, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   312  				success.Success = false
   313  				success.Entity = err
   314  			}
   315  			success.Entity = rlist[0]
   316  		default:
   317  			log.Error("=>TribeService.filterVolunteer", "fail_vsn", chiefInfo.Version, "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   318  			success.Success = false
   319  			success.Entity = errors.New("fail_vsn_now")
   320  		}
   321  	}
   322  	mbox.Rtn <- success
   323  }
   324  
   325  func (self *TribeService) getnodekey(mbox params.Mbox) {
   326  	success := params.MBoxSuccess{Success: true}
   327  	success.Entity = self.server.PrivateKey
   328  	mbox.Rtn <- success
   329  }
   330  
   331  func (self *TribeService) getstatus(mbox params.Mbox) {
   332  	var (
   333  		blockNumber *big.Int     = nil
   334  		blockHash   *common.Hash = nil
   335  	)
   336  	// hash and number can not nil
   337  	if h, ok := mbox.Params["hash"]; ok {
   338  		bh := h.(common.Hash)
   339  		blockHash = &bh
   340  	}
   341  	if n, ok := mbox.Params["number"]; ok {
   342  		blockNumber = n.(*big.Int)
   343  	}
   344  	log.Debug("=>TribeService.getstatus", "blockNumber", blockNumber, "blockHash", blockHash.Hex())
   345  
   346  	success := params.MBoxSuccess{Success: true}
   347  	chiefStatus, err := self.getChiefStatus(blockNumber, blockHash)
   348  	if err != nil {
   349  		success.Success = false
   350  		success.Entity = err
   351  		log.Debug("chief.mbox.rtn: getstatus <-", "success", success.Success, "err", err)
   352  	} else {
   353  		entity := chiefStatus
   354  		success.Entity = entity
   355  		log.Debug("chief.mbox.rtn: getstatus <-", "success", success.Success)
   356  		//log.Debug("chief.mbox.rtn: getstatus <-", "success", success.Success, "entity", entity)
   357  	}
   358  	mbox.Rtn <- success
   359  }
   360  func (self *TribeService) chief100FetchNextRoundSigner(mbox params.Mbox) {
   361  	success := params.MBoxSuccess{Success: true}
   362  	var (
   363  		blockNumber *big.Int
   364  		hash        common.Hash
   365  		vrfn        *big.Int
   366  		v           common.Address
   367  	)
   368  	hash = mbox.Params["hash"].(common.Hash)
   369  	blockNumber = mbox.Params["number"].(*big.Int) //如果出错.立即崩溃亏即可
   370  	vrfn = mbox.Params["vrfn"].(*big.Int)
   371  	if params.IsSIP100Block(blockNumber) {
   372  		nl := self.minerList(blockNumber, hash)
   373  		v = self.takeMiner(nl, hash, vrfn.Bytes())
   374  		log.Debug("chief.mbox.rtn chief100: update <-", "addr", v.String())
   375  	}
   376  	success.Success = true
   377  	success.Entity = v
   378  	mbox.Rtn <- success
   379  	log.Debug("chief.mbox.rtn: update <-", "success", success)
   380  
   381  }
   382  
   383  // --------------------------------------------------------------------------------------------------
   384  // inner private
   385  // --------------------------------------------------------------------------------------------------
   386  func (self *TribeService) getChiefStatus(blockNumber *big.Int, blockHash *common.Hash) (params.ChiefStatus, error) {
   387  	log.Debug(fmt.Sprintf("[getChiefStatus],blockNumber=%s,blockHash=%s", blockNumber, blockHash.String()))
   388  	ctx, cancel := context.WithTimeout(context.Background(), DEF_TIMEOUT)
   389  	defer cancel()
   390  	//opts := &bind.CallOpts{Context: ctx}
   391  	opts := new(bind.CallOptsWithNumber)
   392  	opts.Context = ctx
   393  	opts.Hash = blockHash
   394  	if chiefInfo := params.GetChiefInfo(blockNumber); chiefInfo != nil {
   395  		switch chiefInfo.Version {
   396  		case "0.0.2":
   397  			chiefStatus, err := self.tribeChief_0_0_2.GetStatus(opts)
   398  			if err != nil {
   399  				return params.ChiefStatus{}, err
   400  			}
   401  			return params.ChiefStatus{
   402  				VolunteerList: chiefStatus.VolunteerList,
   403  				SignerList:    chiefStatus.SignerList,
   404  				ScoreList:     chiefStatus.ScoreList,
   405  				NumberList:    chiefStatus.NumberList,
   406  				BlackList:     nil,
   407  				Number:        chiefStatus.Number,
   408  			}, nil
   409  		case "0.0.3":
   410  			chiefStatus, err := self.tribeChief_0_0_3.GetStatus(opts)
   411  			if err != nil {
   412  				return params.ChiefStatus{}, err
   413  			}
   414  			return params.ChiefStatus{
   415  				VolunteerList: chiefStatus.VolunteerList,
   416  				SignerList:    chiefStatus.SignerList,
   417  				ScoreList:     chiefStatus.ScoreList,
   418  				NumberList:    chiefStatus.NumberList,
   419  				BlackList:     nil,
   420  				Number:        chiefStatus.Number,
   421  			}, nil
   422  		case "0.0.4":
   423  			chiefStatus, err := self.tribeChief_0_0_4.GetStatus(opts)
   424  			if err != nil {
   425  				return params.ChiefStatus{}, err
   426  			}
   427  			return params.ChiefStatus{
   428  				VolunteerList: chiefStatus.VolunteerList,
   429  				SignerList:    chiefStatus.SignerList,
   430  				ScoreList:     chiefStatus.ScoreList,
   431  				NumberList:    chiefStatus.NumberList,
   432  				BlackList:     nil,
   433  				Number:        chiefStatus.Number,
   434  			}, nil
   435  		case "0.0.5":
   436  			chiefStatus, err := self.tribeChief_0_0_5.GetStatus(opts)
   437  			if err != nil {
   438  				return params.ChiefStatus{}, err
   439  			}
   440  			epoch, err := self.tribeChief_0_0_5.GetEpoch(opts)
   441  			if err != nil {
   442  				return params.ChiefStatus{}, err
   443  			}
   444  			signerLimit, err := self.tribeChief_0_0_5.GetSignerLimit(opts)
   445  			if err != nil {
   446  				return params.ChiefStatus{}, err
   447  			}
   448  			volunteerLimit, err := self.tribeChief_0_0_5.GetVolunteerLimit(opts)
   449  			if err != nil {
   450  				return params.ChiefStatus{}, err
   451  			}
   452  			return params.ChiefStatus{
   453  				VolunteerList:  chiefStatus.VolunteerList,
   454  				SignerList:     chiefStatus.SignerList,
   455  				ScoreList:      chiefStatus.ScoreList,
   456  				NumberList:     chiefStatus.NumberList,
   457  				BlackList:      chiefStatus.BlackList,
   458  				Number:         chiefStatus.Number,
   459  				Epoch:          epoch,
   460  				SignerLimit:    signerLimit,
   461  				VolunteerLimit: volunteerLimit,
   462  			}, nil
   463  		case "0.0.6":
   464  			chiefStatus, err := self.tribeChief_0_0_6.GetStatus(opts)
   465  			if err != nil {
   466  				return params.ChiefStatus{}, err
   467  			}
   468  			epoch, err := self.tribeChief_0_0_6.GetEpoch(opts)
   469  			if err != nil {
   470  				return params.ChiefStatus{}, err
   471  			}
   472  			signerLimit, err := self.tribeChief_0_0_6.GetSignerLimit(opts)
   473  			if err != nil {
   474  				return params.ChiefStatus{}, err
   475  			}
   476  			volunteerLimit, err := self.tribeChief_0_0_6.GetVolunteerLimit(opts)
   477  			if err != nil {
   478  				return params.ChiefStatus{}, err
   479  			}
   480  			return params.ChiefStatus{
   481  				VolunteerList:  nil,
   482  				SignerList:     chiefStatus.SignerList,
   483  				ScoreList:      chiefStatus.ScoreList,
   484  				NumberList:     chiefStatus.NumberList,
   485  				BlackList:      chiefStatus.BlackList,
   486  				Number:         chiefStatus.Number,
   487  				Epoch:          epoch,
   488  				SignerLimit:    signerLimit,
   489  				VolunteerLimit: volunteerLimit,
   490  				TotalVolunteer: chiefStatus.TotalVolunteer,
   491  			}, nil
   492  		case "0.0.7":
   493  			chiefStatus, err := self.tribeChief_0_0_7.GetStatus(opts)
   494  			if err != nil {
   495  				return params.ChiefStatus{}, err
   496  			}
   497  			epoch, err := self.tribeChief_0_0_7.GetEpoch(opts)
   498  			if err != nil {
   499  				return params.ChiefStatus{}, err
   500  			}
   501  			signerLimit, err := self.tribeChief_0_0_7.GetSignerLimit(opts)
   502  			if err != nil {
   503  				return params.ChiefStatus{}, err
   504  			}
   505  			volunteerLimit, err := self.tribeChief_0_0_7.GetVolunteerLimit(opts)
   506  			if err != nil {
   507  				return params.ChiefStatus{}, err
   508  			}
   509  			return params.ChiefStatus{
   510  				VolunteerList:  nil,
   511  				SignerList:     chiefStatus.SignerList,
   512  				ScoreList:      chiefStatus.ScoreList,
   513  				NumberList:     chiefStatus.NumberList,
   514  				BlackList:      chiefStatus.BlackList,
   515  				Number:         chiefStatus.Number,
   516  				Epoch:          epoch,
   517  				SignerLimit:    signerLimit,
   518  				VolunteerLimit: volunteerLimit,
   519  				TotalVolunteer: chiefStatus.TotalVolunteer,
   520  			}, nil
   521  		case "1.0.0":
   522  			chiefStatus, err := self.tribeChief_1_0_0.GetStatus(opts)
   523  			if err != nil {
   524  				return params.ChiefStatus{}, err
   525  			}
   526  			epoch, err := self.tribeChief_1_0_0.GetEpoch(opts)
   527  			if err != nil {
   528  				return params.ChiefStatus{}, err
   529  			}
   530  			signerLimit, err := self.tribeChief_1_0_0.GetSignerLimit(opts)
   531  			if err != nil {
   532  				return params.ChiefStatus{}, err
   533  			}
   534  			volunteerLimit, err := self.tribeChief_1_0_0.GetVolunteerLimit(opts)
   535  			if err != nil {
   536  				return params.ChiefStatus{}, err
   537  			}
   538  			leaderList, leaderLimit, err := self.GetLeaders(blockNumber, blockHash)
   539  			if err != nil {
   540  				return params.ChiefStatus{}, err
   541  			}
   542  			return params.ChiefStatus{
   543  				LeaderLimit:    leaderLimit,
   544  				LeaderList:     leaderList,
   545  				VolunteerList:  nil,
   546  				SignerList:     chiefStatus.SignerList,
   547  				ScoreList:      chiefStatus.ScoreList,
   548  				NumberList:     chiefStatus.NumberList,
   549  				BlackList:      chiefStatus.BlackList,
   550  				Number:         chiefStatus.Number,
   551  				Epoch:          epoch,
   552  				SignerLimit:    signerLimit,
   553  				VolunteerLimit: volunteerLimit,
   554  				TotalVolunteer: chiefStatus.TotalVolunteer,
   555  			}, nil
   556  		}
   557  	}
   558  	return params.ChiefStatus{}, errors.New("status_not_found")
   559  }
   560  
   561  func (self *TribeService) isVolunteer(dict map[common.Address]interface{}, add common.Address) bool {
   562  	//TODO ****** 关于选拔的各种规则
   563  	// Rule.1 : Do not repeat the selection
   564  	if _, ok := dict[add]; ok {
   565  		return false
   566  	}
   567  	return true
   568  }
   569  
   570  func (self *TribeService) VerifyMiner(mbox params.Mbox) {
   571  	var (
   572  		parentblockHash common.Hash
   573  		addr            common.Address
   574  		vrfn            []byte
   575  		result          bool
   576  	)
   577  
   578  	// hash and number can not nil
   579  	if parenthash, ok := mbox.Params["parenthash"]; ok {
   580  		bh := parenthash.(common.Hash)
   581  		parentblockHash = bh
   582  	}
   583  	if a, ok := mbox.Params["addr"]; ok {
   584  		addr = a.(common.Address)
   585  	}
   586  	if a, ok := mbox.Params["vrfn"]; ok {
   587  		vrfn = a.([]byte)
   588  	}
   589  	success := params.MBoxSuccess{Success: true}
   590  	defer func() {
   591  		success.Entity = result
   592  		mbox.Rtn <- success
   593  	}()
   594  	result = self.verifyMiner(addr, parentblockHash, vrfn)
   595  	if !result {
   596  		log.Error("VerifyMiner failed", "hash", parentblockHash.Hex(), "miners", success.Entity)
   597  		return
   598  	}
   599  }
   600  
   601  // poc normalList and meshboxList
   602  func (self *TribeService) minerList(num *big.Int, hash common.Hash) []common.Address {
   603  	var (
   604  		ss   *statute.StatuteService
   605  		nl   = make([]common.Address, 0)
   606  		opts = new(bind.CallOptsWithNumber)
   607  	)
   608  	ctx, cancel := context.WithTimeout(context.Background(), DEF_TIMEOUT)
   609  	defer cancel()
   610  	opts.Context = ctx
   611  	opts.Hash = &hash
   612  
   613  	vll, err := self.poc.GetNormalList(opts)
   614  	if err != nil {
   615  		log.Error("poc.GetNormalList__fail", "err", err)
   616  	}
   617  
   618  	err = self.ctx.Service(&ss)
   619  	if err != nil {
   620  		log.Error("get_StatuteService_fail", "err", err)
   621  	}
   622  	//暂时不允许meshbox参与出块,如果meshbox出快了也需要抵押
   623  	//mbs, err := ss.GetMeshboxList()
   624  	//if err != nil {
   625  	//	log.Error("poc.GetMeshboxList__fail", "err", err)
   626  	//}
   627  	//if mbs != nil && len(mbs) > 0 {
   628  	//	nl = append(nl, mbs...)
   629  	//}
   630  
   631  	if vll != nil && len(vll) > 0 {
   632  		nl = append(nl, vll...)
   633  	}
   634  	return nl
   635  }
   636  
   637  //下一轮出块节点不能包含当前这一轮的出块人以及下一轮已经被选出来的出块人
   638  func (self *TribeService) getNextRoundSignerExcludeList(blockNumber *big.Int, blockHash common.Hash) (addrs []common.Address) {
   639  	//为了兼容考虑,这里的volunteers是已经选出的下一轮出块人列表,可能没有满员
   640  	vl, err := self._getVolunteers(blockNumber, blockHash)
   641  	if err != nil {
   642  		log.Warn("tribeservice_getVolunteers_fail", "err", err)
   643  	}
   644  	for _, a := range vl.VolunteerList {
   645  		addrs = append(addrs, a)
   646  	}
   647  	chiefStatus, err := self.getChiefStatus(blockNumber, &blockHash)
   648  	if err != nil {
   649  		log.Warn("getChiefStatus", "err", err)
   650  	}
   651  	for _, a := range chiefStatus.SignerList {
   652  		addrs = append(addrs, a)
   653  	}
   654  	return addrs
   655  }
   656  
   657  //从nl也就是可能出块节列表中根据vrf选择一个,如果选中的人已经在下一轮出块列表中就尝试选择下一个,takerMiner只会在1.0.0版本后使用
   658  func (self *TribeService) takeMiner(nl []common.Address, hash common.Hash, _vrfn []byte) common.Address {
   659  	if nl != nil && len(nl) > 0 {
   660  		var (
   661  			block = self.ethereum.BlockChain().GetBlockByHash(hash)
   662  			vrfn  = new(big.Int).SetBytes(_vrfn[:])
   663  			fn    func(_vrfn *big.Int) common.Address
   664  		)
   665  		if block == nil {
   666  			panic(errors.New("get block by hash fail"))
   667  		}
   668  		//排除当前signerList的原因是有可能被选中作为下一轮出块节点,但是同时又
   669  		excludes := self.getNextRoundSignerExcludeList(block.Number(), block.Hash())
   670  		fn = func(_vrfn *big.Int) common.Address {
   671  			m := big.NewInt(int64(len(nl)))
   672  			x := new(big.Int).Sub(_vrfn, vrfn)
   673  			if x.Cmp(m) >= 0 {
   674  				return common.Address{}
   675  			}
   676  			idx := new(big.Int).Mod(_vrfn, m)
   677  			addrLog := make([]string, 0)
   678  			for _, n := range nl {
   679  				addrLog = append(addrLog[:], n.Hex())
   680  			}
   681  			log.Debug("fetchVolunteer-1.0.0-volunteers", "num", block.Number(), "addrList", addrLog)
   682  			// skip if `n` in volunteer list
   683  			v := nl[idx.Int64()]
   684  
   685  			for _, vol := range excludes {
   686  				if vol == v {
   687  					return fn(new(big.Int).Add(_vrfn, big.NewInt(1)))
   688  				}
   689  			}
   690  			log.Debug("fetchVolunteer-1.0.0-final", "num", block.Number(), "idx", idx.String(), "addr", v.Hex(), "vrfn", _vrfn)
   691  			return v
   692  		}
   693  		return fn(vrfn)
   694  	}
   695  	return common.Address{}
   696  }
   697  
   698  func (self *TribeService) verifyMiner(vol common.Address, hash common.Hash, vrfn []byte) bool {
   699  	block := self.ethereum.BlockChain().GetBlockByHash(hash)
   700  	ci := params.GetChiefInfo(block.Number())
   701  	switch ci.Version {
   702  	case "1.0.0":
   703  		m := self.takeMiner(self.minerList(block.Number(), block.Hash()), hash, vrfn)
   704  		log.Debug("<<TribeService.verifyMiner>>", "result", vol == m, "c", vol.Hex(), "t", m.Hex())
   705  		if vol == m {
   706  			return true
   707  		}
   708  	default:
   709  		return true
   710  	}
   711  	return false
   712  }
   713  
   714  func (self *TribeService) GetLeaders(num *big.Int, hash *common.Hash) ([]common.Address, *big.Int, error) {
   715  	ci := params.GetChiefInfo(num)
   716  	if ci != nil {
   717  		switch ci.Version {
   718  		case "1.0.0":
   719  			var (
   720  				leaders = make([]common.Address, 0)
   721  				opts    = new(bind.CallOptsWithNumber)
   722  			)
   723  			ctx, cancel := context.WithTimeout(context.Background(), DEF_TIMEOUT)
   724  			defer cancel()
   725  			opts.Context = ctx
   726  			opts.Hash = hash
   727  			leaders, err := self.base.TakeLeaderList(opts)
   728  			if err != nil {
   729  				return nil, nil, err
   730  			}
   731  			limit, err := self.base.TakeLeaderLimit(opts)
   732  			if err != nil {
   733  				return nil, nil, err
   734  			}
   735  			return leaders, limit, nil
   736  		}
   737  	}
   738  	return nil, nil, errors.New(fmt.Sprintf("not_support_vsn : %s", ci.Version))
   739  }